diff --git a/tests/oracle/DELTAS.md b/tests/oracle/DELTAS.md index b436e94e7..5cbc45a41 100644 --- a/tests/oracle/DELTAS.md +++ b/tests/oracle/DELTAS.md @@ -85,3 +85,13 @@ reviewed line by line, so they now pin the fixed behavior. - `hook-session-fresh-then-pending-then-stop`, `hook-session-two-sessions`: the Stop deep pass syncs the remembered set to the live scan, including findings the per-edit pass already surfaced, so a second Stop with nothing new is silent and a fixed-then-reintroduced finding fires again (upstream 3c442af7). - `hadmin-on`, `hadmin-on-twice`, `hadmin-off-then-status`, `hadmin-on-repairs-existing-manifest`, `hadmin-on-malformed-manifest-backup`: the Claude manifests `hooks on` writes match on `Edit|Write` and the description names the current tools; Claude Code folded multi-edit behavior into Edit (upstream 7d5c60d2). - `live-commit-mock-unreported-file-change`: the rollback-failure results share one constructor, which moved `unreportedFiles` and `notes` after `pageUrl` in the emitted JSON (upstream 1f2c3f9d). + +## Recorded 2026-08-31: main's Aug 17-31 verb fixes ported to the engine, goldens re-recorded + +The goldens below froze pre-fix behavior. Each fix landed on main in JS and +was ported to the engine; the cases were re-recorded from the binary and +reviewed line by line, so they now pin the fixed behavior. + +- `hook-session-fresh-then-pending-then-stop`, `hook-session-two-sessions`: the Stop deep pass syncs the remembered set to the live scan, including findings the per-edit pass already surfaced, so a second Stop with nothing new is silent and a fixed-then-reintroduced finding fires again (upstream 3c442af7). +- `hadmin-on`, `hadmin-on-twice`, `hadmin-off-then-status`, `hadmin-on-repairs-existing-manifest`, `hadmin-on-malformed-manifest-backup`: the Claude manifests `hooks on` writes match on `Edit|Write` and the description names the current tools; Claude Code folded multi-edit behavior into Edit (upstream 7d5c60d2). +- `live-commit-mock-unreported-file-change`: the rollback-failure results share one constructor, which moved `unreportedFiles` and `notes` after `pageUrl` in the emitted JSON (upstream 1f2c3f9d). diff --git a/tests/oracle/cases/context.mjs b/tests/oracle/cases/context.mjs index 16bc72e70..2dd985b00 100644 --- a/tests/oracle/cases/context.mjs +++ b/tests/oracle/cases/context.mjs @@ -239,6 +239,18 @@ const cases = [ { id: 'doctor-product-only-json', verb: 'doctor', workspace: 'ctx-product-only', args: ['--json'], env: env() }, { id: 'doctor-full-text', verb: 'doctor', workspace: 'ctx-full', setup: sidecarNewer, env: env() }, { id: 'doctor-full-json', verb: 'doctor', workspace: 'ctx-full', setup: sidecarNewer, args: ['--json'], env: env() }, + // Boot and deep findings keep their established artifact order (the JS + // shared the boot policy with doctor in 80997663). + { + id: 'doctor-order-boot-and-deep', verb: 'doctor', workspace: 'ctx-empty', + setup: (ws) => { + write(ws, 'PRODUCT.md', '# Product\n\n## Register\n\nbrand\n\n## Users\nDesigners.\n'); + write(ws, 'DESIGN.md', '---\nname: Example\n---\n\n# Design System: Example\n'); + write(ws, '.impeccable/design.json', JSON.stringify({ schemaVersion: 1 })); + write(ws, '.impeccable/config.json', JSON.stringify({ unknownSetting: true })); + }, + args: ['--json'], env: env(), + }, { id: 'doctor-full-sidecar-stale', verb: 'doctor', workspace: 'ctx-full', setup: (ws) => { touch(path.join(ws, 'DESIGN.md'), T_NEW); touch(path.join(ws, '.impeccable/design.json'), T_OLD); }, args: ['--json'], env: env() }, { id: 'doctor-native-ios-text', verb: 'doctor', workspace: 'ctx-native-ios', env: env() }, { id: 'doctor-native-ios-json', verb: 'doctor', workspace: 'ctx-native-ios', args: ['--json'], env: env() }, diff --git a/tests/oracle/cases/hooks.mjs b/tests/oracle/cases/hooks.mjs index 321c53f3f..915fc92de 100644 --- a/tests/oracle/cases/hooks.mjs +++ b/tests/oracle/cases/hooks.mjs @@ -101,6 +101,28 @@ export default [ { stdin: stop({ session_id: 's2' }) }, ], }, + // Grok Build camelCase envelope (#646): the per-edit pass scans and warms + // the session cache without remembering findings (Grok drops PostToolUse + // stdout), the end_turn Stop reports the full set, the observe-only + // shutdown fire and a stopHookActive re-entry stay silent. + { + id: 'hook-session-grok-edit-then-stop', verb: 'hook', workspace: 'hook-project', files: CACHE_FILES, + steps: [ + { stdin: { sessionId: 'g1', cwd: WS, hookEventName: 'post_tool_use', toolName: 'str_replace', toolInput: { file_path: `${WS}/src/components/Card.module.css` } } }, + { stdin: { sessionId: 'g1', cwd: WS, hookEventName: 'stop', reason: 'end_turn' } }, + { stdin: { sessionId: 'g1', cwd: WS, hookEventName: 'stop', reason: 'shutdown' } }, + { stdin: { sessionId: 'g1', cwd: WS, hookEventName: 'stop', reason: 'end_turn', stopHookActive: true } }, + ], + }, + // Codex Stop contract (#603): turn_id identifies Codex, whose Stop channel + // is a top-level decision/block instead of hookSpecificOutput. + { + id: 'hook-session-codex-stop-decision', verb: 'hook', workspace: 'hook-project', files: CACHE_FILES, + steps: [ + { stdin: claudeEdit('src/components/Card.module.css', { session_id: 'cx1', turn_id: 't-1' }) }, + { stdin: stop({ session_id: 'cx1', turn_id: 't-1' }) }, + ], + }, // --- hook-before-edit.mjs (Cursor) --- { id: 'hbe-write-with-findings', verb: 'hook-before-edit', workspace: 'hook-project', stdin: { hook_event_name: 'preToolUse', conversation_id: 'cv1', workspace_roots: [WS], tool_name: 'Write', tool_input: { path: 'src/new.css', content: '.t { background: linear-gradient(90deg,#f00,#00f); -webkit-background-clip: text; color: transparent; }\n' } }, files: CACHE_FILES }, diff --git a/tests/oracle/golden/doctor-order-boot-and-deep.json b/tests/oracle/golden/doctor-order-boot-and-deep.json new file mode 100644 index 000000000..e46af9134 --- /dev/null +++ b/tests/oracle/golden/doctor-order-boot-and-deep.json @@ -0,0 +1,7 @@ +{ + "stdout": "{\n \"projectRoot\": \"\",\n \"repoRoot\": \"\",\n \"isMonorepo\": false,\n \"productPath\": \"PRODUCT.md\",\n \"designPath\": \"DESIGN.md\",\n \"platform\": null,\n \"ruleRegistryAvailable\": true,\n \"findings\": [\n {\n \"id\": \"product-deprecated-register\",\n \"artifact\": \"PRODUCT.md\",\n \"path\": \"PRODUCT.md\",\n \"severity\": \"mention\",\n \"summary\": \"PRODUCT.md still carries a `## Register` section. v4 replaced the brand/product register axis with the four visitor modes (Persuade, Operate, Read, Experience), which are chosen per surface and persisted in that surface's brief. Nothing reads `## Register` any more.\",\n \"fix\": \"Treat `## Register` as absent for every decision this session. Offer to delete the section; do not let its value influence the work either way.\"\n },\n {\n \"id\": \"product-schema-legacy\",\n \"artifact\": \"PRODUCT.md\",\n \"path\": \"PRODUCT.md\",\n \"severity\": \"route\",\n \"summary\": \"PRODUCT.md has no schema stamp and none of the sections the current record adds (Positioning, Operating Context, Evidence on Hand, Product Principles), so it predates this version of the product record.\",\n \"fix\": \"Offer `init`, which preserves confirmed answers and fills the gaps by interview. Do not rewrite the file from inference.\"\n },\n {\n \"id\": \"design-sidecar-schema-outdated\",\n \"artifact\": \"design.json\",\n \"path\": \".impeccable/design.json\",\n \"severity\": \"route\",\n \"summary\": \".impeccable/design.json is schemaVersion 1; the current sidecar is 2. Token primitives moved to the DESIGN.md frontmatter, so the old shape carries values that are now read from two places.\",\n \"fix\": \"Offer `document` to regenerate the sidecar. It reads the existing DESIGN.md, so no interview is needed.\"\n },\n {\n \"id\": \"design-md-coverage\",\n \"artifact\": \"DESIGN.md\",\n \"path\": \"DESIGN.md\",\n \"severity\": \"mention\",\n \"summary\": \"DESIGN.md has no colors, typography, components section. Agents generating new screens get no normative guidance for those, and the live design panel renders generic approximations in their place.\",\n \"fix\": \"Ask whether the section never applied or was never written. `document` fills it from the code if the project has the answer in its CSS.\"\n },\n {\n \"id\": \"config-unknown-keys\",\n \"artifact\": \"config.json\",\n \"path\": \".impeccable/config.json\",\n \"severity\": \"mention\",\n \"summary\": \".impeccable/config.json has top-level key(s) nothing reads: `unknownSetting`. Recognized keys are `hook`, `detector`, `updateCheck`, `stalenessCheck`, `projectRoots`, `buildPath`, `$schema`, `version`.\",\n \"fix\": \"Report the exact keys to the user. A near-miss of a real key is a setting that has never applied.\"\n }\n ],\n \"workspaces\": []\n}\n", + "stderr": "", + "exit": 0, + "signal": null, + "files": {} +} diff --git a/tests/oracle/golden/hadmin-off-then-status.json b/tests/oracle/golden/hadmin-off-then-status.json index 7d02cf599..4e0fdda80 100644 --- a/tests/oracle/golden/hadmin-off-then-status.json +++ b/tests/oracle/golden/hadmin-off-then-status.json @@ -26,7 +26,7 @@ } ], "files": { - ".claude/settings.local.json": "{\n \"description\": \"Impeccable design detector: immediate-tier checks after Edit/Write/MultiEdit on UI files, full-rule deep pass on Stop.\",\n \"hooks\": {\n \"PostToolUse\": [\n {\n \"matcher\": \"Edit|Write|MultiEdit\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 5,\n \"statusMessage\": \"Checking UI changes\"\n }\n ]\n }\n ],\n \"Stop\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 30,\n \"statusMessage\": \"Design deep pass\"\n }\n ]\n }\n ]\n }\n}\n", + ".claude/settings.local.json": "{\n \"description\": \"Impeccable design detector: immediate-tier checks after Edit/Write on UI files, full-rule deep pass on Stop.\",\n \"hooks\": {\n \"PostToolUse\": [\n {\n \"matcher\": \"Edit|Write\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 5,\n \"statusMessage\": \"Checking UI changes\"\n }\n ]\n }\n ],\n \"Stop\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 30,\n \"statusMessage\": \"Design deep pass\"\n }\n ]\n }\n ]\n }\n}\n", ".cursor/hooks.json": "{\n \"version\": 1,\n \"hooks\": {\n \"preToolUse\": [\n {\n \"command\": \"\\\".cursor/skills/impeccable/scripts/impeccable\\\" hook-before-edit\",\n \"timeout\": 5\n }\n ]\n }\n}\n", ".impeccable/config.json": "{\n \"hook\": {\n \"enabled\": true,\n \"limits\": {\n \"maxFindings\": 5,\n \"maxChars\": 8000\n }\n }\n}\n", ".impeccable/config.local.json": "{\n \"hook\": {\n \"consent\": \"accepted\"\n }\n}\n" diff --git a/tests/oracle/golden/hadmin-on-malformed-manifest-backup.json b/tests/oracle/golden/hadmin-on-malformed-manifest-backup.json index 9e4743929..b05f2fffd 100644 --- a/tests/oracle/golden/hadmin-on-malformed-manifest-backup.json +++ b/tests/oracle/golden/hadmin-on-malformed-manifest-backup.json @@ -4,7 +4,7 @@ "exit": 0, "signal": null, "files": { - ".claude/settings.local.json": "{\n \"description\": \"Impeccable design detector: immediate-tier checks after Edit/Write/MultiEdit on UI files, full-rule deep pass on Stop.\",\n \"hooks\": {\n \"PostToolUse\": [\n {\n \"matcher\": \"Edit|Write|MultiEdit\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 5,\n \"statusMessage\": \"Checking UI changes\"\n }\n ]\n }\n ],\n \"Stop\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 30,\n \"statusMessage\": \"Design deep pass\"\n }\n ]\n }\n ]\n }\n}\n", + ".claude/settings.local.json": "{\n \"description\": \"Impeccable design detector: immediate-tier checks after Edit/Write on UI files, full-rule deep pass on Stop.\",\n \"hooks\": {\n \"PostToolUse\": [\n {\n \"matcher\": \"Edit|Write\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 5,\n \"statusMessage\": \"Checking UI changes\"\n }\n ]\n }\n ],\n \"Stop\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 30,\n \"statusMessage\": \"Design deep pass\"\n }\n ]\n }\n ]\n }\n}\n", ".cursor/hooks.json": "{\n \"version\": 1,\n \"hooks\": {\n \"preToolUse\": [\n {\n \"command\": \"\\\".cursor/skills/impeccable/scripts/impeccable\\\" hook-before-edit\",\n \"timeout\": 5\n }\n ]\n }\n}\n", ".cursor/hooks.json.bak": "{ broken", ".impeccable/config.json": "{\n \"hook\": {\n \"enabled\": true,\n \"limits\": {\n \"maxFindings\": 5,\n \"maxChars\": 8000\n }\n }\n}\n", diff --git a/tests/oracle/golden/hadmin-on-repairs-existing-manifest.json b/tests/oracle/golden/hadmin-on-repairs-existing-manifest.json index 12f890f87..29d655e94 100644 --- a/tests/oracle/golden/hadmin-on-repairs-existing-manifest.json +++ b/tests/oracle/golden/hadmin-on-repairs-existing-manifest.json @@ -4,7 +4,7 @@ "exit": 0, "signal": null, "files": { - ".claude/settings.local.json": "{\n \"permissions\": {\n \"allow\": [\n \"Bash(ls)\"\n ]\n },\n \"hooks\": {\n \"PostToolUse\": [\n {\n \"matcher\": \"Write\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"echo other\"\n }\n ]\n },\n {\n \"matcher\": \"Edit|Write|MultiEdit\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 5,\n \"statusMessage\": \"Checking UI changes\"\n }\n ]\n }\n ],\n \"Stop\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 30,\n \"statusMessage\": \"Design deep pass\"\n }\n ]\n }\n ]\n },\n \"description\": \"Impeccable design detector: immediate-tier checks after Edit/Write/MultiEdit on UI files, full-rule deep pass on Stop.\"\n}\n", + ".claude/settings.local.json": "{\n \"permissions\": {\n \"allow\": [\n \"Bash(ls)\"\n ]\n },\n \"hooks\": {\n \"PostToolUse\": [\n {\n \"matcher\": \"Write\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"echo other\"\n }\n ]\n },\n {\n \"matcher\": \"Edit|Write\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 5,\n \"statusMessage\": \"Checking UI changes\"\n }\n ]\n }\n ],\n \"Stop\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 30,\n \"statusMessage\": \"Design deep pass\"\n }\n ]\n }\n ]\n },\n \"description\": \"Impeccable design detector: immediate-tier checks after Edit/Write on UI files, full-rule deep pass on Stop.\"\n}\n", ".cursor/hooks.json": "{\n \"version\": 1,\n \"hooks\": {\n \"preToolUse\": [\n {\n \"command\": \"\\\".cursor/skills/impeccable/scripts/impeccable\\\" hook-before-edit\",\n \"timeout\": 5\n }\n ]\n }\n}\n", ".impeccable/config.json": "{\n \"hook\": {\n \"enabled\": true,\n \"limits\": {\n \"maxFindings\": 5,\n \"maxChars\": 8000\n }\n }\n}\n", ".impeccable/config.local.json": "{\n \"hook\": {\n \"consent\": \"accepted\"\n }\n}\n" diff --git a/tests/oracle/golden/hadmin-on-twice.json b/tests/oracle/golden/hadmin-on-twice.json index fce92124d..9ca007343 100644 --- a/tests/oracle/golden/hadmin-on-twice.json +++ b/tests/oracle/golden/hadmin-on-twice.json @@ -20,7 +20,7 @@ } ], "files": { - ".claude/settings.local.json": "{\n \"description\": \"Impeccable design detector: immediate-tier checks after Edit/Write/MultiEdit on UI files, full-rule deep pass on Stop.\",\n \"hooks\": {\n \"PostToolUse\": [\n {\n \"matcher\": \"Edit|Write|MultiEdit\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 5,\n \"statusMessage\": \"Checking UI changes\"\n }\n ]\n }\n ],\n \"Stop\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 30,\n \"statusMessage\": \"Design deep pass\"\n }\n ]\n }\n ]\n }\n}\n", + ".claude/settings.local.json": "{\n \"description\": \"Impeccable design detector: immediate-tier checks after Edit/Write on UI files, full-rule deep pass on Stop.\",\n \"hooks\": {\n \"PostToolUse\": [\n {\n \"matcher\": \"Edit|Write\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 5,\n \"statusMessage\": \"Checking UI changes\"\n }\n ]\n }\n ],\n \"Stop\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 30,\n \"statusMessage\": \"Design deep pass\"\n }\n ]\n }\n ]\n }\n}\n", ".cursor/hooks.json": "{\n \"version\": 1,\n \"hooks\": {\n \"preToolUse\": [\n {\n \"command\": \"\\\".cursor/skills/impeccable/scripts/impeccable\\\" hook-before-edit\",\n \"timeout\": 5\n }\n ]\n }\n}\n", ".impeccable/config.json": "{\n \"hook\": {\n \"enabled\": true,\n \"limits\": {\n \"maxFindings\": 5,\n \"maxChars\": 8000\n }\n }\n}\n", ".impeccable/config.local.json": "{\n \"hook\": {\n \"consent\": \"accepted\"\n }\n}\n" diff --git a/tests/oracle/golden/hadmin-on.json b/tests/oracle/golden/hadmin-on.json index eb637498b..7d92f520b 100644 --- a/tests/oracle/golden/hadmin-on.json +++ b/tests/oracle/golden/hadmin-on.json @@ -4,7 +4,7 @@ "exit": 0, "signal": null, "files": { - ".claude/settings.local.json": "{\n \"description\": \"Impeccable design detector: immediate-tier checks after Edit/Write/MultiEdit on UI files, full-rule deep pass on Stop.\",\n \"hooks\": {\n \"PostToolUse\": [\n {\n \"matcher\": \"Edit|Write|MultiEdit\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 5,\n \"statusMessage\": \"Checking UI changes\"\n }\n ]\n }\n ],\n \"Stop\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 30,\n \"statusMessage\": \"Design deep pass\"\n }\n ]\n }\n ]\n }\n}\n", + ".claude/settings.local.json": "{\n \"description\": \"Impeccable design detector: immediate-tier checks after Edit/Write on UI files, full-rule deep pass on Stop.\",\n \"hooks\": {\n \"PostToolUse\": [\n {\n \"matcher\": \"Edit|Write\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 5,\n \"statusMessage\": \"Checking UI changes\"\n }\n ]\n }\n ],\n \"Stop\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\\\"${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/impeccable\\\" hook\",\n \"timeout\": 30,\n \"statusMessage\": \"Design deep pass\"\n }\n ]\n }\n ]\n }\n}\n", ".cursor/hooks.json": "{\n \"version\": 1,\n \"hooks\": {\n \"preToolUse\": [\n {\n \"command\": \"\\\".cursor/skills/impeccable/scripts/impeccable\\\" hook-before-edit\",\n \"timeout\": 5\n }\n ]\n }\n}\n", ".impeccable/config.json": "{\n \"hook\": {\n \"enabled\": true,\n \"limits\": {\n \"maxFindings\": 5,\n \"maxChars\": 8000\n }\n }\n}\n", ".impeccable/config.local.json": "{\n \"hook\": {\n \"consent\": \"accepted\"\n }\n}\n" diff --git a/tests/oracle/golden/hook-session-codex-stop-decision.json b/tests/oracle/golden/hook-session-codex-stop-decision.json new file mode 100644 index 000000000..d8006716e --- /dev/null +++ b/tests/oracle/golden/hook-session-codex-stop-decision.json @@ -0,0 +1,19 @@ +{ + "steps": [ + { + "stdout": "{\"hookSpecificOutput\":{\"hookEventName\":\"PostToolUse\",\"additionalContext\":\"[impeccable@1] Design hook findings requiring review in src/components/Card.module.css (1 issue(s)):\\n- L2 [gradient-text] Gradient text. Gradient text is decorative rather than meaningful — a common AI tell, especially on headings and metrics. Use solid colors for text.\\n\\nTriage each finding, then state in your reply what you fixed, what you suppressed, and what you left standing:\\n- Real design problem: fix it. Keep intentional design as designed.\\n- Confident false positive or sanctioned exception (an intentional demo or fixture, documentation of bad design, literal or domain-appropriate motion, a choice the user confirmed): persist the narrowest ignore yourself and disclose it. Run ` ignore-value \\\"\\\" --reason \\\"\\\"` with the pair shown on the finding line, or value \\\"*\\\" plus `--file ` when the line shows none. Write \\\"user confirmed\\\" in a reason only when the user did.\\n- Unsure: leave it as is and ask the user in one line.\\nSelf-serve ends at ignore-value: `ignore-file` and `ignore-rule` need the user's explicit approval, and never add an ignore to push a blocked write through. Full suppression ladder: /impeccable hooks.\"}}", + "stderr": "", + "exit": 0, + "signal": null + }, + { + "stdout": "{\"decision\":\"block\",\"reason\":\"[impeccable@1] Design hook findings requiring review in src/components/Card.module.css (1 issue(s)):\\n- L1 [side-tab] Side-tab accent border. Thick colored border on one side of a card — the most recognizable tell of AI-generated UIs. Use a subtler accent or remove it entirely.\\n\\nTriage per the session policy: fix real problems; persist confident false-positive or sanctioned-exception ignores via `impeccable hooks ignore-value` and disclose them in your reply; unsure, ask in one line.\"}", + "stderr": "", + "exit": 0, + "signal": null + } + ], + "files": { + ".impeccable/hook.cache.json": "{\"version\":1,\"sessions\":{\"cx1\":{\"updatedAt\": ,\"files\":{\"/src/components/Card.module.css\":{\"editCount\":1,\"findings\":[\"side-tab:1\",\"gradient-text:2\"]}},\"footerShown\":true}}}" + } +} diff --git a/tests/oracle/golden/hook-session-fresh-then-pending-then-stop.json b/tests/oracle/golden/hook-session-fresh-then-pending-then-stop.json index bfde47bf8..5be02aca1 100644 --- a/tests/oracle/golden/hook-session-fresh-then-pending-then-stop.json +++ b/tests/oracle/golden/hook-session-fresh-then-pending-then-stop.json @@ -31,13 +31,13 @@ "signal": null }, { - "stdout": "{\"hookSpecificOutput\":{\"hookEventName\":\"Stop\",\"additionalContext\":\"[impeccable@1] Design hook findings requiring review in src/components/Card.module.css (1 issue(s)):\\n- L2 [gradient-text] Gradient text. Gradient text is decorative rather than meaningful — a common AI tell, especially on headings and metrics. Use solid colors for text.\\n\\nTriage per the session policy: fix real problems; persist confident false-positive or sanctioned-exception ignores via `impeccable hooks ignore-value` and disclose them in your reply; unsure, ask in one line.\"}}", + "stdout": "", "stderr": "", "exit": 0, "signal": null } ], "files": { - ".impeccable/hook.cache.json": "{\"version\":1,\"sessions\":{\"s1\":{\"updatedAt\": ,\"files\":{\"/src/components/Card.module.css\":{\"editCount\":2,\"findings\":[\"gradient-text:2\"]},\"/src/components/Clean.tsx\":{\"editCount\":2,\"findings\":[],\"cleanAcked\":true}},\"footerShown\":true}}}" + ".impeccable/hook.cache.json": "{\"version\":1,\"sessions\":{\"s1\":{\"updatedAt\": ,\"files\":{\"/src/components/Card.module.css\":{\"editCount\":2,\"findings\":[\"side-tab:1\",\"gradient-text:2\"]},\"/src/components/Clean.tsx\":{\"editCount\":2,\"findings\":[],\"cleanAcked\":true}},\"footerShown\":true}}}" } } diff --git a/tests/oracle/golden/hook-session-grok-edit-then-stop.json b/tests/oracle/golden/hook-session-grok-edit-then-stop.json new file mode 100644 index 000000000..7f911789c --- /dev/null +++ b/tests/oracle/golden/hook-session-grok-edit-then-stop.json @@ -0,0 +1,31 @@ +{ + "steps": [ + { + "stdout": "{\"hookSpecificOutput\":{\"hookEventName\":\"PostToolUse\",\"additionalContext\":\"[impeccable@1] Design hook findings requiring review in src/components/Card.module.css (1 issue(s)):\\n- L2 [gradient-text] Gradient text. Gradient text is decorative rather than meaningful — a common AI tell, especially on headings and metrics. Use solid colors for text.\\n\\nTriage each finding, then state in your reply what you fixed, what you suppressed, and what you left standing:\\n- Real design problem: fix it. Keep intentional design as designed.\\n- Confident false positive or sanctioned exception (an intentional demo or fixture, documentation of bad design, literal or domain-appropriate motion, a choice the user confirmed): persist the narrowest ignore yourself and disclose it. Run ` ignore-value \\\"\\\" --reason \\\"\\\"` with the pair shown on the finding line, or value \\\"*\\\" plus `--file ` when the line shows none. Write \\\"user confirmed\\\" in a reason only when the user did.\\n- Unsure: leave it as is and ask the user in one line.\\nSelf-serve ends at ignore-value: `ignore-file` and `ignore-rule` need the user's explicit approval, and never add an ignore to push a blocked write through. Full suppression ladder: /impeccable hooks.\"}}", + "stderr": "", + "exit": 0, + "signal": null + }, + { + "stdout": "{\"hookSpecificOutput\":{\"hookEventName\":\"Stop\",\"additionalContext\":\"[impeccable@1] Design hook findings requiring review in src/components/Card.module.css (2 issue(s)):\\n- L1 [side-tab] Side-tab accent border. Thick colored border on one side of a card — the most recognizable tell of AI-generated UIs. Use a subtler accent or remove it entirely.\\n- L2 [gradient-text] Gradient text. Gradient text is decorative rather than meaningful — a common AI tell, especially on headings and metrics. Use solid colors for text.\\n\\nTriage per the session policy: fix real problems; persist confident false-positive or sanctioned-exception ignores via `impeccable hooks ignore-value` and disclose them in your reply; unsure, ask in one line.\"}}", + "stderr": "", + "exit": 0, + "signal": null + }, + { + "stdout": "", + "stderr": "", + "exit": 0, + "signal": null + }, + { + "stdout": "", + "stderr": "", + "exit": 0, + "signal": null + } + ], + "files": { + ".impeccable/hook.cache.json": "{\"version\":1,\"sessions\":{\"g1\":{\"updatedAt\": ,\"files\":{\"/src/components/Card.module.css\":{\"editCount\":1,\"findings\":[\"side-tab:1\",\"gradient-text:2\"]}},\"footerShown\":true}}}" + } +} diff --git a/tests/oracle/golden/hook-session-two-sessions.json b/tests/oracle/golden/hook-session-two-sessions.json index 45315dec6..d31f5ee2a 100644 --- a/tests/oracle/golden/hook-session-two-sessions.json +++ b/tests/oracle/golden/hook-session-two-sessions.json @@ -20,6 +20,6 @@ } ], "files": { - ".impeccable/hook.cache.json": "{\"version\":1,\"sessions\":{\"s1\":{\"updatedAt\": ,\"files\":{\"/src/components/Card.module.css\":{\"editCount\":1,\"findings\":[\"gradient-text:2\"]}},\"footerShown\":true},\"s2\":{\"updatedAt\": ,\"files\":{\"/src/components/Card.module.css\":{\"editCount\":1,\"findings\":[\"side-tab:1\"]}},\"footerShown\":true}}}" + ".impeccable/hook.cache.json": "{\"version\":1,\"sessions\":{\"s1\":{\"updatedAt\": ,\"files\":{\"/src/components/Card.module.css\":{\"editCount\":1,\"findings\":[\"gradient-text:2\"]}},\"footerShown\":true},\"s2\":{\"updatedAt\": ,\"files\":{\"/src/components/Card.module.css\":{\"editCount\":1,\"findings\":[\"side-tab:1\",\"gradient-text:2\"]}},\"footerShown\":true}}}" } } diff --git a/tests/oracle/golden/live-commit-mock-unreported-file-change.json b/tests/oracle/golden/live-commit-mock-unreported-file-change.json index 23833863c..ee87671e1 100644 --- a/tests/oracle/golden/live-commit-mock-unreported-file-change.json +++ b/tests/oracle/golden/live-commit-mock-unreported-file-change.json @@ -1,5 +1,5 @@ { - "stdout": "{\"applied\":[],\"failed\":[{\"id\":\"e1\",\"reason\":\"unreported_source_changes\",\"candidates\":[{\"file\":\"index.html\",\"loc\":\"\",\"line\":13,\"column\":7,\"status\":\"ok\",\"relativeFile\":\"index.html\",\"excerpt\":[{\"line\":10,\"text\":\" \"},{\"line\":11,\"text\":\" \"},{\"line\":12,\"text\":\"
\"},{\"line\":13,\"text\":\"

