@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.
- package/assets/agents/oat-reviewer.md +2 -2
- package/assets/docs/cli-utilities/workflow-gates.md +24 -5
- package/assets/docs/reference/cli-reference.md +1 -1
- package/assets/docs/workflows/projects/dispatch-ceiling.md +11 -3
- package/assets/docs/workflows/projects/pr-flow.md +12 -1
- package/assets/docs/workflows/projects/reviews.md +21 -1
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-agent-instructions-analyze/SKILL.md +3 -2
- package/assets/skills/oat-project-autonomous/SKILL.md +1 -1
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +6 -6
- package/assets/skills/oat-project-complete/SKILL.md +20 -2
- package/assets/skills/oat-project-design/SKILL.md +88 -75
- package/assets/skills/oat-project-discover/SKILL.md +83 -64
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +6 -6
- package/assets/skills/oat-project-implement/SKILL.md +1 -1
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +12 -1
- package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +24 -9
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +6 -6
- package/assets/skills/oat-project-implement/references/phase-execution.md +5 -2
- package/assets/skills/oat-project-next/SKILL.md +21 -6
- package/assets/skills/oat-project-plan/SKILL.md +69 -56
- package/assets/skills/oat-project-plan-writing/SKILL.md +19 -2
- package/assets/skills/oat-project-pr-final/SKILL.md +20 -5
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +6 -6
- package/assets/skills/oat-project-pr-progress/SKILL.md +18 -3
- package/assets/skills/oat-project-progress/SKILL.md +4 -1
- package/assets/skills/oat-project-quick-start/SKILL.md +68 -55
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +6 -6
- package/assets/skills/oat-project-review-provide/SKILL.md +7 -2
- package/assets/skills/oat-project-review-receive/SKILL.md +46 -18
- package/assets/skills/oat-project-review-receive-remote/SKILL.md +41 -8
- package/dist/commands/cleanup/project/project.utils.d.ts.map +1 -1
- package/dist/commands/cleanup/project/project.utils.js +19 -1
- package/dist/commands/gate/index.d.ts +2 -0
- package/dist/commands/gate/index.d.ts.map +1 -1
- package/dist/commands/gate/index.js +29 -1
- package/dist/commands/review/latest.d.ts +1 -0
- package/dist/commands/review/latest.d.ts.map +1 -1
- package/dist/commands/review/latest.js +96 -22
- 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;
|
|
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:
|
|
121
|
-
kind: '
|
|
122
|
-
priority:
|
|
123
|
-
archived:
|
|
124
|
-
actionable:
|
|
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.
|
|
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
|
-
|
|
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({
|
|
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.
|
|
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.
|
|
37
|
+
"@open-agent-toolkit/control-plane": "0.1.69"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.10.0",
|