@tekyzinc/gsd-t 5.11.20 → 5.11.21
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 +23 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/templates/workflows/gsd-t-scan.workflow.js +49 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to GSD-T are documented here. Updated with each release.
|
|
4
4
|
|
|
5
|
+
## [5.11.21] - 2026-08-10
|
|
6
|
+
|
|
7
|
+
### Added — a final sweep that re-runs slices the rush broke
|
|
8
|
+
|
|
9
|
+
Two slices failed an otherwise clean run on rate limits alone: ten agents in
|
|
10
|
+
flight, the account throttled, and all three attempts landing inside the same
|
|
11
|
+
squeeze. That failure says nothing about the slice — only about when it ran.
|
|
12
|
+
|
|
13
|
+
After the deep scan, the run now waits 30 seconds for any active rate-limit
|
|
14
|
+
window to pass, then retries every failed slice **one at a time, outside the
|
|
15
|
+
concurrency gate**. Re-running failures through the same crowded gate that
|
|
16
|
+
caused them would reproduce the cause.
|
|
17
|
+
|
|
18
|
+
It costs a few minutes on runs that need it and nothing at all on runs that do
|
|
19
|
+
not. A recovered slice stops being a coverage gap and its findings reach the
|
|
20
|
+
register.
|
|
21
|
+
|
|
22
|
+
The sweep runs **before** the partial-coverage halt, so the run only stops for
|
|
23
|
+
what is genuinely lost.
|
|
24
|
+
|
|
25
|
+
- `templates/workflows/gsd-t-scan.workflow.js`: the sweep; `allFindings` now reads the array the sweep repairs
|
|
26
|
+
- `test/m112-scan-schema-tolerance.test.js`: 4 more tests — serial, before the halt, waits, and recovered findings reach the register
|
|
27
|
+
|
|
5
28
|
## [5.11.20] - 2026-08-10
|
|
6
29
|
|
|
7
30
|
### Fixed — the real cause of the scan failures: agents pass their answer as a string
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# GSD-T: Contract-Driven Development for Claude Code
|
|
2
2
|
|
|
3
|
-
**v5.11.
|
|
3
|
+
**v5.11.21** - A methodology for reliable, parallelizable development using Claude Code with optional Agent Teams support.
|
|
4
4
|
|
|
5
5
|
**Eliminates context rot** — task-level fresh dispatch (one subagent per task, ~10-20% context each) means compaction never triggers.
|
|
6
6
|
**Compaction-proof debug loops** — `gsd-t headless --debug-loop` runs test-fix-retest cycles as separate `claude -p` sessions. A JSONL debug ledger persists all hypothesis/fix/learning history across fresh sessions. Anti-repetition preamble injection prevents retrying failed hypotheses. Escalation tiers (sonnet → opus → human) and a hard iteration ceiling enforced externally.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tekyzinc/gsd-t",
|
|
3
|
-
"version": "5.11.
|
|
3
|
+
"version": "5.11.21",
|
|
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",
|
|
@@ -824,9 +824,57 @@ slices.forEach((s, i) => {
|
|
|
824
824
|
const r = resultsByIndex[i];
|
|
825
825
|
if (!r || r.failed) failedSlices.push(s.key);
|
|
826
826
|
});
|
|
827
|
+
// ── Final sweep: re-run what the rush broke ─────────────────────────────────
|
|
828
|
+
//
|
|
829
|
+
// A slice can exhaust its three attempts purely because the run was at full
|
|
830
|
+
// tilt — 10 agents in flight, the account rate-limited, and all three tries
|
|
831
|
+
// landing inside the same squeeze. That failure says nothing about the slice.
|
|
832
|
+
//
|
|
833
|
+
// So once the deep scan is over and the burst has drained, try the stragglers
|
|
834
|
+
// again: one at a time, unhurried, with the whole machine to themselves. It
|
|
835
|
+
// costs a few minutes on the runs that need it and nothing at all on the runs
|
|
836
|
+
// that do not.
|
|
837
|
+
//
|
|
838
|
+
// Serial and ungated on purpose. Re-running failures through the same crowded
|
|
839
|
+
// gate that caused them would reproduce the cause.
|
|
840
|
+
if (failedSlices.length > 0) {
|
|
841
|
+
log(`↻ final sweep — retrying ${failedSlices.length} failed slice(s) one at a time, now that the run has drained: ${failedSlices.join(", ")}`);
|
|
842
|
+
await sleep(30000); // let any active rate-limit window pass before starting
|
|
843
|
+
|
|
844
|
+
const stillFailed = [];
|
|
845
|
+
for (const key of failedSlices) {
|
|
846
|
+
const slice = slices.find((sl) => sl.key === key);
|
|
847
|
+
if (!slice) { stillFailed.push(key); continue; }
|
|
848
|
+
|
|
849
|
+
const recovered = await scanSlice(slice); // scanSlice resolves its own graph context
|
|
850
|
+
|
|
851
|
+
if (recovered && !recovered.failed) {
|
|
852
|
+
const idx = slices.indexOf(slice);
|
|
853
|
+
resultsByIndex[idx] = recovered;
|
|
854
|
+
log(`✓ sweep recovered "${key}" — ${(recovered.findings || []).length} finding(s)`);
|
|
855
|
+
} else {
|
|
856
|
+
stillFailed.push(key);
|
|
857
|
+
log(`✗ sweep could not recover "${key}"`);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// Only the failed list needs updating by hand — coverage and the findings
|
|
862
|
+
// list are computed from `resultsByIndex` below, which the sweep has already
|
|
863
|
+
// repaired in place.
|
|
864
|
+
failedSlices.length = 0;
|
|
865
|
+
failedSlices.push(...stillFailed);
|
|
866
|
+
|
|
867
|
+
log(stillFailed.length === 0
|
|
868
|
+
? `✓ final sweep restored full coverage — ${slices.length}/${slices.length} slices`
|
|
869
|
+
: `⚠ final sweep left ${stillFailed.length} slice(s) unrecovered: ${stillFailed.join(", ")}`);
|
|
870
|
+
}
|
|
871
|
+
|
|
827
872
|
const succeededCount = slices.length - failedSlices.length;
|
|
828
873
|
const coverageComplete = failedSlices.length === 0;
|
|
829
|
-
|
|
874
|
+
// Read from resultsByIndex, not sliceResults: the final sweep writes recovered
|
|
875
|
+
// slices back into resultsByIndex, and a recovered slice's findings must reach
|
|
876
|
+
// the register.
|
|
877
|
+
const allFindings = resultsByIndex.filter(Boolean).filter((r) => !r.failed).flatMap((r) => (r.findings || []).map((f) => ({ ...f, slice: r.slice })));
|
|
830
878
|
if (!coverageComplete) {
|
|
831
879
|
log(`⚠ PARTIAL COVERAGE — ${failedSlices.length}/${slices.length} slices failed after retry and produced NO findings: ${failedSlices.join(", ")}.`);
|
|
832
880
|
|