@tekyzinc/gsd-t 3.12.15 → 3.13.10

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.
@@ -25,6 +25,10 @@ Per `.gsd-t/contracts/model-selection-contract.md` v1.0.0. Each phase spawn pick
25
25
 
26
26
  ## Step 0.1: Verify Context Gate Readiness (MANDATORY — first thing in a fresh session)
27
27
 
28
+ ```bash
29
+ node scripts/gsd-t-watch-state.js advance --agent-id "$GSD_T_AGENT_ID" --parent-id "${GSD_T_PARENT_AGENT_ID:-null}" --command gsd-t-wave --step 0 --step-label ".1: Verify Context Gate Readiness (MANDATORY — first thing in a fresh session)" 2>/dev/null || true
30
+ ```
31
+
28
32
  Run via Bash:
29
33
 
30
34
  ```bash
@@ -35,6 +39,10 @@ This calls `getSessionStatus()` which reads `.gsd-t/.context-meter-state.json` p
35
39
 
36
40
  ## Step 1: Load State (Lightweight)
37
41
 
42
+ ```bash
43
+ node scripts/gsd-t-watch-state.js advance --agent-id "$GSD_T_AGENT_ID" --parent-id "${GSD_T_PARENT_AGENT_ID:-null}" --command gsd-t-wave --step 1 --step-label "Load State (Lightweight)" 2>/dev/null || true
44
+ ```
45
+
38
46
  Read ONLY:
39
47
  1. `.gsd-t/progress.md` — current status, milestone name, phase state
40
48
  2. `CLAUDE.md` — autonomy level only (scan for Level 1/2/3)
@@ -54,6 +62,10 @@ Do NOT attempt to fix progress.md yourself — that risks data loss.
54
62
 
55
63
  ## Step 2: Determine Resume Point
56
64
 
65
+ ```bash
66
+ node scripts/gsd-t-watch-state.js advance --agent-id "$GSD_T_AGENT_ID" --parent-id "${GSD_T_PARENT_AGENT_ID:-null}" --command gsd-t-wave --step 2 --step-label "Determine Resume Point" 2>/dev/null || true
67
+ ```
68
+
57
69
  From progress.md status, determine which phase to start from:
58
70
 
59
71
  | Status | Next Phase |
@@ -72,6 +84,10 @@ From progress.md status, determine which phase to start from:
72
84
 
73
85
  ## Step 2.5: Token Budget Pre-Flight (if available)
74
86
 
87
+ ```bash
88
+ node scripts/gsd-t-watch-state.js advance --agent-id "$GSD_T_AGENT_ID" --parent-id "${GSD_T_PARENT_AGENT_ID:-null}" --command gsd-t-wave --step 2 --step-label ".5: Token Budget Pre-Flight (if available)" 2>/dev/null || true
89
+ ```
90
+
75
91
  Before starting the phase loop, check the projected token cost for this milestone:
76
92
 
77
93
  Run via Bash:
@@ -85,6 +101,10 @@ If the file doesn't exist or returns nothing, skip silently and proceed.
85
101
 
86
102
  ## Step 3: Phase Orchestration Loop
87
103
 
104
+ ```bash
105
+ node scripts/gsd-t-watch-state.js advance --agent-id "$GSD_T_AGENT_ID" --parent-id "${GSD_T_PARENT_AGENT_ID:-null}" --command gsd-t-wave --step 3 --step-label "Phase Orchestration Loop" 2>/dev/null || true
106
+ ```
107
+
88
108
  For each remaining phase, spawn an **independent agent** using the Task tool. Each agent gets a fresh context window, loads its own state from files, and reports back.
89
109
 
90
110
  ### Graph Availability
@@ -275,6 +295,10 @@ After each agent completes, run this spot-check before proceeding:
275
295
 
276
296
  ## Step 4: Autonomy Behavior
277
297
 
298
+ ```bash
299
+ node scripts/gsd-t-watch-state.js advance --agent-id "$GSD_T_AGENT_ID" --parent-id "${GSD_T_PARENT_AGENT_ID:-null}" --command gsd-t-wave --step 4 --step-label "Autonomy Behavior" 2>/dev/null || true
300
+ ```
301
+
278
302
  **Level 3 (Full Auto)**: Auto-advance to next phase after each agent completes. Only STOP for:
279
303
  - Destructive Action Guard violations (reported by phase agent)
280
304
  - Impact analysis BLOCK verdict
@@ -285,6 +309,10 @@ After each agent completes, run this spot-check before proceeding:
285
309
 
286
310
  ## Step 5: Completion
287
311
 
312
+ ```bash
313
+ node scripts/gsd-t-watch-state.js advance --agent-id "$GSD_T_AGENT_ID" --parent-id "${GSD_T_PARENT_AGENT_ID:-null}" --command gsd-t-wave --step 5 --step-label "Completion" 2>/dev/null || true
314
+ ```
315
+
288
316
  When all phases are done:
289
317
  ```
