@tekyzinc/gsd-t 5.20.10 → 5.20.11

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 CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable changes to GSD-T are documented here. Updated with each release.
4
4
 
5
+ ## [5.20.11] - 2026-09-17
6
+
7
+ ### Fixed — `update-all` treated a downgrade as an upgrade and rolled 34 projects back
8
+
9
+ Releasing 5.20.10, npm's cached package listing still named 5.19.11 as `@latest` for
10
+ several minutes after publish. `upgradeGlobalBinary()` installed the older release over
11
+ the running one, printed "upgraded: v5.20.10 → v5.19.11", handed off to the OLD binary,
12
+ and that binary rewrote `~/.claude/commands` and every registered project with the
13
+ previous version. It happened twice in one release.
14
+
15
+ - `bin/gsd-t.js`: numeric `versionCmp`; a downgrade now HALTS (exit 1) before the
16
+ "upgraded" branch and names the fix (`npm cache clean --force`, wait for the tarball
17
+ to serve 200, reinstall the current release). Never hands off to an older binary.
18
+ - `commands/cpua.md`: Step 6 polls the tarball URL until it returns 200, cleans the npm
19
+ cache, installs, and checks `dist-tags.latest` equals the new version BEFORE `update-all`.
20
+ - `test/update-all-downgrade-halt.test.js`: the compare is numeric (5.9 < 5.10) and the
21
+ downgrade branch exits instead of re-exec'ing.
22
+
5
23
  ## [5.20.10] - 2026-09-17
6
24
 
7
25
  ### Changed — `/gsd-t-estimate` is the sheet only, and the sheet now has a written spec
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # GSD-T: Contract-Driven Development for Claude Code
2
2
 
3
- **v5.20.10** - A methodology for reliable, parallelizable development using Claude Code with optional Agent Teams support.
3
+ **v5.20.11** - 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/bin/gsd-t.js CHANGED
@@ -3466,6 +3466,20 @@ async function doUpdateAll() {
3466
3466
  );
3467
3467
  }
3468
3468
 
3469
+ // Numeric dotted-version compare: negative when a < b, 0 when equal, positive when a > b.
3470
+ // GSD-T versions are plain Major.Minor.Patch integers (patch always ≥ 10), so a
3471
+ // segment-wise numeric compare is exact; no prerelease tags exist.
3472
+ function versionCmp(a, b) {
3473
+ const pa = String(a).split(".").map((n) => parseInt(n, 10));
3474
+ const pb = String(b).split(".").map((n) => parseInt(n, 10));
3475
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
3476
+ const x = Number.isNaN(pa[i]) ? 0 : pa[i];
3477
+ const y = Number.isNaN(pb[i]) ? 0 : pb[i];
3478
+ if (x !== y) return x - y;
3479
+ }
3480
+ return 0;
3481
+ }
3482
+
3469
3483
  // Upgrade the globally-installed @tekyzinc/gsd-t to @latest. Returns
3470
3484
  // { upgraded: bool, reexec: bool, error?: string }.
3471
3485
  // - reexec=true when the on-disk version after `npm install -g` is newer than
@@ -3499,6 +3513,19 @@ async function upgradeGlobalBinary() {
3499
3513
  // Best-effort; fall through.
3500
3514
  }
3501
3515
 
