@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
@@ -1,178 +0,0 @@
1
- /**
2
- * bin/unattended-watch-format.cjs
3
- *
4
- * Pure formatter for the unattended watch-tick activity block (M38 ES).
5
- * Given an array of events (as returned by event-stream.readSinceCursor) and
6
- * supervisor state, render the human-scannable output per
7
- * `.gsd-t/contracts/unattended-event-stream-contract.md` §4.
8
- *
9
- * Kept separate from the watch command so it can be unit-tested (ES-T3) and
10
- * so the command itself stays a thin shell wrapper.
11
- */
12
-
13
- "use strict";
14
-
15
- function _groupByIter(events) {
16
- const groups = new Map();
17
- for (const ev of events) {
18
- if (!ev || typeof ev !== "object") continue;
19
- const iter = Number.isFinite(ev.iter) ? ev.iter : 0;
20
- if (!groups.has(iter)) groups.set(iter, []);
21
- groups.get(iter).push(ev);
22
- }
23
- return [...groups.entries()].sort((a, b) => a[0] - b[0]);
24
- }
25
-
26
- function _fmtElapsed(startedAt, now) {
27
- if (!startedAt) return "";
28
- const t = Date.parse(startedAt);
29
- if (!Number.isFinite(t)) return "";
30
- const ms = (now || Date.now()) - t;
31
- const m = Math.floor(ms / 60000);
32
- if (m < 60) return `+${m}m elapsed`;
33
- const h = Math.floor(m / 60);
34
- return `+${h}h${m % 60}m elapsed`;
35
- }
36
-
37
- function _fmtDuration(s) {
38
- if (!Number.isFinite(s) || s < 0) return "";
39
- if (s < 60) return `${s}s`;
40
- const m = Math.floor(s / 60);
41
- return `${m}m ${s % 60}s`;
42
- }
43
-
44
- function _formatIteration(iter, evs) {
45
- const taskStart = evs.find((e) => e.type === "task_start");
46
- const taskComplete = evs.find((e) => e.type === "task_complete");
47
- const fileChanges = evs.filter((e) => e.type === "file_changed");
48
- const testResults = evs.filter((e) => e.type === "test_result");
49
- const verdicts = evs.filter((e) => e.type === "subagent_verdict");
50
- const errors = evs.filter((e) => e.type === "error");
51
- const retries = evs.filter((e) => e.type === "retry");
52
-
53
- const lines = [];
54
- if (taskStart) {
55
- const wave = taskStart.wave ? ` (wave ${taskStart.wave})` : "";
56
- const task = taskStart.task || "(unnamed)";
57
- lines.push(` ▶ task: ${task}${wave}`);
58
- }
59
- if (fileChanges.length > 0) {
60
- const paths = fileChanges.map((e) => e.path || "?").filter(Boolean);
61
- const shown = paths.slice(0, 5).join(", ");
62
- const extra = paths.length > 5 ? ` … and ${paths.length - 5} more` : "";
63
- lines.push(` 📝 ${paths.length} file${paths.length === 1 ? "" : "s"} modified (${shown}${extra})`);
64
- }
65
- for (const tr of testResults) {
66
- const suite = tr.suite || "?";
67
- const pass = Number.isFinite(tr.pass) ? tr.pass : 0;
68
- const total = Number.isFinite(tr.total) ? tr.total : 0;
69
- const mark = (tr.fail || 0) > 0 ? "❌" : "✅";
70
- lines.push(` ${mark} test_result: ${suite} ${pass}/${total} pass`);
71
- }
72
- for (const v of verdicts) {
73
- const agent = v.agent || "?";
74
- const verdict = v.verdict || "?";
75
- const findings = Number.isFinite(v.findings_count) ? ` (${v.findings_count} findings)` : "";
76
- const mark = verdict === "pass" || verdict === "grudging_pass" ? "✅" : "❌";
77
- lines.push(` ${mark} subagent_verdict: ${agent} ${verdict}${findings}`);
78
- }
79
- for (const er of errors) {
80
- lines.push(` ❌ error: ${er.error || "(unknown)"}${er.recoverable ? " [recoverable]" : ""}`);
81
- }
82
- for (const r of retries) {
83
- lines.push(` 🔁 retry: attempt ${r.attempt || iter} — ${r.reason || "?"}`);
84
- }
85
- if (taskComplete) {
86
- const dur = _fmtDuration(taskComplete.duration_s);
87
- const verdict = taskComplete.verdict || "?";
88
- lines.push(` ⏱ duration: ${dur} · verdict: ${verdict}`);
89
- }
90
- return lines;
91
- }
92
-
93
- /**
94
- * Format an activity block for the watch tick.
95
- *
96
- * @param {object} args
97
- * @param {object[]} args.events — events since last cursor (may be empty)
98
- * @param {object} args.state — supervisor state.json contents
99
- * @param {number} [args.now] — override for Date.now() (tests)
100
- * @returns {string}
101
- */
102
- function _renderWatchProgressTree(args) {
103
- // M39 D2 — best-effort watch-progress tree appended below the formatter
104
- // output. Banner preserved verbatim; returns "" on any failure so callers
105
- // never see a tree when state is missing/unavailable.
106
- try {
107
- const wp = require("./watch-progress.js");
108
- const stateDir = (args && args.stateDir) || ".gsd-t/.watch-state";
109
- const current = args && args.currentAgent ? args.currentAgent : null;
110
- const tree = wp.buildTree(stateDir);
111
- return wp.renderTree(tree, { currentAgent: current }) || "";
112
- } catch (_) {
113
- return "";
114
- }
115
- }
116
-
117
- function formatWatchTick(args) {
118
- const events = Array.isArray(args && args.events) ? args.events : [];
119
- const state = (args && args.state) || {};
120
- const now = args && Number.isFinite(args.now) ? args.now : Date.now();
121
-
122
- const elapsed = _fmtElapsed(state.startedAt, now);
123
- const iter = Number.isFinite(state.iter) ? state.iter : 0;
124
- const header = `[unattended supervisor — iter ${iter}${elapsed ? `, ${elapsed}` : ""}]`;
125
-
126
- let body;
127
- if (events.length === 0) {
128
- body = `${header} (no new activity since last tick)`;
129
- } else {
130
- const groups = _groupByIter(events);
131
- const blocks = [];
132
- for (const [groupIter, evs] of groups) {
133
- const groupHeader = groups.length > 1 ? `[iter ${groupIter}]` : header;
134
- const bodyLines = _formatIteration(groupIter, evs);
135
- blocks.push([groupHeader, ...bodyLines].join("\n"));
136
- }
137
- body = groups.length > 1 ? `${header}\n${blocks.join("\n")}` : blocks[0];
138
- }
139
-
140
- // M39 D2 — watch-progress tree below the existing formatter output.
141
- // Banner preserved verbatim; tree appended only when caller opts in via
142
- // `args.withWatchProgress = true`. Default-off preserves backward
143
- // compatibility with existing snapshot-style callers (tests).
144
- if (!(args && args.withWatchProgress === true)) return body;
145
- const tree = _renderWatchProgressTree({
146
- stateDir: args && args.stateDir,
147
- currentAgent: args && (args.currentAgent || state.sessionId),
148
- });
149
- return tree ? `${body}\n${tree}` : body;
150
- }
151
-
152
- /**
153
- * Terminal-status block when supervisor reached `done`/`failed`/`stopped`/`crashed`.
154
- * Returns null if status is not terminal.
155
- */
156
- function formatTerminalBlock(state) {
157
- if (!state || typeof state !== "object") return null;
158
- const s = state.status;
159
- if (s === "done") {
160
- return `🎉 Unattended supervisor COMPLETED the milestone (${state.milestone || "?"}, iter ${state.iter || 0}).`;
161
- }
162
- if (s === "failed") {
163
- return `❌ Unattended supervisor HALTED — status=failed (last exit ${state.lastExit ?? "?"}, iter ${state.iter || 0}).`;
164
- }
165
- if (s === "stopped") {
166
- return `🛑 Unattended supervisor STOPPED by user (iter ${state.iter || 0}).`;
167
- }
168
- if (s === "crashed") {
169
- return `💥 Unattended supervisor CRASHED (iter ${state.iter || 0}).`;
170
- }
171
- return null;
172
- }
173
-
174
- module.exports = {
175
- formatWatchTick,
176
- formatTerminalBlock,
177
- _internal: { _groupByIter, _formatIteration, _fmtElapsed, _fmtDuration },
178
- };
@@ -1,155 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * bin/watch-progress.js — GSD-T Watch-Progress Tree Builder + Renderer
4
- *
5
- * Reads `.gsd-t/.watch-state/*.json` state files written by
6
- * `scripts/gsd-t-watch-state.js` and reconstructs the agent workflow tree
7
- * via `parent_agent_id` lineage. Renders a task-list with ✅/🔄/⬜ markers
8
- * below every `--watch` surface (banner preserved intact).
9
- *
10
- * Contract: `.gsd-t/contracts/watch-progress-contract.md` v1.0.0
11
- * Owner: D2 (M39 `d2-progress-watch`)
12
- * Zero external deps.
13
- */
14
-
15
- "use strict";
16
-
17
- const fs = require("fs");
18
- const path = require("path");
19
-
20
- const STALE_MS = 24 * 60 * 60 * 1000; // 24h
21
-
22
- const MARKERS = {
23
- done: "✅",
24
- in_progress: "🔄",
25
- pending: "⬜",
26
- skipped: "➡️",
27
- failed: "❌",
28
- };
29
-
30
- function _readAll(stateDir) {
31
- if (!stateDir || !fs.existsSync(stateDir)) return [];
32
- let entries;
33
- try {
34
- entries = fs.readdirSync(stateDir);
35
- } catch (_) {
36
- return [];
37
- }
38
- const records = [];
39
- for (const f of entries) {
40
- if (!f.endsWith(".json")) continue;
41
- try {
42
- const raw = fs.readFileSync(path.join(stateDir, f), "utf8");
43
- const rec = JSON.parse(raw);
44
- if (rec && typeof rec === "object" && typeof rec.agent_id === "string") {
45
- records.push(rec);
46
- }
47
- } catch (_) { /* skip malformed */ }
48
- }
49
- return records;
50
- }
51
-
52
- function _isStale(record, now) {
53
- if (!record.completed_at) return false;
54
- const t = Date.parse(record.completed_at);
55
- if (!Number.isFinite(t)) return false;
56
- return (now - t) > STALE_MS;
57
- }
58
-
59
- function buildTree(stateDir, options) {
60
- const now = options && Number.isFinite(options.now) ? options.now : Date.now();
61
- const records = _readAll(stateDir).filter((r) => !_isStale(r, now));
62
- const index = new Map();
63
- for (const r of records) index.set(r.agent_id, { record: r, children: [] });
64
- const roots = [];
65
- const orphans = [];
66
- for (const r of records) {
67
- const node = index.get(r.agent_id);
68
- const parentId = r.parent_agent_id;
69
- if (parentId === null || parentId === undefined) {
70
- roots.push(node);
71
- } else if (index.has(parentId)) {
72
- index.get(parentId).children.push(node);
73
- } else {
74
- orphans.push(node);
75
- }
76
- }
77
- return { roots, orphans };
78
- }
79
-
80
- function _marker(status) {
81
- return MARKERS[status] || MARKERS.pending;
82
- }
83
-
84
- function _countDone(node) {
85
- let count = 0;
86
- const s = node.record.status;
87
- if (s === "done" || s === "skipped") count = 1;
88
- for (const c of node.children) count += _countDone(c);
89
- return count;
90
- }
91
-
92
- function _flattenIds(node, acc) {
93
- acc.push(node.record.agent_id);
94
- for (const c of node.children) _flattenIds(c, acc);
95
- return acc;
96
- }
97
-
98
- function _containsAgent(node, agentId) {
99
- if (!agentId) return false;
100
- return _flattenIds(node, []).includes(agentId);
101
- }
102
-
103
- function _pickCurrent(tree) {
104
- let pick = null;
105
- let latest = -Infinity;
106
- const walk = (node) => {
107
- const r = node.record;
108
- if (r.status === "in_progress" && r.started_at) {
109
- const t = Date.parse(r.started_at);
110
- if (Number.isFinite(t) && t > latest) { latest = t; pick = r.agent_id; }
111
- }
112
- for (const c of node.children) walk(c);
113
- };
114
- for (const root of tree.roots) walk(root);
115
- return pick;
116
- }
117
-
118
- function _renderExpanded(node, depth, lines) {
119
- const indent = " ".repeat(depth);
120
- const r = node.record;
121
- lines.push(`${indent}${_marker(r.status)} ${r.step_label || r.command || r.agent_id}`);
122
- for (const c of node.children) _renderExpanded(c, depth + 1, lines);
123
- }
124
-
125
- function _renderCollapsed(node, depth, lines) {
126
- const indent = " ".repeat(depth);
127
- const r = node.record;
128
- const doneCount = _countDone(node);
129
- const label = r.step_label || r.command || r.agent_id;
130
- lines.push(`${indent}${_marker(r.status)} ${label} (${doneCount} tasks done)`);
131
- }
132
-
133
- function renderTree(tree, options) {
134
- if (!tree || (tree.roots.length === 0 && tree.orphans.length === 0)) return "";
135
- const opts = options || {};
136
- const currentAgent = opts.currentAgent || _pickCurrent(tree);
137
- const lines = [];
138
- for (const root of tree.roots) {
139
- if (_containsAgent(root, currentAgent)) _renderExpanded(root, 0, lines);
140
- else _renderCollapsed(root, 0, lines);
141
- }
142
- if (tree.orphans.length > 0) {
143
- lines.push("⬜ (orphan subtree — parent state missing)");
144
- for (const o of tree.orphans) _renderExpanded(o, 1, lines);
145
- }
146
- return lines.join("\n");
147
- }
148
-
149
- module.exports = { buildTree, renderTree, MARKERS, STALE_MS, _pickCurrent };
150
-
151
- if (require.main === module) {
152
- const stateDir = process.argv[2] || path.join(".gsd-t", ".watch-state");
153
- const out = renderTree(buildTree(stateDir));
154
- if (out) process.stdout.write(out + "\n");
155
- }
@@ -1,85 +0,0 @@
1
- # GSD-T: Unattended Stop — Signal Supervisor to Halt
2
-
3
- **Model**: haiku (trivial sentinel toucher — no reasoning needed)
4
-
5
- You are signaling the unattended supervisor to halt cleanly between worker iterations by writing the stop sentinel file at `.gsd-t/.unattended/stop`. This is a fire-and-forget command: no PID kill, no wait, no confirmation prompt.
6
-
7
- See `unattended-supervisor-contract.md` §10 (Stop Mechanism) for the full handshake.
8
-
9
- ## Step 1: Check Supervisor State Directory Exists
10
-
11
- Run via Bash:
12
-
13
- ```bash
14
- if [ ! -d ".gsd-t/.unattended" ]; then
15
- echo "No supervisor state directory — nothing to stop."
16
- exit 0
17
- fi
18
- ```
19
-
20
- If the directory does not exist, exit 0 (not an error — there is simply nothing to signal).
21
-
22
- ## Step 2: Check Supervisor PID File Exists
23
-
24
- Run via Bash:
25
-
26
- ```bash
27
- if [ ! -f ".gsd-t/.unattended/supervisor.pid" ]; then
28
- echo "No supervisor running in this project (no PID file at .gsd-t/.unattended/supervisor.pid)."
29
- exit 0
30
- fi
31
- ```
32
-
33
- If the PID file is missing, the supervisor has already finalized cleanly. Exit 0 without writing the sentinel.
34
-
35
- ## Step 3: Read Current Session Snapshot
36
-
37
- Run via Bash to grab the session ID and current iteration from `state.json` (best-effort — tolerate missing or partial state):
38
-
39
- ```bash
40
- node -e "
41
- try {
42
- const s = JSON.parse(require('fs').readFileSync('.gsd-t/.unattended/state.json', 'utf8'));
43
- console.log('SESSION=' + (s.sessionId || 'unknown'));
44
- console.log('ITER=' + (s.iter ?? 'unknown'));
45
- console.log('STATUS=' + (s.status || 'unknown'));
46
- } catch (e) {
47
- console.log('SESSION=unknown');
48
- console.log('ITER=unknown');
49
- console.log('STATUS=unknown');
50
- }
51
- "
52
- ```
53
-
54
- ## Step 4: Write the Stop Sentinel
55
-
56
- Write `.gsd-t/.unattended/stop` containing the current ISO timestamp as the body (for diagnostics — the supervisor only checks for the file's existence, not its contents):
57
-
58
- ```bash
59
- node -e "require('fs').writeFileSync('.gsd-t/.unattended/stop', new Date().toISOString())"
60
- ```
61
-
62
- This is race-free, terminal-close-safe, and language-agnostic (per contract §10).
63
-
64
- ## Step 5: Print Confirmation
65
-
66
- Output the confirmation block:
67
-
68
- ```
69
- 🛑 Stop sentinel written. Supervisor will halt after the current worker finishes (up to ~5 min).
70
-
71
- Session: {SESSION from Step 3}
72
- Iter: {ITER from Step 3}
73
- Status: {STATUS from Step 3}
74
-
75
- The current worker runs to completion. Stop is honored at the next pre-worker checkpoint.
76
- The watch loop (if running) will detect status=stopped on its next tick and stop itself.
77
- If a watch tick fires before the supervisor processes the sentinel, it may reschedule once
78
- more — this is expected. It will catch the terminal status on the following tick.
79
- ```
80
-
81
- ## Step 6: Return Immediately
82
-
83
- Do NOT wait for the supervisor to acknowledge. Do NOT poll state.json. Do NOT call ScheduleWakeup. The supervisor will finalize state.json with `status=stopped` on its next iteration check — that's the watch loop's job to observe, not this command's.
84
-
85
- $ARGUMENTS