mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-14 15:16:35 +03:00
Gate the concept roll on PRODUCT.md existing
Paul reproduced the Opus smoke failure in a fresh repo: given a natural-language build intent, the model runs concept-seed directly and skips the init divert entirely, so PRODUCT.md never exists and nothing grounds the challenger fusion. Prose already says init-first in both SKILL.md routing and new-work.md; prose alone does not hold the floor. The deal path now refuses with a NO_PRODUCT_MD directive routing to reference/init.md when loadContext finds no PRODUCT.md. The --chosen telemetry ping stays ungated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
ea68bb4722
commit
f6cecf6149
@@ -511,6 +511,19 @@ if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.ur
|
||||
});
|
||||
process.stdout.write(sent ? 'choice recorded\n' : 'choice ping skipped\n');
|
||||
} else {
|
||||
// Mechanical init gate: prose alone does not keep a model from dealing
|
||||
// before init, and fresh repos produced exactly that skip (the model
|
||||
// rolled directions with no PRODUCT.md, so nothing grounded the fusion).
|
||||
// The --chosen branch above stays ungated; telemetry never blocks.
|
||||
const { loadContext } = await import('./context.mjs');
|
||||
if (!loadContext(process.cwd()).hasProduct) {
|
||||
process.stdout.write([
|
||||
'NO_PRODUCT_MD: the dice stay in the cup until product truth exists.',
|
||||
'Complete the init ask round and write PRODUCT.md first (reference/init.md), then re-run this exact command.',
|
||||
'Challengers fuse their form with facts from PRODUCT.md; without it every direction is ungrounded.',
|
||||
].join(' ') + '\n');
|
||||
process.exit(1);
|
||||
}
|
||||
process.stdout.write(await renderConceptSeed({
|
||||
scope: scopeIdx !== -1 ? args[scopeIdx + 1] : 'surface',
|
||||
key: fromIdx !== -1
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { mkdtempSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import {
|
||||
@@ -348,3 +350,39 @@ describe('concept seed scopes', () => {
|
||||
assert.equal(output.indexOf('CREATIVE SPARK:') < output.indexOf('SYSTEM GRAMMAR:'), true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('init gate', () => {
|
||||
const gateRun = (cwd) => spawnSync(process.execPath, [SCRIPT, '--scope', 'direction', '--from', 'gate-test'], {
|
||||
cwd,
|
||||
encoding: 'utf-8',
|
||||
env: { ...process.env, IMPECCABLE_CATALOG_DIR: FIXTURE_DIR, IMPECCABLE_CONTEXT_DIR: '' },
|
||||
});
|
||||
|
||||
it('refuses to deal when no PRODUCT.md exists and routes to init', () => {
|
||||
const dir = mkdtempSync(path.join(tmpdir(), 'concept-seed-noproduct-'));
|
||||
const result = gateRun(dir);
|
||||
assert.equal(result.status, 1);
|
||||
assert.match(result.stdout, /NO_PRODUCT_MD/);
|
||||
assert.match(result.stdout, /init/);
|
||||
assert.doesNotMatch(result.stdout, /ASSIGNED INDEX/);
|
||||
});
|
||||
|
||||
it('deals normally once PRODUCT.md exists', () => {
|
||||
const dir = mkdtempSync(path.join(tmpdir(), 'concept-seed-product-'));
|
||||
writeFileSync(path.join(dir, 'PRODUCT.md'), '# Test Product\n\n## Register\n\nbrand\n');
|
||||
const result = gateRun(dir);
|
||||
assert.equal(result.status, 0);
|
||||
assert.doesNotMatch(result.stdout, /NO_PRODUCT_MD/);
|
||||
});
|
||||
|
||||
it('never gates the choice ping', () => {
|
||||
const dir = mkdtempSync(path.join(tmpdir(), 'concept-seed-ping-'));
|
||||
const result = spawnSync(process.execPath, [SCRIPT, '--chosen', 'assigned', '--from', 'gate-test'], {
|
||||
cwd: dir,
|
||||
encoding: 'utf-8',
|
||||
env: { ...process.env, IMPECCABLE_CATALOG_DIR: FIXTURE_DIR, IMPECCABLE_NO_TELEMETRY: '1' },
|
||||
});
|
||||
assert.equal(result.status, 0);
|
||||
assert.doesNotMatch(result.stdout, /NO_PRODUCT_MD/);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user