agentxchain 2.14.0 → 2.16.0
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/README.md +9 -3
- package/bin/agentxchain.js +20 -2
- package/package.json +3 -1
- package/scripts/release-downstream-truth.sh +15 -14
- package/scripts/release-postflight.sh +21 -5
- package/scripts/sync-homebrew.sh +225 -0
- package/src/commands/init.js +16 -6
- package/src/commands/intake-approve.js +2 -10
- package/src/commands/intake-handoff.js +58 -0
- package/src/commands/intake-plan.js +2 -11
- package/src/commands/intake-record.js +2 -10
- package/src/commands/intake-resolve.js +2 -10
- package/src/commands/intake-scan.js +2 -10
- package/src/commands/intake-start.js +2 -10
- package/src/commands/intake-status.js +6 -10
- package/src/commands/intake-triage.js +2 -10
- package/src/commands/intake-workspace.js +58 -0
- package/src/commands/migrate.js +7 -3
- package/src/commands/multi.js +58 -2
- package/src/commands/run.js +29 -1
- package/src/commands/template-set.js +51 -2
- package/src/lib/adapter-interface.js +31 -0
- package/src/lib/coordinator-acceptance.js +24 -98
- package/src/lib/coordinator-barriers.js +116 -0
- package/src/lib/coordinator-config.js +124 -0
- package/src/lib/coordinator-dispatch.js +10 -1
- package/src/lib/coordinator-gates.js +28 -1
- package/src/lib/coordinator-recovery.js +133 -68
- package/src/lib/coordinator-state.js +74 -0
- package/src/lib/cross-repo-context.js +68 -1
- package/src/lib/governed-templates.js +60 -0
- package/src/lib/intake-handoff.js +58 -0
- package/src/lib/intake.js +300 -11
- package/src/lib/report.js +759 -27
- package/src/lib/workflow-gate-semantics.js +209 -0
- package/src/templates/governed/api-service.json +8 -1
- package/src/templates/governed/cli-tool.json +8 -1
- package/src/templates/governed/library.json +8 -1
- package/src/templates/governed/web-app.json +8 -1
|
@@ -2,9 +2,14 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
|
|
4
4
|
export const PM_SIGNOFF_PATH = '.planning/PM_SIGNOFF.md';
|
|
5
|
+
export const SYSTEM_SPEC_PATH = '.planning/SYSTEM_SPEC.md';
|
|
6
|
+
export const IMPLEMENTATION_NOTES_PATH = '.planning/IMPLEMENTATION_NOTES.md';
|
|
7
|
+
export const ACCEPTANCE_MATRIX_PATH = '.planning/acceptance-matrix.md';
|
|
5
8
|
export const SHIP_VERDICT_PATH = '.planning/ship-verdict.md';
|
|
9
|
+
export const RELEASE_NOTES_PATH = '.planning/RELEASE_NOTES.md';
|
|
6
10
|
|
|
7
11
|
const AFFIRMATIVE_SHIP_VERDICTS = new Set(['YES', 'SHIP', 'SHIP IT']);
|
|
12
|
+
const AFFIRMATIVE_ACCEPTANCE_STATUSES = new Set(['PASS', 'PASSED', 'OK', 'YES']);
|
|
8
13
|
|
|
9
14
|
function normalizeToken(value) {
|
|
10
15
|
return value.trim().replace(/\s+/g, ' ').toUpperCase();
|
|
@@ -42,6 +47,194 @@ function evaluatePmSignoff(content) {
|
|
|
42
47
|
return { ok: true };
|
|
43
48
|
}
|
|
44
49
|
|
|
50
|
+
function evaluateSystemSpec(content) {
|
|
51
|
+
const requiredSections = ['## Purpose', '## Interface', '## Acceptance Tests'];
|
|
52
|
+
const missingSections = requiredSections.filter((section) => !content.includes(section));
|
|
53
|
+
|
|
54
|
+
if (missingSections.length > 0) {
|
|
55
|
+
return {
|
|
56
|
+
ok: false,
|
|
57
|
+
reason: `.planning/SYSTEM_SPEC.md must define ${missingSections.join(', ')} before planning can exit.`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { ok: true };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isMarkdownSeparatorRow(cells) {
|
|
65
|
+
return cells.length > 0 && cells.every((cell) => /^:?-{3,}:?$/.test(cell));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function evaluateAcceptanceMatrix(content) {
|
|
69
|
+
const lines = content.split(/\r?\n/);
|
|
70
|
+
const headerIndex = lines.findIndex((line) => /^\|\s*Req\s*#\s*\|/i.test(line));
|
|
71
|
+
|
|
72
|
+
if (headerIndex === -1) {
|
|
73
|
+
return {
|
|
74
|
+
ok: false,
|
|
75
|
+
reason: 'Acceptance matrix must preserve the `| Req # |` requirement table header in .planning/acceptance-matrix.md.',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const rows = [];
|
|
80
|
+
let sawTable = false;
|
|
81
|
+
|
|
82
|
+
for (let index = headerIndex + 1; index < lines.length; index++) {
|
|
83
|
+
const line = lines[index];
|
|
84
|
+
if (!line.trim()) {
|
|
85
|
+
if (sawTable) break;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!line.trim().startsWith('|')) {
|
|
90
|
+
if (sawTable) break;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
sawTable = true;
|
|
95
|
+
const cells = line
|
|
96
|
+
.trim()
|
|
97
|
+
.split('|')
|
|
98
|
+
.slice(1, -1)
|
|
99
|
+
.map((cell) => cell.trim());
|
|
100
|
+
|
|
101
|
+
if (cells.length === 0 || isMarkdownSeparatorRow(cells)) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
rows.push(cells);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const requirementRows = rows.filter((cells) => {
|
|
109
|
+
const reqId = cells[0] || '';
|
|
110
|
+
return reqId && !/^\(QA fills this from ROADMAP\.md\)$/i.test(reqId);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
if (requirementRows.length === 0) {
|
|
114
|
+
return {
|
|
115
|
+
ok: false,
|
|
116
|
+
reason: 'Acceptance matrix has no real requirement verdict rows. Replace the scaffold placeholder with QA-owned requirement results before requesting ship approval.',
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const failingRows = [];
|
|
121
|
+
for (const cells of requirementRows) {
|
|
122
|
+
const reqId = cells[0] || '<unknown>';
|
|
123
|
+
const status = cells[cells.length - 1] || '';
|
|
124
|
+
const normalizedStatus = status ? normalizeToken(status) : '';
|
|
125
|
+
if (!AFFIRMATIVE_ACCEPTANCE_STATUSES.has(normalizedStatus)) {
|
|
126
|
+
failingRows.push(`${reqId}=${status || 'missing'}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (failingRows.length > 0) {
|
|
131
|
+
return {
|
|
132
|
+
ok: false,
|
|
133
|
+
reason: `Acceptance matrix still has non-passing requirement rows in .planning/acceptance-matrix.md: ${failingRows.join(', ')}. Mark every requirement row with a passing Status before requesting ship approval.`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return { ok: true };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const IMPLEMENTATION_NOTES_PLACEHOLDER = /^\(Dev fills this during implementation\)$/i;
|
|
141
|
+
|
|
142
|
+
function hasSectionContent(content, sectionHeader) {
|
|
143
|
+
const lines = content.split(/\r?\n/);
|
|
144
|
+
const headerIndex = lines.findIndex((line) => line.trim().startsWith(sectionHeader));
|
|
145
|
+
if (headerIndex === -1) {
|
|
146
|
+
return { found: false, hasContent: false };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
for (let i = headerIndex + 1; i < lines.length; i++) {
|
|
150
|
+
const line = lines[i].trim();
|
|
151
|
+
if (line.startsWith('## ')) break;
|
|
152
|
+
if (!line) continue;
|
|
153
|
+
if (IMPLEMENTATION_NOTES_PLACEHOLDER.test(line)) continue;
|
|
154
|
+
return { found: true, hasContent: true };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return { found: true, hasContent: false };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function evaluateImplementationNotes(content) {
|
|
161
|
+
const changes = hasSectionContent(content, '## Changes');
|
|
162
|
+
const verification = hasSectionContent(content, '## Verification');
|
|
163
|
+
|
|
164
|
+
const missingSections = [];
|
|
165
|
+
if (!changes.found) missingSections.push('## Changes');
|
|
166
|
+
if (!verification.found) missingSections.push('## Verification');
|
|
167
|
+
|
|
168
|
+
if (missingSections.length > 0) {
|
|
169
|
+
return {
|
|
170
|
+
ok: false,
|
|
171
|
+
reason: `.planning/IMPLEMENTATION_NOTES.md must define ${missingSections.join(' and ')} before implementation can exit.`,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const emptySections = [];
|
|
176
|
+
if (!changes.hasContent) emptySections.push('## Changes');
|
|
177
|
+
if (!verification.hasContent) emptySections.push('## Verification');
|
|
178
|
+
|
|
179
|
+
if (emptySections.length > 0) {
|
|
180
|
+
return {
|
|
181
|
+
ok: false,
|
|
182
|
+
reason: `${emptySections.join(' and ')} in .planning/IMPLEMENTATION_NOTES.md still contains only placeholder text. Dev must replace placeholder content with real implementation notes.`,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return { ok: true };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const RELEASE_NOTES_PLACEHOLDER = /^\(QA fills this during the QA phase\)$/i;
|
|
190
|
+
|
|
191
|
+
function hasReleaseNotesSectionContent(content, sectionHeader) {
|
|
192
|
+
const lines = content.split(/\r?\n/);
|
|
193
|
+
const headerIndex = lines.findIndex((line) => line.trim().startsWith(sectionHeader));
|
|
194
|
+
if (headerIndex === -1) {
|
|
195
|
+
return { found: false, hasContent: false };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
for (let i = headerIndex + 1; i < lines.length; i++) {
|
|
199
|
+
const line = lines[i].trim();
|
|
200
|
+
if (line.startsWith('## ')) break;
|
|
201
|
+
if (!line) continue;
|
|
202
|
+
if (RELEASE_NOTES_PLACEHOLDER.test(line)) continue;
|
|
203
|
+
return { found: true, hasContent: true };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return { found: true, hasContent: false };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function evaluateReleaseNotes(content) {
|
|
210
|
+
const userImpact = hasReleaseNotesSectionContent(content, '## User Impact');
|
|
211
|
+
const verificationSummary = hasReleaseNotesSectionContent(content, '## Verification Summary');
|
|
212
|
+
|
|
213
|
+
const missingSections = [];
|
|
214
|
+
if (!userImpact.found) missingSections.push('## User Impact');
|
|
215
|
+
if (!verificationSummary.found) missingSections.push('## Verification Summary');
|
|
216
|
+
|
|
217
|
+
if (missingSections.length > 0) {
|
|
218
|
+
return {
|
|
219
|
+
ok: false,
|
|
220
|
+
reason: `.planning/RELEASE_NOTES.md must define ${missingSections.join(' and ')} before ship approval can be requested.`,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const emptySections = [];
|
|
225
|
+
if (!userImpact.hasContent) emptySections.push('## User Impact');
|
|
226
|
+
if (!verificationSummary.hasContent) emptySections.push('## Verification Summary');
|
|
227
|
+
|
|
228
|
+
if (emptySections.length > 0) {
|
|
229
|
+
return {
|
|
230
|
+
ok: false,
|
|
231
|
+
reason: `${emptySections.join(' and ')} in .planning/RELEASE_NOTES.md still contains only placeholder text. QA must replace placeholder content with real release notes.`,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return { ok: true };
|
|
236
|
+
}
|
|
237
|
+
|
|
45
238
|
function evaluateShipVerdict(content) {
|
|
46
239
|
const verdict = parseLineValue(content, /^##\s+Verdict\s*:\s*(.+)$/im);
|
|
47
240
|
if (!verdict) {
|
|
@@ -71,9 +264,25 @@ export function evaluateWorkflowGateSemantics(root, relPath) {
|
|
|
71
264
|
return evaluatePmSignoff(content);
|
|
72
265
|
}
|
|
73
266
|
|
|
267
|
+
if (relPath === SYSTEM_SPEC_PATH) {
|
|
268
|
+
return evaluateSystemSpec(content);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (relPath === IMPLEMENTATION_NOTES_PATH) {
|
|
272
|
+
return evaluateImplementationNotes(content);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (relPath === ACCEPTANCE_MATRIX_PATH) {
|
|
276
|
+
return evaluateAcceptanceMatrix(content);
|
|
277
|
+
}
|
|
278
|
+
|
|
74
279
|
if (relPath === SHIP_VERDICT_PATH) {
|
|
75
280
|
return evaluateShipVerdict(content);
|
|
76
281
|
}
|
|
77
282
|
|
|
283
|
+
if (relPath === RELEASE_NOTES_PATH) {
|
|
284
|
+
return evaluateReleaseNotes(content);
|
|
285
|
+
}
|
|
286
|
+
|
|
78
287
|
return null;
|
|
79
288
|
}
|
|
@@ -27,5 +27,12 @@
|
|
|
27
27
|
"API contract reviewed and endpoints listed",
|
|
28
28
|
"Error cases enumerated with recovery expectations",
|
|
29
29
|
"Verification command covers automated tests or smoke checks"
|
|
30
|
-
]
|
|
30
|
+
],
|
|
31
|
+
"system_spec_overlay": {
|
|
32
|
+
"purpose_guidance": "Describe the API service, its consumers, and the problem it solves. Include the primary use case and why this service exists as a separate boundary.",
|
|
33
|
+
"interface_guidance": "List the endpoints (method, path, auth), request/response schemas, and backward-compatibility commitments. Reference api-contract.md for the full surface.",
|
|
34
|
+
"behavior_guidance": "Describe the expected runtime behavior: request lifecycle, caching, rate limiting, and any async processing. Include latency and throughput expectations.",
|
|
35
|
+
"error_cases_guidance": "List HTTP error responses, upstream dependency failures, auth rejection behavior, and rate-limit enforcement. Reference error-budget.md for failure thresholds.",
|
|
36
|
+
"acceptance_tests_guidance": "- [ ] API contract endpoints return expected status codes and shapes\n- [ ] Error responses match documented error contract\n- [ ] Auth rejection returns 401/403 with correct body\n- [ ] Operational readiness checklist items verified"
|
|
37
|
+
}
|
|
31
38
|
}
|
|
@@ -26,5 +26,12 @@
|
|
|
26
26
|
"Command help audited for every user-facing command touched",
|
|
27
27
|
"Install or invocation path checked on the intended runtime",
|
|
28
28
|
"Failure-mode UX reviewed for invalid flags or missing inputs"
|
|
29
|
-
]
|
|
29
|
+
],
|
|
30
|
+
"system_spec_overlay": {
|
|
31
|
+
"purpose_guidance": "Describe the CLI tool, its primary users, and the workflow it enables. Include the core commands and why this tool exists.",
|
|
32
|
+
"interface_guidance": "List the user-facing commands, flags, and options. Reference command-surface.md for the full command table. Include stdin/stdout/stderr contracts.",
|
|
33
|
+
"behavior_guidance": "Describe the expected behavior for each primary command, including exit codes, output format (human vs JSON), and safe retry semantics.",
|
|
34
|
+
"error_cases_guidance": "List invalid-flag handling, missing-input behavior, permission errors, and network failure UX. Include expected error messages and help fallback behavior.",
|
|
35
|
+
"acceptance_tests_guidance": "- [ ] Primary commands produce expected output and exit codes\n- [ ] Help text is accurate for every user-facing command\n- [ ] Invalid flags and missing inputs produce clear error messages\n- [ ] Install and invocation paths verified on target platforms"
|
|
36
|
+
}
|
|
30
37
|
}
|
|
@@ -27,5 +27,12 @@
|
|
|
27
27
|
"Public API surface reviewed and intentionally versioned",
|
|
28
28
|
"Compatibility or migration expectations documented for consumers",
|
|
29
29
|
"Install/import or package-consumer smoke path verified"
|
|
30
|
-
]
|
|
30
|
+
],
|
|
31
|
+
"system_spec_overlay": {
|
|
32
|
+
"purpose_guidance": "Describe the library, its consumers, and the capability it provides. Include the primary export surface and why this is a separate package.",
|
|
33
|
+
"interface_guidance": "List the public exports, import paths, and stable vs experimental surface. Reference public-api.md for the full consumer contract.",
|
|
34
|
+
"behavior_guidance": "Describe the expected behavior of the public API: input/output contracts, side effects, thread safety, and performance characteristics.",
|
|
35
|
+
"error_cases_guidance": "List invalid-input handling, type errors at the consumer boundary, and breaking-change scenarios. Reference compatibility-policy.md for deprecation paths.",
|
|
36
|
+
"acceptance_tests_guidance": "- [ ] Public API exports match documented surface\n- [ ] Consumer install and import smoke check passes\n- [ ] Breaking changes have deprecation path documented\n- [ ] Supported runtime versions verified"
|
|
37
|
+
}
|
|
31
38
|
}
|
|
@@ -26,5 +26,12 @@
|
|
|
26
26
|
"Primary user flow reviewed end to end",
|
|
27
27
|
"Mobile and desktop behavior checked explicitly",
|
|
28
28
|
"Accessibility or copy regressions noted before ship request"
|
|
29
|
-
]
|
|
29
|
+
],
|
|
30
|
+
"system_spec_overlay": {
|
|
31
|
+
"purpose_guidance": "Describe the web application, its target users, and the primary user flow it enables. Include the core screens and why this product exists.",
|
|
32
|
+
"interface_guidance": "List the user-facing screens, routes, and interactive elements. Reference user-flows.md for the full flow map. Include auth and navigation contracts.",
|
|
33
|
+
"behavior_guidance": "Describe the expected behavior of primary user flows: page load sequence, state management, real-time updates, and responsive breakpoints.",
|
|
34
|
+
"error_cases_guidance": "List network failure UX, form validation errors, auth expiry handling, and empty-state rendering. Reference ui-acceptance.md for visual acceptance criteria.",
|
|
35
|
+
"acceptance_tests_guidance": "- [ ] Primary user flow completes end to end\n- [ ] Mobile and desktop layouts render correctly\n- [ ] Error states and empty states display correctly\n- [ ] Accessibility smoke checks pass (keyboard nav, contrast)"
|
|
36
|
+
}
|
|
30
37
|
}
|