@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.
Files changed (108) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/bin/gsd-t-parallel.cjs +64 -13
  3. package/bin/gsd-t.js +48 -376
  4. package/bin/journey-coverage.cjs +6 -3
  5. package/bin/parallel-cli.cjs +13 -1
  6. package/commands/gsd-t-debug.md +47 -533
  7. package/commands/gsd-t-design-decompose.md +24 -497
  8. package/commands/gsd-t-doc-ripple.md +23 -139
  9. package/commands/gsd-t-execute.md +41 -958
  10. package/commands/gsd-t-help.md +0 -2
  11. package/commands/gsd-t-impact.md +26 -295
  12. package/commands/gsd-t-integrate.md +44 -369
  13. package/commands/gsd-t-milestone.md +25 -124
  14. package/commands/gsd-t-partition.md +28 -539
  15. package/commands/gsd-t-plan.md +26 -472
  16. package/commands/gsd-t-prd.md +25 -311
  17. package/commands/gsd-t-quick.md +1 -1
  18. package/commands/gsd-t-resume.md +0 -33
  19. package/commands/gsd-t-verify.md +52 -569
  20. package/commands/gsd-t-wave.md +41 -430
  21. package/package.json +1 -1
  22. package/scripts/gsd-t-calibration-hook.js +3 -1
  23. package/scripts/hooks/pre-commit-journey-coverage +0 -2
  24. package/scripts/hooks/pre-commit-playwright-gate +0 -2
  25. package/templates/CLAUDE-global.md +43 -173
  26. package/templates/CLAUDE-project.md +118 -104
  27. package/templates/prompts/design-verify-subagent.md +3 -0
  28. package/templates/prompts/qa-subagent.md +3 -0
  29. package/templates/prompts/red-team-subagent.md +5 -2
  30. package/templates/workflows/_lib.js +176 -0
  31. package/templates/workflows/gsd-t-debug.workflow.js +86 -0
  32. package/templates/workflows/gsd-t-execute.workflow.js +206 -0
  33. package/templates/workflows/gsd-t-integrate.workflow.js +71 -0
  34. package/templates/workflows/gsd-t-phase.workflow.js +94 -0
  35. package/templates/workflows/gsd-t-quick.workflow.js +72 -0
  36. package/templates/workflows/gsd-t-verify.workflow.js +348 -0
  37. package/templates/workflows/gsd-t-wave.workflow.js +43 -0
  38. package/bin/check-headless-sessions.js +0 -140
  39. package/bin/context-budget-audit.cjs +0 -447
  40. package/bin/context-meter-config.cjs +0 -101
  41. package/bin/context-meter-config.test.cjs +0 -101
  42. package/bin/event-stream.cjs +0 -205
  43. package/bin/gsd-t-benchmark-orchestrator.js +0 -437
  44. package/bin/gsd-t-capture-lint.cjs +0 -440
  45. package/bin/gsd-t-economics.cjs +0 -315
  46. package/bin/gsd-t-in-session-usage.cjs +0 -213
  47. package/bin/gsd-t-orchestrator-config.cjs +0 -161
  48. package/bin/gsd-t-orchestrator-queue.cjs +0 -180
  49. package/bin/gsd-t-orchestrator-recover.cjs +0 -231
  50. package/bin/gsd-t-orchestrator-worker.cjs +0 -219
  51. package/bin/gsd-t-orchestrator.js +0 -535
  52. package/bin/gsd-t-parallel-probe.cjs +0 -132
  53. package/bin/gsd-t-ratelimit-probe-worker.cjs +0 -237
  54. package/bin/gsd-t-ratelimit-probe.cjs +0 -648
  55. package/bin/gsd-t-report-tokens.cjs +0 -549
  56. package/bin/gsd-t-stream-feed-client.cjs +0 -151
  57. package/bin/gsd-t-token-backfill.cjs +0 -366
  58. package/bin/gsd-t-token-capture.cjs +0 -321
  59. package/bin/gsd-t-token-dashboard.cjs +0 -353
  60. package/bin/gsd-t-token-regenerate-log.cjs +0 -129
  61. package/bin/gsd-t-tool-attribution.cjs +0 -377
  62. package/bin/gsd-t-tool-cost.cjs +0 -195
  63. package/bin/gsd-t-transcript-tee.cjs +0 -246
  64. package/bin/gsd-t-unattended-heartbeat.cjs +0 -188
  65. package/bin/gsd-t-unattended-platform.cjs +0 -551
  66. package/bin/gsd-t-unattended-platform.js +0 -381
  67. package/bin/gsd-t-unattended-safety.cjs +0 -773
  68. package/bin/gsd-t-unattended-safety.js +0 -788
  69. package/bin/gsd-t-unattended.cjs +0 -2109
  70. package/bin/gsd-t-unattended.js +0 -1367
  71. package/bin/gsd-t-worker-dispatch.cjs +0 -211
  72. package/bin/handoff-lock.cjs +0 -249
  73. package/bin/handoff-lock.js +0 -249
  74. package/bin/headless-auto-spawn.cjs +0 -711
  75. package/bin/headless-auto-spawn.js +0 -373
  76. package/bin/headless-exit-codes.cjs +0 -67
  77. package/bin/live-activity-report.cjs +0 -615
  78. package/bin/log-tail.cjs +0 -81
  79. package/bin/m44-proof-measure.cjs +0 -285
  80. package/bin/m46-iter-proof.cjs +0 -149
  81. package/bin/m46-worker-proof.cjs +0 -201
  82. package/bin/m55-substrate-proof.cjs +0 -134
  83. package/bin/metrics-rollup.js +0 -200
  84. package/bin/model-windows.cjs +0 -99
  85. package/bin/model-windows.test.cjs +0 -75
  86. package/bin/parallelism-report.cjs +0 -535
  87. package/bin/runway-estimator.cjs +0 -242
  88. package/bin/spawn-plan-derive.cjs +0 -163
  89. package/bin/spawn-plan-status-updater.cjs +0 -292
  90. package/bin/spawn-plan-writer.cjs +0 -204
  91. package/bin/supervisor-pid-fingerprint.cjs +0 -126
  92. package/bin/token-budget.cjs +0 -265
  93. package/bin/unattended-watch-format.cjs +0 -178
  94. package/bin/watch-progress.js +0 -155
  95. package/commands/gsd-t-unattended-stop.md +0 -85
  96. package/commands/gsd-t-unattended-watch.md +0 -465
  97. package/commands/gsd-t-unattended.md +0 -476
  98. package/commands/gsd-t-visualize.md +0 -116
  99. package/scripts/gsd-t-context-meter.e2e.test.js +0 -364
  100. package/scripts/gsd-t-context-meter.js +0 -341
  101. package/scripts/gsd-t-context-meter.test.js +0 -471
  102. package/scripts/gsd-t-dashboard-server.js +0 -1203
  103. package/scripts/gsd-t-post-commit-spawn-plan.sh +0 -86
  104. package/scripts/gsd-t-transcript.html +0 -1821
  105. package/scripts/hooks/gsd-t-conversation-capture.js +0 -439
  106. package/scripts/hooks/gsd-t-in-session-usage-hook.js +0 -84
  107. package/scripts/spawn-plan-fmt-tokens.cjs +0 -80
  108. package/templates/hooks/post-commit-spawn-plan.sh +0 -85
