@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
@@ -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