Skip to content

feat(pr-management): add review findings data model and parser (part of #1887) - #1920

Merged
potiuk merged 2 commits into
apache:mainfrom
Kaap10:feat/pr-management-findings-mod-pr1
Nov 1, 2026
Merged

potiuk merged 2 commits into
apache:mainfrom
Kaap10:feat/pr-management-findings-mod-pr1

Conversation

@Kaap10

@Kaap10 Kaap10 commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add the foundational TypeScript data models, findings parser, and hook wiring for the interactive review findings pane mod in magpie-pr-management (Part 1 of 3 for feat(pr-management): add interactive review findings pane Claude Code mod (part of #1497) #1887, parent issue Explore Claude Code mods across the skill families #1497).
  • Deliver a robust, fault-tolerant parseFindings function in plugins/magpie-pr-management/hooks/review-findings.ts that safely handles raw JSON, nested structures, markdown fences (with surrounding prose), field aliasing, path sanitization, and deterministic ID assignment without node built-ins.
  • Register magpie-pr-management in CODEX_FAMILY_HOOKS with dedicated codex-hooks.json and .codex-plugin/plugin.json to preserve strict vendor neutrality and avoid harness startup warnings.

Type of change

  • Skill change (.claude/skills/<name>/) — eval fixtures updated below
  • Tool / bridge contract (tools/<system>/*.md)
  • Python package (tools/*/ with pyproject.toml)
  • Groovy reference impl
  • Cross-cutting (RFC, AGENTS.md, sandbox, privacy-LLM)
  • Documentation (docs/, README.md, CONTRIBUTING.md)
  • Project template (projects/_template/)
  • CI / dev loop (prek, workflows, validators)
  • Other: Claude Code mod & Codex manifests (plugins/magpie-pr-management/hooks/)

Test plan

  • Unit test suite in review-findings.test.ts passes via claude plugin test plugins/magpie-pr-management (14 pass, 0 fail across 1 file in 0.46s).
  • Static mod manifest validation passes via claude plugin validate --strict plugins/magpie-pr-management.
  • Codex manifest and family hook verification passes (check_codex_family_hooks() and check_codex_hook_files() return 0 errors).
  • Pre-commit validators pass with zero emoji or formatting violations.

RFC-AI-0004 compliance

  • HITL — any new mutation is gated on explicit user confirmation
  • Sandbox — no new unrestricted host access; mod uses zero node built-ins and complies with Claude Code mod sandbox constraints
  • Vendor neutrality — Claude mod is strictly additive; Codex manifest and hooks cleanly isolated with zero impact on non-Claude harnesses
  • Conversational + correctable — review findings remain fully inspectable and correctable
  • Write-access discipline — no autonomous outbound messages; drafts only, sent on confirmation
  • Privacy LLM — private content does not reach a non-approved LLM; redactor invoked where needed

Linked issues

Notes for reviewers (optional)

This is PR-1 of the 3-part split for #1887:

  • PR-1 (this PR): Data model, findings parser, Codex compatibility manifests, and unit tests.
  • PR-2 (upcoming): ui.render Pane component, severity badges, and terminal fallback.
  • PR-3 (upcoming): Action state toggling (accept/skip/edit) and integration into review-flow.md Step 7a.

@github-actions github-actions Bot added family:pr-management pr-management-* skills family:tools tools/* family:ci .github workflows, prek, validators substrate:framework-dev Tool substrate: build / validate / eval the framework itself labels Oct 31, 2026
@Kaap10
Kaap10 force-pushed the feat/pr-management-findings-mod-pr1 branch 2 times, most recently from 27f5c43 to 979911d Compare October 31, 2026 15:50
@Kaap10

Kaap10 commented Oct 31, 2026

Copy link
Copy Markdown
Contributor Author

up for review!

@potiuk potiuk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for splitting #1887 into three, Kaap10; a small, well-tested parser first is the right foundation for the pane. Since the pane's output is what decides which comments get posted, though, the bridge to render has to agree with it exactly, and two places do not yet (inline below): the keep answer numbers comments over a different list than render does, and an edited finding is dropped from the answer. Both would post a review the maintainer did not pick.

The other inline comments are smaller and fine in the same push.

One question rather than a finding: register adds a pass-through session.start handler, so every session of every magpie-pr-management user loads this module before anything uses it. If it is there only so the mod is wired up and its tests run in CI, a short comment saying so would help; otherwise the hooks.json entry could wait for PR-2, when there is a pane to show.

the keep answer numbers comments differently from render (plugins/magpie-pr-management/hooks/review-findings.ts:160)

Converts finding action states into inline-picker keep answer format

  • compatible with code-review render keep parameter.
const anchored = findings.filter(
    (f) => f.line !== null && f.line !== undefined && f.line >= 1
  );

render numbers the inline comments over the raw findings file, anchored = [f for f in findings if f.get("line")] (tools/pr-management/src/pr_management/code_review/cli.py), while this numbers them over the parsed list. The two disagree whenever the parser normalises: a finding carrying lineNumber or line_number is anchored here and not there, "0" is anchored there and not here, and an item the parser drops as "not an object" shifts every later index. One disagreement moves 1,3 onto different comments, so the review posts comments the maintainer skipped and drops ones they kept. Please number over exactly the list render reads (the pane writes the normalised findings file that render then consumes, or the anchoring predicate is render's on the raw item), and add a test that runs both rules over the same input.

an edited finding is dropped from the review (plugins/magpie-pr-management/hooks/review-findings.ts:171)

The inline picker's answer: A, N, 1,3 (keep), -2,-3 (drop), E 2 (edit).

if (item && item.action === 'accept') {
      acceptedIndices.push(i + 1);

Only accept counts as kept, so a finding the maintainer marked edit is left out of the answer and never posted. In the picker grammar an edit keeps the comment (E 2 keeps every comment and edits number 2). Please treat edit as kept here, and leave how the edited text reaches render to PR-3, with a test for a mixed accept/edit/skip list.

Smaller observations

  • See inline comments on plugins/magpie-pr-management/hooks/review-findings.ts:108, plugins/magpie-pr-management/hooks/review-findings.ts:47, plugins/magpie-pr-management/hooks/review-findings.ts:77, plugins/magpie-pr-management/hooks/review-findings.ts:270.

This review was drafted by an AI-assisted tool and
confirmed by an Apache Magpie maintainer. After you've
addressed the points above and pushed an update, an Apache Magpie
maintainer — a real person — will take the next look
at the PR. The findings cite the project's review criteria;
if you think one of them is mis-applied, please reply on the
PR and a maintainer will weigh in.

More on how Apache Magpie handles maintainer review:
Contributing guide.

@Kaap10
Kaap10 force-pushed the feat/pr-management-findings-mod-pr1 branch from 979911d to e20e6a6 Compare October 31, 2026 16:52
@Kaap10

Kaap10 commented Oct 31, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review and catching these subtle bridge edge cases, @potiuk!

All points and the question have been addressed in this push:

  1. Parity with render numbering: Added isAnchored aligning with render's anchoring rule (finding.line >= 1), along with serializeFindingsForRender so the normalized output consumed by render --findings <file> shares identical 1-based indexing. Added an explicit unit test verifying parity between isAnchored and Python's bool(item.get("line")) over a mixed dataset.
  2. edit actions kept: formatKeepAnswer now treats both accept and edit as kept (matching picker grammar where E <n> keeps the item), with a test for a mixed accept/edit/skip list verifying that edited items are preserved.
  3. Safe action normalization: Missing/undefined defaults to accept, but unrecognized values (e.g. reject, drop, typos) log an error in errors[] and default safely to skip so an unintended comment never posts.
  4. Severity synonyms & error logging: Mapped common synonyms (critical/blocker -> blocking, high -> major, low -> minor, trivial/info -> nit), and unrecognized severities are now recorded in errors[].
  5. Strict line parsing: Switched to /^\d+$/ so malformed prefix strings ("12.5", "12-20", "1e2") are treated as unanchored (null) and logged in errors[].
  6. Preserved suggestion indentation: Switched fixup from .trim() to .trimEnd(), keeping leading whitespace intact for Python code blocks.
  7. session.start hook explanation: Added an explicit docstring in review-findings.ts explaining that session.start is a pass-through scaffolding hook in PR-1 to satisfy Claude Code strict manifest validation (claude plugin validate --strict) and CI test execution (claude plugin test), before the ui.render findings pane lands in PR-2.

All 18 unit tests pass cleanly locally (claude plugin test plugins/magpie-pr-management) and all CI checks on GitHub Actions are green.

Kaap10 and others added 2 commits November 1, 2026 08:28
apache#1887)

Add the core TypeScript data model, findings parser, and hook wiring for the interactive review findings pane mod in magpie-pr-management.

Part 1 of 3 for apache#1887 (parent issue apache#1497):
- Add types.ts defining ReviewFinding, ReviewFindingsSummary, ReviewFindingsState, and ParseFindingsResult.
- Add review-findings.ts with robust parseFindings extracting raw JSON, wrapped markdown fences, and field aliases without node built-ins.
- Add formatKeepAnswer converting accepted and edited findings into Step 7a keep answer format with render indexing parity.
- Add serializeFindingsForRender to bridge 1:1 with render input.
- Add hooks.json and clean codex-hooks.json with CODEX_FAMILY_HOOKS registration to preserve strict vendor neutrality across harnesses.
- Add comprehensive 18-test unit suite in review-findings.test.ts covering synonyms, strict line parsing, action defaults, and suggestion indentation.

All tests pass via claude plugin test and strict manifest validation passes.
Review fixups:

- serializeFindingsForRender wrote body / rule / fixup, which render
  never reads, so every inline comment rendered from the file came out as
  a bare title. It now keeps every field of the original finding
  (explanation, rule_id, quoted_rule, excerpt, suggestion_block, side,
  reviewers, ...), drops the parser-only aliases, overrides the
  normalised file / line / severity, and maps body / rule to explanation
  / rule_id when the finding had only those.
- Tests: a full Step-4 finding round-trips with every key render reads,
  and render's numbering over the serialised file matches
  formatKeepAnswer on the inputs where the raw keys diverge (lineNumber /
  line_number aliases, the string "0", a non-object item).
- A numeric non-integer or negative line and a non-string severity are
  now recorded in errors, like their string counterparts.
- The Codex manifest picks up the version main moved to.

Generated-by: Claude Opus 5.5
@potiuk
potiuk force-pushed the feat/pr-management-findings-mod-pr1 branch from e20e6a6 to abe9a4e Compare November 1, 2026 07:31

@potiuk potiuk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick turnaround — the edit, unknown-action, severity, malformed-line and indentation fixes are all in and tested, and the session.start docstring answers my question. Rather than send this back for another round, I rebased the branch onto main and pushed one fixup commit, abe9a4e, for what was left (please pull before pushing again):

  • hooks/review-findings.ts — serializeFindingsForRender wrote body / rule / fixup, which render never reads, so every inline comment rendered from the file would have come out as a bare title. It now keeps every field of the original finding (explanation, rule_id, quoted_rule, excerpt, suggestion_block, side, reviewers, …), drops the parser-only aliases, and overrides only the normalised file / line / severity; a finding that arrived with only body / rule gets them as explanation / rule_id.
  • hooks/review-findings.test.ts — a full Step-4 finding now round-trips with every key render reads, and the parity test runs render's own rule over the serialised file on the inputs where the raw keys diverge (lineNumber / line_number, the string "0", a non-object item). 21 tests pass under claude plugin test.
  • hooks/review-findings.ts — a numeric non-integer or negative line and a non-string severity are now recorded in errors, like their string counterparts.
  • .codex-plugin/plugin.json — picks up the version main moved to in #1934 (check-family-plugins --fix), which would otherwise have failed the main build after merge.

This review was drafted by an AI-assisted tool and
confirmed by an Apache Magpie maintainer. The maintainer
approving this PR has read the findings and signed off. If
something feels off, please reply on the PR and a maintainer
will follow up.

More on how Apache Magpie handles maintainer review:
Contributing guide.

@potiuk
potiuk merged commit 4db1838 into apache:main Nov 1, 2026
11 checks passed
potiuk pushed a commit that referenced this pull request Nov 4, 2026
…iew-flow integration (part 3 of #1887) (#1992)

This is **PR-3 (Part 3 of 3)** completing Issue #1887 (and part of #1497) for the `magpie-pr-management` Claude Code mod. Building on the data models in PR-1 (#1920) and the presentational Pane component in PR-2 (#1954), this PR wires the live session feed, interactive action toggling, and vendor-neutral skill flow integration:

- **Live session feed (Fail-open):** Intercepts `pr-management code-review disposition --findings <file>` via `tool.call` on Bash. Reads and parses the live drafted findings into `reviewFindingsState`. Unconditionally invokes `next(e)` so tool execution is never blocked or gated. When findings are empty (`[]`), or when reading the findings file fails, resets the state atom to `null` to avoid stale findings sticking across sessions.
- **Zero-token curation command:** Registers the `/magpie-findings` slash command for inspecting and curating review findings directly from the prompt (`status`, `all`, `none`, `keep <indices>`, `drop <indices>`, `edit <idx> <note>`). Shows both inline comments (`1..N`) and general observations (`g1..M`).
- **Edited findings serialization (not wired yet):** `serializeFindingsForRender` removes `base.suggestion` and sets `base.explanation = f.body` for an edited finding. Nothing outside the tests calls it yet, so the pane does not change what is posted.
- **Interactive UI controls & disambiguated indexing:** Attaches interactive Button elements with direct clicks and `ui.press` event handling (`toggle-<N>`, `toggle-general-<N>`, `accept-all`, `skip-all`, `prev-finding`, `next-finding`). Disambiguates 1-based indexing so inline actions map strictly to anchored findings (`1..anchored.length`), returns `-1` on out-of-range indices without arbitrary whole-list fallbacks, and supports `g<N>` / `G<N>` for general observations.
- **Skill workflow documentation:** Documents the interactive pane mod in `review-flow.md` Step 7a as an interactive visual overview during review triage, with semantic line breaks (one sentence per line) while upholding strict vendor neutrality: Codex, Antigravity, Cursor, and headless CI continue using the standard sequential text picker prompt.

Closes #1887
Part of #1497
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

family:ci .github workflows, prek, validators family:pr-management pr-management-* skills family:tools tools/* substrate:framework-dev Tool substrate: build / validate / eval the framework itself

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants