Skip to content

Release feature-runner and pr-review#32

Merged
orioltf merged 124 commits into
mainfrom
develop
May 14, 2026
Merged

Release feature-runner and pr-review#32
orioltf merged 124 commits into
mainfrom
develop

Conversation

@orioltf
Copy link
Copy Markdown
Member

@orioltf orioltf commented May 14, 2026

No description provided.

orioltf and others added 30 commits May 8, 2026 20:44
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ion issues

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

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

Records the decision to refactor review-pr.md into a thin orchestrator
plus three focused agents (ado-fetcher, re-review-coordinator, ado-writer),
and defines the three operating modes and orchestration agent terms in
CONTEXT.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the needs-triage PRD for refactoring review-pr.md into a thin
orchestrator plus ADO Fetcher, Re-review Coordinator, and ADO Writer
agents, covering the pre-PR mode, compact sub-agent output, and
deferred toolkit normalisation decisions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds agent brief and updates status to ready-for-agent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Breaks the orchestrator split PRD into 7 independently-grabbable
vertical slices: ADO Fetcher, ADO Writer, and Re-review Coordinator
agents (parallelizable), thin orchestrator refactor, pre-PR mode,
compact sub-agent output guidance, and version bump.

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

Adds agent briefs and updates status on all seven issues.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Issues in pr-review-rereview, pr-review-doc-context-enrichment,
pr-review-doc-context-spawn-reliability, and inbox-collision-check
were completed through docs/plans/ specs but never advanced past
resolved in the issue tracker.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Parallel terms to Spec / Spec Runner, grounded during the
feature-runner grilling session.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three ADRs capturing decisions reached during the Feature Runner PRD
grilling session:

- 0027: context bundle injected into every /tdd sub-agent invocation,
  with domain-scoped ADR and CONTEXT.md selection
- 0028: ## Blocked by as canonical sequencing signal; topological order
  over numerical filename order; halt on conflict
- 0029: AFK invocation via Agent tool; acceptance criteria replace
  /tdd's interactive planning phase; LOOP_COMPLETE as stop signal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Merges five decisions from the /grill-with-docs session into the
Feature Runner PRD:

- Context bundle: /tdd sub-agents receive issue + PRD + siblings +
  CONTEXT.md + scoped ADRs + recent commits, not just the issue file
- ADR scoping: plugin ADRs for plugin features, root ADRs for tooling;
  inferred from PRD path references
- AFK invocation: Agent tool is non-interactive; acceptance criteria
  replace /tdd's planning phase
- Sequencing: ## Blocked by is the canonical dependency signal;
  topological order over numerical filename order; halt on conflict
- Parallelism: serialisation is an explicit decision, not an omission;
  LOOP_COMPLETE named as the stop signal for /loop composability

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Split Phase 7 in development-workflow.md into Spec Runner and Feature
Runner paths — the two runners are not interchangeable and the previous
single-command entry was misleading. Adds /implement-feature, /loop
composability, and LOOP_COMPLETE to the quick reference table.

Adds ai-development.md: a narrative deep guide covering the mental
model behind the workflow — two-runner architecture, pipeline quality
gates, the correct-but-wrong failure mode, context bundle design, AFK
trust chain, ## Blocked by sequencing, overnight draining, and
CONTEXT.md/ADR maintenance. Complements the quick-reference workflow
doc with the reasoning behind the decisions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Breaks the Feature Runner PRD into 8 vertical slices, all triaged to
ready-for-agent:

  01 — skill scaffold and minimal execution loop (tracer bullet)
  02 — failure handling (blocks on 01)
  03 — PR creation and worktree cleanup (blocks on 02)
  04 — progress reporting (blocks on 01)
  05 — full context bundle (blocks on 01)
  06 — dependency graph and topological ordering (blocks on 01)
  07 — auto-selection and LOOP_COMPLETE (blocks on 01)
  08 — docs/agents/feature-runner.md (blocks on 03–07)

## Blocked by is the canonical dependency signal per ADR-0028.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Creates .claude/skills/implement-feature/SKILL.md — the tracer-bullet
happy path for the Feature Runner: worktree creation, issue filtering
by status, sequential /tdd sub-agent invocation, and resolved marking.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… (issue 02)