Oracle Fixture

\"},{\"line\":14,\"text\":\"

Minimal static page for oracle live-mode goldens.

\"},{\"line\":15,\"text\":\"
\"},{\"line\":16,\"text\":\"
One
\"}]},{\"kind\":\"text\",\"file\":\"index.html\",\"line\":13,\"needle\":\"Oracle Fixture\",\"excerpt\":\"

Oracle Fixture

\"},{\"kind\":\"class\",\"file\":\"index.html\",\"line\":7,\"needle\":\"hero-title\",\"excerpt\":\".hero-title { font-size: 2rem; }\"},{\"kind\":\"class\",\"file\":\"index.html\",\"line\":13,\"needle\":\"hero-title\",\"excerpt\":\"

Oracle Fixture

\"},{\"kind\":\"tag\",\"file\":\"public/docs/guide.html\",\"line\":9,\"needle\":\"Guide\"},{\"kind\":\"tag\",\"file\":\"index.html\",\"line\":13,\"needle\":\"Oracle Fixture\"}],\"files\":[\"index.html\"]},{\"id\":\"e2\",\"reason\":\"unreported_source_changes\",\"candidates\":[{\"kind\":\"text\",\"file\":\"index.html\",\"line\":14,\"needle\":\"Minimal static page for oracle live-mode goldens.\",\"excerpt\":\"

