mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-12 19:44:48 +01:00
Merge remote-tracking branch 'origin/garrytan/opus55-wip-G' into garrytan/opus-5-5-prompt-audit
This commit is contained in:
commit
7eb343904d
79 files changed
+265
-214
No files matched your search
@@ -135,7 +135,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "gstack" --outcome OUTCOME \
|
||||
|
||||
+10
-8
@@ -404,7 +404,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "autoplan" --outcome OUTCOME \
|
||||
@@ -464,12 +464,13 @@ branch name wherever the instructions say "the base branch" or `<default>`.
|
||||
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true # zsh compat
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
|
||||
_LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
_LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
# Repo-local docs win when at least as fresh (#703): office-hours dual-writes
|
||||
# docs/designs/ alongside ~/.gstack, and the committed copy is what teammates
|
||||
# docs/designs/ alongside the state root, and the committed copy is what teammates
|
||||
# see. A stale old repo doc never shadows a newer private session.
|
||||
_REPOTOP=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
|
||||
_REPODOC=""
|
||||
@@ -533,12 +534,13 @@ Execute every other section at full depth. When the loaded skill's instructions
|
||||
After /office-hours completes, re-run the design doc check:
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true # zsh compat
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
|
||||
_LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
_LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
# Repo-local docs win when at least as fresh (#703): office-hours dual-writes
|
||||
# docs/designs/ alongside ~/.gstack, and the committed copy is what teammates
|
||||
# docs/designs/ alongside the state root, and the committed copy is what teammates
|
||||
# see. A stale old repo doc never shadows a newer private session.
|
||||
_REPOTOP=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
|
||||
_REPODOC=""
|
||||
@@ -747,7 +749,7 @@ Re-run: copy RESTORE_PATH's bytes to SOURCE_PLAN, then /autoplan.
|
||||
### Step 2: Read context
|
||||
|
||||
- Read CLAUDE.md, TODOS.md, git log -30, git diff against the base branch --stat
|
||||
- Discover design docs: `ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1`
|
||||
- Discover design docs: `ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-design-*.md 2>/dev/null | head -1`, resolving the state root and slug as the Design Doc Check block does
|
||||
- Detect UI scope: grep the plan for view/rendering terms (component, screen, form,
|
||||
button, modal, layout, dashboard, sidebar, nav, dialog). Require 2+ matches. Exclude
|
||||
false positives ("page" alone, "UI" in acronyms).
|
||||
|
||||
@@ -39,6 +39,7 @@ allowed-tools:
|
||||
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true # zsh compat
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
|
||||
{{DESIGN_DOC_DISCOVERY}}
|
||||
@@ -224,7 +225,7 @@ Re-run: copy RESTORE_PATH's bytes to SOURCE_PLAN, then /autoplan.
|
||||
### Step 2: Read context
|
||||
|
||||
- Read CLAUDE.md, TODOS.md, git log -30, git diff against the base branch --stat
|
||||
- Discover design docs: `ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1`
|
||||
- Discover design docs: `ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-design-*.md 2>/dev/null | head -1`, resolving the state root and slug as the Design Doc Check block does
|
||||
- Detect UI scope: grep the plan for view/rendering terms (component, screen, form,
|
||||
button, modal, layout, dashboard, sidebar, nav, dialog). Require 2+ matches. Exclude
|
||||
false positives ("page" alone, "UI" in acronyms).
|
||||
|
||||
@@ -139,7 +139,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "benchmark-models" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "benchmark" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "browse" --outcome OUTCOME \
|
||||
|
||||
+2
-2
@@ -356,7 +356,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "canary" --outcome OUTCOME \
|
||||
@@ -701,7 +701,7 @@ mkdir -p "$GSTACK_STATE_ROOT"/projects/$SLUG
|
||||
```
|
||||
|
||||
Write a JSONL entry: `{"skill":"canary","timestamp":"<ISO>","status":"<HEALTHY/DEGRADED/BROKEN>","url":"<url>","duration_min":<N>,"alerts":<N>}`
|
||||
Append it to `~/.gstack/projects/$SLUG/canary-history.jsonl`; never overwrite history.
|
||||
Append it to `$GSTACK_STATE_ROOT/projects/$SLUG/canary-history.jsonl` (the directory this block created); never overwrite history.
|
||||
|
||||
### Phase 7: Baseline Update
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ mkdir -p "$GSTACK_STATE_ROOT"/projects/$SLUG
|
||||
```
|
||||
|
||||
Write a JSONL entry: `{"skill":"canary","timestamp":"<ISO>","status":"<HEALTHY/DEGRADED/BROKEN>","url":"<url>","duration_min":<N>,"alerts":<N>}`
|
||||
Append it to `~/.gstack/projects/$SLUG/canary-history.jsonl`; never overwrite history.
|
||||
Append it to `$GSTACK_STATE_ROOT/projects/$SLUG/canary-history.jsonl` (the directory this block created); never overwrite history.
|
||||
|
||||
### Phase 7: Baseline Update
|
||||
|
||||
|
||||
+1
-1
@@ -388,7 +388,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "codex" --outcome OUTCOME \
|
||||
|
||||
@@ -358,7 +358,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "context-restore" --outcome OUTCOME \
|
||||
|
||||
@@ -357,7 +357,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "context-save" --outcome OUTCOME \
|
||||
|
||||
@@ -26,7 +26,7 @@ gbrain:
|
||||
render_as: "## Existing DESIGN.md (if any)"
|
||||
- id: prior-design-decisions
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/*-design-*.md"
|
||||
sort: mtime_desc
|
||||
limit: 3
|
||||
render_as: "## Prior design decisions for this project"
|
||||
@@ -411,7 +411,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "design-consultation" --outcome OUTCOME \
|
||||
@@ -687,7 +687,7 @@ fonts [top-3], colors [top-3], layouts [top-3], aesthetics [top-3]. Bias
|
||||
generation toward these unless the user explicitly requests a different direction.
|
||||
Also avoid their strong rejections: [top-3 rejected per dimension]."
|
||||
|
||||
**Legacy fallback:** Glob `~/.gstack/projects/$SLUG/designs/**/approved.json`; Read the five newest. Use explicit feedback only, never infer fonts/colors from variant letters. No usable files: continue without a taste profile.
|
||||
**Legacy fallback:** Glob `$GSTACK_STATE_ROOT/projects/$SLUG/designs/**/approved.json` (resolve the root with gstack-paths); Read the five newest. Use explicit feedback only, never infer fonts/colors from variant letters. No usable files: continue without a taste profile.
|
||||
|
||||
**Conflict handling:** If the current user request contradicts a strong persistent
|
||||
signal (e.g., "make it playful" when taste profile strongly prefers minimal), flag
|
||||
|
||||
@@ -33,7 +33,7 @@ gbrain:
|
||||
render_as: "## Existing DESIGN.md (if any)"
|
||||
- id: prior-design-decisions
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/*-design-*.md"
|
||||
sort: mtime_desc
|
||||
limit: 3
|
||||
render_as: "## Prior design decisions for this project"
|
||||
|
||||
@@ -363,7 +363,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "design-html" --outcome OUTCOME \
|
||||
|
||||
@@ -389,7 +389,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "design-review" --outcome OUTCOME \
|
||||
|
||||
@@ -30,7 +30,7 @@ gbrain:
|
||||
render_as: "## DESIGN.md (project design system)"
|
||||
- id: recent-design-docs
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/*-design-*.md"
|
||||
sort: mtime_desc
|
||||
limit: 3
|
||||
render_as: "## Recent design docs"
|
||||
@@ -377,7 +377,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "design-shotgun" --outcome OUTCOME \
|
||||
@@ -578,7 +578,7 @@ fonts [top-3], colors [top-3], layouts [top-3], aesthetics [top-3]. Bias
|
||||
generation toward these unless the user explicitly requests a different direction.
|
||||
Also avoid their strong rejections: [top-3 rejected per dimension]."
|
||||
|
||||
**Legacy fallback:** Glob `~/.gstack/projects/$SLUG/designs/**/approved.json`; Read the five newest. Use explicit feedback only, never infer fonts/colors from variant letters. No usable files: continue without a taste profile.
|
||||
**Legacy fallback:** Glob `$GSTACK_STATE_ROOT/projects/$SLUG/designs/**/approved.json` (resolve the root with gstack-paths); Read the five newest. Use explicit feedback only, never infer fonts/colors from variant letters. No usable files: continue without a taste profile.
|
||||
|
||||
**Conflict handling:** If the current user request contradicts a strong persistent
|
||||
signal (e.g., "make it playful" when taste profile strongly prefers minimal), flag
|
||||
|
||||
@@ -36,7 +36,7 @@ gbrain:
|
||||
render_as: "## DESIGN.md (project design system)"
|
||||
- id: recent-design-docs
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/*-design-*.md"
|
||||
sort: mtime_desc
|
||||
limit: 3
|
||||
render_as: "## Recent design docs"
|
||||
|
||||
@@ -391,7 +391,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "devex-review" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -138,7 +138,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "diagram" --outcome OUTCOME \
|
||||
|
||||
@@ -362,7 +362,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "document-generate" --outcome OUTCOME \
|
||||
|
||||
@@ -360,7 +360,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "document-release" --outcome OUTCOME \
|
||||
|
||||
+3
-3
@@ -358,7 +358,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "health" --outcome OUTCOME \
|
||||
@@ -642,7 +642,7 @@ eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" && mkdir -p "$GSTA
|
||||
```
|
||||
|
||||
Only when a numeric composite exists, append one JSONL line to
|
||||
`~/.gstack/projects/$SLUG/health-history.jsonl`. Zero-check and capture-error runs
|
||||
`$GSTACK_STATE_ROOT/projects/$SLUG/health-history.jsonl` (the `PROJECT_DIR` printed above). Zero-check and capture-error runs
|
||||
must leave any existing history unchanged:
|
||||
|
||||
```json
|
||||
@@ -663,7 +663,7 @@ with no `gbrain` field as `null` for that category.
|
||||
|
||||
## Step 6: Trend Analysis + Recommendations
|
||||
|
||||
Read the last 10 entries from `~/.gstack/projects/$SLUG/health-history.jsonl` (if the
|
||||
Read the last 10 entries from `$GSTACK_STATE_ROOT/projects/$SLUG/health-history.jsonl` (if the
|
||||
file exists and has prior entries).
|
||||
|
||||
```bash
|
||||
|
||||
@@ -290,7 +290,7 @@ DETAILS: Lint (3 warnings)
|
||||
```
|
||||
|
||||
Only when a numeric composite exists, append one JSONL line to
|
||||
`~/.gstack/projects/$SLUG/health-history.jsonl`. Zero-check and capture-error runs
|
||||
`$GSTACK_STATE_ROOT/projects/$SLUG/health-history.jsonl` (the `PROJECT_DIR` printed above). Zero-check and capture-error runs
|
||||
must leave any existing history unchanged:
|
||||
|
||||
```json
|
||||
@@ -311,7 +311,7 @@ with no `gbrain` field as `null` for that category.
|
||||
|
||||
## Step 6: Trend Analysis + Recommendations
|
||||
|
||||
Read the last 10 entries from `~/.gstack/projects/$SLUG/health-history.jsonl` (if the
|
||||
Read the last 10 entries from `$GSTACK_STATE_ROOT/projects/$SLUG/health-history.jsonl` (if the
|
||||
file exists and has prior entries).
|
||||
|
||||
```bash
|
||||
|
||||
@@ -44,12 +44,12 @@ gbrain:
|
||||
render_as: "## Prior investigations in this repo"
|
||||
- id: project-learnings
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/learnings.jsonl"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/learnings.jsonl"
|
||||
tail: 10
|
||||
render_as: "## Recent learnings (patterns + pitfalls)"
|
||||
- id: recent-eureka
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/analytics/eureka.jsonl"
|
||||
glob: "{gstack_state_root}/analytics/eureka.jsonl"
|
||||
tail: 5
|
||||
render_as: "## Recent eureka moments (cross-project)"
|
||||
---
|
||||
@@ -397,7 +397,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "investigate" --outcome OUTCOME \
|
||||
|
||||
@@ -51,12 +51,12 @@ gbrain:
|
||||
render_as: "## Prior investigations in this repo"
|
||||
- id: project-learnings
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/learnings.jsonl"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/learnings.jsonl"
|
||||
tail: 10
|
||||
render_as: "## Recent learnings (patterns + pitfalls)"
|
||||
- id: recent-eureka
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/analytics/eureka.jsonl"
|
||||
glob: "{gstack_state_root}/analytics/eureka.jsonl"
|
||||
tail: 5
|
||||
render_as: "## Recent eureka moments (cross-project)"
|
||||
---
|
||||
|
||||
+1
-1
@@ -360,7 +360,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "ios-clean" --outcome OUTCOME \
|
||||
|
||||
@@ -362,7 +362,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "ios-design-review" --outcome OUTCOME \
|
||||
@@ -441,9 +441,16 @@ For each screen in the app, score 0-10 and explain what would push it to 10:
|
||||
## Output
|
||||
|
||||
Write a markdown report to
|
||||
`~/.gstack/projects/<slug>/ios-design-review-<date>.md`. Include the
|
||||
screenshots inline. The CEO/eng review skills can reference this report
|
||||
when planning UI changes.
|
||||
`$GSTACK_STATE_ROOT/projects/<slug>/ios-design-review-<date>.md`, using the
|
||||
`PROJECT_DIR` this block prints:
|
||||
|
||||
```bash
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)" && mkdir -p "$GSTACK_STATE_ROOT/projects/$SLUG" && echo "PROJECT_DIR: $GSTACK_STATE_ROOT/projects/$SLUG"
|
||||
```
|
||||
|
||||
Include the screenshots inline. The CEO/eng review skills can reference this
|
||||
report when planning UI changes.
|
||||
|
||||
## Failure modes
|
||||
|
||||
|
||||
@@ -92,9 +92,15 @@ For each screen in the app, score 0-10 and explain what would push it to 10:
|
||||
## Output
|
||||
|
||||
Write a markdown report to
|
||||
`~/.gstack/projects/<slug>/ios-design-review-<date>.md`. Include the
|
||||
screenshots inline. The CEO/eng review skills can reference this report
|
||||
when planning UI changes.
|
||||
`$GSTACK_STATE_ROOT/projects/<slug>/ios-design-review-<date>.md`, using the
|
||||
`PROJECT_DIR` this block prints:
|
||||
|
||||
```bash
|
||||
{{SLUG_SETUP}}
|
||||
```
|
||||
|
||||
Include the screenshots inline. The CEO/eng review skills can reference this
|
||||
report when planning UI changes.
|
||||
|
||||
## Failure modes
|
||||
|
||||
|
||||
+1
-1
@@ -363,7 +363,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "ios-fix" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -395,7 +395,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "ios-qa" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -360,7 +360,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "ios-sync" --outcome OUTCOME \
|
||||
|
||||
@@ -384,7 +384,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "land-and-deploy" --outcome OUTCOME \
|
||||
|
||||
@@ -357,7 +357,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "landing-report" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -358,7 +358,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "learn" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "make-pdf" --outcome OUTCOME \
|
||||
|
||||
@@ -30,17 +30,17 @@ gbrain:
|
||||
render_as: "## Prior office-hours sessions in this repo"
|
||||
- id: builder-profile
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/developer-profile.json"
|
||||
glob: "{gstack_state_root}/developer-profile.json"
|
||||
render_as: "## Your builder profile snapshot"
|
||||
- id: design-doc-history
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/*-design-*.md"
|
||||
sort: mtime_desc
|
||||
limit: 3
|
||||
render_as: "## Recent design docs for this project"
|
||||
- id: prior-eureka
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/analytics/eureka.jsonl"
|
||||
glob: "{gstack_state_root}/analytics/eureka.jsonl"
|
||||
tail: 5
|
||||
render_as: "## Recent eureka moments"
|
||||
---
|
||||
@@ -421,7 +421,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "office-hours" --outcome OUTCOME \
|
||||
|
||||
@@ -41,17 +41,17 @@ gbrain:
|
||||
render_as: "## Prior office-hours sessions in this repo"
|
||||
- id: builder-profile
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/developer-profile.json"
|
||||
glob: "{gstack_state_root}/developer-profile.json"
|
||||
render_as: "## Your builder profile snapshot"
|
||||
- id: design-doc-history
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/*-design-*.md"
|
||||
sort: mtime_desc
|
||||
limit: 3
|
||||
render_as: "## Recent design docs for this project"
|
||||
- id: prior-eureka
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/analytics/eureka.jsonl"
|
||||
glob: "{gstack_state_root}/analytics/eureka.jsonl"
|
||||
tail: 5
|
||||
render_as: "## Recent eureka moments"
|
||||
---
|
||||
|
||||
@@ -137,7 +137,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "open-gstack-browser" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -359,7 +359,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "pair-agent" --outcome OUTCOME \
|
||||
|
||||
@@ -26,7 +26,7 @@ gbrain:
|
||||
render_as: "## Prior CEO plans for this project"
|
||||
- id: recent-design-docs
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/*-design-*.md"
|
||||
sort: mtime_desc
|
||||
limit: 3
|
||||
render_as: "## Recent design docs for this project"
|
||||
@@ -407,7 +407,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "plan-ceo-review" --outcome OUTCOME \
|
||||
@@ -553,12 +553,13 @@ Then read CLAUDE.md, TODOS.md, and any existing architecture docs.
|
||||
**Design doc check:**
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true # zsh compat
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
|
||||
_LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
_LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
# Repo-local docs win when at least as fresh (#703): office-hours dual-writes
|
||||
# docs/designs/ alongside ~/.gstack, and the committed copy is what teammates
|
||||
# docs/designs/ alongside the state root, and the committed copy is what teammates
|
||||
# see. A stale old repo doc never shadows a newer private session.
|
||||
_REPOTOP=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
|
||||
_REPODOC=""
|
||||
@@ -621,12 +622,13 @@ Execute every other section at full depth. When the loaded skill's instructions
|
||||
After /office-hours completes, re-run the design doc check:
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true # zsh compat
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
|
||||
_LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
_LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
# Repo-local docs win when at least as fresh (#703): office-hours dual-writes
|
||||
# docs/designs/ alongside ~/.gstack, and the committed copy is what teammates
|
||||
# docs/designs/ alongside the state root, and the committed copy is what teammates
|
||||
# see. A stale old repo doc never shadows a newer private session.
|
||||
_REPOTOP=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
|
||||
_REPODOC=""
|
||||
|
||||
@@ -36,7 +36,7 @@ gbrain:
|
||||
render_as: "## Prior CEO plans for this project"
|
||||
- id: recent-design-docs
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/*-design-*.md"
|
||||
sort: mtime_desc
|
||||
limit: 3
|
||||
render_as: "## Recent design docs for this project"
|
||||
@@ -112,6 +112,7 @@ Then read CLAUDE.md, TODOS.md, and any existing architecture docs.
|
||||
**Design doc check:**
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true # zsh compat
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
|
||||
{{DESIGN_DOC_DISCOVERY}}
|
||||
|
||||
@@ -413,7 +413,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "plan-design-review" --outcome OUTCOME \
|
||||
|
||||
@@ -385,7 +385,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "plan-devex-review" --outcome OUTCOME \
|
||||
@@ -577,12 +577,13 @@ No background exploration before those questions; record unknowns for later.
|
||||
**Design doc check:**
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
|
||||
_LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
_LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
# Repo-local docs win when at least as fresh (#703): office-hours dual-writes
|
||||
# docs/designs/ alongside ~/.gstack, and the committed copy is what teammates
|
||||
# docs/designs/ alongside the state root, and the committed copy is what teammates
|
||||
# see. A stale old repo doc never shadows a newer private session.
|
||||
_REPOTOP=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
|
||||
_REPODOC=""
|
||||
@@ -820,12 +821,13 @@ Execute every other section at full depth. When the loaded skill's instructions
|
||||
After /office-hours completes, re-run the design doc check:
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true # zsh compat
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
|
||||
_LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
_LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
# Repo-local docs win when at least as fresh (#703): office-hours dual-writes
|
||||
# docs/designs/ alongside ~/.gstack, and the committed copy is what teammates
|
||||
# docs/designs/ alongside the state root, and the committed copy is what teammates
|
||||
# see. A stale old repo doc never shadows a newer private session.
|
||||
_REPOTOP=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
|
||||
_REPODOC=""
|
||||
|
||||
@@ -106,6 +106,7 @@ No background exploration before those questions; record unknowns for later.
|
||||
**Design doc check:**
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
|
||||
{{DESIGN_DOC_DISCOVERY}}
|
||||
|
||||
@@ -430,7 +430,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "plan-eng-review" --outcome OUTCOME \
|
||||
@@ -567,12 +567,13 @@ Sanitize every query before it leaves the machine: strip hostnames, IPs, file pa
|
||||
### Design Doc Check
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true # zsh compat
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
if _REVIEW_SLUG=$(~/.claude/skills/gstack/bin/gstack-slug); then
|
||||
eval "$_REVIEW_SLUG"
|
||||
_LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
_LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
# Repo-local docs win when at least as fresh (#703): office-hours dual-writes
|
||||
# docs/designs/ alongside ~/.gstack, and the committed copy is what teammates
|
||||
# docs/designs/ alongside the state root, and the committed copy is what teammates
|
||||
# see. A stale old repo doc never shadows a newer private session.
|
||||
_REPOTOP=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
|
||||
_REPODOC=""
|
||||
|
||||
@@ -126,6 +126,7 @@ Apply throughout, not as extra checks:
|
||||
### Design Doc Check
|
||||
```bash
|
||||
setopt +o nomatch 2>/dev/null || true # zsh compat
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
if _REVIEW_SLUG=$(~/.claude/skills/gstack/bin/gstack-slug); then
|
||||
eval "$_REVIEW_SLUG"
|
||||
{{DESIGN_DOC_DISCOVERY}}
|
||||
|
||||
+2
-2
@@ -368,7 +368,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "plan-tune" --outcome OUTCOME \
|
||||
@@ -419,7 +419,7 @@ Each gate is guarded by a marker so the user is prompted at most once per choice
|
||||
`~/.gstack/.declared-setup-prompted` is missing → run `5-Q setup` below.
|
||||
Touch the marker after setup completes OR is declined.
|
||||
3. **Dream-cycle gate.** If
|
||||
`~/.gstack/projects/<slug>/distillation-proposals.json` exists AND has
|
||||
`$GSTACK_STATE_ROOT/projects/<slug>/distillation-proposals.json` exists AND has
|
||||
`applied_at` missing on any proposal → run `Dream cycle review` below.
|
||||
Marker: each proposal carries its own `applied_at` so re-firing this
|
||||
gate naturally skips already-handled items.
|
||||
|
||||
@@ -69,7 +69,7 @@ Each gate is guarded by a marker so the user is prompted at most once per choice
|
||||
`~/.gstack/.declared-setup-prompted` is missing → run `5-Q setup` below.
|
||||
Touch the marker after setup completes OR is declined.
|
||||
3. **Dream-cycle gate.** If
|
||||
`~/.gstack/projects/<slug>/distillation-proposals.json` exists AND has
|
||||
`$GSTACK_STATE_ROOT/projects/<slug>/distillation-proposals.json` exists AND has
|
||||
`applied_at` missing on any proposal → run `Dream cycle review` below.
|
||||
Marker: each proposal carries its own `applied_at` so re-firing this
|
||||
gate naturally skips already-handled items.
|
||||
|
||||
+1
-1
@@ -387,7 +387,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "qa-only" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -391,7 +391,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "qa" --outcome OUTCOME \
|
||||
|
||||
+5
-5
@@ -25,12 +25,12 @@ gbrain:
|
||||
render_as: "## Prior retros for this project"
|
||||
- id: recent-timeline
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/timeline.jsonl"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/timeline.jsonl"
|
||||
tail: 30
|
||||
render_as: "## Recent timeline events"
|
||||
- id: recent-learnings
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/learnings.jsonl"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/learnings.jsonl"
|
||||
tail: 10
|
||||
render_as: "## Recent learnings"
|
||||
---
|
||||
@@ -376,7 +376,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "retro" --outcome OUTCOME \
|
||||
@@ -589,8 +589,8 @@ Also check `RETRO_REF`: if it is not `origin/<default>` (local-only repo, missin
|
||||
- `RETRO_CONTEXT: present` → Read `~/.gstack/retro-context.md`. It is user-authored and may contain meeting notes, calendar events, decisions, and other context that doesn't appear in git history. Incorporate it into the retro narrative where relevant.
|
||||
- `GREPTILE_HISTORY: present` → Read `~/.gstack/greptile-history.md`. Filter entries to the retro window by date. Count by type: `fix`, `fp`, `already-fixed`. Signal ratio = `(fix + already-fixed) / (fix + already-fixed + fp)`. Skip unparseable lines silently; if no entries fall in the window, skip the Greptile metric row.
|
||||
- `TODOS_FILE: present` → Read `TODOS.md`. Compute: total open TODOs (exclude the `## Completed` section), P0/P1 count, P2 count, items completed this period (Completed entries dated within the window), items added this period (cross-reference `COMMIT:` lines that touched TODOS.md).
|
||||
- `SKILL_USAGE_LOG: present` → Read `~/.gstack/analytics/skill-usage.jsonl`. Filter to the window by `ts`. Separate skill activations (no `event` field) from hook fires (`event: "hook_fire"`). Aggregate by skill name.
|
||||
- `EUREKA_LOG: present` → Read `~/.gstack/analytics/eureka.jsonl`. Filter to the window by `ts`. For each eureka moment note the skill that flagged it, the branch, and a one-line summary of the insight.
|
||||
- `SKILL_USAGE_LOG: present` → Read the path it prints (`$GSTACK_STATE_ROOT/analytics/skill-usage.jsonl`). Filter to the window by `ts`. Separate skill activations (no `event` field) from hook fires (`event: "hook_fire"`). Aggregate by skill name.
|
||||
- `EUREKA_LOG: present` → Read the path it prints (`$GSTACK_STATE_ROOT/analytics/eureka.jsonl`). Filter to the window by `ts`. For each eureka moment note the skill that flagged it, the branch, and a one-line summary of the insight.
|
||||
|
||||
### Step 2: Compute Metrics
|
||||
|
||||
|
||||
+4
-4
@@ -30,12 +30,12 @@ gbrain:
|
||||
render_as: "## Prior retros for this project"
|
||||
- id: recent-timeline
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/timeline.jsonl"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/timeline.jsonl"
|
||||
tail: 30
|
||||
render_as: "## Recent timeline events"
|
||||
- id: recent-learnings
|
||||
kind: filesystem
|
||||
glob: "~/.gstack/projects/{repo_slug}/learnings.jsonl"
|
||||
glob: "{gstack_state_root}/projects/{repo_slug}/learnings.jsonl"
|
||||
tail: 10
|
||||
render_as: "## Recent learnings"
|
||||
---
|
||||
@@ -158,8 +158,8 @@ Also check `RETRO_REF`: if it is not `origin/<default>` (local-only repo, missin
|
||||
- `RETRO_CONTEXT: present` → Read `~/.gstack/retro-context.md`. It is user-authored and may contain meeting notes, calendar events, decisions, and other context that doesn't appear in git history. Incorporate it into the retro narrative where relevant.
|
||||
- `GREPTILE_HISTORY: present` → Read `~/.gstack/greptile-history.md`. Filter entries to the retro window by date. Count by type: `fix`, `fp`, `already-fixed`. Signal ratio = `(fix + already-fixed) / (fix + already-fixed + fp)`. Skip unparseable lines silently; if no entries fall in the window, skip the Greptile metric row.
|
||||
- `TODOS_FILE: present` → Read `TODOS.md`. Compute: total open TODOs (exclude the `## Completed` section), P0/P1 count, P2 count, items completed this period (Completed entries dated within the window), items added this period (cross-reference `COMMIT:` lines that touched TODOS.md).
|
||||
- `SKILL_USAGE_LOG: present` → Read `~/.gstack/analytics/skill-usage.jsonl`. Filter to the window by `ts`. Separate skill activations (no `event` field) from hook fires (`event: "hook_fire"`). Aggregate by skill name.
|
||||
- `EUREKA_LOG: present` → Read `~/.gstack/analytics/eureka.jsonl`. Filter to the window by `ts`. For each eureka moment note the skill that flagged it, the branch, and a one-line summary of the insight.
|
||||
- `SKILL_USAGE_LOG: present` → Read the path it prints (`$GSTACK_STATE_ROOT/analytics/skill-usage.jsonl`). Filter to the window by `ts`. Separate skill activations (no `event` field) from hook fires (`event: "hook_fire"`). Aggregate by skill name.
|
||||
- `EUREKA_LOG: present` → Read the path it prints (`$GSTACK_STATE_ROOT/analytics/eureka.jsonl`). Filter to the window by `ts`. For each eureka moment note the skill that flagged it, the branch, and a one-line summary of the insight.
|
||||
|
||||
### Step 2: Compute Metrics
|
||||
|
||||
|
||||
+1
-1
@@ -389,7 +389,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "review" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -134,7 +134,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "scrape" --outcome OUTCOME \
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
* {{DESIGN_DOC_DISCOVERY}} — the canonical design-doc discovery block (#703).
|
||||
*
|
||||
* Finds the design doc a plan review should read: newest branch-scoped doc
|
||||
* under ~/.gstack/projects/<slug>/, falling back to newest project-scoped
|
||||
* under $GSTACK_STATE_ROOT/projects/<slug>/, falling back to newest project-scoped
|
||||
* doc, then lets a repo-local doc (DESIGN.md or docs/designs/*.md) win when
|
||||
* it is at least as fresh. office-hours dual-writes docs/designs/ alongside
|
||||
* ~/.gstack, and the committed copy is what teammates see — but a stale old
|
||||
* the state root, and the committed copy is what teammates see — but a stale old
|
||||
* repo doc must never shadow a newer private session.
|
||||
*
|
||||
* Single source of truth for the freshness-preference logic that previously
|
||||
@@ -16,7 +16,8 @@
|
||||
*
|
||||
* The fragment carries no code fences — the {{DESIGN_DOC_DISCOVERY}} token
|
||||
* sits inside each caller's ```bash block. Callers must set $SLUG and
|
||||
* $BRANCH first (and `setopt +o nomatch` for zsh); the block sets $DESIGN
|
||||
* $BRANCH and resolve $GSTACK_STATE_ROOT through the guarded gstack-paths
|
||||
* eval first (and `setopt +o nomatch` for zsh); the block sets $DESIGN
|
||||
* and prints "Design doc found: ..." or "No design doc found".
|
||||
*/
|
||||
|
||||
@@ -27,10 +28,10 @@ import type { TemplateContext } from './types';
|
||||
* re-check) can interpolate it into their own template strings instead of
|
||||
* embedding a drifting copy.
|
||||
*/
|
||||
export const DESIGN_DOC_DISCOVERY_BLOCK = `_LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
export const DESIGN_DOC_DISCOVERY_BLOCK = `_LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-$BRANCH-design-*.md 2>/dev/null | head -1)
|
||||
[ -z "$_LOCALDOC" ] && _LOCALDOC=$(ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-design-*.md 2>/dev/null | head -1)
|
||||
# Repo-local docs win when at least as fresh (#703): office-hours dual-writes
|
||||
# docs/designs/ alongside ~/.gstack, and the committed copy is what teammates
|
||||
# docs/designs/ alongside the state root, and the committed copy is what teammates
|
||||
# see. A stale old repo doc never shadows a newer private session.
|
||||
_REPOTOP=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
|
||||
_REPODOC=""
|
||||
|
||||
@@ -1410,7 +1410,7 @@ fonts [top-3], colors [top-3], layouts [top-3], aesthetics [top-3]. Bias
|
||||
generation toward these unless the user explicitly requests a different direction.
|
||||
Also avoid their strong rejections: [top-3 rejected per dimension]."
|
||||
|
||||
**Legacy fallback:** Glob \`~/.gstack/projects/$SLUG/designs/**/approved.json\`; Read the five newest. Use explicit feedback only, never infer fonts/colors from variant letters. No usable files: continue without a taste profile.
|
||||
**Legacy fallback:** Glob \`$GSTACK_STATE_ROOT/projects/$SLUG/designs/**/approved.json\` (resolve the root with gstack-paths); Read the five newest. Use explicit feedback only, never infer fonts/colors from variant letters. No usable files: continue without a taste profile.
|
||||
|
||||
**Conflict handling:** If the current user request contradicts a strong persistent
|
||||
signal (e.g., "make it playful" when taste profile strongly prefers minimal), flag
|
||||
|
||||
@@ -69,7 +69,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
\`~/.gstack/analytics/\`, matching preamble analytics writes.
|
||||
\`$GSTACK_STATE_ROOT/analytics/\`, matching preamble analytics writes.
|
||||
|
||||
\`\`\`bash
|
||||
${ctx.paths.binDir}/gstack-skill-end --skill "${ctx.skillName}" --outcome OUTCOME \\
|
||||
|
||||
@@ -258,6 +258,7 @@ Read the resulting doc if found; otherwise continue the standard review.
|
||||
Do not rerun the preamble or re-offer the prerequisite.` : `After /${first} completes, re-run the design doc check:
|
||||
\`\`\`bash
|
||||
setopt +o nomatch 2>/dev/null || true # zsh compat
|
||||
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"; : "\${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
||||
SLUG=$(~/.claude/skills/gstack/browse/bin/remote-slug 2>/dev/null || basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' || echo 'no-branch')
|
||||
${DESIGN_DOC_DISCOVERY_BLOCK}
|
||||
|
||||
@@ -133,7 +133,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "setup-browser-cookies" --outcome OUTCOME \
|
||||
|
||||
@@ -359,7 +359,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "setup-deploy" --outcome OUTCOME \
|
||||
|
||||
@@ -358,7 +358,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "setup-gbrain" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -389,7 +389,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "ship" --outcome OUTCOME \
|
||||
|
||||
@@ -59,7 +59,7 @@ Build this question's options from a LIVE check of installed skills at ask time
|
||||
## Archive and upload
|
||||
|
||||
1. Archive and export the signed Release build with `gym` (it drives xcodebuild and the signing minted in preflight). Projects with custom archive requirements may drop to `xcodebuild archive` directly; the output either way is an App Store-signed `.ipa`.
|
||||
2. The upload is an external effect: run `pilot` (TestFlight) or `deliver` (App Store) under the durable-effect contract: before executing, append the key `appstore.upload.<bundle-id>.<build>` to `~/.gstack/projects/$SLUG/apple-effects.log`; if the key is already present from a prior run (crash, retry), treat the upload as possibly-done and do NOT re-run it. Never re-upload on ambiguity; inspect App Store Connect for the build first.
|
||||
2. The upload is an external effect: run `pilot` (TestFlight) or `deliver` (App Store) under the durable-effect contract: before executing, append the key `appstore.upload.<bundle-id>.<build>` to `$GSTACK_STATE_ROOT/projects/$SLUG/apple-effects.log` (resolve the state root and slug in the same command that reads or appends it); if the key is already present from a prior run (crash, retry), treat the upload as possibly-done and do NOT re-run it. Never re-upload on ambiguity; inspect App Store Connect for the build first.
|
||||
3. The cached session, the minted key, and every credential file are env- or file-level secrets: never argv, never echoed, never committed.
|
||||
4. NEVER demand an app-specific password — the session MINTS the upload key instead.
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ Build this question's options from a LIVE check of installed skills at ask time
|
||||
## Archive and upload
|
||||
|
||||
1. Archive and export the signed Release build with `gym` (it drives xcodebuild and the signing minted in preflight). Projects with custom archive requirements may drop to `xcodebuild archive` directly; the output either way is an App Store-signed `.ipa`.
|
||||
2. The upload is an external effect: run `pilot` (TestFlight) or `deliver` (App Store) under the durable-effect contract: before executing, append the key `appstore.upload.<bundle-id>.<build>` to `~/.gstack/projects/$SLUG/apple-effects.log`; if the key is already present from a prior run (crash, retry), treat the upload as possibly-done and do NOT re-run it. Never re-upload on ambiguity; inspect App Store Connect for the build first.
|
||||
2. The upload is an external effect: run `pilot` (TestFlight) or `deliver` (App Store) under the durable-effect contract: before executing, append the key `appstore.upload.<bundle-id>.<build>` to `$GSTACK_STATE_ROOT/projects/$SLUG/apple-effects.log` (resolve the state root and slug in the same command that reads or appends it); if the key is already present from a prior run (crash, retry), treat the upload as possibly-done and do NOT re-run it. Never re-upload on ambiguity; inspect App Store Connect for the build first.
|
||||
3. The cached session, the minted key, and every credential file are env- or file-level secrets: never argv, never echoed, never committed.
|
||||
4. NEVER demand an app-specific password — the session MINTS the upload key instead.
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ Running bare test migrations without INSTANCE hits an orphan DB and corrupts str
|
||||
Run independent test suites in parallel, each wrapped in the evidence ledger. The
|
||||
wrapper is transparent (streams output live, exit code passes through) and
|
||||
records `{command, exit, working-tree fingerprint, log path}` to
|
||||
`~/.gstack/projects/<slug>/<branch>-evidence.jsonl` — Step 16 cites this
|
||||
`$GSTACK_STATE_ROOT/projects/<slug>/<branch>-evidence.jsonl` — Step 16 cites this
|
||||
record instead of re-running when the content hasn't changed:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -24,7 +24,7 @@ Running bare test migrations without INSTANCE hits an orphan DB and corrupts str
|
||||
Run independent test suites in parallel, each wrapped in the evidence ledger. The
|
||||
wrapper is transparent (streams output live, exit code passes through) and
|
||||
records `{command, exit, working-tree fingerprint, log path}` to
|
||||
`~/.gstack/projects/<slug>/<branch>-evidence.jsonl` — Step 16 cites this
|
||||
`$GSTACK_STATE_ROOT/projects/<slug>/<branch>-evidence.jsonl` — Step 16 cites this
|
||||
record instead of re-running when the content hasn't changed:
|
||||
|
||||
```bash
|
||||
|
||||
+1
-1
@@ -357,7 +357,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "skillify" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -387,7 +387,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "spec" --outcome OUTCOME \
|
||||
|
||||
@@ -359,7 +359,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "sync-gbrain" --outcome OUTCOME \
|
||||
|
||||
+1
-1
@@ -354,7 +354,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "test-audit" --outcome OUTCOME \
|
||||
|
||||
@@ -302,7 +302,7 @@ describe('CEO finding fixture establishes scope before launch', () => {
|
||||
const design = '# Settings export design\n\n## Problem\nOperators need saved settings in a spreadsheet for offline comparison.\n\n## Approach\nReuse the settings API and escape commas, quotes, and newlines in a CSV formatter.\n';
|
||||
seedCeoFindingProject(cwd, plan, design);
|
||||
const output = execFileSync('bash', ['-c', `SLUG=fixture; BRANCH=main; ${DESIGN_DOC_DISCOVERY_BLOCK}`], {
|
||||
cwd, env: { PATH: process.env.PATH!, HOME: home }, encoding: 'utf8', timeout: 10_000,
|
||||
cwd, env: { PATH: process.env.PATH!, HOME: home, GSTACK_STATE_ROOT: path.join(root, 'state') }, encoding: 'utf8', timeout: 10_000,
|
||||
});
|
||||
expect(output).toBe(`Design doc found: ${path.join(cwd, 'DESIGN.md')}\n`);
|
||||
expect(execFileSync('git', ['show', 'HEAD:DESIGN.md'], { cwd, encoding: 'utf8', timeout: 30_000 })).toBe(design);
|
||||
|
||||
@@ -193,7 +193,10 @@ test('taste context has defined count and bounded legacy and malformed-profile f
|
||||
expect(text).not.toContain('head -200');
|
||||
expect(text).toContain('Count retained sessions (at most 50, not lifetime)');
|
||||
expect(text).toContain('malformed/unreadable uses the legacy fallback');
|
||||
expect(text).toContain('Glob `~/.gstack/projects/$SLUG/designs/**/approved.json`');
|
||||
const legacy = text.slice(text.indexOf('**Legacy fallback:**'), text.indexOf('**Conflict handling:**'));
|
||||
expect(legacy).toContain('$GSTACK_STATE_ROOT/projects/$SLUG/designs/');
|
||||
expect(legacy).toContain('approved.json');
|
||||
expect(legacy).not.toContain('~/.gstack');
|
||||
expect(text).toContain('Read the five newest');
|
||||
expect(text).toContain('No usable files: continue without a taste profile');
|
||||
expect(text).toContain('never infer fonts/colors from variant letters');
|
||||
|
||||
Vendored
+50
-50
@@ -1,67 +1,67 @@
|
||||
{
|
||||
"_comment": "Context-budget ratchet ceilings (~tokens). Regenerate: bun test/helpers/capture-context-budget.ts. Headroom: alwaysOnTotal x1.05, eagerPerInvocation x1.1. Graded by test/context-budget-ratchet.test.ts via lib/context-bill.ts checkBudget.",
|
||||
"alwaysOnTotal": 6814,
|
||||
"alwaysOnTotal": 6840,
|
||||
"eagerPerInvocation": {
|
||||
"autoplan": 17100,
|
||||
"benchmark": 7671,
|
||||
"benchmark-models": 3819,
|
||||
"browse": 8137,
|
||||
"autoplan": 17212,
|
||||
"benchmark": 7673,
|
||||
"benchmark-models": 3821,
|
||||
"browse": 8139,
|
||||
"browser-skills/hackernews-frontpage": 371,
|
||||
"canary": 13729,
|
||||
"canary": 13742,
|
||||
"careful": 962,
|
||||
"codex": 15225,
|
||||
"context-restore": 10489,
|
||||
"context-save": 10282,
|
||||
"codex": 15227,
|
||||
"context-restore": 10492,
|
||||
"context-save": 10284,
|
||||
"cso": 4700,
|
||||
"design-consultation": 15614,
|
||||
"design-html": 14322,
|
||||
"design-review": 34519,
|
||||
"design-shotgun": 13862,
|
||||
"design-consultation": 15631,
|
||||
"design-html": 14324,
|
||||
"design-review": 34521,
|
||||
"design-shotgun": 13879,
|
||||
"deslop-shared-libs": 3419,
|
||||
"devex-review": 19735,
|
||||
"diagram": 4264,
|
||||
"document-generate": 12115,
|
||||
"document-release": 10479,
|
||||
"devex-review": 19738,
|
||||
"diagram": 4267,
|
||||
"document-generate": 12118,
|
||||
"document-release": 10481,
|
||||
"freeze": 1053,
|
||||
"gstack": 4145,
|
||||
"gstack": 4147,
|
||||
"gstack-upgrade": 4711,
|
||||
"guard": 939,
|
||||
"health": 11782,
|
||||
"investigate": 12434,
|
||||
"ios-clean": 8587,
|
||||
"ios-design-review": 8674,
|
||||
"ios-fix": 8476,
|
||||
"ios-qa": 11264,
|
||||
"ios-sync": 8602,
|
||||
"land-and-deploy": 19111,
|
||||
"landing-report": 9299,
|
||||
"learn": 8993,
|
||||
"make-pdf": 5230,
|
||||
"office-hours": 22614,
|
||||
"open-gstack-browser": 4838,
|
||||
"health": 11798,
|
||||
"investigate": 12441,
|
||||
"ios-clean": 8589,
|
||||
"ios-design-review": 8774,
|
||||
"ios-fix": 8478,
|
||||
"ios-qa": 11266,
|
||||
"ios-sync": 8604,
|
||||
"land-and-deploy": 19114,
|
||||
"landing-report": 9301,
|
||||
"learn": 8996,
|
||||
"make-pdf": 5233,
|
||||
"office-hours": 22624,
|
||||
"open-gstack-browser": 4840,
|
||||
"openclaw/skills/gstack-openclaw-ceo-review": 2764,
|
||||
"openclaw/skills/gstack-openclaw-investigate": 1429,
|
||||
"openclaw/skills/gstack-openclaw-office-hours": 4433,
|
||||
"openclaw/skills/gstack-openclaw-retro": 2542,
|
||||
"pair-agent": 11397,
|
||||
"plan-ceo-review": 20954,
|
||||
"plan-design-review": 20517,
|
||||
"plan-devex-review": 17816,
|
||||
"plan-eng-review": 13474,
|
||||
"plan-tune": 14730,
|
||||
"qa": 13568,
|
||||
"qa-only": 11740,
|
||||
"retro": 19015,
|
||||
"review": 19560,
|
||||
"scrape": 6874,
|
||||
"setup-browser-cookies": 3494,
|
||||
"setup-deploy": 11369,
|
||||
"setup-gbrain": 15619,
|
||||
"ship": 20627,
|
||||
"skillify": 11957,
|
||||
"spec": 14807,
|
||||
"sync-gbrain": 14738,
|
||||
"test-audit": 10532,
|
||||
"pair-agent": 11399,
|
||||
"plan-ceo-review": 21047,
|
||||
"plan-design-review": 20519,
|
||||
"plan-devex-review": 17906,
|
||||
"plan-eng-review": 13521,
|
||||
"plan-tune": 14734,
|
||||
"qa": 13570,
|
||||
"qa-only": 11742,
|
||||
"retro": 19038,
|
||||
"review": 19562,
|
||||
"scrape": 6876,
|
||||
"setup-browser-cookies": 3497,
|
||||
"setup-deploy": 11372,
|
||||
"setup-gbrain": 15621,
|
||||
"ship": 20629,
|
||||
"skillify": 11960,
|
||||
"spec": 14809,
|
||||
"sync-gbrain": 14740,
|
||||
"test-audit": 10535,
|
||||
"unfreeze": 448
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -389,7 +389,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
~/.claude/skills/gstack/bin/gstack-skill-end --skill "ship" --outcome OUTCOME \
|
||||
|
||||
+2
-2
@@ -396,7 +396,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
$GSTACK_BIN/gstack-skill-end --skill "ship" --outcome OUTCOME \
|
||||
@@ -939,7 +939,7 @@ Running bare test migrations without INSTANCE hits an orphan DB and corrupts str
|
||||
Run independent test suites in parallel, each wrapped in the evidence ledger. The
|
||||
wrapper is transparent (streams output live, exit code passes through) and
|
||||
records `{command, exit, working-tree fingerprint, log path}` to
|
||||
`~/.gstack/projects/<slug>/<branch>-evidence.jsonl` — Step 16 cites this
|
||||
`$GSTACK_STATE_ROOT/projects/<slug>/<branch>-evidence.jsonl` — Step 16 cites this
|
||||
record instead of re-running when the content hasn't changed:
|
||||
|
||||
```bash
|
||||
|
||||
+2
-2
@@ -377,7 +377,7 @@ preamble's skill-start output echoed. It also drains the artifacts-sync queue
|
||||
(the former skill-end sync step — do not run gstack-brain-sync separately).
|
||||
|
||||
**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
|
||||
`~/.gstack/analytics/`, matching preamble analytics writes.
|
||||
`$GSTACK_STATE_ROOT/analytics/`, matching preamble analytics writes.
|
||||
|
||||
```bash
|
||||
$GSTACK_BIN/gstack-skill-end --skill "ship" --outcome OUTCOME \
|
||||
@@ -920,7 +920,7 @@ Running bare test migrations without INSTANCE hits an orphan DB and corrupts str
|
||||
Run independent test suites in parallel, each wrapped in the evidence ledger. The
|
||||
wrapper is transparent (streams output live, exit code passes through) and
|
||||
records `{command, exit, working-tree fingerprint, log path}` to
|
||||
`~/.gstack/projects/<slug>/<branch>-evidence.jsonl` — Step 16 cites this
|
||||
`$GSTACK_STATE_ROOT/projects/<slug>/<branch>-evidence.jsonl` — Step 16 cites this
|
||||
record instead of re-running when the content hasn't changed:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -441,7 +441,7 @@ describe('gen-skill-docs', () => {
|
||||
expect(SKILL_END_SCRIPT).toContain('analytics/skill-usage.jsonl');
|
||||
// The render still tells the model where telemetry lands.
|
||||
const content = fs.readFileSync(path.join(ROOT, 'SKILL.md'), 'utf-8');
|
||||
expect(content).toContain('~/.gstack/analytics');
|
||||
expect(content).toContain('$GSTACK_STATE_ROOT/analytics/');
|
||||
});
|
||||
|
||||
test('plan-review generated preambles stay under the Option A budget', () => {
|
||||
@@ -1905,13 +1905,15 @@ describe('BENEFITS_FROM resolver', () => {
|
||||
fs.chmodSync(helper, 0o755);
|
||||
fs.copyFileSync(path.join(ROOT, 'bin/gstack-state-root.sh'), path.join(path.dirname(helper), 'gstack-state-root.sh'));
|
||||
fs.copyFileSync(path.join(ROOT, 'bin/gstack-remote-identity.sh'), path.join(path.dirname(helper), 'gstack-remote-identity.sh'));
|
||||
const expected = path.join(home, '.gstack/projects/canonical-override/session-unknown-design-current.md');
|
||||
const wrong = path.join(home, '.gstack/projects/project/session-unknown-design-wrong.md');
|
||||
fs.copyFileSync(path.join(ROOT, 'bin/gstack-paths'), path.join(path.dirname(helper), 'gstack-paths'));
|
||||
fs.chmodSync(path.join(path.dirname(helper), 'gstack-paths'), 0o755);
|
||||
const expected = path.join(dir, 'state/projects/canonical-override/session-unknown-design-current.md');
|
||||
const wrong = path.join(dir, 'state/projects/project/session-unknown-design-wrong.md');
|
||||
for (const file of [expected, wrong]) {
|
||||
fs.mkdirSync(path.dirname(file), {recursive: true});
|
||||
fs.writeFileSync(file, '# Design fixture\n');
|
||||
}
|
||||
const env = {...process.env, HOME: home, GSTACK_HOME: path.join(home, '.gstack'),
|
||||
const env = {...process.env, HOME: home, GSTACK_HOME: path.join(dir, 'state'), GSTACK_STATE_ROOT: path.join(dir, 'state'),
|
||||
GSTACK_PROJECT_SLUG: 'canonical-override', GIT_CEILING_DIRECTORIES: dir};
|
||||
for (const command of [initial, recheck]) {
|
||||
expect(command).toContain('if _REVIEW_SLUG=$(~/.claude/skills/gstack/bin/gstack-slug); then');
|
||||
|
||||
@@ -606,6 +606,51 @@ gbrain:
|
||||
}
|
||||
});
|
||||
|
||||
describe("gstack-brain-context-load — shipped state-root manifest files read the configured root", () => {
|
||||
const cases = [
|
||||
{ skill: "investigate", id: "project-learnings", file: ["projects", "test-repo", "learnings.jsonl"] },
|
||||
{ skill: "investigate", id: "recent-eureka", file: ["analytics", "eureka.jsonl"] },
|
||||
{ skill: "office-hours", id: "design-doc-history", file: ["projects", "test-repo", "alice-main-design-20260914.md"] },
|
||||
];
|
||||
for (const c of cases) it(`${c.skill}:${c.id} reads only the configured root`, () => {
|
||||
const dir = mkdtempSync(join(tmpdir(), "gstack-state-manifest-"));
|
||||
const home = join(dir, "home");
|
||||
const configured = join(dir, "configured");
|
||||
try {
|
||||
const target = join(configured, ...c.file);
|
||||
mkdirSync(join(target, ".."), { recursive: true });
|
||||
writeFileSync(target, "{}\n");
|
||||
mkdirSync(home, { recursive: true });
|
||||
const query = parseSkillManifest(join(import.meta.dir, "..", c.skill, "SKILL.md.tmpl"))!
|
||||
.context_queries.find(item => item.id === c.id)!;
|
||||
expect(query.glob!.startsWith("{gstack_state_root}/")).toBe(true);
|
||||
const skillFile = join(dir, "SKILL.md");
|
||||
writeFileSync(skillFile, `---
|
||||
name: state-manifest-fixture
|
||||
gbrain:
|
||||
schema: 1
|
||||
context_queries:
|
||||
- id: ${query.id}
|
||||
kind: filesystem
|
||||
glob: "${query.glob}"
|
||||
render_as: "${query.render_as}"
|
||||
---
|
||||
`);
|
||||
const env = { HOME: home, USERPROFILE: home, GSTACK_HOME: configured, CLAUDE_PLUGIN_DATA: "", CLAUDE_PLUGIN_ROOT: "" };
|
||||
const r = runScript(["--skill-file", skillFile, "--repo", "test-repo", "--explain"], env);
|
||||
expect(r.exitCode).toBe(0);
|
||||
expect(r.stderr).toContain(`OK ${c.id}`);
|
||||
expect(r.stdout).toContain(c.file[c.file.length - 1]!);
|
||||
rmSync(target);
|
||||
mkdirSync(join(home, ".gstack", ...c.file.slice(0, -1)), { recursive: true });
|
||||
writeFileSync(join(home, ".gstack", ...c.file), "{}\n");
|
||||
const legacyOnly = runScript(["--skill-file", skillFile, "--repo", "test-repo", "--explain"], env);
|
||||
expect(legacyOnly.exitCode).toBe(0);
|
||||
expect(legacyOnly.stderr).toContain(`SKIP ${c.id}`);
|
||||
} finally { rmSync(dir, { recursive: true, force: true }); }
|
||||
});
|
||||
});
|
||||
|
||||
describe("gstack-brain-context-load — real gbrain CLI contract (#2883)", () => {
|
||||
const ROWS = [
|
||||
"plans/brand-plan\\tceo-plan\\t2026-10-01\\tBrand plan",
|
||||
|
||||
@@ -160,54 +160,29 @@ describe('/ship step references resolve to the step they mean', () => {
|
||||
|
||||
// Every literal default-root state path in templates and resolvers. Writers
|
||||
// resolve $GSTACK_STATE_ROOT (docs/state-root.md); a literal ~/.gstack path
|
||||
// only matches them when the state root is the default. Rows are either
|
||||
// user-facing descriptions, manifest/legacy forms read literally, or
|
||||
// conversions still pending (tracked in TODOS.md). New hits fail.
|
||||
// only matches them when the state root is the default. Rows are user-facing
|
||||
// descriptions, source comments, or readers that must match a writer outside
|
||||
// the state root. Manifest globs use the `{gstack_state_root}/` prefix. New
|
||||
// hits fail.
|
||||
const STATE_ROOT_LITERAL = /~\/\.gstack\/(?:projects|analytics)\//g;
|
||||
const RATCHET_ALLOWLIST = JSON.parse(read('test/state-root-ratchet.allowlist.json')) as Array<{ path: string; match: string; reason: string }>;
|
||||
const readinessEvalReason = RATCHET_ALLOWLIST.find(entry => entry.path === 'land-and-deploy/sections/readiness-gate.md.tmpl')!.reason;
|
||||
const MANIFEST_GLOB = 'gbrain context_queries manifest glob: bin/gstack-brain-context-load.ts reads the legacy `~` form literally (default state root only); `{gstack_state_root}/` is the state-root form. Conversion pending (TODOS.md: state-root literals in templates)';
|
||||
const DESCRIPTION = 'user-facing description of where the data lives; no command reads or writes this literal';
|
||||
const PENDING = 'agent reads or writes this literal default-root path; it diverges from $GSTACK_STATE_ROOT writers under a non-default state root. Conversion pending (TODOS.md: state-root literals in templates)';
|
||||
const SOURCE_COMMENT = 'source comment, not rendered into any skill';
|
||||
|
||||
const STATE_ROOT_ALLOWLIST: Array<{ file: string; match: string; reason: string }> = [
|
||||
{ file: 'autoplan/SKILL.md.tmpl', match: 'ls -t ~/.gstack/projects/$SLUG/*-design-*.md', reason: PENDING },
|
||||
{ file: 'autoplan/SKILL.md.tmpl', match: 'test plan on disk at ~/.gstack/projects/$SLUG/', reason: DESCRIPTION },
|
||||
{ file: 'canary/SKILL.md.tmpl', match: 'Append it to `~/.gstack/projects/$SLUG/canary-history.jsonl`', reason: PENDING },
|
||||
{ file: 'careful/SKILL.md.tmpl', match: '`~/.gstack/projects/<slug>/careful-patterns.txt` (per-project)', reason: DESCRIPTION },
|
||||
{ file: 'design-consultation/SKILL.md.tmpl', match: 'glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"', reason: MANIFEST_GLOB },
|
||||
{ file: 'design-shotgun/SKILL.md.tmpl', match: 'glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"', reason: MANIFEST_GLOB },
|
||||
{ file: 'design-shotgun/SKILL.md.tmpl', match: 'v1 schema at `~/.gstack/projects/$SLUG/taste-profile.json`', reason: DESCRIPTION },
|
||||
{ file: 'health/SKILL.md.tmpl', match: '`~/.gstack/projects/$SLUG/health-history.jsonl`. Zero-check', reason: PENDING },
|
||||
{ file: 'health/SKILL.md.tmpl', match: 'Read the last 10 entries from `~/.gstack/projects/$SLUG/health-history.jsonl`', reason: PENDING },
|
||||
{ file: 'investigate/SKILL.md.tmpl', match: 'glob: "~/.gstack/projects/{repo_slug}/learnings.jsonl"', reason: MANIFEST_GLOB },
|
||||
{ file: 'investigate/SKILL.md.tmpl', match: 'glob: "~/.gstack/analytics/eureka.jsonl"', reason: MANIFEST_GLOB },
|
||||
{ file: 'ios-design-review/SKILL.md.tmpl', match: '`~/.gstack/projects/<slug>/ios-design-review-<date>.md`', reason: PENDING },
|
||||
{ file: 'land-and-deploy/sections/readiness-gate.md.tmpl', match: 'eval store (`~/.gstack/projects/<slug>/evals/`', reason: readinessEvalReason },
|
||||
{ file: 'land-and-deploy/sections/readiness-gate.md.tmpl', match: 'EVAL_DIR=~/.gstack/projects/$SLUG/evals', reason: readinessEvalReason },
|
||||
{ file: 'office-hours/SKILL.md.tmpl', match: 'glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"', reason: MANIFEST_GLOB },
|
||||
{ file: 'office-hours/SKILL.md.tmpl', match: 'glob: "~/.gstack/analytics/eureka.jsonl"', reason: MANIFEST_GLOB },
|
||||
{ file: 'office-hours/SKILL.md.tmpl', match: "see each other's design docs in `~/.gstack/projects/`", reason: DESCRIPTION },
|
||||
{ file: 'office-hours/sections/design-and-handoff.md.tmpl', match: 'The design doc at `~/.gstack/projects/` is automatically discoverable', reason: DESCRIPTION },
|
||||
{ file: 'plan-ceo-review/SKILL.md.tmpl', match: 'glob: "~/.gstack/projects/{repo_slug}/*-design-*.md"', reason: MANIFEST_GLOB },
|
||||
{ file: 'plan-ceo-review/sections/review-sections.md.tmpl', match: 'Keep in `~/.gstack/projects/` only (local, personal reference)', reason: DESCRIPTION },
|
||||
{ file: 'plan-tune/SKILL.md.tmpl', match: '`~/.gstack/projects/<slug>/distillation-proposals.json` exists', reason: PENDING },
|
||||
{ file: 'plan-tune/SKILL.md.tmpl', match: 'Logs stay local (`~/.gstack/projects/<slug>/question-log.jsonl`)', reason: DESCRIPTION },
|
||||
{ file: 'plan-tune/SKILL.md.tmpl', match: '`~/.gstack/projects/<slug>/question-log.jsonl` — nothing leaves your', reason: DESCRIPTION },
|
||||
{ file: 'retro/SKILL.md.tmpl', match: 'glob: "~/.gstack/projects/{repo_slug}/timeline.jsonl"', reason: MANIFEST_GLOB },
|
||||
{ file: 'retro/SKILL.md.tmpl', match: 'glob: "~/.gstack/projects/{repo_slug}/learnings.jsonl"', reason: MANIFEST_GLOB },
|
||||
{ file: 'retro/SKILL.md.tmpl', match: 'Read `~/.gstack/analytics/skill-usage.jsonl`', reason: PENDING },
|
||||
{ file: 'retro/SKILL.md.tmpl', match: 'Read `~/.gstack/analytics/eureka.jsonl`', reason: PENDING },
|
||||
{ file: 'ship/sections/apple-release.md.tmpl', match: 'to `~/.gstack/projects/$SLUG/apple-effects.log`', reason: PENDING },
|
||||
{ file: 'ship/sections/tests.md.tmpl', match: '`~/.gstack/projects/<slug>/<branch>-evidence.jsonl` — Step 16 cites this', reason: PENDING },
|
||||
{ file: 'scripts/resolvers/design-doc-discovery.ts', match: '* under ~/.gstack/projects/<slug>/, falling back', reason: SOURCE_COMMENT },
|
||||
{ file: 'scripts/resolvers/design-doc-discovery.ts', match: '_LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-$BRANCH-design-*.md', reason: PENDING },
|
||||
{ file: 'scripts/resolvers/design-doc-discovery.ts', match: '_LOCALDOC=$(ls -t ~/.gstack/projects/$SLUG/*-design-*.md', reason: PENDING },
|
||||
{ file: 'scripts/resolvers/design.ts', match: 'Glob \\`~/.gstack/projects/$SLUG/designs/**/approved.json\\`', reason: PENDING },
|
||||
{ file: 'scripts/resolvers/learnings.ts', match: '* Learnings are stored per-project at ~/.gstack/projects/{slug}/learnings.jsonl', reason: SOURCE_COMMENT },
|
||||
{ file: 'scripts/resolvers/preamble.ts', match: 'local JSONL append to ~/.gstack/analytics/ (inline, inspectable)', reason: SOURCE_COMMENT },
|
||||
{ file: 'scripts/resolvers/preamble/generate-completion-status.ts', match: '\\`~/.gstack/analytics/\\`, matching preamble analytics writes', reason: PENDING },
|
||||
];
|
||||
|
||||
describe('templates and resolvers name gstack state only through allowlisted literals', () => {
|
||||
|
||||
Reference in new issue
Block a user