On /tdd sub-agent failure: appends a failure note under ## Comments,
leaves the issue at ready-for-agent, stops the runner, and surfaces a
clear message to the user. The worktree is left in place for inspection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After all issues resolve, the skill pushes the branch, opens a PR
targeting develop via gh CLI (title from PRD frontmatter, body listing
resolved issues), then removes the worktree. Failure path from 02
prevents this step from running on a broken feature.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ll (issue 04)

Before each /tdd invocation the runner outputs "Implementing issue N of M:
<title>". M is frozen at run start from the ready-for-agent queue count,
so the progress line is accurate regardless of failures or mid-run state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…c (issue 05)

Step 1 now detects plugin vs. repo scope from PRD path references and
gathers CONTEXT.md, scoped ADRs, and last-5 commits once before the
loop. Step 4 reads sibling issues at invocation time and assembles the
full six-part context bundle for each /tdd sub-agent call.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…dering (issue 06)

Step 3 now reads all NN-*.md files (including resolved/closed), parses
## Blocked by edges, checks for conflicts where a blocker has a higher
NN than the issue it blocks, and derives a topological execution order.
Resolved/closed issues satisfy dependencies but are not re-executed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nal (issue 07)

Step 0 handles the no-argument path: scans docs/issues/ for features
where every NN-*.md is ready-for-agent, selects the first alphabetically,
and runs it. Emits LOOP_COMPLETE on an empty queue so /loop terminates
cleanly. Partial features (mixed statuses) are skipped.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ument (issue 08)

Covers the full lifecycle (selection → worktree → tdd loop → PR → closed),
the six-part context bundle with ADR scoping rationale, ## Blocked by
ordering and conflict behaviour, failure handling, and the historical
cleanup convention for Spec Runner overlap. No duplication of issue-tracker.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Grilled and rejected. Both failure modes that could trigger a retry are
not worth automating: Agent tool errors have unpredictable resolution
windows, and sub-agent failures mean /tdd already exhausted its own
loop — both call for human review, not an automated retry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds two ready-for-agent issues identified during a post-implementation
skill review and grilling session: extract verbatim output strings to a
references file (10), and add a Quick start section to SKILL.md (11).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…es file (issue 10)

Creates references/runner-output-formats.md with all five canonical
strings (progress line, conflict error, failure note, PR body, LOOP_COMPLETE).
SKILL.md references the file by name, dropping from 213 to 171 lines.
Procedural logic is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds three annotated invocation patterns (named run, auto-select,
overnight loop) between the opening paragraph and ## Steps, so users
can orient themselves before reading the full procedure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two ready-for-agent issues identified after issues 10–11 were resolved:
add heredoc wrapping note to the PR body template in references (12),
and extract the /tdd prompt template to its own references file (13).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…issue 12)

The PR body template section in runner-output-formats.md now shows the
complete gh pr create command with heredoc wrapper so agents know how
to pass the multiline body. No changes to SKILL.md or other sections.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…file (issue 13)

Creates references/tdd-prompt-template.md with the full AFK prompt.
Step 4 of SKILL.md replaces the 23-line inline block with a one-sentence
reference. SKILL.md drops from 177 to 151 lines.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
orioltf and others added 29 commits May 13, 2026 19:03
PR #30 had `## ⚠ Notices` in PRD A's Notice-flow prose but `## Notices`
in the slice files — Copilot flagged the inconsistency on PRD A:49.

Reconcile to the bare heading. Justification: a mixed `info` + `warning`
Notices list would force a single heading emoji to misrepresent one
tier; per-item emoji prefixes (`ℹ️` for `info`, `⚠` for `warning`)
correctly distinguish them without polluting the heading.

Add an explicit doctrine sentence to PRD A's "Notice flow" subsection so
future contributors don't relitigate the choice.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pilot K2)

Prettier had collapsed the whitespace around several inline-code fragments
in the End-to-end demoable paragraph of B5 (lines 26), making the example
unreadable. Rewrite the paragraph with prose spacing instead of inline-code
adjacency, so the example renders cleanly in both raw markdown and GitHub.

