252 Commits

Author SHA1 Message Date
Garry Tan dae251e066 feat: team-friendly gstack install mode (v0.15.7.0) (#809)
* feat: add gstack-settings-hook for atomic Claude Code hook management

DRY helper for adding/removing SessionStart hooks in ~/.claude/settings.json.
Handles missing files, deduplication, malformed JSON, and atomic writes
(.tmp + rename) to prevent corruption on crash or disk-full.

Part of team-install-mode feature (credit: Jared Friedman).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add gstack-session-update for automatic team updates

SessionStart hook target that auto-updates gstack at session start.
Background fork (zero latency), throttled to once/hour, with lockfile
(mkdir + PID), stale lock recovery, GIT_TERMINAL_PROMPT=0, and debug
logging to ~/.gstack/analytics/session-update.log.

Part of team-install-mode feature (credit: Jared Friedman).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add --team, --no-team, -q flags to setup

--team enables auto_upgrade and registers SessionStart hook via
gstack-settings-hook. --no-team reverses it. -q/--quiet suppresses
all informational output (for hook-triggered setup runs). --local
now prints a deprecation warning.

Replaces ~20 echo calls with log() helper for quiet mode support.

Part of team-install-mode feature (credit: Jared Friedman).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add gstack-team-init for repo-level team bootstrapping

Two modes: 'optional' (gentle CLAUDE.md suggestion) and 'required'
(CLAUDE.md enforcement + .claude/hooks/check-gstack.sh PreToolUse hook
that blocks work without gstack installed). Atomic JSON writes,
idempotent, prints git add instructions.

Part of team-install-mode feature (credit: Jared Friedman).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: deprecate vendoring, document team mode, clean up uninstall

- README: replace "Step 2: Add to your repo" vendoring instructions
  with team mode (./setup --team + gstack-team-init)
- CLAUDE.md: rename "Vendored symlink awareness" to "Dev symlink
  awareness", add deprecation note
- CONTRIBUTING.md: remove vendoring language from prefix section
- bin/gstack-uninstall: clean up SessionStart hook on uninstall

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add vendoring deprecation detection to skill preamble

Detects vendored gstack in CWD (.claude/skills/gstack/ that's not a
symlink and has VERSION or .git). Outputs VENDORED_GSTACK: yes/no.
Adds generateVendoringDeprecation() section that offers one-time
migration to team mode via AskUserQuestion.

Part of team-install-mode feature (credit: Jared Friedman).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: regenerate SKILL.md files with vendoring deprecation preamble

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: team mode (v0.15.7.0) — credit Jared Friedman

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: add integration tests for team mode (20 tests)

Covers gstack-settings-hook (add, remove, dedup, preserve existing,
atomic write), gstack-session-update (guards, throttle, non-fatal),
gstack-team-init (optional, required, enforcement hook, idempotent),
and setup flags (-q, --local deprecation).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 23:49:03 -07:00
Garry Tan a94a64f821 fix: snapshot -i auto-detects dropdown/popover interactive elements (#845)
* fix: snapshot -i auto-detects dropdown/popover interactive elements

- Auto-enable cursor-interactive scan (-C) when -i flag is used
- Add floating container detection (portals, popovers, dropdowns)
  - Detects position:fixed/absolute with high z-index
  - Recognizes data-floating-ui-portal, data-radix-* attributes
  - Recognizes role=listbox, role=menu containers
- Elements inside floating containers bypass the hasRole skip
  - Catches dropdown items missed by the accessibility tree
- Role=option/menuitem elements in floating containers captured
  even without cursor:pointer/onclick
- Tag floating container items with 'popover-child' reason
- Include role name in @c ref reasons when present
- Add dropdown.html test fixture
- Add dropdown/popover detection test suite (6 tests)
- Add test: -i alone includes cursor-interactive elements

Fixes: Bookface autocomplete, Radix UI combobox, React portals,
and similar dynamic dropdown patterns where ariaSnapshot() misses
the floating content.

* chore: bump version and changelog (v0.15.12.0)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: update snapshot -i/-C flag descriptions to mention auto-enable behavior

* test: strengthen clickability test guard assertions

The @c ref clickability test previously used if-guards that would
silently pass when no Alice line was found in the snapshot output.
Both Claude and Codex adversarial review flagged this as a test that
could regress without CI noticing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: regenerate top-level SKILL.md with updated flag descriptions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: root <root@localhost>
Co-authored-by: gstack <ship@gstack.dev>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 22:57:45 -07:00
root 237ae2abbe Revert "fix: snapshot -i auto-detects dropdown/popover interactive elements (#844)"
This reverts commit 542e7836d0.
2026-04-06 03:27:13 +00:00
Garry Tan 542e7836d0 fix: snapshot -i auto-detects dropdown/popover interactive elements (#844)
- Auto-enable cursor-interactive scan (-C) when -i flag is used
- Add floating container detection (portals, popovers, dropdowns)
  - Detects position:fixed/absolute with high z-index
  - Recognizes data-floating-ui-portal, data-radix-* attributes
  - Recognizes role=listbox, role=menu containers
- Elements inside floating containers bypass the hasRole skip
  - Catches dropdown items missed by the accessibility tree
- Role=option/menuitem elements in floating containers captured
  even without cursor:pointer/onclick
- Tag floating container items with 'popover-child' reason
- Include role name in @c ref reasons when present
- Add dropdown.html test fixture
- Add dropdown/popover detection test suite (6 tests)
- Add test: -i alone includes cursor-interactive elements

Fixes: Bookface autocomplete, Radix UI combobox, React portals,
and similar dynamic dropdown patterns where ariaSnapshot() misses
the floating content.

Co-authored-by: root <root@localhost>
2026-04-05 20:25:12 -07:00
Garry Tan 422f172fbb feat: ship re-run executes all verification checks (v0.15.10.0) (#833)
* feat: review army idempotency + cross-review dedup resolver

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: ship re-run executes all checks, adds review army + dedup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: regression guards for ship specialist dispatch + dedup + idempotency

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.15.10.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 11:43:13 -07:00
Garry Tan b3cd3fd68b feat: native OpenClaw skills + ClaHub publishing (v0.15.10.0) (#832)
* feat: add 4 native OpenClaw skills for ClaHub publishing

Hand-crafted methodology skills for the OpenClaw wintermute workspace:
- gstack-openclaw-office-hours (375 lines) — 6 forcing questions, startup + builder modes
- gstack-openclaw-ceo-review (193 lines) — 4 scope modes, 18 cognitive patterns
- gstack-openclaw-investigate (136 lines) — Iron Law, 4-phase debugging
- gstack-openclaw-retro (301 lines) — git analytics, per-person praise/growth

Pure methodology, no gstack infrastructure. All frontmatter uses single-line
inline JSON for OpenClaw parser compatibility.

* feat: add AGENTS.md dispatch section with behavioral rules

Ready-to-paste section for OpenClaw AGENTS.md with 3 iron-clad rules:
1. Always spawn sessions, never redirect user to Claude Code
2. Resolve repo path or ask, don't punt
3. Autoplan runs end-to-end, reports back in chat

Includes full dispatch routing (Simple/Medium/Heavy/Full/Plan tiers).

* chore: clear OpenClaw includeSkills — native skills replace generated

Native ClaHub skills replace the gen-skill-docs pipeline output for
these 4 skills. Updated test to validate empty includeSkills array.

* docs: ClaHub install instructions + dispatch routing rules

- README: add Native OpenClaw Skills section with clawhub install command
- OPENCLAW.md: update dispatch routing with behavioral rules, update
  native skills section to reference ClaHub

* chore: bump version and changelog (v0.15.10.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add gstack-upgrade to OpenClaw dispatch routing

Ensures "upgrade gstack" routes to a Claude Code session with
/gstack-upgrade instead of Wintermute trying to handle it conversationally.

* fix: stop tracking 58MB compiled binary bin/gstack-global-discover

Already in .gitignore but was tracked due to historical mistake.
Same issue as browse/dist/ and design/dist/. The .ts source is right
next to it and ./setup builds from source for every platform.

* test: detect compiled binaries and large files tracked by git

Two new tests in skill-validation:
- No Mach-O or ELF binaries tracked (catches accidental git add of compiled output)
- No files over 2MB tracked (catches bloated binaries sneaking in)

Both print the exact git rm --cached command to fix the issue.

* fix: ClaHub → ClawHub (correct spelling)

* docs: add ClawHub publishing instructions to CLAUDE.md

Documents the clawhub publish command (not clawhub skill publish),
auth flow, version bumping, and verification.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 10:07:03 -07:00
Garry Tan bd8d44d641 docs: rewrite README OpenClaw install — one paste, real instructions (#818)
OpenClaw section promoted to peer of Claude Code install. Single copy-paste
prompt that installs gstack for Claude Code AND wires up AGENTS.md dispatch.
Usage table shows what happens when you talk naturally. Other agents collapsed
from repeated git clones into one auto-detect command + table. Voice input
moved after 10-15 parallel sprints section.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:34:02 -07:00
Garry Tan e2d005c7f4 feat: OpenClaw integration v2 — prompt is the bridge (v0.15.9.0) (#816)
* feat: add includeSkills to HostConfig + update OpenClaw config

Add includeSkills allowlist field with union logic (include minus skip).
Update OpenClaw to generate only 4 native methodology skills (office-hours,
plan-ceo-review, investigate, retro). Remove staticFiles.SOUL.md reference
(pointed to non-existent file).

* feat: OpenClaw integration — gstack-lite/full generation + spawned session detection

Add includeSkills filter to gen-skill-docs pipeline. Generate gstack-lite
(planning discipline for spawned coding sessions) and gstack-full (complete
feature pipeline) for OpenClaw host. Add OPENCLAW_SESSION env var detection
in preamble for spawned session auto-detect. Update setup --host openclaw
to print redirect message.

* docs: OpenClaw architecture doc + regenerate all SKILL.md with spawned session detection

Add docs/OPENCLAW.md with 4-tier dispatch routing and integration architecture.
Generate gstack-lite and gstack-full prompt templates. Regenerate all SKILL.md
files with OPENCLAW_SESSION env var check in preamble.

* test: update golden baselines + OpenClaw includeSkills tests

Update golden SKILL.md baselines for preamble SPAWNED_SESSION change.
Replace staticFiles SOUL.md test with includeSkills validation.

* chore: bump version and changelog (v0.15.9.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: remove all Wintermute references from source files

Replace with generic "orchestrator" or "OpenClaw" as appropriate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add Plan dispatch tier — full review gauntlet for Claude Code project planning

New gstack-plan template chains /office-hours → /autoplan (CEO + eng + design + DX
+ codex adversarial), saves the reviewed plan, and reports back to the orchestrator.
The orchestrator persists the plan link to its own memory store. 5 tiers now:
Simple, Medium, Heavy, Full, Plan.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:23:59 -07:00
Garry Tan 2b08cfe71e fix: close redundant PRs + friendly error on all design commands (v0.15.8.1) (#817)
* fix: friendly OpenAI org error on all design commands

Previously only generate.ts showed a user-friendly message when the
OpenAI org wasn't verified. Now evolve, iterate, variants, and check
all detect the 403 + "organization must be verified" pattern and show
a clear message with the correct verification URL.

* test: regression test for >128KB Codex session_meta

Documents the current 128KB buffer limitation. When Codex embeds
session_meta beyond 128KB, this test will fail, signaling the need
for a streaming parse or larger buffer.

* chore: bump version and changelog (v0.15.8.1)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 02:02:06 -07:00
Diego Sens 1652f224c7 fix(discover): parse Codex sessions with large session_meta (>4KB) (#798)
Merged via PR triage plan. Fixes Codex session discovery for v0.117+ with 15KB+ session_meta. Follow-up: add >128KB regression test.
2026-04-05 00:09:35 -07:00
Matt Van Horn f91ad61a15 fix: user-friendly error when OpenAI org is not verified (#776)
Merged via PR triage plan. Friendly error for unverified OpenAI org. Follow-up: expand to evolve.ts, iterate.ts, variants.ts, check.ts.
2026-04-05 00:09:32 -07:00
Garry Tan 9ca8f1d7a9 feat: adaptive gating + cross-review dedup for review army (v0.15.2.0) (#760)
* feat: add test_stub optional field to specialist finding schema

All specialist prompts now document test_stub as an optional output field,
enabling specialists to suggest test code alongside findings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: adaptive gating + test framework detection for review army

Adds gstack-specialist-stats binary for tracking specialist hit rates.
Resolver now detects test framework for test_stub generation, applies
adaptive gating to skip silent specialists, and compiles per-specialist
stats for the review-log entry.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: cross-review finding dedup + test stub override + enriched review-log

Step 5.0 suppresses findings previously skipped by the user when the
relevant code hasn't changed. Test stub findings force ASK classification
so users approve test creation. Review-log now includes quality_score,
per-specialist stats, and per-finding action records.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.15.2.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: bash operator precedence in test framework detection

[ -f a ] || [ -f b ] && X="y" evaluates as A || (B && C), so the
assignment only runs when the second test passes. Wrap the OR group
in braces: { [ -f a ] || [ -f b ]; } && X="y".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 22:46:21 -07:00
Garry Tan 115d81d792 fix: security wave 1 — 14 fixes for audit #783 (v0.15.7.0) (#810)
* fix: DNS rebinding protection checks AAAA (IPv6) records too

Cherry-pick PR #744 by @Gonzih. Closes the IPv6-only DNS rebinding gap
by checking both A and AAAA records independently.

Co-Authored-By: Gonzih <gonzih@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: validateOutputPath symlink bypass — resolve real path before safe-dir check

Cherry-pick PR #745 by @Gonzih. Adds a second pass using fs.realpathSync()
to resolve symlinks after lexical path validation.

Co-Authored-By: Gonzih <gonzih@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: validate saved URLs before navigation in restoreState

Cherry-pick PR #751 by @Gonzih. Prevents navigation to cloud metadata
endpoints or file:// URIs embedded in user-writable state files.

Co-Authored-By: Gonzih <gonzih@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: telemetry-ingest uses anon key instead of service role key

Cherry-pick PR #750 by @Gonzih. The service role key bypasses RLS and
grants unrestricted database access — anon key + RLS is the right model
for a public telemetry endpoint.

Co-Authored-By: Gonzih <gonzih@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: killAgent() actually kills the sidebar claude subprocess

Cherry-pick PR #743 by @Gonzih. Implements cross-process kill signaling
via kill-file + polling pattern, tracks active processes per-tab.

Co-Authored-By: Gonzih <gonzih@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(design): bind server to localhost and validate reload paths

Cherry-pick PR #803 by @garagon. Adds hostname: '127.0.0.1' to Bun.serve()
and validates /api/reload paths are within cwd() or tmpdir(). Closes C1+C2
from security audit #783.

Co-Authored-By: garagon <garagon@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add auth gate to /inspector/events SSE endpoint (C3)

The /inspector/events endpoint had no authentication, unlike /activity/stream
which validates tokens. Now requires the same Bearer header or ?token= query
param check. Closes C3 from security audit #783.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: sanitize design feedback with trust boundary markers (C4+H5)

Wrap user feedback in <user-feedback> XML markers with tag escaping to
prevent prompt injection via malicious feedback text. Cap accumulated
feedback to last 5 iterations to limit incremental poisoning.
Closes C4 and H5 from security audit #783.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: harden file/directory permissions to owner-only (C5+H9+M9+M10)

Add mode 0o700 to all mkdirSync calls for state/session directories.
Add mode 0o600 to all writeFileSync calls for session.json, chat.jsonl,
and log files. Add umask 077 to setup script. Prevents auth tokens, chat
history, and browser logs from being world-readable on multi-user systems.
Closes C5, H9, M9, M10 from security audit #783.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: TOCTOU race in setup symlink creation (C6)

Remove the existence check before mkdir -p (it's idempotent) and validate
the target isn't already a symlink before creating the link. Prevents a
local attacker from racing between the check and mkdir to redirect
SKILL.md writes. Closes C6 from security audit #783.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: remove CORS wildcard, restrict to localhost (H1)

Replace Access-Control-Allow-Origin: * with http://127.0.0.1 on sidebar
tab/chat endpoints. The Chrome extension uses manifest host_permissions
to bypass CORS entirely, so this only blocks malicious websites from
making cross-origin requests. Closes H1 from security audit #783.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: make cookie picker auth mandatory (H2)

Remove the conditional if(authToken) guard that skipped auth when
authToken was undefined. Now all cookie picker data/action routes
reject unauthenticated requests. Closes H2 from security audit #783.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: gate /health token on chrome-extension Origin header

Only return the auth token in /health response when the request Origin
starts with chrome-extension://. The Chrome extension always sends this
origin via manifest host_permissions. Regular HTTP requests (including
tunneled ones from ngrok/SSH) won't get the token. The extension also
has a fallback path through background.js that reads the token from the
state file directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: update server-auth test for chrome-extension Origin gating

The test previously checked for 'localhost-only' comment. Now checks for
'chrome-extension://' since the token is gated on Origin header.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.15.7.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Gonzih <gonzih@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: garagon <garagon@users.noreply.github.com>
2026-04-04 22:12:04 -07:00
Garry Tan 31943b2f02 feat: anti-skip rule for all review skills (v0.15.6.1) (#804)
* feat: anti-skip rule for all review skills

Review skills sometimes skip sections when reviewing strategy or spec
plans. This adds an explicit anti-skip rule to CEO (1-11), eng (1-4),
design (1-7), and DX (1-8) review skills. Also fixes CEO header from
"10 sections" to "11 sections" to match actual count.

* chore: bump version and changelog (v0.15.6.1)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 21:22:40 -07:00
Garry Tan 8038cad4a7 fix: self-healing skill prefix consistency in setup (#805)
* fix: self-healing gstack-relink after setup to prevent skill prefix drift

Setup now runs gstack-relink as a final consistency check after linking
Claude skills. This independently reads skill_prefix from config and
ensures name: fields and directory names match, catching cases where
interrupted setups or stale state left skills incorrectly prefixed.

* chore: bump version and changelog (v0.15.6.1)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 20:59:32 -07:00
Garry Tan 04b709d91a feat: declarative multi-host platform + OpenCode, Slate, Cursor, OpenClaw (v0.15.5.0) (#793)
* test: add golden-file baselines for host config refactor

Snapshot generated SKILL.md output for ship skill across all 3 existing
hosts (Claude, Codex, Factory). These baselines verify the config-driven
refactor produces identical output to the current hardcoded system.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add HostConfig interface and validator for declarative host system

New scripts/host-config.ts defines the typed HostConfig interface that
captures all per-host variation: paths, frontmatter rules, path/tool
rewrites, suppressed resolvers, runtime root symlinks, install strategy,
and behavioral config (co-author trailer, learnings mode, boundary
instruction). Includes validateHostConfig() and validateAllConfigs() with
regex-based security validation and cross-config uniqueness checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add typed host configs for Claude, Codex, Factory, and Kiro

Extract all hardcoded host-specific values from gen-skill-docs.ts,
types.ts, preamble.ts, review.ts, and setup into typed HostConfig
objects. Each host is a single file in hosts/ with its paths, frontmatter
rules, path/tool rewrites, runtime root manifest, and install behavior.

hosts/index.ts exports all configs, derives the Host type, and provides
resolveHostArg() for CLI alias handling (e.g., 'agents' -> 'codex',
'droid' -> 'factory').

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: derive Host type and HOST_PATHS from host configs

types.ts no longer hardcodes host names or paths. The Host type is
derived from ALL_HOST_CONFIGS in hosts/index.ts, and HOST_PATHS is
built dynamically from each config's globalRoot/localSkillRoot/usesEnvVars.
Adding a new host to hosts/index.ts automatically extends the type system.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: gen-skill-docs.ts consumes typed host configs

Replace hardcoded EXTERNAL_HOST_CONFIG, transformFrontmatter host
branches, path/tool rewrite if-chains, and ALL_HOSTS array with
config-driven lookups from hosts/*.ts.

- Host detection uses resolveHostArg() (handles aliases like agents/droid)
- transformFrontmatter uses config's allowlist/denylist mode, extraFields,
  conditionalFields, renameFields, and descriptionLimitBehavior
- Path rewrites use config's pathRewrites array (replaceAll, order matters)
- Tool rewrites use config's toolRewrites object
- Skill skipping uses config's generation.skipSkills
- ALL_HOSTS derived from ALL_HOST_NAMES
- Token budget display regex derived from host configs

Golden-file comparison: all 3 hosts produce IDENTICAL output to baselines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: preamble, co-author trailer, and resolver suppression use host configs

- preamble.ts: hostConfigDir derived from config.globalRoot instead of
  hardcoded Record
- utility.ts: generateCoAuthorTrailer reads from config.coAuthorTrailer
  instead of host switch statement
- gen-skill-docs.ts: suppressedResolvers from config skip resolver
  execution at placeholder replacement time (belt+suspenders with
  existing ctx.host checks in individual resolvers)

Golden-file comparison: all 3 hosts produce IDENTICAL output to baselines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: setup tooling uses config-driven host detection

- host-config-export.ts: new CLI that exposes host configs to bash
  (list, get, detect, validate, symlinks commands)
- bin/gstack-platform-detect: reads host configs instead of hardcoded
  binary/path mapping
- scripts/skill-check.ts: iterates host configs for skill validation
  and freshness checks instead of separate Codex/Factory blocks
- lib/worktree.ts: iterates host configs for directory copy instead
  of hardcoded .agents

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add OpenCode, Slate, and Cursor host configs

Three new hosts added to the declarative config system. Each is a typed
HostConfig object with paths, frontmatter rules, and path rewrites.
All generate valid SKILL.md output with zero .claude/skills path leakage.

- hosts/opencode.ts: OpenCode (opencode.ai), skills at ~/.config/opencode/
- hosts/slate.ts: Slate (Random Labs), skills at ~/.slate/
- hosts/cursor.ts: Cursor, skills at ~/.cursor/
- .gitignore: add .kiro/, .opencode/, .slate/, .cursor/, .openclaw/

Zero code changes needed — just config files + re-export in index.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add OpenClaw host config with adapter for tool mapping

OpenClaw gets a hybrid approach: typed config for paths/frontmatter/
detection + a post-processing adapter for semantic tool rewrites.

Config handles: path rewrites, frontmatter (name+description+version),
CLAUDE.md→AGENTS.md, tool name rewrites (Bash→exec, Read→read, etc.),
suppressed resolvers, SOUL.md via staticFiles.

Adapter handles: AskUserQuestion→prose, Agent→sessions_spawn, $B→exec $B.

Zero .claude/skills path leakage. Zero hardcoded tool references remaining.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: contributor add-host skill + fix version sync

- contrib/add-host/SKILL.md.tmpl: contributor-only skill that guides
  new host config creation. Lives in contrib/, excluded from user installs.
- package.json: sync version with VERSION file (0.15.2.1)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add parameterized host smoke tests for all hosts

35 new tests covering all 7 external hosts (Codex, Factory, Kiro,
OpenCode, Slate, Cursor, OpenClaw). Each host gets 4-5 tests:
- output exists on disk with SKILL.md files
- no .claude/skills path leakage in non-root skills
- frontmatter has name + description fields
- --dry-run freshness check passes
- /codex skill excluded (for hosts with skipSkills: ['codex'])

Tests are parameterized over ALL_HOST_CONFIGS so adding a new host
automatically gets smoke-tested with zero new test code.

Also updates --host all test to verify all registered hosts generate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: 100% coverage for host config system

71 new tests in test/host-config.test.ts covering:
- hosts/index.ts: ALL_HOST_CONFIGS, getHostConfig, resolveHostArg (aliases),
  getExternalHosts, uniqueness checks
- host-config.ts validateHostConfig: name regex, displayName, cliCommand,
  cliAliases, globalRoot, localSkillRoot, hostSubdir, frontmatter.mode,
  linkingStrategy, shell injection attempts, paths with $ and ~
- host-config.ts validateAllConfigs: duplicate name/hostSubdir/globalRoot
  detection, error prefix format, real configs pass
- HOST_PATHS derivation: env vars for external hosts, literal paths for
  Claude, localSkillRoot matches config, every host has entry
- host-config-export.ts CLI: list, get (string/boolean/array), detect,
  validate, symlinks, error cases (missing args, unknown field/host)
- Golden-file regression: claude/codex/factory ship SKILL.md vs baselines
- Individual host config correctness: prefixable, linkingStrategy,
  usesEnvVars, description limits, metadata, sidecar, tool rewrites,
  conditional fields, suppressed resolvers, boundary instruction,
  co-author trailers, skip rules, path rewrites, runtime root assets

Combined with the 35 parameterized smoke tests from gen-skill-docs.test.ts,
total new test coverage for multi-host: 106 tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update golden baselines and sync version after merge from main

Golden files refreshed to match post-merge generated output. package.json
version synced to VERSION file (0.15.4.0).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump version and changelog (v0.15.5.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: sidebar E2E tests now self-contained and passing

- sidebar-url-accuracy: fix stale assertion that expected extensionUrl
  in prompt text (prompt format changed, URL is now in pageUrl field)
- sidebar-css-interaction: simplify task from multi-step HN comment
  navigation to single-page example.com style injection (faster, more
  reliable, still exercises goto + style + completion flow)
- Update golden baselines after merge from main

All 3 sidebar tests now pass: 3/3, 0 fail, ~36s total.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add ADDING_A_HOST.md guide + update docs for multi-host system

- docs/ADDING_A_HOST.md: step-by-step guide for adding a new host
  (create config, register, gitignore, generate, test). Covers the
  full HostConfig interface, adapter pattern, and validation.
- CONTRIBUTING.md: replace stale "Dual-host development" section with
  "Multi-host development" covering all 8 hosts and linking to the guide.
- README.md: consolidate Codex/Factory install sections into one
  "Other AI Agents" section listing all supported hosts with auto-detect.
- CLAUDE.md: add hosts/, host-config.ts, host-adapters/, contrib/ to
  project structure tree.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: README per-host install instructions for all 8 agents

Each supported agent now has its own copy-paste install block with
the exact command and where skills end up on disk. Includes: auto-detect,
Codex, OpenCode, Cursor, Factory, OpenClaw, Slate, and Kiro.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 15:32:20 -07:00
Garry Tan 447851452a feat: interactive /plan-devex-review + plan mode skill fix (v0.15.5.0) (#796)
* fix: skill invocation during plan mode takes precedence over generic plan mode

Adds a "Skill Invocation During Plan Mode" section to the preamble resolver so
all generated SKILL.md files include it. Fixes a bug where Claude treats loaded
skill content as reference material instead of executable instructions, and keeps
trying to ExitPlanMode instead of following the skill workflow step by step.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: interactive /plan-devex-review with persona, benchmarks, and forcing questions

Complete rewrite of the DX review skill to match CEO/eng review depth. New flow:
investigate (persona, empathy, competitors, magical moment, journey tracing) then
force decisions, then score with evidence. Three modes: DX EXPANSION, DX POLISH,
DX TRIAGE. 20-45 interactive STOP points vs 10-12 before.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: autoplan DX POLISH mode + review log schema for new devex fields

Adds mode selection, persona, competitive, and magical moment override rules to
autoplan Phase 3.5. Documents new review log fields (mode, persona, competitive_tier)
in the plan-file-review-report schema. Syncs package.json version to VERSION.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update project documentation for v0.15.5.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 14:36:23 -07:00
Garry Tan 3f080de1b7 feat: GStack Browser — double-click AI browser with anti-bot stealth (#695)
* feat: CDP inspector module — persistent sessions, CSS cascade, style modification

New browse/src/cdp-inspector.ts with full CDP inspection engine:
- inspectElement() via CSS.getMatchedStylesForNode + DOM.getBoxModel
- modifyStyle() via CSS.setStyleTexts with headless page.evaluate fallback
- Persistent CDP session lifecycle (create, reuse, detach on nav, re-create)
- Specificity sorting, overridden property detection, UA rule filtering
- Modification history with undo support
- formatInspectorResult() for CLI output

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: browse server inspector endpoints + inspect/style/cleanup/prettyscreenshot CLI

Server endpoints: POST /inspector/pick, GET /inspector, POST /inspector/apply,
POST /inspector/reset, GET /inspector/history, GET /inspector/events (SSE).
CLI commands: inspect (CDP cascade), style (live CSS mod), cleanup (page clutter
removal), prettyscreenshot (clean screenshot pipeline).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: sidebar CSS inspector — element picker, box model, rule cascade, quick edit

Extension changes for the visual CSS inspector:
- inspector.js: element picker with hover highlight, CSS selector generation,
  basic mode fallback (getComputedStyle + CSSOM), page alteration handlers
- inspector.css: picker overlay styles (blue highlight + tooltip)
- background.js: inspector message routing (picker <-> server <-> sidepanel)
- sidepanel: Inspector tab with box model viz (gstack palette), matched rules
  with specificity badges, computed styles, click-to-edit quick edit,
  Send to Agent/Code button, empty/loading/error states

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: document inspect, style, cleanup, prettyscreenshot browse commands

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: auto-track user-created tabs and handle tab close

browser-manager.ts changes:
- context.on('page') listener: automatically tracks tabs opened by the user
  (Cmd+T, right-click open in new tab, window.open). Previously only
  programmatic newTab() was tracked, so user tabs were invisible.
- page.on('close') handler in wirePageEvents: removes closed tabs from the
  pages map and switches activeTabId to the last remaining tab.
- syncActiveTabByUrl: match Chrome extension's active tab URL to the correct
  Playwright page for accurate tab identity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: per-tab agent isolation via BROWSE_TAB environment variable

Prevents parallel sidebar agents from interfering with each other's tab context.

Three-layer fix:
- sidebar-agent.ts: passes BROWSE_TAB=<tabId> env var to each claude process,
  per-tab processing set allows concurrent agents across tabs
- cli.ts: reads process.env.BROWSE_TAB and includes tabId in command request body
- server.ts: handleCommand() temporarily switches activeTabId when tabId is present,
  restores after command completes (safe: Bun event loop is single-threaded)

Also: per-tab agent state (TabAgentState map), per-tab message queuing,
per-tab chat buffers, verbose streaming narration, stop button endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: sidebar per-tab chat context, tab bar sync, stop button, UX polish

Extension changes:
- sidepanel.js: per-tab chat history (tabChatHistories map), switchChatTab()
  swaps entire chat view, browserTabActivated handler for instant tab sync,
  stop button wired to /sidebar-agent/stop, pollTabs renders tab bar
- sidepanel.html: updated banner text ("Browser co-pilot"), stop button markup,
  input placeholder "Ask about this page..."
- sidepanel.css: tab bar styles, stop button styles, loading state fixes
- background.js: chrome.tabs.onActivated sends browserTabActivated to sidepanel
  with tab URL for instant tab switch detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: per-tab isolation, BROWSE_TAB pinning, tab tracking, sidebar UX

sidebar-agent.test.ts (new tests):
- BROWSE_TAB env var passed to claude process
- CLI reads BROWSE_TAB and sends tabId in body
- handleCommand accepts tabId, saves/restores activeTabId
- Tab pinning only activates when tabId provided
- Per-tab agent state, queue, concurrency
- processingTabs set for parallel agents

sidebar-ux.test.ts (new tests):
- context.on('page') tracks user-created tabs
- page.on('close') removes tabs from pages map
- Tab isolation uses BROWSE_TAB not system prompt hack
- Per-tab chat context in sidepanel
- Tab bar rendering, stop button, banner text

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: resolve merge conflicts — keep security defenses + per-tab isolation

Merged main's security improvements (XML escaping, prompt injection defense,
allowed commands whitelist, --model opus, Write tool, stderr capture) with
our branch's per-tab isolation (BROWSE_TAB env var, processingTabs set,
no --resume). Updated test expectations for expanded system prompt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.9.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add inspector message types to background.js allowlist

Pre-existing bug found by Codex: ALLOWED_TYPES in background.js was missing
all inspector message types (startInspector, stopInspector, elementPicked,
pickerCancelled, applyStyle, toggleClass, injectCSS, resetAll, inspectResult).
Messages were silently rejected, making the inspector broken on ALL pages.

Also: separate executeScript and insertCSS into individual try blocks in
injectInspector(), store inspectorMode for routing, and add content.js
fallback when script injection fails (CSP, chrome:// pages).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: basic element picker in content.js for CSP-restricted pages

When inspector.js can't be injected (CSP, chrome:// pages), content.js
provides a basic picker using getComputedStyle + CSSOM:
- startBasicPicker/stopBasicPicker message handlers
- captureBasicData() with ~30 key CSS properties, box model, matched rules
- Hover highlight with outline save/restore (never leaves artifacts)
- Click uses e.target directly (no re-querying by selector)
- Sends inspectResult with mode:'basic' for sidebar rendering
- Escape key cancels picker and restores outlines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: cleanup + screenshot buttons in sidebar inspector toolbar

Two action buttons in the inspector toolbar:
- Cleanup (🧹): POSTs cleanup --all to server, shows spinner, chat
  notification on success, resets inspector state (element may be removed)
- Screenshot (📸): POSTs screenshot to server, shows spinner, chat
  notification with saved file path

Shared infrastructure:
- .inspector-action-btn CSS with loading spinner via ::after pseudo-element
- chat-notification type in addChatEntry() for system messages
- package.json version bump to 0.13.9.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: inspector allowlist, CSP fallback, cleanup/screenshot buttons

16 new tests in sidebar-ux.test.ts:
- Inspector message allowlist includes all inspector types
- content.js basic picker (startBasicPicker, captureBasicData, CSSOM,
  outline save/restore, inspectResult with mode basic, Escape cleanup)
- background.js CSP fallback (separate try blocks, inspectorMode, fallback)
- Cleanup button (POST /command, inspector reset after success)
- Screenshot button (POST /command, notification rendering)
- Chat notification type and CSS styles

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update project documentation for v0.13.9.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: cleanup + screenshot buttons in chat toolbar (not just inspector)

Quick actions toolbar (🧹 Cleanup, 📸 Screenshot) now appears above the chat
input, always visible. Both inspector and chat buttons share runCleanup() and
runScreenshot() helper functions. Clicking either set shows loading state on
both simultaneously.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: chat toolbar buttons, shared helpers, quick-action-btn styles

Tests that chat toolbar exists (chat-cleanup-btn, chat-screenshot-btn,
quick-actions container), CSS styles (.quick-action-btn, .quick-action-btn.loading),
shared runCleanup/runScreenshot helper functions, and cleanup inspector reset.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: aggressive cleanup heuristics — overlays, scroll unlock, blur removal

Massively expanded CLEANUP_SELECTORS with patterns from uBlock Origin and
Readability.js research:
- ads: 30+ selectors (Google, Amazon, Outbrain, Taboola, Criteo, etc.)
- cookies: OneTrust, Cookiebot, TrustArc, Quantcast + generic patterns
- overlays (NEW): paywalls, newsletter popups, interstitials, push prompts,
  app download banners, survey modals
- social: follow prompts, share tools
- Cleanup now defaults to --all when no args (sidebar button fix)
- Uses !important on all display:none (overrides inline styles)
- Unlocks body/html scroll (overflow:hidden from modal lockout)
- Removes blur/filter effects (paywall content blur)
- Removes max-height truncation (article teaser truncation)
- Collapses empty ad placeholder whitespace (empty divs after ad removal)
- Skips gstack-ctrl indicator in sticky removal

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: disable action buttons when disconnected, no error spam

- setActionButtonsEnabled() toggles .disabled class on all cleanup/screenshot
  buttons (both chat toolbar and inspector toolbar)
- Called with false in updateConnection when server URL is null
- Called with true when connection established
- runCleanup/runScreenshot silently return when disconnected instead of
  showing 'Not connected' error notifications
- CSS .disabled style: pointer-events:none, opacity:0.3, cursor:not-allowed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: cleanup heuristics, button disabled state, overlay selectors

17 new tests:
- cleanup defaults to --all on empty args
- CLEANUP_SELECTORS overlays category (paywall, newsletter, interstitial)
- Major ad networks in selectors (doubleclick, taboola, criteo, etc.)
- Major consent frameworks (OneTrust, Cookiebot, TrustArc, Quantcast)
- !important override for inline styles
- Scroll unlock (body overflow:hidden)
- Blur removal (paywall content blur)
- Article truncation removal (max-height)
- Empty placeholder collapse
- gstack-ctrl indicator skip in sticky cleanup
- setActionButtonsEnabled function
- Buttons disabled when disconnected
- No error spam from cleanup/screenshot when disconnected
- CSS disabled styles for action buttons

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: LLM-based page cleanup — agent analyzes page semantically

Instead of brittle CSS selectors, the cleanup button now sends a prompt to
the sidebar agent (which IS an LLM). The agent:
1. Runs deterministic $B cleanup --all as a quick first pass
2. Takes a snapshot to see what's left
3. Analyzes the page semantically to identify remaining clutter
4. Removes elements intelligently, preserving site branding

This means cleanup works correctly on any site without site-specific selectors.
The LLM understands that "Your Daily Puzzles" is clutter, "ADVERTISEMENT" is
junk, but the SF Chronicle masthead should stay.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: aggressive cleanup heuristics + preserve top nav bar

Deterministic cleanup improvements (used as first pass before LLM analysis):
- New 'clutter' category: audio players, podcast widgets, sidebar puzzles/games,
  recirculation widgets (taboola, outbrain, nativo), cross-promotion banners
- Text-content detection: removes "ADVERTISEMENT", "Article continues below",
  "Sponsored", "Paid content" labels and their parent wrappers
- Sticky fix: preserves the topmost full-width element near viewport top (site
  nav bar) instead of hiding all sticky/fixed elements. Sorts by vertical
  position, preserves the first one that spans >80% viewport width.

Tests: clutter category, ad label removal, nav bar preservation logic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: LLM-based cleanup architecture, deterministic heuristics, sticky nav

22 new tests covering:
- Cleanup button uses /sidebar-command (agent) not /command (deterministic)
- Cleanup prompt includes deterministic first pass + agent snapshot analysis
- Cleanup prompt lists specific clutter categories for agent guidance
- Cleanup prompt preserves site identity (masthead, headline, body, byline)
- Cleanup prompt instructs scroll unlock and $B eval removal
- Loading state management (async agent, setTimeout)
- Deterministic clutter: audio/podcast, games/puzzles, recirculation
- Ad label text patterns (ADVERTISEMENT, Sponsored, Article continues)
- Ad label parent wrapper hiding for small containers
- Sticky nav preservation (sort by position, first full-width near top)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: GStack Browser stealth + branding — anti-bot patches, custom UA, rebrand

- Add GSTACK_CHROMIUM_PATH env var for custom Chromium binary
- Add BROWSE_EXTENSIONS_DIR env var for extension path override
- Move auth token to /health endpoint (fixes read-only .app bundles)
- Anti-bot stealth: disable navigator.webdriver, fake plugins, languages
- Custom user agent: Chrome/<version> GStackBrowser (auto-detects version)
- Rebrand Chromium plist to "GStack Browser" at launch time
- Update security test to match new token-via-health approach

* feat: GStack Browser .app bundle — launcher script + build system

- scripts/app/gstack-browser: dual-mode launcher (dev + .app bundle)
- scripts/build-app.sh: compiles binary, bundles Chromium + extension, creates DMG
- Rebrands Chromium plist during build for "GStack Browser" in menu bar
- 389MB .app, 189MB compressed DMG, launches in ~5s

* docs: GStack Browser V0 master plan — AI-native development browser vision

5-phase roadmap from .app wrapper through Chromium fork, 9 capability
visions, competitive landscape, architecture diagrams, design system.

* fix: restore package.json and sync version to 0.14.3.0

* chore: bump version and changelog (v0.14.4.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: gitignore top-level dist/ (GStack Browser build output)

* feat: GStack Browser icon — custom .icns replaces Chromium's Dock icon

- Generated 1024px icon: dark terminal window with amber prompt cursor
- Converted to .icns with all macOS sizes (16-1024px, 1x and 2x)
- build-app.sh copies icon into both the outer .app and bundled Chromium's
  Resources (Chromium's process owns the Dock icon, not the launcher)
- browser-manager.ts patches Chromium's icon at runtime for dev mode too
- Both the Dock and Cmd+Tab now show the GStack icon

* feat: rename /connect-chrome → /open-gstack-browser

- Rename skill directory + update frontmatter name and description
- Update SKILL.md.tmpl to reference GStack Browser branding/stealth
- Create connect-chrome symlink for backwards compatibility
- Setup script creates /connect-chrome alias in .claude/skills/
- Fix package.json version sync (0.14.5.0 → 0.14.6.0)

* feat: rename /connect-chrome → /open-gstack-browser across all references

Update README skill lists, docs/skills.md deep dive, extension sidepanel
banner copy button, and reconnect clipboard text.

* feat: left-align sidebar UI + extension-ready event for welcome page

- Left-align all sidebar text (chat welcome, loading, empty states,
  notifications, inspector empty, session placeholder)
- Dispatch 'gstack-extension-ready' CustomEvent from content.js so
  the welcome page can detect when the sidebar is active

* chore: add GStack Browser TODOs — CDP stealth patches + Chromium fork

P1: rebrowser-style postinstall patcher for Playwright 1.58.2 (suppress
Runtime.enable, addBinding context discovery, 6 files, ~200 lines).
P2: long-term Chromium fork for permanent stealth + native sidebar.

* chore: regenerate open-gstack-browser/SKILL.md from template

Fix timeline skill name (connect-chrome → open-gstack-browser) and
preamble formatting from merge with main's updated template.

* feat: welcome page served from browse server on headed launch

- Add /welcome endpoint to server.ts, serves welcome.html
- Navigate to /welcome after server starts (not during launchHeaded,
  which runs before the server is listening)
- welcome.html bundled in browse/src/ for portability

* feat: auto-open sidebar on every browser launch, not just first install

- Add top-level setTimeout in background.js that fires on every service
  worker startup (onInstalled only fires on install/update)
- Remove misaligned arrow from welcome page, replace with text fallback
  that hides when extension content script fires gstack-extension-ready

* fix: sidebar auto-open retry with backoff + welcome page tests

- Replace single-attempt sidePanel.open() with autoOpenSidePanel() that
  retries up to 5 times with 500ms-5000ms backoff
- Fire on both onInstalled AND every service worker startup
- Remove misaligned arrow from welcome page, replace with text fallback
- Add 12 tests: welcome page structure, /welcome endpoint, headed launch
  navigation timing, sidebar auto-open retry logic, extension-ready event

* feat: reload button in sidebar footer

Adds a "reload" button next to "debug" and "clear" in the sidebar
footer. Calls location.reload() to fully refresh the side panel,
re-run connection logic, and clear stale state.

* feat: right-pointing arrow hint for sidebar on welcome page

Replace invisible text fallback with visible amber bubble + animated
right arrow (→) pointing toward where the sidebar opens. Always correct
regardless of window size (unlike the old up arrow at toolbar chrome).

* fix: sidebar auth race — pass token in getPort response

The sidebar called tryConnect() → getPort → got {port, connected} but
NO token. All subsequent requests (SSE, chat poll) failed with 401.
The token only arrived later via the health broadcast, but by then
the SSE connection was already broken.

Fix: include authToken in the getPort response so the sidebar has
the token from its very first connection attempt.

* feat: sidebar debug visibility + auth race tests

- Show attempt count in loading screen ("Connecting... attempt 3")
- After 5 failed attempts, show debug details (port, connected, token)
  so stuck users can see exactly what's failing
- Add 4 tests: getPort includes token, tryConnect uses token,
  dead state exists with MAX_RECONNECT_ATTEMPTS, reconnectAttempts visible

* fix: startup health check retries every 1s instead of 10s

Root cause: extension service worker starts before Bun.serve() is
listening. First checkHealth() fails, next attempt is 10 seconds
later. User stares at "Connecting..." for 10 seconds.

Fix: retry every 1s for up to 15 attempts on startup, then switch
to 10s polling once connected (or after 15s gives up). Sidebar
should connect within 1-2 seconds of server becoming available.

3 new tests verify the fast-retry → slow-poll transition.

* feat: detailed step-by-step status in sidebar loading screen

Replace useless "Connecting..." with real-time debug info:
- "Looking for browse server... (attempt N)"
- Shows port, server responding status, token status
- Shows chrome.runtime errors if extension messaging fails
- Tells user to run /open-gstack-browser if server not found

* fix: sidebar connects directly to /health instead of waiting for background

Root cause: sidepanel asked background "are you connected?" but background's
health check hadn't succeeded yet (1-10s gap). Sidepanel waited forever.

Fix: when background says not connected, sidepanel hits /health directly
with fetch(). Gets the token from the response. Bypasses background
entirely for initial connection. Shows step-by-step debug info:
"Checking server directly... port: 34567 / Trying GET /health..."

* fix: suppress fake "session ended" and timeout errors in sidebar

Two issues making the sidebar look broken when it's actually working:
1. "Timed out after 300s" error displayed after agent_done — this is a
   cleanup timer, not a real error. Now suppressed when no active session.
2. "(session ended)" text appended on every idle poll — removed entirely.
   The thinking spinner is cleaned up silently instead.

* fix: sidebar agent passes BROWSE_PORT to child claude

Ensures the child claude process connects to the existing headed
browse server (port 34567) instead of spawning a new headless one.
Without this, sidebar chat commands run in an invisible browser.

* feat: BROWSE_NO_AUTOSTART prevents sidebar from spawning headless browser

When set, the browse CLI refuses to start a new server and exits with
a clear error: "Server not available, run /open-gstack-browser to restart."
The sidebar agent sets this so users never get an invisible headless
browser when the headed one is closed.

* test: BROWSE_NO_AUTOSTART guard in CLI + sidebar-agent env vars

5 tests: CLI checks env var before starting server, shows actionable
error, sidebar-agent sets the flag + BROWSE_PORT, guard runs before
lock acquisition to prevent stale lock files.

* fix: stale auth token causes Unauthorized + invisible error text

background.js checkHealth() never refreshed authToken from /health responses,
so when the browse server restarted with a new token, all sidebar-command
requests got 401 Unauthorized forever.

Also: error placeholder text was #3f3f46 on #0C0C0C (nearly invisible).
Now shows in red to match the error border.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: replace 40+ silent catch blocks with debug logging

Every empty catch {} in sidepanel.js, sidebar-agent.ts now logs with
[gstack sidebar] or [sidebar-agent] prefix. Chat poll 401s, stop agent,
tab poll, clear chat, SSE parse, refs fetch, stream JSON parse, queue
read/parse, process kill — all now visible in console.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: noisy debug logging + auto model routing in browse server

Server-side silent catch blocks (22 instances) now log with [browse] prefix:
chat persistence, session save/load, agent kill, tab pin/restore, welcome
page, buffer flush, worktree cleanup, lock files, SSE streams.

Also adds pickSidebarModel() — routes sidebar messages to sonnet for
navigation/interaction (click, goto, fill, screenshot) and opus for
analysis/comprehension (summarize, describe, find bugs). Sonnet is
~4x faster for action commands with zero quality difference.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: update sidebar tests for model router + longer stopAgent slice

- stopAgent slice 800→1000 to accommodate added error logging lines
- Replace hardcoded opus assertion with model router assertions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: sidebar arrow hint stays visible until sidebar actually opens

Previously the welcome page arrow hid immediately when the extension's
content script loaded — but extension loaded ≠ sidebar open. Now the
signal flow is: sidepanel connects → tells background.js → relays to
content script → dispatches gstack-extension-ready → arrow hides.

Adds welcome-page.test.ts: 14 tests verifying arrow, branding, feature
cards, dark theme, and auto-hide behavior via real HTTP server.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: arrow hide signal chain (4-step) + stale session-ended assertion

8 new tests verify the sidebarOpened → background → content → welcome
signal chain. Updates stale "(session ended)" test that checked for
text removed in a prior commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: preserve optimistic UI during tab switch on first message

When the user sends a message and the server assigns it to a new tab
(because Chrome's active tab changed), switchChatTab() was blowing away
the optimistic user bubble and thinking dots with a welcome screen.
Now preserves the current DOM if we're mid-send with a thinking indicator.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: sidebar message flow architecture doc + CLAUDE.md pointer

SIDEBAR_MESSAGE_FLOW.md documents the full init timeline, message flow
(user types → claude responds), auth token chain, arrow hint signal
chain, model routing, tab concurrency, and known failure modes.

CLAUDE.md now tells you to read it before touching sidebar files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: sidebar chat resets idle timer + shutdown kills sidebar-agent

Two fixes for the "browser died while chatting" problem:

1. /sidebar-command now calls resetIdleTimer(). Previously only CLI
   commands reset it, so the server would shut down after 30 min even
   while the user was actively chatting in the sidebar.

2. shutdown() now pkills the sidebar-agent daemon. Previously the agent
   survived server shutdown, kept polling a dead server, and spawned
   confused claude processes that auto-started headless browsers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: disable idle timeout in headed mode — browser lives until closed

The 30-minute idle timeout only applies to headless mode now. In headed
mode the user is looking at the Chrome window, so auto-shutdown is wrong.
The browser stays alive until explicit disconnect or window close.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: cookies button in sidebar footer opens cookie picker

One-click cookie import from the sidebar. Navigates the headed browser
to /cookie-picker where you can select which domains to import from
your real Chrome profile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update project documentation for GStack Browser improvements

README.md: updated Real browser mode and sidebar agent sections with
model routing, cookie import button, no idle timeout in headed mode.
Updated skill table entries for /browse and /open-gstack-browser.

docs/skills.md: updated /open-gstack-browser deep dive with model
routing and cookie import details.

GSTACK_BROWSER_V0.md: added 6 new SHIPPED items to implementation
status table (model routing, debug logging, idle timeout, cookie
button, arrow hint, architecture doc).

TODOS.md: marked "Sidebar agent Write tool + error visibility" as
SHIPPED. Added new P2 TODO for direct API calls to eliminate
claude -p startup tax.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add Claude Code terminal example to welcome page TRY IT NOW

Fifth example shows the parent agent workflow: navigate, extract CSS,
write to file. The other four are all sidebar-only. This one shows
co-presence — the Claude Code session that launched the browser can
also control it directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: hide internal tool-result file reads from sidebar activity

Claude reads its own ~/.claude/projects/.../tool-results/ files as
internal plumbing. These showed up as long unreadable paths in the
sidebar. Now: describeToolCall returns empty for tool-result reads,
and the sidebar skips rendering tool_use entries with no description.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: collapse tool calls into "See reasoning" disclosure on completion

While the agent is working, tool calls stream live so you can watch
progress. When the agent finishes, all tool calls collapse into a
"See reasoning (N steps)" disclosure. Click to expand and see what
the agent did. The final text answer stays visible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: 17 new tests for recent sidebar fixes

Covers: tool-result file filtering, empty tool_use skip, reasoning
disclosure collapse, idle timeout headed mode bypass, sidebar-command
idle reset, shutdown sidebar-agent kill, cookie button, and model
routing analysis-before-action priority.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: move cookies button to quick actions toolbar

Cookies now sits next to Cleanup and Screenshot as a primary action
button (🍪 Cookies) instead of buried in the footer. Same behavior,
more discoverable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add instructional text to cookie picker page

"Select the domains of cookies you want to import to GStack Browser.
You'll be able to browse those sites with the same login as your
other browser."

Also fixes stale test that expected hardcoded '--model', 'opus'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: 6-card welcome page with cookie import + dual-agent cards

3x2 grid layout (was 2x2). New cards: "Import your cookies" (click
🍪 Cookies to import login sessions from Chrome/Arc/Brave) and
"Or use your main agent" (your Claude Code terminal also controls
this browser). Responsive: 3 cols > 2 cols > 1 col.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: move sidebar arrow hint to top-right instead of vertically centered

The arrow was centered vertically which put it behind the feature cards.
Now positioned at top: 80px where there's open space and it's more visible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 10:17:05 -07:00
Garry Tan cf73db5f19 feat: autoplan DX integration + README docs (v0.15.4.0) (#791)
* docs: document /plan-devex-review and /devex-review in README

Add both skills to the install instructions, skills table, and a new
"Which review?" comparison table showing when to use each review type.

* feat: add /plan-devex-review to /autoplan as conditional Phase 3.5

Auto-detects developer-facing scope (API, CLI, SDK, shell, agent, MCP,
OpenClaw) and runs DX review with dual adversarial voices after Eng review.

* chore: bump version and changelog (v0.15.4.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 17:45:51 -07:00
Garry Tan be96ff5ce7 feat: /plan-devex-review + /devex-review — DX review skills (v0.15.3.0) (#784)
* feat: add DX framework resolver for shared principles and scoring rubric

New {{DX_FRAMEWORK}} resolver provides compact (~150 lines) shared content
for /plan-devex-review and /devex-review: Addy Osmani's 8 DX principles,
7 characteristics table, 10 cognitive patterns, scoring rubric, and TTHW
benchmarks. Hall of Fame examples loaded on-demand per pass to avoid bloat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add DX Review row to review dashboard

Adds plan-devex-review and devex-review schema entries to the review
dashboard resolver and placeholder table in the preamble. All existing
SKILL.md files regenerated to include the new DX Review row.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: /plan-devex-review skill — DX plan review with Osmani framework

Plan-stage developer experience review. Rates 8 DX dimensions 0-10:
getting started, API/CLI/SDK design, error messages, docs, upgrade path,
dev environment, community, and DX measurement. Includes developer empathy
simulation, auto-detect product type with applicability gate, DX scorecard
with trend tracking, and a conditional Claude Code Skill DX checklist.
Hall of Fame examples loaded on-demand per pass from dx-hall-of-fame.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: /devex-review skill — live DX audit with browse

Live-system developer experience audit using browse tool. Tests all 8
dimensions aligned with /plan-devex-review for boomerang comparison
(plan said 3 min TTHW, reality says 8). Each dimension marked TESTED,
INFERRED, or N/A with evidence. Scope-aware: declares what browse can
and cannot test, falls back to file artifacts for untestable dimensions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.15.3.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 16:22:57 -07:00
Garry Tan 103a1b35dc docs: Slate agent integration research + design doc (#782)
Comprehensive research on Slate (Random Labs) as a potential first-class
coding agent host. Includes binary analysis findings, skill discovery paths,
env vars, CLI flags, and npm package structure. Blocked on host config
refactor before implementation.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 06:42:23 -07:00
Garry Tan c620de38e1 fix: setup runs pending migrations so git pull + ./setup works (#774)
* fix: setup runs pending migrations so git pull + ./setup works

Previously, version migrations only ran during /gstack-upgrade (Step 4.75).
Users who updated via git pull + ./setup never got migrations applied,
leaving stale skill directory structures in place. Now setup tracks the
last-run version in ~/.gstack/.last-setup-version and runs any pending
migrations automatically. Idempotent — safe to run multiple times.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: setup runs pending migrations so git pull + ./setup works

Previously, version migrations only ran during /gstack-upgrade (Step 4.75).
Users who updated via git pull + ./setup never got migrations applied,
leaving stale skill directory structures in place. Now setup tracks the
last-run version in ~/.gstack/.last-setup-version and runs any pending
migrations automatically.

Addresses adversarial review findings: space-safe while-read loop,
fresh install guard, upper-bound version check, missing VERSION guard.

* chore: bump version and changelog (v0.15.2.1)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:38:06 -07:00
Garry Tan 846269e3b1 feat: voice-friendly skill triggers for AquaVoice (v0.14.6.0) (#732)
* feat: voice-friendly skill triggers for speech-to-text input

Add voice-triggers YAML field to 10 SKILL.md.tmpl files with natural-language
aliases (e.g. "see-so" for /cso, "tech review" for /plan-eng-review).
gen-skill-docs preprocesses voice triggers before transformFrontmatter,
folding them into the description and stripping the field from output.
Includes unit tests, README voice input section, and CONTRIBUTING.md update.

* chore: bump version and changelog (v0.14.6.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 20:35:18 -07:00
Garry Tan 4fc64f7f96 fix: top-level skill dirs so Claude discovers unprefixed names (#761)
* fix: top-level skill dirs so Claude discovers unprefixed names

Replace directory symlinks (gstack/qa → qa) with real directories
containing a SKILL.md symlink. Claude Code auto-prefixes skills nested
under a parent dir symlink, so /plan-ceo-review became "Unknown skill"
even with skill_prefix=false. Real dirs fix this.

Also syncs package.json version to match VERSION file and updates
test assertions to match the new mkdir + ln approach.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: update symlink references to new top-level directory pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: regression tests for top-level skill directory structure

Verifies the invariant that setup/relink creates real directories (not
symlinks) at the top level, with SKILL.md symlinks inside. This prevents
Claude Code from auto-prefixing skills with gstack- when using --no-prefix.

Tests added:
- unprefixed skills must be real dirs with SKILL.md symlinks
- prefixed skills must also be real dirs with SKILL.md symlinks
- old directory symlinks get upgraded to real directories
- cleanup functions handle both old symlinks and new dir pattern
- link function removes old directory symlinks before mkdir

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: namespace isolation tests for first install + mode switching

Verifies the core invariant: when you pick a prefix mode, ONLY that
mode's entries exist. Zero pollution from the other mode.

- first install --no-prefix: only flat names, zero gstack-* leaks
- first install --prefix: only gstack-* names, zero flat leaks
- non-TTY defaults to flat names
- switching prefix→no-prefix removes ALL gstack-* entries
- switching no-prefix→prefix removes ALL flat entries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: upgrade migration system — versioned fix scripts for broken state

Adds gstack-upgrade/migrations/ directory with version-keyed bash scripts
that run automatically during /gstack-upgrade (Step 4.75, after ./setup).
Each script is idempotent and handles state fixes that setup alone can't
cover. First migration: v0.15.2.0.sh runs gstack-relink to fix stale
directory symlinks from pre-v0.15.2.0 installs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: migration script validation + v0.15.2.0 end-to-end fix test

Tests that migration scripts are executable, parse without syntax errors,
follow the v{VERSION}.sh naming convention, and that v0.15.2.0 actually
fixes stale directory symlinks by converting them to real directories.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: upgrade migration guide in CONTRIBUTING.md + CLAUDE.md pointer

CONTRIBUTING.md: new "Upgrade migrations" section documenting when and
how to add migration scripts for broken on-disk state.

CLAUDE.md: added note under vendored symlink awareness pointing to
CONTRIBUTING.md's migration section when worried about broken installs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 18:34:00 -07:00
Garry Tan 6169273d16 feat: /design-html works from any starting point (v0.15.1.0) (#734)
* feat: /design-html works from any starting point — not just design-shotgun

Three routing modes: approved mockup (Case A), CEO plan or design variants
without formal approval (Case B), or clean slate with just a description
(Case C). Each mode asks the right questions via AskUserQuestion instead of
blocking with "no approved design found."

* chore: bump version and changelog (v0.15.1.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 02:22:39 -06:00
Garry Tan 562a67503a feat: Session Intelligence Layer — /checkpoint + /health + context recovery (v0.15.0.0) (#733)
* feat: session timeline binaries (gstack-timeline-log + gstack-timeline-read)

New binaries for the Session Intelligence Layer. gstack-timeline-log appends
JSONL events to ~/.gstack/projects/$SLUG/timeline.jsonl. gstack-timeline-read
reads, filters, and formats timeline data for /retro consumption.

Timeline is local-only project intelligence, never sent anywhere. Always-on
regardless of telemetry setting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: preamble context recovery + timeline events + predictive suggestions

Layers 1-3 of the Session Intelligence Layer:
- Timeline start/complete events injected into every skill via preamble
- Context recovery (tier 2+): lists recent CEO plans, checkpoints, reviews
- Cross-session injection: LAST_SESSION and LATEST_CHECKPOINT for branch
- Predictive skill suggestion from recent timeline patterns
- Welcome back message synthesis
- Routing rules for /checkpoint and /health

Timeline writes are NOT gated by telemetry (local project intelligence).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: /checkpoint + /health skills (Layers 4-5)

/checkpoint: save/resume/list working state snapshots. Supports cross-branch
listing for Conductor workspace handoff. Session duration tracking.

/health: code quality scorekeeper. Wraps project tools (tsc, biome, knip,
shellcheck, tests), computes composite 0-10 score, tracks trends over time.
Auto-detects tools or reads from CLAUDE.md ## Health Stack.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: regenerate SKILL.md files + add timeline tests

9 timeline tests (all passing) mirroring learnings.test.ts pattern.
All 34 SKILL.md files regenerated with new preamble (context recovery,
timeline events, routing rules for /checkpoint and /health).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.15.0.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update self-learning roadmap post-Session Intelligence

R1-R3 marked shipped with actual versions. R4 becomes Adaptive Ceremony
(trust as separate policy engine, scope-aware, gradual degradation). R5
becomes /autoship (resumable state machine, not linear chain). R6-R7
unbundled from old R5. Added State Systems reference, Risk Register
(Codex-reviewed), and validation metrics for R4.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: E2E tests for Session Intelligence (timeline, recovery, checkpoint)

3 gate-tier E2E tests:
- timeline-event-flow: binary data flow round-trip (no LLM)
- context-recovery-artifacts: seeded artifacts appear in preamble
- checkpoint-save-resume: checkpoint file created with YAML frontmatter

Also fixes package.json version sync (0.14.6.0 → 0.15.0.0).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 00:50:42 -06:00
Garry Tan 8115951284 feat: recursive self-improvement — operational learning + full skill wiring (v0.13.8.0) (#647)
* refactor: remove dead contributor mode, replace with operational self-improvement slot

Contributor mode never fired in 18 days of heavy use (required manual opt-in
via gstack-config, gated behind _CONTRIB=true, wrote disconnected markdown).

Removes: generateContributorMode(), _CONTRIB bash var, 2 E2E tests, touchfile
entry, doc references. Cleans up skip-lists in plan-ceo-review, autoplan,
review resolver, and document-release templates.

The operational self-improvement system (next commit) replaces this slot with
automatic learning capture that requires no opt-in.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: operational self-improvement — every skill learns from failures

Adds universal operational learning capture to the preamble completion protocol.
At the end of every skill session, the agent reflects on CLI failures, wrong
approaches, and project quirks, logging them as type "operational" to the
learnings JSONL. Future sessions surface these automatically.

- generateCompletionStatus(ctx) now includes operational capture section
- Preamble bash shows top 3 learnings inline when count > 5
- New "operational" type in generateLearningsLog alongside pattern/pitfall/etc
- Updated unit tests + operational seed entry in learnings E2E

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: wire learnings into all insight-producing skills

Adds LEARNINGS_SEARCH and/or LEARNINGS_LOG to 10 skill templates that
produce reusable insights but were previously disconnected from the
learning system:

- office-hours, plan-ceo-review, plan-eng-review: add LOG (had SEARCH)
- plan-design-review: add both SEARCH + LOG (had neither)
- design-review, design-consultation, cso, qa, qa-only: add both
- retro: add SEARCH (had LOG)

13 skills now fully participate in the learning loop (read + write).
Every review, QA, investigation, and design session both consults prior
learnings and contributes new ones.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: add operational-learning E2E test (gate-tier)

Validates the write path: agent encounters a CLI failure, logs an
operational learning to JSONL via gstack-learnings-log. Replaces the
removed contributor-mode E2E test.

Setup: temp git repo, copy bin scripts, set GSTACK_HOME.
Prompt: simulated npm test failure needing --experimental-vm-modules.
Assert: learnings.jsonl exists with type=operational entry.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: learnings-show E2E slug mismatch — seed at computed slug, not hardcoded

The test seeded learnings at projects/test-project/ but gstack-slug computes
the slug from basename(workDir) when no git remote exists. The agent's search
looked at the wrong path and found nothing.

Fix: compute slug the same way gstack-slug does (basename + sanitize) and
seed the learnings there.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.8.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 23:08:22 -06:00
Garry Tan db35b8e5bf feat: session intelligence roadmap + design doc (#727)
* docs: Session Intelligence Layer design doc

Frames gstack as the persistent brain that survives Claude's ephemeral
context window. Architecture diagram, 5-layer feature breakdown, and
research sources from claude-mem, Anthropic engineering blog, CodeScene,
and Claude Code Agent Teams.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add context intelligence, health, swarm, and refactoring to roadmap

9 new TODOS across 4 sections based on Claude Code ecosystem research:
- Context Intelligence (P1): preamble artifact recovery, session timeline,
  cross-session injection, /checkpoint skill, vision doc
- Health (P1): /health dashboard with CodeScene MCP integration option,
  /health as /ship quality gate
- Swarm (P2): extract Review Army into reusable multi-agent primitive
- Refactoring (P2): /refactor-prep for pre-refactor token hygiene

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 17:01:22 -06:00
Garry Tan 7ea6ead9fa fix: ship idempotency + skill prefix name patching (v0.14.3.0) (#693)
* fix: add idempotency guards to /ship Steps 4, 7, 8 (#649)

If git push succeeds but gh pr create fails, re-running /ship would
double-bump VERSION and duplicate CHANGELOG entries. Now:
- Step 4: check if VERSION already differs from base branch
- Step 7: fetch only the specific branch, skip push if already up to date
- Step 8: if PR exists, update body via gh pr edit instead of creating duplicate

No CHANGELOG guard needed — Step 5 is already idempotent by design
("replace existing entries with one unified entry").

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: patch name: in SKILL.md frontmatter for prefix mode (#620, #578)

./setup --prefix creates gstack-* symlinks but SKILL.md still says
name: qa, so Claude Code ignores the prefix. Now:
- New bin/gstack-patch-names shared helper patches name: field via sed
- setup calls it after link_claude_skill_dirs
- gstack-relink calls it after symlink loop
- gen-skill-docs.ts prints warning when skill_prefix is true

Edge cases: gstack-upgrade not double-prefixed, root gstack skill
never prefixed, prefix removal restores original names, SKILL.md
without frontmatter is a safe no-op.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: add name patching + ship idempotency tests (#620, #649)

- 4 unit tests for name: patching in relink.test.ts (prefix on/off,
  gstack-upgrade not double-prefixed, no-frontmatter no-op)
- 2 tests for gen-skill-docs prefix warning
- 1 E2E test for ship idempotency (periodic tier)
- Updated setupMockInstall to write SKILL.md with proper frontmatter
- Added ship-idempotency touchfiles + tier classification

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.14.3.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: PR idempotency checks open state, dedupe touchfiles, sync package.json

- Step 8 PR guard now checks state==OPEN so closed PRs don't prevent
  new PR creation (adversarial review finding)
- Remove duplicate ship-idempotency entry in E2E_TOUCHFILES
- Sync package.json version to 0.14.3.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: patch name: before creating symlinks to fix --no-prefix ordering bug

gstack-patch-names must run BEFORE link_claude_skill_dirs so symlink
names reflect the correct (patched) name: values. Previously, switching
from --prefix to --no-prefix would read stale gstack-* names from
SKILL.md and create wrong symlinks. (Codex adversarial finding)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 22:25:46 -06:00
Garry Tan a4a181ca92 feat: Review Army — parallel specialist reviewers for /review (v0.14.3.0) (#692)
* feat: extend gstack-diff-scope with SCOPE_MIGRATIONS, SCOPE_API, SCOPE_AUTH

Three new scope signals for Review Army specialist activation:
- SCOPE_MIGRATIONS: db/migrate/, prisma/migrations/, alembic/, *.sql
- SCOPE_API: *controller*, *route*, *endpoint*, *.graphql, openapi.*
- SCOPE_AUTH: *auth*, *session*, *jwt*, *oauth*, *permission*, *role*

* feat: add 7 specialist checklist files for Review Army

- testing.md (always-on): coverage gaps, flaky patterns, security enforcement
- maintainability.md (always-on): dead code, DRY, stale comments
- security.md (conditional): OWASP deep analysis, auth bypass, injection
- performance.md (conditional): N+1 queries, bundle impact, complexity
- data-migration.md (conditional): reversibility, lock duration, backfill
- api-contract.md (conditional): breaking changes, versioning, error format
- red-team.md (conditional): adversarial analysis, cross-cutting concerns

All use standard header with JSON output schema and NO FINDINGS fallback.

* feat: Review Army resolver — parallel specialist dispatch + merge

New resolver in review-army.ts generates template prose for:
- Stack detection and specialist selection
- Parallel Agent tool dispatch with learning-informed prompts
- JSON finding collection, fingerprint dedup, consensus highlighting
- PR quality score computation
- Red Team conditional dispatch

Registered as REVIEW_ARMY in resolvers/index.ts.

* refactor: restructure /review template for Review Army

- Replace Steps 4-4.75 with CRITICAL pass + {{REVIEW_ARMY}}
- Remove {{DESIGN_REVIEW_LITE}} and {{TEST_COVERAGE_AUDIT_REVIEW}}
  (subsumed into Design and Testing specialists respectively)
- Extract specialist-covered categories from checklist.md
- Keep CRITICAL + uncovered INFORMATIONAL in main agent pass

* test: Review Army — 14 diff-scope tests + 7 E2E tests

- test/diff-scope.test.ts: 14 tests for all 9 scope signals
- test/skill-e2e-review-army.test.ts: 7 E2E tests
  Gate: migration safety, N+1 detection, delivery audit,
        quality score, JSON findings
  Periodic: red team, consensus
- Updated gen-skill-docs tests for new review structure
- Added touchfile entries and tier classifications

* docs: update SELF_LEARNING_V0.md with Release 2 status + Release 2.5

Mark Release 2 (Review Army) as in-progress. Add Release 2.5 for
deferred expansions (E1 adaptive gating, E3 test stubs, E5 cross-review
dedup, E7 specialist tracking).

* chore: bump version and changelog (v0.14.3.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 22:07:50 -06:00
Garry Tan a0328be04c feat: always-on adversarial review + scope drift + plan mode design tools (v0.14.3.0) (#694)
* feat: always-on adversarial review + scope drift resolver + cross-model tension format

Rewrite generateAdversarialStep() to remove LOC-based tier skipping. Every review
now runs both Claude adversarial subagent and Codex adversarial challenge. OLD_CFG
only gates Codex passes, not Claude. Add generateScopeDrift() shared resolver.
Fix cross-model tension AskUserQuestion to include RECOMMENDATION + Completeness.

* feat: add scope drift to /ship, extract from /review template

/ship gets {{SCOPE_DRIFT}} at Step 3.48 + PR body slot. /review replaces
hardcoded scope drift with {{SCOPE_DRIFT}} + {{PLAN_COMPLETION_AUDIT_REVIEW}}.

* feat: plan mode safe operations — browse, design, codex allowed in plan mode

Add preamble section declaring $B, $D, codex, and ~/.gstack/ writes as
plan-mode-safe. Unblocks design skills during planning.

* test: update adversarial + add scope drift assertions

Rename adversarial tests to reflect always-on behavior. Remove tier
threshold assertions. Add scope drift content assertions for both
/review and /ship generated SKILL.md files.

* chore: bump version and changelog (v0.14.3.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 21:45:28 -06:00
Garry Tan a1a933614c feat: sidebar CSS inspector + per-tab agents (v0.13.9.0) (#650)
* feat: CDP inspector module — persistent sessions, CSS cascade, style modification

New browse/src/cdp-inspector.ts with full CDP inspection engine:
- inspectElement() via CSS.getMatchedStylesForNode + DOM.getBoxModel
- modifyStyle() via CSS.setStyleTexts with headless page.evaluate fallback
- Persistent CDP session lifecycle (create, reuse, detach on nav, re-create)
- Specificity sorting, overridden property detection, UA rule filtering
- Modification history with undo support
- formatInspectorResult() for CLI output

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: browse server inspector endpoints + inspect/style/cleanup/prettyscreenshot CLI

Server endpoints: POST /inspector/pick, GET /inspector, POST /inspector/apply,
POST /inspector/reset, GET /inspector/history, GET /inspector/events (SSE).
CLI commands: inspect (CDP cascade), style (live CSS mod), cleanup (page clutter
removal), prettyscreenshot (clean screenshot pipeline).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: sidebar CSS inspector — element picker, box model, rule cascade, quick edit

Extension changes for the visual CSS inspector:
- inspector.js: element picker with hover highlight, CSS selector generation,
  basic mode fallback (getComputedStyle + CSSOM), page alteration handlers
- inspector.css: picker overlay styles (blue highlight + tooltip)
- background.js: inspector message routing (picker <-> server <-> sidepanel)
- sidepanel: Inspector tab with box model viz (gstack palette), matched rules
  with specificity badges, computed styles, click-to-edit quick edit,
  Send to Agent/Code button, empty/loading/error states

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: document inspect, style, cleanup, prettyscreenshot browse commands

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: auto-track user-created tabs and handle tab close

browser-manager.ts changes:
- context.on('page') listener: automatically tracks tabs opened by the user
  (Cmd+T, right-click open in new tab, window.open). Previously only
  programmatic newTab() was tracked, so user tabs were invisible.
- page.on('close') handler in wirePageEvents: removes closed tabs from the
  pages map and switches activeTabId to the last remaining tab.
- syncActiveTabByUrl: match Chrome extension's active tab URL to the correct
  Playwright page for accurate tab identity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: per-tab agent isolation via BROWSE_TAB environment variable

Prevents parallel sidebar agents from interfering with each other's tab context.

Three-layer fix:
- sidebar-agent.ts: passes BROWSE_TAB=<tabId> env var to each claude process,
  per-tab processing set allows concurrent agents across tabs
- cli.ts: reads process.env.BROWSE_TAB and includes tabId in command request body
- server.ts: handleCommand() temporarily switches activeTabId when tabId is present,
  restores after command completes (safe: Bun event loop is single-threaded)

Also: per-tab agent state (TabAgentState map), per-tab message queuing,
per-tab chat buffers, verbose streaming narration, stop button endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: sidebar per-tab chat context, tab bar sync, stop button, UX polish

Extension changes:
- sidepanel.js: per-tab chat history (tabChatHistories map), switchChatTab()
  swaps entire chat view, browserTabActivated handler for instant tab sync,
  stop button wired to /sidebar-agent/stop, pollTabs renders tab bar
- sidepanel.html: updated banner text ("Browser co-pilot"), stop button markup,
  input placeholder "Ask about this page..."
- sidepanel.css: tab bar styles, stop button styles, loading state fixes
- background.js: chrome.tabs.onActivated sends browserTabActivated to sidepanel
  with tab URL for instant tab switch detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: per-tab isolation, BROWSE_TAB pinning, tab tracking, sidebar UX

sidebar-agent.test.ts (new tests):
- BROWSE_TAB env var passed to claude process
- CLI reads BROWSE_TAB and sends tabId in body
- handleCommand accepts tabId, saves/restores activeTabId
- Tab pinning only activates when tabId provided
- Per-tab agent state, queue, concurrency
- processingTabs set for parallel agents

sidebar-ux.test.ts (new tests):
- context.on('page') tracks user-created tabs
- page.on('close') removes tabs from pages map
- Tab isolation uses BROWSE_TAB not system prompt hack
- Per-tab chat context in sidepanel
- Tab bar rendering, stop button, banner text

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: resolve merge conflicts — keep security defenses + per-tab isolation

Merged main's security improvements (XML escaping, prompt injection defense,
allowed commands whitelist, --model opus, Write tool, stderr capture) with
our branch's per-tab isolation (BROWSE_TAB env var, processingTabs set,
no --resume). Updated test expectations for expanded system prompt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.9.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add inspector message types to background.js allowlist

Pre-existing bug found by Codex: ALLOWED_TYPES in background.js was missing
all inspector message types (startInspector, stopInspector, elementPicked,
pickerCancelled, applyStyle, toggleClass, injectCSS, resetAll, inspectResult).
Messages were silently rejected, making the inspector broken on ALL pages.

Also: separate executeScript and insertCSS into individual try blocks in
injectInspector(), store inspectorMode for routing, and add content.js
fallback when script injection fails (CSP, chrome:// pages).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: basic element picker in content.js for CSP-restricted pages

When inspector.js can't be injected (CSP, chrome:// pages), content.js
provides a basic picker using getComputedStyle + CSSOM:
- startBasicPicker/stopBasicPicker message handlers
- captureBasicData() with ~30 key CSS properties, box model, matched rules
- Hover highlight with outline save/restore (never leaves artifacts)
- Click uses e.target directly (no re-querying by selector)
- Sends inspectResult with mode:'basic' for sidebar rendering
- Escape key cancels picker and restores outlines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: cleanup + screenshot buttons in sidebar inspector toolbar

Two action buttons in the inspector toolbar:
- Cleanup (🧹): POSTs cleanup --all to server, shows spinner, chat
  notification on success, resets inspector state (element may be removed)
- Screenshot (📸): POSTs screenshot to server, shows spinner, chat
  notification with saved file path

Shared infrastructure:
- .inspector-action-btn CSS with loading spinner via ::after pseudo-element
- chat-notification type in addChatEntry() for system messages
- package.json version bump to 0.13.9.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: inspector allowlist, CSP fallback, cleanup/screenshot buttons

16 new tests in sidebar-ux.test.ts:
- Inspector message allowlist includes all inspector types
- content.js basic picker (startBasicPicker, captureBasicData, CSSOM,
  outline save/restore, inspectResult with mode basic, Escape cleanup)
- background.js CSP fallback (separate try blocks, inspectorMode, fallback)
- Cleanup button (POST /command, inspector reset after success)
- Screenshot button (POST /command, notification rendering)
- Chat notification type and CSS styles

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update project documentation for v0.13.9.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: cleanup + screenshot buttons in chat toolbar (not just inspector)

Quick actions toolbar (🧹 Cleanup, 📸 Screenshot) now appears above the chat
input, always visible. Both inspector and chat buttons share runCleanup() and
runScreenshot() helper functions. Clicking either set shows loading state on
both simultaneously.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: chat toolbar buttons, shared helpers, quick-action-btn styles

Tests that chat toolbar exists (chat-cleanup-btn, chat-screenshot-btn,
quick-actions container), CSS styles (.quick-action-btn, .quick-action-btn.loading),
shared runCleanup/runScreenshot helper functions, and cleanup inspector reset.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: aggressive cleanup heuristics — overlays, scroll unlock, blur removal

Massively expanded CLEANUP_SELECTORS with patterns from uBlock Origin and
Readability.js research:
- ads: 30+ selectors (Google, Amazon, Outbrain, Taboola, Criteo, etc.)
- cookies: OneTrust, Cookiebot, TrustArc, Quantcast + generic patterns
- overlays (NEW): paywalls, newsletter popups, interstitials, push prompts,
  app download banners, survey modals
- social: follow prompts, share tools
- Cleanup now defaults to --all when no args (sidebar button fix)
- Uses !important on all display:none (overrides inline styles)
- Unlocks body/html scroll (overflow:hidden from modal lockout)
- Removes blur/filter effects (paywall content blur)
- Removes max-height truncation (article teaser truncation)
- Collapses empty ad placeholder whitespace (empty divs after ad removal)
- Skips gstack-ctrl indicator in sticky removal

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: disable action buttons when disconnected, no error spam

- setActionButtonsEnabled() toggles .disabled class on all cleanup/screenshot
  buttons (both chat toolbar and inspector toolbar)
- Called with false in updateConnection when server URL is null
- Called with true when connection established
- runCleanup/runScreenshot silently return when disconnected instead of
  showing 'Not connected' error notifications
- CSS .disabled style: pointer-events:none, opacity:0.3, cursor:not-allowed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: cleanup heuristics, button disabled state, overlay selectors

17 new tests:
- cleanup defaults to --all on empty args
- CLEANUP_SELECTORS overlays category (paywall, newsletter, interstitial)
- Major ad networks in selectors (doubleclick, taboola, criteo, etc.)
- Major consent frameworks (OneTrust, Cookiebot, TrustArc, Quantcast)
- !important override for inline styles
- Scroll unlock (body overflow:hidden)
- Blur removal (paywall content blur)
- Article truncation removal (max-height)
- Empty placeholder collapse
- gstack-ctrl indicator skip in sticky cleanup
- setActionButtonsEnabled function
- Buttons disabled when disconnected
- No error spam from cleanup/screenshot when disconnected
- CSS disabled styles for action buttons

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: LLM-based page cleanup — agent analyzes page semantically

Instead of brittle CSS selectors, the cleanup button now sends a prompt to
the sidebar agent (which IS an LLM). The agent:
1. Runs deterministic $B cleanup --all as a quick first pass
2. Takes a snapshot to see what's left
3. Analyzes the page semantically to identify remaining clutter
4. Removes elements intelligently, preserving site branding

This means cleanup works correctly on any site without site-specific selectors.
The LLM understands that "Your Daily Puzzles" is clutter, "ADVERTISEMENT" is
junk, but the SF Chronicle masthead should stay.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: aggressive cleanup heuristics + preserve top nav bar

Deterministic cleanup improvements (used as first pass before LLM analysis):
- New 'clutter' category: audio players, podcast widgets, sidebar puzzles/games,
  recirculation widgets (taboola, outbrain, nativo), cross-promotion banners
- Text-content detection: removes "ADVERTISEMENT", "Article continues below",
  "Sponsored", "Paid content" labels and their parent wrappers
- Sticky fix: preserves the topmost full-width element near viewport top (site
  nav bar) instead of hiding all sticky/fixed elements. Sorts by vertical
  position, preserves the first one that spans >80% viewport width.

Tests: clutter category, ad label removal, nav bar preservation logic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: LLM-based cleanup architecture, deterministic heuristics, sticky nav

22 new tests covering:
- Cleanup button uses /sidebar-command (agent) not /command (deterministic)
- Cleanup prompt includes deterministic first pass + agent snapshot analysis
- Cleanup prompt lists specific clutter categories for agent guidance
- Cleanup prompt preserves site identity (masthead, headline, body, byline)
- Cleanup prompt instructs scroll unlock and $B eval removal
- Loading state management (async agent, setTimeout)
- Deterministic clutter: audio/podcast, games/puzzles, recirculation
- Ad label text patterns (ADVERTISEMENT, Sponsored, Article continues)
- Ad label parent wrapper hiding for small containers
- Sticky nav preservation (sort by position, first full-width near top)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: prevent repeat chat message rendering on reconnect/replay

Root cause: server persists chat to disk (chat.jsonl) and replays on restart.
Client had no dedup, so every reconnect re-rendered the entire history.
Messages from an old HN session would repeat endlessly on the SF Chronicle tab.

Fix: renderedEntryIds Set tracks which entry IDs have been rendered. addChatEntry
skips entries already in the set. Entries without an id (local notifications)
bypass the check. Clear chat resets the set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: agent stops when done, no focus stealing, opus for prompt injection safety

Three fixes for sidebar agent UX:
- System prompt: "Be CONCISE. STOP as soon as the task is done. Do NOT keep
  exploring or doing bonus work." Prevents agent from endlessly taking
  screenshots and highlighting elements after answering the question.
- switchTab(id, opts): new bringToFront option. Internal tab pinning
  (BROWSE_TAB) uses bringToFront: false so agent commands never steal
  window focus from the user's active app.
- Keep opus model (not sonnet) for prompt injection resistance on untrusted
  web pages. Remove Write from allowedTools (agent only needs Bash for $B).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: agent conciseness, focus stealing, opus model, switchTab opts

Tests for the three UX fixes:
- System prompt contains STOP/CONCISE/Do NOT keep exploring
- sidebar agent uses opus (not sonnet) for prompt injection resistance
- switchTab has bringToFront option, defaults to true (opt-out)
- handleCommand tab pinning uses bringToFront: false (no focus steal)
- Updated stale tests: switchTab signature, allowedTools excludes Write,
  narration -> conciseness, tab pinning restore calls

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: sidebar CSS interaction E2E — HN comment highlight round-trip

New E2E test (periodic tier, ~$2/run) that exercises the full sidebar
agent pipeline with CSS interaction:
1. Agent navigates to Hacker News
2. Clicks into the top story's comments
3. Reads comments and identifies the most insightful one
4. Highlights it with a 4px solid orange outline via style injection

Tests: navigation, snapshot, text reading, LLM judgment, CSS modification.
Requires real browser + real Claude (ANTHROPIC_API_KEY).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: sidebar CSS E2E test — correct idle timeout (ms not s), pipe stdio

Root cause of test failure: BROWSE_IDLE_TIMEOUT is in milliseconds, not
seconds. '600' = 0.6 seconds, server died immediately after health check.
Fixed to '600000' (10 minutes).

Also: use 'pipe' stdio instead of file descriptors (closing fds kills child
on macOS/bun), catch ConnectionRefused on poll retry, 4 min poll timeout
for the multi-step opus task.

Test passes: agent navigates to HN, reads comments, identifies most
insightful one, highlights it with orange CSS, stops. 114s, $0.00.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 12:51:05 -06:00
Garry Tan 7911b7b974 fix: force comparison board as default variant chooser (v0.14.1.0) (#658)
* fix: force comparison board as default variant chooser

The comparison board ($D compare --serve) was being skipped in favor of
showing variants inline + AskUserQuestion "which do you prefer?" — a
degraded experience missing rating controls, comments, and remix buttons.

Changes:
- Replace "show inline" instruction with "do NOT show inline, proceed to
  comparison board" in plan-design-review/SKILL.md.tmpl
- Add CRITICAL RULE: never use AskUserQuestion as the variant chooser
- Change DESIGN_SHOTGUN_LOOP resolver to AskUserQuestion-first wait with
  polling fallback (affects all 3 consumer skills)
- Fix board URL from /design-board.html (404) to / (correct)
- Improve serve-failure fallback to show variants inline via Read tool

* chore: bump version and changelog (v0.14.1.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 03:42:58 -06:00
Garry Tan b2b380bfcc docs: update README and skill deep dives for all 31 skills (#656)
* docs: update README with /design-html and /learn skills, sync all skill lists

- Added /design-html to sprint table (Pretext-native HTML from approved mockups)
- Added /learn to sprint table (project learnings management)
- Synced all 5 skill list locations (install step 1, step 2, troubleshooting,
  sprint table, power tools) to include all 31 skills
- Updated intro count from 20 to 23 specialists
- Updated Codex section skill count from 29 to 31
- Expanded "Design is at the heart" paragraph with full pipeline:
  consultation → shotgun → design-html → review

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add 9 missing skills to deep dives doc

Added table entries + full deep dive sections for:
- /design-shotgun (design exploration with comparison board)
- /design-html (Pretext-native HTML from approved mockups)
- /land-and-deploy (merge + deploy + canary verification)
- /canary (post-deploy monitoring loop)
- /benchmark (performance regression detection)
- /autoplan (auto-review pipeline)
- /learn (project learnings management)
- /connect-chrome (headed Chrome with side panel)
- /setup-deploy (one-time deploy configuration)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 01:17:33 -07:00
Garry Tan 8151fcd589 feat: /design-html skill — Pretext-native HTML from approved mockups (v0.14.0.0) (#653)
* feat: /design-html skill — Pretext-native HTML from approved mockups

New skill that takes approved design-shotgun mockups and generates
production-quality HTML with Pretext for computed text layout. Text
reflows on resize, heights adjust to content, zero hardcoded CSS.

Includes vendored Pretext bundle (30KB), smart API routing per design
type, AskUserQuestion refinement loop, framework detection, and
3-viewport verification screenshots.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: integrate /design-html into design skill pipeline

- design-shotgun: Step 6 option B now chains to /design-html
- design-consultation: suggests /design-html after shipping DESIGN.md
  (conditional on screen-level output, not tokens-only)
- plan-design-review: expanded chaining to include /design-shotgun
  and /design-html alongside review skills

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: update plan-design-review chaining test for design skills

plan-design-review now chains to /design-shotgun and /design-html
in addition to review skills. Update the assertion to match.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add gstack keyword to design-html description for validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.14.0.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 01:54:54 -06:00
Garry Tan 403637f0c8 feat: rotating founder resources in /office-hours closing (v0.13.10.0) (#652)
* feat: rotating founder resources in /office-hours closing

Add Beat 3.5 with 34 curated resources (5 Garry Tan videos, 2 YC Backstory,
9 Lightcone Podcast, 8 Startup School, 10 PG essays) that rotate contextually
each session. Includes dedup log to avoid repeats, analytics logging, and
browser-open offers. Also adds chmod +x safety net to build script.

* chore: bump version and changelog (v0.13.10.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 00:34:30 -06:00
Garry Tan 66c09644a7 feat: composable skills — INVOKE_SKILL resolver + factoring infrastructure (v0.13.7.0) (#644)
* feat: add parameterized resolver support to gen-skill-docs

Extend the placeholder regex from {{WORD}} to {{WORD:arg1:arg2}},
enabling parameterized resolvers like {{INVOKE_SKILL:plan-ceo-review}}.

- Widen ResolverFn type to accept optional args?: string[]
- Update RESOLVERS record to use ResolverFn type
- Both replacement and unresolved-check regexes updated
- Fully backward compatible: existing {{WORD}} patterns unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add INVOKE_SKILL resolver for composable skill loading

New composition.ts resolver module that emits prose instructing Claude
to read another skill's SKILL.md and follow it, skipping preamble
sections. Supports optional skip= parameter for additional sections.

Usage: {{INVOKE_SKILL:plan-ceo-review}} or
       {{INVOKE_SKILL:plan-ceo-review:skip=Outside Voice}}

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: use frontmatter name: for skill symlinks and Codex paths

Patch all 3 name-derivation paths to read name: from SKILL.md
frontmatter instead of relying solely on directory basenames.
This enables directory names that differ from invocation names
(e.g., run-tests/ directory with name: test).

- setup: link_claude_skill_dirs reads name: via grep, falls back to basename
- gen-skill-docs.ts: codexSkillName uses frontmatter name for Codex output paths
- gen-skill-docs.ts: moved frontmatter extraction before Codex path logic

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: extract CHANGELOG_WORKFLOW resolver from /ship

Move changelog generation logic into a reusable resolver. The resolver
is changelog-only (no version bump per Codex review recommendation).
Adds voice rules inline. /ship Step 5 now uses {{CHANGELOG_WORKFLOW}}.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: use INVOKE_SKILL resolver for plan-ceo-review office-hours fallback

Replace inline skill loading prose (read file, skip sections) with
{{INVOKE_SKILL:office-hours}} in the mid-session detection path.
The BENEFITS_FROM prerequisite offer is unchanged (separate use case).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: BENEFITS_FROM resolver delegates to INVOKE_SKILL

Eliminate duplicated skip-list logic by having generateBenefitsFrom
call generateInvokeSkill internally. The wrapper (AskUserQuestion,
design doc re-check) stays in BENEFITS_FROM. The loading instructions
(read file, skip sections, error handling) come from INVOKE_SKILL.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: add resolver tests for INVOKE_SKILL, CHANGELOG_WORKFLOW, parameterized args

12 new tests covering:
- INVOKE_SKILL: template placeholder, default skip list, error handling,
  BENEFITS_FROM delegation
- CHANGELOG_WORKFLOW: content, cross-check, voice guidance, format
- Parameterized resolver infra: colon-separated args processing,
  no unresolved placeholders across all generated SKILL.md files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.7.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: journey routing tests — CLAUDE.md routing rules + stronger descriptions

Three journey E2E tests (ideation, ship, debug) were failing because
Claude answered directly instead of invoking the Skill tool. Root cause:
skill descriptions in system-reminder are too weak to override Claude's
default behavior for tasks it can handle natively.

Fix has two parts:
1. CLAUDE.md routing rules in test workdir — Claude weighs project-level
   instructions higher than skill description metadata
2. "Proactively invoke" (not "suggest") in office-hours, investigate,
   ship descriptions — reinforces the routing signal

10/10 journey tests now pass (was 7/10).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: one-time CLAUDE.md routing injection prompt

Add a preamble section that checks if the project's CLAUDE.md has
skill routing rules. If not (and user hasn't declined), asks once
via AskUserQuestion to inject a "## Skill routing" section.

Root cause: skill descriptions in system-reminder metadata are too
weak to reliably trigger proactive Skill tool invocation. CLAUDE.md
project instructions carry higher weight in Claude's decision making.

- Preamble bash checks for "## Skill routing" in CLAUDE.md
- Stores decline in gstack-config (routing_declined=true)
- Only asks once per project (HAS_ROUTING check + config check)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: annotated config file + routing injection tests

gstack-config now writes a documented header on first config creation
with every supported key explained (proactive, telemetry, auto_upgrade,
skill_prefix, routing_declined, codex_reviews, skip_eng_review, etc.).
Users can edit ~/.gstack/config.yaml directly, anytime.

Also fixes grep to use ^KEY: anchoring so commented header lines don't
shadow real config values.

Tests added:
- 7 new gstack-config tests (annotated header, no duplication, comment
  safety, routing_declined get/set/reset)
- 6 new gen-skill-docs tests (preamble routing injection: bash checks,
  config reads, AskUserQuestion, decline persistence, routing rules)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump to v0.13.9.0, separate CHANGELOG from main's releases

Split our branch's changes into a new 0.13.9.0 entry instead of
jamming them into 0.13.7.0 which already landed on main as
"Community Wave."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: clarify branch-scoped VERSION/CHANGELOG after merging main

Add explicit rules: merging main doesn't mean adopting main's version.
Branch always gets its own entry on top with a higher version number.
Three-point checklist after every merge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: put our 0.13.9.0 entry on top of CHANGELOG

Newest version goes on top. Our branch lands next, so our entry
must be above main's 0.13.8.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: restore missing 0.13.7.0 Community Wave entry

Accidentally dropped the 0.13.7.0 entry when reordering.
All entries now present: 0.13.9.0 > 0.13.8.0 > 0.13.7.0 > 0.13.6.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add CHANGELOG integrity check rule

After any edit that moves/adds/removes entries, grep for version
headers and verify no gaps or duplicates before committing.
Prevents accidentally dropping entries during reordering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 23:35:17 -06:00
Garry Tan 3cda8deec9 fix: security audit round 2 (v0.13.4.0) (#640)
* fix: chrome-cdp localhost-only binding

Restrict Chrome CDP to localhost by adding --remote-debugging-address=127.0.0.1
and --remote-allow-origins to prevent network-accessible debugging sessions.

Clears 1 Socket anomaly (Chrome CDP session exposure).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: extension sender validation + message type allowlist

Add sender.id check and ALLOWED_TYPES allowlist to the Chrome extension's
message handler. Defense-in-depth against message spoofing from external
extensions or future externally_connectable changes.

Clears 2 Socket anomalies (extension permissions).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: checksum-verified bun install

Replace unverified curl|bash bun installation with checksum-verified
download-then-execute pattern. The install script is downloaded, sha256
verified against a known hash, then executed. Preserves the Bun-native
install path without adding a Node/npm dependency.

Clears Snyk W012 + 3 Socket anomalies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: content trust boundary markers in browse output

Wrap page-content commands (text, html, links, forms, accessibility,
console, dialog, snapshot) with --- BEGIN/END UNTRUSTED EXTERNAL CONTENT ---
markers. Covers direct commands (server.ts), chain sub-commands, and
snapshot output (meta-commands.ts).

Adds PAGE_CONTENT_COMMANDS set and wrapUntrustedContent() helper in
commands.ts (single source of truth, DRY). Expands the SKILL.md trust
warning with explicit processing rules for agents.

Clears Snyk W011 (third-party content exposure).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: harden trust boundary markers against escape attacks

- Sanitize URLs in markers (remove newlines, cap at 200 chars) to prevent
  marker injection via history.pushState
- Escape marker strings in content (zero-width space) so malicious pages
  can't forge the END marker to break out of the untrusted block
- Wrap resume command snapshot with trust boundary markers
- Wrap diff command output with trust boundary markers
- Wrap watch stop last snapshot with trust boundary markers

Found by cross-model adversarial review (Claude + Codex).

* chore: bump version and changelog (v0.13.4.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: gitignore .factory/ and remove from tracking

Factory Droid support was removed in this branch. The .factory/ directory
was re-added by merging main (which had v0.13.5.0 Factory support).
Gitignore it so it stays out.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:46:33 -06:00
Garry Tan cdd6f7865d feat: community wave — 7 fixes, relink, sidebar Write, discoverability (v0.13.5.0) (#641)
* test: add 16 failing tests for 6 community fixes

Tests-first for all fixes in this PR wave:
- #594 discoverability: gstack tag in descriptions, 120-char first line
- #573 feature signals: ship/SKILL.md Step 4 detection
- #510 context warnings: no preemptive warnings in generated files
- #474 Safety Net: no find -delete in generated files
- #467 telemetry: JSONL writes gated by _TEL conditional
- #584 sidebar: Write in allowedTools, stderr capture
- #578 relink: prefixed/flat symlinks, cleanup, error, config hook

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: replace find -delete with find -exec rm for Safety Net (#474)

-delete is a non-POSIX extension that fails on Safety Net environments.
-exec rm {} + is POSIX-compliant and works everywhere.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: gate local JSONL writes by telemetry setting (#467)

When telemetry is off, nothing is written anywhere — not just remote,
but local JSONL too. Clean trust contract: off means off everywhere.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: remove preemptive context warnings from plan-eng-review (#510)

The system handles context compaction automatically. Preemptive warnings
waste tokens and create false urgency. Skills should not warn about
context limits — just describe the compression priority order.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add (gstack) tag to skill descriptions for discoverability (#594)

Every SKILL.md.tmpl description now contains "gstack" on the last line,
making skills findable in Claude Code's command palette. First-line hooks
stay under 120 chars. Split ship description to fix wrapping.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: auto-relink skill symlinks on prefix config change (#578)

New bin/gstack-relink creates prefixed (gstack-*) or flat symlinks
based on skill_prefix config. gstack-config auto-triggers relink
when skill_prefix changes. Setup guards against recursive calls
with GSTACK_SETUP_RUNNING env var.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add feature signal detection to version bump heuristic (#573)

/ship Step 4 now checks for feature signals (new routes, migrations,
test+source pairs, feat/ branches) when deciding version bumps.
PATCH requires no feature signals. MINOR asks the user if any signal
is detected or 500+ lines changed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: sidebar Write tool, stderr capture, cross-platform URL opener (#584)

Add Write to sidebar allowedTools (both sidebar-agent.ts and server.ts).
Write doesn't expand attack surface beyond what Bash already provides.
Replace empty stderr handler with buffer capture for better error
diagnostics. New bin/gstack-open-url for cross-platform URL opening.

Does NOT include Search Before Building intro flow (deferred).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: update sidebar-security test for Write tool addition

The fallback allowedTools string now includes Write, matching the
sidebar-agent.ts change from commit 68dc957.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.5.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: prevent gstack-relink from double-prefixing gstack-upgrade

gstack-relink now checks if a skill directory is already named gstack-*
before prepending the prefix. Previously, setting skill_prefix=true would
create gstack-gstack-upgrade, breaking the /gstack-upgrade command.

Matches setup script behavior (setup:260) which already has this guard.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: add double-prefix fix to changelog

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: remove .factory/ from git tracking and add to .gitignore

Generated Factory Droid skills are build output, same as .agents/.
They should not be committed to the repo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 21:43:36 -06:00
Garry Tan ae0a9ad195 feat: GStack Learns — per-project self-learning infrastructure (v0.13.4.0) (#622)
* feat: learnings + confidence resolvers — cross-skill memory infrastructure

Three new resolvers for the self-learning system:
- LEARNINGS_SEARCH: tells skills to load prior learnings before analysis
- LEARNINGS_LOG: tells skills to capture discoveries after completing work
- CONFIDENCE_CALIBRATION: adds 1-10 confidence scoring to all review findings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: learnings bin scripts — append-only JSONL read/write

gstack-learnings-log: validates JSON, auto-injects timestamp, appends to
~/.gstack/projects/$SLUG/learnings.jsonl. Append-only (no mutation).

gstack-learnings-search: reads/filters/dedupes learnings with confidence
decay (observed/inferred lose 1pt/30d), cross-project discovery, and
"latest winner" resolution per key+type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: learnings count in preamble output

Every skill now prints "LEARNINGS: N entries loaded" during preamble,
making the compounding loop visible to the user.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: integrate learnings + confidence into 9 skill templates

Add {{LEARNINGS_SEARCH}}, {{LEARNINGS_LOG}}, and {{CONFIDENCE_CALIBRATION}}
placeholders to review, ship, plan-eng-review, plan-ceo-review, office-hours,
investigate, retro, and cso templates. Regenerated all SKILL.md files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: /learn skill — manage project learnings

New skill for reviewing, searching, pruning, and exporting what gstack
has learned across sessions. Commands: /learn, /learn search, /learn prune,
/learn export, /learn stats, /learn add.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: self-learning roadmap — 5-release design doc

Covers: R1 GStack Learns (v0.14), R2 Review Army (v0.15), R3 Smart Ceremony
(v0.16), R4 /autoship (v0.17), R5 Studio (v0.18). Inspired by Compound
Engineering, adapted to GStack's architecture.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: learnings bin script unit tests — 13 tests, free

Tests gstack-learnings-log (valid/invalid JSON, timestamp injection,
append-only) and gstack-learnings-search (dedup, type/query/limit filters,
confidence decay, user-stated no-decay, malformed JSONL skip).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.4.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: learnings resolver + bin script edge case tests — 21 new tests, free

Adds gen-skill-docs coverage for LEARNINGS_SEARCH, LEARNINGS_LOG, and
CONFIDENCE_CALIBRATION resolvers. Adds bin script edge cases: timestamp
preservation, special characters, files array, sort order, type grouping,
combined filtering, missing fields, confidence floor at 0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: sync package.json version with VERSION file (0.13.4.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: gitignore .factory/ — generated output, not source

Same pattern as .claude/skills/ and .agents/. These SKILL.md files are
generated from .tmpl templates by gen:skill-docs --host factory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: /learn E2E — seed 3 learnings, verify agent surfaces them

Seeds N+1 query pattern, stale cache pitfall, and rubocop preference
into learnings.jsonl, then runs /learn and checks that at least 2/3
appear in the agent's output. Gate tier, ~$0.25/run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 17:02:01 -06:00
Garry Tan 66894601e3 chore: gitignore .factory and remove tracked files (v0.13.5.1) (#642)
* chore: gitignore .factory and remove tracked files

The .factory/ directory contains generated skill definitions for
Factory Droid compatibility. These should not be tracked in git,
same as .claude/skills/ and .agents/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.5.1)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 16:50:01 -06:00
Garry Tan 484cf1fb3b feat: Factory Droid compatibility — works across Claude Code, Codex, and Factory (v0.13.5.0) (#621)
* refactor: extract processExternalHost() shared helper for multi-host generation

Refactor the Codex-specific output routing block in gen-skill-docs.ts into
a shared processExternalHost() function. Both Codex and future external hosts
(Factory Droid) will use this helper for output routing, symlink loop detection,
frontmatter transformation, path rewrites, and metadata generation.

- Rename codexSkillName() to externalSkillName() everywhere
- Extract ExternalHostConfig interface with per-host settings
- Codex output is byte-identical (verified via --dry-run)
- Skip /codex skill for all non-Claude hosts (not just codex)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add Factory Droid host type, preamble, and co-author trailer

- Add 'factory' to Host union type with .factory/skills/gstack paths
- Extend preamble runtime root detection for Factory ($HOME/.factory/)
- Add GSTACK_DESIGN env var to preamble (was missing for Codex too)
- Add Factory Droid co-author trailer for git commits

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Factory Droid generation, --host all, and host-aware frontmatter

- Add --host factory (alias: --host droid) to gen-skill-docs
- Add --host all: generates for claude, codex, and factory in one invocation
  with fault-tolerant per-host error handling (only fails if claude fails)
- Factory frontmatter: name + description + user-invocable: true
- Factory sensitive skills: disable-model-invocation: true (from sensitive: field)
- Claude: strips sensitive: field from output (only Factory uses it)
- Factory tool name translation: Claude tool names → generic phrasing
- Replace chained gen:skill-docs calls with --host all in package.json build

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: sensitive frontmatter for Factory Droid auto-invocation safety

Add sensitive: true to 6 skill templates with side effects that Factory
Droids shouldn't auto-invoke (ship, land-and-deploy, guard, careful,
freeze, unfreeze). The field is:
- Factory: emitted as disable-model-invocation: true
- Claude/Codex: stripped from output by transformFrontmatter()

Also fix Claude host path: call transformFrontmatter() for Claude to
strip the sensitive: field from Claude output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: gstack-platform-detect binary for multi-host debugging

Bash script that prints a table of installed AI coding agents (Claude,
Codex, Factory Droid, Kiro) with versions, skill paths, and gstack
installation status. Useful for debugging multi-host setups.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Factory Droid support in setup script

- Add factory to --host values (auto-detected via command -v droid)
- Add .factory/ skill doc generation step alongside .agents/
- Add create_factory_runtime_root() and link_factory_skill_dirs()
  helpers mirroring the Codex equivalents
- Factory install section creates ~/.factory/skills/ with symlinks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: Factory Droid awareness in skill-check and uninstall

- skill-check.ts: add Factory skills validation and freshness check
- gstack-uninstall: add Factory artifact cleanup (~/.factory/skills/gstack*
  and per-project .factory/ sidecar)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: Factory Droid generation + --host all test suites

Add 13 new tests:
- Factory output paths, frontmatter (user-invocable, disable-model-invocation)
- Sensitive vs non-sensitive skill classification
- Path rewrites (no .claude/skills/ in Factory output)
- /codex skill exclusion, openai.yaml absence
- Factory keeps Codex integration blocks (for second opinions)
- --host droid alias, --dry-run freshness, preamble paths
- --host all generates for all 3 hosts
- Setup script host validation updated for factory

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: Factory Droid install instructions + CI freshness check

- README: add Factory Droid section with install instructions and
  restart note (Factory requires restart to rescan skills)
- CI: add Factory skill doc freshness verification to skill-docs.yml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: generated Factory Droid skill output (.factory/skills/)

29 skills generated for Factory Droid with:
- user-invocable: true on all skills
- disable-model-invocation: true on 6 sensitive skills
- .factory/skills/ paths (no .claude/skills/ references)
- $GSTACK_ROOT env vars for runtime root detection
- Tool name translation (Claude tool names → generic phrasing)

Committed to git for CI freshness checks and direct consumption.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: add Factory Droid P1 TODO for browse MCP server

Add 3 TODOs under new ## Factory Droid section:
- P1: Browse MCP server (Option B, deeper Factory integration)
- P3: .agent/skills/ dual output for cross-agent compatibility
- P3: Custom Droid definitions alongside skills

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.5.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 08:57:34 -07:00
Garry Tan ea7dbc9a39 fix: sidebar prompt injection defense (v0.13.4.0) (#611)
* fix: sidebar prompt injection defense — XML framing, command allowlist, arg plumbing

Three security fixes for the Chrome sidebar:

1. XML-framed prompts with trust boundaries and escape of < > & in user
   messages to prevent tag injection attacks.

2. Bash command allowlist in system prompt — only browse binary commands
   ($B goto, $B click, etc.) allowed. All other bash commands forbidden.

3. Fix sidebar-agent.ts ignoring queued args — server-side --model and
   --allowedTools changes were silently dropped because the agent rebuilt
   args from scratch instead of using the queue entry.

Also defaults sidebar to Opus (harder to manipulate).

12 new tests covering XML escaping, command allowlist, Opus default,
trust boundary instructions, and arg plumbing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.4.0)

ML prompt injection defense design doc + P0 TODO for follow-up PR.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: clear stale worktree and claude session on sidebar reconnect

loadSession() was restoring worktreePath and claudeSessionId from prior
crashes. The worktree directory no longer existed (deleted on cleanup)
and --resume with a dead session ID caused claude to fail silently.

Now validates worktree exists on load and clears stale claude session
IDs on every server restart.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 22:10:35 -06:00
Garry Tan cd66fc2f89 fix: 6 critical fixes + community PR guardrails (v0.13.2.0) (#602)
* fix(security): commit bun.lock to pin dependency versions

Remove bun.lock from .gitignore and commit the lockfile. Every bun install
now uses exact pinned versions instead of resolving floating ^ ranges from
npm fresh. Closes the supply-chain vector from #566.

Co-Authored-By: boinger <boinger@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: gstack-slug falls back to dirname/unknown when git context is absent

Add || true to git commands and fallback defaults so gstack-slug works
outside git repos. Prevents unbound variable crash that kills every
review skill when no git context exists.

Co-Authored-By: collinstraka-clov <collinstraka-clov@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: setup auto-selects default after 10s timeout to prevent CI hangs

Add -t 10 to the read command in the skill-prefix prompt. In CI, Docker,
and Conductor workspaces where a TTY exists but nobody is watching, the
prompt now auto-selects short names after 10 seconds instead of blocking
forever.

Co-Authored-By: stedfn <stedfn@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: browse CLI Windows lockfile — use string flag instead of numeric constants

Bun compiled binaries on Windows don't handle numeric fs.constants
correctly. The string flag 'wx' is semantically identical to
O_CREAT | O_EXCL | O_WRONLY per Node docs and works on all platforms.

Fixes #599

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add ~/.gstack/projects/ to plan file search path

/office-hours writes design docs to ~/.gstack/projects/$SLUG/ but /ship
and /review only searched ~/.claude/plans, ~/.codex/plans, and .gstack/plans.
Add the project-scoped directory as the first search location so plan
validation finds design docs created by the standard workflow.

Fixes #591

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: autoplan dual-voice — sequential foreground execution instead of broken parallel

Background subagents don't inherit tool permissions in Claude Code, so the
Claude subagent in dual-voice mode was silently failing on every invocation.
Every autoplan run was degrading to single-reviewer mode without warning.

Change all three phases (CEO, Design, Eng) from "simultaneously" to
sequential foreground execution: Claude subagent first (Agent tool,
foreground), then Codex (Bash). Both complete before the consensus table.

Fixes #497

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: regenerate SKILL.md files from updated templates

Regenerated from autoplan/SKILL.md.tmpl (dual-voice fix) and
scripts/resolvers/review.ts (plan search path fix).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add community PR guardrails — protect ETHOS.md and voice

Add explicit CLAUDE.md rule requiring AskUserQuestion before accepting
any community PR that touches ETHOS.md, removes promotional material,
or changes Garry's voice. No exceptions, no auto-merging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.2.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: gen-skill-docs detects symlink loop, skips codex write that overwrites Claude SKILL.md

When .agents/skills/gstack is symlinked to the repo root (vendored dev mode),
gen-skill-docs --host codex was writing the Codex-transformed SKILL.md through
the symlink, overwriting the Claude version. This caused SKILL.md and
agents/openai.yaml to silently revert to Codex paths after every build.

Now detects when the codex output path resolves to the same real file as the
Claude output and skips the write. Content is still generated for token budget
tracking. The openai.yaml write is also skipped for the same symlink case.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: resolve all 7 test failures — version sync, zsh glob guard, symlink-aware codex tests

1. package.json version synced with VERSION file (0.13.3.0)
2. design-shotgun/SKILL.md.tmpl: added setopt +o nomatch guard to
   bash block with variant-*.png glob
3. Codex generation tests: skip skills where .agents/skills/{name}
   is a symlink back to repo root (vendored dev mode). These can't
   have proper codex content since gen-skill-docs skips the write
   to avoid overwriting the Claude SKILL.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: boinger <boinger@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: collinstraka-clov <collinstraka-clov@users.noreply.github.com>
Co-authored-by: stedfn <stedfn@users.noreply.github.com>
2026-03-28 11:31:56 -06:00
Garry Tan 247fc3ba0b feat: user sovereignty — AI models recommend, users decide (v0.13.2.0) (#603)
* feat: user sovereignty — AI models recommend, users decide

When Claude and Codex agree on a scope change, they now present it to the
user instead of auto-incorporating it. Adds User Sovereignty as the third
core principle in ETHOS.md. Fixes the cross-model tension template in
review.ts to present both perspectives neutrally instead of judging. Adds
User Challenge category to autoplan with proper contract updates (intro,
important rules, audit trail, gate handling). Adds Outside Voice Integration
Rule to CEO and eng review templates.

* chore: regenerate SKILL.md files from updated templates

* chore: bump version and changelog (v0.13.2.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: proper gstack description in openai.yaml + block Codex from rewriting it

Codex kept overwriting agents/openai.yaml with a browse-only description.
Two fixes: (1) better description covering full PM/dev/eng/CEO/QA scope,
(2) add agents/ to the filesystem boundary so Codex stops modifying it.

* chore: regenerate SKILL.md files with updated filesystem boundary

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 10:25:37 -06:00
Garry Tan 7450b5160b fix: security audit remediation — 12 fixes, 20 tests (v0.13.1.0) (#595)
* fix: remove auth token from /health, secure extension bootstrap (CRITICAL-02 + HIGH-03)

- Remove token from /health response (was leaked to any localhost process)
- Write .auth.json to extension dir for Manifest V3 bootstrap
- sidebar-agent reads token from state file via BROWSE_STATE_FILE env var
- Remove getToken handler from extension (token via health broadcast)
- Extension loads token before first health poll to prevent race condition

* fix: require auth on cookie-picker data routes (CRITICAL-01)

- Add Bearer token auth gate on all /cookie-picker/* data/action routes
- GET /cookie-picker HTML page stays unauthenticated (UI shell)
- Token embedded in served HTML for picker's fetch calls
- CORS preflight now allows Authorization header

* fix: add state file TTL and plaintext cookie warning (HIGH-02)

- Add savedAt timestamp to state save output
- Warn on load if state file older than 7 days
- Auto-delete stale state files (>7 days) on server startup
- Warning about plaintext cookie storage in save message

* fix: innerHTML XSS in extension content script and sidepanel (MEDIUM-01)

- content.js: replace innerHTML with createElement/textContent for ref panel
- sidepanel.js: escape entry.command with escapeHtml() in activity feed
- Both found by security audit + Codex adversarial red team

* fix: symlink bypass in validateReadPath (MEDIUM-02)

- Always resolve to absolute path first (fixes relative path bypass)
- Use realpathSync to follow symlinks before boundary check
- Throw on non-ENOENT realpathSync failures (explicit over silent)
- Resolve SAFE_DIRECTORIES through realpathSync (macOS /tmp → /private/tmp)
- Resolve directory part for non-existent files (ENOENT with symlinked parent)

* fix: freeze hook symlink bypass and prefix collision (MEDIUM-03)

- Add POSIX-portable path resolution (cd + pwd -P, works on macOS)
- Fix prefix collision: /project-evil no longer matches /project freeze dir
- Use trailing slash in boundary check to require directory boundary

* fix: shell script injection in gstack-config and telemetry (MEDIUM-04)

- gstack-config: validate keys (alphanumeric+underscore only)
- gstack-config: use grep -F (fixed string) instead of -E (regex)
- gstack-config: escape sed special chars in values, drop newlines
- gstack-telemetry-log: sanitize REPO_SLUG and BRANCH via json_safe()

* test: 20 security tests for audit remediation

- server-auth: verify token removed from /health, auth on /refs, /activity/*
- cookie-picker: auth required on data routes, HTML page unauthenticated
- path-validation: symlink bypass blocked, realpathSync failure throws
- gstack-config: regex key rejected, sed special chars preserved
- state-ttl: savedAt timestamp, 7-day TTL warning
- telemetry: branch/repo with quotes don't corrupt JSON
- adversarial: sidepanel escapes entry.command, freeze prefix collision

* chore: bump version and changelog (v0.13.1.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: tone down changelog — defense in depth, not catastrophic bugs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-28 08:35:24 -06:00
Garry Tan 78bc1d1968 feat: design binary — real UI mockup generation for gstack skills (v0.13.0.0) (#551)
* docs: design tools v1 plan — visual mockup generation for gstack skills

Full design doc covering the `design` binary that wraps OpenAI's GPT Image API
to generate real UI mockups from gstack's design skills. Includes comparison
board UX spec, auth model, 6 CEO expansions (design memory, mockup diffing,
screenshot evolution, design intent verification, responsive variants,
design-to-code prompt), and 9-commit implementation plan.

Reviewed: /office-hours + /plan-eng-review (CLEARED) + /plan-ceo-review
(EXPANSION, 6/6 accepted) + /plan-design-review (2/10 → 8/10).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: design tools prototype validation — GPT Image API works

Prototype script sends 3 design briefs to OpenAI Responses API with
image_generation tool. Results: dashboard (47s, 2.1MB), landing page
(42s, 1.3MB), settings page (37s, 1.3MB) all produce real, implementable
UI mockups with accurate text rendering and clean layouts.

Key finding: Codex OAuth tokens lack image generation scopes. Direct
API key (sk-proj-*) required, stored in ~/.gstack/openai.json.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: design binary core — generate, check, compare commands

Stateless CLI (design/dist/design) wrapping OpenAI Responses API for
UI mockup generation. Three working commands:

- generate: brief -> PNG mockup via gpt-4o + image_generation tool
- check: vision-based quality gate via GPT-4o (text readability, layout
  completeness, visual coherence)
- compare: generates self-contained HTML comparison board with star
  ratings, radio Pick, per-variant feedback, regenerate controls,
  and Submit button that writes structured JSON for agent polling

Auth reads from ~/.gstack/openai.json (0600), falls back to
OPENAI_API_KEY env var. Compiled separately from browse binary
(openai added to devDependencies, not runtime deps).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: design binary variants + iterate commands

variants: generates N style variations with staggered parallel (1.5s
between launches, exponential backoff on 429). 7 built-in style
variations (bold, calm, warm, corporate, dark, playful + default).
Tested: 3/3 variants in 41.6s.

iterate: multi-turn design iteration using previous_response_id for
conversational threading. Falls back to re-generation with accumulated
feedback if threading doesn't retain visual context.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: DESIGN_SETUP + DESIGN_MOCKUP template resolvers

Add generateDesignSetup() and generateDesignMockup() to the existing
design.ts resolver file. Add designDir to HostPaths (claude + codex).
Register DESIGN_SETUP and DESIGN_MOCKUP in the resolver index.

DESIGN_SETUP: $D binary discovery (mirrors $B browse setup pattern).
Falls back to DESIGN_SKETCH if binary not available.

DESIGN_MOCKUP: full visual exploration workflow template — construct
brief from DESIGN.md context, generate 3 variants, open comparison
board in Chrome, poll for user feedback, save approved mockup to
docs/designs/, generate HTML wireframe for implementation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: sync package.json version with VERSION file (0.12.2.0)

Pre-existing mismatch: VERSION was 0.12.2.0 but package.json was
0.12.0.0. Also adds design binary to build script and dev:design
convenience command.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: /office-hours visual design exploration integration

Add {{DESIGN_MOCKUP}} to office-hours template before the existing
{{DESIGN_SKETCH}}. When the design binary is available, /office-hours
generates 3 visual mockup variants, opens a comparison board in Chrome,
and polls for user feedback. Falls back to HTML wireframes if the
design binary isn't built.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: /plan-design-review visual mockup integration

Add {{DESIGN_SETUP}} to pre-review audit and "show me what 10/10
looks like" mockup generation to the 0-10 rating method. When a
design dimension rates below 7/10, the review can generate a mockup
showing the improved version. Falls back to text descriptions if
the design binary isn't available.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: design memory — extract visual language from mockups into DESIGN.md

New `$D extract` command: sends approved mockup to GPT-4o vision,
extracts color palette, typography, spacing, and layout patterns,
writes/updates DESIGN.md with an "Extracted Design Language" section.

Progressive constraint: if DESIGN.md exists, future mockup briefs
include it as style context. If no DESIGN.md, explorations run wide.
readDesignConstraints() reads existing DESIGN.md for brief construction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: mockup diffing + design intent verification

New commands:
- $D diff --before old.png --after new.png: visual diff using GPT-4o
  vision. Returns differences by area with severity (high/medium/low)
  and a matchScore (0-100).
- $D verify --mockup approved.png --screenshot live.png: compares live
  site screenshot against approved design mockup. Pass if matchScore
  >= 70 and no high-severity differences.

Used by /design-review to close the design loop: design -> implement ->
verify visually.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: screenshot-to-mockup evolution ($D evolve)

New command: $D evolve --screenshot current.png --brief "make it calmer"

Two-step process: first analyzes the screenshot via GPT-4o vision to
produce a detailed description, then generates a new mockup that keeps
the existing layout structure but applies the requested changes. Starts
from reality, not blank canvas.

Bridges the gap between /design-review critique ("the spacing is off")
and a visual proposal of the fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: responsive variants + design-to-code prompt

Responsive variants: $D variants --viewports desktop,tablet,mobile
generates mockups at 1536x1024, 1024x1024, and 1024x1536 (portrait)
with viewport-appropriate layout instructions.

Design-to-code prompt: $D prompt --image approved.png extracts colors,
typography, layout, and components via GPT-4o vision, producing a
structured implementation prompt. Reads DESIGN.md for additional
constraint context.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version and changelog (v0.13.0.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: gstack designer as first-class tool in /plan-design-review

Brand the gstack designer prominently, add Step 0.5 for proactive visual
mockup generation before review passes, and update priority hierarchy.
When a plan describes new UI, the skill now offers to generate mockups
with $D variants, run $D check for quality gating, and present a
comparison board via $B goto before any review passes begin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: integrate mockups into review passes and outputs

Thread Step 0.5 mockups through the review workflow: Pass 4 (AI Slop)
evaluates generated mockups visually, Pass 7 uses mockups as evidence
for unresolved decisions, post-pass offers one-shot regeneration after
design changes, and Approved Mockups section records chosen variants
with paths for the implementer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: gstack designer target mockups in /design-review fix loop

Add $D generate for target mockups in Phase 8a.5 — before fixing a
design finding, generate a mockup showing what it should look like.
Add $D verify in Phase 9 to compare fix results against targets.
Not plan mode — goes straight to implementation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: gstack designer AI mockups in /design-consultation Phase 5

Replace HTML preview with $D variants + comparison board when designer
is available (Path A). Use $D extract to derive DESIGN.md tokens from
the approved mockup. Handles both plan mode (write to plan) and
non-plan mode (implement immediately). Falls back to HTML preview
(Path B) when designer binary is unavailable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: make gstack designer the default in /plan-design-review, not optional

The transcript showed the agent writing 5 text descriptions of homepage
variants instead of generating visual mockups, even when the user explicitly
asked for design tools. The skill treated mockups as optional ("Want me to
generate?") when they should be the default behavior.

Changes:
- Rename "Your Visual Design Tool" to "YOUR PRIMARY TOOL" with aggressive
  language: "Don't ask permission. Show it."
- Step 0.5 now generates mockups automatically when DESIGN_READY, no
  AskUserQuestion gatekeeping the default path
- Priority hierarchy: mockups are "non-negotiable" not "if available"
- Step 0D tells the user mockups are coming next
- DESIGN_NOT_AVAILABLE fallback now tells user what they're missing

The only valid reasons to skip mockups: no UI scope, or designer not
installed. Everything else generates by default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: persist design mockups to ~/.gstack/projects/$SLUG/designs/

Mockups were going to .context/mockups/ (gitignored, workspace-local).
This meant designs disappeared when switching workspaces or conversations,
and downstream skills couldn't reference approved mockups from earlier
reviews.

Now all three design skills save to persistent project-scoped dirs:
- /plan-design-review: ~/.gstack/projects/$SLUG/designs/<screen>-<date>/
- /design-consultation: ~/.gstack/projects/$SLUG/designs/design-system-<date>/
- /design-review: ~/.gstack/projects/$SLUG/designs/design-audit-<date>/

Each directory gets an approved.json recording the user's pick, feedback,
and branch. This lets /design-review verify against mockups that
/plan-design-review approved, and design history is browsable via
ls ~/.gstack/projects/$SLUG/designs/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: regenerate codex ship skill with zsh glob guards

Picked up setopt +o nomatch guards from main's v0.12.8.1 merge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add browse binary discovery to DESIGN_SETUP resolver

The design setup block now discovers $B alongside $D, so skills can
open comparison boards via $B goto and poll feedback via $B eval.
Falls back to `open` on macOS when browse binary is unavailable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: comparison board DOM polling in plan-design-review

After opening the comparison board, the agent now polls
#status via $B eval instead of asking a rigid AskUserQuestion.
Handles submit (read structured JSON feedback), regenerate
(new variants with updated brief), and $B-unavailable fallback
(free-form text response). The user interacts with the real
board UI, not a constrained option picker.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: comparison board feedback loop integration test

16 tests covering the full DOM polling cycle: structure verification,
submit with pick/rating/comment, regenerate flows (totally different,
more like this, custom text), and the agent polling pattern
(empty → submitted → read JSON). Uses real generateCompareHtml()
from design/src/compare.ts, served via HTTP. Runs in <1s.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add $D serve command for HTTP-based comparison board feedback

The comparison board feedback loop was fundamentally broken: browse blocks
file:// URLs (url-validation.ts:71), so $B goto file://board.html always
fails. The fallback open + $B eval polls a different browser instance.

$D serve fixes this by serving the board over HTTP on localhost. The server
is stateful: stays alive across regeneration rounds, exposes /api/progress
for the board to poll, and accepts /api/reload from the agent to swap in
new board HTML. Stdout carries feedback JSON only; stderr carries telemetry.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: dual-mode feedback + post-submit lifecycle in comparison board

When __GSTACK_SERVER_URL is set (injected by $D serve), the board POSTs
feedback to the server instead of only writing to hidden DOM elements.
After submit: disables all inputs, shows "Return to your coding agent."
After regenerate: shows spinner, polls /api/progress, auto-refreshes on
ready. On POST failure: shows copyable JSON fallback. On progress timeout
(5 min): shows error with /design-shotgun prompt. DOM fallback preserved
for headed browser mode and tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: HTTP serve command endpoints and regeneration lifecycle

11 tests covering: HTML serving with injected server URL, /api/progress
state reporting, submit → done lifecycle, regenerate → regenerating state,
remix with remixSpec, malformed JSON rejection, /api/reload HTML swapping,
missing file validation, and full regenerate → reload → submit round-trip.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add DESIGN_SHOTGUN_LOOP resolver + fix design artifact paths

Adds generateDesignShotgunLoop() resolver for the shared comparison board
feedback loop (serve via HTTP, handle regenerate/remix, AskUserQuestion
fallback, feedback confirmation). Registered as {{DESIGN_SHOTGUN_LOOP}}.

Fixes generateDesignMockup() to use ~/.gstack/projects/$SLUG/designs/
instead of /tmp/ and docs/designs/. Replaces broken $B goto file:// +
$B eval polling with $D compare --serve (HTTP-based, stdout feedback).

Adds CRITICAL PATH RULE guardrail to DESIGN_SETUP: design artifacts must
go to ~/.gstack/projects/$SLUG/designs/, never .context/ or /tmp/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add /design-shotgun standalone design exploration skill

New skill for visual brainstorming: generate AI design variants, open a
comparison board in the user's browser, collect structured feedback, and
iterate. Features: session detection (revisit prior explorations), 5-dimension
context gathering (who, job to be done, what exists, user flow, edge cases),
taste memory (prior approved designs bias new generations), inline variant
preview, configurable variant count, screenshot-to-variants via $D evolve.

Uses {{DESIGN_SHOTGUN_LOOP}} resolver for the feedback loop. Saves all
artifacts to ~/.gstack/projects/$SLUG/designs/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: regenerate SKILL.md files for design-shotgun + resolver changes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add remix UI to comparison board

Per-variant element selectors (Layout, Colors, Typography, Spacing) with
radio buttons in a grid. Remix button collects selections into a remixSpec
object and sends via the same HTTP POST feedback mechanism. Enabled only
when at least one element is selected. Board shows regenerating spinner
while agent generates the hybrid variant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add $D gallery command for design history timeline

Generates a self-contained HTML page showing all prior design explorations
for a project: every variant (approved or not), feedback notes, organized
by date (newest first). Images embedded as base64. Handles corrupted
approved.json gracefully (skips, still shows the session). Empty state
shows "No history yet" with /design-shotgun prompt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: gallery generation — sessions, dates, corruption, empty state

7 tests: empty dir, nonexistent dir, single session with approved variant,
multiple sessions sorted newest-first, corrupted approved.json handled
gracefully, session without approved.json, self-contained HTML (no
external dependencies).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: replace broken file:// polling with {{DESIGN_SHOTGUN_LOOP}}

plan-design-review and design-consultation templates previously used
$B goto file:// + $B eval polling for the comparison board feedback loop.
This was broken (browse blocks file:// URLs). Both templates now use
{{DESIGN_SHOTGUN_LOOP}} which serves via HTTP, handles regeneration in
the same browser tab, and falls back to AskUserQuestion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: add design-shotgun touchfile entries and tier classifications

design-shotgun-path (gate): verify artifacts go to ~/.gstack/, not .context/
design-shotgun-session (gate): verify repeat-run detection + AskUserQuestion
design-shotgun-full (periodic): full round-trip with real design binary

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: regenerate SKILL.md files for template refactor

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: comparison board UI improvements — option headers, pick confirmation, grid view

Three changes to the design comparison board:

1. Pick confirmation: selecting "Pick" on Option A shows "We'll move
   forward with Option A" in green, plus a status line above the submit
   button repeating the choice.

2. Clear option headers: each variant now has "Option A" in bold with a
   subtitle above the image, instead of just the raw image.

3. View toggle: top-right Large/Grid buttons switch between single-column
   (default) and 3-across grid view.

Also restructured the bottom section into a 2-column grid: submit/overall
feedback on the left, regenerate controls on the right.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use 127.0.0.1 instead of localhost for serve URL

Avoids DNS resolution issues on some systems where localhost may resolve
to IPv6 ::1 while Bun listens on IPv4 only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: write ALL feedback to disk so agent can poll in background mode

The agent backgrounds $D serve (Claude Code can't block on a subprocess
and do other work simultaneously). With stdout-only feedback delivery,
the agent never sees regenerate/remix feedback.

Fix: write feedback-pending.json (regenerate/remix) and feedback.json
(submit) to disk next to the board HTML. Agent polls the filesystem
instead of reading stdout. Both channels (stdout + disk) are always
active so foreground mode still works.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: DESIGN_SHOTGUN_LOOP uses file polling instead of stdout reading

Update the template resolver to instruct the agent to background $D serve
and poll for feedback-pending.json / feedback.json on a 5-second loop.
This matches the real-world pattern where Claude Code / Conductor agents
can't block on subprocess stdout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: regenerate SKILL.md files for file-polling feedback loop

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: null-safe DOM selectors for post-submit and regenerating states

The user's layout restructure renamed .regenerate-bar → .regen-column,
.submit-bar → .submit-column, and .overall-section → .bottom-section.
The JS still referenced the old class names, causing querySelector to
return null and showPostSubmitState() / showRegeneratingState() to
silently crash. This meant Submit and Regenerate buttons appeared to
work (DOM elements updated, HTTP POST succeeded) but the visual
feedback (disabled inputs, spinner, success message) never appeared.

Fix: use fallback selectors that check both old and new class names,
with null guards so a missing element doesn't crash the function.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: end-to-end feedback roundtrip — browser click to file on disk

The test that proves "changes on the website propagate to Claude Code."
Opens the comparison board in a real headless browser with __GSTACK_SERVER_URL
injected, simulates user clicks (Submit, Regenerate, More Like This), and
verifies that feedback.json / feedback-pending.json land on disk with the
correct structured data.

6 tests covering: submit → feedback.json, post-submit UI lockdown,
regenerate → feedback-pending.json, more-like-this → feedback-pending.json,
regenerate spinner display, and full regen → reload → submit round-trip.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: comprehensive design doc for Design Shotgun feedback loop

Documents the full browser-to-agent feedback architecture: state machine,
file-based polling, port discovery, post-submit lifecycle, and every known
edge case (zombie forms, dead servers, stale spinners, file:// bug,
double-click races, port coordination, sequential generate rule).

Includes ASCII diagrams of the data flow and state transitions, complete
step-by-step walkthrough of happy path and regeneration path, test coverage
map with gaps, and short/medium/long-term improvement ideas.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: plan-design-review agent guardrails for feedback loop

Four fixes to prevent agents from reinventing the feedback loop badly:

1. Sequential generate rule: explicit instruction that $D generate calls
   must run one at a time (API rate-limits concurrent image generation).
2. No-AskUserQuestion-for-feedback rule: agent reads feedback.json instead
   of re-asking what the user picked.
3. Remove file:// references: $B goto file:// was always rejected by
   url-validation.ts. The --serve flag handles everything.
4. Remove $B eval polling reference: no longer needed with HTTP POST.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: design-shotgun Step 3 progressive reveal, silent failure detection, timing estimate

Three production UX bugs fixed:
1. Dead air — now shows timing estimate before generation starts
2. Silent variant drop — replaced $D variants batch with individual $D generate
   calls, each verified for existence and non-zero size with retry
3. No progressive reveal — each variant shown inline via Read tool immediately
   after generation (~60s increments instead of all at ~180s)

Also: /tmp/ then cp as default output pattern (sandbox workaround),
screenshot taken once for evolve path (not per-variant).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: parallel design-shotgun with concept-first confirmation

Step 3 rewritten to concept-first + parallel Agent architecture:
- 3a: generate text concepts (free, instant)
- 3b: AskUserQuestion to confirm/modify before spending API credits
- 3c: launch N Agent subagents in parallel (~60s total regardless of count)
- 3d: show all results, dynamic image list for comparison board

Adds Agent to allowed-tools. Softens plan-design-review sequential
warning to note design-shotgun uses parallel at Tier 2+.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: update project documentation for v0.13.0.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: untrack .agents/skills/ — generated at setup, already gitignored

These files were committed despite .agents/ being in .gitignore.
They regenerate from ./setup --host codex on any machine.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: regenerate design-shotgun SKILL.md for v0.12.12.0 preamble changes

Merge from main brought updated preamble resolver (conditional telemetry,
local JSONL logging) but design-shotgun/SKILL.md wasn't regenerated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:32:59 -06:00
Garry Tan 11695e3aca fix: security audit compliance — credentials, telemetry, bun pin, untrusted warning (v0.12.12.0) (#574)
* fix: replace hardcoded credentials with env vars in documentation

Addresses Snyk W007 (HIGH). Replaces test@example.com/password123 with
$TEST_EMAIL/$TEST_PASSWORD env vars. Adds credential safety and cookie
safety notes.

* fix: make telemetry binary calls conditional on _TEL and binary existence

Addresses Socket's 14 MEDIUM findings for opaque telemetry binary.
Adds local JSONL fallback (always available, inspectable). Remote
binary only runs if _TEL != "off" and binary exists.

* fix: pin bun install to v1.3.10 with existence check

Addresses Snyk W012 (MEDIUM). Pins BUN_VERSION in browse.ts resolver,
Dockerfile.ci, and setup script error message. Adds command -v check
to skip install if bun already present.

* docs: add data flow documentation to review.ts

Addresses Socket HIGH finding (98% confidence). Documents what data
is sent to external review services and what is NOT sent.

* test: add audit compliance regression tests

6 tests enforce Snyk/Socket fixes stay in place: no hardcoded creds,
conditional telemetry, version-pinned bun, untrusted content warning,
data flow docs, all SKILL.md telemetry conditional.

* refactor: remove 2017 lines of dead code from gen-skill-docs.ts

The Placeholder Resolvers section (lines 77-2092) contained duplicate
functions that were superseded by scripts/resolvers/*.ts. The RESOLVERS
map from resolvers/index.ts is the sole resolution path. Verified: zero
call sites outside self-references.

* chore: regenerate SKILL.md files from updated templates

Reflects: conditional telemetry, version-pinned bun install,
untrusted content warning after Navigation commands.

* chore: bump version and changelog (v0.12.12.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:06:58 -06:00
Garry Tan 43c078f19a feat: skill prefix is now a persistent user choice (v0.12.11.0) (#571)
* feat: make skill prefix a persistent, interactive user setting

- Add --prefix flag alongside --no-prefix
- Read/write skill_prefix from ~/.gstack/config.yaml (true/false)
- Interactive prompt on first setup when no preference saved
- Non-TTY environments default to flat names (no prefix)
- Add cleanup_prefixed_claude_symlinks() for reverse direction
- Fix gstack-config sed portability (mktemp+mv instead of BSD sed -i '')
- Add SKILL_PREFIX to preamble output with namespace-aware instruction

* test: add prefix config tests + README switching instructions

8 structural tests for persistent prefix setting:
config reading, --prefix flag, config persistence, interactive
prompt, TTY fallback, reverse cleanup, cleanup ordering, welcome.

* chore: regenerate SKILL.md files with SKILL_PREFIX preamble

* chore: bump version and changelog (v0.12.11.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: reframe changelog as feature, not mea culpa

* docs: update CONTRIBUTING + CLAUDE.md for prefix-aware vendoring

- CONTRIBUTING: vendoring now includes ./setup step for per-skill symlinks
- CONTRIBUTING: prefix choice documented in contributor workflow + dev diagram
- CONTRIBUTING: switching prefix mode section added
- CLAUDE.md: vendored symlink awareness section covers prefix setting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 08:08:15 -07:00
Garry Tan 22ad3e5b64 fix: Codex filesystem boundary — prevent skill-file prompt injection (v0.12.10.0) (#570)
* fix: add filesystem boundary to all codex prompts

Codex CLI can read files outside the repo root despite -s read-only.
It discovers ~/.claude/skills/ and ~/.agents/skills/, treats SKILL.md
files as instructions, and executes preamble scripts instead of
reviewing code. Fix: prepend a boundary instruction to all 11 codex
exec/review callsites across codex/SKILL.md.tmpl (3), autoplan/
SKILL.md.tmpl (3), and scripts/resolvers/review.ts (5). Add rabbit-
hole detection rule and 5 regression tests.

* chore: bump version and changelog (v0.12.10.0)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 08:42:19 -06:00