audit-tools 0.30.25 → 0.30.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/remediate/contractPipeline/artifactStore.d.ts +7 -0
  2. package/dist/remediate/contractPipeline/artifactStore.d.ts.map +1 -1
  3. package/dist/remediate/contractPipeline/artifactStore.js +11 -0
  4. package/dist/remediate/contractPipeline/artifactStore.js.map +1 -1
  5. package/dist/remediate/contractPipeline/phaseCut.d.ts +80 -0
  6. package/dist/remediate/contractPipeline/phaseCut.d.ts.map +1 -0
  7. package/dist/remediate/contractPipeline/phaseCut.js +184 -0
  8. package/dist/remediate/contractPipeline/phaseCut.js.map +1 -0
  9. package/dist/remediate/contractPipeline/phaseCutArtifact.d.ts +31 -0
  10. package/dist/remediate/contractPipeline/phaseCutArtifact.d.ts.map +1 -0
  11. package/dist/remediate/contractPipeline/phaseCutArtifact.js +48 -0
  12. package/dist/remediate/contractPipeline/phaseCutArtifact.js.map +1 -0
  13. package/dist/remediate/riskSignal.d.ts +16 -0
  14. package/dist/remediate/riskSignal.d.ts.map +1 -1
  15. package/dist/remediate/riskSignal.js +4 -0
  16. package/dist/remediate/riskSignal.js.map +1 -1
  17. package/dist/remediate/state/types.d.ts +24 -0
  18. package/dist/remediate/state/types.d.ts.map +1 -1
  19. package/dist/remediate/state/types.js +9 -0
  20. package/dist/remediate/state/types.js.map +1 -1
  21. package/dist/remediate/steps/contractPipeline.d.ts +11 -5
  22. package/dist/remediate/steps/contractPipeline.d.ts.map +1 -1
  23. package/dist/remediate/steps/contractPipeline.js +215 -29
  24. package/dist/remediate/steps/contractPipeline.js.map +1 -1
  25. package/dist/remediate/steps/dispatch.d.ts +17 -0
  26. package/dist/remediate/steps/dispatch.d.ts.map +1 -1
  27. package/dist/remediate/steps/dispatch.js +46 -2
  28. package/dist/remediate/steps/dispatch.js.map +1 -1
  29. package/dist/remediate/steps/nextStep.d.ts.map +1 -1
  30. package/dist/remediate/steps/nextStep.js +35 -11
  31. package/dist/remediate/steps/nextStep.js.map +1 -1
  32. package/package.json +1 -1
@@ -30,6 +30,15 @@ export const RemediationBlockSchema = z
30
30
  * declared surface is a producer bug, not an implicit empty.
31
31
  */
32
32
  touched_files: z.array(z.string()),
33
+ /**
34
+ * 0-based foundations→consumers phase ordinal (auto-phasing, T3). Derived
35
+ * mechanically at promotion from the persisted phase cut (the module a block's
36
+ * obligations belong to). The rolling scheduler treats it as a hard barrier: a
37
+ * block never dispatches until every lower-ordinal block is verified-complete,
38
+ * giving a per-phase whole-repo green checkpoint. Optional — absent (or all
39
+ * blocks sharing one ordinal) means a single phase, i.e. no barrier.
40
+ */
41
+ phase_ordinal: z.number().int().nonnegative().optional(),
33
42
  })
34
43
  .strict();
35
44
  export const RemediationPlanSchema = z
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/remediate/state/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/remediate/state/types.ts"],"names":[],"mappings":"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"}
@@ -2,12 +2,18 @@ import { type ValidationIssue, type JudgeReport, type SessionConfig } from "audi
2
2
  import type { ContractPipelineArtifactName } from "../contractPipeline/artifactStore.js";
3
3
  import type { RemediationStep } from "./types.js";
4
4
  /**
5
- * Maximum judge-ordered contract repairs per run. After the cap, the run
6
- * proceeds to implementation planning with the unrepaired counterexamples
7
- * carried as residual risks an unbounded critic↔repair oscillation is the
8
- * failure mode this exists to prevent.
5
+ * Runaway backstop for the judge↔repair loop the LOUD exception path, NOT the
6
+ * normal terminator. The loop normally terminates by *convergence*: it keeps
7
+ * repairing only while each round surfaces a genuinely NEW accepted counterexample
8
+ * (real progress), reaches a fixpoint when the judge approves, and escalates to the
9
+ * user the moment a round re-accepts an already-addressed counterexample without
10
+ * progress (a stall/oscillation). This ceiling exists only so a pathological run
11
+ * that keeps minting brand-new accepted counterexamples forever cannot loop without
12
+ * bound; hitting it is itself an escalation (loud), never a silent proceed. It is
13
+ * deliberately generous — a genuinely deep but converging design (each round a new
14
+ * real defect) must not be cut mid-convergence (the failure mode of the former N=2).
9
15
  */