Copilot caught this on PR #30 line 26 of the slice file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…opilot K3)

The earlier wording read as if `git remote show origin HEAD branch` were a
single command invocation (an invalid one — `git remote show` takes a
remote name only). Reword to make clear we parse the `HEAD branch:` line
out of `git remote show origin`'s output and pass the parsed branch name
into the helper via a new `remoteHeadBranch` argument. Step A's prose
mirrors the helper signature.

Copilot caught this on PR #30 line 19 of the slice file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Copilot K4)

PRD B's "Test-scope choice" section stated MODIFY helpers receive no new
unit tests, but slices B2/B3/B4/B6 each explicitly require 2–3 new test
cases pinning the new behaviour branches. Copilot flagged this real
contradiction on PR #30 line 81.

Reconcile by clarifying the doctrine: the user's "NEW deep modules only"
answer during grilling was about not writing whole new test suites for
MODIFY helpers; the minimal branch-verification cases each slice requires
are necessary to confirm the new behaviour landed and do not constitute
new suites. Update Test-scope choice + Modules under test sections and
two Out of Scope bullets in PRD B and its Agent Brief.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t K3 follow-up)

The K3 commit (3a63d78) only fixed slice 06's description of
detect-default-branch.mjs. PRD B itself carried four stale references to
the same helper that contradicted the slice:

- Implementation Decisions: helper signature missing `remoteHeadBranch`
  parameter; fallback chain described as `git remote show origin HEAD`
  (the exact invalid-command wording K3 was meant to remove).
- Testing Decisions: listed test cases referenced `git remote show
  succeeds` without naming the `remoteHeadBranch` injection.
- Agent Brief desired-behaviour: said the helper walks `develop → main
  → master` (omitting the `remote-show` first level).
- Agent Brief acceptance criteria: said orchestrator wires the helper
  via injectable `branchExists` only, omitting `remoteHeadBranch`.

Reconcile all four against slice 06's K3-corrected contract so an AFK
agent picking up B6 reads one consistent signature across PRD and
slice. No effect on the other 9 slices.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docs(pr-review): prep ADO fetcher reliability — Notice Tier doctrine + PRD A/B triage
Lands the foundational tracer-bullet slice of PRD A (ADO Fetcher
reliability). Wires the four-tier Notice doctrine end-to-end with one
concrete emission site — the Doc-Context EMPTY-BY-DESIGN info Notice
fired when WORK_ITEM_IDS=[] — and adds the mandatory end-of-run Trailer
in the Claude interface. Subsequent slices (A2/A3/A4 and PRD B) extend
the same surface with DEGRADED + ABORTED emission sites on the Fetcher,
Writer, Coordinator, and Pre-PR paths.

What this slice ships:

- scripts/ado/notices.mjs — pure helpers (createNotice, mergeNotices,
  formatNoticesAsSummaryBlock, formatNoticesAsPrePrPreamble,
  formatTrailer). 14 unit-test cases pinning the dedup-by-kind merge,
  the per-severity emoji rendering (ℹ️ for info, ⚠ for warning, bare
  ## Notices heading), and the four Trailer shapes (first-review,
  re-review, pre-pr, aborted) including pluralisation.

- ADR 0014 — Notice Tier doctrine + failure-classification helper
  layer; refines ADR 0013's testing posture (orchestration in agent
  prompts, classification in pure-JS helpers).

- ADO Fetcher (.agents/ado-fetcher.md) — new Step 6 builds the NOTICES
  array and emits the Doc-Context info Notice when WORK_ITEM_IDS=[].
  ADO_FETCHER_RESULT block grows a NOTICES JSON-array field.

- Orchestrator (commands/review-pr.md) — parses NOTICES from the
  Fetcher result block, sets NOTICES_JSON via mergeNotices (single
  source today; subsequent slices add Coordinator/Writer sources),
  threads it into the ADO Writer prompt, and prints one mandatory
  formatTrailer line via a new Step 8. Pre-PR Step E's completion
  message becomes a formatTrailer call (mode: 'pre-pr'). The 200-line
  cap is held exactly by folding the documentation-only Constants
  section into the lead paragraph (SIGNATURE_PREFIX value was already
  inlined at both call sites; no behavioural change).