@@ -0,0 +1,176 @@
1
+ // templates/workflows/_lib.js
2
+ // Shared helpers for GSD-T Workflow scripts. CommonJS, zero deps.
3
+ //
4
+ // Workflow scripts call these helpers from inside agent()/parallel()/pipeline()
5
+ // stages so the brains (file-disjointness prover, brief generator, preflight,
6
+ // verify-gate) stay invocable while the orchestration shell becomes a Workflow.
7
+
8
+ "use strict";
9
+
10
+ const fs = require("fs");
11
+ const path = require("path");
12
+ const { spawnSync } = require("child_process");
13
+
14
+ // 4.8-audit fix: prefer project-local bin/<tool>.cjs when present, fall back to
15
+ // global `gsd-t` PATH binary. Preserves M55-D5 project-local-bin invariant: a
16
+ // detached/sandboxed Workflow worker no longer requires `gsd-t` on PATH.
17
+ //
18
+ // Returns { cmd, args, source: "local" | "global" }.
19
+ function _resolveTool(projectDir, subcommand, subcommandArgs, localBinName) {
20
+ if (localBinName) {
21
+ const local = path.join(projectDir, "bin", localBinName);
22
+ if (fs.existsSync(local)) {
23
+ return {
24
+ cmd: process.execPath,
25
+ args: [local, ...subcommandArgs],
26
+ source: "local",
27
+ };
28
+ }
29
+ }
30
+ return { cmd: "gsd-t", args: [subcommand, ...subcommandArgs], source: "global" };
31
+ }
32
+
33
+ function readBrief(briefPath) {
34
+ if (!briefPath || !fs.existsSync(briefPath)) {
35
+ return { _missing: true, briefPath: briefPath || null };
36
+ }
37
+ try {
38
+ return JSON.parse(fs.readFileSync(briefPath, "utf8"));
39
+ } catch (e) {
40
+ return { _missing: true, error: String(e && e.message) };
41
+ }
42
+ }
43
+
44
+ function generateBrief({ kind, milestone, domain, task, spawnId, projectDir = "." } = {}) {
45
+ const id =
46
+ spawnId ||
47
+ `${kind || "generic"}-${Date.now().toString(36)}-${Math.floor(Math.random() * 1e6).toString(36)}`;
48
+ const outDir = path.join(projectDir, ".gsd-t", "briefs");
49
+ fs.mkdirSync(outDir, { recursive: true });
50
+ const out = path.join(outDir, `${id}.json`);
51
+ const args = [
52
+ "brief",
53
+ "--kind",
54
+ kind || "execute",
55
+ "--spawn-id",
56
+ id,
57
+ "--out",
58
+ out,
59
+ ];
60
+ if (milestone) args.push("--milestone", milestone);
61
+ if (domain) args.push("--domain", domain);
62
+ if (task) args.push("--task", task);
63
+ const t = _resolveTool(projectDir, "brief", args, "gsd-t-context-brief.cjs");
64
+ const r = spawnSync(t.cmd, t.args, { cwd: projectDir, stdio: "pipe" });
65
+ if (r.status !== 0) {
66
+ return {
67
+ ok: false,
68
+ briefPath: out,
69
+ stderr: r.stderr && r.stderr.toString(),
70
+ spawnError: r.error ? String(r.error.message) : null,
71
+ via: t.source,
72
+ };
73
+ }
74
+ return { ok: true, briefPath: out, via: t.source };
75
+ }
76
+
77
+ function runPreflight({ projectDir = ".", checks } = {}) {
78
+ const subArgs = ["--json"];
79
+ if (Array.isArray(checks) && checks.length) subArgs.push("--checks", checks.join(","));
80
+ const t = _resolveTool(projectDir, "preflight", subArgs, "cli-preflight.cjs");
81
+ const r = spawnSync(t.cmd, t.args, { cwd: projectDir, stdio: "pipe" });
82
+ const stdout = r.stdout ? r.stdout.toString() : "";
83
+ let envelope = null;
84
+ try {
85
+ envelope = stdout ? JSON.parse(stdout) : null;
86
+ } catch (_) {
87
+ envelope = null;
88
+ }
89
+ return {
90
+ ok: r.status === 0,
91
+ exitCode: r.status,
92
+ envelope,
93
+ stderr: r.stderr && r.stderr.toString(),
94
+ spawnError: r.error ? String(r.error.message) : null,
95
+ via: t.source,
96
+ };
97
+ }
98
+
99
+ function proveFileDisjointness({ projectDir = ".", domains, taskIds } = {}) {
100
+ // Shells out to `gsd-t parallel --dry-run` (or project-local equivalent).
101
+ // 4.8-audit: domains array preferred over taskIds (the CLI supports --domain
102
+ // but not --tasks). taskIds kept for back-compat but logged as no-op.
103
+ const subArgs = ["--dry-run"];
104
+ if (Array.isArray(domains) && domains.length) {
105
+ for (const d of domains) subArgs.push("--domain", d);
106
+ }
107
+ const t = _resolveTool(projectDir, "parallel", subArgs, "gsd-t-parallel.cjs");
108
+ const r = spawnSync(t.cmd, t.args, { cwd: projectDir, stdio: "pipe" });
109
+ return {
110
+ ok: r.status === 0,
111
+ exitCode: r.status,
112
+ stdout: r.stdout && r.stdout.toString(),
113
+ stderr: r.stderr && r.stderr.toString(),
114
+ spawnError: r.error ? String(r.error.message) : null,
115
+ via: t.source,
116
+ };
117
+ }
118
+
119
+ function runVerifyGate({ projectDir = ".", skipTrack1, skipTrack2 } = {}) {
120
+ const subArgs = ["--json"];
121
+ if (skipTrack1) subArgs.push("--skip-track1");
122
+ if (skipTrack2) subArgs.push("--skip-track2");
123
+ const t = _resolveTool(projectDir, "verify-gate", subArgs, "gsd-t-verify-gate.cjs");
124
+ const r = spawnSync(t.cmd, t.args, { cwd: projectDir, stdio: "pipe" });
125
+ let envelope = null;
126
+ try {
127
+ envelope = r.stdout ? JSON.parse(r.stdout.toString()) : null;
128
+ } catch (_) {
129
+ envelope = null;
130
+ }
131
+ return {
132
+ ok: r.status === 0,
133
+ exitCode: r.status,
134
+ envelope,
135
+ stderr: r.stderr && r.stderr.toString(),
136
+ spawnError: r.error ? String(r.error.message) : null,
137
+ via: t.source,
138
+ };
139
+ }
140
+
141
+ function loadProtocol(name) {
142
+ // name = "qa" | "red-team" | "design-verify"
143
+ const validNames = ["qa", "red-team", "design-verify"];
144
+ if (!validNames.includes(name)) {
145
+ throw new Error(
146
+ `loadProtocol: unknown protocol ${JSON.stringify(name)}. Valid: ${validNames.join(", ")}`
147
+ );
148
+ }
149
+ const fp = path.join(__dirname, "..", "prompts", `${name}-subagent.md`);
150
+ return fs.readFileSync(fp, "utf8");
151
+ }
152
+
153
+ function readDomainTasks({ projectDir = ".", domain } = {}) {
154
+ if (!domain) throw new Error("readDomainTasks: domain required");
155
+ const fp = path.join(projectDir, ".gsd-t", "domains", domain, "tasks.md");
156
+ if (!fs.existsSync(fp)) return null;
157
+ return fs.readFileSync(fp, "utf8");
158
+ }
159
+
160
+ function readScope({ projectDir = ".", domain } = {}) {
161
+ if (!domain) throw new Error("readScope: domain required");
162
+ const fp = path.join(projectDir, ".gsd-t", "domains", domain, "scope.md");
163
+ if (!fs.existsSync(fp)) return null;
164
+ return fs.readFileSync(fp, "utf8");
165
+ }
166
+
167
+ module.exports = {
168
+ readBrief,
169
+ generateBrief,
170
+ runPreflight,
171
+ proveFileDisjointness,
172
+ runVerifyGate,
173
+ loadProtocol,
174
+ readDomainTasks,
175
+ readScope,
176
+ };
@@ -0,0 +1,86 @@
1
+ // templates/workflows/gsd-t-debug.workflow.js
2
+ //
3
+ // Runtime: Anthropic native Workflow tool only.
4
+ // Debug phase — up to 2 fix cycles per CLAUDE.md Prime Rule. If still failing
5
+ // after 2 cycles, exit with `needs-human` so the human operator can step in.
6
+ //
7
+ // args: { symptom, projectDir? }
8
+
9
+ export const meta = {
10
+ name: "gsd-t-debug",
11
+ description: "Diagnose and fix a failing test or runtime error (up to 2 attempts)",
12
+ phases: [
13
+ { title: "Preflight", detail: "preflight + brief" },
14
+ { title: "Cycle 1", detail: "diagnose + propose + apply + verify" },
15
+ { title: "Cycle 2", detail: "if cycle 1 didn't resolve" },
16
+ ],
17
+ };
18
+
19
+ const lib = require("./_lib.js");
20
+
21
+ const projectDir = (args && args.projectDir) || ".";
22
+ const symptom = (args && args.symptom) || null;
23
+
24
+ const DEBUG_CYCLE_SCHEMA = {
25
+ type: "object",
26
+ required: ["resolved", "rootCause", "filesEdited"],
27
+ properties: {
28
+ resolved: { type: "boolean" },
29
+ rootCause: { type: "string" },
30
+ filesEdited: { type: "array", items: { type: "string" } },
31
+ testRunResult: {
32
+ type: "object",
33
+ properties: { pass: { type: "integer" }, fail: { type: "integer" } },
34
+ },
35
+ nextStepsIfNotResolved: { type: "string" },
36
+ },
37
+ };
38
+
39
+ if (!symptom) {
40
+ log("debug: args.symptom required (description of failing test or error)");
41
+ return { status: "failed", reason: "no-symptom" };
42
+ }
43
+
44
+ phase("Preflight");
45
+ const pre = lib.runPreflight({ projectDir });
46
+ if (!pre.ok) return { status: "failed", reason: "preflight-failed", preflight: pre.envelope };
47
+ const brief = lib.generateBrief({ kind: "execute", projectDir });
48
+
49
+ let lastResult = null;
50
+ for (let cycle = 1; cycle <= 2; cycle++) {
51
+ phase(`Cycle ${cycle}`);
52
+ const prompt = [
53
+ `Debug cycle ${cycle} of 2. Symptom: ${symptom}`,
54
+ `**Brief:** ${brief.briefPath || "(no brief)"}`,
55
+ cycle > 1 && lastResult
56
+ ? `\nPREVIOUS CYCLE'S ROOT CAUSE HYPOTHESIS (did not resolve the issue):\n${lastResult.rootCause}\nFiles edited: ${lastResult.filesEdited.join(", ")}\nIf the hypothesis was right, the fix was incomplete. If wrong, formulate a different hypothesis.`
57
+ : "",
58
+ ``,
59
+ `Steps: (1) read the relevant code, (2) form a hypothesis, (3) apply a fix, (4) run the affected test(s), (5) report.`,
60
+ `Commit the fix with prefix "m61(debug-cycle${cycle})".`,
61
+ `Return JSON per the schema.`,
62
+ ].filter(Boolean).join("\n");
63
+
64
+ lastResult = await agent(prompt, {
65
+ label: `debug-cycle-${cycle}`,
66
+ phase: `Cycle ${cycle}`,
67
+ schema: DEBUG_CYCLE_SCHEMA,
68
+ model: "opus",
69
+ }).catch((e) => ({
70
+ resolved: false,
71
+ rootCause: `agent error: ${e && e.message}`,
72
+ filesEdited: [],
73
+ nextStepsIfNotResolved: "agent threw — investigate directly",
74
+ }));
75
+
76
+ if (lastResult.resolved) {
77
+ return { status: "complete", cyclesUsed: cycle, finalResult: lastResult };
78
+ }
79
+ }
80
+
81
+ return {
82
+ status: "needs-human",
83
+ cyclesUsed: 2,
84
+ finalResult: lastResult,
85
+ nextSteps: lastResult.nextStepsIfNotResolved || "Two fix cycles exhausted; human review required.",
86
+ };
@@ -0,0 +1,206 @@
1
+ // templates/workflows/gsd-t-execute.workflow.js
2
+ //
3
+ // IMPORTANT: this file is NOT executable via `node` directly. It is a script
4
+ // body for the Anthropic native Workflow tool, which wraps the body in an
5
+ // async runtime and exposes globals: agent(), parallel(), pipeline(), log(),
6
+ // phase(), budget, args. Top-level await + return are runtime-legal in that
7
+ // context. To run: invoke the Workflow tool with {script: this file contents,
8
+ // args: {milestone, domains, projectDir?}}.
9
+ //
10
+ // Canonical native-Workflow implementation of the GSD-T execute phase.
11
+ // Replaces the orchestrator/worker/parallel/spawn-plan scaffolding with a
12
+ // single deterministic Workflow script. KEEPS the brains: preflight,
13
+ // context-brief, file-disjointness, verify-gate — all invoked from inside
14
+ // stages via templates/workflows/_lib.js helpers.
15
+ //
16
+ // Invocation contract:
17
+ // The Workflow tool reads this file's `meta` block and runs the script
18
+ // body. `args` is the JSON object passed in via Workflow({args}). Expected
19
+ // shape:
20
+ // {
21
+ // milestone: "M61",
22
+ // domains: ["m61-d6-migrate-orchestration-to-workflow", ...],
23
+ // projectDir: ".", // optional
24
+ // }
25
+
26
+ export const meta = {
27
+ name: "gsd-t-execute",
28
+ description:
29
+ "Run a GSD-T execute phase: preflight → brief → parallel domain workers → integrate barrier → verify-gate",
30
+ phases: [
31
+ { title: "Preflight", detail: "gsd-t preflight + brief generation" },
32
+ { title: "Disjointness", detail: "prove tasks are file-disjoint" },
33
+ { title: "Domains", detail: "parallel domain workers" },
34
+ { title: "Integrate", detail: "cross-domain wire-up" },
35
+ { title: "Verify-Gate", detail: "two-track verify-gate" },
36
+ ],
37
+ };
38
+
39
+ // ───── Shared schemas (re-used across stages) ───────────────────────────────
40
+
41
+ const DOMAIN_RESULT_SCHEMA = {
42
+ type: "object",
43
+ required: ["domain", "status", "filesTouched"],
44
+ additionalProperties: false,
45
+ properties: {
46
+ domain: { type: "string" },
47
+ status: { type: "string", enum: ["complete", "partial", "blocked", "failed"] },
48
+ filesTouched: { type: "array", items: { type: "string" } },
49
+ tasksDone: { type: "array", items: { type: "string" } },
50
+ tasksBlocked: { type: "array", items: { type: "string" } },
51
+ notes: { type: "string" },
52
+ },
53
+ };
54
+
55
+ const INTEGRATE_RESULT_SCHEMA = {
56
+ type: "object",
57
+ required: ["status", "crossDomainEdits"],
58
+ additionalProperties: false,
59
+ properties: {
60
+ status: { type: "string", enum: ["green", "warnings", "failed"] },
61
+ crossDomainEdits: { type: "array", items: { type: "string" } },
62
+ notes: { type: "string" },
63
+ },
64
+ };
65
+
66
+ // ───── Script body ──────────────────────────────────────────────────────────
67
+
68
+ const lib = require("./_lib.js");
69
+ const path = require("path");
70
+
71
+ const projectDir = (args && args.projectDir) || ".";
72
+ const milestone = (args && args.milestone) || null;
73
+ const domains = (args && Array.isArray(args.domains) && args.domains) || [];
74
+
75
+ if (!milestone) {
76
+ log("execute: no milestone provided — args.milestone is required");
77
+ return { status: "failed", reason: "missing-milestone" };
78
+ }
79
+ if (!domains.length) {
80
+ log("execute: no domains — args.domains is required (non-empty list)");
81
+ return { status: "failed", reason: "no-domains" };
82
+ }
83
+
84
+ phase("Preflight");
85
+ log(`execute: milestone=${milestone}, domains=${domains.length}`);
86
+ const pre = lib.runPreflight({ projectDir });
87
+ if (!pre.ok) {
88
+ log(`preflight FAIL — exitCode=${pre.exitCode}: ${pre.stderr || "(no stderr)"}`);
89
+ return { status: "failed", reason: "preflight-failed", preflight: pre.envelope };
90
+ }
91
+ log(`preflight OK`);
92
+
93
+ phase("Disjointness");
94
+ // 4.8-audit fix: scope disjointness to the requested domain set, not the whole project.
95
+ // Without this, an unrelated DRAFT domain elsewhere in the project could flip the result.
96
+ const disj = lib.proveFileDisjointness({ projectDir, domains });
97
+ if (!disj.ok) {
98
+ log(`disjointness FAIL — exitCode=${disj.exitCode}: ${disj.stderr || disj.stdout}`);
99
+ return { status: "failed", reason: "non-disjoint" };
100
+ }
101
+ log(`disjointness OK`);
102
+
103
+ phase("Domains");
104
+ const domainResults = await parallel(
105
+ domains.map((domain) => async () => {
106
+ // 4.8-audit fix: per-domain brief (M55-D2 brief-per-spawn semantic) — each worker
107
+ // gets a brief scoped to its own domain so grep-the-brief is most effective.
108
+ const domBrief = lib.generateBrief({ kind: "execute", milestone, domain, projectDir });
109
+ const briefRef = domBrief.ok
110
+ ? domBrief.briefPath
111
+ : "(brief generation failed — re-walk repo)";
112
+
113
+ // 4.8-audit fix: do NOT truncate scope/tasks. The worker is being told to "execute
114
+ // every task" — silently dropping tail content is a correctness regression. Briefs
115
+ // are the compression layer; raw scope/tasks must pass whole.
116
+ const scope = lib.readScope({ projectDir, domain }) || "(scope.md missing)";
117
+ const tasks = lib.readDomainTasks({ projectDir, domain }) || "(tasks.md missing)";
118
+ const prompt = [
119
+ `You are the worker agent for the GSD-T domain \`${domain}\` in milestone \`${milestone}\`.`,
120
+ ``,
121
+ `Your job: execute every task listed under "## Tasks" in this domain's tasks.md, respecting the file ownership in scope.md.`,
122
+ ``,
123
+ `**Brief (REQUIRED READ):** ${briefRef} — if present, grep this JSON first instead of re-reading CLAUDE.md and contracts.`,
124
+ ``,
125
+ `**Scope (your owned files):**`,
126
+ "```",
127
+ scope,
128
+ "```",
129
+ ``,
130
+ `**Tasks:**`,
131
+ "```",
132
+ tasks,
133
+ "```",
134
+ ``,
135
+ `Constraints:`,
136
+ `- Touch only files in your scope's "Owned Files" list.`,
137
+ `- Make commits via bash/git tools FIRST as you complete each task or task group, THEN emit the final StructuredOutput JSON describing what you did. Do not skip commits to satisfy the schema faster.`,
138
+ `- Update affected docs (progress.md Decision Log, architecture.md, contracts/, requirements.md, README.md) per the Document Ripple Completion Gate in CLAUDE.md — in the SAME commits as the code changes.`,
139
+ `- If a task is blocked (dependency not met), record it in tasksBlocked and continue with the next.`,
140
+ `- Return a JSON object matching the StructuredOutput schema. The "status" field is the OVERALL domain status: "complete" if all tasks done, "partial" if some done and some blocked, "blocked" if you couldn't start, "failed" on error.`,
141
+ ].join("\n");
142
+
143
+ try {
144
+ return await agent(prompt, {
145
+ label: `worker:${domain}`,
146
+ phase: "Domains",
147
+ model: "sonnet", // 4.8-audit fix: explicit per Model Display contract
148
+ schema: DOMAIN_RESULT_SCHEMA,
149
+ });
150
+ } catch (e) {
151
+ return {
152
+ domain,
153
+ status: "failed",
154
+ filesTouched: [],
155
+ notes: `agent error: ${e && e.message}`,
156
+ };
157
+ }
158
+ })
159
+ );
160
+
161
+ const blocking = domainResults.filter(Boolean).filter((r) => r.status === "failed");
162
+ if (blocking.length) {
163
+ log(`${blocking.length} domain(s) failed — halting before integrate`);
164
+ return { status: "failed", reason: "domain-failed", domainResults };
165
+ }
166
+
167
+ phase("Integrate");
168
+ const integratePrompt = [
169
+ `You are the integration agent. ${domainResults.length} domain workers have completed.`,
170
+ ``,
171
+ `Domain results:`,
172
+ "```json",
173
+ JSON.stringify(domainResults, null, 2),
174
+ "```",
175
+ ``,
176
+ `Your job: perform any cross-domain wire-up needed (e.g. resolving shared-file edits sequenced at integrate, updating cross-domain contracts, running interleaved-touch resolution). DO NOT re-do work the domain workers already did. Make commits for the cross-domain edits only.`,
177
+ ``,
178
+ `Return a JSON object per the StructuredOutput schema. status="green" if all wiring landed cleanly, "warnings" if there are non-blocking issues, "failed" if cross-domain integration cannot complete.`,
179
+ ].join("\n");
180
+
181
+ const integrate = await agent(integratePrompt, {
182
+ label: "integrate",
183
+ phase: "Integrate",
184
+ schema: INTEGRATE_RESULT_SCHEMA,
185
+ }).catch((e) => ({
186
+ status: "failed",
187
+ crossDomainEdits: [],
188
+ notes: `integrate agent error: ${e && e.message}`,
189
+ }));
190
+
191
+ if (integrate.status === "failed") {
192
+ log("integrate FAILED — halting before verify-gate");
193
+ return { status: "failed", reason: "integrate-failed", domainResults, integrate };
194
+ }
195
+
196
+ phase("Verify-Gate");
197
+ const vg = lib.runVerifyGate({ projectDir });
198
+ log(`verify-gate exitCode=${vg.exitCode} ok=${vg.ok}`);
199
+
200
+ return {
201
+ status: vg.ok ? "complete" : "verify-failed",
202
+ milestone,
203
+ domainResults,
204
+ integrate,
205
+ verifyGate: vg.envelope,
206
+ };
@@ -0,0 +1,71 @@
1
+ // templates/workflows/gsd-t-integrate.workflow.js
2
+ //
3
+ // Runtime: Anthropic native Workflow tool only.
4
+ // Integrate phase — runs after parallel domains have committed their work.
5
+ // Cross-domain wire-up + lightweight verify-gate sanity check.
6
+ //
7
+ // args: { milestone, domains: [...], projectDir? }
8
+
9
+ export const meta = {
10
+ name: "gsd-t-integrate",
11
+ description: "Cross-domain integration after parallel workers complete",
12
+ phases: [
13
+ { title: "Preflight", detail: "preflight + brief" },
14
+ { title: "Integrate", detail: "cross-domain wire-up" },
15
+ { title: "Verify-Gate", detail: "quick verify-gate" },
16
+ ],
17
+ };
18
+
19
+ const lib = require("./_lib.js");
20
+
21
+ const projectDir = (args && args.projectDir) || ".";
22
+ const milestone = (args && args.milestone) || null;
23
+ const domains = (args && args.domains) || [];
24
+
25
+ const INTEGRATE_SCHEMA = {
26
+ type: "object",
27
+ required: ["status", "crossDomainEdits"],
28
+ properties: {
29
+ status: { type: "string", enum: ["green", "warnings", "failed"] },
30
+ crossDomainEdits: { type: "array", items: { type: "string" } },
31
+ notes: { type: "string" },
32
+ },
33
+ };
34
+
35
+ if (!milestone || !domains.length) {
36
+ log("integrate: args.milestone and args.domains required");
37
+ return { status: "failed", reason: "missing-args" };
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", milestone, projectDir });
44
+
45
+ phase("Integrate");
46
+ const integrate = await agent(
47
+ [
48
+ `You are the integration agent for milestone \`${milestone}\`. Domains complete: ${domains.join(", ")}.`,
49
+ `**Brief:** ${brief.briefPath || "(no brief — re-walk repo)"}`,
50
+ ``,
51
+ `Read .gsd-t/contracts/${milestone ? milestone.toLowerCase() : ""}-integration-points.md if present.`,
52
+ `Resolve any shared-file edits sequenced at integrate (per "Cross-Domain File Contention Matrix").`,
53
+ `Update cross-domain contracts as needed.`,
54
+ `Commit cross-domain edits with a clear "m61(integrate)" prefix.`,
55
+ ``,
56
+ `Return JSON per the schema.`,
57
+ ].join("\n"),
58
+ { label: "integrate", phase: "Integrate", schema: INTEGRATE_SCHEMA, model: "sonnet" }
59
+ ).catch((e) => ({ status: "failed", crossDomainEdits: [], notes: `agent error: ${e && e.message}` }));
60
+
61
+ if (integrate.status === "failed") {
62
+ return { status: "failed", reason: "integrate-failed", integrate };
63
+ }
64
+
65
+ phase("Verify-Gate");
66
+ const vg = lib.runVerifyGate({ projectDir });
67
+ return {
68
+ status: vg.ok ? "complete" : "verify-failed",
69
+ integrate,
70
+ verifyGate: vg.envelope,
71
+ };
@@ -0,0 +1,94 @@
1
+ // templates/workflows/gsd-t-phase.workflow.js
2
+ //
3
+ // Runtime: Anthropic native Workflow tool only.
4
+ // Generic upper-stage phase runner — covers partition, plan, discuss, impact,
5
+ // milestone, prd, design-decompose, doc-ripple.
6
+ //
7
+ // Each upper-stage phase is essentially: load brief -> primary agent (with phase-
8
+ // specific protocol) -> optional validation -> commit artifacts. Wrapping each
9
+ // in its own Workflow script is overengineering; this generic runner takes the
10
+ // phase name as an arg and threads the right brief kind + acceptance schema.
11
+ //
12
+ // args: {
13
+ // phase: "partition" | "plan" | "discuss" | "impact" | "milestone"
14
+ // | "prd" | "design-decompose" | "doc-ripple",
15
+ // milestone?: "M61",
16
+ // projectDir?: ".",
17
+ // userInput?: string, // arbitrary input to the phase (e.g. "$ARGUMENTS")
18
+ // }
19
+
20
+ export const meta = {
21
+ name: "gsd-t-phase",
22
+ description: "Generic upper-stage phase runner (partition/plan/discuss/etc.)",
23
+ phases: [
24
+ { title: "Preflight", detail: "preflight + brief" },
25
+ { title: "Phase", detail: "primary agent with phase-specific protocol" },
26
+ ],
27
+ };
28
+
29
+ const lib = require("./_lib.js");
30
+
31
+ const VALID_PHASES = [
32
+ "partition", "plan", "discuss", "impact",
33
+ "milestone", "prd", "design-decompose", "doc-ripple",
34
+ ];
35
+
36
+ const PHASE_RESULT_SCHEMA = {
37
+ type: "object",
38
+ required: ["status", "artifacts"],
39
+ additionalProperties: false,
40
+ properties: {
41
+ status: { type: "string", enum: ["complete", "partial", "blocked", "failed"] },
42
+ artifacts: { type: "array", items: { type: "string" } },
43
+ summary: { type: "string" },
44
+ decisions: { type: "array", items: { type: "string" } },
45
+ },
46
+ };
47
+
48
+ const projectDir = (args && args.projectDir) || ".";
49
+ const milestone = (args && args.milestone) || null;
50
+ const userInput = (args && args.userInput) || "";
51
+ const phaseName = args && args.phase;
52
+
53
+ if (!phaseName || !VALID_PHASES.includes(phaseName)) {
54
+ log(`phase: args.phase must be one of: ${VALID_PHASES.join(", ")}`);
55
+ return { status: "failed", reason: "invalid-phase" };
56
+ }
57
+
58
+ phase("Preflight");
59
+ const pre = lib.runPreflight({ projectDir });
60
+ if (!pre.ok) return { status: "failed", reason: "preflight-failed", preflight: pre.envelope };
61
+ const brief = lib.generateBrief({ kind: phaseName, milestone, projectDir });
62
+
63
+ phase("Phase");
64
+ const promptByPhase = {
65
+ partition: `Decompose the milestone into 2-5 independent domains. Write .gsd-t/domains/{domain}/{scope,constraints,tasks}.md. Cross-domain contracts in .gsd-t/contracts/.`,
66
+ plan: `For each domain, write atomic tasks.md entries with files, contract refs, dependencies, acceptance criteria. Update .gsd-t/contracts/integration-points.md with wave groupings.`,
67
+ discuss: `Multi-perspective exploration of design questions. Settle locked decisions into .gsd-t/CONTEXT.md. Do NOT implement.`,
68
+ impact: `Analyze downstream effects of proposed changes. Identify breaking changes, affected consumers, migration paths.`,
69
+ milestone: `Define a new milestone — origin, goal, success criteria, falsifiable acceptance. Append to .gsd-t/progress.md. Defer partition/plan.`,
70
+ prd: `Generate a product requirements doc at docs/prd.md. Functional + non-functional requirements traceable to acceptance criteria.`,
71
+ "design-decompose": `Decompose a design reference (Figma URL / images) into hierarchical contracts: elements -> widgets -> pages, each at .gsd-t/contracts/design/.`,
72
+ "doc-ripple": `Identify and update all docs affected by recent code changes per the Document Ripple Completion Gate. No code edits.`,
73
+ };
74
+
75
+ const result = await agent(
76
+ [
77
+ `You are the ${phaseName} phase agent.`,
78
+ milestone ? `Milestone: ${milestone}` : "",
79
+ `**Brief (REQUIRED):** ${brief.briefPath || "(no brief — re-walk repo)"}`,
80
+ userInput ? `\nUser input:\n${userInput}` : "",
81
+ ``,
82
+ `Objective: ${promptByPhase[phaseName]}`,
83
+ ``,
84
+ `Follow the CLAUDE.md Pre-Commit Gate. Commit artifacts with prefix "m61(${phaseName})" or similar.`,
85
+ `Return JSON per the schema.`,
86
+ ].filter(Boolean).join("\n"),
87
+ { label: phaseName, phase: "Phase", schema: PHASE_RESULT_SCHEMA, model: "opus" }
88
+ ).catch((e) => ({
89
+ status: "failed",
90
+ artifacts: [],
91
+ summary: `agent error: ${e && e.message}`,
92
+ }));
93
+
94
+ return result;