From 022f5d3f27a135aac400efcda5472185c68ed302 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 11:19:02 -0700 Subject: [PATCH 1/4] feat: add founder_resources config key for persistent resources opt-out Co-Authored-By: Claude Fable 5 --- bin/gstack-config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/gstack-config b/bin/gstack-config index 6d2a688d0c..b9c9044063 100755 --- a/bin/gstack-config +++ b/bin/gstack-config @@ -51,6 +51,9 @@ const defaults = Object.freeze({ plan_tune_hooks: "prompt", redact_repo_visibility: "", redact_prepush_hook: false, + // Founder resources (PG essays, YC videos) in /office-hours. "Never show + // me these again" sets this to false. + founder_resources: true, salience_allowlist: "", // Remote pair-agent (ngrok tunnel) is opt-in: OFF exposes nothing to the // internet. Set "on" to allow the tunnel to start. @@ -135,6 +138,7 @@ function validateClosedValue(key, value) { [/^artifacts_sync_mode$/, ["off", "artifacts-only", "full"], "off"], [/^redact_repo_visibility$/, ["public", "private", "unknown"], "unknown"], [/^redact_prepush_hook$/, ["true", "false"], "false"], + [/^founder_resources$/, ["true", "false"], "true"], [/^plan_tune_hooks$/, ["prompt", "yes", "no"], "prompt"], [/^pair_agent$/, ["off", "on"], "off"], ]; From cc62d0677ac0a36b5ecb7457eab39a7c65c19885 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 11:21:12 -0700 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20overlay=20#538=20=E2=80=94=20founder?= =?UTF-8?q?=20resources=20honor=20a=20never-show-again=20opt-out?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- scripts/gstack2/bug-fix-overlays.ts | 28 ++++++++++++++++++++++++++ scripts/gstack2/generate-skill-tree.ts | 2 +- scripts/gstack2/run-parity.ts | 9 +++++---- test/gstack2-skills.test.ts | 2 +- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/scripts/gstack2/bug-fix-overlays.ts b/scripts/gstack2/bug-fix-overlays.ts index 291658decf..20aa977848 100644 --- a/scripts/gstack2/bug-fix-overlays.ts +++ b/scripts/gstack2/bug-fix-overlays.ts @@ -427,6 +427,25 @@ A question is only answerable if the user can see what it refers to. Before any }, }, }, + { + pr: 538, + url: 'https://github.com/garrytan/gstack/issues/538', + title: 'Founder resources honor a persistent never-show-again opt-out', + targets: ['office-hours'], + anchor: 'GSTACK2_FIX_538_FOUNDER_RESOURCES_OPTOUT', + body: `### Founder-resources opt-out + +Before sharing any founder resources (Paul Graham essays, Garry Tan or YC videos, or similar motivational recommendations), check the persistent opt-out with \`"$GSTACK_BIN/gstack-config" get founder_resources\`. If it prints \`false\`, skip the entire resources phase silently — no resources, no mention that they were skipped — and continue with the rest of the handoff, which is unaffected. When resources are shown, the offer-to-open question must include a **"Never show me these again"** option alongside the open/skip options. Choosing it runs \`"$GSTACK_BIN/gstack-config" set founder_resources false\`, confirms in one line that resources will not be recommended again and that \`gstack-config set founder_resources true\` re-enables them, then continues. The opt-out is a durable user decision: never re-pitch the resources, never ask the user to reconsider, and never let a session's context override the stored \`false\`.`, + regression: { + input: { founder_resources_config: 'false', phase: 'founder-resources' }, + expected: { + resources_shown: false, + skip_is_silent: true, + never_again_option_when_shown: true, + opt_out_persisted_via: 'gstack-config set founder_resources false', + }, + }, + }, ]; export function overlaysForSource(source: string): BugFixOverlay[] { @@ -663,6 +682,15 @@ export function evaluateBugFixRegression(pr: number, rawInput: unknown): Record< step_unit: ['hours', 'days', 'weeks', 'stage-appropriate', 'stage-appropriate'][rank], }; } + case 538: { + const optedOut = String(input.founder_resources_config ?? '') === 'false'; + return { + resources_shown: !optedOut, + skip_is_silent: optedOut, + never_again_option_when_shown: true, + opt_out_persisted_via: 'gstack-config set founder_resources false', + }; + } default: throw new Error(`No executable GStack 2 regression evaluator for PR #${pr}`); } diff --git a/scripts/gstack2/generate-skill-tree.ts b/scripts/gstack2/generate-skill-tree.ts index 95120458e7..41a4a629d7 100644 --- a/scripts/gstack2/generate-skill-tree.ts +++ b/scripts/gstack2/generate-skill-tree.ts @@ -82,7 +82,7 @@ function assertInventory(): void { } if (legacySections().length !== 16) throw new Error(`Expected 16 section templates, found ${legacySections().length}`); if (SCENARIOS.length !== 25) throw new Error(`Expected 25 parity scenarios, found ${SCENARIOS.length}`); - if (BUG_FIX_OVERLAYS.length !== 29) throw new Error(`Expected 29 upstream judgment overlays, found ${BUG_FIX_OVERLAYS.length}`); + if (BUG_FIX_OVERLAYS.length !== 30) throw new Error(`Expected 30 upstream judgment overlays, found ${BUG_FIX_OVERLAYS.length}`); } function toc(body: string): string { diff --git a/scripts/gstack2/run-parity.ts b/scripts/gstack2/run-parity.ts index fe289dcfcf..1d59ba4df0 100644 --- a/scripts/gstack2/run-parity.ts +++ b/scripts/gstack2/run-parity.ts @@ -24,8 +24,9 @@ const ALLOWED_DISPOSITIONS = new Set(['VERBATIM_PORT', 'MECHANICAL_PORT', 'JUDGM // targets) added 13 more. The design-doc concision overlay for issue #2000 // (27 -> 28, office-hours only) added 5 more. The self-contained-questions // overlay for issue #879 (28 -> 29, targets '*', all 55 modules) added 113 -// more (2 per module + 3 regression checks). -export const EXPECTED_PARITY_CHECKS = 5027; +// more (2 per module + 3 regression checks). The founder-resources opt-out +// overlay for issue #538 (29 -> 30, office-hours only) added 5 more. +export const EXPECTED_PARITY_CHECKS = 5032; function sha256(value: string | Uint8Array): string { return createHash('sha256').update(value).digest('hex'); @@ -260,8 +261,8 @@ export function runParity(): ParityResult { check(JSON.stringify(json(path.join(ROOT, 'evals', 'parity', 'scenarios', `${scenario.id}.json`))) === JSON.stringify(scenario), `${scenario.id} generated fixture drift`); } - check(BUG_FIX_OVERLAYS.length === 29, `Expected 29 regression definitions; got ${BUG_FIX_OVERLAYS.length}`); - check(files(path.join(ROOT, 'evals', 'parity', 'regressions'), '.json').length === 29, 'Generated regression fixture count is not 29'); + check(BUG_FIX_OVERLAYS.length === 30, `Expected 30 regression definitions; got ${BUG_FIX_OVERLAYS.length}`); + check(files(path.join(ROOT, 'evals', 'parity', 'regressions'), '.json').length === 30, 'Generated regression fixture count is not 30'); for (const overlay of BUG_FIX_OVERLAYS) { const fixture = json(path.join(ROOT, 'evals', 'parity', 'regressions', `pr-${overlay.pr}.json`)); check(JSON.stringify(fixture) === JSON.stringify(overlay), `PR #${overlay.pr} regression fixture drift`); diff --git a/test/gstack2-skills.test.ts b/test/gstack2-skills.test.ts index a7f198ac89..ee4768feb1 100644 --- a/test/gstack2-skills.test.ts +++ b/test/gstack2-skills.test.ts @@ -27,7 +27,7 @@ describe('GStack 2 skill parity', () => { const result = runParity(); expect(result.sources).toBe(55); expect(result.sections).toBe(16); - expect(result.regressions).toBe(29); + expect(result.regressions).toBe(30); }, 30_000); test('keeps image generation host-native, optional, and provider-free', () => { From 1f6f95ed189c85b5b436b03fb019ec94fe1af133 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 11:24:15 -0700 Subject: [PATCH 3/4] chore: regenerate gstack2 tree for overlay #538 Co-Authored-By: Claude Fable 5 --- docs/gstack-2/JUDGMENT-PARITY.md | 2 +- docs/gstack-2/JUDGMENT-PROVENANCE.json | 13 ++++++++++- docs/gstack-2/SKILL-MIGRATION.md | 2 +- evals/parity/contracts/office-hours.json | 3 ++- evals/parity/manifest.json | 13 ++++++++++- evals/parity/regressions/pr-538.json | 22 +++++++++++++++++++ evals/parity/runtime-helper-closure.json | 1 + .../deterministic/office-hours.json | 7 ++++++ skills/plan/references/legacy/office-hours.md | 10 +++++++++ 9 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 evals/parity/regressions/pr-538.json diff --git a/docs/gstack-2/JUDGMENT-PARITY.md b/docs/gstack-2/JUDGMENT-PARITY.md index 1bb2770297..a5c6fb6104 100644 --- a/docs/gstack-2/JUDGMENT-PARITY.md +++ b/docs/gstack-2/JUDGMENT-PARITY.md @@ -2,7 +2,7 @@ Parity is executable, not a prose claim. Run `bun run scripts/gstack2/run-parity.ts` or the dedicated Bun tests. -The pinned release inventory passes **5,027 checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 28 regression ports, and **78 assets**. +The pinned release inventory passes **5,032 checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 28 regression ports, and **78 assets**. The suite verifies: diff --git a/docs/gstack-2/JUDGMENT-PROVENANCE.json b/docs/gstack-2/JUDGMENT-PROVENANCE.json index fa2c95496e..856c4d2654 100644 --- a/docs/gstack-2/JUDGMENT-PROVENANCE.json +++ b/docs/gstack-2/JUDGMENT-PROVENANCE.json @@ -95,7 +95,8 @@ 886, 703, 2000, - 879 + 879, + 538 ], "original_source_file": "office-hours/SKILL.md.tmpl", "original_line_range": "1-526", @@ -6736,6 +6737,7 @@ "consumer_modules": [ "autoplan", "document-generate", + "office-hours", "plan-tune", "setup-gbrain", "ship", @@ -7533,6 +7535,15 @@ "*" ], "anchor": "GSTACK2_FIX_879_SELF_CONTAINED_QUESTIONS" + }, + { + "pr": 538, + "url": "https://github.com/garrytan/gstack/issues/538", + "title": "Founder resources honor a persistent never-show-again opt-out", + "targets": [ + "office-hours" + ], + "anchor": "GSTACK2_FIX_538_FOUNDER_RESOURCES_OPTOUT" } ] } diff --git a/docs/gstack-2/SKILL-MIGRATION.md b/docs/gstack-2/SKILL-MIGRATION.md index 617425fced..fddc2942cf 100644 --- a/docs/gstack-2/SKILL-MIGRATION.md +++ b/docs/gstack-2/SKILL-MIGRATION.md @@ -11,7 +11,7 @@ The fixed public modes are: Design = `Explore | Generate | Critique | Implement` | Legacy invocation | Replacement | Visibility | Mandatory | Judgment overlays | |---|---|---|---|---| | `/gstack` | `$plan --mode Discovery --module gstack` | internal (internal) | no | #679, #879 | -| `/office-hours` | `$plan --mode Discovery --module office-hours` | internal (primary) | yes | #679, #2030, #1049, #1116, #886, #703, #2000, #879 | +| `/office-hours` | `$plan --mode Discovery --module office-hours` | internal (primary) | yes | #679, #2030, #1049, #1116, #886, #703, #2000, #879, #538 | | `/plan-ceo-review` | `$plan --mode Product --module plan-ceo-review` | internal (primary) | yes | #679, #2030, #886, #703, #879 | | `/plan-eng-review` | `$plan --mode Engineering --module plan-eng-review` | internal (primary) | yes | #679, #1071, #2030, #592, #886, #703, #879 | | `/plan-devex-review` | `$plan --mode DX --module plan-devex-review` | internal (primary) | yes | #679, #2030, #886, #703, #879 | diff --git a/evals/parity/contracts/office-hours.json b/evals/parity/contracts/office-hours.json index 11579b3693..3f5983288d 100644 --- a/evals/parity/contracts/office-hours.json +++ b/evals/parity/contracts/office-hours.json @@ -19,7 +19,8 @@ 886, 703, 2000, - 879 + 879, + 538 ], "contract": { "question_order": "Preserve the source workflow order; gather prerequisites before consequential questions.", diff --git a/evals/parity/manifest.json b/evals/parity/manifest.json index fa2c95496e..856c4d2654 100644 --- a/evals/parity/manifest.json +++ b/evals/parity/manifest.json @@ -95,7 +95,8 @@ 886, 703, 2000, - 879 + 879, + 538 ], "original_source_file": "office-hours/SKILL.md.tmpl", "original_line_range": "1-526", @@ -6736,6 +6737,7 @@ "consumer_modules": [ "autoplan", "document-generate", + "office-hours", "plan-tune", "setup-gbrain", "ship", @@ -7533,6 +7535,15 @@ "*" ], "anchor": "GSTACK2_FIX_879_SELF_CONTAINED_QUESTIONS" + }, + { + "pr": 538, + "url": "https://github.com/garrytan/gstack/issues/538", + "title": "Founder resources honor a persistent never-show-again opt-out", + "targets": [ + "office-hours" + ], + "anchor": "GSTACK2_FIX_538_FOUNDER_RESOURCES_OPTOUT" } ] } diff --git a/evals/parity/regressions/pr-538.json b/evals/parity/regressions/pr-538.json new file mode 100644 index 0000000000..e812e40f10 --- /dev/null +++ b/evals/parity/regressions/pr-538.json @@ -0,0 +1,22 @@ +{ + "pr": 538, + "url": "https://github.com/garrytan/gstack/issues/538", + "title": "Founder resources honor a persistent never-show-again opt-out", + "targets": [ + "office-hours" + ], + "anchor": "GSTACK2_FIX_538_FOUNDER_RESOURCES_OPTOUT", + "body": "### Founder-resources opt-out\n\nBefore sharing any founder resources (Paul Graham essays, Garry Tan or YC videos, or similar motivational recommendations), check the persistent opt-out with `\"$GSTACK_BIN/gstack-config\" get founder_resources`. If it prints `false`, skip the entire resources phase silently — no resources, no mention that they were skipped — and continue with the rest of the handoff, which is unaffected. When resources are shown, the offer-to-open question must include a **\"Never show me these again\"** option alongside the open/skip options. Choosing it runs `\"$GSTACK_BIN/gstack-config\" set founder_resources false`, confirms in one line that resources will not be recommended again and that `gstack-config set founder_resources true` re-enables them, then continues. The opt-out is a durable user decision: never re-pitch the resources, never ask the user to reconsider, and never let a session's context override the stored `false`.", + "regression": { + "input": { + "founder_resources_config": "false", + "phase": "founder-resources" + }, + "expected": { + "resources_shown": false, + "skip_is_silent": true, + "never_again_option_when_shown": true, + "opt_out_persisted_via": "gstack-config set founder_resources false" + } + } +} diff --git a/evals/parity/runtime-helper-closure.json b/evals/parity/runtime-helper-closure.json index 882bb780f5..b1352d01fe 100644 --- a/evals/parity/runtime-helper-closure.json +++ b/evals/parity/runtime-helper-closure.json @@ -171,6 +171,7 @@ "consumer_modules": [ "autoplan", "document-generate", + "office-hours", "plan-tune", "setup-gbrain", "ship", diff --git a/evals/parity/transcripts/deterministic/office-hours.json b/evals/parity/transcripts/deterministic/office-hours.json index 8e3978bb1f..0b259c4af4 100644 --- a/evals/parity/transcripts/deterministic/office-hours.json +++ b/evals/parity/transcripts/deterministic/office-hours.json @@ -137,6 +137,13 @@ "reproduced_defect": "Show the content a question refers to before asking it", "regression_fixture": "evals/parity/regressions/pr-879.json", "explanation": "### Self-contained questions\n\nA question is only answerable if the user can see what it refers to. Before any AskUserQuestion or prose decision brief that asks the user to confirm, approve, rank, or choose among content this session produced — premises, findings, plans, approaches, scores, summaries — render that content in full as direct assistant text immediately before the question, or restate it inside the question and option descriptions. Internal reasoning is invisible to the user, and collapsed tool output (Bash cat, Read) does not count as shown. Never ask \"do you agree with the N premises?\" when the premises exist only in your reasoning: print them, then ask. This generalizes the inline design-doc approval rule from PR #1116 to every question in every workflow." + }, + { + "classification": "INTENTIONAL_IMPROVEMENT", + "issue_or_pr": "https://github.com/garrytan/gstack/issues/538", + "reproduced_defect": "Founder resources honor a persistent never-show-again opt-out", + "regression_fixture": "evals/parity/regressions/pr-538.json", + "explanation": "### Founder-resources opt-out\n\nBefore sharing any founder resources (Paul Graham essays, Garry Tan or YC videos, or similar motivational recommendations), check the persistent opt-out with `\"$GSTACK_BIN/gstack-config\" get founder_resources`. If it prints `false`, skip the entire resources phase silently — no resources, no mention that they were skipped — and continue with the rest of the handoff, which is unaffected. When resources are shown, the offer-to-open question must include a **\"Never show me these again\"** option alongside the open/skip options. Choosing it runs `\"$GSTACK_BIN/gstack-config\" set founder_resources false`, confirms in one line that resources will not be recommended again and that `gstack-config set founder_resources true` re-enables them, then continues. The opt-out is a durable user decision: never re-pitch the resources, never ask the user to reconsider, and never let a session's context override the stored `false`." } ] } diff --git a/skills/plan/references/legacy/office-hours.md b/skills/plan/references/legacy/office-hours.md index d021036d0a..aabf03ed8a 100644 --- a/skills/plan/references/legacy/office-hours.md +++ b/skills/plan/references/legacy/office-hours.md @@ -817,3 +817,13 @@ The design doc is a decision record, not a transcript of the session. There is n A question is only answerable if the user can see what it refers to. Before any AskUserQuestion or prose decision brief that asks the user to confirm, approve, rank, or choose among content this session produced — premises, findings, plans, approaches, scores, summaries — render that content in full as direct assistant text immediately before the question, or restate it inside the question and option descriptions. Internal reasoning is invisible to the user, and collapsed tool output (Bash cat, Read) does not count as shown. Never ask "do you agree with the N premises?" when the premises exist only in your reasoning: print them, then ask. This generalizes the inline design-doc approval rule from PR #1116 to every question in every workflow. + + +## Upstream judgment port: issue #538 + +[Founder resources honor a persistent never-show-again opt-out](https://github.com/garrytan/gstack/issues/538) + +### Founder-resources opt-out + +Before sharing any founder resources (Paul Graham essays, Garry Tan or YC videos, or similar motivational recommendations), check the persistent opt-out with `"$GSTACK_BIN/gstack-config" get founder_resources`. If it prints `false`, skip the entire resources phase silently — no resources, no mention that they were skipped — and continue with the rest of the handoff, which is unaffected. When resources are shown, the offer-to-open question must include a **"Never show me these again"** option alongside the open/skip options. Choosing it runs `"$GSTACK_BIN/gstack-config" set founder_resources false`, confirms in one line that resources will not be recommended again and that `gstack-config set founder_resources true` re-enables them, then continues. The opt-out is a durable user decision: never re-pitch the resources, never ask the user to reconsider, and never let a session's context override the stored `false`. + From a5dd6a221d0f39376bcf5888bfd0b5ab6f6b1553 Mon Sep 17 00:00:00 2001 From: Sinabina Date: Thu, 23 Jul 2026 12:05:58 -0700 Subject: [PATCH 4/4] docs: CHANGELOG + VERSION 1.61.2.0 for founder-resources opt-out Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 34 ++++++++++++++++++++++++++++++++++ VERSION | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 023e7b7068..2bf0152262 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,40 @@ > completion state and remaining P0 gates. No version bump or release claim is > made here while that status holds. +## [1.61.2.0] - 2026-07-23 + +## **The founder-resources pitch now takes no for an answer.** +## **Never means never.** + +Office-hours ends by recommending 2-3 items from a 34-item pool of Paul Graham essays and Garry Tan / YC videos, every single session. Until now your only choices were open them or skip them this once, and the reporter on issue #538 found that even memory instructions telling the agent to stop kept getting overridden on every update. This release adds a "Never show me these again" option to that offer. Pick it once and the opt-out is stored in config, where session context cannot override it: every future session skips the entire resources phase silently, no resources, no "skipped as requested" mention. The rest of the handoff is untouched. + +### The three numbers that matter + +Source: the executable parity inventory (`bun run scripts/gstack2/run-parity.ts`) and the office-hours resource pool in `skills/plan/references/sections/office-hours/design-and-handoff.md`. + +| Metric | Before | After | +|---|---|---| +| Ways to permanently decline the 34-resource pool | 0 | 1 selection | +| Sessions that re-pitch after you decline | every one | 0 | +| Judgment overlays / parity checks | 29 / 5,027 | 30 / 5,032 | + +The middle row is the fix. A stored `false` in `~/.gstack` beats a memory instruction because config survives updates and the overlay forbids the agent from re-litigating it. + +### What this means for builders + +Run `/plan` product mode as often as you want. The essays and videos show up until the day you say never, and then they stay gone. Changed your mind later? `gstack-config set founder_resources true` brings them back. That is the whole contract. + +### Itemized changes + +#### Added + +- **"Never show me these again"** option in the office-hours Founder Resources offer. Selecting it runs `gstack-config set founder_resources false`, confirms in one line with the re-enable command, and continues the handoff. +- New `founder_resources` config key (default `true`, validated to `true`/`false`), shipped with the managed runtime. + +#### For contributors + +- Judgment overlay #538 (`GSTACK2_FIX_538_FOUNDER_RESOURCES_OPTOUT`, office-hours only) with executable regression fixture `evals/parity/regressions/pr-538.json`; parity inventory grows 5,027 to 5,032. + ## [1.61.1.0] - 2026-07-22 ## **Design docs now read like decision records.** diff --git a/VERSION b/VERSION index ad37b0f1be..b6cc76b174 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.61.1.0 +1.61.2.0