Minimal static page for oracle live-mode goldens.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":4,\"needle\":\"First card body copy.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":8,\"needle\":\"Second card body copy.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":12,\"needle\":\"Third card body copy.

\"},{\"kind\":\"tag\",\"file\":\"public/docs/guide.html\",\"line\":10,\"needle\":\"A second page covered by the config glob.

\"},{\"kind\":\"text\",\"file\":\"index.html\",\"line\":21,\"needle\":\"Nested content.\",\"excerpt\":\"

Nested content.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":4,\"needle\":\"First card body copy.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":8,\"needle\":\"Second card body copy.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":12,\"needle\":\"Third card body copy.

\"},{\"kind\":\"tag\",\"file\":\"public/docs/guide.html\",\"line\":10,\"needle\":\"A second page covered by the config glob.

\"}],\"files\":[\"index.html\"]}],\"files\":[],\"unreportedFiles\":[\"index.html\"],\"cleared\":0,\"count\":3,\"pageUrl\":\"/\",\"notes\":[],\"rolledBackFiles\":[\"index.html\"],\"rollbackFailures\":[],\"totalCount\":4,\"perPage\":{\"/\":3,\"/docs/guide\":1}}\n", + "stdout": "{\"applied\":[],\"failed\":[{\"id\":\"e1\",\"reason\":\"unreported_source_changes\",\"candidates\":[{\"file\":\"index.html\",\"loc\":\"\",\"line\":13,\"column\":7,\"status\":\"ok\",\"relativeFile\":\"index.html\",\"excerpt\":[{\"line\":10,\"text\":\" \"},{\"line\":11,\"text\":\" \"},{\"line\":12,\"text\":\"
\"},{\"line\":13,\"text\":\"

