Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"name": "unic-spec-review",
"source": "./",
"tags": ["productivity", "quality"],
"version": "0.1.0"
"version": "0.1.1"
}
]
}
3 changes: 2 additions & 1 deletion apps/claude-code/unic-spec-review/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
"name": "Unic AG",
"url": "https://www.unic.com"
},
"agents": ["./agents/gaps-agent.md"],
"commands": ["./commands/review-spec.md", "./commands/spec-doctor.md", "./commands/setup-confluence.md"],
"description": "Adversarial review of web specifications across Confluence pages & comments, Figma designs, and the live system. Produces Confidence-scored, Six-Hats-tagged Findings with an interactive Approval Loop that posts selected comments back to Confluence.",
"homepage": "https://github.com/unic/unic-agents-plugins",
"keywords": ["spec-review", "confluence", "figma", "adversarial-review", "six-hats", "unic"],
"license": "LGPL-3.0-or-later",
"name": "unic-spec-review",
"version": "0.1.0"
"version": "0.1.1"
}
6 changes: 3 additions & 3 deletions apps/claude-code/unic-spec-review/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Guidance for any AI agent working inside this Plugin directory. `CLAUDE.md` in t

`unic-spec-review` is a Claude Code Plugin in the [`unic-agents-plugins`](../../../AGENTS.md) monorepo. It runs an adversarial review of web specifications across four sources (Confluence pages & comments, Figma designs via the Dev Mode MCP, the live production system via the Playwright MCP, and the local repo) and emits Confidence-scored, Six-Hats-tagged Findings. An interactive Approval Loop, gated behind `--post`, publishes selected Findings as Confluence comments.

> Status: scaffolding only. The command/agent logic is specified in the PRD under `docs/issues/` and not yet implemented.
> Status: S1 skeleton implemented (URL classify → Confluence fetch → Gaps agent → report). Full design (traversal, Figma, live-system, Approval Loop, de-dup) is specified in the [PRD](docs/issues/unic-spec-review/PRD.md) and lands in later slices.

## Where to start

Expand Down Expand Up @@ -40,8 +40,8 @@ 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-spec-review@<version> git tag locally
pnpm verify:changelog # check CHANGELOG entry for the current version
pnpm test # run node:test suite
pnpm typecheck # tsc --noEmit type check
```

> `pnpm test` and `pnpm typecheck` (plus `tsconfig.json` and the `scripts/`/`tests/` dirs) will be added back once the first `.mjs` script is vendored during implementation. The plugin is command-only at scaffold time.

Monorepo-wide commands (`pnpm install`, `pnpm check`, `pnpm format`, `pnpm ci:check`) are documented in the [root AGENTS.md](../../../AGENTS.md).
23 changes: 22 additions & 1 deletion apps/claude-code/unic-spec-review/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Breaking

- (none)

### Added
- Cover two previously untested paths flagged in PR #210 review: `loadAtlassianCreds` preferring env vars over a present credentials file, and `fetchConfluencePage` capping the stripped excerpt at 800 characters.

### Fixed
- Reject non-http(s) URLs in arg parsing, link classification, and validate `pageTitle`/`pageUrl` in the report-renderer CLI entry, so ftp/file/mailto inputs no longer slip through and missing report fields no longer render as literal `undefined`.
- Make `/review-spec` orchestration portable: write the scratch report JSON into the gitignored `.spec-review/` directory instead of the POSIX-only `/tmp` path (broke on Windows CI), and surface the structured `errors[].kind`/`errors[].message` from the fetch script so the real failure cause is shown.

### Documentation
- Correct stale cross-plugin references in code comments (drop the `render-summary.mjs`, `doctor.mjs`, and inaccurate `ADR-0001` citations), reword the `CONTEXT.md` status line so it no longer promises an unused `(S1)` per-term marking convention, and replace em dashes with hyphens in authored comments and messages per the org typography rule.

## [0.1.1] — 2026-06-05

### Breaking

- (none)

### Added

- Vendor `atlassian-fetch.mjs` and `credentials.mjs` from `unic-pr-review` (ADR-0001 self-containment); only the Confluence page-read path is used in this slice.
- Add `link-classifier` module: routes a pasted URL to `confluence` / `figma-page` / `figma-frame` / `live` / `unknown` and extracts the Confluence page id.
- Add `args` module: parses `/review-spec` arguments (URL list + `--post` flag recognition).
- Add `report-renderer` module: renders a timestamped markdown report and writes it to `.spec-review/` (gitignored).
- Add `gaps-agent` (Gaps/Completeness dimension agent): inspects a Confluence page for missing states, undefined behaviour, and absent acceptance criteria.
- Implement `/review-spec` S1 skeleton: classify URL, fetch one Confluence page, run Gaps agent, print findings, write report.
- Restore test harness: `pnpm test` and `pnpm typecheck` scripts, `tsconfig.json`, `scripts/` and `tests/` directories.

### Fixed

- (none)
Expand Down
2 changes: 1 addition & 1 deletion apps/claude-code/unic-spec-review/CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Domain vocabulary for the `unic-spec-review` plugin. This is a single bounded context inside the [monorepo context map](../../../CONTEXT-MAP.md).

> Status: scaffolding. The behaviour behind these terms is specified in [`docs/issues/unic-spec-review/PRD.md`](docs/issues/unic-spec-review/PRD.md) and not yet implemented.
> Status: S1 implements classify -> Confluence fetch -> Gaps agent -> report. The rest of the vocabulary below describes the full design specified in [`docs/issues/unic-spec-review/PRD.md`](docs/issues/unic-spec-review/PRD.md).

## Vocabulary

Expand Down
2 changes: 1 addition & 1 deletion apps/claude-code/unic-spec-review/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ Findings are presented for triage first. With `--post`, an interactive Approval

The plugin is fully self-contained: it ships its own `/setup-confluence` wizard and vendored credential handling, so it can be installed and used without any other plugin. It stores credentials in `~/.unic-confluence.json` (the same convention `unic-pr-review` uses, or `CONFLUENCE_*` env vars), so a user with both plugins configures Confluence once. Figma access is via the Figma Dev Mode MCP; live-system access is via the Playwright MCP. Both are discovered at runtime.

> Status: scaffolding. Behaviour is specified in the PRD (`docs/issues/`) and not yet implemented.
> **S1 available:** pass a single Confluence page URL to run a Gaps/Completeness review. Full multi-source adversarial review (Figma, live system, Approval Loop) lands in later slices; see `docs/issues/` for the roadmap.
64 changes: 64 additions & 0 deletions apps/claude-code/unic-spec-review/agents/gaps-agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
name: gaps-agent
description: Gaps/Completeness Agent. Inspects a Confluence spec page for missing states, undefined behaviour, and absent acceptance criteria. Emits structured Findings with Confidence Scores.
model: opus
color: yellow
---

# Gaps / Completeness Agent

You are the Gaps/Completeness reviewer for `unic-spec-review`.

You receive a Confluence spec page (title, URL, and text content). Your job is to identify **gaps and completeness issues**: places where the specification is under-specified, silent, or missing.

Return your output as a single JSON object with the shape below. Output ONLY that JSON object: no prose, no markdown fence, no explanation.

## What to look for

- **Missing states:** what happens when a user does X but condition Y is not met?
- **Undefined behaviour:** actions the spec describes but does not define the outcome of.
- **Missing acceptance criteria:** features or flows with no verifiable success condition.
- **Silent error handling:** the spec says a step happens but never says what happens on failure.
- **Absent edge cases:** boundary conditions the spec does not address (empty state, zero results, maximum limits).
- **Incomplete user journeys:** a flow that starts but has no described end or escape.

## Confidence-Score rubric

Every Finding must carry a Confidence Score from 0 to 100. Drop any Finding below 60; do not include it.

| Range | Severity | When to use |
| ------ | --------- | ------------------------------------------------------- |
| 90-100 | critical | Certain gap that will cause ambiguity or build failures |
| 80-89 | important | High confidence; the spec is definitely incomplete here |
| 60-79 | minor | Real observation but minor or low-impact |
| < 60 | Drop | Do not emit |

## Input format

The calling command provides:

```json
{
"pageTitle": "...",
"pageUrl": "https://...",
"pageContent": "..."
}
```

## Output format

```json
{
"findings": [
{
"title": "short imperative title",
"description": "one or two sentences explaining the gap and its impact",
"severity": "critical | important | minor",
"confidence": 85,
"anchor": "exact verbatim phrase from the spec text where the gap is located, or null"
}
]
}
```

If the spec has no gaps, return `{ "findings": [] }`.
129 changes: 124 additions & 5 deletions apps/claude-code/unic-spec-review/commands/review-spec.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,129 @@
---
description: Adversarial review of web specifications (Confluence + Figma + live system). Read-only by default; --post enables the Approval Loop.
argument-hint: '[confluence/figma/live URLs…] [--post]'
allowed-tools: Agent, Bash(node *), Write
argument-hint: '<confluence-url> [--post]'
description: Adversarial review of web specifications (Confluence). Read-only by default; --post enables the Approval Loop (inert in S1).
---

# Review Spec
# /review-spec (S1 Skeleton)

> ⚠️ Scaffold stub: not yet implemented. Behaviour is specified in the [PRD](../docs/issues/unic-spec-review/PRD.md) (#200); the command body lands with its implementation slice.
Runs a read-only Gaps/Completeness review of one Confluence spec page, prints ranked Findings, and writes a durable timestamped report under `.spec-review/`.

This command will run an adversarial, Six-Hats-tagged review of a web specification and (with `--post`) publish selected Findings as Confluence comments. See `AGENTS.md` for the locked design.
> **S1 scope:** one source, one page, one agent. No traversal, no comments, no Figma, no live-system, no posting. `--post` is recognised but inert.

## Step 1 - Parse arguments

Split `$ARGUMENTS` on whitespace. Collect tokens that parse as valid `http://` or `https://` URLs into `URLS`. Set `IS_POST=true` when `--post` appears.

