diff --git a/.agents/skills/setup-matt-pocock-skills/triage-labels.md b/.agents/skills/setup-matt-pocock-skills/triage-labels.md index b716855d..376e1e4b 100644 --- a/.agents/skills/setup-matt-pocock-skills/triage-labels.md +++ b/.agents/skills/setup-matt-pocock-skills/triage-labels.md @@ -2,13 +2,13 @@ The skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker. -| Label in mattpocock/skills | Label in our tracker | Meaning | -| -------------------------- | -------------------- | ---------------------------------------- | -| `needs-triage` | `needs-triage` | Maintainer needs to evaluate this issue | -| `needs-info` | `needs-info` | Waiting on reporter for more information | -| `ready-for-agent` | `ready-for-agent` | Fully specified, ready for an AFK agent | -| `ready-for-human` | `ready-for-human` | Requires human implementation | -| `wontfix` | `wontfix` | Will not be actioned | +| Label in our tracker | Meaning | +| -------------------- | ---------------------------------------- | +| `needs-triage` | Maintainer needs to evaluate this issue | +| `needs-info` | Waiting on reporter for more information | +| `ready-for-agent` | Fully specified, ready for an AFK agent | +| `ready-for-human` | Requires human implementation | +| `wontfix` | Will not be actioned | When a skill mentions a role (e.g. "apply the AFK-ready triage label"), use the corresponding label string from this table. diff --git a/.archon/commands/.gitkeep b/.archon/commands/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/.archon/commands/unic-dlc-build.md b/.archon/commands/unic-dlc-build.md new file mode 100644 index 00000000..95ef3f38 --- /dev/null +++ b/.archon/commands/unic-dlc-build.md @@ -0,0 +1,59 @@ +# /unic-dlc-build + +Execute the TDD build workflow for a planning session, enforcing red → green per issue. + +## Usage + +``` +/unic-dlc-build +``` + +Where `` is the session identifier used when you ran `/unic-dlc-plan`. The generated +`.archon/workflows/build-.yaml` must already exist (produced by the `yaml-gen` node in plan). + +## What this command does + +1. **Slopcheck gate** — before any implementation begins, scans `package.json` (and other + manifest files) for packages introduced since the last commit. Each new package is checked + against the npm registry. Packages that fail the check are flagged `[ASSUMED]` and require + explicit human approval before the build can continue. + + Registry check strategy (in order of preference): + + - Python `slopcheck` tool (GSD's slopsquatting gate) if available on `PATH` + - npm registry HEAD request fallback + - If neither is available: all new packages are treated as `[ASSUMED]` (strict default) + + To bypass slopcheck for known-safe cases: `SLOPCHECK_BYPASS=1 /unic-dlc-build ` + +2. **Generated build workflow** — executes `.archon/workflows/build-.yaml` which was + produced by the `yaml-gen` node in `/unic-dlc-plan`. The generated workflow: + - Issues a `code-red` node per issue: writes FAILING acceptance tests + - Issues a `code-green` node per issue: writes minimum implementation to pass those tests + - Enforces `code-red` before `code-green` within each issue via `depends_on` edges + - Runs independent issues' `code-red` (and `code-green`) phases in parallel + +## Prerequisites + +- `/unic-dlc-plan ` must have been run and the plan PR approved +- `.archon/workflows/build-.yaml` must exist +- `.archon/unic-dlc.config.json` must be present (created by the install hook) + +## TDD contract + +Every issue in the build goes through: + +``` +RED: code-red- → write failing acceptance tests +GREEN: code-green- → write minimum implementation to pass those tests +``` + +No `code-green` node may run before its corresponding `code-red` node completes. +Independent issues run their `code-red` and `code-green` phases in parallel, +giving the fastest possible end-to-end build time. + +## Runs + +``` +archon workflow run unic-dlc-build --input slug= +``` diff --git a/.archon/commands/unic-dlc-cleanup.md b/.archon/commands/unic-dlc-cleanup.md new file mode 100644 index 00000000..36497ac2 --- /dev/null +++ b/.archon/commands/unic-dlc-cleanup.md @@ -0,0 +1,61 @@ +# /unic-dlc-cleanup + +Post-merge cleanup for a planning session: architecture review, ADR consolidation, and a +triage pass to refresh project state. + +## Usage + +``` +/unic-dlc-cleanup +``` + +Where `` is the session identifier used throughout the plan → build → qa cycle. + +## What this command does + +1. **`arch-review` node** — reads `docs/workflow//PRD.md` (intent) and + `docs/workflow//report.md` (technical outcome) alongside the changed code. + Detects three categories of drift: + + - **Technical drift**: too-shallow modules, tight coupling, leaky abstractions. + - **Intent drift**: delivered behaviour that diverges from the PRD; silently dropped + acceptance criteria; scope creep added during build. + - **Deepening opportunities**: modules that could hide more complexity behind their + current interface. + + Output: `docs/workflow//arch-review.md` + +2. **`adr-consolidation` interactive node** — presents each proposed ADR individually for + human approval. Sources: + + - "Decisions Made" section of `report.md` + - "Accept as ADR" items from `arch-review.md` + + Each ADR is shown with Context, Decision, and Consequences. The user accepts (A), + rejects (R), or edits (E) each candidate. Only accepted ADRs are written to `docs/adr/`. + +3. **`run-triage` node** — invokes the shared triage workflow by name via + `archon workflow run unic-dlc-triage`. No triage logic is duplicated in the cleanup + workflow. This produces `HANDOFF.md` and updates `docs/workflow/ROADMAP.md` exactly + once per cleanup run. + +## Prerequisites + +- The build and QA cycles for `` must be complete (build PR merged, QA approved) +- `docs/workflow//PRD.md` and `docs/workflow//report.md` must exist +- `.archon/unic-dlc.config.json` must be present + +## Outputs + +| File | Description | +| ------------------------------------- | ----------------------------------------------- | +| `docs/workflow//arch-review.md` | Architecture review with drift findings | +| `docs/adr/NNNN-*.md` | Accepted ADRs (one file per accepted candidate) | +| `HANDOFF.md` | Updated handoff snapshot (from triage) | +| `docs/workflow/ROADMAP.md` | Updated project phase (from triage) | + +## Runs + +``` +archon workflow run unic-dlc-cleanup --input slug= +``` diff --git a/.archon/commands/unic-dlc-explore.md b/.archon/commands/unic-dlc-explore.md new file mode 100644 index 00000000..29ba263e --- /dev/null +++ b/.archon/commands/unic-dlc-explore.md @@ -0,0 +1,54 @@ +--- +description: Run the unic-archon-dlc explore workflow — parallel research across stack, features, architecture, and pitfalls, then synthesize into docs/workflow//findings.md +--- + +# /unic-dlc-explore + +Runs the `explore` workflow: four parallel research agents investigate the project from different angles, then a synthesize node combines their findings into a single `findings.md` document. + +## When to use + +- At the start of a new feature or investigation to build a shared mental model. +- When onboarding to an unfamiliar project or module. +- Before writing a spec, to surface pitfalls and architecture constraints early. +- Any time you want a structured snapshot of what the project is, what it does, and where the risks are. + +## What it produces + +- **`docs/workflow//findings.md`** — five sections: + - **Stack** — runtime, package manager, toolchain + - **Features** — shipped capabilities, in-progress work, planned features + - **Architecture** — directory structure, design patterns, ADR decisions, cross-platform constraints + - **Pitfalls** — TODOs, untested modules, CI issues, HANDOFF.md blockers + - **Integrated Brief** — 3-5 sentence synthesis with the highest-impact next step + +## Usage + +```sh +archon workflow run unic-dlc-explore --input slug= +``` + +Or invoke from Claude Code: + +``` +/unic-dlc-explore +``` + +Replace `` with a short identifier for this exploration (e.g. `auth-refactor`, `v2-planning`). + +## Workflow structure + +``` +research-stack ──┐ +research-features ─┤ + ├──▶ synthesize ──▶ findings.md +research-architecture ─┤ +research-pitfalls ──┘ +``` + +All four research nodes are independent and run in parallel. The `synthesize` node depends on all four and writes the final output. + +## Inspiration + +- Parallel research pattern from the Archon workflow specification. +- This plugin's `lib/findings-writer.mjs` handles idempotent directory and file creation. diff --git a/.archon/commands/unic-dlc-plan.md b/.archon/commands/unic-dlc-plan.md new file mode 100644 index 00000000..a659f25e --- /dev/null +++ b/.archon/commands/unic-dlc-plan.md @@ -0,0 +1,61 @@ +--- +description: Run the unic-archon-dlc plan workflow — adversarial spec interview, PRD synthesis, and human PR gate +--- + +# /unic-dlc-plan + +Runs the `plan` workflow: loads project context and prior research, runs an adversarial interview to surface requirements and decisions, synthesises the transcript into a structured PRD, and opens a PR for human review before proceeding. + +## When to use + +- After `/unic-dlc-explore` to turn research findings into a formal PRD. +- When starting a new feature and you want to stress-test assumptions before writing specs. +- Any time you need a structured `PRD.md` that captures problem, solution, stories, decisions, and scope. + +## What it produces + +- **`docs/workflow//PRD.md`** — seven sections: Problem Statement, Solution, User Stories, Implementation Decisions, Testing Decisions, Out of Scope, Further Notes. +- **`docs/adr/NNNN-.md`** — one or more ADR files for non-obvious decisions surfaced during the interview (written live, confirmed by user). +- **PR** targeting `develop` — pauses until approved. Rejection returns control to the adversarial interview for refinement. + +## Usage + +```sh +archon workflow run unic-dlc-plan --input slug= +``` + +Or invoke from Claude Code: + +``` +/unic-dlc-plan +``` + +Replace `` with a short identifier for this planning session (e.g. `auth-refactor`, `v2-planning`). + +## Options + +Set `workflow.discuss_mode` in `.archon/unic-dlc.config.json` to control the interview style: + +| Value | Behaviour | +| --------------------- | ------------------------------------------------------------------------ | +| `interview` (default) | One focused, adversarial question per turn; probes deeply | +| `assumptions` | Surfaces all implicit assumptions upfront, then confirms or refutes each | + +## Workflow structure + +``` +load-context ──▶ specs (loop) ──▶ to-prd ──▶ prd-gate (interactive) + ▲ │ + └──────── rejected ────────────┘ +``` + +- `load-context` reads CONTEXT.md, CONTEXT-MAP.md, all ADRs, and findings.md (if present). +- `specs` runs the adversarial interview; writes ADRs live for confirmed decisions. +- `to-prd` synthesises the interview transcript into PRD.md. +- `prd-gate` validates all 7 sections, opens a PR, and waits for human approval. + +## Inspiration + +- The `grill-with-docs` skill — adversarial interview pattern against the domain model. +- The `to-prd` skill — structured PRD synthesis from conversation context. +- Archon PR-gate pattern for human-in-the-loop workflow checkpoints. diff --git a/.archon/commands/unic-dlc-qa.md b/.archon/commands/unic-dlc-qa.md new file mode 100644 index 00000000..f44bfbee --- /dev/null +++ b/.archon/commands/unic-dlc-qa.md @@ -0,0 +1,78 @@ +--- +description: Run the unic-archon-dlc QA workflow — e2e tests, coverage gate, UAT checklist, and merge +--- + +# /unic-dlc-qa + +Runs the `qa` workflow: executes end-to-end tests, enforces the coverage threshold, walks through +a UAT checklist derived from the PRD's acceptance criteria, and merges the PR once the human approves. + +## When to use + +- After `/unic-dlc-build ` is complete and the build PR has been reviewed and approved. +- When you want a structured QA gate before merging a feature branch. +- Any time you need to confirm that acceptance criteria are met before shipping. + +## What it produces + +- **e2e results** — pass/fail output from the command configured in `e2e_command`. +- **Coverage report** — pass/fail against the `coverage_threshold` set in `.archon/unic-dlc.config.json`. +- **UAT checklist** — numbered acceptance criteria from `docs/workflow//PRD.md`, presented alongside build coverage evidence. +- **Merged PR** — once UAT is approved, the PR is merged via the configured tracker CLI and the feature branch is cleaned up (Gitflow only). + +## Usage + +```sh +archon workflow run unic-dlc-qa --input slug= +``` + +Or invoke from Claude Code: + +``` +/unic-dlc-qa +``` + +Replace `` with the same identifier used in `/unic-dlc-plan` and `/unic-dlc-build`. + +## Prerequisites + +- `/unic-dlc-build ` must have been run and the build PR approved. +- `.archon/unic-dlc.config.json` must be present (created by the install hook). +- `e2e_command` must be set in the config. If not, run `archon install --reconfigure` to set it. +- The current branch must have an open PR targeting `develop` (for the merge step). + +## Workflow structure + +``` +e2e ──▶ coverage-gate ──▶ uat-gate (interactive) ──▶ merge +``` + +- `e2e` — reads `e2e_command` from config; fails fast with a helpful message if it is not set. +- `coverage-gate` — runs `pnpm test --coverage`; parses the output to compare against `coverage_threshold`. Skipped if no threshold is configured. +- `uat-gate` — presents the numbered UAT checklist; waits for APPROVE or REJECT from the human. +- `merge` — merges the PR via the tracker CLI (gh / az / manual instructions for jira and local-markdown); deletes the feature branch on Gitflow. + +## Configuration reference + +All settings are read from `.archon/unic-dlc.config.json`: + +| Field | Type | Default | Description | +| -------------------- | ------ | ----------- | ------------------------------------------------------------------------ | +| `e2e_command` | string | — | Shell command to run e2e tests (e.g. `"pnpm test:e2e"`) | +| `coverage_threshold` | number | — | Minimum coverage % required (e.g. `80`). Omit to skip the gate. | +| `tracker` | string | `"github"` | Issue tracker: `github`, `ado`, `jira`, `local-markdown` | +| `branching` | string | `"gitflow"` | Branch strategy: `gitflow` (delete feature branch) or `github-flow` | +| `pr_strategy` | string | `"squash"` | GitHub merge style: `squash` or `merge` (used for `github` tracker only) | + +## UAT interaction + +The `uat-gate` node pauses and asks for your decision: + +- Type **`APPROVE`** to proceed to merge. +- Type **`REJECT AC-N`** (e.g. `REJECT AC-3`) to flag a failing criterion. The workflow halts and you are returned to address the issue before re-running. + +## Runs + +``` +archon workflow run unic-dlc-qa --input slug= +``` diff --git a/.archon/commands/unic-dlc-review.md b/.archon/commands/unic-dlc-review.md new file mode 100644 index 00000000..3f016f28 --- /dev/null +++ b/.archon/commands/unic-dlc-review.md @@ -0,0 +1,82 @@ +--- +description: Run the unic-archon-dlc self-contained code review workflow — four aspects, structured findings, single PR comment, idempotent re-run +--- + +# /unic-dlc-review + +Runs the `review` workflow: analyses the current PR diff across four review aspects +(code quality, test coverage, silent failures, type design), then posts — or updates — a +single structured comment on the PR. + +**No runtime dependency on pr-review-toolkit or any other plugin.** +All review logic is self-contained in `.archon/workflows/unic-dlc-review.yaml`. + +## When to use + +- After opening a PR and before requesting human review. +- As a final quality gate before merging. +- Re-run it after addressing feedback — it will **update** the prior comment rather than + posting a duplicate. + +## What it produces + +A single structured PR comment (or updated comment on re-run) with four sections: + +1. **Code quality** — readability, naming, function length, project-convention adherence +2. **Test coverage adequacy** — exercises public interfaces, output-focused assertions, no + internal-collaborator mocks +3. **Silent failure patterns** — swallowed exceptions, empty catch blocks, fallbacks that + hide bugs +4. **Type design quality** — encapsulation, invariants in types, illegal-state-unrepresentable + patterns + +Each section lists specific findings with `file:line` references, or an explicit +"No findings." line if nothing was detected. + +## Usage + +```sh +archon workflow run unic-dlc-review +``` + +Or invoke from Claude Code: + +``` +/unic-dlc-review +``` + +No arguments needed. The workflow reads `.archon/unic-dlc.config.json` to determine the +tracker and the current open PR. + +## Workflow structure + +``` +code-review ──▶ structured comment posted / updated on PR +``` + +Single-node DAG. The node reads CLAUDE.md / AGENTS.md for project conventions, runs the +four review aspects, and calls the tracker adapter to post or update the comment. + +## Re-run behaviour + +When you run `/unic-dlc-review` again on the same PR: + +- The workflow searches for a prior comment whose body contains the sentinel marker + ``. +- If found, it **updates** that comment in-place. +- If not found, it creates a new comment. + +This prevents duplicate review threads accumulating over multiple runs. + +## Inspiration + +- `apps/claude-code/pr-review/` — multi-aspect analysis structure, compact finding + schema (`severity / filePath / startLine / endLine / title / body`), re-review + detection via sentinel, and the discipline of posting a single summary comment rather + than many inline threads. +- Matt Pocock's review skill + (https://github.com/mattpocock/skills/blob/main/skills/in-progress/review/SKILL.md) — + aspect-driven review structure, explicit "no findings" lines, and the principle that + every run should produce actionable output even when everything looks good. +- This plugin's `lib/tracker-adapter.mjs` — used to post or update the comment via the + configured tracker backend (github / ado / jira / local-markdown). diff --git a/.archon/commands/unic-dlc-triage.md b/.archon/commands/unic-dlc-triage.md new file mode 100644 index 00000000..e0eb8ad2 --- /dev/null +++ b/.archon/commands/unic-dlc-triage.md @@ -0,0 +1,35 @@ +--- +description: Run the unic-archon-dlc triage workflow — produces HANDOFF.md and updates ROADMAP.md +--- + +# /unic-dlc-triage + +Runs the `triage` workflow: reads current issue states from the configured tracker, reconciles them against `docs/workflow/ROADMAP.md`, and produces `HANDOFF.md` at the repo root. + +## When to use + +- After a session boundary to resume cleanly in a fresh context. +- As the final step of the `/unic-dlc-cleanup` workflow (reused by the cleanup DAG). +- Any time you want a status snapshot of open issues, blockers, and recent decisions. + +## What it produces + +- **`HANDOFF.md`** (repo root) — four sections: current phase, open issues by state, blockers, recent decisions. +- **`docs/workflow/ROADMAP.md`** — created on first run; phase status updated on each run. Human-edited sections are preserved. + +## Usage + +```sh +archon workflow run unic-dlc-triage +``` + +Or invoke from Claude Code: + +``` +/unic-dlc-triage +``` + +## Inspiration + +- Matt Pocock skills repo — `/triage` skill pattern. +- This plugin's `docs/agents/` files (written by the install hook) provide the domain context consumed by the triage prompt nodes. diff --git a/.archon/unic-dlc.config.json b/.archon/unic-dlc.config.json new file mode 100644 index 00000000..4db29997 --- /dev/null +++ b/.archon/unic-dlc.config.json @@ -0,0 +1,36 @@ +{ + "model_profile": "balanced", + "tdd_mode": true, + "nyquist_validation": true, + "slopsquatting_gate": true, + "tracker": "github", + "pr_strategy": "merge", + "branching": "gitflow", + "e2e_command": null, + "repo_layout": "multi-context", + "labels": { + "state": { + "needs-triage": "needs-triage", + "needs-info": "needs-info", + "needs-specs": "needs-specs", + "ready-for-agent": "ready-for-agent", + "ready-for-human": "ready-for-human", + "resolved": "resolved", + "closed": "closed", + "rejected": "rejected" + }, + "type": { + "feature": "feature", + "bug": "bug", + "spike": "spike", + "tech-debt": "tech-debt", + "docs": "docs" + }, + "priority": { + "p0": "p0", + "p1": "p1", + "p2": "p2", + "p3": "p3" + } + } +} diff --git a/apps/claude-code/unic-archon-dlc/.archon/workflows/build.yaml b/.archon/workflows/unic-dlc-build.yaml similarity index 98% rename from apps/claude-code/unic-archon-dlc/.archon/workflows/build.yaml rename to .archon/workflows/unic-dlc-build.yaml index da2433a9..37bc35fc 100644 --- a/apps/claude-code/unic-archon-dlc/.archon/workflows/build.yaml +++ b/.archon/workflows/unic-dlc-build.yaml @@ -13,6 +13,7 @@ nodes: - id: slopcheck name: Slopcheck — Verify New Packages type: bash + runtime: bun depends_on: [] script: | #!/usr/bin/env node @@ -130,8 +131,8 @@ nodes: "build-{{ inputs.slug }}.yaml not found. Run /unic-dlc-plan {{ inputs.slug }} first to generate it." and halt. - 2. Invoke the generated workflow via Archon: - Run: archon run .archon/workflows/build-{{ inputs.slug }}.yaml --input slug={{ inputs.slug }} + 2. Invoke the generated workflow via Archon by name: + Run: archon workflow run unic-dlc-build-{{ inputs.slug }} --input slug={{ inputs.slug }} The generated workflow contains: - code-red- nodes: write FAILING acceptance tests per issue @@ -152,6 +153,7 @@ nodes: - id: verification name: Verification — Test Suite, Stubs, Wiring type: bash + runtime: bun depends_on: [run-build] script: | #!/usr/bin/env node diff --git a/apps/claude-code/unic-archon-dlc/.archon/workflows/cleanup.yaml b/.archon/workflows/unic-dlc-cleanup.yaml similarity index 97% rename from apps/claude-code/unic-archon-dlc/.archon/workflows/cleanup.yaml rename to .archon/workflows/unic-dlc-cleanup.yaml index eb6d54b6..7cbc946e 100644 --- a/apps/claude-code/unic-archon-dlc/.archon/workflows/cleanup.yaml +++ b/.archon/workflows/unic-dlc-cleanup.yaml @@ -139,6 +139,7 @@ nodes: - id: run-triage name: Run Triage — Refresh Project State type: bash + runtime: bun depends_on: [adr-consolidation] script: | #!/usr/bin/env node @@ -147,11 +148,11 @@ nodes: import { execFileSync } from 'node:child_process' try { - execFileSync('archon', ['run', '.archon/workflows/triage.yaml'], { + execFileSync('archon', ['workflow', 'run', 'unic-dlc-triage'], { stdio: 'inherit', env: { ...process.env }, }) } catch (err) { - console.error('run-triage: archon run failed:', err.message) + console.error('run-triage: archon workflow run failed:', err.message) process.exit(1) } diff --git a/apps/claude-code/unic-archon-dlc/.archon/workflows/explore.yaml b/.archon/workflows/unic-dlc-explore.yaml similarity index 100% rename from apps/claude-code/unic-archon-dlc/.archon/workflows/explore.yaml rename to .archon/workflows/unic-dlc-explore.yaml diff --git a/apps/claude-code/unic-archon-dlc/.archon/workflows/plan.yaml b/.archon/workflows/unic-dlc-plan.yaml similarity index 99% rename from apps/claude-code/unic-archon-dlc/.archon/workflows/plan.yaml rename to .archon/workflows/unic-dlc-plan.yaml index 6c127069..5c79b155 100644 --- a/apps/claude-code/unic-archon-dlc/.archon/workflows/plan.yaml +++ b/.archon/workflows/unic-dlc-plan.yaml @@ -344,6 +344,7 @@ nodes: - id: yaml-gen name: YAML Gen — Build Workflow Generator type: bash + runtime: bun depends_on: [plan-checker] script: | #!/usr/bin/env node diff --git a/apps/claude-code/unic-archon-dlc/.archon/workflows/qa.yaml b/.archon/workflows/unic-dlc-qa.yaml similarity index 99% rename from apps/claude-code/unic-archon-dlc/.archon/workflows/qa.yaml rename to .archon/workflows/unic-dlc-qa.yaml index 3146594b..dcf50f18 100644 --- a/apps/claude-code/unic-archon-dlc/.archon/workflows/qa.yaml +++ b/.archon/workflows/unic-dlc-qa.yaml @@ -12,6 +12,7 @@ nodes: - id: e2e name: End-to-End Tests type: bash + runtime: bun depends_on: [] script: | #!/usr/bin/env node @@ -61,6 +62,7 @@ nodes: - id: coverage-gate name: Coverage Gate type: bash + runtime: bun depends_on: [e2e] script: | #!/usr/bin/env node @@ -191,6 +193,7 @@ nodes: - id: verify-pr-base name: Verify PR Base Branch type: bash + runtime: bun depends_on: [uat-gate] script: | #!/usr/bin/env node @@ -253,6 +256,7 @@ nodes: - id: merge name: Merge PR type: bash + runtime: bun depends_on: [verify-pr-base] script: | #!/usr/bin/env node diff --git a/apps/claude-code/unic-archon-dlc/.archon/workflows/review.yaml b/.archon/workflows/unic-dlc-review.yaml similarity index 100% rename from apps/claude-code/unic-archon-dlc/.archon/workflows/review.yaml rename to .archon/workflows/unic-dlc-review.yaml diff --git a/apps/claude-code/unic-archon-dlc/.archon/workflows/triage.yaml b/.archon/workflows/unic-dlc-triage.yaml similarity index 100% rename from apps/claude-code/unic-archon-dlc/.archon/workflows/triage.yaml rename to .archon/workflows/unic-dlc-triage.yaml diff --git a/.claude/commands/inbox.md b/.claude/commands/inbox.md deleted file mode 100644 index 9b0d9608..00000000 --- a/.claude/commands/inbox.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -allowed-tools: [Write, Bash] -argument-hint: '' -description: 'Capture a raw idea into docs/inbox/ without interrupting the current conversation' ---- - -# Inbox capture - -**Arguments:** "$ARGUMENTS" - -Capture the idea in `$ARGUMENTS` as a file in `docs/inbox/`. Act immediately — no follow-up -questions. - -## Step 1 — Generate a slug - -From the idea text: - -1. Lowercase everything -2. Replace spaces and punctuation with hyphens -3. Collapse multiple hyphens into one -4. Strip leading/trailing hyphens -5. Truncate to 50 characters at a word boundary - -Examples: - -- `"pr-review should support GitLab!"` → `pr-review-should-support-gitlab` -- `"add dark mode support to the dashboard component"` → `add-dark-mode-support-to-the-dashboard-component` -- `"implement user authentication with OAuth2 and role-based access control"` → `implement-user-authentication-with-oauth2-and` (truncated at word boundary before 50 chars) - -## Step 2 — Check for collisions - -```bash -node -e " - const root = require('child_process').execSync('git rev-parse --show-toplevel').toString().trim(); - const p = require('path').join(root, 'docs', 'inbox', '.md'); - process.exit(require('fs').existsSync(p) ? 1 : 0); -" -``` - -If the file exists, append `-2` (then `-3`, etc.) until the path is free. - -## Step 3 — Write the file - -Resolve the repo root with `git rev-parse --show-toplevel`, then create `/docs/inbox/.md`: - -```markdown ---- -title: -created: ---- - - -``` - -Use the `Write` tool. Do not create any other files. - -## Step 4 — Confirm - -Reply with exactly one line: - -```txt -Captured → docs/inbox/.md -``` - -Nothing else. No summary, no next steps, no follow-up questions. The user is in the middle -of something else. diff --git a/.claude/settings.json b/.claude/settings.json index 5e66f824..32909885 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,23 +1,35 @@ { + "permissions": { + "allow": [ + "Bash(pnpm --filter * test)", + "Bash(pnpm bump *)", + "Bash(pnpm check *)", + "Bash(pnpm ci:check)", + "Bash(pnpm format *)", + "Bash(pnpm typecheck *)", + "Skill(archon)", + "Skill(commit-commands:commit)" + ] + }, "hooks": { - "PreToolUse": [ + "PostToolUse": [ { "matcher": "Write|Edit|MultiEdit", "hooks": [ { "type": "command", - "command": "node .claude/hooks/block-lockfile.mjs" + "command": "node .claude/hooks/test-on-edit.mjs" } ] } ], - "PostToolUse": [ + "PreToolUse": [ { "matcher": "Write|Edit|MultiEdit", "hooks": [ { "type": "command", - "command": "node .claude/hooks/test-on-edit.mjs" + "command": "node .claude/hooks/block-lockfile.mjs" } ] } diff --git a/.claude/skills/implement-feature/SKILL.md b/.claude/skills/implement-feature/SKILL.md deleted file mode 100644 index 28ef8ab3..00000000 --- a/.claude/skills/implement-feature/SKILL.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -name: implement-feature -argument-hint: '[slug]' -description: This skill should be used when the user asks to "implement a feature", "run the Feature Runner", "/implement-feature", "implement all issues for ", or "drain the issue queue overnight". Automates the implementation side of the AI-development cycle for one Feature: creates an isolated worktree and branch, runs /tdd on every ready-for-agent issue in dependency order, and opens a PR when done. ---- - -# Implement Feature - -Automate the implementation side of the AI-development cycle for one Feature. Takes a slug, creates an isolated branch, runs `/tdd` on every `ready-for-agent` issue in dependency order, and marks each `resolved` on success. - -**Invocation:** `/implement-feature [slug]` - -## Quick start - -- **Named run** — `/implement-feature pr-review-doc-context-enrichment` — targets a specific Feature slug directly; creates a worktree, runs all `ready-for-agent` issues, opens a PR. -- **Auto-select** — `/implement-feature` with no argument — scans `docs/issues/` and picks the first Feature alphabetically that has at least one `ready-for-agent` issue and no unprepped issues (`needs-triage`, `needs-info`, `needs-specs`). Picks up partial features after a failure fix automatically. -- **Overnight loop** — `/loop /implement-feature` — drains the queue unattended; the runner emits `LOOP_COMPLETE` when no qualifying Feature remains, which terminates the loop. -- **Safe to interrupt** — Ctrl+C during any issue leaves that issue at `ready-for-agent`; re-running resumes from the first unresolved issue. Note: a **/tdd failure** (as opposed to a Ctrl+C interrupt) sets the failing issue to `needs-info`, preventing auto-select from retrying until the developer intervenes. - -## Steps - -### 0. Resolve the slug - -**If a slug argument was provided**, use it directly and proceed to step 1. - -**If no argument was provided**, scan `docs/issues/` for qualifying features: - -1. Use the Bash tool to list immediate subdirectories of `docs/issues/`: - -``` -ls -d docs/issues/*/ -``` - -2. For each subdirectory (potential feature slug), use the Bash tool to list its `NN-*.md` files and use the Read tool to check the `**Status:**` line of each one. A feature **qualifies** if: - - - At least one `NN-*.md` file has status `ready-for-agent`, **and** - - Every `NN-*.md` file has a status in `{ready-for-agent, resolved, closed, rejected, ready-for-human}`. - - Any file with status `needs-triage`, `needs-info`, `needs-specs`, or any unrecognised state **disqualifies the whole feature** — it is not fully prepped for autonomous execution. Features where every file is `resolved`, `closed`, or `rejected` (nothing left to run) are also skipped. - -3. Sort the qualifying slugs alphabetically and select the first one. - -4. **If no qualifying feature exists**, emit the **LOOP_COMPLETE signal** (see `references/runner-output-formats.md`) on its own line and exit cleanly (no error). Do not output anything after it. - -5. **If a qualifying feature was found**, set the slug to that feature's directory name and continue to step 1. - -### 1. Resolve the feature directory and assemble the static context bundle - -The slug argument maps directly to `docs/issues//`. Use the Bash tool to confirm: - -1. The directory exists (e.g. `ls docs/issues//`). -2. It contains at least one `NN-*.md` file (e.g. `ls docs/issues//[0-9]*.md`). -3. At least one of those files has `**Status:** ready-for-agent` (use the Read tool on each file and inspect the `**Status:**` line). - -If any of these checks fails, stop and report the specific reason to the user. Do not create a worktree. - -**Read the PRD:** `docs/issues//PRD.md`. Scan its content for references matching `apps/claude-code//` (any path that starts with that prefix). This determines the ADR scope: - -- **Plugin feature** — one or more `apps/claude-code//` references found → use that plugin's `apps/claude-code//CONTEXT.md` and `apps/claude-code//docs/adr/`. Do **not** also inject root ADRs. -- **Repo/tooling feature** — no such references found → use root `CONTEXT.md` and root `docs/adr/`. - -Also extract the `title:` field from the PRD's YAML frontmatter (the value between the opening `---` and closing `---` at the top of the file). Retain it for use in step 7's PR title derivation. - -**Read the scoped CONTEXT.md** using the Read tool. - -**Read all ADR files** in the scoped ADR directory: list `*.md` files using the Bash tool, then read each one using the Read tool. - -**Get the last 5 git commits** using the Bash tool: - -``` -git log --oneline -5 -``` - -These items (PRD content + title, CONTEXT.md, ADRs, recent commits) are static — gather them once before the issue loop begins. - -### 2. Create the worktree and branch - -First, check whether a worktree from a prior run already exists using the Bash tool: - -``` -ls .claude/worktrees/ -``` - -- **Exists** — reuse it. The branch `feature/afk/` already contains the committed work from the previous run. Skip `git worktree add`. -- **Does not exist** — create it using the Bash tool: - -``` -git worktree add .claude/worktrees/ -b feature/afk/ develop -``` - -The worktree lands at `.claude/worktrees/`. All subsequent implementation work happens inside that worktree. - -### 3. Collect issues, build the dependency graph, and derive execution order - -Use the Bash tool to list **all** `NN-*.md` files in `docs/issues//` (including `resolved` and `closed` — they are needed for graph completeness): - -``` -ls docs/issues//[0-9]*.md -``` - -Use the Read tool to read each file. For every file record: - -- Its **numeric prefix** (the `NN` integer from the filename). -- Its **status** (`**Status:**` line). -- Its **`## Blocked by`** list — the filenames or paths referenced there. `## Blocked by: None`, `## Blocked by: None — can start immediately`, or a missing `## Blocked by` section all mean no predecessors. - -**Missing-blocker check — halt before executing anything if violated:** - -For each `## Blocked by` reference, verify the referenced filename actually exists in `docs/issues//`. If a referenced blocker file is missing (typo, renamed, deleted), halt immediately with the **missing blocker error** (see `references/runner-output-formats.md`), naming the issue and the unresolvable reference. Do not silently treat it as satisfied. - -**Conflict check — halt before executing anything if violated:** - -For each issue A that lists issue B in `## Blocked by`: if B's numeric prefix is greater than A's numeric prefix, the dependency contradicts numerical convention. Halt immediately with the **dependency conflict error** (see `references/runner-output-formats.md`), naming both issues. - -**Build the execution queue:** - -From the dependency graph, compute a topological order over all issues (using `## Blocked by` edges). Filter the topological sequence to only `ready-for-agent` issues — `resolved`, `closed`, and `rejected` issues are satisfied and act as satisfied dependency nodes, not as items to execute. - -**Unsatisfied dependency check — halt before executing anything if violated:** - -For each `ready-for-agent` issue in the execution queue, inspect its `## Blocked by` list. If any listed blocker has status `ready-for-human`, halt immediately with the **unsatisfied dependency error** (see `references/runner-output-formats.md`), naming both issues. - -This ordered list is the execution queue. Record M = number of items in the queue (frozen at this moment — do not recount mid-run). - -### 4. Implement each issue via `/tdd` - -For each issue file in queue order (N = 1, 2, … M), before invoking `/tdd`, emit the **progress line** (see `references/runner-output-formats.md`) substituting N, M, and the issue title (first `# Heading` line of the issue file). - -Invoke the sub-agent using the Agent tool with `subagent_type: general-purpose` — the only stock type with access to both the Skill tool (to load `/tdd`) and the Edit/Write tools (to write code). The issue's `## Acceptance criteria` replaces the interactive planning phase — pass it as the pre-approved plan so the agent skips confirmation and proceeds directly to implementation. - -Before constructing the prompt, use the Read tool to read all sibling issue files (`docs/issues//[0-9]*.md` except the current issue) at their current state — this gives the sub-agent visibility into what is already resolved and what is still pending. - -Construct the prompt using the template in `references/tdd-prompt-template.md`, substituting all `` values at runtime. Pass the constructed prompt to the Agent tool. Wait for the agent to return before continuing. - -**On failure:** If the Agent call signals failure (throws, returns an error, or explicitly reports it could not complete the issue): - -1. Using the Edit tool, change the `**Status:** ready-for-agent` line to `**Status:** needs-info`. This prevents auto-select from picking up this Feature on subsequent loop iterations. - -2. Append the **failure note** (see `references/runner-output-formats.md`) to the issue file using the Edit tool, substituting ``. - -3. Stop the runner immediately. Do not execute any subsequent issues — they may depend on a foundation this issue was meant to lay. - -4. Report to the user: which issue failed, that the worktree is at `.claude/worktrees/` on branch `feature/afk/`, and that no subsequent issues were run. - -### 5. Mark each issue resolved - -After the Agent call for an issue returns **successfully**, update the issue file using the Edit tool: change the `**Status:** ready-for-agent` line to `**Status:** resolved`. - -### 6. Continue until queue is empty - -Repeat steps 4–5 for every issue in the queue. When the last issue is resolved, proceed to step 7. - -### 7. Open a pull request and clean up - -**Push the branch:** - -``` -git -C .claude/worktrees/ push -u origin feature/afk/ -``` - -**Derive the PR title** from the PRD's `title` frontmatter field (already read in step 1) and the slug: - -``` -feat(): -``` - -**List the resolved issues** — all `NN-*.md` files in `docs/issues//` whose status is now `resolved` (every issue the runner just processed, in numerical order). - -**Open the PR** using the Bash tool. The exact `gh pr create` invocation with the heredoc-wrapped body lives in `references/runner-output-formats.md` under "PR body template" — use that form verbatim, substituting ``, ``, and the resolved-issue list before running it. Run from inside the worktree (`git -C .claude/worktrees/`) or pass `--repo` if needed. **Do not run the snippet without substitution** — angle-bracket placeholders are not valid shell. - -**Failure handling for steps 7a and 7b:** If `git push` or `gh pr create` fails (non-zero exit, network error, permission denied, branch protection, etc.): - -1. Stop immediately. Do **not** remove the worktree. -2. Report to the user: which command failed, the error output, that the worktree is at `.claude/worktrees/` on branch `feature/afk/`, and that all issues are still `resolved` (the failure is post-implementation). -3. Suggest re-running `git push` / `gh pr create` manually once the cause is resolved. - -**Remove the worktree** only after the PR is opened successfully (PR URL returned by `gh`): - -``` -git worktree remove .claude/worktrees/ -``` - -Report the PR URL and the list of resolved issues to the user. - -## Supporting Documentation - -- **`references/runner-output-formats.md`** — verbatim strings for the progress line, dependency conflict error, unsatisfied dependency error, failure note, PR body template, and `LOOP_COMPLETE` signal. -- **`references/tdd-prompt-template.md`** — the AFK prompt template passed to the Agent tool for each `/tdd` sub-agent invocation; substitute all `` values at runtime. -- **`docs/agents/feature-runner.md`** — human-facing reference: lifecycle diagram, dependency-satisfaction matrix, ADR scope, historical cleanup convention. Maintained in parallel; consult for broader context, not for runtime instructions. diff --git a/.claude/skills/implement-feature/references/runner-output-formats.md b/.claude/skills/implement-feature/references/runner-output-formats.md deleted file mode 100644 index 23ae43fd..00000000 --- a/.claude/skills/implement-feature/references/runner-output-formats.md +++ /dev/null @@ -1,106 +0,0 @@ -# Runner output formats - -Verbatim strings emitted or embedded by the Feature Runner. `SKILL.md` references this file by name rather than repeating these strings inline. - ---- - -## Progress line - -Emitted to the user before each `/tdd` invocation. - -``` -Implementing issue N of M: -``` - ---- - -## Missing blocker error - -Emitted when a `## Blocked by` reference points to a filename that does not exist in `docs/issues//`. The runner halts before executing any issue. - -``` -Feature Runner error: missing blocker reference. - Issue NN- lists "" in ## Blocked by, but that file does not exist in docs/issues//. - Check for a typo, a rename, or a deleted issue. Resolve the reference manually before re-running. -``` - ---- - -## Dependency conflict error - -Emitted when a `## Blocked by` reference points to an issue with a higher numeric prefix than the issue being blocked. The runner halts before executing any issue. - -``` -Feature Runner error: dependency conflict detected. - Issue NN- is blocked by NN-, but NN- has a higher number than NN-. - This conflicts with the numerical ordering convention. Resolve the ordering manually before re-running. -``` - ---- - -## Unsatisfied dependency error - -Emitted when a `ready-for-agent` issue in the execution queue has a `## Blocked by` dependency whose status is `ready-for-human`. The runner halts before executing any issue. - -``` -Feature Runner error: unsatisfied dependency. - Issue NN- is blocked by NN-, but NN- has status ready-for-human. - Complete issue NN- manually (or update its status) before re-running /implement-feature . -``` - ---- - -## Failure note - -Appended to a failing issue file under `## Comments` when `/tdd` cannot complete an issue. The `**Status:**` line is also changed to `needs-info` (see SKILL.md step 4). - -```markdown -## Comments - -> _This was generated by AI during triage._ - -**Feature Runner failure** — `/tdd` could not complete this issue. Status has been set to `needs-info`. - -The worktree at `.claude/worktrees/` has been left in place for inspection. Once the issue is resolved manually, restore `**Status:** ready-for-agent` and re-run `/implement-feature ` to resume. Alternatively, close or reject the issue if it should not be retried. -``` - ---- - -## PR body template - -The body passed to `gh pr create` after all issues in a feature are resolved. - -```markdown -## Feature - -`docs/issues//PRD.md` - -## Resolved issues - -- `docs/issues//NN-.md` -- ... - -🤖 Implemented by the Feature Runner via `/implement-feature ` -``` - -Pass via a bash heredoc: - -``` -gh pr create \ - --base develop \ - --title "feat(): " \ - --body "$(cat <<'EOF' - -EOF -)" -``` - ---- - -## LOOP_COMPLETE signal - -Emitted on its own line when no qualifying feature exists during auto-selection. Must appear alone — nothing before or after it on the same line. This is the stop signal that `/loop /implement-feature` uses to terminate an overnight draining run. - -``` -LOOP_COMPLETE -``` diff --git a/.claude/skills/implement-feature/references/tdd-prompt-template.md b/.claude/skills/implement-feature/references/tdd-prompt-template.md deleted file mode 100644 index ff4a8d9d..00000000 --- a/.claude/skills/implement-feature/references/tdd-prompt-template.md +++ /dev/null @@ -1,27 +0,0 @@ -# /tdd AFK prompt template - -Passed to the Agent tool for each `/tdd` sub-agent invocation. All `` values are substituted at runtime before the prompt is sent. - -``` -You are running `/tdd` in AFK mode. The interactive planning phase is complete — do not ask for confirmation. Begin by invoking the `tdd` skill via the Skill tool to load its full procedural guidance (red→green→refactor, vertical-slice rule, deep-modules / interface-design / refactoring sub-references), then follow it using the acceptance criteria below as the pre-approved plan and proceed directly to the red→green→refactor loop. - -Working directory: .claude/worktrees/ - ---- ISSUE --- - - ---- PRD (parent context) --- - - ---- SIBLING ISSUES --- - - ---- CONTEXT.md --- - - ---- ADRs --- - - ---- RECENT COMMITS (last 5) --- - -``` diff --git a/.claude/skills/new-plugin/SKILL.md b/.claude/skills/new-plugin/SKILL.md index 6ac564c8..932e45d8 100644 --- a/.claude/skills/new-plugin/SKILL.md +++ b/.claude/skills/new-plugin/SKILL.md @@ -82,18 +82,12 @@ Only include if the plugin registers hooks. } ``` -**`ralph.yml`** — copy from `apps/claude-code/auto-format/ralph.yml`, replace the comment header plugin name. - -**`PROMPT.md`** — minimal stub: `# — Ralph Prompt\n\nDescribe the task here.` - **`CHANGELOG.md`** — use the exact format from `apps/claude-code/auto-format/CHANGELOG.md` as template. Include only `## [Unreleased]` with empty Breaking/Added/Fixed subsections — no historical version entry yet. **`README.md`** — one-paragraph description of what the plugin does. **`CLAUDE.md`** — plugin-specific guidance (not a symlink at the plugin level; see `auto-format/CLAUDE.md` for structure). -**`docs/plans/README.md`** — stub with: `# Spec Roadmap\n\nSpec files for this plugin go here.` - **`scripts/`** and **`tests/`** — empty directories, only if the plugin has scripts or tests. ## Bundled resources diff --git a/.claude/skills/new-plugin/references/package-json-template.md b/.claude/skills/new-plugin/references/package-json-template.md index 64b77ba4..188fc03f 100644 --- a/.claude/skills/new-plugin/references/package-json-template.md +++ b/.claude/skills/new-plugin/references/package-json-template.md @@ -19,11 +19,9 @@ Use this as the starting shape for a new plugin's `package.json`. Copy `packageM "bump": "unic-bump", "sync-version": "unic-sync-version", "tag": "unic-tag", - "verify:changelog": "unic-verify-changelog", - "ralph": "ralph run -c ralph.yml -H builtin:code-assist" + "verify:changelog": "unic-verify-changelog" }, "devDependencies": { - "@ralph-orchestrator/ralph-cli": "catalog:", "@types/node": "catalog:", "@unic/release-tools": "workspace:*", "@unic/tsconfig": "workspace:*", @@ -51,11 +49,9 @@ Omit `test`, `typecheck`, and the `@types/node`/`@unic/tsconfig`/`typescript` de "bump": "unic-bump", "sync-version": "unic-sync-version", "tag": "unic-tag", - "verify:changelog": "unic-verify-changelog", - "ralph": "ralph run -c ralph.yml -H builtin:code-assist" + "verify:changelog": "unic-verify-changelog" }, "devDependencies": { - "@ralph-orchestrator/ralph-cli": "catalog:", "@unic/release-tools": "workspace:*" } } diff --git a/.claude/skills/verify-spec/SKILL.md b/.claude/skills/verify-spec/SKILL.md index 9a5a4eea..e121f3ab 100644 --- a/.claude/skills/verify-spec/SKILL.md +++ b/.claude/skills/verify-spec/SKILL.md @@ -1,7 +1,7 @@ --- name: verify-spec -description: This skill should be used when the user asks to "verify spec 15", "check acceptance criteria for spec N", "is spec 14 ready to merge", "run verify-spec on 08", "check if spec 15 is done", or invokes /verify-spec with a spec number or filename. Locates the matching spec file and checks every acceptance criterion against the current codebase. -argument-hint: ' (e.g. 15 or 15-release-tools-tests.md)' +description: This skill should be used when the user asks to "verify spec auto-format-config", "check acceptance criteria for pr-review-rereview", "is pr-review-ado-fetcher-reliability ready to merge", "run verify-spec on unic-archon-dlc", or invokes /verify-spec with an issue slug or partial name. Locates the matching PRD file in docs/issues/ and checks every acceptance criterion against the current codebase. +argument-hint: ' (e.g. auto-format-config or pr-review-rereview)' user-invocable: true --- @@ -13,24 +13,26 @@ Verify that all acceptance criteria in a spec file are satisfied by the current `$ARGUMENTS` is one of: -- A bare spec number: `15` -- A full filename: `15-release-tools-tests.md` -- A partial name: `release-tools` +- A full issue slug: `auto-format-config` +- A partial slug: `auto-format` (substring match) +- A done sub-task filename: `01-end-to-end-notice-pipeline.md` ## Locating the spec file +Spec files live in `docs/issues/` as `/PRD.md`. Completed vertical-slice sub-tasks live under `docs/issues//done/NN-title.md`. + Search in order: -1. `docs/plans/` at the repo root -2. `apps/claude-code//docs/plans/` +1. `docs/issues/` at the repo root — match `/PRD.md` +2. `apps/claude-code//docs/issues/` — same structure Matching rules: -- **Bare number** (`15`, `1`): interpret as an exact numeric prefix. `15` matches `15-*` only; `1` matches `01-*` only (left-zero-pad to two digits). It does NOT substring-match `10-`, `11-`, etc. -- **Partial name** (`release-tools`): substring match against the filename. -- **Full filename** (`15-release-tools-tests.md`): exact match. +- **Full slug** (`auto-format-config`): look for `docs/issues/auto-format-config/PRD.md`. +- **Partial slug** (`auto-format`): substring match against slug directory names; list all matches and ask which to use if more than one. +- **Done sub-task filename** (`01-end-to-end-notice-pipeline.md` or bare `01`): search `done/` sub-directories under matching slugs. -If more than one file matches, list the candidates and ask which to use. If no file matches, report that clearly and stop. +If no file matches, report that clearly and stop. ## Spec file format diff --git a/.claude/skills/verify-spec/references/spec-format.md b/.claude/skills/verify-spec/references/spec-format.md index db317bfe..011e9beb 100644 --- a/.claude/skills/verify-spec/references/spec-format.md +++ b/.claude/skills/verify-spec/references/spec-format.md @@ -1,15 +1,24 @@ # Spec File Format Reference -All spec files under `docs/plans/` (root or plugin-level) follow this template. +Spec files live under `docs/issues/` (root or plugin-level) and follow this structure. -## File naming +## File layout + +### Top-level PRD (primary intake format) + +``` +docs/issues//PRD.md +``` + +`` is a kebab-case identifier matching the GitHub Issue title. Example: `auto-format-config/PRD.md`. + +### Done sub-tasks (vertical slices completed within a PRD) ``` -NN-kebab-case-title.md +docs/issues//done/NN-kebab-case-title.md ``` -`NN` is a zero-padded two-digit or three-digit number (e.g. `00`, `09`, `15`). The title slug is -kebab-case and matches the spec title. Example: `15-release-tools-tests.md`. +`NN` is a zero-padded two-digit number. Example: `done/01-end-to-end-notice-pipeline.md`. ## Full template diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f3f3ed0..452d883a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,8 @@ jobs: needs.changes.outputs.auto-format == 'true' || needs.changes.outputs.unic-confluence == 'true' || needs.changes.outputs.release-tools == 'true' || - needs.changes.outputs.unic-archon-dlc == 'true' + needs.changes.outputs.unic-archon-dlc == 'true' || + needs.changes.outputs.pr-review == 'true' strategy: fail-fast: false matrix: @@ -67,6 +68,8 @@ jobs: changed: ${{ needs.changes.outputs.release-tools }} - name: unic-archon-dlc changed: ${{ needs.changes.outputs.unic-archon-dlc }} + - name: pr-review + changed: ${{ needs.changes.outputs.pr-review }} exclude: - package: changed: 'false' @@ -84,6 +87,14 @@ jobs: run: pnpm install --frozen-lockfile - if: runner.os == 'Windows' run: pnpm install --frozen-lockfile --ignore-scripts + # Install Azure CLI + azure-devops extension only on Linux/Node 24 so the + # pr-review ADO CLI smoke test (tests/ado-cli-smoke.test.mjs) actually + # invokes `--help` against each inventory entry on at least one matrix + # cell. Other cells fall through the t.skip path cleanly. + - if: matrix.package.name == 'pr-review' && matrix.os == 'ubuntu-latest' && matrix.node == '24' + run: | + curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash + az extension add --name azure-devops - run: pnpm --filter ${{ matrix.package.name }} --if-present test - run: pnpm --filter ${{ matrix.package.name }} --if-present typecheck - if: github.event_name == 'pull_request' diff --git a/.idea/conventionalCommit.xml b/.idea/conventionalCommit.xml new file mode 100644 index 00000000..a09c8599 --- /dev/null +++ b/.idea/conventionalCommit.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index aae8b7c8..4c6280eb 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -9,4 +9,4 @@ - + \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 80de4255..55b7278b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,16 +21,20 @@ packages/ ├── tsconfig/ # @unic/tsconfig └── release-tools/ # @unic/release-tools (bump / sync-version / tag / verify-changelog) docs/ -└── plans/ # Monorepo-level Spec Runner roadmap (specs 00–14) +├── adr/ # Architectural Decision Records +├── agents/ # Agent skill documentation +├── inbox/ # Retired idea-capture notes (historical) +├── issues/ # Grilled and scoped feature issues +├── plans/ # Retired spec files (historical) +├── process/ # Process and workflow guides +└── research/ # Research notes and explorations ``` -Each plugin under `apps//` also has its own `docs/plans/` for plugin-specific future work. - ## Navigation - Plugin manifests: `apps///.claude-plugin/plugin.json` and `marketplace.json` - Shared release scripts: `packages/release-tools/scripts/` -- Monorepo roadmap: `docs/plans/` +- Architectural decisions: `docs/adr/` - Process templates: `docs/process/` ## Commands @@ -42,12 +46,10 @@ pnpm format # Biome + Prettier fix (whole tree) pnpm ci:check # same as check, non-interactive (for CI) pnpm test # run tests across all packages pnpm typecheck # type-check across all packages -pnpm ralph # run the monorepo Spec Runner loop (specs 00–14) -# Per-plugin operations (after spec 03 sets up release-tools) +# Per-plugin operations pnpm --filter bump patch # bump plugin version pnpm --filter verify:changelog # check changelog -pnpm --filter ralph # run that plugin's own Spec Runner loop ``` ## Tech stack @@ -79,7 +81,7 @@ Tag scheme: `@` (e.g. `auto-format@0.5.5`). ## Conventional commits -Use package scope: `feat(auto-format): …`, `fix(pr-review): …`, `chore(release-tools): …`, `chore(spec-NN): …`. +Use package scope: `feat(auto-format): …`, `fix(pr-review): …`, `chore(release-tools): …`, `chore(unic-archon-dlc): …`. ## Git branching (Gitflow) @@ -110,40 +112,25 @@ To ship a new plugin version: | Push to `develop` | ✓ | ✓ (changed packages) | — | | Push to `main` | ✓ | ✓ (changed packages) | — | -## Spec-driven development - -All work starts with a spec file under `docs/plans/`. Specs follow this format: - -``` -# NN. Title -**Priority:** / **Effort:** / **Version impact:** / **Depends on:** / **Touches:** -## Context -## Current behaviour -## Target behaviour -## Affected files -## Implementation steps -## Verification -## Acceptance criteria -## Out of scope -``` +## Feature-driven development -`pnpm ralph` runs the Spec Runner (currently `ralph-orchestrator`), which implements specs one at a time in a loop. +New work enters through the issue tracker as Features. Use `/tdd` to implement individual issues, or `unic-dlc-build` (via `unic-archon-dlc`) once the harness is set up in this repo. ## Do not add - External runtime deps to plugins unless truly essential (`auto-format` has zero; that's the bar) - Turborepo or other build orchestrators — plain pnpm workspaces is the current choice -- Features not described in an open spec file — open a spec first +- Features not tracked in the issue tracker — open a Feature first ## LICENSE files -**Never create, copy, or delete `LICENSE` files.** The maintainer manages these manually in every package and plugin directory. If a spec step or acceptance criterion requires a `LICENSE` file to exist, warn the maintainer to add it themselves before continuing. +**Never create, copy, or delete `LICENSE` files.** The maintainer manages these manually in every package and plugin directory. If an acceptance criterion requires a `LICENSE` file to exist, warn the maintainer to add it themselves before continuing. -## Agent skills +## Skill summary ### Issue tracker -Issues live as local markdown files under `docs/issues/`. See `docs/agents/issue-tracker.md`. +Issues live in GitHub Issues at `unic/unic-agents-plugins` (planned migration to Azure DevOps). See `docs/agents/issue-tracker.md`. ### Triage labels @@ -153,6 +140,14 @@ Issues live as local markdown files under `docs/issues/`. See `docs/agents/issue Multi-context repo: Per-plugin `CONTEXT.md` files live under `apps/claude-code//`. Root `CONTEXT-MAP.md` at repo root. See `docs/agents/domain.md`. -### Inbox +## Agent skills + + + -Raw ideas, bugs, and stray thoughts that haven't been grilled or scoped yet live in `docs/inbox/`. Use `/inbox ` to capture without interrupting the current flow. Items graduate to `docs/issues//` after grilling. See `docs/inbox/README.md`. +- [issue-tracker.md](docs/agents/issue-tracker.md) — issue tracker backend, CLI, create/update conventions +- [labels.md](docs/agents/labels.md) — three-tier label taxonomy: state, type, priority +- [branching.md](docs/agents/branching.md) — branching strategy, branch names, PR targets +- [domain.md](docs/agents/domain.md) — single-context vs multi-context, CONTEXT.md and ADR locations +- [workflow.md](docs/agents/workflow.md) — seven workflow phases, artifact outputs, docs/workflow/ paths + diff --git a/CONTEXT-MAP.md b/CONTEXT-MAP.md index c6ebe22d..3c28dbaa 100644 --- a/CONTEXT-MAP.md +++ b/CONTEXT-MAP.md @@ -2,7 +2,7 @@ ## Shared vocabulary -- [Monorepo](./CONTEXT.md) — Plugin, Workspace Package, Release, Spec, Spec Runner, Consumer +- [Monorepo](./CONTEXT.md) — Plugin, Workspace Package, Release, Feature, Feature Runner, Consumer ## Plugin contexts @@ -18,3 +18,4 @@ - **unic-confluence** can be installed as a git dependency for use outside Claude Code. - **pr-review** has a soft dependency on the `pr-review-toolkit` plugin from `anthropics/claude-plugins-official` - **unic-archon-dlc** requires the Archon workflow engine (version ≥ 0.10) in the target project; it has no runtime dependencies on any other plugin in this repo +- Architectural decisions are split by scope: monorepo-wide decisions live in root `docs/adr/`; decisions scoped to a single context live in that context's own `docs/adr/`. diff --git a/CONTEXT.md b/CONTEXT.md index d66161eb..ca762a57 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -20,20 +20,12 @@ _Avoid_: package (too generic), library, module A versioned, tagged snapshot of a single Plugin published to `main`. A per-Plugin event — there is no monorepo-wide release. _Avoid_: deploy, publish, version bump -**Spec**: -A structured markdown file under `docs/plans/` that defines a unit of work with context, target behaviour, and acceptance criteria. The atomic input to the Spec Runner. -_Avoid_: ticket, task, issue, story - -**Spec Runner**: -The agent automation that reads Specs and implements them one at a time. Currently backed by `ralph-orchestrator` but the concept is tool-agnostic. -_Avoid_: Ralph, Ralph Orchestrator (tool-specific, not domain terms) - **Feature**: A self-contained unit of work tracked as a directory under `docs/issues//`, containing a PRD and numbered implementation issues. The atomic input to the Feature Runner. _Avoid_: ticket, epic, story **Feature Runner**: -The skill that implements a Feature's issues end-to-end in one worktree, branch, and pull request. Parallel concept to Spec Runner, but driven by the issue tracker rather than `docs/plans/`. +The skill that implements a Feature's issues end-to-end in one worktree, branch, and pull request. Backed by `unic-dlc-build`. _Avoid_: issue runner, queue runner **Consumer**: @@ -45,8 +37,7 @@ _Avoid_: client, user repo, target repo, host repo - A **Plugin** belongs to one agent ecosystem (e.g., Claude Code) and has zero or more **Releases** - A **Claude Code Plugin** is a **Plugin** — the inverse is not always true - A **Workspace Package** supports **Plugin** development but is not itself a **Plugin** -- A **Spec** drives exactly one **Spec Runner** iteration -- A **Feature** drives one **Feature Runner** execution — a Feature is to the Feature Runner what a Spec is to the Spec Runner +- A **Feature** drives one **Feature Runner** execution - A **Consumer** installs one or more **Plugins** ## Example dialogue @@ -56,6 +47,3 @@ _Avoid_: client, user repo, target repo, host repo > **Dev:** "A Consumer reported the auto-format Plugin failing on Windows." > **Domain expert:** "That's a cross-platform gap. Plugins must use Node.js APIs — no shell commands or POSIX paths." - -> **Dev:** "Can I use Ralph to implement this Spec?" -> **Domain expert:** "You mean the Spec Runner — Ralph is just the current tool backing it." diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed3f1d09..87d6331e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,8 @@ # Contributing -This monorepo uses a spec-driven development workflow. For the full lifecycle — from idea capture through grilling, PRD, issues, execution, and QA — see **[`docs/process/development-workflow.md`](docs/process/development-workflow.md)**. +This monorepo uses a Feature-driven development workflow. For the full lifecycle — from idea capture through grilling, PRD, issues, execution, and QA — see **[`docs/process/development-workflow.md`](docs/process/development-workflow.md)**. -New features and fixes are described in self-contained spec files under `docs/plans/`. Implementation is automated with the **Spec Runner** (`pnpm ralph`, currently backed by `ralph-orchestrator`) or done by hand following the same steps. +New features and fixes are tracked as Features in the issue tracker under `docs/issues//`. Implementation is done manually using `/tdd` for individual issues; the **Feature Runner** (`unic-dlc-build`, shipped by `unic-archon-dlc`) is the long-term AFK runner once it is wired into this repo (see [ADR-0009](apps/claude-code/unic-archon-dlc/docs/adr/0009-retire-ralph-adopt-archon-runner.md)). ## Cross-cutting standards @@ -48,7 +48,7 @@ Enforced by Biome (`pnpm ci:check`) for `.mjs`/`.js`/`.ts`/`.json`/`.css` and Pr - Zero external runtime deps unless essential (`auto-format` ships zero; `unic-confluence` has `marked` — that's the bar). - Zero-config from the user's perspective: no configuration files users must create beyond credentials. -- Every plugin uses the spec-driven workflow: `docs/plans/` + `ralph.yml` + `PROMPT.md` per the template in `docs/process/`. +- New plugin work enters through the issue tracker as Features — open a Feature before starting implementation. ### License @@ -56,87 +56,29 @@ LGPL-3.0-or-later for all packages in this monorepo. ## Prerequisites -| Tool | Version | How to get it | -| --------------- | ----------------------------------------------- | -------------------------------------------------------------------------------- | -| Node.js | ≥ 22 (see `.nvmrc` for the recommended version) | [nodejs.org](https://nodejs.org) | -| pnpm | ≥ 10 | `npm install -g pnpm` | -| Claude Code CLI | latest | [claude.ai/code](https://claude.ai/code) — required as the Spec Runner's backend | +| Tool | Version | How to get it | +| --------------- | ----------------------------------------------- | ---------------------------------------- | +| Node.js | ≥ 22 (see `.nvmrc` for the recommended version) | [nodejs.org](https://nodejs.org) | +| pnpm | ≥ 10 | `npm install -g pnpm` | +| Claude Code CLI | latest | [claude.ai/code](https://claude.ai/code) | -Everything else (ralph-orchestrator, Biome, Prettier, TypeScript) is a workspace devDependency and installs with: +Everything else (Biome, Prettier, TypeScript) is a workspace devDependency and installs with: ```sh pnpm install ``` -**ralph-loop** is a Claude Code plugin and must be installed once globally: +## Starting new work -```sh -claude plugins install anthropics/claude-plugins-official/plugins/ralph-loop -``` - -## Writing a spec - -All work starts with a spec file. See the existing specs under `docs/plans/` for examples. - -### 1. Pick a number - -Check `docs/plans/README.md` for the current highest spec number. Create `docs/plans/NN-short-slug.md`. - -### 2. Required metadata - -```markdown -# NN. Title - -**Priority:** P0 | P1 | P2 -**Effort:** XS | S | M | L -**Version impact:** none | patch (plugin: ) | minor (plugin: ) | major (plugin: ) -**Depends on:** (spec numbers, or "none") -**Touches:** (comma-separated files/dirs) -``` - -### 3. Required sections - -| Section | What to write | -| ------------------------- | ---------------------------------------- | -| `## Context` | Why this change is needed | -| `## Current behaviour` | Exact code/behaviour _before_ the change | -| `## Target behaviour` | What it should look like _after_ | -| `## Affected files` | Table: path → Create / Modify / Delete | -| `## Implementation steps` | Numbered steps with before → after diffs | -| `## Verification` | Shell commands + expected output | -| `## Acceptance criteria` | Checkbox list | -| `## Out of scope` | Explicit list of things NOT to change | - -Good specs are **self-contained** — the Spec Runner has no memory of prior runs. Include actual code snapshots. +All work enters through the issue tracker as a Feature. The recommended flow: -### 4. Register the spec +1. Capture the idea — open a GitHub Issue directly, or run `/triage` to walk it through the state machine. +2. Grill the design with `/grill-me` or `/grill-with-docs` until the problem and solution are clear. +3. Create a PRD and issues with `/to-prd` → `/to-issues`. +4. Implement each issue manually with `/tdd`. (AFK execution via `unic-dlc-build` will replace this step once the harness is wired in — see [ADR-0009](apps/claude-code/unic-archon-dlc/docs/adr/0009-retire-ralph-adopt-archon-runner.md) and [ADR-0010](apps/claude-code/unic-archon-dlc/docs/adr/0010-retire-implement-feature-skill.md).) +5. Open a PR targeting `develop`. -Add a row to the execution order table in `docs/plans/README.md`. - -## Running the Spec Runner - -```sh -pnpm ralph -``` - -The Spec Runner reads `ralph.yml`, which points to `PROMPT.md`. Each iteration implements one spec, commits, and stops. Run `pnpm ralph` again for the next spec. - -- **Stop early**: `Ctrl+C` -- **Resume**: `pnpm ralph` again — it finds the first unfinished spec -- **Paused for review**: a `## Questions` section in a spec means the Spec Runner emitted `LOOP_COMPLETE` — answer the question, remove the section, re-run - -## Running manually (without the Spec Runner) - -Follow the steps in `PROMPT.md` yourself, replacing the Spec Runner's role. - -## Running per-plugin Spec Runner loops - -Each plugin also has its own `ralph.yml` + `PROMPT.md` for plugin-specific development. Run from inside the plugin directory: - -```sh -cd apps/claude-code/pr-review -pnpm ralph -``` +See [`docs/process/development-workflow.md`](docs/process/development-workflow.md) for the full 8-phase lifecycle. ## Verification commands diff --git a/PROMPT.md b/PROMPT.md deleted file mode 100644 index 735fa6dc..00000000 --- a/PROMPT.md +++ /dev/null @@ -1,106 +0,0 @@ -# Ralph Orchestrator — unic-agents-plugins Roadmap - -You are implementing the roadmap for the `unic-agents-plugins` monorepo, one spec at a time. - -## Step 1 — Determine what's next - -Check the execution order in `docs/plans/README.md`. Then scan spec files in order (00 → 13) and find the first file that does NOT contain the string `**Status: done`. - -If **all** specs contain `**Status: done`, output exactly: - -``` -LOOP_COMPLETE -``` - -…and stop. Do nothing else. - -## Step 2 — Read the spec completely - -Read the entire spec file before writing any code. Pay special attention to: - -- **Current behaviour** — verify the code actually works this way before starting; if it doesn't, add a `## Deviations` section at the bottom of the spec file documenting the discrepancy -- **Out of scope** — list of things you must NOT change in this iteration -- **Depends on** — if a dependency spec is not yet marked done, skip this spec and move to the next one that can be done - -## Step 3 — Implement - -Check the spec's `**Version impact:**` line to choose the implementation approach: - -**`none` (workspace/infrastructure spec)** — implement directly. Follow the "Implementation steps" exactly. If a step's "before" snapshot doesn't match the current file, consult the "Deviations" section (if you wrote one) or document the discrepancy and adapt minimally. - -**`patch` / `minor` / `major` (plugin spec)** — use `/tdd` to drive implementation. Treat the spec's "Implementation steps" as guidance (key files to touch, rough order), not a recipe. The spec's **Acceptance criteria** are the target; the red-green-refactor cycle drives the path there. - -Ground rules (from `docs/plans/README.md`): - -- Use `pnpm` for all package operations (not `npm`) -- Tabs for indentation in `.mjs`/`.js`/`.ts` files, spaces for `.json`/`.yml`/`.yaml` (per `.editorconfig`) -- Conventional commits: `feat(scope): description`, `fix(scope): description`, `chore(scope): description` -- Cross-platform: use Node.js APIs (`node:path`, `node:fs`, `node:os`) instead of shell commands; no bash/sh assumptions -- If something can't be followed as written: document it in `## Deviations`, don't silently deviate - -**Supporting skill:** `/diagnose` — if a failure persists and the root cause appears to be outside the spec's scope (an existing module, tooling, or dependency the spec doesn't touch), use `/diagnose` to isolate it before continuing. - -## Step 4 — Verify - -Run the exact commands in the spec's **Verification** section. Fix any failures before proceeding. - -Check every item in **Acceptance criteria**. If any item fails, fix it. - -Then run the always-on repo hygiene checks regardless of spec type: - -```sh -pnpm check # Biome + Prettier — fix any failures before proceeding -``` - -## Step 4.5 — Version bump (conditional) - -Check the spec's `**Version impact:**` line: - -**`none` (workspace/infrastructure spec)** — skip this step entirely. No CHANGELOG update. Proceed to Step 5. - -**`patch` / `minor` / `major` (plugin: ``)** — bump the specified plugin: - -1. Append one bullet under the matching subsection of `## [Unreleased]` in `apps/claude-code//CHANGELOG.md`: - - - `### Breaking` — CLI flag change, exit-code change, on-disk schema change - - `### Added` — new flag, subcommand, or user-visible feature - - `### Fixed` — bug fix, refactor, docs, internal tooling - -2. Run: `pnpm --filter bump ` - -3. Run: `pnpm --filter verify:changelog` - -## Step 5 — Mark done and commit - -1. Add this line immediately after the spec's `# NN. Title` heading (as the second line): - -``` -**Status: done — YYYY-MM-DD** -``` - -Replace `YYYY-MM-DD` with today's date. - -2. Stage and commit all changes using the appropriate prefix: - -- **Workspace specs** (version impact: none): `git commit -m "chore(spec-NN): "` -- **Plugin specs** (version impact: patch/minor/major): `git commit -m "feat(spec-NN): (vX.Y.Z)"` -- **Migration specs** (05–07): the `git merge --allow-unrelated-histories` creates a first commit; any post-merge fixups go in a second commit: `git commit -m "feat(spec-NN): finalize migration"` - -3. **Do not push.** Commits only. - -## Step 6 — Stop for this iteration - -Output a brief summary of what was implemented and committed. Then stop — Ralph will feed this prompt again for the next spec. - ---- - -## Important constraints - -- Implement **one spec per iteration**. Do not implement multiple specs in a single run. -- If a spec requires human judgment (e.g. choosing between two design approaches not covered by the spec), stop, document the question in a `## Questions` section at the bottom of the spec file, and output: - ``` - LOOP_COMPLETE - ``` - This pauses the loop for human review. -- Do not create any files outside of what the spec describes. -- Do not modify any spec files except to add `**Status: done**`, `## Deviations`, or `## Questions` sections. diff --git a/apps/claude-code/auto-format/AGENTS.md b/apps/claude-code/auto-format/AGENTS.md new file mode 100644 index 00000000..e6e16226 --- /dev/null +++ b/apps/claude-code/auto-format/AGENTS.md @@ -0,0 +1,74 @@ +# AGENTS.md — auto-format + +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 + +`auto-format` is a Claude Code Plugin in the [`unic-agents-plugins`](../../../AGENTS.md) monorepo. It registers a `PostToolUse` hook that auto-formats and lints files after `Write` / `Edit` / `MultiEdit` / `NotebookEdit` events. The hook script (`scripts/format-hook.mjs`) uses only Node built-ins and shells out to whichever Formatter the Consumer project has configured locally. See [`CONTEXT.md`](CONTEXT.md) for the domain vocabulary (Format Hook, Formatter, Consumer). + +## 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 (Plugin, Workspace Package, Release, Feature, Consumer) +- [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/) — Plugin-specific architecture decisions + +## Commands + +Plugin-specific pnpm scripts (run from this directory or with `pnpm --filter auto-format