@open-agent-toolkit/cli 0.1.63 → 0.1.65

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 (54) hide show
  1. package/assets/agents/oat-phase-implementer.md +9 -1
  2. package/assets/agents/oat-reviewer.md +8 -1
  3. package/assets/docs/cli-utilities/backlog-lifecycle.md +2 -2
  4. package/assets/docs/cli-utilities/config-and-local-state.md +20 -6
  5. package/assets/docs/cli-utilities/tool-packs.md +1 -0
  6. package/assets/docs/cli-utilities/workflow-gates.md +3 -1
  7. package/assets/docs/contributing/code.md +18 -0
  8. package/assets/docs/contributing/skills.md +22 -0
  9. package/assets/docs/workflows/projects/artifacts.md +30 -0
  10. package/assets/docs/workflows/projects/dispatch-ceiling.md +13 -0
  11. package/assets/public-package-versions.json +4 -4
  12. package/assets/skills/oat-pjm-add-backlog-item/SKILL.md +17 -72
  13. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +165 -165
  14. package/assets/skills/oat-project-document/SKILL.md +8 -1
  15. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +165 -165
  16. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +165 -165
  17. package/assets/skills/oat-project-plan-writing/SKILL.md +48 -12
  18. package/assets/skills/oat-project-pr-final/SKILL.md +9 -1
  19. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +165 -165
  20. package/assets/skills/oat-project-quick-start/SKILL.md +8 -1
  21. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +165 -165
  22. package/assets/skills/oat-project-review-provide/SKILL.md +9 -1
  23. package/assets/skills/oat-project-review-receive/SKILL.md +9 -1
  24. package/assets/skills/oat-project-summary/SKILL.md +16 -4
  25. package/assets/templates/plan.md +2 -0
  26. package/dist/commands/backlog/archive.d.ts.map +1 -1
  27. package/dist/commands/backlog/archive.js +5 -5
  28. package/dist/commands/backlog/index.d.ts +4 -0
  29. package/dist/commands/backlog/index.d.ts.map +1 -1
  30. package/dist/commands/backlog/index.js +55 -0
  31. package/dist/commands/backlog/new.d.ts +27 -0
  32. package/dist/commands/backlog/new.d.ts.map +1 -0
  33. package/dist/commands/backlog/new.js +158 -0
  34. package/dist/commands/backlog/regenerate-index.d.ts.map +1 -1
  35. package/dist/commands/backlog/regenerate-index.js +42 -3
  36. package/dist/commands/decision/index.d.ts.map +1 -1
  37. package/dist/commands/decision/index.js +4 -0
  38. package/dist/commands/decision/new.d.ts +2 -0
  39. package/dist/commands/decision/new.d.ts.map +1 -1
  40. package/dist/commands/decision/new.js +4 -2
  41. package/dist/commands/doctor/index.d.ts +1 -0
  42. package/dist/commands/doctor/index.d.ts.map +1 -1
  43. package/dist/commands/doctor/index.js +3 -0
  44. package/dist/commands/doctor/stale-invocations.d.ts +3 -0
  45. package/dist/commands/doctor/stale-invocations.d.ts.map +1 -0
  46. package/dist/commands/doctor/stale-invocations.js +173 -0
  47. package/dist/commands/gate/index.d.ts +1 -0
  48. package/dist/commands/gate/index.d.ts.map +1 -1
  49. package/dist/commands/gate/index.js +9 -2
  50. package/dist/commands/project/new/scaffold.d.ts.map +1 -1
  51. package/dist/commands/project/new/scaffold.js +24 -9
  52. package/dist/commands/tools/update/index.d.ts.map +1 -1
  53. package/dist/commands/tools/update/index.js +22 -12
  54. package/package.json +2 -2
