@lab43/q 0.4.0 → 0.6.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.
- package/README.md +80 -50
- package/package.json +21 -4
- package/{.claude-plugin → q-extension/.claude-plugin}/plugin.json +1 -1
- package/q-extension/agents/adversarial-reviewer.md +98 -0
- package/q-extension/conventions/conventions.md +49 -0
- package/q-extension/conventions/documentation.md +79 -0
- package/q-extension/conventions/extensions.md +70 -0
- package/q-extension/conventions/issue-tracking.md +56 -0
- package/{conventions → q-extension/conventions}/plans.md +7 -3
- package/{conventions → q-extension/conventions}/principles.md +4 -2
- package/{conventions → q-extension/conventions}/pull-requests.md +2 -2
- package/q-extension/conventions/specs.md +31 -0
- package/{conventions → q-extension/conventions}/writing.md +8 -0
- package/q-extension/hooks/locked-version.mjs +169 -0
- package/q-extension/hooks/session-start.mjs +155 -0
- package/{hooks → q-extension/hooks}/session-start.sh +9 -8
- package/q-extension/references/agent-briefing.md +66 -0
- package/q-extension/references/enforce-declarations.md +16 -0
- package/q-extension/references/q-state.md +31 -0
- package/{references → q-extension/references}/run-contract.md +18 -10
- package/{skills → q-extension/skills}/address-feedback/SKILL.md +19 -15
- package/q-extension/skills/clean-worktrees/SKILL.md +66 -0
- package/{skills → q-extension/skills}/create-plan/SKILL.md +5 -5
- package/{skills → q-extension/skills}/drive/SKILL.md +1 -1
- package/q-extension/skills/groom-docs/SKILL.md +65 -0
- package/{skills/tackle → q-extension/skills/implement}/SKILL.md +14 -14
- package/{skills → q-extension/skills}/implement-plan/SKILL.md +14 -14
- package/q-extension/skills/install/SKILL.md +136 -0
- package/{skills → q-extension/skills}/parallelize/SKILL.md +5 -5
- package/q-extension/skills/reconcile/SKILL.md +110 -0
- package/{skills → q-extension/skills}/review/SKILL.md +5 -4
- package/{skills → q-extension/skills}/triage/SKILL.md +11 -11
- package/{skills → q-extension/skills}/update-docs/SKILL.md +22 -17
- package/{skills → q-extension/skills}/upstream/SKILL.md +10 -8
- package/.claude-plugin/marketplace.json +0 -6
- package/agents/adversarial-reviewer.md +0 -62
- package/conventions/documentation.md +0 -99
- package/conventions/extensions.md +0 -48
- package/conventions/issue-tracking.md +0 -19
- package/hooks/session-start.mjs +0 -125
- package/references/agent-briefing.md +0 -54
- package/references/enforce-pins.md +0 -16
- package/references/q-state.md +0 -31
- package/skills/groom-docs/SKILL.md +0 -62
- package/skills/install/SKILL.md +0 -150
- package/skills/sync/SKILL.md +0 -45
- package/skills/uninstall-extension/SKILL.md +0 -52
- package/skills/update/SKILL.md +0 -75
- /package/{hooks → q-extension/hooks}/hooks.json +0 -0
|
@@ -12,30 +12,30 @@ Given no plan, list the `pending` plans in `docs/plans/` and ask which one.
|
|
|
12
12
|
- **Follow the run contract** — `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`.
|
|
13
13
|
- **Track resolutions**: keep a scratchpad note of each review round's BLOCKING findings and how each was resolved (fixed / rejected with reason) — it feeds the PR's Callouts and Caveats, stated as facts about the change.
|
|
14
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
|
-
- **Plan doc amendments**: when execution deviates from the plan or a verification step contradicts it, fold the outcome into the plan doc as a marked amendment per the lifecycle rules (see: q conventions/plans.md, Lifecycle), alongside the work of the phase that surfaced it.
|
|
15
|
+
- **Plan doc amendments**: when execution deviates from the plan or a verification step contradicts it, fold the outcome into the plan doc as a marked amendment per the lifecycle rules (see: @lab43/q conventions/plans.md, Lifecycle), alongside the work of the phase that surfaced it.
|
|
16
16
|
- **Doc updates**: make the doc changes the plan schedules through `/q:update-docs`, alongside the phase that carries them.
|
|
17
17
|
|
|
18
18
|
## Step 1: Understand
|
|
19
19
|
|
|
20
20
|
1. Read the plan in full.
|
|
21
21
|
2. Announce the plan, and the items its `tracks` frontmatter names, before going further (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Working alongside a peer). Release them if the run ends without delivering.
|
|
22
|
-
3. Read the conventions governing the plan's territory, found from the agent briefing's docs index.
|
|
22
|
+
3. Read the conventions and specs governing the plan's territory, found from the agent briefing's docs index.
|
|
23
23
|
4. Explore the affected code — use an Explore subagent for broad reconnaissance.
|
|
24
24
|
5. Plans can predate refactors: check every plan step against the current codebase and note steps that are already done, obsolete, or in conflict with current structure.
|
|
25
25
|
6. The plan's external facts were verified at planning time. If the plan has aged — the dependency manifests, lockfile, or files the plan cites changed since the doc was last written (its last commit, or mtime if uncommitted) — re-verify the load-bearing ones before building on them; a plan executed fresh skips this.
|
|
26
26
|
|
|
27
27
|
## Step 2: Clarify
|
|
28
28
|
|
|
29
|
-
Clarify the plan with the user, in conversational mode (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Collaboration modes) — everything asked here is a question the
|
|
29
|
+
Clarify the plan with the user, in conversational mode (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Collaboration modes) — everything asked here is a question the run won't have to stop for once it is autonomous. One batch, via AskUserQuestion:
|
|
30
30
|
|
|
31
|
-
- The ambiguities, plan/codebase conflicts,
|
|
31
|
+
- The ambiguities, plan/codebase conflicts, scope questions, and any spec the plan's work contradicts without scheduling the amendment, as Step 1 surfaced them — when none need the user's attention, state your working assumptions instead. If consequential questions keep accumulating, the plan is underspecified — say so and suggest revising it with `/q:create-plan` before implementing.
|
|
32
32
|
- The review mode, always asked (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Review modes): in this run, ship covers every commit (a stacked run's `gh stack` operations included), push, and PR; local commits nothing until the user has reviewed it, each PR's content at that PR's boundary.
|
|
33
33
|
|
|
34
34
|
What emerges completes the agreement: the plan, as clarified, authorizes the rest of the run as autonomous.
|
|
35
35
|
|
|
36
36
|
## Step 3: Branch
|
|
37
37
|
|
|
38
|
-
Settle the branch (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The delivery branch). A plan is its own delivery unit, so the call is fresh branching. Require a clean working tree first, the plan doc itself excepted — it may be untracked or modified. Stop and ask the user what to do with anything else. Branch per the plan's `delivery` frontmatter (absent means single-PR). A single-PR run skips the command below when the contract's peer check already put it on a worktree's branch; a stacked run's `gh stack init` adopts that branch or creates its first layer:
|
|
38
|
+
Settle the branch (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The delivery branch). A plan is its own delivery unit, so the call is fresh branching. Require a clean working tree first, the plan doc itself excepted — it may be untracked or modified. Stop and ask the user what to do with anything else. Branch per the plan's `delivery` frontmatter (absent means single-PR). `<plan-name>` below is the plan's filename without its date prefix (source: @lab43/q conventions/plans.md, Filename). A single-PR run skips the command below when the contract's peer check already put it on a worktree's branch; a stacked run's `gh stack init` adopts that branch or creates its first layer:
|
|
39
39
|
|
|
40
40
|
**Single PR:**
|
|
41
41
|
|
|
@@ -55,7 +55,7 @@ gh stack init <plan-name>/01-<group-slug> --base <default-branch>
|
|
|
55
55
|
|
|
56
56
|
Either way, in ship mode record the group-start SHA (`git rev-parse HEAD`) as soon as the branch exists, before anything commits to it. It scopes this PR's final review in Step 5. Each later group records its own when its branch opens in Step 4.
|
|
57
57
|
|
|
58
|
-
A plan doc not yet in merged history — new, or changed since it merged — becomes the run's first commit, at the bottom of the stack in a stacked run — exactly as planning left it. Material Step 2 clarification answers are folded in as a second commit on top, so the diff between the two records what clarification changed.
|
|
58
|
+
A plan doc not yet in merged history — new, or changed since it merged — becomes the run's first commit, at the bottom of the stack in a stacked run — exactly as planning left it. Material Step 2 clarification answers are folded in as a second commit on top, so the diff between the two records what clarification changed. Both commits land in local mode too. The plan as planning left it is already the user's reviewed work, so committing it holds back nothing local mode protects, and every amendment the run adds then shows as a diff against it.
|
|
59
59
|
|
|
60
60
|
## Step 4: Implement in phases
|
|
61
61
|
|
|
@@ -63,7 +63,7 @@ In a stacked run, this step and Step 5 alternate: implement a group's phases her
|
|
|
63
63
|
|
|
64
64
|
Derive phases from the plan's Phases section — a boundary problem visible up front was Step 2's to settle and fold in. The plan's breakdown is not yours to redesign; when implementation reveals a phase that can't stand alone as a commit that builds and passes its tests, merge or split at that seam and record the change as a plan amendment.
|
|
65
65
|
|
|
66
|
-
In local
|
|
66
|
+
In local mode, commits wait for the user's review at each PR boundary (Step 5): phases accumulate uncommitted, and a phase's adversarial review takes the uncommitted diff plus the phase's file list.
|
|
67
67
|
|
|
68
68
|
Then work phase by phase. In a stacked run, a phase that starts a new PR group first opens the group's branch — `gh stack add <plan-name>/<NN>-<group-slug>`, the first group using Step 3's branch — so the group's phases commit to their own branch. A new group records its group-start SHA as Step 3 describes.
|
|
69
69
|
|
|
@@ -74,18 +74,18 @@ For each phase:
|
|
|
74
74
|
1. **Implement** the phase's steps, following the governing conventions and matching surrounding code.
|
|
75
75
|
2. **Verify**: run the project's checks — lint, typecheck, and the tests covering what the phase touched, as the project's briefing, conventions, or scripts name them (parallel background subagents are fine). When the phase produced a newly drivable surface — an endpoint, a screen — drive it through `/q:drive`, naming that surface as what to exercise. This is a cheap incremental check so later phases don't build on something broken, not the full verification pass; fix what it catches before moving on.
|
|
76
76
|
3. **Commit the implementation**, in ship mode, before review — so the review history is inspectable in git.
|
|
77
|
-
4. **Adversarial review**: launch a single `adversarial-reviewer` subagent over the phase's diff with **both lenses** (correctness + conventions). Give it: the plan path, the full derived phase breakdown (which plan steps are in this phase, which came earlier, which are deferred), and the diff scope — `git diff <phase-start-sha>..HEAD` in ship mode; the uncommitted diff plus the phase's file list in local
|
|
77
|
+
4. **Adversarial review**: launch a single `adversarial-reviewer` subagent over the phase's diff with **both lenses** (correctness + conventions). Give it: the plan path, the full derived phase breakdown (which plan steps are in this phase, which came earlier, which are deferred), and the diff scope — `git diff <phase-start-sha>..HEAD` in ship mode; the uncommitted diff plus the phase's file list in local mode. The lenses and those inputs are the whole prompt (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Validation). One review per phase — there is no per-phase re-review loop; the PR's final review (Step 5) is the backstop that verifies the fixes.
|
|
78
78
|
5. **Fix**: fix all BLOCKING findings (apply your judgment on NITS), re-run the checks covering the fixed code — re-driving the phase's surface only when a fix could change what driving showed — and, in ship mode, commit the fixes. A review with no accepted findings gets no commit.
|
|
79
79
|
|
|
80
80
|
## Step 5: Wrap up each PR
|
|
81
81
|
|
|
82
82
|
When a group's last phase lands, finish that PR before starting the next group:
|
|
83
83
|
|
|
84
|
-
1. **Verify its work in the running product**: drive what the PR delivers through `/q:drive`, naming the flows to exercise. Derive the scope from the group's content — a judgment that can land on nothing at all, when Step 4's checks fully characterize the work. The final PR is the exception. Drive the plan's Verification section: the integrated state exists now, and its end-to-end proof belongs ahead of this last review. Run the project's full test suite too — the run's only unscoped check. Fix what verification catches and re-verify. In ship mode, commit what this step produced: the fixes, plus anything driving recorded. Record for the PR's Testing section what was exercised and what it demonstrated. The standing suite goes unlisted (source: q conventions/pull-requests.md, Sections).
|
|
85
|
-
2. **Final review**: validate the PR's diff (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Validation) with the **correctness** and **conventions** lenses. Hand the reviewers the plan path, which plan steps this PR delivers (and that the rest live in other PRs), and the diff scope — `git diff <group-start-sha>..HEAD` in ship mode; the uncommitted diff plus the group's file list (every file its phases touched) in local
|
|
86
|
-
3. **
|
|
87
|
-
4. **Mark the plan completed** — last or only PR: set `status: completed` in the plan doc's frontmatter and commit it (in a stacked run the lower PRs still show `pending`; the flip lands when the whole stack merges). In local
|
|
88
|
-
5. **Open the PR**, so the user can start reviewing while later groups build. Author every PR's title and body per the PR-authoring rules (see: q conventions/pull-requests.md).
|
|
84
|
+
1. **Verify its work in the running product**: drive what the PR delivers through `/q:drive`, naming the flows to exercise. Derive the scope from the group's content — a judgment that can land on nothing at all, when Step 4's checks fully characterize the work. The final PR is the exception. Drive the plan's Verification section: the integrated state exists now, and its end-to-end proof belongs ahead of this last review. Run the project's full test suite too — the run's only unscoped check. Fix what verification catches and re-verify. In ship mode, commit what this step produced: the fixes, plus anything driving recorded. Record for the PR's Testing section what was exercised and what it demonstrated. The standing suite goes unlisted (source: @lab43/q conventions/pull-requests.md, Sections).
|
|
85
|
+
2. **Final review**: validate the PR's diff (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Validation) with the **correctness** and **conventions** lenses. Hand the reviewers the plan path, which plan steps this PR delivers (and that the rest live in other PRs), and the diff scope — `git diff <group-start-sha>..HEAD` in ship mode; the uncommitted diff plus the group's file list (every file its phases touched) in local mode. Per loop round, re-drive a flow from item 1 only when a fix could change what driving showed. Surviving findings become Caveats in the PR description.
|
|
86
|
+
3. **The local gate**: run it over the PR's uncommitted diff (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The local gate); commits land onto the PR's layer.
|
|
87
|
+
4. **Mark the plan completed** — last or only PR: set `status: completed` in the plan doc's frontmatter and commit it (in a stacked run the lower PRs still show `pending`; the flip lands when the whole stack merges). In local mode this flip rides the go-ahead just given. That is a deliberate exception to the gate: the go-ahead already covers this bookkeeping. Don't ask again.
|
|
88
|
+
5. **Open the PR**, so the user can start reviewing while later groups build. Author every PR's title and body per the PR-authoring rules (see: @lab43/q conventions/pull-requests.md).
|
|
89
89
|
|
|
90
90
|
Single PR: `git push -u origin <plan-name>`, then `gh pr create`.
|
|
91
91
|
|
|
@@ -96,4 +96,4 @@ When a group's last phase lands, finish that PR before starting the next group:
|
|
|
96
96
|
|
|
97
97
|
Reached once a run: after the only PR, or after the stack's last. Every earlier group returns to Step 4 instead.
|
|
98
98
|
|
|
99
|
-
Close the session by reporting the PR URL(s), the phase list, 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).
|
|
99
|
+
Close the session by reporting the PR URL(s), the phase list, any caveats, any amendment raised instead of applied, and any follow-up work — filed in the tracker on the user's agreement (source: @lab43/q conventions/issue-tracking.md, Ask before filing).
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: install
|
|
3
|
+
description: Set up q in a project the developer has already npm-installed it into, or repair a scaffold that has drifted. Invoke bare. Safe to re-run on a partially set-up project. An extension's arrival is /q:reconcile's. The changes ship as a PR.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Install
|
|
7
|
+
|
|
8
|
+
The scaffold is deliberately near-empty — this skill creates the structure the other skills expect, not content.
|
|
9
|
+
|
|
10
|
+
Follow the run contract — `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`. Scaffolding brings q's surfaces to the forms in Step 3: create what is absent, correct what has drifted. Any run therefore completes a partially set-up project. Never rewrite what the user owns — each item below marks its own boundary.
|
|
11
|
+
|
|
12
|
+
## Step 1: Survey current state
|
|
13
|
+
|
|
14
|
+
Hold the project against each of Step 3's scaffold items, noting what is absent and what has drifted from its form. Alongside, check:
|
|
15
|
+
|
|
16
|
+
- Convention-like docs living elsewhere — a `docs/` scan for rule-carrying files, a briefing bloated with per-task rules
|
|
17
|
+
- Content already in `docs/conventions/` that has drifted from the documentation policy
|
|
18
|
+
- Whether an earlier run's scaffold sits uncommitted in the working tree
|
|
19
|
+
- The GitHub CLI: `gh auth status`, and that the repo's `origin` is GitHub-hosted (`gh repo view` succeeds). q's workflow skills require both. If either fails, tell the user the fix (install via <https://cli.github.com> and authenticate with `gh auth login`; `gh repo view` failing with an authenticated CLI means `origin` is not GitHub-hosted) and continue — the scaffold still lands.
|
|
20
|
+
|
|
21
|
+
## Step 2: Settle delivery
|
|
22
|
+
|
|
23
|
+
Skip this step in any of these cases:
|
|
24
|
+
|
|
25
|
+
- A run where Step 1 found nothing missing or drifted, and no scaffold sitting uncommitted from an earlier run — there is nothing to change or deliver. An unpopulated `node_modules/` is machine state rather than drift: a fresh clone nobody has installed on. Enforce the declarations per `${CLAUDE_PLUGIN_ROOT}/references/enforce-declarations.md`, which populates it, then stop with the closing report (Step 5).
|
|
26
|
+
- Step 1 found no `@lab43/q` in `devDependencies` in the repo root's `package.json` — q's bytes have not arrived, and nothing scaffolds without them. Report the bootstrap for the developer to run — `npm install --save-dev --save-exact --ignore-scripts @lab43/q`, or their package manager's equivalent — and stop with the closing report (Step 5): this skill runs no package manager against a named package.
|
|
27
|
+
- Step 1's GitHub CLI check failed — there is no delivery to settle.
|
|
28
|
+
- Another skill's run invoked this one — the changes join that run's change.
|
|
29
|
+
|
|
30
|
+
Otherwise ask which review mode — local or ship — the run delivers under (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Review modes). Then pick the delivery branch (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The delivery branch).
|
|
31
|
+
|
|
32
|
+
## Step 3: Scaffold
|
|
33
|
+
|
|
34
|
+
The invocation is the agreement — scaffold autonomously; on a fully set-up, undrifted project the whole step is a no-op:
|
|
35
|
+
|
|
36
|
+
1. **The two mirror docs** — create each if missing, with exactly this content; if present, leave it untouched. A seeded doc is the user's from creation, intro and entries alike — never corrected on a re-run. `docs/conventions/principles.md`:
|
|
37
|
+
|
|
38
|
+
```markdown
|
|
39
|
+
# Principles
|
|
40
|
+
|
|
41
|
+
This project's cross-cutting rules, including any deviations from q's (see: @lab43/q conventions/principles.md).
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`docs/conventions/documentation.md`:
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
# Documentation
|
|
48
|
+
|
|
49
|
+
This project's documentation rulings and deviations (see: @lab43/q conventions/conventions.md, Three tiers of conventions).
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
No other conventions doc is scaffolded — `/q:update-docs` creates each topical doc when its first entry is recorded.
|
|
53
|
+
2. **The q dependency** — q arrives as one npm package, its conventions and its plugin together, and the developer installs it; Step 2 stopped any run where it is undeclared. Its declaration lives in `devDependencies` in the `package.json` at the repo root — the only place anything looks for it, whatever else the repo's layout holds (source: @lab43/q conventions/extensions.md, Pinning). Leave the recorded declaration alone.
|
|
54
|
+
3. **Agent briefing** — ensure the project's briefing carries the section the briefing template defines, adding what is missing and correcting drift, per that file's rules (see: `${CLAUDE_PLUGIN_ROOT}/references/agent-briefing.md`).
|
|
55
|
+
4. **Plugin declaration** — the project publishes its own marketplace, sourcing the q it already has in `node_modules` and the plugin of each installed extension that ships one. Two files hold it, created if missing.
|
|
56
|
+
|
|
57
|
+
`.claude-plugin/marketplace.json` at the project root is the conventional path for a project publishing a marketplace, so the file is shared territory rather than q's. Merge q's entry and the extensions' into an existing manifest: leave every other `plugins` entry and the recorded name untouched. Write the whole file only when creating it.
|
|
58
|
+
|
|
59
|
+
The marketplace needs a name no other project on the machine will use. The registry the CLI resolves against holds one entry per marketplace name, machine-wide (source: ${CLAUDE_PLUGIN_ROOT}/references/enforce-declarations.md). Two projects sharing a name means the second one loads another project's q rather than its own.
|
|
60
|
+
|
|
61
|
+
Name it `q-pin-<owner>-<repo>-<suffix>` — for example, `q-pin-acme-storefront-4f2ab9`. Owner and repo keep the name legible in that registry. The suffix is six random hex characters. It is what keeps the name unique. Read owner and repo from the repo's GitHub origin with `gh repo view --json nameWithOwner`. Use the project directory's name in their place when that command yields nothing. Lowercase the whole name and replace every character outside `a-z0-9-` with a hyphen.
|
|
62
|
+
|
|
63
|
+
Generate that name only when creating the file. A project that already records one keeps it, whatever it is. Other clones have already registered that name locally. Regenerating it strands them.
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"name": "<marketplace>",
|
|
68
|
+
"owner": { "name": "this project" },
|
|
69
|
+
"metadata": { "description": "Pins the q this project's sessions load. The name must stay unique to this project. Sharing another project's name makes this one resolve to that project's q." },
|
|
70
|
+
"plugins": [
|
|
71
|
+
{
|
|
72
|
+
"name": "q",
|
|
73
|
+
"source": "./node_modules/@lab43/q/q-extension",
|
|
74
|
+
"description": "The q workflow plugin, pinned for this project."
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
An extension ships a plugin when its payload holds `.claude-plugin/` (source: @lab43/q conventions/extensions.md, Layout). Look for one across the installed extensions — the direct dependencies, in `dependencies` and `devDependencies` alike, whose installed copy carries both halves of an extension's identity (source: @lab43/q conventions/extensions.md, Identity). Each extension shipping a plugin gets an entry beside q's, sourced at `./node_modules/<package>/q-extension` and named by the `name` in its `q-extension/.claude-plugin/plugin.json`, with that manifest's `description` when it carries one. Tell entries apart by `source`, never by name — the name is the author's to choose. Bring an entry whose source is already present to this form in place. An extension whose plugin manifest names no plugin, or names one that another source's entry already holds, gets no entry: report it as the extension author's to fix. An entry already in the manifest keeps its name against a newcomer claiming it. Between two extensions arriving with the same name, neither gets an entry.
|
|
81
|
+
|
|
82
|
+
Then merge into `.claude/settings.json`, leaving other keys untouched. Key the marketplace and every plugin entry to whatever name the manifest records, and correct any that has drifted from it:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"extraKnownMarketplaces": {
|
|
87
|
+
"<marketplace>": { "source": { "source": "directory", "path": "./" } }
|
|
88
|
+
},
|
|
89
|
+
"enabledPlugins": { "q@<marketplace>": true, "<plugin>@<marketplace>": true }
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Write this settings entry by hand, its `path` the literal `./` shown — producing it with `claude plugin marketplace add` records an absolute path instead, which breaks every other checkout of the repo.
|
|
94
|
+
5. **Enforce the declarations** — make this machine match what the project now declares, per `${CLAUDE_PLUGIN_ROOT}/references/enforce-declarations.md`.
|
|
95
|
+
6. **State file** — write `.claude/q-state.json` per `${CLAUDE_PLUGIN_ROOT}/references/q-state.md`: a `reconciledAgainst` entry for `@lab43/q`, from the version in `node_modules/@lab43/q/package.json`. Write only absent watermarks — a present entry, stale or not, is reconciliation's to move (source: ${CLAUDE_PLUGIN_ROOT}/references/q-state.md).
|
|
96
|
+
7. **Ignore rules** — ensure `.gitignore` covers `node_modules/`, `.claude/settings.local.json`, and `.claude/worktrees/`, and that the committed scaffold files are not ignored: run `git check-ignore` on `.claude/settings.json`, `.claude-plugin/`, and `.claude/q-state.json`, fixing the rules until it reports nothing. A bare negation under an ignored `.claude/` does nothing — the directory rule itself must become `.claude/*` plus the negations. Leave every unrelated ignore rule alone.
|
|
97
|
+
8. **The README's q section** — when the README doesn't mention q, add this section verbatim:
|
|
98
|
+
|
|
99
|
+
```markdown
|
|
100
|
+
## Claude Code
|
|
101
|
+
|
|
102
|
+
This project uses [q](https://www.npmjs.com/package/@lab43/q), an agentic coding workflow that grounds Claude Code sessions in the project's own conventions. It arrives with the project's dependencies, and Claude Code loads it from the repo's tracked settings.
|
|
103
|
+
|
|
104
|
+
The project's rules live in `docs/conventions/`, and q ships rules of its own inside the package. Sessions read both before writing code, and record new decisions into the project's docs as they are made — the docs assemble themselves out of the work.
|
|
105
|
+
|
|
106
|
+
A session lists every `/q:` skill. Start with these:
|
|
107
|
+
|
|
108
|
+
- `/q:implement` — take on a task or bug
|
|
109
|
+
- `/q:create-plan`, then `/q:implement-plan` — plan bigger work, then execute the plan
|
|
110
|
+
- `/q:review` — review anything against the project's conventions
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
When the README already mentions q, keep its wording; correct only what it says about q that is no longer true. When the project has no README, create a minimal one holding just this section.
|
|
114
|
+
9. Scaffold nothing else. An empty taxonomy directory arrives when its first document does.
|
|
115
|
+
|
|
116
|
+
## Step 4: Deliver
|
|
117
|
+
|
|
118
|
+
Invoked from another skill's run, stop here — the changes are that run's to validate and deliver. When the run changed nothing tracked and no earlier run's scaffold awaits delivery: switch back to the prior branch, delete any branch this run created, and report that and stop. When Step 1's GitHub CLI check failed, stop here with the closing report (Step 5), adding:
|
|
119
|
+
|
|
120
|
+
- That the changes stay uncommitted — restate the `gh` fix.
|
|
121
|
+
- That a re-run delivers them once `gh` is in place.
|
|
122
|
+
|
|
123
|
+
Otherwise, in ship mode, commit. No adversarial review closes this run: the scaffold is deliberately deterministic — much of it is verbatim templates a reviewer would only second-guess — and the user reviews the delivered diff. Then:
|
|
124
|
+
|
|
125
|
+
1. **The local gate**: run it over the uncommitted changes (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The local gate) — minus the adversarial pass the gate otherwise adds after substantial iteration. The no-review ruling above covers the gate's too.
|
|
126
|
+
2. **Open the PR**: push the branch and open the PR per the PR-authoring rules (see: @lab43/q conventions/pull-requests.md).
|
|
127
|
+
|
|
128
|
+
## Step 5: Report
|
|
129
|
+
|
|
130
|
+
Close the session by reporting:
|
|
131
|
+
|
|
132
|
+
- What was created.
|
|
133
|
+
- What already existed and was left untouched.
|
|
134
|
+
- Each shipped plugin left without a marketplace entry, and why.
|
|
135
|
+
- Convention-like content Step 1 found outside `docs/conventions/` — migration candidates this run leaves alone. Moving a project's existing docs is its own delivery: suggest `/q:create-plan` for a docs tree, or `/q:implement` for a handful of rules.
|
|
136
|
+
- Content already in `docs/conventions/` that has drifted from the documentation policy — grooming's territory: suggest `/q:groom-docs`.
|
|
@@ -36,7 +36,7 @@ Every entry on the list goes one of two ways:
|
|
|
36
36
|
|
|
37
37
|
Settle the run with the user, in conversational mode (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Collaboration modes). One batch: the list, which way each entry goes, and the review mode (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Review modes). In this run, ship covers commit, push, and the PR; local commits nothing until the user has reviewed the diff.
|
|
38
38
|
|
|
39
|
-
Answers settle decisions
|
|
39
|
+
Answers settle decisions. They are not the agreement. Close the conversation by summarizing the agreed scope and asking for the go-ahead. That go-ahead, not the last answer, is what makes the rest of the run autonomous.
|
|
40
40
|
|
|
41
41
|
When the agreed isolation won't fit one reviewable PR, continue into `/q:create-plan` in this session on the go-ahead, handing over what Step 1 found and what the batch already settled. This run ends there; the plan carries the build.
|
|
42
42
|
|
|
@@ -60,10 +60,10 @@ Drive what you built through `/q:drive`. What to exercise: each resource the run
|
|
|
60
60
|
|
|
61
61
|
## Step 5: Adversarial review
|
|
62
62
|
|
|
63
|
-
Validate the diff (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Validation) with the **correctness** and **conventions** lenses. Hand the reviewers the agreed scope and the diff scope: `git diff origin/<default-branch>...HEAD` in ship mode, or the uncommitted diff plus the changed-file list in local
|
|
63
|
+
Validate the diff (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Validation) with the **correctness** and **conventions** lenses. Hand the reviewers the agreed scope and the diff scope: `git diff origin/<default-branch>...HEAD` in ship mode, or the uncommitted diff plus the changed-file list in local mode. Per loop round, re-drive a resource only when a fix could change what driving showed. Surviving findings become Caveats in the PR description.
|
|
64
64
|
|
|
65
65
|
## Step 6: Open the PR
|
|
66
66
|
|
|
67
|
-
1. **
|
|
68
|
-
2. **Open the PR**: `git push -u origin <work-slug>`, then `gh pr create`, per the PR-authoring rules (see: q conventions/pull-requests.md).
|
|
69
|
-
3. Close the session by reporting the PR URL, every resource left shared, 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).
|
|
67
|
+
1. **The local gate**: run it over the session's uncommitted work (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The local gate).
|
|
68
|
+
2. **Open the PR**: `git push -u origin <work-slug>`, then `gh pr create`, per the PR-authoring rules (see: @lab43/q conventions/pull-requests.md).
|
|
69
|
+
3. Close the session by reporting the PR URL, every resource left shared, any caveats, any amendment raised instead of applied, and any follow-up work — filed in the tracker on the user's agreement (source: @lab43/q conventions/issue-tracking.md, Ask before filing).
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reconcile
|
|
3
|
+
description: Reconcile the project's records with what npm already did — q or an extension updated, installed, or removed (your own npm install, a teammate's merge, a Dependabot bump). The changes ship as a PR. Also sets up or repairs this machine for a q-using project — use it on a fresh clone, or whenever the session-start check reports drift. A project with no q scaffold routes to /q:install instead. A run finding nothing to reconcile repairs the machine, asks nothing, and stops.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Reconcile
|
|
7
|
+
|
|
8
|
+
Follow the run contract — `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`.
|
|
9
|
+
|
|
10
|
+
## Step 1: Enforce the declarations
|
|
11
|
+
|
|
12
|
+
Propose `/q:install` and stop in either of these states — there is nothing to reconcile yet:
|
|
13
|
+
|
|
14
|
+
- The project declares no `@lab43/q` devDependency. It has nothing to enforce.
|
|
15
|
+
- It declares one but has no `.claude/q-state.json`. q's bytes arrived. The scaffold that records them has not run.
|
|
16
|
+
|
|
17
|
+
Otherwise enforce the declarations per `${CLAUDE_PLUGIN_ROOT}/references/enforce-declarations.md`.
|
|
18
|
+
|
|
19
|
+
## Step 2: Check the GitHub CLI
|
|
20
|
+
|
|
21
|
+
Run `gh auth status`, and `gh repo view` to confirm the repo's `origin` is GitHub-hosted — q's workflow skills require both. When either fails, report the fix: install via <https://cli.github.com> and authenticate with `gh auth login` for a missing or unauthenticated CLI; a failing `gh repo view` with an authenticated CLI means `origin` is not GitHub-hosted.
|
|
22
|
+
|
|
23
|
+
## Step 3: Take stock
|
|
24
|
+
|
|
25
|
+
Read `.claude/q-state.json` (see: ${CLAUDE_PLUGIN_ROOT}/references/q-state.md) and compare:
|
|
26
|
+
|
|
27
|
+
- the version the project's lockfile resolves for `@lab43/q` and for each extension against its `reconciledAgainst` entry, and the version installed under `node_modules/` against the lockfile's, in both directions — the extensions are the direct dependencies, in `dependencies` and `devDependencies` alike, whose installed copy carries both halves of an extension's identity — the `q-extension` keyword and a payload directory (source: @lab43/q conventions/extensions.md, Identity). A dependency carrying the keyword, shipping no payload, and holding no `reconciledAgainst` entry is not an extension: leave it out of scope rather than reporting a missing record no skill could resolve. A watermarked package stays in scope however it changed, because a record already exists and only reconciliation or removal clears it
|
|
28
|
+
|
|
29
|
+
Each finding routes to its remedy:
|
|
30
|
+
|
|
31
|
+
- A lockfile version differing from its watermark (moved, never reconciled) — a version move: this run reconciles it (Step 5). When the release stopped shipping a payload, the rules departed while the code stayed: reconcile it as a departure (Step 6) instead.
|
|
32
|
+
- An entry for an extension in neither `dependencies` nor `devDependencies` (removed, the removal never reconciled) — a departure: this run reconciles it (Step 6). Read both before treating it as one: an extension held as a regular dependency is healthy, and reading `devDependencies` alone reports it as removed. `@lab43/q` never routes here — a project that dropped its q declaration is Step 1's stop.
|
|
33
|
+
- A `reconciledAgainst` map with no `@lab43/q` entry → `/q:install`, invoked bare. The scaffold was never fully recorded, and scaffolding is install's to complete. A state file missing altogether never reaches this step — it is Step 1's stop.
|
|
34
|
+
- Any other declared extension with no entry, from either dependency map — an arrival, installed by hand and never recorded: this run reconciles it (Step 7).
|
|
35
|
+
|
|
36
|
+
Alongside, hold each third-party extension's q declaration — the `@lab43/q` devDependency in its own `node_modules/<extension>/package.json` (source: @lab43/q conventions/extensions.md, Pinning) — against the project's own installed q, and flag a mismatch either way in the close. A declaration ahead of the project's q closes by the developer moving q forward; one behind closes only by that extension's release. A ranged q declaration states no version at all — flag it as the extension author's to fix.
|
|
37
|
+
|
|
38
|
+
## Step 4: Settle delivery
|
|
39
|
+
|
|
40
|
+
A run that found nothing to reconcile — no finding at all, or only the `/q:install` hand-off — skips to Step 10: it asks nothing and delivers nothing, Steps 1 and 2 having changed machine state only. Otherwise ask which review mode — local or ship — the run delivers under (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Review modes), then pick the delivery branch (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The delivery branch). The findings are the agreement — the rest of the run is autonomous. However many packages moved, one run reconciles them into one change: they are the same project catching up with the same npm install.
|
|
41
|
+
|
|
42
|
+
## Step 5: Reconcile each version move
|
|
43
|
+
|
|
44
|
+
Diff the two published versions: `npm pack <package>@<version>` for the watermark and for the installed version into a scratch directory, extract both, and diff the trees. Diff the whole tarball rather than the payload's `conventions/` alone, because a release can change skills, hooks, agents and references too. Work only from the diff. What it touched decides which of these applies, and a diff may touch more than one:
|
|
45
|
+
|
|
46
|
+
- **Changed conventions docs** — hold the project's docs, and the exception markers its code carries, against each changed rule:
|
|
47
|
+
- remove an override whose target updated to agree or disappeared — it is spent (source: @lab43/q conventions/conventions.md, Three tiers of conventions)
|
|
48
|
+
- re-check each "(source: …)" restatement against its changed home
|
|
49
|
+
- re-check each exception against its changed rule — retarget one whose rule moved, and remove one that is spent, its rule gone or changed to admit the site (source: @lab43/q conventions/documentation.md, Markers)
|
|
50
|
+
- prune a project rule the new text now owns — it is duplication now
|
|
51
|
+
- ask about a project rule the new text contradicts, the one call the go-ahead didn't settle: keep it as a recorded deviation (add the overrides marker) or adopt the incoming rule. Adopting can leave code non-conforming — suggest `/q:review` on the affected area; bringing code back into conformance is out of scope here
|
|
52
|
+
|
|
53
|
+
An extension authored in this repo is part of that surface: re-check its docs and its own `q.description` the same way. The exact `@lab43/q` pin in its root `package.json` is also that extension's shipped declaration of which q version its rules were written against — the manifest goes into the published tarball, which makes this the one `package.json` entry still read as a version (source: @lab43/q conventions/extensions.md, Pinning). Flag it when it no longer names the q the project now runs; moving it is the developer's npm edit.
|
|
54
|
+
|
|
55
|
+
Then sync the briefing's index lines for the package — a doc added or removed changes the list, and a changed intro means rewriting the doc's blurb (see: @lab43/q conventions/documentation.md, Taxonomy).
|
|
56
|
+
- **A changed `q.description`** — rewrite that extension's group heading in the briefing's docs index (see: `${CLAUDE_PLUGIN_ROOT}/references/agent-briefing.md`). A release can change the blurb alone.
|
|
57
|
+
- **A changed plugin**, q's or an extension's — re-run `/q:install`, scoped to join this run's change: it is idempotent, creating what the new version's scaffold expects and correcting what has drifted from it. A plugin's changed contents reach sessions from `node_modules/` as they stand; the re-run is what registers a plugin the release started shipping. A plugin the release stopped shipping takes the reverse: remove it from the project's marketplace the way Step 6 does for a departed extension.
|
|
58
|
+
|
|
59
|
+
After each package's reconciliation, write its watermark per `${CLAUDE_PLUGIN_ROOT}/references/q-state.md`: its `reconciledAgainst` entry to its installed version.
|
|
60
|
+
|
|
61
|
+
Step 4's go-ahead already covers this reconciliation, the prunes, drops and watermark writes included. Apply it without re-asking.
|
|
62
|
+
|
|
63
|
+
## Step 6: Reconcile each departure
|
|
64
|
+
|
|
65
|
+
The developer already removed the package; this run reconciles the records it left behind. Run the package manager's dependency install once, catching up any lockfile and `node_modules` remnants the removals left — it realizes what the manifest already declares: no named package, no manifest write. A package that departed by dropping its payload takes the same treatment minus that install — its code is still installed, and only its records leave. Then, for each departed extension, remove without asking — each item a no-op when already absent:
|
|
66
|
+
|
|
67
|
+
1. Remove the extension's group from the agent briefing's docs index — its heading and every line under it. An extension that shipped no conventions docs has no group to remove.
|
|
68
|
+
2. Drop the extension's `reconciledAgainst` entry, per `${CLAUDE_PLUGIN_ROOT}/references/q-state.md`.
|
|
69
|
+
3. Remove the extension's plugin from the project's marketplace. Drop the `.claude-plugin/marketplace.json` entry whose `source` is `./node_modules/<extension>/q-extension`. Then drop the `enabledPlugins` key in `.claude/settings.json` that names the removed entry's plugin at the project's marketplace. Leave every other entry and key alone. An extension that shipped no plugin has neither.
|
|
70
|
+
|
|
71
|
+
Then rule on what the departure orphaned. Grep the docs the documentation policy owns (see: @lab43/q conventions/documentation.md, Taxonomy) for the extension's name, and grep the project's code for exception markers naming it, excluding `node_modules/` and build artifacts. Every hit lost its backing with the extension: an overrides marker's target, an exception marker's target, a restatement's home, a cross-reference's destination. On a clean sweep, skip this. Otherwise recommend a resolution for each hit, grounded in the documentation policy, in conversational mode (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Collaboration modes) — one AskUserQuestion batch. The user rules. Apply the rulings.
|
|
72
|
+
|
|
73
|
+
## Step 7: Reconcile each arrival
|
|
74
|
+
|
|
75
|
+
The developer already installed the package; this run records it. For each arrived extension:
|
|
76
|
+
|
|
77
|
+
1. Verify both halves of its identity (source: @lab43/q conventions/extensions.md, Identity): `node_modules/<extension>/package.json` carries the `q-extension` keyword, and the package holds `q-extension/conventions/`, `q-extension/.claude-plugin/`, or both. Step 3 scoped by this same identity; re-verify at the acting site, because the watermark write is what a misclassification would poison. A package failing the check is reported in the close and left alone — no index lines, and above all no watermark, which would record a package q cannot reconcile.
|
|
78
|
+
2. An extension shipping conventions docs gets its own group in the briefing's docs index, written to that file's rules (see: `${CLAUDE_PLUGIN_ROOT}/references/agent-briefing.md`). One shipping none is watermarked without being indexed, having no docs to index (source: @lab43/q conventions/extensions.md, Layout).
|
|
79
|
+
3. An extension shipping a plugin gets it registered in the project's marketplace: re-run `/q:install`, scoped to join this run's change. One shipping none has nothing to load.
|
|
80
|
+
4. Write its watermark from the version in `node_modules/<extension>/package.json`. Never overwrite a present entry, stale or not: a stale watermark moves only by reconciling the version move behind it (source: ${CLAUDE_PLUGIN_ROOT}/references/q-state.md).
|
|
81
|
+
|
|
82
|
+
Report in the close, per arrival:
|
|
83
|
+
|
|
84
|
+
- A missing `q.description`, if the package ships conventions docs without one (source: @lab43/q conventions/extensions.md, Description). Its group falls back to a heading of the package name alone (source: `${CLAUDE_PLUGIN_ROOT}/references/agent-briefing.md`). Name it as the extension author's to fix, not the installing project's. Index it anyway — one missing blurb does not stop rules that otherwise work.
|
|
85
|
+
- Any overrides markers its docs carry against q's rules. These are deviations the project now lives under. The project's own rulings still win on conflict.
|
|
86
|
+
|
|
87
|
+
## Step 8: Adversarial review
|
|
88
|
+
|
|
89
|
+
In ship mode, commit first. In both modes, validate the changes (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Validation) with the **correctness** and **conventions** lenses.
|
|
90
|
+
|
|
91
|
+
## Step 9: Open the PR
|
|
92
|
+
|
|
93
|
+
Skip this step when Step 4 found nothing to deliver.
|
|
94
|
+
|
|
95
|
+
1. **The local gate**: run it over the uncommitted changes (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The local gate).
|
|
96
|
+
2. **Open the PR**: push the branch and open the PR per the PR-authoring rules (see: @lab43/q conventions/pull-requests.md).
|
|
97
|
+
|
|
98
|
+
## Step 10: Report, then hand off
|
|
99
|
+
|
|
100
|
+
Close the session by reporting:
|
|
101
|
+
|
|
102
|
+
- What Step 1 enforced, and any tracked file it rewrote (a lockfile) left in the tree as the user's.
|
|
103
|
+
- The GitHub CLI result, with the fix when it failed.
|
|
104
|
+
- Each version move reconciled and what its release changed.
|
|
105
|
+
- Each arrival reconciled — the group and lines indexed, the plugin registered, the watermark written — with Step 7's per-arrival notes, and each package that failed the identity check, left alone.
|
|
106
|
+
- Each departure reconciled — the records and plugin registration dropped, any lockfile catch-up applied, and each orphaned reference with the user's ruling. Name a departure by dropped payload as a release that stopped shipping rules, since the project may want the dependency reconsidered.
|
|
107
|
+
- Any plugin an install re-run left without a marketplace entry, and why.
|
|
108
|
+
- Each flagged q declaration, and what closes it.
|
|
109
|
+
|
|
110
|
+
Then, where Step 3 found no `@lab43/q` record, make its `/q:install` hand-off — a full run of its own that asks and delivers for itself.
|
|
@@ -15,6 +15,7 @@ The target comes from the invocation. Map it to an artifact the adversarial revi
|
|
|
15
15
|
- **A diff, file, or directory**: as given.
|
|
16
16
|
- **A feature or area named in words**: locate its files (an Explore subagent for breadth) and confirm the file list with the user before reviewing.
|
|
17
17
|
- **A plan doc in `docs/plans/`**: a plan review when its status is `pending`. Review any other plan as prose.
|
|
18
|
+
- **A spec doc in `docs/specs/`**: a work review over the spec itself plus the files carrying its spec markers. Find them by grepping the repo for `spec:` followed by the doc's path, excluding `node_modules/` and build artifacts.
|
|
18
19
|
|
|
19
20
|
## Step 2: Launch the review
|
|
20
21
|
|
|
@@ -22,7 +23,7 @@ Launch `adversarial-reviewer` subagents over the artifact, passing what the agen
|
|
|
22
23
|
|
|
23
24
|
## Step 3: Rule with the user
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
In conversational mode (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Collaboration modes), triage the findings:
|
|
26
27
|
|
|
27
28
|
- **Fix outright**: a finding that is clearly right, with a fix that reopens nothing. Apply it and present it as applied, where the user can veto it.
|
|
28
29
|
- **Reject outright**: a finding the session's context refutes. Present it with its reason — never drop one silently, since the refuting context may itself be wrong.
|
|
@@ -34,7 +35,7 @@ Fixes to an outstanding change another run owns stay uncommitted with it — don
|
|
|
34
35
|
|
|
35
36
|
1. When delivering now, create a branch unless the session is already on one.
|
|
36
37
|
2. The rulings are the agreement — apply the approved fixes autonomously, approved convention amendments included. Fixes and amendments that land in policy-governed docs go through `/q:update-docs`, the documentation surface's single write path. Run the project's checks covering what changed.
|
|
37
|
-
3. Sweep the rulings for lessons the docs should carry: a rejected finding whose reason is a rule nobody wrote down, or a correction the next reviewer would have to re-derive. Each one is a correction to record (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Corrections become rules). In ship mode, commit the fixes and the recordings together.
|
|
38
|
+
3. Sweep the rulings for lessons the docs should carry: a rejected finding whose reason is a rule nobody wrote down, a finding rejected because this one site is legitimately outside the rule, or a correction the next reviewer would have to re-derive. Each one is a correction to record (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Corrections become rules). In ship mode, commit the fixes and the recordings together.
|
|
38
39
|
|
|
39
40
|
## Step 5: Adversarial review
|
|
40
41
|
|
|
@@ -43,6 +44,6 @@ When delivering now, validate the whole diff being delivered (see: ${CLAUDE_PLUG
|
|
|
43
44
|
## Step 6: Deliver
|
|
44
45
|
|
|
45
46
|
1. Fixes not delivered now — joining an outstanding change another run owns, or left in the tree — stay uncommitted for the run that delivers them. Skip to the report.
|
|
46
|
-
2. **
|
|
47
|
-
3. **Open the PR**: push the branch and open the PR per the PR-authoring rules (see: q conventions/pull-requests.md).
|
|
47
|
+
2. **The local gate**: run it over the uncommitted fixes (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The local gate).
|
|
48
|
+
3. **Open the PR**: push the branch and open the PR per the PR-authoring rules (see: @lab43/q conventions/pull-requests.md).
|
|
48
49
|
4. Close the session by reporting: findings and rulings including what was dropped, the check results, the doc entries recorded, and any amendment raised instead of applied, listed on its own. When work was left in the tree, say that it is unvalidated until delivered, and that a later bare `/q:review` reviews and delivers the accumulation.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: triage
|
|
3
|
-
description: Choose what to work on next from a set of items — a Jira board, GitHub issues, a Notion doc, a file or pasted list — and work through it one pick at a time. Priority guidelines steer the ranking when given ("newest first"). Each agreed pick runs as a /q:
|
|
3
|
+
description: Choose what to work on next from a set of items — a Jira board, GitHub issues, a Notion doc, a file or pasted list — and work through it one pick at a time. Priority guidelines steer the ranking when given ("newest first"). Each agreed pick runs as a /q:implement cycle in this session, claimed in the source (assignee, status) only with the user's agreement. For a single known item, invoke /q:implement directly.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Triage
|
|
@@ -8,30 +8,30 @@ description: Choose what to work on next from a set of items — a Jira board, G
|
|
|
8
8
|
## Ground rules
|
|
9
9
|
|
|
10
10
|
- **Follow the run contract** — `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`.
|
|
11
|
-
- **
|
|
12
|
-
- **Conventions govern the tracker**: read and follow the issue-tracking conventions (see: q conventions/issue-tracking.md), plus any project rulings, which win. Never re-ask what they settle.
|
|
13
|
-
- **Track the session**: keep a scratchpad note of the session's agreements (review mode, write-backs, priority guidelines) and each item's outcome. An outcome is the PR, plan, or nothing-to-do verdict the
|
|
11
|
+
- **Ranking is not grounding**: judge items on what the source says — titles, descriptions, labels, dates — never by exploring the code. Grounding an item against the codebase is the first step of its implement cycle, not a triage cost paid across the whole set.
|
|
12
|
+
- **Conventions govern the tracker**: read and follow the issue-tracking conventions (see: @lab43/q conventions/issue-tracking.md), plus any project rulings, which win. Never re-ask what they settle.
|
|
13
|
+
- **Track the session**: keep a scratchpad note of the session's agreements (review mode, write-backs, priority guidelines) and each item's outcome. An outcome is the PR, plan, or nothing-to-do verdict the implement cycle produced, or that the user skipped the item. Ranking and the closing recap read from this note, and it keeps the loop intact when earlier cycles are compacted away.
|
|
14
14
|
|
|
15
15
|
## Step 1: Read the set
|
|
16
16
|
|
|
17
17
|
The set comes from the invocation — a Jira board or filter, a GitHub repo's issues, a Notion doc, a file, a pasted list; given nothing, ask what to triage. Read it with whatever tool serves the source, fetching summaries rather than full item histories. Note any priority guidelines the invocation carries.
|
|
18
18
|
|
|
19
|
-
Read the priority the user set, when the source records one — a hand-ordered position, a priority field, a label. A default listing order is not one: creation date and ID say nothing about priority. A fetch can drop
|
|
19
|
+
Read the priority the user set, when the source records one — a hand-ordered position, a priority field, a label. A default listing order is not one: creation date and ID say nothing about priority. A fetch can drop fields silently. Confirm the call you use preserves the priority and carries descriptions, labels, dates, assignees. A GitHub milestone records its priority as a hand-ordered position. That order comes back only through GraphQL:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
gh api graphql -f query='{repository(owner:"<owner>",name:"<repo>"){milestones(query:"<milestone-title>",first:10){nodes{title issues(first:100,states:OPEN){nodes{number title}}}}}}'
|
|
22
|
+
gh api graphql -f query='{repository(owner:"<owner>",name:"<repo>"){milestones(query:"<milestone-title>",first:10){nodes{title issues(first:100,states:OPEN){nodes{number title body labels(first:20){nodes{name}} assignees(first:10){nodes{login}} createdAt updatedAt}}}}}}'
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
`milestones(query:)` matches titles by substring, so take the node whose title is the one you were given. `gh issue list --milestone` returns creation order instead. Omitting `states: OPEN` pulls in the milestone's closed issues.
|
|
26
26
|
|
|
27
|
-
Set aside items not available to pick up rather than proposing them (source: q conventions/issue-tracking.md, Respect existing claims). Check the project's open PRs (`gh pr list`) against the set — the source may not show a fix in review. Ask the peers what work items they hold, and set those aside too (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Working alongside a peer). Any session holds an item, not just another triage run — a `/q:
|
|
27
|
+
Set aside items not available to pick up rather than proposing them (source: @lab43/q conventions/issue-tracking.md, Respect existing claims). Check the project's open PRs (`gh pr list`) against the set — the source may not show a fix in review. Ask the peers what work items they hold, and set those aside too (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Working alongside a peer). Any session holds an item, not just another triage run — a `/q:implement` invoked straight on an issue holds it too. A peer triaging the same set holds no item until it picks. Never divide the set between sessions. Never ask the user to resolve the overlap. Name the set-asides once; the user can pull any back in.
|
|
28
28
|
|
|
29
29
|
## Step 2: Settle the session
|
|
30
30
|
|
|
31
31
|
In conversational mode (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Collaboration modes), settle the session in one batch of questions:
|
|
32
32
|
|
|
33
|
-
- The review mode every
|
|
34
|
-
- The write-backs the issue-tracking conventions gate on a session-wide agreement: claiming each agreed pick, commenting PR links (see: q conventions/issue-tracking.md). Skip what the source can't support and what conventions already settle.
|
|
33
|
+
- The review mode every implement cycle will run under (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Review modes).
|
|
34
|
+
- The write-backs the issue-tracking conventions gate on a session-wide agreement: claiming each agreed pick, commenting PR links (see: @lab43/q conventions/issue-tracking.md). Skip what the source can't support and what conventions already settle.
|
|
35
35
|
- Anything about the set itself that ranking genuinely turns on.
|
|
36
36
|
|
|
37
37
|
Settle each answer once and don't re-ask it per item, though the user may change any answer between items. Don't ask for priority guidelines when none were given. Rank on the first of these the set gives you:
|
|
@@ -44,9 +44,9 @@ State the basis with each proposal so the user can redirect it.
|
|
|
44
44
|
|
|
45
45
|
## Step 3: Propose and hand off
|
|
46
46
|
|
|
47
|
-
Rank what remains — items neither picked nor skipped this session — and take the top one. Announce it to the peers before proposing it: you hold an item from the moment you pick it, so no two sessions spend a conversation scoping the same one. Then propose it: the recommended item, why it's next under the guidelines (or the stated basis), and the runners-up. When a set-aside would outrank the pick, or an item's claim looks stale, flag it alongside the proposal: the status may be wrong, and the user rules (source: q conventions/issue-tracking.md, Respect existing claims). The user may agree, pick a different item, adjust the guidelines — reranking takes effect immediately — or stop. Release the item you announced as soon as you are no longer holding it, and announce the next one you take up.
|
|
47
|
+
Rank what remains — items neither picked nor skipped this session — and take the top one. Announce it to the peers before proposing it: you hold an item from the moment you pick it, so no two sessions spend a conversation scoping the same one. Then propose it: the recommended item, why it's next under the guidelines (or the stated basis), and the runners-up. When a set-aside would outrank the pick, or an item's claim looks stale, flag it alongside the proposal: the status may be wrong, and the user rules (source: @lab43/q conventions/issue-tracking.md, Respect existing claims). The user may agree, pick a different item, adjust the guidelines — reranking takes effect immediately — or stop. Release the item you announced as soon as you are no longer holding it, and announce the next one you take up.
|
|
48
48
|
|
|
49
|
-
The agreed pick authorizes its handoff, nothing more. Claim the item in the source when claiming was agreed. Then continue into `/q:
|
|
49
|
+
The agreed pick authorizes its handoff, nothing more. Claim the item in the source when claiming was agreed. Then continue into `/q:implement` in this session, passing only what triage settled: the item's reference in its source (its text, when the set was pasted inline), the review mode, and any constraints from the conversation. The run reads the source itself and settles the verdict, route, and approach with the user — the pick decides only what's next.
|
|
50
50
|
|
|
51
51
|
## Step 4: Loop
|
|
52
52
|
|
|
@@ -14,41 +14,46 @@ Follow the run contract — `${CLAUDE_PLUGIN_ROOT}/references/run-contract.md`.
|
|
|
14
14
|
The change comes from the invocation: named in the prompt, surfaced by the session's own work, or handed over by a delegating skill. On a bare invocation, sweep the session for candidates — decisions made, gotchas hit, corrections taken. Route each by what it is:
|
|
15
15
|
|
|
16
16
|
- **A lesson, pattern, or decision to record — including a decision to change an existing convention** → the conventions path, Step 3.
|
|
17
|
-
- **A fact, instruction, or overview change for the product's readers** → the surface the taxonomy assigns it — a guide, the README, or the briefing, whether or not the invocation named one (see: q conventions/documentation.md, Taxonomy).
|
|
18
|
-
- **A
|
|
17
|
+
- **A fact, instruction, or overview change for the product's readers** → the surface the taxonomy assigns it — a guide, the README, or the briefing, whether or not the invocation named one (see: @lab43/q conventions/documentation.md, Taxonomy).
|
|
18
|
+
- **A spec change — a commitment the product makes, which the invocation names: the user's instruction, or a plan's scheduled step** → the spec path, Step 4. A bare sweep never takes this route: report a swept lesson that reads as a product commitment to the user as a spec candidate, and leave it unwritten (source: @lab43/q conventions/documentation.md, Taxonomy).
|
|
19
|
+
- **A plan change** → the lifecycle's rules — status flips and marked amendments; authoring new plans belongs to `/q:create-plan`, and amendments during an implementation run to `/q:implement-plan`, not here (see: @lab43/q conventions/plans.md, Lifecycle).
|
|
19
20
|
- **A change that belongs in a q skill's instructions** → not a doc change; flag it as an upstream candidate — suggest `/q:upstream`. (A change that belongs in an extension's doc stays on the conventions path — Step 3 records it locally as a deviation first.)
|
|
20
21
|
|
|
21
22
|
## Step 2: Read the policy
|
|
22
23
|
|
|
23
|
-
Read q's documentation policy (see: q conventions/documentation.md) and its writing rules (see: q conventions/writing.md), plus any installed extension's doc whose topic governs documentation, and the project's `docs/conventions/documentation.md` — its recorded rulings and deviations win on conflict.
|
|
24
|
+
Read q's documentation policy (see: @lab43/q conventions/documentation.md), its conventions rules (see: @lab43/q conventions/conventions.md), and its writing rules (see: @lab43/q conventions/writing.md), plus any installed extension's doc whose topic governs documentation, and the project's `docs/conventions/documentation.md` — its recorded rulings and deviations win on conflict.
|
|
24
25
|
|
|
25
26
|
## Step 3: The conventions path — qualify the lesson
|
|
26
27
|
|
|
27
|
-
Read q's principles (see: q conventions/principles.md), plus any installed extension's doc whose topic governs cross-cutting principles, and the project's `docs/conventions/principles.md`. Then hold the lesson to four gates, in order:
|
|
28
|
+
Read q's principles (see: @lab43/q conventions/principles.md), plus any installed extension's doc whose topic governs cross-cutting principles, and the project's `docs/conventions/principles.md`. Then hold the lesson to four gates, in order:
|
|
28
29
|
|
|
29
30
|
1. **Is it a rule?** Would it change what a future reader writes or flags? Narrative, descriptions of current behavior, and code-readable facts don't qualify — the code carries those. What qualifies is the binding form: the constraint, the do/don't, the decision with rationale. No rule in it ends the path — report that, don't force an entry.
|
|
30
|
-
2. **Where will its next reader be standing?** A fact needed only when touching one specific site becomes a comment there, in code or in a doc's markup, not a conventions entry. A lesson the next person would re-trip writing similar code elsewhere is cross-cutting even with one current instance — that one goes in the doc. Genuinely uncertain: comment now, promote on second occurrence (source: q conventions/principles.md, Colocate knowledge with its next reader).
|
|
31
|
-
3. **Is prose the right rung?** A rule that a component or lint could hold shouldn't settle for documentation (source: q conventions/principles.md, Prefer the strongest enforcement rung). If a stronger rung exists, propose *that* as the fix (or schedule it), with the rationale colocated in the component or lint rule.
|
|
32
|
-
4. **Which tier?** A lesson about the project's code belongs in its `docs/conventions/`. A lesson that seems to belong elsewhere — about the q workflow itself, or a topic an installed extension owns — is recorded in the project's `docs/conventions/` too, as a marked project deviation where it contradicts that rule, and flagged to the user in the session as an upstream candidate — suggest `/q:upstream`. Workflow-general versus project-specific is hard to call from inside one project: record and flag, don't withhold (source: q conventions/
|
|
31
|
+
2. **Where will its next reader be standing?** A fact needed only when touching one specific site becomes a comment there, in code or in a doc's markup, not a conventions entry. A lesson the next person would re-trip writing similar code elsewhere is cross-cutting even with one current instance — that one goes in the doc. Genuinely uncertain: comment now, promote on second occurrence (source: @lab43/q conventions/principles.md, Colocate knowledge with its next reader). When the lesson is that this one site sits outside a rule, the comment carries an exception marker naming that rule (see: @lab43/q conventions/documentation.md, Markers).
|
|
32
|
+
3. **Is prose the right rung?** A rule that a component or lint could hold shouldn't settle for documentation (source: @lab43/q conventions/principles.md, Prefer the strongest enforcement rung). If a stronger rung exists, propose *that* as the fix (or schedule it), with the rationale colocated in the component or lint rule.
|
|
33
|
+
4. **Which tier?** A lesson about the project's code belongs in its `docs/conventions/`. A lesson that seems to belong elsewhere — about the q workflow itself, or a topic an installed extension owns — is recorded in the project's `docs/conventions/` too, as a marked project deviation where it contradicts that rule, and flagged to the user in the session as an upstream candidate — suggest `/q:upstream`. Workflow-general versus project-specific is hard to call from inside one project: record and flag, don't withhold (source: @lab43/q conventions/conventions.md, Three tiers of conventions). One case differs: a repo that publishes rules of its own. Decide whether the lesson belongs in what it publishes or in its own `docs/conventions/` (see: @lab43/q conventions/extensions.md, Which rules ship).
|
|
33
34
|
|
|
34
|
-
A lesson through the gates gets a home: the topically-owning doc — grep the surface first, q's conventions and every installed extension's included: a project rule may already exist to refine, and a rule q or an extension already carries is already law — record it only as a marked deviation if the lesson disagrees, never as a copy. A new doc only when no existing topic owns the rule,
|
|
35
|
+
A lesson through the gates gets a home: the topically-owning doc — grep the surface first, q's conventions and every installed extension's included: a project rule may already exist to refine, and a rule q or an extension already carries is already law — record it only as a marked deviation if the lesson disagrees, never as a copy. A new doc is created only when no existing topic owns the rule (source: @lab43/q conventions/conventions.md, Conventions docs). It arrives with its intro and its index line in the same change (source: @lab43/q conventions/documentation.md, Taxonomy).
|
|
35
36
|
|
|
36
|
-
## Step 4:
|
|
37
|
+
## Step 4: The spec path — hold each statement
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
Read the specs rules (see: @lab43/q conventions/specs.md). Hold each statement to the admission test: it belongs when a future change breaking it should stop for the user's ruling, and it is cut otherwise (source: @lab43/q conventions/specs.md, What a spec holds). Put each statement in the spec doc whose feature owns it, or create that doc, arriving with its intro and its index line in the same change (source: @lab43/q conventions/documentation.md, Taxonomy). When the change amends a section, visit every site marked with it (source: @lab43/q conventions/specs.md, Enforcement). A stronger rung is still preferred for the commitment itself: propose the test, the validation, or the constraint that would enforce it, each carrying the spec marker. The statement stays in the spec regardless, because a spec's prose survives a test holding it (source: @lab43/q conventions/specs.md, Enforcement).
|
|
40
|
+
|
|
41
|
+
## Step 5: Confirm the scope
|
|
42
|
+
|
|
43
|
+
Confirm what the session derived, in conversational mode (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Collaboration modes) — candidates a sweep surfaced, a genuinely contestable home or treatment: state each change, its home, and its treatment — what gets rewritten, deleted, or added. A change the invocation spelled out — the user's prompt or a calling skill's — is already agreed and skips this step: state its classification's small calls rather than asking.
|
|
39
44
|
|
|
40
45
|
In a run invoked directly by the user, ask which review mode — local or ship — the delivery runs under (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Review modes), even when a spelled-out change skips the rest of this step.
|
|
41
46
|
|
|
42
|
-
## Step
|
|
47
|
+
## Step 6: Apply per policy
|
|
43
48
|
|
|
44
|
-
Act autonomously once the scope is agreed. In a run that delivers here (Steps
|
|
49
|
+
Act autonomously once the scope is agreed. In a run that delivers here (Steps 7–8), first pick the delivery branch (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The delivery branch). Then edit the docs directly rather than proposing wording and waiting for approval — the user reviews the applied changes as a git diff. Draft to each surface's own taxonomy rules (see: @lab43/q conventions/documentation.md, Taxonomy) and the writing rules (see: @lab43/q conventions/writing.md). Keep the briefing's docs index in sync if membership or a gloss changed, to the shape the briefing template defines (see: `${CLAUDE_PLUGIN_ROOT}/references/agent-briefing.md`). In a delivering run's ship mode, commit.
|
|
45
50
|
|
|
46
|
-
## Step
|
|
51
|
+
## Step 7: Adversarial review
|
|
47
52
|
|
|
48
|
-
Changes made for a calling skill end at Step
|
|
53
|
+
Changes made for a calling skill end at Step 6: they join the calling run's change, which validates and delivers them. The exception is a caller that asks for full delivery: those changes continue here like a direct run's, under the review mode the calling run settled. Validate the applied changes (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, Validation) with the **correctness** and **conventions** lenses.
|
|
49
54
|
|
|
50
|
-
## Step
|
|
55
|
+
## Step 8: Open the PR
|
|
51
56
|
|
|
52
|
-
1. **
|
|
53
|
-
2. **Open the PR**: push the branch and open the PR per the PR-authoring rules (see: q conventions/pull-requests.md).
|
|
57
|
+
1. **The local gate**: run it over the uncommitted changes (see: ${CLAUDE_PLUGIN_ROOT}/references/run-contract.md, The local gate).
|
|
58
|
+
2. **Open the PR**: push the branch and open the PR per the PR-authoring rules (see: @lab43/q conventions/pull-requests.md).
|
|
54
59
|
3. Close the session by reporting each change and its home, plus anything swept but not recorded and why.
|