10
- export declare const MAX_CONTRACT_REPAIR_ITERATIONS = 2;
16
+ export declare const MAX_CONTRACT_REPAIR_ITERATIONS = 8;
11
17
  /** Maximum implementation_dag regenerations after traceability rejections. */
12
18
  export declare const MAX_DAG_REGENERATION_ATTEMPTS = 2;
13
19
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"contractPipeline.d.ts","sourceRoot":"","sources":["../../../src/remediate/steps/contractPipeline.ts"],"names":[],"mappings":"AAwBA,OAAO,EAOL,KAAK,eAAe,EACpB,KAAK,WAAW,EAIhB,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAC;AA6D5B,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AAIzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAwClD;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAEhD,8EAA8E;AAC9E,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,mCAAmC,IAAI,CAAC;AAuCrD,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,oEAAoE,CAAC;IACrF,qFAAqF;IACrF,QAAQ,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IACzE,qDAAqD;IACrD,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAMD,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAWhC;AAED,wBAAsB,0BAA0B,CAC9C,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf;AAgED,qCAAqC;AACrC,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,4BAA4B,EAClC,KAAK,EAAE,OAAO,GAAG,SAAS,EAC1B,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAU,GAC7D,OAAO,CAAC,cAAc,CAAC,CAazB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGpF;AAED,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,QAAQ,EAAE,4BAA4B,EAAE,CAAC;IACzC,+EAA+E;IAC/E,OAAO,EAAE;QAAE,IAAI,EAAE,4BAA4B,CAAC;QAAC,MAAM,EAAE,eAAe,EAAE,CAAA;KAAE,EAAE,CAAC;CAC9E;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,uBAAuB,CAAC,CA6BlC;AAID,MAAM,WAAW,2BAA2B;IAC1C,mEAAmE;IACnE,4BAA4B,EAAE,OAAO,CAAC;IACtC,6EAA6E;IAC7E,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,GAAG,SAAS,GACpC,2BAA2B,CAa7B;AAED,4EAA4E;AAC5E,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU5E;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC;;;;;;OAMG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAID,MAAM,WAAW,SAAS;IACxB,cAAc,EAAE,uDAAuD,CAAC;IACxE,4DAA4D;IAC5D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,gBAAgB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,uEAAuE;IACvE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAC9C,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC,IAAI,CAAC,CAsCf;AAID;;;;GAIG;AAGH,KAAK,oBAAoB,GAAG,4BAA4B,GAAG,mBAAmB,GAAG,4BAA4B,CAAC;AAE9G;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,eAAe,EAAE,WAAW,CAAC,iBAAiB,CAAC,GAC9C,oBAAoB,CAYtB;AAwDD,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAsB,qCAAqC,CACzD,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,qBAAqB,CAAC,CA6ChC;AAID,MAAM,WAAW,6BAA6B;IAC5C,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,wCAAwC,CAC5D,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,6BAA6B,CAAC,CAsCxC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,+BAA+B,CACnD,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,KAAK,EAAE,uBAAuB,GAAG,qBAAqB,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAAC,CAgDlG;AAgFD;;;GAGG;AACH,wBAAsB,qCAAqC,CACzD,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAAC,CAa1C;AAcD,8EAA8E;AAC9E,QAAA,MAAM,sBAAsB;;;CAGlB,CAAC;AAEX,KAAK,mBAAmB,GAAG,MAAM,OAAO,sBAAsB,CAAC;AAE/D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,mBAAmB,CAEjF;AA0JD;;;GAGG;AACH,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CA8mCjC;AAkED;;;GAGG;AACH,wBAAsB,uCAAuC,CAC3D,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAqJf"}
1
+ {"version":3,"file":"contractPipeline.d.ts","sourceRoot":"","sources":["../../../src/remediate/steps/contractPipeline.ts"],"names":[],"mappings":"AAwBA,OAAO,EAOL,KAAK,eAAe,EACpB,KAAK,WAAW,EAIhB,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAC;AAqE5B,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AAIzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA4DlD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAEhD,8EAA8E;AAC9E,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,mCAAmC,IAAI,CAAC;AA8CrD,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,oEAAoE,CAAC;IACrF,qFAAqF;IACrF,QAAQ,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IACzE,qDAAqD;IACrD,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAMD,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAWhC;AAED,wBAAsB,0BAA0B,CAC9C,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf;AA0DD,qCAAqC;AACrC,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,4BAA4B,EAClC,KAAK,EAAE,OAAO,GAAG,SAAS,EAC1B,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAU,GAC7D,OAAO,CAAC,cAAc,CAAC,CAazB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGpF;AAED,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,QAAQ,EAAE,4BAA4B,EAAE,CAAC;IACzC,+EAA+E;IAC/E,OAAO,EAAE;QAAE,IAAI,EAAE,4BAA4B,CAAC;QAAC,MAAM,EAAE,eAAe,EAAE,CAAA;KAAE,EAAE,CAAC;CAC9E;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,uBAAuB,CAAC,CA6BlC;AAID,MAAM,WAAW,2BAA2B;IAC1C,mEAAmE;IACnE,4BAA4B,EAAE,OAAO,CAAC;IACtC,6EAA6E;IAC7E,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,GAAG,SAAS,GACpC,2BAA2B,CAa7B;AAED,4EAA4E;AAC5E,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU5E;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC;;;;;;OAMG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAID,MAAM,WAAW,SAAS;IACxB,cAAc,EAAE,uDAAuD,CAAC;IACxE,4DAA4D;IAC5D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,gBAAgB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,uEAAuE;IACvE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAC9C,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC,IAAI,CAAC,CAsCf;AAID;;;;GAIG;AAGH,KAAK,oBAAoB,GAAG,4BAA4B,GAAG,mBAAmB,GAAG,4BAA4B,CAAC;AAE9G;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,eAAe,EAAE,WAAW,CAAC,iBAAiB,CAAC,GAC9C,oBAAoB,CAYtB;AA2GD,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAsB,qCAAqC,CACzD,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,qBAAqB,CAAC,CA6ChC;AAID,MAAM,WAAW,6BAA6B;IAC5C,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,wCAAwC,CAC5D,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,6BAA6B,CAAC,CAsCxC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,+BAA+B,CACnD,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,KAAK,EAAE,uBAAuB,GAAG,qBAAqB,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAAC,CAgDlG;AAgFD;;;GAGG;AACH,wBAAsB,qCAAqC,CACzD,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAAC,CAa1C;AAcD,8EAA8E;AAC9E,QAAA,MAAM,sBAAsB;;;CAGlB,CAAC;AAEX,KAAK,mBAAmB,GAAG,MAAM,OAAO,sBAAsB,CAAC;AAE/D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,mBAAmB,CAEjF;AA0JD;;;GAGG;AACH,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAouCjC;AAkED;;;GAGG;AACH,wBAAsB,uCAAuC,CAC3D,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAoLf"}
@@ -23,8 +23,10 @@ import { existsSync } from "node:fs";
23
23
  import { mkdir, rename } from "node:fs/promises";