290
318
  ═══════════════════════════════════════════════════════════════════════════════
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekyzinc/gsd-t",
3
- "version": "3.12.15",
3
+ "version": "3.13.10",
4
4
  "description": "GSD-T: Contract-Driven Development for Claude Code — 54 slash commands with headless-by-default workflow spawning, unattended supervisor relay with event stream, graph-powered code analysis, real-time agent dashboard, task telemetry, doc-ripple enforcement, backlog management, impact analysis, test sync, milestone archival, and PRD generation",
5
5
  "author": "Tekyz, Inc.",
6
6
  "license": "MIT",
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * scripts/gsd-t-watch-state.js — GSD-T Watch-State Writer CLI
4
+ *
5
+ * Records per-agent progress into `.gsd-t/.watch-state/{agent_id}.json` so
6
+ * the watch-progress renderer can reconstruct the workflow tree live.
7
+ *
8
+ * Contract: `.gsd-t/contracts/watch-progress-contract.md` v1.0.0
9
+ * Owner: D2 (M39 `d2-progress-watch`)
10
+ *
11
+ * Subcommands (contract §4):
12
+ * start — create/overwrite a new in-progress record
13
+ * advance — record current step (acts as start if no file exists)
14
+ * done — terminal: status=done, sets completed_at
15
+ * skip — terminal: status=skipped, sets completed_at
16
+ * fail — terminal: status=failed, sets completed_at
17
+ *
18
+ * Exit codes:
19
+ * 0 — success
20
+ * 1 — validation (bad args, unknown subcommand)
21
+ * 2 — filesystem (EACCES / ENOSPC / permission)
22
+ *
23
+ * Zero external deps (Node.js built-ins only).
24
+ */
25
+
26
+ "use strict";
27
+
28
+ const fs = require("fs");
29
+ const path = require("path");
30
+ const crypto = require("crypto");
31
+
32
+ const STATE_DIR_REL = path.join(".gsd-t", ".watch-state");
33
+ const VALID_SUB = new Set(["start", "advance", "done", "skip", "fail"]);
34
+
35
+ function _parseArgs(argv) {
36
+ const out = { _sub: argv[0] || null };
37
+ for (let i = 1; i < argv.length; i++) {
38
+ const a = argv[i];
39
+ if (!a.startsWith("--")) continue;
40
+ const key = a.slice(2);
41
+ const next = argv[i + 1];
42
+ if (next === undefined || next.startsWith("--")) {
43
+ out[key] = true;
44
+ } else {
45
+ out[key] = next;
46
+ i++;
47
+ }
48
+ }
49
+ return out;
50
+ }
51
+
52
+ function _validate(sub, args) {
53
+ if (!VALID_SUB.has(sub)) return `unknown subcommand: ${sub}`;
54
+ if (sub === "start" || sub === "advance") {
55
+ if (!args["command"]) return "--command is required";
56
+ if (!args["step"] || !/^-?\d+$/.test(String(args["step"]))) {
57
+ return "--step must be an integer";
58
+ }
59
+ if (!args["step-label"]) return "--step-label is required";
60
+ }
61
+ return null;
62
+ }
63
+
64
+ function _resolveAgentId(args) {
65
+ const v = args["agent-id"];
66
+ if (v && typeof v === "string" && v !== "true") return v;
67
+ if (process.env.GSD_T_AGENT_ID) return process.env.GSD_T_AGENT_ID;
68
+ return `shell-${process.pid}-${Date.now()}`;
69
+ }
70
+
71
+ function _stateDir(cwd) {
72
+ return path.join(cwd || process.cwd(), STATE_DIR_REL);
73
+ }
74
+
75
+ function _readExisting(filePath) {
76
+ try {
77
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
78
+ } catch (_) {
79
+ return null;
80
+ }
81
+ }
82
+
83
+ function _atomicWrite(filePath, data) {
84
+ const dir = path.dirname(filePath);
85
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
86
+ const rand = crypto.randomBytes(4).toString("hex");
87
+ const tmp = `${filePath}.tmp-${process.pid}-${rand}`;
88
+ fs.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n");
89
+ fs.renameSync(tmp, filePath);
90
+ }
91
+
92
+ function _parseParentId(raw) {
93
+ if (raw === undefined || raw === null || raw === "null" || raw === "") return null;
94
+ return String(raw);
95
+ }
96
+
97
+ function _parseMetadata(raw) {
98
+ if (!raw || raw === true) return {};
99
+ try {
100
+ const parsed = JSON.parse(raw);
101
+ return parsed && typeof parsed === "object" ? parsed : {};
102
+ } catch (_) {
103
+ return {};
104
+ }
105
+ }
106
+
107
+ function _buildRecord(sub, args, existing, resolvedAgentId) {
108
+ const now = new Date().toISOString();
109
+ const base = existing || {
110
+ agent_id: resolvedAgentId || args["agent-id"],
111
+ parent_agent_id: _parseParentId(args["parent-id"]),
112
+ command: "",
113
+ step: 0,
114
+ step_label: "",
115
+ status: "pending",
116
+ started_at: null,
117
+ completed_at: null,
118
+ metadata: {},
119
+ };
120
+ // Always sync parent_agent_id if explicitly provided (supports late lineage).
121
+ if (args["parent-id"] !== undefined) base.parent_agent_id = _parseParentId(args["parent-id"]);
122
+ const mergedMeta = Object.assign({}, base.metadata || {}, _parseMetadata(args["metadata"]));
123
+ base.metadata = mergedMeta;
124
+ if (sub === "start" || sub === "advance") {
125
+ base.command = String(args["command"]);
126
+ base.step = parseInt(args["step"], 10);
127
+ base.step_label = String(args["step-label"]);
128
+ base.status = "in_progress";
129
+ base.completed_at = null;
130
+ if (!base.started_at) base.started_at = now;
131
+ } else if (sub === "done") {
132
+ base.status = "done";
133
+ base.completed_at = now;
134
+ } else if (sub === "skip") {
135
+ base.status = "skipped";
136
+ base.completed_at = now;
137
+ } else if (sub === "fail") {
138
+ base.status = "failed";
139
+ base.completed_at = now;
140
+ }
141
+ return base;
142
+ }
143
+
144
+ function main(argv, cwd) {
145
+ const args = _parseArgs(argv);
146
+ const sub = args._sub;
147
+ const err = _validate(sub, args);
148
+ if (err) {
149
+ process.stderr.write(`[gsd-t-watch-state] ${err}\n`);
150
+ return 1;
151
+ }
152
+ const agentId = _resolveAgentId(args);
153
+ const filePath = path.join(_stateDir(cwd), `${agentId}.json`);
154
+ const existing = _readExisting(filePath);
155
+ const record = _buildRecord(sub, args, existing, agentId);
156
+ try {
157
+ _atomicWrite(filePath, record);
158
+ } catch (e) {
159
+ process.stderr.write(`[gsd-t-watch-state] fs error: ${e.message}\n`);
160
+ return 2;
161
+ }
162
+ return 0;
163
+ }
164
+
165
+ if (require.main === module) {
166
+ const code = main(process.argv.slice(2));
167
+ process.exit(code);
168
+ }
169
+
170
+ module.exports = { main, _parseArgs, _validate, _buildRecord, _stateDir };