@open-agent-toolkit/cli 0.2.72 → 0.2.74

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 (165) hide show
  1. package/assets/agents/oat-reviewer.md +4 -3
  2. package/assets/agents/recon-worker.md +42 -8
  3. package/assets/bundle-metadata.json +1 -1
  4. package/assets/docs/cli-utilities/configuration.md +3 -56
  5. package/assets/docs/cli-utilities/tool-packs.md +4 -4
  6. package/assets/docs/contributing/code.md +2 -2
  7. package/assets/docs/contributing/index.md +0 -1
  8. package/assets/docs/reference/cli-reference.md +1 -1
  9. package/assets/docs/reference/troubleshooting.md +17 -40
  10. package/assets/docs/workflows/projects/artifacts.md +16 -34
  11. package/assets/docs/workflows/projects/lifecycle.md +20 -19
  12. package/assets/docs/workflows/skills/explainer-kit.md +180 -440
  13. package/assets/docs/workflows/skills/index.md +1 -2
  14. package/assets/docs/workflows/skills/recon.md +114 -23
  15. package/assets/public-package-versions.json +4 -4
  16. package/assets/skills/explainer-kit/SKILL.md +96 -171
  17. package/assets/skills/explainer-kit/recipes/engineer-tour.json +1 -22
  18. package/assets/skills/explainer-kit/recipes/program-recap.json +1 -29
  19. package/assets/skills/explainer-kit/recipes/project-explainer.json +1 -22
  20. package/assets/skills/explainer-kit/recipes/project-recap.v2.json +1 -43
  21. package/assets/skills/explainer-kit/references/fact-base-contract.md +76 -101
  22. package/assets/skills/explainer-kit/references/recap-authoring.md +99 -0
  23. package/assets/skills/explainer-kit/schemas/manifest.schema.json +13 -135
  24. package/assets/skills/explainer-kit/scripts/bundle.mjs +712 -0
  25. package/assets/skills/explainer-kit/scripts/lib/claim-subject.mjs +40 -0
  26. package/assets/skills/explainer-kit/scripts/lib/contracts.mjs +113 -1504
  27. package/assets/skills/explainer-kit/scripts/lib/failure.mjs +13 -0
  28. package/assets/skills/explainer-kit/scripts/lib/package-coverage.mjs +57 -403
  29. package/assets/skills/explainer-kit/scripts/lib/qa-result.mjs +168 -0
  30. package/assets/skills/explainer-kit/scripts/lib/qa.mjs +90 -488
  31. package/assets/skills/explainer-kit/scripts/lib/recipes.mjs +28 -545
  32. package/assets/skills/explainer-kit/scripts/lib/run-package.mjs +120 -0
  33. package/assets/skills/explainer-kit/scripts/lib/sanitize.mjs +42 -0
  34. package/assets/skills/explainer-kit/scripts/record.mjs +335 -0
  35. package/assets/skills/explainer-kit/scripts/verify.mjs +648 -0
  36. package/assets/skills/oat-explainer-kit/SKILL.md +57 -117
  37. package/assets/skills/oat-explainer-kit/references/config-contract.md +20 -64
  38. package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +85 -237
  39. package/assets/skills/oat-explainer-kit/scripts/bind-project-sources.mjs +18 -10
  40. package/assets/skills/oat-explainer-kit/scripts/check-core.mjs +1 -0
  41. package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +256 -21
  42. package/assets/skills/oat-explainer-kit/scripts/persist-intent.mjs +82 -3
  43. package/assets/skills/oat-explainer-kit/scripts/resolve-config.mjs +0 -162
  44. package/assets/skills/oat-explainer-kit/scripts/resolve-intent.mjs +57 -123
  45. package/assets/skills/oat-project-autonomous/SKILL.md +14 -13
  46. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +165 -165
  47. package/assets/skills/oat-project-complete/SKILL.md +168 -349
  48. package/assets/skills/oat-project-complete/scripts/consume-persisted-recap-intent.mjs +125 -0
  49. package/assets/skills/oat-project-complete/scripts/execute-synced-archive-entry.mjs +0 -30
  50. package/assets/skills/oat-project-complete/scripts/parse-completion-retry-fields.mjs +4 -37
  51. package/assets/skills/oat-project-complete/scripts/parse-synced-archive-resume-fields.mjs +17 -16
  52. package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +9 -174
  53. package/assets/skills/oat-project-complete/scripts/resolve-completion-retry.mjs +1 -2
  54. package/assets/skills/oat-project-document/SKILL.md +1 -1
  55. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +165 -165
  56. package/assets/skills/oat-project-implement/SKILL.md +1 -1
  57. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +44 -56
  58. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +165 -165
  59. package/assets/skills/oat-project-lite/SKILL.md +1 -1
  60. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +165 -165
  61. package/assets/skills/oat-project-plan/SKILL.md +5 -6
  62. package/assets/skills/oat-project-pr-final/SKILL.md +1 -1
  63. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +165 -165
  64. package/assets/skills/oat-project-quick-start/SKILL.md +1 -1
  65. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +165 -165
  66. package/assets/skills/oat-project-review-receive/SKILL.md +14 -1
  67. package/assets/skills/oat-project-summary/SKILL.md +35 -25
  68. package/assets/skills/oat-wave-execute/SKILL.md +11 -36
  69. package/assets/skills/oat-wave-program/SKILL.md +13 -37
  70. package/assets/skills/recon/SKILL.md +103 -40
  71. package/assets/skills/recon/references/packet-contract.md +150 -67
  72. package/assets/skills/recon/references/profiles.md +38 -16
  73. package/assets/skills/recon/references/worker-contract.md +39 -8
  74. package/assets/skills/recon/scripts/lib/contracts.mjs +703 -55
  75. package/assets/skills/recon/scripts/lib/routing.mjs +588 -0
  76. package/assets/skills/recon/scripts/lib/validated-run.mjs +2 -0
  77. package/assets/skills/recon/scripts/prepare-routing.mjs +88 -0
  78. package/assets/skills/recon/scripts/render-packet.mjs +69 -1
  79. package/assets/skills/recon/scripts/validate-packet.mjs +473 -56
  80. package/assets/skills/subagent-orchestration/SKILL.md +18 -9
  81. package/assets/skills/subagent-orchestration/references/model-selection-principles.md +17 -8
  82. package/dist/commands/config/index.d.ts.map +1 -1
  83. package/dist/commands/config/index.js +9 -113
  84. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  85. package/dist/commands/project/archive/archive-utils.js +32 -184
  86. package/dist/commands/project/archive/explainer-package-coverage.d.ts +3 -8
  87. package/dist/commands/project/archive/explainer-package-coverage.d.ts.map +1 -1
  88. package/dist/commands/project/archive/explainer-package-coverage.js +1 -1
  89. package/dist/config/oat-config.d.ts +0 -11
  90. package/dist/config/oat-config.d.ts.map +1 -1
  91. package/dist/config/oat-config.js +0 -34
  92. package/dist/config/resolve.d.ts.map +1 -1
  93. package/dist/config/resolve.js +0 -8
  94. package/dist/release/public-package-contract.d.ts.map +1 -1
  95. package/dist/release/public-package-contract.js +2 -10
  96. package/dist/validation/project-state.d.ts.map +1 -1
  97. package/dist/validation/project-state.js +42 -3
  98. package/package.json +2 -2
  99. package/assets/docs/contributing/explainer-kit-verification.md +0 -133
  100. package/assets/docs/workflows/skills/explainer-kit-providers.md +0 -155
  101. package/assets/skills/explainer-kit/briefs/deep-dive.md +0 -35
  102. package/assets/skills/explainer-kit/briefs/project-page.md +0 -38
  103. package/assets/skills/explainer-kit/briefs/supporting-diagram.md +0 -28
  104. package/assets/skills/explainer-kit/briefs/walkthrough-deck.md +0 -35
  105. package/assets/skills/explainer-kit/examples/project-explainer/content.md +0 -31
  106. package/assets/skills/explainer-kit/examples/project-explainer/fact-base.md +0 -22
  107. package/assets/skills/explainer-kit/examples/project-recap/content.md +0 -77
  108. package/assets/skills/explainer-kit/examples/project-recap/fact-base.json +0 -104
  109. package/assets/skills/explainer-kit/examples/project-recap/fact-base.md +0 -44
  110. package/assets/skills/explainer-kit/examples/theme-bundle.json +0 -87
  111. package/assets/skills/explainer-kit/recipes/project-recap.v1.json +0 -93
  112. package/assets/skills/explainer-kit/references/contracts.md +0 -324
  113. package/assets/skills/explainer-kit/references/destination-contract.md +0 -210
  114. package/assets/skills/explainer-kit/references/extension-contract.md +0 -80
  115. package/assets/skills/explainer-kit/references/golden-conformance.md +0 -80
  116. package/assets/skills/explainer-kit/references/visual-review.md +0 -71
  117. package/assets/skills/explainer-kit/schemas/author-request.v2.schema.json +0 -212
  118. package/assets/skills/explainer-kit/schemas/author-request.v3.schema.json +0 -241
  119. package/assets/skills/explainer-kit/schemas/author-result.v2.schema.json +0 -52
  120. package/assets/skills/explainer-kit/schemas/build-record.schema.json +0 -98
  121. package/assets/skills/explainer-kit/schemas/durability-evidence.schema.json +0 -53
  122. package/assets/skills/explainer-kit/schemas/publish-receipt.v1.schema.json +0 -97
  123. package/assets/skills/explainer-kit/schemas/publish-receipt.v2.schema.json +0 -215
  124. package/assets/skills/explainer-kit/schemas/publish-request.v1.schema.json +0 -32
  125. package/assets/skills/explainer-kit/schemas/publish-request.v2.schema.json +0 -34
  126. package/assets/skills/explainer-kit/schemas/run-request.schema.json +0 -147
  127. package/assets/skills/explainer-kit/schemas/set-plan.v1.schema.json +0 -149
  128. package/assets/skills/explainer-kit/schemas/terminal-evidence.v1.schema.json +0 -81
  129. package/assets/skills/explainer-kit/schemas/visual-review-evidence.v1.schema.json +0 -66
  130. package/assets/skills/explainer-kit/schemas/visual-review-request.v1.schema.json +0 -117
  131. package/assets/skills/explainer-kit/schemas/visual-review-result.v1.schema.json +0 -80
  132. package/assets/skills/explainer-kit/scripts/lib/catalog.mjs +0 -349
  133. package/assets/skills/explainer-kit/scripts/lib/content-approval.mjs +0 -418
  134. package/assets/skills/explainer-kit/scripts/lib/diagram.mjs +0 -514
  135. package/assets/skills/explainer-kit/scripts/lib/durability.mjs +0 -643
  136. package/assets/skills/explainer-kit/scripts/lib/fact-base.mjs +0 -664
  137. package/assets/skills/explainer-kit/scripts/lib/internal-references.mjs +0 -538
  138. package/assets/skills/explainer-kit/scripts/lib/markdown.mjs +0 -414
  139. package/assets/skills/explainer-kit/scripts/lib/publication-policy.mjs +0 -54
  140. package/assets/skills/explainer-kit/scripts/lib/records.mjs +0 -954
  141. package/assets/skills/explainer-kit/scripts/lib/render.mjs +0 -703
  142. package/assets/skills/explainer-kit/scripts/lib/s3-roots.mjs +0 -353
  143. package/assets/skills/explainer-kit/scripts/lib/s3-static.mjs +0 -759
  144. package/assets/skills/explainer-kit/scripts/lib/set-plan.mjs +0 -209
  145. package/assets/skills/explainer-kit/scripts/lib/source-backlinks.mjs +0 -218
  146. package/assets/skills/explainer-kit/scripts/lib/terminal-evidence.mjs +0 -157
  147. package/assets/skills/explainer-kit/scripts/lib/visual-review.mjs +0 -400
  148. package/assets/skills/explainer-kit/scripts/publish.mjs +0 -76
  149. package/assets/skills/explainer-kit/scripts/record-durability.mjs +0 -64
  150. package/assets/skills/explainer-kit/scripts/render-qa.mjs +0 -461
  151. package/assets/skills/explainer-kit/scripts/run.mjs +0 -3038
  152. package/assets/skills/explainer-kit/scripts/validate.mjs +0 -59
  153. package/assets/skills/oat-explainer-kit/references/author-callback.md +0 -53
  154. package/assets/skills/oat-explainer-kit/references/migration.md +0 -144
  155. package/assets/skills/oat-explainer-kit/references/visual-review-callback.md +0 -83
  156. package/assets/skills/oat-explainer-kit/scripts/derive-destination.mjs +0 -91
  157. package/assets/skills/oat-explainer-kit/scripts/finalize-tracked-run.mjs +0 -531
  158. package/assets/skills/oat-explainer-kit/scripts/probe-recap-seams.mjs +0 -371
  159. package/assets/skills/oat-explainer-kit/scripts/run.mjs +0 -905
  160. package/dist/commands/project/archive/explainer-source-backlinks.d.ts +0 -18
  161. package/dist/commands/project/archive/explainer-source-backlinks.d.ts.map +0 -1
  162. package/dist/commands/project/archive/explainer-source-backlinks.js +0 -27
  163. package/dist/commands/project/archive/explainer-terminal-evidence.d.ts +0 -29
  164. package/dist/commands/project/archive/explainer-terminal-evidence.d.ts.map +0 -1
  165. package/dist/commands/project/archive/explainer-terminal-evidence.js +0 -37
