From 83e8b4645c31442e69afc6e0a91d951bb7a13591 Mon Sep 17 00:00:00 2001 From: Paul Bakaus Date: Thu, 13 Aug 2026 23:44:38 -0400 Subject: [PATCH 1/2] Ask the build path as its own question, and record only a real answer A live Codex session folded the build path into the stack question as a trailing recommendation ("I recommend static and code-first"), never said what either name means, treated its own recommendation as the user's answer, and wrote `buildPath: code` as a standing default. The user disagreed and flipped the board to comp-first, but a flip binds one session, so the unasked default stayed on disk to steer every later round. Step 5 said to "ask once ... stated as the trade it is", which the run violated, but the step left the shortcut open: it sits after the interview ends, it never says a recommendation is not an answer, and unlike the stack question it offers no way to end without a value, so an agent holding no answer writes one anyway. Now: it is its own question, never a clause inside another; the trade is stated in the question the user reads, because the two names mean nothing on first contact; only the user's own choice is written; and an unanswered question records nothing and says so. Unset is a working state, since the page toggle governs the session and new-work's one-time offer still captures the answer at the first flip. The same run also wrote "Code-first build path" into PRODUCT.md's `## Stack`, so the step now says the config is the only place this lives: a copy in product truth outlives the setting and steers rounds nobody can trace back to it. Written with AI assistance (Claude Code). Co-Authored-By: Claude Opus 5 (1M context) --- skill/reference/init.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/skill/reference/init.md b/skill/reference/init.md index 34ef41548..708480330 100644 --- a/skill/reference/init.md +++ b/skill/reference/init.md @@ -109,7 +109,11 @@ Before loading new-work or resuming shape/build, verify that PRODUCT.md exists a ## Step 5: Record workflow defaults -When image generation is available (context.mjs reports it) and no `buildPath` is recorded yet, ask once how new surfaces should be built, stated as the trade it is: **comp-first** (an image sets the bar before any code; bolder composition, slower, and the build must match the image) or **code-first** (build directly; the ambition is written into the direction contract and audited at the finish; leaner, faster). Write the answer to `.impeccable/config.json` as `"buildPath": "comp"` or `"buildPath": "code"`, merging with the keys already there. A value already recorded in `.impeccable/config.json` or the gitignored `.impeccable/config.local.json` is a confirmed answer: on a re-run, honor it in silence rather than asking again. This is a default, not a lock: the decision page renders a toggle whose flip binds a single session and is never written back. Without image generation there is no choice to record; code-first is the only path. +When image generation is available (context.mjs reports it) and no `buildPath` is recorded yet, ask once how new surfaces should be built. This is its own question, never a clause riding inside another one. The stack round asks what to build with; this asks how the building starts, and an answer to the first carries no consent about the second. State the trade in the question the user actually reads, because the two names mean nothing to someone meeting them for the first time: **comp-first** (an image sets the bar before any code; bolder composition, slower, and the build must match the image) or **code-first** (build directly; the ambition is written into the direction contract and audited at the finish; leaner, faster). + +Write the answer to `.impeccable/config.json` as `"buildPath": "comp"` or `"buildPath": "code"`, merging with the keys already there. Write only the value the user chose. A recommendation you made is not an answer you received, and a value taken from silence is a standing default nobody set: it then rides every future round in the project, which is the opposite of asking once. When the question goes unanswered, record nothing and say in one line which path this session is taking and that it is not stored. Unset is a working state, not a gap: the decision page's toggle governs each session, and new-work's one-time offer records the answer the first time the user flips it. The config is the only place this lives. It is a workflow setting, not product truth, so it never joins `## Stack` or any other PRODUCT.md section, where a second copy would outlive the setting and steer rounds nobody could trace back to it. + +A value already recorded in `.impeccable/config.json` or the gitignored `.impeccable/config.local.json` is a confirmed answer: on a re-run, honor it in silence rather than asking again. This is a default, not a lock: the decision page renders a toggle whose flip binds a single session and is never written back. Without image generation there is no choice to record; code-first is the only path. Then configure live mode when useful: skip native or non-runnable projects and leave existing config untouched. Otherwise follow [live.md](live.md)'s first-time setup. Any CSP source edit still requires its stated consent. From ae56d719afe84966057d5b1474e6b9cc94ab0168 Mon Sep 17 00:00:00 2001 From: Paul Bakaus Date: Fri, 14 Aug 2026 00:06:17 -0400 Subject: [PATCH 2/2] Name the image-gen sources and the unanswered default Two review findings on #583. "context.mjs reports it" undersold what counts: that directive only fires on an OPENAI_API_KEY, so a harness with a native image tool and no key generates images while the boot output says nothing. Read literally, the step would skip the question exactly where the toggle belongs. It now names both sources and says a silent boot is not evidence. The unanswered branch said to state which path the session takes without saying which one it is. Left implicit, an agent picks its own, which is the failure this step exists to stop. It now names comp-first, the default new-work applies when nothing is recorded. Written with AI assistance (Claude Code). Co-Authored-By: Claude Opus 5 (1M context) --- skill/reference/init.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skill/reference/init.md b/skill/reference/init.md index 708480330..7733498c7 100644 --- a/skill/reference/init.md +++ b/skill/reference/init.md @@ -109,9 +109,9 @@ Before loading new-work or resuming shape/build, verify that PRODUCT.md exists a ## Step 5: Record workflow defaults -When image generation is available (context.mjs reports it) and no `buildPath` is recorded yet, ask once how new surfaces should be built. This is its own question, never a clause riding inside another one. The stack round asks what to build with; this asks how the building starts, and an answer to the first carries no consent about the second. State the trade in the question the user actually reads, because the two names mean nothing to someone meeting them for the first time: **comp-first** (an image sets the bar before any code; bolder composition, slower, and the build must match the image) or **code-first** (build directly; the ambition is written into the direction contract and audited at the finish; leaner, faster). +When image generation is available and no `buildPath` is recorded yet, ask once how new surfaces should be built. Availability means a harness-native image tool or the API fallback that context.mjs reports as `IMAGE_GEN_AVAILABLE`, and the first of those leaves no trace in the boot output: context.mjs only sees the key, so a silent boot on a harness that generates images is not evidence there is nothing to ask about. This is its own question, never a clause riding inside another one. The stack round asks what to build with; this asks how the building starts, and an answer to the first carries no consent about the second. State the trade in the question the user actually reads, because the two names mean nothing to someone meeting them for the first time: **comp-first** (an image sets the bar before any code; bolder composition, slower, and the build must match the image) or **code-first** (build directly; the ambition is written into the direction contract and audited at the finish; leaner, faster). -Write the answer to `.impeccable/config.json` as `"buildPath": "comp"` or `"buildPath": "code"`, merging with the keys already there. Write only the value the user chose. A recommendation you made is not an answer you received, and a value taken from silence is a standing default nobody set: it then rides every future round in the project, which is the opposite of asking once. When the question goes unanswered, record nothing and say in one line which path this session is taking and that it is not stored. Unset is a working state, not a gap: the decision page's toggle governs each session, and new-work's one-time offer records the answer the first time the user flips it. The config is the only place this lives. It is a workflow setting, not product truth, so it never joins `## Stack` or any other PRODUCT.md section, where a second copy would outlive the setting and steer rounds nobody could trace back to it. +Write the answer to `.impeccable/config.json` as `"buildPath": "comp"` or `"buildPath": "code"`, merging with the keys already there. Write only the value the user chose. A recommendation you made is not an answer you received, and a value taken from silence is a standing default nobody set: it then rides every future round in the project, which is the opposite of asking once. When the question goes unanswered, record nothing and say in one line which path this session is taking and that it is not stored. That path is comp-first, the default new-work applies wherever image generation exists and nothing is recorded; name it rather than choosing a quieter one, because a silent default invented here is the same failure as a value written without an answer. Unset is a working state, not a gap: the decision page's toggle governs each session, and new-work's one-time offer records the answer the first time the user flips it. The config is the only place this lives. It is a workflow setting, not product truth, so it never joins `## Stack` or any other PRODUCT.md section, where a second copy would outlive the setting and steer rounds nobody could trace back to it. A value already recorded in `.impeccable/config.json` or the gitignored `.impeccable/config.local.json` is a confirmed answer: on a re-run, honor it in silence rather than asking again. This is a default, not a lock: the decision page renders a toggle whose flip binds a single session and is never written back. Without image generation there is no choice to record; code-first is the only path.