Oracle Fixture

\"},{\"line\":14,\"text\":\"

Minimal static page for oracle live-mode goldens.

\"},{\"line\":15,\"text\":\"
\"},{\"line\":16,\"text\":\"
One
\"}]},{\"kind\":\"text\",\"file\":\"index.html\",\"line\":13,\"needle\":\"Oracle Fixture\",\"excerpt\":\"

Oracle Fixture

\"},{\"kind\":\"class\",\"file\":\"index.html\",\"line\":7,\"needle\":\"hero-title\",\"excerpt\":\".hero-title { font-size: 2rem; }\"},{\"kind\":\"class\",\"file\":\"index.html\",\"line\":13,\"needle\":\"hero-title\",\"excerpt\":\"

Oracle Fixture

\"},{\"kind\":\"tag\",\"file\":\"public/docs/guide.html\",\"line\":9,\"needle\":\"Guide\"},{\"kind\":\"tag\",\"file\":\"index.html\",\"line\":13,\"needle\":\"Oracle Fixture\"}],\"files\":[\"index.html\"]},{\"id\":\"e2\",\"reason\":\"unreported_source_changes\",\"candidates\":[{\"kind\":\"text\",\"file\":\"index.html\",\"line\":14,\"needle\":\"Minimal static page for oracle live-mode goldens.\",\"excerpt\":\"