@@ -0,0 +1,125 @@
1
+ import { readdir, realpath } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+
5
+ import { readPersistedIntent } from '../../oat-explainer-kit/scripts/persist-intent.mjs';
6
+
7
+ function consumptionError(message) {
8
+ const error = new Error(message);
9
+ error.code = 'E_RECAP_CONSUMPTION';
10
+ return error;
11
+ }
12
+
13
+ async function discoverManifestCandidates(explainersPath) {
14
+ let entries;
15
+ try {
16
+ entries = await readdir(explainersPath, { withFileTypes: true });
17
+ } catch (error) {
18
+ if (error?.code === 'ENOENT') return [];
19
+ throw error;
20
+ }
21
+
22
+ const candidates = [];
23
+ for (const entry of entries.sort((left, right) =>
24
+ left.name.localeCompare(right.name),
25
+ )) {
26
+ if (!entry.isDirectory()) continue;
27
+ const runEntries = await readdir(join(explainersPath, entry.name), {
28
+ withFileTypes: true,
29
+ });
30
+ if (
31
+ runEntries.some(
32
+ (runEntry) => runEntry.isFile() && runEntry.name === 'manifest.json',
33
+ )
34
+ ) {
35
+ candidates.push(`explainers/${entry.name}/manifest.json`);
36
+ }
37
+ }
38
+ return candidates;
39
+ }
40
+
41
+ async function resolveFailedAttemptEvidence(projectRoot, locator) {
42
+ try {
43
+ const { resolveProjectFailedAttemptEvidence } =
44
+ await import('../../oat-explainer-kit/scripts/check-terminal-outcome.mjs');
45
+ return await resolveProjectFailedAttemptEvidence({
46
+ projectPath: projectRoot,
47
+ locator,
48
+ });
49
+ } catch (error) {
50
+ throw consumptionError(
51
+ `Persisted failed-attempt evidence is invalid: ${error.message}`,
52
+ );
53
+ }
54
+ }
55
+
56
+ export async function consumePersistedRecapIntent({ projectPath }) {
57
+ const projectRoot = await realpath(projectPath);
58
+ const record = await readPersistedIntent({
59
+ statePath: join(projectRoot, 'state.md'),
60
+ product: 'projectRecap',
61
+ });
62
+ if (record === null) {
63
+ throw consumptionError(
64
+ 'Completion recap intent must be persisted before consumption.',
65
+ );
66
+ }
67
+ if (record.decision === 'skip') {
68
+ const failedAttemptEvidence =
69
+ record.source === 'failed_attempt'
70
+ ? await resolveFailedAttemptEvidence(
71
+ projectRoot,
72
+ record.failed_attempt_evidence,
73
+ )
74
+ : null;
75
+ return {
76
+ decision: 'skip',
77
+ source: record.source,
78
+ route: 'skip',
79
+ manifestDiscoveryPerformed: false,
80
+ manifestCandidates: [],
81
+ authoringPermitted: false,
82
+ failedAttemptEvidence,
83
+ };
84
+ }
85
+ if (record.decision !== 'generate') {
86
+ throw consumptionError(
87
+ `Unsupported persisted recap decision: ${String(record.decision)}`,
88
+ );
89
+ }
90
+ const manifestCandidates = await discoverManifestCandidates(
91
+ join(projectRoot, 'explainers'),
92
+ );
93
+ return {
94
+ decision: 'generate',
95
+ source: record.source,
96
+ route: 'generate',
97
+ manifestDiscoveryPerformed: true,
98
+ manifestCandidates,
99
+ authoringPermitted: true,
100
+ failedAttemptEvidence: null,
101
+ };
102
+ }
103
+
104
+ async function main(argv) {
105
+ if (argv.length !== 1) {
106
+ throw consumptionError(
107
+ 'Usage: consume-persisted-recap-intent.mjs <project-path>',
108
+ );
109
+ }
110
+ return consumePersistedRecapIntent({ projectPath: argv[0] });
111
+ }
112
+
113
+ if (
114
+ process.argv[1] &&
115
+ import.meta.url === pathToFileURL(process.argv[1]).href
116
+ ) {
117
+ main(process.argv.slice(2))
118
+ .then((result) => process.stdout.write(`${JSON.stringify(result)}\n`))
119
+ .catch((error) => {
120
+ process.stderr.write(
121
+ `${JSON.stringify({ ok: false, code: error.code, message: error.message })}\n`,
122
+ );
123
+ process.exitCode = 1;
124
+ });
125
+ }
@@ -5,7 +5,6 @@ import { pathToFileURL } from 'node:url';
5
5
  import { promisify } from 'node:util';
