mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-19 09:36:59 +03:00
Build path becomes a config key existing projects can actually reach
The build-path preference shipped as a question only `init` asks, written to a file only `init` writes. Nothing routes an initialized project back through init, so every existing project took the comp-first default without anyone choosing it, and the only recourse was a footer toggle that binds one session. Neither the setting nor the round that preceded it ever reached a release (skill-v4.0.4 has no `buildPath`, no `comp-led`, no `.impeccable/settings.json`), so the PRODUCT.md standing-commitment fallback describes an era that never existed publicly. It is deleted rather than honored: told a field might exist, models go hunting for it and preserve it. - `buildPath` moves from `.impeccable/settings.json` into the unified `.impeccable/config.json`, which already has a known-keys registry, doctor coverage, and a gitignored `config.local.json` override. Whether a machine has an image tool is a property of that machine, so the local file wins. - new-work captures the answer from behavior instead of an interview: a toggle flip on a project recording nothing asks once, after the round closes, whether to keep it. The answer is written either way, because a declined offer nothing writes down is an offer the next session makes again. - Two findings: `config-invalid-build-path` (an unread value rides the default rather than the opposite path) and `config-build-path-unset`, gated on a product record plus evidence of direction work so polish-and-audit projects never hear about a setting they do not use. - init treats a recorded value as a confirmed answer, resolving its conflict with Step 1's "do not reopen confirmed fields". - The setting was undocumented in the README and doctor.md. Both now cover it. Also records a measured skill-behavior baseline. Three cells fail on unmodified main (scenarios 9 and 15, `initialized natural build`), verified against a clean worktree; the suite README now says so, so the next person does not spend the hour attributing them to their own branch. Written with AI assistance (Claude Code). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ddd23b1807
commit
c489335799
+29
-12
@@ -1142,7 +1142,7 @@ async function cli() {
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
appendDetectorFallback(parts, ctx);
|
||||
appendImageGenDirective(parts);
|
||||
appendBuildPathDirective(parts);
|
||||
appendBuildPathDirective(parts, ctx);
|
||||
appendAutonomyCounterDirective(parts);
|
||||
appendSubagentAuthorizationDirective(parts);
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -1162,7 +1162,7 @@ async function cli() {
|
||||
parts.push(buildResolvedContextDirective(ctx, cliOptions, { targetExists }));
|
||||
appendDetectorFallback(parts, ctx);
|
||||
appendImageGenDirective(parts);
|
||||
appendBuildPathDirective(parts);
|
||||
appendBuildPathDirective(parts, ctx);
|
||||
appendAutonomyCounterDirective(parts);
|
||||
appendSubagentAuthorizationDirective(parts);
|
||||
if (shouldWarnMissingTarget(ctx, targetProvided, targetExists)) {
|
||||
@@ -1271,17 +1271,34 @@ function automaticHookMode(ctx) {
|
||||
}
|
||||
|
||||
|
||||
// Build-path preference: a workflow setting (comp-led vs code-led), read
|
||||
// here so every session starts knowing it without a file hunt. Absence
|
||||
// stays silent; new-work's own default applies, and the decision page
|
||||
// toggle can flip the value for a single session.
|
||||
function appendBuildPathDirective(parts) {
|
||||
try {
|
||||
const settings = JSON.parse(fs.readFileSync(path.join(process.cwd(), '.impeccable', 'settings.json'), 'utf8'));
|
||||
if (settings.buildPath === 'comp' || settings.buildPath === 'code') {
|
||||
parts.push(`BUILD_PATH_DEFAULT: ${settings.buildPath} (from .impeccable/settings.json). Author direction and surface rounds with this as buildPath.value and toggle: true; a flip on the page binds that session only and is never written back to settings.`);
|
||||
// Build-path preference: a workflow setting (comp-led vs code-led), read here
|
||||
// so every session starts knowing it without a file hunt. It rides the unified
|
||||
// config beside the hook and detector settings, and the gitignored local file
|
||||
// wins, because whether a machine has an image tool is a property of that
|
||||
// machine, not of the team's committed default. Absence stays silent;
|
||||
// new-work's own default applies, and the decision page toggle can flip the
|
||||
// value for a single session.
|
||||
function readBuildPathAt(root) {
|
||||
let value = null;
|
||||
let source = null;
|
||||
for (const name of ['config.json', 'config.local.json']) {
|
||||
const raw = readJson(path.join(root, '.impeccable', name));
|
||||
if (raw?.buildPath === 'comp' || raw?.buildPath === 'code') {
|
||||
value = raw.buildPath;
|
||||
source = `.impeccable/${name}`;
|
||||
}
|
||||
} catch { /* no settings file */ }
|
||||
}
|
||||
return value ? { value, source } : null;
|
||||
}
|
||||
|
||||
function appendBuildPathDirective(parts, ctx) {
|
||||
const roots = [...new Set([ctx?.projectRoot, process.cwd()].filter(Boolean).map((root) => path.resolve(root)))];
|
||||
for (const root of roots) {
|
||||
const found = readBuildPathAt(root);
|
||||
if (!found) continue;
|
||||
parts.push(`BUILD_PATH_DEFAULT: ${found.value} (from ${found.source}). Author direction and surface rounds with this as buildPath.value and toggle: true; a flip on the page binds that session only and is never written back to the config.`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Image generation availability: harness-native tools always win, but when the
|
||||
|
||||
Reference in New Issue
Block a user