mirror of https://github.com/garrytan/gstack.git
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 <noreply@anthropic.com>
This commit is contained in:
parent
4cb406ca77
commit
66c8a55dbb
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
Loading…
Reference in New Issue