@open-agent-toolkit/cli 0.2.73 → 0.2.75

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 (149) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/cli-utilities/configuration.md +3 -56
  3. package/assets/docs/cli-utilities/tool-packs.md +4 -4
  4. package/assets/docs/contributing/code.md +2 -2
  5. package/assets/docs/contributing/index.md +0 -1
  6. package/assets/docs/reference/cli-reference.md +1 -1
  7. package/assets/docs/reference/troubleshooting.md +17 -40
  8. package/assets/docs/workflows/projects/artifacts.md +16 -34
  9. package/assets/docs/workflows/projects/lifecycle.md +20 -19
  10. package/assets/docs/workflows/skills/explainer-kit.md +180 -440
  11. package/assets/docs/workflows/skills/index.md +1 -2
  12. package/assets/public-package-versions.json +4 -4
  13. package/assets/skills/explainer-kit/SKILL.md +96 -171
  14. package/assets/skills/explainer-kit/recipes/engineer-tour.json +1 -22
  15. package/assets/skills/explainer-kit/recipes/program-recap.json +1 -29
  16. package/assets/skills/explainer-kit/recipes/project-explainer.json +1 -22
  17. package/assets/skills/explainer-kit/recipes/project-recap.v2.json +1 -43
  18. package/assets/skills/explainer-kit/references/fact-base-contract.md +76 -101
  19. package/assets/skills/explainer-kit/references/recap-authoring.md +99 -0
  20. package/assets/skills/explainer-kit/schemas/manifest.schema.json +13 -135
  21. package/assets/skills/explainer-kit/scripts/bundle.mjs +712 -0
  22. package/assets/skills/explainer-kit/scripts/lib/claim-subject.mjs +40 -0
  23. package/assets/skills/explainer-kit/scripts/lib/contracts.mjs +113 -1504
  24. package/assets/skills/explainer-kit/scripts/lib/failure.mjs +13 -0
  25. package/assets/skills/explainer-kit/scripts/lib/package-coverage.mjs +57 -403
  26. package/assets/skills/explainer-kit/scripts/lib/qa-result.mjs +168 -0
  27. package/assets/skills/explainer-kit/scripts/lib/qa.mjs +90 -488
  28. package/assets/skills/explainer-kit/scripts/lib/recipes.mjs +28 -545
  29. package/assets/skills/explainer-kit/scripts/lib/run-package.mjs +120 -0
  30. package/assets/skills/explainer-kit/scripts/lib/sanitize.mjs +42 -0
  31. package/assets/skills/explainer-kit/scripts/record.mjs +335 -0
  32. package/assets/skills/explainer-kit/scripts/verify.mjs +648 -0
  33. package/assets/skills/oat-explainer-kit/SKILL.md +57 -117
  34. package/assets/skills/oat-explainer-kit/references/config-contract.md +20 -64
  35. package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +85 -237
  36. package/assets/skills/oat-explainer-kit/scripts/bind-project-sources.mjs +18 -10
  37. package/assets/skills/oat-explainer-kit/scripts/check-core.mjs +1 -0
  38. package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +256 -21
  39. package/assets/skills/oat-explainer-kit/scripts/persist-intent.mjs +82 -3
  40. package/assets/skills/oat-explainer-kit/scripts/resolve-config.mjs +0 -162
  41. package/assets/skills/oat-explainer-kit/scripts/resolve-intent.mjs +57 -123
  42. package/assets/skills/oat-project-autonomous/SKILL.md +14 -13
  43. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +165 -165
  44. package/assets/skills/oat-project-complete/SKILL.md +168 -349
  45. package/assets/skills/oat-project-complete/scripts/consume-persisted-recap-intent.mjs +125 -0
  46. package/assets/skills/oat-project-complete/scripts/execute-synced-archive-entry.mjs +0 -30
  47. package/assets/skills/oat-project-complete/scripts/parse-completion-retry-fields.mjs +4 -37
  48. package/assets/skills/oat-project-complete/scripts/parse-synced-archive-resume-fields.mjs +17 -16
  49. package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +9 -174
  50. package/assets/skills/oat-project-complete/scripts/resolve-completion-retry.mjs +1 -2
  51. package/assets/skills/oat-project-document/SKILL.md +1 -1
  52. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +165 -165
  53. package/assets/skills/oat-project-implement/SKILL.md +1 -1
  54. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +44 -56
  55. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +165 -165
  56. package/assets/skills/oat-project-lite/SKILL.md +1 -1
  57. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +165 -165
  58. package/assets/skills/oat-project-plan/SKILL.md +5 -6
  59. package/assets/skills/oat-project-pr-final/SKILL.md +1 -1
  60. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +165 -165
  61. package/assets/skills/oat-project-quick-start/SKILL.md +1 -1
  62. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +165 -165
  63. package/assets/skills/oat-project-summary/SKILL.md +35 -25
  64. package/assets/skills/oat-wave-execute/SKILL.md +11 -36
  65. package/assets/skills/oat-wave-program/SKILL.md +13 -37
  66. package/dist/commands/config/index.d.ts.map +1 -1
  67. package/dist/commands/config/index.js +9 -113
  68. package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
  69. package/dist/commands/project/archive/archive-utils.js +32 -184
  70. package/dist/commands/project/archive/explainer-package-coverage.d.ts +3 -8
  71. package/dist/commands/project/archive/explainer-package-coverage.d.ts.map +1 -1
  72. package/dist/commands/project/archive/explainer-package-coverage.js +1 -1
  73. package/dist/config/oat-config.d.ts +0 -11
  74. package/dist/config/oat-config.d.ts.map +1 -1
  75. package/dist/config/oat-config.js +0 -34
  76. package/dist/config/resolve.d.ts.map +1 -1
  77. package/dist/config/resolve.js +0 -8
  78. package/dist/release/public-package-contract.d.ts.map +1 -1
  79. package/dist/release/public-package-contract.js +2 -10
  80. package/dist/validation/project-state.d.ts.map +1 -1
  81. package/dist/validation/project-state.js +42 -3
  82. package/package.json +2 -2
  83. package/assets/docs/contributing/explainer-kit-verification.md +0 -133
  84. package/assets/docs/workflows/skills/explainer-kit-providers.md +0 -155
  85. package/assets/skills/explainer-kit/briefs/deep-dive.md +0 -35
  86. package/assets/skills/explainer-kit/briefs/project-page.md +0 -38
  87. package/assets/skills/explainer-kit/briefs/supporting-diagram.md +0 -28
  88. package/assets/skills/explainer-kit/briefs/walkthrough-deck.md +0 -35
  89. package/assets/skills/explainer-kit/examples/project-explainer/content.md +0 -31
  90. package/assets/skills/explainer-kit/examples/project-explainer/fact-base.md +0 -22
  91. package/assets/skills/explainer-kit/examples/project-recap/content.md +0 -77
  92. package/assets/skills/explainer-kit/examples/project-recap/fact-base.json +0 -104
  93. package/assets/skills/explainer-kit/examples/project-recap/fact-base.md +0 -44
  94. package/assets/skills/explainer-kit/examples/theme-bundle.json +0 -87
  95. package/assets/skills/explainer-kit/recipes/project-recap.v1.json +0 -93
  96. package/assets/skills/explainer-kit/references/contracts.md +0 -324
  97. package/assets/skills/explainer-kit/references/destination-contract.md +0 -210
  98. package/assets/skills/explainer-kit/references/extension-contract.md +0 -80
  99. package/assets/skills/explainer-kit/references/golden-conformance.md +0 -80
  100. package/assets/skills/explainer-kit/references/visual-review.md +0 -71
  101. package/assets/skills/explainer-kit/schemas/author-request.v2.schema.json +0 -212
  102. package/assets/skills/explainer-kit/schemas/author-request.v3.schema.json +0 -241
  103. package/assets/skills/explainer-kit/schemas/author-result.v2.schema.json +0 -52
  104. package/assets/skills/explainer-kit/schemas/build-record.schema.json +0 -98
  105. package/assets/skills/explainer-kit/schemas/durability-evidence.schema.json +0 -53
  106. package/assets/skills/explainer-kit/schemas/publish-receipt.v1.schema.json +0 -97
  107. package/assets/skills/explainer-kit/schemas/publish-receipt.v2.schema.json +0 -215
  108. package/assets/skills/explainer-kit/schemas/publish-request.v1.schema.json +0 -32
  109. package/assets/skills/explainer-kit/schemas/publish-request.v2.schema.json +0 -34
  110. package/assets/skills/explainer-kit/schemas/run-request.schema.json +0 -147
  111. package/assets/skills/explainer-kit/schemas/set-plan.v1.schema.json +0 -149
  112. package/assets/skills/explainer-kit/schemas/terminal-evidence.v1.schema.json +0 -81
  113. package/assets/skills/explainer-kit/schemas/visual-review-evidence.v1.schema.json +0 -66
  114. package/assets/skills/explainer-kit/schemas/visual-review-request.v1.schema.json +0 -117
  115. package/assets/skills/explainer-kit/schemas/visual-review-result.v1.schema.json +0 -80
  116. package/assets/skills/explainer-kit/scripts/lib/catalog.mjs +0 -349
  117. package/assets/skills/explainer-kit/scripts/lib/content-approval.mjs +0 -418
  118. package/assets/skills/explainer-kit/scripts/lib/diagram.mjs +0 -514
  119. package/assets/skills/explainer-kit/scripts/lib/durability.mjs +0 -643
  120. package/assets/skills/explainer-kit/scripts/lib/fact-base.mjs +0 -664
  121. package/assets/skills/explainer-kit/scripts/lib/internal-references.mjs +0 -538
  122. package/assets/skills/explainer-kit/scripts/lib/markdown.mjs +0 -414
  123. package/assets/skills/explainer-kit/scripts/lib/publication-policy.mjs +0 -54
  124. package/assets/skills/explainer-kit/scripts/lib/records.mjs +0 -954
  125. package/assets/skills/explainer-kit/scripts/lib/render.mjs +0 -703
  126. package/assets/skills/explainer-kit/scripts/lib/s3-roots.mjs +0 -353
  127. package/assets/skills/explainer-kit/scripts/lib/s3-static.mjs +0 -759
  128. package/assets/skills/explainer-kit/scripts/lib/set-plan.mjs +0 -209
  129. package/assets/skills/explainer-kit/scripts/lib/source-backlinks.mjs +0 -218
  130. package/assets/skills/explainer-kit/scripts/lib/terminal-evidence.mjs +0 -157
  131. package/assets/skills/explainer-kit/scripts/lib/visual-review.mjs +0 -400
  132. package/assets/skills/explainer-kit/scripts/publish.mjs +0 -76
  133. package/assets/skills/explainer-kit/scripts/record-durability.mjs +0 -64
  134. package/assets/skills/explainer-kit/scripts/render-qa.mjs +0 -461
  135. package/assets/skills/explainer-kit/scripts/run.mjs +0 -3038
  136. package/assets/skills/explainer-kit/scripts/validate.mjs +0 -59
  137. package/assets/skills/oat-explainer-kit/references/author-callback.md +0 -53
  138. package/assets/skills/oat-explainer-kit/references/migration.md +0 -144
  139. package/assets/skills/oat-explainer-kit/references/visual-review-callback.md +0 -83
  140. package/assets/skills/oat-explainer-kit/scripts/derive-destination.mjs +0 -91
  141. package/assets/skills/oat-explainer-kit/scripts/finalize-tracked-run.mjs +0 -531
  142. package/assets/skills/oat-explainer-kit/scripts/probe-recap-seams.mjs +0 -371
  143. package/assets/skills/oat-explainer-kit/scripts/run.mjs +0 -905
  144. package/dist/commands/project/archive/explainer-source-backlinks.d.ts +0 -18
  145. package/dist/commands/project/archive/explainer-source-backlinks.d.ts.map +0 -1
  146. package/dist/commands/project/archive/explainer-source-backlinks.js +0 -27
  147. package/dist/commands/project/archive/explainer-terminal-evidence.d.ts +0 -29
  148. package/dist/commands/project/archive/explainer-terminal-evidence.d.ts.map +0 -1
  149. 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