Require verbatim skip quote for seed pause and fix hidden doc shell.

Direction rolls on projects without DESIGN.md now refuse until the user accepts document --seed or re-runs with --seed-declined carrying their actual skip answer; IMPECCABLE_SEED_DECLINED=1 remains the unattended harness escape. Hide the design context shell when [hidden] so it does not reserve viewport space. Extend concept-seed tests for the seed gate.

AI-assisted.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Abdul Wahab
2026-09-01 10:02:40 +05:00
co-authored by Cursor
parent 5758e4c6bd
commit c582fd4699
3 changed files with 129 additions and 3 deletions
+4
View File
@@ -65,6 +65,10 @@ body.dcx-open { overflow: hidden; background: linear-gradient(180deg, var(--ks-l
padding: var(--dcx-gap) clamp(14px, 2vw, 26px) clamp(16px, 2.2vw, 28px);
}
/* The author display above would defeat the hidden attribute the shell ships
with, leaving an invisible 100svh box under the questionnaire. */
.dcx-shell[hidden] { display: none; }
.dcx-grid {
position: relative;
flex: 1 1 0;
+57 -1
View File
@@ -47,6 +47,7 @@
*
* Usage:
* node scripts/concept-seed.mjs --scope direction --mode persuade
* node scripts/concept-seed.mjs --scope direction --mode persuade --seed-declined="<user's verbatim skip answer>"
* node scripts/concept-seed.mjs --scope surface --mode operate --from <key>
* node scripts/concept-seed.mjs --scope surface --mode operate --grain flow
* node scripts/concept-seed.mjs --scope direction --candidate-count 6
@@ -55,6 +56,16 @@
* node scripts/concept-seed.mjs --chosen <challenger-id> --kind challenger --from <key> --scope direction
* node scripts/concept-seed.mjs --kind assigned --from <key> --scope direction
*
* --seed-declined records that the user was offered the document --seed
* questionnaire on a no-DESIGN.md project and skipped it. The flag carries
* evidence: its value is the user's verbatim skip answer, quoted from the
* conversation. Without it, a --scope direction roll on a project with no
* DESIGN.md refuses to deal and prints the pause directive instead; a bare
* or empty flag refuses the same way (a real live session self-passed the
* boolean form without asking, which is why the flag demands the quote).
* Fabricating or paraphrasing the quote is a contract violation, not a
* shortcut.
*
* --grain names how much of the product is in play: product, flow, view, or
* region. A docs site, an onboarding flow, a landing page and a data table are
* four different amounts of product and want different compositions. Grain is a
@@ -87,6 +98,10 @@
* IMPECCABLE_CATALOG_DIR — directory holding the four catalog JSON files.
* IMPECCABLE_API_URL — roll API base (default https://impeccable.style/api).
* IMPECCABLE_NO_TELEMETRY — disables the choice ping (DO_NOT_TRACK also honored).
* IMPECCABLE_SEED_DECLINED — set to 1 to bypass the seed pause without a
* quote; the unattended escape for eval and CI harnesses that
* legitimately roll direction on a no-DESIGN.md workspace. Never for
* attended sessions; the bypass is logged to stderr so it stays auditable.
*/
import crypto from 'node:crypto';
@@ -736,6 +751,21 @@ if (isMainModule()) {
const candidateCountIdx = args.indexOf('--candidate-count');
const chosenIdx = args.indexOf('--chosen');
const kindIdx = args.indexOf('--kind');
// --seed-declined carries evidence: the user's verbatim skip answer, in
// either --seed-declined="<answer>" or --seed-declined <answer> form. A
// bare or empty flag does not count; a live session self-passed the
// boolean form without asking the user, so the flag demands the quote.
let seedDeclinedAnswer = null;
for (let i = 0; i < args.length; i += 1) {
if (args[i] === '--seed-declined') {
const next = args[i + 1];
seedDeclinedAnswer = next !== undefined && !next.startsWith('--') ? next : '';
} else if (args[i].startsWith('--seed-declined=')) {
seedDeclinedAnswer = args[i].slice('--seed-declined='.length);
}
}
const seedDeclinedByEnv = process.env.IMPECCABLE_SEED_DECLINED === '1';
const seedDeclined = Boolean(seedDeclinedAnswer && seedDeclinedAnswer.trim()) || seedDeclinedByEnv;
try {
if (chosenIdx !== -1 || kindIdx !== -1) {
// Choice ping: always exits 0, telemetry must never fail a design flow.
@@ -776,7 +806,8 @@ if (isMainModule()) {
// 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) {
const ctx = loadContext(process.cwd());
if (!ctx.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.',
@@ -784,6 +815,31 @@ if (isMainModule()) {
].join(' ') + '\n');
process.exit(1);
}
// Mechanical seed-pause gate: prose alone did not keep a model from
// rolling a direction before offering the seed questionnaire (a real
// session read a stale reference file and dealt straight after init),
// and a boolean flag did not either (the next session self-passed it
// without asking). A direction roll invents the visual world, so on a
// project with no DESIGN.md the user gets the choice first; a seed
// DESIGN.md counts as present, so a post-questionnaire re-entry never
// re-asks. The flag now carries the user's verbatim skip answer.
const scopeArg = scopeIdx !== -1 ? args[scopeIdx + 1] : 'surface';
if (scopeArg === 'direction' && !ctx.hasDesign && !seedDeclined) {
process.stdout.write([
'NO_DESIGN_MD: the dice stay in the cup until the user answers the seed question.',
'First action: create a tracked todo "Ask user: document --seed or skip" with the harness todo tool and start no other todo until it is answered; with no todo tool, state this gate to the user in chat before anything else.',
'Then ask one question: recommend `document --seed`, the guided interview plus browser questionnaire (reference/document.md, seed mode), because a world built from the user\'s own choices beats one assigned to them; offer the skip in the same breath.',
'User accepts: run document seed mode; its seed DESIGN.md reads as an established world, so no direction roll happens.',
'User skips: re-run this exact command with --seed-declined="<their verbatim skip answer>" quoting the user\'s actual words from this conversation.',
'The original build request is never a skip answer, a bare or empty flag refuses again, and a fabricated or paraphrased quote is a contract violation.',
].join(' ') + '\n');
process.exit(1);
}
if (scopeArg === 'direction' && !ctx.hasDesign && seedDeclinedByEnv && !(seedDeclinedAnswer && seedDeclinedAnswer.trim())) {
// Auditable trace for the unattended escape; stderr keeps the seed
// output clean for the agent.
process.stderr.write('seed pause bypassed via IMPECCABLE_SEED_DECLINED (unattended harness escape)\n');
}
process.stdout.write(await renderConceptSeed({
scope: scopeIdx !== -1 ? args[scopeIdx + 1] : 'surface',
key: fromIdx !== -1
+68 -2
View File
@@ -532,7 +532,9 @@ 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: '' },
// Blank the escape hatch so a developer shell carrying it never turns
// the refusal assertions green for the wrong reason.
env: { ...process.env, IMPECCABLE_CATALOG_DIR: FIXTURE_DIR, IMPECCABLE_CONTEXT_DIR: '', IMPECCABLE_SEED_DECLINED: '' },
});
it('refuses to deal when no PRODUCT.md exists and routes to init', () => {
@@ -547,11 +549,75 @@ describe('init gate', () => {
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');
// DESIGN.md keeps this case about the product gate; the seed pause has
// its own suite below.
writeFileSync(path.join(dir, 'DESIGN.md'), '# Design\n\nEstablished world.\n');
const result = gateRun(dir);
assert.equal(result.status, 0);
assert.doesNotMatch(result.stdout, /NO_PRODUCT_MD/);
});
// The seed pause: a direction roll invents the visual world, so a project
// with PRODUCT.md but no DESIGN.md gets the questionnaire offer before the
// deal. The refusal is mechanical because prose alone did not stop a real
// session from rolling straight after init.
const seedGateDir = (design = null) => {
const dir = mkdtempSync(path.join(tmpdir(), 'concept-seed-seedgate-'));
writeFileSync(path.join(dir, 'PRODUCT.md'), '# Test Product\n\n## Platform\n\nweb\n');
if (design !== null) writeFileSync(path.join(dir, 'DESIGN.md'), design);
return dir;
};
it('refuses a direction roll with no DESIGN.md and routes to the seed questionnaire offer', () => {
const result = gateRun(seedGateDir());
assert.equal(result.status, 1);
assert.match(result.stdout, /NO_DESIGN_MD/);
assert.match(result.stdout, /document --seed/);
assert.match(result.stdout, /--seed-declined/);
assert.doesNotMatch(result.stdout, /ASSIGNED INDEX/);
});
it('deals a direction once --seed-declined records the user skip', () => {
const dir = seedGateDir();
const result = spawnSync(process.execPath, [SCRIPT, '--scope', 'direction', '--from', 'gate-test', '--seed-declined'], {
cwd: dir,
encoding: 'utf-8',
env: { ...process.env, IMPECCABLE_CATALOG_DIR: FIXTURE_DIR, IMPECCABLE_CONTEXT_DIR: '' },
});
assert.equal(result.status, 0);
assert.doesNotMatch(result.stdout, /NO_DESIGN_MD/);
assert.match(result.stdout, /ASSIGNED INDEX/);
});
it('honors IMPECCABLE_SEED_DECLINED=1 for harnesses that cannot thread the flag', () => {
const dir = seedGateDir();
const result = spawnSync(process.execPath, [SCRIPT, '--scope', 'direction', '--from', 'gate-test'], {
cwd: dir,
encoding: 'utf-8',
env: { ...process.env, IMPECCABLE_CATALOG_DIR: FIXTURE_DIR, IMPECCABLE_CONTEXT_DIR: '', IMPECCABLE_SEED_DECLINED: '1' },
});
assert.equal(result.status, 0);
assert.doesNotMatch(result.stdout, /NO_DESIGN_MD/);
});
it('treats a seed DESIGN.md as present so a post-questionnaire re-entry never re-asks', () => {
const seedDesign = '# Design\n\n<!-- SEED: established with the user before implementation; re-run /impeccable document once there\'s code to capture the actual tokens and components. -->\n';
const result = gateRun(seedGateDir(seedDesign));
assert.equal(result.status, 0);
assert.doesNotMatch(result.stdout, /NO_DESIGN_MD/);
});
it('never seed-gates a surface roll', () => {
const dir = seedGateDir();
const result = spawnSync(process.execPath, [SCRIPT, '--scope', 'surface', '--from', 'gate-test'], {
cwd: dir,
encoding: 'utf-8',
env: { ...process.env, IMPECCABLE_CATALOG_DIR: FIXTURE_DIR, IMPECCABLE_CONTEXT_DIR: '' },
});
assert.equal(result.status, 0);
assert.doesNotMatch(result.stdout, /NO_DESIGN_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'], {
@@ -809,7 +875,7 @@ describe('API roll path', () => {
const result = await new Promise((resolveRun, rejectRun) => {
const child = spawn(NODE, [
'--import', pathToFileURL(preloadPath).href,
SCRIPT, '--scope', 'direction', '--mode', 'persuade', '--from', 'api-test',
SCRIPT, '--scope', 'direction', '--mode', 'persuade', '--from', 'api-test', '--seed-declined',
], {
cwd: dir,
env: {