@tekyzinc/gsd-t 3.29.11 → 4.0.14

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 (114) hide show
  1. package/CHANGELOG.md +171 -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-complete-milestone.md +6 -12
  7. package/commands/gsd-t-debug.md +47 -533
  8. package/commands/gsd-t-design-decompose.md +24 -497
  9. package/commands/gsd-t-doc-ripple.md +23 -139
  10. package/commands/gsd-t-execute.md +41 -958
  11. package/commands/gsd-t-feature.md +2 -6
  12. package/commands/gsd-t-gap-analysis.md +3 -6
  13. package/commands/gsd-t-help.md +2 -4
  14. package/commands/gsd-t-impact.md +26 -295
  15. package/commands/gsd-t-init-scan-setup.md +7 -7
  16. package/commands/gsd-t-integrate.md +44 -369
  17. package/commands/gsd-t-milestone.md +25 -124
  18. package/commands/gsd-t-partition.md +28 -539
  19. package/commands/gsd-t-plan.md +26 -472
  20. package/commands/gsd-t-prd.md +25 -311
  21. package/commands/gsd-t-quick.md +1 -1
  22. package/commands/gsd-t-resume.md +0 -33
  23. package/commands/gsd-t-scan.md +45 -652
  24. package/commands/gsd-t-verify.md +52 -569
  25. package/commands/gsd-t-wave.md +41 -430
  26. package/package.json +1 -1
  27. package/scripts/gsd-t-calibration-hook.js +3 -1
  28. package/scripts/hooks/pre-commit-journey-coverage +0 -2
  29. package/scripts/hooks/pre-commit-playwright-gate +0 -2
  30. package/templates/CLAUDE-global.md +44 -173
  31. package/templates/CLAUDE-project.md +118 -104
  32. package/templates/prompts/design-verify-subagent.md +3 -0
  33. package/templates/prompts/qa-subagent.md +3 -0
  34. package/templates/prompts/red-team-subagent.md +5 -2
  35. package/templates/workflows/_lib.js +176 -0
  36. package/templates/workflows/gsd-t-debug.workflow.js +86 -0
  37. package/templates/workflows/gsd-t-execute.workflow.js +206 -0
  38. package/templates/workflows/gsd-t-integrate.workflow.js +71 -0
  39. package/templates/workflows/gsd-t-phase.workflow.js +94 -0
  40. package/templates/workflows/gsd-t-quick.workflow.js +72 -0
  41. package/templates/workflows/gsd-t-scan.workflow.js +711 -0
  42. package/templates/workflows/gsd-t-verify.workflow.js +348 -0
  43. package/templates/workflows/gsd-t-wave.workflow.js +43 -0
  44. package/bin/check-headless-sessions.js +0 -140
  45. package/bin/context-budget-audit.cjs +0 -447
  46. package/bin/context-meter-config.cjs +0 -101
  47. package/bin/context-meter-config.test.cjs +0 -101
  48. package/bin/event-stream.cjs +0 -205
  49. package/bin/gsd-t-benchmark-orchestrator.js +0 -437
  50. package/bin/gsd-t-capture-lint.cjs +0 -440
  51. package/bin/gsd-t-economics.cjs +0 -315
  52. package/bin/gsd-t-in-session-usage.cjs +0 -213
  53. package/bin/gsd-t-orchestrator-config.cjs +0 -161
  54. package/bin/gsd-t-orchestrator-queue.cjs +0 -180
  55. package/bin/gsd-t-orchestrator-recover.cjs +0 -231
  56. package/bin/gsd-t-orchestrator-worker.cjs +0 -219
  57. package/bin/gsd-t-orchestrator.js +0 -535
  58. package/bin/gsd-t-parallel-probe.cjs +0 -132
  59. package/bin/gsd-t-ratelimit-probe-worker.cjs +0 -237
  60. package/bin/gsd-t-ratelimit-probe.cjs +0 -648
  61. package/bin/gsd-t-report-tokens.cjs +0 -549
  62. package/bin/gsd-t-stream-feed-client.cjs +0 -151
  63. package/bin/gsd-t-token-backfill.cjs +0 -366
  64. package/bin/gsd-t-token-capture.cjs +0 -321
  65. package/bin/gsd-t-token-dashboard.cjs +0 -353
  66. package/bin/gsd-t-token-regenerate-log.cjs +0 -129
  67. package/bin/gsd-t-tool-attribution.cjs +0 -377
  68. package/bin/gsd-t-tool-cost.cjs +0 -195
  69. package/bin/gsd-t-transcript-tee.cjs +0 -246
  70. package/bin/gsd-t-unattended-heartbeat.cjs +0 -188
  71. package/bin/gsd-t-unattended-platform.cjs +0 -551
  72. package/bin/gsd-t-unattended-platform.js +0 -381
  73. package/bin/gsd-t-unattended-safety.cjs +0 -773
  74. package/bin/gsd-t-unattended-safety.js +0 -788
  75. package/bin/gsd-t-unattended.cjs +0 -2109
  76. package/bin/gsd-t-unattended.js +0 -1367
  77. package/bin/gsd-t-worker-dispatch.cjs +0 -211
  78. package/bin/handoff-lock.cjs +0 -249
  79. package/bin/handoff-lock.js +0 -249
  80. package/bin/headless-auto-spawn.cjs +0 -711
  81. package/bin/headless-auto-spawn.js +0 -373
  82. package/bin/headless-exit-codes.cjs +0 -67
  83. package/bin/live-activity-report.cjs +0 -615
  84. package/bin/log-tail.cjs +0 -81
  85. package/bin/m44-proof-measure.cjs +0 -285
  86. package/bin/m46-iter-proof.cjs +0 -149
  87. package/bin/m46-worker-proof.cjs +0 -201
  88. package/bin/m55-substrate-proof.cjs +0 -134
  89. package/bin/metrics-rollup.js +0 -200
  90. package/bin/model-windows.cjs +0 -99
  91. package/bin/model-windows.test.cjs +0 -75
  92. package/bin/parallelism-report.cjs +0 -535
  93. package/bin/runway-estimator.cjs +0 -242
  94. package/bin/spawn-plan-derive.cjs +0 -163
  95. package/bin/spawn-plan-status-updater.cjs +0 -292
  96. package/bin/spawn-plan-writer.cjs +0 -204
  97. package/bin/supervisor-pid-fingerprint.cjs +0 -126
  98. package/bin/token-budget.cjs +0 -265
  99. package/bin/unattended-watch-format.cjs +0 -178
  100. package/bin/watch-progress.js +0 -155
  101. package/commands/gsd-t-unattended-stop.md +0 -85
  102. package/commands/gsd-t-unattended-watch.md +0 -465
  103. package/commands/gsd-t-unattended.md +0 -476
  104. package/commands/gsd-t-visualize.md +0 -116
  105. package/scripts/gsd-t-context-meter.e2e.test.js +0 -364
  106. package/scripts/gsd-t-context-meter.js +0 -341
  107. package/scripts/gsd-t-context-meter.test.js +0 -471
  108. package/scripts/gsd-t-dashboard-server.js +0 -1203
  109. package/scripts/gsd-t-post-commit-spawn-plan.sh +0 -86
  110. package/scripts/gsd-t-transcript.html +0 -1821
  111. package/scripts/hooks/gsd-t-conversation-capture.js +0 -439
  112. package/scripts/hooks/gsd-t-in-session-usage-hook.js +0 -84
  113. package/scripts/spawn-plan-fmt-tokens.cjs +0 -80
  114. 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;