- ADO Writer (.agents/ado-writer.md) — accepts NOTICES_JSON input and
  renders a ## Notices block above severity-grouped findings in the
  Review Summary content. Empty NOTICES_JSON ⇒ no heading.

- Version: pr-review 1.0.0 → 1.1.0 (Added: user-visible Trailer +
  Notices block). CHANGELOG dated 2026-05-13; verify:changelog clean.

Key decisions (locked during the 2026-05-13 /grill-with-docs session):

- Four tiers, no fifth ASK tier — AFK runs cannot block on user input.
  Failures that would tempt ASK reclassified as ABORTED.
- Doc-Context info-Notice is the one EMPTY-BY-DESIGN carve-out — every
  other empty state is silent.
- Notice shape: { severity, kind, message }; kind is an enum, not a
  free-form string, so cross-agent dedup is structural rather than
  textual.
- Trailer is mandatory for every run (success, abort, pre-pr); designed
  for AFK skim — invoker sees outcome status without opening the PR.
- Helper layer refines (not replaces) ADR 0013: orchestration still in
  agent prompts; failure classification moves to scripts/ado/.

Files: 12 changed (5 new, 7 modified). Issue
docs/issues/pr-review-ado-fetcher-reliability/01-end-to-end-notice-pipeline.md
flipped to Status: resolved with a Deviations section documenting the
sandbox-driven manual bump (no pnpm — Node 24 unreachable here, Node 20
runs node --test directly), the manual prettier/tsc feedback loops, and
the Biome layer left to CI (only darwin-arm64 cli binary is installed;
sandbox is linux-arm64).

Unblocks: A2 (work-items DEGRADED), A4 (DIFF_RANGE sentinel), B2
(parseAdoWriterResult discriminated-union), B4 (match-finding throw),
B6 (Pre-PR Notice surface). A3 and B-others remain blocked on A2/A4/B1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…for Node

Sandboxed AFK runs were failing two ways: pnpm's `useNodeVersion: 24.15.0`
triggered an outbound `nodejs.org` fetch the firewall blocked, and Biome's
platform binary was only installed for the host arch, so `pnpm check` couldn't
run on Linux. Fix both by deferring Node version selection to `.nvmrc` (already
consumed by `actions/setup-node` and every local version manager) and by
declaring `supportedArchitectures` so all OS/arch pairs of platform-specific
packages land in `node_modules` regardless of where `pnpm install` runs.

Relaxing the engines range from `>=24` to `>=22` makes the existing CI matrix
(Node 22 + 24) honest — `useNodeVersion` was silently forcing Node 24 even on
the "Node 22" job.

Docs (AGENTS.md, README, CONTRIBUTING, plugin CLAUDE.md/CONTRIBUTING, and the
new-plugin scaffolding template) updated to point at `.nvmrc` and the relaxed
engine range. Historical artifacts under docs/adr/ and docs/plans/ are left
intact.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…er + ADR-0015 (v1.2.0)

Wires the DEGRADED tier end-to-end for the work-item fetch path. Two new
pure JS helpers replace the inline parseWorkItemIds helper and introduce
the canonical HTTP-tier mapping used by PRD B's write-side helpers.

New helpers:
- scripts/ado/classify-http-error.mjs — classifyHttpError({ status, body,
  exitCode }) → { tier, kind, message }. Canonical mapping: 200/201/404/409
  → ok; 401/403 → aborted (kind: auth); 5xx → degraded (kind: transient);
  other 4xx → degraded (kind: malformed-request); non-zero exit + no status
  → degraded (kind: network). 16 unit-test cases.
- scripts/ado/fetch-work-items.mjs — fetchWorkItems({ responseText, exitCode
  }) → { ok: true, ids } | { ok: false, reason, message }. Distinguishes
  EMPTY-BY-DESIGN (ok: true, ids: []) from fetch failure (ok: false). 9
  unit-test cases.

