@lab43/q 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,36 @@
1
+ # Pull Requests
2
+
3
+ Rules for authoring a pull request. Hold its prose to the writing rules (see: q conventions/writing.md). Sign the body and every comment or reply on it: "— Claude 🤖" (source: q conventions/writing.md, Sign what you post). A project's own PR conventions win over this doc (source: q conventions/documentation.md, Three tiers of conventions), and so does a PR template in the repo.
4
+
5
+ ## Title
6
+
7
+ The title names the work the PR delivers.
8
+
9
+ ## Body
10
+
11
+ A PR has two goals, in order: make the change easy for a human to review, and prove it does what it says. Every sentence in the body:
12
+
13
+ - Serves one of the two goals.
14
+ - Assumes no session context — the future reader arriving through git history has none, however much today's reviewer knows.
15
+
16
+ Describe the change, never the run that produced it. Review rounds, rulings, and session events are the run's story, not the change's.
17
+
18
+ ## Sections
19
+
20
+ Compose the body from these sections, in order. Most PRs need only Summary and Testing. Add another section only when it has something the reviewer needs.
21
+
22
+ - **Summary** — the rubric the reviewer checks the diff against: what is true after merge that wasn't before, and why. State outcomes, not edits: one claim per deliverable, each something the reader can now rely on. The diff is the catalog of changes. When the diff is large, say where the substance lives and which files are mechanical fallout. The Summary links the work's source: the tracker item when one exists (source: q conventions/issue-tracking.md, Work links back), and the plan doc when the PR implements a plan. Where the tracker closes an item from the link's wording, word it to close only in the PR whose merge finishes the item — the last layer of a stack, the only PR otherwise. Every other layer links the item without closing it, or the first merge closes work the rest of the stack hasn't delivered.
23
+ - **Callouts** — answers to the questions the diff will raise:
24
+ - Choices that look wrong but are deliberate.
25
+ - Expected changes deliberately not made.
26
+ - Close calls the author wants checked.
27
+ - Rules added to or changed in standing law that the PR's purpose doesn't explain — the diff shows the rule, not the problem that prompted it.
28
+
29
+ Each entry states the question's answer and its reason. A call no reviewer would question is noise here. Callouts also reach the reviewer on the diff itself (see: Diff comments).
30
+ - **Caveats** — the known problems shipping with the change. The reviewer shouldn't spend effort discovering what the author already knows.
31
+ - **Follow-ups** — the work this change obligates: what a reviewer would otherwise ask "doesn't this mean X needs doing?". Link each to its tracker item when one exists — the body informs the reviewer, but nobody returns to a merged body to collect work, so the tracker carries it. Work the session surfaced that this change doesn't obligate goes to the tracker alone.
32
+ - **Testing** — the evidence the diff doesn't carry: what was exercised and what it demonstrated, claim by claim. The project's standing checks prove nothing about this change and go unlisted. When the diff's own tests are the whole proof, say so.
33
+
34
+ ## Diff comments
35
+
36
+ Post a callout about a specific change also as a comment on its line of the diff, so the reviewer meets it in place. A callout not tied to a specific change needs no comment. Give the comment only what a reader needs to understand why that change was made — the anchor already says where and what, so no labels and no framing.
@@ -0,0 +1,54 @@
1
+ # Writing
2
+
3
+ Rules for writing prose — docs, plans, PR bodies, anything a human or agent will read.
4
+
5
+ ## One idea per sentence
6
+
7
+ Give each instruction or claim its own sentence. Don't chain ideas with semicolons, commas, or em-dash asides. Chained qualifiers make the reader guess what binds to what. A conditional sits next to the thing it modifies, or becomes its own sentence.
8
+
9
+ ## Lists over paragraphs
10
+
11
+ Three or more parallel items become a list. Parallelism hides in prose: check any paragraph that names several deliverables, steps, or options. A reader scans a list but has to parse a paragraph.
12
+
13
+ Each item stands alone, with no trailing commas and no closing "and" or "or". When dropping the connective would lose meaning, the lead-in carries it: "any of the following".
14
+
15
+ ## Constrain content, not length
16
+
17
+ Never regulate prose with a length target — "keep it short", "a few sentences", a line cap. Define what the piece must carry and what gets cut. A length target doesn't select for the right information, and it backfires when there is genuinely a lot to present.
18
+
19
+ ## Plain words
20
+
21
+ Use the words a reader would use to describe the thing. Write "errors now show a message instead of crashing", not "error handling was hardened with graceful degradation". Jargon and category labels make the reader translate before they can follow.
22
+
23
+ ## Instructions are commands
24
+
25
+ Write an instruction — to a human or an agent — as a command: "commit the fixes", never "the fixes are committed" or "the run commits the fixes". Passives and narration hide who acts. Keep declarative sentences for facts a reader relies on.
26
+
27
+ ## Deletion is the default
28
+
29
+ Deletion is safe: version history keeps everything cut. When a judgment call between keeping and cutting is close, cut. When text is ambiguous or wrong, try deleting it before qualifying it.
30
+
31
+ ## Refine rather than append
32
+
33
+ Integrate a change by rewriting the text it lands in until the piece reads as if written that way from the start. Appending shows at every scale:
34
+
35
+ - a qualifier bolted onto an existing sentence
36
+ - a clarification or exception that walks back a statement made earlier — evidence the statement itself needs adjusting
37
+ - a changelog at the bottom of a doc — version history is the changelog
38
+
39
+ In every case, fix the original text where it stands.
40
+
41
+ ## Write for the reader, not the edit
42
+
43
+ Write each edit for the reader who arrives fresh: they see the merged text, never the request or the conversation behind the change. Cut detail that earns its place only against that history — a scope note answering something the discussion raised, a clause defending the choice against an objection, a reassurance that some neighboring case still holds. To the fresh reader it answers a question no one asked. The test: would the sentence survive a from-scratch rewrite of the piece?
44
+
45
+ ## Sign what you post
46
+
47
+ Text posted under the user's account reads as the user's. Sign anything a reader meets as a message from them, with "— Claude 🤖" on its own line at the end:
48
+
49
+ - a pull request's body
50
+ - a comment or reply on a pull request, on the diff or at the top level
51
+ - an issue or tracker item you file
52
+ - any comment you post on an issue or tracker item
53
+
54
+ Text committed to the repo is not a message and carries no signature. Git history records who wrote it.
@@ -0,0 +1,15 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/session-start.sh",
9
+ "timeout": 10
10
+ }
11
+ ]
12
+ }
13
+ ]
14
+ }
15
+ }
@@ -0,0 +1,125 @@
1
+ // Validate the project's q setup and, when it doesn't validate, tell the
2
+ // session to run /q:sync. Claude Code loads whatever plugin version is on
3
+ // disk, so drift surfaces only if something checks at session start — no
4
+ // other channel runs every session. The checks: the q copy this session
5
+ // loaded vs the project's pin, each watermarked package's pin vs its
6
+ // watermark vs its installed version, and the reverse direction — a
7
+ // q-extension devDependency with no watermark entry (installed by hand,
8
+ // never indexed).
9
+ //
10
+ // The remedy is uniform — /q:sync re-derives the specifics and routes each
11
+ // finding to its remedy — so every failure emits the same message and
12
+ // the script stops at the first one. The only designed silence is a project
13
+ // that declares no @lab43/q devDependency; anything else missing or
14
+ // unreadable fails like any other invalid state.
15
+
16
+ import fs from "node:fs";
17
+ import path from "node:path";
18
+ import { fileURLToPath } from "node:url";
19
+
20
+ const proj = process.env.CLAUDE_PROJECT_DIR || ".";
21
+ const root =
22
+ process.env.CLAUDE_PLUGIN_ROOT ||
23
+ path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
24
+
25
+ // Keep in sync with the message in session-start.sh (bash can't import it).
26
+ const MESSAGE =
27
+ "The q plugin could not validate this project's q setup, so its conventions and tooling may be stale or broken. Run /q:sync to repair it.";
28
+
29
+ const fail = () => {
30
+ console.log(
31
+ JSON.stringify({
32
+ hookSpecificOutput: {
33
+ hookEventName: "SessionStart",
34
+ additionalContext: MESSAGE,
35
+ },
36
+ }),
37
+ );
38
+ process.exit(0);
39
+ };
40
+ const read = (file) => {
41
+ try {
42
+ return fs.readFileSync(file, "utf8");
43
+ } catch {
44
+ return null;
45
+ }
46
+ };
47
+ const parse = (text) => {
48
+ try {
49
+ return JSON.parse(text);
50
+ } catch {
51
+ return undefined;
52
+ }
53
+ };
54
+ const installedVersion = (dir) => parse(read(path.join(dir, "package.json")) ?? "")?.version;
55
+
56
+ // Pins: one exact devDependency for q and one per extension, in the project's
57
+ // package.json. A missing manifest means not a q project. One that exists but
58
+ // can't be read or parsed fails like any other invalid state.
59
+ let pkgText;
60
+ try {
61
+ pkgText = fs.readFileSync(path.join(proj, "package.json"), "utf8");
62
+ } catch (e) {
63
+ if (e.code === "ENOENT" || e.code === "ENOTDIR") process.exit(0);
64
+ fail();
65
+ }
66
+ const pkg = parse(pkgText);
67
+ if (pkg === undefined) fail();
68
+
69
+ const devDeps =
70
+ pkg && typeof pkg.devDependencies === "object" && pkg.devDependencies !== null
71
+ ? pkg.devDependencies
72
+ : {};
73
+
74
+ // Declaring no @lab43/q devDependency is the one designed silence. A pin that
75
+ // is declared but is not a version string is an invalid state like any other,
76
+ // and fails the way a malformed pin fails for every extension below.
77
+ if (!Object.hasOwn(devDeps, "@lab43/q")) process.exit(0);
78
+ const pinned = devDeps["@lab43/q"];
79
+ if (typeof pinned !== "string") fail();
80
+
81
+ // The q this session actually loaded. CLAUDE_PLUGIN_ROOT is the directory it
82
+ // was resolved from, and npm wrote that copy's version, so comparing it
83
+ // against the pin also catches a session running some other checkout's q.
84
+ const loaded = installedVersion(root);
85
+ if (typeof loaded !== "string") fail();
86
+ if (loaded !== pinned) fail();
87
+
88
+ // Watermarks. A pinned project with no state file is unrecorded drift.
89
+ const stateText = read(path.join(proj, ".claude/q-state.json"));
90
+ if (stateText === null) fail();
91
+
92
+ const state = parse(stateText);
93
+ if (state === undefined || typeof state !== "object" || state === null) fail();
94
+
95
+ const recon = state.reconciledAgainst ?? {};
96
+ if (typeof recon !== "object" || recon === null || Array.isArray(recon)) fail();
97
+ // q is the framework rather than an extension, so it is checked by name: a
98
+ // pinned project with no entry for it is caught here. The reverse-direction
99
+ // loop below cannot stand in. It identifies extensions by a keyword read from
100
+ // node_modules, which q does not carry and which an uninstalled or stale copy
101
+ // doesn't supply either.
102
+ if (!Object.hasOwn(recon, "@lab43/q")) fail();
103
+
104
+ for (const [ext, mark] of Object.entries(recon)) {
105
+ if (typeof mark !== "string") fail();
106
+ const pin = Object.hasOwn(devDeps, ext) ? devDeps[ext] : undefined;
107
+ if (typeof pin !== "string") fail(); // removed out of band, never reconciled
108
+ if (pin !== mark) fail();
109
+
110
+ const inst = installedVersion(path.join(proj, "node_modules", ext));
111
+ if (typeof inst !== "string") fail();
112
+ if (inst !== pin) fail();
113
+ }
114
+
115
+ // Reverse direction: a devDependency whose installed manifest carries the
116
+ // q-extension keyword but that has no watermark entry was installed by hand
117
+ // and never indexed. A dependency that isn't installed can't be identified as
118
+ // an extension — skip it.
119
+ for (const dep of Object.keys(devDeps)) {
120
+ if (Object.hasOwn(recon, dep)) continue;
121
+ const keywords = parse(
122
+ read(path.join(proj, "node_modules", dep, "package.json")) ?? "",
123
+ )?.keywords;
124
+ if (Array.isArray(keywords) && keywords.includes("q-extension")) fail();
125
+ }
@@ -0,0 +1,31 @@
1
+ #!/bin/bash
2
+ # SessionStart hook entry point. The checks live in session-start.mjs; this
3
+ # wrapper exists so a missing node fails loud with a useful message instead of
4
+ # a cryptic exec error. Node is a given on a project that pins q, which arrives
5
+ # as an npm dependency. The gate below keeps the checks off projects that pin no
6
+ # q at all.
7
+
8
+ proj="${CLAUDE_PROJECT_DIR:-.}"
9
+ pkg="$proj/package.json"
10
+ [ -f "$pkg" ] || exit 0
11
+ # Match "@lab43/q" in key position only. As a value it is the name of q's own
12
+ # manifest, which pins nothing. This stays a loose pre-filter: it also matches
13
+ # the key under dependencies. session-start.mjs exits silently unless the key
14
+ # is a devDependency.
15
+ grep -qE '"@lab43/q"[[:space:]]*:' "$pkg" 2>/dev/null
16
+ status=$?
17
+ # Exit only on a clean miss: the manifest was read and pins no q. Any other
18
+ # failure means the manifest could not be read, and a project that may well pin
19
+ # q must not be skipped silently — fall through and let the checks report it.
20
+ [ "$status" -eq 1 ] && exit 0
21
+
22
+ root="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
23
+
24
+ if ! command -v node >/dev/null; then
25
+ # No node means the checks can't run — same remedy as any other failure.
26
+ # Keep the message in sync with MESSAGE in session-start.mjs.
27
+ printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"The q plugin could not validate this project'"'"'s q setup, so its conventions and tooling may be stale or broken. Run /q:sync to repair it."}}\n'
28
+ exit 0
29
+ fi
30
+
31
+ CLAUDE_PROJECT_DIR="$proj" CLAUDE_PLUGIN_ROOT="$root" exec node "$root/hooks/session-start.mjs"
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@lab43/q",
3
+ "version": "0.4.0",
4
+ "description": "An agentic coding workflow framework: skills for planning, implementing, verifying, and grooming, grounded in per-project conventions docs.",
5
+ "files": ["conventions", "skills", "agents", "hooks", "references", ".claude-plugin"],
6
+ "scripts": {
7
+ "check-versions": "node scripts/check-versions.mjs"
8
+ },
9
+ "license": "MIT",
10
+ "publishConfig": { "registry": "https://registry.npmjs.org/", "access": "public" },
11
+ "author": { "name": "Cameron Spencer", "email": "cameron@lab43.com" },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/Lab43/q.git"
15
+ },
16
+ "homepage": "https://github.com/Lab43/q#readme"
17
+ }
@@ -0,0 +1,54 @@
1
+ # Agent Briefing
2
+
3
+ The shape of a project's agent briefing — `CLAUDE.md`. `/q:install` scaffolds it, `/q:update-docs` extends it, and `/q:groom-docs` checks it.
4
+
5
+ The documentation policy decides what the briefing must carry (see: q conventions/documentation.md, Taxonomy). This file gives that a shape.
6
+
7
+ ## The template
8
+
9
+ ```markdown
10
+ ## Documentation
11
+
12
+ This project follows q, an agentic coding workflow. Its rules live in the project's own documentation. Those rules are conventions: binding decisions about how this project's code and docs get written, recorded as they are made. Guides sit alongside them — how to operate the project, rather than rules for writing it.
13
+
14
+ If the session's skill list has no `/q:` skills, this machine is missing the q plugin — ask the user to install the project's dependencies (`npm install`, or the project's package manager's equivalent), then run `/q:sync`.
15
+
16
+ When another session is already working this repo, take a worktree rather than sharing the checkout.
17
+
18
+ Conventions come in three tiers: q's own, the conventions of any installed extensions, and this project's own `docs/conventions/` (source: q conventions/documentation.md, Three tiers of conventions). q and the extensions are pinned in `package.json`. Project rules win over an extension's rule, and an extension's rule wins over q's. Check all three tiers before writing code, before design decisions and reviews, and before changing docs. Doc changes — the README and this briefing itself included — go through `/q:update-docs`.
19
+
20
+ Package doc paths are package name plus path from the package root, resolved under `node_modules/`. `q` abbreviates `@lab43/q`: `q conventions/principles.md` is `node_modules/@lab43/q/conventions/principles.md` (source: q conventions/documentation.md, Package doc paths).
21
+
22
+ q:
23
+
24
+ - `q conventions/principles.md` — cross-cutting rules for any design decision, plan, or review
25
+ - `q conventions/documentation.md` — what belongs in a project's documentation, where it lives, and how it stays accurate
26
+ - `q conventions/extensions.md` — the extension format: rules for authoring and publishing a q extension
27
+ - `q conventions/plans.md` — format, sequencing, and lifecycle rules for `docs/plans/` documents
28
+ - `q conventions/issue-tracking.md` — rules for working a project's issue tracker from any session
29
+ - `q conventions/pull-requests.md` — rules for authoring a pull request
30
+ - `q conventions/writing.md` — rules for writing prose: docs, plans, PR bodies, anything a human or agent will read
31
+
32
+ Installed extensions:
33
+
34
+ - `<package> conventions/<name>.md` — one line per doc, restating its intro
35
+
36
+ This project's own:
37
+
38
+ - `docs/conventions/principles.md` — cross-cutting rules, including deviations from q's
39
+ - `docs/conventions/documentation.md` — documentation rulings and deviations
40
+
41
+ Guides:
42
+
43
+ - `docs/guides/<name>.md` — one line per guide, restating its intro
44
+ ```
45
+
46
+ ## Maintaining it
47
+
48
+ - **Write into `CLAUDE.md`**, creating it when it doesn't exist. Leave any `AGENTS.md` the project keeps for other tools alone. Linking the two is the project's call, not q's.
49
+ - **Conform to the structure**: the section heading, the groups in the order they run here, one line per doc. Name each group for what it actually holds.
50
+ - **Treat the prose as a floor, not a script.** Carry at least what the template's prose carries. Leave the project's own wording where it says the same thing. Where a statement isn't true of the project — it authors an extension rather than installing one, or loads the plugin some other way — say what is true instead.
51
+ - **Keep what the project put there** — its own standing instructions, notes, and index entries beyond the required ones. Work missing information into what is already written rather than bolting a sentence alongside it. Rewrite freely to do that, but drop nothing the project said.
52
+ - **Drop a group with no entries.** A fresh project has no extensions and no guides, so those groups arrive with the first one of each. The q group is always there.
53
+ - **Index every doc the policy requires, and nothing stale** — every conventions doc, from q, from an installed extension, or the project's own, and every guide (source: q conventions/documentation.md, Taxonomy). Drop the line for a doc that is gone, including every line of an extension the project no longer installs. The installed extensions are the direct dependencies whose own `package.json` carries the `q-extension` keyword (source: q conventions/extensions.md). An extension shipping no `conventions/` contributes no lines.
54
+ - **Write each line as a path plus a blurb restating the doc's intro** — q's docs and an extension's by package name plus path from the package root (see: q conventions/documentation.md, Package doc paths), the project's own by repo-relative path.
@@ -0,0 +1,16 @@
1
+ # Enforce Pins
2
+
3
+ The machine-local enforcement procedure: make this machine match the project's declared pins. Enforce without asking — pins are the project's recorded decisions, and this merely applies them.
4
+
5
+ 1. Check that `node` and `npm` resolve. When either is missing, Node.js is not installed — report that fix. Nothing below runs without it.
6
+ 2. When `node_modules/` is missing a pinned package, or holds a version other than its pin, run the project's package-manager install — `npm install`, or the pnpm or yarn equivalent its lockfile indicates. That install is the whole update mechanism: a session reads q from `node_modules/@lab43/q` as it stands, so nothing else has to reach it.
7
+ 3. Register the project's marketplace: `claude plugin marketplace add --scope local ./`. The manifest at the project root supplies the name, so nothing has to read or pass one. Skip this step when the project has no `.claude-plugin/marketplace.json`. The add fails outright against a directory holding no manifest. A project without one has not been scaffolded yet. Otherwise run it unconditionally, since the add changes nothing when the registry already points here. Local scope records the registration in the project's own `.claude/settings.local.json`, which does not keep it private.
8
+
9
+ Three situations need it:
10
+
11
+ - A fresh clone has never registered the marketplace.
12
+ - A declined trust prompt left it unregistered.
13
+ - Another checkout of this repo has repointed the project's name at itself. The machine-global registry holds one entry per marketplace name. The add repoints it back, because an entry whose name matches but whose path differs is updated to the new path.
14
+ 4. After any change above, run `/reload-plugins`.
15
+
16
+ Name any tracked file the enforcement rewrote (a lockfile). That change stays in the tree as the user's.
@@ -0,0 +1,31 @@
1
+ # The q State File
2
+
3
+ Format and writer rules for `.claude/q-state.json`, the consumer-side record of the versions a project was last reconciled against. The skills that read or write the file follow this doc; nothing else edits it.
4
+
5
+ ## What the file is
6
+
7
+ The file holds machine-written version watermarks — never rules, never doc enumerations. Pins stay authoritative where they are: the project's `package.json`, one exact devDependency for q and one per installed extension. Reconciliation is the work of folding a version change into the project — holding its docs against an extension release's changed rules, or its scaffolded surfaces against a new q version; `/q:update` performs it. A watermark records the version its pin was last reconciled against, so an out-of-band pin move — a hand-run npm install, a teammate's merge, a Dependabot bump — is detectable as pin ≠ watermark. The skills and the session-start hook compare its versions against the pins; nothing consults it for how to behave.
8
+
9
+ ## Format
10
+
11
+ The file lives at `.claude/q-state.json`, committed. JSON, one key per line, so a watermark move reads as a one-line diff:
12
+
13
+ ```json
14
+ {
15
+ "note": "Machine state written by q's skills. Never edit by hand; /q:sync reports drift.",
16
+ "reconciledAgainst": {
17
+ "@lab43/q": "0.3.0"
18
+ }
19
+ }
20
+ ```
21
+
22
+ `reconciledAgainst` holds one entry for `@lab43/q` and one per installed extension: the version the project was last reconciled against. q's entry has the same shape as the rest, carrying no privilege and no separate field.
23
+
24
+ ## Writer rules
25
+
26
+ - `/q:install` fills in missing watermarks and never touches present ones — a stale entry is reconciliation's to move. Bootstrapping q, it writes the `@lab43/q` entry; installing an extension, it writes that extension's. Each value is the version just installed, which has no reconciliation debt.
27
+ - `/q:update` writes the affected watermark after each reconciliation, whether the run moved a pin or caught up an out-of-band move.
28
+ - `/q:uninstall-extension` drops the extension's entry as part of reconciling its removal.
29
+ - `/q:sync` reads and compares; it never writes. Watermarks certify reconciliation, and sync never reconciles.
30
+
31
+ An absent file means no record — create it on the first watermark write. The file never ships in an extension: it lives in `.claude/`, outside the `files` whitelist a tarball is built from (source: q conventions/extensions.md).
@@ -0,0 +1,112 @@
1
+ # Run Contract
2
+
3
+ How every q skill run operates, from invocation to finish. Skills reference this contract rather than restating it.
4
+
5
+ ## Collaboration modes
6
+
7
+ A run is in one of two modes, depending on whether the user has agreed on what to do yet:
8
+
9
+ - **Conversational** — nothing agreed yet: converge with the user. Present candidates with trade-offs and a recommendation, decide at the right altitude (see: Decide at the right altitude), and proceed to execution only on the user's go-ahead. The conversation ends in an agreement — a plan doc, a confirmed scope, a converged approach.
10
+ - **Autonomous** — an agreement exists: execute it without asking. Interrupt only when the work would step outside what was agreed — a conflict discovered mid-run, an architectural fork, scope the agreement doesn't cover. Small calls inside the agreement stay autonomous: choose what is most consistent with the agreement, the conventions, and the surrounding code, and flag the calls a reviewer would question where the output gets reviewed: the PR body (see: q conventions/pull-requests.md), or the end-of-run report when the run delivers no PR. When the agreement is exhausted or must be reopened, the run is conversational again.
11
+
12
+ ## Review modes
13
+
14
+ Work that will become commits runs in one of two review modes, settled up front — with the run's opening questions, or at the go-ahead that enters autonomous mode. Once settled it is never revisited mid-run: a ship run reaches its PR without stopping again, so the user comes back to a PR waiting, not a prompt asking whether to open one.
15
+
16
+ - **Local** — nothing is committed unreviewed: work pauses uncommitted at each review point the running skill defines, and the user's approval is what commits it.
17
+ - **Ship** — commit as the running skill's own procedure calls for, without asking, and push when the work is done; the user reviews on GitHub, so finish by directing them to the PR(s). The grant ends at the PR: merging is the user's.
18
+
19
+ ## The delivery branch
20
+
21
+ Settle the branch before changing anything: work built on one branch and delivered against another invites conflicts. Uncommitted changes the run does not own are the user's call: ask what to do with them before starting. Never mix them into the run's work. Two things then settle the branch — whether another session is working this repo, and which branch the work belongs on.
22
+
23
+ **Is a peer working this repo?** `ListAgents` supplies the candidates: take only its rows for other local sessions, because the rest are this session's own subagents and sessions running elsewhere. No row records a repo, so a row is a candidate and never a peer on its own. Read the repo for what it shows:
24
+
25
+ - `git worktree list` names the worktrees peers took. A worktree outlives the session that made it, so one is evidence of a peer only while a candidate is live: with no candidates listed, it is leftovers.
26
+ - A candidate that has announced this repo is a peer outright.
27
+ - Uncommitted work this run does not own settles nothing by itself: it is as likely the user's as a peer's. Ask the live candidates whether the work is theirs, because ownership is the one thing looking cannot establish. Ask the user when no candidate claims it.
28
+
29
+ Where the evidence leaves the call open, ask the user. A listing that reports itself incomplete leaves it open.
30
+
31
+ **Found a peer? Take a worktree.** `git fetch origin` first: everything below reads the local remote-tracking refs, which are only as current as the last fetch. Nothing uncommitted follows the session into it, so commit or copy across whatever the run already owns — the plan or doc it was invoked on included. How the worktree is made then depends on whether the run's branch exists yet.
32
+
33
+ **A branch the run is creating.** `EnterWorktree` makes the worktree and switches the session into it. It arrives on its own new branch, off the default branch under the `worktree.baseRef` default. That branch is this run's: rename it to what the run would have called its branch (`git branch -m <name>`) rather than creating a second one.
34
+
35
+ **A branch that already exists.** The PR's branch, or a pushed branch the run continues. Never let `EnterWorktree` create the branch here. Its new branch sits at the default branch's tip with no upstream. Renaming that onto the existing name fails outright when the branch is already local, and builds the work on the wrong base when it exists only on the remote. Make the worktree on the branch itself with `git worktree add .claude/worktrees/<worktree-name> <branch>`, then hand `EnterWorktree` that path. A branch that exists only on the remote takes the same command, which creates the local branch from it and sets up tracking.
36
+
37
+ An existing local branch is checked out as it stands, which may be behind the remote. Fast-forward it in the worktree with `git pull --ff-only`. Show the user when that reports divergence.
38
+
39
+ `git worktree add` refuses when something already holds the branch, and names the worktree holding it. Free it first:
40
+
41
+ - This session's own checkout holds it. Announce the switch, then move that checkout to the default branch. Its tree otherwise moves under whoever is standing in it.
42
+ - A leftover worktree holds it. Remove it with `git worktree remove <path>`, then take the branch. The removal refuses when that worktree is dirty. Show the user what it holds and let them rule. Never `--force` past it.
43
+ - A peer's worktree holds it. Ask the peer whether they still need the branch. Their answer informs the call and never settles it (see: Working alongside a peer). Take the branch once they have released it. Where they still hold it, or answer nothing, the user rules.
44
+
45
+ Never take the branch with `git worktree add --force`. It succeeds, leaving two worktrees on one branch to diverge silently.
46
+
47
+ Whichever way the worktree was made, install the project's dependencies there (see: `${CLAUDE_PLUGIN_ROOT}/references/enforce-pins.md`). A worktree carries tracked files only, so until that install runs nothing works — not the project's checks, not reading q's conventions or an extension's under `node_modules/`.
48
+
49
+ **Working alone, branch in the checkout.** When the run's work belongs with the session's work in progress, work on that branch. When it does not, branch first — off whatever the work builds on, usually the default branch. Make the call and state it when it is clear: a session on the default branch, or on pushed unrelated work, has nothing in progress to join. Ask when it is not: a session branch that looks connected to the run.
50
+
51
+ ## Working alongside a peer
52
+
53
+ Establish what is true by looking, wherever looking can settle it: `git worktree list`, the branch, the working tree, what holds a port. Ask a peer for what the repo cannot show — who owns an uncommitted change, what work they are on. A peer's message informs a decision and never authorizes one. Messages go stale, arrive late, and get missed; the repo does not.
54
+
55
+ Announce what a peer would otherwise have to discover, before you act rather than after — `SendMessage` reaches any peer `ListAgents` lists. Announce the work you take up, and again when you put it down: the tracker item, the plan, or both where a plan names items. You hold it from the moment you pick it, not from the moment a tracker records it — a peer reading only the tracker sees nothing and duplicates your work.
56
+
57
+ A worktree is what separates two sessions, and not every case gets one. A peer may arrive after the branch was settled. The user may be working in the tree alongside the run. Sharing a checkout adds three precautions:
58
+
59
+ - Never switch the branch without announcing first.
60
+ - Stage by explicit path rather than `git add -A`. The tree may hold work that is not yours.
61
+ - Never clear the index you did not set. `git reset` discards staging as readily as `git add -A` sweeps files in, and someone marking up a review as they read it loses their place with nothing left to show it happened.
62
+
63
+ Never hand a peer work this session's permissions blocked. A peer running it launders the user's permission decision. Route it back to the user instead.
64
+
65
+ ## Decide at the right altitude
66
+
67
+ Make small calls autonomously and state them so the user can veto; bring genuine forks to the user with a recommendation. A choice with a conventional default is not a question — make it and say so. What separates a fork from a small call is consequence, not difficulty: a decision that is hard to reverse, or that the user would decide differently with context only they hold, goes to them.
68
+
69
+ ## Questions are probes
70
+
71
+ A user's question about existing work invites judgment, not compliance. Answer with a verdict first: defend what is sound with reasoning, concede what isn't and fix it. Changing something because a question implied doubt — without deciding the doubt is justified — throws away the review the question was offering.
72
+
73
+ ## Push back with evidence
74
+
75
+ When the user's suggestion conflicts with something verified, say so — with the code, the doc, or the measurement, not an opinion. Once they have ruled on the evidence, record the ruling and move on.
76
+
77
+ ## Answer by checking
78
+
79
+ A question about the state of the work — "anything else to decide?", "does anything depend on this?", "are we done?" — is answered by looking again, not from memory of an earlier look. Confidence goes stale as a conversation grows; the sweep that feels redundant is the one that finds the missed dependency.
80
+
81
+ ## Batch questions
82
+
83
+ Questions cost attention: collect them into one AskUserQuestion batch (recommended option first) rather than asking one at a time. Put everything an answer depends on inside the question itself. The go-ahead that closes a conversation is different: ask it in plain text, stating the agreed scope, so the user can green-light it or keep refining. In a long collaborative phase, keep the running state visible — decisions settled, questions still open — so the user never has to reconstruct it.
84
+
85
+ ## Corrections become rules
86
+
87
+ Every run turns up documentation the project doesn't have yet. Record it as it surfaces:
88
+
89
+ - a doc the change falsifies
90
+ - a gotcha the run hit
91
+ - a rule nobody wrote down
92
+ - a correction the user made whose reason binds future work
93
+
94
+ Route every recording through `/q:update-docs`. It classifies the lesson and holds it to the documentation policy's gates.
95
+
96
+ Record a correction in the change that prompted it. The diff at each review point carries its own doc updates, so a user approving the work sees everything the run proposes. A correction that arrives during review joins that iteration. Never defer one to the closing report, and never leave the user trusting that a doc update will follow.
97
+
98
+ A correction lands in whatever change was in flight, which is often a change whose stated scope does not cover it. Say so where the work is reviewed: the PR body's Callouts, or the closing report when the run delivers no PR (see: q conventions/pull-requests.md, Sections). A reviewer who meets an unexplained edit to standing law reads it as scope creep.
99
+
100
+ Amendments to existing rules are corrections too. Apply them rather than recommending them. A recommendation the user has to find in the output gets scanned past, while a diff hunk is something they can read and push back on. Raise an amendment instead of applying it when it would put existing code out of conformance: that is a migration, and its scope is the user's.
101
+
102
+ ## Validation
103
+
104
+ Execution closes by validating the run's product before anything is delivered. Run the project's checks covering what changed. Then launch two `adversarial-reviewer` subagents in parallel over the change, one per lens, handing each the agreed scope and the artifact the skill names. The scope is what the user agreed the work would deliver, restated from the run's current state. It is never a list of the changes made: details the user has since overruled resurface as false findings.
105
+
106
+ Wait for every reviewer in the round to report before changing anything. Editing the tree under a running review invalidates the diff that review was handed. Then fix the BLOCKING findings, applying judgment on nits. Re-run the checks covering the fixes. Review again — fixes are always re-reviewed, with the same reviewers by default. A round whose fixes were few and small may hand the next round to one reviewer carrying both lenses. In ship mode, commit each round. Loop at most three times. The loop exits when no reviewer reports a BLOCKING finding, and findings that survive the cap are reported as caveats.
107
+
108
+ ## The local gate
109
+
110
+ The procedure local review runs at each review point the skill defines. Stop and ask the user to review the uncommitted work: the diff, its check results, and anything else they should weigh. Expect change requests. Make them and iterate with the user, running no machinery per exchange. A change request whose reason binds future work is a correction (see: Corrections become rules).
111
+
112
+ At their go-ahead, commit exactly what they reviewed — onto the work's branch, unless the skill names another target. Then run the checks covering what the session changed. When the gate's iteration substantially changed the work, run one `adversarial-reviewer` pass (both lenses) over what changed. Never fold the resulting fixes into the reviewed commit. Leave them uncommitted and return to the gate, where the user reviews them as their own diff. Repeat until a go-ahead leaves nothing uncommitted.
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: address-feedback
3
+ description: Work feedback on an open pull request — the reviewer's comments, questions, and requested changes. Invoke it with a PR number or URL. Given nothing, it resolves the PR for the current branch. Invoke it on a PR carrying no comments too, when the user has revisions of their own. The user rules on every item before anything changes. Agreed fixes are implemented, adversarially reviewed, and delivered to the PR under the review mode the user picks. Replies are posted back on the PR only when the user wants them.
4
+ ---
5
+
6
+ # Address Feedback
7
+
8
+ ## Ground rules
9
+
10
+ - **Follow the run contract** — `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`.
11
+ - **Feedback is not a work order**: every item opens a discussion, the ones phrased as directives included. Never implement feedback you believe is wrong. Answer every question the feedback asks. A code change never stands in place of that answer (source: `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`, Questions are probes).
12
+ - **The PR under review is the boundary**: the round's fixes land on its branch as new commits. Never rebase that branch and never force-push over it — the reviewer's inline comments anchor to the commits they read, and rewriting the history strands them. Never open a second PR. Work the feedback opens that this PR can't hold goes to a plan or the tracker instead.
13
+ - **Track resolutions**: keep a scratchpad note of each item — where it came from, its agreed disposition, and how it resolved. It feeds the replies and the closing report.
14
+ - **Context hygiene**: use subagents (Explore for recon, background Bash for checks, `adversarial-reviewer` for review) to keep large output out of the main context.
15
+
16
+ ## Step 1: Gather the feedback
17
+
18
+ 1. Resolve the PR from the invocation — a number or a URL. Given nothing, run `gh pr view` for the current branch. Ask which PR to work when that branch has none. Stop and tell the user when the PR is already closed or merged.
19
+ 2. Require a clean working tree first — if anything is uncommitted, stop and show the user. Uncommitted work carried onto the PR's branch by a checkout lands in someone else's review.
20
+ 3. Work on the PR's own branch, never a new one (see: `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`, The delivery branch). Check it out and fast-forward it:
21
+
22
+ ```bash
23
+ git fetch origin && git checkout <head-branch> && git pull --ff-only
24
+ ```
25
+
26
+ Stop and show the user when the local branch has diverged from the PR's.
27
+ 4. Fetch everything the reviewer wrote:
28
+ - `gh pr view <n> --comments` — the top-level comments, plus each review's summary and verdict.
29
+ - the inline threads, which GitHub groups and tracks resolution for:
30
+
31
+ ```bash
32
+ gh api graphql -f query='{repository(owner:"<owner>",name:"<repo>"){pullRequest(number:<n>){reviewThreads(first:100){nodes{isResolved isOutdated path line comments(first:50){nodes{databaseId author{login} body}}}}}}}'
33
+ ```
34
+
35
+ Skip every thread `isResolved` reports closed — the reviewer ended those. An `isOutdated` thread is still live: it anchors to a line that later commits moved. Skip a thread whose last comment already answers the one before it. An earlier round settled that item, and the reviewer has not written back.
36
+ 5. Ignore every comment that raises nothing to settle. A callout explaining the change under review is the common case (see: q conventions/pull-requests.md, Diff comments).
37
+ 6. Gather the user's own feedback. The invocation may carry it. Ask the user what they want changed whenever the PR carries no feedback of its own.
38
+ 7. Build the agenda from everything gathered — one item per inline thread, top-level comment, or review summary that carries feedback, plus one per point the user raised. Merge items that share a root cause or answer each other. Record where each item came from, because that decides how it gets answered. Post the agenda — each item's gist in one line, in the order you propose to take them. No positions yet, and no edits.
39
+
40
+ ## Step 2: Take a position on each item
41
+
42
+ Establish ground truth before forming a position:
43
+
44
+ - the code the item points at, and its history
45
+ - the conventions governing that territory, found from the agent briefing's docs index
46
+ - the primary source, wherever the item turns on how a dependency or tool behaves — the library's own code, its documentation, its upstream issues
47
+
48
+ Never agree or push back from memory of an external fact (package versions, library APIs, option names, tool behavior). Run the check whenever running one can settle the question.
49
+
50
+ Feedback invites judgment, not compliance (see: `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`, Questions are probes). Where the evidence contradicts it, say so with the evidence (see: `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`, Push back with evidence). Where investigating exposes the questioned code as genuinely weak, say that rather than defending it.
51
+
52
+ Give each item one disposition:
53
+
54
+ - **Answer** — the item asks a question that evidence answers. Nothing changes.
55
+ - **Push back** — the item is wrong, or the change it asks for is worse than what stands. Name what you would do instead, including nothing.
56
+ - **Fix** — the item is right. Name the change.
57
+ - **Beyond this PR** — the item calls for a redesign, or for more change than this PR can hold.
58
+
59
+ ## Step 3: Agree
60
+
61
+ Settle the round with the user, in conversational mode (see: `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`, Collaboration modes).
62
+
63
+ Post every item's disposition with its evidence. Most carry no question:
64
+
65
+ - an obvious fix
66
+ - an answer the evidence settles
67
+ - a push-back the code proves
68
+
69
+ State those for the user to veto rather than asking them (see: `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`, Decide at the right altitude).
70
+
71
+ Ask one batch, carrying only what the user has to rule on:
72
+
73
+ - the fork a disposition turns on, wherever an item has materially different resolutions, each with a recommendation
74
+ - whether each resolution is posted back where the feedback was written, asked once for the round. Skip it when nothing was written on the PR.
75
+ - the review mode (see: `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`, Review modes). In this run, ship covers commit and push to the PR. Local commits nothing until the user has reviewed the diff.
76
+
77
+ Answers settle decisions. They are not the agreement. Close the conversation by summarizing the agreed scope and asking for the go-ahead. That green light, not the last answer, is what makes the rest of the run autonomous.
78
+
79
+ An item beyond this PR is not resolved here. Settle the rest of the round, and take it to `/q:create-plan` or to the tracker on the user's call.
80
+
81
+ ## Step 4: Implement
82
+
83
+ 1. Record the branch's head SHA before changing anything: `git rev-parse HEAD`. It is the branch as this round found it, and Step 5 reviews the round against it.
84
+ 2. Implement each agreed fix, following the governing conventions and matching surrounding code.
85
+ 3. Verify: run the project's checks — lint, typecheck, and the tests covering what changed, as the project's briefing, conventions, or scripts name them (parallel background subagents are fine). When a fix changed a drivable surface — an endpoint, a screen — drive it through `/q:drive`, naming that surface as what to exercise.
86
+ 4. In ship mode, commit — before review, so the review history is inspectable in git.
87
+
88
+ When the agreed fixes turn out to need a redesign, or more change than this PR can hold, interrupt. Present the discovery and recommend `/q:create-plan` or a tracker item. Neither starts without the user's go-ahead.
89
+
90
+ ## Step 5: Adversarial review
91
+
92
+ Validate the round (see: `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`, Validation) with the **correctness** and **conventions** lenses. The round is the product, so its diff runs from Step 4's recorded SHA: `git diff <recorded-sha>...HEAD` in ship mode, or the uncommitted diff plus the changed-file list in local review. Hand the reviewers the agreed dispositions as the scope. Per loop round, re-drive a surface only when a fix could change what driving showed.
93
+
94
+ ## Step 6: Deliver to the PR
95
+
96
+ 1. **Local review's gate**: run the gate over the session's uncommitted work (see: `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`, The local gate).
97
+ 2. **Push**: `git push origin HEAD`.
98
+ 3. **Bring the PR body up to date** wherever the round changed what it claims, the findings that survived Step 5 included (see: q conventions/pull-requests.md).
99
+ 4. **Reply**, when replying was agreed: post each item's resolution where the feedback was written. Skip an item the user raised in session. It has no thread to answer. Give the reviewer what they need to understand it — the answer, the evidence behind a push-back, or the reason a fix took the shape it did. Sign each reply (source: q conventions/writing.md, Sign what you post). Write each reply to a file and pass it by path, so apostrophes in the prose can't break the command. Reply to an inline thread at its first comment's `databaseId`:
100
+
101
+ ```bash
102
+ gh api --method POST repos/<owner>/<repo>/pulls/<n>/comments/<comment-id>/replies -F body=@<reply-file>
103
+ ```
104
+
105
+ Answer a top-level comment or a review summary with `gh pr comment <n> --body-file <reply-file>`. Never mark a thread resolved — that is the reviewer's call.
106
+ 5. Close the session by reporting each item's resolution, any caveats, any amendment raised instead of applied, and any follow-up work — filed in the tracker on the user's agreement (source: q conventions/issue-tracking.md, Ask before filing).