@tekyzinc/gsd-t 3.23.11 → 3.25.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.
- package/CHANGELOG.md +48 -0
- package/README.md +7 -0
- package/bin/cli-preflight-checks/branch-guard.cjs +110 -0
- package/bin/cli-preflight-checks/contracts-stable.cjs +128 -0
- package/bin/cli-preflight-checks/deps-installed.cjs +89 -0
- package/bin/cli-preflight-checks/manifest-fresh.cjs +98 -0
- package/bin/cli-preflight-checks/ports-free.cjs +110 -0
- package/bin/cli-preflight-checks/working-tree-state.cjs +149 -0
- package/bin/cli-preflight.cjs +265 -0
- package/bin/gsd-t-context-brief-kinds/design-verify.cjs +139 -0
- package/bin/gsd-t-context-brief-kinds/execute.cjs +205 -0
- package/bin/gsd-t-context-brief-kinds/qa.cjs +130 -0
- package/bin/gsd-t-context-brief-kinds/red-team.cjs +131 -0
- package/bin/gsd-t-context-brief-kinds/scan.cjs +118 -0
- package/bin/gsd-t-context-brief-kinds/verify.cjs +157 -0
- package/bin/gsd-t-context-brief.cjs +395 -0
- package/bin/gsd-t-ratelimit-probe-worker.cjs +236 -0
- package/bin/gsd-t-ratelimit-probe.cjs +648 -0
- package/bin/gsd-t-verify-gate-judge.cjs +224 -0
- package/bin/gsd-t-verify-gate.cjs +612 -0
- package/bin/gsd-t.js +45 -1
- package/bin/live-activity-report.cjs +615 -0
- package/bin/m55-substrate-proof.cjs +134 -0
- package/bin/parallel-cli-tee.cjs +206 -0
- package/bin/parallel-cli.cjs +478 -0
- package/commands/gsd-t-execute.md +31 -0
- package/commands/gsd-t-help.md +21 -0
- package/commands/gsd-t-verify.md +38 -0
- package/docs/architecture.md +194 -0
- package/docs/diagrams/.gsd-t/.context-meter-state.json +10 -0
- package/docs/diagrams/.gsd-t/context-meter.log +9 -0
- package/docs/diagrams/.gsd-t/events/2026-05-08.jsonl +45 -0
- package/docs/diagrams/.gsd-t/events/2026-05-09.jsonl +1 -0
- package/docs/diagrams/.gsd-t/heartbeat-cd9e7f59-ba5b-406a-9ed6-16762f039e81.jsonl +48 -0
- package/docs/diagrams/01-top-level-map-d2.png +0 -0
- package/docs/diagrams/01-top-level-map.d2 +77 -0
- package/docs/diagrams/01-top-level-map.mmd +48 -0
- package/docs/diagrams/01-top-level-map.png +0 -0
- package/docs/diagrams/01-top-level-map.svg +126 -0
- package/docs/diagrams/02-milestone-lifecycle-d2.png +0 -0
- package/docs/diagrams/02-milestone-lifecycle.d2 +38 -0
- package/docs/diagrams/02-milestone-lifecycle.mmd +36 -0
- package/docs/diagrams/02-milestone-lifecycle.png +0 -0
- package/docs/diagrams/02-milestone-lifecycle.svg +114 -0
- package/docs/diagrams/03-wave-mode-d2.png +0 -0
- package/docs/diagrams/03-wave-mode.d2 +33 -0
- package/docs/diagrams/03-wave-mode.mmd +21 -0
- package/docs/diagrams/03-wave-mode.png +0 -0
- package/docs/diagrams/03-wave-mode.svg +113 -0
- package/docs/diagrams/04-design-to-code-d2.png +0 -0
- package/docs/diagrams/04-design-to-code.d2 +35 -0
- package/docs/diagrams/04-design-to-code.mmd +29 -0
- package/docs/diagrams/04-design-to-code.png +0 -0
- package/docs/diagrams/04-design-to-code.svg +115 -0
- package/docs/diagrams/05-backlog-d2.png +0 -0
- package/docs/diagrams/05-backlog.d2 +40 -0
- package/docs/diagrams/05-backlog.mmd +20 -0
- package/docs/diagrams/05-backlog.png +0 -0
- package/docs/diagrams/05-backlog.svg +113 -0
- package/docs/diagrams/06-automation-utilities-d2.png +0 -0
- package/docs/diagrams/06-automation-utilities.d2 +48 -0
- package/docs/diagrams/06-automation-utilities.mmd +47 -0
- package/docs/diagrams/06-automation-utilities.png +0 -0
- package/docs/diagrams/06-automation-utilities.svg +110 -0
- package/docs/diagrams/_theme.d2 +86 -0
- package/docs/requirements.md +48 -0
- package/docs/workflow-diagram.md +338 -0
- package/package.json +1 -1
- package/scripts/gsd-t-dashboard-server.js +190 -0
- package/scripts/gsd-t-transcript.html +200 -0
- package/templates/CLAUDE-global.md +46 -0
- package/templates/prompts/design-verify-subagent.md +3 -0
- package/templates/prompts/qa-subagent.md +3 -0
- package/templates/prompts/red-team-subagent.md +3 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* GSD-T verify-gate judge (M55 D5)
|
|
6
|
+
*
|
|
7
|
+
* Companion to bin/gsd-t-verify-gate.cjs. Takes a verify-gate envelope JSON
|
|
8
|
+
* (object or stringified) and produces a ≤500-token LLM prompt scaffold the
|
|
9
|
+
* orchestrator can hand to the LLM judge.
|
|
10
|
+
*
|
|
11
|
+
* Pure synchronous — no LLM call, no spawn, no I/O beyond reading stdin or
|
|
12
|
+
* the path passed via --in.
|
|
13
|
+
*
|
|
14
|
+
* Contract: .gsd-t/contracts/verify-gate-contract.md v1.0.0 STABLE.
|
|
15
|
+
*
|
|
16
|
+
* Hard rules:
|
|
17
|
+
* 1. Output prompt is ≤MAX_PROMPT_TOKENS regardless of envelope size
|
|
18
|
+
* (4 chars/token approximation).
|
|
19
|
+
* 2. The judge sees `summary` only — never `track1.checks[]` raw or
|
|
20
|
+
* Track 2 worker logs.
|
|
21
|
+
* 3. Pure function — same envelope in, same prompt out.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const fs = require('fs');
|
|
25
|
+
|
|
26
|
+
const MAX_PROMPT_TOKENS = 500;
|
|
27
|
+
const TOKENS_PER_CHAR = 0.25;
|
|
28
|
+
const SUMMARY_BUDGET_TOKENS = 380; // leave headroom for instruction prefix
|
|
29
|
+
const PROMPT_PREFIX_LINES = [
|
|
30
|
+
'GSD-T verify-gate result. Render PASS / FAIL.',
|
|
31
|
+
'Deterministic verdict in `summary.verdict`. Confirm or contradict.',
|
|
32
|
+
'If FAIL, name the failing track in one short line.',
|
|
33
|
+
'',
|
|
34
|
+
'```json',
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const PROMPT_SUFFIX_LINES = [
|
|
38
|
+
'```',
|
|
39
|
+
'',
|
|
40
|
+
'Verdict (PASS|FAIL) and 1-line reason:',
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
// ── Public API ──────────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Build a judge prompt from a verify-gate envelope.
|
|
47
|
+
* @param {object|string} envelope
|
|
48
|
+
* @returns {string} the prompt scaffold
|
|
49
|
+
*/
|
|
50
|
+
function buildJudgePrompt(envelope) {
|
|
51
|
+
const env = typeof envelope === 'string' ? _safeParse(envelope) : envelope;
|
|
52
|
+
if (!env || typeof env !== 'object') {
|
|
53
|
+
return _wrap({ verdict: 'FAIL', reason: 'envelope-malformed' });
|
|
54
|
+
}
|
|
55
|
+
let summary = env.summary;
|
|
56
|
+
if (!summary || typeof summary !== 'object') {
|
|
57
|
+
return _wrap({
|
|
58
|
+
verdict: 'FAIL',
|
|
59
|
+
reason: 'summary-missing',
|
|
60
|
+
schemaVersion: env.schemaVersion || null,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// Shrink the summary if needed to fit within SUMMARY_BUDGET_TOKENS.
|
|
64
|
+
const shrunk = _fitSummary(summary);
|
|
65
|
+
return _wrap(shrunk);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Estimate token count for a string (4 chars/token approximation).
|
|
70
|
+
* @param {string} s
|
|
71
|
+
* @returns {number}
|
|
72
|
+
*/
|
|
73
|
+
function estimateTokens(s) {
|
|
74
|
+
return Math.ceil((s || '').length * TOKENS_PER_CHAR);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ── Internal helpers ────────────────────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
function _safeParse(s) {
|
|
80
|
+
try { return JSON.parse(s); } catch (_) { return null; }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function _wrap(summaryObj) {
|
|
84
|
+
const body = JSON.stringify(summaryObj, null, 2);
|
|
85
|
+
return [
|
|
86
|
+
...PROMPT_PREFIX_LINES,
|
|
87
|
+
body,
|
|
88
|
+
...PROMPT_SUFFIX_LINES,
|
|
89
|
+
].join('\n');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function _fitSummary(summary) {
|
|
93
|
+
// Start with a copy. If the JSON exceeds budget, shrink failedChecks /
|
|
94
|
+
// failedWorkers entries iteratively.
|
|
95
|
+
const copy = JSON.parse(JSON.stringify(summary));
|
|
96
|
+
|
|
97
|
+
const tokens = (obj) => estimateTokens(JSON.stringify(obj, null, 2));
|
|
98
|
+
if (tokens(copy) <= SUMMARY_BUDGET_TOKENS) return copy;
|
|
99
|
+
|
|
100
|
+
// Shrink summarySnippets in failedWorkers first.
|
|
101
|
+
if (Array.isArray(copy.track2 && copy.track2.failedWorkers)) {
|
|
102
|
+
let cap = 100;
|
|
103
|
+
while (tokens(copy) > SUMMARY_BUDGET_TOKENS && cap >= 8) {
|
|
104
|
+
copy.track2.failedWorkers = copy.track2.failedWorkers.map((w) => ({
|
|
105
|
+
...w,
|
|
106
|
+
summarySnippet: _trim(w.summarySnippet, cap),
|
|
107
|
+
}));
|
|
108
|
+
cap = Math.floor(cap / 2);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Truncate failedWorkers list if still over.
|
|
113
|
+
if (Array.isArray(copy.track2 && copy.track2.failedWorkers)) {
|
|
114
|
+
while (tokens(copy) > SUMMARY_BUDGET_TOKENS && copy.track2.failedWorkers.length > 1) {
|
|
115
|
+
const removed = copy.track2.failedWorkers.length - 1;
|
|
116
|
+
copy.track2.failedWorkers = [copy.track2.failedWorkers[0]];
|
|
117
|
+
copy.track2.failedWorkersTruncated = removed;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Truncate failedChecks list if still over.
|
|
122
|
+
if (Array.isArray(copy.track1 && copy.track1.failedChecks)) {
|
|
123
|
+
while (tokens(copy) > SUMMARY_BUDGET_TOKENS && copy.track1.failedChecks.length > 1) {
|
|
124
|
+
const removed = copy.track1.failedChecks.length - 1;
|
|
125
|
+
copy.track1.failedChecks = [copy.track1.failedChecks[0]];
|
|
126
|
+
copy.track1.failedChecksTruncated = removed;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// If still over, last resort — drop msgs.
|
|
131
|
+
if (tokens(copy) > SUMMARY_BUDGET_TOKENS) {
|
|
132
|
+
if (copy.track1 && Array.isArray(copy.track1.failedChecks)) {
|
|
133
|
+
copy.track1.failedChecks = copy.track1.failedChecks.map((c) => ({ id: c.id, severity: c.severity }));
|
|
134
|
+
}
|
|
135
|
+
if (copy.track2 && Array.isArray(copy.track2.failedWorkers)) {
|
|
136
|
+
copy.track2.failedWorkers = copy.track2.failedWorkers.map((w) => ({ id: w.id, exitCode: w.exitCode }));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return copy;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function _trim(s, cap) {
|
|
144
|
+
if (typeof s !== 'string' || s.length <= cap * 2) return s || '';
|
|
145
|
+
return s.slice(0, cap) + '\n…\n' + s.slice(-cap);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ── CLI ─────────────────────────────────────────────────────────────────────
|
|
149
|
+
|
|
150
|
+
function _parseArgv(argv) {
|
|
151
|
+
const out = { in: null, help: false };
|
|
152
|
+
for (let i = 0; i < argv.length; i++) {
|
|
153
|
+
const a = argv[i];
|
|
154
|
+
if (a === '--in') out.in = argv[++i] || null;
|
|
155
|
+
else if (a.startsWith('--in=')) out.in = a.slice(5);
|
|
156
|
+
else if (a === '--help' || a === '-h') out.help = true;
|
|
157
|
+
else { out._badFlag = 'unknown flag: ' + a; }
|
|
158
|
+
}
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function _printHelp() {
|
|
163
|
+
process.stdout.write([
|
|
164
|
+
'Usage: gsd-t verify-gate-judge [--in PATH]',
|
|
165
|
+
'',
|
|
166
|
+
'Reads a verify-gate envelope (JSON) from --in PATH or stdin, prints the',
|
|
167
|
+
'LLM judge prompt scaffold (≤500 tokens) to stdout.',
|
|
168
|
+
'',
|
|
169
|
+
'Exit codes:',
|
|
170
|
+
' 0 prompt emitted',
|
|
171
|
+
' 2 CLI usage error',
|
|
172
|
+
].join('\n') + '\n');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function _readStdin() {
|
|
176
|
+
// Synchronous read — judge is meant to be piped from verify-gate.
|
|
177
|
+
try {
|
|
178
|
+
return fs.readFileSync(0, 'utf8');
|
|
179
|
+
} catch (_) {
|
|
180
|
+
return '';
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function _runCli(argv) {
|
|
185
|
+
const args = _parseArgv(argv);
|
|
186
|
+
if (args.help) {
|
|
187
|
+
_printHelp();
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
if (args._badFlag) {
|
|
191
|
+
process.stderr.write('verify-gate-judge: ' + args._badFlag + '\n');
|
|
192
|
+
return 2;
|
|
193
|
+
}
|
|
194
|
+
let raw = '';
|
|
195
|
+
if (args.in) {
|
|
196
|
+
try {
|
|
197
|
+
raw = fs.readFileSync(args.in, 'utf8');
|
|
198
|
+
} catch (err) {
|
|
199
|
+
process.stderr.write('verify-gate-judge: cannot read ' + args.in + ' (' + err.message + ')\n');
|
|
200
|
+
return 2;
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
raw = _readStdin();
|
|
204
|
+
}
|
|
205
|
+
const prompt = buildJudgePrompt(raw);
|
|
206
|
+
process.stdout.write(prompt + '\n');
|
|
207
|
+
return 0;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (require.main === module) {
|
|
211
|
+
process.exit(_runCli(process.argv.slice(2)));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
module.exports = {
|
|
215
|
+
buildJudgePrompt,
|
|
216
|
+
estimateTokens,
|
|
217
|
+
MAX_PROMPT_TOKENS,
|
|
218
|
+
SUMMARY_BUDGET_TOKENS,
|
|
219
|
+
// Test surface:
|
|
220
|
+
_fitSummary,
|
|
221
|
+
_trim,
|
|
222
|
+
_wrap,
|
|
223
|
+
_parseArgv,
|
|
224
|
+
};
|