diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 3a0c5fb..fabc707 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -7,7 +7,7 @@ { "name": "working-process", "source": "./plugins/working-process", - "description": "Spec-driven working process on top of superpowers: grilling-session, architect-session and sync-rules skills, architect and plan-adversary review agents, plus distributed process rules" + "description": "Spec-driven working process on top of superpowers: grilling-session, architect-session, system-designer-session and sync-rules skills, architect and plan-adversary review agents, architect-consult and system-designer-consult consultation agents, plus distributed process rules" }, { "name": "python-standards", diff --git a/.claude/rules/plugin-authoring.md b/.claude/rules/plugin-authoring.md index 291db1e..d56ea24 100644 --- a/.claude/rules/plugin-authoring.md +++ b/.claude/rules/plugin-authoring.md @@ -12,7 +12,9 @@ paths: `claude plugin validate plugins/` must both pass. - Names are kebab-case. Skills whose content is an open-ended conversation are named `*-session`; formal reviews that end in a verdict - are agents. Operational skills may prompt for decisions without being + are agents; verdict-free consultation agents — one briefing in, one + contribution out, from a fresh isolated context — are named `*-consult`. + Operational skills may prompt for decisions without being sessions — they are named for what they do (e.g. `sync-rules`). - Author skills with the `skill-creator` skill when it is available — scaffolding, `description:` tuning, and evals; it complements diff --git a/.claude/rules/plugin-versioning.md b/.claude/rules/plugin-versioning.md index eb1ecbc..3263b59 100644 --- a/.claude/rules/plugin-versioning.md +++ b/.claude/rules/plugin-versioning.md @@ -7,17 +7,47 @@ paths: - Every plugin follows semver in its `.claude-plugin/plugin.json` `version` field. -- A commit/PR that changes ANY file under `plugins//` bumps that - plugin's version IN THE SAME commit/PR. The `version` field is the - update-delivery mechanism, not hygiene: pushing new commits without - changing that string delivers nothing to existing users. +- `develop` is the integration branch: topic branches merge into it + WITHOUT version bumps — unfinished plugin updates accumulate there + unreleased. `master` holds released state only; the marketplace + serves it. +- The bump happens exactly once, in the release PR from `develop` to + `master`: one commit bumps every plugin changed since the last + release, sized by the total accumulated change per plugin. The + `version` field is the update-delivery mechanism, not hygiene: + merging to master without changing that string delivers nothing to + existing users, so a release PR with no bumps for its changed + plugins is invalid. +- Dogfooding unreleased content needs a changed version string — the + plugin cache keys content by version. A topic branch that dogfoods a + plugin sets `X.Y.Z-dev.` on it — the issue number the + branch name carries, or the branch short-name when the topic has no + issue (e.g. `-dev.design-personas`). Widening the discriminator + instead of minting another channel keeps one channel for one purpose; + the discriminator only needs to be unique among parallel topics. The + suffix flows into develop as-is. A topic that + does not dogfood never touches the version. On a version-line merge + conflict between parallel topics, the merging topic's own + `-dev.` wins — both strings are provisional. The release PR + strips every `-dev` suffix while minting the final numbers; the + `release-guard` workflow fails any PR to master that carries a + prerelease version or a changed plugin without a bump. +- Prerelease grammar: `-.`. Defined channels: + `dev.` (topic-branch dogfooding, above) and `rc.` (release + candidate — a freeze of develop dogfooded as one bundle when a + release warrants whole-unit validation; minted by a release-prep + commit and stripped by the release PR like any prerelease). Future + channels extend this list by editing this rule only — the + release-guard workflow rejects every prerelease on master + (`*-*`), so new channels never need a CI change. - **patch** — wording or docs fixes, no behavior change; - **minor** — a new component or section, backward-compatible behavior additions; - **major** — rename or removal of a component, or a breaking change to a convention others rely on (the frontmatter process fields, the - `*-plan-review` discovery convention, the plugin-root persona path — - `ARCHITECT_PERSONA.md`). + `*-plan-review` discovery convention, the plugin-root persona paths — + `ARCHITECT_PERSONA.md`, `SYSTEM_DESIGNER_PERSONA.md`, + `PERSONA_COMMON.md`). - Before 1.0.0, breaking changes ride a **minor** bump (semver's 0.x rule); major is reserved for the promotion to 1.0.0 and for breaking changes after it. diff --git a/.claude/rules/repo-hygiene.md b/.claude/rules/repo-hygiene.md index 7435587..c22f2f9 100644 --- a/.claude/rules/repo-hygiene.md +++ b/.claude/rules/repo-hygiene.md @@ -12,8 +12,9 @@ docs, README — and in commit messages: placeholders; - no company or client names; - all committed text is in English. One narrow exception: quoted example - trigger phrases inside a skill's `description:`, and the `query` values of - its trigger-eval files (`evals/trigger-evals.json`), may be non-English — - both mirror how a developer actually asks, and the evals exercise exactly - those phrases (precedent: grilling-session's "przemagluj"). The - surrounding prose stays English. + trigger phrases inside a component's `description:` (skill or agent), + the README trigger lines that mirror them, and the `query` values of + trigger-eval files (`evals/trigger-evals.json`), may be non-English — + all mirror how a developer actually asks, and the evals exercise + exactly those phrases (precedent: project-memory's "przejrzyjmy + memory"). The surrounding prose stays English. diff --git a/.claude/settings.json b/.claude/settings.json index 5f79860..95b5934 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -23,7 +23,7 @@ }, "enabledPlugins": { "superpowers@claude-plugins-official": true, - "skill-creator@claude-plugins-official": true + "elements-of-style@superpowers-marketplace": true }, "extraKnownMarketplaces": { "claude-plugins-official": { @@ -31,6 +31,12 @@ "source": "github", "repo": "anthropics/claude-plugins-official" } + }, + "superpowers-marketplace": { + "source": { + "source": "github", + "repo": "obra/superpowers-marketplace" + } } } } diff --git a/.github/workflows/release-guard.yml b/.github/workflows/release-guard.yml new file mode 100644 index 0000000..423fbfb --- /dev/null +++ b/.github/workflows/release-guard.yml @@ -0,0 +1,49 @@ +# Release guard — runs on PRs targeting master (release PRs from develop). +# Enforces the plugin-versioning rule's release-time invariants: +# 1. no prerelease (-dev.*) version string reaches master; +# 2. every plugin changed since master carries a version bump. +name: release-guard + +on: + pull_request: + branches: [master] + +jobs: + release-guard: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: No prerelease versions reach master + run: | + fail=0 + for m in plugins/*/.claude-plugin/plugin.json; do + v=$(jq -r .version "$m") + case "$v" in + *-*) + echo "::error file=$m::prerelease version '$v' must not reach master — strip the -dev suffix and size the final bump" + fail=1 + ;; + esac + done + exit $fail + + - name: Changed plugins carry a bump + run: | + base="origin/${{ github.base_ref }}" + fail=0 + for d in plugins/*/; do + name=$(basename "$d") + manifest="${d}.claude-plugin/plugin.json" + if ! git diff --quiet "$base"...HEAD -- "$d"; then + base_v=$(git show "$base:$manifest" 2>/dev/null | jq -r .version || echo "") + head_v=$(jq -r .version "$manifest") + if [ "$base_v" = "$head_v" ]; then + echo "::error file=$manifest::plugin '$name' changed since master but version stayed '$head_v' — the release PR must bump it" + fail=1 + fi + fi + done + exit $fail diff --git a/CLAUDE.md b/CLAUDE.md index 86104e3..d42d776 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -20,9 +20,12 @@ override defaults; follow them. ## Worktrees and topic branches Feature work happens on a topic branch named `feature/-` -(e.g. `feature/6-salesforce-standards`), branched off `master`. When an -isolated workspace is used, its git worktree lives at -`.claude/worktrees//` — one per topic branch, git-ignored. +(e.g. `feature/6-salesforce-standards`), branched off `develop` — the +integration branch topic PRs target. `master` holds released state +only; releases are PRs from `develop` to `master`, where version bumps +happen (see the plugin-versioning rule). When an isolated workspace is +used, its git worktree lives at `.claude/worktrees//` — +one per topic branch, git-ignored. ## Authoring skills diff --git a/README.md b/README.md index 0a1293b..7c9a393 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Marketplace of [Claude Code](https://code.claude.com) plugins by Missing Bits. | Plugin | Description | |--------|-------------| -| `working-process` | Spec-driven working process: grilling-session, architect-session and sync-rules skills, architect and plan-adversary review agents, distributed process rules | +| `working-process` | Spec-driven working process: grilling-session, architect-session, system-designer-session and sync-rules skills, architect and plan-adversary review agents, two verdict-free consultation agents, distributed process rules | | `python-standards` | Python coding standards for uv + ruff + pytest + pyright: area skills, code-review stack, plan-review checklist, distributed toolchain rule | | `salesforce-standards` | Salesforce coding standards for the sf CLI toolchain: area skills (Apex, LWC, Flow, data/security model, legacy UI), code-review stack, plan-review checklist, distributed toolchain rule | | `project-memory` | In-repo project memory: committed Team memory (`docs/memory/`) and per-user Private memory (`.claude/memory/`), with `memory-review-session` and `migrate-memory` skills, distributed as a Rules payload | diff --git a/docs/domain/adr/0001-persona-independence.md b/docs/domain/adr/0001-persona-independence.md new file mode 100644 index 0000000..65805e1 --- /dev/null +++ b/docs/domain/adr/0001-persona-independence.md @@ -0,0 +1,16 @@ +--- +ticket: none +--- + +# Personas never consult each other + +The working process fields two design personas — architect and system +designer, split by dimension rather than by stance — and a developer +dispatches them to get two independent readings of one subject. Both +consult agents therefore ship with `SendMessage` removed via +`disallowedTools`, plus a standing instruction never to spawn another +persona: two personas that reconcile before answering hand back one +opinion where the developer asked for two, and the reconciling happens +where nobody can inspect it. The main thread is left as the only place +the two readings meet, which is also the only place the developer can +weigh them against each other. diff --git a/docs/domain/glossary.md b/docs/domain/glossary.md index db078fb..bec4c70 100644 --- a/docs/domain/glossary.md +++ b/docs/domain/glossary.md @@ -16,9 +16,14 @@ _Avoid_: artifact folder **First-create question**: The question — ignored mode or tracked mode — asked when a process -directory is created for the first time, or exists with no observable -prior decision (neither a `.gitignore` containing exactly `*` nor a -git-tracked file). Never asked when either signal is present. +directory is created for the first time, or exists with no prior +decision: neither an observable signal (a `.gitignore` containing +exactly `*`, a git-tracked file) nor an explicit project instruction +declaring the mode (e.g. a CLAUDE.md note). Never asked when any of +these signals is present. A declared ignored mode is materialized by +whoever first acts on it — writing the `*` `.gitignore` — making the +decision observable; a declared tracked mode becomes observable with +the first committed file. _Avoid_: self-ignore **Ignored mode**: @@ -32,7 +37,8 @@ A process directory whose files are committed; detected by any git-tracked file under it. **Contract probe**: -The ordered path check a domain review skill runs to find the installed +The ordered path check a domain review skill — or a dispatching +review command, pre-dispatch — runs to find the installed report contract: `/.claude/rules/working-process/review-reports.md`, then `$HOME/.claude/rules/working-process/review-reports.md` — first hit wins, mirroring the Rules engine's project-over-user conflict rule. Part @@ -47,6 +53,21 @@ contract; a domain plugin's inline fallback is a strict subset of it, never a different shape. _Avoid_: review output, report file +**Finding**: +One graded problem a review round reports, cited with evidence — in a +design review (`architect`, `plan-adversary`) that is all it is. In a +Review report it additionally takes the counted shape the review-reports +contract defines: one violation class in one file, or at project level +when no existing file carries the violation — for tagged rules the rule +id names the class; for a Candidate gap the class is the one its offer +names. Its body enumerates every violating site — line numbers, or the +domain's stable key where lines do not apply. Cites exactly one rule id +(or `rule: none`); its severity is the cited rule's (a Candidate gap's +comes from the Authoring rubric). A finding with any site unfixed counts +as remaining in a rerun. Never what a Consultation returns — that is a +Contribution. +_Avoid_: issue, violation (as a name for the unit) + **Standards plugin**: A domain plugin of this marketplace encoding coding standards for one technology: area skills, a review stack that writes Review reports, @@ -130,10 +151,15 @@ _Avoid_: severity definitions, step-3 definition **Candidate gap**: A review finding that violates no defined rule: reported and counted -normally, cited `rule: none`, graded by the Authoring rubric, and -surfaced in the run's reply as a candidate for a new rule — with offers -to park it in Project memory (when a store exists) or report it -upstream, generalized. Never cited with an invented rule id. +normally, cited `rule: none` (against the loaded domain skill lacking +the rule, or the standards plugin itself when no skill of the plugin +covers the concern — never asserted against a skill the run did not +read), graded by the Authoring rubric, and surfaced in the run's +reply as a candidate for a new rule — or, at a plugin-level citation, a +new skill — with offers to park it in Project memory (when a store +exists) or report it upstream, generalized. Never cited with an +invented rule id; the `rule: none` citation is the report's only +candidate-gap marker. _Avoid_: uncited observation, unmatched finding **Sub-rule**: @@ -198,6 +224,48 @@ implementation for a plan. Where re-review offers on fallback-recorded verdicts fire. _Avoid_: usage point +**Persona**: +A role plus its duties, single-sourced in one `*_PERSONA.md` file at the +working-process plugin root and adopted by one or more persona surfaces; +two exist — architect and system designer — their shared duties and mutual +boundary held once in `PERSONA_COMMON.md`. `plan-adversary` carries its +role inline and is a reviewer, not a persona; the org user roles the +salesforce-security-model skill calls personas are a different domain +entirely. +_Avoid_: role, hat + +**Persona surface**: +A component that adopts a persona and puts it to work: a verdict-bearing +agent (`architect`), a consult agent (`*-consult`), or a session skill +(`*-session`) — the architect has three, the system designer two. Short +form "surface" inside working-process material; unqualified "surface" in +the repo's own rules means something else, a document location where a +statement lives. +_Avoid_: mode, channel, entrypoint + +**Session skill**: +A skill whose content is an open-ended conversation, named `*-session` — +`architect-session`, `grilling-session`, `memory-review-session` among +them. Some are persona surfaces, some adopt no persona at all +(`grilling-session`). Unqualified "session" always means the Claude Code +conversation instead: what a session-scoped consent decision lasts for, +and what a consult agent is isolated from. +_Avoid_: session (for the skill), conversational skill + +**Consultation**: +A verdict-free exchange with a persona, returning a contribution and +stamping nothing. Verdict absence is the discriminator, not the absence of +stamping — an `architect` dispatch on a bare question also stamps nothing +(no document to stamp) yet still grades, so it stays a review round. +_Avoid_: informal review, advisory review + +**Contribution**: +What a consultation returns: reasoning, options, and the questions the +persona would need answered next, relayed to the developer attributed and +substantially verbatim. Never graded and never counted — the graded, +counted unit is a Finding, which belongs to verdict-bearing reviews. +_Avoid_: consultation finding, recommendation + **Project memory**: The in-repo, rule-loaded memory store the project-memory plugin defines, in two parts — Team memory and Private memory — mirroring Home-dir memory's diff --git a/docs/plans/2026-07-24-review-contract-sharpening.md b/docs/plans/2026-07-24-review-contract-sharpening.md new file mode 100644 index 0000000..19f68a6 --- /dev/null +++ b/docs/plans/2026-07-24-review-contract-sharpening.md @@ -0,0 +1,1172 @@ +--- +ticket: "#10" +date: 2026-07-24 +status: implemented +adversary: concerns (resolved 2026-07-24) +branch: feature/10-contract-sharpening +base: develop +--- + +# Review-report contract sharpening — implementation plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use +> superpowers:subagent-driven-development (recommended) or +> superpowers:executing-plans to implement this plan task-by-task. +> Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Land the six contract decisions of +`docs/specs/2026-07-23-review-contract-sharpening-design.md` (grilled, +architect LGTM) across the review-reports contract, the +process-artifacts rule, both code-review skills, and both review +commands. + +**Architecture:** Pure documentation/rule edits — no code. The +contract owns report shape and citation semantics; the +process-artifacts rule owns the first-create signal list; each skill's +cascade and inline fallback mirror only what the spec assigns them; +the commands become background dispatchers carrying the self-contained +pre-dispatch check. Every task is a set of exact text edits plus grep +verification. + +**Tech Stack:** Markdown, `claude plugin validate`, `rg`/`grep`. + +## Global Constraints + +- Work in the `feature/10-contract-sharpening` worktree + (`.claude/worktrees/contract-sharpening/`), branched off `develop`. +- NO version bumps on this branch (plugin-versioning rule: bumps land + at the develop→master release PR). Task 9 mints `-dev.10` + prerelease strings for dogfooding — that is not a release bump. +- The authoring rubric stays verbatim in exactly its four existing + places (repo rule `.claude/rules/standards-rule-tags.md`, the + contract, both inline fallbacks) — no task edits any rubric copy's + three severity bullets. +- No new report frontmatter fields; `findings:` keeps its three keys. +- `.claude/rules/standards-rule-tags.md` is NOT edited. +- Commit messages: ONE line, conventional-commit subject, no body, no + trailers (repo commit-messages rule). +- Public-repo hygiene: English, no machine paths, no client names. +- All `git`/file commands run from the worktree root + (`.claude/worktrees/contract-sharpening/`). +- **Line-wrapping rule for edits:** NEVER rewrap any line of a + replacement block — the verification greps are single-line matchers + and every replacement block below is pre-wrapped so each grep + phrase sits on one line. Apply replacement texts byte-exact. + +## Review rounds + +Adversary round 1 (2026-07-24, Fable 5): **blocking** — three +Important (verification arithmetic: phrases wrapped across line breaks +defeat single-line greps in Tasks 3/5/6/7; `rg -n | wc -l` counts +lines, not matches) and three Minor (Task 4 verify passing by +accident, contract referencing the declared-instruction signal one +commit before the rule defines it, empirical check unowned). All +amended: phrases unwrapped (line-wrapping rule above), verifications +switched to per-phrase `rg -c` checks, process-artifacts task moved +BEFORE the contract task, and the dogfooding gate added with explicit +pass criteria. Content edits were verified faithful (old-strings +byte-exact, agents exist, versions match). + +Adversary round 2 (2026-07-24, Fable 5): **blocking** — three +Important (the dogfooding gate verified only the plugin cache while +the contract is read from the INSTALLED rule file, synced by content +hash — a stale contract would misattribute failures; the +declared-instruction signal forked in two remaining restatement +surfaces, grilling-session and the project-memory core rule; the +fallback `## Project` parenthetical dropped "same severity +subsections", letting a standalone shape drift) and three Minor +(glossary Contract probe term names only skills as probe runners; the +line-wrapping constraint listed four phrases instead of banning all +rewrapping; the gate rerun did not require launch via the review +command). All amended: sync-rules step and command-launch requirement +in the gate (Task 10), grilling-session reference in Task 2, +project-memory restatement as new Task 8, "same severity subsections" +in Tasks 4/6, Contract probe term extension in Task 1, blanket +no-rewrap constraint. Spec and its Review rounds updated to match +(post-LGTM amendments, no new decisions). + +Adversary round 3 (2026-07-24, Fable 5): **concerns** — one Important +(the gate's conditional pass criteria could be vacuously satisfied by +a target that never triggers the new report paths) and four Minor +(zero-match audit grep exits 1 without `|| true`; both skills' +`description:` still named the command as invoker; the commands' +`mode: agent` parenthetical was unconditional, contradicting the +Standalone fallback; "at least one rerun" could ship one command +unexercised). Resolved same day without a fresh round: Task 10 now +requires one rerun per rewritten command with at least one target +whose prior report has file-less and `rule: none` findings, and Step 5 +records exercised vs vacuous criteria; `|| true` added in Task 9; +description invoker-chain edits added to Tasks 4/6; the parenthetical +qualified "under the installed contract". Byte-exactness of all +old-strings and all grep arithmetic confirmed clean this round. + +Dogfooding gate round 1 (2026-07-27, Task 10): five reruns across +five projects plus two first-run session transcripts. Passed: the +command path (contract probe, pre-dispatch first-create check, +background dispatch with a live session and task-notification +summary), single-rule citations in all reports, justify-not-critical +clauses, rerun dispositions with the convention boundary, the +first-review path, and the full candidate-gap reply machinery +(verbatim proposals, store probes, degraded upstream, consent gates). +Failed, two layers: reviewer agents folded systemic multi-file +violation classes into project-level findings (three targets — twice +self-chosen, once mandated by an aggregation instruction the +dispatching session added to the dispatch prompt on its own), one +rerun carried the prior report's counting convention forward for +comparability, and one report annotated `rule: none` citations with +"candidate gap, see reply". Fixes: three explicit bans appended to +both code-review skills' step 4, and a dispatch-prompt constraint +appended to both commands' step 3. Gate re-runs per Step 5; the +systemic-aggregation design tension is parked as a Private-memory +idea for a future family decision. + +Dogfooding gate rounds 2–3 (2026-07-27). Round 2: the command-layer +constraint held (both dispatch prompts clean, shown by the +developer), but reruns exposed a loophole — the reviewer inherited +the prior report's counting-policy section, including its +now-stale claim about what the dispatch asked; fixed by sharpening +the rerun ban in both skills (no counting-policy/finding-unit-note +inheritance, no alleged prior-dispatch instructions, an unchanged +tree does not change the unit). Round 3, both commands: PASS on all +criteria. The python rerun unfolded the mechanical classes +(81→210 findings, boundary declared non-comparable, the +toolchain-config finding correctly kept project-level with +violations per file); the salesforce rerun — against a prior report +that was aggregated AND carried the stale dispatch claim — quoted +the ban, refused inheritance, re-derived every finding from source +(53→540, three corrections to the prior run), and ran on the +inherited session model, isolating the text effect. Residual risks +for the PR description: the first-create ask-path was never +exercised (every target already carried a decision signal), and the +python round-3 agent was explicitly dispatched on a stronger model +by its session (the salesforce round-3 run covers the weaker tier). +Gate: PASSED. + +--- + +### Task 1: Commit the process documents + +The spec and glossary changes already sit uncommitted in this +worktree (moved from the design session). This is the +implementation-ready gate — they ride ahead of the content commits. + +**Files:** +- Commit (already modified): `docs/domain/glossary.md` +- Commit (already created): + `docs/specs/2026-07-23-review-contract-sharpening-design.md` +- Commit (already created): + `docs/plans/2026-07-24-review-contract-sharpening.md` + +**Interfaces:** +- Produces: committed spec/plan/glossary that later tasks' texts + mirror (glossary terms **Finding**, **Candidate gap**, + **First-create question**). + +- [ ] **Step 1: Verify the three files are the only dirty paths** + +Run: `git status --short` +Expected: exactly `M docs/domain/glossary.md`, +`?? docs/specs/2026-07-23-review-contract-sharpening-design.md`, +`?? docs/plans/2026-07-24-review-contract-sharpening.md`. + +- [ ] **Step 2: Flip the spec's status to approved** + +In `docs/specs/2026-07-23-review-contract-sharpening-design.md` +frontmatter, change `status: draft` → `status: approved` (the plan +exists and the developer approved proceeding; the plan file's own +status flips at its adversary gate, not here). + +- [ ] **Step 3: Extend the glossary Contract probe term** + +In `docs/domain/glossary.md`, in the **Contract probe** term, replace: + +```markdown +**Contract probe**: +The ordered path check a domain review skill runs to find the installed +report contract: +``` + +with: + +```markdown +**Contract probe**: +The ordered path check a domain review skill — or a dispatching +review command, pre-dispatch — runs to find the installed +report contract: +``` + +- [ ] **Step 4: Commit** + +```bash +git add docs/domain/glossary.md docs/specs/2026-07-23-review-contract-sharpening-design.md docs/plans/2026-07-24-review-contract-sharpening.md +git commit -m "docs(working-process): spec, plan, and glossary for review-contract sharpening" +``` + +--- + +### Task 2: `plugins/working-process/rules/process-artifacts.md` — +declared-instruction signal + +Runs BEFORE the contract task so the contract's cross-reference to +the declared-instruction signal resolves at every commit boundary. + +**Files:** +- Modify: `plugins/working-process/rules/process-artifacts.md` +- Modify: `plugins/working-process/skills/grilling-session/SKILL.md` + +**Interfaces:** +- Produces: the owned signal list (three signals + materialization) + that the contract and grilling-session reference (Task 3 Step 5, + this task's Step 3) and the commands and project-memory core rule + restate self-contained (Tasks 5, 7, 8). + +- [ ] **Step 1: Extend the ask condition and add the third signal** + +Replace: + +```markdown +When creating a Process directory — or touching one that already exists +with no observable prior decision (neither a `.gitignore` containing +exactly `*` nor any git-tracked file under it) — ASK the developer which +mode the directory gets. Assume no default: +``` + +with: + +```markdown +When creating a Process directory — or touching one that already exists +with no prior decision (no `.gitignore` containing exactly `*`, no +git-tracked file under it, and no explicit project instruction +declaring the mode) — ASK the developer which mode the directory gets. +Assume no default: +``` + +- [ ] **Step 2: Add the declared-decision paragraph with + materialization** + +Replace: + +```markdown +Never ask when either signal is already present: only a `.gitignore` +containing exactly `*` means ignored mode was chosen — one with any +other content (e.g. a local pocket's `local-*`) signals nothing by +itself; a git-tracked file under the directory (`git ls-files ` +non-empty) means tracked mode was chosen. +``` + +with: + +```markdown +Never ask when any signal is already present: only a `.gitignore` +containing exactly `*` means ignored mode was chosen — one with any +other content (e.g. a local pocket's `local-*`) signals nothing by +itself; a git-tracked file under the directory (`git ls-files ` +non-empty) means tracked mode was chosen; and an +explicit project instruction declaring the mode (e.g. a CLAUDE.md +note that a directory is always git-ignored) counts as the decision. +A declared ignored mode is materialized by whoever first acts on it — +writing the `*` `.gitignore` — making the decision observable; a +declared tracked mode becomes observable with the first committed +file. This rule owns the signal list; other surfaces reference it +rather than restating it (a self-contained command restatement is the +one justified exception). +``` + +- [ ] **Step 3: Close the grilling-session fork — reference the + owned list** + +In `plugins/working-process/skills/grilling-session/SKILL.md`, +replace: + +```markdown +- The directory already exists? Never ask when a prior decision is + observable: a `.gitignore` with `*` means ignored mode; any + git-tracked file under it (`git ls-files docs/domain` non-empty) means + tracked mode. Neither signal present? No decision was ever made — ask, + exactly as on first creation. +``` + +with: + +```markdown +- The directory already exists? Never ask when a prior decision is + present — the decided signals (observable marks and the + declared-instruction signal, with its materialization duty) are + owned by the working-process process-artifacts rule; consult it. No + signal present? No decision was ever made — ask, exactly as on + first creation. +``` + +- [ ] **Step 4: Verify (per-phrase counts)** + +```bash +rg -c "explicit project instruction" plugins/working-process/rules/process-artifacts.md +rg -c "materialized" plugins/working-process/rules/process-artifacts.md +rg -c "owned by the working-process process-artifacts rule" plugins/working-process/skills/grilling-session/SKILL.md +``` +Expected: 2, then 1, then 1. + +- [ ] **Step 5: Commit** + +```bash +git add plugins/working-process/rules/process-artifacts.md plugins/working-process/skills/grilling-session/SKILL.md +git commit -m "feat(working-process): declared-instruction signal with materialization in first-create convention" +``` + +--- + +### Task 3: Contract — `plugins/working-process/rules/review-reports.md` + +All contract-owned decisions: finding unit + `## Project` (D1), rerun +disposition + self-describing boundary (D1), single citation (D2), +plugin-level `rule: none` + mixed-run routing (D3), +justify-not-critical (D4), candidate-gap marker (D5), background +dispatch sentence (D6). + +**Files:** +- Modify: `plugins/working-process/rules/review-reports.md` + +**Interfaces:** +- Consumes: the signal list from Task 2 (referenced, not restated). +- Produces: the contract text Tasks 4–7 mirror. Key phrases later + tasks grep for: "one violation class in one file", + "`## Project`", "counts as remaining", "exactly one rule id", + "falls short of critical", "only candidate-gap marker", + "never blocks an interactive dispatching session". + +- [ ] **Step 1: Layout — finding unit and `## Project` section** + +Replace: + +```markdown +1. **Summary** — outcome, out-of-scope notes, and (for a rerun) the + prior findings' disposition. +2. **Per-file sections**, each with **Critical → Important → Minor** + subsections; findings within a subsection in ascending line order. + Findings without a line anchor — files reviewed from metadata + rather than source lines — are ordered by a domain-stated stable + key: the reviewing domain names the key (e.g. cited element name, + alphabetically) and applies it consistently. +``` + +with: + +```markdown +1. **Summary** — outcome, out-of-scope notes, and (for a rerun) the + prior findings' disposition. +2. **`## Project` section**, present only when needed, always FIRST — + before the per-file sections: the home of findings not + attributable to an existing file (a missing lockfile, an absent + manifest). Same severity subsections as a file section; findings + ordered by rule id, `rule: none` findings last, ordered by + violation-class name. +3. **Per-file sections**, each with **Critical → Important → Minor** + subsections; findings within a subsection in ascending line order. + Findings without a line anchor — files reviewed from metadata + rather than source lines — are ordered by a domain-stated stable + key: the reviewing domain names the key (e.g. cited element name, + alphabetically) and applies it consistently. + +A finding is one violation class in one file (or at project level): +for tagged rules the rule id names the class; for `rule: none` +findings the class is the one the candidate-gap offer names. The +finding's body enumerates every violating site — line numbers, or the +domain's stable key where lines do not apply — and the finding +anchors and sorts by its first violating site. One location violating +two rules yields two findings. `findings:` counts therefore mean: the +number of (violation class, file-or-project) pairs to fix. +``` + +- [ ] **Step 2: `rerun-of` — site disposition and convention boundary** + +Replace: + +```markdown + re-reviews, resolved among reports of the SAME scope — runids are + model-generated and not globally unique, so the scope, not the runid + alone, carries the identification. When set, the run's owner reads + that report and notes the prior findings' disposition in Summary — + fixed / remaining / new. +``` + +with: + +```markdown + re-reviews, resolved among reports of the SAME scope — runids are + model-generated and not globally unique, so the scope, not the runid + alone, carries the identification. When set, the run's owner reads + that report and notes the prior findings' disposition in Summary — + fixed / remaining / new. Disposition tracks sites within a finding + ("lines 42, 87 fixed; 130 remaining"); a partially fixed finding + counts as remaining — a finding lives until its last site is fixed. + Reports are self-describing (they may live git-ignored or in an + archive outside the repo): rerun behavior never depends on anything + unreadable from the reports themselves. When the prior report's + findings do not follow the finding unit (a pre-convention report, + readable off the report itself), the Summary disposition says so + and maps prior findings best-effort; count deltas across that + boundary are not comparable. +``` + +- [ ] **Step 3: Finding citations — single citation, plugin-level + `rule: none`, justify clause** + +Replace: + +```markdown +- A finding that violates a defined rule cites its most specific id: + `(standard: , rule: )` — the sub-id when a sub-rule + matched, the group id otherwise. When a matching rule exists, the + specific id is mandatory; a bare `(standard: )` citation is + not a valid finding. +- A finding no defined rule covers is still reported and counted: + cited `(standard: , + rule: none)`, graded by the authoring rubric below, and — when graded + critical — always `kind: defect` (hardening denotes a + standards-mandated protection, and a `rule: none` finding has no + standard mandating it). A plausible-looking rule id is never + fabricated. +``` + +with: + +```markdown +- A finding that violates a defined rule cites its most specific id: + `(standard: , rule: )` — the sub-id when a sub-rule + matched, the group id otherwise. When a matching rule exists, the + specific id is mandatory; a bare `(standard: )` citation is + not a valid finding. A finding cites exactly one rule id — singular + `rule:` key; its severity is the cited rule's. +- A finding no defined rule covers is still reported and counted: + cited `(standard: , + rule: none)` — or, when no skill of the plugin covers the concern, + at plugin level: `(standard: , rule: none)`. A concern + covered by the domain of an existing but not-yet-loaded skill is + NOT a candidate gap — the reviewer loads that skill and grades by + its tags; `rule: none` is never asserted against a skill the run + did not read. In a mixed run the cited plugin is the one whose + domain owns the finding's file; a project-level finding routes by + its violation-class domain. Graded by the authoring rubric below; + when graded critical — always `kind: defect` (hardening denotes a + standards-mandated protection, and a `rule: none` finding has no + standard mandating it); when graded below critical while touching + data integrity, security or sharing, or a platform limit — the + finding states in one clause why it falls short of critical. A + plausible-looking rule id is never fabricated. +``` + +- [ ] **Step 4: Candidate-gap offers — marker sentence and new-skill + proposals** + +Replace: + +```markdown +`rule: none` findings are candidate standards gaps. After writing the +report, the run's owner lists them in its reply — one line each: +violation class, proposed rule id, graded severity — and then offers, +never performs unprompted: +``` + +with: + +```markdown +`rule: none` findings are candidate standards gaps. The `rule: none` +citation is the report's only candidate-gap marker; the proposals +live in the run's reply, never in the report. After writing the +report, the run's owner lists them in its reply — one line each: +violation class, proposed rule id, graded severity (a plugin-level +`rule: none` finding may propose a new skill instead of a new rule) — +and then offers, never performs unprompted: +``` + +- [ ] **Step 5: Dispatcher bullet — background dispatch and signal + reference** + +Replace: + +```markdown +- Dispatching a reviewer agent from an interactive session: the + dispatcher runs the first-create check BEFORE dispatch and asks then + — exactly as when the process creates `docs/specs/` or `docs/plans/` + — so the agent never meets an undecided directory. +``` + +with: + +```markdown +- Dispatching a reviewer agent from an interactive session: the + dispatcher runs the first-create check BEFORE dispatch and asks then + — exactly as when the process creates `docs/specs/` or `docs/plans/` + — so the agent never meets an undecided directory. The decided + signals (including the declared-instruction signal) are owned by + the process-artifacts rule. The dispatch itself runs in the + background: a review never blocks an interactive dispatching + session, and the run's owner writes the one report regardless of + fore/background mode. +``` + +- [ ] **Step 6: Verify (per-phrase counts)** + +```bash +f=plugins/working-process/rules/review-reports.md +rg -c "one violation class in one file" $f # expected: 1 +rg -c "counts as remaining" $f # expected: 1 +rg -c "exactly one rule id" $f # expected: 1 +rg -c "falls short of critical" $f # expected: 1 +rg -c "only candidate-gap marker" $f # expected: 1 +rg -c "never blocks an interactive" $f # expected: 1 +rg -c "## Project" $f # expected: 1 +``` + +- [ ] **Step 7: Commit** + +```bash +git add plugins/working-process/rules/review-reports.md +git commit -m "feat(working-process): finding unit, citation rules, and background dispatch in review-reports contract" +``` + +--- + +### Task 4: `plugins/python-standards/skills/python-code-review/SKILL.md` + +Cascade mirrors D3 + D4; Run-scope boundary replaces the +out-of-scope-note sentence; fallback absorbs the finding unit, +single citation, and `## Project`. + +**Files:** +- Modify: `plugins/python-standards/skills/python-code-review/SKILL.md` + +**Interfaces:** +- Consumes: contract phrases from Task 3 (mirrored, not referenced — + the cascade must work standalone). +- Produces: the cascade text Task 6 parallels for salesforce. + +- [ ] **Step 1: Extend the `rule: none` cascade bullet (D3 + D4)** + +Replace: + +```markdown + - no defined rule covers the finding → report and count it anyway, + cited `(standard: , + rule: none)`, graded by the authoring rubric in the review-reports + contract; at critical its kind is always `defect`. Never invent a + rule id. +``` + +with: + +```markdown + - no defined rule covers the finding → report and count it anyway, + cited `(standard: , + rule: none)` — or `(standard: python-standards, rule: none)` when + no skill of this plugin covers the concern. A concern covered by + the domain of an existing but not-yet-loaded skill is NOT a + candidate gap: load that skill and grade by its tags — + `rule: none` is never asserted against a skill the run did not + read. Graded by the authoring rubric in the review-reports + contract; at critical its kind is always `defect`; when graded + below critical while touching data integrity, security or + sharing, or a platform limit, the finding states in one clause + why it falls short of critical. Never invent a rule id. +``` + +- [ ] **Step 2: Single citation + Run-scope boundary (D2 + D3)** + +Replace: + +```markdown + When a matching rule exists, citing its specific id is mandatory — + a bare `(standard: )` citation is not a valid finding. + Critical findings carry the rule's kind inline + (`…, kind: defect|hardening`); the Summary headline breaks critical + counts down by kind. Content matching no loaded domain skill stays a + Summary out-of-scope note, not a finding. +``` + +with: + +```markdown + When a matching rule exists, citing its specific id is mandatory — + a bare `(standard: )` citation is not a valid finding. A + finding cites exactly one rule id; one location violating two + rules yields two findings. Critical findings carry the rule's kind + inline (`…, kind: defect|hardening`); the Summary headline breaks + critical counts down by kind. The Run scope is given by the caller + and never self-extended: within it, a Python-domain concern no + rule covers is a counted `rule: none` finding (cascade above); + files outside the domain (Run scope section) stay Summary + out-of-scope notes. +``` + +- [ ] **Step 3: Fallback Body — finding unit and `## Project`** + +Replace: + +```markdown +- **Body**: a Summary section (scope reviewed, out-of-scope files, + headline counts), then per-file sections with Critical → Important → + Minor subsections, line-ascending within a subsection; omit + no-findings files and empty severity sections; a zero-findings run + still writes the document. +``` + +with: + +```markdown +- **Body**: a Summary section (scope reviewed, out-of-scope files, + headline counts); a `## Project` section FIRST when findings are + not attributable to an existing file (same severity subsections as + a file section; ordered by rule id, `rule: none` last by + violation-class name); then per-file sections + with Critical → Important → Minor subsections, line-ascending + within a subsection; omit no-findings files and empty severity + sections; a zero-findings run still writes the document. A finding + is one violation class in one file (or at project level), its body + enumerating every violating site, anchored by its first site; it + cites exactly one rule id. +``` + +- [ ] **Step 4: Update the `description:` invoker chain** + +After Task 5 the command no longer loads this skill — the agent does. +In the frontmatter, replace: + +```markdown +description: Use when auditing existing Python code against the python-standards skills — invoked by the /python-review command or the python-code-reviewer agent. +``` + +with: + +```markdown +description: Use when auditing existing Python code against the python-standards skills — invoked by the python-code-reviewer agent, which the /python-review command dispatches in the background. +``` + +- [ ] **Step 5: Verify (per-phrase counts)** + +```bash +f=plugins/python-standards/skills/python-code-review/SKILL.md +rg -c "Content matching no loaded domain skill" $f || true # expected: no output (0 matches) +rg -c "one violation class in one file" $f # expected: 1 +rg -c "exactly one rule id" $f # expected: 2 +rg -c "falls short of critical" $f # expected: 1 +rg -c "## Project" $f # expected: 1 +rg -c "dispatches in the background" $f # expected: 1 +``` + +- [ ] **Step 6: Commit** + +```bash +git add plugins/python-standards/skills/python-code-review/SKILL.md +git commit -m "feat(python-standards): plugin-level rule-none, justify clause, and finding unit in review cascade" +``` + +--- + +### Task 5: `plugins/python-standards/commands/python-review.md` — +background dispatcher + +**Files:** +- Modify: `plugins/python-standards/commands/python-review.md` + +**Interfaces:** +- Consumes: `python-code-reviewer` agent + (`plugins/python-standards/agents/python-code-reviewer.md`, exists); + probe paths owned by the contract; signal list owned by + process-artifacts (both restated self-contained here by design). + +- [ ] **Step 1: Rewrite the command body** + +Replace the whole body (everything after the frontmatter): + +```markdown +Review Python code against the python-standards skills. + +1. Load the `python-code-review` skill and follow it end to end. +2. Scope: `$ARGUMENTS` when given (named files); otherwise the current + diff — staged plus unstaged changes, or, on a clean tree, the diff of + the current branch against its base. +3. Python files only (`*.py`, `pyproject.toml`); note out-of-domain + files in the report Summary as out of scope. +4. Write the review report per the skill's report contract and reply + as the python-code-review skill specifies (report path, severity + summary, candidate gaps and offers). +``` + +with: + +```markdown +Review Python code against the python-standards skills by dispatching +the reviewer agent in the background — the review must never block +this session. + +1. Resolve the scope: `$ARGUMENTS` when given (named files); + otherwise the current diff — staged plus unstaged changes, or, on + a clean tree, the diff of the current branch against its base. +2. Pre-dispatch first-create check, gated on the contract probe: + check `/.claude/rules/working-process/review-reports.md`, + then `$HOME/.claude/rules/working-process/review-reports.md` — + first hit wins (paths owned by the review-reports contract; + restated here so the command is self-contained). No contract found + (Standalone install) → skip this step entirely. Contract found and + `docs/code-review/` carries no decision — no `.gitignore` of + exactly `*`, no git-tracked file under it, and no + explicit project instruction declaring the mode (signal list owned + by the process-artifacts rule) — ask the developer now: ignored or + tracked mode. +3. Dispatch the `python-code-reviewer` agent in the BACKGROUND with + the resolved scope. Python files only (`*.py`, `pyproject.toml`); + the agent notes out-of-domain files in the report Summary as out + of scope and writes the one report itself (`mode: agent` under the + installed contract). +4. Tell the developer: the review is running in the background; the + summary arrives as a task notification, not inline; progress via + `/tasks`; the report will land under `docs/code-review/`. +5. When the run's notification arrives, relay its reply to the + developer: report path, findings by severity, and the + candidate-gap offers verbatim. +``` + +- [ ] **Step 2: Verify (per-phrase counts)** + +```bash +f=plugins/python-standards/commands/python-review.md +rg -c "BACKGROUND" $f # expected: 1 +rg -c "task notification" $f # expected: 1 +rg -c "contract probe" $f # expected: 1 +rg -c "python-code-reviewer" $f # expected: 1 +``` + +- [ ] **Step 3: Commit** + +```bash +git add plugins/python-standards/commands/python-review.md +git commit -m "feat(python-standards): python-review dispatches the reviewer in the background with probe-gated first-create check" +``` + +--- + +### Task 6: `plugins/salesforce-standards/skills/salesforce-code-review/SKILL.md` + +Salesforce mirror of Task 4 — same three edits, salesforce texts. + +**Files:** +- Modify: + `plugins/salesforce-standards/skills/salesforce-code-review/SKILL.md` + +**Interfaces:** +- Consumes: contract phrases from Task 3 (mirrored). + +- [ ] **Step 1: Extend the `rule: none` cascade bullet (D3 + D4)** + +Replace: + +```markdown + - no defined rule covers the finding → report and count it anyway, + cited `(standard: , + rule: none)`, graded by the authoring rubric in the review-reports + contract; at critical its kind is always `defect`. Never invent a + rule id. +``` + +with: + +```markdown + - no defined rule covers the finding → report and count it anyway, + cited `(standard: , + rule: none)` — or `(standard: salesforce-standards, rule: none)` + when no skill of this plugin covers the concern. A concern + covered by the domain of an existing but not-yet-loaded skill is + NOT a candidate gap: load that skill and grade by its tags — + `rule: none` is never asserted against a skill the run did not + read. Graded by the authoring rubric in the review-reports + contract; at critical its kind is always `defect`; when graded + below critical while touching data integrity, security or + sharing, or a platform limit, the finding states in one clause + why it falls short of critical. Never invent a rule id. +``` + +- [ ] **Step 2: Single citation + Run-scope boundary (D2 + D3)** + +Replace: + +```markdown + When a matching rule exists, citing its specific id is mandatory — + a bare `(standard: )` citation is not a valid finding. + Critical findings carry the rule's kind inline + (`…, kind: defect|hardening`); the Summary headline breaks critical + counts down by kind (e.g. "critical: 33 — 12 defect, 21 hardening"). + Content matching no loaded domain skill stays a Summary out-of-scope + note, not a finding. +``` + +with: + +```markdown + When a matching rule exists, citing its specific id is mandatory — + a bare `(standard: )` citation is not a valid finding. A + finding cites exactly one rule id; one location violating two + rules yields two findings. Critical findings carry the rule's kind + inline (`…, kind: defect|hardening`); the Summary headline breaks + critical counts down by kind (e.g. "critical: 33 — 12 defect, + 21 hardening"). The Run scope is given by the caller and never + self-extended: within it, a Salesforce-domain concern no rule + covers is a counted `rule: none` finding (cascade above); files + outside the domain (Run scope section) stay Summary out-of-scope + notes. +``` + +- [ ] **Step 3: Fallback Body — finding unit and `## Project`** + +Replace: + +```markdown +- **Body**: a Summary section (scope reviewed, out-of-scope files, + headline counts), then per-file sections with Critical → Important → + Minor subsections — line-ascending within a subsection, line-less + findings alphabetically by cited element name; omit no-findings + files and empty severity sections; a zero-findings run still writes + the document. +``` + +with: + +```markdown +- **Body**: a Summary section (scope reviewed, out-of-scope files, + headline counts); a `## Project` section FIRST when findings are + not attributable to an existing file (same severity subsections as + a file section; ordered by rule id, `rule: none` last by + violation-class name); then per-file sections + with Critical → Important → Minor subsections — line-ascending + within a subsection, line-less findings alphabetically by cited + element name; omit no-findings files and empty severity sections; a + zero-findings run still writes the document. A finding + is one violation class in one file (or at project level), its body + enumerating every violating site, anchored by its first site; it + cites exactly one rule id. +``` + +- [ ] **Step 4: Update the `description:` invoker chain** + +After Task 7 the command no longer loads this skill — the agent does. +In the frontmatter, replace: + +```markdown +description: Use when auditing existing Salesforce code and metadata against the salesforce-standards skills — invoked by the /salesforce-review command or the salesforce-code-reviewer agent. +``` + +with: + +```markdown +description: Use when auditing existing Salesforce code and metadata against the salesforce-standards skills — invoked by the salesforce-code-reviewer agent, which the /salesforce-review command dispatches in the background. +``` + +- [ ] **Step 5: Verify (per-phrase counts)** + +```bash +f=plugins/salesforce-standards/skills/salesforce-code-review/SKILL.md +rg -c "Content matching no loaded domain skill" $f || true # expected: no output (0 matches) +rg -c "one violation class in one file" $f # expected: 1 +rg -c "exactly one rule id" $f # expected: 2 +rg -c "falls short of critical" $f # expected: 1 +rg -c "## Project" $f # expected: 1 +rg -c "dispatches in the background" $f # expected: 1 +``` + +- [ ] **Step 6: Commit** + +```bash +git add plugins/salesforce-standards/skills/salesforce-code-review/SKILL.md +git commit -m "feat(salesforce-standards): plugin-level rule-none, justify clause, and finding unit in review cascade" +``` + +--- + +### Task 7: `plugins/salesforce-standards/commands/salesforce-review.md` +— background dispatcher + +**Files:** +- Modify: `plugins/salesforce-standards/commands/salesforce-review.md` + +**Interfaces:** +- Consumes: `salesforce-code-reviewer` agent + (`plugins/salesforce-standards/agents/salesforce-code-reviewer.md`, + exists). + +- [ ] **Step 1: Rewrite the command body** + +Replace the whole body (everything after the frontmatter): + +```markdown +Review Salesforce code and metadata against the salesforce-standards +skills. + +1. Load the `salesforce-code-review` skill and follow it end to end. +2. Scope: `$ARGUMENTS` when given (named files); otherwise the current + diff — staged plus unstaged changes, or, on a clean tree, the diff + of the current branch against its base. +3. Salesforce files only, per the skill's run scope; note + out-of-domain files in the report Summary as out of scope. +4. Write the review report per the skill's report contract and reply + as the salesforce-code-review skill specifies (report path, severity + summary, candidate gaps and offers). +``` + +with: + +```markdown +Review Salesforce code and metadata against the salesforce-standards +skills by dispatching the reviewer agent in the background — the +review must never block this session. + +1. Resolve the scope: `$ARGUMENTS` when given (named files); + otherwise the current diff — staged plus unstaged changes, or, on + a clean tree, the diff of the current branch against its base. +2. Pre-dispatch first-create check, gated on the contract probe: + check `/.claude/rules/working-process/review-reports.md`, + then `$HOME/.claude/rules/working-process/review-reports.md` — + first hit wins (paths owned by the review-reports contract; + restated here so the command is self-contained). No contract found + (Standalone install) → skip this step entirely. Contract found and + `docs/code-review/` carries no decision — no `.gitignore` of + exactly `*`, no git-tracked file under it, and no + explicit project instruction declaring the mode (signal list owned + by the process-artifacts rule) — ask the developer now: ignored or + tracked mode. +3. Dispatch the `salesforce-code-reviewer` agent in the BACKGROUND + with the resolved scope. Salesforce files only, per the skill's + run scope; the agent notes out-of-domain files in the report + Summary as out of scope and writes the one report itself + (`mode: agent` under the installed contract). +4. Tell the developer: the review is running in the background; the + summary arrives as a task notification, not inline; progress via + `/tasks`; the report will land under `docs/code-review/`. +5. When the run's notification arrives, relay its reply to the + developer: report path, findings by severity, and the + candidate-gap offers verbatim. +``` + +- [ ] **Step 2: Verify (per-phrase counts)** + +```bash +f=plugins/salesforce-standards/commands/salesforce-review.md +rg -c "BACKGROUND" $f # expected: 1 +rg -c "task notification" $f # expected: 1 +rg -c "contract probe" $f # expected: 1 +rg -c "salesforce-code-reviewer" $f # expected: 1 +``` + +- [ ] **Step 3: Commit** + +```bash +git add plugins/salesforce-standards/commands/salesforce-review.md +git commit -m "feat(salesforce-standards): salesforce-review dispatches the reviewer in the background with probe-gated first-create check" +``` + +--- + +### Task 8: `plugins/project-memory/rules/project-memory.md` — +declared-instruction signal restatement + +The project-memory core rule owns the `docs/memory/` first-create +question and must stand without working-process — so it restates the +third signal self-contained (the spec's second justified restatement) +instead of referencing the process-artifacts rule. + +**Files:** +- Modify: `plugins/project-memory/rules/project-memory.md` + +**Interfaces:** +- Consumes: the signal semantics from Task 2 (restated, not + referenced). + +- [ ] **Step 1: Add the declared-instruction signal** + +Replace: + +```markdown +Never ask when a prior decision is observable: a `.gitignore` containing +exactly `*` means ignored was chosen; any git-tracked file under the +directory means tracked. Private memory (`.claude/memory/`) is always +ignored, so it is never asked. +``` + +with: + +```markdown +Never ask when a prior decision is present: a `.gitignore` containing +exactly `*` means ignored was chosen; any git-tracked file under the +directory means tracked; and an +explicit project instruction declaring the mode (e.g. a CLAUDE.md +note) counts as the decision — a declared ignored mode is +materialized by whoever first acts on it (writing the `*` +`.gitignore`), a declared tracked mode becomes observable with the +first committed file. Private memory (`.claude/memory/`) is always +ignored, so it is never asked. +``` + +- [ ] **Step 2: Verify (per-phrase counts)** + +```bash +f=plugins/project-memory/rules/project-memory.md +rg -c "explicit project instruction" $f # expected: 1 +rg -c "materialized" $f # expected: 1 +``` + +- [ ] **Step 3: Commit** + +```bash +git add plugins/project-memory/rules/project-memory.md +git commit -m "feat(project-memory): declared-instruction signal in the docs/memory first-create question" +``` + +--- + +### Task 9: Cross-file audit, validation, and `-dev.10` prerelease + +**Files:** +- Modify: `plugins/working-process/.claude-plugin/plugin.json` +- Modify: `plugins/python-standards/.claude-plugin/plugin.json` +- Modify: `plugins/salesforce-standards/.claude-plugin/plugin.json` + +**Interfaces:** +- Consumes: everything above. +- Produces: a branch ready for the dogfooding gate (Task 10) with + distinct cache version strings. + +- [ ] **Step 1: Cross-file consistency audit** + +Run each; expected results as noted: + +```bash +# The superseded sentence is gone everywhere (rg exits 1 on the +# expected zero matches — the || true keeps the audit green): +rg -l "Content matching no loaded domain skill" plugins/ || true # no matches +# The rubric is still verbatim in exactly its 3 plugin copies (+ repo rule = 4): +rg -l "corrupts data, breaks security" plugins/ .claude/rules/ # exactly 4 files +# The finding unit is stated in contract + both fallbacks: +rg -l "one violation class in one file" plugins/ # exactly 3 files +# Both commands background-dispatch: +rg -l "BACKGROUND" plugins/python-standards/commands/ plugins/salesforce-standards/commands/ # exactly 2 files +``` + +- [ ] **Step 2: Plugin validation** + +Run: +```bash +claude plugin validate . && for p in working-process python-standards salesforce-standards; do claude plugin validate plugins/$p; done +``` +Expected: all pass. (Run under bash, not zsh — see the #8 ledger +note.) + +- [ ] **Step 3: Mint `-dev.10` prerelease versions for dogfooding** + +Per the plugin-versioning rule (dogfooding needs a changed version +string; final numbers are minted by the release PR): in each of the +three manifests change only the `version` value — + +- `plugins/working-process/.claude-plugin/plugin.json`: + `"version": "0.11.0"` → `"version": "0.11.0-dev.10"` +- `plugins/python-standards/.claude-plugin/plugin.json`: + `"version": "0.2.0"` → `"version": "0.2.0-dev.10"` +- `plugins/salesforce-standards/.claude-plugin/plugin.json`: + `"version": "0.2.0"` → `"version": "0.2.0-dev.10"` + +- [ ] **Step 4: Re-validate and commit** + +```bash +claude plugin validate . +git add plugins/working-process/.claude-plugin/plugin.json plugins/python-standards/.claude-plugin/plugin.json plugins/salesforce-standards/.claude-plugin/plugin.json +git commit -m "chore: mint -dev.10 prerelease versions for contract-sharpening dogfooding" +``` + +- [ ] **Step 5: Report** + +Reply with the commit list (`git log --oneline develop..HEAD`) and the +audit results from Step 1. Task 10 (dogfooding gate) runs next, with +the developer. + +--- + +### Task 10: Dogfooding gate (with the developer, before the PR to +develop) + +The spec's empirical check, owned here. Runs in the developer's +projects — this task is executed together with the developer, who +reloads plugins and launches the review runs; the pass criteria are +checked against the reports they bring back. + +**Files:** +- None in this repo (reports land in the reviewed projects). + +**Interfaces:** +- Consumes: the `-dev.10` content from Task 9 (distinct cache version + strings make the reload observable). + +- [ ] **Step 1: Developer reloads plugins and verifies the cache** + +The plugin cache must show the `-dev.10` directories for the three +plugins. Not observable → stop; dogfooding against stale content +proves nothing. + +- [ ] **Step 2: Developer syncs the installed rules and verifies the + contract** + +The reviewer reads the contract from the INSTALLED rule file (content +hash via sync-rules, never plugin version) — a fresh cache does NOT +refresh it. Run the working-process sync-rules skill in the +dogfooding environment, then verify the installed contract carries +the new finding unit: + +```bash +rg -c "one violation class in one file" "$HOME/.claude/rules/working-process/review-reports.md" +``` +Expected: 1 (or the project-level copy when that is the installed +one). Not present → stop; the run would grade against the stale +contract and misattribute failures to this branch. + +- [ ] **Step 3: Developer runs one review rerun per rewritten + command** + +Both commands changed, so both are exercised: one `/python-review` +run and one `/salesforce-review` run, each launched from an +interactive session — the command path is itself under test +(background dispatch, pre-dispatch check) — and each setting +`rerun-of` to its prior report's runid (same scope). Target choice is +NOT free: at least one target must be a codebase whose prior report +contains file-less findings AND `rule: none` findings, so the +`## Project` section, the plugin-level citation, and the justify +clause actually fire (the python codebase whose prior runs invented +two pseudo-file sections for absent-manifest findings qualifies — +see the spec's Motivation). A target that cannot trigger a criterion +leaves it vacuous; Step 5 records that. + +- [ ] **Step 4: Check the report against the pass criteria** + +All must hold: + +- counts follow the finding unit: one finding per violation class per + file, sites enumerated inside findings (no per-instance explosion, + no cross-file folding, no self-declared "counting convention" + section); +- `## Project` section used — first — if any file-less findings exist; +- every finding cites exactly one rule id (no plural `rules:`, no + multi-id citations); +- any `rule: none` finding below critical touching data integrity, + security or sharing, or a platform limit carries its one-clause + justification; +- no "candidate gap" annotations inside the report body (the citation + is the marker); proposals appear in the run's reply; +- the Summary disposition maps the prior findings and declares the + pre-convention boundary (the prior report predates the finding + unit), with count deltas marked non-comparable; +- the dispatching session was not blocked (review ran in the + background; summary arrived as a task notification). + +- [ ] **Step 5: Gate decision** + +For each criterion record: exercised-and-passed, exercised-and-failed, +or vacuous (the targets never triggered it). All exercised criteria +pass → open the PR to develop, listing any vacuous criteria in the PR +description as explicitly accepted residual risk. Any criterion fails +→ the failure is a finding against this branch's texts; fix, re-run +this gate. diff --git a/docs/plans/2026-07-30-working-process-design-personas.md b/docs/plans/2026-07-30-working-process-design-personas.md new file mode 100644 index 0000000..d64f250 --- /dev/null +++ b/docs/plans/2026-07-30-working-process-design-personas.md @@ -0,0 +1,1155 @@ +--- +ticket: none +date: 2026-07-30 +status: implemented +adversary: concerns (resolved 2026-07-30) +branch: feature/design-personas +base: develop +--- + +# Design Personas Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Ship the system designer persona and two verdict-free consultation +agents in the working-process plugin, per the grilled and architect-reviewed +spec `docs/specs/2026-07-28-working-process-design-personas-design.md`. + +**Architecture:** Two personas (architect, system designer) single-sourced in +`*_PERSONA.md` files at the plugin root, with shared duties, the persona +boundary, and the consultation contract held once in `PERSONA_COMMON.md`. +Each persona gets a `*-consult` agent (one briefing in, one contribution +out, fresh isolated context, no verdict) and a `*-session` skill (live +main-thread dialogue); the architect keeps its verdict-bearing agent. +Selection between surfaces is lexical — trigger phrases and counterpoints +in `description:` fields. Two repo rules widen to stay consistent with the +new components. + +**Tech Stack:** Claude Code plugin components (markdown agents/skills with +YAML frontmatter), `claude plugin validate`, git. + +## Global Constraints + +Every task's requirements implicitly include all of these: + +- **Working directory**: the git worktree at `.claude/worktrees/design-personas/` + (branch `feature/design-personas`, based on `develop`). All paths below are + relative to that worktree root. +- **Baseline state**: trial artifacts already exist uncommitted in the + worktree — `plugins/working-process/PERSONA_COMMON.md`, + `SYSTEM_DESIGNER_PERSONA.md`, both `agents/*-consult.md`, plus edits to + `ARCHITECT_PERSONA.md`, `agents/architect.md`, + `skills/architect-session/SKILL.md`. Tasks below EDIT these files toward + the exact content shown; do not assume they are absent, and do not + recreate them from scratch when an Edit would do. +- **Public-repo hygiene**: all committed text in English; no machine paths + (`/home//…`); no company or client names. ONE exception: quoted + example trigger phrases inside a component's `description:` (skill or + agent) and the README trigger lines mirroring them may be non-English — + Task 3 Step 1 widens the repo-hygiene rule to exactly this scope before + the first agent phrases ship (precedent: grilling-session's + "przemagluj"). +- **Commit messages**: exactly one line, conventional-commit style + (`type:` or `type(scope):`), NO body, NO trailers — in particular no + `Co-Authored-By` line, even though the default harness instruction asks + for one; the user's instruction overrides it. +- **Never** create `evals/trigger-evals.json` or any eval artifact for any + skill. Never push or open a PR as part of this plan; committing locally + per the steps below is authorized by the developer's approval of this + plan, pushing is not. +- **Frontmatter safety**: any YAML scalar containing `: ` (colon+space) + must be quoted, or the component silently loads with empty metadata. +- **Validation**: after every change under `plugins/working-process/`, run + both `claude plugin validate .` and + `claude plugin validate plugins/working-process`; both must pass before + the task's commit. `rules/` files are NOT covered by validation — review + their text by hand. +- **Glossary bans bind prose** (`docs/domain/glossary.md`): never "mode" + for a persona surface; a consultation returns a **contribution**, never + a finding; the qualified persona form is "working-process persona", + never "process persona"; unqualified "session" means the Claude Code + conversation, `*-session` components are "session skills". +- **Plugin-internal references** use `${CLAUDE_PLUGIN_ROOT}/…` in agent and + skill bodies. Persona files reference `PERSONA_COMMON.md` in prose (no + variable) — deliberate, recorded in the spec §2; do not "fix" it. +- Plugin content never references this repo's `docs/domain/` artifacts by + path as if they ship with the plugin — the plugin installs into other + projects. + +--- + +### Task 1: Baseline commit — process artifacts + +**Files:** +- Commit (already written, no edits): `docs/specs/2026-07-28-working-process-design-personas-design.md`, + `docs/domain/glossary.md`, `docs/domain/adr/0001-persona-independence.md` + +**Interfaces:** +- Consumes: nothing. +- Produces: a clean baseline so later tasks' `git add` of plugin paths + never drags unrelated docs along. + +- [x] **Step 1: Verify the three artifacts are the only dirty docs paths** + +Run: `git status --short docs/` +Expected: exactly `M docs/domain/glossary.md`, `?? docs/domain/adr/`, +`?? docs/specs/2026-07-28-working-process-design-personas-design.md` +(plus, after this plan file is saved, +`?? docs/plans/2026-07-30-working-process-design-personas.md` — include it). + +- [x] **Step 2: Commit** + +```bash +git add docs/specs/2026-07-28-working-process-design-personas-design.md docs/domain/glossary.md docs/domain/adr/0001-persona-independence.md docs/plans/2026-07-30-working-process-design-personas.md +git commit -m "docs: add design-personas spec, plan, glossary entries, and persona-independence ADR" +``` + +--- + +### Task 2: `PERSONA_COMMON.md` — consultation contract and reworked opening + +**Files:** +- Modify: `plugins/working-process/PERSONA_COMMON.md` +- Modify: `plugins/working-process/ARCHITECT_PERSONA.md` (pointer sentence) +- Modify: `plugins/working-process/SYSTEM_DESIGNER_PERSONA.md` (pointer sentence) + +**Interfaces:** +- Consumes: current trial `PERSONA_COMMON.md` (three sections: Domain + expertise, Glossary and ADR duty, The boundary between the personas). +- Produces: a fourth section `## The consultation contract` with a scoping + clause; Tasks 3–6 reference it by that exact heading. Persona files + point at the contract for consult dispatches. + +- [x] **Step 1: Rework the file opening** + +In `plugins/working-process/PERSONA_COMMON.md`, replace the two opening +paragraphs (everything between the `# ` title and `## Domain expertise`) +with: + +```markdown +Every working-process persona carries the two duties below alongside its +own, respects the boundary between the personas, and — when dispatched in +consultation — is governed by the consultation contract that closes this +file. All four sections are defined only here, so they can never drift +between their consumers. + +`plan-adversary` carries the same two duties without being a persona: it +holds its role inline rather than in a persona file, and neither the +boundary section nor the consultation contract binds it — its own charter +is the one the persona files state, failure hunting on plan mechanics. +``` + +- [x] **Step 2: Append the contract section** + +At the end of the file, after the boundary section, append: + +```markdown +## The consultation contract + +This section binds `*-consult` dispatches and their dispatcher only. The +file's verdict-bearing consumers — `plan-adversary` directly, the +`architect` agent through its persona file — grade and stamp by duty, and +no sentence here overrides that. + +A consultation is one dispatch: briefed once, answered once, nothing kept +alive. What the persona knows is what its briefing says. + +The briefing — the dispatcher's obligations: + +- carry the subject, the constraints that bind it, and — stated + separately — what the developer has already decided against what is + still open; +- point, don't paste: name files and areas rather than inviting + exploration — what a consultation reads is what it costs; +- when both personas are consulted on one subject: one canonical briefing + text given to both, each with its own focusing question appended, and + no cross-persona content — neither is told what the other said. A + cross-check dispatch ("the architect argued X; does that hold + mechanically?") is legitimate on explicit request and is labelled as + one, so the reply is read as a response rather than as an independent + opinion. + +The reply — a contribution, never a finding, never a verdict; nothing +from it is stamped into frontmatter: + +- relayed to the developer attributed, in its own block, and + substantially verbatim — compression is allowed, merging is not; every + recommendation and every named risk survives, and text from two + personas never lands in one bullet; +- disagreement between the personas is presented as a disagreement, with + both positions — the choice is the developer's; the relaying thread may + add its own opinion, marked as its own; +- a consultation is dispatched as a named background agent, so the + developer can open its transcript and verify the relay rather than + trust it. +``` + +- [x] **Step 3: Add the third leg to the boundary section** + +Spec §2: "A consumer must not read a boundary that omits it" — and +`plan-adversary` (Task 6) reads only this file, never the persona files. +In `## The boundary between the personas`, after the two persona bullets +(system designer / architect), insert a third bullet: + +```markdown +- **`plan-adversary`** asks *how this will fail in execution* — the third + leg, standing outside the design-quality/mechanics split rather than + inside it: a reviewer hunting failure on plan mechanics, not a persona. +``` + +- [x] **Step 4: Extend both persona files' pointer sentences** + +Both edits are exact drop-in replace pairs. In +`plugins/working-process/ARCHITECT_PERSONA.md`, replace: + +```markdown +judgement, and the boundary with the system +designer. +``` + +with: + +```markdown +judgement, and the boundary with the system designer; a consult dispatch +is additionally governed by the consultation contract there. +``` + +In `plugins/working-process/SYSTEM_DESIGNER_PERSONA.md`, replace: + +```markdown +duty that comes before any judgement, and the boundary with the architect. +``` + +with: + +```markdown +duty that comes before any judgement, and the boundary with the +architect; a consult dispatch is additionally governed by the +consultation contract there. +``` + +- [x] **Step 5: Validate** + +Run: `claude plugin validate . && claude plugin validate plugins/working-process` +Expected: both pass. + +- [x] **Step 6: Commit** + +```bash +git add plugins/working-process/PERSONA_COMMON.md plugins/working-process/ARCHITECT_PERSONA.md plugins/working-process/SYSTEM_DESIGNER_PERSONA.md +git commit -m "feat(working-process): add shared persona file with consultation contract" +``` + +--- + +### Task 3: Consult agents — `background`, trigger phrases, contract deferral + +**Files:** +- Modify: `plugins/working-process/agents/architect-consult.md` (full target content below) +- Modify: `plugins/working-process/agents/system-designer-consult.md` (full target content below) + +**Interfaces:** +- Consumes: `PERSONA_COMMON.md` `## The consultation contract` (Task 2); + persona files at the plugin root. +- Produces: the two dispatchable consult agents. Their `description:` + trigger phrases are what Task 5's counterpoints and Task 7's workflow + line rely on. Frontmatter keys: `disallowedTools: SendMessage`, + `background: true`. Also widens the repo-hygiene exception (Step 1) — + a prerequisite, or the agent descriptions below would ship non-English + phrases the rule's letter covers only for skills. + +- [x] **Step 1: Widen the repo-hygiene exception to agent descriptions** + +In `.claude/rules/repo-hygiene.md`, replace: + +```markdown +- all committed text is in English. One narrow exception: quoted example + trigger phrases inside a skill's `description:`, and the `query` values of + its trigger-eval files (`evals/trigger-evals.json`), may be non-English — + both mirror how a developer actually asks, and the evals exercise exactly + those phrases (precedent: grilling-session's "przemagluj"). The + surrounding prose stays English. +``` + +with: + +```markdown +- all committed text is in English. One narrow exception: quoted example + trigger phrases inside a component's `description:` (skill or agent), + the README trigger lines that mirror them, and the `query` values of + trigger-eval files (`evals/trigger-evals.json`), may be non-English — + all mirror how a developer actually asks, and the evals exercise + exactly those phrases (precedent: grilling-session's "przemagluj"). + The surrounding prose stays English. +``` + +Commit this rule edit on its own, before the agent files: + +```bash +git add .claude/rules/repo-hygiene.md +git commit -m "docs(rules): widen the non-English trigger-phrase exception to agent descriptions" +``` + +- [x] **Step 2: Write `agents/architect-consult.md` — exact full content** + +```markdown +--- +name: architect-consult +description: "Architect in consultation — judges whether a design's shape is right: fit to the stated problem, single-purpose units, speculative structure, alternatives weighed, convention fit. Answers once from a fresh, isolated context, working from a briefing rather than a document — a second opinion unshaped by the current conversation (\"konsultacja z architektem\", \"consult the architect from a clean context\", \"second opinion from the architect\"). Verdict-free by construction — it returns a contribution, and nothing it returns is stamped into frontmatter: for a formal review ending in LGTM | concerns | blocking and stamped into frontmatter, dispatch the architect agent instead; for a live back-and-forth in the main thread, use the architect-session skill. When both personas are consulted on one subject, give both the same canonical briefing (each with its own focusing question appended) and tell neither what the other said. Dispatch on the most capable available model, named, as a background agent." +disallowedTools: SendMessage +background: true +--- + +Consultation surface of the architect persona — the isolated one. +FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/ARCHITECT_PERSONA.md` and adopt it fully, including +the standing duties, the persona boundary, and the consultation contract +it points at; per the glossary duty, read `docs/domain/glossary.md` and +`docs/domain/adr/` before any judgement. + +## Neither the `architect` agent nor `architect-session` + +One persona, three surfaces. The `architect` agent reviews a document and +returns a verdict the dispatcher stamps into frontmatter. The +`architect-session` skill holds a live conversation in the main thread, +where follow-up questions and immediate correction matter most. This agent +answers from a fresh, isolated context — the main thread's context stays +clean, and nothing the conversation has already committed to shapes the +judgement — and returns no verdict at all. + +## The dispatch + +One briefing, one answer, self-contained: you are not resumed and not +spawned ahead of need, so the briefing is everything you know. Its shape — +and the shape of your reply — is the consultation contract in +`${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md`; follow it from there rather +than from any summary. +Treat a settled decision as settled unless it contradicts a recorded ADR, +which the glossary duty tells you how to handle. + +Work the dimensions of your own duty. Where the briefing carries no +decomposition at all, say so and point at the system designer instead of +filling the gap. End with the questions you would need answered next, and +name plainly anywhere the briefing left you guessing — a briefing gap is +worth more to the developer than a confident answer built on it. + +## Hard limits + +- NO verdict, NO severity grading, NO frontmatter stamping. Your output + is a contribution, never a finding. +- Never rewrite the developer's documents. Propose in your reply and let + the dispatcher carry it. +- Write the reply for the developer, not as a report to the dispatcher — + the contract has it relayed attributed and substantially verbatim. +- You may spawn helpers for search and documentation lookup — the + domain-expertise duty often requires it. Never spawn another + working-process persona: two personas reconciled inside one answer hand + back one opinion where the developer asked for two. +``` + +- [x] **Step 3: Write `agents/system-designer-consult.md` — exact full content** + +```markdown +--- +name: system-designer-consult +description: "System designer in consultation — works out what a design is made of and how its parts behave together: parts and responsibilities, interactions and contracts, state and its lifecycle, behaviour under load, observability, technology choice. Answers once from a fresh, isolated context, working from a briefing — a second opinion unshaped by the current conversation (\"konsultacja z system designerem\", \"zapytaj designera na świeżo\", \"second opinion from the system designer\", \"consult the designer from a clean context\"). Verdict-free by construction: it returns a contribution — it grades nothing and nothing it returns is stamped into frontmatter. For a live back-and-forth in the main thread, use the system-designer-session skill instead. When both personas are consulted on one subject, give both the same canonical briefing (each with its own focusing question appended) and tell neither what the other said. Dispatch on the most capable available model, named, as a background agent." +disallowedTools: SendMessage +background: true +--- + +Consultation surface of the system designer persona — the isolated one. +FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/SYSTEM_DESIGNER_PERSONA.md` and adopt it fully, +including the standing duties, the persona boundary, and the consultation +contract it points at; per the glossary duty, read +`docs/domain/glossary.md` and `docs/domain/adr/` before any judgement. + +## Not `system-designer-session` + +One persona, two surfaces. The `system-designer-session` skill holds a +live conversation in the main thread, where follow-up questions and +immediate correction matter most. This agent answers from a fresh, +isolated context — the main thread's context stays clean, and nothing the +conversation has already committed to shapes the proposal. + +## The dispatch + +One briefing, one answer, self-contained: you are not resumed and not +spawned ahead of need, so the briefing is everything you know. Its shape — +and the shape of your reply — is the consultation contract in +`${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md`; follow it from there rather +than from any summary. +Treat a settled decision as settled unless it contradicts a recorded ADR, +which the glossary duty tells you how to handle. + +Work the dimensions of your own duty and dismiss by name the ones that do +not apply. End with the questions you would need answered next, and name +plainly anywhere the briefing left you guessing — a briefing gap is worth +more to the developer than a confident proposal built on it. + +## Hard limits + +- NO verdict, NO severity grading, NO frontmatter stamping. Formal review + ending in a verdict belongs to the `architect` agent. Your output is a + contribution, never a finding. +- Never rewrite the developer's documents. Propose in your reply and let + the dispatcher carry it. +- Write the reply for the developer, not as a report to the dispatcher — + the contract has it relayed attributed and substantially verbatim. +- You may spawn helpers for search and documentation lookup — the + domain-expertise duty often requires it. Never spawn another + working-process persona: two personas reconciled inside one answer hand + back one opinion where the developer asked for two. +``` + +- [x] **Step 4: Validate** + +Run: `claude plugin validate . && claude plugin validate plugins/working-process` +Expected: both pass — this exercises the quoted descriptions (which +contain `: ` and escaped quotes) and the `background: true` key. + +- [x] **Step 5: Commit** + +```bash +git add plugins/working-process/agents/architect-consult.md plugins/working-process/agents/system-designer-consult.md +git commit -m "feat(working-process): add architect-consult and system-designer-consult agents" +``` + +--- + +### Task 4: `system-designer-session` skill (new) + +**Files:** +- Create: `plugins/working-process/skills/system-designer-session/SKILL.md` + +**Interfaces:** +- Consumes: `SYSTEM_DESIGNER_PERSONA.md`; the consultation contract + heading (Task 2); the `system-designer-consult` agent name (Task 3). +- Produces: the designer's interactive surface. Do NOT create any + `evals/` directory or `trigger-evals.json` for it. + +- [x] **Step 1: Write the skill — exact full content** + +```markdown +--- +name: system-designer-session +description: "In-session consultation with the system designer persona — interactive work on what a design is made of: parts, contracts, state, behaviour under load, observability, technology choice. Use ONLY when the developer explicitly asks to talk to the system designer (\"ask the designer\", \"porozmawiajmy z designerem\", \"system designer session\"); generic design questions belong to brainstorming. For a second opinion from a fresh context unshaped by this conversation, dispatch the system-designer-consult agent instead — this skill can assemble its briefing." +--- + +Consultation surface of the system designer persona — the interactive +one. FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/SYSTEM_DESIGNER_PERSONA.md` and adopt it fully, +including the standing duties and the persona boundary it points at +(glossary before anything else). + +## Running the session + +- A live design conversation in the main thread: propose the + decomposition, the contracts, the state, the behaviour under load — + steered by the persona's mechanics dimensions, saying "not applicable + here" out loud for any dimension the subject genuinely lacks. +- Being interactive, you may simply ask the developer which domains + matter instead of only inferring them. +- One topic at a time; take a position on every question discussed. + +## Hard limits + +- NO verdict and NO frontmatter stamping — the designer has no + verdict-bearing agent; a document this session shaped goes through the + `architect` agent gate as usual. +- Never rewrite the developer's documents unasked. + +## Handing off + +As decisions settle, point at the right next step: + +- new or changed domain terms/decisions → a grilling-session (it records + the glossary/ADR updates); +- the same question, wanted from a fresh context unshaped by this + conversation → a `system-designer-consult` dispatch. This skill runs in + the main thread, so it assembles the briefing the consultation contract + in `${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md` requires: the subject, + the binding constraints, + settled decisions separated from open questions, and pointers to files + rather than pasted content; +- a document ready for formal review → an `architect` agent dispatch, + with a domain hint from this session. +``` + +- [x] **Step 2: Validate** + +Run: `claude plugin validate . && claude plugin validate plugins/working-process` +Expected: both pass. + +- [x] **Step 3: Commit** + +```bash +git add plugins/working-process/skills/system-designer-session/SKILL.md +git commit -m "feat(working-process): add system-designer-session skill" +``` + +--- + +### Task 5: Architect surfaces — arbitration counterpoints and narrowing + +**Files:** +- Modify: `plugins/working-process/agents/architect.md` +- Modify: `plugins/working-process/skills/architect-session/SKILL.md` + +**Interfaces:** +- Consumes: agent name `architect-consult` (Task 3). +- Produces: descriptions that no longer compete head-on with the consult + agent; glossary duty re-tightened to "earns a finding" on the + verdict-bearing agent. + +- [x] **Step 1: Narrow and counterpoint the `architect` agent description** + +In `plugins/working-process/agents/architect.md`, in the `description:` +value, replace: + +``` +Architect reviewing design quality — a grilled spec (primary target) or any design document or question dispatched standalone. +``` + +with: + +``` +Architect reviewing design quality — a grilled spec (primary target) or any design document dispatched standalone; its report always ends in a verdict. For a verdict-free second opinion on a question, dispatch architect-consult instead. +``` + +The rest of the description is unchanged. + +- [x] **Step 2: Re-tighten the glossary duty in the agent body** + +In the same file, replace: + +```markdown +Formal-review surface of the architect persona. FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/ARCHITECT_PERSONA.md` and adopt it fully; per its glossary +duty, read `docs/domain/glossary.md` and `docs/domain/adr/` right after +the persona, before any judgement. +``` + +with: + +```markdown +Formal-review surface of the architect persona. FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/ARCHITECT_PERSONA.md` and adopt it fully; per its glossary +duty, read `docs/domain/glossary.md` and `docs/domain/adr/` right after +the persona, before any judgement. Re-tightening that duty's shared +floor: a subject contradicting a glossary term or a recorded ADR earns a +finding (evidence = that file), not only a call-out. +``` + +- [x] **Step 3: Extend the Stamping section to both consultation surfaces** + +In the same file, replace: + +```markdown +bare question has nothing to stamp. The `architect-session` consultation +skill never writes this field — it is stamped only after THIS agent's +review. +``` + +with: + +```markdown +bare question has nothing to stamp. Neither consultation surface — the +`architect-session` skill or the `architect-consult` agent — ever writes +this field; it is stamped only after THIS agent's review. +``` + +- [x] **Step 4: Counterpoint and staleness fix in `architect-session`** + +In `plugins/working-process/skills/architect-session/SKILL.md`: + +(a) In `description:`, append before the closing sentence boundary — the +current value ends with "A formal review with a verdict is the architect +agent's job, never this skill's." Extend the value so it ends with: + +``` +A formal review with a verdict is the architect agent's job, never this skill's; for a second opinion from a fresh context unshaped by this conversation, dispatch the architect-consult agent instead — this skill can assemble its briefing. +``` + +The current value is an unquoted plain scalar with no `: ` inside, and +the appended text introduces none — quoting stays optional; if in doubt, +quote the whole value. + +(b) Replace the stale opening (post-extraction "both duties" wording): + +```markdown +Consultation surface of the architect persona — the interactive one. +FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/ARCHITECT_PERSONA.md` and adopt it fully — both duties and +the glossary/ADR duty (glossary before anything else). +``` + +with: + +```markdown +Consultation surface of the architect persona — the interactive one. +FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/ARCHITECT_PERSONA.md` and adopt it fully, including +the standing duties and the persona boundary it points at (glossary +before anything else). +``` + +(c) In `## Handing off`, insert a new second bullet between the +grilling-session bullet and the formal-review bullet: + +```markdown +- the same question, wanted from a fresh context unshaped by this + conversation → an `architect-consult` dispatch. This skill runs in the + main thread, so it assembles the briefing the consultation contract in + `${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md` requires: the subject, the + binding constraints, + settled decisions separated from open questions, and pointers to files + rather than pasted content; +``` + +- [x] **Step 5: Validate** + +Run: `claude plugin validate . && claude plugin validate plugins/working-process` +Expected: both pass. + +- [x] **Step 6: Commit** + +```bash +git add plugins/working-process/agents/architect.md plugins/working-process/skills/architect-session/SKILL.md +git commit -m "feat(working-process): tighten architect surfaces for consultation arbitration" +``` + +--- + +### Task 6: `plan-adversary` sources standing duties from the shared file + +**Files:** +- Modify: `plugins/working-process/agents/plan-adversary.md` + +**Interfaces:** +- Consumes: `PERSONA_COMMON.md` (Task 2) — its carve-out clause names + `plan-adversary`. +- Produces: the declared behaviour change (spec Scope): plan-adversary + gains the domain-expertise duty; its checklist scan becomes that duty's + first source. + +- [x] **Step 1: Replace the FIRST ACTION paragraph** + +In `plugins/working-process/agents/plan-adversary.md`, replace: + +```markdown +FIRST ACTION: read `docs/domain/glossary.md` and `docs/domain/adr/` when +they exist. Canonical terms bind your wording, and a plan contradicting a +glossary term or a recorded ADR is a finding (evidence = that file). +``` + +with: + +```markdown +FIRST ACTION: read `${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md` and adopt +its standing duties — domain expertise and the glossary/ADR duty; the +boundary section and the consultation contract there carve you out by +name. Then, per that glossary duty, read `docs/domain/glossary.md` and +`docs/domain/adr/` when they exist. Canonical terms bind your wording, +and — re-tightening the shared file's "called out" floor — a plan +contradicting a glossary term or a recorded ADR is a finding +(evidence = that file). +``` + +- [x] **Step 2: Position the checklist mechanism under the duty** + +In the same file, replace the `## Domain checklists` section body: + +```markdown +Scan the available skills for names matching `*-plan-review`. For every +domain the plan touches — judged from its content and the repo's markers +(e.g. `sfdx-project.json` → Salesforce) — load the matching checklist and +walk its dimensions with the same rigor as the generic ones below. +Domains without a checklist get the generic dimensions only. +``` + +with: + +```markdown +The first source under the shared file's domain-expertise duty: scan the +available skills for names matching `*-plan-review`. For every domain the +plan touches — judged from its content and the repo's markers (e.g. +`sfdx-project.json` → Salesforce) — load the matching checklist and walk +its dimensions with the same rigor as the generic ones below. Domains +without a checklist get the generic dimensions only, with the duty's +remaining sources (other skills, then verified model knowledge) covering +the expertise. +``` + +- [x] **Step 3: Validate** + +Run: `claude plugin validate . && claude plugin validate plugins/working-process` +Expected: both pass. + +- [x] **Step 4: Commit** + +```bash +git add plugins/working-process/agents/plan-adversary.md +git commit -m "feat(working-process): source plan-adversary standing duties from the shared persona file" +``` + +--- + +### Task 7: `rules/workflow.md` — consent offer and the two collisions + +**Files:** +- Modify: `plugins/working-process/rules/workflow.md` + +**Interfaces:** +- Consumes: agent names `architect-consult`, `system-designer-consult` + (Task 3). +- Produces: the step-1 consent offer; "architect" disambiguated to the + backticked `architect` agent; consultations named in the + model-selection paragraph. This file is the payload's only always-on + rule — keep the additions to the lines specified, nothing more. + +- [x] **Step 1: Extend step 1** + +Replace: + +```markdown +1. **Idea → spec.** When the superpowers:brainstorming skill is + available, start non-trivial features there; capture the agreed design + as a spec in `docs/specs/`. +``` + +with: + +```markdown +1. **Idea → spec.** When the superpowers:brainstorming skill is + available, start non-trivial features there; capture the agreed design + as a spec in `docs/specs/`. When the working-process consult agents + (`architect-consult`, `system-designer-consult`) are available, ask + once, early in the design conversation, whether the two personas + should be consulted as the design forms — yes / not now / not in this + session (honoured for the Claude Code session only; a durable + preference belongs in the developer's own instructions and is + respected when present). After a yes, dispatch a consultation when it + looks worth its cost, without asking again for that conversation, and + state the consent decision whenever it is made or changed. On a + genuinely ambiguous ask — in-thread dialogue or a fresh-context + consultation? — ask one short question rather than silently picking a + surface. +``` + +- [x] **Step 2: Tighten "architect" to the agent in step 3 and the stamping sentence** + +Replace: + +```markdown +3. **Grilled spec → architect review.** Offer a dispatch of the + working-process architect agent (when available); stamp its verdict +``` + +with: + +```markdown +3. **Grilled spec → architect review.** Offer a dispatch of the + working-process `architect` agent (when available); stamp its verdict +``` + +and replace: + +```markdown +After every architect or plan-adversary round, record the verdict +(`LGTM` | `concerns` | `blocking`) in the reviewed document's +`architect:` / `adversary:` frontmatter field. +``` + +with: + +```markdown +After every round of the `architect` agent or plan-adversary, record the +verdict (`LGTM` | `concerns` | `blocking`) in the reviewed document's +`architect:` / `adversary:` frontmatter field. A consultation +(`*-consult`) produces no verdict and nothing to record. +``` + +- [x] **Step 3: Name consultations in the model-selection paragraph** + +Replace: + +```markdown +in both directions. Reviews are never dispatched on the cheapest +available family. +``` + +with: + +```markdown +in both directions. Reviews are never dispatched on the cheapest +available family. Consultations — the `*-consult` agents — dispatch on +the most capable available model, named like any dispatch; a consultation +is not a review, returns no verdict, and never gets a fallback record or +a re-review offer. +``` + +- [x] **Step 4: Hand-review and validate** + +`rules/` is not covered by `claude plugin validate` — re-read the whole +file top to bottom checking: the file still has no YAML frontmatter (it +is the deliberate always-on rule), every mention of a skill or agent is +conditional ("when available"), and no line exceeds the file's plain-text +conventions. Then run +`claude plugin validate . && claude plugin validate plugins/working-process` +(unaffected, but confirms nothing else broke). + +- [x] **Step 5: Commit** + +```bash +git add plugins/working-process/rules/workflow.md +git commit -m "feat(working-process): add consultation consent offer to the workflow rule" +``` + +--- + +### Task 8: Repo rules — `*-consult` category and prerelease widening + +**Files:** +- Modify: `.claude/rules/plugin-authoring.md` +- Modify: `.claude/rules/plugin-versioning.md` + +**Interfaces:** +- Consumes: nothing from other tasks. +- Produces: the naming category Task 3's agents instantiate; the version + grammar Task 9's `0.11.0-dev.design-personas` requires. The versioning + edit MUST carry its rationale inline — the grilling declined this + decision an ADR on exactly that condition. + +- [x] **Step 1: Add the `*-consult` category to the authoring rule** + +In `.claude/rules/plugin-authoring.md`, replace: + +```markdown +- Names are kebab-case. Skills whose content is an open-ended + conversation are named `*-session`; formal reviews that end in a verdict + are agents. Operational skills may prompt for decisions without being + sessions — they are named for what they do (e.g. `sync-rules`). +``` + +with: + +```markdown +- Names are kebab-case. Skills whose content is an open-ended + conversation are named `*-session`; formal reviews that end in a verdict + are agents; verdict-free consultation agents — one briefing in, one + contribution out, from a fresh isolated context — are named `*-consult`. + Operational skills may prompt for decisions without being + sessions — they are named for what they do (e.g. `sync-rules`). +``` + +- [x] **Step 2: Widen the `dev` discriminator in the versioning rule** + +In `.claude/rules/plugin-versioning.md`, replace: + +```markdown +- Dogfooding unreleased content needs a changed version string — the + plugin cache keys content by version. A topic branch that dogfoods a + plugin sets `X.Y.Z-dev.` on it (the issue number the branch + name carries); the suffix flows into develop as-is. A topic that + does not dogfood never touches the version. On a version-line merge + conflict between parallel topics, the merging topic's own + `-dev.` wins — both strings are provisional. The release PR +``` + +with: + +```markdown +- Dogfooding unreleased content needs a changed version string — the + plugin cache keys content by version. A topic branch that dogfoods a + plugin sets `X.Y.Z-dev.` on it — the issue number the + branch name carries, or the branch short-name when the topic has no + issue (e.g. `-dev.design-personas`). Widening the discriminator + instead of minting another channel keeps one channel for one purpose; + the discriminator only needs to be unique among parallel topics. The + suffix flows into develop as-is. A topic that + does not dogfood never touches the version. On a version-line merge + conflict between parallel topics, the merging topic's own + `-dev.` wins — both strings are provisional. The release PR +``` + +and replace: + +```markdown +- Prerelease grammar: `-.`. Defined channels: + `dev.` (topic-branch dogfooding, above) and `rc.` (release +``` + +with: + +```markdown +- Prerelease grammar: `-.`. Defined channels: + `dev.` (topic-branch dogfooding, above) and `rc.` (release +``` + +- [x] **Step 3: Add the two persona paths to the breaking-surface list** + +In the same file, replace: + +```markdown + `*-plan-review` discovery convention, the plugin-root persona path — + `ARCHITECT_PERSONA.md`). +``` + +with: + +```markdown + `*-plan-review` discovery convention, the plugin-root persona paths — + `ARCHITECT_PERSONA.md`, `SYSTEM_DESIGNER_PERSONA.md`, + `PERSONA_COMMON.md`). +``` + +- [x] **Step 4: Hand-review** + +Re-read both edited rules end to end: rule files under `.claude/rules/` +are not validated by any tool; check no other line still says +`-dev.` (`grep -n 'dev\.' .claude/rules/plugin-versioning.md` +must return nothing). + +- [x] **Step 5: Commit** + +```bash +git add .claude/rules/plugin-authoring.md .claude/rules/plugin-versioning.md +git commit -m "docs(rules): add *-consult naming category and widen the dev prerelease discriminator" +``` + +--- + +### Task 9: Plugin identity, version, and the three synced surfaces + +**Files:** +- Modify: `plugins/working-process/.claude-plugin/plugin.json` +- Modify: `.claude-plugin/marketplace.json` +- Modify: `README.md` (repo root — the plugin table row) +- Modify: `plugins/working-process/README.md` + +All four in ONE commit — the marketplace-sync rule requires plugin.json, +catalog, and repo README to move together on any description change; the +plugin README rides along. + +**Interfaces:** +- Consumes: all shipped component names (Tasks 3–4); the widened grammar + (Task 8) legalizing the version string. +- Produces: version `0.11.0-dev.design-personas` — the dogfooding key for + the whole topic. + +- [x] **Step 1: `plugin.json` — description and version** + +Replace the `description` value with: + +``` +Spec-driven working process on top of superpowers: grilling-session, architect-session, system-designer-session and sync-rules skills, architect and plan-adversary review agents, architect-consult and system-designer-consult consultation agents, and process rules distributed as a Rules payload; domain plugins hook in via *-plan-review checklist skills and their own rules/ payloads +``` + +Replace the `version` value: `0.11.0-dev.10` → `0.11.0-dev.design-personas`. + +- [x] **Step 2: `.claude-plugin/marketplace.json` — catalog description** + +Replace the working-process entry's `description` value with: + +``` +Spec-driven working process on top of superpowers: grilling-session, architect-session, system-designer-session and sync-rules skills, architect and plan-adversary review agents, architect-consult and system-designer-consult consultation agents, plus distributed process rules +``` + +- [x] **Step 3: Repo `README.md` — the plugin table row** + +Replace the `working-process` row's description cell with: + +``` +Spec-driven working process: grilling-session, architect-session, system-designer-session and sync-rules skills, architect and plan-adversary review agents, two verdict-free consultation agents, distributed process rules +``` + +- [x] **Step 4: Plugin `README.md` — components, single-sourcing, model selection** + +(a) In `## Components`, after the `architect-session` entry, insert: + +```markdown +- **`architect-consult` agent** — the architect as a one-shot + consultation from a fresh, isolated context: one briefing in, one + contribution out, no verdict, nothing stamped. Dispatched as a named + background agent on the most capable available model. Triggers: + "konsultacja z architektem" / "second opinion from the architect". +- **`system-designer-consult` agent** — the system designer persona + (parts, contracts, state, behaviour under load, observability, + technology choice) as the same kind of one-shot consultation. + Triggers: "zapytaj designera na świeżo" / "second opinion from the + system designer". +- **`system-designer-session` skill** — the system designer as an + interactive in-session consultation; hands off to a grilling-session, + a `system-designer-consult` dispatch (assembling its briefing), or an + `architect` dispatch. Triggers: "ask the designer" / "porozmawiajmy z + designerem". +``` + +(b) Replace the single-sourcing paragraph: + +```markdown +The architect persona is single-sourced in [ARCHITECT_PERSONA.md](./ARCHITECT_PERSONA.md), +shared by the `architect` agent and the `architect-session` skill. Every +component reads `docs/domain/glossary.md` and `docs/domain/adr/` first, +when they exist, so it speaks the project's language from its first +message. +``` + +with: + +```markdown +Each persona is single-sourced in its file at the plugin root — +[ARCHITECT_PERSONA.md](./ARCHITECT_PERSONA.md) and +[SYSTEM_DESIGNER_PERSONA.md](./SYSTEM_DESIGNER_PERSONA.md) — with the +shared duties, the persona boundary, and the consultation contract held +once in [PERSONA_COMMON.md](./PERSONA_COMMON.md). `plan-adversary` +sources its standing duties from the same shared file without being a +persona. Every component reads `docs/domain/glossary.md` and +`docs/domain/adr/` first, when they exist, so it speaks the project's +language from its first message. +``` + +(c) In `## Model selection`, after the sentence ending "one family below +for small mechanical ones.", insert: + +```markdown +Consultations (the `*-consult` agents) dispatch on the most capable +available model as named background agents; they return no verdict, so +the fallback machinery below never applies to them. +``` + +- [x] **Step 5: Validate** + +Run: `claude plugin validate . && claude plugin validate plugins/working-process` +Expected: both pass (this exercises the edited JSON files). + +- [x] **Step 6: Commit** + +```bash +git add plugins/working-process/.claude-plugin/plugin.json .claude-plugin/marketplace.json README.md plugins/working-process/README.md +git commit -m "feat(working-process): sync plugin identity and set dogfooding version 0.11.0-dev.design-personas" +``` + +--- + +### Task 10: Final verification sweep + +**Files:** +- No new edits expected; fixes discovered here ride in a final + `fix(working-process):` commit. + +- [x] **Step 1: Validate both levels one last time** + +Run: `claude plugin validate . && claude plugin validate plugins/working-process` +Expected: both pass. + +- [x] **Step 2: Glossary-ban greps — all must come back clean** + +```bash +# banned qualified persona form (only the "working-process persona(s)" +# compound may appear — the -i exclusion covers its capitalized and +# plural forms while still catching a bare "process personas"): +grep -rn -i 'process persona' plugins/working-process/ | grep -v -i 'working-process persona' +# banned "mode" for a persona surface — inspect any hit by eye: +grep -rn '\bmode\b' plugins/working-process/agents/ plugins/working-process/skills/architect-session/ plugins/working-process/skills/system-designer-session/ plugins/working-process/*.md +# a consultation never returns a "finding": +grep -rn -i 'finding' plugins/working-process/agents/architect-consult.md plugins/working-process/agents/system-designer-consult.md plugins/working-process/skills/system-designer-session/SKILL.md +``` + +Expected: first grep empty; second grep only "failure … modes" senses +(e.g. `SYSTEM_DESIGNER_PERSONA.md` "failure and recovery modes") or +review-report `mode:` mentions, never "X mode of the Y persona"; third +grep only the contrastive "never a finding" lines. + +- [x] **Step 3: Cross-reference sweep** + +```bash +# every plugin file naming the consult agents spells them correctly: +grep -rn 'consult' plugins/working-process/ .claude/rules/plugin-authoring.md | grep -v -- '-consult' +# no plugin file references this repo's ADR by path: +grep -rn '0001-persona-independence' plugins/ +# version string consistent: +grep -rn 'design-personas' plugins/working-process/.claude-plugin/plugin.json +``` + +Expected: first grep only prose uses of "consultation/consulted"; second +grep empty; third grep exactly the one version line. + +- [x] **Step 4: Confirm a clean tree** + +Run: `git status --short` +Expected: empty (every task committed its files). If anything is dirty, +it belongs to a task above — finish that task rather than sweeping it in +here. + +--- + +## Self-review record + +Checked against the spec section by section: §1 dimensions and the +"not applicable" licence live in the persona files (baseline, Task 2 +pointer edits); §2 single-sourcing incl. the two stated consequences +(Tasks 2, 6) and the versioning-list addition (Task 8); §3 surface table, +lexical arbitration — trigger phrases and counterpoints (Tasks 3, 4, 5) +plus the ask-on-ambiguity rule (Task 7); +§4 one-shot dispatch + `background` (Task 3); §5 independence — +`disallowedTools` retained, textual limit reworded to "working-process +persona" (Task 3); §6–7 the contract in `PERSONA_COMMON.md` with its +scoping clause and the invariant sentence in both descriptions (Tasks 2, +3); §8 the offer and the two workflow collisions (Task 7); §9 has no +implementable artifact (cost is an argument, not a mechanism); §10 +attribution/verifiability via the contract and `background: true` +(Tasks 2, 3), consent-state line (Task 7). Non-goals introduce no tasks. +Files-to-touch list fully mapped: every file it names appears in exactly +one task above. Accepted risks: the `disallowedTools`-floor check and +selection-quality dogfooding happen after implementation under the +`-dev.design-personas` version, outside this plan. + +## Adversary findings — 2026-07-30 round 1 + +Dispatched on Fable 5 (self-reported: fable 5; prescribed tier). Verdict: +blocking — three Important, three Minor. The round verified every quoted +replace-block in Tasks 5–9 character-exact against the worktree; the +blockers were coverage gaps, not stale old-strings. All six resolved the +same day by plan revision: + +- **Important**: the boundary section's third leg (spec §2: + "A consumer must not read a boundary that omits it") had no task — + `plan-adversary` reads only `PERSONA_COMMON.md`. → Fixed: Task 2 Step 3 + adds the third bullet to the boundary section. +- **Important**: spec §3's ask-on-ambiguity bullet landed in no artifact. + → Fixed: appended to the workflow.md step-1 addition (Task 7), the + always-on main-thread surface where the picking happens. +- **Important**: Polish trigger phrases in *agent* descriptions and README + bullets exceeded the repo-hygiene exception's letter ("a skill's + `description:`"). → Fixed: Task 3 Step 1 widens the rule (own commit, + before the first agent phrases ship); Global Constraints updated to + match. +- **Minor**: Task 2's first pointer-edit old-string did not match + `ARCHITECT_PERSONA.md` verbatim. → Fixed: verbatim ending quoted. +- **Minor**: neither consult description carried the noun "contribution" + (spec §7: "the descriptions alike"). → Fixed in both target + descriptions. +- **Minor**: the Task 10 banned-form grep masked the plural via + `grep -v 'personas'`. → Fixed: case-insensitive exclusion of the + legitimate compound only. + +## Adversary findings — 2026-07-30 round 2 + +Fresh dispatch on the revised plan, Fable 5 (self-reported: fable 5; +prescribed tier). Verdict: concerns — two Minor, both introduced by the +round-1 revision; all six round-1 resolutions independently confirmed +against the worktree. Both resolved the same day; the frontmatter carries +`concerns (resolved 2026-07-30)`: + +- **Minor**: Task 2 Step 4's replacement block was not a drop-in for its + quoted old-string — it opened with a literal ellipsis and re-quoted + text preceding the old-string, so a mechanical replace would corrupt + the pointer sentence. → Fixed: both persona-file edits are now exact + replace pairs, the designer file's quoted verbatim too. +- **Minor**: four agent/skill body sites referenced the shared file as + bare `PERSONA_COMMON.md`, against the plan's own Global Constraint and + the authoring rule (`${CLAUDE_PLUGIN_ROOT}/…` in bodies; the bare-name + carve-out covers persona files only). → Fixed: all four sites use + `${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md`. diff --git a/docs/specs/2026-07-23-review-contract-sharpening-design.md b/docs/specs/2026-07-23-review-contract-sharpening-design.md new file mode 100644 index 0000000..de6818c --- /dev/null +++ b/docs/specs/2026-07-23-review-contract-sharpening-design.md @@ -0,0 +1,366 @@ +--- +ticket: "#10" +date: 2026-07-23 +status: implemented +grilled: 2026-07-23 +architect: LGTM +branch: feature/10-contract-sharpening +base: develop +--- + +# Review-report contract sharpening — design + +## Overview + +Six contract-level decisions closing the gaps that dogfooding the 0.2.0 +severity-in-tag model exposed: the counting convention, single-citation +findings, a plugin-level `rule: none` form, a justify-not-critical +clause, the candidate-gap marker, and background review dispatch. All +changes live in the review-reports contract, the two `*-code-review` +skills' grading procedures, and the two review commands. No rule +content changes — new rules, sub-rules, and audit-mode semantics are +domain work tracked separately. + +## Motivation + +Post-#8 dogfooding (2026-07-23, seven agent runs across six real +codebases, python + salesforce) confirmed the severity-in-tag model: +zero fabricated ids, `findings:` counts matching the body in every +complete report, kind labels 100% tag-consistent, the bare-citation +failure mode closed by a direct A/B on the same code. The residual +variance is contract-level — places where two honest runs produce +incomparable reports because the contract does not regulate the choice: + +- The same codebase audited twice on the same day returned counts of + 35/39/3 (per-file enumeration) vs 10/8/6 (one finding per violation + class, cross-file `## Cross-cutting` sections bending the per-file + layout); the second run declared its own "Counting convention" + Summary section — the agent noticed the contract's silence. +- One finding cited two rule ids of different severities + (Important + Minor in a single entry), another used a plural + `rules:` key, another cited two standards at once. +- A run met findings no loaded skill's domain covers and spontaneously + cited the plugin name: `(standard: python-standards, rule: none)` — + a form the contract does not define. +- One run justified an Important grade on a data-integrity `rule: none` + finding ("Not critical only because …"); another graded a comparable + finding with no justification — only the first is auditable. +- One report annotated `rule: none` findings "candidate gap, see + reply"; another, for the same class of findings, did not. +- Review runs block the dispatching session either way today: the + committed commands run the review in-session end to end, and the + dogfooded agent dispatches ran synchronously (the CLI's default), + freezing the session for the whole run. + +## Decisions + +### 1. Counting convention: one finding = one rule × one file + +A finding is one violated rule in one file — or at project level when +the violation is not attributable to an existing file (a missing +lockfile, an absent manifest). Every violating site is enumerated in +the finding body: line numbers, or the domain's stable key where lines +do not apply (metadata reviewed without source lines). A line-anchored +finding sorts by its first violating line, so the existing "ascending +line order" layout text is unchanged; project-level findings live in a +single canonical `## Project` section that behaves like a file section +(same severity subsections), placed first — before the per-file +sections — its findings ordered by rule id, with `rule: none` findings +last, ordered by violation-class name. +Dogfooding showed the need: two runs invented two different pseudo-file +sections for the same absent-manifest findings. + +The unit is uniformly one **violation class** per file (or project +level): for tagged rules the rule id names the class; for `rule: none` +findings — where the "rule" in the pair is literally `none` — the +class is the one the candidate-gap offer names anyway, so two +unrelated uncovered concerns in one file are two findings, each with +its own severity and rerun disposition. `findings:` counts therefore +mean: the number of (violation class, file-or-project) pairs to fix. + +Rationale: this is the only convention consistent with the layout the +contract already mandates (per-file sections, line-ordered findings) — +cross-file folding cannot name a file or a line, and per-instance +enumeration makes full-audit reports unreadable. On a diff review a +file rarely violates one rule at more than one site, so the convention +degenerates to per-instance naturally — one convention covers both run +shapes without a reviewer-judged "diff vs audit" switch. Codifies what +the per-file-enumeration run already did unprompted. + +Accepted cost: `findings:` no longer measures violation magnitude +(three sites of one rule in one file count as 1); magnitude stays +visible in the finding body. A systemic violation across N files is N +findings — verbose but faithful; a prose pattern note in Summary is +welcome and never affects counts. + +Rerun disposition (`rerun-of`) tracks sites within a finding ("lines +42, 87 fixed; 130 remaining"); a partially fixed finding counts as +**remaining** — a finding lives until its last site is fixed. + +Reports are self-describing — they may live git-ignored or in an +archive outside the repo, so rerun behavior never depends on anything +unreadable from the reports themselves. When the prior report's +findings do not follow the finding unit (a pre-convention report — +readable off the report itself), the Summary disposition says so and +maps prior findings best-effort; count deltas across that boundary are +not comparable. + +### 2. One finding, one citation + +A finding cites exactly one rule id — singular `rule:` key; the +finding's severity is the cited rule's severity. A code location that +violates two rules yields two findings, one per (rule, file) entry, +even when both point at the same line; each gets its own severity, +kind, counter position, and rerun disposition. This generalizes the +standards-rule-tags sentence "distinct sub-rule violations at one code +location are distinct findings" from sub-rules to rules and standards; +the generalized statement is contract-owned (report level), the repo +authoring rule keeps only its sub-rule sentence. + +### 3. Plugin-level `rule: none` citation + +When no loaded skill's domain covers a finding, it is cited +`(standard: , rule: none)` — the standards plugin itself. +At `rule: none` the citation's only job is routing the candidate gap +(which surface would receive the new rule; which repository an +upstream report targets); when no skill covers the domain, the plugin +is exactly the right granularity, because the gap may call for a new +skill, not a new rule in an existing one. A "nearest domain skill" +rule was rejected: it forces fake precision and reintroduces a +discretionary reviewer choice. The candidate-gap offer line may then +propose a new skill instead of a new rule. + +This supersedes the cascade sentence "content matching no loaded +domain skill stays a Summary out-of-scope note, not a finding" in both +code-review skills. The boundary replacing it: the Run scope is given +by the dispatch (a diff or named paths) and a run never extends it. +Within that scope, a concern covered by the domain of an existing but +not-yet-loaded skill of the plugin is NOT a candidate gap — the +cascade's own instruction (load skills as the content demands) applies: +load that skill and grade by its tags. A `rule: none` citation asserts +"no rule covers this", which cannot be asserted against a skill the +run never read. Only a concern no skill of the plugin covers is a +counted plugin-level `rule: none` finding. In a mixed run the cited +plugin is the one whose domain owns the finding's file — the same +routing that assigns files to domains; a project-level finding routes +by its violation-class domain. Files outside every loaded plugin's +domain stay Summary out-of-scope notes, exactly as today. + +### 4. Justify-not-critical clause + +Appended to the `rule: none` grading step, after "a critical-graded +`rule: none` finding is always `kind: defect`": + +> A `rule: none` finding graded below critical while touching data +> integrity, security or sharing, or a platform limit states in one +> clause why it falls short of critical. + +The predicate is observable (the critical rubric's territory, not a +judgment word), and the clause doubles as a self-check: when it cannot +be written, the finding should be critical. It lives in the grading +step of the contract and both skills' cascades — the four verbatim +authoring-rubric copies stay untouched. + +### 5. Candidate-gap marker: the citation is the marker + +The `rule: none` citation is the report's only candidate-gap marker; +the proposals (violation class, proposed rule id, graded severity) +live in the run's reply, never in the report. Division of labor: +report = durable facts about the code; reply = ephemeral offers; +Project memory = accepted parks. A second in-report marker is a second +surface restating the same fact — the same drift class the +`## Review severities` roll-up removal eliminated, and it had already +drifted (present in one report, absent in another). + +### 6. Background review dispatch + +A Standards code review never blocks the dispatching session. The +convention lives in two layers with distinct audiences: + +- **Both review commands** carry the instruction self-contained + (standalone installs have no working-process rules): dispatch the + reviewer agent in the background; the summary arrives as a task + notification, not inline; progress via `/tasks`; report location + unchanged. +- **The contract** adds one family-convention sentence to the existing + dispatcher bullet: a reviewer-agent dispatch from an interactive + session runs in the background — a review never blocks an + interactive dispatching session; the run's owner writes the one + report regardless of fore/background mode. This binds any future + interactive dispatcher, not just today's two commands; + non-interactive dispatchers (CI, automation) stay free to run + synchronously — the contract's existing no-interactive-dispatcher + path is untouched. + +The duplication is deliberate and role-split (standalone +self-sufficiency vs family convention), not a drifting restatement. + +Command-initiated runs change ownership: today both commands run the +review in-session (`mode: solo`); dispatching a reviewer agent makes +them dispatchers of `mode: agent` runs. The dispatcher duties ride in +the self-contained command text (the contract is not in the +dispatching session's context) — chiefly the pre-dispatch first-create +check for `docs/code-review/`. The check is gated on the contract +probe: it runs only when the probe finds an installed contract — in a +Standalone install the question does not exist (as both inline +fallbacks already record) and the reviewer agent creates the directory +per its fallback, unchanged. The contract owns the probe paths; the +commands carry a justified self-contained restatement of them — the +same ownership pattern as the first-create signal list. When it runs, it asks only when the +dispatcher is interactive AND no prior decision exists; a +non-interactive dispatcher keeps the contract's existing defer +behavior. After the run's task +notification arrives, the dispatching session relays the reply's +candidate-gap offers to the developer. + +The declared-decision signal is promoted into the first-create +convention itself rather than special-cased here: the convention's +"decided" signals become three — a `.gitignore` of exactly `*`, a +git-tracked file under the directory, or an explicit project +instruction declaring the mode (e.g. a CLAUDE.md note that review +reports are always git-ignored). A declared ignored mode is +materialized by whoever first acts on it — writing the `*` +`.gitignore` — so the decision becomes observable and every consumer +(the process-artifacts rule included) reads the same answer; a +declared tracked mode becomes observable with the first committed +file. Ownership: the process-artifacts rule owns the operational +signal list; the glossary term mirrors it, the contract's dispatcher +bullet and the grilling-session skill reference it, and the justified +self-contained restatements are the review commands and the +project-memory core rule (which must stand without working-process) — +one definition, no fork. + +## Surfaces and changes + +- `plugins/working-process/rules/review-reports.md` — Layout gains the + finding-unit definition, first-line anchoring, and the canonical + `## Project` section for file-less findings (decision 1); + `rerun-of` gains partially-fixed-counts-as-remaining (1); + Finding citations gains single-citation (2), the plugin-level + `rule: none` form (3), and the justify-not-critical clause (4); + Candidate-gap offers gains the marker sentence and the new-skill + proposal sentence (5, 3); the dispatcher bullet gains the background + sentence (6). +- `plugins/python-standards/skills/python-code-review/SKILL.md` and + `plugins/salesforce-standards/skills/salesforce-code-review/SKILL.md` + — the grading cascade mirrors decisions 3 and 4; decision 3 replaces + the cascades' out-of-scope-note sentence ("content matching no + loaded domain skill…") with the Run-scope boundary stated there; the + inline standalone fallback (a strict subset of the contract) absorbs + the finding unit and single-citation, and its Body gains the + canonical `## Project` section (first, same severity subsections) so + project-level findings have a defined home in standalone runs; the + justify clause reaches the fallback through its existing step-3 + cascade reference — no second in-file copy. A standalone install is + never laxer than a full one. +- `plugins/working-process/rules/process-artifacts.md` — the + first-create question gains the declared-instruction signal and its + materialization (decision 6). +- `plugins/working-process/skills/grilling-session/SKILL.md` — its + first-create restatement becomes a reference to the + process-artifacts signal list (decision 6, fork closure). +- `plugins/project-memory/rules/project-memory.md` — its + observable-decision sentence gains the declared-instruction signal + as a self-contained restatement, it owns `docs/memory/` and must + stand without working-process (decision 6, fork closure). +- `plugins/python-standards/commands/python-review.md` and + `plugins/salesforce-standards/commands/salesforce-review.md` — + background dispatch with notification expectations, the solo→agent + run-ownership change, the pre-dispatch first-create check, and the + candidate-gap offer relay (6). + +## Invariants + +- The authoring rubric stays verbatim in exactly its four existing + places; nothing here edits or restates it. +- No new report frontmatter fields; `findings:` keeps its three keys; + existing layout sections keep their names and order (decision 1 adds + the `## Project` section, always first). +- `.claude/rules/standards-rule-tags.md` is unchanged. +- Inline fallbacks remain strict subsets of the contract — never a + different shape. + +## Review rounds + +Architect round 1 (2026-07-23, Fable 5): **blocking** — four findings, +all amended in place: (F1) decision 3 now names the superseded cascade +sentence and states the Run-scope boundary (the scope is given by the +dispatch, never self-extended); (F2) decision 6 now states the +commands' solo→agent run-ownership change, the pre-dispatch +first-create check with its ask-conditions (observable signals and +explicit project guidance both count as decided; non-interactive +dispatchers defer), and the candidate-gap offer relay; (F3) the +`## Project` section is placed first and the layout invariant +reworded; (F4) the background-dispatch convention is scoped to +interactive dispatching sessions. + +Architect round 2 (2026-07-23, Fable 5): **blocking** — four findings, +all amended in place: (F1) the round-1 "existing but unloaded skill" +citation branch dropped — a concern an existing skill's domain covers +loads that skill and re-enters the cascade; `rule: none` is never +asserted against an unread skill; (F2) the counting unit stated +uniformly as one violation class per file — the rule id names the +class for tagged rules, the candidate-gap class names it at +`rule: none`; glossary Finding term mirrored; (F3) the +declared-instruction signal promoted into the first-create convention +itself (glossary term, process-artifacts rule, contract dispatcher +bullet — one definition) with materialization semantics, instead of a +command-local special case; (F4) the justify-not-critical predicate +regains "or sharing". + +Architect round 3 (2026-07-23, Fable 5): **concerns** — one Important, +four Minor, all amended in place (2026-07-24): (F1) the command's +pre-dispatch first-create check is gated on the contract probe — +Standalone installs keep no-question behavior, the fallback sentence +stays true; (F2) `## Project` ordering gains the `rule: none` tiebreak +(last, by violation-class name); (F3) the justify clause reaches the +inline fallback via its existing step-3 reference instead of a second +in-file copy; (F4) signal-list ownership stated — process-artifacts +rule owns, glossary mirrors, contract references, commands carry the +one self-contained restatement; (F5) `ticket: none` is deliberate — +this spec awaits its own ticket (created after this review cycle); +the stale `feature/8` branch context of the worktree does not source +it. + +Architect round 4 (2026-07-24, Fable 5): **LGTM** — three Minor +edge-closure suggestions, applied same day: mixed-run routing for the +plugin-level citation (the plugin whose domain owns the finding's +file; project-level routes by violation-class domain), the inline +fallback Body gains the `## Project` section, and probe-path ownership +stated (contract owns, commands carry the justified self-contained +restatement). + +Post-LGTM amendments (2026-07-24, from plan-adversary round 2, no new +decisions): the signal-list fork closure named its two remaining +restatement surfaces (grilling-session → reference; project-memory +core rule → self-contained restatement, and the ownership sentence +now lists both exceptions); the fallback `## Project` section +explicitly keeps the same severity subsections; the glossary Contract +probe term gains dispatching review commands as probe runners; the +empirical check requires a sync-rules update of the installed +contract first (drift is content-hash, not plugin-version) and a +command-launched run. + +## Out of scope + +Rule content of any kind: new rules (SOQL injection, dangerous +grants), candidate sub-rules surfaced by dogfooding, audit-mode +semantics, sub-rule boundary changes, README provenance wording, +writing-skills compliance edits — tracked in #6 (salesforce) and the +skills-rework backlog. + +## Versioning and validation + +- No version bumps on this branch: per the plugin-versioning rule, + bumps happen once, in the develop→master release PR, sized by each + plugin's total accumulated change since the last release. For the + changes specified here the expected size is minor for all three + touched plugins (backward-compatible contract additions; cascade and + command changes) — the release PR decides the final numbers. +- Dogfooding from this branch mints the `-dev.10` prerelease on each + plugin whose content it loads (e.g. `0.11.0-dev.10`); the suffix + flows into develop and is stripped by the release PR. +- `claude plugin validate .` and per-plugin validation pass. +- Empirical check: a dogfooding rerun on a previously reviewed + codebase produces counts with the decision-1 semantics and a + disposition comparable to its prior report. diff --git a/docs/specs/2026-07-28-working-process-design-personas-design.md b/docs/specs/2026-07-28-working-process-design-personas-design.md new file mode 100644 index 0000000..a90937d --- /dev/null +++ b/docs/specs/2026-07-28-working-process-design-personas-design.md @@ -0,0 +1,739 @@ +--- +ticket: none +date: 2026-07-28 +status: implemented +grilled: 2026-07-30 +architect: concerns (resolved 2026-07-30) +branch: feature/design-personas +base: develop +--- + +# Design personas — a system designer alongside the architect + +## Problem + +The working-process plugin ships one design persona, the architect, across +two surfaces: the `architect` agent (formal design-quality review ending in a +verdict the dispatcher stamps into a document's `architect:` field) and the +`architect-session` skill (interactive in-session consultation, no +verdict). A third component, `plan-adversary`, hunts failure modes in +plans. + +Two gaps follow. First, nobody owns the *mechanics* of a system — what its +parts are, what crosses the boundaries between them, what state it keeps, +how it behaves when loaded. The architect judges whether a shape is right; +it does not produce one, and its own persona file says so. A developer +forming a design has a critic available and no counterpart to help build +the thing being criticized. + +Second, design expertise comes in only two shapes today: a formal review +that ends in a stamped verdict, or a conversation held in the main thread. +There is no way to ask a persona for a contribution from a fresh, isolated +context without also asking it for a verdict. + +## Scope + +This spec covers a second persona, the files that define both personas +without duplication, a consultation surface for each, and a consent-based +offer that brings them into a design conversation. It does not change the +spec/plan lifecycle, add a review gate, or alter what the `architect` agent +does with a document. Model-selection mechanics stay owned by the workflow +rule. + +Two changes fall outside the plugin and are in scope deliberately: the repo +authoring rule learns the `*-consult` naming category, and the versioning +rule's prerelease grammar widens so a topic branch without an issue number +can still be dogfooded. Both are consequences of this change that would +otherwise leave a repo rule contradicting the code it governs. + +One behaviour change to an existing verdict-bearing component is +**declared, not incidental**: `plan-adversary` starts sourcing its standing +duties from the shared persona file and thereby gains the domain-expertise +duty it does not have today. This is intended — a plan reviewer that +verifies load-bearing facts against documentation is strictly better — and +is called out because a silent widening of a gate's behaviour would not be. + +### What was cut + +An earlier draft orchestrated both personas through +`superpowers:brainstorming`: a warm-start spawn, two consultation +checkpoints, agents kept alive across the conversation and resumed by +message, a delta-briefing contract, and a record of what each persona had +been told. That machinery is gone; the reasoning is under non-goals, +because the argument is worth keeping even though the feature is not. What +survives from it is the *offer* — being asked, which cost nothing — not the +bookkeeping. + +### Minimum viable version + +So a later reader can judge whether the structure is earned: the minimum +that solves the stated problem is `SYSTEM_DESIGNER_PERSONA.md` plus +`system-designer-consult`. Everything else is added for a named reason — +`PERSONA_COMMON.md` because three components would otherwise carry +duplicate duty text that has already been observed to diverge; +`architect-consult` because the second half of the problem (a contribution +without a verdict) applies to the architect too, and its own agent cannot +suppress the verdict its report format requires; +`system-designer-session` because a skill body loads into the main thread +and can therefore carry the handoff into a consult dispatch, which no agent +file can. + +## Verified platform facts + +### Doc-verified (Claude Code docs, July 2026) + +- A non-fork subagent "starts with a fresh, isolated context window. It + doesn't see your conversation history, the skills you've already + invoked, or the files Claude has already read." +- A fork "inherits the entire conversation so far instead of starting + fresh. This drops the input isolation that subagents otherwise + provide." Its first request reads the parent's cache. +- `SendMessage` "doesn't require agent teams to be enabled" and is in a + background subagent's default tool pool. The sibling roster "appears + only when the subagent's tools include `SendMessage` and at least one + other agent has a name", and needs Claude Code 2.1.206 or later. +- A teammate's coordination tools override `tools` / `disallowedTools`. +- `disallowedTools` is a documented frontmatter key for both subagents and + plugin agents: "Tools to deny, removed from inherited or specified + list". `background` and `isolation` are likewise plugin-agent keys; + `permissionMode`, `hooks`, and `mcpServers` are not available to them. +- A dispatching thread sees only an agent's `name` and `description` when + choosing it; the agent's body becomes the subagent's system prompt. +- Subagent output is not shown to the developer; the dispatching thread + receives it and relays what matters. +- "Latency matters. Subagents start fresh and may need time to gather + context." +- "Subagents use the five-minute TTL even on a subscription, since the + automatic one-hour TTL applies to the main conversation." +- The `memory` field takes `user | project | local` and grants the + subagent a persistent directory across conversations. +- The default subagent nesting depth has changed across releases (5 on + 2.1.172–2.1.216, 1 on 2.1.217–2.1.218, 3 from 2.1.219). + +### Locally verified (Claude Code 2.1.220) + +- `claude plugin validate` passes at the repo root and for the plugin with + the new `disallowedTools` key and quoted descriptions. +- `disallowedTools` with a bare string value loads without error. +- A consultation dispatched by pointing an agent at persona files on disk + behaves as intended — this is how the trial described under Trial + evidence was run. + +### Undocumented — treated as unknown + +- The minimum Claude Code version for `disallowedTools`, and what happens + to an agent file carrying an unrecognized frontmatter key: ignored with + the agent still loading, or the agent failing to load. The two branches + have different consequences and both are covered under accepted risks. +- Whether an agent's body reaches the dispatching thread before dispatch. + Treated as "no", which is why every dispatcher-facing obligation is + duplicated into `description`. + +## Design + +### 1. Two personas, split by dimension + +The two personas are distinguished by the question they answer, not by +their stance toward the material: + +- the **system designer** asks *what the parts are and how they interact*; +- the **architect** asks *whether that shape is right*. + +The system designer's dimensions: parts and responsibilities; interactions +and contracts; state and its lifecycle; behaviour under load; +observability; technology choice. The architect keeps its own: fit, +boundaries, over-engineering, alternatives, convention fit. + +Proposing a decomposition is the designer's work; grading it is the +architect's. Each persona names and hands over what belongs to the other +rather than filling the gap itself. + +The system designer must be able to answer "not applicable here", with one +line of why, for any dimension the subject genuinely lacks: six mechanics +dimensions create real pressure to fill them, and a persona that invents a +load profile for a markdown plugin spends the developer's attention on +noise. Dropping a dimension silently is the opposite failure — it is named +and dismissed. This licence stays in the designer's own persona file. It +cannot move to the shared file, because `plan-adversary` reads that file and its +own instruction is the opposite: walk every dimension, nothing passes by +default. + +### 2. Persona files and single-sourcing + +`PERSONA_COMMON.md` at the plugin root holds what is not specific to one +persona, and is read by both personas and by `plan-adversary`: + +- the **domain-expertise duty** and the **glossary/ADR duty**; +- the **boundary between the personas**, including its third leg — + `plan-adversary` asks *how this will fail in execution*, and stands + outside the design-quality/mechanics split rather than inside it. A + consumer must not read a boundary that omits it; +- the **consultation contract** of sections 6 and 7, which both + `*-consult` agents would otherwise duplicate. This section carries its + own scoping clause, mirroring the boundary's `plan-adversary` carve-out: + it binds `*-consult` dispatches and their dispatcher only — the file's + verdict-bearing consumers (`plan-adversary` directly, `architect` via + its persona file) grade and stamp by duty, and must not read a sentence + saying contributions are never graded as binding them. The file's + opening ("All three are defined only here") is reworked when this + fourth section lands. + +The extraction is driven by evidence, not tidiness. A first draft +duplicated the boundary across both persona files and the two copies had +already diverged — four criteria against three — before anyone read them. +The same pattern then reappeared in the two `*-consult` files: roughly 70% +identical body text, with the divergence already started (one file carried +"formal review ending in a verdict belongs to the `architect` agent", the +other did not, though it is the architect that has the verdict-bearing +agent). The repo authoring rule sets the threshold at two consumers; this +is three and two respectively. + +Two consequences to state rather than discover: + +- **`plan-adversary` adopts the file whole**, gaining the domain-expertise + duty. Declared in Scope. Its `*-plan-review` checklist mechanism becomes + the first source under that duty rather than a parallel one. +- **The glossary duty's wording is looser in the shared file** ("must be + called out, citing the file") than the two verdict-bearing agents need. + Both `architect` and `plan-adversary` re-tighten it to "earns a finding" + on their own surfaces; the spec says so for both, not only the architect. + +The persona files stay at the plugin root under their current names, and +join `ARCHITECT_PERSONA.md` in the versioning rule's list of public +surfaces whose rename is a breaking change. + +Persona files point at the shared file in prose rather than through +`${CLAUDE_PLUGIN_ROOT}`, because a persona file is read as raw text by an +agent that has already resolved its own root — the variable would not +expand. This is not an exception to the authoring rule, which bans absolute +paths and says nothing about prose; it is recorded only so nobody "fixes" +it into a variable. + +### 3. Surfaces and how the right one gets chosen + +| Surface | Persona | Input | Output | Context | +|---|---|---|---|---| +| `architect` agent | architect only | a document | verdict, stamped | fresh, isolated | +| `*-consult` agent | both | a briefing | contribution, never stamped | fresh, isolated | +| `*-session` skill | both | live dialogue | contribution, never stamped | the main thread | + +The architect has three surfaces, the system designer two. The designer has +no verdict-bearing agent; its review counterpart is the existing architect +gate, which reads the spec the designer's contribution shaped. + +**Why the architect needs a third surface.** Its own agent cannot serve as +a consultation: that agent's report format requires a Verdict section, so +any dispatch produces a verdict word, and a produced-but-unstamped verdict +is exactly the contamination the formal gate must not carry. The argument +belongs here rather than only in the non-goals table, or the third surface +reads as symmetry. + +**Choosing between the two consultation surfaces.** The distinction is +isolation against interactivity: the consult agent protects the main +thread's context and is unshaped by the conversation so far; the session +skill supports live back-and-forth and immediate correction. That +distinction is real but it is *not* a phrase anyone says, and a surface is +selected from what the developer actually types. Today +`architect-session`'s description carries verbatim trigger phrases ("ask +the architect", "porozmawiajmy z architektem") under a hard "Use ONLY +when", while a consult agent would carry an abstract criterion. The session +skill would therefore win systematically — including on the very sentence +this spec calls ambiguous. + +So the arbitration is lexical, not conceptual: + +- each consult surface gets its own trigger phrases naming isolation or a + second opinion ("konsultacja z architektem", "zapytaj designera na + świeżo", "second opinion from the system designer", "consult the + designer from a clean context"); +- each session skill's description gains a counterpoint naming its consult + agent by name, and vice versa; +- on a genuinely ambiguous request the main thread asks one short question + — in-thread or from a fresh context — rather than silently picking. This + matches the plugin's culture, where everything is an offer. + +A session skill's body loads into the main thread, which gives it a job no +agent file can do: it carries the handoff, telling the developer how to +escalate the same question into a consult dispatch and what to brief it +with. That is the concrete reason `system-designer-session` exists beyond +symmetry. + +### 4. Consultation mechanism — one dispatch, self-contained + +A consult agent is dispatched when a consultation is wanted, answers once, +and is not kept alive. It is not resumed, not spawned ahead of need, and +carries `background` in its frontmatter so that running as a background +agent — which section 10 relies on for verifiability — is true by +construction rather than by the dispatcher's habit. + +The isolation this buys is the point. Two worries motivated it: polluting +the main conversation's context with a persona's instructions, reasoning, +and file reads; and a persona's judgement being shaped by everything the +conversation has already committed to. + +| | context pollution | conversation bias | +|---|---|---| +| persona loaded in-session | not solved | not solved | +| fork | solved | not solved (inherits the history) | +| fresh one-shot subagent | solved | solved | + +Being self-contained removes the hardest problem the orchestrated draft +had. When a persona is kept alive, every later briefing must state what +changed since the previous one, the dispatcher must track what each +persona has already been told, and that record is exactly what a +compaction of the main thread destroys. A single dispatch has no delta to +compute and no state to lose, and cannot accumulate its own bias across +successive briefings. + +The five-minute subagent cache TTL is the other reason not to hold a +persona open: a persona resumed after a human-length pause re-reads its +entire accumulated transcript uncached, every time. One dispatch pays for +its context once. + +### 5. Independence between personas + +When both personas are consulted on one subject, they are consulted +independently. Two agents that reconcile privately hand back one opinion +where the developer asked for two, and their disagreement is the most +useful thing they produce. + +The mechanical half is `disallowedTools: SendMessage` on both consult +agents. This is not a relic of the orchestrated draft: consulting both +personas on one subject means two concurrent background dispatches, both +named, so the sibling roster would otherwise appear — and since the roster +needs 2.1.206 while the plugin's floor is 2.1.207, it is live on every +supported installation. The key therefore has real effect wherever the +plugin runs at all. + +Two limits are recorded rather than papered over: + +- consult agents keep the `Agent` tool, so a persona could spawn its own + copy of the other persona and fold the result into one answer. Removing + `Agent` is the worse trade: the domain-expertise duty asks for + documentation verification, and both personas used a lookup subagent for + exactly that during the trial. The limit is textual — helpers for search + and documentation are allowed, a second working-process persona never is. The + argument does not rest on helpers being available, since nesting depth + has varied by release and has been 1; where no helper can be spawned, + the duty's own "when available" wording governs and web lookup remains; +- `disallowedTools` binds only when the dispatch goes through the agent + file. A dispatcher that pastes a persona inline gets no enforcement. + +The substantive half is what the briefing says, and it decides the outcome +regardless of any tool: a briefing sentence saying "the architect raised X" +produces convergence with no message between agents at all. Hence section +6 — and hence that contract living inside the plugin, not only here. + +### 6. Briefing contract + +A consult agent knows only what its briefing says, so the briefing is a +defined artifact. Two of its three rules are invariants *across* +dispatches, which no agent can enforce because no agent sees the other's +briefing — the obligation is the dispatcher's. That makes its location +load-bearing: this spec does not ship with the plugin, so the contract +lives in `PERSONA_COMMON.md`, and the two cross-dispatch invariants — the +only rules no agent can enforce — are duplicated into each agent's +`description`, the only surface a dispatching thread reads before +choosing, as one sentence: "When both personas are consulted on one +subject, give both the same canonical briefing (each with its own +focusing question appended) and tell neither what the other said." The +plugin already uses this device — the `architect` agent's description +restates the stamping obligation from its body for the same reason. + +The base case is **one** dispatch, which is the ordinary path now that +nothing fires on a schedule: + +- **Contents**: the subject; the constraints that bind it; and, stated + separately, what the developer has already decided against what is + still open. A persona that cannot tell a settled decision from an open + question either re-litigates the settled one or treats an open one as + fixed. +- **Point, don't paste.** What a consultation reads is what it costs, so a + briefing names the files and the area rather than inviting exploration. + +When both personas are consulted on one subject, two further rules apply: + +- **One canonical briefing text**, given to both, each with its own + focusing question appended. Two personas briefed differently return two + opinions about two different subjects, and nothing in the output would + reveal it. +- **No cross-persona content.** Neither is told what the other said. A + cross-check dispatch — "the architect argued X; does that hold + mechanically?" — is legitimate on explicit request, and is labelled as + one so the reply is read as a response rather than as an independent + opinion. + +### 7. Reporting contract + +Subagent output never reaches the developer directly; the dispatching +thread relays it. That thread is both a lossy channel and the same actor +that wrote the briefing, so a silent synthesis would hand the developer +one reconciled opinion — the failure of section 5, moved one node closer. + +- Each contribution is relayed **attributed, in its own block, and + substantially verbatim**. Compression is allowed; merging is not. The + checkable floor: every recommendation and every named risk survives, and + text from two personas never lands in one bullet. +- Where the personas disagree, the disagreement is presented **as a + disagreement**, with both positions, and the choice is the developer's. +- The relaying thread may add its own opinion, marked as its own. +- The developer can verify the relay rather than trust it: a consult agent + is a named background agent, so its transcript can be opened and read. + Naming the agent at dispatch is therefore part of this contract, not a + nicety. +- A persona's output is a **contribution**, never a *finding* — that noun + is reserved by the glossary for the graded unit of a verdict-bearing + review round. One noun, used in the persona files, the agent bodies, and + the descriptions alike. + +### 8. The offer + +Consultations are not something the developer must remember to ask for, +and not something that fires unasked. Once, early in a design +conversation, the main thread asks whether the two personas should be +consulted as the design forms. Three answers: + +- **yes** — from then on, a consultation is dispatched when it looks + worth its cost, without asking again for that design conversation; +- **not now** — nothing is dispatched, and the question may return for the + next design; +- **not in this session** — the question does not return until a new + session. It is labelled exactly that, because it is honoured for the + session only: the plugin has no settings store, and writing the + preference somewhere durable would be a write nobody authorized. A + developer who wants it permanent puts it in their own instructions, + which the rule respects when present. + +Consent replaces counting offers. There is no fixed checkpoint list and no +warm start; after consent, the judgement of *when* a consultation earns its +cost is the main thread's, exercised the same way it decides to invoke any +skill. That is the whole of the automatic half — no orchestration state, no +briefing ledger, nothing kept alive. + +Integration is one addition to `rules/workflow.md`, step 1, phrased +conditionally because payload rules load for people without the plugin. +Two collisions inside that rule have to be fixed in the same edit: + +- the rule says "After every architect or plan-adversary round, record the + verdict … in the reviewed document's `architect:` field". After this + change "architect" names three components, so read cold the rule + instructs stamping a consultation. It is tightened to the backticked + `architect` **agent**, in both that sentence and step 3. +- the model-selection paragraph opens "Model selection for these + dispatches" and says "Reviews are never dispatched on the cheapest + available family". A consultation is not a review, so it is named there + explicitly rather than left to inference — which keeps the tier + mechanics in the one place that owns them and keeps the step-1 line + short. + +No new rule file is added, so the authoring rule's list of always-on +exceptions is untouched. The added lines do land in `workflow.md`, which is +the payload's only file without `paths:` — so they are resident in every +session on every machine with a user-level install. What this design avoids +is a *second* always-on file, not the cost of a few lines; the earlier +claim of "no addition to the always-on budget" was simply false. + +Nothing a consultation produces is a verdict, and nothing is stamped. An +opinion from a consultation may never be carried into the `architect:` +field; only a dispatch of the `architect` agent writes it. Consultations +therefore have no fallback record and no re-review offer. + +### 9. Cost + +The classical load dimensions do not apply — one developer, one +conversation, no throughput, no concurrency, no bulk path. What remains is +a per-dispatch cost, bounded by construction: a consultation reads the +domain artifacts, the conventions, and what its briefing points at, +answers once, and ends. There is no re-billing across resumptions, no idle +agent, and no cost at all in a design conversation where consent was +declined. + +Latency is paid at the moment of dispatch, on the most capable available +model. The consequence worth carrying forward is section 6's "point, don't +paste": what a consultation reads is what it costs. + +### 10. Observability + +- **Attribution** — a relayed contribution names its persona, and a + disagreement is visible as one (section 7). +- **Verifiability** — the consult agents declare `background`, so they + appear in the task panel and the developer can open a transcript and + read what the persona actually read, rather than trusting the relay. +- **Consent state** — whether consultations are on for this design + conversation is stated when it is decided and when it changes, so the + developer is never guessing why a persona did or did not appear. + +This design deliberately leaves **no durable record that a consultation +happened**: no frontmatter field, no required body note. That is the price +of cutting the bookkeeping, and it means the effect of the feature cannot +be measured after the fact by comparing specs. An earlier draft claimed it +could; the claim was a wish, not a mechanism, and is withdrawn. + +## Non-goals and rejected alternatives + +| Rejected | Reason | +|---|---| +| Orchestrating the personas through brainstorming | Built as a draft, then dropped. It required a warm-start spawn, personas kept alive and resumed, a delta-briefing contract, and a record of what each persona had been told — and that record is what a main-thread compaction destroys. The cost and the moving parts outgrew the value. The consent offer of section 8 keeps the benefit of not having to remember, with none of the bookkeeping | +| A designer verdict and a `designer:` field | A third gate in the lifecycle; the designer's output is spec content, which the existing architect gate reviews | +| Persona cross-talk | Opinions converge, and the debate leaves the developer's view | +| Agent teams | Not needed — messaging works without them — and teammate coordination tools override `disallowedTools`, which would break the enforcement in section 5 | +| `memory:` per-persona stores | A competing decision store beside `docs/domain/adr/` and Project memory; it also auto-enables file writes for the agent | +| Fork-based consultation | A fork inherits the conversation and "drops the input isolation" — it solves pollution but not bias, and bias isolation is the reason the surface exists. Its cache advantage is real and named, not hidden | +| Compaction as a persona switch | Summarization keeps conclusions and drops the deliberation that would let them be re-examined, so it does not de-bias. The cost objection is weaker than it first appears — the summarization request shares the conversation's prefix and reads the cache — so this rejection rests on fidelity, not on price | +| One consult persona covering both duties | Both roles in one context return the single reconciled opinion section 5 exists to prevent | +| One session surface for both personas | Weighed for completeness, since the objection above is much weaker in a session: the developer is present, sees the whole exchange, and picks. Rejected because a session skill is selected by trigger phrases, and one skill answering to both personas' phrases makes section 3's lexical arbitration impossible — the surface could no longer tell the developer which persona it is speaking as | +| Reusing the `architect` agent as its own consultation surface | Its report requires a Verdict section, so a consultation would produce a verdict word that cannot be suppressed without editing the agent. An earlier draft also argued the agent "expects a document"; that argument is false — its own definition accepts "any design document or question dispatched standalone" — and is withdrawn. That description phrase does need narrowing, so it stops competing head-on with `architect-consult` | +| A durable record that a consultation happened | Would reintroduce the bookkeeping just cut; the cost is stated in section 10 rather than hidden | +| The `best` model alias | The declarative form of "most capable available", fitting the glossary's tier definition, but absent from the subagent frontmatter table and skippable by an availability policy. Deferred, not dismissed | +| Editing `superpowers:brainstorming` | Another plugin's skill | + +## Glossary additions + +Settled in the 2026-07-30 grilling-session and already applied to +`docs/domain/glossary.md`: + +- **Persona** — a role plus its duties, single-sourced in one + `*_PERSONA.md` file at the plugin root and adopted by one or more + persona surfaces. Left unqualified with a disambiguating clause rather + than becoming "Process persona", the way **Tier** and **Severity** + already settle their own collisions — `salesforce-security-model` uses + "persona" for an org user role. The session also corrected the count: + two personas, not three. `plan-adversary` reads no persona file and + carries its role inline, so it is a reviewer, not a persona — which + forced a clause into `PERSONA_COMMON.md`, since its opening claimed + every carrier of those duties is a persona while this spec has + `plan-adversary` sourcing them from exactly that file (done). +- **Persona surface** — the component that adopts a persona. Qualified, + because the repo's own rules already use bare "surface" for a document + location (`standards-rule-tags.md:19`, + `working-process/rules/process-artifacts.md:43`). Its `_Avoid_: mode` + bites six existing lines, all rewritten in the same session: the opening + line of `agents/architect.md`, `skills/architect-session/SKILL.md` and + both consult agents, plus the two consult-agent `description:` fields — + the last mattering most, being the only text a dispatcher reads before + dispatching. +- **Session skill** — the `*-session` component kind, which reserves + unqualified "session" for the Claude Code conversation. Section 8's + consent is scoped to the latter, and that is the one place where + conflating the two would change behaviour. +- **Consultation** — a verdict-free exchange returning a contribution. + Sharpened here: the discriminator is the absence of a verdict, not the + absence of stamping, since an `architect` dispatch on a bare question + also stamps nothing (`agents/architect.md`: "A bare question has nothing + to stamp") and still grades. +- **Contribution** — what a consultation returns, relayed attributed and + substantially verbatim; never graded, never counted. +- **Finding** — widened to two levels instead of staying report-only: the + core is one graded problem a review round reports with evidence, and the + counted per-file, single-`rule id` shape is what a Review report + additionally imposes. `architect` and `plan-adversary` stop being + undocumented exceptions, and section 7's reservation now rests on a + term with one meaning. `_Avoid_` narrowed to "as a name for the unit", + which leaves "one finding per issue" standing in both agents — there the + two words are contrasted, not substituted. +- **Tier** — verified rather than changed: both uses in this spec are the + canonical model ladder. + +Of the two ADR candidates, one was written — +`docs/domain/adr/0001-persona-independence.md`, for section 5, because +`disallowedTools: SendMessage` on both agents reads as an arbitrary +restriction from the frontmatter alone. The prerelease-grammar widening +was declined an ADR on the grounds that the rule it edits can carry its +own rationale, which turns that sentence into a requirement of the edit +rather than an optional nicety. + +## Files to touch + +**Plugin, new**: `PERSONA_COMMON.md`, `SYSTEM_DESIGNER_PERSONA.md`, +`agents/architect-consult.md`, `agents/system-designer-consult.md`, +`skills/system-designer-session/SKILL.md`. + +**Plugin, edited**: `ARCHITECT_PERSONA.md` (own duty plus a pointer; +boundary moved out); `agents/plan-adversary.md` (standing duties sourced +from the shared file, glossary duty re-tightened, its checklist mechanism +positioned under the domain-expertise duty); +`skills/architect-session/SKILL.md` ("both duties" is stale after the +extraction, the arbitration counterpoint, and the opening line off +"mode" — done); `agents/architect.md` (arbitration counterpoint, the "or +question dispatched standalone" phrase narrowed, glossary duty +re-tightened, and the opening line off "mode" — done); `rules/workflow.md` (the step-1 +addition, the two collisions of section 8); `README.md` (components, and +the persona single-sourcing line, both stale); `.claude-plugin/plugin.json` +(description, and the version below). + +**Repo**: `.claude/rules/plugin-authoring.md` — the naming convention says +"formal reviews that end in a verdict are agents" and knows no +verdict-free agent, so `*-consult` is added as a third category, or the +rule contradicts the components this change ships. +`.claude/rules/plugin-versioning.md` — the prerelease grammar's `dev` +channel takes the branch short-name as its discriminator when a topic has +no issue number (`0.11.0-dev.design-personas`), and the breaking-surface +list gains the two new persona paths. Widening the discriminator rather +than minting a channel keeps one channel for one purpose, and the rule +already anticipates its own extension: "Future channels extend this list +by editing this rule only — the release-guard workflow rejects every +prerelease on master, so new channels never need a CI change." Because the +grilling declined this decision an ADR on the grounds that the rule can +hold its own rationale, the edit must carry that one sentence inline — +otherwise the "why" survives nowhere. +`.claude-plugin/marketplace.json` and the repo `README.md`, which +enumerate components alongside the plugin description — all three in one +commit per the marketplace-sync rule. + +**Version**: `0.11.0-dev.design-personas`. The branch cannot reuse +`0.11.0-dev.10`, which it inherits from develop: the plugin cache keys +content by version and that string is already consumed by the +contract-sharpening topic's dogfooding. Widening the discriminator makes +this branch dogfoodable, which matters because section 3's lexical +arbitration is the one thing in this design that cannot be verified any +other way. The release PR strips the suffix as it does any prerelease. + +**Validation**: `claude plugin validate` at the repo root and for the +plugin. Rule frontmatter is reviewed by hand, since validation does not +cover `rules/`. + +## Trial evidence + +Before this spec was written, both personas were dispatched on the design +itself — briefed identically, with no channel between them, each pointed at +its persona files on disk. They were dispatched again on the spec. + +What the trial does and does not establish. It establishes that the +charters hold: the architect named the mechanics dimensions and handed them +over instead of filling them; the designer dismissed the classical load +profile by name and then found the real cost profile behind section 9. It +also establishes the shape of section 4 — self-contained one-shot +consultations, nothing kept alive. It does **not** test the mechanical half +of section 5: the trial dispatched by path, and `disallowedTools` binds +only through the agent file, so the consulting agents did in fact hold +`SendMessage`. And it cannot test section 3's arbitration at all, which is +selection behaviour, not persona behaviour. + +The consultations changed the design rather than ratifying it. From the +first round: the briefing and reporting contracts (sections 6 and 7), which +had been named but not specified, and a withdrawn false argument. From the +second: that the briefing contract had no owner and would not ship with the +plugin; that `background` could be declared rather than assumed; that the +"measure the outcome" claim was a wish; that "standalone install" has a +glossary meaning which made the earlier degradation path empty; that +"Mode" collides with existing canon; that the always-on budget claim +contradicted itself; that `workflow.md` already instructs stamping a +consultation; and that the stated reason for skipping dogfooding was +factually wrong. + +Both rounds converged independently on the same three things, which is the +strongest evidence available that the two charters are not one charter +twice: the undefined briefing contract, the relaying thread as the +unguarded convergence point, and the weakness of a symmetry-only session +skill. + +## Architect findings — 2026-07-30 round 1 + +Dispatched on Fable 5 (self-reported: fable 5; prescribed tier). Verdict: +concerns — one Important, five Minor. All resolved the same day; details +below, verdict annotated in frontmatter. + +- **Important**: the consultation contract was routed into + `PERSONA_COMMON.md` with no scoping — the file's verdict-bearing + consumers (`plan-adversary` directly, `architect` transitively) would + read "contributions are never graded" against their own verdict duty, + and only the boundary section had a carve-out. → Fixed: §2 now specifies + a scoping clause on the contract section (binds `*-consult` dispatches + and their dispatcher only) and the rework of the file's "All three are + defined only here" opening when the fourth section lands. +- **Minor**: "read by all three personas" contradicted the settled count + (two personas; `plan-adversary` is a reviewer). → Fixed: "by both + personas and by `plan-adversary`". +- **Minor**: "process persona" re-introduced the qualified form the + grilling declined, in §5 and both consult-agent bodies. → Fixed in all + three: "working-process persona". +- **Minor**: §7's reservation argument was stale after the same grilling + ("the counted unit of a Review report" — Finding is two-level now). → + Fixed: "the graded unit of a verdict-bearing review round". +- **Minor**: §6 said a singular "operative sentence" goes into the + `description` fields without naming it, and the trial descriptions + carried none of it — the only dispatcher-readable surface. → Fixed: §6 + now quotes the exact sentence (the two cross-dispatch invariants), and + both trial descriptions carry it. +- **Minor**: "stays on the designer's own surface" misused the fresh + Persona-surface term for what is a persona file. → Fixed: "in the + designer's own persona file". + +## Accepted risks + +- **`disallowedTools` has no documented minimum version, and the failure + mode is silent either way.** If an unrecognized key is ignored, the + agent still loads and the mechanical half of section 5 becomes a no-op + with nothing reporting it; if it prevents the agent from loading, the + surface disappears from selection and the arbitration of section 3 + silently degrades to the session skill. Which of the two happens is + undocumented for agent files. The substantive half — the briefing rule — + does not depend on the key. Worth one empirical check on the oldest + floor available. +- **Selection quality among four dispatchable agents is unverified.** After + this change the plugin ships `architect`, `architect-consult`, + `plan-adversary`, and `system-designer-consult`, with overlapping + description surfaces. The trigger phrases and counterpoints of section 3 + are the mitigation; dogfooding under the new version string is how it + gets checked before release. +- **The arbitration rule is guidance, not enforcement.** Nothing prevents a + session skill from being invoked where a consult agent was the better + choice. With trigger phrases in place this is no longer a systematic + bias toward one surface, but it remains a judgement the descriptions can + only inform. +- **`plan-adversary` gains a duty.** Declared in Scope rather than + discovered later, and believed to be an improvement — but it is a + behaviour change to a verdict-bearing gate, shipped in a change whose + headline is a new persona. + +## Amendment — 2026-07-30: domain artifacts resolve from the repo root + +Found by the first dogfooding dispatch of `system-designer-consult`, on +itself: the glossary/ADR duty named its artifacts by relative path, so a +dispatch from a session whose working directory sits below the repo root +would conclude in good faith that no glossary exists — a silent +degradation of exactly the shape the Accepted risks list carries, but +unlisted. The consultation demonstrated it empirically (its own +environment started in a subdirectory) and proposed the fix applied +here: the shared glossary duty now resolves `docs/domain/` against the +repo root (`git rev-parse --show-toplevel`), all four agents defer to +that clause, and the briefing contract gains a bullet obliging the +dispatcher to name where the subject lives. Residual: a subject outside +any git repository still depends on that briefing line. The same +consultation also surfaced the consent state's unspecified lifecycle +across compaction; `rules/workflow.md` now says to re-ask when a +compacted conversation leaves it unclear. + +## Amendment — 2026-07-30: dispatcher duties move to the workflow rule + +Acting early on two watch items from the same consultation — the context +tax of four long descriptions on a user-level install, and the +dispatcher carrying the most obligations while owning no file — both +consult descriptions are trimmed to selection-critical content +(identity and dimensions, trigger phrases, counterpoints, a one-line +dispatch trace), and the dispatcher-side obligations now live in a +dedicated paragraph of `rules/workflow.md`, which is already resident +in every session. `PERSONA_COMMON.md`'s contract section +cross-references it so the two copies are edited together. This +supersedes §6's choice to duplicate the cross-dispatch invariants into +each `description:` — the always-on rule reaches the dispatcher just as +early and is paid once rather than per agent. Residual: a standalone +install without the rules keeps only the descriptions' compressed +trace. The contract and the rule also codify a lesson the first +dogfooding session paid for: a follow-up to a consultation is a fresh +cross-check dispatch, never a resumption — a message sent to a running +one-shot agent races its completion and can be silently lost. + +## Amendment — 2026-07-30: trigger phrases go English-only + +At the developer's direction, every Polish trigger phrase leaves this +plugin — the surfaces this spec added and the pre-existing +`architect-session` ("porozmawiajmy z architektem") and +`grilling-session` ("przemagluj") alike, descriptions and the README +lines that mirror them. Each removed phrase is replaced by an English +equivalent so no surface drops below two triggers. Section 3's lexical +arbitration is unaffected — it never depended on the phrases' language, +only on their verbatim presence. The repo-hygiene exception for +non-English phrases stays: the project-memory plugin still uses it, and +its precedent citation is repointed there ("przejrzyjmy memory") so the +rule cites a phrase that exists. diff --git a/plugins/project-memory/.claude-plugin/plugin.json b/plugins/project-memory/.claude-plugin/plugin.json index a2b3430..d8641e2 100644 --- a/plugins/project-memory/.claude-plugin/plugin.json +++ b/plugins/project-memory/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "project-memory", "description": "In-repo project memory for Claude Code sessions — committed Team memory (docs/memory/) and git-ignored per-user Private memory (.claude/memory/); a Rules payload plus memory-review-session and migrate-memory skills", - "version": "0.2.0", + "version": "0.3.0", "author": { "name": "Missing Bits (Jacek Nakonieczny)" }, "license": "MIT", "keywords": ["memory", "notes", "ideas", "knowledge", "rules"] diff --git a/plugins/project-memory/rules/project-memory.md b/plugins/project-memory/rules/project-memory.md index 4d31b58..017ae10 100644 --- a/plugins/project-memory/rules/project-memory.md +++ b/plugins/project-memory/rules/project-memory.md @@ -43,9 +43,14 @@ writing anything — this rule owns that question: - **Tracked**: files are committed like any other; no `.gitignore` is written. -Never ask when a prior decision is observable: a `.gitignore` containing +Never ask when a prior decision is present: a `.gitignore` containing exactly `*` means ignored was chosen; any git-tracked file under the -directory means tracked. Private memory (`.claude/memory/`) is always +directory means tracked; and an +explicit project instruction declaring the mode (e.g. a CLAUDE.md +note) counts as the decision — a declared ignored mode is +materialized by whoever first acts on it (writing the `*` +`.gitignore`), a declared tracked mode becomes observable with the +first committed file. Private memory (`.claude/memory/`) is always ignored, so it is never asked. When the working-process rules are installed, `docs/memory/` additionally counts as a Process directory there. diff --git a/plugins/python-standards/.claude-plugin/plugin.json b/plugins/python-standards/.claude-plugin/plugin.json index 136fc9e..1a326b5 100644 --- a/plugins/python-standards/.claude-plugin/plugin.json +++ b/plugins/python-standards/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "python-standards", "description": "Python coding standards for the uv + ruff + pytest + pyright toolchain: six area skills, a code-review stack (python-code-review skill, python-code-reviewer agent, /python-review command) writing review reports to docs/code-review/, a python-plan-review checklist for plan reviews, and a python-toolchain rule shipped as a Rules payload", - "version": "0.2.0", + "version": "0.3.0", "author": { "name": "Missing Bits (Jacek Nakonieczny)" }, "license": "MIT", "keywords": ["python", "standards", "uv", "ruff", "pytest", "pyright", "typer", "fastapi", "review"] diff --git a/plugins/python-standards/commands/python-review.md b/plugins/python-standards/commands/python-review.md index 3fa872d..b87a0a8 100644 --- a/plugins/python-standards/commands/python-review.md +++ b/plugins/python-standards/commands/python-review.md @@ -2,14 +2,37 @@ description: Review the current diff (or named files) against the Python coding standards --- -Review Python code against the python-standards skills. +Review Python code against the python-standards skills by dispatching +the reviewer agent in the background — the review must never block +this session. -1. Load the `python-code-review` skill and follow it end to end. -2. Scope: `$ARGUMENTS` when given (named files); otherwise the current - diff — staged plus unstaged changes, or, on a clean tree, the diff of - the current branch against its base. -3. Python files only (`*.py`, `pyproject.toml`); note out-of-domain - files in the report Summary as out of scope. -4. Write the review report per the skill's report contract and reply - as the python-code-review skill specifies (report path, severity - summary, candidate gaps and offers). +1. Resolve the scope: `$ARGUMENTS` when given (named files); + otherwise the current diff — staged plus unstaged changes, or, on + a clean tree, the diff of the current branch against its base. +2. Pre-dispatch first-create check, gated on the contract probe: + check `/.claude/rules/working-process/review-reports.md`, + then `$HOME/.claude/rules/working-process/review-reports.md` — + first hit wins (paths owned by the review-reports contract; + restated here so the command is self-contained). No contract found + (Standalone install) → skip this step entirely. Contract found and + `docs/code-review/` carries no decision — no `.gitignore` of + exactly `*`, no git-tracked file under it, and no + explicit project instruction declaring the mode (signal list owned + by the process-artifacts rule) — ask the developer now: ignored or + tracked mode. +3. Dispatch the `python-code-reviewer` agent in the BACKGROUND with + the resolved scope. Python files only (`*.py`, `pyproject.toml`); + the agent notes out-of-domain files in the report Summary as out + of scope and writes the one report itself (`mode: agent` under the + installed contract). The dispatch prompt carries the scope, the + prior report's runid for a rerun (`rerun-of`), and the + directory-mode decision from step 2 — never report-shaping + instructions of its own: aggregation and counting policy, layout, + and severity policy belong to the contract and the reviewer's + skill, and a whole-project scope is no exception. +4. Tell the developer: the review is running in the background; the + summary arrives as a task notification, not inline; progress via + `/tasks`; the report will land under `docs/code-review/`. +5. When the run's notification arrives, relay its reply to the + developer: report path, findings by severity, and the + candidate-gap offers verbatim. diff --git a/plugins/python-standards/skills/python-code-review/SKILL.md b/plugins/python-standards/skills/python-code-review/SKILL.md index faf79a3..1a597b4 100644 --- a/plugins/python-standards/skills/python-code-review/SKILL.md +++ b/plugins/python-standards/skills/python-code-review/SKILL.md @@ -1,6 +1,6 @@ --- name: python-code-review -description: Use when auditing existing Python code against the python-standards skills — invoked by the /python-review command or the python-code-reviewer agent. +description: Use when auditing existing Python code against the python-standards skills — invoked by the python-code-reviewer agent, which the /python-review command dispatches in the background. --- # Python code review @@ -29,16 +29,47 @@ them in the report's Summary as out of scope. group id's severity; cite the group id; - no defined rule covers the finding → report and count it anyway, cited `(standard: , - rule: none)`, graded by the authoring rubric in the review-reports - contract; at critical its kind is always `defect`. Never invent a - rule id. + rule: none)` — or `(standard: python-standards, rule: none)` when + no skill of this plugin covers the concern. A concern covered by + the domain of an existing but not-yet-loaded skill is NOT a + candidate gap: load that skill and grade by its tags — + `rule: none` is never asserted against a skill the run did not + read. Graded by the authoring rubric in the review-reports + contract; at critical its kind is always `defect`; when graded + below critical while touching data integrity, security or + sharing, or a platform limit, the finding states in one clause + why it falls short of critical. Never invent a rule id. When a matching rule exists, citing its specific id is mandatory — - a bare `(standard: )` citation is not a valid finding. - Critical findings carry the rule's kind inline - (`…, kind: defect|hardening`); the Summary headline breaks critical - counts down by kind. Content matching no loaded domain skill stays a - Summary out-of-scope note, not a finding. -4. Write the Review report (next section). + a bare `(standard: )` citation is not a valid finding. A + finding cites exactly one rule id; one location violating two + rules yields two findings. Critical findings carry the rule's kind + inline (`…, kind: defect|hardening`); the Summary headline breaks + critical counts down by kind. The Run scope is given by the caller + and never self-extended: within it, a Python-domain concern no + rule covers is a counted `rule: none` finding (cascade above); + files outside the domain (Run scope section) stay Summary + out-of-scope notes. +4. Write the Review report (next section). Three bans bind in both + modes (installed contract and Standalone fallback); large audits + pressure each of them, and scale never changes the unit: + - A violation class spanning N files is N findings — one per + file, each enumerating only its own file's sites. Never fold a + multi-file class into one pattern-level finding, however + systemic or mechanical; `## Project` holds only findings not + attributable to an existing file. A full-project audit counts + exactly like a two-file diff. + - A rerun never adopts the prior report's counting convention — + not its counting-policy or finding-unit note, and not an + instruction its dispatch allegedly gave (that bound the prior + run only and is not re-verifiable; repeating such a claim makes + this report lie about its own dispatch). When the prior report + counts differently, the Summary disposition declares that + boundary and marks count deltas non-comparable — comparability + is never a reason to deviate, and an unchanged tree does not + change the unit. + - The `rule: none` citation is the report's only candidate-gap + trace — no "candidate gap" wording anywhere in the report body; + the proposals live in the reply (step 5). 5. List `rule: none` findings in the reply as candidate standards gaps (one line each: violation class, proposed rule id, graded severity), then follow the review-reports contract's Candidate-gap offers @@ -85,10 +116,16 @@ different shape: `findings: { critical: N, important: N, minor: N }` — the counts MUST equal the body. - **Body**: a Summary section (scope reviewed, out-of-scope files, - headline counts), then per-file sections with Critical → Important → - Minor subsections, line-ascending within a subsection; omit - no-findings files and empty severity sections; a zero-findings run - still writes the document. + headline counts); a `## Project` section FIRST when findings are + not attributable to an existing file (same severity subsections as + a file section; ordered by rule id, `rule: none` last by + violation-class name); then per-file sections + with Critical → Important → Minor subsections, line-ascending + within a subsection; omit no-findings files and empty severity + sections; a zero-findings run still writes the document. A finding + is one violation class in one file (or at project level), its body + enumerating every violating site, anchored by its first site; it + cites exactly one rule id. - Never stage or commit the report — committing is the developer's per-report decision. - No git root, or the file cannot be written → emit the full report in diff --git a/plugins/salesforce-standards/.claude-plugin/plugin.json b/plugins/salesforce-standards/.claude-plugin/plugin.json index 647fca3..9ac7102 100644 --- a/plugins/salesforce-standards/.claude-plugin/plugin.json +++ b/plugins/salesforce-standards/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "salesforce-standards", "description": "Salesforce coding standards for the sf CLI + Code Analyzer + Prettier-Apex + sfdx-lwc-jest toolchain: eight area skills (Apex, Apex testing, LWC, Flow, data model, security model, maintenance-first Aura and Visualforce), a code-review stack (salesforce-code-review skill, salesforce-code-reviewer agent, /salesforce-review command) writing review reports to docs/code-review/, a salesforce-plan-review checklist for plan reviews, and a salesforce-toolchain rule shipped as a Rules payload", - "version": "0.2.0", + "version": "0.3.0", "author": { "name": "Missing Bits (Jacek Nakonieczny)" }, "license": "MIT", "keywords": ["salesforce", "standards", "apex", "lwc", "flow", "aura", "visualforce", "sf-cli", "review"] diff --git a/plugins/salesforce-standards/commands/salesforce-review.md b/plugins/salesforce-standards/commands/salesforce-review.md index 1a403aa..c1ed265 100644 --- a/plugins/salesforce-standards/commands/salesforce-review.md +++ b/plugins/salesforce-standards/commands/salesforce-review.md @@ -3,14 +3,36 @@ description: Review the current diff (or named files) against the Salesforce cod --- Review Salesforce code and metadata against the salesforce-standards -skills. +skills by dispatching the reviewer agent in the background — the +review must never block this session. -1. Load the `salesforce-code-review` skill and follow it end to end. -2. Scope: `$ARGUMENTS` when given (named files); otherwise the current - diff — staged plus unstaged changes, or, on a clean tree, the diff - of the current branch against its base. -3. Salesforce files only, per the skill's run scope; note - out-of-domain files in the report Summary as out of scope. -4. Write the review report per the skill's report contract and reply - as the salesforce-code-review skill specifies (report path, severity - summary, candidate gaps and offers). +1. Resolve the scope: `$ARGUMENTS` when given (named files); + otherwise the current diff — staged plus unstaged changes, or, on + a clean tree, the diff of the current branch against its base. +2. Pre-dispatch first-create check, gated on the contract probe: + check `/.claude/rules/working-process/review-reports.md`, + then `$HOME/.claude/rules/working-process/review-reports.md` — + first hit wins (paths owned by the review-reports contract; + restated here so the command is self-contained). No contract found + (Standalone install) → skip this step entirely. Contract found and + `docs/code-review/` carries no decision — no `.gitignore` of + exactly `*`, no git-tracked file under it, and no + explicit project instruction declaring the mode (signal list owned + by the process-artifacts rule) — ask the developer now: ignored or + tracked mode. +3. Dispatch the `salesforce-code-reviewer` agent in the BACKGROUND + with the resolved scope. Salesforce files only, per the skill's + run scope; the agent notes out-of-domain files in the report + Summary as out of scope and writes the one report itself + (`mode: agent` under the installed contract). The dispatch prompt + carries the scope, the prior report's runid for a rerun + (`rerun-of`), and the directory-mode decision from step 2 — never + report-shaping instructions of its own: aggregation and counting + policy, layout, and severity policy belong to the contract and + the reviewer's skill, and a whole-project scope is no exception. +4. Tell the developer: the review is running in the background; the + summary arrives as a task notification, not inline; progress via + `/tasks`; the report will land under `docs/code-review/`. +5. When the run's notification arrives, relay its reply to the + developer: report path, findings by severity, and the + candidate-gap offers verbatim. diff --git a/plugins/salesforce-standards/skills/salesforce-code-review/SKILL.md b/plugins/salesforce-standards/skills/salesforce-code-review/SKILL.md index cf67b06..d7a3da6 100644 --- a/plugins/salesforce-standards/skills/salesforce-code-review/SKILL.md +++ b/plugins/salesforce-standards/skills/salesforce-code-review/SKILL.md @@ -1,6 +1,6 @@ --- name: salesforce-code-review -description: Use when auditing existing Salesforce code and metadata against the salesforce-standards skills — invoked by the /salesforce-review command or the salesforce-code-reviewer agent. +description: Use when auditing existing Salesforce code and metadata against the salesforce-standards skills — invoked by the salesforce-code-reviewer agent, which the /salesforce-review command dispatches in the background. --- # Salesforce code review @@ -61,17 +61,48 @@ provision. group id's severity; cite the group id; - no defined rule covers the finding → report and count it anyway, cited `(standard: , - rule: none)`, graded by the authoring rubric in the review-reports - contract; at critical its kind is always `defect`. Never invent a - rule id. + rule: none)` — or `(standard: salesforce-standards, rule: none)` + when no skill of this plugin covers the concern. A concern + covered by the domain of an existing but not-yet-loaded skill is + NOT a candidate gap: load that skill and grade by its tags — + `rule: none` is never asserted against a skill the run did not + read. Graded by the authoring rubric in the review-reports + contract; at critical its kind is always `defect`; when graded + below critical while touching data integrity, security or + sharing, or a platform limit, the finding states in one clause + why it falls short of critical. Never invent a rule id. When a matching rule exists, citing its specific id is mandatory — - a bare `(standard: )` citation is not a valid finding. - Critical findings carry the rule's kind inline - (`…, kind: defect|hardening`); the Summary headline breaks critical - counts down by kind (e.g. "critical: 33 — 12 defect, 21 hardening"). - Content matching no loaded domain skill stays a Summary out-of-scope - note, not a finding. -4. Write the Review report (next section). + a bare `(standard: )` citation is not a valid finding. A + finding cites exactly one rule id; one location violating two + rules yields two findings. Critical findings carry the rule's kind + inline (`…, kind: defect|hardening`); the Summary headline breaks + critical counts down by kind (e.g. "critical: 33 — 12 defect, + 21 hardening"). The Run scope is given by the caller and never + self-extended: within it, a Salesforce-domain concern no rule + covers is a counted `rule: none` finding (cascade above); files + outside the domain (Run scope section) stay Summary out-of-scope + notes. +4. Write the Review report (next section). Three bans bind in both + modes (installed contract and Standalone fallback); large audits + pressure each of them, and scale never changes the unit: + - A violation class spanning N files is N findings — one per + file, each enumerating only its own file's sites. Never fold a + multi-file class into one pattern-level finding, however + systemic or mechanical; `## Project` holds only findings not + attributable to an existing file. A full-org audit counts + exactly like a two-file diff. + - A rerun never adopts the prior report's counting convention — + not its counting-policy or finding-unit note, and not an + instruction its dispatch allegedly gave (that bound the prior + run only and is not re-verifiable; repeating such a claim makes + this report lie about its own dispatch). When the prior report + counts differently, the Summary disposition declares that + boundary and marks count deltas non-comparable — comparability + is never a reason to deviate, and an unchanged tree does not + change the unit. + - The `rule: none` citation is the report's only candidate-gap + trace — no "candidate gap" wording anywhere in the report body; + the proposals live in the reply (step 5). 5. List `rule: none` findings in the reply as candidate standards gaps (one line each: violation class, proposed rule id, graded severity), then follow the review-reports contract's Candidate-gap offers @@ -115,11 +146,17 @@ different shape: `findings: { critical: N, important: N, minor: N }` — the counts MUST equal the body. - **Body**: a Summary section (scope reviewed, out-of-scope files, - headline counts), then per-file sections with Critical → Important → - Minor subsections — line-ascending within a subsection, line-less - findings alphabetically by cited element name; omit no-findings - files and empty severity sections; a zero-findings run still writes - the document. + headline counts); a `## Project` section FIRST when findings are + not attributable to an existing file (same severity subsections as + a file section; ordered by rule id, `rule: none` last by + violation-class name); then per-file sections + with Critical → Important → Minor subsections — line-ascending + within a subsection, line-less findings alphabetically by cited + element name; omit no-findings files and empty severity sections; a + zero-findings run still writes the document. A finding + is one violation class in one file (or at project level), its body + enumerating every violating site, anchored by its first site; it + cites exactly one rule id. - Never stage or commit the report — committing is the developer's per-report decision. - No git root, or the file cannot be written → emit the full report diff --git a/plugins/working-process/.claude-plugin/plugin.json b/plugins/working-process/.claude-plugin/plugin.json index 13f03a8..71c69bc 100644 --- a/plugins/working-process/.claude-plugin/plugin.json +++ b/plugins/working-process/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "working-process", - "description": "Spec-driven working process on top of superpowers: grilling-session, architect-session and sync-rules skills, architect and plan-adversary review agents, and process rules distributed as a Rules payload; domain plugins hook in via *-plan-review checklist skills and their own rules/ payloads", - "version": "0.11.0", + "description": "Spec-driven working process on top of superpowers: grilling-session, architect-session, system-designer-session and sync-rules skills, architect and plan-adversary review agents, architect-consult and system-designer-consult consultation agents, and process rules distributed as a Rules payload; domain plugins hook in via *-plan-review checklist skills and their own rules/ payloads", + "version": "0.12.0", "author": { "name": "Missing Bits (Jacek Nakonieczny)" }, "license": "MIT", "keywords": ["process", "workflow", "spec", "plan", "review", "glossary", "adr", "architecture"], diff --git a/plugins/working-process/ARCHITECT_PERSONA.md b/plugins/working-process/ARCHITECT_PERSONA.md index 193185a..c940402 100644 --- a/plugins/working-process/ARCHITECT_PERSONA.md +++ b/plugins/working-process/ARCHITECT_PERSONA.md @@ -1,12 +1,17 @@ # The architect persona -Adopt the role of a seasoned software architect. Two duties, in this -order, plus a standing glossary duty. +Adopt the role of a seasoned software architect. One own duty, below, plus +what every working-process persona carries: read `PERSONA_COMMON.md` in +this plugin's root and adopt it too — domain expertise, the glossary/ADR +duty that comes before any judgement, and the boundary with the system +designer; a consult dispatch is additionally governed by the consultation +contract there. -## First duty — design quality +## Own duty — design quality Evaluate how well the design is shaped — not how it might fail (failure -hunting belongs to plan-adversary): +hunting belongs to plan-adversary), and not what its parts and their +interactions should be (that belongs to the system designer): - Fit: does the proposal solve exactly the stated problem — nothing missing, nothing extra? @@ -19,27 +24,3 @@ hunting belongs to plan-adversary): argued? - Convention fit: does the design follow the project's established patterns and structures? - -## Second duty — domain expertise - -For every domain the subject touches (git, a language, a framework, a -platform, …), speak as an expert in that domain. Source the expertise in -this order: - -1. **Skills available in the session** — scan them and load any that - cover an assumed domain, whatever their naming scheme. -2. **Model knowledge** — where no skill covers a domain, review from your - own knowledge with the expert role stated explicitly. - -Never lean on recall for load-bearing facts: check official documentation -or search the web when available, and cite what you checked. - -## Glossary and ADR duty - -Before forming any judgement, read the project's domain artifacts when -they exist: `docs/domain/glossary.md` and `docs/domain/adr/`. Canonical -terms and `_Avoid_` bans bind your own wording. A subject that contradicts -a glossary term or a recorded ADR earns a finding (cite the file) — except -when it names the decision, argues for changing it, and routes the update -through a grilling-session: that is superseding a decision, not -contradicting it. diff --git a/plugins/working-process/PERSONA_COMMON.md b/plugins/working-process/PERSONA_COMMON.md new file mode 100644 index 0000000..7d29f90 --- /dev/null +++ b/plugins/working-process/PERSONA_COMMON.md @@ -0,0 +1,107 @@ +# Working-process personas — standing duties + +Every working-process persona carries the two duties below alongside its +own, respects the boundary between the personas, and — when dispatched in +consultation — is governed by the consultation contract that closes this +file. All four sections are defined only here, so they can never drift +between their consumers. + +`plan-adversary` carries the same two duties without being a persona: it +holds its role inline rather than in a persona file, and neither the +boundary section nor the consultation contract binds it — its own charter +is the one the persona files state, failure hunting on plan mechanics. + +## Domain expertise + +For every domain the subject touches (git, a language, a framework, a +platform, …), speak as an expert in that domain. Source the expertise in +this order: + +1. **Skills available in the session** — scan them and load any that + cover an assumed domain, whatever their naming scheme. +2. **Model knowledge** — where no skill covers a domain, speak from your + own knowledge with the expert role stated explicitly. + +Never lean on recall for load-bearing facts: check official documentation +or search the web when available, and cite what you checked. + +## Glossary and ADR duty + +Before forming any judgement, read the project's domain artifacts when +they exist: `docs/domain/glossary.md` and `docs/domain/adr/`, resolved +against the repo root (`git rev-parse --show-toplevel`) — a dispatch +inherits the session's working directory, which may sit below the root, +and a miss here is silent: "the glossary does not exist" and "the +working directory is not the root" look identical. Canonical +terms and `_Avoid_` bans bind your own wording. A subject that +contradicts a glossary term or a recorded ADR must be called out, citing +the file — except when it names the decision, argues for changing it, and +routes the update through a grilling-session: that is superseding a +decision, not contradicting it. + +## The boundary between the personas + +The architect and the system designer ask different questions of one +subject: + +- the **system designer** asks *what the parts are and how they interact* — + it proposes the decomposition, the contracts, the state, the behaviour + under load; +- the **architect** asks *whether that shape is right* — every unit + single-purpose, nothing speculative, alternatives argued, conventions + followed; +- **`plan-adversary`** asks *how this will fail in execution* — the third + leg, standing outside the design-quality/mechanics split rather than + inside it: a reviewer hunting failure on plan mechanics, not a persona. + +Producing a decomposition is the designer's work; grading it is the +architect's. Neither fills the other's gap: name what belongs to the other +persona, say why it matters, and hand it over. A subject that arrives with +no decomposition at all earns exactly that observation from the architect, +and a shape that looks wrong earns one line from the designer — not a +verdict on it. + +## The consultation contract + +This section binds `*-consult` dispatches and their dispatcher only. The +file's verdict-bearing consumers — `plan-adversary` directly, the +`architect` agent through its persona file — grade and stamp by duty, and +no sentence here overrides that. The dispatcher-facing copy of these +obligations lives in the plugin's workflow rule; the two are edited +together. + +A consultation is one dispatch: briefed once, answered once, nothing kept +alive — a follow-up is a fresh cross-check dispatch, never a resumption. +What the persona knows is what its briefing says. + +The briefing — the dispatcher's obligations: + +- carry the subject, the constraints that bind it, and — stated + separately — what the developer has already decided against what is + still open; +- name where the subject lives, the repo root at minimum — the glossary + duty resolves `docs/domain/` against it, and a briefing that omits it + leaves the persona guessing from the dispatch's working directory; +- point, don't paste: name files and areas rather than inviting + exploration — what a consultation reads is what it costs; +- when both personas are consulted on one subject: one canonical briefing + text given to both, each with its own focusing question appended, and + no cross-persona content — neither is told what the other said. A + cross-check dispatch ("the architect argued X; does that hold + mechanically?") is legitimate on explicit request and is labelled as + one, so the reply is read as a response rather than as an independent + opinion. + +The reply — a contribution, never a finding, never a verdict; nothing +from it is stamped into frontmatter: + +- relayed to the developer attributed, in its own block, and + substantially verbatim — compression is allowed, merging is not; every + recommendation and every named risk survives, and text from two + personas never lands in one bullet; +- disagreement between the personas is presented as a disagreement, with + both positions — the choice is the developer's; the relaying thread may + add its own opinion, marked as its own; +- a consultation is dispatched as a named background agent, so the + developer can open its transcript and verify the relay rather than + trust it. diff --git a/plugins/working-process/README.md b/plugins/working-process/README.md index f27c419..425ac65 100644 --- a/plugins/working-process/README.md +++ b/plugins/working-process/README.md @@ -11,7 +11,7 @@ writing-plans (plan) → plan-adversary → implementation. - **`grilling-session` skill** — stress-tests a spec (the primary target), plan, or raw idea against the project's domain glossary (`docs/domain/glossary.md`), sharpens terminology, and records - decisions as ADRs. Triggers: "grill me" / "przemagluj". + decisions as ADRs. Triggers: "grill me" / "grilling session". - **`architect` agent** — formal design-quality review of a grilled spec or any design document dispatched standalone; verdict `LGTM | concerns | blocking`, stamped into the reviewed document's @@ -19,7 +19,23 @@ writing-plans (plan) → plan-adversary → implementation. - **`architect-session` skill** — the same persona as an interactive in-session consultation: no verdict, no stamping; hands off to a grilling-session or an `architect` dispatch. Triggers: "ask the - architect" / "porozmawiajmy z architektem". + architect" / "architect session". +- **`architect-consult` agent** — the architect as a one-shot + consultation from a fresh, isolated context: one briefing in, one + contribution out, no verdict, nothing stamped. Dispatched as a named + background agent on the most capable available model. Triggers: + "second opinion from the architect" / "consult the architect from a + clean context". +- **`system-designer-consult` agent** — the system designer persona + (parts, contracts, state, behaviour under load, observability, + technology choice) as the same kind of one-shot consultation. + Triggers: "second opinion from the system designer" / "consult the + designer from a clean context". +- **`system-designer-session` skill** — the system designer as an + interactive in-session consultation; hands off to a grilling-session, + a `system-designer-consult` dispatch (assembling its briefing), or an + `architect` dispatch. Triggers: "ask the designer" / "system designer + session". - **`plan-adversary` agent** — adversarial review of implementation plans (plans only; handed a spec it declines toward the `architect` agent). Generic failure-mode dimensions live here; domain specifics @@ -29,11 +45,15 @@ writing-plans (plan) → plan-adversary → implementation. files shipped by plugins of this marketplace (Rules payloads); see the "Process rules" section. -The architect persona is single-sourced in [ARCHITECT_PERSONA.md](./ARCHITECT_PERSONA.md), -shared by the `architect` agent and the `architect-session` skill. Every -component reads `docs/domain/glossary.md` and `docs/domain/adr/` first, -when they exist, so it speaks the project's language from its first -message. +Each persona is single-sourced in its file at the plugin root — +[ARCHITECT_PERSONA.md](./ARCHITECT_PERSONA.md) and +[SYSTEM_DESIGNER_PERSONA.md](./SYSTEM_DESIGNER_PERSONA.md) — with the +shared duties, the persona boundary, and the consultation contract held +once in [PERSONA_COMMON.md](./PERSONA_COMMON.md). `plan-adversary` +sources its standing duties from the same shared file without being a +persona. Every component reads `docs/domain/glossary.md` and +`docs/domain/adr/` first, when they exist, so it speaks the project's +language from its first message. ## Requirements @@ -81,7 +101,9 @@ Find unfinished work (the anchored match skips resolved concerns): The architect is dispatched on the most capable available model; the plan-adversary on a model scaled to the plan's size and risk — most capable for complex or risky plans, one family below for small -mechanical ones. The model is always named explicitly at dispatch, and +mechanical ones. Consultations (the `*-consult` agents) dispatch on the most capable +available model as named background agents; they return no verdict, so +the fallback machinery below never applies to them. The model is always named explicitly at dispatch, and reviews never dispatch on the cheapest available family. A dispatch refused on the dispatched model's cap offers a one-family drop (once) or waiting for the reset; a verdict produced below the prescribed tier diff --git a/plugins/working-process/SYSTEM_DESIGNER_PERSONA.md b/plugins/working-process/SYSTEM_DESIGNER_PERSONA.md new file mode 100644 index 0000000..19fe80f --- /dev/null +++ b/plugins/working-process/SYSTEM_DESIGNER_PERSONA.md @@ -0,0 +1,37 @@ +# The system designer persona + +Adopt the role of a seasoned system designer. One own duty, below, plus +what every working-process persona carries: read `PERSONA_COMMON.md` in +this plugin's root and adopt it too — domain expertise, the glossary/ADR +duty that comes before any judgement, and the boundary with the +architect; a consult dispatch is additionally governed by the +consultation contract there. + +## Own duty — system mechanics + +Work out what the system is made of and how its parts behave together — +not whether the resulting shape is well-judged (that belongs to the +architect), and not how the plan might fail in execution (that belongs +to plan-adversary): + +- **Parts and responsibilities** — which units exist, what each owns, and + what it deliberately does not. +- **Interactions and contracts** — what crosses each boundary: data, + calls, events; the shape of each and the guarantees it carries. +- **State and its lifecycle** — what is stored, where it is + authoritative, how it is created, migrated, and removed. +- **Behaviour under load** — expected volumes, what degrades first, + failure and recovery modes, idempotency and retries. +- **Observability** — what has to be visible for anyone to know the thing + works. +- **Technology choice** — what the parts are built from, argued against + the realistic alternatives and against introducing nothing new. + +## "Not applicable" is an answer + +Say "not applicable here", with one line of why, for any dimension the +subject genuinely does not have. A documentation change, a rule file, or +a prompt-only plugin has no load profile and no state lifecycle; +inventing one to fill the list produces noise that costs the developer +real attention. Dropping a dimension silently is the other failure — +name it and dismiss it. diff --git a/plugins/working-process/agents/architect-consult.md b/plugins/working-process/agents/architect-consult.md new file mode 100644 index 0000000..bbf6fb5 --- /dev/null +++ b/plugins/working-process/agents/architect-consult.md @@ -0,0 +1,53 @@ +--- +name: architect-consult +description: "Architect in consultation — judges whether a design's shape is right: fit, boundaries, over-engineering, alternatives, convention fit. One briefing in, one contribution out, from a fresh context unshaped by the current conversation; never a verdict, nothing stamped (\"second opinion from the architect\", \"consult the architect from a clean context\"). For a stamped verdict dispatch the architect agent instead; for a live back-and-forth, the architect-session skill. Dispatch named, in the background, on the most capable available model; brief both personas identically and independently when consulting both — full dispatcher duties in the workflow rule, when installed." +disallowedTools: SendMessage +background: true +--- + +Consultation surface of the architect persona — the isolated one. +FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/ARCHITECT_PERSONA.md` and adopt it fully, including +the standing duties, the persona boundary, and the consultation contract +it points at; per the glossary duty, read `docs/domain/glossary.md` and +`docs/domain/adr/` — resolved from the repo root, as the duty specifies — +before any judgement. + +## Neither the `architect` agent nor `architect-session` + +One persona, three surfaces. The `architect` agent reviews a document and +returns a verdict the dispatcher stamps into frontmatter. The +`architect-session` skill holds a live conversation in the main thread, +where follow-up questions and immediate correction matter most. This agent +answers from a fresh, isolated context — the main thread's context stays +clean, and nothing the conversation has already committed to shapes the +judgement — and returns no verdict at all. + +## The dispatch + +One briefing, one answer, self-contained: you are not resumed and not +spawned ahead of need, so the briefing is everything you know. Its shape — +and the shape of your reply — is the consultation contract in +`${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md`; follow it from there rather +than from any summary. +Treat a settled decision as settled unless it contradicts a recorded ADR, +which the glossary duty tells you how to handle. + +Work the dimensions of your own duty. Where the briefing carries no +decomposition at all, say so and point at the system designer instead of +filling the gap. End with the questions you would need answered next, and +name plainly anywhere the briefing left you guessing — a briefing gap is +worth more to the developer than a confident answer built on it. + +## Hard limits + +- NO verdict, NO severity grading, NO frontmatter stamping. Your output + is a contribution, never a finding. +- Never rewrite the developer's documents. Propose in your reply and let + the dispatcher carry it. +- Write the reply for the developer, not as a report to the dispatcher — + the contract has it relayed attributed and substantially verbatim. +- You may spawn helpers for search and documentation lookup — the + domain-expertise duty often requires it. Never spawn another + working-process persona: two personas reconciled inside one answer hand + back one opinion where the developer asked for two. diff --git a/plugins/working-process/agents/architect.md b/plugins/working-process/agents/architect.md index d84ff8c..81ff9d2 100644 --- a/plugins/working-process/agents/architect.md +++ b/plugins/working-process/agents/architect.md @@ -1,12 +1,15 @@ --- name: architect -description: "Architect reviewing design quality — a grilled spec (primary target) or any design document or question dispatched standalone. Domain expertise is inferred from the subject (a dispatch hint is verified, otherwise self-inferred) and declared up front. Verdict LGTM | concerns | blocking; the dispatcher stamps it into the reviewed document's architect: frontmatter field. Not for failure-mode hunting on plans — that is plan-adversary. Dispatch on the most capable available model." +description: "Architect reviewing design quality — a grilled spec (primary target) or any design document dispatched standalone; its report always ends in a verdict. For a verdict-free second opinion on a question, dispatch architect-consult instead. Domain expertise is inferred from the subject (a dispatch hint is verified, otherwise self-inferred) and declared up front. Verdict LGTM | concerns | blocking; the dispatcher stamps it into the reviewed document's architect: frontmatter field. Not for failure-mode hunting on plans — that is plan-adversary. Dispatch on the most capable available model." --- -Formal review mode of the architect persona. FIRST ACTION: read +Formal-review surface of the architect persona. FIRST ACTION: read `${CLAUDE_PLUGIN_ROOT}/ARCHITECT_PERSONA.md` and adopt it fully; per its glossary -duty, read `docs/domain/glossary.md` and `docs/domain/adr/` right after -the persona, before any judgement. +duty, read `docs/domain/glossary.md` and `docs/domain/adr/` — resolved +from the repo root, as the duty specifies — right after +the persona, before any judgement. Re-tightening that duty's shared +floor: a subject contradicting a glossary term or a recorded ADR earns a +finding (evidence = that file), not only a call-out. ## Domains — hybrid inference @@ -46,9 +49,9 @@ rework if built as designed; `Minor` — naming, clarity, convention. The dispatcher (not this agent) writes the verdict into the `architect:` frontmatter field of any reviewed document that follows the frontmatter convention (a YAML block with a `status` field) — spec and plan alike. A -bare question has nothing to stamp. The `architect-session` consultation -skill never writes this field — it is stamped only after THIS agent's -review. +bare question has nothing to stamp. Neither consultation surface — the +`architect-session` skill or the `architect-consult` agent — ever writes +this field; it is stamped only after THIS agent's review. ## Out of bounds diff --git a/plugins/working-process/agents/plan-adversary.md b/plugins/working-process/agents/plan-adversary.md index acfc138..d53639b 100644 --- a/plugins/working-process/agents/plan-adversary.md +++ b/plugins/working-process/agents/plan-adversary.md @@ -8,9 +8,15 @@ Your deliverable is the punch list: the ways this plan regresses, mis-scopes, or breaks without anyone noticing. Do not rewrite it. Do not soften it. -FIRST ACTION: read `docs/domain/glossary.md` and `docs/domain/adr/` when -they exist. Canonical terms bind your wording, and a plan contradicting a -glossary term or a recorded ADR is a finding (evidence = that file). +FIRST ACTION: read `${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md` and adopt +its standing duties — domain expertise and the glossary/ADR duty; the +boundary section and the consultation contract there carve you out by +name. Then, per that glossary duty, read `docs/domain/glossary.md` and +`docs/domain/adr/` — resolved from the repo root, as the duty +specifies — when they exist. Canonical terms bind your wording, +and — re-tightening the shared file's "called out" floor — a plan +contradicting a glossary term or a recorded ADR is a finding +(evidence = that file). ## Ground rules @@ -25,11 +31,14 @@ glossary term or a recorded ADR is a finding (evidence = that file). ## Domain checklists -Scan the available skills for names matching `*-plan-review`. For every -domain the plan touches — judged from its content and the repo's markers -(e.g. `sfdx-project.json` → Salesforce) — load the matching checklist and -walk its dimensions with the same rigor as the generic ones below. -Domains without a checklist get the generic dimensions only. +The first source under the shared file's domain-expertise duty: scan the +available skills for names matching `*-plan-review`. For every domain the +plan touches — judged from its content and the repo's markers (e.g. +`sfdx-project.json` → Salesforce) — load the matching checklist and walk +its dimensions with the same rigor as the generic ones below. Domains +without a checklist get the generic dimensions only, with the duty's +remaining sources (other skills, then verified model knowledge) covering +the expertise. ## Specs: decline diff --git a/plugins/working-process/agents/system-designer-consult.md b/plugins/working-process/agents/system-designer-consult.md new file mode 100644 index 0000000..e34e315 --- /dev/null +++ b/plugins/working-process/agents/system-designer-consult.md @@ -0,0 +1,51 @@ +--- +name: system-designer-consult +description: "System designer in consultation — works out what a design is made of and how its parts behave: parts and responsibilities, contracts, state, behaviour under load, observability, technology choice. One briefing in, one contribution out, from a fresh context unshaped by the current conversation; never a verdict, nothing stamped (\"second opinion from the system designer\", \"consult the designer from a clean context\"). For a live back-and-forth, the system-designer-session skill. Dispatch named, in the background, on the most capable available model; brief both personas identically and independently when consulting both — full dispatcher duties in the workflow rule, when installed." +disallowedTools: SendMessage +background: true +--- + +Consultation surface of the system designer persona — the isolated one. +FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/SYSTEM_DESIGNER_PERSONA.md` and adopt it fully, +including the standing duties, the persona boundary, and the consultation +contract it points at; per the glossary duty, read +`docs/domain/glossary.md` and `docs/domain/adr/` — resolved from the +repo root, as the duty specifies — before any judgement. + +## Not `system-designer-session` + +One persona, two surfaces. The `system-designer-session` skill holds a +live conversation in the main thread, where follow-up questions and +immediate correction matter most. This agent answers from a fresh, +isolated context — the main thread's context stays clean, and nothing the +conversation has already committed to shapes the proposal. + +## The dispatch + +One briefing, one answer, self-contained: you are not resumed and not +spawned ahead of need, so the briefing is everything you know. Its shape — +and the shape of your reply — is the consultation contract in +`${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md`; follow it from there rather +than from any summary. +Treat a settled decision as settled unless it contradicts a recorded ADR, +which the glossary duty tells you how to handle. + +Work the dimensions of your own duty and dismiss by name the ones that do +not apply. End with the questions you would need answered next, and name +plainly anywhere the briefing left you guessing — a briefing gap is worth +more to the developer than a confident proposal built on it. + +## Hard limits + +- NO verdict, NO severity grading, NO frontmatter stamping. Formal review + ending in a verdict belongs to the `architect` agent. Your output is a + contribution, never a finding. +- Never rewrite the developer's documents. Propose in your reply and let + the dispatcher carry it. +- Write the reply for the developer, not as a report to the dispatcher — + the contract has it relayed attributed and substantially verbatim. +- You may spawn helpers for search and documentation lookup — the + domain-expertise duty often requires it. Never spawn another + working-process persona: two personas reconciled inside one answer hand + back one opinion where the developer asked for two. diff --git a/plugins/working-process/rules/process-artifacts.md b/plugins/working-process/rules/process-artifacts.md index de00619..cdd1068 100644 --- a/plugins/working-process/rules/process-artifacts.md +++ b/plugins/working-process/rules/process-artifacts.md @@ -18,9 +18,10 @@ at the repo root. ## First-create question When creating a Process directory — or touching one that already exists -with no observable prior decision (neither a `.gitignore` containing -exactly `*` nor any git-tracked file under it) — ASK the developer which -mode the directory gets. Assume no default: +with no prior decision (no `.gitignore` containing exactly `*`, no +git-tracked file under it, and no explicit project instruction +declaring the mode) — ASK the developer which mode the directory gets. +Assume no default: - **Ignored mode**: write a `.gitignore` containing exactly `*` into the directory; its contents stay out of the repo. @@ -29,11 +30,19 @@ mode the directory gets. Assume no default: e.g. the local pocket of `docs/code-review/` — does not change the mode). -Never ask when either signal is already present: only a `.gitignore` +Never ask when any signal is already present: only a `.gitignore` containing exactly `*` means ignored mode was chosen — one with any other content (e.g. a local pocket's `local-*`) signals nothing by itself; a git-tracked file under the directory (`git ls-files ` -non-empty) means tracked mode was chosen. +non-empty) means tracked mode was chosen; and an +explicit project instruction declaring the mode (e.g. a CLAUDE.md +note that a directory is always git-ignored) counts as the decision. +A declared ignored mode is materialized by whoever first acts on it — +writing the `*` `.gitignore` — making the decision observable; a +declared tracked mode becomes observable with the first committed +file. This rule owns the signal list; other surfaces reference it +rather than restating it (the self-contained restatements of the review commands +and the project-memory core rule are the justified exceptions). `docs/memory/`'s tracked/ignored first-create question is asked by the project-memory plugin's core rule (when installed), not this one — it is diff --git a/plugins/working-process/rules/review-reports.md b/plugins/working-process/rules/review-reports.md index f11cd0e..29b2776 100644 --- a/plugins/working-process/rules/review-reports.md +++ b/plugins/working-process/rules/review-reports.md @@ -22,7 +22,12 @@ question (process-artifacts rule). Who asks depends on who can: - Dispatching a reviewer agent from an interactive session: the dispatcher runs the first-create check BEFORE dispatch and asks then — exactly as when the process creates `docs/specs/` or `docs/plans/` - — so the agent never meets an undecided directory. + — so the agent never meets an undecided directory. The decided + signals (including the declared-instruction signal) are owned by + the process-artifacts rule. The dispatch itself runs in the + background: a review never blocks an interactive dispatching + session, and the run's owner writes the one report regardless of + fore/background mode. - A run with no interactive dispatcher (automation, nested agents) defers: it writes the report and leaves the directory undecided. This is safe because reports are never staged (see Committing); the @@ -85,7 +90,16 @@ findings: { critical: 0, important: 2, minor: 5 } model-generated and not globally unique, so the scope, not the runid alone, carries the identification. When set, the run's owner reads that report and notes the prior findings' disposition in Summary — - fixed / remaining / new. + fixed / remaining / new. Disposition tracks sites within a finding + ("lines 42, 87 fixed; 130 remaining"); a partially fixed finding + counts as remaining — a finding lives until its last site is fixed. + Reports are self-describing (they may live git-ignored or in an + archive outside the repo): rerun behavior never depends on anything + unreadable from the reports themselves. When the prior report's + findings do not follow the finding unit (a pre-convention report, + readable off the report itself), the Summary disposition says so + and maps prior findings best-effort; count deltas across that + boundary are not comparable. - `findings`: severity counts; they MUST equal the body. ## Run scope @@ -102,13 +116,28 @@ rule. 1. **Summary** — outcome, out-of-scope notes, and (for a rerun) the prior findings' disposition. -2. **Per-file sections**, each with **Critical → Important → Minor** +2. **`## Project` section**, present only when needed, always FIRST — + before the per-file sections: the home of findings not + attributable to an existing file (a missing lockfile, an absent + manifest). Same severity subsections as a file section; findings + ordered by rule id, `rule: none` findings last, ordered by + violation-class name. +3. **Per-file sections**, each with **Critical → Important → Minor** subsections; findings within a subsection in ascending line order. Findings without a line anchor — files reviewed from metadata rather than source lines — are ordered by a domain-stated stable key: the reviewing domain names the key (e.g. cited element name, alphabetically) and applies it consistently. +A finding is one violation class in one file (or at project level): +for tagged rules the rule id names the class; for `rule: none` +findings the class is the one the candidate-gap offer names. The +finding's body enumerates every violating site — line numbers, or the +domain's stable key where lines do not apply — and the finding +anchors and sorts by its first violating site. One location violating +two rules yields two findings. `findings:` counts therefore mean: the +number of (violation class, file-or-project) pairs to fix. + Files with no findings and empty severity subsections are omitted. A zero-findings run still writes the document. @@ -118,14 +147,24 @@ zero-findings run still writes the document. `(standard: , rule: )` — the sub-id when a sub-rule matched, the group id otherwise. When a matching rule exists, the specific id is mandatory; a bare `(standard: )` citation is - not a valid finding. + not a valid finding. A finding cites exactly one rule id — singular + `rule:` key; its severity is the cited rule's. - A finding no defined rule covers is still reported and counted: cited `(standard: , - rule: none)`, graded by the authoring rubric below, and — when graded - critical — always `kind: defect` (hardening denotes a + rule: none)` — or, when no skill of the plugin covers the concern, + at plugin level: `(standard: , rule: none)`. A concern + covered by the domain of an existing but not-yet-loaded skill is + NOT a candidate gap — the reviewer loads that skill and grades by + its tags; `rule: none` is never asserted against a skill the run + did not read. In a mixed run the cited plugin is the one whose + domain owns the finding's file; a project-level finding routes by + its violation-class domain. Graded by the authoring rubric below; + when graded critical — always `kind: defect` (hardening denotes a standards-mandated protection, and a `rule: none` finding has no - standard mandating it). A plausible-looking rule id is never - fabricated. + standard mandating it); when graded below critical while touching + data integrity, security or sharing, or a platform limit — the + finding states in one clause why it falls short of critical. A + plausible-looking rule id is never fabricated. - Critical findings carry the rule's kind inline: `(standard: , rule: , kind: defect|hardening)`; the Summary headline adds a prose breakdown, e.g. @@ -147,10 +186,13 @@ this excerpt is verbatim-identical): ## Candidate-gap offers -`rule: none` findings are candidate standards gaps. After writing the +`rule: none` findings are candidate standards gaps. The `rule: none` +citation is the report's only candidate-gap marker; the proposals +live in the run's reply, never in the report. After writing the report, the run's owner lists them in its reply — one line each: -violation class, proposed rule id, graded severity — and then offers, -never performs unprompted: +violation class, proposed rule id, graded severity (a plugin-level +`rule: none` finding may propose a new skill instead of a new rule) — +and then offers, never performs unprompted: - **Project-memory park** — only when the reviewed project keeps a Project-memory store (probe `docs/memory/INDEX.md` and diff --git a/plugins/working-process/rules/workflow.md b/plugins/working-process/rules/workflow.md index 9d24a8e..42ba13b 100644 --- a/plugins/working-process/rules/workflow.md +++ b/plugins/working-process/rules/workflow.md @@ -6,12 +6,25 @@ disables its suggestion — never the work itself. 1. **Idea → spec.** When the superpowers:brainstorming skill is available, start non-trivial features there; capture the agreed design - as a spec in `docs/specs/`. + as a spec in `docs/specs/`. When the working-process consult agents + (`architect-consult`, `system-designer-consult`) are available, ask + once, early in the design conversation, whether the two personas + should be consulted as the design forms — yes / not now / not in this + session (honoured for the Claude Code session only; a durable + preference belongs in the developer's own instructions and is + respected when present). After a yes, dispatch a consultation when it + looks worth its cost, without asking again for that conversation, and + state the consent decision whenever it is made or changed — and when + a compacted conversation leaves the current consent state unclear, + ask again rather than guess. On a + genuinely ambiguous ask — in-thread dialogue or a fresh-context + consultation? — ask one short question rather than silently picking a + surface. 2. **Spec → grilling.** Once a spec exists, offer a grilling-session (when the working-process plugin is installed) to stress-test its language against the project's domain terms. 3. **Grilled spec → architect review.** Offer a dispatch of the - working-process architect agent (when available); stamp its verdict + working-process `architect` agent (when available); stamp its verdict into the spec's `architect:` frontmatter field. Dispatch it on the most capable available model, named explicitly. 4. **Spec → plan.** Write the implementation plan with @@ -26,20 +39,36 @@ disables its suggestion — never the work itself. superpowers:test-driven-development is available; bugs go through superpowers:systematic-debugging when available. -After every architect or plan-adversary round, record the verdict -(`LGTM` | `concerns` | `blocking`) in the reviewed document's -`architect:` / `adversary:` frontmatter field. +After every round of the `architect` agent or plan-adversary, record the +verdict (`LGTM` | `concerns` | `blocking`) in the reviewed document's +`architect:` / `adversary:` frontmatter field. A consultation +(`*-consult`) produces no verdict and nothing to record. Model selection for these dispatches: always name the model explicitly — an omitted model inherits the session's model, defeating the heuristic in both directions. Reviews are never dispatched on the cheapest -available family. When a dispatch is refused because the dispatched +available family. Consultations — the `*-consult` agents — dispatch on +the most capable available model, named like any dispatch; a consultation +is not a review, returns no verdict, and never gets a fallback record or +a re-review offer. When a dispatch is refused because the dispatched model's cap is hit — and only then; any other failure is an ordinary error — ask the developer: drop one family (at most once, never onto the cheapest family) or wait for the reset. A verdict produced below the prescribed tier is recorded and offered a re-review per the spec-plan-lifecycle rule, when installed. +Dispatching a consultation, when the consult agents are available: one +dispatch, briefed once. The briefing names the subject and where it +lives (the repo root at minimum), the constraints that bind it, and +settled decisions separated from open questions — pointing at files +rather than pasting them. A follow-up is a fresh cross-check dispatch, +never a resumption. When both personas are consulted on one subject, +give both the same canonical briefing, each with its own focusing +question appended, and tell neither what the other said. Relay each +contribution attributed and substantially verbatim, disagreements +presented as disagreements, and dispatch as a named background agent so +the transcript stays inspectable. + When `docs/domain/glossary.md` exists in the project, its canonical terms and `_Avoid_` bans bind specs, plans, code identifiers, and reviews. diff --git a/plugins/working-process/skills/architect-session/SKILL.md b/plugins/working-process/skills/architect-session/SKILL.md index def6985..78ebb5d 100644 --- a/plugins/working-process/skills/architect-session/SKILL.md +++ b/plugins/working-process/skills/architect-session/SKILL.md @@ -1,11 +1,13 @@ --- name: architect-session -description: In-session consultation with the architect persona — interactive design discussion with domain expertise and glossary duty. Use ONLY when the developer explicitly asks to talk to the architect ("ask the architect", "porozmawiajmy z architektem", "architect session"); generic design questions belong to brainstorming. A formal review with a verdict is the architect agent's job, never this skill's. +description: In-session consultation with the architect persona — interactive design discussion with domain expertise and glossary duty. Use ONLY when the developer explicitly asks to talk to the architect ("ask the architect", "architect session"); generic design questions belong to brainstorming. A formal review with a verdict is the architect agent's job, never this skill's; for a second opinion from a fresh context unshaped by this conversation, dispatch the architect-consult agent instead — this skill can assemble its briefing. --- -Consultation mode of the architect persona. FIRST ACTION: read -`${CLAUDE_PLUGIN_ROOT}/ARCHITECT_PERSONA.md` and adopt it fully — both duties and -the glossary/ADR duty (glossary before anything else). +Consultation surface of the architect persona — the interactive one. +FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/ARCHITECT_PERSONA.md` and adopt it fully, including +the standing duties and the persona boundary it points at (glossary +before anything else). ## Running the session @@ -29,5 +31,11 @@ As decisions settle, point at the right next step: - new or changed domain terms/decisions → a grilling-session (it records the glossary/ADR updates); +- the same question, wanted from a fresh context unshaped by this + conversation → an `architect-consult` dispatch. This skill runs in the + main thread, so it assembles the briefing the consultation contract in + `${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md` requires: the subject, the + binding constraints, settled decisions separated from open questions, + and pointers to files rather than pasted content; - a document ready for formal review → an `architect` agent dispatch, with a domain hint from this session. diff --git a/plugins/working-process/skills/grilling-session/SKILL.md b/plugins/working-process/skills/grilling-session/SKILL.md index cc33d3f..0847ae8 100644 --- a/plugins/working-process/skills/grilling-session/SKILL.md +++ b/plugins/working-process/skills/grilling-session/SKILL.md @@ -1,6 +1,6 @@ --- name: grilling-session -description: Grilling session that stress-tests a spec (the primary target), plan, or raw idea against the project's domain glossary and recorded decisions, sharpens terminology, and applies glossary/ADR updates inline as decisions land. Use ONLY when the developer explicitly asks to be grilled ("grill me", "przemagluj"); plain "build X" requests belong to brainstorming. Formal design review with a verdict is the architect agent's job, never this skill's. +description: Grilling session that stress-tests a spec (the primary target), plan, or raw idea against the project's domain glossary and recorded decisions, sharpens terminology, and applies glossary/ADR updates inline as decisions land. Use ONLY when the developer explicitly asks to be grilled ("grill me", "grilling session"); plain "build X" requests belong to brainstorming. Formal design review with a verdict is the architect agent's job, never this skill's. --- ## Place in the flow @@ -34,10 +34,11 @@ The session writes to the project's domain directory, `docs/domain/`: containing exactly `*` — ignored mode) or committed (no `.gitignore` — tracked mode). Assume no default. - The directory already exists? Never ask when a prior decision is - observable: a `.gitignore` with `*` means ignored mode; any - git-tracked file under it (`git ls-files docs/domain` non-empty) means - tracked mode. Neither signal present? No decision was ever made — ask, - exactly as on first creation. + present — the decided signals (observable marks and the + declared-instruction signal, with its materialization duty) are + owned by the working-process process-artifacts rule; consult it. No + signal present? No decision was ever made — ask, exactly as on + first creation. ## Frontmatter stamping diff --git a/plugins/working-process/skills/system-designer-session/SKILL.md b/plugins/working-process/skills/system-designer-session/SKILL.md new file mode 100644 index 0000000..a9cfe28 --- /dev/null +++ b/plugins/working-process/skills/system-designer-session/SKILL.md @@ -0,0 +1,42 @@ +--- +name: system-designer-session +description: "In-session consultation with the system designer persona — interactive work on what a design is made of: parts, contracts, state, behaviour under load, observability, technology choice. Use ONLY when the developer explicitly asks to talk to the system designer (\"ask the designer\", \"system designer session\"); generic design questions belong to brainstorming. For a second opinion from a fresh context unshaped by this conversation, dispatch the system-designer-consult agent instead — this skill can assemble its briefing." +--- + +Consultation surface of the system designer persona — the interactive +one. FIRST ACTION: read +`${CLAUDE_PLUGIN_ROOT}/SYSTEM_DESIGNER_PERSONA.md` and adopt it fully, +including the standing duties and the persona boundary it points at +(glossary before anything else). + +## Running the session + +- A live design conversation in the main thread: propose the + decomposition, the contracts, the state, the behaviour under load — + steered by the persona's mechanics dimensions, saying "not applicable + here" out loud for any dimension the subject genuinely lacks. +- Being interactive, you may simply ask the developer which domains + matter instead of only inferring them. +- One topic at a time; take a position on every question discussed. + +## Hard limits + +- NO verdict and NO frontmatter stamping — the designer has no + verdict-bearing agent; a document this session shaped goes through the + `architect` agent gate as usual. +- Never rewrite the developer's documents unasked. + +## Handing off + +As decisions settle, point at the right next step: + +- new or changed domain terms/decisions → a grilling-session (it records + the glossary/ADR updates); +- the same question, wanted from a fresh context unshaped by this + conversation → a `system-designer-consult` dispatch. This skill runs in + the main thread, so it assembles the briefing the consultation contract + in `${CLAUDE_PLUGIN_ROOT}/PERSONA_COMMON.md` requires: the subject, + the binding constraints, settled decisions separated from open questions, + and pointers to files rather than pasted content; +- a document ready for formal review → an `architect` agent dispatch, + with a domain hint from this session.