@tekyzinc/gsd-t 3.29.11 → 4.0.12
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/CHANGELOG.md +146 -0
- package/bin/gsd-t-parallel.cjs +64 -13
- package/bin/gsd-t.js +48 -376
- package/bin/journey-coverage.cjs +6 -3
- package/bin/parallel-cli.cjs +13 -1
- package/commands/gsd-t-debug.md +47 -533
- package/commands/gsd-t-design-decompose.md +24 -497
- package/commands/gsd-t-doc-ripple.md +23 -139
- package/commands/gsd-t-execute.md +41 -958
- package/commands/gsd-t-help.md +0 -2
- package/commands/gsd-t-impact.md +26 -295
- package/commands/gsd-t-integrate.md +44 -369
- package/commands/gsd-t-milestone.md +25 -124
- package/commands/gsd-t-partition.md +28 -539
- package/commands/gsd-t-plan.md +26 -472
- package/commands/gsd-t-prd.md +25 -311
- package/commands/gsd-t-quick.md +1 -1
- package/commands/gsd-t-resume.md +0 -33
- package/commands/gsd-t-verify.md +52 -569
- package/commands/gsd-t-wave.md +41 -430
- package/package.json +1 -1
- package/scripts/gsd-t-calibration-hook.js +3 -1
- package/scripts/hooks/pre-commit-journey-coverage +0 -2
- package/scripts/hooks/pre-commit-playwright-gate +0 -2
- package/templates/CLAUDE-global.md +43 -173
- package/templates/CLAUDE-project.md +118 -104
- package/templates/prompts/design-verify-subagent.md +3 -0
- package/templates/prompts/qa-subagent.md +3 -0
- package/templates/prompts/red-team-subagent.md +5 -2
- package/templates/workflows/_lib.js +176 -0
- package/templates/workflows/gsd-t-debug.workflow.js +86 -0
- package/templates/workflows/gsd-t-execute.workflow.js +206 -0
- package/templates/workflows/gsd-t-integrate.workflow.js +71 -0
- package/templates/workflows/gsd-t-phase.workflow.js +94 -0
- package/templates/workflows/gsd-t-quick.workflow.js +72 -0
- package/templates/workflows/gsd-t-verify.workflow.js +348 -0
- package/templates/workflows/gsd-t-wave.workflow.js +43 -0
- package/bin/check-headless-sessions.js +0 -140
- package/bin/context-budget-audit.cjs +0 -447
- package/bin/context-meter-config.cjs +0 -101
- package/bin/context-meter-config.test.cjs +0 -101
- package/bin/event-stream.cjs +0 -205
- package/bin/gsd-t-benchmark-orchestrator.js +0 -437
- package/bin/gsd-t-capture-lint.cjs +0 -440
- package/bin/gsd-t-economics.cjs +0 -315
- package/bin/gsd-t-in-session-usage.cjs +0 -213
- package/bin/gsd-t-orchestrator-config.cjs +0 -161
- package/bin/gsd-t-orchestrator-queue.cjs +0 -180
- package/bin/gsd-t-orchestrator-recover.cjs +0 -231
- package/bin/gsd-t-orchestrator-worker.cjs +0 -219
- package/bin/gsd-t-orchestrator.js +0 -535
- package/bin/gsd-t-parallel-probe.cjs +0 -132
- package/bin/gsd-t-ratelimit-probe-worker.cjs +0 -237
- package/bin/gsd-t-ratelimit-probe.cjs +0 -648
- package/bin/gsd-t-report-tokens.cjs +0 -549
- package/bin/gsd-t-stream-feed-client.cjs +0 -151
- package/bin/gsd-t-token-backfill.cjs +0 -366
- package/bin/gsd-t-token-capture.cjs +0 -321
- package/bin/gsd-t-token-dashboard.cjs +0 -353
- package/bin/gsd-t-token-regenerate-log.cjs +0 -129
- package/bin/gsd-t-tool-attribution.cjs +0 -377
- package/bin/gsd-t-tool-cost.cjs +0 -195
- package/bin/gsd-t-transcript-tee.cjs +0 -246
- package/bin/gsd-t-unattended-heartbeat.cjs +0 -188
- package/bin/gsd-t-unattended-platform.cjs +0 -551
- package/bin/gsd-t-unattended-platform.js +0 -381
- package/bin/gsd-t-unattended-safety.cjs +0 -773
- package/bin/gsd-t-unattended-safety.js +0 -788
- package/bin/gsd-t-unattended.cjs +0 -2109
- package/bin/gsd-t-unattended.js +0 -1367
- package/bin/gsd-t-worker-dispatch.cjs +0 -211
- package/bin/handoff-lock.cjs +0 -249
- package/bin/handoff-lock.js +0 -249
- package/bin/headless-auto-spawn.cjs +0 -711
- package/bin/headless-auto-spawn.js +0 -373
- package/bin/headless-exit-codes.cjs +0 -67
- package/bin/live-activity-report.cjs +0 -615
- package/bin/log-tail.cjs +0 -81
- package/bin/m44-proof-measure.cjs +0 -285
- package/bin/m46-iter-proof.cjs +0 -149
- package/bin/m46-worker-proof.cjs +0 -201
- package/bin/m55-substrate-proof.cjs +0 -134
- package/bin/metrics-rollup.js +0 -200
- package/bin/model-windows.cjs +0 -99
- package/bin/model-windows.test.cjs +0 -75
- package/bin/parallelism-report.cjs +0 -535
- package/bin/runway-estimator.cjs +0 -242
- package/bin/spawn-plan-derive.cjs +0 -163
- package/bin/spawn-plan-status-updater.cjs +0 -292
- package/bin/spawn-plan-writer.cjs +0 -204
- package/bin/supervisor-pid-fingerprint.cjs +0 -126
- package/bin/token-budget.cjs +0 -265
- package/bin/unattended-watch-format.cjs +0 -178
- package/bin/watch-progress.js +0 -155
- package/commands/gsd-t-unattended-stop.md +0 -85
- package/commands/gsd-t-unattended-watch.md +0 -465
- package/commands/gsd-t-unattended.md +0 -476
- package/commands/gsd-t-visualize.md +0 -116
- package/scripts/gsd-t-context-meter.e2e.test.js +0 -364
- package/scripts/gsd-t-context-meter.js +0 -341
- package/scripts/gsd-t-context-meter.test.js +0 -471
- package/scripts/gsd-t-dashboard-server.js +0 -1203
- package/scripts/gsd-t-post-commit-spawn-plan.sh +0 -86
- package/scripts/gsd-t-transcript.html +0 -1821
- package/scripts/hooks/gsd-t-conversation-capture.js +0 -439
- package/scripts/hooks/gsd-t-in-session-usage-hook.js +0 -84
- package/scripts/spawn-plan-fmt-tokens.cjs +0 -80
- package/templates/hooks/post-commit-spawn-plan.sh +0 -85
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// templates/workflows/gsd-t-quick.workflow.js
|
|
2
|
+
//
|
|
3
|
+
// Runtime: Anthropic native Workflow tool only.
|
|
4
|
+
// Quick — small one-shot task with contract awareness.
|
|
5
|
+
// preflight + brief + agent(task) + verify-gate (light)
|
|
6
|
+
//
|
|
7
|
+
// args: { task, projectDir?, model? }
|
|
8
|
+
|
|
9
|
+
export const meta = {
|
|
10
|
+
name: "gsd-t-quick",
|
|
11
|
+
description: "Fast single-task execution with brief, preflight, and verify-gate",
|
|
12
|
+
phases: [
|
|
13
|
+
{ title: "Preflight", detail: "preflight + brief" },
|
|
14
|
+
{ title: "Execute", detail: "single-agent task" },
|
|
15
|
+
{ title: "Verify", detail: "verify-gate" },
|
|
16
|
+
],
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const lib = require("./_lib.js");
|
|
20
|
+
|
|
21
|
+
const projectDir = (args && args.projectDir) || ".";
|
|
22
|
+
const task = (args && args.task) || null;
|
|
23
|
+
const model = (args && args.model) || "sonnet";
|
|
24
|
+
|
|
25
|
+
const QUICK_SCHEMA = {
|
|
26
|
+
type: "object",
|
|
27
|
+
required: ["status", "filesEdited"],
|
|
28
|
+
properties: {
|
|
29
|
+
status: { type: "string", enum: ["complete", "partial", "blocked", "failed"] },
|
|
30
|
+
filesEdited: { type: "array", items: { type: "string" } },
|
|
31
|
+
summary: { type: "string" },
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (!task) {
|
|
36
|
+
log("quick: args.task required");
|
|
37
|
+
return { status: "failed", reason: "no-task" };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
phase("Preflight");
|
|
41
|
+
const pre = lib.runPreflight({ projectDir });
|
|
42
|
+
if (!pre.ok) return { status: "failed", reason: "preflight-failed", preflight: pre.envelope };
|
|
43
|
+
const brief = lib.generateBrief({ kind: "execute", projectDir });
|
|
44
|
+
|
|
45
|
+
phase("Execute");
|
|
46
|
+
const result = await agent(
|
|
47
|
+
[
|
|
48
|
+
`Quick task: ${task}`,
|
|
49
|
+
`**Brief:** ${brief.briefPath || "(no brief)"}`,
|
|
50
|
+
``,
|
|
51
|
+
`Constraints from CLAUDE.md:`,
|
|
52
|
+
`- SIMPLICITY ABOVE ALL — minimal change`,
|
|
53
|
+
`- Check downstream effects before changing existing code`,
|
|
54
|
+
`- Run affected tests before reporting done`,
|
|
55
|
+
`- Update relevant docs in the same commit`,
|
|
56
|
+
``,
|
|
57
|
+
`Commit with prefix "m61(quick)". Return JSON per the schema.`,
|
|
58
|
+
].join("\n"),
|
|
59
|
+
{ label: "quick", phase: "Execute", schema: QUICK_SCHEMA, model }
|
|
60
|
+
).catch((e) => ({ status: "failed", filesEdited: [], summary: `agent error: ${e && e.message}` }));
|
|
61
|
+
|
|
62
|
+
if (result.status === "failed" || result.status === "blocked") {
|
|
63
|
+
return { status: result.status, result };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
phase("Verify");
|
|
67
|
+
const vg = lib.runVerifyGate({ projectDir });
|
|
68
|
+
return {
|
|
69
|
+
status: vg.ok ? "complete" : "verify-failed",
|
|
70
|
+
result,
|
|
71
|
+
verifyGate: vg.envelope,
|
|
72
|
+
};
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
// templates/workflows/gsd-t-verify.workflow.js
|
|
2
|
+
//
|
|
3
|
+
// Runtime: Anthropic native Workflow tool only (not standalone-Node parseable).
|
|
4
|
+
// Globals provided by runtime: agent, parallel, pipeline, log, phase, budget, args.
|
|
5
|
+
//
|
|
6
|
+
// Canonical verify-phase Workflow. Replaces the gsd-t-verify command shell with
|
|
7
|
+
// a deterministic pipeline:
|
|
8
|
+
// preflight → brief → verify-gate (deterministic, hard-fail) →
|
|
9
|
+
// parallel( /code-review ultra cooperative, Red Team adversarial, QA mechanics ) →
|
|
10
|
+
// synthesis ( merge findings WITHOUT collapsing categories — see orthogonal-validation-contract.md )
|
|
11
|
+
//
|
|
12
|
+
// args shape:
|
|
13
|
+
// {
|
|
14
|
+
// milestone: "M61",
|
|
15
|
+
// projectDir: ".", // optional
|
|
16
|
+
// skipUltra: false, // optional — skip /code-review ultra if rate-limited
|
|
17
|
+
// }
|
|
18
|
+
|
|
19
|
+
export const meta = {
|
|
20
|
+
name: "gsd-t-verify",
|
|
21
|
+
description:
|
|
22
|
+
"GSD-T verify phase: preflight → brief → verify-gate → CI-parity gate (M57) → test-data purge gate (M58) → parallel(code-review-ultra, Red Team, QA) → synthesis",
|
|
23
|
+
phases: [
|
|
24
|
+
{ title: "Preflight", detail: "preflight + brief" },
|
|
25
|
+
{ title: "Verify-Gate", detail: "deterministic two-track verify-gate" },
|
|
26
|
+
{ title: "CI-Parity", detail: "M57 build-coverage + ci-parity (FAIL-blocking)" },
|
|
27
|
+
{ title: "Test-Data Purge", detail: "M58 test-data --purge (FAIL-blocking)" },
|
|
28
|
+
{ title: "Orthogonal Triad", detail: "code-review ultra ∥ Red Team ∥ QA" },
|
|
29
|
+
{ title: "Synthesis", detail: "merge without collapsing categories" },
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const lib = require("./_lib.js");
|
|
34
|
+
|
|
35
|
+
const projectDir = (args && args.projectDir) || ".";
|
|
36
|
+
const milestone = (args && args.milestone) || null;
|
|
37
|
+
const skipUltra = (args && args.skipUltra) || false;
|
|
38
|
+
const skipUltraReason = (args && args.skipUltraReason) || null;
|
|
39
|
+
|
|
40
|
+
// 4.8-audit fix: skipUltra requires a recorded reason per
|
|
41
|
+
// orthogonal-validation-contract.md Rule #2. Refuse without one.
|
|
42
|
+
if (skipUltra && !skipUltraReason) {
|
|
43
|
+
log("verify: args.skipUltra=true requires args.skipUltraReason: string (per contract Rule #2)");
|
|
44
|
+
return { status: "failed", reason: "skipUltra-without-reason" };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ───── Schemas ─────
|
|
48
|
+
|
|
49
|
+
const REVIEW_ULTRA_SCHEMA = {
|
|
50
|
+
type: "object",
|
|
51
|
+
required: ["category", "findings"],
|
|
52
|
+
additionalProperties: false,
|
|
53
|
+
properties: {
|
|
54
|
+
category: { const: "correctness-and-cleanup" },
|
|
55
|
+
findings: {
|
|
56
|
+
type: "array",
|
|
57
|
+
items: {
|
|
58
|
+
type: "object",
|
|
59
|
+
required: ["severity", "file", "summary"],
|
|
60
|
+
properties: {
|
|
61
|
+
severity: { type: "string", enum: ["important", "nit", "pre-existing"] },
|
|
62
|
+
file: { type: "string" },
|
|
63
|
+
line: { type: "integer" },
|
|
64
|
+
summary: { type: "string" },
|
|
65
|
+
suggestion: { type: "string" },
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
notes: { type: "string" },
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const RED_TEAM_SCHEMA = {
|
|
74
|
+
type: "object",
|
|
75
|
+
required: ["category", "verdict", "bugs"],
|
|
76
|
+
additionalProperties: false,
|
|
77
|
+
properties: {
|
|
78
|
+
category: { const: "adversarial-security-boundaries" },
|
|
79
|
+
verdict: { type: "string", enum: ["FAIL", "GRUDGING-PASS"] },
|
|
80
|
+
bugs: {
|
|
81
|
+
type: "array",
|
|
82
|
+
items: {
|
|
83
|
+
type: "object",
|
|
84
|
+
required: ["severity", "title", "lens"],
|
|
85
|
+
properties: {
|
|
86
|
+
severity: { type: "string", enum: ["CRITICAL", "HIGH", "MEDIUM", "LOW"] },
|
|
87
|
+
title: { type: "string" },
|
|
88
|
+
lens: { type: "string" },
|
|
89
|
+
file: { type: "string" },
|
|
90
|
+
repro: { type: "string" },
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
notes: { type: "string" },
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const QA_SCHEMA = {
|
|
99
|
+
type: "object",
|
|
100
|
+
required: ["category", "suiteResult", "shallowTests", "contractCompliance"],
|
|
101
|
+
additionalProperties: false,
|
|
102
|
+
properties: {
|
|
103
|
+
category: { const: "test-mechanics-and-compliance" },
|
|
104
|
+
suiteResult: {
|
|
105
|
+
type: "object",
|
|
106
|
+
required: ["pass", "fail"],
|
|
107
|
+
properties: {
|
|
108
|
+
pass: { type: "integer" },
|
|
109
|
+
fail: { type: "integer" },
|
|
110
|
+
skipped: { type: "integer" },
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
shallowTests: {
|
|
114
|
+
type: "array",
|
|
115
|
+
items: {
|
|
116
|
+
type: "object",
|
|
117
|
+
required: ["file", "test", "reason"],
|
|
118
|
+
properties: {
|
|
119
|
+
file: { type: "string" },
|
|
120
|
+
test: { type: "string" },
|
|
121
|
+
reason: { type: "string" },
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
contractCompliance: {
|
|
126
|
+
type: "object",
|
|
127
|
+
required: ["compliant", "violations"],
|
|
128
|
+
properties: {
|
|
129
|
+
compliant: { type: "boolean" },
|
|
130
|
+
violations: { type: "array", items: { type: "string" } },
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
notes: { type: "string" },
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const VERDICT_SCHEMA = {
|
|
138
|
+
type: "object",
|
|
139
|
+
required: ["overallVerdict", "summary"],
|
|
140
|
+
additionalProperties: false,
|
|
141
|
+
properties: {
|
|
142
|
+
overallVerdict: { type: "string", enum: ["VERIFIED", "VERIFIED-WITH-WARNINGS", "VERIFY-FAILED"] },
|
|
143
|
+
summary: { type: "string" },
|
|
144
|
+
blockingFindings: { type: "array", items: { type: "string" } },
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// ───── Script body ─────
|
|
149
|
+
|
|
150
|
+
if (!milestone) {
|
|
151
|
+
log("verify: args.milestone required");
|
|
152
|
+
return { status: "failed", reason: "missing-milestone" };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
phase("Preflight");
|
|
156
|
+
const pre = lib.runPreflight({ projectDir });
|
|
157
|
+
if (!pre.ok) {
|
|
158
|
+
log(`preflight FAIL — halting verify`);
|
|
159
|
+
return { status: "failed", reason: "preflight-failed", preflight: pre.envelope };
|
|
160
|
+
}
|
|
161
|
+
const brief = lib.generateBrief({ kind: "verify", milestone, projectDir });
|
|
162
|
+
|
|
163
|
+
phase("Verify-Gate");
|
|
164
|
+
const vg = lib.runVerifyGate({ projectDir });
|
|
165
|
+
if (!vg.ok) {
|
|
166
|
+
log(`verify-gate FAIL exitCode=${vg.exitCode} — halting before triad`);
|
|
167
|
+
return {
|
|
168
|
+
status: "verify-gate-failed",
|
|
169
|
+
overallVerdict: "VERIFY-FAILED",
|
|
170
|
+
verifyGate: vg.envelope,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
log(`verify-gate green`);
|
|
174
|
+
|
|
175
|
+
// ─── M57 CI-Parity Gate (FAIL-blocking) ───────────────────────────────────
|
|
176
|
+
// Per commands/gsd-t-verify.md Step 2.6 + cli-build-coverage-contract.md +
|
|
177
|
+
// ci-parity-contract.md. NEITHER track is currently inside verify-gate.cjs.
|
|
178
|
+
// Origin: TimeTracking v1.10.12 shipped VERIFIED+tagged with a new dir absent
|
|
179
|
+
// from Dockerfile COPY — silent CI-divergence regression. M57 made this gate
|
|
180
|
+
// mandatory; Workflow MUST preserve it or we re-introduce that exact failure.
|
|
181
|
+
// Detected by user/worker in parallel session 2026-05-29 13:00.
|
|
182
|
+
phase("CI-Parity");
|
|
183
|
+
const { spawnSync } = require("child_process");
|
|
184
|
+
function _runJsonCli(subcmd, argv = []) {
|
|
185
|
+
// Use _lib-style resolution — prefer project-local bin/<tool>.cjs
|
|
186
|
+
const fsMod = require("fs");
|
|
187
|
+
const pMod = require("path");
|
|
188
|
+
const localMap = {
|
|
189
|
+
"build-coverage": "gsd-t-build-coverage.cjs",
|
|
190
|
+
"ci-parity": "gsd-t-ci-parity.cjs",
|
|
191
|
+
"test-data": "gsd-t-test-data-ledger.cjs",
|
|
192
|
+
};
|
|
193
|
+
const local = pMod.join(projectDir, "bin", localMap[subcmd] || "");
|
|
194
|
+
const cmd = fsMod.existsSync(local) ? process.execPath : "gsd-t";
|
|
195
|
+
const args = fsMod.existsSync(local) ? [local, ...argv] : [subcmd, ...argv];
|
|
196
|
+
const r = spawnSync(cmd, args, { cwd: projectDir, stdio: "pipe" });
|
|
197
|
+
let envelope = null;
|
|
198
|
+
try { envelope = r.stdout ? JSON.parse(r.stdout.toString()) : null; } catch (_) {}
|
|
199
|
+
return {
|
|
200
|
+
ok: r.status === 0,
|
|
201
|
+
exitCode: r.status,
|
|
202
|
+
envelope,
|
|
203
|
+
stderr: r.stderr && r.stderr.toString(),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
const bc = _runJsonCli("build-coverage", ["--json"]);
|
|
207
|
+
if (!bc.ok) {
|
|
208
|
+
log(`M57 build-coverage FAIL exitCode=${bc.exitCode} — halting (FAIL-blocking)`);
|
|
209
|
+
return { status: "ci-parity-failed", overallVerdict: "VERIFY-FAILED", buildCoverage: bc.envelope };
|
|
210
|
+
}
|
|
211
|
+
const cip = _runJsonCli("ci-parity", ["--json"]);
|
|
212
|
+
if (!cip.ok) {
|
|
213
|
+
log(`M57 ci-parity FAIL exitCode=${cip.exitCode} — halting (FAIL-blocking)`);
|
|
214
|
+
return { status: "ci-parity-failed", overallVerdict: "VERIFY-FAILED", ciParity: cip.envelope };
|
|
215
|
+
}
|
|
216
|
+
log(`M57 CI-parity gate green`);
|
|
217
|
+
|
|
218
|
+
// ─── M58 Test-Data Purge Gate (FAIL-blocking) ─────────────────────────────
|
|
219
|
+
// Per commands/gsd-t-verify.md Step 4.5 + test-data-tagging-contract.md v1.1.0.
|
|
220
|
+
// Origin: GSD-T-Board v0.1.10 shipped VERIFIED with 2442 E2E_TEST_* orphans
|
|
221
|
+
// live in production data. M58 made post-E2E purge mandatory; M60 hardened
|
|
222
|
+
// the adapters against empty-prefix bypass. Workflow MUST preserve.
|
|
223
|
+
phase("Test-Data Purge");
|
|
224
|
+
const verifyRunId = `verify-${milestone || "M??"}-${Date.now().toString(36)}`;
|
|
225
|
+
const td = _runJsonCli("test-data", ["--purge", "--run", verifyRunId, "--json"]);
|
|
226
|
+
if (!td.ok) {
|
|
227
|
+
log(`M58 test-data purge FAIL exitCode=${td.exitCode} — halting (FAIL-blocking)`);
|
|
228
|
+
return { status: "test-data-purge-failed", overallVerdict: "VERIFY-FAILED", testDataPurge: td.envelope };
|
|
229
|
+
}
|
|
230
|
+
log(`M58 test-data purge green — proceeding to orthogonal triad`);
|
|
231
|
+
|
|
232
|
+
phase("Orthogonal Triad");
|
|
233
|
+
|
|
234
|
+
const briefRef = brief.briefPath || "(brief generation failed — re-walk repo)";
|
|
235
|
+
|
|
236
|
+
// Load the methodology protocols KEPT in templates/prompts/. The protocol body
|
|
237
|
+
// IS the methodology — Workflow just hosts the agent() call.
|
|
238
|
+
const redTeamProtocol = lib.loadProtocol("red-team");
|
|
239
|
+
const qaProtocol = lib.loadProtocol("qa");
|
|
240
|
+
|
|
241
|
+
const stages = [
|
|
242
|
+
// Stage A — /code-review ultra (cooperative correctness + cleanup)
|
|
243
|
+
// Per orthogonal-validation-contract.md: this finds bugs+cleanups in the
|
|
244
|
+
// "build it right" lens. NEVER substitutes for Red Team.
|
|
245
|
+
!skipUltra && (() => agent(
|
|
246
|
+
[
|
|
247
|
+
`You are running a /code-review ultra cooperative pass for milestone \`${milestone}\`.`,
|
|
248
|
+
``,
|
|
249
|
+
`**Brief (REQUIRED):** ${briefRef}`,
|
|
250
|
+
``,
|
|
251
|
+
`Per .gsd-t/contracts/orthogonal-validation-contract.md, your scope is`,
|
|
252
|
+
`**correctness + cleanup** — reuse, simplification, efficiency, altitude cleanups.`,
|
|
253
|
+
`You are COOPERATIVE — assume the code is being built in good faith. You are`,
|
|
254
|
+
`NOT looking for adversarial security bugs (Red Team's job) or test-mechanics`,
|
|
255
|
+
`issues (QA's job). Report only findings in your category.`,
|
|
256
|
+
``,
|
|
257
|
+
`Severity: "important" (must-fix bugs), "nit" (style/clarity), "pre-existing"`,
|
|
258
|
+
`(out of milestone scope but worth flagging).`,
|
|
259
|
+
``,
|
|
260
|
+
`Return JSON per the schema.`,
|
|
261
|
+
].join("\n"),
|
|
262
|
+
{ label: "code-review-ultra", phase: "Orthogonal Triad", schema: REVIEW_ULTRA_SCHEMA, model: "opus" }
|
|
263
|
+
)),
|
|
264
|
+
|
|
265
|
+
// Stage B — Red Team (adversarial / security / boundaries)
|
|
266
|
+
() => agent(
|
|
267
|
+
[
|
|
268
|
+
`You are the Red Team adversarial validator for milestone \`${milestone}\`.`,
|
|
269
|
+
``,
|
|
270
|
+
`**Brief (REQUIRED):** ${briefRef}`,
|
|
271
|
+
``,
|
|
272
|
+
`Per .gsd-t/contracts/orthogonal-validation-contract.md, your scope is`,
|
|
273
|
+
`**adversarial / security / boundaries**. You are NOT cooperative — your`,
|
|
274
|
+
`success is measured in bugs FOUND, not tests passed. Try to break the code.`,
|
|
275
|
+
``,
|
|
276
|
+
`Run the Red Team protocol:`,
|
|
277
|
+
"----- BEGIN RED TEAM PROTOCOL -----",
|
|
278
|
+
redTeamProtocol.slice(0, 8000),
|
|
279
|
+
"----- END RED TEAM PROTOCOL -----",
|
|
280
|
+
``,
|
|
281
|
+
`Verdict is FAIL if you found any CRITICAL or HIGH severity bug; GRUDGING-PASS`,
|
|
282
|
+
`if you searched exhaustively and found nothing. Return JSON per the schema.`,
|
|
283
|
+
].join("\n"),
|
|
284
|
+
{ label: "red-team", phase: "Orthogonal Triad", schema: RED_TEAM_SCHEMA, model: "opus" }
|
|
285
|
+
),
|
|
286
|
+
|
|
287
|
+
// Stage C — QA (test execution + shallow-test detection + contract compliance)
|
|
288
|
+
() => agent(
|
|
289
|
+
[
|
|
290
|
+
`You are the QA validator for milestone \`${milestone}\`.`,
|
|
291
|
+
``,
|
|
292
|
+
`**Brief (REQUIRED):** ${briefRef}`,
|
|
293
|
+
``,
|
|
294
|
+
`Per .gsd-t/contracts/orthogonal-validation-contract.md, your scope is`,
|
|
295
|
+
`**test mechanics + contract compliance**. Run the test suite. Report pass/fail/skip`,
|
|
296
|
+
`counts. Detect shallow tests (layout-only assertions that pass on an empty HTML page).`,
|
|
297
|
+
`Verify contract compliance against .gsd-t/contracts/.`,
|
|
298
|
+
``,
|
|
299
|
+
`Run the QA protocol:`,
|
|
300
|
+
"----- BEGIN QA PROTOCOL -----",
|
|
301
|
+
qaProtocol.slice(0, 8000),
|
|
302
|
+
"----- END QA PROTOCOL -----",
|
|
303
|
+
``,
|
|
304
|
+
`Return JSON per the schema.`,
|
|
305
|
+
].join("\n"),
|
|
306
|
+
{ label: "qa", phase: "Orthogonal Triad", schema: QA_SCHEMA, model: "sonnet" }
|
|
307
|
+
),
|
|
308
|
+
].filter(Boolean);
|
|
309
|
+
|
|
310
|
+
const triadResults = await parallel(stages);
|
|
311
|
+
|
|
312
|
+
phase("Synthesis");
|
|
313
|
+
const synthesisPrompt = [
|
|
314
|
+
`You are the synthesis agent. Three orthogonal validators have run.`,
|
|
315
|
+
`**Do NOT collapse categories**: a Red Team CRITICAL is not the same as a`,
|
|
316
|
+
`/code-review ultra "important" finding. Per orthogonal-validation-contract.md,`,
|
|
317
|
+
`they're declared orthogonal objective functions and must stay distinct in the report.`,
|
|
318
|
+
``,
|
|
319
|
+
`Validator results:`,
|
|
320
|
+
"```json",
|
|
321
|
+
JSON.stringify(triadResults, null, 2),
|
|
322
|
+
"```",
|
|
323
|
+
``,
|
|
324
|
+
`Compute the overall verdict per orthogonal-validation-contract.md v1.0.0:`,
|
|
325
|
+
`- VERIFIED iff: Red Team verdict=GRUDGING-PASS AND QA suiteResult.fail=0 AND QA shallowTests=[] AND QA contractCompliance.compliant=true AND code-review ultra ran AND has no "important" findings. **skipUltra=${skipUltra} → ${skipUltra ? "INELIGIBLE for VERIFIED (skipUltra=true downgrades to VERIFIED-WITH-WARNINGS at best per Rule #2)" : "eligible"}.**`,
|
|
326
|
+
`- VERIFIED-WITH-WARNINGS if: Red Team GRUDGING-PASS, QA suite green, contracts compliant, AND any of: code-review ultra has "important" findings, OR skipUltra=true (reason: ${skipUltraReason || "(none — would have failed above)"}), OR QA shallowTests.length === 1 (single non-core).`,
|
|
327
|
+
`- VERIFY-FAILED otherwise (Red Team FAIL, QA fail>0, contract violations>0, shallowTests ≥ 2 or in core paths).`,
|
|
328
|
+
``,
|
|
329
|
+
`Return JSON per VERDICT_SCHEMA with blockingFindings listing concrete things that must fix.`,
|
|
330
|
+
].join("\n");
|
|
331
|
+
|
|
332
|
+
const verdict = await agent(synthesisPrompt, {
|
|
333
|
+
label: "synthesis",
|
|
334
|
+
phase: "Synthesis",
|
|
335
|
+
schema: VERDICT_SCHEMA,
|
|
336
|
+
model: "opus",
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
return {
|
|
340
|
+
status: verdict.overallVerdict === "VERIFY-FAILED" ? "failed" : "complete",
|
|
341
|
+
overallVerdict: verdict.overallVerdict,
|
|
342
|
+
verifyGate: vg.envelope,
|
|
343
|
+
buildCoverage: bc.envelope,
|
|
344
|
+
ciParity: cip.envelope,
|
|
345
|
+
testDataPurge: td.envelope,
|
|
346
|
+
triad: triadResults,
|
|
347
|
+
verdict,
|
|
348
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// templates/workflows/gsd-t-wave.workflow.js
|
|
2
|
+
//
|
|
3
|
+
// Runtime: Anthropic native Workflow tool only.
|
|
4
|
+
// Full milestone wave: execute then verify, with C-checkpoint gates between.
|
|
5
|
+
//
|
|
6
|
+
// args: { milestone, domains: [...], projectDir?, autoIntegrate? }
|
|
7
|
+
|
|
8
|
+
export const meta = {
|
|
9
|
+
name: "gsd-t-wave",
|
|
10
|
+
description: "Execute then verify a milestone end-to-end, with integrate barrier",
|
|
11
|
+
phases: [
|
|
12
|
+
{ title: "Execute", detail: "domain workers + integrate" },
|
|
13
|
+
{ title: "Verify", detail: "orthogonal triad + verify-gate" },
|
|
14
|
+
],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const lib = require("./_lib.js");
|
|
18
|
+
|
|
19
|
+
const projectDir = (args && args.projectDir) || ".";
|
|
20
|
+
const milestone = (args && args.milestone) || null;
|
|
21
|
+
const domains = (args && args.domains) || [];
|
|
22
|
+
|
|
23
|
+
if (!milestone || !domains.length) {
|
|
24
|
+
log("wave: args.milestone and args.domains required");
|
|
25
|
+
return { status: "failed", reason: "missing-args" };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
phase("Execute");
|
|
29
|
+
const execResult = await workflow("gsd-t-execute", { milestone, domains, projectDir });
|
|
30
|
+
if (execResult.status !== "complete") {
|
|
31
|
+
log(`execute status=${execResult.status} — halting before verify`);
|
|
32
|
+
return { status: execResult.status, stage: "execute", execResult };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
phase("Verify");
|
|
36
|
+
const verifyResult = await workflow("gsd-t-verify", { milestone, projectDir });
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
status: verifyResult.status === "complete" ? "complete" : "verify-failed",
|
|
40
|
+
milestone,
|
|
41
|
+
execResult,
|
|
42
|
+
verifyResult,
|
|
43
|
+
};
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* GSD-T Check Headless Sessions — Read-back banner helper
|
|
5
|
-
*
|
|
6
|
-
* Scans .gsd-t/headless-sessions/ for completed sessions that have not yet
|
|
7
|
-
* been surfaced to the user. Consumed by `gsd-t-resume` and `gsd-t-status`
|
|
8
|
-
* to print a "Headless runs since you left" banner at the start of their
|
|
9
|
-
* output. After surfacing, marks the session file with `surfaced: true`
|
|
10
|
-
* so the banner never re-appears for the same session.
|
|
11
|
-
*
|
|
12
|
-
* Zero external dependencies (Node.js built-ins only).
|
|
13
|
-
*
|
|
14
|
-
* Contract: .gsd-t/contracts/headless-auto-spawn-contract.md v1.0.0
|
|
15
|
-
* Consumers: commands/gsd-t-resume.md, commands/gsd-t-status.md
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const fs = require("fs");
|
|
19
|
-
const path = require("path");
|
|
20
|
-
|
|
21
|
-
const SESSIONS_DIR_REL = path.join(".gsd-t", "headless-sessions");
|
|
22
|
-
|
|
23
|
-
module.exports = {
|
|
24
|
-
checkCompletedSessions,
|
|
25
|
-
markSurfaced,
|
|
26
|
-
formatBanner,
|
|
27
|
-
printBannerIfAny,
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @param {string} [projectDir]
|
|
32
|
-
* @returns {Array<object>} unsurfaced completed sessions, oldest first
|
|
33
|
-
*/
|
|
34
|
-
function checkCompletedSessions(projectDir) {
|
|
35
|
-
const dir = path.join(projectDir || process.cwd(), SESSIONS_DIR_REL);
|
|
36
|
-
if (!fs.existsSync(dir)) return [];
|
|
37
|
-
|
|
38
|
-
const entries = [];
|
|
39
|
-
let files;
|
|
40
|
-
try {
|
|
41
|
-
files = fs.readdirSync(dir);
|
|
42
|
-
} catch (_) {
|
|
43
|
-
return [];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
for (const f of files) {
|
|
47
|
-
if (!f.endsWith(".json")) continue;
|
|
48
|
-
if (f.endsWith("-context.json")) continue;
|
|
49
|
-
const fp = path.join(dir, f);
|
|
50
|
-
try {
|
|
51
|
-
const s = JSON.parse(fs.readFileSync(fp, "utf8"));
|
|
52
|
-
if (s && s.status === "completed" && s.surfaced !== true) {
|
|
53
|
-
entries.push(s);
|
|
54
|
-
}
|
|
55
|
-
} catch (_) {
|
|
56
|
-
// skip malformed session files silently
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
entries.sort((a, b) => {
|
|
61
|
-
const ta = a.endTimestamp || a.startTimestamp || "";
|
|
62
|
-
const tb = b.endTimestamp || b.startTimestamp || "";
|
|
63
|
-
return ta.localeCompare(tb);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
return entries;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Mark a session as surfaced so the banner won't re-appear for it.
|
|
71
|
-
* @param {string} projectDir
|
|
72
|
-
* @param {string} id
|
|
73
|
-
*/
|
|
74
|
-
function markSurfaced(projectDir, id) {
|
|
75
|
-
const fp = path.join(projectDir || process.cwd(), SESSIONS_DIR_REL, `${id}.json`);
|
|
76
|
-
if (!fs.existsSync(fp)) return;
|
|
77
|
-
try {
|
|
78
|
-
const s = JSON.parse(fs.readFileSync(fp, "utf8"));
|
|
79
|
-
s.surfaced = true;
|
|
80
|
-
fs.writeFileSync(fp, JSON.stringify(s, null, 2) + "\n");
|
|
81
|
-
} catch (_) {
|
|
82
|
-
/* ignore */
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Format a human-readable banner for the given sessions. Does not print.
|
|
88
|
-
* @param {Array<object>} sessions
|
|
89
|
-
* @returns {string}
|
|
90
|
-
*/
|
|
91
|
-
function formatBanner(sessions) {
|
|
92
|
-
if (!sessions || sessions.length === 0) return "";
|
|
93
|
-
const lines = [];
|
|
94
|
-
lines.push("## Headless runs since you left");
|
|
95
|
-
lines.push("");
|
|
96
|
-
for (const s of sessions) {
|
|
97
|
-
const duration = computeDurationLabel(s.startTimestamp, s.endTimestamp);
|
|
98
|
-
const outcome = s.exitCode === 0 ? "success" : `exit ${s.exitCode}`;
|
|
99
|
-
const cmd = s.command || "(unknown)";
|
|
100
|
-
lines.push(`- **${s.id}** — ${cmd} — ${duration} — ${outcome}`);
|
|
101
|
-
if (s.logPath) lines.push(` Log: \`${s.logPath}\``);
|
|
102
|
-
}
|
|
103
|
-
lines.push("");
|
|
104
|
-
return lines.join("\n");
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Convenience wrapper: check, print to stdout if any, mark surfaced.
|
|
109
|
-
* Returns number of sessions surfaced.
|
|
110
|
-
*/
|
|
111
|
-
function printBannerIfAny(projectDir) {
|
|
112
|
-
const sessions = checkCompletedSessions(projectDir);
|
|
113
|
-
if (sessions.length === 0) return 0;
|
|
114
|
-
process.stdout.write(formatBanner(sessions) + "\n");
|
|
115
|
-
for (const s of sessions) markSurfaced(projectDir, s.id);
|
|
116
|
-
return sessions.length;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function computeDurationLabel(startIso, endIso) {
|
|
120
|
-
if (!startIso || !endIso) return "unknown duration";
|
|
121
|
-
const start = Date.parse(startIso);
|
|
122
|
-
const end = Date.parse(endIso);
|
|
123
|
-
if (!isFinite(start) || !isFinite(end) || end < start) return "unknown duration";
|
|
124
|
-
const secs = Math.round((end - start) / 1000);
|
|
125
|
-
if (secs < 60) return `${secs}s`;
|
|
126
|
-
const mins = Math.floor(secs / 60);
|
|
127
|
-
const rem = secs % 60;
|
|
128
|
-
if (mins < 60) return `${mins}m ${rem}s`;
|
|
129
|
-
const hrs = Math.floor(mins / 60);
|
|
130
|
-
const remMins = mins % 60;
|
|
131
|
-
return `${hrs}h ${remMins}m`;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// ── CLI entry point ─────────────────────────────────────────────────────────
|
|
135
|
-
|
|
136
|
-
if (require.main === module) {
|
|
137
|
-
const projectDir = process.argv[2] || process.cwd();
|
|
138
|
-
const n = printBannerIfAny(projectDir);
|
|
139
|
-
process.exit(n > 0 ? 0 : 0);
|
|
140
|
-
}
|