24
24
  import { join } from "node:path";
25
25
  import { writeJsonFile, readOptionalJsonFile, formatValidationIssues, hashContent, isRecord, withFsRetry, captureStepBoundaryFriction, } from "audit-tools/shared";
26
- import { CP_ARTIFACT_NAMES, contractArtifactExists, contractArtifactFilePath, contractPipelineDir, detectStaleArtifacts, isEnvelope, pathASeedFilePath, readContractArtifact, writeContractArtifact, } from "../contractPipeline/artifactStore.js";
27
- import { readIntakeRiskSignal, writeIntakeRiskSignal, escalateRiskSignal, decompositionRiskEvidence, adversarialDepthForTier, } from "../riskSignal.js";
26
+ import { CP_ARTIFACT_NAMES, contractArtifactExists, contractArtifactFilePath, contractPipelineDir, detectStaleArtifacts, envelopePayload, isEnvelope, pathASeedFilePath, readContractArtifact, writeContractArtifact, } from "../contractPipeline/artifactStore.js";
27
+ import { readIntakeRiskSignal, writeIntakeRiskSignal, escalateRiskSignal, decompositionRiskEvidence, adversarialDepthForTier, roundTripGranularityForTier, } from "../riskSignal.js";
28
+ import { phaseOrdinalForObligations, moduleSlug, renderPhaseCutSection, } from "../contractPipeline/phaseCut.js";
29
+ import { ensurePhaseCutArtifact, readPhaseCutArtifact } from "../contractPipeline/phaseCutArtifact.js";
28
30
  import { detectCyclicSeamObligations, validateCycleBreak, } from "../contractPipeline/cyclicSeamResolution.js";