Minimal static page for oracle live-mode goldens.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":4,\"needle\":\"First card body copy.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":8,\"needle\":\"Second card body copy.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":12,\"needle\":\"Third card body copy.

\"},{\"kind\":\"tag\",\"file\":\"public/docs/guide.html\",\"line\":10,\"needle\":\"A second page covered by the config glob.

\"},{\"kind\":\"text\",\"file\":\"index.html\",\"line\":21,\"needle\":\"Nested content.\",\"excerpt\":\"

Nested content.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":4,\"needle\":\"First card body copy.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":8,\"needle\":\"Second card body copy.

\"},{\"kind\":\"tag\",\"file\":\"src/cards.html\",\"line\":12,\"needle\":\"Third card body copy.

\"},{\"kind\":\"tag\",\"file\":\"public/docs/guide.html\",\"line\":10,\"needle\":\"A second page covered by the config glob.

\"}],\"files\":[\"index.html\"]}],\"files\":[],\"cleared\":0,\"count\":3,\"pageUrl\":\"/\",\"unreportedFiles\":[\"index.html\"],\"notes\":[],\"rolledBackFiles\":[\"index.html\"],\"rollbackFailures\":[],\"totalCount\":4,\"perPage\":{\"/\":3,\"/docs/guide\":1}}\n", "stderr": "", "exit": 0, "signal": null,