diff --git a/docs/method/backlog/bad-code/PROCESS_generated-reference-sync-coupling.md b/docs/method/backlog/bad-code/PROCESS_generated-reference-sync-coupling.md new file mode 100644 index 0000000..8ef1fb3 --- /dev/null +++ b/docs/method/backlog/bad-code/PROCESS_generated-reference-sync-coupling.md @@ -0,0 +1,57 @@ +--- +title: "Generated Reference Sync Coupling" +legend: PROCESS +lane: bad-code +owner: "METHOD maintainers" +priority: medium +acceptance_criteria: + - "The note names the current bad behavior: refreshing generated reference docs like docs/MCP.md or docs/CLI.md currently requires `method sync ship`, which also mutates repo-level ship surfaces such as BEARING and CHANGELOG." + - "The proposal defines a bounded way to regenerate reference docs without touching ship-only artifacts that are supposed to move on merged main." + - "The contract keeps full `method sync ship` as the post-merge main maneuver rather than weakening that workflow." + - "The contract specifies regression expectations proving a scoped reference-doc refresh leaves BEARING and CHANGELOG unchanged on branch-local runs." +--- + +# Generated Reference Sync Coupling + +Refreshing generated reference docs during PR work currently requires +running `method sync ship`, even when the only intended output is a file +like `docs/MCP.md` or `docs/CLI.md`. That full ship maneuver also +touches repo-level artifacts such as `docs/BEARING.md` and +`CHANGELOG.md`, which are explicitly supposed to reflect merged `main` +state rather than branch-local review work. + +In practice, that means a small documentation regeneration step creates +unrelated branch noise that then has to be manually reverted. This is +the sort of coupling that wastes review time and makes agents less +confident about running the generator they actually need. + +## Proposed Contract + +- Current bad behavior: + regenerating generated reference docs on a feature branch should not + require mutating ship-only artifacts whose truth is tied to merged + `main`. +- Desired split: + keep `method sync ship` as the full post-merge ship maneuver, and add + a dedicated branch-local reference-doc refresh surface such as + `method sync refs`, backed by a TypeScript helper such as + `generateReferenceDocs()`, for regenerating reference docs without + mutating ship-only artifacts. +- Scoped outputs: + `method sync refs` should refresh the current generated reference + signposts exactly: `ARCHITECTURE.md`, `docs/CLI.md`, `docs/MCP.md`, + and `docs/GUIDE.md`. It must not edit ship-only artifacts such as + `docs/BEARING.md` or `CHANGELOG.md`. +- Safety: + `method sync refs` MUST print the list of refreshed targets, and + `generateReferenceDocs()` MUST return the same target list for MCP or + other callers. That surfaced scope must name the exact refreshed + targets (`ARCHITECTURE.md`, `docs/CLI.md`, `docs/MCP.md`, + `docs/GUIDE.md`) and exclude ship-only files such as + `docs/BEARING.md` and `CHANGELOG.md`. + +## Non-goals + +- Remove or weaken `method sync ship`. +- Make `BEARING` or `CHANGELOG` branch-local artifacts again. +- Solve every generated-document refresh problem in the same slice. diff --git a/docs/method/backlog/bad-code/PROCESS_typed-frontmatter-access.md b/docs/method/backlog/bad-code/PROCESS_typed-frontmatter-access.md new file mode 100644 index 0000000..963ce36 --- /dev/null +++ b/docs/method/backlog/bad-code/PROCESS_typed-frontmatter-access.md @@ -0,0 +1,72 @@ +--- +title: "Typed Frontmatter Access" +legend: PROCESS +lane: bad-code +owner: "METHOD maintainers" +priority: medium +acceptance_criteria: + - "The note names the current lossy behavior in src/frontmatter.ts: parsed YAML values are stringified, which discards arrays, booleans, and richer scalar distinctions." + - "The proposal defines a bounded typed-read surface for frontmatter without requiring every existing caller to migrate in one slice." + - "The contract keeps simple update behavior explicit, including what types are supported for round-trip writes." + - "Regression coverage proves fields such as acceptance_criteria arrays and boolean-like frontmatter survive typed reads without collapsing to plain strings." +--- + +# Typed Frontmatter Access + +METHOD's frontmatter parser currently converts every parsed YAML value +to `String(value)` before handing it to callers. That makes the read +surface simple, but it is also lossy: arrays, booleans, and richer YAML +values collapse into plain strings. + +That tradeoff is no longer cheap. Backlog items now carry structured +fields such as `acceptance_criteria`, and newer agent-first features +like backlog query or next-work want real metadata rather than +hand-reconstructed strings. + +## Current Bad Behavior + +- `acceptance_criteria` arrays lose structure on read. +- Boolean-like fields cannot be distinguished from arbitrary strings + once they pass through the current helper. +- Agents and higher-level features have to re-parse raw markdown or + avoid using the existing frontmatter API when they need structured + truth. + +## Proposed Contract + +- Add a typed read path: + keep the current string-oriented helpers for compatibility, but add a + typed frontmatter read surface that returns YAML-native values for the + bounded scalar and collection types METHOD actually uses. +- Supported first-cut types: + strings, booleans, numeric YAML scalars, and arrays of strings for + fields like `acceptance_criteria` or `source_files`. Quoted numeric + literals such as `"123"` remain strings per YAML parsing semantics, + and `null` does not become a supported typed value in the first cut. +- Compatibility: + existing callers that only need simple string metadata do not have to + migrate in the same slice. +- Typed writes: + add a typed write or merge helper that validates frontmatter updates + against the supported schema before persisting. A write that would + downgrade a typed field, such as replacing an array with a string, + MUST fail by default with an error that names the field, expected + shape, and attempted shape. A later explicit opt-in downgrade path may + exist, but it must be deliberate rather than silent. + Example error: + `Cannot downgrade typed field 'acceptance_criteria': expected array, attempted string`. +- Legacy helpers: + `updateFrontmatter()` remains available for plain string-only metadata + but MUST NOT be used for schema-backed typed fields such as + `acceptance_criteria`. +- Migration path: + automated writers such as the GitHub adapter's `pushItem()` must be + audited and moved to the typed write surface for any schema-backed + frontmatter before typed reads become the default read contract. + +## Non-goals + +- Support every obscure YAML feature. +- Migrate every existing frontmatter caller in one sweep. +- Turn frontmatter into a free-form database with no document-level + contract. diff --git a/docs/method/backlog/cool-ideas/PROCESS_backlog-query-surface.md b/docs/method/backlog/cool-ideas/PROCESS_backlog-query-surface.md new file mode 100644 index 0000000..c6c1d20 --- /dev/null +++ b/docs/method/backlog/cool-ideas/PROCESS_backlog-query-surface.md @@ -0,0 +1,84 @@ +--- +title: "Backlog Query Surface" +legend: PROCESS +lane: cool-ideas +owner: "METHOD maintainers" +priority: medium +acceptance_criteria: + - "The note defines both a CLI and MCP surface for enumerating backlog items as structured data." + - "The result schema includes repo path plus parsed frontmatter fields such as lane, legend, title, priority, and owner when present." + - "The surface supports bounded filtering or selection by lane, legend, and priority without requiring manual filesystem grep." + - "The proposal explicitly says higher-level features like `next-work` may build on this query surface but do not have to land in the same slice." +--- + +# Backlog Query Surface + +Agents and humans currently have to inspect `docs/method/backlog/` +directly or fall back to shell grep whenever they want a structured +answer to simple questions like "show all `bad-code` items", "what +`up-next` items exist?", or "which items have `priority: medium`?". + +That friction shows up again and again in coordination work. A native +backlog query surface would make METHOD better for both day-to-day human +triage and agent workflows that need real repo truth without re-parsing +markdown ad hoc. + +## Proposed Contract + +- Surface: + ship both a CLI query such as + `method backlog list [--lane ] [--legend ] [--priority ] [--json]` + and an MCP tool such as `method_backlog_query`. +- Shared output: + CLI `--json` and MCP return the same structured result object with + item arrays plus summary counts. +- Schema dependency: + implementing the richer item shape requires extending + `BacklogItem` in `src/domain.ts` with `title`, `priority`, `owner`, + and `has_acceptance_criteria`, and depends on typed frontmatter access + being available for those fields. +- Implementation phasing: + this surface may ship in two phases. Phase one may return only the + current `BacklogItem` identity fields (`path`, `stem`, `slug`, `lane`, + `legend`) without waiting for typed frontmatter. Phase two adds + `title`, `priority`, `owner`, and `has_acceptance_criteria` once + typed frontmatter and the `BacklogItem` extension land. If those + dependencies are already available, the full surface may ship in one + slice instead. +- Item shape: + each returned item includes existing backlog identity fields + (`path`, `stem`, `slug`, `lane`, `legend`) plus extended metadata + fields `title`, `priority`, `owner`, and + `has_acceptance_criteria: boolean` where that boolean is `true` when + the `acceptance_criteria` field exists in frontmatter and `false` + otherwise. +- Filtering: + the first slice should support bounded filtering by lane, legend, and + priority. Unfiltered output must stay bounded rather than dumping the + entire backlog at once: accept `limit` / `--limit` with default `50` + and maximum `100`, return at most that many items, and include + `truncated: boolean` plus optional `total_count` when additional + matches exist. +- Relationship to higher-level features: + surfaces like `method next` may build on this query result, but the + query surface should remain useful on its own as a plain inventory and + selection primitive. + +## Agent-First Rationale + +- Agents need: + deterministic structured backlog data without scraping markdown by + hand every turn. +- Humans benefit too: + the same command becomes a reliable triage tool for backlog grooming, + planning, and design-pull decisions. +- Explainability: + when higher-level recommendation features rank items, they should be + able to cite this query surface as the source of the underlying + backlog facts. + +## Non-goals + +- Auto-pull or reorder backlog items just because they match a filter. +- Replace human planning judgment with a raw listing command. +- Fold recommendation logic into the base query surface. diff --git a/docs/method/backlog/cool-ideas/PROCESS_design-doc-template-catalog.md b/docs/method/backlog/cool-ideas/PROCESS_design-doc-template-catalog.md new file mode 100644 index 0000000..562a6bd --- /dev/null +++ b/docs/method/backlog/cool-ideas/PROCESS_design-doc-template-catalog.md @@ -0,0 +1,183 @@ +--- +title: "Design Doc Template Catalog" +legend: PROCESS +lane: cool-ideas +owner: "METHOD maintainers" +priority: medium +acceptance_criteria: + - "The note defines a bounded catalog of at least four design-doc templates instead of a single universal scaffold." + - "Each template states when it should be used plus the sections or prompts it must contain." + - "The proposal preserves the current shared core sections and separates them from template-specific additions." + - "The note explains how `method pull` or a future scaffolder could select a template without requiring implementation in the same slice." +--- + +# Design Doc Template Catalog + +METHOD's current design docs share a strong baseline scaffold, but the +same outline is not equally informative for every slice. A feature +delivery cycle, a contract-surface change, a cleanup refactor, a +docs-policy change, and an exploratory spike do not all need the same +questions emphasized in the same order. + +That mismatch produces placeholder sections, strained prose, and design +docs that technically satisfy the scaffold while still being weaker than +they should be. A small template catalog would make the initial design +doc shape fit the work instead of forcing every slice through one +universal outline. + +## Proposed Contract + +- Enforcement level: + each template's "Must contain" list defines scaffold prompts and + review expectations, not an immediate hard validator. A design doc + using `contract-surface` or another template SHOULD address those + topics, but authors may merge or omit headings when reviewers accept + the rationale. A later validation slice may choose to turn those + prompts into explicit heading checks once template metadata is stable. +- Shared core across all templates: + all templates keep the current frontmatter contract + (`title`, `legend`, `cycle`, `source_backlog`) plus the shared + sections `## Sponsors`, `## Hill`, `## Playback Questions`, + `## Accessibility and Assistive Reading`, + `## Localization and Directionality`, + `## Agent Inspectability and Explainability`, `## Non-goals`, and + `## Backlog Context`. +- Template identifier: + future scaffolds may add an explicit template marker such as + `template: default-change | contract-surface | refactor-cleanup | docs-policy | spike`. + Historical docs do not need immediate backfill. + +## Template Catalog + +### `default-change` + +- Use when: + the slice introduces or changes user-visible behavior, a workflow, or + a meaningful internal capability with shipped outcomes. +- Must contain: + the intended behavior or contract, the main happy path, expected + failure or edge cases, and a verification plan that proves the slice + actually landed. +- Recommended scaffold sections: + `## Intended Behavior`, + `## Happy Path`, + `## Edge Cases and Failure Modes`, + `## Verification Plan`. + Authors may merge or rename these sections when reviewers accept the + rationale, but the scaffold should present them as the default + structure. +- Optional emphasis: + examples, sequence diagrams, rollout notes, or migration notes when + the change is user-visible. + +### `contract-surface` + +- Use when: + the slice is mainly about a bounded surface such as CLI flags, MCP + tools, JSON shapes, exit codes, schemas, or generated reference docs. +- Must contain: + an explicit surface inventory, required input and output shapes, + compatibility expectations, failure modes, and concrete examples of + the resulting contract. +- Recommended scaffold sections: + `## Surface Inventory`, + `## Input and Output Contract`, + `## Compatibility Expectations`, + `## Failure Modes`, + `## Examples`. +- Optional emphasis: + deprecation notes, migration windows, or parity requirements across + multiple surfaces such as CLI and MCP. + +### `refactor-cleanup` + +- Use when: + the main value is structural cleanup, extraction, decomposition, or + removing drift without intentionally changing external behavior. +- Must contain: + the current pain or maintenance risk, the invariants that must remain + true after the refactor, the planned cut boundaries, and the + regression checks that prove the cleanup did not create behavioral + drift. +- Recommended scaffold sections: + `## Current Pain`, + `## Invariants`, + `## Cut Boundaries`, + `## Regression Checks`. +- Optional emphasis: + before/after module maps, ownership boundaries, or dependency + simplification notes. + +### `docs-policy` + +- Use when: + the slice primarily changes README content, process rules, signposts, + wording policy, or repo-truth coordination docs. +- Must contain: + the affected audiences, the truth sources that must stay aligned, the + semantic wording changes being made, and any regeneration or sync + surfaces that must remain consistent after the edit. +- Recommended scaffold sections: + `## Audience`, + `## Truth Sources`, + `## Wording Changes`, + `## Regeneration and Sync Impact`. +- Optional emphasis: + before/after wording examples, cross-reference tables, or explicit + reader journeys. + +### `spike` + +- Use when: + the slice is exploratory and the main output is a recommendation, + evidence bundle, or narrowed decision rather than shipped production + behavior. +- Must contain: + the question being investigated, the working hypothesis, the evidence + collection plan, the exit criteria for the spike, and the expected + handoff into a later implementation or backlog decision. +- Recommended scaffold sections: + `## Question`, + `## Working Hypothesis`, + `## Evidence Plan`, + `## Exit Criteria`, + `## Expected Handoff`. +- Optional emphasis: + rejected alternatives, benchmark notes, or criteria that would cancel + the follow-on implementation entirely. + +## Selection Rules + +- Default selection: + this note does not claim that today's `renderDesignDoc()` scaffold + already satisfies the `default-change` prompts. When template support + lands, the no-template path must either update `renderDesignDoc()` to + emit prompts for intended behavior or contract, main happy path, + expected failures or edge cases, and verification plan, or introduce + a distinct legacy template for the current scaffold instead of + pretending it is already `default-change`. +- Explicit selection: + a future `method pull --template ` or interactive scaffolder can + choose a more specific template when the backlog item clearly fits a + template type. +- Authoring guidance: + the selector UX should offer short one-line descriptions for each + template so humans and agents can pick one without reading a long + manual during pull. + +## Validation Boundary + +- First step: + template support should initially be a scaffold and authoring aid, + not an immediate hard validator. +- Follow-on validation: + once the catalog settles, a later slice can decide whether heading or + frontmatter checks belong in a markdown contract gate or generated + scaffold test. + +## Non-goals + +- Generate full design-doc prose automatically. +- Force every historical design doc to declare a template immediately. +- Create a large taxonomy of narrow templates that is harder to choose + from than the current scaffold. diff --git a/docs/method/backlog/cool-ideas/PROCESS_next-work-menu.md b/docs/method/backlog/cool-ideas/PROCESS_next-work-menu.md new file mode 100644 index 0000000..376b406 --- /dev/null +++ b/docs/method/backlog/cool-ideas/PROCESS_next-work-menu.md @@ -0,0 +1,164 @@ +--- +title: "Next Work Menu" +legend: PROCESS +lane: cool-ideas +owner: "METHOD maintainers" +priority: medium +acceptance_criteria: + - "The note defines both a CLI and MCP surface for asking what to work on next." + - "The proposed result is a bounded menu of recommendations with supporting stats, not a single imperative answer." + - "The recommendation logic names the repo-truth inputs it may consider, including backlog lanes, backlog frontmatter, and BEARING." + - "The contract distinguishes evidence-backed ranking signals from optional heuristic weighting so the surface stays inspectable." +--- + +# Next Work Menu + +METHOD can describe current state through backlog lanes, frontmatter, +status output, and signposts like `BEARING`, but it still makes humans +and agents manually synthesize that data into "what should we work on +next?" every time. That synthesis is exactly the sort of bounded +coordination question the repo should be able to answer for itself. + +The right answer is not a single authoritarian recommendation. It is a +small menu that says what looks strong, why it looks strong, what the +queue currently contains, and what evidence supported the ranking. + +## Proposed Contract + +- Surface: + ship both `method next [--json] [--limit ]` and an MCP tool such + as `method_next_work`. CLI default output is a short ranked menu for + humans; `--json` and MCP return the same structured result object. +- Result goal: + answer "what looks like the next sensible work items?" with a menu of + candidates and supporting repo stats, not a single `do_this_now` + directive. +- Bounded default: + the default output should show a small menu such as the top `3` + recommendations plus repo summary stats. `--limit` may widen the menu + within a bounded maximum. + +## Implementation Prerequisites + +- Typed frontmatter dependency: + the surface depends on typed frontmatter access for fields such as + `acceptance_criteria`, `priority`, and `owner`. It should either wait + for `PROCESS_typed-frontmatter-access` to land first or include the + required typed-read support in the same implementation slice. +- Backlog item schema extension: + the result shape assumes backlog items can expose `priority`, `owner`, + and `has_acceptance_criteria` in addition to the current + `BacklogItem` identity fields, so the slice must extend that schema or + provide an equivalent typed query object. +- Backlog query reuse: + `PROCESS_backlog-query-surface` is reusable but not mandatory. The + next-work slice may either build on that shared query surface or ship + equivalent backlog enumeration logic in the same bounded change. + +## Repo-Truth Inputs + +- Backlog lanes: + inspect the actual files under `docs/method/backlog/` and respect the + lane ordering and semantics already present in the repo, especially + `up-next`, `asap`, `bad-code`, `inbox`, and `cool-ideas`. +- Backlog frontmatter: + parse frontmatter such as `legend`, `lane`, `priority`, `owner`, and + `acceptance_criteria` so the recommendations are grounded in declared + metadata rather than filename heuristics alone. +- `BEARING`: + treat [BEARING.md](../../../BEARING.md) as a + directional signal, not an override. If `BEARING` names a current + priority or describes repo discomfort, that should influence the menu + and be cited as evidence when it materially changes ranking. +- Current status: + incorporate repo-visible counts or conditions already surfaced by + `method status`, such as whether `up-next` is empty, whether `asap` + contains items, how many `bad-code` items remain, and whether an + active cycle already exists. +- Optional future signals: + design or retro recency, legend coverage gaps, or graveyard patterns + may later become weighted inputs, but they are not required for the + first slice. + +## Output Shape + +- Shared result fields: + `generated_at`, + `summary: { active_cycle_count, lane_counts, bearing_priority, bearing_concerns }`, + `recommendations: Array`, + `selection_notes: string[]`. +- Recommendation shape: + each recommendation includes at minimum + `path`, + `title`, + `lane`, + `priority`, + `why_now: string[]`, + `signals: Array<{ type: string, value: string | number | boolean, source: string }>`, + and `score_band: "highest" | "strong" | "worth-considering"`. +- Score band rules: + `score_band` is a relative ranking within the returned menu, not an + absolute score. The menu MUST be sorted by score band in the order + `highest`, `strong`, `worth-considering`, and then by lane precedence + inside each band. Multiple recommendations may share a band. A typical + menu gives the top `1-2` items `highest`, the next `2-3` items + `strong`, and the rest `worth-considering`, but those bands remain + relative to the current menu rather than fixed numeric thresholds. +- CLI rendering: + print a short summary block first, then a numbered menu where each + item shows the backlog file, lane, priority, and 2-4 concise `why + now` bullets. Keep the tone advisory rather than imperative. + +## Ranking Rules + +- Deterministic first-pass ordering: + when `BEARING` does not explicitly elevate another lane, lane + precedence is `asap`, then `up-next`, then `bad-code`, then `inbox`, + then `cool-ideas`. If a lane is empty, the next non-empty lane + provides candidates. If `BEARING` materially changes that order, the + output must cite the exact bearing evidence that justified the + override. +- BEARING detection: + the first slice should stay deterministic. It MUST populate + `signals` entries with `type: "bearing_mention"` only by literal + substring matching of backlog item stems against the `## Where are we + going?` and `## What feels wrong?` sections of `docs/BEARING.md`. It + MUST NOT use LLM inference, fuzzy matching, or hidden manual + overrides. +- BEARING override threshold: + a BEARING signal counts as materially changing ranking only when it + moves an item above at least one item from a higher-precedence lane or + moves the item into the top `3` recommendations. When that happens, + the recommendation must include the matching `bearing_mention` signal + plus the quoted source section name. +- Evidence before heuristics: + every recommendation must cite the concrete repo facts that pushed it + upward, such as `lane=up-next`, `priority=medium`, `BEARING current + priority mentions legend coverage`, or `bad-code count > 0`. +- No fake precision: + avoid opaque numeric scoring that implies certainty the repo cannot + support. If a score exists internally, the user-facing contract should + expose it only as a coarse band plus explicit signals. +- Explainable divergence: + if `BEARING` pushes a `cool-ideas` item above a `bad-code` item, the + output must say so clearly instead of silently overriding lane order. + +## Failure Modes + +- Empty backlog: + return an explicit empty-menu result with summary stats and a note + that no candidate backlog items were found. +- Active cycle present: + if a cycle is already open, the surface may still show the menu but + must note that new pull decisions should usually wait until the active + cycle is resolved. +- Missing or malformed frontmatter: + do not crash; skip malformed items or include a warning note in + `selection_notes`, depending on whether partial parsing is safe. + +## Non-goals + +- Auto-pull or auto-assign work from the returned menu. +- Replace human judgment about strategy or timing. +- Pretend the repo can infer a single objectively correct next task from + incomplete signals. diff --git a/docs/method/backlog/cool-ideas/PROCESS_review-closeout-helper.md b/docs/method/backlog/cool-ideas/PROCESS_review-closeout-helper.md new file mode 100644 index 0000000..9592a0e --- /dev/null +++ b/docs/method/backlog/cool-ideas/PROCESS_review-closeout-helper.md @@ -0,0 +1,121 @@ +--- +title: "Review Closeout Helper" +legend: PROCESS +lane: cool-ideas +owner: "METHOD maintainers" +priority: medium +acceptance_criteria: + - "The note defines a bounded CLI and/or MCP surface for closing out a PR review round." + - "The proposal distinguishes read-only inspection from write actions such as replying to comments or resolving threads." + - "The output contract includes unresolved-thread inventory plus a machine-readable summary of which comments were addressed by which commit." + - "The helper is explicitly scoped to review-round coordination and does not replace human judgment about whether a comment should be fixed, rebutted, or left open." +--- + +# Review Closeout Helper + +PR review work in METHOD now has better visibility through review-state, +but the actual closeout maneuver is still mostly manual: inspect +unresolved threads, map fixes to comments, reply with SHA-backed notes, +resolve threads, and post a summary comment that explains what landed in +the round. + +That workflow is repetitive enough that both humans and agents keep +reconstructing it from `gh` commands and handwritten checklists. The +repo has enough structure now to support a first-class helper for that +coordination move. + +## Proposed Contract + +- Surface: + add a bounded helper such as + `method review closeout [--pr |--current-branch] [--json]` + plus an MCP tool such as `method_review_closeout`. +- Read-first design: + default behavior is read-only and returns a closeout plan or summary. + Replying to comments, resolving threads, or posting a rollup comment + should be explicit write actions, not hidden side effects of a read. +- Write surface: + write behavior must stay explicit. The CLI should require named write + actions such as `--reply`, `--resolve`, and `--post-summary`, plus an + overall `--apply` switch. MCP should expose the same mutations as + explicit action fields rather than implicit side effects of a read. +- Write semantics: + write actions operate per thread in declared order, with summary + comment posting last after reply or resolve work succeeds. CLI write + mode must support `--dry-run` and require confirmation through + `--yes` before mutating GitHub state. Exit code `0` means all + requested mutations applied or no mutations were needed, with stdout + or JSON explicitly noting no-op status. Exit code `2` means partial + write failure: successful writes remain in place, failed thread ids + are reported individually, and no automatic rollback is attempted. + Exit code `3` means validation or mapping failed before any write + happened. Exit code `4` means auth or permission failed before writes + began; if auth or permission fails mid-batch after some writes + succeeded, treat the run as partial failure (`2`). `--json` keeps the + same numeric exit codes and must include per-thread result objects and + machine-readable error codes. +- Idempotency: + retrying a closeout should be safe. Re-resolving an already resolved + thread or reusing an existing SHA-backed reply should be treated as a + no-op, and duplicate rollup comments should require explicit operator + confirmation rather than being posted silently. +- Shared result: + the structured result should include + `pr_number`, + `pr_url`, + `unresolved_threads`, + `addressed_threads`, + `pending_threads`, + and a `round_summary` array that maps thread or comment identifiers to + an outcome like `fixed`, `explained`, `left-open`, or `not-applicable`. +- Outcome rules: + `round_summary[*].outcome` should be determined by explicit operator + input first, then by helper inference if the operator did not set it. + `fixed` requires at least one mapped commit SHA and target comment or + thread id, `explained` requires a posted explanation or prepared reply, + `left-open` means the thread remains unresolved or was intentionally + deferred, and `not-applicable` requires a short rationale. Each + summary entry should record actor, timestamp, and + `confidence: "confirmed" | "inferred-high" | "inferred-low" | "unknown"` + so later automation can audit how the outcome was chosen. Operator-set + outcomes use `confirmed`; helper-inferred outcomes use + `inferred-high`, `inferred-low`, or `unknown`. Audit tooling should + flag `inferred-low` and `unknown` for human review. + +## Coordination Features + +- Thread inventory: + enumerate unresolved review threads with path, line, author, and + comment URL so a human or agent can see the review round as a bounded + worklist. +- Commit mapping: + use explicit mapping supplied by the operator or agent, not silent + heuristic guessing, to associate one or more commit SHAs with each + addressed thread in the closeout summary. Read mode may suggest + possible mappings, but write mode should only post mappings that were + explicitly confirmed. When no confident mapping exists, the thread + remains unmapped and stays in the pending set instead of inventing a + commit relationship. +- Summary comment generation: + generate a concise markdown table or bullet summary suitable for a PR + comment, but keep actual posting as an explicit write step. +- Resolution staging: + support a dry-run or staged mode that shows which threads would be + replied to or resolved before any remote mutation happens. + +## Relationship To Existing Work + +- Distinct from review-state: + `review-state` answers whether a PR is blocked or merge-ready. + Closeout answers how to finish a review round and record what changed. +- Distinct from comment-sync identity: + stable remote comment identity is still useful plumbing, but the + closeout helper is a workflow surface rather than a low-level sync + mechanism. + +## Non-goals + +- Auto-fix review comments without a human or agent deciding they are + valid. +- Auto-merge the PR once all threads are resolved. +- Hide GitHub write actions behind a supposedly read-only command.