@open-agent-toolkit/cli 0.1.65 → 0.1.69

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 (40) hide show
  1. package/assets/agents/oat-reviewer.md +2 -2
  2. package/assets/docs/cli-utilities/workflow-gates.md +24 -5
  3. package/assets/docs/reference/cli-reference.md +1 -1
  4. package/assets/docs/workflows/projects/dispatch-ceiling.md +11 -3
  5. package/assets/docs/workflows/projects/pr-flow.md +12 -1
  6. package/assets/docs/workflows/projects/reviews.md +21 -1
  7. package/assets/public-package-versions.json +4 -4
  8. package/assets/skills/oat-agent-instructions-analyze/SKILL.md +3 -2
  9. package/assets/skills/oat-project-autonomous/SKILL.md +1 -1
  10. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +6 -6
  11. package/assets/skills/oat-project-complete/SKILL.md +20 -2
  12. package/assets/skills/oat-project-design/SKILL.md +88 -75
  13. package/assets/skills/oat-project-discover/SKILL.md +83 -64
  14. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +6 -6
  15. package/assets/skills/oat-project-implement/SKILL.md +1 -1
  16. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +12 -1
  17. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +24 -9
  18. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +6 -6
  19. package/assets/skills/oat-project-implement/references/phase-execution.md +5 -2
  20. package/assets/skills/oat-project-next/SKILL.md +21 -6
  21. package/assets/skills/oat-project-plan/SKILL.md +69 -56
  22. package/assets/skills/oat-project-plan-writing/SKILL.md +19 -2
  23. package/assets/skills/oat-project-pr-final/SKILL.md +20 -5
  24. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +6 -6
  25. package/assets/skills/oat-project-pr-progress/SKILL.md +18 -3
  26. package/assets/skills/oat-project-progress/SKILL.md +4 -1
  27. package/assets/skills/oat-project-quick-start/SKILL.md +68 -55
  28. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +6 -6
  29. package/assets/skills/oat-project-review-provide/SKILL.md +7 -2
  30. package/assets/skills/oat-project-review-receive/SKILL.md +46 -18
  31. package/assets/skills/oat-project-review-receive-remote/SKILL.md +41 -8
  32. package/dist/commands/cleanup/project/project.utils.d.ts.map +1 -1
  33. package/dist/commands/cleanup/project/project.utils.js +19 -1
  34. package/dist/commands/gate/index.d.ts +2 -0
  35. package/dist/commands/gate/index.d.ts.map +1 -1
  36. package/dist/commands/gate/index.js +29 -1
  37. package/dist/commands/review/latest.d.ts +1 -0
  38. package/dist/commands/review/latest.d.ts.map +1 -1
  39. package/dist/commands/review/latest.js +96 -22
  40. package/package.json +2 -2
