Skip to content

fix(unic-pr-review): remove identity matching, detect re-reviews by hidden Iteration Marker#195

Merged
orioltf merged 7 commits into
developfrom
archon/task-feature-unic-pr-review-194-remove-identity-matchin
Jun 4, 2026
Merged

fix(unic-pr-review): remove identity matching, detect re-reviews by hidden Iteration Marker#195
orioltf merged 7 commits into
developfrom
archon/task-feature-unic-pr-review-194-remove-identity-matchin

Conversation

@orioltf

@orioltf orioltf commented Jun 4, 2026

Copy link
Copy Markdown
Member

Why

az devops user show resolves identity via _apis/UserEntitlements — an org-administration surface readable only by Project Collection Administrators. Normal reviewers get HTTP 404, so the doctor's identity check and author.id-based re-review detection were permanently broken for the typical user (issue #194).

The fix removes identity end-to-end and replaces it with the hidden Iteration Marker <!-- unic-pr-review:iteration=N --> that the Bot Signature already embeds in every bot-authored comment, making re-review detection self-sufficient (ADR-0006, revised 2026-06).

What changed

  • scripts/lib/signature.mjsrenderFooter(n) now appends the Iteration Marker on its own line; parseSignature matches ITERATION_MARKER_REGEX only (not the visible footer text); priorAuthorUserId removed from ParsedSignature
  • scripts/doctor.mjscheckAzIdentity deleted; runDoctor now runs five checks (was six)
  • scripts/parse-prior-signature.mjs — docstring updated: caller pre-filters by Iteration Marker, not author identity
  • agents/ado-fetcher.md — Step 1 (identity cache) deleted; Step 4a filters threads by Iteration Marker presence in comments[0].content; identity field removed from output JSON contract; steps renumbered 1-6
  • agents/ado-writer.md — Step 7a summary lookup now matches by Iteration Marker (<!-- unic-pr-review:iteration=), not author.id === identity.id; identity removed from re-review input
  • agents/re-review-coordinator.mdidentityId removed from input; human replies identified by absence of Iteration Marker; persistent-unaddressed logic counts marker-bearing comments
  • commands/review-pr.mdidentity-cache-failed error path removed; identityId/signaturePrefix removed from Coordinator input; identity removed from ADO Writer re-review input
  • commands/doctor.md — check Develop #4 (az devops user show) removed; checks renumbered to 5
  • AGENTS.md (plugin) — ADR-0006 doctrine bullet updated to reflect marker-based detection

Tests

  • tests/doctor.test.mjscheckAzIdentity describe block deleted; identity stubs removed from allOkExec; waterfall assertions updated
  • tests/signature.test.mjspriorAuthorUserId assertions removed; 5 new tests added: Iteration Marker in renderFooter, marker on its own line, visible-footer-only rejection, quote-reply rejection, marker round-trip

pnpm --filter unic-pr-review test — 483/483 pass
pnpm --filter unic-pr-review typecheck — clean

