Files
get-shit-done/tests/bug-1818-unknown-flags.test.cjs
Tom Boucher e881c91ef1 fix(cli): reject help/version flags instead of silently ignoring them (#1822)
* fix(cli): reject help/version flags instead of silently ignoring them (#1818)

AI agents can hallucinate --help or --version on gsd-tools invocations.
Without a guard, unknown flags were silently ignored and the command
proceeded — including destructive ones like `phases clear`. Add a
pre-dispatch check in main() that errors immediately if any never-valid
flag (-h, --help, -?, --version, -v, --usage) is present in args after
global flags are stripped. Regression test covers phases clear, generate-
slug, state load, and current-timestamp with both --help and -h variants.

Closes #1818

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(agents): convert gsd-verifier required_reading to inline wiring

The thinking-model-guidance test requires inline @-reference wiring at
decision points rather than a <required_reading> block. Convert
verification-overrides.md reference from the <required_reading> block
to an inline reference inside <verification_process> alongside the
existing thinking-models-verification.md reference.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(tests): resolve conflict between thinking-model and verification-overrides tests

thinking-model-guidance.test prohibited <required_reading> entirely, but
verification-overrides.test requires gsd-verifier.md to have a
<required_reading> block for verification-overrides.md between </role>
and <project_context>. The tests were mutually exclusive.

Fix: narrow the thinking-model assertion to check that the thinking-models
reference is not *inside* a <required_reading> block (using regex extraction),
rather than asserting no <required_reading> block exists at all. Restore the
<required_reading> block in gsd-verifier.md. Both suites now pass (2345/2345).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 17:32:18 -04:00

85 lines
3.3 KiB
JavaScript

/**
* Regression test for bug #1818
*
* gsd-tools must reject unknown/invalid flags (--help, -h, etc.) with a
* non-zero exit and an error message instead of silently ignoring them and
* proceeding with the command — which can cause destructive operations to run
* when an AI agent hallucinates a flag like --help.
*/
'use strict';
const { describe, test, beforeEach, afterEach } = require('node:test');
const assert = require('node:assert/strict');
const { runGsdTools, createTempProject, cleanup } = require('./helpers.cjs');
describe('unknown flag guard (bug #1818)', () => {
let tmpDir;
beforeEach(() => {
tmpDir = createTempProject();
});
afterEach(() => {
cleanup(tmpDir);
});
// ── --help flag ────────────────────────────────────────────────────────────
test('phases clear --help is rejected with non-zero exit', () => {
const result = runGsdTools(['phases', 'clear', '--help'], tmpDir);
assert.strictEqual(result.success, false, 'should fail, not run destructive clear');
assert.match(result.error, /--help/);
});
test('generate-slug hello --help is rejected', () => {
// Non-destructive baseline: generate-slug hello succeeds without --help
const ok = runGsdTools(['generate-slug', 'hello'], tmpDir);
assert.strictEqual(ok.success, true, 'control: generate-slug without --help must succeed');
const result = runGsdTools(['generate-slug', 'hello', '--help'], tmpDir);
assert.strictEqual(result.success, false);
assert.match(result.error, /--help/);
});
test('phase complete --help is rejected', () => {
const result = runGsdTools(['phase', 'complete', '--help'], tmpDir);
assert.strictEqual(result.success, false);
assert.match(result.error, /--help/);
});
test('state load --help is rejected', () => {
const result = runGsdTools(['state', 'load', '--help'], tmpDir);
assert.strictEqual(result.success, false);
assert.match(result.error, /--help/);
});
// ── -h shorthand ──────────────────────────────────────────────────────────
test('phases clear -h is rejected', () => {
const result = runGsdTools(['phases', 'clear', '-h'], tmpDir);
assert.strictEqual(result.success, false);
assert.match(result.error, /-h/);
});
test('generate-slug hello -h is rejected', () => {
const result = runGsdTools(['generate-slug', 'hello', '-h'], tmpDir);
assert.strictEqual(result.success, false);
assert.match(result.error, /-h/);
});
// ── other common hallucinated flags ───────────────────────────────────────
test('generate-slug hello --version is rejected', () => {
const result = runGsdTools(['generate-slug', 'hello', '--version'], tmpDir);
assert.strictEqual(result.success, false);
assert.match(result.error, /--version/);
});
test('current-timestamp --help is rejected', () => {
const result = runGsdTools(['current-timestamp', '--help'], tmpDir);
assert.strictEqual(result.success, false);
assert.match(result.error, /--help/);
});
});