Skip to content

feat: opt-in unit-major iteration for construction design stages (2.2.13) - #512

Merged
apackeer merged 1 commit into
v2from
feature/issue-503-unit-major-construction-ordering
Jul 9, 2026
Merged

feat: opt-in unit-major iteration for construction design stages (2.2.13)#512
apackeer merged 1 commit into
v2from
feature/issue-503-unit-major-construction-ordering

Conversation

@apackeer

@apackeer apackeer commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Implements the first increment of #503 (RFC).

What

Opt-in unit-major iteration for the four inline construction design stages (functional-design, nfr-requirements, nfr-design, infrastructure-design): with the knob on, the engine designs unit 1 across all four stages, then unit 2, and so on - instead of running each stage across all units before the next stage starts.

  • Zero new state. The per-(stage, unit) coverage ledger already exists as artifact existence on disk; unit-major only changes which (stage, unit) pair the engine picks next. New emitUnitMajorRunStage walks units outer (Bolt DAG topological order) and block stages inner (graph order, which respects requires_stage), routed from a single strictly-guarded branch in emitForSlug.
  • Zero gate-machinery changes. The four per-stage gates still fire, cascading at block end via the existing fully-covered branch; approve advances stage by stage; the early-approve refusal guard and revision re-entry work unchanged.
  • The knob: Construction Iteration: unit-major runtime state field, set via the new aidlc-state.ts set-construction-iteration subcommand (a sibling of set-skeleton-stance), recorded at delivery-planning so the Bolt plan's sequencing finally has an executable effect. The read is strict (exact value only): absent, junk, or stage-major all take the byte-identical pre-existing path, proven by deep-equal directive comparisons in t210.
  • code-generation (mode: subagent) and the swarm path are untouched.

Version 2.2.13, CHANGELOG entry (states the opt-in, the exact command, and the default-unchanged guarantee), README badge, docs and all four harness SKILL.md updated. Tests: t209 (unit-major walk order, gate presentation, early-approve refusal, revision re-entry) and t210 (knob absent/junk/stage-major byte-equivalence + a diverging knob-on negative control; swarm still first-refusal with knob on).

Why

The engine iterates construction stage-major, so with N units the first line of code appears after 4xN design-document passes, and the human-approved Bolt plan's sequencing has no executable meaning. This increment restores per-unit design coherence (a unit is designed as a whole, immediately before what follows) and gives delivery-planning an executable knob, while explicitly NOT yet changing time-to-first-code (code-generation still runs last; that is the follow-up, by widening the walk's block filter).

Relationship to siblings (merge order matters)

Verification

  • Adversarial verification pass proved knob-off equivalence (single guarded branch; the knob is read in exactly one place; deep-equal directives across three coverage states), audited every Current Stage reader, and ran two out-of-band engine simulations confirming the gate cascade re-enters correctly and mid-walk partial coverage resumes at the right (stage, unit).
  • Deterministic tier + deterministic e2e slice green with the knob absent (construction/bolt/swarm journeys all pass). Reds triaged: t185/t72/t183 are documented contention flakes (green solo); t126 is a live poc journey structurally out of this diff's blast radius (poc SKIPs all four touched stages; the knob is never set; the failing runs died before construction; unmodified by this diff).
  • package.ts --check clean on all four harnesses, typecheck clean, coverage registry fresh, t68 version sync green.
  • Known non-blocking notes: the sensor-fire hook keys on Current Stage, so mid-walk artifact writes for a later design stage fire under the earlier stage's sensor list - harmless today because all four design stages declare the identical four sensors, but a future per-stage sensor divergence would misfire under unit-major; --status shows Current Stage as the first block stage during the walk (cosmetic, documented); a follow-up integration test could drive the full four-gate approve cascade live.

Gate: the combined pre-merge live gate ran GREEN on 2026-07-06 against a local integration branch composing all five sibling PRs (2.2.9-2.2.13) in version order - smoke+unit, Claude SDK integration, deterministic e2e, Claude TUI, Kiro ACP, Kiro TUI, and Codex exec slices, live vars set explicitly per slice. The one codex red (compose-front) reproduced identically on clean v2 and is a pre-existing sandbox fragility, not from this series. Merge in version order; whoever merges later re-bumps per the CHANGELOG conflict-trap policy.

@leandrodamascena leandrodamascena left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read the walk and checked it against current v2. It works — knob-off is byte-identical, the walk covers every unit, and the gate cascade runs on stock machinery.

What holds:

  • Knob-off is byte-identical. The routing guard is node.mode === "inline" && readConstructionIteration(...) === "unit-major"; anything but the exact trimmed "unit-major" falls through to the same emitPerUnitRunStage call, and code-generation (mode subagent) short-circuits before the read. t210's deep-equal across absent/stage-major/junk pins it.
  • The walk covers every unit and resumes mid-walk. It re-scans from the first uncovered (unit, stage) pair each time, so no skip and no double-emit; once the grid is covered it delegates to emitPerUnitRunStage(node) and the per-stage gate cascade runs unchanged.
  • Unit-outer ordering is dependency-safe — within a unit the block runs in graph order (respects requires_stage), and units are topo-ordered.

Two things worth doing, non-blocking:

  • The four-gate cascade isn't pinned end-to-end. t209's fixture hardcodes Current Stage = functional-design, so only gate 1 is observed. A case seeding Current Stage at nfr-design (earlier stages [x], grid covered) asserting that stage's gate presents would catch a regression in the post-first-gate advance.
  • Sensor dispatch keys on Current Stage, so a mid-walk write for a later design stage fires the earlier stage's sensors. Harmless only because all four design stages declare identical sensors, and nothing pins that — a comment or an assertion that the four share sensors_applicable would document the assumption.

Merge-order note: this and #511 both call unitCovered / buildRunStageDirective, so whichever lands second needs the mechanical align (read readBoltDagUnitKinds once, pass kinds.get(u) ?? null through both). Against current v2 this compiles as-is. The CONFLICTING status is the usual series rebase (CHANGELOG/README/version), not a code conflict.

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