# Open-question resolution engine

> Walks the Section 20 rows of an analysis v3 document one at a time, proposing source-labeled answer candidates and merging the chosen answer into the proper body section. Two mount points share this file: `/multi-agent:analysis-resolve` (standalone, for a document produced earlier) and pipeline Phase 4 in analysis mode. In the full pipeline the same walk runs at the end of Phase 2, before the Plan Approval Gate, because Phase 4 comes after development and a question answered then is answered too late.
>
> The 31 inherited decisions are in `locked.md`; the ones below are this engine's own. Core invariant: the document is authoritative and forward-looking. The engine never invents an answer - when no source produces a credible candidate the only options are Defer and Other.

## New Locked decisions (this command)

1. **One question per `AskUserQuestion` call.** Never batch Section 20 rows. Sequential resolution keeps each decision explicit and traceable.
2. **Up to 3 source-labeled candidates plus Defer = 4 options max.** Each candidate's `description` carries its source label: `From evidence - <doc section / citation>`, `From repo - <file:line>`, `AI reasoned - <one-line rationale>`. The auto-provided Other accepts free text and stop tokens.
3. **Three sources, never blended.**
   - **From evidence**: the answer is already derivable from the doc's own sections and their citations (Sections 5, 6, 9, 13, 21) or from cached `state.analysisSpec.evidence.*` when the session still holds it. Cite the section or evidence bucket.
   - **From repo**: the batched Phase 1 repo lookup (one Explore subagent) returned an answer with a `file:line` citation.
   - **AI reasoned**: contextual reasoning grounded in the loaded doc (feature scope, platform, surrounding sections). Requires a one-line rationale; skip if the basis is no stronger than guessing.
4. **Never invent.** If no source produces a credible candidate, offer only Defer and Other.
5. **Stop tokens** (case-insensitive, typed into Other): `stop`, `pause`, `dur`, `kes`. Halt immediately, save current state, jump to the Finalize phase.
6. **Follow-up questions surface immediately.** If an answer creates a new question ("use a new endpoint" leads to "endpoint name?"), insert a new `Acik / Open` row into Section 20 directly after the current row and process it next, not at queue end.
7. **Save after every answer.** Each resolution writes the full doc to disk atomically before the next question. Interruption loses nothing.
8. **Status enum is fixed:** `Acik / Open`, `Girdi bekleniyor / Pending input`, `Karar verildi / Decided` (render the side matching the doc's `language`). Only the Status cell and a trailing `[Cozum: <value> - <source>]` / `[Resolved: <value> - <source>]` fragment on the question cell are edited in Section 20; Owner is never synthesized or changed.
9. **Sibling propagation is explicit, never silent.** Per-platform sibling files (front-matter `siblings:`) are touched only in the Finalize phase, only for rows whose question text matches verbatim, and only after the user approves one summary question. Platform-specific rows (convention fallbacks, per-platform reuse rows) never propagate.
10. **`evidence_digest` stays untouched.** Resolving questions does not change the evidence inputs; the front-matter digest and `generated` timestamp are preserved. Only the Section 23 changelog records the revision.


### Phase 1 - Parse and batched repo lookup

1. Read the doc end-to-end. Capture:
   - Front-matter: `feature`, `platform`, `language`, `mode`, `siblings[]`.
   - The Risks and Open Questions table: ordered rows `{index, question, owner, status}`.
   - Context for reasoning: Summary, Goals, API Contracts, Architecture Plan (concept table + footnotes), Files to Add, References.
2. Filter to rows whose status is `Acik / Open` or `Girdi bekleniyor / Pending input`. If zero remain, report `Section 20 has no open rows.` and stop.
3. **Classify each row** by its auto-population fingerprint:

   | Class | Fingerprint (from analysis.md auto-population rules) | Extra candidate source |
   |---|---|---|
   | `convention-fallback` | row text contains `convention fallback applied` or cites `conventions-defaults.md:C<n>-` (Locked 23) | re-run `~/.claude/lib/extract-conventions.sh <repo> <platform>` for that one field; offer the default vs the fresh extraction |
   | `reuse-vs-new` | row text matches `existing <X> candidate found; reuse or document why a new one is needed` (Locked 11) | repo lookup reads the candidate `file:line` and summarizes its fit |
   | `citation-tbd` | row originated from a `[label TBD - see Open Questions]` downgrade (Locked 3) | repo localization keys / Figma evidence already cited elsewhere in the doc |
   | `legacy-decision` | row phrased `current code does X; should the new feature keep, change, or drop this?` (Locked 4) | repo lookup confirms current behavior with `file:line` |
   | `standards-conflict` | row cites a binding standards source (Locked 8) | quote the binding section verbatim from References |
   | `design-gap` | row needs new Figma/design information (tier-3 forced questions, missing variants per Locked 12/19) | NONE - Locked 30; offer only Defer + the re-run recommendation |
   | `generic` | anything else | all three standard sources |

4. **Batched repo lookup** (single Explore subagent, one call regardless of row count; skip if every row classified `design-gap`):
   > "For the feature `<feature>` on platform `<platform>`, answer the following questions from the repo at `<repo-root>`. Return one entry per question ID with either an answer plus `file:line` citation OR `not-found`. Scope reading to paths the questions name plus their direct dependencies; do not roam, do not propose changes.
   > Q1: <row 1 text> ..."
5. Cache per-question answers keyed by row index. These feed the `From repo` candidate in Phase 2.

### Phase 2 - Sequential resolution loop

For each open row in source order:

1. **Generate candidates** per the row's class (max 3). Skip any source with no credible output. For `design-gap` rows, skip candidate generation entirely.
2. **Ask** (interactive mode) - single AskUserQuestion:
   - `header`: the target section anchor, max 12 chars (e.g. `S13 Arch`, `S9 API`, `S10 L10n`, `Conventions`)
   - `question`: the row text verbatim, prefixed `[R-<index>]` (follows the doc, so it may be Turkish; that is correct here - the row IS the doc content)
   - `options`: up to 3 candidates + `Defer - keep open`. Candidate descriptions carry the source label per New Locked 2.
   - Autonomous mode: pick the single credible candidate if exactly one source produced one; otherwise Defer. Log each auto-decision as one line.
3. **Apply**:
   - **Concrete answer**: locate the target body section from the row's anchor or content (convention rows target the Architecture Plan concept table; reuse rows target Files to Add + Architecture Plan; API rows target API Contracts; etc.).
     - `From evidence` / `AI reasoned` / user Other: write as primary content in the doc's `language`, ASCII punctuation, citations preserved.
     - `From repo` describing current behavior: write as `> Legacy reference: <text> (file:line)` under the target entry (Locked 4). A repo answer that the user adopts as the forward decision is primary content WITH its `file:line` citation.
     - `convention-fallback`: update the convention cell, rewrite its footnote to `^[user-override: resolved via analysis-resolve <YYYY-MM-DD>]` (Locked 24).
     - Update the Section 20 row: Status to `Karar verildi / Decided`, append ` [Cozum: <one-line> - <source>]` (tr) / ` [Resolved: <one-line> - <source>]` (en) to the question cell. Do not delete the row; the table stays a decision log.
   - **Defer**: Status to `Girdi bekleniyor / Pending input`. Row otherwise untouched.
   - **Stop token**: save, jump to Phase 3.
   - **Follow-up**: insert the new `Acik / Open` row right after the current one (New Locked 6) and process it next.
4. **Save the full doc to disk** before the next iteration (New Locked 7).

### Phase 3 - Finalize

1. **Sibling propagation** (only if front-matter `siblings[]` is non-empty AND at least one resolved row's question text appears verbatim with an open status in a sibling file on disk): one AskUserQuestion, `header: "Siblings"`, question `<localized: "N resolved rows also appear open in sibling file(s) <list>. Apply the same resolutions there?">`, options `Apply to all listed` / `Skip siblings`. On apply: repeat the Phase 2 apply step per matching row per sibling, then give each touched sibling its own changelog row. Platform-specific classes (`convention-fallback`, `reuse-vs-new`) are excluded from matching (New Locked 9).
2. **Changelog**: append one row to the Changelog section of every touched file: next version (integer scheme `v1 -> v2`; dotted scheme bumps the minor), today's date, author `analysis-resolve`, change `Resolved <N> of <M> Section 20 rows; <K> deferred`.
3. **Punctuation gate**: run the Locked 7 verification grep over every touched file; fix any hit before reporting.
4. **Report** (in `outputLanguage`, max 12 lines): doc path(s) + new version, counts (resolved / deferred / follow-ups created / still open), `design-gap` rows that need a `/multi-agent:analysis` re-run (list inputs to re-supply), and - if open rows remain - a reminder that re-running this command resumes where it left off (state is the doc itself; no separate state file).

**Stop. No commit, no branch, no dispatch.** The user reviews the diff and commits manually (Locked 6).
