Skip to content

D6: bundle composition — legacy splice path deleted, engine trimmed per entry - #100

Merged
open-coder-ai merged 2 commits into
mainfrom
w43/d6-bundle-composition
Sep 1, 2026
Merged

D6: bundle composition — legacy splice path deleted, engine trimmed per entry#100
open-coder-ai merged 2 commits into
mainfrom
w43/d6-bundle-composition

Conversation

@open-coder-ai

Copy link
Copy Markdown
Owner

What this changes

bundle() now has exactly two compositions and no filesystem-probed legacy splice path: bundle_entry(cfg) (public) renders contract + one family-engine section trimmed to what the entry uses + the inlined VENDOR literal + the runtime for all eleven config-driven vendors, and vscode_copilot — the deliberate dialect-module exception — keeps a dedicated composition whose output is byte-identical to the legacy splice it replaces. Docs' "adding an agent" paths now describe the config entry; design §7 records the measured numbers.

Trimming (dialect-families.md §7's open item, owned by D6) is composition logic only — no engine module changed: the family's bound entry points (hj_* / <family>_* + hook_entry_config) plus their transitive dependencies are extracted from the shared modules, minus

  • the grammar renderers no gate of the entry speaks (_g2 leaves devin and every F2 bundle; _g1 leaves kimi_code),
  • the marker-claims and hj_respond machinery the singleton dialects never call,
  • the TOML emitter unless config_format is toml,
  • the probe/windows helpers the entry does not cite (unchanged conditions, now inside the one engine section).

Measured sizes (lines, same base — before is main 6838d69, where every engine bundle inlined the whole engine):

bundle before after bundle before after
claude_code 786 698 tabnine 760 652
codex_cli 772 685 junie 760 652
kimi_code 760 654 grok 760 652
devin 786 669 cursor 883 608
gemini_cli 786 669 windsurf 814 581
antigravity 796 643 vscode_copilot 503 503 (identical)

The singletons give back most of D5's growth (cursor −31%, windsurf −29%, antigravity −19%). F1/F2 members give back 11–15% but stay above their own wave-base numbers (claude_code 698 vs 650 at D3's base): the D4/D5 devices live inside shared function bodies (_g1, hj_parse), where line-level trimming would mean per-vendor engine variants — §3.1's config/code line says no, so those lines stay, recorded in design §7.

Also: the dead adapters/_common.py (last user deleted in D3–D5) is removed; CHANGELOG Unreleased entry added; no version bump.

New tests (design §5, D6's rows):

  • test_bundle_equivalence.py — every bundle replays the whole golden set (every frozen payload × outcome through the bundle's own main(), plus both hook_config paths) — the §5.5 equivalence proof, on top of the existing 12-agent × outcome subprocess replay, which passes identically before and after the trim.
  • test_bundler.py — exactly one family-engine section and exactly one VENDOR literal per config-driven bundle (the re-homed intent of the retired cross-adapter splice test, per §5); trimmed-device presence derived from the entry's own gates/config_format; probes inlined exactly where cited.
  • test_thirteenth_vendor.py — §5.4: a synthetic vendor added by config alone is schema-validated, bound, claims/parses/responds/wires, and bundles via bundle_entry with the bundle matching the library's wire truth — no code.

Claim check

  • No capability claim is widened without a mechanism behind it (no matrix, config, or engine change; the synthetic thirteenth vendor lives only inside its test)
  • No new/changed MATRIX row (the test's synthetic row is injected and removed by a fixture)
  • No new payload shapes — every replayed payload is a frozen D1 golden fixture

Checks

  • pytest -q passes — 1399 passed, 4 skipped (was 1348: +51 new tests); golden fixtures byte-for-byte untouched
  • ruff check . and ruff format --check . pass
  • Runtime path is still stdlib-only (tests/check_stdlib_only.py green; bundler change is compose-time only)
  • Commits are signed off (git commit -s)

Notes for the reviewer

  • A trimmed bundle can retain a dead reference: F2's hj_respond still reads if gate["grammar"] == "G2": return _g2(...) with _g2 absent. That branch is unreachable for the inlined entry's data — the same pattern _hook_entry.py's own comment already documents for powershell_command — and the golden-set equivalence test plus the subprocess replay pin the behavior. If you'd rather fail-closed on it, the alternative is rewriting the dispatch in the emitted source, which I judged worse than a provably-dead name.
  • Grammar-renderer trimming keys on the entry's own gate table, not a hardcoded family→grammar map, so it is self-maintaining (devin, F1 but G1-only, drops _g2); the engine modules stay fully shared.
  • render_config (kimi's TOML emitter) is kept in bundles whose config_format is toml and trimmed elsewhere — bundles never call it at runtime, but it is part of that vendor's config surface.

Generated by Claude Code

…y uses

The legacy adapter-splice path is deleted. bundle() now has exactly two
compositions: bundle_entry(cfg) -- public, so a thirteenth vendor's entry
bundles without being registered -- renders contract + one family-engine
section + the inlined VENDOR literal + the runtime; vscode_copilot keeps a
dedicated dialect composition whose output is byte-identical to the legacy
splice it replaces. The engine section is trimmed by composition, never by
editing engine code: the family's bound entry points plus their transitive
dependencies are extracted from the shared modules, minus the grammar
renderers no gate of the entry speaks, the TOML emitter unless
config_format is toml, and the probe/windows helpers the entry does not
cite (same base: cursor 883->608, windsurf 814->581, antigravity 796->643,
F1 -11-15%, F2 -14%). Golden fixtures byte-for-byte unchanged; the
12-agent bundler subprocess replay is green before and after the trim.
New tests: every bundle replays the whole golden set (payloads x outcomes
plus both hook_config paths) through its own main(); exactly one
family-engine section and one VENDOR literal per config-driven bundle;
trimmed-device presence derived from the entry; and the design §5.4
thirteenth-vendor test adds a synthetic vendor by config alone --
schema-validated, bound, wired and bundled with no code. The dead
adapters/_common.py helper is removed with the legacy path that fed it.

Signed-off-by: Claude <noreply@anthropic.com>
…rim numbers

README, AGENTS.md and CONTRIBUTING now describe adding an agent as a
data/vendors entry (plus its _CONFIG_DRIVEN registration, matrix row and
fixtures), with a family module only for a genuinely new dialect. The
design doc's §7 gains the measured D6 bundle sizes with the honest
caveat that F1/F2 members stay above their own wave-base numbers because
the D4/D5 devices live inside shared function bodies. CHANGELOG carries
the D6 entry under Unreleased; no version bump, release stays frozen.

Signed-off-by: Claude <noreply@anthropic.com>
@open-coder-ai
open-coder-ai marked this pull request as ready for review September 1, 2026 15:38
@open-coder-ai
open-coder-ai merged commit a50aec4 into main Sep 1, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants