From 10d8c1c0277f26ec55c73bba8c4cac74c38aa556 Mon Sep 17 00:00:00 2001 From: garrytan Date: Sat, 3 Oct 2026 02:18:36 +0000 Subject: [PATCH] fix(state-root): taste-profile legacy fallback globs $GSTACK_STATE_ROOT designs The legacy approved.json fallback in {{TASTE_PROFILE}} (design-consultation, design-shotgun) named the literal ~/.gstack/projects path while the approval writers use $GSTACK_STATE_ROOT/projects/$SLUG/designs. Allowlist: drops the design.ts PENDING row. Pin (W7a): design-consultation-contract's exact glob string becomes a meaning-level check (legacy fallback names the state-root designs dir and approved.json, and no ~/.gstack literal). --- scripts/resolvers/design.ts | 2 +- test/design-consultation-contract.test.ts | 5 ++++- test/instruction-facts.test.ts | 1 - 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/resolvers/design.ts b/scripts/resolvers/design.ts index 21420784e..8c234a3ea 100644 --- a/scripts/resolvers/design.ts +++ b/scripts/resolvers/design.ts @@ -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 diff --git a/test/design-consultation-contract.test.ts b/test/design-consultation-contract.test.ts index 56fa19f38..fe70b59e0 100644 --- a/test/design-consultation-contract.test.ts +++ b/test/design-consultation-contract.test.ts @@ -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'); diff --git a/test/instruction-facts.test.ts b/test/instruction-facts.test.ts index 2ca9f94de..b468c9e3e 100644 --- a/test/instruction-facts.test.ts +++ b/test/instruction-facts.test.ts @@ -191,7 +191,6 @@ const STATE_ROOT_ALLOWLIST: Array<{ file: string; match: string; reason: string { file: 'plan-tune/SKILL.md.tmpl', match: '`~/.gstack/projects//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: '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 },