Skip to content

[unic-pr-review] Approval Loop (interactive walking, resumable, non-TTY guard) #149

@orioltf

Description

@orioltf

Parent

docs/issues/unic-pr-review/PRD.md

What to build

Add the interactive Approval Loop (ADR-0003). With --post, the orchestrator hands Findings to a Node script that walks them one at a time, asking accept / edit / skip per Finding; with --post --yes decisions are auto-filled; without --post the script is never invoked. The loop is resumable across Ctrl-C via state at <cwd>/.unic-pr-review/<key>/state.json and a self-ignoring .gitignore written on first use.

This slice keeps the ADO Writer out: the loop just walks Findings and writes approved.json to disk. The actual ADO writes come in the next slice.

Per US 17 / ADR-0003: --post in a non-TTY context without --yes aborts cleanly (exit 2) so the plugin never silently posts unreviewed Findings in CI.

Acceptance criteria

  • scripts/approval-loop.mjs reads findings.json, walks each Finding interactively (a/e/s keys), and writes approved.json (the Findings the reviewer accepted, with any edits applied).
  • scripts/lib/cache-paths.mjs exports getApprovalStateDir(key) returning <cwd>/.unic-pr-review/<key>/ and creates <cwd>/.unic-pr-review/.gitignore containing * on first use so the directory is never tracked.
  • Key derivation: sha16(pr-url) in ADO modes, sha16(cwd + ' ' + branch) in Pre-PR mode.
  • State file state.json shape: { pluginVersion, createdAt, mode, key, headSha, iteration?, findings: [...] } where each Finding carries { id, severity, confidence, filePath, startLine, endLine, title, body, suggestion?, decision: 'pending'|'accept'|'edit'|'skip', editedBody?, decidedAt? }. Stable Finding ordering: severity bucket → file → startLine → stable id.
  • --post without --yes in a non-TTY context exits 2 with a clear message before reading state.
  • --yes auto-fills every decision as accept but still writes state (single code path).
  • Resume: when the state file already exists, the loop skips any non-pending Findings.
  • Head-SHA mismatch on resume → prompts the user "code has changed since this review was generated — start fresh or continue with stale findings?" with a --reset flag to force fresh.
  • After successful Writer run (later slice signal), the per-key directory is deleted. On Ctrl-C / error, the directory is preserved.
  • tests/approval-loop.test.mjs covers: state-file shape, accept/edit/skip transitions, resume from partial state, head-SHA mismatch prompt, non-TTY abort, --yes bulk-accept (still writes state), cleanup on completion. Tests pipe scripted stdin.
  • Cross-platform: tests pass on macOS, Linux, Windows.

Blocked by

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew capabilityfeature/unic-pr-reviewIssues from the unic-pr-review featureready-for-agentFully specified, ready for an AFK agent

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions