@open-agent-toolkit/cli 0.2.23 → 0.2.25
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 +12 -1
- package/assets/docs/cli-utilities/configuration.md +2 -4
- package/assets/docs/cli-utilities/workflow-gates.md +27 -3
- package/assets/docs/reference/cli-reference.md +1 -1
- package/assets/docs/workflows/projects/reviews.md +19 -10
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +3 -3
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-implement/SKILL.md +1 -1
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-implement/references/phase-execution.md +29 -0
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +3 -3
- package/assets/skills/oat-project-review-provide/SKILL.md +124 -26
- package/assets/skills/oat-project-review-provide-remote/SKILL.md +64 -15
- package/assets/skills/oat-project-review-receive/SKILL.md +21 -1
- package/assets/skills/oat-project-review-receive-remote/SKILL.md +39 -2
- package/assets/skills/oat-review-provide-remote/SKILL.md +55 -12
- package/assets/templates/plan.md +13 -7
- package/dist/commands/config/index.js +8 -8
- package/dist/commands/gate/child-process.d.ts +32 -0
- package/dist/commands/gate/child-process.d.ts.map +1 -0
- package/dist/commands/gate/child-process.js +210 -0
- package/dist/commands/gate/index.d.ts +2 -31
- package/dist/commands/gate/index.d.ts.map +1 -1
- package/dist/commands/gate/index.js +24 -150
- package/dist/commands/review/latest.d.ts.map +1 -1
- package/dist/commands/review/latest.js +22 -9
- package/dist/config/resolve.js +1 -1
- package/dist/review-remote/body-builder.d.ts +12 -3
- package/dist/review-remote/body-builder.d.ts.map +1 -1
- package/dist/review-remote/body-builder.js +11 -0
- package/dist/review-remote/marker-parser.d.ts +8 -3
- package/dist/review-remote/marker-parser.d.ts.map +1 -1
- package/dist/review-remote/marker-parser.js +13 -2
- package/dist/review-remote/narrowing.d.ts +44 -8
- package/dist/review-remote/narrowing.d.ts.map +1 -1
- package/dist/review-remote/narrowing.js +106 -10
- package/package.json +2 -2
|
@@ -9,16 +9,85 @@
|
|
|
9
9
|
* range, so a rebased/force-pushed/shallow prior SHA never produces a
|
|
10
10
|
* misleading partial range.
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
const FULL_COMMIT_SHA = /^[0-9a-f]{40}$/i;
|
|
13
|
+
/**
|
|
14
|
+
* Normalize one parsed GitHub marker into a narrowing candidate. Unknown
|
|
15
|
+
* invocation and target-less gate markers preserve their metadata but carry no
|
|
16
|
+
* lineage, so tuple matching rejects them and fails open.
|
|
17
|
+
*/
|
|
18
|
+
export function priorReviewFromMarker(marker, submittedAt) {
|
|
19
|
+
const lineage = markerLineage(marker);
|
|
20
|
+
return {
|
|
21
|
+
headSha: marker.oat_review_head_sha,
|
|
22
|
+
scope: marker.oat_review_scope,
|
|
23
|
+
...(marker.oat_project ? { project: marker.oat_project } : {}),
|
|
24
|
+
...(marker.oat_review_invocation
|
|
25
|
+
? { invocation: marker.oat_review_invocation }
|
|
26
|
+
: {}),
|
|
27
|
+
...(lineage ? { lineage } : {}),
|
|
28
|
+
submittedAt,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function markerLineage(marker) {
|
|
32
|
+
if (marker.oat_review_invocation === 'manual' ||
|
|
33
|
+
marker.oat_review_invocation === 'auto') {
|
|
34
|
+
return { kind: 'lifecycle' };
|
|
35
|
+
}
|
|
36
|
+
const gateTarget = marker.oat_gate_target?.trim();
|
|
37
|
+
return marker.oat_review_invocation === 'gate' && gateTarget
|
|
38
|
+
? { kind: 'gate', target: gateTarget }
|
|
39
|
+
: undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Normalize durable ledger provenance into the same candidate shape used by
|
|
43
|
+
* artifact-sourced reviews. Both sources then pass through {@link matchesTuple}
|
|
44
|
+
* and cannot drift into separate lineage predicates.
|
|
45
|
+
*/
|
|
46
|
+
export function priorReviewFromLedger(row) {
|
|
47
|
+
const invocation = isReviewInvocationKind(row.invocation)
|
|
48
|
+
? row.invocation
|
|
49
|
+
: undefined;
|
|
50
|
+
const lineage = ledgerLineage(row);
|
|
51
|
+
return {
|
|
52
|
+
headSha: row.reviewedHead,
|
|
53
|
+
scope: row.scope,
|
|
54
|
+
...(row.project ? { project: row.project } : {}),
|
|
55
|
+
...(invocation ? { invocation } : {}),
|
|
56
|
+
...(lineage ? { lineage } : {}),
|
|
57
|
+
submittedAt: row.submittedAt,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function isReviewInvocationKind(invocation) {
|
|
61
|
+
return (invocation === 'manual' || invocation === 'auto' || invocation === 'gate');
|
|
62
|
+
}
|
|
63
|
+
function ledgerLineage(row) {
|
|
64
|
+
if (row.invocation === 'manual' || row.invocation === 'auto') {
|
|
65
|
+
return { kind: 'lifecycle' };
|
|
66
|
+
}
|
|
67
|
+
const gateTarget = row.gateTarget?.trim();
|
|
68
|
+
return row.invocation === 'gate' && gateTarget
|
|
69
|
+
? { kind: 'gate', target: gateTarget }
|
|
70
|
+
: undefined;
|
|
71
|
+
}
|
|
72
|
+
/** Does a prior review match the current rail, project, scope, and lineage? */
|
|
13
73
|
function matchesTuple(review, input) {
|
|
74
|
+
if (!FULL_COMMIT_SHA.test(review.headSha)) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
const sameLineage = review.lineage !== undefined &&
|
|
78
|
+
review.lineage.kind === input.lineage.kind &&
|
|
79
|
+
(input.lineage.kind === 'lifecycle' ||
|
|
80
|
+
(review.lineage.kind === 'gate' &&
|
|
81
|
+
review.lineage.target === input.lineage.target));
|
|
14
82
|
if (input.rail === 'ad-hoc') {
|
|
15
83
|
// Ad-hoc: scope sentinel must match AND there must be no project key.
|
|
16
|
-
return review.scope === 'ad-hoc' && review.project === undefined;
|
|
84
|
+
return (review.scope === 'ad-hoc' && review.project === undefined && sameLineage);
|
|
17
85
|
}
|
|
18
86
|
// Project rail: same project AND same scope.
|
|
19
87
|
return (review.project !== undefined &&
|
|
20
88
|
review.project === input.project &&
|
|
21
|
-
review.scope === input.scope
|
|
89
|
+
review.scope === input.scope &&
|
|
90
|
+
sameLineage);
|
|
22
91
|
}
|
|
23
92
|
function mostRecentMatch(input) {
|
|
24
93
|
const matches = input.reviews.filter((r) => matchesTuple(r, input));
|
|
@@ -48,16 +117,47 @@ async function guardPasses(priorSha, input) {
|
|
|
48
117
|
}
|
|
49
118
|
return input.git.isAncestor(priorSha, input.headSha);
|
|
50
119
|
}
|
|
120
|
+
async function classifyRange(priorSha, input) {
|
|
121
|
+
let files;
|
|
122
|
+
try {
|
|
123
|
+
files = await input.git.changedFiles(priorSha, input.headSha);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Classification is reporting-only, so enumeration failure must not block
|
|
127
|
+
// dispatch. Treat unknown work as substantive and disclose the fallback.
|
|
128
|
+
return {
|
|
129
|
+
classification: 'substantive',
|
|
130
|
+
classificationReason: 'changed-files-unavailable',
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (files.length === 0) {
|
|
134
|
+
return { classification: 'empty' };
|
|
135
|
+
}
|
|
136
|
+
const projectPrefix = input.project === null ? null : `${input.project.replace(/\/+$/, '')}/`;
|
|
137
|
+
// Path-only classification is sufficient while it is reporting-only. If it
|
|
138
|
+
// ever authorizes skipping work, strengthen it with lifecycle corroboration.
|
|
139
|
+
return {
|
|
140
|
+
classification: projectPrefix !== null &&
|
|
141
|
+
files.every((file) => file.startsWith(projectPrefix))
|
|
142
|
+
? 'bookkeeping-only'
|
|
143
|
+
: 'substantive',
|
|
144
|
+
};
|
|
145
|
+
}
|
|
51
146
|
/**
|
|
52
147
|
* Pick the narrowing target for the current re-review pass.
|
|
53
148
|
*/
|
|
54
149
|
export async function pickNarrowingTarget(input) {
|
|
150
|
+
if (input.narrowingPreference === false && !input.forceNarrow) {
|
|
151
|
+
return {
|
|
152
|
+
kind: 'full-scope-fallback',
|
|
153
|
+
reason: 'narrowing-disabled',
|
|
154
|
+
};
|
|
155
|
+
}
|
|
55
156
|
const prior = mostRecentMatch(input);
|
|
56
157
|
if (!prior) {
|
|
57
158
|
return {
|
|
58
159
|
kind: 'full-scope-fallback',
|
|
59
160
|
reason: 'no-prior-review',
|
|
60
|
-
prompted: false,
|
|
61
161
|
};
|
|
62
162
|
}
|
|
63
163
|
const passed = await guardPasses(prior.headSha, input);
|
|
@@ -66,8 +166,7 @@ export async function pickNarrowingTarget(input) {
|
|
|
66
166
|
kind: 'narrow-range',
|
|
67
167
|
priorSha: prior.headSha,
|
|
68
168
|
headSha: input.headSha,
|
|
69
|
-
|
|
70
|
-
prompted: !input.autoNarrow,
|
|
169
|
+
...(await classifyRange(prior.headSha, input)),
|
|
71
170
|
};
|
|
72
171
|
}
|
|
73
172
|
// Guard failed. The user explicitly asked to narrow → hard error.
|
|
@@ -78,13 +177,10 @@ export async function pickNarrowingTarget(input) {
|
|
|
78
177
|
priorSha: prior.headSha,
|
|
79
178
|
};
|
|
80
179
|
}
|
|
81
|
-
// Otherwise
|
|
82
|
-
// auto-fallback notice (no prompt); manual mode does not prompt here either —
|
|
83
|
-
// the fallback is informational.
|
|
180
|
+
// Otherwise fail open to full scope and preserve the guard failure reason.
|
|
84
181
|
return {
|
|
85
182
|
kind: 'full-scope-fallback',
|
|
86
183
|
reason: 'stale-sha',
|
|
87
184
|
priorSha: prior.headSha,
|
|
88
|
-
prompted: false,
|
|
89
185
|
};
|
|
90
186
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-agent-toolkit/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.25",
|
|
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.2.
|
|
37
|
+
"@open-agent-toolkit/control-plane": "0.2.25"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.10.0",
|