@open-agent-toolkit/cli 0.3.9 → 0.3.11

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 (193) hide show
  1. package/README.md +2 -1
  2. package/assets/bundle-metadata.json +1 -1
  3. package/assets/config/dispatch-matrix-recommendation.json +6 -6
  4. package/assets/docs/cli-utilities/configuration.md +12 -8
  5. package/assets/docs/cli-utilities/meta.json +13 -0
  6. package/assets/docs/cli-utilities/tool-packs.md +8 -2
  7. package/assets/docs/cli-utilities/workflow-gates.md +14 -1
  8. package/assets/docs/contributing/code.md +8 -2
  9. package/assets/docs/contributing/documentation.md +7 -1
  10. package/assets/docs/contributing/meta.json +15 -0
  11. package/assets/docs/contributing/updating-model-guidance.md +34 -6
  12. package/assets/docs/contributing/verifying-cursor-pins.md +38 -9
  13. package/assets/docs/docs-tooling/add-docs-to-a-repo.md +14 -5
  14. package/assets/docs/docs-tooling/commands.md +26 -8
  15. package/assets/docs/docs-tooling/meta.json +4 -0
  16. package/assets/docs/docs-tooling/workflows.md +2 -2
  17. package/assets/docs/guide/meta.json +4 -0
  18. package/assets/docs/meta.json +14 -0
  19. package/assets/docs/provider-sync/instruction-sync.md +8 -0
  20. package/assets/docs/provider-sync/meta.json +11 -0
  21. package/assets/docs/provider-sync/providers.md +4 -4
  22. package/assets/docs/provider-sync/scope-and-surface.md +3 -4
  23. package/assets/docs/reference/cli-reference.md +5 -2
  24. package/assets/docs/reference/docs-index-contract.md +22 -6
  25. package/assets/docs/reference/file-locations.md +7 -2
  26. package/assets/docs/reference/index.md +1 -1
  27. package/assets/docs/reference/meta.json +10 -0
  28. package/assets/docs/reference/troubleshooting.md +41 -6
  29. package/assets/docs/workflows/ideas/meta.json +4 -0
  30. package/assets/docs/workflows/meta.json +4 -0
  31. package/assets/docs/workflows/projects/cursor-cloud.md +8 -3
  32. package/assets/docs/workflows/projects/dispatch-ceiling.md +21 -14
  33. package/assets/docs/workflows/projects/evidence-layers.md +6 -8
  34. package/assets/docs/workflows/projects/implementation-execution.md +34 -5
  35. package/assets/docs/workflows/projects/lifecycle.md +7 -1
  36. package/assets/docs/workflows/projects/meta.json +25 -0
  37. package/assets/docs/workflows/projects/orchestration-model.md +5 -6
  38. package/assets/docs/workflows/skills/meta.json +10 -0
  39. package/assets/docs/workflows/skills/recon.md +28 -3
  40. package/assets/public-package-versions.json +4 -4
  41. package/assets/skills/oat-cursor-cloud-projects/SKILL.md +30 -16
  42. package/assets/skills/oat-dispatch-subagents/SKILL.md +4 -12
  43. package/assets/skills/oat-dispatch-subagents/references/managed-claude-example.json +1 -1
  44. package/assets/skills/oat-dispatch-subagents/references/provider-codex.md +51 -0
  45. package/assets/skills/oat-dispatch-subagents/references/provider-cursor.md +5 -2
  46. package/assets/skills/oat-dispatch-subagents/references/record-schema.md +8 -7
  47. package/assets/skills/oat-docs-analyze/SKILL.md +28 -3
  48. package/assets/skills/oat-docs-apply/SKILL.md +3 -3
  49. package/assets/skills/oat-docs-authoring/SKILL.md +1 -1
  50. package/assets/skills/oat-docs-authoring/references/oat-fumadocs-contract.md +5 -2
  51. package/assets/skills/oat-docs-bootstrap/SKILL.md +4 -3
  52. package/assets/skills/oat-docs-bootstrap/assets/AGENTS.md.template +3 -3
  53. package/assets/skills/oat-pjm-decision/SKILL.md +3 -2
  54. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +4 -4
  55. package/assets/skills/oat-project-complete/SKILL.md +47 -2
  56. package/assets/skills/oat-project-design/SKILL.md +10 -6
  57. package/assets/skills/oat-project-discover/SKILL.md +3 -3
  58. package/assets/skills/oat-project-dispatch-subagents/SKILL.md +3 -10
  59. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +4 -4
  60. package/assets/skills/oat-project-implement/SKILL.md +1 -1
  61. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +135 -3
  62. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +8 -10
  63. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +4 -4
  64. package/assets/skills/oat-project-implement/references/plan-and-resume.md +1 -1
  65. package/assets/skills/oat-project-import-plan/SKILL.md +3 -3
  66. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +4 -4
  67. package/assets/skills/oat-project-new/SKILL.md +3 -3
  68. package/assets/skills/oat-project-next/SKILL.md +50 -7
  69. package/assets/skills/oat-project-plan/SKILL.md +4 -4
  70. package/assets/skills/oat-project-plan-writing/SKILL.md +4 -4
  71. package/assets/skills/oat-project-pr-final/SKILL.md +11 -1
  72. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +4 -4
  73. package/assets/skills/oat-project-promote-spec-driven/SKILL.md +2 -2
  74. package/assets/skills/oat-project-quick-start/SKILL.md +12 -8
  75. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +4 -4
  76. package/assets/skills/oat-project-retro/SKILL.md +6 -3
  77. package/assets/skills/oat-project-review-provide/SKILL.md +2 -2
  78. package/assets/skills/oat-project-review-provide-remote/SKILL.md +2 -2
  79. package/assets/skills/oat-project-spec/SKILL.md +3 -3
  80. package/assets/skills/oat-project-summary/SKILL.md +22 -3
  81. package/assets/skills/oat-repo-improve/SKILL.md +2 -2
  82. package/assets/skills/recon/SKILL.md +24 -3
  83. package/assets/skills/recon/references/packet-contract.md +36 -6
  84. package/assets/skills/recon/references/profiles.md +3 -0
  85. package/assets/skills/recon/references/worker-contract.md +16 -3
  86. package/assets/skills/recon/scripts/create-review-brief.mjs +17 -86
  87. package/assets/skills/recon/scripts/lib/contracts.mjs +158 -41
  88. package/assets/skills/recon/scripts/lib/review-binding.mjs +123 -0
  89. package/assets/skills/recon/scripts/lib/routing.mjs +5 -2
  90. package/assets/skills/recon/scripts/reconcile-ledger.mjs +18 -7
  91. package/assets/skills/recon/scripts/render-packet.mjs +93 -1
  92. package/assets/skills/recon/scripts/validate-packet.mjs +119 -88
  93. package/assets/skills/subagent-orchestration/SKILL.md +1 -1
  94. package/assets/skills/subagent-orchestration/references/evidence-and-refresh.md +20 -8
  95. package/assets/skills/subagent-orchestration/references/provider-claude.md +25 -12
  96. package/assets/skills/subagent-orchestration/references/provider-codex.md +27 -18
  97. package/assets/skills/subagent-orchestration/references/provider-cursor.md +40 -10
  98. package/assets/templates/state.md +1 -0
  99. package/dist/commands/backlog/new.d.ts +2 -2
  100. package/dist/commands/backlog/new.d.ts.map +1 -1
  101. package/dist/commands/backlog/new.js +2 -2
  102. package/dist/commands/decision/new.d.ts +2 -2
  103. package/dist/commands/decision/new.d.ts.map +1 -1
  104. package/dist/commands/decision/new.js +2 -2
  105. package/dist/commands/docs/nav/contents.d.ts +9 -0
  106. package/dist/commands/docs/nav/contents.d.ts.map +1 -1
  107. package/dist/commands/docs/nav/contents.js +7 -2
  108. package/dist/commands/docs/nav/fumadocs.d.ts +51 -0
  109. package/dist/commands/docs/nav/fumadocs.d.ts.map +1 -0
  110. package/dist/commands/docs/nav/fumadocs.js +301 -0
  111. package/dist/commands/docs/nav/sync.d.ts +31 -1
  112. package/dist/commands/docs/nav/sync.d.ts.map +1 -1
  113. package/dist/commands/docs/nav/sync.js +163 -6
  114. package/dist/commands/index.d.ts.map +1 -1
  115. package/dist/commands/index.js +2 -0
  116. package/dist/commands/instructions/instructions.utils.d.ts +19 -0
  117. package/dist/commands/instructions/instructions.utils.d.ts.map +1 -1
  118. package/dist/commands/instructions/instructions.utils.js +89 -17
  119. package/dist/commands/instructions/sync/sync.d.ts.map +1 -1
  120. package/dist/commands/instructions/sync/sync.js +49 -2
  121. package/dist/commands/pjm/init.d.ts.map +1 -1
  122. package/dist/commands/pjm/init.js +2 -2
  123. package/dist/commands/project/closeout-check/closeout-invariant.d.ts +97 -0
  124. package/dist/commands/project/closeout-check/closeout-invariant.d.ts.map +1 -0
  125. package/dist/commands/project/closeout-check/closeout-invariant.js +301 -0
  126. package/dist/commands/project/closeout-check/index.d.ts +38 -0
  127. package/dist/commands/project/closeout-check/index.d.ts.map +1 -0
  128. package/dist/commands/project/closeout-check/index.js +117 -0
  129. package/dist/commands/project/complete-state/index.d.ts +4 -0
  130. package/dist/commands/project/complete-state/index.d.ts.map +1 -1
  131. package/dist/commands/project/complete-state/index.js +11 -13
  132. package/dist/commands/project/dispatch/index.d.ts.map +1 -1
  133. package/dist/commands/project/dispatch/index.js +6 -30
  134. package/dist/commands/project/dispatch/record.d.ts +9 -18
  135. package/dist/commands/project/dispatch/record.d.ts.map +1 -1
  136. package/dist/commands/project/dispatch/record.js +15 -212
  137. package/dist/commands/project/index.d.ts.map +1 -1
  138. package/dist/commands/project/index.js +2 -0
  139. package/dist/commands/project/new/scaffold.d.ts +0 -1
  140. package/dist/commands/project/new/scaffold.d.ts.map +1 -1
  141. package/dist/commands/project/new/scaffold.js +19 -20
  142. package/dist/commands/project/promote/promote.d.ts +2 -2
  143. package/dist/commands/project/promote/promote.d.ts.map +1 -1
  144. package/dist/commands/project/promote/promote.js +13 -11
  145. package/dist/commands/shared/frontmatter.d.ts +21 -0
  146. package/dist/commands/shared/frontmatter.d.ts.map +1 -1
  147. package/dist/commands/shared/frontmatter.js +70 -4
  148. package/dist/commands/shared/template-source.d.ts +29 -0
  149. package/dist/commands/shared/template-source.d.ts.map +1 -0
  150. package/dist/commands/{pjm → shared}/template-source.js +24 -7
  151. package/dist/commands/state/generate.js +2 -2
  152. package/dist/commands/template/index.d.ts +10 -0
  153. package/dist/commands/template/index.d.ts.map +1 -0
  154. package/dist/commands/template/index.js +87 -0
  155. package/dist/commands/template/resolve.d.ts +31 -0
  156. package/dist/commands/template/resolve.d.ts.map +1 -0
  157. package/dist/commands/template/resolve.js +86 -0
  158. package/dist/fs/io.d.ts +0 -41
  159. package/dist/fs/io.d.ts.map +1 -1
  160. package/dist/fs/io.js +2 -414
  161. package/dist/providers/claude/dispatch-envelope.d.ts.map +1 -1
  162. package/dist/providers/claude/dispatch-envelope.js +1 -0
  163. package/dist/providers/claude/targets.d.ts +1 -0
  164. package/dist/providers/claude/targets.d.ts.map +1 -1
  165. package/dist/providers/claude/targets.js +3 -1
  166. package/dist/providers/codex/codec/shared.d.ts +3 -0
  167. package/dist/providers/codex/codec/shared.d.ts.map +1 -1
  168. package/dist/providers/codex/codec/shared.js +4 -0
  169. package/dist/providers/cursor/codec/catalog.d.ts +2 -2
  170. package/dist/providers/cursor/codec/catalog.d.ts.map +1 -1
  171. package/dist/providers/cursor/codec/catalog.js +45 -0
  172. package/dist/providers/cursor/codec/mapping-validation.d.ts +4 -0
  173. package/dist/providers/cursor/codec/mapping-validation.d.ts.map +1 -0
  174. package/dist/providers/cursor/codec/mapping-validation.js +25 -0
  175. package/dist/providers/cursor/codec/materialize.d.ts.map +1 -1
  176. package/dist/providers/cursor/codec/materialize.js +2 -11
  177. package/dist/providers/cursor/codec/sync-extension.d.ts.map +1 -1
  178. package/dist/providers/cursor/codec/sync-extension.js +2 -11
  179. package/dist/providers/identity/absolute-paths.d.ts +4 -13
  180. package/dist/providers/identity/absolute-paths.d.ts.map +1 -1
  181. package/dist/providers/identity/absolute-paths.js +4 -17
  182. package/dist/providers/identity/generic-dispatch-record.d.ts +1 -1
  183. package/dist/providers/identity/generic-dispatch-record.js +2 -2
  184. package/dist/providers/identity/oat-dispatch-record.d.ts +4 -357
  185. package/dist/providers/identity/oat-dispatch-record.d.ts.map +1 -1
  186. package/dist/providers/identity/oat-dispatch-record.js +4 -236
  187. package/dist/release/public-package-contract.d.ts.map +1 -1
  188. package/dist/release/public-package-contract.js +12 -4
  189. package/dist/validation/skills.d.ts.map +1 -1
  190. package/dist/validation/skills.js +32 -6
  191. package/package.json +2 -2
  192. package/dist/commands/pjm/template-source.d.ts +0 -14
  193. package/dist/commands/pjm/template-source.d.ts.map +0 -1
@@ -6,6 +6,12 @@ import { join, resolve } from 'node:path';
6
6
 
7
7
  import { hashFile } from './lib/canonical-json.mjs';
8
8
  import { isDirectExecution } from './lib/cli-entry.mjs';
9
+ import {
10
+ affirmingDispositionByReviewKind,
11
+ classifyUnresolvedIssue,
12
+ requiredReviewKinds,
13
+ unresolvedIssuesBlockClaim,
14
+ } from './lib/contracts.mjs';
9
15
  import {
10
16
  assertSafeExistingPath,
11
17
  assertSafeOutputPath,
@@ -99,7 +105,7 @@ function intendedRoutingSection(manifest, routing) {
99
105
  '',
100
106
  `- **Manifest routing version:** ${routing.sourceSchemaVersion}`,
101
107
  `- **Approved authority:** ${escapeInline(routing.authority)}`,
102
- `- **Approved limits:** ${routing.waves.length} waves; ${routing.waves.reduce((count, wave) => count + wave.lanes.length, 0)} lanes; concurrency ${routing.maxConcurrency}; deadline ${routing.deadlineSeconds}s; retries ${routing.retryLimit}`,
108
+ `- **Approved limits:** ${routing.waves.length} waves; ${routing.waves.reduce((count, wave) => count + wave.lanes.length, 0)} lanes; concurrency ${routing.maxConcurrency}; deadline ${routing.deadlineSeconds}s; pre-acceptance admission retries per lane ${routing.retryLimit}`,
103
109
  '- **Evidence boundary:** These are normalized approved intended targets and root-recorded condition dispositions. They are not launcher receipts or observations of native runtime identity, usage, cost, or conclusion correctness.',
104
110
  '',
105
111
  '### Waves',
@@ -115,6 +121,88 @@ function intendedRoutingSection(manifest, routing) {
115
121
  ];
116
122
  }
117
123
 
124
+ // The required reviews that gave `claimId` no disposition at all. Such a
125
+ // claim stays below `verified`, like an uncertain one, and is listed as not
126
+ // reviewed.
127
+ function omittedReviews(claimId, reviews) {
128
+ return requiredReviewKinds
129
+ .map((kind) => reviews.find((review) => review.reviewKind === kind))
130
+ .filter(
131
+ (review) =>
132
+ review &&
133
+ !(review.dispositions ?? []).some((item) => item.claimId === claimId),
134
+ );
135
+ }
136
+
137
+ function issueText(entry) {
138
+ return typeof entry === 'string' ? entry : (entry?.text ?? '');
139
+ }
140
+
141
+ // Every claim an incorporated review kept below `verified` (an unresolved
142
+ // issue that applies to it, a coverage finding that names it, a
143
+ // non-affirming disposition, or a required review that left it without a
144
+ // disposition), with the review's own words. Key-claim status
145
+ // alone would let a `complete` packet hide a downgraded non-key claim.
146
+ function reviewDowngradeLines(validatedRun) {
147
+ const { ledger, artifacts, assuranceReviewIds } = validatedRun;
148
+ const assurance = new Set(assuranceReviewIds);
149
+ const reviews = artifacts
150
+ .map(({ value }) => value)
151
+ .filter(
152
+ (value) =>
153
+ value.kind === 'recon.review-result' && assurance.has(value.id),
154
+ );
155
+ const lines = [];
156
+ for (const claim of ledger.claims) {
157
+ if (claim.status === 'verified') continue;
158
+ const reasons = [];
159
+ for (const review of reviews) {
160
+ const disposition = (review.dispositions ?? []).find(
161
+ (item) => item.claimId === claim.id,
162
+ );
163
+ if (!disposition) continue;
164
+ if (
165
+ disposition.disposition !==
166
+ affirmingDispositionByReviewKind[review.reviewKind]
167
+ ) {
168
+ reasons.push(`${review.reviewKind} review: ${disposition.disposition}`);
169
+ }
170
+ if (unresolvedIssuesBlockClaim(review, claim.id)) {
171
+ for (const entry of review.unresolvedIssues) {
172
+ const classification = classifyUnresolvedIssue(entry);
173
+ if (
174
+ classification.scope === 'claims' &&
175
+ !classification.claimIds.includes(claim.id)
176
+ ) {
177
+ continue;
178
+ }
179
+ const scope =
180
+ classification.scope === 'claims' ? 'issue' : 'global issue';
181
+ reasons.push(`${review.reviewKind} ${scope}: ${issueText(entry)}`);
182
+ }
183
+ }
184
+ }
185
+ for (const review of omittedReviews(claim.id, reviews)) {
186
+ reasons.push(
187
+ `${review.reviewKind} review: not reviewed (no disposition)`,
188
+ );
189
+ }
190
+ for (const review of reviews) {
191
+ for (const finding of review.coverageFindings ?? []) {
192
+ if (!finding.claimIds.includes(claim.id)) continue;
193
+ reasons.push(
194
+ `${finding.material ? 'material ' : ''}coverage finding ${finding.code}: ${finding.message}`,
195
+ );
196
+ }
197
+ }
198
+ if (reasons.length === 0) continue;
199
+ lines.push(
200
+ `**${escapeInline(claim.id)}** (${escapeInline(claim.status)}): ${escapeInline(claim.statement)} — ${reasons.map(escapeInline).join('; ')}`,
201
+ );
202
+ }
203
+ return lines;
204
+ }
205
+
118
206
  export function renderPacketDocument(validatedRun) {
119
207
  const { manifest, ledger, routing } = assertValidatedRun(validatedRun);
120
208
  const evidenceById = new Map(
@@ -186,6 +274,10 @@ export function renderPacketDocument(validatedRun) {
186
274
  ),
187
275
  ),
188
276
  '',
277
+ '## Review Downgrades',
278
+ '',
279
+ ...bulletLines(reviewDowngradeLines(validatedRun)),
280
+ '',
189
281
  '## Unresolved Questions',
190
282
  '',
191
283
  ...bulletLines(
@@ -3,15 +3,20 @@
3
3
  import { readFile, rm } from 'node:fs/promises';
4
4
  import { join, resolve } from 'node:path';
5
5
 
6
+ import { createReviewBrief } from './create-review-brief.mjs';
6
7
  import { hashCanonicalJson, hashFile, sha256 } from './lib/canonical-json.mjs';
7
8
  import { isDirectExecution } from './lib/cli-entry.mjs';
8
9
  import {
10
+ affirmingDispositionByReviewKind,
9
11
  isDigest,
10
12
  isObject,
11
13
  issue,
12
14
  profiles,
15
+ requiredReviewKinds,
16
+ unresolvedIssuesBlockClaim,
13
17
  validateArtifactShape,
14
18
  } from './lib/contracts.mjs';
19
+ import { reviewBriefEntries } from './lib/review-binding.mjs';
15
20
  import { normalizeManifestRouting } from './lib/routing.mjs';
16
21
  import {
17
22
  assertCanonicalRoot,
@@ -1318,44 +1323,69 @@ function resolveTerminalReconciliation(
1318
1323
  };
1319
1324
  }
1320
1325
 
1321
- function reviewBriefBindsClaim(brief, reviewKind, claim, ledger, manifest) {
1322
- const projected =
1323
- reviewKind === 'semantic' || reviewKind === 'redundant-verification'
1324
- ? brief?.claims?.find((item) => item.id === claim.id)
1325
- : reviewKind === 'adversarial' ||
1326
- reviewKind === 'contradiction-resolution'
1327
- ? brief?.provisionalStatements?.find((item) => item.id === claim.id)
1328
- : brief?.claims?.find((item) => item.id === claim.id);
1329
- if (!projected || projected.statement !== claim.statement) return false;
1330
- if (reviewKind !== 'semantic' && reviewKind !== 'redundant-verification') {
1331
- return Object.keys(projected).sort().join(',') === 'id,statement';
1332
- }
1333
- const evidenceById = new Map(ledger.evidence.map((item) => [item.id, item]));
1334
- const expectedEvidence = claim.evidence.map((link) => {
1335
- const evidence = evidenceById.get(link.evidenceId);
1336
- return evidence
1337
- ? {
1338
- id: evidence.id,
1339
- sourceId: evidence.sourceId,
1340
- displayExcerpt: evidence.displayExcerpt,
1341
- locator: evidence.locator,
1342
- }
1343
- : null;
1344
- });
1345
- if (
1346
- expectedEvidence.some((item) => !item) ||
1347
- hashCanonicalJson(projected.evidence) !==
1348
- hashCanonicalJson(expectedEvidence)
1349
- ) {
1350
- return false;
1351
- }
1352
- const sourceIds = new Set(expectedEvidence.map((item) => item.sourceId));
1353
- const expectedSources = manifest.sources.filter((source) =>
1354
- sourceIds.has(source.id),
1355
- );
1356
- return (
1357
- hashCanonicalJson(brief.sources) === hashCanonicalJson(expectedSources)
1326
+ // Brief integrity is one check: rebuild the brief with the production
1327
+ // generator from the prior ledger and the manifest, for the claim IDs it
1328
+ // lists, and require identical canonical JSON. Any edited, injected,
1329
+ // duplicated, or unprojected field differs, so no field-by-field binding is
1330
+ // needed. Briefs stay blind because the generator is the only projection.
1331
+ function checkReviewBrief(
1332
+ brief,
1333
+ reviewKind,
1334
+ { manifest, ledger, rebuildReviewBrief = createReviewBrief },
1335
+ ) {
1336
+ const entryIds = reviewBriefEntries(brief, reviewKind).map(
1337
+ (entry) => entry?.id,
1358
1338
  );
1339
+ let rebuilt;
1340
+ try {
1341
+ rebuilt = rebuildReviewBrief({
1342
+ id: brief.id,
1343
+ mode: brief.mode,
1344
+ createdAt: brief.createdAt,
1345
+ manifest,
1346
+ ledger,
1347
+ claimIds: entryIds,
1348
+ });
1349
+ } catch (error) {
1350
+ return {
1351
+ ok: false,
1352
+ entryIds,
1353
+ reason: `rebuild failed: ${error instanceof Error ? error.message : error}`,
1354
+ };
1355
+ }
1356
+ if (hashCanonicalJson(rebuilt) === hashCanonicalJson(brief)) {
1357
+ return { ok: true, entryIds };
1358
+ }
1359
+ const keys = [...new Set([...Object.keys(brief), ...Object.keys(rebuilt)])]
1360
+ .sort()
1361
+ .filter(
1362
+ (key) =>
1363
+ !Object.hasOwn(brief, key) ||
1364
+ !Object.hasOwn(rebuilt, key) ||
1365
+ hashCanonicalJson(brief[key]) !== hashCanonicalJson(rebuilt[key]),
1366
+ );
1367
+ return { ok: false, entryIds, reason: `differs at ${keys[0]}` };
1368
+ }
1369
+
1370
+ // One rebuild per distinct brief per validation pass. The key is the exact
1371
+ // artifact reference (path and digest) plus the review kind that selects the
1372
+ // brief's entries; the cache lives only as long as this pass's checker.
1373
+ function createBriefChecker({ manifest, ledger, rebuildReviewBrief }) {
1374
+ const results = new Map();
1375
+ return (briefEntry, reviewKind) => {
1376
+ const key = `${briefEntry.reference?.path}\u0000${briefEntry.reference?.digest}\u0000${reviewKind}`;
1377
+ if (!results.has(key)) {
1378
+ results.set(
1379
+ key,
1380
+ checkReviewBrief(briefEntry.value, reviewKind, {
1381
+ manifest,
1382
+ ledger,
1383
+ rebuildReviewBrief,
1384
+ }),
1385
+ );
1386
+ }
1387
+ return results.get(key);
1388
+ };
1359
1389
  }
1360
1390
 
1361
1391
  function validateReviewBindings(
@@ -1365,6 +1395,7 @@ function validateReviewBindings(
1365
1395
  artifactsByPath,
1366
1396
  reconciliationContext,
1367
1397
  errors,
1398
+ checkBrief,
1368
1399
  ) {
1369
1400
  const claims = new Map(ledger.claims.map((claim) => [claim.id, claim]));
1370
1401
  const priorLedger = reconciliationContext.priorLedger;
@@ -1378,11 +1409,12 @@ function validateReviewBindings(
1378
1409
  ) {
1379
1410
  continue;
1380
1411
  }
1381
- const brief = [...artifactsByPath.values()].find(
1412
+ const briefEntry = [...artifactsByPath.values()].find(
1382
1413
  ({ reference, value }) =>
1383
1414
  sameReference(reference, result.brief) &&
1384
1415
  value.kind === 'recon.review-brief',
1385
- )?.value;
1416
+ );
1417
+ const brief = briefEntry?.value;
1386
1418
  const expectedMode =
1387
1419
  result.reviewKind === 'semantic' ||
1388
1420
  result.reviewKind === 'redundant-verification'
@@ -1401,27 +1433,26 @@ function validateReviewBindings(
1401
1433
  );
1402
1434
  continue;
1403
1435
  }
1436
+ const check = checkBrief(briefEntry, result.reviewKind);
1437
+ if (!check.ok) {
1438
+ errors.push(
1439
+ issue(
1440
+ 'REVIEW_BRIEF_MISMATCH',
1441
+ `Review ${result.id} brief is not the production brief rebuilt from the prior ledger and manifest (${check.reason})`,
1442
+ result.id,
1443
+ ),
1444
+ );
1445
+ }
1404
1446
  const seen = new Set();
1405
1447
  for (const disposition of result.dispositions) {
1406
- const currentClaim = claims.get(disposition.claimId);
1407
- const priorClaim = priorClaims.get(disposition.claimId);
1408
- const claim = priorClaim ?? currentClaim;
1409
- const bindingLedger = priorClaim ? priorLedger : ledger;
1410
1448
  if (
1411
- !claim ||
1412
1449
  seen.has(disposition.claimId) ||
1413
- !reviewBriefBindsClaim(
1414
- brief,
1415
- result.reviewKind,
1416
- claim,
1417
- bindingLedger,
1418
- manifest,
1419
- )
1450
+ !check.entryIds.includes(disposition.claimId)
1420
1451
  ) {
1421
1452
  errors.push(
1422
1453
  issue(
1423
1454
  'REVIEW_BRIEF_MISMATCH',
1424
- `Review ${result.id} dispositions must exactly match claim-bearing brief projections`,
1455
+ `Review ${result.id} dispositions must be unique members of its brief's claims`,
1425
1456
  result.id,
1426
1457
  ),
1427
1458
  );
@@ -1869,16 +1900,13 @@ function validateReconciliation(
1869
1900
  );
1870
1901
  }
1871
1902
  if (disposition?.disposition === 'accepted-gap') {
1903
+ // A material finding forces every named claim below `verified`, the
1904
+ // same downgrade the reconciler applies. The reviewer's per-statement
1905
+ // disposition may stay `covered`: a question omission is not a
1906
+ // statement defect.
1872
1907
  for (const claimId of finding.claimIds) {
1873
1908
  const claim = currentClaims.get(claimId);
1874
- const coverageDisposition = coverage.dispositions.find(
1875
- (item) => item.claimId === claimId,
1876
- );
1877
- if (
1878
- finding.material === true &&
1879
- (claim?.status === 'verified' ||
1880
- coverageDisposition?.disposition !== 'gap')
1881
- ) {
1909
+ if (finding.material === true && claim?.status === 'verified') {
1882
1910
  errors.push(
1883
1911
  issue(
1884
1912
  'MATERIAL_COVERAGE_ASSURANCE_EXCEEDED',
@@ -1969,7 +1997,7 @@ function validateDerivedSourceGaps(manifest, ledger, errors) {
1969
1997
  }
1970
1998
  }
1971
1999
 
1972
- function validateAssurance(validatedRun, errors) {
2000
+ function validateAssurance(validatedRun, errors, checkBrief) {
1973
2001
  const { manifest, ledger, achievedProfile } = validatedRun;
1974
2002
  const exactEvidence = new Set(validatedRun.exactEvidenceIds);
1975
2003
  const assuranceReviewIds = new Set(validatedRun.assuranceReviewIds);
@@ -1979,9 +2007,6 @@ function validateAssurance(validatedRun, errors) {
1979
2007
  const evidenceById = new Map(
1980
2008
  (ledger.evidence ?? []).map((item) => [item.id, item]),
1981
2009
  );
1982
- const priorClaims = new Map(
1983
- (validatedRun.priorLedger?.claims ?? []).map((claim) => [claim.id, claim]),
1984
- );
1985
2010
  const claimIds = new Set((ledger.claims ?? []).map((claim) => claim.id));
1986
2011
  for (const claimId of ledger.synthesis?.keyClaimIds ?? []) {
1987
2012
  if (!claimIds.has(claimId)) {
@@ -2056,14 +2081,12 @@ function validateAssurance(validatedRun, errors) {
2056
2081
  ),
2057
2082
  );
2058
2083
  }
2059
- const required = new Map([
2060
- ['semantic', 'affirmed'],
2061
- ['adversarial', 'unchallenged'],
2062
- ['coverage', 'covered'],
2063
- ]);
2064
- if (achievedProfile === 'thorough') {
2065
- required.set('redundant-verification', 'affirmed');
2066
- }
2084
+ const required = new Map(
2085
+ [
2086
+ ...requiredReviewKinds,
2087
+ ...(achievedProfile === 'thorough' ? ['redundant-verification'] : []),
2088
+ ].map((kind) => [kind, affirmingDispositionByReviewKind[kind]]),
2089
+ );
2067
2090
  const satisfied = new Set();
2068
2091
  const reviewerLanes = new Set();
2069
2092
  for (const reviewId of new Set(claim.reviewIds ?? [])) {
@@ -2128,11 +2151,12 @@ function validateAssurance(validatedRun, errors) {
2128
2151
  );
2129
2152
  }
2130
2153
  reviewerLanes.add(artifact.reviewerLane);
2131
- const brief = [...artifactsById.values()].find(
2154
+ const briefEntry = [...artifactsById.values()].find(
2132
2155
  ({ reference, value }) =>
2133
2156
  sameReference(reference, artifact.brief) &&
2134
2157
  value.kind === 'recon.review-brief',
2135
- )?.value;
2158
+ );
2159
+ const brief = briefEntry?.value;
2136
2160
  const expectedMode =
2137
2161
  artifact.reviewKind === 'semantic' ||
2138
2162
  artifact.reviewKind === 'redundant-verification'
@@ -2141,17 +2165,15 @@ function validateAssurance(validatedRun, errors) {
2141
2165
  artifact.reviewKind === 'contradiction-resolution'
2142
2166
  ? 'adversary'
2143
2167
  : 'coverage';
2168
+ const briefCheck = brief
2169
+ ? checkBrief(briefEntry, artifact.reviewKind)
2170
+ : null;
2144
2171
  if (
2145
2172
  !brief ||
2146
2173
  brief.runId !== ledger.runId ||
2147
2174
  brief.mode !== expectedMode ||
2148
- !reviewBriefBindsClaim(
2149
- brief,
2150
- artifact.reviewKind,
2151
- priorClaims.get(claim.id) ?? claim,
2152
- priorClaims.has(claim.id) ? validatedRun.priorLedger : ledger,
2153
- manifest,
2154
- ) ||
2175
+ !briefCheck.ok ||
2176
+ !briefCheck.entryIds.includes(claim.id) ||
2155
2177
  !artifact.permittedInputs?.some((reference) =>
2156
2178
  sameReference(reference, artifact.brief),
2157
2179
  )
@@ -2168,9 +2190,7 @@ function validateAssurance(validatedRun, errors) {
2168
2190
  (item) => item.claimId === claim.id,
2169
2191
  );
2170
2192
  const expectedDisposition =
2171
- artifact.reviewKind === 'contradiction-resolution'
2172
- ? 'resolved'
2173
- : required.get(artifact.reviewKind);
2193
+ affirmingDispositionByReviewKind[artifact.reviewKind];
2174
2194
  if (
2175
2195
  dispositions.length !== 1 ||
2176
2196
  dispositions[0].disposition !== expectedDisposition
@@ -2183,11 +2203,11 @@ function validateAssurance(validatedRun, errors) {
2183
2203
  ),
2184
2204
  );
2185
2205
  }
2186
- if ((artifact.unresolvedIssues ?? []).length > 0) {
2206
+ if (unresolvedIssuesBlockClaim(artifact, claim.id)) {
2187
2207
  errors.push(
2188
2208
  issue(
2189
2209
  'REVIEW_DISPOSITION_MISMATCH',
2190
- `Review ${reviewId} retains unresolved issues`,
2210
+ `Review ${reviewId} retains an unresolved issue that applies to this claim`,
2191
2211
  claim.id,
2192
2212
  ),
2193
2213
  );
@@ -2280,7 +2300,12 @@ function validateAssurance(validatedRun, errors) {
2280
2300
  }
2281
2301
  }
2282
2302
 
2283
- export async function compileValidatedRun(packetDirectory) {
2303
+ // `rebuildReviewBrief` is a test seam for counting brief rebuilds; production
2304
+ // callers use the default generator.
2305
+ export async function compileValidatedRun(
2306
+ packetDirectory,
2307
+ { rebuildReviewBrief = createReviewBrief } = {},
2308
+ ) {
2284
2309
  const packetRoot = resolve(packetDirectory);
2285
2310
  const errors = [];
2286
2311
  const warnings = [];
@@ -2532,6 +2557,11 @@ export async function compileValidatedRun(packetDirectory) {
2532
2557
  errors,
2533
2558
  );
2534
2559
  }
2560
+ const checkBrief = createBriefChecker({
2561
+ manifest,
2562
+ ledger: reconciliationContext.priorLedger ?? ledger,
2563
+ rebuildReviewBrief,
2564
+ });
2535
2565
  validateReviewBindings(
2536
2566
  manifest,
2537
2567
  ledger,
@@ -2539,6 +2569,7 @@ export async function compileValidatedRun(packetDirectory) {
2539
2569
  artifactsByPath,
2540
2570
  reconciliationContext,
2541
2571
  errors,
2572
+ checkBrief,
2542
2573
  );
2543
2574
  validateReconciliation(
2544
2575
  manifest,
@@ -2586,7 +2617,7 @@ export async function compileValidatedRun(packetDirectory) {
2586
2617
  assuranceReviewIds,
2587
2618
  reconciliationContext,
2588
2619
  });
2589
- validateAssurance(validatedRun, errors);
2620
+ validateAssurance(validatedRun, errors, checkBrief);
2590
2621
  }
2591
2622
 
2592
2623
  const valid = errors.length === 0;
@@ -4,7 +4,7 @@ description: Use when delegating work to subagents or choosing a model for a tas
4
4
  compatibility: Self-contained; no OAT installation required.
5
5
  user-invocable: true
6
6
  metadata:
7
- version: 1.0.10
7
+ version: 1.0.11
8
8
  ---
9
9
 
10
10
  # Subagent Orchestration
@@ -1,10 +1,10 @@
1
1
  # Evidence and Refresh Policy
2
2
 
3
3
  ```yaml
4
- guidance_version: 2026-09-24
5
- last_verified: 2026-09-24
6
- review_after: 2026-10-08
7
- stale_after: 2026-10-23
4
+ guidance_version: 2026-10-01
5
+ last_verified: 2026-10-01
6
+ review_after: 2026-10-15
7
+ stale_after: 2026-10-30
8
8
  ```
9
9
 
10
10
  This file governs dated provider examples. It does not override a live catalog,
@@ -17,7 +17,9 @@ authorization boundary.
17
17
  - `review-required`: older than 45 days, a newer family is observed, or a material control, price, tool, context, alias, or harness change is detected.
18
18
  - `stale`: older than 90 days, named models are unavailable or deprecated, or the launching surface can no longer express the recorded controls.
19
19
 
20
- The named routes were refreshed against provider catalogues on 2026-09-23.
20
+ The October 1 availability refresh adds GPT-6.1 Sol and Sonnet 5.5 support;
21
+ it migrates active Codex Sol selectors by user direction while preserving
22
+ efforts. Earlier provider observations retain their own dates.
21
23
  The benchmark observations below remain dated to 2026-07-25 and require
22
24
  review before making a new cross-provider performance claim. Each provider
23
25
  reference carries its own verification date; availability refresh does not
@@ -83,8 +85,9 @@ publish a provider-independent effort conversion.
83
85
  explicit user direction. No local task evaluation establishes an Astra
84
86
  advantage, and this preference is not acceptance by the separately
85
87
  maintained model-selection policy.
86
- - GPT-6 Sol and Luna are selectable in the current Codex catalogue and are
87
- the default new-work routes in `provider-codex.md`. GPT-5.6 Sol/Luna/Terra
88
+ - GPT-6.1 Sol and GPT-6 Luna are the default new-work selectors in
89
+ `provider-codex.md`. The Sol migration preserves existing effort choices,
90
+ including medium for intelligent recon. GPT-6 Sol and GPT-5.6 Sol/Luna/Terra
88
91
  remain supported for explicit configurations. The July independent coding
89
92
  data on GPT-5.6 Luna/Terra supported a mechanical floor of Luna high; this
90
93
  is historical evidence, not a measured GPT-6 performance comparison.
@@ -93,7 +96,12 @@ publish a provider-independent effort conversion.
93
96
  evidence. Earlier Opus 5 effort observations are historical and do not
94
97
  establish an Opus 5.5 benchmark result. Consequence adds independent review
95
98
  rather than automatically raising effort.
96
- - Sonnet 5 is a conditional route when measured latency, throughput, access,
99
+ - Sonnet 5.5 is a supported Claude conditional route and the user-selected
100
+ Economy medium candidate. Cursor 3.22.12 native probes matched Sonnet 5.5
101
+ exact-ID pins; its bracket-form pins fell back. Every pin requires its own
102
+ approved evidence and registry entry. Sonnet 5 remains
103
+ supported for compatibility and established workflows. Sonnet is a
104
+ conditional route when measured latency, throughput, access,
97
105
  rate limits, or end-to-end workload economics win. Fable 5 is an
98
106
  eligibility-gated specialist; its missing-domain-concept or long-horizon
99
107
  reviewer instantiation remains provisional, and zero-data-retention
@@ -195,6 +203,10 @@ component it cannot resolve. Probe a non-default rung as well, or a result that
195
203
  merely matches the family default cannot distinguish an honored parameter from
196
204
  an ignored one.
197
205
 
206
+ An exact-ID Cursor pin meets the same evidence gate as a bracket-form pin;
207
+ CLI catalog presence alone never permits generic pass-through. The Sonnet 5.5
208
+ refresh uses explicit exact-ID mappings because its bracket-form pins fell back.
209
+
198
210
  The six Cursor `claude-opus-5` and `claude-opus-4-8` mappings shipped on
199
211
  2026-07-25 met this gate; their resolved identities are listed in
200
212
  `provider-cursor.md`.
@@ -1,7 +1,7 @@
1
1
  ---
2
- guidance_version: 2026-09-23
3
- last_verified: 2026-09-23
4
- review_after: 2026-12-22
2
+ guidance_version: 2026-10-01
3
+ last_verified: 2026-10-01
4
+ review_after: 2026-12-30
5
5
  ---
6
6
 
7
7
  # Claude Model Selection
@@ -17,7 +17,12 @@ the dated model examples below. Launch mechanics for OAT dispatch live in
17
17
  high-volume, mechanically verified work.
18
18
  - `claude-opus-5-5`: normal substantive route and the default for
19
19
  interpretation-heavy implementation, hard reasoning, and consequential work.
20
- - `claude-sonnet-5`: conditional route when measured latency, throughput,
20
+ - `claude-sonnet-5-5`: supported conditional route at `low`, `medium`,
21
+ `high`, `xhigh`, and `max`; qualify it against the relevant Opus route on
22
+ representative work. The bundled Economy tier selects medium by explicit
23
+ user direction; this is separate from task-performance qualification.
24
+ - `claude-sonnet-5`: supported compatibility and established-workflow route
25
+ when measured latency, throughput,
21
26
  access, rate limits, or established-workflow economics beat the relevant
22
27
  Opus route.
23
28
  - `claude-fable-5-1`: eligibility-gated specialist for a directly relevant
@@ -45,6 +50,12 @@ host.
45
50
  is the bottleneck or an evaluated long-horizon workload benefits. Max is
46
51
  exceptional and requires a workload-specific effort sweep or an explicit
47
52
  quality-first exception.
53
+ - Sonnet 5.5: availability and its five efforts are documented in the
54
+ [Sonnet 5.5 overview](https://platform.claude.com/docs/en/models/sonnet-5-5/overview)
55
+ and [effort reference](https://platform.claude.com/docs/en/build-with-claude/effort).
56
+ The existing conditional-route posture applies; availability is not an
57
+ evaluated workload ranking. Check the installed Claude Code version and
58
+ returned assistant model before launch.
48
59
  - Sonnet 5: use medium or high only when measured latency, throughput, access,
49
60
  or workload economics justify the conditional route. Do not preserve xhigh
50
61
  or max as generic workhorse settings.
@@ -65,13 +76,13 @@ These routes are dated guidance and benchmark-derived routing hypotheses.
65
76
  Evaluate them on representative local work before treating fine boundaries as
66
77
  stable.
67
78
 
68
- | Task class | Default | Economy | Escalation | Floor notes |
69
- | ------------------------ | ------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
70
- | `mechanical-recon` | Haiku 4.5 | Same, with strict output and mechanical verification | Opus 5.5 medium | Haiku is below floor for semantic audits and silent-miss-prone exploration. |
71
- | `intelligent-recon` | Opus 5.5 low | Sonnet 5 medium/high only when its measured route wins | Opus 5.5 medium; high when deeper reasoning is needed | Verify silent-miss-prone conclusions; do not use Sonnet low for open-ended recon. |
72
- | `default-implementation` | Opus 5.5 medium | Sonnet 5 medium/high for evaluated bounded throughput | Opus 5.5 high | Fable is not a routine implementation or economy route. |
73
- | `hard-reasoning` | Opus 5.5 high | Opus 5.5 medium only after narrowing and evaluation | Opus 5.5 xhigh for a reasoning-depth bottleneck | Use max only after a workload-specific effort sweep. |
74
- | `consequential` | Opus 5.5 high plus independent review | No routine economy route | Opus 5.5 xhigh when deeper reasoning is also required | Consequence adds review and root authorization; it does not automatically require xhigh or max. |
79
+ | Task class | Default | Economy | Escalation | Floor notes |
80
+ | ------------------------ | ------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
81
+ | `mechanical-recon` | Haiku 4.5 | Same, with strict output and mechanical verification | Opus 5.5 medium | Haiku is below floor for semantic audits and silent-miss-prone exploration. |
82
+ | `intelligent-recon` | Opus 5.5 low | Sonnet 5.5 medium/high only when its measured route wins | Opus 5.5 medium; high when deeper reasoning is needed | Verify silent-miss-prone conclusions; do not use Sonnet low for open-ended recon. |
83
+ | `default-implementation` | Opus 5.5 medium | Sonnet 5.5 medium/high for evaluated bounded throughput | Opus 5.5 high | Fable is not a routine implementation or economy route. |
84
+ | `hard-reasoning` | Opus 5.5 high | Opus 5.5 medium only after narrowing and evaluation | Opus 5.5 xhigh for a reasoning-depth bottleneck | Use max only after a workload-specific effort sweep. |
85
+ | `consequential` | Opus 5.5 high plus independent review | No routine economy route | Opus 5.5 xhigh when deeper reasoning is also required | Consequence adds review and root authorization; it does not automatically require xhigh or max. |
75
86
 
76
87
  ## Root and Subagent Cost Posture
77
88
 
@@ -108,7 +119,9 @@ verified before selection.
108
119
 
109
120
  Eligibility filters the candidate set before capability or economy is compared.
110
121
  A route that fails one of these gates is unavailable regardless of benchmark
111
- standing. The non-Opus constraints are dated observations; reverify against the live
122
+ standing. The table below records existing generations; it does not establish Sonnet 5.5
123
+ retention, service tiers, or context limits. Verify those separately.
124
+ The non-Opus constraints are dated observations; reverify against the live
112
125
  schema and the organization's actual plan before launch. Do not transfer Opus 5
113
126
  service-tier or retention claims to Opus 5.5 without fresh evidence.
114
127