29
31
  import { deriveObligationLedger, buildTestValidatorPlanScaffold, buildImplementationDagScaffold, acceptedCounterexampleIds, } from "../contractPipeline/derive.js";
30
32
  import { ensureNodeId, toBlockId } from "../contractPipeline/idRegistry.js";
@@ -60,14 +62,39 @@ const ARTIFACT_TO_PHASE = {
60
62
  // ── Phase → step kind mapping ──────────────────────────────────────────────────
61
63
  const CONTRACT_STEP_KIND = "contract_pipeline";
62
64
  const PRE_IMPLEMENTATION_PHASE_ORDER = CONTRACT_PIPELINE_PHASE_ORDER.filter((phase) => phase !== "closing");
65
+ /**
66
+ * Granularity collapse group (T1 slice 4b). The framing phases — goal, context,
67
+ * decomposition — are ONE coherent act of authoring (scope the change top-down):
68
+ * they carry no adversarial judgment and no deterministic derivation interleaves
69
+ * them, so for low-complexity work they fold into a single round-trip producing
70
+ * all three artifacts instead of three gated steps. The group deliberately STOPS
71
+ * at decomposition (before module_contract_drafting): keeping the decomposition→
72
+ * drafting boundary lets the slice-4a escalate-on-evidence intercept inspect the
73
+ * fresh decomposition and raise the tier — un-collapsing every remaining phase —
74
+ * before any contract is drafted or the per-module wave fans out. Collapse is
75
+ * best-effort: any member artifact the worker omits or writes malformed is
76
+ * re-emitted as its own fine-grained step by `nextMissingContractPhase`, so no
77
+ * work is ever lost. See `roundTripGranularityForTier`.
78
+ */
79
+ const FRAMING_COLLAPSE_GROUP = [
80
+ "goal_normalization",
81
+ "context_collection",
82
+ "decomposition",
83
+ ];
63
84
  // ── Bounded-loop caps ─────────────────────────────────────────────────────────
64
85
  /**
65
- * Maximum judge-ordered contract repairs per run. After the cap, the run
66
- * proceeds to implementation planning with the unrepaired counterexamples
67
- * carried as residual risks an unbounded critic↔repair oscillation is the
68
- * failure mode this exists to prevent.
86
+ * Runaway backstop for the judge↔repair loop the LOUD exception path, NOT the
87
+ * normal terminator. The loop normally terminates by *convergence*: it keeps
88
+ * repairing only while each round surfaces a genuinely NEW accepted counterexample
89
+ * (real progress), reaches a fixpoint when the judge approves, and escalates to the
90
+ * user the moment a round re-accepts an already-addressed counterexample without
91
+ * progress (a stall/oscillation). This ceiling exists only so a pathological run
92
+ * that keeps minting brand-new accepted counterexamples forever cannot loop without
93
+ * bound; hitting it is itself an escalation (loud), never a silent proceed. It is
94
+ * deliberately generous — a genuinely deep but converging design (each round a new
95
+ * real defect) must not be cut mid-convergence (the failure mode of the former N=2).
69
96
  */
70
- export const MAX_CONTRACT_REPAIR_ITERATIONS = 2;
97
+ export const MAX_CONTRACT_REPAIR_ITERATIONS = 8;
71
98
  /** Maximum implementation_dag regenerations after traceability rejections. */
72
99
  export const MAX_DAG_REGENERATION_ATTEMPTS = 2;
73
100
  /**
@@ -106,12 +133,6 @@ export async function writeCyclicSeamRepairState(artifactsDir, state) {
106
133
  await writeJsonFile(cyclicSeamRepairStatePath(artifactsDir), state);
107
134
  }
108
135
  // ── Envelope handling ─────────────────────────────────────────────────────────
109
- /** Payload of a stored artifact whether or not it has been enveloped yet. */
110
- function envelopePayload(envelope) {
111
- if (!envelope)
112
- return undefined;
113
- return isEnvelope(envelope) ? envelope.payload : envelope;
114
- }
115
136
  /**
116
137
  * Render a pre-filled skeleton section (S3 scaffold) for the partially-derivable
117
138
  * phases. The tool derives the structure/ids/cross-refs from the already-present
@@ -318,11 +339,26 @@ function inferRepairDirective(judge) {
318
339
  instruction: "Address every judge-accepted counterexample in the judge report's classifications.",
319
340
  };
320
341
  }
342
+ /** Judge-accepted counterexample ids from a judge report's classifications. */
343
+ function acceptedCeIdsOf(judge) {
344
+ return (judge?.classifications ?? [])
345
+ .filter((c) => c.classification === "accepted")
346
+ .map((c) => c.counterexample_id);
347
+ }
321
348
  /**
322
- * Decide whether implementation planning may proceed: an approved judge
323
- * verdict proceeds; a failing verdict triggers one targeted repair per judge
324
- * report, capped at MAX_CONTRACT_REPAIR_ITERATIONS — after the cap, the run
325
- * proceeds with the unrepaired counterexamples recorded as residual risks.
349
+ * Decide whether implementation planning may proceed. Convergence-terminated,
350
+ * NOT capped at an arbitrary count:
351
+ * - approved verdict proceed (the fixpoint);
352
+ * - a needs_repair verdict that surfaces a NEW accepted counterexample (one not
353
+ * already addressed by a prior repair) ⇒ repair (genuine progress);
354
+ * - a needs_repair verdict whose accepted counterexamples were ALL already
355
+ * addressed ⇒ escalate (stall/oscillation — the repair loop is not converging,
356
+ * surface the outstanding counterexamples to the user instead of silently
357
+ * shipping residual risk or looping);
358
+ * - the runaway backstop (MAX_CONTRACT_REPAIR_ITERATIONS) ⇒ escalate (loud).
359
+ * The former fixed N=2 cap that proceeded-with-residual-risk at an arbitrary count
360
+ * is gone: a deep-but-converging run is no longer cut mid-convergence, and a
361
+ * genuinely non-converging run is surfaced rather than buried.
326
362
  */
327
363
  async function evaluateJudgeGate(artifactsDir) {
328
364
  const judgeEnvelope = await readContractArtifact(artifactsDir, "judge_report");
@@ -334,12 +370,6 @@ async function evaluateJudgeGate(artifactsDir) {
334
370
  const repairState = await readRepairState(artifactsDir);
335
371
  const judgeHash = judgeEnvelope.content_hash;
336
372
  const alreadyHandled = repairState.repairs.some((repair) => repair.judge_hash === judgeHash);
337
- if (!alreadyHandled && repairState.repairs.length >= MAX_CONTRACT_REPAIR_ITERATIONS) {
338
- return {
339
- kind: "proceed_residual",
340
- note: `The judge verdict remains "needs_repair" after ${repairState.repairs.length} repair iteration(s) (the cap). Proceed anyway: treat every judge-accepted counterexample that remains unaddressed as a residual risk, and cover each one with an implementation or verification node.`,
341
- };
342
- }
343
373
  // Map judge.repair_directive.target if present; if absent, infer from classifications.
344
374
  const rawDirective = judge.repair_directive;
345
375
  const directive = rawDirective
@@ -350,7 +380,36 @@ async function evaluateJudgeGate(artifactsDir) {
350
380
  instruction: rawDirective.instruction,
351
381
  }
352
382
  : inferRepairDirective(judge);
353
- return { kind: "repair", directive, judgeHash };
383
+ const acceptedIds = acceptedCeIdsOf(judge);
384
+ const addressed = new Set(repairState.repairs.flatMap((r) => r.accepted_ce_ids ?? []));
385
+ const newAccepted = acceptedIds.filter((id) => !addressed.has(id));
386
+ // Idempotent re-entry: this exact judge report already drove a repair (its hash
387
+ // is recorded). Re-emit the same repair directive; do not re-evaluate convergence
388
+ // (the repair has not yet produced a fresh judge report).
389
+ if (alreadyHandled) {
390
+ return { kind: "repair", directive, judgeHash, acceptedCeIds: newAccepted };
391
+ }
392
+ // Runaway backstop (loud) — the exception path, not the normal terminator.
393
+ if (repairState.repairs.length >= MAX_CONTRACT_REPAIR_ITERATIONS) {
394
+ return {
395
+ kind: "escalate",
396
+ reason: "runaway",
397
+ outstanding: acceptedIds,
398
+ note: `The judge↔repair loop reached its runaway backstop (${repairState.repairs.length} repair rounds) without converging. Each round was still surfacing accepted counterexamples. This is pathological non-convergence — review the outstanding counterexamples and the contract design with the user before proceeding.`,
399
+ };
400
+ }
401
+ // Progress: a new accepted counterexample (or the first round) ⇒ repair.
402
+ if (repairState.repairs.length === 0 || newAccepted.length > 0) {
403
+ return { kind: "repair", directive, judgeHash, acceptedCeIds: newAccepted };
404
+ }
405
+ // Stall: a needs_repair verdict whose every accepted counterexample was already
406
+ // addressed by a prior repair ⇒ the loop is not converging ⇒ escalate.
407
+ return {
408
+ kind: "escalate",
409
+ reason: "stall",
410
+ outstanding: acceptedIds,
411
+ note: `The judge re-accepted counterexample(s) that a prior repair already addressed (${acceptedIds.join(", ") || "none newly accepted"}), with no new accepted counterexample this round. The repair loop is not converging on these items. Resolve them with the user — adjust the contract design or accept the counterexamples as known limitations — before the plan can be promoted.`,
412
+ };
354
413
  }
355
414
  /**
356
415
  * The traceability invariant: no implementation_dag node may exist without
@@ -777,6 +836,45 @@ After writing the output file, run:
777
836
  stopCondition: `Stop after writing the contract-pipeline output for phase "${phase}" and running next-step.`,
778
837
  });
779
838
  };
839
+ // T1 slice 4b: emit ONE round-trip whose prompt concatenates the rendered
840
+ // specs of several consecutive authoring phases. The worker writes every
841
+ // named artifact top-down (each later phase's inputs are the files it wrote in
842
+ // the earlier sections of the same round-trip), then runs next-step once. The
843
+ // group header overrides the per-section "stop after writing" lines so they are
844
+ // not read as three separate stop points.
845
+ const buildCollapsedFramingStep = (phases) => {
846
+ const sections = phases.map((phase) => {
847
+ const rendered = renderContractPipelinePrompt({
848
+ role: phase,
849
+ artifactPaths,
850
+ sourcePaths,
851
+ repoRoot: root,
852
+ pathASeedPath,
853
+ hostCanDispatchSubagents: options.hostCanDispatchSubagents,
854
+ adversarialDepth,
855
+ });
856
+ return { phase, rendered };
857
+ });
858
+ const outputPaths = sections.map((s) => s.rendered.outputPath);
859
+ const header = `# Collapsed Authoring Round-Trip — ${phases.length} Phases
860
+
861
+ This is a low-complexity change, so these ${phases.length} coherent authoring phases are combined into a SINGLE round-trip. Complete EVERY section below — author them top-down, writing each artifact to its named path (each later section's inputs are the files you write in the earlier sections of this same round-trip). Then run next-step ONCE.
862
+
863
+ Treat any per-section "Stop after writing the output file / do not advance" instruction as scoped to that section only — it does NOT mean stop the round-trip. Finish all sections first.
864
+
865
+ If you cannot complete a section (an artifact would be malformed), write the ones you can and run next-step: the pipeline re-emits any missing or invalid artifact as its own fine-grained step, so no work is lost.
866
+
867
+ Artifacts to produce (in order):
868
+ ${outputPaths.map((p, i) => `${i + 1}. \`${p}\` (${phases[i]})`).join("\n")}`;
869
+ const body = sections
870
+ .map((s) => `\n---\n\n${s.rendered.prompt}`)
871
+ .join("\n");
872
+ return buildStep({
873
+ prompt: `${header}\n${body}`,
874
+ outputPath: outputPaths[outputPaths.length - 1],
875
+ stopCondition: `Stop after writing all ${phases.length} collapsed-framing artifacts (${phases.join(", ")}) and running next-step once.`,
876
+ });
877
+ };
780
878
  const buildParallelModuleWaveStep = async (phase) => {
781
879
  // DC-3: fan the phase out to ONE agent per module, concurrency-capped by the
782
880
  // shared wave scheduler (the same quota/host machinery implement dispatch
@@ -1061,8 +1159,10 @@ ${rejectionRewriteInstruction(archived.archivedPath)}`);
1061
1159
  return buildNextContractPipelineStep(options);
1062
1160
  }
1063
1161
  }
1064
- // 3. Judge gate: implementation planning is reachable only through an
1065
- // approved verdict, a bounded targeted repair, or the repair cap.
1162
+ // 3. Judge gate: implementation planning is reachable only through an approved
1163
+ // verdict (the fixpoint) or a convergent targeted repair. A stalled /
1164
+ // non-converging repair loop escalates to the user (blocked) instead of
1165
+ // silently proceeding with residual risk.
1066
1166
  if (nextPhase === "implementation_planning") {
1067
1167
  const gate = await evaluateJudgeGate(artifactsDir);
1068
1168
  if (gate.kind === "repair") {
@@ -1073,6 +1173,7 @@ ${rejectionRewriteInstruction(archived.archivedPath)}`);
1073
1173
  judge_hash: gate.judgeHash,
1074
1174
  target: repairTarget,
1075
1175
  at: new Date().toISOString(),
1176
+ accepted_ce_ids: gate.acceptedCeIds,
1076
1177
  });
1077
1178
  await writeRepairState(artifactsDir, repairState);
1078
1179
  }
@@ -1088,11 +1189,37 @@ ${rejectionRewriteInstruction(archived.archivedPath)}`);
1088
1189
  stopCondition: `Stop after rewriting "${repairTarget}" per the judge repair directive and running next-step.`,
1089
1190
  });
1090
1191
  }
1091
- if (gate.kind === "proceed_residual") {
1092
- return buildPhaseStep("implementation_planning", `## Repair Cap Reached Residual Risks
1192
+ if (gate.kind === "escalate") {
1193
+ // Non-convergence (stall or runaway backstop): surface it to the user
1194
+ // loudly rather than promoting a plan over an un-converged contract. The
1195
+ // outstanding accepted counterexamples are named so the user can resolve
1196
+ // them (revise the contract design or accept them as known limitations).
1197
+ await captureStepBoundaryFriction(artifactsDir, runId, {
1198
+ eventType: "repair_round",
1199
+ discriminator: `judge_nonconvergence:${gate.reason}`,
1200
+ note: `Judge↔repair loop escalated (${gate.reason}): ${gate.note}`,
1201
+ category: "trap",
1202
+ }, "remediate-code");
1203
+ return writeCurrentStep({
1204
+ stepKind: CONTRACT_STEP_KIND,
1205
+ status: "blocked",
1206
+ runId,
1207
+ repoRoot: root,
1208
+ artifactsDir,
1209
+ prompt: `# Judge↔Repair Loop Did Not Converge
1093
1210
 
1094
1211
  ${gate.note}
1095
- `);
1212
+
1213
+ ## Outstanding accepted counterexamples
1214
+
1215
+ ${gate.outstanding.length > 0
1216
+ ? gate.outstanding.map((id) => `- ${id}`).join("\n")
1217
+ : "_(none newly accepted this round)_"}
1218
+
1219
+ Read the judge_report and counterexample artifacts, decide with the user how to resolve each outstanding counterexample (revise the contract design and re-run, or accept it as a known limitation), then re-run next-step.`,
1220
+ allowedCommands: [],
1221
+ stopCondition: "Stop — the contract pipeline is blocked on a non-converging judge↔repair loop pending a user decision.",
1222
+ });
1096
1223
  }
1097
1224
  // gate.kind === "proceed": fall through to the normal phase step below.
1098
1225
  }
@@ -1601,6 +1728,39 @@ ${preCriticCitationGate.errorLines.join("\n")}
1601
1728
  }
1602
1729
  return buildParallelModuleWaveStep(nextPhase);
1603
1730
  }
1731
+ // Auto-phasing (T3): at the conceptual-design critique, hand the critic the
1732
+ // tool-DERIVED phase cut so it assesses design quality WITHIN a mechanically
1733
+ // dependency-ordered foundations→consumers phasing, instead of rejecting an
1734
+ // arbitrary N-goal change as "over-scoped" and forcing the host to re-scope by
1735
+ // hand at intake. The cut is derived deterministically from the finalized module
1736
+ // contracts' directional neighbor_needs edges (present by the critique phase) and
1737
+ // PERSISTED as the `phase_cut.json` sidecar here, so the cut the critic sees and
1738
+ // the cut the implementation-DAG promotion enforces are one source. Only injected
1739
+ // into the prompt when there is a genuine multi-phase cut to communicate.
1740
+ if (nextPhase === "critique") {
1741
+ const cut = await ensurePhaseCutArtifact(artifactsDir);
1742
+ if (cut && cut.phases.length > 1) {
1743
+ const reReview = await buildReReviewSection(nextPhase, artifactsDir);
1744
+ const phaseCutSection = renderPhaseCutSection(cut);
1745
+ return buildPhaseStep("critique", reReview ? `${phaseCutSection}\n${reReview}` : phaseCutSection);
1746
+ }
1747
+ }
1748
+ // Granularity collapse (T1 slice 4b): for low-complexity work, fold the framing
1749
+ // suffix [nextPhase..decomposition] into ONE round-trip producing several
1750
+ // artifacts, instead of one gated step per phase. Reads the POST-escalation
1751
+ // riskSignal (slice 4a may have already raised the tier above), so the dial is
1752
+ // never frozen at run start — `fine` for medium/high keeps full per-phase
1753
+ // isolation. Only collapses a genuine multi-phase suffix; a single trailing
1754
+ // framing phase falls through to the normal per-phase dispatch below.
1755
+ if (nextPhase &&
1756
+ roundTripGranularityForTier(riskSignal?.tier) === "collapsed" &&
1757
+ FRAMING_COLLAPSE_GROUP.includes(nextPhase)) {
1758
+ const startIdx = FRAMING_COLLAPSE_GROUP.indexOf(nextPhase);
1759
+ const suffix = FRAMING_COLLAPSE_GROUP.slice(startIdx);
1760
+ if (suffix.length > 1) {
1761
+ return buildCollapsedFramingStep([...suffix]);
1762
+ }
1763
+ }
1604
1764
  // Skeleton-scaffolded phases (S3): the tool pre-fills structure/ids from the
1605
1765
  // derived obligation ledger so the worker fills only the judgment slots.
1606
1766
  if (nextPhase === "test_validator_plan" || nextPhase === "implementation_planning") {
@@ -1683,6 +1843,22 @@ export async function promoteImplementationDagToExtractedPlan(artifactsDir) {
1683
1843
  obligationMap.set(obl.id, obl.kind);
1684
1844
  }
1685
1845
  }
1846
+ // Auto-phasing (T3): read the persisted phase cut and re-key its module-phase
1847
+ // map by `moduleSlug(name)` — the fragment the obligation ledger encodes into
1848
+ // `OBL-<slug>-…` ids. The block phase ordinal is then derived MECHANICALLY from
1849
+ // each node's obligations (never trusting a worker-carried field, which a node
1850
+ // merge could drop), so a foundation block always sorts below the consumers that
1851
+ // depend on it. Absent cut (single module / no finalized contracts) → no
1852
+ // ordinals, i.e. one phase, no barrier.
1853
+ const phaseCut = await readPhaseCutArtifact(artifactsDir);
1854
+ const slugToOrdinal = new Map();
1855
+ if (phaseCut) {
1856
+ for (const [name, ordinal] of Object.entries(phaseCut.module_phase)) {
1857
+ slugToOrdinal.set(moduleSlug(name), ordinal);
1858
+ }
1859
+ }
1860
+ const lastOrdinal = Math.max(0, ...slugToOrdinal.values());
1861
+ const hasMultiPhase = phaseCut ? phaseCut.phases.length > 1 : false;
1686
1862
  const nodes = Array.isArray(dag?.nodes) ? dag.nodes : [];
1687
1863
  const findings = nodes.map((node, index) => {
1688
1864
  const id = ensureNodeId(node.id, index);
@@ -1755,6 +1931,15 @@ export async function promoteImplementationDagToExtractedPlan(artifactsDir) {
1755
1931
  const touchedFiles = [
1756
1932
  ...new Set(node.output_files ?? node.files_likely_touched ?? []),
1757
1933
  ];
1934
+ // Phase ordinal from the union of this node's obligations (max → fail-toward-
1935
+ // later). Only stamped when there is a genuine multi-phase cut, so a single-
1936
+ // phase change carries no ordinal and the scheduler runs no barrier.
1937
+ const phaseOrdinal = hasMultiPhase
1938
+ ? phaseOrdinalForObligations([
1939
+ ...(node.satisfies_obligations ?? []),
1940
+ ...(node.verification_obligation_ids ?? []),
1941
+ ], slugToOrdinal, lastOrdinal)
1942
+ : undefined;
1758
1943
  return {
1759
1944
  block_id: toBlockId(nodeId),
1760
1945
  items: [nodeId],
@@ -1765,6 +1950,7 @@ export async function promoteImplementationDagToExtractedPlan(artifactsDir) {
1765
1950
  // touched_files is REQUIRED on the block contract; promote the node's
1766
1951
  // declared write scope so the file-ownership scheduler can read it.
1767
1952
  touched_files: touchedFiles,
1953
+ ...(phaseOrdinal !== undefined ? { phase_ordinal: phaseOrdinal } : {}),
1768
1954
  ...(node.targeted_commands && node.targeted_commands.length > 0
1769
1955
  ? { targeted_commands: [...node.targeted_commands] }
1770
1956
  : {}),