{"id":"1a2ed8db-6176-48a6-b77c-81fdab7ae552","entityType":"agent","slug":"clawhub-parkertoddbrooks-wip-ai-devops-toolbox","name":"Wip Ai Devops Toolbox Private","canonicalUrl":"https://www.xpersona.co/agent/clawhub-parkertoddbrooks-wip-ai-devops-toolbox","canonicalPath":"/agent/clawhub-parkertoddbrooks-wip-ai-devops-toolbox","generatedAt":"2026-10-09T22:49:30.286Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:42:48.241Z","emptyReason":null},"description":"Complete DevOps toolkit for AI-assisted software development. Release pipeline, license compliance, copyright enforcement, repo visibility guard, identity fi...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 4.9K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s17620xzyc7kfan8m36at57m6n83h8he:wip-ai-devops-toolbox","sourceUrl":"https://clawhub.ai/parkertoddbrooks/wip-ai-devops-toolbox","homepage":"https://clawhub.ai/parkertoddbrooks/skills/wip-ai-devops-toolbox","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/parkertoddbrooks/wip-ai-devops-toolbox","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/parkertoddbrooks/skills/wip-ai-devops-toolbox","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":58,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Wip Ai Devops Toolbox Private technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:42:48.241Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:42:48.241Z","emptyReason":null},"stars":null,"forks":null,"downloads":4886,"packageName":null,"latestVersion":"1.9.72","tractionLabel":"4.9K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:42:48.241Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T04:42:48.241Z","lastCrawledAt":"2026-10-09T04:42:48.241Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T04:42:48.241Z","lastVerifiedAt":null,"highlights":[{"version":"1.9.72","createdAt":"2026-04-21T21:26:17.753Z","changelog":"# AI DevOps Toolbox v1.9.72 ## Promote v1.9.71-alpha series to stable Closes #256. Consolidates 21 alpha prereleases (`v1.9.71-alpha.1` through `v1.9.71-alpha.21`) into a stable v1.9.72 release. No code changes beyond the version bump in the toolbox root `package.json`; the sub-tool code has been stable and dogfooded across the alpha iterations. ## Why The root `package.json` had been sitting at `1.9.71-alpha.21` without a stable promotion. That blocked `deploy-public.sh` from syncing the private repo to the public mirror ... the script gates public release on stable root versions. Symptom during 2026-04-21: wip-branch-guard sub-tool shipped stable (v1.9.82 → v1.9.83 → v1.9.84) to npm successfully, but the public `wipcomputer/wip-ai-devops-toolbox` GitHub releases page did not show any of them because `deploy-public.sh` refused to run with an alpha root. ## What's in the diff - `package.json` - Version bump `1.9.71-alpha.21` → `1.9.72` Everything else flows from `wip-release`: - CHANGELOG.md updated - Git tag `v1.9.72` - GitHub release on private repo - npm publish to `@latest` - `deploy-public.sh` runs, syncs private code (minus `ai/`) to `wipcomputer/wip-ai-devops-toolbox` - Public GitHub release created ## Sub-tool versions at this release | Sub-tool | npm version | |---|---| | `@wipcomputer/wip-branch-guard` | 1.9.84 | | Other sub-tools | See their individual `package.json` | The sub-tool releases have their own cadence; this release is purely the toolbox root bump. ## Co-authors Parker Todd Brooks, Lēsa (oc-lesa-mini, Opus 4.7), Claude Code (cc-mini, Opus 4.7).","fileCount":412,"zipByteSize":1146559},{"version":"1.9.68","createdAt":"2026-04-01T13:28:54.812Z","changelog":"# Release Notes: wip-ai-devops-toolbox v1.9.68 Closes #239 ## Four-track release pipeline The release tool now supports four tracks: alpha, beta, hotfix, and stable. This replaces the single-track model where every release was public. Alpha is silent (no public release notes by default). Beta publishes prerelease notes to the public repo. Hotfix publishes to npm @latest without syncing code to public. Stable is the full deploy: npm + code sync + release notes. Developers can iterate on private, ship betas to testers, and only go public when ready. Version numbering uses standard semver prereleases: `1.9.68-alpha.1`, `1.9.68-beta.1`. The installer (`ldm install --beta` / `--alpha`) pulls the right tag from npm.","fileCount":388,"zipByteSize":1058824},{"version":"1.9.67","createdAt":"2026-03-31T07:29:03.519Z","changelog":"# Release Notes: wip-ai-devops-toolbox v1.9.67 **Date:** 2026-03-30 ## What changed ### Hardcoded path removal Two files in the devops toolbox had paths that assumed a specific username or iCloud layout. **ldm-jobs/backup.sh** referenced `/Users/lesa/Library/Mobile Documents/.../ldm/bin/` to find the `ldm` binary for scheduled backup jobs. This iCloud path was fragile (iCloud sync delays, different usernames). The script now uses `$HOME/.ldm/bin/` which is the standard LDM install location and works on any machine (#301). **test.sh** (the branch guard test harness) had `/Users/lesa` hardcoded for creating temp directories. It now uses `$HOME` so tests run correctly under any user account (#301). ### Earlier changes included in this release **v1.9.66** added auto-combine for release notes from batched PRs (#237). When multiple PRs are merged between releases, their individual RELEASE-NOTES files are automatically combined into a single changelog entry. **v1.9.65** fixed the scaffold-on-main issue (#223) where scaffolding left untracked files that blocked `git pull` on the main working tree. ## Why The backup job is scheduled via LaunchAgent and runs unattended. If the path to `ldm` is wrong, backups silently fail. Moving to `$HOME/.ldm/bin/` aligns with the standard LDM install path and eliminates the iCloud dependency. The test fix ensures CI and local test runs work for all contributors. ## Issues closed - #301 ## How to verify ```bash grep -r \"/Users/lesa\" ldm-jobs/ tools/wip-branch-guard/test.sh # Should return zero results ```","fileCount":387,"zipByteSize":1051963},{"version":"1.9.66","createdAt":"2026-03-30T13:30:02.769Z","changelog":"# Release Notes: wip-ai-devops-toolbox v1.9.66 Auto-combine release notes when batching multiple PRs into a single release. ## The story When multiple PRs merge to main before wip-release runs, the release had no good way to gather all their stories. Each PR might have its own RELEASE-NOTES file committed on the branch, but once the branch merges and the file gets trashed, the next release only sees an empty repo root. The agent had to write a new RELEASE-NOTES file from scratch, losing the narrative that was already reviewed in each PR. Now wip-release looks back through git history. It finds every merge commit since the last tag, checks each one for RELEASE-NOTES files via `git diff-tree` and `git show`, and combines them into a single document. If only one PR had notes, it uses them as-is (fully backwards compatible). If multiple PRs had notes, it wraps them with per-PR section headers, strips duplicate top-level headings, and collects all issue references into a combined list at the end. The detection sits at priority 2.5 in the release notes cascade: after the single-file check (RELEASE-NOTES-v{ver}.md on disk) but before the dev-update fallback. A file on disk always wins. The merged-PR scan only kicks in when nothing is found on disk. ## What changed - New exported function `collectMergedPRNotes()` in `core.mjs` that scans git merge history for RELEASE-NOTES files - Updated `cli.js` to call it at priority 2.5 in the notes detection cascade - Updated help text to document the new detection path - Zero breaking changes. Single-file detection still works exactly as before. ## Issues closed - Closes #237 ## How to verify ```bash # In any repo with multiple merged PRs since last tag, each having RELEASE-NOTES files: wip-release patch --dry-run # Should show: \"Combined release notes from N merged PRs\" ```","fileCount":386,"zipByteSize":1050976},{"version":"1.9.65","createdAt":"2026-03-29T23:58:22.432Z","changelog":"# Release Notes: wip-ai-devops-toolbox v1.9.65 **Fix release notes scaffold on protected branches** When `wip-release patch` runs on main without a RELEASE-NOTES file, it used to scaffold a template directly in the working tree. On repos with branch guards (pre-commit hooks that block commits to main), this scaffolded file could not be removed or committed. It would block `git pull` and leave the working tree dirty. This has happened multiple times across different repos. The fix adds a branch check before scaffolding. If the current branch is main or master, wip-release now prints a clear error telling the user to write release notes on their feature branch before merging, then exits non-zero without creating any files. The scaffold behavior still works on feature branches, where it's actually useful. ## Issues closed - Closes #223 ## How to verify ```bash # On main, without release notes: should error, NOT scaffold cd any-repo && git checkout main wip-release patch # Expected: \"Release notes missing. Write RELEASE-NOTES-v*.md on your feature branch before merging.\" # Expected: no RELEASE-NOTES file created in working tree # On a feature branch: should scaffold as before git checkout -b test/scaffold-check wip-release patch # Expected: scaffolded template created ```","fileCount":385,"zipByteSize":1048103},{"version":"1.9.64","createdAt":"2026-03-29T23:39:32.247Z","changelog":"# Release Notes: wip-ai-devops-toolbox v1.9.64 Closes #295 ## Branch guard: allow extension cleanup The branch guard blocked `rm` on deployed extension directories (`~/.openclaw/extensions/` and `~/.ldm/extensions/`) because those paths live inside git repos. But deployed extensions are managed by `ldm install`, not by hand. When a stale `-private` extension needed to be removed (e.g. `wip-xai-grok-private` replaced by the public `wip-xai-grok`), the agent couldn't clean it up without asking the user to run the command manually. Added an allowlist pattern for `rm` targeting `.openclaw/extensions/` and `.ldm/extensions/` paths. Same approach as the existing `.ldm/state/` allowlist. The guard still blocks `rm` on actual repo source files.","fileCount":384,"zipByteSize":1047018},{"version":"1.9.63","createdAt":"2026-03-29T19:13:07.447Z","changelog":"# Release Notes: wip-ai-devops-toolbox v1.9.63 **Fix all wip-release errors: branch cleanup crashes, shell injection, stale remote refs.** ## The story Every wip-release run produced errors: \"fatal: Not a valid object name +\", \"remote ref does not exist\", and shell injection risks from branch names passed through execSync template strings. These were dismissed as \"non-blocking\" but they cluttered every release output and masked real problems. Root cause: branch cleanup code (sections 10 and 11) used `execSync` with template strings, which breaks on branch names with special characters and allows shell injection. Also tried to delete remote branches that GitHub already deleted during PR merge. Fix: replaced all `execSync` template strings with `execFileSync` array args (safe from injection). Added character validation to skip branches with special chars. Wrapped remote delete in try/catch since GitHub PR merge already handles deletion. ## Issues closed - #231 (continued: release pipeline reliability) ## How to verify ```bash wip-release patch --dry-run # Should show no \"fatal\" or \"Not a valid object name\" errors # Guard tests: cd tools/wip-branch-guard && bash test.sh ```","fileCount":382,"zipByteSize":1045485},{"version":"1.9.62","createdAt":"2026-03-29T19:06:50.414Z","changelog":"# Release Notes: wip-ai-devops-toolbox v1.9.62 **Fix wip-release leaving dirty state on main after every release.** ## The story wip-release writes to 15+ files during a release (root package.json, 12 sub-tool package.json files, SKILL.md, CHANGELOG.md, product docs, trashed release notes). But gitCommitAndTag() only staged 3 files (package.json, CHANGELOG.md, SKILL.md). The other 12+ files were left modified on disk, uncommitted. This blocked git pull on the next operation and required manual `git checkout -- .` every time. Fix: stage all files that wip-release modifies. Sub-tool package.json files, product docs (ai/product/), and trashed release notes (_trash/) are now included in the release commit. ## Issues closed - #231 (wip-release rollback version bumps on failure) ## How to verify ```bash wip-release patch git status # Should show clean working tree after release ```","fileCount":381,"zipByteSize":1043647}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17620xzyc7kfan8m36at57m6n83h8he:wip-ai-devops-toolbox","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17620xzyc7kfan8m36at57m6n83h8he:wip-ai-devops-toolbox` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/parkertoddbrooks/wip-ai-devops-toolbox before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-parkertoddbrooks-wip-ai-devops-toolbox/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-parkertoddbrooks-wip-ai-devops-toolbox/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-parkertoddbrooks-wip-ai-devops-toolbox/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-parkertoddbrooks-wip-ai-devops-toolbox/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-parkertoddbrooks-wip-ai-devops-toolbox/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-parkertoddbrooks-wip-ai-devops-toolbox/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-09T22:49:30.282Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-parkertoddbrooks-wip-ai-devops-toolbox/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-parkertoddbrooks-wip-ai-devops-toolbox/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-parkertoddbrooks-wip-ai-devops-toolbox/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-parkertoddbrooks-wip-ai-devops-toolbox/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T04:42:48.241Z","emptyReason":null},"readme":"Skill: Wip Ai Devops Toolbox Private\n\nOwner: parkertoddbrooks\n\nSummary: Complete DevOps toolkit for AI-assisted software development. Release pipeline, license compliance, copyright enforcement, repo visibility guard, identity fi...\n\nTags: latest:1.9.72\n\nVersion history:\n\nv1.9.72 | 2026-04-21T21:26:17.753Z | user\n\n# AI DevOps Toolbox v1.9.72\n\n## Promote v1.9.71-alpha series to stable\n\nCloses #256.\n\nConsolidates 21 alpha prereleases (`v1.9.71-alpha.1` through `v1.9.71-alpha.21`) into a stable v1.9.72 release. No code changes beyond the version bump in the toolbox root `package.json`; the sub-tool code has been stable and dogfooded across the alpha iterations.\n\n## Why\n\nThe root `package.json` had been sitting at `1.9.71-alpha.21` without a stable promotion. That blocked `deploy-public.sh` from syncing the private repo to the public mirror ... the script gates public release on stable root versions.\n\nSymptom during 2026-04-21: wip-branch-guard sub-tool shipped stable (v1.9.82 → v1.9.83 → v1.9.84) to npm successfully, but the public `wipcomputer/wip-ai-devops-toolbox` GitHub releases page did not show any of them because `deploy-public.sh` refused to run with an alpha root.\n\n## What's in the diff\n\n- `package.json`\n  - Version bump `1.9.71-alpha.21` → `1.9.72`\n\nEverything else flows from `wip-release`:\n\n- CHANGELOG.md updated\n- Git tag `v1.9.72`\n- GitHub release on private repo\n- npm publish to `@latest`\n- `deploy-public.sh` runs, syncs private code (minus `ai/`) to `wipcomputer/wip-ai-devops-toolbox`\n- Public GitHub release created\n\n## Sub-tool versions at this release\n\n| Sub-tool | npm version |\n|---|---|\n| `@wipcomputer/wip-branch-guard` | 1.9.84 |\n| Other sub-tools | See their individual `package.json` |\n\nThe sub-tool releases have their own cadence; this release is purely the toolbox root bump.\n\n## Co-authors\n\nParker Todd Brooks, Lēsa (oc-lesa-mini, Opus 4.7), Claude Code (cc-mini, Opus 4.7).\n\nv1.9.68 | 2026-04-01T13:28:54.812Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.68\n\nCloses #239\n\n## Four-track release pipeline\n\nThe release tool now supports four tracks: alpha, beta, hotfix, and stable. This replaces the single-track model where every release was public.\n\nAlpha is silent (no public release notes by default). Beta publishes prerelease notes to the public repo. Hotfix publishes to npm @latest without syncing code to public. Stable is the full deploy: npm + code sync + release notes. Developers can iterate on private, ship betas to testers, and only go public when ready.\n\nVersion numbering uses standard semver prereleases: `1.9.68-alpha.1`, `1.9.68-beta.1`. The installer (`ldm install --beta` / `--alpha`) pulls the right tag from npm.\n\nv1.9.67 | 2026-03-31T07:29:03.519Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.67\n\n**Date:** 2026-03-30\n\n## What changed\n\n### Hardcoded path removal\n\nTwo files in the devops toolbox had paths that assumed a specific username or iCloud layout.\n\n**ldm-jobs/backup.sh** referenced `/Users/lesa/Library/Mobile Documents/.../ldm/bin/` to find the `ldm` binary for scheduled backup jobs. This iCloud path was fragile (iCloud sync delays, different usernames). The script now uses `$HOME/.ldm/bin/` which is the standard LDM install location and works on any machine (#301).\n\n**test.sh** (the branch guard test harness) had `/Users/lesa` hardcoded for creating temp directories. It now uses `$HOME` so tests run correctly under any user account (#301).\n\n### Earlier changes included in this release\n\n**v1.9.66** added auto-combine for release notes from batched PRs (#237). When multiple PRs are merged between releases, their individual RELEASE-NOTES files are automatically combined into a single changelog entry.\n\n**v1.9.65** fixed the scaffold-on-main issue (#223) where scaffolding left untracked files that blocked `git pull` on the main working tree.\n\n## Why\n\nThe backup job is scheduled via LaunchAgent and runs unattended. If the path to `ldm` is wrong, backups silently fail. Moving to `$HOME/.ldm/bin/` aligns with the standard LDM install path and eliminates the iCloud dependency. The test fix ensures CI and local test runs work for all contributors.\n\n## Issues closed\n\n- #301\n\n## How to verify\n\n```bash\ngrep -r \"/Users/lesa\" ldm-jobs/ tools/wip-branch-guard/test.sh\n# Should return zero results\n```\n\nv1.9.66 | 2026-03-30T13:30:02.769Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.66\n\nAuto-combine release notes when batching multiple PRs into a single release.\n\n## The story\n\nWhen multiple PRs merge to main before wip-release runs, the release had no good way to gather all their stories. Each PR might have its own RELEASE-NOTES file committed on the branch, but once the branch merges and the file gets trashed, the next release only sees an empty repo root. The agent had to write a new RELEASE-NOTES file from scratch, losing the narrative that was already reviewed in each PR.\n\nNow wip-release looks back through git history. It finds every merge commit since the last tag, checks each one for RELEASE-NOTES files via `git diff-tree` and `git show`, and combines them into a single document. If only one PR had notes, it uses them as-is (fully backwards compatible). If multiple PRs had notes, it wraps them with per-PR section headers, strips duplicate top-level headings, and collects all issue references into a combined list at the end.\n\nThe detection sits at priority 2.5 in the release notes cascade: after the single-file check (RELEASE-NOTES-v{ver}.md on disk) but before the dev-update fallback. A file on disk always wins. The merged-PR scan only kicks in when nothing is found on disk.\n\n## What changed\n\n- New exported function `collectMergedPRNotes()` in `core.mjs` that scans git merge history for RELEASE-NOTES files\n- Updated `cli.js` to call it at priority 2.5 in the notes detection cascade\n- Updated help text to document the new detection path\n- Zero breaking changes. Single-file detection still works exactly as before.\n\n## Issues closed\n\n- Closes #237\n\n## How to verify\n\n```bash\n# In any repo with multiple merged PRs since last tag, each having RELEASE-NOTES files:\nwip-release patch --dry-run\n# Should show: \"Combined release notes from N merged PRs\"\n```\n\nv1.9.65 | 2026-03-29T23:58:22.432Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.65\n\n**Fix release notes scaffold on protected branches**\n\nWhen `wip-release patch` runs on main without a RELEASE-NOTES file, it used to scaffold a\ntemplate directly in the working tree. On repos with branch guards (pre-commit hooks that\nblock commits to main), this scaffolded file could not be removed or committed. It would\nblock `git pull` and leave the working tree dirty. This has happened multiple times across\ndifferent repos.\n\nThe fix adds a branch check before scaffolding. If the current branch is main or master,\nwip-release now prints a clear error telling the user to write release notes on their\nfeature branch before merging, then exits non-zero without creating any files. The scaffold\nbehavior still works on feature branches, where it's actually useful.\n\n## Issues closed\n\n- Closes #223\n\n## How to verify\n\n```bash\n# On main, without release notes: should error, NOT scaffold\ncd any-repo && git checkout main\nwip-release patch\n# Expected: \"Release notes missing. Write RELEASE-NOTES-v*.md on your feature branch before merging.\"\n# Expected: no RELEASE-NOTES file created in working tree\n\n# On a feature branch: should scaffold as before\ngit checkout -b test/scaffold-check\nwip-release patch\n# Expected: scaffolded template created\n```\n\nv1.9.64 | 2026-03-29T23:39:32.247Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.64\n\nCloses #295\n\n## Branch guard: allow extension cleanup\n\nThe branch guard blocked `rm` on deployed extension directories (`~/.openclaw/extensions/` and `~/.ldm/extensions/`) because those paths live inside git repos. But deployed extensions are managed by `ldm install`, not by hand. When a stale `-private` extension needed to be removed (e.g. `wip-xai-grok-private` replaced by the public `wip-xai-grok`), the agent couldn't clean it up without asking the user to run the command manually.\n\nAdded an allowlist pattern for `rm` targeting `.openclaw/extensions/` and `.ldm/extensions/` paths. Same approach as the existing `.ldm/state/` allowlist. The guard still blocks `rm` on actual repo source files.\n\nv1.9.63 | 2026-03-29T19:13:07.447Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.63\n\n**Fix all wip-release errors: branch cleanup crashes, shell injection, stale remote refs.**\n\n## The story\n\nEvery wip-release run produced errors: \"fatal: Not a valid object name +\", \"remote ref does not exist\", and shell injection risks from branch names passed through execSync template strings. These were dismissed as \"non-blocking\" but they cluttered every release output and masked real problems.\n\nRoot cause: branch cleanup code (sections 10 and 11) used `execSync` with template strings, which breaks on branch names with special characters and allows shell injection. Also tried to delete remote branches that GitHub already deleted during PR merge.\n\nFix: replaced all `execSync` template strings with `execFileSync` array args (safe from injection). Added character validation to skip branches with special chars. Wrapped remote delete in try/catch since GitHub PR merge already handles deletion.\n\n## Issues closed\n\n- #231 (continued: release pipeline reliability)\n\n## How to verify\n\n```bash\nwip-release patch --dry-run\n# Should show no \"fatal\" or \"Not a valid object name\" errors\n# Guard tests: cd tools/wip-branch-guard && bash test.sh\n```\n\nv1.9.62 | 2026-03-29T19:06:50.414Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.62\n\n**Fix wip-release leaving dirty state on main after every release.**\n\n## The story\n\nwip-release writes to 15+ files during a release (root package.json, 12 sub-tool package.json files, SKILL.md, CHANGELOG.md, product docs, trashed release notes). But gitCommitAndTag() only staged 3 files (package.json, CHANGELOG.md, SKILL.md). The other 12+ files were left modified on disk, uncommitted. This blocked git pull on the next operation and required manual `git checkout -- .` every time.\n\nFix: stage all files that wip-release modifies. Sub-tool package.json files, product docs (ai/product/), and trashed release notes (_trash/) are now included in the release commit.\n\n## Issues closed\n\n- #231 (wip-release rollback version bumps on failure)\n\n## How to verify\n\n```bash\nwip-release patch\ngit status\n# Should show clean working tree after release\n```\n\nv1.9.61 | 2026-03-29T18:59:52.690Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.61\n\n**Add test script for branch guard. Fix node bypass regex.**\n\n## The story\n\nEvery guard bug this session (v1.9.56-59) would have been caught by running a test before merging. This release adds test.sh to the guard that pipes test JSON into guard.mjs and verifies allow/deny results. 30 test cases covering destructive commands, quoted strings (Bug 1/3), compound commands (Bug 2), safe commands, and plan files.\n\nAlso fixes the node bypass regex: `require('fs').writeFileSync` wasn't caught because the regex looked for `fs.writeFile` literally. Broadened to match `writeFile` after `node -e`.\n\n## Issues closed\n\n- #232 (guard test coverage)\n\n## How to verify\n\n```bash\ncd tools/wip-branch-guard && bash test.sh\n# Should show: 30 passed, 0 failed, 3 skipped\n```\n\nv1.9.60 | 2026-03-29T15:45:07.885Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.60\n\n**Fix npm package bloat: exclude worktrees and _trash from published tarball.**\n\n## The story\n\nv1.9.59 published 869 files (3.9 MB) to npm because leftover worktree directories and _trash/ were included in the tarball. The .npmignore only excluded ai/ and .DS_Store. Added _trash/, .worktrees/, _worktrees/, .claude/, .wrangler/ to .npmignore. Also cleaned up 10 stale worktrees from previous sessions.\n\n## Issues closed\n\n- #232 (continued cleanup)\n\n## How to verify\n\n```bash\nnpm pack --dry-run 2>&1 | tail -5\n# Should show ~200 files, not 869\n```\n\nv1.9.59 | 2026-03-29T15:42:07.541Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.59\n\n**Fix three bugs in branch guard destructive command handling.**\n\n## The story\n\nv1.9.56 added destructive command blocking but introduced three bugs because the new code was written differently from the existing guard pattern. The existing guard checks allowed patterns before blocked patterns and works per-command. The new code skipped the allowed check and matched against the entire raw command string, causing false positives on quoted text (blocking `gh issue create` when the body mentioned git commands) and false negatives on compound commands (allowing `rm -f file ; echo done` because `echo` is in the allowed list).\n\nFix: two helper functions that strip quoted content before matching and check each command segment independently. Same pattern as the existing guard code. Also adds `~/.claude/plans/` to the shared state allowlist so plan files are editable.\n\n## Issues closed\n\n- #232 (branch guard three bugs in v1.9.56)\n\n## How to verify\n\n```bash\n# These should now be ALLOWED (were false-positive blocked):\n# gh issue create --body \"use git checkout -- to fix\"\n# echo \"don't run git commit on main\"\n\n# These should now be DENIED (were false-negative allowed):\n# rm -f file ; echo done  (on main)\n\n# These should still be DENIED:\n# git checkout -- file.txt\n# python3 -c \"open('f').write('x')\"\n```\n\nv1.9.58 | 2026-03-29T14:47:30.924Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.58\n\n**Fix deploy-public.sh losing release notes when invoked with relative path.**\n\n## The story\n\nWhen deploy-public.sh was called with `.` as the private repo path (e.g. `bash scripts/deploy-public.sh . wipcomputer/repo`), the script later cd'd into a temp directory. After that, `cd \".\"` no longer pointed to the private repo, so `gh release view` failed silently and release notes fell back to the empty \"Release vX.Y.Z\" default. This has been broken since at least v1.9.51.\n\nFix: resolve PRIVATE_REPO to an absolute path at startup before any cd happens.\n\n## Issues closed\n\n- #228 (continued from v1.9.57)\n\n## How to verify\n\n```bash\n# From a repo directory, run with \".\" and check public release has real notes:\ncd /path/to/private-repo\nbash scripts/deploy-public.sh . wipcomputer/public-repo --dry-run\n```\n\nv1.9.57 | 2026-03-29T14:39:38.507Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.57\n\n**deploy-public.sh now excludes .worktrees/ and _worktrees/ from public repo syncs.**\n\n## The story\n\nv1.9.56 accidentally deployed worktree directories (containing embedded git repos) to the public repo. The deploy script's rsync excluded ai/, .git/, _trash/, and other dev artifacts but didn't exclude worktree directories. Added both .worktrees/ (new convention) and _worktrees/ (old convention) to the exclude list.\n\n## Issues closed\n\n- #228 (deploy-public.sh leaks .worktrees/ to public repo)\n\n## How to verify\n\n```bash\n# Run deploy-public.sh --dry-run and confirm .worktrees/ is not synced\ngrep -n \"worktrees\" scripts/deploy-public.sh\n```\n\nv1.9.56 | 2026-03-29T14:22:57.875Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.56\n\n**Branch guard now blocks destructive git commands on all branches.**\n\n## The story\n\nThe branch guard blocked commits and file writes on main, but allowed destructive git commands that destroy uncommitted work. Commands like `git clean -fd`, `git checkout --`, `git stash drop`, and `git reset --hard` slipped through because they were either in the allowed list or not in the blocked list. These commands destroyed Parker's Finder aliases, other agents' uncommitted edits, and user files multiple times on Mar 28-29.\n\nThe fix adds a new DESTRUCTIVE_PATTERNS list that fires on ALL branches, not just main. The guard also closes several bypass vectors: `node -e` removed from the allowed list, python/node file-write patterns detected, and `git checkout` narrowed to branch-switching only.\n\n## What changed\n\n- Added DESTRUCTIVE_PATTERNS: git clean -f, git checkout --, git stash drop/pop/clear, git reset --hard, git restore, python/node bypasses\n- Removed `git checkout` blanket allow. Now only allows `git checkout <branch>` (switching)\n- Removed `git stash drop` from allowed list\n- Removed `node -e` from allowed bash patterns (bypass vector)\n- Added `git stash show` and `git restore --staged` as safe read-only operations\n- Deny message tells agent to use worktrees and safety checkpoints instead\n\n## Issues closed\n\n- #240 (branch guard + harness directories)\n- #241 (python bypass detection)\n- PR #284\n\n## How to verify\n\n```bash\n# These should all be BLOCKED:\n# git clean -fd\n# git checkout -- somefile\n# git stash drop\n# git stash pop\n# git reset --hard\n# python3 -c \"open('f','w').write('x')\"\n\n# These should still WORK:\n# git checkout main (branch switching)\n# git stash list (read-only)\n# git status, git log, git diff\n# Normal worktree workflow\n```\n\nv1.9.55 | 2026-03-28T19:03:53.175Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.55\n\nForce redeploy: .worktrees guard fix.\n\n## The story\n\nv1.9.53 had the guard fix but deploy-public was missed. v1.9.54 force-redeployed but installer had already cached v1.9.54. This version ensures the public repo and npm are in sync so ldm install deploys the correct guard.mjs with .worktrees convention.\n\n## Issues closed\n\n- #240 (partial)\n\nv1.9.54 | 2026-03-28T18:55:37.190Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.54\n\nForce redeploy: guard files were stale after v1.9.53.\n\n## The story\n\nv1.9.53 published the .worktrees guard fix to npm but ldm install saw the version as current and skipped redeploying the files. The deployed guard.mjs was still the old version. This release forces a version bump so the installer re-deploys.\n\nThis is a bug in the installer: it checks version numbers but not file contents. Filed for future fix.\n\n## Issues closed\n\n- #240 (partial: .worktrees convention)\n\nv1.9.53 | 2026-03-28T18:46:48.882Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.53\n\n**One-line summary of what this release does**\n\nTell the story. What was broken or missing? What did we build? Why does the user care?\nWrite at least one real paragraph of prose. Not just bullets. The release notes gate\nwill block if there is no narrative. Bullets are fine for details, but the story comes first.\n\n## The story\n\n(Write a paragraph here. What was the problem? What does this release fix? Why does it matter?\nThis is what users read. Make it worth reading.)\n\n## Issues closed\n\n- #282\n\n## How to verify\n\n```bash\n# Commands to test the changes\n```\n\nv1.9.52 | 2026-03-27T15:15:16.651Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.52\n\n**Fix branch guard false-blocking bash commands targeting worktree paths**\n\n## What changed\n\n- Branch guard now extracts absolute paths from any bash command (mkdir, cp, mv, touch, etc.) and resolves the git branch from the target path's repo, not the CWD\n- `findRepoRoot()` improved to walk up to existing directories for paths that don't exist yet (handles mkdir for new directories)\n- Added `.ldm/worktrees` to allowed worktree locations alongside `_worktrees/` and `.claude/worktrees`\n\n## Why\n\nWhen Claude Code launches from `~/wipcomputerinc/` (on main) and runs bash commands targeting files inside a worktree (e.g., `mkdir -p /path/to/_worktrees/repo--branch/new-dir/`), the guard only knew how to extract paths from `cd` and `git -C` patterns. Any other command fell back to CWD resolution, saw \"main\", and blocked incorrectly. This caused minutes of wasted time every session.\n\n## Issues closed\n\n- wipcomputer/wip-ldm-os#187\n\n## How to verify\n\n```bash\n# From CWD on main, this should no longer be blocked:\n# mkdir -p /path/to/_worktrees/repo--branch/new-directory/\n# cp file.txt /path/to/_worktrees/repo--branch/\n```\n\nv1.9.51 | 2026-03-24T17:42:20.977Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.51\n\n## Branch Guard: Workspace Files Allowlist (#185)\n\nAdded TOOLS.md, MEMORY.md, IDENTITY.md, SOUL.md, WHERE-TO-WRITE.md, HEARTBEAT.md to the shared state allowlist. Both agents can now write to workspace files on main without being blocked.\n\nPreviously only SHARED-CONTEXT.md was allowed. This broke Lesa's ability to edit her own workspace files during the migration to ~/wipcomputerinc/.\n\n## TECHNICAL.md: Backup Documentation\n\nUpdated LDM Dev Tools.app backup section to reflect the unified backup system. backup.sh now calls `~/.ldm/bin/ldm-backup.sh` (deployed by ldm install from wip-ldm-os-private/scripts/).\n\nv1.9.50 | 2026-03-20T17:40:03.283Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.50\n\n**wip-release: require product update doc on every release.**\n\n## What changed\n\nNew quality gate in wip-release: checks that `ai/dev-updates/product-update/*-product-update.md` was modified since the last release tag. Same pattern as dev-updates, roadmap, and readme-first checks.\n\nThe product update doc is a human-readable test guide. Each release entry has: what changed, how it's supposed to work, and how to test. New entries go at the top. Additive only.\n\n## Why\n\nThree repos now have product update docs but nothing enforced keeping them current. Without the gate, the docs will drift immediately (same problem we had with TECHNICAL.md).\n\n## Issues closed\n\n- #220\n\n## How to verify\n\n```bash\nwip-release patch --dry-run\n# Should warn if product update doc not modified since last release\n```\n\nv1.9.49 | 2026-03-20T16:30:09.647Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.49\n\n**TECHNICAL.md audit: 2 weeks of undocumented features now documented.**\n\n## What changed\n\nFull TECHNICAL.md audit covering v1.9.15 through v1.9.48. Two passes. Key additions:\n\n- **wip-release quality gates:** Technical docs gate, interface coverage gate, product docs auto-sync, all skip flags documented.\n- **deploy-public.sh:** Full 8-step pipeline including GitHub Packages publishing, repo URL rewrite, co-author sync.\n- **wip-license-guard:** Now documented as both CLI and Claude Code PreToolUse hook (guard.mjs). Enforcement details.\n- **wip-branch-guard:** Worktree requirement on branches, non-repo file passthrough, workflow teaching messages.\n- **wip-repos claude:** Cross-repo CLAUDE.md ecosystem generator fully documented.\n- **Source code table:** Missing files added (guard.mjs, claude.mjs, mcp-server.mjs).\n- **Log paths:** Fixed stale /tmp/ references to ~/.ldm/logs/.\n\n## Why\n\n15 releases shipped without TECHNICAL.md updates. Agents reading the docs were missing critical features: release gates, license enforcement hooks, deploy pipeline details.\n\n## Issues closed\n\n- #218\n\n## How to verify\n\n```bash\ngrep \"Interface coverage\" TECHNICAL.md    # new gate\ngrep \"guard.mjs\" TECHNICAL.md             # license-guard hook\ngrep \"GitHub Packages\" TECHNICAL.md       # deploy pipeline\n```\n\nv1.9.48 | 2026-03-20T15:08:37.024Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.48\n\n**Document wip-repos claude command in SKILL.md and TECHNICAL.md.**\n\n## What changed\n\n- SKILL.md: added `wip-repos claude` commands to the wip-repos section\n- TECHNICAL.md: full documentation of how the ecosystem generator works, template locations, delimiter convention\n\n## Why\n\nv1.9.47 shipped the `wip-repos claude` command without updating technical docs. Now documented.\n\n## Issues closed\n\n- #212 (docs portion)\n\n## How to verify\n\n```bash\ngrep \"wip-repos claude\" SKILL.md TECHNICAL.md\n```\n\nv1.9.47 | 2026-03-20T14:20:50.772Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.47\n\n**New: `wip-repos claude` command + CLAUDE.md templates.**\n\n## What changed\n\n### `wip-repos claude` (Phases 1-3 of the CLAUDE.md plan)\n\nNew subcommand that generates cross-repo ecosystem sections in CLAUDE.md files. When an agent opens repo-A, it can't read repo-B. This command pre-generates the context.\n\n```bash\nwip-repos claude              # regenerate all repos\nwip-repos claude my-repo      # regenerate one repo\nwip-repos claude --init       # create CLAUDE.md for repos missing one\nwip-repos claude --dry-run    # preview changes\n```\n\nFeatures:\n- Reads all repos from manifest, extracts metadata (package.json, SKILL.md, directory structure)\n- Generates `## Ecosystem` sections with delimiter comments (`<!-- wip-repos:start/end -->`)\n- Hand-written sections are never overwritten\n- Relevance filtering: only related repos shown (same category + core repos)\n- `--init` creates starter CLAUDE.md from template for repos missing one\n\n### Templates\n\n- `templates/global-claude-md.md` ... universal CLAUDE.md for ~/.claude/CLAUDE.md\n- `templates/repo-claude-md.template` ... per-repo starter with ecosystem placeholder\n\n## Why\n\nAgents lose context across repos. They can't read sibling repos at runtime. Pre-generating cross-repo maps into CLAUDE.md solves this without requiring runtime access.\n\n## Issues closed\n\n- #212 (partial: Phases 1-3 of 6)\n\n## How to verify\n\n```bash\nwip-repos claude --dry-run\n```\n\nv1.9.46 | 2026-03-19T03:34:40.416Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.46\n\n**Centralized worktree management: guard rule, wip-release prune, Dev Guide convention.**\n\n## What changed\n\n### Guard: worktree path warning (#212)\nBranch guard now warns when `git worktree add` creates a worktree outside `_worktrees/`. Shows the convention and suggests `ldm worktree add`. Warning only, not a hard block.\n\n### wip-release: worktree prune (#212)\nNew step 12 in the release pipeline. After branch cleanup, prunes stale worktrees from `_worktrees/` whose branches are merged into main. Automatic cleanup after every release.\n\n### Dev Guide: _worktrees/ convention (#212)\nDocuments the centralized worktree convention:\n- All worktrees go in `_worktrees/<repo-name>--<branch-suffix>/`\n- Use `ldm worktree add` (auto-detects repo, creates in the right place)\n- Guard warns about worktrees outside the convention\n- `wip-release` auto-prunes merged worktrees\n\n## Why\n\nWorktrees created as repo siblings confused iCloud sync, looked like real repos in directory listings, and were never cleaned up. This session alone created 10+ stale worktrees. The convention keeps them organized and the release pipeline cleans them automatically.\n\n## Issues closed\n\n- #212\n- #213\n\n## How to verify\n\n```bash\n# Guard warning:\ncd /path/to/repo\ngit worktree add ../my-worktree -b test   # should warn about _worktrees/\n\n# Correct path:\nldm worktree add cc-mini/test             # creates _worktrees/<repo>--cc-mini--test/\n```\n\nv1.9.45 | 2026-03-19T02:23:32.252Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.45\n\n**Guard now teaches the workflow instead of just blocking.**\n\n## What changed\n\n- **Branch guard error messages overhauled (#213).** When the guard blocks a write on main, it now shows the full 8-step process: worktree, branch, commit, push, PR, merge, wip-release, deploy-public. Includes the lesson that release notes go on the feature branch, not as a separate PR.\n- **Separate error for \"on branch but not in worktree.\"** Tells the agent to go back to main and create a worktree properly.\n- **CLAUDE.md added to shared state allowlist.** Was patched in the deployed guard but missing from source. Now in sync.\n\n## Why\n\nAgents kept getting blocked by the guard and then trying workarounds instead of following the process. The error message said \"Use a worktree\" but didn't explain the full workflow. Today's session hit this 5+ times. The guard works. The gap was agent knowledge.\n\n## Issues closed\n\n- #213\n- #256\n\n## How to verify\n\n```bash\n# In any repo on main, try to edit a file. The error should show the full workflow.\n# In any repo on a branch (not worktree), try to edit. Should show worktree instructions.\n```\n\nv1.9.44 | 2026-03-17T15:24:50.385Z | user\n\n# Guard non-repo files fix + UTC date fix\n\nTwo bugs fixed in one PR.\n\n## Bug 1: Guard blocks files outside git repos (#77)\n\n**Problem:** When Write/Edit targets a file outside any git repo (e.g. `~/.claude/plans/`), `findRepoRoot()` returns null. The guard fell back to CWD (`~/.openclaw` on main) and blocked the operation. Files outside repos aren't the guard's concern.\n\n**Fix:** If `findRepoRoot(filePath)` returns null for Write/Edit operations, allow immediately. The guard only protects git repos from direct-on-main edits.\n\n**File:** `tools/wip-branch-guard/guard.mjs`\n\n## Bug 2: UTC date mismatch in wip-release\n\n**Problem:** Dev-update files are named with local date (e.g. `2026-03-16--cc-mini--...md`). But `new Date().toISOString().split('T')[0]` returns UTC date. After midnight UTC (4 PM PST), the dates diverge. Release notes gate fails to find today's dev-update.\n\n**Fix:** Replaced all three instances of `toISOString()` date extraction with explicit local date construction using `getFullYear()/getMonth()/getDate()`.\n\n**Files:**\n- `tools/wip-release/cli.js` (line 80, dev-update detection)\n- `tools/wip-release/core.mjs` (line 92, CHANGELOG date)\n- `tools/wip-release/core.mjs` (line 582, product docs sync date)\n\nv1.9.43 | 2026-03-17T14:48:54.405Z | user\n\n# Guard non-repo files fix + UTC date fix\n\nTwo bugs fixed in one PR.\n\n## Bug 1: Guard blocks files outside git repos (#77)\n\n**Problem:** When Write/Edit targets a file outside any git repo (e.g. `~/.claude/plans/`), `findRepoRoot()` returns null. The guard fell back to CWD (`~/.openclaw` on main) and blocked the operation. Files outside repos aren't the guard's concern.\n\n**Fix:** If `findRepoRoot(filePath)` returns null for Write/Edit operations, allow immediately. The guard only protects git repos from direct-on-main edits.\n\n**File:** `tools/wip-branch-guard/guard.mjs`\n\n## Bug 2: UTC date mismatch in wip-release\n\n**Problem:** Dev-update files are named with local date (e.g. `2026-03-16--cc-mini--...md`). But `new Date().toISOString().split('T')[0]` returns UTC date. After midnight UTC (4 PM PST), the dates diverge. Release notes gate fails to find today's dev-update.\n\n**Fix:** Replaced all three instances of `toISOString()` date extraction with explicit local date construction using `getFullYear()/getMonth()/getDate()`.\n\n**Files:**\n- `tools/wip-release/cli.js` (line 80, dev-update detection)\n- `tools/wip-release/core.mjs` (line 92, CHANGELOG date)\n- `tools/wip-release/core.mjs` (line 582, product docs sync date)\n\nv1.9.42 | 2026-03-17T13:52:16.991Z | user\n\n# Guard non-repo files fix + UTC date fix\n\nTwo bugs fixed in one PR.\n\n## Bug 1: Guard blocks files outside git repos (#77)\n\n**Problem:** When Write/Edit targets a file outside any git repo (e.g. `~/.claude/plans/`), `findRepoRoot()` returns null. The guard fell back to CWD (`~/.openclaw` on main) and blocked the operation. Files outside repos aren't the guard's concern.\n\n**Fix:** If `findRepoRoot(filePath)` returns null for Write/Edit operations, allow immediately. The guard only protects git repos from direct-on-main edits.\n\n**File:** `tools/wip-branch-guard/guard.mjs`\n\n## Bug 2: UTC date mismatch in wip-release\n\n**Problem:** Dev-update files are named with local date (e.g. `2026-03-16--cc-mini--...md`). But `new Date().toISOString().split('T')[0]` returns UTC date. After midnight UTC (4 PM PST), the dates diverge. Release notes gate fails to find today's dev-update.\n\n**Fix:** Replaced all three instances of `toISOString()` date extraction with explicit local date construction using `getFullYear()/getMonth()/getDate()`.\n\n**Files:**\n- `tools/wip-release/cli.js` (line 80, dev-update detection)\n- `tools/wip-release/core.mjs` (line 92, CHANGELOG date)\n- `tools/wip-release/core.mjs` (line 582, product docs sync date)\n\nv1.9.41 | 2026-03-17T13:40:12.048Z | user\n\n# Doc enforcement gates for wip-release\n\n**Date:** 2026-03-16\n**Closes:** #117, #128\n\n## What changed\n\nTwo new pre-release gates in wip-release:\n\n**Technical Docs Gate (#117):** When source code (*.mjs, *.js, *.ts) changed since the last release tag, checks that SKILL.md or TECHNICAL.md was also modified. Catches code shipping without doc updates. Warns on patch, blocks on minor/major. Skip with `--skip-tech-docs-check`.\n\n**Interface Coverage Gate (#128):** For toolbox repos, scans each tool in tools/*/ for actual interfaces (CLI, Module, MCP, OC Plugin, Skill, CC Hook) and compares to the coverage table in README.md and SKILL.md. Reports: tools missing from table, interfaces detected but not marked Y, interfaces marked Y but not detected, tool count mismatches. Warns on patch, blocks on minor/major. Skip with `--skip-coverage-check`.\n\nBoth follow the same pattern as existing gates (checkProductDocs, checkStaleBranches). Both run in real and dry-run modes.\n\n## Why\n\nSource code was shipping without doc updates constantly. SKILL.md and TECHNICAL.md fell behind the code. Interface coverage tables drifted from reality. These gates catch it before release instead of after.\n\nv1.9.40 | 2026-03-16T22:22:06.993Z | user\n\n# Auto-sync product docs version/date on release\n\n**Date:** 2026-03-16\n**Closes:** #202\n\n## What changed\n\nwip-release now auto-updates version and date lines in product docs before the release commit. No more stale \"Current version: v1.9.1\" when you're shipping v1.9.39.\n\nFiles updated automatically:\n- `ai/product/plans-prds/roadmap.md`: \"Current version\" and \"Last updated\"\n- `ai/product/readme-first-product.md`: \"Last updated\" and \"What's Built (as of vX.Y.Z)\"\n\nRuns between changelog update and git commit (step 3.75). Only touches files that exist. Only updates lines that match the expected patterns.\n\n## Why\n\nThese files were stale from v1.9.1 through v1.9.39 (8 days, 38 releases). Nobody remembered to update them. The existing product docs gate warned about it but couldn't fix it. Now it fixes itself.\n\nv1.9.39 | 2026-03-16T22:06:11.835Z | user\n\n# Wire license-guard as Claude Code PreToolUse hook\n\n**Date:** 2026-03-16\n**Closes:** #130\n\n## What changed\n\nlicense-guard now registers as a Claude Code PreToolUse hook on install. Previously the hook code existed (hook.mjs) but was never wired into the deploy system. Now:\n\n- Renamed hook.mjs to guard.mjs (matches file-guard/branch-guard convention that LDM OS deploy.mjs expects)\n- Added `claudeCode.hook` config to package.json (event: PreToolUse, matcher: Bash, timeout: 5)\n- On next `ldm install`, the hook auto-registers in ~/.claude/settings.json\n\nThe hook blocks git commit and git push when license compliance fails:\n- LICENSE file missing\n- Copyright doesn't match .license-guard.json config\n- CLA.md missing\n- README.md missing ## License section\n- MIT+AGPL config but LICENSE or README only mentions MIT\n\nRepos without .license-guard.json are not affected (the hook silently passes).\n\n## Also done\n\n- Updated plan statuses: license guard Phase 1 complete, bootstrap LDM OS complete\n- Bootstrap LDM OS was already shipped in install.js (lines 740-812)\n\nv1.9.38 | 2026-03-16T21:56:21.025Z | user\n\n# GitHub Packages publish from public repo\n\n**Date:** 2026-03-16\n**Closes:** #193\n\n## What changed\n\n`deploy-public.sh` now publishes to GitHub Packages from the public repo clone after the npm publish step. Previously, GitHub Packages were only published from the private repo during `wip-release`, so they showed on the private repo's Packages tab. Users couldn't see them.\n\nNow packages show on the public repo's Packages tab where users expect to find them. Uses `gh auth token` for authentication (already available from the gh CLI).\n\n## Why\n\nThe Packages tab on public repos was empty. Users visiting wipcomputer/wip-ldm-os or wipcomputer/wip-ai-devops-toolbox saw no packages even though they were published. The packages existed but were linked to the private repo.\n\nv1.9.37 | 2026-03-16T21:31:52.206Z | user\n\n# GitHub Packages publish from public repo\n\n**Date:** 2026-03-16\n**Closes:** #193\n\n## What changed\n\n`deploy-public.sh` now publishes to GitHub Packages from the public repo clone after the npm publish step. Previously, GitHub Packages were only published from the private repo during `wip-release`, so they showed on the private repo's Packages tab. Users couldn't see them.\n\nNow packages show on the public repo's Packages tab where users expect to find them. Uses `gh auth token` for authentication (already available from the gh CLI).\n\n## Why\n\nThe Packages tab on public repos was empty. Users visiting wipcomputer/wip-ldm-os or wipcomputer/wip-ai-devops-toolbox saw no packages even though they were published. The packages existed but were linked to the private repo.\n\nv1.9.36 | 2026-03-16T18:21:16.650Z | user\n\n# GitHub Packages publish from public repo\n\n**Date:** 2026-03-16\n**Closes:** #193\n\n## What changed\n\n`deploy-public.sh` now publishes to GitHub Packages from the public repo clone after the npm publish step. Previously, GitHub Packages were only published from the private repo during `wip-release`, so they showed on the private repo's Packages tab. Users couldn't see them.\n\nNow packages show on the public repo's Packages tab where users expect to find them. Uses `gh auth token` for authentication (already available from the gh CLI).\n\n## Why\n\nThe Packages tab on public repos was empty. Users visiting wipcomputer/wip-ldm-os or wipcomputer/wip-ai-devops-toolbox saw no packages even though they were published. The packages existed but were linked to the private repo.\n\nv1.9.35 | 2026-03-16T18:01:58.541Z | user\n\n# GitHub Packages publish from public repo\n\n**Date:** 2026-03-16\n**Closes:** #193\n\n## What changed\n\n`deploy-public.sh` now publishes to GitHub Packages from the public repo clone after the npm publish step. Previously, GitHub Packages were only published from the private repo during `wip-release`, so they showed on the private repo's Packages tab. Users couldn't see them.\n\nNow packages show on the public repo's Packages tab where users expect to find them. Uses `gh auth token` for authentication (already available from the gh CLI).\n\n## Why\n\nThe Packages tab on public repos was empty. Users visiting wipcomputer/wip-ldm-os or wipcomputer/wip-ai-devops-toolbox saw no packages even though they were published. The packages existed but were linked to the private repo.\n\nv1.9.34 | 2026-03-16T16:32:57.906Z | user\n\n# GitHub Packages publish from public repo\n\n**Date:** 2026-03-16\n**Closes:** #193\n\n## What changed\n\n`deploy-public.sh` now publishes to GitHub Packages from the public repo clone after the npm publish step. Previously, GitHub Packages were only published from the private repo during `wip-release`, so they showed on the private repo's Packages tab. Users couldn't see them.\n\nNow packages show on the public repo's Packages tab where users expect to find them. Uses `gh auth token` for authentication (already available from the gh CLI).\n\n## Why\n\nThe Packages tab on public repos was empty. Users visiting wipcomputer/wip-ldm-os or wipcomputer/wip-ai-devops-toolbox saw no packages even though they were published. The packages existed but were linked to the private repo.\n\nv1.9.33 | 2026-03-15T23:16:02.541Z | user\n\n# --version on all CLIs + issue cleanup\n\n**Date:** 2026-03-15\n**Closes:** #190, #191, #169, #123, #119\n\n## What changed\n\nAll 7 CLI tools now support `--version` and `-v`. Each reads its own `package.json` and prints the version. Previously, `wip-release --version` printed the help text instead of a version number.\n\nTools updated: wip-release, wip-repos, wip-license-guard, wip-repo-permissions, wip-repo-init, wip-readme-format, wip-file-guard, wip-branch-guard.\n\nwip-license-guard also got a proper README (#169) with all commands, config format, and integration docs.\n\n## Issues closed\n\n- #190: wip-release --version should work\n- #191: enforce --version on all CLI tools\n- #169: wip-license-guard needs its own README\n- #123: Merge/Deploy/Install conflated (enforced across v1.9.25-v1.9.30)\n- #119: All destructive tools must have --dry-run (all confirmed)\n\nv1.9.32 | 2026-03-15T23:14:41.115Z | user\n\n# --version on all CLIs + issue cleanup\n\n**Date:** 2026-03-15\n**Closes:** #190, #191, #169, #123, #119\n\n## What changed\n\nAll 7 CLI tools now support `--version` and `-v`. Each reads its own `package.json` and prints the version. Previously, `wip-release --version` printed the help text instead of a version number.\n\nTools updated: wip-release, wip-repos, wip-license-guard, wip-repo-permissions, wip-repo-init, wip-readme-format, wip-file-guard, wip-branch-guard.\n\nwip-license-guard also got a proper README (#169) with all commands, config format, and integration docs.\n\n## Issues closed\n\n- #190: wip-release --version should work\n- #191: enforce --version on all CLI tools\n- #169: wip-license-guard needs its own README\n- #123: Merge/Deploy/Install conflated (enforced across v1.9.25-v1.9.30)\n- #119: All destructive tools must have --dry-run (all confirmed)\n\nv1.9.31 | 2026-03-15T22:53:58.002Z | user\n\n# Release Notes: wip-ai-devops-toolbox v1.9.31\n\nBranch guard no longer blocks global npm operations on main.\n\n## What changed\n\nMoved `npm install -g` and `npm link` from BLOCKED_BASH_PATTERNS to ALLOWED_BASH_PATTERNS in `wip-branch-guard/guard.mjs`. Global npm operations modify `/opt/homebrew/`, not the repo. Local `npm install` (no -g flag) remains blocked.\n\n## Why\n\nDuring LDM OS v0.4.0 dogfood, a CC session couldn't run `npm install -g @wipcomputer/wip-ldm-os@0.4.0` even after Parker explicitly said \"install.\" The guard was too aggressive. Original intent (issue #137) was to block repo writes on main, not system-level package installs.\n\n## Issues closed\n\n- Closes #188 (branch guard blocks npm install -g)\n- Cross-ref: wipcomputer/wip-ldm-os#44\n\n## How to verify\n\n```bash\n# On main branch, these should now succeed:\nnpm install -g @wipcomputer/wip-ldm-os@0.4.0\nnpm link\n# This should still be blocked on main:\nnpm install\n```\n\nv1.9.30 | 2026-03-15T22:17:29.505Z | user\n\n# Release notes must be a file on disk\n\n**Date:** 2026-03-15\n\n## What changed\n\nwip-release no longer accepts the `--notes` flag. Release notes MUST come from a file on disk:\n\n1. `RELEASE-NOTES-v{version}.md` in repo root (auto-detected)\n2. `ai/dev-updates/YYYY-MM-DD--description.md` (auto-detected)\n3. `--notes-file=path` (explicit file path)\n\nIf no file exists, the release is blocked. The gate scaffolds a template (`RELEASE-NOTES-v{version}.md`) so the agent has something to fill in.\n\n## Why\n\nThe `--notes` flag was the root cause of every bad release note. Agents passed one-liners like `--notes=\"fix bug\"` and the gate let them through. Even after we added length checks and changelog detection, agents found ways around it. The flag was an escape hatch that undermined the entire system.\n\nThe file-on-disk requirement solves three problems:\n1. **Reviewability.** The file is on the branch. It shows up in the PR diff. Parker can read and approve the release notes before merge.\n2. **Quality.** Writing a file forces the agent to think about what changed and why. A flag encourages one-liners.\n3. **History.** The file is committed to git. The release notes are part of the repo history, not a transient CLI argument.\n\n## What agents need to do\n\nBefore running `wip-release`:\n1. Write `RELEASE-NOTES-v{version}.md` or `ai/dev-updates/YYYY-MM-DD--description.md`\n2. Commit it on the branch\n3. The file shows up in the PR for review\n4. After merge to main, `wip-release` auto-detects it\n\nIf the agent forgets, `wip-release` blocks and scaffolds a template.\n\nv1.9.29 | 2026-03-15T22:14:08.266Z | user\n\n# Release notes must be a file on disk\n\n**Date:** 2026-03-15\n\n## What changed\n\nwip-release no longer accepts the `--notes` flag. Release notes MUST come from a file on disk:\n\n1. `RELEASE-NOTES-v{version}.md` in repo root (auto-detected)\n2. `ai/dev-updates/YYYY-MM-DD--description.md` (auto-detected)\n3. `--notes-file=path` (explicit file path)\n\nIf no file exists, the release is blocked. The gate scaffolds a template (`RELEASE-NOTES-v{version}.md`) so the agent has something to fill in.\n\n## Why\n\nThe `--notes` flag was the root cause of every bad release note. Agents passed one-liners like `--notes=\"fix bug\"` and the gate let them through. Even after we added length checks and changelog detection, agents found ways around it. The flag was an escape hatch that undermined the entire system.\n\nThe file-on-disk requirement solves three problems:\n1. **Reviewability.** The file is on the branch. It shows up in the PR diff. Parker can read and approve the release notes before merge.\n2. **Quality.** Writing a file forces the agent to think about what changed and why. A flag encourages one-liners.\n3. **History.** The file is committed to git. The release notes are part of the repo history, not a transient CLI argument.\n\n## What agents need to do\n\nBefore running `wip-release`:\n1. Write `RELEASE-NOTES-v{version}.md` or `ai/dev-updates/YYYY-MM-DD--description.md`\n2. Commit it on the branch\n3. The file shows up in the PR for review\n4. After merge to main, `wip-release` auto-detects it\n\nIf the agent forgets, `wip-release` blocks and scaffolds a template.\n\nv1.9.28 | 2026-03-15T19:02:41.483Z | user\n\n# Release Notes Quality Gate\n\n**Date:** 2026-03-15\n\n## What changed\n\nwip-release now blocks ALL releases (patch, minor, major) if the release notes are bad. Previously, patch releases only warned. Now they block.\n\nThe gate checks:\n- Notes must be at least 50 characters\n- Notes can't look like a changelog entry (\"fix: ...\", \"add: ...\", \"update: ...\")\n- Minor/major still require a file (not --notes flag)\n\nIf the gate blocks, it tells you exactly how to fix it: write a RELEASE-NOTES file, write a dev update, or use --notes with at least 50 chars of real description.\n\n## Why\n\nRelease notes were consistently garbage. One-liner --notes flags like \"Fix bug\" or \"Update docs\" sailed through on patch releases. The warnings were ignored by both humans and agents. Every release page on GitHub had thin, useless notes that didn't explain what changed or why.\n\n## Also in this release\n\n- wip-repo-init templates renamed from ai/ to templates/ so they ship with npm install (deploy-public.sh was stripping them)\n- SKILL.md restart notice after install (hooks need session restart)\n- SPEC.md and TECHNICAL.md updated with all 17 tools and LDM OS links\n- Branch guard matcher fix (catches Bash + NotebookEdit)\n- Forced Git Worktrees and Branch Guard sections added to SKILL.md\n\nv1.9.27 | 2026-03-15T17:31:51.698Z | user\n\n# Release Notes Quality Gate\n\n**Date:** 2026-03-15\n\n## What changed\n\nwip-release now blocks ALL releases (patch, minor, major) if the release notes are bad. Previously, patch releases only warned. Now they block.\n\nThe gate checks:\n- Notes must be at least 50 characters\n- Notes can't look like a changelog entry (\"fix: ...\", \"add: ...\", \"update: ...\")\n- Minor/major still require a file (not --notes flag)\n\nIf the gate blocks, it tells you exactly how to fix it: write a RELEASE-NOTES file, write a dev update, or use --notes with at least 50 chars of real description.\n\n## Why\n\nRelease notes were consistently garbage. One-liner --notes flags like \"Fix bug\" or \"Update docs\" sailed through on patch releases. The warnings were ignored by both humans and agents. Every release page on GitHub had thin, useless notes that didn't explain what changed or why.\n\n## Also in this release\n\n- wip-repo-init templates renamed from ai/ to templates/ so they ship with npm install (deploy-public.sh was stripping them)\n- SKILL.md restart notice after install (hooks need session restart)\n- SPEC.md and TECHNICAL.md updated with all 17 tools and LDM OS links\n- Branch guard matcher fix (catches Bash + NotebookEdit)\n- Forced Git Worktrees and Branch Guard sections added to SKILL.md\n\nv1.9.26 | 2026-03-15T16:16:47.620Z | user\n\nAdd restart notice after install/update. Hooks need session restart to take effect.\n\nv1.9.25 | 2026-03-14T17:29:26.636Z | user\n\nFix branch guard matcher (catches Bash + NotebookEdit). Add Forced Git Worktrees and Branch Guard sections to SKILL.md. Update SPEC.md and TECHNICAL.md with all 17 tools and LDM OS links.\n\nv1.9.24 | 2026-03-14T17:05:34.289Z | user\n\nNumber tools in dry run and already-installed lists. Dogfood iteration.\n\nv1.9.23 | 2026-03-14T17:01:44.052Z | user\n\nForce verbatim tool list display. AI must show all 17 tools with descriptions, never summarize.\n\nv1.9.22 | 2026-03-14T16:54:36.080Z | user\n\nAll 17 tools listed with descriptions. New section order: Setup, Infrastructure, Repo Management, License, Release. Conversational prompt.\n\nv1.9.21 | 2026-03-14T16:41:55.083Z | user\n\nAdd Already Installed section with tool descriptions. Dogfood fix.\n\nv1.9.20 | 2026-03-14T16:27:18.679Z | user\n\nMake root package publishable. npm install -g @wipcomputer/wip-ai-devops-toolbox now installs all 12 CLI tools.\n\nArchive index:\n\nArchive v1.9.72: 412 files, 1146559 bytes\n\nFiles: _trash/guide 2/DEV-GUIDE.md (19403b), _trash/guide 2/scripts/deploy-public.sh (5627b), _trash/RELEASE-NOTES-v1-8-0.md (1582b), _trash/RELEASE-NOTES-v1-8-1.md (550b), _trash/RELEASE-NOTES-v1-8-2.md (423b), _trash/RELEASE-NOTES-v1-9-0.md (2646b), _trash/RELEASE-NOTES-v1-9-1.md (3189b), _trash/RELEASE-NOTES-v1-9-10.md (1445b), _trash/RELEASE-NOTES-v1-9-2.md (1768b), _trash/RELEASE-NOTES-v1-9-31.md (936b), _trash/RELEASE-NOTES-v1-9-32.md (610b), _trash/RELEASE-NOTES-v1-9-41.md (416b), _trash/RELEASE-NOTES-v1-9-45.md (1170b), _trash/RELEASE-NOTES-v1-9-46.md (1467b), _trash/RELEASE-NOTES-v1-9-47.md (1460b), _trash/RELEASE-NOTES-v1-9-48.md (542b), _trash/RELEASE-NOTES-v1-9-49.md (1350b), _trash/RELEASE-NOTES-v1-9-50.md (846b), _trash/RELEASE-NOTES-v1-9-51.md (662b), _trash/RELEASE-NOTES-v1-9-52.md (1174b), _trash/RELEASE-NOTES-v1-9-53.md (609b), _trash/RELEASE-NOTES-v1-9-54.md (522b), _trash/RELEASE-NOTES-v1-9-55.md (390b), _trash/RELEASE-NOTES-v1-9-56.md (1809b), _trash/RELEASE-NOTES-v1-9-57.md (692b), _trash/RELEASE-NOTES-v1-9-58.md (855b), _trash/RELEASE-NOTES-v1-9-59.md (1359b), _trash/RELEASE-NOTES-v1-9-6.md (2668b), _trash/RELEASE-NOTES-v1-9-60.md (596b), _trash/RELEASE-NOTES-v1-9-61.md (809b), _trash/RELEASE-NOTES-v1-9-62.md (897b), _trash/RELEASE-NOTES-v1-9-63.md (1199b), _trash/RELEASE-NOTES-v1-9-64.md (751b), _trash/RELEASE-NOTES-v1-9-65.md (1297b), _trash/RELEASE-NOTES-v1-9-66.md (1849b), _trash/RELEASE-NOTES-v1-9-68.md (725b), _trash/RELEASE-NOTES-v1-9-7.md (924b), _trash/RELEASE-NOTES-v1-9-71-alpha-11.md (4841b), _trash/RELEASE-NOTES-v1-9-71-alpha-15.md (1363b), _trash/RELEASE-NOTES-v1-9-71-alpha-7.md (4809b), _trash/RELEASE-NOTES-v1-9-71-alpha-8.md (2479b), _trash/RELEASE-NOTES-v1-9-72-alpha-1.md (2421b), _trash/RELEASE-NOTES-v1-9-72.md (1617b), _trash/RELEASE-NOTES-v1-9-9.md (2667b), _trash/RELEASE-NOTES-v1.9.67.md (1572b), ai/_sort/_trash/ai_old/_trash/DEV-GUIDE-private.md (10068b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-07--15-50--cc-mini--claude-md-repo-paths-fix.md (2322b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-09--11-32--cc-mini--v1.2.0-reorg-and-roadmap.md (2417b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-09--16-45--cc-mini--v1.3.0-toolbox-consolidation.md (2864b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-10--14-00--cc-mini--devops-toolbox-rename-and-licensing.md (3641b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-10--19-00--cc-mini--readme-rewrite-and-release-notes-standard.md (4488b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-10--22-10--cc-mini--skill-md-as-the-real-interface.md (6745b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-10--22-40--cc-mini--smart-install-and-platform-compat.md (2900b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-10--23-00--cc-mini--cross-platform-testing-and-wip-cloud.md (4995b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-11--08-30--cc-mini--github-issues-convention.md (1497b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-11--08-55--cc-mini--fix-hook-duplicates.md (1360b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-11--09-15--cc-mini--fix-eexist-cli-install.md (829b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-11--09-30--cc-mini--trash-release-notes.md (924b), ai/_sort/_trash/ai_old/_trash/dev-updates/2026-03-11--10-15--cc-mini--repo-init-tool.md (1163b), ai/_sort/_trash/ai_old/plan/2026-03-01--cc-mini--repo-permissions-hook.md (4455b), ai/_sort/README.md (573b), ai/_trash/DEV-GUIDE-private.md (10068b), ai/_trash/README.md (702b), ai/DEV-GUIDE-FOR-WIP-ONLY-PRIVATE.md (1318b), ai/dev-updates/2026-03-07--15-50--cc-mini--claude-md-repo-paths-fix.md (2322b), ai/dev-updates/2026-03-09--11-32--cc-mini--v1.2.0-reorg-and-roadmap.md (2417b), ai/dev-updates/2026-03-09--16-45--cc-mini--v1.3.0-toolbox-consolidation.md (2864b), ai/dev-updates/2026-03-10--14-00--cc-mini--devops-toolbox-rename-and-licensing.md (3641b), ai/dev-updates/2026-03-10--19-00--cc-mini--readme-rewrite-and-release-notes-standard.md (4488b), ai/dev-updates/2026-03-10--22-10--cc-mini--skill-md-as-the-real-interface.md (6745b), ai/dev-updates/2026-03-10--22-40--cc-mini--smart-install-and-platform-compat.md (2900b), ai/dev-updates/2026-03-10--23-00--cc-mini--cross-platform-testing-and-wip-cloud.md (4995b), ai/dev-updates/2026-03-11--08-30--cc-mini--github-issues-convention.md (1497b), ai/dev-updates/2026-03-11--08-55--cc-mini--fix-hook-duplicates.md (1360b), ai/dev-updates/2026-03-11--09-15--cc-mini--fix-eexist-cli-install.md (829b), ai/dev-updates/2026-03-11--09-30--cc-mini--trash-release-notes.md (924b), ai/dev-updates/2026-03-11--10-15--cc-mini--repo-init-tool.md (1163b), ai/dev-updates/2026-03-11--13-30--cc-mini--v1.9.0-readme-formatter-and-dev-guide.md (2389b), ai/dev-updates/2026-03-11--14-30--cc-mini--release-gates.md (1763b), ai/dev-updates/2026-03-12--10-39--cc-mini--ldm-os-crosslink.md (673b) (+12 more)\n\nFile v1.9.72:ai/repos/gstack-private/browse/SKILL.md\n\n---\nname: browse\nversion: 1.1.0\ndescription: |\n  Fast headless browser for QA testing and site dogfooding. Navigate any URL, interact with\n  elements, verify page state, diff before/after actions, take annotated screenshots, check\n  responsive layouts, test forms and uploads, handle dialogs, and assert element states.\n  ~100ms per command. Use when you need to test a feature, verify a deployment, dogfood a\n  user flow, or file a bug with evidence. Use when asked to \"open in browser\", \"test the\n  site\", \"take a screenshot\", or \"dogfood this\".\nallowed-tools:\n  - Bash\n  - Read\n  - AskUserQuestion\n\n---\n<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n<!-- Regenerate: bun run gen:skill-docs -->\n\n## Preamble (run first)\n\n```bash\n_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)\n[ -n \"$_UPD\" ] && echo \"$_UPD\" || true\nmkdir -p ~/.gstack/sessions\ntouch ~/.gstack/sessions/\"$PPID\"\n_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')\nfind ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true\n_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)\n_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo \"true\")\n_BRANCH=$(git branch --show-current 2>/dev/null || echo \"unknown\")\necho \"BRANCH: $_BRANCH\"\necho \"PROACTIVE: $_PROACTIVE\"\n_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo \"yes\" || echo \"no\")\necho \"LAKE_INTRO: $_LAKE_SEEN\"\nmkdir -p ~/.gstack/analytics\necho '{\"skill\":\"browse\",\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"repo\":\"'$(basename \"$(git rev-parse --show-toplevel 2>/dev/null)\" 2>/dev/null || echo \"unknown\")'\"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true\n```\n\nIf `PROACTIVE` is `\"false\"`, do not proactively suggest gstack skills — only invoke\nthem when the user explicitly asks. The user opted out of proactive suggestions.\n\nIf output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the \"Inline upgrade flow\" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user \"Running gstack v{to} (just updated!)\" and continue.\n\nIf `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle.\nTell the user: \"gstack follows the **Boil the Lake** principle — always do the complete\nthing when AI makes the marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean\"\nThen offer to open the essay in their default browser:\n\n```bash\nopen https://garryslist.org/posts/boil-the-ocean\ntouch ~/.gstack/.completeness-intro-seen\n```\n\nOnly run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once.\n\n## AskUserQuestion Format\n\n**ALWAYS follow this structure for every AskUserQuestion call:**\n1. **Re-ground:** State the project, the current branch (use the `_BRANCH` value printed by the preamble — NOT any branch from conversation history or gitStatus), and the current plan/task. (1-2 sentences)\n2. **Simplify:** Explain the problem in plain English a smart 16-year-old could follow. No raw function names, no internal jargon, no implementation details. Use concrete examples and analogies. Say what it DOES, not what it's called.\n3. **Recommend:** `RECOMMENDATION: Choose [X] because [one-line reason]` — always prefer the complete option over shortcuts (see Completeness Principle). Include `Completeness: X/10` for each option. Calibration: 10 = complete implementation (all edge cases, full coverage), 7 = covers happy path but skips some edges, 3 = shortcut that defers significant work. If both options are 8+, pick the higher; if one is ≤5, flag it.\n4. **Options:** Lettered options: `A) ... B) ... C) ...` — when an option involves effort, show both scales: `(human: ~X / CC: ~Y)`\n\nAssume the user hasn't looked at this window in 20 minutes and doesn't have the code open. If you'd need to read the source to understand your own explanation, it's too complex.\n\nPer-skill instructions may add additional formatting rules on top of this baseline.\n\n## Completeness Principle — Boil the Lake\n\nAI-assisted coding makes the marginal cost of completeness near-zero. When you present options:\n\n- If Option A is the complete implementation (full parity, all edge cases, 100% coverage) and Option B is a shortcut that saves modest effort — **always recommend A**. The delta between 80 lines and 150 lines is meaningless with CC+gstack. \"Good enough\" is the wrong instinct when \"complete\" costs minutes more.\n- **Lake vs. ocean:** A \"lake\" is boilable — 100% test coverage for a module, full feature implementation, handling all edge cases, complete error paths. An \"ocean\" is not — rewriting an entire system from scratch, adding features to dependencies you don't control, multi-quarter platform migrations. Recommend boiling lakes. Flag oceans as out of scope.\n- **When estimating effort**, always show both scales: human team time and CC+gstack time. The compression ratio varies by task type — use this reference:\n\n| Task type | Human team | CC+gstack | Compression |\n|-----------|-----------|-----------|-------------|\n| Boilerplate / scaffolding | 2 days | 15 min | ~100x |\n| Test writing | 1 day | 15 min | ~50x |\n| Feature implementation | 1 week | 30 min | ~30x |\n| Bug fix + regression test | 4 hours | 15 min | ~20x |\n| Architecture / design | 2 days | 4 hours | ~5x |\n| Research / exploration | 1 day | 3 hours | ~3x |\n\n- This principle applies to test coverage, error handling, documentation, edge cases, and feature completeness. Don't skip the last 10% to \"save time\" — with AI, that 10% costs seconds.\n\n**Anti-patterns — DON'T do this:**\n- BAD: \"Choose B — it covers 90% of the value with less code.\" (If A is only 70 lines more, choose A.)\n- BAD: \"We can skip edge case handling to save time.\" (Edge case handling costs minutes with CC.)\n- BAD: \"Let's defer test coverage to a follow-up PR.\" (Tests are the cheapest lake to boil.)\n- BAD: Quoting only human-team effort: \"This would take 2 weeks.\" (Say: \"2 weeks human / ~1 hour CC.\")\n\n## Contributor Mode\n\nIf `_CONTRIB` is `true`: you are in **contributor mode**. You're a gstack user who also helps make it better.\n\n**At the end of each major workflow step** (not after every single command), reflect on the gstack tooling you used. Rate your experience 0 to 10. If it wasn't a 10, think about why. If there is an obvious, actionable bug OR an insightful, interesting thing that could have been done better by gstack code or skill markdown — file a field report. Maybe our contributor will help make us better!\n\n**Calibration — this is the bar:** For example, `$B js \"await fetch(...)\"` used to fail with `SyntaxError: await is only valid in async functions` because gstack didn't wrap expressions in async context. Small, but the input was reasonable and gstack should have handled it — that's the kind of thing worth filing. Things less consequential than this, ignore.\n\n**NOT worth filing:** user's app bugs, network errors to user's URL, auth failures on user's site, user's own JS logic bugs.\n\n**To file:** write `~/.gstack/contributor-logs/{slug}.md` with **all sections below** (do not truncate — include every section through the Date/Version footer):\n\n```\n# {Title}\n\nHey gstack team — ran into this while using /{skill-name}:\n\n**What I was trying to do:** {what the user/agent was attempting}\n**What happened instead:** {what actually happened}\n**My rating:** {0-10} — {one sentence on why it wasn't a 10}\n\n## Steps to reproduce\n1. {step}\n\n## Raw output\n```\n{paste the actual error or unexpected output here}\n```\n\n## What would make this a 10\n{one sentence: what gstack should have done differently}\n\n**Date:** {YYYY-MM-DD} | **Version:** {gstack version} | **Skill:** /{skill}\n```\n\nSlug: lowercase, hyphens, max 60 chars (e.g. `browse-js-no-await`). Skip if file already exists. Max 3 reports per session. File inline and continue — don't stop the workflow. Tell user: \"Filed gstack field report: {title}\"\n\n## Completion Status Protocol\n\nWhen completing a skill workflow, report status using one of:\n- **DONE** — All steps completed successfully. Evidence provided for each claim.\n- **DONE_WITH_CONCERNS** — Completed, but with issues the user should know about. List each concern.\n- **BLOCKED** — Cannot proceed. State what is blocking and what was tried.\n- **NEEDS_CONTEXT** — Missing information required to continue. State exactly what you need.\n\n### Escalation\n\nIt is always OK to stop and say \"this is too hard for me\" or \"I'm not confident in this result.\"\n\nBad work is worse than no work. You will not be penalized for escalating.\n- If you have attempted a task 3 times without success, STOP and escalate.\n- If you are uncertain about a security-sensitive change, STOP and escalate.\n- If the scope of work exceeds what you can verify, STOP and escalate.\n\nEscalation format:\n```\nSTATUS: BLOCKED | NEEDS_CONTEXT\nREASON: [1-2 sentences]\nATTEMPTED: [what you tried]\nRECOMMENDATION: [what the user should do next]\n```\n\n# browse: QA Testing & Dogfooding\n\nPersistent headless Chromium. First call auto-starts (~3s), then ~100ms per command.\nState persists between calls (cookies, tabs, login sessions).\n\n## SETUP (run this check BEFORE any browse command)\n\n```bash\n_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)\nB=\"\"\n[ -n \"$_ROOT\" ] && [ -x \"$_ROOT/.claude/skills/gstack/browse/dist/browse\" ] && B=\"$_ROOT/.claude/skills/gstack/browse/dist/browse\"\n[ -z \"$B\" ] && B=~/.claude/skills/gstack/browse/dist/browse\nif [ -x \"$B\" ]; then\n  echo \"READY: $B\"\nelse\n  echo \"NEEDS_SETUP\"\nfi\n```\n\nIf `NEEDS_SETUP`:\n1. Tell the user: \"gstack browse needs a one-time build (~10 seconds). OK to proceed?\" Then STOP and wait.\n2. Run: `cd <SKILL_DIR> && ./setup`\n3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash`\n\n## Core QA Patterns\n\n### 1. Verify a page loads correctly\n```bash\n$B goto https://yourapp.com\n$B text                          # content loads?\n$B console                       # JS errors?\n$B network                       # failed requests?\n$B is visible \".main-content\"    # key elements present?\n```\n\n### 2. Test a user flow\n```bash\n$B goto https://app.com/login\n$B snapshot -i                   # see all interactive elements\n$B fill @e3 \"user@test.com\"\n$B fill @e4 \"password\"\n$B click @e5                     # submit\n$B snapshot -D                   # diff: what changed after submit?\n$B is visible \".dashboard\"       # success state present?\n```\n\n### 3. Verify an action worked\n```bash\n$B snapshot                      # baseline\n$B click @e3                     # do something\n$B snapshot -D                   # unified diff shows exactly what changed\n```\n\n### 4. Visual evidence for bug reports\n```bash\n$B snapshot -i -a -o /tmp/annotated.png   # labeled screenshot\n$B screenshot /tmp/bug.png                # plain screenshot\n$B console                                # error log\n```\n\n### 5. Find all clickable elements (including non-ARIA)\n```bash\n$B snapshot -C                   # finds divs with cursor:pointer, onclick, tabindex\n$B click @c1                     # interact with them\n```\n\n### 6. Assert element states\n```bash\n$B is visible \".modal\"\n$B is enabled \"#submit-btn\"\n$B is disabled \"#submit-btn\"\n$B is checked \"#agree-checkbox\"\n$B is editable \"#name-field\"\n$B is focused \"#search-input\"\n$B js \"document.body.textContent.includes('Success')\"\n```\n\n### 7. Test responsive layouts\n```bash\n$B responsive /tmp/layout        # mobile + tablet + desktop screenshots\n$B viewport 375x812              # or set specific viewport\n$B screenshot /tmp/mobile.png\n```\n\n### 8. Test file uploads\n```bash\n$B upload \"#file-input\" /path/to/file.pdf\n$B is visible \".upload-success\"\n```\n\n### 9. Test dialogs\n```bash\n$B dialog-accept \"yes\"           # set up handler\n$B click \"#delete-button\"        # trigger dialog\n$B dialog                        # see what appeared\n$B snapshot -D                   # verify deletion happened\n```\n\n### 10. Compare environments\n```bash\n$B diff https://staging.app.com https://prod.app.com\n```\n\n### 11. Show screenshots to the user\nAfter `$B screenshot`, `$B snapshot -a -o`, or `$B responsive`, always use the Read tool on the output PNG(s) so the user can see them. Without this, screenshots are invisible.\n\n## User Handoff\n\nWhen you hit something you can't handle in headless mode (CAPTCHA, complex auth, multi-factor\nlogin), hand off to the user:\n\n```bash\n# 1. Open a visible Chrome at the current page\n$B handoff \"Stuck on CAPTCHA at login page\"\n\n# 2. Tell the user what happened (via AskUserQuestion)\n#    \"I've opened Chrome at the login page. Please solve the CAPTCHA\n#     and let me know when you're done.\"\n\n# 3. When user says \"done\", re-snapshot and continue\n$B resume\n```\n\n**When to use handoff:**\n- CAPTCHAs or bot detection\n- Multi-factor authentication (SMS, authenticator app)\n- OAuth flows that require user interaction\n- Complex interactions the AI can't handle after 3 attempts\n\nThe browser preserves all state (cookies, localStorage, tabs) across the handoff.\nAfter `resume`, you get a fresh snapshot of wherever the user left off.\n\n## Snapshot Flags\n\nThe snapshot is your primary tool for understanding and interacting with pages.\n\n```\n-i        --interactive           Interactive elements only (buttons, links, inputs) with @e refs\n-c        --compact               Compact (no empty structural nodes)\n-d <N>    --depth                 Limit tree depth (0 = root only, default: unlimited)\n-s <sel>  --selector              Scope to CSS selector\n-D        --diff                  Unified diff against previous snapshot (first call stores baseline)\n-a        --annotate              Annotated screenshot with red overlay boxes and ref labels\n-o <path> --output                Output path for annotated screenshot (default: /tmp/browse-annotated.png)\n-C        --cursor-interactive    Cursor-interactive elements (@c refs — divs with pointer, onclick)\n```\n\nAll flags can be combined freely. `-o` only applies when `-a` is also used.\nExample: `$B snapshot -i -a -C -o /tmp/annotated.png`\n\n**Ref numbering:** @e refs are assigned sequentially (@e1, @e2, ...) in tree order.\n@c refs from `-C` are numbered separately (@c1, @c2, ...).\n\nAfter snapshot, use @refs as selectors in any command:\n```bash\n$B click @e3       $B fill @e4 \"value\"     $B hover @e1\n$B html @e2        $B css @e5 \"color\"      $B attrs @e6\n$B click @c1       # cursor-interactive ref (from -C)\n```\n\n**Output format:** indented accessibility tree with @ref IDs, one element per line.\n```\n  @e1 [heading] \"Welcome\" [level=1]\n  @e2 [textbox] \"Email\"\n  @e3 [button] \"Submit\"\n```\n\nRefs are invalidated on navigation — run `snapshot` again after `goto`.\n\n## Full Command List\n\n### Navigation\n| Command | Description |\n|---------|-------------|\n| `back` | History back |\n| `forward` | History forward |\n| `goto <url>` | Navigate to URL |\n| `reload` | Reload page |\n| `url` | Print current URL |\n\n### Reading\n| Command | Description |\n|---------|-------------|\n| `accessibility` | Full ARIA tree |\n| `forms` | Form fields as JSON |\n| `html [selector]` | innerHTML of selector (throws if not found), or full page HTML if no selector given |\n| `links` | All links as \"text → href\" |\n| `text` | Cleaned page text |\n\n### Interaction\n| Command | Description |\n|---------|-------------|\n| `click <sel>` | Click element |\n| `cookie <name>=<value>` | Set cookie on current page domain |\n| `cookie-import <json>` | Import cookies from JSON file |\n| `cookie-import-browser [browser] [--domain d]` | Import cookies from Comet, Chrome, Arc, Brave, or Edge (opens picker, or use --domain for direct import) |\n| `dialog-accept [text]` | Auto-accept next alert/confirm/prompt. Optional text is sent as the prompt response |\n| `dialog-dismiss` | Auto-dismiss next dialog |\n| `fill <sel> <val>` | Fill input |\n| `header <name>:<value>` | Set custom request header (colon-separated, sensitive values auto-redacted) |\n| `hover <sel>` | Hover element |\n| `press <key>` | Press key — Enter, Tab, Escape, ArrowUp/Down/Left/Right, Backspace, Delete, Home, End, PageUp, PageDown, or modifiers like Shift+Enter |\n| `scroll [sel]` | Scroll element into view, or scroll to page bottom if no selector |\n| `select <sel> <val>` | Select dropdown option by value, label, or visible text |\n| `type <text>` | Type into focused element |\n| `upload <sel> <file> [file2...]` | Upload file(s) |\n| `useragent <string>` | Set user agent |\n| `viewport <WxH>` | Set viewport size |\n| `wait <sel|--networkidle|--load>` | Wait for element, network idle, or page load (timeout: 15s) |\n\n### Inspection\n| Command | Description |\n|---------|-------------|\n| `attrs <sel|@ref>` | Element attributes as JSON |\n| `console [--clear|--errors]` | Console messages (--errors filters to error/warning) |\n| `cookies` | All cookies as JSON |\n| `css <sel> <prop>` | Computed CSS value |\n| `dialog [--clear]` | Dialog messages |\n| `eval <file>` | Run JavaScript from file and return result as string (path must be under /tmp or cwd) |\n| `is <prop> <sel>` | State check (visible/hidden/enabled/disabled/checked/editable/focused) |\n| `js <expr>` | Run JavaScript expression and return result as string |\n| `network [--clear]` | Network requests |\n| `perf` | Page load timings |\n| `storage [set k v]` | Read all localStorage + sessionStorage as JSON, or set <key> <value> to write localStorage |\n\n### Visual\n| Command | Description |\n|---------|-------------|\n| `diff <url1> <url2>` | Text diff between pages |\n| `pdf [path]` | Save as PDF |\n| `responsive [prefix]` | Screenshots at mobile (375x812), tablet (768x1024), desktop (1280x720). Saves as {prefix}-mobile.png etc. |\n| `screenshot [--viewport] [--clip x,y,w,h] [selector|@ref] [path]` | Save screenshot (supports element crop via CSS/@ref, --clip region, --viewport) |\n\n### Snapshot\n| Command | Description |\n|---------|-------------|\n| `snapshot [flags]` | Accessibility tree with @e refs for element selection. Flags: -i interactive only, -c compact, -d N depth limit, -s sel scope, -D diff vs previous, -a annotated screenshot, -o path output, -C cursor-interactive @c refs |\n\n### Meta\n| Command | Description |\n|---------|-------------|\n| `chain` | Run commands from JSON stdin. Format: [[\"cmd\",\"arg1\",...],...] |\n\n### Tabs\n| Command | Description |\n|---------|-------------|\n| `closetab [id]` | Close tab |\n| `newtab [url]` | Open new tab |\n| `tab <id>` | Switch to tab |\n| `tabs` | List open tabs |\n\n### Server\n| Command | Description |\n|---------|-------------|\n| `handoff [message]` | Open visible Chrome at current page for user takeover |\n| `restart` | Restart server |\n| `resume` | Re-snapshot after user takeover, return control to AI |\n| `status` | Health check |\n| `stop` | Shutdown server |\n\nFile v1.9.72:ai/repos/gstack-private/careful/SKILL.md\n\n---\nname: careful\nversion: 0.1.0\ndescription: |\n  Safety guardrails for destructive commands. Warns before rm -rf, DROP TABLE,\n  force-push, git reset --hard, kubectl delete, and similar destructive operations.\n  User can override each warning. Use when touching prod, debugging live systems,\n  or working in a shared environment. Use when asked to \"be careful\", \"safety mode\",\n  \"prod mode\", or \"careful mode\".\nallowed-tools:\n  - Bash\n  - Read\nhooks:\n  PreToolUse:\n    - matcher: \"Bash\"\n      hooks:\n        - type: command\n          command: \"bash ${CLAUDE_SKILL_DIR}/bin/check-careful.sh\"\n          statusMessage: \"Checking for destructive commands...\"\n---\n<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n<!-- Regenerate: bun run gen:skill-docs -->\n\n# /careful — Destructive Command Guardrails\n\nSafety mode is now **active**. Every bash command will be checked for destructive\npatterns before running. If a destructive command is detected, you'll be warned\nand can choose to proceed or cancel.\n\n```bash\nmkdir -p ~/.gstack/analytics\necho '{\"skill\":\"careful\",\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"repo\":\"'$(basename \"$(git rev-parse --show-toplevel 2>/dev/null)\" 2>/dev/null || echo \"unknown\")'\"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true\n```\n\n## What's protected\n\n| Pattern | Example | Risk |\n|---------|---------|------|\n| `rm -rf` / `rm -r` / `rm --recursive` | `rm -rf /var/data` | Recursive delete |\n| `DROP TABLE` / `DROP DATABASE` | `DROP TABLE users;` | Data loss |\n| `TRUNCATE` | `TRUNCATE orders;` | Data loss |\n| `git push --force` / `-f` | `git push -f origin main` | History rewrite |\n| `git reset --hard` | `git reset --hard HEAD~3` | Uncommitted work loss |\n| `git checkout .` / `git restore .` | `git checkout .` | Uncommitted work loss |\n| `kubectl delete` | `kubectl delete pod` | Production impact |\n| `docker rm -f` / `docker system prune` | `docker system prune -a` | Container/image loss |\n\n## Safe exceptions\n\nThese patterns are allowed without warning:\n- `rm -rf node_modules` / `.next` / `dist` / `__pycache__` / `.cache` / `build` / `.turbo` / `coverage`\n\n## How it works\n\nThe hook reads the command from the tool input JSON, checks it against the\npatterns above, and returns `permissionDecision: \"ask\"` with a warning message\nif a match is found. You can always override the warning and proceed.\n\nTo deactivate, end the conversation or start a new one. Hooks are session-scoped.\n\nFile v1.9.72:ai/repos/gstack-private/codex/SKILL.md\n\n---\nname: codex\nversion: 1.0.0\ndescription: |\n  OpenAI Codex CLI wrapper — three modes. Code review: independent diff review via\n  codex review with pass/fail gate. Challenge: adversarial mode that tries to break\n  your code. Consult: ask codex anything with session continuity for follow-ups.\n  The \"200 IQ autistic developer\" second opinion. Use when asked to \"codex review\",\n  \"codex challenge\", \"ask codex\", \"second opinion\", or \"consult codex\".\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Glob\n  - Grep\n  - AskUserQuestion\n---\n<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n<!-- Regenerate: bun run gen:skill-docs -->\n\n## Preamble (run first)\n\n```bash\n_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)\n[ -n \"$_UPD\" ] && echo \"$_UPD\" || true\nmkdir -p ~/.gstack/sessions\ntouch ~/.gstack/sessions/\"$PPID\"\n_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')\nfind ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true\n_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)\n_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo \"true\")\n_BRANCH=$(git branch --show-current 2>/dev/null || echo \"unknown\")\necho \"BRANCH: $_BRANCH\"\necho \"PROACTIVE: $_PROACTIVE\"\n_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo \"yes\" || echo \"no\")\necho \"LAKE_INTRO: $_LAKE_SEEN\"\nmkdir -p ~/.gstack/analytics\necho '{\"skill\":\"codex\",\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"repo\":\"'$(basename \"$(git rev-parse --show-toplevel 2>/dev/null)\" 2>/dev/null || echo \"unknown\")'\"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true\n```\n\nIf `PROACTIVE` is `\"false\"`, do not proactively suggest gstack skills — only invoke\nthem when the user explicitly asks. The user opted out of proactive suggestions.\n\nIf output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the \"Inline upgrade flow\" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user \"Running gstack v{to} (just updated!)\" and continue.\n\nIf `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle.\nTell the user: \"gstack follows the **Boil the Lake** principle — always do the complete\nthing when AI makes the marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean\"\nThen offer to open the essay in their default browser:\n\n```bash\nopen https://garryslist.org/posts/boil-the-ocean\ntouch ~/.gstack/.completeness-intro-seen\n```\n\nOnly run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once.\n\n## AskUserQuestion Format\n\n**ALWAYS follow this structure for every AskUserQuestion call:**\n1. **Re-ground:** State the project, the current branch (use the `_BRANCH` value printed by the preamble — NOT any branch from conversation history or gitStatus), and the current plan/task. (1-2 sentences)\n2. **Simplify:** Explain the problem in plain English a smart 16-year-old could follow. No raw function names, no internal jargon, no implementation details. Use concrete examples and analogies. Say what it DOES, not what it's called.\n3. **Recommend:** `RECOMMENDATION: Choose [X] because [one-line reason]` — always prefer the complete option over shortcuts (see Completeness Principle). Include `Completeness: X/10` for each option. Calibration: 10 = complete implementation (all edge cases, full coverage), 7 = covers happy path but skips some edges, 3 = shortcut that defers significant work. If both options are 8+, pick the higher; if one is ≤5, flag it.\n4. **Options:** Lettered options: `A) ... B) ... C) ...` — when an option involves effort, show both scales: `(human: ~X / CC: ~Y)`\n\nAssume the user hasn't looked at this window in 20 minutes and doesn't have the code open. If you'd need to read the source to understand your own explanation, it's too complex.\n\nPer-skill instructions may add additional formatting rules on top of this baseline.\n\n## Completeness Principle — Boil the Lake\n\nAI-assisted coding makes the marginal cost of completeness near-zero. When you present options:\n\n- If Option A is the complete implementation (full parity, all edge cases, 100% coverage) and Option B is a shortcut that saves modest effort — **always recommend A**. The delta between 80 lines and 150 lines is meaningless with CC+gstack. \"Good enough\" is the wrong instinct when \"complete\" costs minutes more.\n- **Lake vs. ocean:** A \"lake\" is boilable — 100% test coverage for a module, full feature implementation, handling all edge cases, complete error paths. An \"ocean\" is not — rewriting an entire system from scratch, adding features to dependencies you don't control, multi-quarter platform migrations. Recommend boiling lakes. Flag oceans as out of scope.\n- **When estimating effort**, always show both scales: human team time and CC+gstack time. The compression ratio varies by task type — use this reference:\n\n| Task type | Human team | CC+gstack | Compression |\n|-----------|-----------|-----------|-------------|\n| Boilerplate / scaffolding | 2 days | 15 min | ~100x |\n| Test writing | 1 day | 15 min | ~50x |\n| Feature implementation | 1 week | 30 min | ~30x |\n| Bug fix + regression test | 4 hours | 15 min | ~20x |\n| Architecture / design | 2 days | 4 hours | ~5x |\n| Research / exploration | 1 day | 3 hours | ~3x |\n\n- This principle applies to test coverage, error handling, documentation, edge cases, and feature completeness. Don't skip the last 10% to \"save time\" — with AI, that 10% costs seconds.\n\n**Anti-patterns — DON'T do this:**\n- BAD: \"Choose B — it covers 90% of the value with less code.\" (If A is only 70 lines more, choose A.)\n- BAD: \"We can skip edge case handling to save time.\" (Edge case handling costs minutes with CC.)\n- BAD: \"Let's defer test coverage to a follow-up PR.\" (Tests are the cheapest lake to boil.)\n- BAD: Quoting only human-team effort: \"This would take 2 weeks.\" (Say: \"2 weeks human / ~1 hour CC.\")\n\n## Contributor Mode\n\nIf `_CONTRIB` is `true`: you are in **contributor mode**. You're a gstack user who also helps make it better.\n\n**At the end of each major workflow step** (not after every single command), reflect on the gstack tooling you used. Rate your experience 0 to 10. If it wasn't a 10, think about why. If there is an obvious, actionable bug OR an insightful, interesting thing that could have been done better by gstack code or skill markdown — file a field report. Maybe our contributor will help make us better!\n\n**Calibration — this is the bar:** For example, `$B js \"await fetch(...)\"` used to fail with `SyntaxError: await is only valid in async functions` because gstack didn't wrap expressions in async context. Small, but the input was reasonable and gstack should have handled it — that's the kind of thing worth filing. Things less consequential than this, ignore.\n\n**NOT worth filing:** user's app bugs, network errors to user's URL, auth failures on user's site, user's own JS logic bugs.\n\n**To file:** write `~/.gstack/contributor-logs/{slug}.md` with **all sections below** (do not truncate — include every section through the Date/Version footer):\n\n```\n# {Title}\n\nHey gstack team — ran into this while using /{skill-name}:\n\n**What I was trying to do:** {what the user/agent was attempting}\n**What happened instead:** {what actually happened}\n**My rating:** {0-10} — {one sentence on why it wasn't a 10}\n\n## Steps to reproduce\n1. {step}\n\n## Raw output\n```\n{paste the actual error or unexpected output here}\n```\n\n## What would make this a 10\n{one sentence: what gstack should have done differently}\n\n**Date:** {YYYY-MM-DD} | **Version:** {gstack version} | **Skill:** /{skill}\n```\n\nSlug: lowercase, hyphens, max 60 chars (e.g. `browse-js-no-await`). Skip if file already exists. Max 3 reports per session. File inline and continue — don't stop the workflow. Tell user: \"Filed gstack field report: {title}\"\n\n## Completion Status Protocol\n\nWhen completing a skill workflow, report status using one of:\n- **DONE** — All steps completed successfully. Evidence provided for each claim.\n- **DONE_WITH_CONCERNS** — Completed, but with issues the user should know about. List each concern.\n- **BLOCKED** — Cannot proceed. State what is blocking and what was tried.\n- **NEEDS_CONTEXT** — Missing information required to continue. State exactly what you need.\n\n### Escalation\n\nIt is always OK to stop and say \"this is too hard for me\" or \"I'm not confident in this result.\"\n\nBad work is worse than no work. You will not be penalized for escalating.\n- If you have attempted a task 3 times without success, STOP and escalate.\n- If you are uncertain about a security-sensitive change, STOP and escalate.\n- If the scope of work exceeds what you can verify, STOP and escalate.\n\nEscalation format:\n```\nSTATUS: BLOCKED | NEEDS_CONTEXT\nREASON: [1-2 sentences]\nATTEMPTED: [what you tried]\nRECOMMENDATION: [what the user should do next]\n```\n\n## Step 0: Detect base branch\n\nDetermine which branch this PR targets. Use the result as \"the base branch\" in all subsequent steps.\n\n1. Check if a PR already exists for this branch:\n   `gh pr view --json baseRefName -q .baseRefName`\n   If this succeeds, use the printed branch name as the base branch.\n\n2. If no PR exists (command fails), detect the repo's default branch:\n   `gh repo view --json defaultBranchRef -q .defaultBranchRef.name`\n\n3. If both commands fail, fall back to `main`.\n\nPrint the detected base branch name. In every subsequent `git diff`, `git log`,\n`git fetch`, `git merge`, and `gh pr create` command, substitute the detected\nbranch name wherever the instructions say \"the base branch.\"\n\n---\n\n# /codex — Multi-AI Second Opinion\n\nYou are running the `/codex` skill. This wraps the OpenAI Codex CLI to get an independent,\nbrutally honest second opinion from a different AI system.\n\nCodex is the \"200 IQ autistic developer\" — direct, terse, technically precise, challenges\nassumptions, catches things you might miss. Present its output faithfully, not summarized.\n\n---\n\n## Step 0: Check codex binary\n\n```bash\nCODEX_BIN=$(which codex 2>/dev/null || echo \"\")\n[ -z \"$CODEX_BIN\" ] && echo \"NOT_FOUND\" || echo \"FOUND: $CODEX_BIN\"\n```\n\nIf `NOT_FOUND`: stop and tell the user:\n\"Codex CLI not found. Install it: `npm install -g @openai/codex` or see https://github.com/openai/codex\"\n\n---\n\n## Step 1: Detect mode\n\nParse the user's input to determine which mode to run:\n\n1. `/codex review` or `/codex review <instructions>` — **Review mode** (Step 2A)\n2. `/codex challenge` or `/codex challenge <focus>` — **Challenge mode** (Step 2B)\n3. `/codex` with no arguments — **Auto-detect:**\n   - Check for a diff (with fallback if origin isn't available):\n     `git diff origin/<base> --stat 2>/dev/null | tail -1 || git diff <base> --stat 2>/dev/null | tail -1`\n   - If a diff exists, use AskUserQuestion:\n     ```\n     Codex detected changes against the base branch. What should it do?\n     A) Review the diff (code review with pass/fail gate)\n     B) Challenge the diff (adversarial — try to break it)\n     C) Something else — I'll provide a prompt\n     ```\n   - If no diff, check for plan files scoped to the current project:\n     `ls -t ~/.claude/plans/*.md 2>/dev/null | xargs grep -l \"$(basename $(pwd))\" 2>/dev/null | head -1`\n     If no project-scoped match, fall back to: `ls -t ~/.claude/plans/*.md 2>/dev/null | head -1`\n     but warn the user: \"Note: this plan may be from a different project.\"\n   - If a plan file exists, offer to review it\n   - Otherwise, ask: \"What would you like to ask Codex?\"\n4. `/codex <anything else>` — **Consult mode** (Step 2C), where the remaining text is the prompt\n\n---\n\n## Step 2A: Review Mode\n\nRun Codex code review against the current branch diff.\n\n1. Create temp files for output capture:\n```bash\nTMPERR=$(mktemp /tmp/codex-err-XXXXXX.txt)\n```\n\n2. Run the review (5-minute timeout):\n```bash\ncodex review --base <base> -c 'model_reasoning_effort=\"high\"' --enable web_search_cached 2>\"$TMPERR\"\n```\n\nUse `timeout: 300000` on the Bash call. If the user provided custom instructions\n(e.g., `/codex review focus on security`), pass them as the prompt argument:\n```bash\ncodex review \"focus on security\" --base <base> -c 'model_reasoning_effort=\"high\"' --enable web_search_cached 2>\"$TMPERR\"\n```\n\n3. Capture the output. Then parse cost from stderr:\n```bash\ngrep \"tokens used\" \"$TMPERR\" 2>/dev/null || echo \"tokens: unknown\"\n```\n\n4. Determine gate verdict by checking the review output for critical findings.\n   If the output contains `[P1]` — the gate is **FAIL**.\n   If no `[P1]` markers are found (only `[P2]` or no findings) — the gate is **PASS**.\n\n5. Present the output:\n\n```\nCODEX SAYS (code review):\n════════════════════════════════════════════════════════════\n<full codex output, verbatim — do not truncate or summarize>\n════════════════════════════════════════════════════════════\nGATE: PASS                    Tokens: 14,331 | Est. cost: ~$0.12\n```\n\nor\n\n```\nGATE: FAIL (N critical findings)\n```\n\n6. **Cross-model comparison:** If `/review` (Claude's own review) was already run\n   earlier in this conversation, compare the two sets of findings:\n\n```\nCROSS-MODEL ANALYSIS:\n  Both found: [findings that overlap between Claude and Codex]\n  Only Codex found: [findings unique to Codex]\n  Only Claude found: [findings unique to Claude's /review]\n  Agreement rate: X% (N/M total unique findings overlap)\n```\n\n7. Persist the review result:\n```bash\n~/.claude/skills/gstack/bin/gstack-review-log '{\"skill\":\"codex-review\",\"timestamp\":\"TIMESTAMP\",\"status\":\"STATUS\",\"gate\":\"GATE\",\"findings\":N}'\n```\n\nSubstitute: TIMESTAMP (ISO 8601), STATUS (\"clean\" if PASS, \"issues_found\" if FAIL),\nGATE (\"pass\" or \"fail\"), findings (count of [P1] + [P2] markers).\n\n8. Clean up temp files:\n```bash\nrm -f \"$TMPERR\"\n```\n\n---\n\n## Step 2B: Challenge (Adversarial) Mode\n\nCodex tries to break your code — finding edge cases, race conditions, security holes,\nand failure modes that a normal review would miss.\n\n1. Construct the adversarial prompt. If the user provided a focus area\n(e.g., `/codex challenge security`), include it:\n\nDefault prompt (no focus):\n\"Review the changes on this branch against the base branch. Run `git diff origin/<base>` to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems.\"\n\nWith focus (e.g., \"security\"):\n\"Review the changes on this branch against the base branch. Run `git diff origin/<base>` to see the diff. Focus specifically on SECURITY. Your job is to find every way an attacker could exploit this code. Think about injection vectors, auth bypasses, privilege escalation, data exposure, and timing attacks. Be adversarial.\"\n\n2. Run codex exec with **JSONL output** to capture reasoning traces and tool calls (5-minute timeout):\n```bash\ncodex exec \"<prompt>\" -s read-only -c 'model_reasoning_effort=\"xhigh\"' --enable web_search_cached --json 2>/dev/null | python3 -c \"\nimport sys, json\nfor line in sys.stdin:\n    line = line.strip()\n    if not line: continue\n    try:\n        obj = json.loads(line)\n        t = obj.get('type','')\n        if t == 'item.completed' and 'item' in obj:\n            item = obj['item']\n            itype = item.get('type','')\n            text = item.get('text','')\n            if itype == 'reasoning' and text:\n                print(f'[codex thinking] {text}')\n                print()\n            elif itype == 'agent_message' and text:\n                print(text)\n            elif itype == 'command_execution':\n                cmd = item.get('command','')\n                if cmd: print(f'[codex ran] {cmd}')\n        elif t == 'turn.completed':\n            usage = obj.get('usage',{})\n            tokens = usage.get('input_tokens',0) + usage.get('output_tokens',0)\n            if tokens: print(f'\\ntokens used: {tokens}')\n    except: pass\n\"\n```\n\nThis parses codex's JSONL events to extract reasoning traces, tool calls, and the final\nresponse. The `[codex thinking]` lines show what codex reasoned through before its answer.\n\n3. Present the full streamed output:\n\n```\nCODEX SAYS (adversarial challenge):\n════════════════════════════════════════════════════════════\n<full output from above, verbatim>\n════════════════════════════════════════════════════════════\nTokens: N | Est. cost: ~$X.XX\n```\n\n---\n\n## Step 2C: Consult Mode\n\nAsk Codex anything about the codebase. Supports session continuity for follow-ups.\n\n1. **Check for existing session:**\n```bash\ncat .context/codex-session-id 2>/dev/null || echo \"NO_SESSION\"\n```\n\nIf a session file exists (not `NO_SESSION`), use AskUserQuestion:\n```\nYou have an active Codex conversation from earlier. Continue it or start fresh?\nA) Continue the conversation (Codex remembers the prior context)\nB) Start a new conversation\n```\n\n2. Create temp files:\n```bash\nTMPRESP=$(mktemp /tmp/codex-resp-XXXXXX.txt)\nTMPERR=$(mktemp /tmp/codex-err-XXXXXX.txt)\n```\n\n3. **Plan review auto-detection:** If the user's prompt is about reviewing a plan,\nor if plan files exist and the user said `/codex` with no arguments:\n```bash\nls -t ~/.claude/plans/*.md 2>/dev/null | xargs grep -l \"$(basename $(pwd))\" 2>/dev/null | head -1\n```\nIf no project-scoped match, fall back to `ls -t ~/.claude/plans/*.md 2>/dev/null | head -1`\nbut warn: \"Note: this plan may be from a different project — verify before sending to Codex.\"\nRead the plan file and prepend the persona to the user's prompt:\n\"You are a brutally honest technical reviewer. Review this plan for: logical gaps and\nunstated assumptions, missing error handling or edge cases, overcomplexity (is there a\nsimpler approach?), feasibility risks (what could go wrong?), and missing dependencies\nor sequencing issues. Be direct. Be terse. No compliments. Just the problems.\n\nTHE PLAN:\n<plan content>\"\n\n4. Run codex exec with **JSONL output** to capture reasoning traces (5-minute timeout):\n\nFor a **new session:**\n```bash\ncodex exec \"<prompt>\" -s read-only -c 'model_reasoning_effort=\"high\"' --enable web_search_cached --json 2>\"$TMPERR\" | python3 -c \"\nimport sys, json\nfor line in sys.stdin:\n    line = line.strip()\n    if not line: continue\n    try:\n        obj = json.loads(line)\n        t = obj.get('type','')\n        if t == 'thread.started':\n            tid = obj.get('thread_id','')\n            if tid: print(f'SESSION_ID:{tid}')\n        elif t == 'item.completed' and 'item' in obj:\n            item = obj['item']\n            itype = item.get('type','')\n            text = item.get('text','')\n            if itype == 'reasoning' and text:\n                print(f'[codex thinking] {text}')\n                print()\n            elif itype == 'agent_message' and text:\n                print(text)\n            elif itype == 'command_execution':\n                cmd = item.get('command','')\n                if cmd: print(f'[codex ran] {cmd}')\n        elif t == 'turn.completed':\n            usage = obj.get('usage',{})\n            tokens = usage.get('input_tokens',0) + usage.get('output_tokens',0)\n            if tokens: print(f'\\ntokens used: {tokens}')\n    except: pass\n\"\n```\n\nFor a **resumed session** (user chose \"Continue\"):\n```bash\ncodex exec resume <session-id> \"<prompt>\" -s read-only -c 'model_reasoning_effort=\"high\"' --enable web_search_cached --json 2>\"$TMPERR\" | python3 -c \"\n<same python streaming parser as above>\n\"\n```\n\n5. Capture session ID from the streamed output. The parser prints `SESSION_ID:<id>`\n   from the `thread.started` event. Save it for follow-ups:\n```bash\nmkdir -p .context\n```\nSave the session ID printed by the parser (the line starting with `SESSION_ID:`)\nto `.context/codex-session-id`.\n\n6. Present the full streamed output:\n\n```\nCODEX SAYS (consult):\n════════════════════════════════════════════════════════════\n<full output, verbatim — includes [codex thinking] traces>\n════════════════════════════════════════════════════════════\nTokens: N | Est. cost: ~$X.XX\nSession saved — run /codex again to continue this conversation.\n```\n\n7. After presenting, note any points where Codex's analysis differs from your own\n   understanding. If there is a disagreement, flag it:\n   \"Note: Claude Code disagrees on X because Y.\"\n\n---\n\n## Model & Reasoning\n\n**Model:** No model is hardcoded — codex uses whatever its current default is (the frontier\nagentic coding model). This means as OpenAI ships newer models, /codex automatically\nuses them. If the user wants a specific model, pass `-m` through to codex.\n\n**Reasoning effort** varies by mode — use the right level for each task:\n- **Review mode:** `high` — thorough but not slow. Diff review benefits from depth but doesn't need maximum compute.\n- **Challenge (adversarial) mode:** `xhigh` — maximum reasoning power. When trying to break code, you want the model thinking as hard as possible.\n- **Consult mode:** `high` — good balance of depth and speed for conversations.\n\n**Web search:** All codex commands use `--enable web_search_cached` so Codex can look up\ndocs and APIs during review. This is OpenAI's cached index — fast, no extra cost.\n\nIf the user specifies a model (e.g., `/codex review -m gpt-5.1-codex-max`\nor `/codex challenge -m gpt-5.2`), pass the `-m` flag through to codex.\n\n---\n\n## Cost Estimation\n\nParse token count from stderr. Codex prints `tokens used\\nN` to stderr.\n\nDisplay as: `Tokens: N`\n\nIf token count is not available, display: `Tokens: unknown`\n\n---\n\n## Error Handling\n\n- **Binary not found:** Detected in Step 0. Stop with install instructions.\n- **Auth error:** Codex prints an auth error to stderr. Surface the error:\n  \"Codex authentication failed. Run `codex login` in your terminal to authenticate via ChatGPT.\"\n- **Timeout:** If the Bash call times out (5 min), tell the user:\n  \"Codex timed out after 5 minutes. The diff may be too large or the API may be slow. Try again or use a smaller scope.\"\n- **Empty response:** If `$TMPRESP` is empty or doesn't exist, tell the user:\n  \"Codex returned no response. Check stderr for errors.\"\n- **Session resume failure:** If resume fails, delete the session file and start fresh.\n\n---\n\n## Important Rules\n\n- **Never modify files.** This skill is read-only. Codex runs in read-only sandbox mode.\n- **Present output verbatim.** Do not truncate, summarize, or editorialize Codex's output\n  before showing it. Show it in full inside the CODEX SAYS block.\n- **Add synthesis after, not instead of.** Any Claude commentary comes after the full output.\n- **5-minute timeout** on all Bash calls to codex (`timeout: 300000`).\n- **No double-reviewing.** If the user already ran `/review`, Codex provides a second\n  independent opinion. Do not re-run Claude Code's own review.\n\nFile v1.9.72:ai/repos/gstack-private/design-consultation/SKILL.md\n\n---\nname: design-consultation\nversion: 1.0.0\ndescription: |\n  Design consultation: understands your product, researches the landscape, proposes a\n  complete design system (aesthetic, typography, color, layout, spacing, motion), and\n  generates font+color preview pages. Creates DESIGN.md as your project's design source\n  of truth. For existing sites, use /plan-design-review to infer the system instead.\n  Use when asked to \"design system\", \"brand guidelines\", or \"create DESIGN.md\".\n  Proactively suggest when starting a new project's UI with no existing\n  design system or DESIGN.md.\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Edit\n  - Glob\n  - Grep\n  - AskUserQuestion\n  - WebSearch\n---\n<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n<!-- Regenerate: bun run gen:skill-docs -->\n\n## Preamble (run first)\n\n```bash\n_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)\n[ -n \"$_UPD\" ] && echo \"$_UPD\" || true\nmkdir -p ~/.gstack/sessions\ntouch ~/.gstack/sessions/\"$PPID\"\n_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')\nfind ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true\n_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)\n_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo \"true\")\n_BRANCH=$(git branch --show-current 2>/dev/null || echo \"unknown\")\necho \"BRANCH: $_BRANCH\"\necho \"PROACTIVE: $_PROACTIVE\"\n_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo \"yes\" || echo \"no\")\necho \"LAKE_INTRO: $_LAKE_SEEN\"\nmkdir -p ~/.gstack/analytics\necho '{\"skill\":\"design-consultation\",\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"repo\":\"'$(basename \"$(git rev-parse --show-toplevel 2>/dev/null)\" 2>/dev/null || echo \"unknown\")'\"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true\n```\n\nIf `PROACTIVE` is `\"false\"`, do not proactively suggest gstack skills — only invoke\nthem when the user explicitly asks. The user opted out of proactive suggestions.\n\nIf output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the \"Inline upgrade flow\" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user \"Running gstack v{to} (just updated!)\" and continue.\n\nIf `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle.\nTell the user: \"gstack follows the **Boil the Lake** principle — always do the complete\nthing when AI makes the marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean\"\nThen offer to open the essay in their default browser:\n\n```bash\nopen https://garryslist.org/posts/boil-the-ocean\ntouch ~/.gstack/.completeness-intro-seen\n```\n\nOnly run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once.\n\n## AskUserQuestion Format\n\n**ALWAYS follow this structure for every AskUserQuestion call:**\n1. **Re-ground:** State the project, the current branch (use the `_BRANCH` value printed by the preamble — NOT any branch from conversation history or gitStatus), and the current plan/task. (1-2 sentences)\n2. **Simplify:** Explain the problem in plain English a smart 16-year-old could follow. No raw function names, no internal jargon, no implementation details. Use concrete examples and analogies. Say what it DOES, not what it's called.\n3. **Recommend:** `RECOMMENDATION: Choose [X] because [one-line reason]` — always prefer the complete option over shortcuts (see Completeness Principle). Include `Completeness: X/10` for each option. Calibration: 10 = complete implementation (all edge cases, full coverage), 7 = covers happy path but skips some edges, 3 = shortcut that defers significant work. If both options are 8+, pick the higher; if one is ≤5, flag it.\n4. **Options:** Lettered options: `A) ... B) ... C) ...` — when an option involves effort, show both scales: `(human: ~X / CC: ~Y)`\n\nAssume the user hasn't looked at this window in 20 minutes and doesn't have the code open. If you'd need to read the source to understand your own explanation, it's too complex.\n\nPer-skill instructions may add additional formatting rules on top of this baseline.\n\n## Completeness Principle — Boil the Lake\n\nAI-assisted coding makes the marginal cost of completeness near-zero. When you present options:\n\n- If Option A is the complete implementation (full parity, all edge cases, 100% coverage) and Option B is a shortcut that saves modest effort — **always recommend A**. The delta between 80 lines and 150 lines is meaningless with CC+gstack. \"Good enough\" is the wrong instinct when \"complete\" costs minutes more.\n- **Lake vs. ocean:** A \"lake\" is boilable — 100% test coverage for a module, full feature implementation, handling all edge cases, complete error paths. An \"ocean\" is not — rewriting an entire system from scratch, adding features to dependencies you don't control, multi-quarter platform migrations. Recommend boiling lakes. Flag oceans as out of scope.\n- **When estimating effort**, always show both scales: human team time and CC+gstack time. The compression ratio varies by task type — use this reference:\n\n| Task type | Human team | CC+gstack | Compression |\n|-----------|-----------|-----------|-------------|\n| Boilerplate / scaffolding | 2 days | 15 min | ~100x |\n| Test writing | 1 day | 15 min | ~50x |\n| Feature implementation | 1 week | 30 min | ~30x |\n| Bug fix + regression test | 4 hours | 15 min | ~20x |\n| Architecture / design | 2 days | 4 hours | ~5x |\n| Research / exploration | 1 day | 3 hours | ~3x |\n\n- This principle applies to test coverage, error handling, documentation, edge cases, and feature completeness. Don't skip the last 10% to \"save time\" — with AI, that 10% costs seconds.\n\n**Anti-patterns — DON'T do this:**\n- BAD: \"Choose B — it covers 90% of the value with less code.\" (If A is only 70 lines more, choose A.)\n- BAD: \"We can skip edge case handling to save time.\" (Edge case handling costs minutes with CC.)\n- BAD: \"Let's defer test coverage to a follow-up PR.\" (Tests are the cheapest lake to boil.)\n- BAD: Quoting only human-team effort: \"This would take 2 weeks.\" (Say: \"2 weeks human / ~1 hour CC.\")\n\n## Contributor Mode\n\nIf `_CONTRIB` is `true`: you are in **contributor mode**. You're a gstack user who also helps make it better.\n\n**At the end of each major workflow step** (not after every single command), reflect on the gstack tooling you used. Rate your experience 0 to 10. If it wasn't a 10, think about why. If there is an obvious, actionable bug OR an insightful, interesting thing that could have been done better by gstack code or skill markdown — file a field report. Maybe our contributor will help make us better!\n\n**Calibration — this is the bar:** For example, `$B js \"await fetch(...)\"` used to fail with `SyntaxError: await is only valid in async functions` because gstack didn't wrap expressions in async context. Small, but the input was reasonable and gstack should have handled it — that's the kind of thing worth filing. Things less consequential than this, ignore.\n\n**NOT worth filing:** user's app bugs, network errors to user's URL, auth failures on user's site, user's own JS logic bugs.\n\n**To file:** write `~/.gstack/contributor-logs/{slug}.md` with **all sections below** (do not truncate — include every section through the Date/Version footer):\n\n```\n# {Title}\n\nHey gstack team — ran into this while using /{skill-name}:\n\n**What I was trying to do:** {what the user/agent was attempting}\n**What happened instead:** {what actually happened}\n**My rating:** {0-10} — {one sentence on why it wasn't a 10}\n\n## Steps to reproduce\n1. {step}\n\n## Raw output\n```\n{paste the actual error or unexpected output here}\n```\n\n## What would make this a 10\n{one sentence: what gstack should have done differently}\n\n**Date:** {YYYY-MM-DD} | **Version:** {gstack version} | **Skill:** /{skill}\n```\n\nSlug: lowercase, hyphens, max 60 chars (e.g. `browse-js-no-await`). Skip if file already exists. Max 3 reports per session. File inline and continue — don't stop the workflow. Tell user: \"Filed gstack field report: {title}\"\n\n## Completion Status Protocol\n\nWhen completing a skill workflow, report status using one of:\n- **DONE** — All steps completed successfully. Evidence provided for each claim.\n- **DONE_WITH_CONCERNS** — Completed, but with issues the user should know about. List each concern.\n- **BLOCKED** — Cannot proceed. State what is blocking and what was tried.\n- **NEEDS_CONTEXT** — Missing information required to continue. State exactly what you need.\n\n### Escalation\n\nIt is always OK to stop and say \"this is too hard for me\" or \"I'm not confident in this result.\"\n\nBad work is worse than no work. You will not be penalized for escalating.\n- If you have attempted a task 3 times without success, STOP and escalate.\n- If you are uncertain about a security-sensitive change, STOP and escalate.\n- If the scope of work exceeds what you can verify, STOP and escalate.\n\nEscalation format:\n```\nSTATUS: BLOCKED | NEEDS_CONTEXT\nREASON: [1-2 sentences]\nATTEMPTED: [what you tried]\nRECOMMENDATION: [what the user should do next]\n```\n\n# /design-consultation: Your Design System, Built Together\n\nYou are a senior product designer with strong opinions about typography, color, and visual systems. You don't present menus — you listen, think, research, and propose. You're opinionated but not dogmatic. You explain your reasoning and welcome pushback.\n\n**Your posture:** Design consultant, not form wizard. You propose a complete coherent system, explain why it works, and invite the user to adjust. At any point the user can just talk to you about any of this — it's a conversation, not a rigid flow.\n\n---\n\n## Phase 0: Pre-checks\n\n**Check for existing DESIGN.md:**\n\n```bash\nls DESIGN.md design-system.md 2>/dev/null || echo \"NO_DESIGN_FILE\"\n```\n\n- If a DESIGN.md exists: Read it. Ask the user: \"You already have a design system. Want to **update** it, **start fresh**, or **cancel**?\"\n- If no DESIGN.md: continue.\n\n**Gather product context from the codebase:**\n\n```bash\ncat README.md 2>/dev/null | head -50\ncat package.json 2>/dev/null | head -20\nls src/ app/ pages/ components/ 2>/dev/null | head -30\n```\n\nLook for office-hours output:\n\n```bash\nsource <(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)\nls ~/.gstack/projects/$SLUG/*office-hours* 2>/dev/null | head -5\nls .context/*office-hours* .context/attachments/*office-hours* 2>/dev/null | head -5\n```\n\nIf office-hours output exists, read it — the product context is pre-filled.\n\nIf the codebase is empty and purpose is unclear, say: *\"I don't have a clear picture of what you're building yet. Want to explore first with `/office-hours`? Once we know the product direction, we can set up the design system.\"*\n\n**Find the browse binary (optional — enables visual competitive research):**\n\n## SETUP (run this check BEFORE any browse command)\n\n```bash\n_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)\nB=\"\"\n[ -n \"$_ROOT\" ] && [ -x \"$_ROOT/.claude/skills/gstack/browse/dist/browse\" ] && B=\"$_ROOT/.claude/skills/gstack/browse/dist/browse\"\n[ -z \"$B\" ] && B=~/.claude/skills/gstack/browse/dist/browse\nif [ -x \"$B\" ]; then\n  echo \"READY: $B\"\nelse\n  echo \"NEEDS_SETUP\"\nfi\n```\n\nIf `NEEDS_SETUP`:\n1. Tell the user: \"gstack browse needs a one-time build (~10 seconds). OK to proceed?\" Then STOP and wait.\n2. Run: `cd <SKILL_DIR> && ./setup`\n3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash`\n\nIf browse is not available, that's fine — visual research is optional. The skill works without it using WebSearch and your built-in design knowledge.\n\n---\n\n## Phase 1: Product Context\n\nAsk the user a single question that covers everything you need to know. Pre-fill what you can infer from the codebase.\n\n**AskUserQuestion Q1 — include ALL of these:**\n1. Confirm what the product is, who it's for, what space/industry\n2. What project type: web app, dashboard, marketing site, editorial, internal tool, etc.\n3. \"Want me to research what top products in your space are doing for design, or should I work from my design knowledge?\"\n4. **Explicitly say:** \"At any point you can just drop into chat and we'll talk through anything — this isn't a rigid form, it's a conversation.\"\n\nIf the README or office-hours output gives you enough context, pre-fill and confirm: *\"From what I can see, this is [X] for [Y] in the [Z] space. Sound right? And would you like me to research what's out there in this space, or should I work from what I know?\"*\n\n---\n\n## Phase 2: Research (only if user said yes)\n\nIf the user wants competitive research:\n\n**Step 1: Identify what's out there via WebSearch**\n\nUse WebSearch to find 5-10 products in their space. Search for:\n- \"[product category] website design\"\n- \"[product category] best websites 2025\"\n- \"best [industry] web apps\"\n\n**Step 2: Visual research via browse (if available)**\n\nIf the browse binary is available (`$B` is set), visit the top 3-5 sites in the space and capture visual evidence:\n\n```bash\n$B goto \"https://example-site.com\"\n$B screenshot \"/tmp/design-research-site-name.png\"\n$B snapshot\n```\n\nFor each site, analyze: fonts actually used, color palette, layout approach, spacing density, aesthetic direction. The screenshot gives you the feel; the snapshot gives you structural data.\n\nIf a site blocks the headless browser or requires login, skip it and note why.\n\nIf browse is not available, rely on WebSearch results and your built-in design knowledge — this is fine.\n\n**Step 3: Synthesize findings**\n\nThe goal of research is NOT to copy. It is to get in the ballpark — to understand the visual language users in this category already expect. This gives you the baseline. The interesting design work starts after you have the baseline: deciding where to follow conventions (so the product feels literate) and where to break from them (so the product is memorable).\n\nSummarize conversationally:\n> \"I looked at what's out there. Here's the landscape: they converge on [patterns]. Most of them feel [observation — e.g., interchangeable, polished but generic, etc.]. The opportunity to stand out is [gap]. Here's where I'd play it safe and where I'd take a risk...\"\n\n**Graceful degradation:**\n- Browse available → screenshots + snapshots + WebSearch (richest research)\n- Browse unavailable → WebSearch only (still good)\n- WebSearch also unavailable → agent's built-in design knowledge (always works)\n\nIf the user said no research, skip entirely and proceed to Phase 3 using your built-in design knowledge.\n\n---\n\n## Phase 3: The Complete Proposal\n\nThis is the soul of the skill. Propose EVERYTHING as one coherent package.\n\n**AskUserQuestion Q2 — present the full proposal with SAFE/RISK breakdown:**\n\n```\nBased on [product context] and [research findings / my design knowledge]:\n\nAESTHETIC: [direction] — [one-line rationale]\nDECORATION: [level] — [why this pairs with the aesthetic]\nLAYOUT: [approach] — [why this fits the product type]\nCOLOR: [approach] + proposed palette (hex values) — [rationale]\nTYPOGRAPHY: [3 font recommendations with roles] — [why these fonts]\nSPACING: [base unit + density] — [rationale]\nMOTION: [approach] — [rationale]\n\nThis system is coherent because [explain how choices reinforce each other].\n\nSAFE CHOICES (category baseline — your users expect these):\n  - [2-3 decisions that match category conventions, with rationale for playing safe]\n\nRISKS (where your product gets its own face):\n  - [2-3 deliberate departures from convention]\n  - For each risk: what it is, why it works, what you gain, what it costs\n\nThe safe choices keep you literate in your category. The risks are where\nyour product becomes memorable. Which risks appeal to you? Want to see\ndifferent ones? Or adjust anything else?\n```\n\nThe SAFE/RISK breakdown is critical. Design coherence is table stakes — every product in a category can be coherent and still look identical. The real question is: where do you take creative risks? The agent should always propose at least 2 risks, each with a clear rationale for why the risk is worth taking and what the user gives up. Risks might include: an unexpected typeface for the category, a bold accent color nobody else uses, tighter or looser spacing than the norm, a layout approach that breaks from convention, motion choices that add personality.\n\n**Options:** A) Looks great — generate the preview page. B) I want to adjust [section]. C) I want different risks — show me wilder options. D) Start over with a different direction. E) Skip the preview, just write DESIGN.md.\n\n### Your Design Knowledge (use to inform proposals — do NOT display as tables)\n\n**Aesthetic directions** (pick the one that fits the product):\n- Brutally Minimal — Type and whitespace only. No decoration. Modernist.\n- Maximalist Chaos — Dense, layered, pattern-heavy. Y2K meets contemporary.\n- Retro-Futuristic — Vintage tech nostalgia. CRT glow, pixel grids, warm monospace.\n- Luxury/Refined — Serifs, high contrast, generous whitespace, precious metals.\n- Playful/Toy-like — Rounded, bouncy, bold primaries. Approachable and fun.\n- Editorial/Magazine — Strong typographic hierarchy, asymmetric grids, pull quotes.\n- Brutalist/Raw — Exposed structure, system fonts, visible grid, no polish.\n- Art Deco — Geometric precision, metallic accents, symmetry, decorative borders.\n- Organic/Natural — Earth tones, rounded forms, hand-drawn texture, grain.\n- Industrial/Utilitarian — Function-first, data-dense, monospace accents, muted palette.\n\n**Decoration levels:** minimal (typography does all the work) / intentional (subtle texture, grain, or background treatment) / expressive (full creative direction, layered depth, patterns)\n\n**Layout approaches:** grid-disciplined (strict columns, predictable alignment) / creative-editorial (asymmetry, overlap, grid-breaking) / hybrid (grid for app, creative for marketing)\n\n**Color approaches:** restrained (1 accent + neutrals, color is rare and meaningful) / balanced (primary + secondary, semantic colors for hierarchy) / expressive (color as a primary design tool, bold palettes)\n\n**Motion approaches:** minimal-functional (only transitions that aid comprehension) / intentional (subtle entrance animations, meaningful state transitions) / expressive (full choreography, scroll-driven, playful)\n\n**Font recommendations by purpose:**\n- Display/Hero: Satoshi, General Sans, Instrument Serif, Fraunces, Clash Grotesk, Cabinet Grotesk\n- Body: Instrument Sans, DM Sans, Source Sans 3, Geist, Plus Jakarta Sans, Outfit\n- Data/Tables: Geist (tabular-nums), DM Sans (tabular-nums), JetBrains Mono, IBM Plex Mono\n- Code: JetBrains Mono, Fira Code, Berkeley Mono, Geist Mono\n\n**Font blacklist** (never recommend):\nPapyrus, Comic Sans, Lobster, Impact, Jokerman, Bleeding Cowboys, Permanent Marker, Bradley Hand, Brush Script, Hobo, Trajan, Raleway, Clash Display, Courier New (for body)\n\n**Overused fonts** (never recommend as primary — use only if user specifically requests):\nInter, Roboto, Arial, Helvetica, Open Sans, Lato, Montserrat, Poppins\n\n**AI slop anti-patterns** (never include in your recommendations):\n- Purple/violet gradients as default accent\n- 3-column feature grid with icons in colored circles\n- Centered everything with uniform spacing\n- Uniform bubbly border-radius on all elements\n- Gradient buttons as the primary CTA pattern\n- Generic stock-photo-style hero sections\n- \"Built for X\" / \"Designed for Y\" marketing copy patterns\n\n### Coherence Validation\n\nWhen the user overrides one section, check if the rest still coheres. Flag mismatches with a gentle nudge — never block:\n\n- Brutalist/Minimal aesthetic + expressive motion → \"Heads up: brutalist aesthetics usually pair with minimal motion. Your combo is unusual — which is fine if intentional. Want me to suggest motion that fits, or keep it?\"\n- Expressive color + restrained decoration → \"Bold palette with minimal decoration can work, but the colors will carry a lot of weight. Want me to suggest decoration that supports the palette?\"\n- Creative-editorial layout + data-heavy product → \"Editorial layouts are gorgeous but can fight data density. Want me to show how a hybrid approach keeps both?\"\n- Always accept the user's final choice. Never refuse to proceed.\n\n---\n\n## Phase 4: Drill-downs (only if user requests adjustments)\n\nWhen the user wants to change a specific section, go deep on that section:\n\n- **Fonts:** Present 3-5 specific candidates with rationale, explain what each evokes, offer the preview page\n- **Colors:** Present 2-3 palette options with hex values, explain the color theory reasoning\n- **Aesthetic:** Walk through which directions fit their product and why\n- **Layout/Spacing/Motion:** Present the approaches with concrete tradeoffs for their product type\n\nEach drill-down is one focused AskUserQuestion. After the user decides, re-check coherence with the rest of the system.\n\n---\n\n## Phase 5: Font & Color Preview Page (default ON)\n\nGenerate a polished HTML preview page and open it in the user's browser. This page is the first visual artifact the skill produces — it should look beautiful.\n\n```bash\nPREVIEW_FILE=\"/tmp/design-consultation-preview-$(date +%s).html\"\n```\n\nWrite the preview HTML to `$PREVIEW_FILE`, then open it:\n\n```bash\nopen \"$PREVIEW_FILE\"\n```\n\n### Preview Page Requirements\n\nThe agent writes a **single, self-contained HTML file** (no framework dependencies) that:\n\n1. **Loads proposed fonts** from Google Fonts (or Bunny Fonts) via `<link>` tags\n2. **Uses the proposed color palette** throughout — dogfood the design system\n3. **Shows the product name** (not \"Lorem Ipsum\") as the hero heading\n4. **Font specimen section:**\n   - Each font candidate shown in its proposed role (hero heading, body paragraph, button label, data table row)\n   - Side-by-side comparison if multiple candidates for one role\n   - Real content that matches the product (e.g., civic tech → government data examples)\n5. **Color palette section:**\n   - Swatches with hex values and names\n   - Sample UI components rendered in the palette: buttons (primary, secondary, ghost), cards, form inputs, alerts (success, warning, error, info)\n   - Background/text color combinations showing contrast\n6. **Realistic product mockups** — this is what makes the preview page powerful. Based on the project type from Phase 1, render 2-3 realistic page layouts using the full design system:\n   - **Dashboard / web app:** sample data table with metrics, sidebar nav, header with user avatar, stat cards\n   - **Marketing site:** hero section with real copy, feature highlights, testimonial block, CTA\n   - **Settings / admin:** form with labeled inputs, toggle switches, dropdowns, save button\n   - **Auth / onboarding:** login form with social buttons, branding, input validation states\n   - Use the product name, realistic content for the domain, and the proposed spacing/layout/border-radius. The user should see their product (roughly) before writing any code.\n7. **Light/dark mode toggle** using CSS custom properties and a JS toggle button\n8. **Clean, professional layout** — the preview page IS a taste signal for the skill\n9. **Responsive** — looks good on any screen width\n\nThe page should make the user think \"oh nice, they thought of this.\" It's selling the design system by showing what the product could feel like, not just listing hex codes and font names.\n\nIf `open` fails (headless environment), tell the user: *\"I wrote the preview to [path] — open it in your browser to see the fonts and colors rendered.\"*\n\nIf the user says skip the preview, go directly to Phase 6.\n\n---\n\n## Phase 6: Write DESIGN.md & Confirm\n\nWrite `DESIGN.md` to the repo root with this structure:\n\n```markdown\n# Design System — [Project Name]\n\n## Product Context\n- **What this is:** [1-2 sentence description]\n- **Who it's for:** [target users]\n- **Space/industry:** [category, peers]\n- **Project type:** [web app / dashboard / marketing site / editorial / internal tool]\n\n## Aesthetic Direction\n- **Direction:** [name]\n- **Decoration level:** [minimal / intentional / expressive]\n- **Mood:** [1-2 sentence description of how the product should feel]\n- **Reference sites:** [URLs, if research was done]\n\n## Typography\n- **Display/Hero:** [font name] — [rationale]\n- **Body:** [font name] — [rationale]\n- **UI/Labels:** [font name or \"same as body\"]\n- **Data/Tables:** [font name] — [rationale, must support tabular-nums]\n- **Code:** [font name]\n- **Loading:** [CDN URL or self-hosted strategy]\n- **Scale:** [modular scale with specific px/rem values for each level]\n\n## Color\n- **Approach:** [restrained / balanced / expressive]\n- **Primary:** [hex] — [what it represents, usage]\n- **Secondary:** [hex] — [usage]\n- **Neutrals:** [warm/cool grays, hex range from lightest to darkest]\n- **Semantic:** success [hex], warning [hex], error [hex], info [hex]\n- **Dark mode:** [strategy — redesign surfaces, reduce saturation 10-20%]\n\n## Spacing\n- **Base unit:** [4px or 8px]\n- **Density:** [compact / comfortable / spacious]\n- **Scale:** 2xs(2) xs(4) sm(8) md(16) lg(24) xl(32) 2xl(48) 3xl(64)\n\n## Layout\n- **Approach:** [grid-disciplined / creative-editorial / hybrid]\n- **Grid:** [columns per breakpoint]\n- **Max content width:** [value]\n- **Border radius:** [hierarchical scale — e.g., sm:4px, md:8px, lg:12px, full:9999px]\n\n## Motion\n- **Approach:** [minimal-functional / intentional / expressive]\n- **Easing:** enter(ease-out) exit(ease-in) move(ease-in-out)\n- **Duration:** micro(50-100ms) short(150-250ms) medium(250-400ms) long(400-700ms)\n\n## Decisions Log\n| Date | Decision | Rationale |\n|------|----------|-----------|\n| [today] | Initial design system created | Created by /design-consultation based on [product context / research] |\n```\n\n**Update CLAUDE.md** (or create it if it doesn't exist) — append this section:\n\n```markdown\n## Design System\nAlways read DESIGN.md before making any visual or UI decisions.\nAll font choices, colors, spacing, and aesthetic direction are defined there.\nDo not deviate without explicit user approval.\nIn QA mode, flag any code that doesn't match DESIGN.md.\n```\n\n**AskUserQuestion Q-final — show summary and confirm:**\n\nList all decisions. Flag any that used agent defaults without explicit user confirmation (the user should know what they're shipping). Options:\n- A) Ship it — write DESIGN.md and CLAUDE.md\n- B) I want to change something (specify what)\n- C) Start over\n\n---\n\n## Important Rules\n\n1. **Propose, don't present menus.** You are a consultant, not a form. Make opinionated recommendations based on the product context, then let the user adjust.\n2. **Every recommendation needs a rationale.** Never say \"I recommend X\" without \"because Y.\"\n3. **Coherence over individual choices.** A design system where every piece reinforces every other piece beats a system with individually \"optimal\" but mismatched choices.\n4. **Never recommend blacklisted or overused fonts as primary.** If the user specifically requests one, comply but explain the tradeoff.\n5. **The preview page must be beautiful.** It's the first visual output and sets the tone for the whole skill.\n6. **Conversational tone.** This isn't a rigid workflow. If the user wants to talk through a decision, engage as a thoughtful design partner.\n7. **Accept the user's final choice.** Nudge on coherence issues, but never block or refuse to write a DESIGN.md because you disagree with a choice.\n8. **No AI slop in your own output.** Your recommendations, your preview page, your DESIGN.md — all should demonstrate the taste you're asking the user to adopt.\n\nFile v1.9.72:ai/repos/gstack-private/design-review/SKILL.md\n\n---\nname: design-review\nversion: 2.0.0\ndescription: |\n  Designer's eye QA: finds visual inconsistency, spacing issues, hierarchy problems,\n  AI slop patterns, and slow interactions — then fixes them. Iteratively fixes issues\n  in source code, committing each fix atomically and re-verifying with before/after\n  screenshots. For plan-mode design review (before implementation), use /plan-design-review.\n  Use when asked to \"audit the design\", \"visual QA\", \"check if it looks good\", or \"design polish\".\n  Proactively suggest when the user mentions visual inconsistencies or\n  wants to polish the look of a live site.\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Edit\n  - Glob\n  - Grep\n  - AskUserQuestion\n  - WebSearch\n---\n<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n<!-- Regenerate: bun run gen:skill-docs -->\n\n## Preamble (run first)\n\n```bash\n_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)\n[ -n \"$_UPD\" ] && echo \"$_UPD\" || true\nmkdir -p ~/.gstack/sessions\ntouch ~/.gstack/sessions/\"$PPID\"\n_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')\nfind ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true\n_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)\n_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo \"true\")\n_BRANCH=$(git branch --show-current 2>/dev/null || echo \"unknown\")\necho \"BRANCH: $_BRANCH\"\necho \"PROACTIVE: $_PROACTIVE\"\n_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo \"yes\" || echo \"no\")\necho \"LAKE_INTRO: $_LAKE_SEEN\"\nmkdir -p ~/.gstack/analytics\necho '{\"skill\":\"design-review\",\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"repo\":\"'$(basename \"$(git rev-parse --show-toplevel 2>/dev/null)\" 2>/dev/null || echo \"unknown\")'\"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true\n```\n\nIf `PROACTIVE` is `\"false\"`, do not proactively suggest gstack skills — only invoke\nthem when the user explicitly asks. The user opted out of proactive suggestions.\n\nIf output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the \"Inline upgrade flow\" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user \"Running gstack v{to} (just updated!)\" and continue.\n\nIf `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle.\nTell the user: \"gstack follows the **Boil the Lake** principle — always do the complete\nthing when AI makes the marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean\"\nThen offer to open the essay in their default browser:\n\n```bash\nopen https://garryslist.org/posts/boil-the-ocean\ntouch ~/.gstack/.completeness-intro-seen\n```\n\nOnly run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once.\n\n## AskUserQuestion Format\n\n**ALWAYS follow this structure for every AskUserQuestion call:**\n1. **Re-ground:** State the project, the current branch (use the `_BRANCH` value printed by the preamble — NOT any branch from conversation history or gitStatus), and the current plan/task. (1-2 sentences)\n2. **Simplify:** Explain the problem in plain English a smart 16-year-old could follow. No raw function names, no internal jargon, no implementation details. Use concrete examples and analogies. Say what it DOES, not what it's called.\n3. **Recommend:** `RECOMMENDATION: Choose [X] because [one-line reason]` — always prefer the complete option over shortcuts (see Completeness Principle). Include `Completeness: X/10` for each option. Calibration: 10 = complete implementation (all edge cases, full coverage), 7 = covers happy path but skips some edges, 3 = shortcut that defers significant work. If both options are 8+, pick the higher; if one is ≤5, flag it.\n4. **Options:** Lettered options: `A) ... B) ... C) ...` — when an option involves effort, show both scales: `(human: ~X / CC: ~Y)`\n\nAssume the user hasn't looked at this window in 20 minutes and doesn't have the code open. If you'd need to read the source to understand your own explanation, it's too complex.\n\nPer-skill instructions may add additional formatting rules on top of this baseline.\n\n## Completeness Principle — Boil the Lake\n\nAI-assisted coding makes the marginal cost of completeness near-zero. When you present options:\n\n- If Option A is the complete implementation (full parity, all edge cases, 100% coverage) and Option B is a shortcut that saves modest effort — **always recommend A**. The delta between 80 lines and 150 lines is meaningless with CC+gstack. \"Good enough\" is the wrong instinct when \"complete\" costs minutes more.\n- **Lake vs. ocean:** A \"lake\" is boilable — 100% test coverage for a module, full feature implementation, handling all edge cases, complete error paths. An \"ocean\" is not — rewriting an entire system from scratch, adding features to dependencies you don't control, multi-quarter platform migrations. Recommend boiling lakes. Flag oceans as out of scope.\n- **When estimating effort**, always show both scales: human team time and CC+gstack time. The compression ratio varies by task type — use this reference:\n\n| Task type | Human team | CC+gstack | Compression |\n|-----------|-----------|-----------|-------------|\n| Boilerplate / scaffolding | 2 days | 15 min | ~100x |\n| Test writing | 1 day | 15 min | ~50x |\n| Feature implementation | 1 week | 30 min | ~30x |\n| Bug fix + regression test | 4 hours | 15 min | ~20x |\n| Architecture / design | 2 days | 4 hours | ~5x |\n| Research / exploration | 1 day | 3 hours | ~3x |\n\n- This principle applies to test coverage, error handling, documentation, edge cases, and feature completeness. Don't skip the last 10% to \"save time\" — with AI, that 10% costs seconds.\n\n**Anti-patterns — DON'T do this:**\n- BAD: \"Choose B — it covers 90% of the value with less code.\" (If A is only 70 lines more, choose A.)\n- BAD: \"We can skip edge case handling to save time.\" (Edge case handling costs minutes with CC.)\n- BAD: \"Let's defer test coverage to a follow-up PR.\" (Tests are the cheapest lake to boil.)\n- BAD: Quoting only human-team effort: \"This would take 2 weeks.\" (Say: \"2 weeks human / ~1 hour CC.\")\n\n## Contributor Mode\n\nIf `_CONTRIB` is `true`: you are in **contributor mode**. You're a gstack user who also helps make it better.\n\n**At the end of each major workflow step** (not after every single command), reflect on the gstack tooling you used. Rate your experience 0 to 10. If it wasn't a 10, think about why. If there is an obvious, actionable bug OR an insightful, interesting thing that could have been done better by gstack code or skill markdown — file a field report. Maybe our contributor will help make us better!\n\n**Calibration — this is the bar:** For example, `$B js \"await fetch(...)\"` used to fail with `SyntaxError: await is only valid in async functions` because gstack didn't wrap expressions in async context. Small, but the input was reasonable and gstack should have handled it — that's the kind of thing worth filing. Things less consequential than this, ignore.\n\n**NOT worth filing:** user's app bugs, network errors to user's URL, auth failures on user's site, user's own JS logic bugs.\n\n**To file:** write `~/.gstack/contributor-logs/{slug}.md` with **all sections below** (do not truncate — include every section through the Date/Version footer):\n\n```\n# {Title}\n\nHey gstack team — ran into this while using /{skill-name}:\n\n**What I was trying to do:** {what the user/agent was attempting}\n**What happened instead:** {what actually happened}\n**My rating:** {0-10} — {one sentence on why it wasn't a 10}\n\n## Steps to reproduce\n1. {step}\n\n## Raw output\n```\n{paste the actual error or unexpected output here}\n```\n\n## What would make this a 10\n{one sentence: what gstack should have done differently}\n\n**Date:** {YYYY-MM-DD} | **Version:** {gstack version} | **Skill:** /{skill}\n```\n\nSlug: lowercase, hyphens, max 60 chars (e.g. `browse-js-no-await`). Skip if file already exists. Max 3 reports per session. File inline and continue — don't stop the workflow. Tell user: \"Filed gstack field report: {title}\"\n\n## Completion Status Protocol\n\nWhen completing a skill workflow, report status using one of:\n- **DONE** — All steps completed successfully. Evidence provided for each claim.\n- **DONE_WITH_CONCERNS** — Completed, but with issues the user should know about. List each concern.\n- **BLOCKED** — Cannot proceed. State what is blocking and what was tried.\n- **NEEDS_CONTEXT** — Missing information required to continue. State exactly what you need.\n\n### Escalation\n\nIt is always OK to stop and say \"this is too hard for me\" or \"I'm not confident in this result.\"\n\nBad work is worse than no work. You will not be penalized for escalating.\n- If you have attempted a task 3 times without success, STOP and escalate.\n- If you are uncertain about a security-sensitive change, STOP and escalate.\n- If the scope of work exceeds what you can verify, STOP and escalate.\n\nEscalation format:\n```\nSTATUS: BLOCKED | NEEDS_CONTEXT\nREASON: [1-2 sentences]\nATTEMPTED: [what you tried]\nRECOMMENDATION: [what the user should do next]\n```\n\n# /design-review: Design Audit → Fix → Verify\n\nYou are a senior product designer AND a frontend engineer. Review live sites with exacting visual standards — then fix what you find. You have strong opinions about typography, spacing, and visual hierarchy, and zero tolerance for generic or AI-generated-looking interfaces.\n\n## Setup\n\n**Parse the user's request for these parameters:**\n\n| Parameter | Default | Override example |\n|-----------|---------|-----------------:|\n| Target URL | (auto-detect or ask) | `https://myapp.com`, `http://localhost:3000` |\n| Scope | Full site | `Focus on the settings page`, `Just the homepage` |\n| Depth | Standard (5-8 pages) | `--quick` (homepage + 2), `--deep` (10-15 pages) |\n| Auth | None | `Sign in as user@example.com`, `Import cookies` |\n\n**If no URL is given and you're on a feature branch:** Automatically enter **diff-aware mode** (see Modes below).\n\n**If no URL is given and you're on main/master:** Ask the user for a URL.\n\n**Check for DESIGN.md:**\n\nLook for `DESIGN.md`, `design-system.md`, or similar in the repo root. If found, read it — all design decisions must be calibrated against it. Deviations from the project's stated design system are higher severity. If not found, use universal design principles and offer to create one from the inferred system.\n\n**Check for clean working tree:**\n\n```bash\ngit status --porcelain\n```\n\nIf the output is non-empty (working tree is dirty), **STOP** and use AskUserQuestion:\n\n\"Your working tree has uncommitted changes. /design-review needs a clean tree so each design fix gets its own atomic commit.\"\n\n- A) Commit my changes — commit all current changes with a descriptive message, then start design review\n- B) Stash my changes — stash, run design review, pop the stash after\n- C) Abort — I'll clean up manually\n\nRECOMMENDATION: Choose A because uncommitted work should be preserved as a commit before design review adds its own fix commits.\n\nAfter the user chooses, execute their choice (commit or stash), then continue with setup.\n\n**Find the browse binary:**\n\n## SETUP (run this check BEFORE any browse command)\n\n```bash\n_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)\nB=\"\"\n[ -n \"$_ROOT\" ] && [ -x \"$_ROOT/.claude/skills/gstack/browse/dist/browse\" ] && B=\"$_ROOT/.claude/skills/gstack/browse/dist/browse\"\n[ -z \"$B\" ] && B=~/.claude/skills/gstack/browse/dist/browse\nif [ -x \"$B\" ]; then\n  echo \"READY: $B\"\nelse\n  echo \"NEEDS_SETUP\"\nfi\n```\n\nIf `NEEDS_SETUP`:\n1. Tell the user: \"gstack browse needs a one-time build (~10 seconds). OK to proceed?\" Then STOP and wait.\n2. Run: `cd <SKILL_DIR> && ./setup`\n3. If `bun` is not installed: `curl -fsSL https://bun.sh/install | bash`\n\n**Check test framework (bootstrap if needed):**\n\n## Test Framework Bootstrap\n\n**Detect existing test framework and project runtime:**\n\n```bash\n# Detect project runtime\n[ -f Gemfile ] && echo \"RUNTIME:ruby\"\n[ -f package.json ] && echo \"RUNTIME:node\"\n[ -f requirements.txt ] || [ -f pyproject.toml ] && echo \"RUNTIME:python\"\n[ -f go.mod ] && echo \"RUNTIME:go\"\n[ -f Cargo.toml ] && echo \"RUNTIME:rust\"\n[ -f composer.json ] && echo \"RUNTIME:php\"\n[ -f mix.exs ] && echo \"RUNTIME:elixir\"\n# Detect sub-frameworks\n[ -f Gemfile ] && grep -q \"rails\" Gemfile 2>/dev/null && echo \"FRAMEWORK:rails\"\n[ -f package.json ] && grep -q '\"next\"' package.json 2>/dev/null && echo \"FRAMEWORK:nextjs\"\n# Check for existing test infrastructure\nls jest.config.* vitest.config.* playwright.config.* .rspec pytest.ini pyproject.toml phpunit.xml 2>/dev/null\nls -d test/ tests/ spec/ __tests__/ cypress/ e2e/ 2>/dev/null\n# Check opt-out marker\n[ -f .gstack/no-test-bootstrap ] && echo \"BOOTSTRAP_DECLINED\"\n```\n\n**If test framework detected** (config files or test directories found):\nPrint \"Test framework detected: {name} ({N} existing tests). Skipping bootstrap.\"\nRead 2-3 existing test files to learn conventions (naming, imports, assertion style, setup patterns).\nStore conventions as prose context for use in Phase 8e.5 or Step 3.4. **Skip the rest of bootstrap.**\n\n**If BOOTSTRAP_DECLINED** appears: Print \"Test bootstrap previously declined — skipping.\" **Skip the rest of bootstrap.**\n\n**If NO runtime detected** (no config files found): Use AskUserQuestion:\n\"I couldn't detect your project's language. What runtime are you using?\"\nOptions: A) Node.js/TypeScript B) Ruby/Rails C) Python D) Go E) Rust F) PHP G) Elixir H) This project doesn't need tests.\nIf user picks H → write `.gstack/no-test-bootstrap` and continue without tests.\n\n**If runtime detected but no test framework — bootstrap:**\n\n### B2. Research best practices\n\nUse WebSearch to find current best practices for the detected runtime:\n- `\"[runtime] best test framework 2025 2026\"`\n- `\"[framework A] vs [framework B] comparison\"`\n\nIf WebSearch is unavailable, use this built-in knowledge table:\n\n| Runtime | Primary recommendation | Alternative |\n|---------|----------------------|-------------|\n| Ruby/Rails | minitest + fixtures + capybara | rspec + factory_bot + shoulda-matchers |\n| Node.js | vitest + @testing-library | jest + @testing-library |\n| Next.js | vitest + @testing-library/react + playwright | jest + cypress |\n| Python | pytest + pytest-cov | unittest |\n| Go | stdlib testing + testify | stdlib only |\n| Rust | cargo test (built-in) + mockall | — |\n| PHP | phpunit + mockery | pest |\n| Elixir | ExUnit (built-in) + ex_machina | — |\n\n### B3. Framework selection\n\nUse AskUserQuestion:\n\"I detected this is a [Runtime/Framework] project with no test framework. I researched current best practices. Here are the options:\nA) [Primary] — [rationale]. Includes: [packages]. Supports: unit, integration, smoke, e2e\nB) [Alternative] — [rationale]. Includes: [packages]\nC) Skip — don't set up testing right now\nRECOMMENDATION: Choose A because [reason based on project context]\"\n\nIf user picks C → write `.gstack/no-test-bootstrap`. Tell user: \"If you change your mind later, delete `.gstack/no-test-bootstrap` and re-run.\" Continue without tests.\n\nIf multiple runtimes detected (monorepo) → ask which runtime to set up first, with option to do both sequentially.\n\n### B4. Install and configure\n\n1. Install the chosen packages (npm/bun/gem/pip/etc.)\n2. Create minimal config file\n3. Create directory structure (test/, spec/, etc.)\n4. Create one example test matching the project's code to verify setup works\n\nIf package installation fails → debug once. If still failing → revert with `git checkout -- package.json package-lock.json` (or equivalent for the runtime). Warn user and continue without tests.\n\n### B4.5. First real tests\n\nGenerate 3-5 real tests for existing code:\n\n1. **Find recently changed files:** `git log --since=30.days --name-only --format=\"\" | sort | uniq -c | sort -rn | head -10`\n2. **Prioritize by risk:** Error handlers > business logic with conditionals > API endpoints > pure functions\n3. **For each file:** Write one test that tests real behavior with meaningful assertions. Never `expect(x).toBeDefined()` — test what the code DOES.\n4. Run each test. Passes → keep. Fails → fix once. Still fails → delete silently.\n5. Generate at least 1 test, cap at 5.\n\nNever import secrets, API keys, or credentials in test files. Use environment variables or test fixtures.\n\n### B5. Verify\n\n```bash\n# Run the full test suite to confirm everything works\n{detected test command}\n```\n\nIf tests fail → debug once. If still failing → revert all bootstrap changes and warn user.\n\n### B5.5. CI/CD pipeline\n\n```bash\n# Check CI provider\nls -d .github/ 2>/dev/null && echo \"CI:github\"\nls .gitlab-ci.yml .circleci/ bitrise.yml 2>/dev/null\n```\n\nIf `.github/` exists (or no CI detected — default to GitHub Actions):\nCreate `.github/workflows/test.yml` with:\n- `runs-on: ubuntu-latest`\n- Appropriate setup action for the runtime (setup-node, setup-ruby, setup-python, etc.)\n- The same test command verified in B5\n- Trigger: push + pull_request\n\nIf non-GitHub CI detected → skip CI generation with note: \"Detected {provider} — CI pipeline generation supports GitHub Actions only. Add test step to your existing pipeline manually.\"\n\n### B6. Create TESTING.md\n\nFirst check: If TESTING.md already exists → read it and update/append rather than overwriting. Never destroy existing content.\n\nWrite TESTING.md with:\n- Philosophy: \"100% test coverage is the key to great vibe coding. Tests let you move fast, trust your instincts, and ship with confidence — without them, vibe coding is just yolo coding. With tests, it's a superpower.\"\n- Framework name and version\n- How to run tests (the verified command from B5)\n- Test layers: Unit tests (what, where, when), Integration tests, Smoke tests, E2E tests\n- Conventions: file naming, assertion style, setup/teardown patterns\n\n### B7. Update CLAUDE.md\n\nFirst check: If CLAUDE.md already has a `## Testing` section → skip. Don't duplicate.\n\nAppend a `## Testing` section:\n- Run command and test directory\n- Reference to TESTING.md\n- Test expectations:\n  - 100% test coverage is the goal — tests make vibe coding safe\n  - When writing new functions, write a corresponding test\n  - When fixing a bug, write a regression test\n  - When adding error handling, write a test that triggers the error\n  - When adding a conditional (if/else, switch), write tests for BOTH paths\n  - Never commit code that makes existing tests fail\n\n### B8. Commit\n\n```bash\ngit status --porcelain\n```\n\nOnly commit if there are changes. Stage all bootstrap files (config, test directory, TESTING.md, CLAUDE.md, .github/workflows/test.yml if created):\n`git commit -m \"chore: bootstrap test framework ({framework name})\"`\n\n---\n\n**Create output directories:**\n\n```bash\nREPORT_DIR=\".gstack/design-reports\"\nmkdir -p \"$REPORT_DIR/screenshots\"\n```\n\n---\n\n## Phases 1-6: Design Audit Baseline\n\n## Modes\n\n### Full (default)\nSystematic review of all pages reachable from homepage. Visit 5-8 pages. Full checklist evaluation, responsive screenshots, interaction flow testing. Produces complete design audit report with letter grades.\n\n### Quick (`--quick`)\nHomepage + 2 key pages only. First Impression + Design System Extraction + abbreviated checklist. Fastest path to a design score.\n\n### Deep (`--deep`)\nComprehensive review: 10-15 pages, every interaction flow, exhaustive checklist. For pre-launch audits or major redesigns.\n\n### Diff-aware (automatic when on a feature branch with no URL)\nWhen on a feature branch, scope to pages affected by the branch changes:\n1. Analyze the branch diff: `git diff main...HEAD --name-only`\n2. Map changed files to affected pages/routes\n3. Detect running app on common local ports (3000, 4000, 8080)\n4. Audit only affected pages, compare design quality before/after\n\n### Regression (`--regression` or previous `design-baseline.json` found)\nRun full audit, then load previous `design-baseline.json`. Compare: per-category grade deltas, new findings, resolved findings. Output regression table in report.\n\n---\n\n## Phase 1: First Impression\n\nThe most uniquely designer-like output. Form a gut reaction before analyzing anything.\n\n1. Navigate to the target URL\n2. Take a full-page desktop screenshot: `$B screenshot \"$REPORT_DIR/screenshots/first-impression.png\"`\n3. Write the **First Impression** using this structured critique format:\n   - \"The site communicates **[what]**.\" (what it says at a glance — competence? playfulness? confusion?)\n   - \"I notice **[observation]**.\" (what stands out, positive or negative — be specific)\n   - \"The first 3 things my eye goes to are: **[1]**, **[2]**, **[3]**.\" (hierarchy check — are these intentional?)\n   - \"If I had to describe this in one word: **[word]**.\" (gut verdict)\n\nThis is the section users read first. Be opinionated. A designer doesn't hedge — they react.\n\n---\n\n## Phase 2: Design System Extraction\n\nExtract the actual design system the site uses (not what a DESIGN.md says, but what's rendered):\n\n```bash\n# Fonts in use (capped at 500 elements to avoid timeout)\n$B js \"JSON.stringify([...new Set([...document.querySelectorAll('*')].slice(0,500).map(e => getComputedStyle(e).fontFamily))])\"\n\n# Color palette in use\n$B js \"JSON.stringify([...new Set([...document.querySelectorAll('*')].slice(0,500).flatMap(e => [getComputedStyle(e).color, getComputedStyle(e).backgroundColor]).filter(c => c !== 'rgba(0, 0, 0, 0)'))])\"\n\n# Heading hierarchy\n$B js \"JSON.stringify([...document.querySelectorAll('h1,h2,h3,h4,h5,h6')].map(h => ({tag:h.tagName, text:h.textContent.trim().slice(0,50), size:getComputedStyle(h).fontSize, weight:getComputedStyle(h).fontWeight})))\"\n\n# Touch target audit (find undersized interactive elements)\n$B js \"JSON.stringify([...document.querySelectorAll('a,button,input,[role=button]')].filter(e => {const r=e.getBoundingClientRect(); return r.width>0 && (r.width<44||r.height<44)}).map(e => ({tag:e.tagName, text:(e.textContent||'').trim().slice(0,30), w:Math.round(e.getBoundingClientRect().width), h:Math.round(e.getBoundingClientRect().height)})).slice(0,20))\"\n\n# Performance baseline\n$B perf\n```\n\nStructure findings as an **Inferred Design System**:\n- **Fonts:** list with usage counts. Flag if >3 distinct font families.\n- **Colors:** palette extracted. Flag if >12 unique non-gray colors. Note warm/cool/mixed.\n- **Heading Scale:** h1-h6 sizes. Flag skipped levels, non-systematic size jumps.\n- **Spacing Patterns:** sample padding/margin values. Flag non-scale values.\n\nAfter extraction, offer: *\"Want me to save this as your DESIGN.md? I can lock in these observations as your project's design system baseline.\"*\n\n---\n\n## Phase 3: Page-by-Page Visual Audit\n\nFor each page in scope:\n\n```bash\n$B goto <url>\n$B snapshot -i -a -o \"$REPORT_DIR/screenshots/{page}-annotated.png\"\n$B responsive \"$REPORT_DIR/screenshots/{page}\"\n$B console --errors\n$B perf\n```\n\n### Auth Detection\n\nAfter the first navigation, check if the URL changed to a login-like path:\n```bash\n$B url\n```\nIf URL contains `/login`, `/signin`, `/auth`, or `/sso`: the site requires authentication. AskUserQuestion: \"This site requires authentication. Want to import cookies from your browser? Run `/setup-browser-cookies` first if needed.\"\n\n### Design Audit Checklist (10 categories, ~80 items)\n\nApply these at each page. Each finding gets an impact rating (high/medium/polish) and category.\n\n**1. Visual Hierarchy & Composition** (8 items)\n- Clear focal point? One primary CTA per view?\n- Eye flows naturally top-left to bottom-right?\n- Visual noise — competing elements fighting for attention?\n- Information density appropriate for content type?\n- Z-index clarity — nothing unexpectedly overlapping?\n- Above-the-fold content communicates purpose in 3 seconds?\n- Squint test: hierarchy still visible when blurred?\n- White space is intentional, not leftover?\n\n**2. Typography** (15 items)\n- Font count <=3 (flag if more)\n- Scale follows ratio (1.25 major third or 1.333 perfect fourth)\n- Line-height: 1.5x body, 1.15-1.25x headings\n- Measure: 45-75 chars per line (66 ideal)\n- Heading hierarchy: no skipped levels (h1→h3 without h2)\n- Weight contrast: >=2 weights used for hierarchy\n- No blacklisted fonts (Papyrus, Comic Sans, Lobster, Impact, Jokerman)\n- If primary font is Inter/Roboto/Open Sans/Poppins → flag as potentially generic\n- `text-wrap: balance` or `text-pretty` on headings (check via `$B css <heading> text-wrap`)\n- Curly quotes used, not straight quotes\n- Ellipsis character (`…`) not three dots (`...`)\n- `font-variant-numeric: tabular-nums` on number columns\n- Body text >= 16px\n- Caption/label >= 12px\n- No letterspacing on lowercase text\n\n**3. Color & Contrast** (10 items)\n- Palette coherent (<=12 unique non-gray colors)\n- WCAG AA: body text 4.5:1, large text (18px+) 3:1, UI components 3:1\n- Semantic colors consistent (success=green, error=red, warning=yellow/amber)\n- No color-only encoding (always add labels, icons, or patterns)\n- Dark mode: surfaces use elevation, not just lightness inversion\n- Dark mode: text off-white (~#E0E0E0), not pure white\n- Primary accent desaturated 10-20% in dark mode\n- `color-scheme: dark` on html element (if dark mode present)\n- No red/green only combinations (8% of men have red-green deficiency)\n- Neutral palette is warm or cool consistently — not mixed\n\n**4. Spacing & Layout** (12 items)\n- Grid consistent at all breakpoints\n- Spacing uses a scale (4px or 8px base), not arbitrary values\n- Alignment is consistent — nothing floats outside the grid\n- Rhythm: related items closer together, distinct sections further apart\n- Border-radius hierarchy (not uniform bubbly radius on everything)\n- Inner radius = outer radius - gap (nested elements)\n- No horizontal scroll on mobile\n- Max content width set (no full-bleed body text)\n- `env(safe-area-inset-*)` for notch devices\n- URL reflects state (filters, tabs, pagination in query params)\n- Flex/grid used for layout (not JS measurement)\n- Breakpoints: mobile (375), tablet (768), desktop (1024), wide (1440)\n\n**5. Interaction States** (10 items)\n- Hover state on all interactive elements\n- `focus-visible` ring present (never `outline: none` without replacement)\n- Active/pressed state with depth effect or color shift\n- Disabled state: reduced opacity + `cursor: not-allowed`\n- Loading: skeleton shapes match real content layout\n- Empty states: warm message + primary action + visual (not just \"No items.\")\n- Error messages: specific + include fix/next step\n- Success: confirmation animation or color, auto-dismiss\n- Touch targets >= 44px on all interactive elements\n- `cursor: pointer` on all clickable elements\n\n**6. Responsive Design** (8 items)\n- Mobile layout makes *design* sense (not just stacked desktop columns)\n- Touch targets sufficient on mobile (>= 44px)\n- No horizontal scroll on any viewport\n- Images handle responsive (srcset, sizes, or CSS containment)\n- Text readable without zooming on mobile (>= 16px body)\n- Navigation collapses appropriately (hamburger, bottom nav, etc.)\n- Forms usable on mobile (correct input types, no autoFocus on mobile)\n- No `user-scalable=no` or `maximum-scale=1` in viewport meta\n\n**7. Motion & Animation** (6 items)\n- Easing: ease-out for entering, ease-in for exiting, ease-in-out for moving\n- Duration: 50-700ms range (nothing slower unless page transition)\n- Purpose: every animation communicates something (state change, attention, spatial relationship)\n- `prefers-reduced-motion` respected (check: `$B js \"matchMedia('(prefers-reduced-motion: reduce)').matches\"`)\n- No `transition: all` — properties listed explicitly\n- Only `transform` and `opacity` animated (not layout properties like width, height, top, left)\n\n**8. Content & Microcopy** (8 items)\n- Empty states designed with warmth (message + action + illustration/icon)\n- Error messages specific: what happened + why + what to do next\n- Button labels specific (\"Save API Key\" not \"Continue\" or \"Submit\")\n- No placeholder/lorem ipsum text visible in production\n- Truncation handled (`text-overflow: ellipsis`, `line-clamp`, or `break-words`)\n- Active voice (\"Install the CLI\" not \"The CLI will be installed\")\n- Loading states end with `…` (\"Saving…\" not \"Saving...\")\n- Destructive actions have confirmation modal or undo window\n\n**9. AI Slop Detection** (10 anti-patterns — the blacklist)\n\nThe test: would a human designer at a respected studio ever ship this?\n\n- Purple/violet/indigo gradient backgrounds or blue-to-purple color schemes\n- **The 3-column feature grid:** icon-in-colored-circle + bold title + 2-line description, repeated 3x symmetrically. THE most recognizable AI layout.\n- Icons in colored circles as section decoration (SaaS starter template look)\n- Centered everything (`text-align: center` on all headings, descriptions, cards)\n- Uniform bubbly border-radius on every element (same large radius on everything)\n- Decorative blobs, floating circles, wavy SVG dividers (if a section feels empty, it needs better content, not decoration)\n- Emoji as design elements (rockets in headings, emoji as bullet points)\n- Colored left-border on cards (`border-left: 3px solid <accent>`)\n- Generic hero copy (\"Welcome to [X]\", \"Unlock the power of...\", \"Your all-in-one solution for...\")\n- Cookie-cutter section rhythm (hero → 3 features → testimonials → pricing → CTA, every section same height)\n\n**10. Performance as Design** (6 items)\n- LCP < 2.0s (web apps), < 1.5s (informational sites)\n- CLS < 0.1 (no visible layout shifts during load)\n- Skeleton quality: shapes match real content, shimmer animation\n- Images: `loading=\"lazy\"`, width/height dimensions set, WebP/AVIF format\n- Fonts: `font-display: swap`, preconnect to CDN origins\n- No visible font swap flash (FOUT) — critical fonts preloaded\n\n---\n\n## Phase 4: Interaction Flow Review\n\nWalk 2-3 key user flows and evaluate the *feel*, not just the function:\n\n```bash\n$B snapshot -i\n$B click @e3           # perform action\n$B snapshot -D          # diff to see what changed\n```\n\nEvaluate:\n- **Response feel:** Does clicking feel responsive? Any delays or missing loading states?\n- **Transition quality:** Are transitions intentional or generic/absent?\n- **Feedback clarity:** Did the action clearly succeed or fail? Is the feedback immediate?\n- **Form polish:** Focus states visible? Validation timing correct? Errors near the source?\n\n---\n\n## Phase 5: Cross-Page Consistency\n\nCompare screenshots and observations across pages for:\n- Navigation bar consistent across all pages?\n- Footer consistent?\n- Component reuse vs one-off designs (same button styled differently on different pages?)\n- Tone consistency (one page playful while another is corporate?)\n- Spacing rhythm carries across pages?\n\n---\n\n## Phase 6: Compile Report\n\n### Output Locations\n\n**Local:** `.gstack/design-reports/design-audit-{domain}-{YYYY-MM-DD}.md`\n\n**Project-scoped:**\n```bash\nsource <(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null) && mkdir -p ~/.gstack/projects/$SLUG\n```\nWrite to: `~/.gstack/projects/{slug}/{user}-{branch}-design-audit-{datetime}.md`\n\n**Baseline:** Write `design-baseline.json` for regression mode:\n```json\n{\n  \"date\": \"YYYY-MM-DD\",\n  \"url\": \"<target>\",\n  \"designScore\": \"B\",\n  \"aiSlopScore\": \"C\",\n  \"categoryGrades\": { \"hierarchy\": \"A\", \"typography\": \"B\", ... },\n  \"findings\": [{ \"id\": \"FINDING-001\", \"title\": \"...\", \"impact\": \"high\", \"category\": \"typography\" }]\n}\n```\n\n### Scoring System\n\n**Dual headline scores:**\n- **Design Score: {A-F}** — weighted average of all 10 categories\n- **AI Slop Score: {A-F}** — standalone grade with pithy verdict\n\n**Per-category grades:**\n- **A:** Intentional, polished, delightful. Shows design thinking.\n- **B:** Solid fundamentals, minor inconsistencies. Looks professional.\n- **C:** Functional but generic. No major problems, no design point of view.\n- **D:** Noticeable problems. Feels unfinished or careless.\n- **F:** Actively hurting user experience. Needs significant rework.\n\n**Grade computation:** Each category starts at A. Each High-impact finding drops one letter grade. Each Medium-impact finding drops half a letter grade. Polish findings are noted but do not affect grade. Minimum is F.\n\n**Category weights for Design Score:**\n| Category | Weight |\n|----------|--------|\n| Visual Hierarchy | 15% |\n| Typography | 15% |\n| Spacing & Layout | 15% |\n| Color & Contrast | 10% |\n| Interaction States | 10% |\n| Responsive | 10% |\n| Content Quality | 10% |\n| AI Slop | 5% |\n| Motion | 5% |\n| Performance Feel | 5% |\n\nAI Slop is 5% of Design Score but also graded independently as a headline metric.\n\n### Regression Output\n\nWhen previous `design-baseline.json` exists or `--regression` flag is used:\n- Load baseline grades\n- Compare: per-category deltas, new findings, resolved findings\n- Append regression table to report\n\n---\n\n## Design Critique Format\n\nUse structured feedback, not opinions:\n- \"I notice...\" — observation (e.g., \"I notice the primary CTA competes with the secondary action\")\n- \"I wonder...\" — question (e.g., \"I wonder if users will understand what 'Process' means here\")\n- \"What if...\" — suggestion (e.g., \"What if we moved search to a more prominent position?\")\n- \"I think... because...\" — reasoned opinion (e.g., \"I think the spacing between sections is too uniform because it doesn't create hierarchy\")\n\nTie everything to user goals and product objectives. Always suggest specific improvements alongside problems.\n\n---\n\n## Important Rules\n\n1. **Think like a designer, not a QA engineer.** You care whether things feel right, look intentional, and respect the user. You do NOT just care whether things \"work.\"\n2. **Screenshots are evidence.** Every finding needs at least one screenshot. Use annotated screenshots (`snapshot -a`) to highlight elements.\n3. **Be specific and actionable.** \"Change X to Y because Z\" — not \"the spacing feels off.\"\n4. **Never read source code.** Evaluate the rendered site, not the implementation. (Exception: offer to write DESIGN.md from extracted observations.)\n5. **AI Slop detection is your superpower.** Most developers can't evaluate whether their site looks AI-generated. You can. Be direct about it.\n6. **Quick wins matter.** Always include a \"Quick Wins\" section — the 3-5 highest-impact fixes that take <30 minutes each.\n7. **Use `snapshot -C` for tricky UIs.** Finds clickable divs that the accessibility tree misses.\n8. **R...","readmeExcerpt":"Skill: Wip Ai Devops Toolbox Private Owner: parkertoddbrooks Summary: Complete DevOps toolkit for AI-assisted software development. Release pipeline, license compliance, copyright enforcement, repo visibility guard, identity fi... Tags: latest:1.9.72 Version history: v1.9.72 | 2026-04-21T21:26:17.753Z | user AI DevOps Toolbox v1.9.72 Promote v1.9.71-alpha series to stable Closes #256. Consolidates 21 alpha prerelease","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"grep -r \"/Users/lesa\" ldm-jobs/ tools/wip-branch-guard/test.sh\n# Should return zero results"},{"language":"bash","snippet":"# In any repo with multiple merged PRs since last tag, each having RELEASE-NOTES files:\nwip-release patch --dry-run\n# Should show: \"Combined release notes from N merged PRs\""},{"language":"bash","snippet":"# On main, without release notes: should error, NOT scaffold\ncd any-repo && git checkout main\nwip-release patch\n# Expected: \"Release notes missing. Write RELEASE-NOTES-v*.md on your feature branch before merging.\"\n# Expected: no RELEASE-NOTES file created in working tree\n\n# On a feature branch: should scaffold as before\ngit checkout -b test/scaffold-check\nwip-release patch\n# Expected: scaffolded template created"},{"language":"bash","snippet":"wip-release patch --dry-run\n# Should show no \"fatal\" or \"Not a valid object name\" errors\n# Guard tests: cd tools/wip-branch-guard && bash test.sh"},{"language":"bash","snippet":"wip-release patch\ngit status\n# Should show clean working tree after release"},{"language":"bash","snippet":"cd tools/wip-branch-guard && bash test.sh\n# Should show: 30 passed, 0 failed, 3 skipped"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"ai/repos/gstack-private/browse/SKILL.md","content":"---\nname: browse\nversion: 1.1.0\ndescription: |\n  Fast headless browser for QA testing and site dogfooding. Navigate any URL, interact with\n  elements, verify page state, diff before/after actions, take annotated screenshots, check\n  responsive layouts, test forms and uploads, handle dialogs, and assert element states.\n  ~100ms per command. Use when you need to test a feature, verify a deployment, dogfood a\n  user flow, or file a bug with evidence. Use when asked to \"open in browser\", \"test the\n  site\", \"take a screenshot\", or \"dogfood this\".\nallowed-tools:\n  - Bash\n  - Read\n  - AskUserQuestion\n\n---\n<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n<!-- Regenerate: bun run gen:skill-docs -->\n\n## Preamble (run first)\n\n```bash\n_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)\n[ -n \"$_UPD\" ] && echo \"$_UPD\" || true\nmkdir -p ~/.gstack/sessions\ntouch ~/.gstack/sessions/\"$PPID\"\n_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')\nfind ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true\n_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)\n_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo \"true\")\n_BRANCH=$(git branch --show-current 2>/dev/null || echo \"unknown\")\necho \"BRANCH: $_BRANCH\"\necho \"PROACTIVE: $_PROACTIVE\"\n_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo \"yes\" || echo \"no\")\necho \"LAKE_INTRO: $_LAKE_SEEN\"\nmkdir -p ~/.gstack/analytics\necho '{\"skill\":\"browse\",\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"repo\":\"'$(basename \"$(git rev-parse --show-toplevel 2>/dev/null)\" 2>/dev/null || echo \"unknown\")'\"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true\n```\n\nIf `PROACTIVE` is `\"false\"`, do not proactively suggest gstack skills — only invoke\nthem when the user explicitly asks. The user opted out of proactive suggestions.\n\nIf output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the \"Inline upgrade flow\" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user \"Running gstack v{to} (just updated!)\" and continue.\n\nIf `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle.\nTell the user: \"gstack follows the **Boil the Lake** principle — always do the complete\nthing when AI makes the marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean\"\nThen offer to open the essay in their default browser:\n\n```bash\nopen https://garryslist.org/posts/boil-the-ocean\ntouch ~/.gstack/.completeness-intro-seen\n```\n\nOnly run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once.\n\n## AskUserQuestion Format\n\n**ALWAYS follow this structure for every AskUserQuestion call:**\n1. **Re-ground:** State the pro"},{"path":"ai/repos/gstack-private/careful/SKILL.md","content":"---\nname: careful\nversion: 0.1.0\ndescription: |\n  Safety guardrails for destructive commands. Warns before rm -rf, DROP TABLE,\n  force-push, git reset --hard, kubectl delete, and similar destructive operations.\n  User can override each warning. Use when touching prod, debugging live systems,\n  or working in a shared environment. Use when asked to \"be careful\", \"safety mode\",\n  \"prod mode\", or \"careful mode\".\nallowed-tools:\n  - Bash\n  - Read\nhooks:\n  PreToolUse:\n    - matcher: \"Bash\"\n      hooks:\n        - type: command\n          command: \"bash ${CLAUDE_SKILL_DIR}/bin/check-careful.sh\"\n          statusMessage: \"Checking for destructive commands...\"\n---\n<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n<!-- Regenerate: bun run gen:skill-docs -->\n\n# /careful — Destructive Command Guardrails\n\nSafety mode is now **active**. Every bash command will be checked for destructive\npatterns before running. If a destructive command is detected, you'll be warned\nand can choose to proceed or cancel.\n\n```bash\nmkdir -p ~/.gstack/analytics\necho '{\"skill\":\"careful\",\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"repo\":\"'$(basename \"$(git rev-parse --show-toplevel 2>/dev/null)\" 2>/dev/null || echo \"unknown\")'\"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true\n```\n\n## What's protected\n\n| Pattern | Example | Risk |\n|---------|---------|------|\n| `rm -rf` / `rm -r` / `rm --recursive` | `rm -rf /var/data` | Recursive delete |\n| `DROP TABLE` / `DROP DATABASE` | `DROP TABLE users;` | Data loss |\n| `TRUNCATE` | `TRUNCATE orders;` | Data loss |\n| `git push --force` / `-f` | `git push -f origin main` | History rewrite |\n| `git reset --hard` | `git reset --hard HEAD~3` | Uncommitted work loss |\n| `git checkout .` / `git restore .` | `git checkout .` | Uncommitted work loss |\n| `kubectl delete` | `kubectl delete pod` | Production impact |\n| `docker rm -f` / `docker system prune` | `docker system prune -a` | Container/image loss |\n\n## Safe exceptions\n\nThese patterns are allowed without warning:\n- `rm -rf node_modules` / `.next` / `dist` / `__pycache__` / `.cache` / `build` / `.turbo` / `coverage`\n\n## How it works\n\nThe hook reads the command from the tool input JSON, checks it against the\npatterns above, and returns `permissionDecision: \"ask\"` with a warning message\nif a match is found. You can always override the warning and proceed.\n\nTo deactivate, end the conversation or start a new one. Hooks are session-scoped."},{"path":"ai/repos/gstack-private/codex/SKILL.md","content":"---\nname: codex\nversion: 1.0.0\ndescription: |\n  OpenAI Codex CLI wrapper — three modes. Code review: independent diff review via\n  codex review with pass/fail gate. Challenge: adversarial mode that tries to break\n  your code. Consult: ask codex anything with session continuity for follow-ups.\n  The \"200 IQ autistic developer\" second opinion. Use when asked to \"codex review\",\n  \"codex challenge\", \"ask codex\", \"second opinion\", or \"consult codex\".\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Glob\n  - Grep\n  - AskUserQuestion\n---\n<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n<!-- Regenerate: bun run gen:skill-docs -->\n\n## Preamble (run first)\n\n```bash\n_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)\n[ -n \"$_UPD\" ] && echo \"$_UPD\" || true\nmkdir -p ~/.gstack/sessions\ntouch ~/.gstack/sessions/\"$PPID\"\n_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')\nfind ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true\n_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)\n_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo \"true\")\n_BRANCH=$(git branch --show-current 2>/dev/null || echo \"unknown\")\necho \"BRANCH: $_BRANCH\"\necho \"PROACTIVE: $_PROACTIVE\"\n_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo \"yes\" || echo \"no\")\necho \"LAKE_INTRO: $_LAKE_SEEN\"\nmkdir -p ~/.gstack/analytics\necho '{\"skill\":\"codex\",\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"repo\":\"'$(basename \"$(git rev-parse --show-toplevel 2>/dev/null)\" 2>/dev/null || echo \"unknown\")'\"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true\n```\n\nIf `PROACTIVE` is `\"false\"`, do not proactively suggest gstack skills — only invoke\nthem when the user explicitly asks. The user opted out of proactive suggestions.\n\nIf output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the \"Inline upgrade flow\" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user \"Running gstack v{to} (just updated!)\" and continue.\n\nIf `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle.\nTell the user: \"gstack follows the **Boil the Lake** principle — always do the complete\nthing when AI makes the marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean\"\nThen offer to open the essay in their default browser:\n\n```bash\nopen https://garryslist.org/posts/boil-the-ocean\ntouch ~/.gstack/.completeness-intro-seen\n```\n\nOnly run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once.\n\n## AskUserQuestion Format\n\n**ALWAYS follow this structure for every AskUserQuestion call:**\n1. **Re-ground:** State the project, the current branch (use the `_BRANCH` value printed by the preambl"},{"path":"ai/repos/gstack-private/design-consultation/SKILL.md","content":"---\nname: design-consultation\nversion: 1.0.0\ndescription: |\n  Design consultation: understands your product, researches the landscape, proposes a\n  complete design system (aesthetic, typography, color, layout, spacing, motion), and\n  generates font+color preview pages. Creates DESIGN.md as your project's design source\n  of truth. For existing sites, use /plan-design-review to infer the system instead.\n  Use when asked to \"design system\", \"brand guidelines\", or \"create DESIGN.md\".\n  Proactively suggest when starting a new project's UI with no existing\n  design system or DESIGN.md.\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Edit\n  - Glob\n  - Grep\n  - AskUserQuestion\n  - WebSearch\n---\n<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n<!-- Regenerate: bun run gen:skill-docs -->\n\n## Preamble (run first)\n\n```bash\n_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)\n[ -n \"$_UPD\" ] && echo \"$_UPD\" || true\nmkdir -p ~/.gstack/sessions\ntouch ~/.gstack/sessions/\"$PPID\"\n_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')\nfind ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true\n_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)\n_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo \"true\")\n_BRANCH=$(git branch --show-current 2>/dev/null || echo \"unknown\")\necho \"BRANCH: $_BRANCH\"\necho \"PROACTIVE: $_PROACTIVE\"\n_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo \"yes\" || echo \"no\")\necho \"LAKE_INTRO: $_LAKE_SEEN\"\nmkdir -p ~/.gstack/analytics\necho '{\"skill\":\"design-consultation\",\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"repo\":\"'$(basename \"$(git rev-parse --show-toplevel 2>/dev/null)\" 2>/dev/null || echo \"unknown\")'\"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true\n```\n\nIf `PROACTIVE` is `\"false\"`, do not proactively suggest gstack skills — only invoke\nthem when the user explicitly asks. The user opted out of proactive suggestions.\n\nIf output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the \"Inline upgrade flow\" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user \"Running gstack v{to} (just updated!)\" and continue.\n\nIf `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle.\nTell the user: \"gstack follows the **Boil the Lake** principle — always do the complete\nthing when AI makes the marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean\"\nThen offer to open the essay in their default browser:\n\n```bash\nopen https://garryslist.org/posts/boil-the-ocean\ntouch ~/.gstack/.completeness-intro-seen\n```\n\nOnly run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once.\n\n## AskUserQuestion Fo"},{"path":"ai/repos/gstack-private/design-review/SKILL.md","content":"---\nname: design-review\nversion: 2.0.0\ndescription: |\n  Designer's eye QA: finds visual inconsistency, spacing issues, hierarchy problems,\n  AI slop patterns, and slow interactions — then fixes them. Iteratively fixes issues\n  in source code, committing each fix atomically and re-verifying with before/after\n  screenshots. For plan-mode design review (before implementation), use /plan-design-review.\n  Use when asked to \"audit the design\", \"visual QA\", \"check if it looks good\", or \"design polish\".\n  Proactively suggest when the user mentions visual inconsistencies or\n  wants to polish the look of a live site.\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Edit\n  - Glob\n  - Grep\n  - AskUserQuestion\n  - WebSearch\n---\n<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->\n<!-- Regenerate: bun run gen:skill-docs -->\n\n## Preamble (run first)\n\n```bash\n_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)\n[ -n \"$_UPD\" ] && echo \"$_UPD\" || true\nmkdir -p ~/.gstack/sessions\ntouch ~/.gstack/sessions/\"$PPID\"\n_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')\nfind ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true\n_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)\n_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo \"true\")\n_BRANCH=$(git branch --show-current 2>/dev/null || echo \"unknown\")\necho \"BRANCH: $_BRANCH\"\necho \"PROACTIVE: $_PROACTIVE\"\n_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo \"yes\" || echo \"no\")\necho \"LAKE_INTRO: $_LAKE_SEEN\"\nmkdir -p ~/.gstack/analytics\necho '{\"skill\":\"design-review\",\"ts\":\"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'\",\"repo\":\"'$(basename \"$(git rev-parse --show-toplevel 2>/dev/null)\" 2>/dev/null || echo \"unknown\")'\"}'  >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true\n```\n\nIf `PROACTIVE` is `\"false\"`, do not proactively suggest gstack skills — only invoke\nthem when the user explicitly asks. The user opted out of proactive suggestions.\n\nIf output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the \"Inline upgrade flow\" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user \"Running gstack v{to} (just updated!)\" and continue.\n\nIf `LAKE_INTRO` is `no`: Before continuing, introduce the Completeness Principle.\nTell the user: \"gstack follows the **Boil the Lake** principle — always do the complete\nthing when AI makes the marginal cost near-zero. Read more: https://garryslist.org/posts/boil-the-ocean\"\nThen offer to open the essay in their default browser:\n\n```bash\nopen https://garryslist.org/posts/boil-the-ocean\ntouch ~/.gstack/.completeness-intro-seen\n```\n\nOnly run `open` if the user says yes. Always run `touch` to mark as seen. This only happens once.\n"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":3141,"uniquenessScore":35,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T04:42:48.241Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T04:42:48.241Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-09T22:49:30.286Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}