Skip to content

feat(plan): growth guards, trim enforcement, and contract slimming - #154

Merged
klpanagi merged 5 commits into
devfrom
feat/plan-growth-guards
Oct 1, 2026
Merged

klpanagi merged 5 commits into
devfrom
feat/plan-growth-guards

Conversation

@klpanagi

@klpanagi klpanagi commented Oct 1, 2026

Copy link
Copy Markdown
Owner

Summary

Breaks the Oracle near-cap stall loop (Ariadne: plan crept 102186 to 102307 of 102400 bytes via unbounded Smith revisions) without touching the ONE PLAN doctrine or Branch 3.

Changes

  • Oracle pre-write byte-estimate rule (tasks x ~2KB + ~15KB skeleton; trim/defer past 80 percent of cap, deferrals into the out-of-scope table).
  • Smith loop bounded (SMITH_LOOP_MAX_ITERATIONS = 3) with removals-only gate past 90 percent of cap.
  • plan-write-guard: per-path consecutive-refusal counter; past TRIM_REQUIRED_AFTER_CONSECUTIVE_REFUSALS = 2, growing writes refused with new trim_required code (actual/cap/overBy/headroom), shrinking writes still persist so over-cap plans can be trimmed back.
  • Contract slimming: QA guidance externalized to docs/plan-qa-scenarios.md (empty skeleton 14675 to 11789 bytes); Must NOT do and Parallelization demoted to optional; validator stays advisory (single errors.push).
  • resolvePlanCap() seam added; wiring the configured cap through it is a follow-up once PR feat(plan): configurable plan file size cap via plans.max_plan_file_bytes #153 merges.

Verification

  • bash script/run-ci.sh: 7/7 green. New tests/tools/plan/plan-write-guard-trim.test.ts RED-first, 3 pass.
  • Locked single-cap-literal test untouched and passing; no new 102400 literal in src/.

Notes

  • Merge with merge commit (squash disabled). No version bump.

Oracle pre-write byte-estimate rule and bounded Smith loop (max 3
iterations, removals-only past 90 percent of cap). plan-write-guard
refuses consecutive growing over-cap writes with trim_required while
still persisting shrinking writes. QA guidance externalized to
docs/plan-qa-scenarios.md; Must NOT do and Parallelization optional.
ONE PLAN doctrine and Branch 3 unchanged.
Resolves conflicts after PR 153 merge: keeps configurable cap
plumbing, unifies the duplicated resolvePlanCap seam into the
config-based resolver, and threads the resolved cap through
trim_required diagnostics. Full CI 7/7 green.
102400 proved too tight in practice (Ariadne review plan stalled at
102307 bytes). 140000 was chosen over 128000 because 128000 already
denotes the unrelated non-Anthropic context fallback in src/, which
would have tripped the single-cap-literal locked test. Over-cap test
fixtures moved from 120000 to 150000 to stay above the new cap.
The review ceiling introduced for this branch conflated two different
things and produced a loop that neither improved plans nor bounded burn.

Three defects:

1. Off-by-one. Rule 3 said "third rejection -> fix and resubmit" while the
   fence was `round <= 3`, so round 3's fixes were never re-reviewed. The
   delivered plan was an un-reviewed rejected revision presented as passed.

2. A fixed round count is the wrong stopping rule. Rounds are only worth
   spending while they are still finding new problems. The loop now exits
   on convergence - a round that introduces no new issue category - with the
   ceiling demoted to pure burn control.

3. The SIZE GATE instructed *Smith's verdicts* to demand removals-only.
   Smith is a separate agent with no plan-byte context and cannot honor it,
   and enforcement already lives in plan-write-guard as `trim_required`.
   That sentence is removed; the Oracle-side half is kept.

Four exits are now distinguished instead of one implicit bound:

  OKAY       approved
  CONVERGED  no new issue category this round - shipping is correct
  STALL      identical category set twice - author and reviewer disagree,
             so stop and ask the user rather than loop again
  CEILING    budget exhausted; unresolved blockers must be recorded and
             named, never quietly shipped

Classification is Oracle-side. Each of Smith's free-text blockers is
bucketed into the same three categories Smith already checks - reference,
executability, blocker - and the sets are compared across rounds. Smith
itself is untouched.

Smith is deliberately NOT modified. `src/agents/smith.ts` is byte-frozen by
a mission guardrail (task11-locked-decisions.test.ts, plus two
doc-coverage sweeps that fail if the freeze is lifted). Smith is the
pre-execution gate that blocks plan delivery; Auditor is the post-execution
scorer with veto powers deliberately withheld. Merging their concerns would
delete one of the two capabilities, so the edit belongs on the Oracle side.

`plans.smith_max_review_rounds` makes the ceiling configurable (default 8,
min 2, max 20). This required converting ORACLE_SYSTEM_PROMPT into a
factory to reach config at all; it is preserved as the default instance so
the existing importers keep passing untouched.

Verified: bash script/run-ci.sh 7/7 green, 3836 pass / 0 fail.
Regression fence for the reported failure: Oracle could not create or
update a plan because the size limits refused the writes.

Drives the real plan tool factories over a plan built from the actual
renderPlanSkeleton(), so the guard is exercised through the same entry
points production uses rather than enforcePlanCap in isolation.

11 cases covering: a plan in the 102400..140000 band the cap raise
opened (and its refusal at the old cap), plan_tasks manifest, plan_update
check-off round-trip, the lowered max_plan_file_bytes knob, contract
slimming, trim_required escalation with byte-identical refusals, recovery
via a shrinking write, ceiling-not-wall reads, and the UTF-8 byte ruler.

Verified by mutation: reverting the pre-154 cap literal collapses the
band and fails 5 of the 11 cases.

Lives in script/ (not scripts/) because CI discovers tests with
'find tests script -name *.test.ts'.
@klpanagi
klpanagi merged commit f8594b8 into dev Oct 1, 2026
6 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.

1 participant