-
Notifications
You must be signed in to change notification settings - Fork 0
feat(unic-pr-review): plugin scaffold + doctor command #155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
944666d
feat(unic-pr-review): plugin scaffold + doctor command (#143)
orioltf 859009d
fix(unic-pr-review): address all review findings from PR #155
orioltf d9de6a7
refactor(unic-pr-review): extract readJsonFile helper in credentials …
orioltf 6e3e6db
ci(unic-pr-review): register plugin in CI matrix
orioltf b5a3b40
ci: render package name in test job display
orioltf 4f885e2
fix(unic-pr-review): address copilot review findings on PR #155
orioltf 034ce02
ci: fix unic-confluence change-detection output name
orioltf File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
apps/claude-code/unic-pr-review/.claude-plugin/marketplace.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| { | ||
| "metadata": { | ||
| "description": "AI-powered PR review with intent checking against Azure Boards and Jira, Confidence-scored Findings, and interactive Approval Loop", | ||
| "homepage": "https://github.com/unic/unic-agents-plugins" | ||
| }, | ||
| "name": "unic-pr-review", | ||
| "owner": { | ||
| "name": "Unic AG" | ||
| }, | ||
| "plugins": [ | ||
| { | ||
| "author": { | ||
| "name": "Unic AG" | ||
| }, | ||
| "category": "productivity", | ||
| "description": "AI-powered PR review with intent checking against Azure Boards and Jira work items, Confidence-scored Findings filtered by confidence threshold, and an interactive per-Finding Approval Loop.", | ||
| "displayName": "Unic PR Review", | ||
| "homepage": "https://github.com/unic/unic-agents-plugins", | ||
| "keywords": ["pr-review", "azure-devops", "jira", "confluence", "code-review", "unic"], | ||
| "license": "LGPL-3.0-or-later", | ||
| "name": "unic-pr-review", | ||
| "source": "./", | ||
| "tags": ["productivity", "code-review", "azure-devops"], | ||
| "version": "2.0.0" | ||
| } | ||
| ] | ||
| } |
13 changes: 13 additions & 0 deletions
13
apps/claude-code/unic-pr-review/.claude-plugin/plugin.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "author": { | ||
| "name": "Unic AG", | ||
| "url": "https://www.unic.com" | ||
| }, | ||
| "commands": ["./commands/doctor.md"], | ||
| "description": "AI-powered PR review with intent checking against Azure Boards and Jira work items, Confidence-scored Findings, and an interactive Approval Loop.", | ||
| "homepage": "https://github.com/unic/unic-agents-plugins", | ||
| "keywords": ["pr-review", "azure-devops", "jira", "confluence", "code-review", "unic"], | ||
| "license": "LGPL-3.0-or-later", | ||
| "name": "unic-pr-review", | ||
| "version": "2.0.0" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| # AGENTS.md — unic-pr-review | ||
|
|
||
| Guidance for any AI agent working inside this Plugin directory. `CLAUDE.md` in this directory is a symlink to this file. | ||
|
|
||
| ## What this Plugin is | ||
|
|
||
| `unic-pr-review` is a Claude Code Plugin in the [`unic-agents-plugins`](../../../AGENTS.md) monorepo. It runs an AI-powered PR Review with intent checking against Azure Boards and Jira Work Items, Confidence-scored Findings, and an interactive Approval Loop. See [`CONTEXT.md`](CONTEXT.md) for the domain vocabulary (Plugin, Review, Finding, Confidence, Severity, Intent Brief, Intent Check, Bot Signature, Iteration, Approval Loop, Mode, Provider, Work Item, Notice). | ||
|
|
||
| ## Where to start | ||
|
|
||
| Root docs (monorepo-wide conventions live here — pnpm scripts, Gitflow, SemVer, Conventional Commits, code conventions, LICENSE policy, cross-platform requirement): | ||
|
|
||
| - [Root AGENTS.md](../../../AGENTS.md) — source of truth for cross-cutting rules | ||
| - [Root CONTEXT.md](../../../CONTEXT.md) — monorepo-wide vocabulary | ||
| - [Root CONTEXT-MAP.md](../../../CONTEXT-MAP.md) — index of all bounded contexts in the repo | ||
| - [Root docs/adr/](../../../docs/adr/) — monorepo-wide architecture decisions | ||
| - [Root docs/process/](../../../docs/process/) — process and workflow guides | ||
|
|
||
| This Plugin's own decisions: | ||
|
|
||
| - [Plugin docs/adr/](docs/adr/) — ADRs 0001–0009 and a README listing them | ||
|
|
||
| ## Commands | ||
|
|
||
| Plugin-specific pnpm scripts (run from this directory or with `pnpm --filter unic-pr-review <script>` from the repo root): | ||
|
|
||
| ```sh | ||
| pnpm test # run the doctor unit-test suite via node:test | ||
| pnpm typecheck # tsc --noEmit over the Plugin's .mjs sources | ||
| pnpm bump <patch|minor|major> # bump plugin.json version + promote CHANGELOG | ||
| pnpm sync-version # mirror plugin.json version into marketplace.json + package.json | ||
| pnpm tag # create the unic-pr-review@<version> git tag locally | ||
| pnpm verify:changelog # check CHANGELOG entry for the current version | ||
| ``` | ||
|
|
||
| Monorepo-wide commands (`pnpm install`, `pnpm check`, `pnpm format`, `pnpm ci:check`) are documented in the [root AGENTS.md](../../../AGENTS.md). | ||
|
|
||
| ## Layout | ||
|
|
||
| ```tree | ||
| .claude-plugin/ # Plugin manifest (plugin.json) and marketplace listing | ||
| commands/ # Claude Code slash command definitions (.md files) | ||
| scripts/ # Node.js implementation (.mjs, // @ts-check, no compilation) | ||
| scripts/lib/ # Pure-function library modules | ||
| tests/ # node:test suites (*.test.mjs) | ||
| docs/adr/ # Plugin-scoped Architecture Decision Records | ||
| ``` | ||
|
|
||
| ## Plugin doctrines | ||
|
|
||
| Load-bearing invariants captured as ADRs. All nine must be understood before editing: | ||
|
|
||
| - **ADR-0001** — Multi-source intent gathering with shared Atlassian credentials (`.unic-confluence.json` covers both Confluence and Jira) | ||
| - **ADR-0002** — Confidence-scored Findings with explicit Severity thresholds (Critical 90-100, Important 80-89, Minor 60-79; drop below 60) | ||
| - **ADR-0003** — Interactive Approval Loop as the default write path | ||
| - **ADR-0004** — Hard-stop when intent sources are unreachable; empty intent is legitimate | ||
| - **ADR-0005** — `az` CLI for Azure DevOps reads/writes; `node:https` (or global `fetch`) for Atlassian | ||
| - **ADR-0006** — Iteration state lives in the PR's Bot Signature, not on disk; identity is cached from `az devops user show --user me` at startup | ||
| - **ADR-0007** — Re-review uses a delta diff against the prior reviewed Revision | ||
| - **ADR-0008** — Conditional sub-agent spawning by changed-file analysis | ||
| - **ADR-0009** — Pre-PR Mode is a peer of the ADO Modes, not a special case | ||
|
|
||
| ADR-0010 (Provider folder bundle layout) is planned but not yet landed; the [docs/adr/README.md](docs/adr/README.md) lists it as planned. | ||
|
|
||
| ## Conventions | ||
|
|
||
| - SPDX header `// SPDX-License-Identifier: LGPL-3.0-or-later` on every `.mjs` | ||
| - Copyright header `// Copyright © 2026 Unic` | ||
| - `// @ts-check` at the top of every `.mjs`; types via JSDoc `@typedef` / `@param` | ||
| - Tabs for indentation, single quotes, no semicolons (Biome) | ||
| - No external runtime npm dependencies — every ADO read/write goes through `az`, every Atlassian call uses `node:https` or global `fetch` | ||
| - Tests use `node:test` + `node:assert/strict`; predicates accept injectable executor / fetch parameters so they are unit-testable without mocking the module system | ||
|
|
||
| ## Clean-slate doctrine | ||
|
|
||
| This Plugin takes **no code, no prompts, no fixtures, and no soft dependency** on `apps/claude-code/pr-review/`. That directory is treated as out of scope. Every module is re-derived from the PRD and ADRs. | ||
|
|
||
| ## Do not add | ||
|
|
||
| - External runtime npm dependencies (zero is the bar — the doctor uses only built-ins) | ||
| - A `LICENSE` file in this directory; per root AGENTS.md the maintainer manages LICENSE files manually | ||
| - An `0010-*.md` ADR file — ADR-0010 is listed as planned in `docs/adr/README.md` but has not yet been merged | ||
| - Any file outside `apps/claude-code/unic-pr-review/` except the one-line entry in the root `CONTEXT-MAP.md` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # Changelog | ||
|
|
||
| All notable changes to this project will be documented in this file. | ||
|
|
||
| The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | ||
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
|
||
| ## [Unreleased] | ||
|
|
||
| ### Breaking | ||
|
|
||
| - (none) | ||
|
|
||
| ### Added | ||
|
|
||
| - (none) | ||
|
|
||
| ### Fixed | ||
|
|
||
| - Test runner now executes credentials.test.mjs in addition to doctor.test.mjs | ||
| - doctor stays fully silent about Jira when jiraUrl is not configured (US-35) | ||
| - realPing degrades gracefully when given a malformed URL instead of crashing the doctor | ||
| - credentials loader distinguishes file-read errors from JSON-parse errors | ||
|
|
||
| ## [2.0.0] — 2026-05-28 | ||
|
|
||
| ### Added | ||
|
|
||
| - Plugin scaffold: `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `package.json`, `tsconfig.json` | ||
| - Domain vocabulary in `CONTEXT.md` (Plugin, Review, Finding, Confidence, Severity, Intent Brief, Intent Check, Bot Signature, Iteration, Approval Loop, Mode, Provider, Work Item, Notice) | ||
| - `/unic-pr-review:doctor` slash command (`commands/doctor.md`) | ||
| - `scripts/doctor.mjs`: six preflight checks — `az` CLI, `azure-devops` extension, `az devops` login, `az devops user show --user me` identity (for ADR-0006 caching), Confluence reachability, Jira reachability (silent when `jiraUrl` is unset per US 35) | ||
| - `scripts/lib/credentials.mjs`: shared loader for `~/.unic-confluence.json` and `~/.unic-azure.json` with env-var overrides | ||
| - `tests/doctor.test.mjs`: unit tests for all six predicates with stubbed executors and fetchers |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| AGENTS.md |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| # unic-pr-review | ||
|
|
||
| A Claude Code Plugin that runs AI-powered PR Reviews with intent checking against Azure Boards / Jira Work Items, emits Confidence-scored Findings, and walks the reviewer through an interactive Approval Loop before any write to the PR. | ||
|
|
||
| ## Language | ||
|
|
||
| **Plugin**: | ||
| The `unic-pr-review` Claude Code Plugin itself; the subject of this context. Ships at `apps/claude-code/unic-pr-review/`. | ||
| _Avoid_: tool, app, integration | ||
|
|
||
| **Review**: | ||
| A complete run of the Plugin against either an Azure DevOps Pull Request (ADO Mode) or a local feature branch (Pre-PR Mode) — from intent gathering through aspect fan-out and Approval Loop to the optional write-back. | ||
| _Avoid_: scan, audit, check | ||
|
|
||
| **Finding**: | ||
| A single code observation emitted by a Review Aspect agent, carrying `{ severity, confidence, filePath, startLine, endLine, title, body, suggestion? }`. | ||
| _Avoid_: comment, issue, note | ||
|
|
||
| **Confidence**: | ||
| A 0-100 integer score attached to every Finding. Findings below 60 are dropped before the reviewer ever sees them (ADR-0002). | ||
| _Avoid_: score, weight, certainty | ||
|
|
||
| **Severity**: | ||
| The bucket derived from Confidence — Critical (90-100), Important (80-89), Minor (60-79). | ||
| _Avoid_: priority, urgency, level | ||
|
|
||
| **Intent Brief**: | ||
| The structured synthesis of Work Item intent (description, Acceptance Criteria or Repro Steps, plus Confluence context) produced by the Intent Checker and passed verbatim as a preamble to every Review Aspect agent. | ||
| _Avoid_: context, summary, brief | ||
|
|
||
| **Intent Check**: | ||
| The per-Acceptance-Criterion verdict block (`addressed` / `partially addressed` / `unaddressed`) rendered at the top of the Review Summary. Omitted when no Work Items are linked (ADR-0004). | ||
| _Avoid_: gap analysis, intent diff, requirements check | ||
|
|
||
| **Bot Signature**: | ||
| The load-bearing footer wording `🤖 Reviewed by Claude Code — Iteration N`, owned solely by `scripts/lib/signature.mjs`. Used for Re-review detection and Iteration counting (ADR-0006). | ||
| _Avoid_: marker, tag, watermark | ||
|
|
||
| **Iteration**: | ||
| The review count for a single PR, stored in the Bot Signature, incremented on each Re-review. | ||
| _Avoid_: pass, round, run | ||
|
|
||
| **Approval Loop**: | ||
| The interactive per-Finding `accept` / `edit` / `skip` flow entered when `--post` is given. Resumable state lives under `<cwd>/.unic-pr-review/<key>/state.json` (ADR-0003). | ||
| _Avoid_: confirmation, prompt, gate | ||
|
|
||
| **Mode**: | ||
| One of `pre-pr`, `first-review`, `re-review`, `first-review-fallback`. Selected at runtime by URL presence and Bot Signature detection (ADR-0009). | ||
| _Avoid_: state, phase, kind | ||
|
|
||
| **Provider**: | ||
| A folder bundle at `providers/<name>/` implementing the Source Platform contract (`parsePrUrl`, `agents.{fetcher, writer}`, `discoverWorkItems`). v2 ships `providers/azure_devops/`; later releases may add GitHub or GitLab. | ||
| _Avoid_: adapter, backend, driver | ||
|
|
||
| **Work Item**: | ||
| A normalised task record `{ id, type, url, raw }` returned by `provider.discoverWorkItems(prMetadata)` — an Azure Boards Work Item, a Jira issue, or a manually pasted URL in Pre-PR Mode. | ||
| _Avoid_: ticket, story, task | ||
|
|
||
| **Notice**: | ||
| A prose block at the top of the Review Summary (before the Intent Check) used for warnings, escalations, and fallback conditions. | ||
| _Avoid_: alert, banner, warning | ||
|
|
||
| ## Relationships | ||
|
|
||
| - A **Review** runs in exactly one **Mode**, decided at startup | ||
| - A **Mode** is selected by the active **Provider**'s URL parsing plus **Bot Signature** detection | ||
| - The Intent Checker turns one or more **Work Items** into a single **Intent Brief** | ||
| - Every Review Aspect agent receives the **Intent Brief** and emits zero or more **Findings** | ||
| - Each **Finding** carries a **Confidence** score that determines its **Severity** bucket | ||
| - The **Approval Loop** mediates between **Findings** and PR write-back | ||
| - The **Bot Signature** records the **Iteration** and lets the next Review detect prior runs | ||
| - A **Notice** can appear above the **Intent Check** when something needs the reviewer's attention | ||
|
|
||
| ## Example dialogue | ||
|
|
||
| > **Dev:** "What happens if a PR links no Work Items at all?" | ||
| > **Domain expert:** "The Intent Check block is just omitted from the Review Summary. Per ADR-0004 the absence of intent is a legitimate state — we only hard-stop if a referenced source is unreachable." | ||
|
|
||
| > **Dev:** "Why does `doctor` verify `az devops user show --user me` and not just `az devops login`?" | ||
| > **Domain expert:** "ADR-0006 stores Iteration state in the PR's own Bot Signature. To detect our own prior comments at Review time the Plugin caches the authenticated ADO user id at startup. If `user show` can't resolve the identity, Re-review detection breaks — so we check it during doctor instead of failing mid-Review." | ||
|
|
||
| > **Dev:** "A Finding came back with Confidence 55. Why didn't I see it in the Summary?" | ||
| > **Domain expert:** "Anything below 60 is filtered out per ADR-0002. That's the noise floor — Minor starts at 60." |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.