// allow-test-rule: source-text-is-the-product // execute-plan.md and planning-config.md are deployed workflow/reference files // whose text IS the product loaded by agents at runtime. The config-set tests // use runGsdTools and assert on success/failure (typed). Migration from // pending-migration-to-typed-ir per #455. /** * Tests for workflow.inline_plan_threshold config key and routing logic (#1979). * * Verifies: * 1. The config key is accepted by config-set (VALID_CONFIG_KEYS contains it) * 2. The key is documented in planning-config.md * 3. The execute-plan.md routing instruction uses the correct grep pattern * (matches { let tmpDir; beforeEach(() => { tmpDir = createTempProject(); }); afterEach(() => { cleanup(tmpDir); }); test('config-set accepts workflow.inline_plan_threshold', () => { const result = runGsdTools('config-set workflow.inline_plan_threshold 3', tmpDir); assert.ok(result.success, `config-set should accept workflow.inline_plan_threshold: ${result.error}`); }); test('config-set accepts threshold=0 to disable inline routing', () => { const result = runGsdTools('config-set workflow.inline_plan_threshold 0', tmpDir); assert.ok(result.success, `config-set should accept 0: ${result.error}`); }); test('planning-config.md documents workflow.inline_plan_threshold', () => { const content = fs.readFileSync(planningConfigPath, 'utf-8'); assert.match( content, /workflow\.inline_plan_threshold/, 'planning-config.md must document workflow.inline_plan_threshold' ); }); }); describe('execute-plan.md routing instruction (#1979)', () => { test('grep pattern matches { const content = fs.readFileSync(executePlanPath, 'utf-8'); // The new pattern should use \s* for leading whitespace, not ^ anchor alone // Must match both " { // Simulate how the grep pattern would behave against sample PLAN.md content // Extract the pattern from execute-plan.md const content = fs.readFileSync(executePlanPath, 'utf-8'); // eslint-disable-next-line local/no-unbounded-quantifier -- parses maintainer-authored execute-plan.md workflow, bounded prose, not adversarial input const patternMatch = content.match(/TASK_COUNT=\$\(grep -cE '([^']+)'/); assert.ok(patternMatch, 'must find TASK_COUNT grep pattern'); const regexSource = patternMatch[1].replace(/\[\[:space:\]>\]/, '[\\s>]'); const re = new RegExp(regexSource, 'gm'); // Test cases: should match all of these as single tasks const samples = [ '', ' ', ' ', '\t', ]; for (const sample of samples) { const matches = sample.match(re); assert.ok(matches && matches.length > 0, `Pattern must match: ${JSON.stringify(sample)}`); } // Non-task lines should not match const nonMatches = [ '', '', '//