From 66c8a55dbbe1c7c04e819771fcbfc1792ef26467 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Thu, 14 May 2026 18:34:36 -0700 Subject: [PATCH] chore: bump to v1.38.1.0 VERSION + package.json + CHANGELOG header + migration filename + test reference all consistently at v1.38.1.0. Migration renamed: gstack-upgrade/migrations/v1.38.0.0.sh -> v1.38.1.0.sh. Co-Authored-By: Claude Opus 4.7 --- CHANGELOG.md | 6 +++--- VERSION | 2 +- .../migrations/{v1.38.0.0.sh => v1.38.1.0.sh} | 10 +++++----- package.json | 2 +- test/artifacts-init-migration.test.ts | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) rename gstack-upgrade/migrations/{v1.38.0.0.sh => v1.38.1.0.sh} (91%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 160c59bf8..d2f639d08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [1.38.0.0] - 2026-05-14 +## [1.38.1.0] - 2026-05-14 ## **Page captures stop crashing on broken emoji bytes, every review skill ends with a build-actionable task checklist, federation sync no longer drops office-hours design docs.** ## **Three community-filed issues landed as one bug-fix wave: surrogate-safe browse responses (including `/batch`), per-skill Implementation Tasks with JSONL handoff to `/autoplan`, and root-level artifact patterns in `.brain-allowlist`.** @@ -9,7 +9,7 @@ Page captures from real-world HTML hit `API Error 400: no low surrogate in strin All four review skills (CEO / design / eng / DX) now end with an `## Implementation Tasks` markdown checklist and write a `jq`-built JSONL artifact to `~/.gstack/projects/$SLUG/tasks-{phase}-{datetime}.jsonl`. `/autoplan`'s Phase 4 reads all four files, scopes by current branch + 5-commit window, dedupes on exact `(component, sorted(files), title)` matches, and renders one aggregated list inside the final approval gate. Tasks that derive from the same finding now collapse; tasks that just happen to touch the same file with different titles surface separately so the human can decide whether they're the same work. Standalone review runs (`/plan-eng-review` alone, etc.) produce their own task list and JSONL file even outside autoplan — the JSONL is the handoff contract. -Federation sync (`gstack-brain-sync`) was silently skipping root-level design and test-plan docs — `/office-hours` and `/plan-eng-review` write at `projects/{slug}/{user}-{branch}-design-*.md`, but the allowlist only knew about `projects/*/designs/*.md` and `projects/*/ceo-plans/*.md`. New patterns ship in `.brain-allowlist`, `.brain-privacy-map.json` (classified as `artifact`), and `.gitattributes` (with `merge=union` to handle cross-machine conflicts). An idempotent jq-based migration (`gstack-upgrade/migrations/v1.38.0.0.sh`) patches existing installs in-place without re-running `gstack-artifacts-init` (which would have done a git commit + push and clobbered user state). +Federation sync (`gstack-brain-sync`) was silently skipping root-level design and test-plan docs — `/office-hours` and `/plan-eng-review` write at `projects/{slug}/{user}-{branch}-design-*.md`, but the allowlist only knew about `projects/*/designs/*.md` and `projects/*/ceo-plans/*.md`. New patterns ship in `.brain-allowlist`, `.brain-privacy-map.json` (classified as `artifact`), and `.gitattributes` (with `merge=union` to handle cross-machine conflicts). An idempotent jq-based migration (`gstack-upgrade/migrations/v1.38.1.0.sh`) patches existing installs in-place without re-running `gstack-artifacts-init` (which would have done a git commit + push and clobbered user state). ### The numbers that matter @@ -42,7 +42,7 @@ Page captures with mixed-script Unicode round-trip cleanly to the Claude API now - **`## Implementation Tasks` section + JSONL handoff in every review skill (#1454)** — `plan-ceo-review`, `plan-design-review`, `plan-eng-review`, `plan-devex-review` each emit a per-skill markdown checklist and write `~/.gstack/projects/$SLUG/tasks-{phase}-{datetime}.jsonl` via `jq -nc` (never hand-rolled echo). `/autoplan` Phase 4 reads all four phase JSONL files, scopes by current branch and 5-commit window, dedupes on exact `(component, sorted(files), title)` matches, and renders one aggregated list. Near-duplicates surface separately with a possible-duplicate note for human resolution. - **`browse/src/sanitize.ts`** — two surrogate-stripping utilities plus a convenience selector keyed on content-type. Pairs with a refactored `buildCommandResponse` in `server.ts` (exported for testability) and per-result sanitization in the `/batch` handler. -- **`gstack-upgrade/migrations/v1.38.0.0.sh`** — idempotent per-file repair for `.brain-allowlist`, `.brain-privacy-map.json`, and `.gitattributes`. Uses `jq` for the JSON file (preserves validity); falls back with a clear warning if `jq` is missing. Does NOT re-run `gstack-artifacts-init` (which would commit + push to the user's federated repo). +- **`gstack-upgrade/migrations/v1.38.1.0.sh`** — idempotent per-file repair for `.brain-allowlist`, `.brain-privacy-map.json`, and `.gitattributes`. Uses `jq` for the JSON file (preserves validity); falls back with a clear warning if `jq` is missing. Does NOT re-run `gstack-artifacts-init` (which would commit + push to the user's federated repo). - **32 new unit tests** across `browse/test/sanitize.test.ts` (18), `browse/test/build-command-response.test.ts` (7), `test/artifacts-init-migration.test.ts` (7). All gate-tier (free, runs on every PR). #### Changed diff --git a/VERSION b/VERSION index be9cbf2dc..446eb32e7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.38.0.0 +1.38.1.0 diff --git a/gstack-upgrade/migrations/v1.38.0.0.sh b/gstack-upgrade/migrations/v1.38.1.0.sh similarity index 91% rename from gstack-upgrade/migrations/v1.38.0.0.sh rename to gstack-upgrade/migrations/v1.38.1.0.sh index 02f7f0135..2a56634d7 100755 --- a/gstack-upgrade/migrations/v1.38.0.0.sh +++ b/gstack-upgrade/migrations/v1.38.1.0.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Migration: v1.38.0.0 — add root-level design + test-plan patterns to +# Migration: v1.38.1.0 — add root-level design + test-plan patterns to # .brain-allowlist, .brain-privacy-map.json, and .gitattributes (#1452). # # Why a migration: gstack-artifacts-init regenerates these files but also @@ -21,7 +21,7 @@ PRIVACY="${GSTACK_HOME}/.brain-privacy-map.json" GITATTRS="${GSTACK_HOME}/.gitattributes" MIGRATION_DIR="${GSTACK_HOME}/.migrations" -DONE="${MIGRATION_DIR}/v1.38.0.0.done" +DONE="${MIGRATION_DIR}/v1.38.1.0.done" mkdir -p "${MIGRATION_DIR}" 2>/dev/null || true if [ -f "${DONE}" ]; then @@ -67,12 +67,12 @@ if [ -f "${PRIVACY}" ]; then added_any=1 else rm -f "${PRIVACY}.tmp" - echo " [v1.38.0.0] WARN: jq failed to patch ${PRIVACY}; skipping pattern ${PATTERN}." >&2 + echo " [v1.38.1.0] WARN: jq failed to patch ${PRIVACY}; skipping pattern ${PATTERN}." >&2 fi fi done else - echo " [v1.38.0.0] WARN: jq not found; skipping privacy-map repair. Install jq and re-run gstack-upgrade, or run gstack-artifacts-init manually." >&2 + echo " [v1.38.1.0] WARN: jq not found; skipping privacy-map repair. Install jq and re-run gstack-upgrade, or run gstack-artifacts-init manually." >&2 fi fi @@ -92,7 +92,7 @@ fi touch "${DONE}" if [ "${added_any}" = "1" ]; then - echo " [v1.38.0.0] allowlist/privacy-map/gitattributes patched for root-level design + test-plan artifacts (idempotent)" >&2 + echo " [v1.38.1.0] allowlist/privacy-map/gitattributes patched for root-level design + test-plan artifacts (idempotent)" >&2 fi # NEVER `git commit + push` from this migration. The user controls when the diff --git a/package.json b/package.json index d2a4a20d5..4922a37e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gstack", - "version": "1.38.0.0", + "version": "1.38.1.0", "description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.", "license": "MIT", "type": "module", diff --git a/test/artifacts-init-migration.test.ts b/test/artifacts-init-migration.test.ts index fdf449523..e2f27f444 100644 --- a/test/artifacts-init-migration.test.ts +++ b/test/artifacts-init-migration.test.ts @@ -1,4 +1,4 @@ -// Unit tests for gstack-upgrade/migrations/v1.38.0.0.sh (#1452). +// Unit tests for gstack-upgrade/migrations/v1.38.1.0.sh (#1452). // Verifies idempotent in-place repair of .brain-allowlist, // .brain-privacy-map.json, and .gitattributes. @@ -8,7 +8,7 @@ import { tmpdir } from 'os'; import { join } from 'path'; const REPO_ROOT = new URL('..', import.meta.url).pathname; -const MIGRATION = join(REPO_ROOT, 'gstack-upgrade', 'migrations', 'v1.38.0.0.sh'); +const MIGRATION = join(REPO_ROOT, 'gstack-upgrade', 'migrations', 'v1.38.1.0.sh'); function setupFakeHome(): string { const dir = mkdtempSync(join(tmpdir(), 'mig-v1340-')); @@ -30,7 +30,7 @@ function runMigration(fakeHome: string): { code: number; stdout: string; stderr: }; } -describe('v1.38.0.0 migration', () => { +describe('v1.38.1.0 migration', () => { test('adds patterns to allowlist before USER ADDITIONS marker', () => { const home = setupFakeHome(); try { @@ -166,7 +166,7 @@ describe('v1.38.0.0 migration', () => { writeFileSync(join(home, '.gstack', '.brain-allowlist'), '# ---- USER ADDITIONS BELOW\n'); runMigration(home); // Confirm marker file exists - expect(existsSync(join(home, '.gstack', '.migrations', 'v1.38.0.0.done'))).toBe(true); + expect(existsSync(join(home, '.gstack', '.migrations', 'v1.38.1.0.done'))).toBe(true); // Modify allowlist so we can detect if the migration would re-run writeFileSync(join(home, '.gstack', '.brain-allowlist'), '# minimal\n');