@@ -0,0 +1,173 @@
1
+ import { readdir, readFile, stat } from 'node:fs/promises';
2
+ import { extname, join } from 'node:path';
3
+ const KNOWN_STALE_INVOCATIONS = [
4
+ {
5
+ id: 'global-scope-sync',
6
+ pattern: /\boat\s+--scope(?:\s+|=)all\s+sync\b/g,
7
+ replacement: 'oat sync --scope all',
8
+ },
9
+ ];
10
+ const SCANNED_EXTENSIONS = new Set([
11
+ '.bash',
12
+ '.cjs',
13
+ '.fish',
14
+ '.js',
15
+ '.json',
16
+ '.jsonc',
17
+ '.md',
18
+ '.mdc',
19
+ '.mdx',
20
+ '.mjs',
21
+ '.mts',
22
+ '.sh',
23
+ '.toml',
24
+ '.ts',
25
+ '.yaml',
26
+ '.yml',
27
+ '.zsh',
28
+ ]);
29
+ const EXCLUDED_DIRECTORY_NAMES = new Set([
30
+ '.git',
31
+ '.next',
32
+ '.turbo',
33
+ 'archived',
34
+ 'build',
35
+ 'coverage',
36
+ 'dist',
37
+ 'node_modules',
38
+ 'out',
39
+ ]);
40
+ const GENERATED_PROVIDER_ROOTS = new Set([
41
+ '.claude',
42
+ '.codex',
43
+ '.cursor',
44
+ '.gemini',
45
+ ]);
46
+ const GENERATED_GITHUB_DIRECTORIES = new Set([
47
+ 'agents',
48
+ 'instructions',
49
+ 'prompts',
50
+ 'skills',
51
+ ]);
52
+ const ALLOW_MARKER = 'oat-doctor: allow-stale-invocation';
53
+ const MAX_FILE_BYTES = 1024 * 1024;
54
+ const MAX_SCANNED_FILES = 10_000;
55
+ const MAX_REPORTED_MATCHES = 50;
56
+ function isExcludedDirectory(parts) {
57
+ const name = parts.at(-1);
58
+ if (!name || EXCLUDED_DIRECTORY_NAMES.has(name)) {
59
+ return true;
60
+ }
61
+ if (parts.length === 1 && name === '.worktrees') {
62
+ return true;
63
+ }
64
+ if (GENERATED_PROVIDER_ROOTS.has(name)) {
65
+ return true;
66
+ }
67
+ const parent = parts.at(-2);
68
+ if (parent === '.oat' && (name === 'projects' || name === 'sync')) {
69
+ return true;
70
+ }
71
+ return parent === '.github' && GENERATED_GITHUB_DIRECTORIES.has(name);
72
+ }
73
+ function isScannableFile(relativePath) {
74
+ const parts = relativePath.split('/');
75
+ const fileName = parts.at(-1) ?? '';
76
+ if (/\.(?:test|spec)\.[^.]+$/.test(fileName)) {
77
+ return false;
78
+ }
79
+ if (fileName === 'copilot-instructions.md' && parts.at(-2) === '.github') {
80
+ return false;
81
+ }
82
+ return SCANNED_EXTENSIONS.has(extname(fileName).toLowerCase());
83
+ }
84
+ async function listScannableFiles(repoRoot) {
85
+ const files = [];
86
+ async function walk(parts) {
87
+ if (files.length >= MAX_SCANNED_FILES) {
88
+ return;
89
+ }
90
+ const entries = await readdir(join(repoRoot, ...parts), {
91
+ withFileTypes: true,
92
+ });
93
+ entries.sort((left, right) => left.name.localeCompare(right.name));
94
+ for (const entry of entries) {
95
+ if (files.length >= MAX_SCANNED_FILES) {
96
+ break;
97
+ }
98
+ if (entry.isSymbolicLink()) {
99
+ continue;
100
+ }
101
+ const childParts = [...parts, entry.name];
102
+ if (entry.isDirectory()) {
103
+ if (!isExcludedDirectory(childParts)) {
104
+ await walk(childParts);
105
+ }
106
+ continue;
107
+ }
108
+ const relativePath = childParts.join('/');
109
+ if (entry.isFile() && isScannableFile(relativePath)) {
110
+ files.push(relativePath);
111
+ }
112
+ }
113
+ }
114
+ await walk([]);
115
+ return files;
116
+ }
117
+ function findMatches(relativePath, content) {
118
+ const matches = [];
119
+ const lines = content.split(/\r?\n/);
120
+ for (const [lineIndex, line] of lines.entries()) {
121
+ if (line.includes(ALLOW_MARKER)) {
122
+ continue;
123
+ }
124
+ for (const stale of KNOWN_STALE_INVOCATIONS) {
125
+ stale.pattern.lastIndex = 0;
126
+ for (const match of line.matchAll(stale.pattern)) {
127
+ matches.push({
128
+ relativePath,
129
+ line: lineIndex + 1,
130
+ invocation: match[0],
131
+ replacement: stale.replacement,
132
+ });
133
+ }
134
+ }
135
+ }
136
+ return matches;
137
+ }
138
+ export async function checkStaleInvocations(repoRoot) {
139
+ const matches = [];
140
+ for (const relativePath of await listScannableFiles(repoRoot)) {
141
+ const absolutePath = join(repoRoot, relativePath);
142
+ const metadata = await stat(absolutePath);
143
+ if (metadata.size > MAX_FILE_BYTES) {
144
+ continue;
145
+ }
146
+ matches.push(...findMatches(relativePath, await readFile(absolutePath, 'utf8')));
147
+ if (matches.length >= MAX_REPORTED_MATCHES) {
148
+ break;
149
+ }
150
+ }
151
+ if (matches.length === 0) {
152
+ return {
153
+ name: 'project:stale_invocations',
154
+ description: 'Known-stale CLI invocation grammar',
155
+ status: 'pass',
156
+ message: 'No known-stale CLI invocations found in repository scripts or documentation.',
157
+ };
158
+ }
159
+ const evidence = matches
160
+ .slice(0, MAX_REPORTED_MATCHES)
161
+ .map((match) => `${match.relativePath}:${match.line} (\`${match.invocation}\` → \`${match.replacement}\`)`)
162
+ .join(', ');
163
+ const replacements = [...new Set(matches.map((match) => match.replacement))];
164
+ return {
165
+ name: 'project:stale_invocations',
166
+ description: 'Known-stale CLI invocation grammar',
167
+ status: 'warn',
168
+ message: `Known-stale CLI invocations found: ${evidence}.`,
169
+ fix: `Update each invocation to the current command grammar: ${replacements
170
+ .map((replacement) => `\`${replacement}\``)
171
+ .join(', ')}.`,
172
+ };
173
+ }
@@ -26,6 +26,7 @@ interface ProcessRunOptions {
26
26
  livenessIntervalMs?: number;
27
27
  onLiveness?: (snapshot: GateLivenessSnapshot) => void;
28
28
  purpose: 'host-detection' | 'availability' | 'execute';
29
+ stdin: 'ignore' | 'inherit';
29
30
  stdio: 'ignore' | 'inherit' | 'pipe';
30
31
  timeoutMs: number;
31
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAQL,KAAK,UAAU,EAIf,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,iBAAiB,CAAC;AAWzB,OAAO,EAEL,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EAExB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EACL,sBAAsB,EAIvB,MAAM,kBAAkB,CAAC;AAE1B,UAAU,uBAAuB;IAC/B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,UAAU,EAAE,CACV,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/B,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AA6CD,UAAU,iBAAiB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,OAAO,EAAE,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAC;IACvD,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,oBAAoB;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,kBAAkB,GAAG,aAAa,GAAG,cAAc,GAAG,MAAM,CAAC;AAClE,KAAK,qBAAqB,GACtB,kBAAkB,GAClB,4BAA4B,GAC5B,2CAA2C,GAC3C,kBAAkB,CAAC;AAUvB,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,kBAAkB,CAAC;IAC/B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,mBAAmB,GAAG,SAAS,CAAC;CAC5D;AAED,UAAU,qBAAqB;IAC7B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,kBAAkB,CAAC;QAC/B,UAAU,EAAE,kBAAkB,CAAC;QAC/B,MAAM,EAAE,WAAW,CAAC;QACpB,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QACvC,aAAa,EAAE,WAAW,EAAE,CAAC;QAC7B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;KACjC,CAAC;IACF,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,WAAW,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA2lCD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAC9C,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,kBAAkB,EACzB,gBAAgB,CAAC,EAAE,oBAAoB,GACtC,kBAAkB,GAAG,IAAI,CAS3B;AAshDD,wBAAgB,iBAAiB,CAC/B,SAAS,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAC/C,OAAO,CAwMT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAQL,KAAK,UAAU,EAIf,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,iBAAiB,CAAC;AAWzB,OAAO,EAEL,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EAExB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EACL,sBAAsB,EAIvB,MAAM,kBAAkB,CAAC;AAE1B,UAAU,uBAAuB;IAC/B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,UAAU,EAAE,CACV,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/B,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AA6CD,UAAU,iBAAiB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,OAAO,EAAE,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAC;IACvD,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,oBAAoB;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,kBAAkB,GAAG,aAAa,GAAG,cAAc,GAAG,MAAM,CAAC;AAClE,KAAK,qBAAqB,GACtB,kBAAkB,GAClB,4BAA4B,GAC5B,2CAA2C,GAC3C,kBAAkB,CAAC;AAUvB,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,kBAAkB,CAAC;IAC/B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,mBAAmB,GAAG,SAAS,CAAC;CAC5D;AAED,UAAU,qBAAqB;IAC7B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,kBAAkB,CAAC;QAC/B,UAAU,EAAE,kBAAkB,CAAC;QAC/B,MAAM,EAAE,WAAW,CAAC;QACpB,MAAM,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QACvC,aAAa,EAAE,WAAW,EAAE,CAAC;QAC7B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;KACjC,CAAC;IACF,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,WAAW,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA+lCD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAC9C,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,kBAAkB,EACzB,gBAAgB,CAAC,EAAE,oBAAoB,GACtC,kBAAkB,GAAG,IAAI,CAS3B;AAwhDD,wBAAgB,iBAAiB,CAC/B,SAAS,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAC/C,OAAO,CAwMT"}
@@ -54,7 +54,10 @@ const VALID_IDENTITY_PROVENANCES = [
54
54
  'inferred',
55
55
  'unknown',
56
56
  ];
57
- const REVIEW_GATE_CONTEXT_NOTE = 'This review is gate-originated. If you run `oat-project-review-provide`, set `oat_review_invocation: gate` in the review artifact. Write a canonical review artifact with `### Critical`, `### Important`, `### Medium`, and `### Minor` headings in that order, using `None` for empty sections.';
57
+ const REVIEW_GATE_CONTEXT_NOTE = [
58
+ 'This review is gate-originated. If you run `oat-project-review-provide`, set `oat_review_invocation: gate` in the review artifact. Write a canonical review artifact with `### Critical`, `### Important`, `### Medium`, and `### Minor` headings in that order, using `None` for empty sections.',
59
+ "Artifact hygiene contract: Before finishing or committing, format every file you created or edited. Use the concrete write/fix formatting command supplied by the governing plan, task, or brief. If none is usable, discover the repository's documented write/fix command from applicable `AGENTS.md`/`CLAUDE.md` instructions and relevant package manifests; do not infer or hardcode a formatter. Prefer a file-scoped invocation when supported, and avoid rewriting unrelated files. If no command is discoverable, warn once with `no format command discovered in repo instructions; skipping`, then continue.",
60
+ ].join('\n\n');
58
61
  const GATE_CHECK_TIMEOUT_MS = 5_000;
59
62
  const GATE_EXEC_TIMEOUT_MS = 15 * 60 * 1_000;
60
63
  const GATE_LIVENESS_INTERVAL_MS = 30_000;
@@ -203,7 +206,9 @@ async function runChildProcess(command, args, options) {
203
206
  const child = spawn(command, args, {
204
207
  cwd: options.cwd,
205
208
  env: options.env,
206
- stdio: options.stdio === 'pipe' ? ['inherit', 'pipe', 'pipe'] : options.stdio,
209
+ stdio: options.stdio === 'pipe'
210
+ ? [options.stdin, 'pipe', 'pipe']
211
+ : options.stdio,
207
212
  });
208
213
  const recordActivity = () => {
209
214
  lastActivityAt = Date.now();
@@ -811,6 +816,7 @@ async function checkArgv(argv, purpose, context, dependencies) {
811
816
  cwd: context.cwd,
812
817
  env: dependencies.processEnv,
813
818
  purpose,
819
+ stdin: 'ignore',
814
820
  stdio: 'ignore',
815
821
  timeoutMs: GATE_CHECK_TIMEOUT_MS,
816
822
  });
@@ -895,6 +901,7 @@ async function executeTarget(selected, prompt, context, dependencies) {
895
901
  }
896
902
  },
897
903
  purpose: 'execute',
904
+ stdin: 'ignore',
898
905
  stdio: 'pipe',
899
906
  timeoutMs,
900
907
  });
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/new/scaffold.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wBAAwB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAC5B,WAAW,GACX,kBAAkB,GAClB,qBAAqB,GACrB,iBAAiB,GACjB,QAAQ,CAAC;AAEb,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,oBAAoB,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA2SD,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAoFhC"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/new/scaffold.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wBAAwB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAC5B,WAAW,GACX,kBAAkB,GAClB,qBAAqB,GACrB,iBAAiB,GACjB,QAAQ,CAAC;AAEb,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,oBAAoB,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA4UD,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAoFhC"}
@@ -20,6 +20,7 @@ const TEMPLATES_BY_MODE = {
20
20
  quick: ['state.md', 'discovery.md', 'plan.md', 'implementation.md'],
21
21
  import: ['state.md', 'plan.md', 'implementation.md'],
22
22
  };
23
+ const OAT_PLACEHOLDER_PATTERN = /(?<!\{)\{\s*(OAT_[A-Z0-9_]+)\s*\}(?!\})/g;
23
24
  const STATE_TEMPLATE_BY_MODE = {
24
25
  'spec-driven': {
25
26
  hillCheckpoints: "['discovery', 'design']",
@@ -79,6 +80,17 @@ const STATE_TEMPLATE_BY_MODE = {
79
80
  nextMilestone: 'Run `oat-project-import-plan` to normalize the external plan',
80
81
  },
81
82
  };
83
+ function replaceOatPlaceholders(template, replacements) {
84
+ return template.replace(OAT_PLACEHOLDER_PATTERN, (placeholder, token) => replacements[token] ?? placeholder);
85
+ }
86
+ function assertNoUnresolvedOatPlaceholders(rendered, templateFile) {
87
+ const unresolved = [
88
+ ...new Set([...rendered.matchAll(OAT_PLACEHOLDER_PATTERN)].map(([placeholder]) => placeholder)),
89
+ ];
90
+ if (unresolved.length > 0) {
91
+ throw new Error(`Cannot scaffold ${templateFile}: unresolved OAT placeholder(s): ${unresolved.join(', ')}`);
92
+ }
93
+ }
82
94
  function validateProjectName(name) {
83
95
  if (name.startsWith('-')) {
84
96
  throw new Error(`Invalid project name "${name}". Project names must not start with a dash.`);
@@ -89,17 +101,19 @@ function validateProjectName(name) {
89
101
  }
90
102
  function applyTemplateReplacements(template, projectName, today, nowUtc, mode) {
91
103
  const stateContent = STATE_TEMPLATE_BY_MODE[mode];
92
- return template
104
+ const oatReplacements = {
105
+ OAT_HILL_CHECKPOINTS: stateContent.hillCheckpoints,
106
+ OAT_WORKFLOW_MODE: mode,
107
+ OAT_PHASE: stateContent.phase,
108
+ OAT_STATUS: stateContent.status,
109
+ OAT_CURRENT_PHASE: stateContent.currentPhase,
110
+ OAT_ARTIFACTS: stateContent.artifacts.join('\n'),
111
+ OAT_PROGRESS: stateContent.progress.join('\n'),
112
+ OAT_NEXT_MILESTONE: stateContent.nextMilestone,
113
+ };
114
+ return replaceOatPlaceholders(template, oatReplacements)
93
115
  .replaceAll('{Project Name}', projectName)
94
116
  .replaceAll('YYYY-MM-DD', today)
95
- .replaceAll('{OAT_HILL_CHECKPOINTS}', stateContent.hillCheckpoints)
96
- .replaceAll('{OAT_WORKFLOW_MODE}', mode)
97
- .replaceAll('{OAT_PHASE}', stateContent.phase)
98
- .replaceAll('{OAT_STATUS}', stateContent.status)
99
- .replaceAll('{OAT_CURRENT_PHASE}', stateContent.currentPhase)
100
- .replaceAll('{OAT_ARTIFACTS}', stateContent.artifacts.join('\n'))
101
- .replaceAll('{OAT_PROGRESS}', stateContent.progress.join('\n'))
102
- .replaceAll('{OAT_NEXT_MILESTONE}', stateContent.nextMilestone)
103
117
  .replaceAll(/oat_project_created:\s*null/gi, `oat_project_created: "${nowUtc}"`)
104
118
  .replaceAll(/oat_project_state_updated:\s*null/gi, `oat_project_state_updated: "${nowUtc}"`)
105
119
  .replaceAll(/\n?oat_template:\s*true\s*\n/gi, '\n')
@@ -176,6 +190,7 @@ async function scaffoldModeTemplates(userOatRoot, repoRoot, projectPath, project
176
190
  }
177
191
  const template = await readFile(src, 'utf8');
178
192
  const rendered = applyTemplateReplacements(template, projectName, today, nowUtc, mode);
193
+ assertNoUnresolvedOatPlaceholders(rendered, templateFile);
179
194
  if (templateFile === 'state.md') {
180
195
  assertValidProjectStateContent(rendered, { filePath: dest });
181
196
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/index.ts"],"names":[],"mappings":"AAeA,OAAO,EACL,KAAK,oBAAoB,EAE1B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAKvE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,uBAAuB,EAE7B,MAAM,gBAAgB,CAAC;AAgBxB,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GAClD,MAAM,EAAE,CAaV;AAgCD,wBAAgB,wBAAwB,CACtC,YAAY,GAAE,uBAA6C,EAC3D,gBAAgB,GAAE,oBAA8C,GAC/D,OAAO,CAoKT;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAI7E;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,GACnB,OAAO,CAOT;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,GACd,MAAM,CAMR"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/update/index.ts"],"names":[],"mappings":"AAeA,OAAO,EACL,KAAK,oBAAoB,EAE1B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAKvE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,uBAAuB,EAE7B,MAAM,gBAAgB,CAAC;AAgBxB,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GAClD,MAAM,EAAE,CAaV;AAgCD,wBAAgB,wBAAwB,CACtC,YAAY,GAAE,uBAA6C,EAC3D,gBAAgB,GAAE,oBAA8C,GAC/D,OAAO,CAqKT;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAI7E;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,YAAY,GACnB,OAAO,CAOT;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,OAAO,GACd,MAAM,CAMR"}
@@ -79,12 +79,13 @@ export function createToolsUpdateCommand(dependencies = defaultDependencies, syn
79
79
  const globalOptions = readGlobalOptions(command);
80
80
  const context = buildCommandContext(globalOptions);
81
81
  const { logger } = context;
82
- const target = resolveTarget(name, opts.pack, opts.all);
83
- if (!target) {
84
- logger.error('Specify a tool name, --pack <pack>, or --all.');
82
+ const targetResolution = resolveTarget(name, opts.pack, opts.all);
83
+ if ('error' in targetResolution) {
84
+ logger.error(targetResolution.error);
85
85
  process.exitCode = 1;
86
86
  return;
87
87
  }
88
+ const target = targetResolution.target;
88
89
  const scopes = resolveConcreteScopes(context.scope);
89
90
  const dryRun = opts.dryRun ?? false;
90
91
  const result = await updateTools(target, scopes, context.cwd, context.home, dryRun, dependencies);
@@ -200,18 +201,27 @@ export function formatUpdatedToolMessage(tool, dryRun) {
200
201
  }
201
202
  function resolveTarget(name, pack, all) {
202
203
  const specified = [name, pack, all].filter(Boolean).length;
203
- if (specified !== 1)
204
- return null;
204
+ if (specified === 0) {
205
+ return {
206
+ error: 'Specify a tool name, --pack <pack>, or --all. To update all tools, run: oat tools update --all',
207
+ };
208
+ }
209
+ if (specified > 1) {
210
+ return {
211
+ error: 'Specify exactly one update target: a tool name, --pack <pack>, or --all.',
212
+ };
213
+ }
205
214
  if (name)
206
- return { kind: 'name', name };
215
+ return { target: { kind: 'name', name } };
207
216
  if (pack) {
208
- if (!VALID_PACKS.includes(pack))
209
- return null;
210
- return { kind: 'pack', pack: pack };
217
+ if (!VALID_PACKS.includes(pack)) {
218
+ return {
219
+ error: `Invalid pack '${pack}'. Expected one of: ${VALID_PACKS.join(', ')}.`,
220
+ };
221
+ }
222
+ return { target: { kind: 'pack', pack: pack } };
211
223
  }
212
- if (all)
213
- return { kind: 'all' };
214
- return null;
224
+ return { target: { kind: 'all' } };
215
225
  }
216
226
  function describeTarget(target) {
217
227
  switch (target.kind) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.1.63",
3
+ "version": "0.1.65",
4
4
  "private": false,
5
5
  "description": "Open Agent Toolkit CLI",
6
6
  "homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/cli",
@@ -34,7 +34,7 @@
34
34
  "ora": "^9.0.0",
35
35
  "yaml": "2.8.2",
36
36
  "zod": "^3.25.76",
37
- "@open-agent-toolkit/control-plane": "0.1.63"
37
+ "@open-agent-toolkit/control-plane": "0.1.65"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.0",