Non-goals (per issue #194)

  • No connectionData HTTP call or alternative identity source
  • No ~/.unic-azure.json / loadAzureCreds wiring
  • No backward compatibility for v1 (visible-footer-only) PRs — treated as First Review, self-heals

Closes #194

🤖 Generated with Claude Code

…teration Marker

`az devops user show` resolves via the admin-only `_apis/UserEntitlements` API
(HTTP 404 for normal reviewers), making the doctor identity check and the
`author.id`-based re-review detection permanently broken for the typical user.

Replace identity matching end-to-end with the hidden Iteration Marker
(`<!-- unic-pr-review:iteration=N -->`) that `renderFooter` now embeds in every
bot-authored comment. `parseSignature` keys on `ITERATION_MARKER_REGEX` only;
`checkAzIdentity` is deleted from `doctor.mjs`; agent prompts and commands are
updated to remove the `identity` / `identityId` fields from every contract.

Resolves #194. Conforms to ADR-0006 (revised 2026-06).

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

orioltf commented Jun 4, 2026

Copy link
Copy Markdown
Member Author

Comprehensive PR Review

PR: #195fix(unic-pr-review): remove identity matching, detect re-reviews by hidden Iteration Marker
Reviewed by: 4 specialized agents (code-review, error-handling, test-coverage, docs-impact)
Date: 2026-06-04


Summary

Clean, targeted cleanup PR. Identity-matching removal is complete end-to-end: priorAuthorUserId gone from all consumers, checkAzIdentity fully excised, ITERATION_MARKER_REGEX round-trip test-proven, all 9 CI checks green. One MEDIUM doc fix recommended before merge; four LOW style/test suggestions can be deferred.

Verdict: APPROVE (pending README one-liner)

Severity Count
CRITICAL 0
HIGH 0
MEDIUM 1
LOW 4

MEDIUM — Fix Before Merge

README.md says "six checks" but doctor now runs five

Location: apps/claude-code/unic-pr-review/README.md:37

# Current (wrong)
It runs six checks and tells you exactly what is missing before any Review is attempted.

# Recommended
It runs all prerequisite checks and tells you exactly what is missing before any Review is attempted.

Removing the hard-coded count avoids the same drift if a check is added/removed again.


LOW — Defer or Follow-up

View 4 low-priority suggestions

1. Duplicate allOkExec in doctor.test.mjs

  • tests/doctor.test.mjs:350 — inner const shadows module-scope one (byte-for-byte identical today, silent drift risk later)
  • Fix: delete inner copy at L350-354

2. Two describe blocks cover same credential-failure scenarios

  • tests/doctor.test.mjs:262 (runDoctor — missing credentials) and :348 (runDoctor — credential errors) test the same null/throwing loadCreds cases
  • Fix: merge into one group; add /One or more checks failed/ assertion to the credential errors block; delete missing credentials block

3. parseInt not NaN-guarded in parseSignature

  • scripts/lib/signature.mjs:88 — cannot produce NaN today (regex is \d+-only) but not future-safe if regex is widened
  • Fix: add if (Number.isNaN(n)) continue after parseInt, matching the if (!match) continue pattern directly above

4. runDoctor all-ok summary text not asserted

  • scripts/doctor.mjs:311'All checks passed.' trailer not covered by any test; semantic ok === true is covered
  • Fix: optional assert.match(output, /All checks passed/) in one all-ok test case

What's Good

  • priorAuthorUserId absent from every consumer — no dangling references anywhere
  • checkAzIdentity fully excised: doctor.mjs, runDoctor waterfall, doctor.test.mjs all updated consistently
  • Regex and renderer co-located in signature.mjs — detection cannot drift from rendering; proven by round-trip test at signature.test.mjs:131-138
  • ADO step numbers renumbered 2-5 → 1-4 in ado-fetcher.md consistently with review-pr.md
  • 18 meaningful signature/doctor tests including the critical visible-footer-only rejection case and CRLF normalization
  • ADR-0006, AGENTS.md, CONTEXT.md, CHANGELOG.md, and all 5 agent/command prompts correctly updated
  • Scope discipline: no connectionData call, no backward-compat shim for v1 PRs — per issue [unic-pr-review] doctor identity check fails for non-admins — remove identity matching, detect re-reviews by hidden Iteration Marker #194 ACs

Suggested Follow-up Issues

Title Priority
Clean up duplicate allOkExec + overlapping describe blocks in doctor.test.mjs P3
Add NaN guard after parseInt in signature.mjs parseSignature P3

Reviewed by Archon comprehensive-pr-review workflow
Artifacts: /Users/oriol.torrent/.archon/workspaces/unic/unic-agents-plugins/artifacts/runs/5ee33cb586f5f6642cbce482caeffb5c/review/

- README: "six checks" → "all prerequisite checks" (avoids count drift)
- signature.mjs: add NaN guard after parseInt (mirrors existing !match guard pattern)
- doctor.test.mjs: remove duplicate allOkExec shadow inside credential-errors block
- doctor.test.mjs: merge overlapping "missing credentials" + "credential errors" describe
  groups; consolidated "credential errors" is the canonical home; added
  "One or more checks failed" assertion to both tests
- doctor.test.mjs: assert "All checks passed" in all-ok Jira-silence test

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

orioltf commented Jun 4, 2026

Copy link
Copy Markdown
Member Author

⚡ Self-Fix Report (Aggressive)

Status: COMPLETE
Pushed: ✅ Changes pushed to archon/task-feature-unic-pr-review-194-remove-identity-matchin
Commit: c9a5ef4
Philosophy: Fix everything unless clearly a new concern


Fixes Applied (5 total)

Severity Count
🔴 CRITICAL 0
🟠 HIGH 0
🟡 MEDIUM 1
🟢 LOW 4
View all fixes
  • README "six checks" → "all prerequisite checks" (README.md:37) — avoids count drift on future doctor check additions/removals
  • NaN guard after parseInt (scripts/lib/signature.mjs:88) — if (Number.isNaN(n)) continue mirrors the existing if (!match) continue pattern; forward-safe if regex capture group ever widens
  • Remove duplicate allOkExec shadow (tests/doctor.test.mjs:350) — inner const was byte-for-byte identical to module-scope one; removed; all four describe groups now share one source of truth
  • Merge overlapping credential-failure describe blocks (tests/doctor.test.mjs:262 and :348) — deleted "missing credentials" block; added assert.match(output, /One or more checks failed/) to both tests in "credential errors"; one canonical group with the sharpest assertions
  • Assert "All checks passed" summary text (tests/doctor.test.mjs) — added to the Jira-silence all-ok test; catches accidental deletion of the trailer line

Tests Added

(none — assertions added to existing tests)


Skipped (0)

(none — all findings addressed)


Suggested Follow-up Issues

(none)


Validation

✅ Type check | ✅ Lint | ✅ Tests (481 passed)


Self-fix by Archon · aggressive mode · fixes pushed to archon/task-feature-unic-pr-review-194-remove-identity-matchin

`highest-N-wins` and `picks the highest iteration when multiple signatures exist`
both pass [1,5,2]-equivalent inputs and assert priorRevisionId===5.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The archon self-fix left the new test file unformatted, which made
`biome ci` emit one error and failed Root checks on PR #195. Format
fix only; no logic change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the unic-pr-review plugin to remove all Azure DevOps identity resolution (which fails for non-admin users) and makes re-review detection rely solely on a hidden Iteration Marker embedded in the bot signature, aligning implementation with ADR-0006 / issue #194.

Changes:

  • Replace signature detection from visible footer/author identity to the hidden <!-- unic-pr-review:iteration=N --> Iteration Marker.
  • Remove the az devops user show identity check from doctor and update related docs/tests.
  • Update agent contracts/docs to drop identity plumbing; bump plugin version to 2.1.1.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apps/claude-code/unic-pr-review/scripts/lib/signature.mjs Emit Iteration Marker in footer; parse iteration from marker only; drop priorAuthorUserId.
apps/claude-code/unic-pr-review/tests/signature.test.mjs Update tests for marker-based detection and new footer format.
apps/claude-code/unic-pr-review/scripts/doctor.mjs Remove identity check; cascade now stops at session validity before Atlassian checks.
apps/claude-code/unic-pr-review/tests/doctor.test.mjs Remove identity stubs/tests; update waterfall and output assertions.
apps/claude-code/unic-pr-review/scripts/parse-prior-signature.mjs Update docstring to reflect marker-based pre-filtering.
apps/claude-code/unic-pr-review/agents/ado-fetcher.md Remove identity cache step; filter bot threads by marker; renumber steps/output contract.
apps/claude-code/unic-pr-review/agents/ado-writer.md Update summary-thread detection to key on marker, not author.id.
apps/claude-code/unic-pr-review/agents/re-review-coordinator.md Update classification rules to treat marker presence as “bot comment”.
apps/claude-code/unic-pr-review/commands/review-pr.md Remove identity-related error path and coordinator/writer inputs.
apps/claude-code/unic-pr-review/commands/doctor.md Update checklist and remediation guidance to remove identity step.
apps/claude-code/unic-pr-review/README.md Generalize doctor description now that check count changed.
apps/claude-code/unic-pr-review/AGENTS.md Update ADR-0006 doctrine bullet to marker-based detection + doctor behavior.
apps/claude-code/unic-pr-review/CHANGELOG.md Add 2.1.1 entry describing identity removal and marker detection.
apps/claude-code/unic-pr-review/package.json Bump version to 2.1.1.
apps/claude-code/unic-pr-review/.claude-plugin/plugin.json Bump plugin version to 2.1.1.
apps/claude-code/unic-pr-review/.claude-plugin/marketplace.json Bump marketplace version to 2.1.1.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/claude-code/unic-pr-review/agents/ado-fetcher.md Outdated
Comment thread apps/claude-code/unic-pr-review/agents/ado-fetcher.md
orioltf and others added 3 commits June 4, 2026 18:03
…umber (#195)

This PR renamed ado-fetcher.md "Step 4a" to "Step 3a" but left two
cross-references pointing at the old name, so a maintainer following
them would not find the mode-detection logic.

Why: keep internal cross-references consistent with the renumbered
ADO Fetcher steps introduced in the same change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ceholders (#195)

Addresses two Copilot review comments on agents/ado-fetcher.md:

- Frontmatter claimed `rawDiff` is "returned empty" unconditionally, but
  Step 5 populates it with the git delta diff in re-review mode. Now
  states it is empty in first-review modes and carries the delta diff in
  re-review mode.
- The emit-result JSON template quotes `prMetadata`/`revisions`/`threads`
  as string placeholders. Clarified above the block that each `<…>` token
  is replaced with the real value it names and these three are objects,
  not strings — keeping the template shape intact per maintainer preference.

Why: the agent spec is the contract downstream consumers reason about;
internal contradictions mislead them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…0006 (#195)

US-34 and the "Identity caching" / "Signature module" implementation
bullets in PRD.md still describe the `az devops user show` identity
mechanism this PR removed. Added inline "Superseded by ADR-0006" notes
pointing at the live source of truth rather than rewriting the frozen
spec.

Why: US-34 directly contradicted the shipped doctor checks; leaving the
drift unmarked is how a future change reintroduces the identity probe
and the non-admin 404 bug.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@orioltf orioltf merged commit ab38291 into develop Jun 4, 2026
8 checks passed
@orioltf orioltf deleted the archon/task-feature-unic-pr-review-194-remove-identity-matchin branch June 4, 2026 16:16
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.

[unic-pr-review] doctor identity check fails for non-admins — remove identity matching, detect re-reviews by hidden Iteration Marker

2 participants