Prompt change (.agents/ado-fetcher.md Step 5): delegates work-item fetch to
fetchWorkItems via await import. On { ok: false }, emits DEGRADED Notice
(kind: work-items) into NOTICES array. On { ok: true, ids: [] }, emits
EMPTY-BY-DESIGN info Notice (kind: doc-context) as before.

Cleanup: parseWorkItemIds removed from scripts/ado-fetcher.mjs and its
tests; ado-fetcher.test.mjs updated to assert fetchWorkItems usage instead.

ADR 0015 (docs/adr/0015-canonical-http-tier-mapping.md): records the
HTTP-tier mapping table, the 401/403 abort rule, and the no-retries-in-v1
stance. Consumed by PRD B's parse-write-response (B1).

Deviations: version bumped manually (unic-bump requires a clean working
tree; sandbox does not support committing mid-step). Version updated in
plugin.json + marketplace.json; CHANGELOG moved [Unreleased] to [1.2.0].

Unblocks: A3 (fetch-iterations ABORTED), B1 (parse-write-response + Writer
HTTP-tier mapping). A3 depends on classify-http-error; B1 depends on both.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the invalid `iterationId=1` fallback and wires the ABORTED tier
for the iterations fetch path. An empty or failed iterations response now
aborts the run rather than silently signing comments with the wrong ID.

New helper:
- scripts/ado/fetch-iterations.mjs — fetchIterations({ responseText,
  exitCode }) → { ok: true, latestIterationId, latestCommitSha } |
  { ok: false, reason: 'empty-iterations' | 'auth' | 'transient' |
  'malformed', message }. Uses classifyHttpError for HTTP failures.
  8 unit-test cases covering every branch.

Prompt changes:
- .agents/ado-fetcher.md Step 2: delegates to fetchIterations via
  await import. On { ok: false }, exits non-zero with a clear stderr
  message ('az devops login' hint for auth; explicit empty-iterations
  message for that reason).
- commands/review-pr.md Step 5: detects absent result block (Fetcher
  exited non-zero), infers abortKind from output, calls formatTrailer
  and stops. Line count held at exactly 200.

Cleanup:
- scripts/ado-fetcher.mjs deleted (parseIterations was its only export;
  all callers updated).
- tests/ado-fetcher.test.mjs: parseIterations import + describe block
  removed; new assertions check for fetchIterations usage and verify
  no iterationId=1 default remains in the agent prompt.
- package.json: tests/fetch-iterations.test.mjs added to test script.

Deviations: version bumped manually (unic-bump requires a clean working
tree; sandbox does not support committing mid-step).

Unblocks: A4 (diff-range sentinel) had no dependency on A3; A3 itself
had no dependents in the current issue queue.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ndment (v1.2.2)

Emits the DIFF_RANGE sentinel in the ADO Fetcher result block and fires
a DEGRADED Notice when the incremental diff fallback triggers.

ADO Fetcher (.agents/ado-fetcher.md):
- Step 4: sets DIFF_RANGE=incremental on successful incremental diff,
  DIFF_RANGE=full + DIFF_RANGE_FALLBACK=true when prior commit is
  unreachable, DIFF_RANGE=full on first-review, DIFF_RANGE=incremental
  on no-new-commits branch.
- Step 6: passes DIFF_RANGE_FB into the Notice-building script; emits
  warning Notice (kind: diff-range) when DIFF_RANGE_FALLBACK=true.
  Removes the forward-looking A4 comment (now implemented).
- Output block: adds DIFF_RANGE: {DIFF_RANGE} field with Where: docs.

Orchestrator (commands/review-pr.md): adds DIFF_RANGE to the parsed
fields list in Step 5 with a note that B3 will consume it. 200 lines.

ADR 0004: adds "Degraded baseline" subsection documenting the γ-downgrade
rule (remap addressed/obsolete → pending when DIFF_RANGE=full). B3 impls.

Tests: adds 3 new ado-fetcher content assertions (DIFF_RANGE assignments,
DIFF_RANGE_FALLBACK flag, diff-range Notice). 185 tests, all passing.

Deviations: version bumped manually (unic-bump requires a clean working
tree; sandbox does not support committing mid-step).

Unblocks: B3 (Coordinator γ-downgrade consumes DIFF_RANGE from A4).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…(v1.2.3)

Routes every ADO write call site in the ADO Writer through one canonical
helper. Fixes the H1 auth gap (401/403 on inline-POST now aborts the Writer
instead of log-and-continue), wires the DEGRADED Notice surface end-to-end
for write failures, and adds the NOTICES field to the Writer result block.

New helper:
- scripts/ado/parse-write-response.mjs — parseWriteResponse({ httpExit,
  responseText, errStream }) → { ok: true, id } | { ok: false, tier, kind,
  message }. Composes classifyHttpError with response-id extraction. 404/409
  map to { ok: true, id: null } (canonical ok, no resource created); 200
  without numeric id → { ok: false, tier: 'degraded', kind: 'malformed-
  response' }. 13 unit cases covering all branches.

Prompt changes (.agents/ado-writer.md):
- New "Helper: parse-write-response" section shows the canonical invoke
  pattern once; each of the four call sites (inline POST + fallback, summary
  POST, delta reply, completion marker) references it.
- On tier: aborted → stream *.err to stderr + exit 1 at every call site.
- On tier: degraded → push typed Warning Notice to NOTICES='[]' and continue.
- ADO_WRITER_RESULT_START/END grows NOTICES: [...] field.
- Cleanup (Step 4) is unconditional (no retention based on counts).

Orchestrator (commands/review-pr.md):
- Step 8 renamed to "Merge Writer notices + Trailer"; parses NOTICES from
  ADO_WRITER_RESULT_START/END and merges via mergeNotices before Trailer.
  200 lines.

Helper changes (scripts/ado-writer.mjs):
- parseAdoWriterResult return type extended to { summaryThreadId,
  findingsPosted, notices: Notice[] }. Legacy blocks without NOTICES return
  notices: []. Tests updated (7 parseAdoWriterResult cases + 3 new
  agent-content assertions for parse-write-response usage).

Deviations: version bumped manually (unic-bump requires clean working tree).

Unblocks: B5 (Coordinator PATCH-to-fixed mapping depends on parse-write-
response).

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

Distinguishes Writer crash from zero-success: the old `null` return could
not tell "block was never emitted" from "block parsed, zero findings."

Helper change (scripts/ado-writer.mjs):
- parseAdoWriterResult now returns
  { ok: true, summaryThreadId, findingsPosted, notices }
  | { ok: false, reason: 'missing-block' | 'malformed' }
- missing-block: ADO_WRITER_RESULT_START/END absent from output
- malformed: block present but FINDINGS_POSTED field absent/non-numeric
- summaryThreadId remains nullable (empty SUMMARY_THREAD_ID is valid)

Tests (tests/ado-writer.test.mjs):
- All valid-block cases assert result.ok === true before field access
- Renamed "returns null for both numeric fields" → "returns { ok: false,
  reason: 'missing-block' } when no result block is present"
- New case: "returns { ok: false, reason: 'malformed' } when block is
  present but FINDINGS_POSTED is absent"
- 205 tests, all passing

ADO Writer prompt (.agents/ado-writer.md):
- Round-trip validation updated from
  `if (parsed.summaryThreadId === null || parsed.findingsPosted === null)`
  to `if (!parsed.ok)`, with reason included in the error message.

Orchestrator (commands/review-pr.md):
- Step 8 renamed "Parse Writer result + Trailer"; branches on result.ok.
  On { ok: false }, emits ERROR stderr message (with reason) and Trailer
  aborted line, then stops. On { ok: true }, extracts result.notices and
  merges with fetcher notices as before.
- File remains at exactly 200 lines.

Deviations: version bumped manually (unic-bump requires clean working
tree; sandbox does not support committing mid-step).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… wiring (v1.2.5)

Extends classify-thread with the γ-downgrade rule (ADR-0004) and wires
DIFF_RANGE from the ADO Fetcher result block into every thread classification
call in the Re-review Coordinator.

Helper change (scripts/re-review/classify-thread.mjs):
- classifyThread now accepts diffRange: 'full' | 'incremental' (default 'incremental')
- When diffRange === 'full', outputs 'addressed' and 'obsolete' are remapped
  to 'pending' via a single post-processing branch; 'disputed' is unaffected
  (its derivation is reviewer-reply-based, not diff-position-based)

Tests (tests/classify-thread.test.mjs):
- Three new γ-downgrade cases: full+intersects→pending, full+absent→pending,
  full+disputed→still disputed; 208 tests, all passing

Coordinator (.agents/re-review-coordinator.md):
- Inputs: added DIFF_RANGE as a parsed field with description
- Step 5: parses DIFF_RANGE from ADO_FETCHER_RESULT (default incremental),
  passes DIFF_R env var into the classifyThread invocation

Orchestrator (commands/review-pr.md):
- Step 5 note updated: "not yet consumed" removed; explains Coordinator
  parses DIFF_RANGE from ADO_FETCHER_RESULT to apply γ-downgrade
- File remains at exactly 200 lines

Deviations: version bumped manually (unic-bump requires clean working tree).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ress-addressed-reply/01)

Removes the cosmetic "Resolved — thanks!" reply comment from the addressed
branch of the Re-review Coordinator. The thread status PATCH to fixed (status 2),
ADDRESSED_COUNT, and FINDINGS_POSTED counts are all unchanged.

Motivation: the reply generated an ADO notification for every thread participant.
Developers often self-resolve threads before the bot runs, causing the bot to
comment on already-closed threads (notification spam).

Changes:
- .agents/re-review-coordinator.md: removed Reply POST az devops invoke block,
  updated section heading ("post resolution confirmation and" removed), updated
  Step 8 description for addressed count
- docs/adr/0006-reply-not-duplicate-auto-resolve.md: updated Decision bullet for
  addressed threads; added Revised note (2026-05-14) with reason
- docs/issues/done/01-remove-addressed-reply.md: moved from ready-for-agent to resolved

Note: version bump and CHANGELOG covered by suppress-addressed-reply/02.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ed-reply/02)

Bumped manually (unic-bump requires a clean working tree; sandbox does not
support committing mid-step).

Changes:
- plugin.json + marketplace.json: 1.2.5 → 1.2.6
- CHANGELOG.md: [Unreleased] promoted to [1.2.6] — 2026-05-14 with the
  addressed-thread reply removal entry; fresh empty [Unreleased] added
- docs/issues/done/02-version-bump.md: moved from ready-for-agent to resolved

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

Changes match-finding's null-vs-throw contract so parse errors are
distinguishable from legitimate no-match, and wires the Coordinator
to surface a DEGRADED Notice instead of silently posting duplicates.

Helper change (scripts/re-review/match-finding.mjs):
- Throws TypeError when priorThreads is not an array
- Throws TypeError when finding is null or missing typed fields
- Returns null only for legitimate no-match (contract unchanged)

Tests (tests/match-finding.test.mjs):
- Three new throw-path cases: non-array priorThreads, null finding,
  wrong field types; 211 tests, all passing

Coordinator (.agents/re-review-coordinator.md):
- Initialises NOTICES='[]' alongside FRESH_FINDINGS_JSON in Step 6
- Step 6a captures Node exit code (MATCH_EXIT); on non-zero, pushes
  DEGRADED Notice (kind: thread-match) and falls through to no-match
- Result block gains NOTICES: {NOTICES} field; Step 8 description updated

Orchestrator (commands/review-pr.md):
- Step 7: extracts coordinatorNotices from RE_REVIEW_COORDINATOR_RESULT
- Step 8: merges coordinatorNotices into combined mergeNotices call
- File remains at exactly 200 lines

Deviations: version bumped manually (unic-bump requires clean working tree).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…(v1.2.8)

Routes the PATCH-to-fixed call site in the Re-review Coordinator through
the canonical parse-write-response helper, replacing the old 409-only
catch-all with uniform HTTP-tier handling.

Coordinator (.agents/re-review-coordinator.md):
- addressed branch: captures PATCH_RESP + PATCH_EXIT separately; routes
  through parseWriteResponse via Node heredoc (same PWR_JSON pattern as
  ADO Writer); on ok: true → continue; on tier: aborted → stderr + exit 1;
  on tier: degraded → push patch-to-fixed Notice + continue
- 404/409 map to ok: true (canonical mapping) — silent continue as before
- Old 409-only catch-all removed

Orchestrator (commands/review-pr.md):
- Step 7: added coordinator-abort handling — missing result block infers
  abortKind from output and calls formatTrailer before stopping
- File remains at exactly 200 lines

Deviations: version bumped manually (unic-bump requires clean working tree).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… (v1.2.9)

Gives Pre-PR mode the same Notice surface as ADO modes. Detects malformed
diff inputs. Replaces the hardcoded 'main' fallback with a Gitflow-aware
fallback chain that emits visible Notices.

New helper (scripts/pre-pr/detect-default-branch.mjs):
- detectDefaultBranch({ branchExists, remoteHeadBranch })
  → { branch, source, notice? }
- Chain: remote-show → develop-fallback → main-fallback → master-fallback → none
- Warning Notice (kind: default-branch) for every fallback level
- branch: null means no detectable branch → caller aborts
- 7 unit cases (tests/detect-default-branch.test.mjs)

Helper change (scripts/pre-pr.mjs):
- buildPrePrContext returns notices: Notice[] alongside existing fields
- Suspicious-shape detection: non-empty diff with diff --git headers but
  zero parsed paths → DEGRADED Notice (kind: diff-parse)
- 4 new test cases in tests/pre-pr.test.mjs

Orchestrator (commands/review-pr.md):
- Pre-PR Step A: calls detectDefaultBranch; on branch: null aborts with Trailer;
  any fallback notice pushed to PRE_PR_NOTICES
- Pre-PR Step B: merges buildPrePrContext().notices via mergeNotices
- Pre-PR Step E: formatNoticesAsPrePrPreamble before findings;
  formatTrailer receives PRE_PR_NOTICES (notice count reflected in Trailer)
- File is 187 lines (≤ 200)

package.json: added tests/detect-default-branch.test.mjs to test script.
Deviations: version bumped manually (unic-bump requires clean working tree).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n malformed-JSON httpExit:0 test

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

Tracks F7 from Copilot review of PR #31 — valid improvement but out of scope
of any current PRD. Deferred until after the orchestrator-split branch ships.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d + sentinel doc

- B3: map malformed-request kind to 'malformed' reason instead of 'transient'
- B1: filter null array elements before reduce; treat all-null array as empty-iterations
- B4: document latestCommitSha '' sentinel in JSDoc comment
- D1: add tests for missing value key and HTTP 400 → malformed paths

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

Route non-zero exit codes through classifyHttpError for consistent tier
mapping (auth/transient/malformed) matching fetch-iterations.mjs pattern.
Guard against null/non-object elements in ADO value array to prevent TypeError.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…c + test coverage

Corrects the classify-thread JSDoc to accurately list 5 ordered rules
(ADR-0004) instead of collapsing status-check and intersection-check into
one; documents minor-findings omission from the trailer in notices.mjs;
adds γ-downgrade/status=fixed test, full RESOLVED_STATUSES coverage,
re-review trailer test, and mergeNotices null-source tolerance test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…am in classified write failures

- A1: parseAdoWriterResult returns { ok: false, reason: 'malformed' } on malformed NOTICES JSON
  instead of silently falling back to empty notices; broadened NOTICES regex to detect
  unclosed arrays too
- A3: parseWriteResponse appends errStream detail to classified failure messages (same
  pattern already used for malformed-response path)
- D4: add HTTP 400 and 422 test cases to parse-write-response.test.mjs
- D10: update malformed JSON (non-zero exit) test to assert kind: 'network'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e, add none-notice

- Import Notice from notices.mjs instead of local typedef (kind was string, not NoticeKind)
- Trim whitespace from remoteHeadBranch before truthy check (whitespace-only input now falls through to fallback chain)
- Add warning Notice to source='none' result for consistency with levels 2–4

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

Add whitespace-only remoteHeadBranch test (D6) and update source='none'
assertions to expect a warning notice (pairs with A4 fix in 3ee5c6a).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(pr-review): orchestrator split + platform failure handling + suppress addressed reply (v1.1.0–v1.2.9)
@orioltf orioltf merged commit a09a315 into main May 14, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant