@open-agent-toolkit/cli 0.2.40 → 0.2.45
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.
- package/assets/agents/oat-codebase-mapper.md +15 -3
- package/assets/agents/oat-phase-implementer.md +34 -9
- package/assets/agents/oat-reviewer.md +2 -2
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/configuration.md +11 -1
- package/assets/docs/cli-utilities/tool-packs.md +8 -0
- package/assets/docs/contributing/skills.md +67 -14
- package/assets/docs/quickstart.md +9 -0
- package/assets/docs/reference/cli-reference.md +56 -1
- package/assets/docs/reference/file-locations.md +18 -1
- package/assets/docs/reference/oat-directory-structure.md +20 -4
- package/assets/docs/workflows/projects/artifacts.md +27 -1
- package/assets/docs/workflows/projects/implementation-execution.md +22 -0
- package/assets/docs/workflows/projects/index.md +6 -0
- package/assets/docs/workflows/projects/lifecycle.md +19 -5
- package/assets/docs/workflows/projects/picking-up-projects.md +75 -0
- package/assets/docs/workflows/projects/pr-flow.md +22 -1
- package/assets/docs/workflows/projects/reviewing-oat-prs.md +60 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/analyze/SKILL.md +13 -5
- package/assets/skills/compare/SKILL.md +11 -2
- package/assets/skills/oat-brainstorm/SKILL.md +135 -32
- package/assets/skills/oat-brainstorm/references/destinations.md +9 -6
- package/assets/skills/oat-cursor-cloud-projects/SKILL.md +11 -1
- package/assets/skills/oat-dispatch-subagents/SKILL.md +19 -6
- package/assets/skills/oat-doctor/SKILL.md +8 -1
- package/assets/skills/oat-project-autonomous/SKILL.md +45 -1
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +8 -8
- package/assets/skills/oat-project-capture/SKILL.md +29 -9
- package/assets/skills/oat-project-complete/SKILL.md +610 -38
- package/assets/skills/oat-project-complete/scripts/parse-completion-retry-fields.mjs +265 -0
- package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +764 -0
- package/assets/skills/oat-project-complete/scripts/resolve-completion-retry.mjs +134 -0
- package/assets/skills/oat-project-complete/scripts/validate-nonarchive-lifecycle-receipt.mjs +160 -0
- package/assets/skills/oat-project-design/SKILL.md +33 -9
- package/assets/skills/oat-project-discover/SKILL.md +16 -3
- package/assets/skills/oat-project-document/SKILL.md +10 -4
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-implement/SKILL.md +14 -3
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +18 -6
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-implement/references/phase-execution.md +9 -3
- package/assets/skills/oat-project-implement/references/plan-and-resume.md +3 -0
- package/assets/skills/oat-project-import-plan/SKILL.md +15 -9
- package/assets/skills/oat-project-new/SKILL.md +7 -5
- package/assets/skills/oat-project-next/SKILL.md +32 -10
- package/assets/skills/oat-project-plan/SKILL.md +18 -3
- package/assets/skills/oat-project-pr-final/SKILL.md +23 -2
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-pr-progress/SKILL.md +23 -2
- package/assets/skills/oat-project-progress/SKILL.md +23 -9
- package/assets/skills/oat-project-promote-spec-driven/SKILL.md +20 -2
- package/assets/skills/oat-project-quick-start/SKILL.md +48 -18
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +8 -8
- package/assets/skills/oat-project-reconcile/SKILL.md +14 -10
- package/assets/skills/oat-project-retro/SKILL.md +3 -3
- package/assets/skills/oat-project-retro/references/apply-procedure.md +102 -6
- package/assets/skills/oat-project-retro-file/SKILL.md +57 -6
- package/assets/skills/oat-project-review-provide/SKILL.md +56 -6
- package/assets/skills/oat-project-review-receive/SKILL.md +16 -7
- package/assets/skills/oat-project-review-receive-remote/SKILL.md +9 -3
- package/assets/skills/oat-project-revise/SKILL.md +12 -3
- package/assets/skills/oat-project-spec/SKILL.md +16 -3
- package/assets/skills/oat-project-summary/SKILL.md +113 -13
- package/assets/skills/oat-repo-improve/SKILL.md +18 -7
- package/assets/skills/oat-review-provide-remote/SKILL.md +11 -2
- package/assets/skills/oat-wave-execute/SKILL.md +34 -2
- package/assets/skills/oat-worktree-bootstrap/SKILL.md +13 -1
- package/assets/skills/oat-worktree-bootstrap-auto/SKILL.md +13 -1
- package/dist/commands/config/index.d.ts +1 -0
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +30 -2
- package/dist/commands/doctor/index.d.ts +2 -0
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +27 -3
- package/dist/commands/doctor/synced-projects.d.ts +12 -0
- package/dist/commands/doctor/synced-projects.d.ts.map +1 -0
- package/dist/commands/doctor/synced-projects.js +208 -0
- package/dist/commands/init/gitattributes.d.ts +4 -0
- package/dist/commands/init/gitattributes.d.ts.map +1 -0
- package/dist/commands/init/gitattributes.js +12 -0
- package/dist/commands/init/gitignore.d.ts +8 -1
- package/dist/commands/init/gitignore.d.ts.map +1 -1
- package/dist/commands/init/gitignore.js +146 -41
- package/dist/commands/init/index.d.ts +2 -0
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +3 -0
- package/dist/commands/init/managed-block.d.ts +10 -0
- package/dist/commands/init/managed-block.d.ts.map +1 -0
- package/dist/commands/init/managed-block.js +40 -0
- package/dist/commands/init/tools/workflows/install-workflows.js +1 -1
- package/dist/commands/local/index.d.ts.map +1 -1
- package/dist/commands/local/index.js +5 -1
- package/dist/commands/local/sync.d.ts +4 -0
- package/dist/commands/local/sync.d.ts.map +1 -1
- package/dist/commands/local/sync.js +123 -2
- package/dist/commands/pjm/adoption.d.ts +2 -0
- package/dist/commands/pjm/adoption.d.ts.map +1 -1
- package/dist/commands/pjm/adoption.js +1 -1
- package/dist/commands/project/archive/archive-utils.d.ts +24 -0
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +349 -22
- package/dist/commands/project/archive/index.d.ts.map +1 -1
- package/dist/commands/project/archive/index.js +1 -0
- package/dist/commands/project/archive/push-runner.d.ts +5 -1
- package/dist/commands/project/archive/push-runner.d.ts.map +1 -1
- package/dist/commands/project/archive/push-runner.js +33 -4
- package/dist/commands/project/complete-state/index.d.ts.map +1 -1
- package/dist/commands/project/complete-state/index.js +3 -1
- package/dist/commands/project/index.d.ts.map +1 -1
- package/dist/commands/project/index.js +12 -0
- package/dist/commands/project/links/compute.d.ts +9 -0
- package/dist/commands/project/links/compute.d.ts.map +1 -0
- package/dist/commands/project/links/compute.js +27 -0
- package/dist/commands/project/links/index.d.ts +17 -0
- package/dist/commands/project/links/index.d.ts.map +1 -0
- package/dist/commands/project/links/index.js +72 -0
- package/dist/commands/project/links/refresh.d.ts +26 -0
- package/dist/commands/project/links/refresh.d.ts.map +1 -0
- package/dist/commands/project/links/refresh.js +92 -0
- package/dist/commands/project/links/render.d.ts +24 -0
- package/dist/commands/project/links/render.d.ts.map +1 -0
- package/dist/commands/project/links/render.js +68 -0
- package/dist/commands/project/list.d.ts +5 -0
- package/dist/commands/project/list.d.ts.map +1 -1
- package/dist/commands/project/list.js +182 -9
- package/dist/commands/project/migrate/index.d.ts +22 -0
- package/dist/commands/project/migrate/index.d.ts.map +1 -0
- package/dist/commands/project/migrate/index.js +79 -0
- package/dist/commands/project/new/index.d.ts +2 -0
- package/dist/commands/project/new/index.d.ts.map +1 -1
- package/dist/commands/project/new/index.js +14 -2
- package/dist/commands/project/new/scaffold.d.ts +22 -1
- package/dist/commands/project/new/scaffold.d.ts.map +1 -1
- package/dist/commands/project/new/scaffold.js +287 -69
- package/dist/commands/project/open/index.d.ts +16 -0
- package/dist/commands/project/open/index.d.ts.map +1 -1
- package/dist/commands/project/open/index.js +151 -19
- package/dist/commands/project/pause/index.d.ts +8 -0
- package/dist/commands/project/pause/index.d.ts.map +1 -1
- package/dist/commands/project/pause/index.js +129 -19
- package/dist/commands/project/prune/index.d.ts +21 -0
- package/dist/commands/project/prune/index.d.ts.map +1 -0
- package/dist/commands/project/prune/index.js +95 -0
- package/dist/commands/project/pull/index.d.ts +28 -0
- package/dist/commands/project/pull/index.d.ts.map +1 -0
- package/dist/commands/project/pull/index.js +157 -0
- package/dist/commands/project/push/index.d.ts +22 -0
- package/dist/commands/project/push/index.d.ts.map +1 -0
- package/dist/commands/project/push/index.js +100 -0
- package/dist/commands/project/scope/index.d.ts +17 -0
- package/dist/commands/project/scope/index.d.ts.map +1 -0
- package/dist/commands/project/scope/index.js +107 -0
- package/dist/commands/project/split/run.d.ts +4 -0
- package/dist/commands/project/split/run.d.ts.map +1 -1
- package/dist/commands/project/split/run.js +48 -10
- package/dist/commands/project/sync/git.d.ts +18 -0
- package/dist/commands/project/sync/git.d.ts.map +1 -0
- package/dist/commands/project/sync/git.js +60 -0
- package/dist/commands/project/sync/record.d.ts +22 -0
- package/dist/commands/project/sync/record.d.ts.map +1 -0
- package/dist/commands/project/sync/record.js +133 -0
- package/dist/commands/project/sync/ref-sync.d.ts +120 -0
- package/dist/commands/project/sync/ref-sync.d.ts.map +1 -0
- package/dist/commands/project/sync/ref-sync.js +962 -0
- package/dist/commands/project/sync/resolve-target.d.ts +27 -0
- package/dist/commands/project/sync/resolve-target.d.ts.map +1 -0
- package/dist/commands/project/sync/resolve-target.js +159 -0
- package/dist/commands/shared/oat-paths.d.ts +4 -1
- package/dist/commands/shared/oat-paths.d.ts.map +1 -1
- package/dist/commands/shared/oat-paths.js +2 -2
- package/dist/commands/shared/project-scope.d.ts +23 -0
- package/dist/commands/shared/project-scope.d.ts.map +1 -0
- package/dist/commands/shared/project-scope.js +106 -0
- package/dist/commands/tools/migrate/index.js +1 -1
- package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-inventory.js +11 -0
- package/dist/commands/tools/shared/pack-lifecycle.js +1 -1
- package/dist/commands/tools/shared/pack-reconcile.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-reconcile.js +4 -1
- package/dist/commands/tools/update/index.d.ts.map +1 -1
- package/dist/commands/tools/update/index.js +20 -10
- package/dist/commands/tools/update/update-tools.d.ts +2 -0
- package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
- package/dist/config/oat-config.d.ts +6 -3
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +41 -7
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +2 -1
- package/dist/fs/io.d.ts +2 -1
- package/dist/fs/io.d.ts.map +1 -1
- package/dist/fs/io.js +5 -2
- package/dist/projects/split/finalize.d.ts.map +1 -1
- package/dist/projects/split/finalize.js +55 -2
- package/dist/projects/split/resume.d.ts +3 -0
- package/dist/projects/split/resume.d.ts.map +1 -1
- package/dist/projects/split/resume.js +34 -7
- package/dist/projects/split/seed-children.d.ts.map +1 -1
- package/dist/projects/split/seed-children.js +6 -0
- package/dist/projects/split/write-parent.d.ts +7 -0
- package/dist/projects/split/write-parent.d.ts.map +1 -1
- package/dist/projects/split/write-parent.js +7 -4
- package/dist/release/public-package-contract.d.ts.map +1 -1
- package/dist/release/public-package-contract.js +1 -0
- package/dist/validation/skills.d.ts.map +1 -1
- package/dist/validation/skills.js +434 -0
- package/package.json +4 -4
- package/dist/__tests__/skills/split-flow-fixtures.d.ts +0 -50
- package/dist/__tests__/skills/split-flow-fixtures.d.ts.map +0 -1
- package/dist/__tests__/skills/split-flow-fixtures.js +0 -161
- package/dist/commands/__tests__/helpers.d.ts +0 -12
- package/dist/commands/__tests__/helpers.d.ts.map +0 -1
- package/dist/commands/__tests__/helpers.js +0 -36
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { lstat, readdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
detectCompletionReceiptCandidate,
|
|
7
|
+
recoverCompletionPinSource,
|
|
8
|
+
recoverCompletionReceipts,
|
|
9
|
+
} from './recover-completion-receipts.mjs';
|
|
10
|
+
|
|
11
|
+
const SKIPPED_MUTATIONS = [
|
|
12
|
+
'project-log',
|
|
13
|
+
'review-move',
|
|
14
|
+
'complete-state',
|
|
15
|
+
'active-pointer',
|
|
16
|
+
'pr-artifact',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
function completionRetryError(message) {
|
|
20
|
+
const error = new Error(message);
|
|
21
|
+
error.code = 'E_COMPLETION_RETRY';
|
|
22
|
+
return error;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function parseArguments(argv) {
|
|
26
|
+
const result = { evidencePaths: [] };
|
|
27
|
+
for (let index = 0; index < argv.length; index += 2) {
|
|
28
|
+
const flag = argv[index];
|
|
29
|
+
const value = argv[index + 1];
|
|
30
|
+
if (value === undefined) {
|
|
31
|
+
throw completionRetryError(`Missing value for ${flag ?? 'argument'}.`);
|
|
32
|
+
}
|
|
33
|
+
if (flag === '--project-path') result.projectPath = value;
|
|
34
|
+
else if (flag === '--retained-ref') result.retainedRef = value;
|
|
35
|
+
else if (flag === '--pr-artifact') result.prArtifactPath = value;
|
|
36
|
+
else if (flag === '--evidence-path') result.evidencePaths.push(value);
|
|
37
|
+
else if (flag === '--remote') result.remote = value;
|
|
38
|
+
else throw completionRetryError(`Unsupported argument: ${flag}.`);
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function resolvePrArtifact(projectPath) {
|
|
44
|
+
let names;
|
|
45
|
+
try {
|
|
46
|
+
names = await readdir(join(projectPath, 'pr'));
|
|
47
|
+
} catch (error) {
|
|
48
|
+
throw completionRetryError(
|
|
49
|
+
`Recognized completion receipt requires exactly one PR artifact: ${error.message}`,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const candidates = [];
|
|
54
|
+
for (const name of names.sort()) {
|
|
55
|
+
if (!/^project-pr-.*\.md$/.test(name)) continue;
|
|
56
|
+
const candidate = join(projectPath, 'pr', name);
|
|
57
|
+
const stat = await lstat(candidate);
|
|
58
|
+
if (stat.isFile() && !stat.isSymbolicLink()) {
|
|
59
|
+
candidates.push(`pr/${name}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (candidates.length !== 1) {
|
|
63
|
+
throw completionRetryError(
|
|
64
|
+
'Recognized completion receipt requires exactly one regular, non-symlinked PR artifact.',
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return candidates[0];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function resolveCompletionRetry(options) {
|
|
71
|
+
const candidateResult = await detectCompletionReceiptCandidate(options);
|
|
72
|
+
if (!candidateResult.candidate) {
|
|
73
|
+
return {
|
|
74
|
+
status: 'continue',
|
|
75
|
+
route: 'normal',
|
|
76
|
+
candidate: false,
|
|
77
|
+
nextStep: '3.7',
|
|
78
|
+
skipMutations: false,
|
|
79
|
+
skippedMutations: [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const prArtifactPath =
|
|
84
|
+
options.prArtifactPath ?? (await resolvePrArtifact(options.projectPath));
|
|
85
|
+
if (candidateResult.candidateType === 'pin-source') {
|
|
86
|
+
const pinSource = await recoverCompletionPinSource({
|
|
87
|
+
...options,
|
|
88
|
+
prArtifactPath,
|
|
89
|
+
});
|
|
90
|
+
return {
|
|
91
|
+
...pinSource,
|
|
92
|
+
route: 'pin-source',
|
|
93
|
+
candidate: true,
|
|
94
|
+
nextStep: '8.6',
|
|
95
|
+
skipMutations: true,
|
|
96
|
+
skippedMutations: SKIPPED_MUTATIONS,
|
|
97
|
+
prArtifactPath,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
const receipts = await recoverCompletionReceipts({
|
|
101
|
+
...options,
|
|
102
|
+
prArtifactPath,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
...receipts,
|
|
107
|
+
route: 'recovery',
|
|
108
|
+
candidate: true,
|
|
109
|
+
nextStep: '7.5',
|
|
110
|
+
skipMutations: true,
|
|
111
|
+
skippedMutations: SKIPPED_MUTATIONS,
|
|
112
|
+
prArtifactPath,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function main(argv) {
|
|
117
|
+
return resolveCompletionRetry(parseArguments(argv));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (
|
|
121
|
+
process.argv[1] &&
|
|
122
|
+
import.meta.url === pathToFileURL(process.argv[1]).href
|
|
123
|
+
) {
|
|
124
|
+
main(process.argv.slice(2))
|
|
125
|
+
.then((result) => {
|
|
126
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
127
|
+
})
|
|
128
|
+
.catch((error) => {
|
|
129
|
+
process.stderr.write(
|
|
130
|
+
`${JSON.stringify({ ok: false, code: error.code, message: error.message })}\n`,
|
|
131
|
+
);
|
|
132
|
+
process.exitCode = 1;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
5
|
+
import {
|
|
6
|
+
basename,
|
|
7
|
+
dirname,
|
|
8
|
+
extname,
|
|
9
|
+
isAbsolute,
|
|
10
|
+
relative,
|
|
11
|
+
resolve,
|
|
12
|
+
sep,
|
|
13
|
+
} from 'node:path';
|
|
14
|
+
|
|
15
|
+
function fail(message) {
|
|
16
|
+
process.stderr.write(`Invalid non-archive lifecycle receipt: ${message}\n`);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function git(cwd, args) {
|
|
21
|
+
try {
|
|
22
|
+
return execFileSync('git', args, {
|
|
23
|
+
cwd,
|
|
24
|
+
encoding: 'utf8',
|
|
25
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
26
|
+
}).trim();
|
|
27
|
+
} catch (error) {
|
|
28
|
+
const detail =
|
|
29
|
+
error?.stderr?.toString().trim() || error?.message || String(error);
|
|
30
|
+
fail(detail);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function gitRaw(cwd, args) {
|
|
35
|
+
try {
|
|
36
|
+
return execFileSync('git', args, {
|
|
37
|
+
cwd,
|
|
38
|
+
encoding: 'utf8',
|
|
39
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
40
|
+
});
|
|
41
|
+
} catch (error) {
|
|
42
|
+
const detail =
|
|
43
|
+
error?.stderr?.toString().trim() || error?.message || String(error);
|
|
44
|
+
fail(detail);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function gitSucceeds(cwd, args) {
|
|
49
|
+
try {
|
|
50
|
+
execFileSync('git', args, {
|
|
51
|
+
cwd,
|
|
52
|
+
stdio: ['ignore', 'ignore', 'ignore'],
|
|
53
|
+
});
|
|
54
|
+
return true;
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const [recordArgument, commit, projectName] = process.argv.slice(2);
|
|
61
|
+
if (!recordArgument || !/^[0-9a-f]{40}$/.test(commit ?? '') || !projectName) {
|
|
62
|
+
fail('expected <record-path> <full-commit-sha> <project-name>.');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const unresolvedRecordPath = resolve(recordArgument);
|
|
66
|
+
if (!existsSync(unresolvedRecordPath)) {
|
|
67
|
+
fail('record path does not exist; restore the synced discovery record.');
|
|
68
|
+
}
|
|
69
|
+
const recordPath = realpathSync(unresolvedRecordPath);
|
|
70
|
+
const repoRoot = realpathSync(
|
|
71
|
+
git(dirname(recordPath), ['rev-parse', '--show-toplevel']),
|
|
72
|
+
);
|
|
73
|
+
const recordRelative = relative(repoRoot, recordPath);
|
|
74
|
+
if (
|
|
75
|
+
recordRelative === '' ||
|
|
76
|
+
recordRelative === '..' ||
|
|
77
|
+
recordRelative.startsWith(`..${sep}`) ||
|
|
78
|
+
isAbsolute(recordRelative)
|
|
79
|
+
) {
|
|
80
|
+
fail('record path is outside the repository root.');
|
|
81
|
+
}
|
|
82
|
+
const gitRecordPath = recordRelative.split(sep).join('/');
|
|
83
|
+
if (basename(gitRecordPath, extname(gitRecordPath)) !== projectName) {
|
|
84
|
+
fail('record filename must match the project name.');
|
|
85
|
+
}
|
|
86
|
+
if (!gitSucceeds(repoRoot, ['merge-base', '--is-ancestor', commit, 'HEAD'])) {
|
|
87
|
+
fail('receipt commit must be an ancestor of the current repository HEAD.');
|
|
88
|
+
}
|
|
89
|
+
const changedPaths = git(repoRoot, [
|
|
90
|
+
'diff-tree',
|
|
91
|
+
'--root',
|
|
92
|
+
'--no-commit-id',
|
|
93
|
+
'--name-only',
|
|
94
|
+
'-r',
|
|
95
|
+
'--format=',
|
|
96
|
+
commit,
|
|
97
|
+
])
|
|
98
|
+
.split('\n')
|
|
99
|
+
.filter(Boolean);
|
|
100
|
+
if (changedPaths.length !== 1 || changedPaths[0] !== gitRecordPath) {
|
|
101
|
+
fail('receipt commit must change exactly the synced discovery record path.');
|
|
102
|
+
}
|
|
103
|
+
const expectedSubject = `chore(oat): complete synced project ${projectName}`;
|
|
104
|
+
const subject = git(repoRoot, ['show', '-s', '--format=%s', commit]);
|
|
105
|
+
if (subject !== expectedSubject) {
|
|
106
|
+
fail(`commit subject must be "${expectedSubject}".`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let committedRecordContents;
|
|
110
|
+
let record;
|
|
111
|
+
try {
|
|
112
|
+
committedRecordContents = gitRaw(repoRoot, [
|
|
113
|
+
'show',
|
|
114
|
+
`${commit}:${gitRecordPath}`,
|
|
115
|
+
]);
|
|
116
|
+
record = JSON.parse(committedRecordContents);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
fail(
|
|
119
|
+
`committed record is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
if (readFileSync(recordPath, 'utf8') !== committedRecordContents) {
|
|
123
|
+
fail('working-tree record content must exactly match the receipt commit.');
|
|
124
|
+
}
|
|
125
|
+
const expectedKeys = new Set([
|
|
126
|
+
'archiveSnapshot',
|
|
127
|
+
'completedAt',
|
|
128
|
+
'createdAt',
|
|
129
|
+
'ref',
|
|
130
|
+
'remote',
|
|
131
|
+
'schemaVersion',
|
|
132
|
+
'scope',
|
|
133
|
+
'slug',
|
|
134
|
+
'status',
|
|
135
|
+
]);
|
|
136
|
+
if (
|
|
137
|
+
!record ||
|
|
138
|
+
typeof record !== 'object' ||
|
|
139
|
+
Array.isArray(record) ||
|
|
140
|
+
Object.keys(record).some((key) => !expectedKeys.has(key)) ||
|
|
141
|
+
record.schemaVersion !== 1 ||
|
|
142
|
+
record.slug !== projectName ||
|
|
143
|
+
record.scope !== 'synced' ||
|
|
144
|
+
record.ref !== `refs/oat/projects/${projectName}` ||
|
|
145
|
+
record.remote !== 'origin' ||
|
|
146
|
+
record.status !== 'complete' ||
|
|
147
|
+
typeof record.createdAt !== 'string' ||
|
|
148
|
+
Number.isNaN(Date.parse(record.createdAt)) ||
|
|
149
|
+
typeof record.completedAt !== 'string' ||
|
|
150
|
+
Number.isNaN(Date.parse(record.completedAt)) ||
|
|
151
|
+
(record.archiveSnapshot !== undefined &&
|
|
152
|
+
(typeof record.archiveSnapshot !== 'string' ||
|
|
153
|
+
record.archiveSnapshot.length === 0))
|
|
154
|
+
) {
|
|
155
|
+
fail(
|
|
156
|
+
'committed record must be a complete synced record with the exact project identity and lifecycle content.',
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
process.stdout.write(`${commit}\n`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-project-design
|
|
3
|
-
version: 2.3.
|
|
3
|
+
version: 2.3.1
|
|
4
4
|
description: Use when discovery is complete and implementation-ready decisions are needed. Runs a collaborative, selective collaborative, or draft-and-review design flow, confirms requirements and produces both `spec.md` and `design.md`, and commits artifacts before the user-review gate.
|
|
5
5
|
disable-model-invocation: true
|
|
6
6
|
user-invocable: true
|
|
@@ -321,8 +321,14 @@ oat_last_updated: { today }
|
|
|
321
321
|
Commit separately (keeps history clean; lets reviewers fetch spec independently):
|
|
322
322
|
|
|
323
323
|
```bash
|
|
324
|
-
|
|
325
|
-
|
|
324
|
+
PROJECT_SCOPE=$(oat project scope "$PROJECT_PATH" --format value) || { echo "oat: cannot resolve project scope for $PROJECT_PATH; refusing to commit artifacts" >&2; exit 1; }
|
|
325
|
+
# fail closed: never fall back to branch bookkeeping when scope resolution fails
|
|
326
|
+
if [ "$PROJECT_SCOPE" = "synced" ]; then
|
|
327
|
+
oat project push "$PROJECT_PATH" --message "docs: confirm requirements for {project-name}" || { echo "oat: project push failed; run oat project pull, resolve the reported state, and retry" >&2; exit 1; }
|
|
328
|
+
else
|
|
329
|
+
git add "$PROJECT_PATH/spec.md"
|
|
330
|
+
git commit -m "docs: confirm requirements for {project-name}"
|
|
331
|
+
fi
|
|
326
332
|
```
|
|
327
333
|
|
|
328
334
|
### Step 2.5: Approach Reaffirmation (one divergent moment)
|
|
@@ -573,8 +579,14 @@ Even when no HiLL checkpoint is configured, the artifact is committed — consis
|
|
|
573
579
|
# oat_ready_for: null
|
|
574
580
|
# oat_last_updated: {today}
|
|
575
581
|
|
|
576
|
-
|
|
577
|
-
|
|
582
|
+
PROJECT_SCOPE=$(oat project scope "$PROJECT_PATH" --format value) || { echo "oat: cannot resolve project scope for $PROJECT_PATH; refusing to commit artifacts" >&2; exit 1; }
|
|
583
|
+
# fail closed: never fall back to branch bookkeeping when scope resolution fails
|
|
584
|
+
if [ "$PROJECT_SCOPE" = "synced" ]; then
|
|
585
|
+
oat project push "$PROJECT_PATH" --message "docs: draft design for {project-name} (awaiting review)" || { echo "oat: project push failed; run oat project pull, resolve the reported state, and retry" >&2; exit 1; }
|
|
586
|
+
else
|
|
587
|
+
git add "$PROJECT_PATH/spec.md" "$PROJECT_PATH/design.md" "$PROJECT_PATH/state.md"
|
|
588
|
+
git diff --cached --quiet || git commit -m "docs: draft design for {project-name} (awaiting review)"
|
|
589
|
+
fi
|
|
578
590
|
```
|
|
579
591
|
|
|
580
592
|
**Step 6b: Read state.md frontmatter**
|
|
@@ -610,8 +622,14 @@ Wait for user response:
|
|
|
610
622
|
- Approval → continue to Step 7.
|
|
611
623
|
- Change requests → revise the relevant section(s), re-run Step 5
|
|
612
624
|
(Self-Review), then MAKE A NEW COMMIT:
|
|
613
|
-
|
|
614
|
-
|
|
625
|
+
PROJECT_SCOPE=$(oat project scope "$PROJECT_PATH" --format value) || { echo "oat: cannot resolve project scope for $PROJECT_PATH; refusing to commit artifacts" >&2; exit 1; }
|
|
626
|
+
# fail closed: never fall back to branch bookkeeping when scope resolution fails
|
|
627
|
+
if [ "$PROJECT_SCOPE" = "synced" ]; then
|
|
628
|
+
oat project push "$PROJECT_PATH" --message "docs: revise design after user review feedback" || { echo "oat: project push failed; run oat project pull, resolve the reported state, and retry" >&2; exit 1; }
|
|
629
|
+
else
|
|
630
|
+
git add "$PROJECT_PATH/spec.md" "$PROJECT_PATH/design.md"
|
|
631
|
+
git commit -m "docs: revise design after user review feedback"
|
|
632
|
+
fi
|
|
615
633
|
Re-present this prompt.
|
|
616
634
|
- If user does not approve yet (wants to pause without explicit change
|
|
617
635
|
requests): keep design frontmatter as oat_status: in_progress /
|
|
@@ -759,8 +777,14 @@ Reach this commit step only after the configured gate passes or resolves
|
|
|
759
777
|
according to its `onFailure` policy.
|
|
760
778
|
|
|
761
779
|
```bash
|
|
762
|
-
|
|
763
|
-
|
|
780
|
+
PROJECT_SCOPE=$(oat project scope "$PROJECT_PATH" --format value) || { echo "oat: cannot resolve project scope for $PROJECT_PATH; refusing to commit artifacts" >&2; exit 1; }
|
|
781
|
+
# fail closed: never fall back to branch bookkeeping when scope resolution fails
|
|
782
|
+
if [ "$PROJECT_SCOPE" = "synced" ]; then
|
|
783
|
+
oat project push "$PROJECT_PATH" --message "chore(oat): mark design complete for {project-name}" || { echo "oat: project push failed; run oat project pull, resolve the reported state, and retry" >&2; exit 1; }
|
|
784
|
+
else
|
|
785
|
+
git add "$PROJECT_PATH/design.md" "$PROJECT_PATH/state.md"
|
|
786
|
+
git diff --cached --quiet || git commit -m "chore(oat): mark design complete for {project-name}"
|
|
787
|
+
fi
|
|
764
788
|
```
|
|
765
789
|
|
|
766
790
|
### Step 9: Output Summary
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-project-discover
|
|
3
|
-
version: 2.2.
|
|
3
|
+
version: 2.2.1
|
|
4
4
|
description: Use when the user explicitly asks to continue discovery for an active spec-driven OAT project — e.g. "continue discovery", "run discovery", or confirms a previously offered discovery step. Do NOT auto-invoke for new ideas or quick-mode projects. Gathers requirements and context before spec/design.
|
|
5
5
|
disable-model-invocation: false
|
|
6
6
|
user-invocable: true
|
|
@@ -549,14 +549,27 @@ according to its `onFailure` policy.
|
|
|
549
549
|
During implementation of OAT itself, use standard commit format.
|
|
550
550
|
|
|
551
551
|
```bash
|
|
552
|
-
|
|
553
|
-
|
|
552
|
+
PROJECT_SCOPE=$(oat project scope "$PROJECT_PATH" --format value) || { echo "oat: cannot resolve project scope for $PROJECT_PATH; refusing to commit artifacts" >&2; exit 1; }
|
|
553
|
+
# fail closed: never fall back to branch bookkeeping when scope resolution fails
|
|
554
|
+
if [ "$PROJECT_SCOPE" = "synced" ]; then
|
|
555
|
+
oat project push "$PROJECT_PATH" --message "docs: complete discovery for {project-name}
|
|
556
|
+
|
|
557
|
+
Key decisions:
|
|
558
|
+
- {Decision 1}
|
|
559
|
+
- {Decision 2}
|
|
560
|
+
|
|
561
|
+
Ready for design phase" || { echo "oat: project push failed; run oat project pull, resolve the reported state, and retry" >&2; exit 1; }
|
|
562
|
+
else
|
|
563
|
+
PROJECT_OUTPUT_PATHS=("$PROJECT_PATH/discovery.md" "$PROJECT_PATH/state.md")
|
|
564
|
+
git add -- "${PROJECT_OUTPUT_PATHS[@]}"
|
|
565
|
+
git commit -m "docs: complete discovery for {project-name}
|
|
554
566
|
|
|
555
567
|
Key decisions:
|
|
556
568
|
- {Decision 1}
|
|
557
569
|
- {Decision 2}
|
|
558
570
|
|
|
559
571
|
Ready for design phase"
|
|
572
|
+
fi
|
|
560
573
|
```
|
|
561
574
|
|
|
562
575
|
### Step 16: Output Summary
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-project-document
|
|
3
|
-
version: 1.8.
|
|
3
|
+
version: 1.8.1
|
|
4
4
|
description: Use when the user requests or confirms documenting an active OAT project — e.g. "document the project", "update the docs", "run oat-project-document", or confirms a previously offered documentation run. Do NOT auto-invoke when implementation completes. Analyzes project artifacts, presents a documentation delta plan, and applies approved changes.
|
|
5
5
|
argument-hint: '[project-path] [--auto]'
|
|
6
6
|
disable-model-invocation: false
|
|
7
7
|
user-invocable: true
|
|
8
|
-
allowed-tools: Read, Write, Edit, Bash(git:*), Bash(oat tools:*), Glob, Grep, AskUserQuestion, Skill
|
|
8
|
+
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
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Project Documentation Sync
|
|
@@ -524,8 +524,14 @@ Update `$PROJECT_PATH/state.md` frontmatter based on apply outcome:
|
|
|
524
524
|
- If `$ALL_SUCCEEDED` is false: do **not** set `oat_docs_updated: complete` — leave the field as `null` so the skill can be re-run. Still set `oat_project_state_updated: "{ISO 8601 UTC timestamp}"`. Surface the failures clearly in the summary report (Step 8d) so the user knows which updates failed and why.
|
|
525
525
|
|
|
526
526
|
```bash
|
|
527
|
-
|
|
528
|
-
|
|
527
|
+
PROJECT_SCOPE=$(oat project scope "$PROJECT_PATH" --format value) || { echo "oat: cannot resolve project scope for $PROJECT_PATH; refusing to commit artifacts" >&2; exit 1; }
|
|
528
|
+
# fail closed: never fall back to branch bookkeeping when scope resolution fails
|
|
529
|
+
if [ "$PROJECT_SCOPE" = "synced" ]; then
|
|
530
|
+
oat project push "$PROJECT_PATH" --message "chore({project-name}): mark docs updated" || { echo "oat: project push failed; run oat project pull, resolve the reported state, and retry" >&2; exit 1; }
|
|
531
|
+
else
|
|
532
|
+
git add "$PROJECT_PATH/state.md"
|
|
533
|
+
git diff --cached --quiet || git commit -m "chore({project-name}): mark docs updated"
|
|
534
|
+
fi
|
|
529
535
|
```
|
|
530
536
|
|
|
531
537
|
**8c. Handle edge cases:**
|