From 81bdbbd08e0c423c177a68ccd245107f8334d986 Mon Sep 17 00:00:00 2001 From: jinhongkuan Date: Sun, 3 May 2026 00:10:54 -0700 Subject: [PATCH] fix(skill): capture refinements when prompt contradicts surfaced decision (#154) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds Step 5.6 to bicameral-preflight: when a user's prompt contradicts a decision the surfaced block just rendered, mechanically ingest the refinement with source=agent_session and call bicameral.resolve_collision to wire it to the seed. Three actions documented (supersede / keep_both / link_parent) so the agent can pick mechanically without asking. The user has already stated the refinement explicitly; PM ratifies the supersession in the inbox. Closes #154. Validation: tests/e2e/run_e2e_flows.py Flow 2a should flip FAIL → PASS without any other change. Co-Authored-By: Claude Opus 4.7 (1M context) --- skills/bicameral-preflight/SKILL.md | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/skills/bicameral-preflight/SKILL.md b/skills/bicameral-preflight/SKILL.md index bf6b6e5a..ff738b7a 100644 --- a/skills/bicameral-preflight/SKILL.md +++ b/skills/bicameral-preflight/SKILL.md @@ -382,6 +382,41 @@ A one-line forward narration helps: > from idempotency.ts. I'll flag the event.id deduplication question > for you to answer before I commit." +### 5.6 Capture refinements when the user's prompt contradicts a surfaced decision + +If any decision rendered in the surfaced block describes an approach the user's current request **replaces** (signals: "instead of", "actually we're switching to", "no more X", "I know X said Y but…", "X is out — we're going with Z"), this is a contradiction. Before doing any code work: + +1. **Ingest the refinement** with `source=agent_session`, scoped to the same `feature_group` as the contradicted decision: + +``` +bicameral.ingest(payload={ + "query": "", + "source": "agent_session", + "title": "", + "date": "", + "decisions": [{ "description": "" }] +}, feature_group="") +``` + +2. **Wire it to the seeded decision** via `bicameral.resolve_collision`: + +``` +bicameral.resolve_collision( + new_id="", + old_id="", + action="supersede" | "keep_both" | "link_parent" +) +``` + +Pick `action` mechanically: +- `supersede` — user fully replaces the old direction ("drag-drop is out, text-editor instead"). Writes a RELATE edge; old decision's status becomes `superseded`. +- `keep_both` — user adds a constraint or narrows the surface without invalidating the old ("also need X for accessibility" / "only on the conflict UI surface"). No edge; both remain. +- `link_parent` — the user's direction is a child decision under a higher-level (e.g. L1) parent; the contradicted decision is the parent. Writes `parent_decision_id`, no supersede edge, no status change. + +Mechanical — the user already stated the refinement. Do not ask. PM ratifies in the inbox. + +Narrate one line: "Captured refinement: '' — wired as of roadmap entry." + ### 6. Honor blocking hints (guided mode vs normal mode) The agent's `guided_mode` setting controls whether action hints are