3516
+ if (newVersion && versionCmp(newVersion, PKG_VERSION) < 0) {
3517
+ // v5.20.10 (2026-09-17): right after `npm publish`, npm's cached package
3518
+ // listing still named the PREVIOUS version as @latest, so this step
3519
+ // installed 5.19.11 over a running 5.20.10, reported it as an "upgrade",
3520
+ // handed off to the OLD binary, and that binary overwrote ~/.claude/commands
3521
+ // and every project with the old release. A downgrade is never an upgrade —
3522
+ // HALT and say how to fix it, never continue on a stale listing.
3523
+ error(`HALT: npm installed v${newVersion} over the running v${PKG_VERSION} — @latest resolved to an OLDER release.`);
3524
+ info("npm's cached package listing is stale. Run `npm cache clean --force`, wait until");
3525
+ info(`\`curl -sI https://registry.npmjs.org/@tekyzinc/gsd-t/-/gsd-t-${PKG_VERSION}.tgz\` returns 200, then re-run update-all.`);
3526
+ info(`Restore the current release first: npm install -g @tekyzinc/gsd-t@${PKG_VERSION}`);
3527
+ process.exit(1);
3528
+ }
3502
3529
  if (newVersion && newVersion !== PKG_VERSION) {
3503
3530
  success(`Global binary upgraded: v${PKG_VERSION} → v${newVersion}`);
3504
3531
  info("Handing off to the newly-installed binary for propagation...");
package/commands/cpua.md CHANGED
@@ -120,6 +120,19 @@ G="$(npm root -g)/@tekyzinc/gsd-t"
120
120
  # the pre-publish package listing cached and `@tekyzinc/gsd-t@{NEW}` returns ETARGET
121
121
  # for minutes while `npm view` already shows the version (v5.17.14, 2026-09-03).
122
122
  # The tarball URL bypasses the cached listing and is deterministic.
123
+ # 1b. WAIT until the registry actually SERVES the tarball, then CLEAR npm's cached listing.
124
+ # v5.20.10 (2026-09-17): `npm publish` printed "+ @tekyzinc/gsd-t@5.20.10" and `npm view`
125
+ # showed it, but the tarball URL 404'd for ~4 minutes. Worse, npm's cached package
126
+ # listing still said latest = the PREVIOUS version, so `gsd-t update-all` (which runs
127
+ # `npm install -g @tekyzinc/gsd-t@latest`) DOWNGRADED the global, handed off to the old
128
+ # binary, and that binary rewrote ~/.claude/commands and 34 projects with the old release
129
+ # — twice. Poll the tarball, then clean the cache, then install. Never skip either.
130
+ for i in $(seq 1 60); do
131
+ [ "$(curl -s -o /dev/null -w '%{http_code}' "https://registry.npmjs.org/@tekyzinc/gsd-t/-/gsd-t-{NEW_VERSION}.tgz")" = "200" ] && break
132
+ sleep 10
133
+ done
134
+ [ "$(curl -s -o /dev/null -w '%{http_code}' "https://registry.npmjs.org/@tekyzinc/gsd-t/-/gsd-t-{NEW_VERSION}.tgz")" = "200" ] || { echo "HALT: tarball still 404 after 10 min"; exit 1; }
135
+ npm cache clean --force
123
136
  npm install -g "https://registry.npmjs.org/@tekyzinc/gsd-t/-/gsd-t-{NEW_VERSION}.tgz"
124
137
  # 2. VERIFY ON DISK — never trust npm's exit code for this step. On v5.17.13 `npm install -g`
125
138
  # reported success and left the OLD version in place; `update-all` then ran from the
@@ -140,7 +153,11 @@ fi
140
153
  # file and the command files; only then does update-all see the new release.
141
154
  gsd-t install 2>&1 | tail -5
142
155
  [ "$(cat ~/.claude/.gsd-t-version)" = "{NEW_VERSION}" ] || { echo "HALT: ~/.claude/.gsd-t-version did not advance"; exit 1; }
143
- # 4. Propagate, then prove the global is STILL the new version and a NEW file reached a project.
156
+ # 4. Prove `@latest` now resolves to the NEW version (update-all installs `@latest`; a stale
157
+ # listing here is the downgrade path — since v5.20.11 update-all HALTS on a downgrade
158
+ # instead of handing off, but do not rely on the halt: check first).
159
+ [ "$(npm view @tekyzinc/gsd-t dist-tags.latest)" = "{NEW_VERSION}" ] || { echo "HALT: registry latest is not {NEW_VERSION}"; exit 1; }
160
+ # 5. Propagate, then prove the global is STILL the new version and a NEW file reached a project.
144
161
  gsd-t update-all 2>&1 | tail -30
145
162
  [ "$(node -p "require('$G/package.json').version")" = "{NEW_VERSION}" ] || { echo "HALT: global package reverted during update-all"; exit 1; }
146
163
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekyzinc/gsd-t",
3
- "version": "5.20.10",
3
+ "version": "5.20.11",
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",