If `URLS` is empty, stop with:

```
Usage: /review-spec <confluence-page-url> [--post]
Example: /review-spec https://yoursite.atlassian.net/wiki/spaces/X/pages/123456/Title
```

Use `URLS[0]` as `TARGET_URL`.

## Step 2 - Classify the URL

```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/lib/link-classifier.mjs" "$TARGET_URL"
```

Parse the JSON output. If `kind` is not `"confluence"`, stop with:

```
S1 supports only Confluence page URLs.
Got kind: <kind> for <TARGET_URL>

S1 recognises: /wiki/spaces/SPACE/pages/ID/Title or ?pageId=ID
```

Store `PAGE_ID` from the output.

## Step 3 - Fetch the Confluence page

```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/atlassian-fetch.mjs" --urls "$TARGET_URL"
```

Parse the JSON from stdout. The fetch script writes its JSON to stdout **before** exiting non-zero, so a non-zero exit together with the `url === ''` auth-error sentinel is the expected credentials-missing signal - prefer the friendly "credentials not configured" message below over a raw command-failure report.

- If `errors` contains an entry where `kind === 'auth-error'` AND `url === ''`, stop with:
```
Confluence credentials not configured.
Run /unic-spec-review:setup-confluence to add them.
```
- Otherwise, if `errors` contains any entry whose `url === TARGET_URL` (or `url === ''`), stop and print that entry's `errors[0].kind` and `errors[0].message` verbatim, so the real cause (`parse-error` / `unreachable` / `not-found` / `auth-error`) is shown:
```
Could not fetch the Confluence page.
<errors[0].kind>: <errors[0].message>
```
- If `items` is empty (and no matching error was reported), stop and report that the page returned no content.

Extract from `items[0]`:

- `PAGE_TITLE` = `title`
- `PAGE_CONTENT` = `excerpt` (first 800 chars of the page body, HTML-stripped)

## Step 4 - Run the Gaps/Completeness agent

Use the Agent tool to spawn `unic-spec-review:gaps-agent`. Pass as its prompt input:

```json
{
"pageTitle": "<PAGE_TITLE>",
"pageUrl": "<TARGET_URL>",
"pageContent": "<PAGE_CONTENT>"
}
```

Wait for the agent. Parse its JSON response to get the `findings` array. If the response is not valid JSON, print the raw output plus the parse error and stop.

## Step 5 - Print findings conversationally

Sort findings by `confidence` descending (highest first).

For each finding, present:

```
[severity] Finding: <title> (confidence: X%)
<description>
Anchor: <anchor text, if present>
```

If `findings` is empty:

```
No gaps or completeness issues found in this spec.
```

## Step 6 - Write the report

Construct the report input object:

```json
{
"pageTitle": "<PAGE_TITLE>",
"pageUrl": "<TARGET_URL>",
"timestamp": "<current ISO timestamp>",
"findings": [<findings array>]
}
```

Use the **Write tool** to write this JSON to `.spec-review/.report-input.json` (the `.spec-review/` directory is gitignored, so the scratch file stays out of git; writing via the tool avoids shell-quoting issues with apostrophes in page titles, and the path is portable across macOS, Windows, and Linux). Then run:

```bash
REPORT_OUTPUT_DIR=".spec-review" node "${CLAUDE_PLUGIN_ROOT}/scripts/lib/report-renderer.mjs" .spec-review/.report-input.json
```

The script prints the path to the written file. Report it to the user:

```
Report written: .spec-review/spec-review-YYYY-MM-DDTHH-MM-SS.md
```

If `IS_POST` was true, note:

```
Note: --post is not yet active in S1. The report has been saved locally only.
```
9 changes: 7 additions & 2 deletions apps/claude-code/unic-spec-review/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "unic-spec-review",
"version": "0.1.0",
"version": "0.1.1",
"private": true,
"license": "LGPL-3.0-or-later",
"type": "module",
Expand All @@ -13,9 +13,14 @@
"bump": "unic-bump",
"sync-version": "unic-sync-version",
"tag": "unic-tag",
"test": "node --test tests/*.test.mjs",
"typecheck": "tsc --noEmit --project tsconfig.json",
"verify:changelog": "unic-verify-changelog"
},
"devDependencies": {
"@unic/release-tools": "workspace:*"
"@types/node": "catalog:",
"@unic/release-tools": "workspace:*",
"@unic/tsconfig": "workspace:*",
"typescript": "catalog:"
}
}
Loading
Loading