@@ -201,6 +201,8 @@ async function runChildProcess(command, args, options) {
201
201
  return new Promise((resolve, reject) => {
202
202
  let timedOut = false;
203
203
  let killTimeout = null;
204
+ let stderrBytes = 0;
205
+ let stdoutBytes = 0;
204
206
  const startedAt = Date.now();
205
207
  let lastActivityAt = startedAt;
206
208
  const child = spawn(command, args, {
@@ -214,10 +216,12 @@ async function runChildProcess(command, args, options) {
214
216
  lastActivityAt = Date.now();
215
217
  };
216
218
  child.stdout?.on('data', (chunk) => {
219
+ stdoutBytes += chunk.byteLength;
217
220
  recordActivity();
218
221
  process.stdout.write(chunk);
219
222
  });
220
223
  child.stderr?.on('data', (chunk) => {
224
+ stderrBytes += chunk.byteLength;
221
225
  recordActivity();
222
226
  process.stderr.write(chunk);
223
227
  });
@@ -261,6 +265,8 @@ async function runChildProcess(command, args, options) {
261
265
  }
262
266
  resolve({
263
267
  exitCode: timedOut ? 124 : (code ?? 1),
268
+ stderrBytes,
269
+ stdoutBytes,
264
270
  ...(timedOut ? { timedOut: true } : {}),
265
271
  });
266
272
  });
@@ -1298,6 +1304,9 @@ function writeReviewGateExecutionFailure(context, payload) {
1298
1304
  ...(payload.timeoutMs !== undefined
1299
1305
  ? { timeoutMs: payload.timeoutMs }
1300
1306
  : {}),
1307
+ ...(payload.noOutputProduced !== undefined
1308
+ ? { noOutputProduced: payload.noOutputProduced }
1309
+ : {}),
1301
1310
  message,
1302
1311
  });
1303
1312
  return;
@@ -1574,7 +1583,7 @@ async function runReviewGate(prompt, options, context, dependencies) {
1574
1583
  ]);
1575
1584
  const childResult = await executeTarget(selected, [reviewPrompt], context, dependencies);
1576
1585
  const childExitCode = childResult.exitCode;
1577
- if (childExitCode !== 0) {
1586
+ if (childExitCode !== 0 && !childResult.timedOut) {
1578
1587
  writeReviewGateExecutionFailure(context, {
1579
1588
  runId,
1580
1589
  target: selected.id,
@@ -1599,6 +1608,24 @@ async function runReviewGate(prompt, options, context, dependencies) {
1599
1608
  before,
1600
1609
  after,
1601
1610
  });
1611
+ if (childResult.timedOut &&
1612
+ artifactResolution.matchingArtifactPaths.length === 0 &&
1613
+ !artifactResolution.diagnosticArtifact) {
1614
+ writeReviewGateExecutionFailure(context, {
1615
+ runId,
1616
+ target: selected.id,
1617
+ project: projectPath,
1618
+ projectResolutionSource: reviewProject.source,
1619
+ exitCode: childExitCode,
1620
+ timedOut: true,
1621
+ timeoutMs: resolveGateExecTimeoutMs(dependencies.processEnv),
1622
+ noOutputProduced: childResult.stdoutBytes + childResult.stderrBytes === 0,
1623
+ gateInvocation,
1624
+ dispatchReport,
1625
+ });
1626
+ process.exitCode = childExitCode;
1627
+ return;
1628
+ }
1602
1629
  const initialTargetCorroboration = corroborateReviewTarget({
1603
1630
  repoRoot,
1604
1631
  reviewProject,
@@ -1766,6 +1793,7 @@ async function runReviewGate(prompt, options, context, dependencies) {
1766
1793
  gateInvocation,
1767
1794
  dispatchReport,
1768
1795
  corroboration,
1796
+ ...(childResult.timedOut ? { lateCompletion: true } : {}),
1769
1797
  });
1770
1798
  process.exitCode = blocking ? 1 : 0;
1771
1799
  }
@@ -13,6 +13,7 @@ export interface LatestReview {
13
13
  export interface FindLatestReviewOptions {
14
14
  repoRoot: string;
15
15
  projectPath?: string | null;
16
+ actionableProjectOnly?: boolean;
16
17
  }
17
18
  interface ReviewLatestDependencies {
18
19
  buildCommandContext: (options: GlobalOptions) => CommandContext;
@@ -1 +1 @@
1
- {"version":3,"file":"latest.d.ts","sourceRoot":"","sources":["../../../src/commands/review/latest.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE7E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACrB;AAQD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,UAAU,wBAAwB;IAChC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CACnE;AAsID,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAqF9B;AA+CD,wBAAgB,yBAAyB,CACvC,SAAS,GAAE,OAAO,CAAC,wBAAwB,CAAM,GAChD,OAAO,CAkBT"}
1
+ {"version":3,"file":"latest.d.ts","sourceRoot":"","sources":["../../../src/commands/review/latest.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE7E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACrB;AASD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,UAAU,wBAAwB;IAChC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CACnE;AAgOD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAkG9B;AAmDD,wBAAgB,yBAAyB,CACvC,SAAS,GAAE,OAAO,CAAC,wBAAwB,CAAM,GAChD,OAAO,CA2BT"}
@@ -77,9 +77,11 @@ async function readReviewCandidate(repoRoot, relativePath, kind, priority, archi
77
77
  return null;
78
78
  }
79
79
  const scope = getFrontmatterField(frontmatter, 'oat_review_scope') ?? '';
80
+ const reviewType = getFrontmatterField(frontmatter, 'oat_review_type') ?? 'code';
80
81
  return {
81
82
  path: relativePath,
82
83
  scope,
84
+ reviewType,
83
85
  generatedAt,
84
86
  kind,
85
87
  archived,
@@ -89,6 +91,62 @@ async function readReviewCandidate(repoRoot, relativePath, kind, priority, archi
89
91
  priority,
90
92
  };
91
93
  }
94
+ function parseReviewLedgerEvents(planContent) {
95
+ const heading = /^## Reviews[ \t]*\r?$/m.exec(planContent);
96
+ if (!heading) {
97
+ return [];
98
+ }
99
+ const remaining = planContent.slice(heading.index + heading[0].length);
100
+ const nextHeadingIndex = remaining.search(/^##(?!#)[ \t]+\S.*\r?$/m);
101
+ const section = nextHeadingIndex === -1 ? remaining : remaining.slice(0, nextHeadingIndex);
102
+ return section
103
+ .split('\n')
104
+ .filter((line) => line.trim().startsWith('|'))
105
+ .slice(2)
106
+ .map((line) => line
107
+ .split('|')
108
+ .slice(1, -1)
109
+ .map((cell) => cell.trim()))
110
+ .filter((cells) => cells.length === 5)
111
+ .map(([scope = '', type = '', status = '', , artifact = '']) => ({
112
+ scope,
113
+ type,
114
+ status,
115
+ artifact,
116
+ }));
117
+ }
118
+ async function correlateProjectActionability(repoRoot, projectPath, candidates) {
119
+ let planContent;
120
+ try {
121
+ planContent = await readFile(join(repoRoot, projectPath, 'plan.md'), 'utf8');
122
+ }
123
+ catch (error) {
124
+ if (typeof error === 'object' &&
125
+ error !== null &&
126
+ 'code' in error &&
127
+ error.code === 'ENOENT') {
128
+ return candidates;
129
+ }
130
+ throw error;
131
+ }
132
+ const events = parseReviewLedgerEvents(planContent);
133
+ if (events.length === 0) {
134
+ return candidates;
135
+ }
136
+ return candidates.map((candidate) => {
137
+ if (candidate.kind !== 'project' || candidate.archived) {
138
+ return candidate;
139
+ }
140
+ const artifact = normalizeToPosixPath(relative(projectPath, candidate.path));
141
+ const matchingEvent = events.find((event) => event.scope.toLowerCase() === candidate.scope.toLowerCase() &&
142
+ event.type.toLowerCase() === candidate.reviewType.toLowerCase() &&
143
+ normalizeToPosixPath(event.artifact) === artifact);
144
+ return {
145
+ ...candidate,
146
+ actionable: matchingEvent?.status.toLowerCase() === 'received',
147
+ };
148
+ });
149
+ }
92
150
  function sortReviewCandidates(a, b) {
93
151
  if (a.generatedTime !== b.generatedTime) {
94
152
  return b.generatedTime - a.generatedTime;
@@ -116,34 +174,45 @@ export async function findLatestReview(options) {
116
174
  priority: 0,
117
175
  archived: false,
118
176
  actionable: true,
177
+ });
178
+ if (!options.actionableProjectOnly) {
179
+ scanTargets.push({
180
+ dir: `${projectPath}/reviews/archived`,
181
+ kind: 'project',
182
+ priority: 1,
183
+ archived: true,
184
+ actionable: false,
185
+ });
186
+ }
187
+ }
188
+ if (!options.actionableProjectOnly) {
189
+ scanTargets.push({
190
+ dir: '.oat/repo/reviews',
191
+ kind: 'adhoc',
192
+ priority: 2,
193
+ archived: false,
194
+ actionable: true,
119
195
  }, {
120
- dir: `${projectPath}/reviews/archived`,
121
- kind: 'project',
122
- priority: 1,
123
- archived: true,
124
- actionable: false,
196
+ dir: '.oat/projects/local/orphan-reviews',
197
+ kind: 'adhoc',
198
+ priority: 3,
199
+ archived: false,
200
+ actionable: true,
125
201
  });
126
202
  }
127
- scanTargets.push({
128
- dir: '.oat/repo/reviews',
129
- kind: 'adhoc',
130
- priority: 2,
131
- archived: false,
132
- actionable: true,
133
- }, {
134
- dir: '.oat/projects/local/orphan-reviews',
135
- kind: 'adhoc',
136
- priority: 3,
137
- archived: false,
138
- actionable: true,
139
- });
140
- const candidates = (await Promise.all(scanTargets.map(async (target) => {
203
+ let candidates = (await Promise.all(scanTargets.map(async (target) => {
141
204
  const files = await listMarkdownFiles(options.repoRoot, target.dir);
142
205
  return Promise.all(files.map((file) => readReviewCandidate(options.repoRoot, file, target.kind, target.priority, target.archived, target.actionable)));
143
206
  })))
144
207
  .flat()
145
- .filter((candidate) => candidate !== null)
146
- .sort(sortReviewCandidates);
208
+ .filter((candidate) => candidate !== null);
209
+ if (projectPath) {
210
+ candidates = await correlateProjectActionability(options.repoRoot, projectPath, candidates);
211
+ }
212
+ if (options.actionableProjectOnly) {
213
+ candidates = candidates.filter((candidate) => candidate.actionable);
214
+ }
215
+ candidates.sort(sortReviewCandidates);
147
216
  const latest = candidates[0];
148
217
  if (!latest) {
149
218
  return null;
@@ -168,7 +237,11 @@ async function runReviewLatest(context, options, dependencies) {
168
237
  try {
169
238
  const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
170
239
  const projectPath = await resolveProjectPath(repoRoot, options.project, dependencies);
171
- const result = await findLatestReview({ repoRoot, projectPath });
240
+ const result = await findLatestReview({
241
+ repoRoot,
242
+ projectPath,
243
+ actionableProjectOnly: options.actionableProject,
244
+ });
172
245
  if (context.json) {
173
246
  context.logger.json(result ?? EMPTY_RESULT);
174
247
  }
@@ -196,6 +269,7 @@ export function createReviewLatestCommand(overrides = {}) {
196
269
  return new Command('latest')
197
270
  .description('Find the most recent OAT review artifact')
198
271
  .option('--project <path>', 'Project path to scan in addition to ad-hoc review locations')
272
+ .option('--actionable-project', 'Scan only active project reviews, excluding archived and ad-hoc history')
199
273
  .action(async (options, command) => {
200
274
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
201
275
  await runReviewLatest(context, options, dependencies);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.1.65",
3
+ "version": "0.1.69",
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.65"
37
+ "@open-agent-toolkit/control-plane": "0.1.69"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.0",