fix(state-root): history, report and ledger paths name $GSTACK_STATE_ROOT

Agent-facing read/write paths that named the literal ~/.gstack default now
name the state root their writers use:
- canary-history.jsonl and health-history.jsonl (the blocks above already
  resolve the root and print PROJECT_DIR)
- ios-design-review report: adds {{SLUG_SETUP}} so the report path is the
  PROJECT_DIR it prints
- plan-tune dream-cycle gate's distillation-proposals.json
- retro's skill-usage and eureka reads: read the path gstack-retro-metrics
  prints (it already checks $_gstack_sr_root/analytics)
- ship's apple-effects.log durable-effect ledger and the gstack-evidence
  ledger description (bin/gstack-evidence writes under resolveStateRoot())

Allowlist: drops the nine matching PENDING rows from STATE_ROOT_ALLOWLIST.
This commit is contained in:
garrytan committed 2026-10-03 02:17:50 +00:00
1 parent 3c3a013a3b
commit 1fdda72ab9
8 files changed
+17 -20

No files matched your search

+1 -1
View File
@@ -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
+2 -2
View File
@@ -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
+9 -3
View File
@@ -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
View File
@@ -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.
+2 -2
View File
@@ -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
View File
@@ -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.
+1 -1
View File
@@ -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
-9
View File
@@ -173,16 +173,12 @@ 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: '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 },
@@ -191,15 +187,10 @@ const STATE_ROOT_ALLOWLIST: Array<{ file: string; match: string; reason: string
{ 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.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 },