6
6
 
7
7
  import { validateSyncedArchiveTerminalReport } from './finalize-synced-archive.mjs';
8
- import { recoverArchivedRecapEvidenceReceipt } from './recover-completion-receipts.mjs';
9
8
  import { resolveSyncedArchiveEntry } from './resolve-synced-archive-entry.mjs';
10
9
 
11
10
  const execFile = promisify(execFileCallback);
@@ -20,13 +19,9 @@ async function buildPostArchiveContinuation(
20
19
  archiveReport,
21
20
  projectPath,
22
21
  repoRoot,
23
- recoverArchiveEvidence,
24
22
  ) {
25
23
  let selectedProjectRecapRun = '';
26
24
  let exportedManifestPath = '';
27
- let exportedBuildRecordPath = '';
28
- let evidenceCommit = '';
29
- let evidencePushRequired = false;
30
25
  if (archiveReport.projectRecapExport != null) {
31
26
  const sourceRunRoot = archiveReport.projectRecapExport?.sourceRunRoot;
32
27
  const exportRoot = archiveReport.projectRecapExport?.exportRoot;
@@ -66,19 +61,6 @@ async function buildPostArchiveContinuation(
66
61
  );
67
62
  }
68
63
  exportedManifestPath = posix.join(exportRootRelative, manifestPath);
69
- exportedBuildRecordPath = posix.join(
70
- exportRootRelative,
71
- 'build-record.json',
72
- );
73
- const recoveredEvidence = await recoverArchiveEvidence({
74
- repoRoot,
75
- lifecycleCommit: archiveReport.lifecycleCommit,
76
- evidencePaths: [exportedManifestPath, exportedBuildRecordPath],
77
- });
78
- if (recoveredEvidence.evidenceCommit !== null) {
79
- evidenceCommit = recoveredEvidence.evidenceCommit;
80
- evidencePushRequired = recoveredEvidence.evidencePushRequired;
81
- }
82
64
  }
83
65
  return {
84
66
  required: true,
@@ -90,9 +72,6 @@ async function buildPostArchiveContinuation(
90
72
  selectedProjectRecapRun,
91
73
  projectRecapExport: archiveReport.projectRecapExport ?? null,
92
74
  exportedManifestPath,
93
- exportedBuildRecordPath,
94
- evidenceCommit,
95
- evidencePushRequired,
96
75
  };
97
76
  }
98
77
 
@@ -100,7 +79,6 @@ export async function continueSyncedArchiveCompletion({
100
79
  executionResult,
101
80
  finalizeLinks,
102
81
  refreshDashboard,
103
- attestRecap,
104
82
  pushBookkeeping,
105
83
  closeoutPr,
106
84
  clearPointer,
@@ -118,12 +96,6 @@ export async function continueSyncedArchiveCompletion({
118
96
  }
119
97
  await finalizeLinks(executionResult.continuation);
120
98
  await refreshDashboard(executionResult.continuation);
121
- if (
122
- executionResult.continuation.projectRecapExport !== null &&
123
- executionResult.continuation.evidenceCommit === ''
124
- ) {
125
- await attestRecap(executionResult.continuation);
126
- }
127
99
  await pushBookkeeping(executionResult.continuation);
128
100
  await closeoutPr(executionResult.continuation);
129
101
  await clearPointer(executionResult.archiveReport);
@@ -145,7 +117,6 @@ export async function executeSyncedArchiveEntry({
145
117
  runActiveWorkflowSteps,
146
118
  archiveProject,
147
119
  validateArchive,
148
- recoverArchiveEvidence = recoverArchivedRecapEvidenceReceipt,
149
120
  }) {
150
121
  const entry = record
151
122
  ? await resolveSyncedArchiveEntry({
@@ -214,7 +185,6 @@ export async function executeSyncedArchiveEntry({
214
185
  archiveReport,
215
186
  projectPath,
216
187
  repoRoot,
217
- recoverArchiveEvidence,
218
188
  ),
219
189
  };
220
190
  }
@@ -141,8 +141,6 @@ export function parseCompletionRetryFields(input) {
141
141
 
142
142
  requireExactKeys(value, [
143
143
  'candidate',
144
- 'evidenceCommit',
145
- 'evidencePushRequired',
146
144
  'localCommit',
147
145
  'nextStep',
148
146
  'prArtifactPath',
@@ -177,16 +175,6 @@ export function parseCompletionRetryFields(input) {
177
175
  'Recovered completion retry receipts must use full commit SHAs.',
178
176
  );
179
177
  }
180
- if (value.evidenceCommit !== null && !FULL_SHA.test(value.evidenceCommit)) {
181
- throw completionRetryFieldsError(
182
- 'Recovered completion retry evidence receipt must be null or a full commit SHA.',
183
- );
184
- }
185
- if (typeof value.evidencePushRequired !== 'boolean') {
186
- throw completionRetryFieldsError(
187
- 'Recovered completion retry evidence push flag must be boolean.',
188
- );
189
- }
190
178
  if (
191
179
  typeof value.retainedRef !== 'string' ||
192
180
  !RETAINED_REF.test(value.retainedRef)
@@ -203,31 +191,12 @@ export function parseCompletionRetryFields(input) {
203
191
  'Recovered completion retry PR artifact path is malformed.',
204
192
  );
205
193
  }
206
- if (value.evidenceCommit === null) {
207
- if (
208
- value.evidencePushRequired ||
209
- value.localCommit !== value.projectRefCommit ||
210
- value.remoteCommit !== value.projectRefCommit
211
- ) {
212
- throw completionRetryFieldsError(
213
- 'Recovered completion retry receipts are contradictory without evidence.',
214
- );
215
- }
216
- } else if (value.evidencePushRequired) {
217
- if (
218
- value.localCommit !== value.evidenceCommit ||
219
- value.remoteCommit !== value.projectRefCommit
220
- ) {
221
- throw completionRetryFieldsError(
222
- 'Recovered unpublished evidence receipts are contradictory.',
223
- );
224
- }
225
- } else if (
226
- value.localCommit !== value.evidenceCommit ||
227
- value.remoteCommit !== value.evidenceCommit
194
+ if (
195
+ value.localCommit !== value.projectRefCommit ||
196
+ value.remoteCommit !== value.projectRefCommit
228
197
  ) {
229
198
  throw completionRetryFieldsError(
230
- 'Recovered published evidence receipts are contradictory.',
199
+ 'Recovered completion retry receipts are contradictory.',
231
200
  );
232
201
  }
233
202
 
@@ -235,8 +204,6 @@ export function parseCompletionRetryFields(input) {
235
204
  'recovery',
236
205
  value.projectLinksPinCommit,
237
206
  value.projectRefCommit,
238
- value.evidenceCommit ?? '-',
239
- String(value.evidencePushRequired),
240
207
  value.prArtifactPath,
241
208
  ].join('\t');
242
209
  }
@@ -13,7 +13,22 @@ function shellQuote(value) {
13
13
  export function parseSyncedArchiveResumeFields(result) {
14
14
  const continuation = result?.continuation;
15
15
  const hasRecapExport = continuation?.projectRecapExport !== null;
16
+ const allowedContinuationFields = new Set([
17
+ 'required',
18
+ 'rejoinStep',
19
+ 'archivePath',
20
+ 'summaryExportFile',
21
+ 'lifecycleCommit',
22
+ 's3Path',
23
+ 'selectedProjectRecapRun',
24
+ 'projectRecapExport',
25
+ 'exportedManifestPath',
26
+ ]);
16
27
  if (
28
+ !continuation ||
29
+ Object.keys(continuation).some(
30
+ (field) => !allowedContinuationFields.has(field),
31
+ ) ||
17
32
  result?.status !== 'ok' ||
18
33
  result?.route !== 'archive-resumed' ||
19
34
  result?.terminal !== true ||
@@ -25,21 +40,10 @@ export function parseSyncedArchiveResumeFields(result) {
25
40
  continuation.archivePath.length === 0 ||
26
41
  typeof continuation.lifecycleCommit !== 'string' ||
27
42
  !/^[0-9a-f]{40}$/.test(continuation.lifecycleCommit) ||
28
- typeof continuation.evidenceCommit !== 'string' ||
29
- (continuation.evidenceCommit !== '' &&
30
- !/^[0-9a-f]{40}$/.test(continuation.evidenceCommit)) ||
31
- typeof continuation.evidencePushRequired !== 'boolean' ||
32
- (continuation.evidenceCommit === '' &&
33
- continuation.evidencePushRequired !== false) ||
34
43
  (hasRecapExport &&
35
44
  (typeof continuation.exportedManifestPath !== 'string' ||
36
- continuation.exportedManifestPath.length === 0 ||
37
- typeof continuation.exportedBuildRecordPath !== 'string' ||
38
- continuation.exportedBuildRecordPath.length === 0)) ||
39
- (!hasRecapExport &&
40
- (continuation.exportedManifestPath !== '' ||
41
- continuation.exportedBuildRecordPath !== '' ||
42
- continuation.evidenceCommit !== ''))
45
+ continuation.exportedManifestPath.length === 0)) ||
46
+ (!hasRecapExport && continuation.exportedManifestPath !== '')
43
47
  ) {
44
48
  throw fieldsError(
45
49
  'Synced archive resume result has no verified post-archive continuation.',
@@ -59,10 +63,7 @@ export function parseSyncedArchiveResumeFields(result) {
59
63
  PROJECT_RECAP_EXPORT_JSON: JSON.stringify(
60
64
  continuation.projectRecapExport ?? null,
61
65
  ),
62
- EVIDENCE_COMMIT: continuation.evidenceCommit,
63
- EVIDENCE_PUSH_REQUIRED: String(continuation.evidencePushRequired),
64
66
  EXPORTED_MANIFEST_PATH: continuation.exportedManifestPath,
65
- EXPORTED_BUILD_RECORD_PATH: continuation.exportedBuildRecordPath,
66
67
  PROJECT_REF_COMMIT: '',
67
68
  SHOULD_OPEN_PR: 'false',
68
69
  };
@@ -7,7 +7,6 @@ const execFileAsync = promisify(execFile);
7
7
 
8
8
  const PIN_SOURCE_MESSAGE = 'chore(oat): finalize project lifecycle';
9
9
  const FINAL_ARTIFACT_MESSAGE = 'chore(oat): publish final project links';
10
- const EVIDENCE_MESSAGE = 'chore(oat): attest final project recap';
11
10
  const LINKS_START = '<!-- oat:project-links:start -->';
12
11
  const LINKS_END = '<!-- oat:project-links:end -->';
13
12
  const FULL_SHA = /^[0-9a-f]{40}$/;
@@ -91,23 +90,6 @@ async function changedPaths(projectPath, commit) {
91
90
  return output === '' ? [] : output.split('\n').sort();
92
91
  }
93
92
 
94
- async function isAncestor(projectPath, ancestor, descendant) {
95
- try {
96
- await execFileAsync(
97
- 'git',
98
- ['merge-base', '--is-ancestor', ancestor, descendant],
99
- { cwd: projectPath, encoding: 'utf8' },
100
- );
101
- return true;
102
- } catch (error) {
103
- if (error?.code === 1) return false;
104
- const detail = error?.stderr?.trim() || error?.message || String(error);
105
- throw completionReceiptError(
106
- `git merge-base failed while recovering completion receipts: ${detail}`,
107
- );
108
- }
109
- }
110
-
111
93
  async function committedFile(projectPath, commit, path, label) {
112
94
  const content = await git(projectPath, ['show', `${commit}:${path}`], {
113
95
  allowFailure: true,
@@ -394,7 +376,7 @@ export async function detectCompletionReceiptCandidate({
394
376
  'Retained ref must be a canonical OAT project ref.',
395
377
  );
396
378
  }
397
- const receiptSubjects = new Set([FINAL_ARTIFACT_MESSAGE, EVIDENCE_MESSAGE]);
379
+ const receiptSubjects = new Set([FINAL_ARTIFACT_MESSAGE]);
398
380
  const head = await git(projectPath, ['rev-parse', 'HEAD']);
399
381
  const retained = await git(
400
382
  projectPath,
@@ -528,7 +510,6 @@ export async function recoverCompletionReceipts({
528
510
  projectPath,
529
511
  retainedRef,
530
512
  prArtifactPath,
531
- evidencePaths = [],
532
513
  remote = 'origin',
533
514
  }) {
534
515
  if (typeof projectPath !== 'string' || projectPath.length === 0) {
@@ -552,13 +533,6 @@ export async function recoverCompletionReceipts({
552
533
  `Project checkout basename must match retained project ${expectedSlug}.`,
553
534
  );
554
535
  }
555
- const exactEvidencePaths = evidencePaths.map((path, index) =>
556
- requireRelativeGitPath(path, `Evidence path ${index + 1}`),
557
- );
558
- if (new Set(exactEvidencePaths).size !== exactEvidencePaths.length) {
559
- throw completionReceiptError('Evidence paths must be unique.');
560
- }
561
-
562
536
  const status = await git(projectPath, [
563
537
  'status',
564
538
  '--porcelain=v1',
@@ -594,60 +568,17 @@ export async function recoverCompletionReceipts({
594
568
  const expectedRepository = parseGitHubRepository(remoteUrl);
595
569
  const localSubject = await commitSubject(projectPath, localCommit);
596
570
 
597
- let finalArtifactCommit;
598
- let evidenceCommit = null;
599
- let evidencePushRequired = false;
600
-
601
- if (localSubject === FINAL_ARTIFACT_MESSAGE) {
602
- if (
603
- localCommit !== remoteCommit ||
604
- localRetainedRefCommit !== localCommit
605
- ) {
606
- throw completionReceiptError(
607
- 'Final-artifact receipt recovery requires equal checkout, local retained ref, and remote retained ref commits.',
608
- );
609
- }
610
- finalArtifactCommit = localCommit;
611
- } else if (localSubject === EVIDENCE_MESSAGE) {
612
- if (exactEvidencePaths.length === 0) {
613
- throw completionReceiptError(
614
- 'Recap-evidence receipt recovery requires exact evidence paths.',
615
- );
616
- }
617
- evidenceCommit = localCommit;
618
- requireExactPaths(
619
- await changedPaths(projectPath, evidenceCommit),
620
- exactEvidencePaths,
621
- 'Recap evidence commit',
622
- );
623
- finalArtifactCommit = await singleParent(
624
- projectPath,
625
- evidenceCommit,
626
- 'Recap evidence commit',
627
- );
628
- if (remoteCommit === finalArtifactCommit) {
629
- if (localRetainedRefCommit !== finalArtifactCommit) {
630
- throw completionReceiptError(
631
- 'Unpublished recap evidence requires the local retained ref to remain at the final-artifact parent.',
632
- );
633
- }
634
- evidencePushRequired = true;
635
- } else if (remoteCommit === evidenceCommit) {
636
- if (localRetainedRefCommit !== evidenceCommit) {
637
- throw completionReceiptError(
638
- 'Published recap evidence requires equal local and remote retained refs.',
639
- );
640
- }
641
- } else {
642
- throw completionReceiptError(
643
- 'Recap-evidence recovery requires the remote retained ref to equal either the evidence commit or its final-artifact parent.',
644
- );
645
- }
646
- } else {
571
+ if (localSubject !== FINAL_ARTIFACT_MESSAGE) {
647
572
  throw completionReceiptError(
648
573
  `HEAD subject ${JSON.stringify(localSubject)} is not an exact completion receipt.`,
649
574
  );
650
575
  }
576
+ if (localCommit !== remoteCommit || localRetainedRefCommit !== localCommit) {
577
+ throw completionReceiptError(
578
+ 'Final-artifact receipt recovery requires equal checkout, local retained ref, and remote retained ref commits.',
579
+ );
580
+ }
581
+ const finalArtifactCommit = localCommit;
651
582
 
652
583
  if (
653
584
  (await commitSubject(projectPath, finalArtifactCommit)) !==
@@ -710,101 +641,6 @@ export async function recoverCompletionReceipts({
710
641
  remoteCommit,
711
642
  projectLinksPinCommit,
712
643
  projectRefCommit: finalArtifactCommit,
713
- evidenceCommit,
714
- evidencePushRequired,
715
- };
716
- }
717
-
718
- export async function recoverArchivedRecapEvidenceReceipt({
719
- repoRoot,
720
- lifecycleCommit,
721
- evidencePaths,
722
- }) {
723
- if (typeof repoRoot !== 'string' || repoRoot.length === 0) {
724
- throw completionReceiptError(
725
- 'Archived recap evidence recovery requires the repository root.',
726
- );
727
- }
728
- if (!FULL_SHA.test(lifecycleCommit ?? '')) {
729
- throw completionReceiptError(
730
- 'Archived recap evidence recovery requires a full lifecycle commit SHA.',
731
- );
732
- }
733
- if (!Array.isArray(evidencePaths) || evidencePaths.length !== 2) {
734
- throw completionReceiptError(
735
- 'Archived recap evidence recovery requires exactly two evidence paths.',
736
- );
737
- }
738
- const exactEvidencePaths = evidencePaths.map((path, index) =>
739
- requireRelativeGitPath(path, `Archived evidence path ${index + 1}`),
740
- );
741
- if (new Set(exactEvidencePaths).size !== exactEvidencePaths.length) {
742
- throw completionReceiptError('Archived evidence paths must be unique.');
743
- }
744
-
745
- const resolvedLifecycle = await git(repoRoot, [
746
- 'rev-parse',
747
- '--verify',
748
- `${lifecycleCommit}^{commit}`,
749
- ]);
750
- if (resolvedLifecycle !== lifecycleCommit) {
751
- throw completionReceiptError(
752
- 'Archived recap lifecycle receipt does not resolve to the exact commit.',
753
- );
754
- }
755
- const head = await git(repoRoot, ['rev-parse', 'HEAD']);
756
- if (head === lifecycleCommit) {
757
- return {
758
- status: 'none',
759
- evidenceCommit: null,
760
- evidencePushRequired: false,
761
- evidencePaths: exactEvidencePaths,
762
- };
763
- }
764
- if ((await commitSubject(repoRoot, head)) !== EVIDENCE_MESSAGE) {
765
- throw completionReceiptError(
766
- 'Archived recap retry HEAD is neither the lifecycle commit nor the exact evidence commit.',
767
- );
768
- }
769
- if (
770
- (await singleParent(repoRoot, head, 'Archived recap evidence commit')) !==
771
- lifecycleCommit
772
- ) {
773
- throw completionReceiptError(
774
- 'Archived recap evidence commit must be the immediate child of the lifecycle commit.',
775
- );
776
- }
777
- requireExactPaths(
778
- await changedPaths(repoRoot, head),
779
- exactEvidencePaths,
780
- 'Archived recap evidence commit',
781
- );
782
-
783
- const upstream = await git(
784
- repoRoot,
785
- ['rev-parse', '--verify', '@{u}^{commit}'],
786
- { allowFailure: true },
787
- );
788
- let evidencePushRequired;
789
- if (upstream === head) {
790
- evidencePushRequired = false;
791
- } else if (
792
- upstream === null ||
793
- (FULL_SHA.test(upstream) &&
794
- (await isAncestor(repoRoot, upstream, lifecycleCommit)))
795
- ) {
796
- evidencePushRequired = true;
797
- } else {
798
- throw completionReceiptError(
799
- 'Archived recap evidence retry requires upstream to equal the evidence commit or remain an ancestor of its lifecycle parent.',
800
- );
801
- }
802
-
803
- return {
804
- status: 'recovered',
805
- evidenceCommit: head,
806
- evidencePushRequired,
807
- evidencePaths: exactEvidencePaths,
808
644
  };
809
645
  }
810
646
 
@@ -815,7 +651,7 @@ function parseBoolean(value, label) {
815
651
  }
816
652
 
817
653
  function parseArguments(argv) {
818
- const result = { evidencePaths: [] };
654
+ const result = {};
819
655
  for (let index = 0; index < argv.length; index += 2) {
820
656
  const flag = argv[index];
821
657
  const value = argv[index + 1];
@@ -825,7 +661,6 @@ function parseArguments(argv) {
825
661
  if (flag === '--project-path') result.projectPath = value;
826
662
  else if (flag === '--retained-ref') result.retainedRef = value;
827
663
  else if (flag === '--pr-artifact') result.prArtifactPath = value;
828
- else if (flag === '--evidence-path') result.evidencePaths.push(value);
829
664
  else if (flag === '--remote') result.remote = value;
830
665
  else if (flag === '--detect-candidate') {
831
666
  result.detectCandidate = parseBoolean(value, flag);
@@ -23,7 +23,7 @@ function completionRetryError(message) {
23
23
  }
24
24
 
25
25
  function parseArguments(argv) {
26
- const result = { evidencePaths: [] };
26
+ const result = {};
27
27
  for (let index = 0; index < argv.length; index += 2) {
28
28
  const flag = argv[index];
29
29
  const value = argv[index + 1];
@@ -33,7 +33,6 @@ function parseArguments(argv) {
33
33
  if (flag === '--project-path') result.projectPath = value;
34
34
  else if (flag === '--retained-ref') result.retainedRef = value;
35
35
  else if (flag === '--pr-artifact') result.prArtifactPath = value;
36
- else if (flag === '--evidence-path') result.evidencePaths.push(value);
37
36
  else if (flag === '--remote') result.remote = value;
38
37
  else throw completionRetryError(`Unsupported argument: ${flag}.`);
39
38
  }
@@ -6,7 +6,7 @@ disable-model-invocation: false
6
6
  user-invocable: true
7
7
  allowed-tools: Read, Write, Edit, Bash(git:*), Bash(jq:*), Bash(oat pjm:*), Bash(oat project push:*), Bash(oat project scope:*), Bash(oat tools:*), Glob, Grep, AskUserQuestion, Skill
8
8
  metadata:
9
- version: 1.8.3
9
+ version: 1.8.4
10
10
  ---
11
11
 
12
12
  # Project Documentation Sync