@tekyzinc/gsd-t 2.71.18 → 2.71.20
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 +7 -0
- package/bin/orchestrator.js +27 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to GSD-T are documented here. Updated with each release.
|
|
4
4
|
|
|
5
|
+
## [2.71.20] - 2026-04-08
|
|
6
|
+
|
|
7
|
+
### Fixed (orchestrator — reviewer crash false-pass + Ctrl+C + build logging)
|
|
8
|
+
- **Reviewer crash no longer treated as "pass"** — if the reviewer exits with non-zero code in under 10s, it's a crash, not a clean review. Retried on next cycle. Previously, empty output from a crashed reviewer was parsed as "0 issues = pass."
|
|
9
|
+
- **Ctrl+C now works** — replaced `Atomics.wait` with `sleep` command for synchronous polling. `Atomics.wait` blocks the event loop completely, preventing SIGINT.
|
|
10
|
+
- **Build output logging** — builder output written to `.gsd-t/design-review/build-logs/{phase}-build.log` for debugging.
|
|
11
|
+
|
|
5
12
|
## [2.71.18] - 2026-04-08
|
|
6
13
|
|
|
7
14
|
### Fixed (orchestrator — Claude permissions and timeouts)
|
package/bin/orchestrator.js
CHANGED
|
@@ -52,10 +52,12 @@ function ensureDir(dir) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
function syncSleep(ms) {
|
|
55
|
+
// Use sleep command instead of Atomics.wait — Atomics blocks the event loop
|
|
56
|
+
// completely, preventing SIGINT (Ctrl+C) from being handled
|
|
55
57
|
try {
|
|
56
|
-
|
|
58
|
+
execFileSync("sleep", [String(ms / 1000)], { stdio: "pipe" });
|
|
57
59
|
} catch {
|
|
58
|
-
|
|
60
|
+
// sleep interrupted by signal — that's fine
|
|
59
61
|
}
|
|
60
62
|
}
|
|
61
63
|
|
|
@@ -569,6 +571,14 @@ ${BOLD}Phases:${RESET} ${this.wf.phases.join(" → ")}
|
|
|
569
571
|
warn(`Claude exited with code ${buildResult.exitCode} after ${buildResult.duration}s`);
|
|
570
572
|
}
|
|
571
573
|
|
|
574
|
+
// Log build output for debugging
|
|
575
|
+
const buildLogDir = path.join(this.getReviewDir(projectDir), "build-logs");
|
|
576
|
+
ensureDir(buildLogDir);
|
|
577
|
+
fs.writeFileSync(
|
|
578
|
+
path.join(buildLogDir, `${phase}-build.log`),
|
|
579
|
+
`Exit code: ${buildResult.exitCode}\nDuration: ${buildResult.duration}s\nPrompt length: ${prompt.length}\n\n--- OUTPUT ---\n${buildResult.output.slice(0, 20000)}`
|
|
580
|
+
);
|
|
581
|
+
|
|
572
582
|
// 6c. Collect built paths
|
|
573
583
|
const builtPaths = items.map(item =>
|
|
574
584
|
item.sourcePath || (this.wf.guessPaths ? this.wf.guessPaths(phase, item) : "")
|
|
@@ -599,14 +609,22 @@ ${BOLD}Phases:${RESET} ${this.wf.phases.join(" → ")}
|
|
|
599
609
|
const reviewResult = this.spawnClaude(projectDir, reviewPrompt, reviewTimeout);
|
|
600
610
|
|
|
601
611
|
// Parse reviewer output for issues
|
|
602
|
-
|
|
603
|
-
? this.wf.parseReviewResult(reviewResult.output, phase)
|
|
604
|
-
: this._parseDefaultReviewResult(reviewResult.output);
|
|
612
|
+
let issues;
|
|
605
613
|
|
|
606
|
-
|
|
607
|
-
|
|
614
|
+
// Treat reviewer crash (non-zero exit, very short duration) as a failed review, not a pass
|
|
615
|
+
if (reviewResult.exitCode !== 0 && reviewResult.duration < 10) {
|
|
616
|
+
warn(`Reviewer crashed (code ${reviewResult.exitCode}, ${reviewResult.duration}s) — treating as review failure, will retry`);
|
|
617
|
+
issues = [{ component: "ALL", severity: "critical", description: `Reviewer crashed with exit code ${reviewResult.exitCode} — review not performed` }];
|
|
608
618
|
} else {
|
|
609
|
-
|
|
619
|
+
issues = this.wf.parseReviewResult
|
|
620
|
+
? this.wf.parseReviewResult(reviewResult.output, phase)
|
|
621
|
+
: this._parseDefaultReviewResult(reviewResult.output);
|
|
622
|
+
|
|
623
|
+
if (reviewResult.exitCode === 0) {
|
|
624
|
+
success(`Reviewer finished in ${reviewResult.duration}s`);
|
|
625
|
+
} else {
|
|
626
|
+
warn(`Reviewer exited with code ${reviewResult.exitCode} after ${reviewResult.duration}s`);
|
|
627
|
+
}
|
|
610
628
|
}
|
|
611
629
|
|
|
612
630
|
// Write review report
|
|
@@ -614,7 +632,7 @@ ${BOLD}Phases:${RESET} ${this.wf.phases.join(" → ")}
|
|
|
614
632
|
ensureDir(reportDir);
|
|
615
633
|
fs.writeFileSync(
|
|
616
634
|
path.join(reportDir, `${phase}-cycle-${autoReviewCycle}.json`),
|
|
617
|
-
JSON.stringify({ cycle: autoReviewCycle, issues, output: reviewResult.output.slice(0, 5000) }, null, 2)
|
|
635
|
+
JSON.stringify({ cycle: autoReviewCycle, issues, exitCode: reviewResult.exitCode, duration: reviewResult.duration, output: reviewResult.output.slice(0, 5000) }, null, 2)
|
|
618
636
|
);
|
|
619
637
|
|
|
620
638
|
if (issues.length === 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tekyzinc/gsd-t",
|
|
3
|
-
"version": "2.71.
|
|
3
|
+
"version": "2.71.20",
|
|
4
4
|
"description": "GSD-T: Contract-Driven Development for Claude Code — 56 slash commands with headless CI/CD mode, graph-powered code analysis, real-time agent dashboard, execution intelligence, 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",
|