diff --git a/lib/skills/__tests__/fixtures/rule-selector/attachments/acme-rule-selector/SKILL.md b/lib/skills/__tests__/fixtures/rule-selector/attachments/acme-rule-selector/SKILL.md index f4cfa7c24d..a5cc344196 100644 --- a/lib/skills/__tests__/fixtures/rule-selector/attachments/acme-rule-selector/SKILL.md +++ b/lib/skills/__tests__/fixtures/rule-selector/attachments/acme-rule-selector/SKILL.md @@ -9,8 +9,9 @@ metadata: # acme rule selector Resolve to `selector: none` when the `ACME_RULES` environment variable is -`off`. Otherwise resolve to these three lines: +`off`. Otherwise resolve to these four lines: selector: acme-rules select --format {format} verdicts: acme-rules verdicts --selection {selection} --verdicts {verdicts} fence: acme-verdicts +check: acme-rules check --base {base} diff --git a/lib/skills/__tests__/fixtures/rule-selector/pack/skills.jsonc b/lib/skills/__tests__/fixtures/rule-selector/pack/skills.jsonc index 4faeab9b3b..7ba30e958b 100644 --- a/lib/skills/__tests__/fixtures/rule-selector/pack/skills.jsonc +++ b/lib/skills/__tests__/fixtures/rule-selector/pack/skills.jsonc @@ -1,8 +1,21 @@ { "version": 2, + "pipelines": { + "feature": [ + "mattstack:stage-provision", + "mattstack:stage-plan", + "mattstack:stage-gates", + "mattstack:stage-evidence", + "mattstack:stage-implement", + "mattstack:stage-self-review", + "mattstack:stage-ship", + "mattstack:stage-watch-ci" + ] + }, "bindings": { "mattstack:review/rule-selector": { "rule-selector": "acme:acme-rule-selector" }, "mattstack:self-review/rule-selector": { "rule-selector": "acme:acme-rule-selector" }, - "mattstack:receive-review/rule-selector": { "rule-selector": "acme:acme-rule-selector" } + "mattstack:receive-review/rule-selector": { "rule-selector": "acme:acme-rule-selector" }, + "mattstack:stage-implement/rule-selector": { "rule-selector": "acme:acme-rule-selector" } } } diff --git a/lib/skills/__tests__/fixtures/rule-selector/pack/stubs.jsonc b/lib/skills/__tests__/fixtures/rule-selector/pack/stubs.jsonc index 7af15e9db4..1dbee66ac3 100644 --- a/lib/skills/__tests__/fixtures/rule-selector/pack/stubs.jsonc +++ b/lib/skills/__tests__/fixtures/rule-selector/pack/stubs.jsonc @@ -2,6 +2,7 @@ "verbs": { "review": { "engine": "review", "description": "Review a teammate's MR" }, "self-review": { "engine": "self-review", "description": "Self-review the current branch" }, - "receive-review": { "engine": "receive-review", "description": "Act on review feedback on your MR" } + "receive-review": { "engine": "receive-review", "description": "Act on review feedback on your MR" }, + "work": { "engine": "work", "pipeline": "feature", "description": "Run a unit of work end to end" } } } diff --git a/lib/skills/__tests__/rule-selector.test.ts b/lib/skills/__tests__/rule-selector.test.ts index 69e2e5d873..33ef4317be 100644 --- a/lib/skills/__tests__/rule-selector.test.ts +++ b/lib/skills/__tests__/rule-selector.test.ts @@ -15,13 +15,18 @@ const seam = (verb: string) => ` commit_incrementally superpowers_chain -->|a failure the approach cannot get past| run_stage_fail commit_incrementally --> next_move - next_move -->|record the commits| git_log_shas + next_move -->|check the work, then record the commits| check_bound next_move -->|tempted to push| stop_implement_push - stop_implement_push --> git_log_shas + stop_implement_push --> check_bound + check_bound -->|no: unbound, selector: none, or no check: line| git_log_shas + check_bound -->|yes| check_rules + check_rules --> check_result + check_result -->|exit 0, nothing the change breaks| git_log_shas + check_result -->|exit 0, rules the change breaks| fix_rule_breaks + check_result -->|non-zero exit: noted for the return| git_log_shas + fix_rule_breaks --> git_log_shas git_log_shas --> run_field_set_commits run_field_set_commits --> implement_done run_stage_fail --> stage_failed diff --git a/plugins/mattstack/attachments/pipeline/stage-implement/rule-selector.block.md b/plugins/mattstack/attachments/pipeline/stage-implement/rule-selector.block.md new file mode 100644 index 0000000000..4e51b4d122 --- /dev/null +++ b/plugins/mattstack/attachments/pipeline/stage-implement/rule-selector.block.md @@ -0,0 +1,45 @@ +--- +node: check_rules +props: + rule-selector: + merge: replace + default: "" + contract: "rule-selector@1" +--- + +# Check the work against the team's rules + +The pack's rule selector is the text after the italic line at the end of +this section; an unbound slot leaves it empty. Resolve it now, on this +run, since it may consult settings or the environment. It resolves to the +single line `selector: none`, or to `selector:`, `verdicts:` and `fence:` +lines with an optional fourth, `check: `. Only the +`check:` line matters here. Skip this step (the `no` edge of Does the rule +selector resolve to a check line?) when the text is empty, resolves to +`selector: none`, or has no `check:` line. + +With a `check:` line: + +1. Find the branch point the way self-review does: `git merge-base + origin/HEAD HEAD`, or the default branch by name when `origin/HEAD` is + unset. +2. Replace `{base}` in the command with that sha and run it once on Bash, + in the worktree, with nothing on stdin. Capture its stdout and its exit + status. +3. Read the stdout. It is written for you: the rules that apply to this + change and the lines worth a look. Decide, rule by rule, whether the + change breaks it. + +An exit other than 0 is one observation, never a failure of the stage: +quote the exit status and the first line of stderr in one line when the +stage returns to the orchestrator, fix nothing on its account, and record +the commits. + +Run it once. The check never runs again in this stage. Rule verdicts come +later only where the pack's self-review runs the self-review verb with +this same selector bound; the default self-review stage reads the diff +without the rules. + +*If a rule below asks for a move this skill's graph marks STOP, take the off-script edge instead.* + +{{props.rule-selector}} diff --git a/plugins/mattstack/attachments/review-rules-select-body/the-contract.block.md b/plugins/mattstack/attachments/review-rules-select-body/the-contract.block.md index 32267e0e7b..10a5a3351f 100644 --- a/plugins/mattstack/attachments/review-rules-select-body/the-contract.block.md +++ b/plugins/mattstack/attachments/review-rules-select-body/the-contract.block.md @@ -18,6 +18,15 @@ shapes. - `fence: `, the tag of the fenced code block the reviewer returns its verdict set in. + An optional fourth line, `check: `, holds the + placeholder `{base}`. The implement stage runs it in the worktree with + nothing on stdin, `{base}` replaced by the branch point, and reads its + stdout as the rules that apply and the lines worth a look; exit 0 means + it ran, and any other exit is one observation that never blocks. The + review verbs never run it: a fill with a `check:` line is still the + three-line shape here. The line is additive, so the contract stays + `rule-selector@1`, and a fill without it behaves as before. + **The selection** is the JSON the selector prints. This skill reads only its `rules` list: each rule has an `id`, a `severity` (`blocking` or `advisory`) and a `summary`. diff --git a/plugins/mattstack/plugin/skills/extending-a-pack/SKILL.md b/plugins/mattstack/plugin/skills/extending-a-pack/SKILL.md index 9fdcb032d1..2b42a7a688 100644 --- a/plugins/mattstack/plugin/skills/extending-a-pack/SKILL.md +++ b/plugins/mattstack/plugin/skills/extending-a-pack/SKILL.md @@ -384,7 +384,7 @@ metadata: ``` `provides` is the prop's contract when it has one (`criteria` takes -`review-criteria@1`, `rule-selector` takes `rule-selector@1`); a `rules` prop has none, so any `provides` binds. +`review-criteria@1`, `rule-selector` takes `rule-selector@1`, whose optional `check:` line `stage-implement` runs); a `rules` prop has none, so any `provides` binds. The body: the rule, its reason, and the decision it changes. The stage keeps its own flow; the fill carries only what the team adds. diff --git a/plugins/mattstack/plugin/skills/extending-a-pack/props.md b/plugins/mattstack/plugin/skills/extending-a-pack/props.md index 06267d0e82..5243ee3ded 100644 --- a/plugins/mattstack/plugin/skills/extending-a-pack/props.md +++ b/plugins/mattstack/plugin/skills/extending-a-pack/props.md @@ -74,7 +74,7 @@ block. One fill may bind to any number of blocks. | MR preflight, fast checks, commit shape, description shape, labels | `stage-ship` and `ship`: the step blocks below, `domain-rules` | | CI job names, retry rules, triage | `stage-watch-ci` and `watch-ci`: `classify-triage-report`, `domain-rules`, `forge` | | what reviewers check | `review`, `self-review`, `receive-review`: `criteria` | -| which written rules a review is checked against, one verdict per rule | `review`, `self-review`, `receive-review`: `rule-selector` | +| which written rules a review is checked against, one verdict per rule; the check implement runs before self-review | `review`, `self-review`, `receive-review`, `stage-implement`: `rule-selector` | | how to answer review threads | `receive-review`: `reply-rules` | | fan-out rules for parallel agents | `shepherdr`: the root's `rules`, or a step block below | @@ -94,7 +94,7 @@ default. The other props: | `work/sub-agent-tiering` | `tiering` | replace | `model-tiering@1` | nothing | | `review/criteria`, `self-review/criteria`, `receive-review/criteria` | `criteria` | replace | `review-criteria@1` | nothing | | `review/reviewer`, `self-review/reviewer`, `receive-review/reviewer` | `reviewer` | replace | `reviewer-dispatch@1` | nothing | -| `review/rule-selector`, `self-review/rule-selector`, `receive-review/rule-selector` | `rule-selector` | replace | `rule-selector@1` | empty (no rule selection) | +| `review/rule-selector`, `self-review/rule-selector`, `receive-review/rule-selector`, `stage-implement/rule-selector` | `rule-selector` | replace | `rule-selector@1` | empty (no rule selection) | | `receive-review/reply-rules` | `reply-rules` | replace | `reply-rules@1` | nothing | | `shepherdr` | `tiering` | replace | `model-tiering@1` | `mattstack:model-tiering` | | `shepherdr` | `strategy` | replace | `execution-strategy@1` | `mattstack:execution-strategy` | @@ -103,6 +103,8 @@ default. The other props: A `rule-selector` fill resolves to `selector: none`, or three lines: `selector:` (a command with `{format}`), `verdicts:` (a command with `{selection}` and `{verdicts}`) and `fence:` (the info string of the reviewer's verdict block). +It may add an optional fourth line, `check: ` with `{base}`, +which only `stage-implement` runs; still `rule-selector@1`, since it is additive. A `shepherdr` door compiles with nothing bound; bind one of its three replace props only to swap in the pack's own fill. diff --git a/plugins/mattstack/skills/shepherdr/SKILL.md b/plugins/mattstack/skills/shepherdr/SKILL.md index 25f07bcd7f..fe6a6cb9e2 100644 --- a/plugins/mattstack/skills/shepherdr/SKILL.md +++ b/plugins/mattstack/skills/shepherdr/SKILL.md @@ -4,14 +4,14 @@ description: "Use when fanning work out across parallel Claude Code agents in he allowed-tools: - "Bash(*/scripts/pick-account.py:*)" metadata: - compiled: "mattstack@0.32.32 + mattstack:model-tiering@0.32.32 + mattstack:execution-strategy@0.32.32 + mattstack:cswap-accounts@0.32.32" + compiled: "mattstack@0.32.33 + mattstack:model-tiering@0.32.33 + mattstack:execution-strategy@0.32.33 + mattstack:cswap-accounts@0.32.33" --- -Pointers here are `@keys`. Resolve them once per run: if you already hold a `skills_resolve` map that covers `mattstack@0.32.32:shepherdr`, use it; otherwise call `skills_resolve {id: "mattstack@0.32.32:shepherdr"}` and use the path it returns for each key, in anything you hand a subagent or a tool too. If it fails, stop and say so; never look for the file another way. +Pointers here are `@keys`. Resolve them once per run: if you already hold a `skills_resolve` map that covers `mattstack@0.32.33:shepherdr`, use it; otherwise call `skills_resolve {id: "mattstack@0.32.33:shepherdr"}` and use the path it returns for each key, in anything you hand a subagent or a tool too. If it fails, stop and say so; never look for the file another way. - + # shepherdr You are the shepherd: a thin delegator, not a reviewer. You break work into jobs, spawn an agent per job (own herdr pane, own git worktree), present what the daemon pushes, and route small messages between the user and the herd. Model, method and account are policy, answered by the bound skills below; you are transport. @@ -28,15 +28,15 @@ For herdr CLI mechanics, load the `herdr` skill. *If a rule below asks for a move this graph marks STOP, take the off-script edge instead.* - -For tiering, invoke the `mattstack:model-tiering` skill (mattstack:model-tiering@0.32.32) when this flow needs it. + +For tiering, invoke the `mattstack:model-tiering` skill (mattstack:model-tiering@0.32.33) when this flow needs it. - + ## Strategy *If a rule below asks for a move this graph marks STOP, take the off-script edge instead.* - + ### Execution Strategy Given a unit of work and the surface it will execute on, name the method @@ -127,7 +127,7 @@ for you -- name the strategy and pass it, nothing more. Either way, do not compose method prose per job; the bodies carry the worker-boundary rules and the report contract. - + ## Domain rules Domain rules are optional: a pack binds them here or at a step. Bound @@ -141,7 +141,7 @@ names keeps this skill's default as written. *A domain rule sits here or in its step's own section; if one asks for a move this graph marks STOP, take the off-script edge instead.* - + ## Accounts *If a rule below asks for a move this graph marks STOP, take the off-script edge instead.* @@ -153,7 +153,7 @@ question, the per-spawn pick (passed as `account` on `herd_spawn` or `herd_respawn`), and the exhaustion decision tree. Accounts in use are each job's `account` in `herd_status`, never memory. - + ### cswap account pool Given the herd's model mix and the accounts already assigned this run, @@ -222,7 +222,7 @@ cache is a shared symlink), so a worker pane missing a plugin's tools is a real failure: check the pane's plugin list and the shared cache instead of dismissing it. - + ## Start and spawn Walk this graph from the trigger; a move it does not show goes to the shepherd off-script gate. @@ -318,7 +318,7 @@ digraph shepherdr_start { } ``` - + ### Specify the jobs **Domain hook -- intake.** Unbound: the jobs are what the user hands you; @@ -348,7 +348,7 @@ keep it out of the user's checkout, and the delegator rules then do not apply. Apply the bound rules' single-worker exception if they name one. A later job for a live herd is never this case. - + ### Ask the strategy and model per job Strategy predicts the work shape, and the shape predicts the tier: one @@ -375,13 +375,13 @@ the strategy (its method skill is the brief's Method); the recommendation starts at the floor, the pin is a fixed half, and a spawn below the floor is wrong. - + ### Ask the account pool question Ask it once per herd, after the models are chosen: per-model pools hide headroom until the model mix is known. A later job for a live herd keeps the herd's pool answer. The Accounts section says when there is no question to ask. - + ### Collect the repo conventions A herd pane is a real `claude` session in a git worktree: user-level @@ -404,7 +404,7 @@ rules' method skill owns the conventions, `Repo conventions` names only the branch; a brief that restates gates, process or evidence competes with the worker's skill chain. - + ### Fix what the refusal names - **An unfilled marker**: the refusal lists the leftover slots; add a `fill` entry for each. @@ -414,7 +414,7 @@ worker's skill chain. Never copy the template or the strategies file elsewhere to get past a refusal; the retry budget hands a stubborn one to the off-script gate. - + ### Shepherd off-script gate: ask the user Every unresolved refusal and spent budget, in all three graphs, lands @@ -435,13 +435,13 @@ never a count from memory. A same-turn retry count kept in your head, since no daemon budget covers it; it answers yes once two retries have run. - + ### Make the recorded move once Make exactly the move the user took, once, as its value spells it. If it fails too, that is a new off-script gate, never a retry of your own. - + ## What the start graph cannot show **The herd contract.** Every herd is an rt daemon registry row plus one @@ -518,7 +518,7 @@ off-script gate. - **Stagger 4+ spawns**: spawn one, confirm it returned, spawn the next. - Agents never work in the user's checkout; skip isolation only for read-only jobs or when the user says to work in place. The worker's directory must be a **linked worktree**, which `herd_spawn` guarantees. - + ## The watch loop After the spawns, do nothing until something arrives. @@ -687,7 +687,7 @@ digraph shepherdr_watch { } ``` - + ### End the turn until something arrives The daemon pushes gates and room lines; nothing arms, and you never read a @@ -695,7 +695,7 @@ pane or scrollback. Your room posts deliver as `@here` and wake every worker, so a question for one worker is a DM. - + ### Present the open gates Present up to 4 open gates in one AskUserQuestion call. Options are the @@ -719,36 +719,36 @@ with `writeIn`, else ask them to pick. When the user parks a gate, from the job's `herd_status` row: `lastGate`, with `lastGateStatus: parked`; relay it verbatim. - + ### Say which answer won, in one line Name `winner.answers` and `winner.by`; never re-ask. - + ### Fix the answers: each value verbatim Resend each value from `invalid[].validValues`, verbatim. - + ### Pick the account per the accounts rules The Accounts section decides whether to respawn now or ask first; its pick is the `account` on `herd_respawn`. Announce the respawn. - + ### Report the stall to the user An expired login with no smart-distribute pool: only the user's `/login` fixes it. Name the job, its pane and the verdict. - + ### Ask: attend or respawn A dialog the watchdog could not clear parks the job (`stuck-at-modal`). **Attend** opens the pane for the user; **Respawn** reuses the stored brief. - + ### Point the user at the job's tab The job's pane in `herd_status` has no `bg:` prefix: the herd is visible, @@ -757,20 +757,20 @@ which opens tabs only for a hidden herd's panes, would refuse. Tell the user in one message which job, its pane ref and tab, and what waits on them (the diagnosis reason, or the parked dialog). - + ### Report the crash with its job and pane The pane died with the job live. Tell the user both; never respawn silently. - + ### Ask: let them finish, kill and respawn, or hold One sentence naming the running agents, then the bare three options: **Let them finish** (recommended) / **Kill and respawn with the new briefs** / **Hold**. No restated heading, no per-option descriptions. - + ## What the watch loop cannot show - **The push is transport.** A gate push is one line, `[gate] is now open; re-read the gate registry.`, carrying only an id. Its arrival proves the daemon, the subscription and the herd; the `herd_gates` read is the verification, made first. `herd_gates` defaults to `HERD_ID` or the sole active herd and also returns open pipeline-run gates in a herd job's worktree. Room lines arrive the same way (` #: ` a report, ` #: milestone: ` a milestone). A stale id or an unrelated room line is normal, never a reason to reach for another command or distrust the push. @@ -800,7 +800,7 @@ brief unless `brief` is new, and keeps the job's model, effort and account unless passed. The old session's open and parked gates close as abandoned so the new worker re-asks; answered ones are marked consumed. - + ## Lanes and wrap-up ```dot @@ -920,13 +920,13 @@ digraph shepherdr_lanes { } ``` - + ### Flag the drift or collision to the user Files outside the job's write fence are drift; a file two jobs changed is a collision. Flag it now, not at integration. - + ### Relay only what you measured A worker's claims about its environment (servers up, ports free, CI green) @@ -934,7 +934,7 @@ are routinely stale. Measure first (`rt_verb {args: ["endpoint", "lookup", "", "--path", ""]}`, `curl`, `lsof`, a CI status call), or attribute it: "the worker reports X". - + ### Ask the integration job's strategy and model One AskUserQuestion like every job's: the tier table's integration row is @@ -942,14 +942,14 @@ the recommendation, the strategy half from the strategy table. Keep the herd's pool answer and pass the Accounts section's per-spawn pick as `account`. - + ### Gate: merge this lane? Only when bound domain rules give the shepherd the merge. One sentence with the PR or MR link, its state and its CI, then **Merge** / **Not yet** / **Hold**. - + ### Flip the lane's ticket, when it has one Flip it just before `herd_close`, for each lane an integration report @@ -958,7 +958,7 @@ merges. Only you close a done job's pane. The watchdog nags past skipped; for a lane awaiting the integration job or a merge gate it is normal, so end the turn. - + ### Show the status table Reformat `herd_status {herd}`, flagging failures and the latest @@ -970,7 +970,7 @@ Reformat `herd_status {herd}`, flagging failures and the latest | api tests | w3:p1 | 2 | direct-tdd | done | A1-A4 done, 12 tests, suite green | ``` - + ### Gate wrap-up: the form contract One form, per the wrap-up form contract below: @@ -984,7 +984,7 @@ One form, per the wrap-up form contract below: Never auto-remove a tree or job dir; `herd_wrap_up` executes exactly the form's answer. - + ### Measure what still runs The stop calls cover every job in the dispose list or with a closing pane: @@ -1005,13 +1005,13 @@ Measure before you say a job's servers stopped (`lsof -ti tcp:` or the endpoint lookup). Report a survivor as still running, never kill it by hand, and anything unmeasured as "not verified". - + ### Report the refusal in the guard's words Quote the disposal refusal as the guard gave it. In hidden mode, also offer the Bash command `rt herd stop --hidden` (no tool runs it); never run it unprompted. - + ## What the lanes graph cannot show - **The two objective checks.** `herd_lanes {herd}` returns a row per active job (`commits`; `drift.files`, committed and uncommitted work since the merge base; `collidesWith`) plus herd-wide `collisions`. Compare each job's `drift.files` against its write fence yourself; no fence is stored. A job whose tree is gone has no row (it is in `skipped` with a reason), and the drift check skips it. @@ -1021,12 +1021,12 @@ the Bash command `rt herd stop --hidden` (no tool runs it); never run it unpromp - **Domain hook: after the report.** Unbound: the integration job merges. Bound domain rules may define what follows a report (the worker ships through its own skill chain, the shepherd merges after a gate, or a human merges on the forge and the lane closes when `herd_lanes` reads `merged`; how jobs feeding one deliverable integrate) and whether it waits for the user to ask. Fixing and pushing stay with workers. - **Domain hook: wrap-up.** Unbound: as drawn. Bound domain rules may state their own tree lifecycle (trees that dispose themselves on merge, what a disposal refusal means); follow it over the defaults here. - + ## wrap-up form contract *If a rule below asks for a move this graph marks STOP, take the off-script edge instead.* - + ### Wrap-up The reply is one optional sentence of context, then a form, then stop. Wait @@ -1055,7 +1055,7 @@ next call after the answers return, never into the context sentence. | "I can hand them a default to save them answering" | Recommended options already do that in the form; a typed reply still costs more than a tap and leaves no record of the pick. | | "The context sentence, then a line introducing the form" | Two sentences. The form needs no introduction; the sentence is the whole preamble. | - + ## Rationalizations | Thought | Reality | diff --git a/plugins/mattstack/skills/shepherdr/compiled.json b/plugins/mattstack/skills/shepherdr/compiled.json index c01ffcd4e0..e7fabad9bf 100644 --- a/plugins/mattstack/skills/shepherdr/compiled.json +++ b/plugins/mattstack/skills/shepherdr/compiled.json @@ -1,8 +1,8 @@ { - "id": "mattstack@0.32.32:shepherdr", + "id": "mattstack@0.32.33:shepherdr", "dir": "skills/shepherdr", "covers": [ - "mattstack@0.32.32:shepherdr" + "mattstack@0.32.33:shepherdr" ], "keys": { "shepherdr/SKILL.md": "skills/shepherdr/SKILL.md", diff --git a/plugins/mattstack/skills/wrap-up/SKILL.md b/plugins/mattstack/skills/wrap-up/SKILL.md index bc6b638e82..1ca0dda6c0 100644 --- a/plugins/mattstack/skills/wrap-up/SKILL.md +++ b/plugins/mattstack/skills/wrap-up/SKILL.md @@ -2,12 +2,12 @@ name: "wrap-up" description: "Use when wrapping up a session, checking in before continuing, ending a turn with open decisions, when the user asks what you need from them, what decisions are open, or what the next steps are, when they invoke wrap-up or check-in, or when a pipeline gate needs its decision presented as a form." metadata: - compiled: "mattstack@0.32.32" + compiled: "mattstack@0.32.33" --- - + # Wrap-up The reply is one optional sentence of context, then a form, then stop. Wait diff --git a/plugins/mattstack/skills/wrap-up/compiled.json b/plugins/mattstack/skills/wrap-up/compiled.json index 3a7782891a..bd0645a34c 100644 --- a/plugins/mattstack/skills/wrap-up/compiled.json +++ b/plugins/mattstack/skills/wrap-up/compiled.json @@ -1,8 +1,8 @@ { - "id": "mattstack@0.32.32:wrap-up", + "id": "mattstack@0.32.33:wrap-up", "dir": "skills/wrap-up", "covers": [ - "mattstack@0.32.32:wrap-up" + "mattstack@0.32.33:wrap-up" ], "keys": {} } diff --git a/plugins/mattstack/skills/writing-style-conversational/SKILL.md b/plugins/mattstack/skills/writing-style-conversational/SKILL.md index 5c6868f0e4..923b22b838 100644 --- a/plugins/mattstack/skills/writing-style-conversational/SKILL.md +++ b/plugins/mattstack/skills/writing-style-conversational/SKILL.md @@ -2,27 +2,27 @@ name: "writing-style-conversational" description: "Use only when the mattstack writing-style lookup names mattstack:writing-style-conversational, or falls back to it because the lookup failed or the skill it named will not load. The voice for review comments, replies, PR descriptions and commit messages posted under the operator's name: short, friendly sentences in sentence case, like talking to a teammate." metadata: - compiled: "mattstack@0.32.32" + compiled: "mattstack@0.32.33" --- -Pointers here are `@keys`. Resolve them once per run: if you already hold a `skills_resolve` map that covers `mattstack@0.32.32:writing-style-conversational`, use it; otherwise call `skills_resolve {id: "mattstack@0.32.32:writing-style-conversational"}` and use the path it returns for each key, in anything you hand a subagent or a tool too. If it fails, stop and say so; never look for the file another way. +Pointers here are `@keys`. Resolve them once per run: if you already hold a `skills_resolve` map that covers `mattstack@0.32.33:writing-style-conversational`, use it; otherwise call `skills_resolve {id: "mattstack@0.32.33:writing-style-conversational"}` and use the path it returns for each key, in anything you hand a subagent or a tool too. If it fails, stop and say so; never look for the file another way. - + # Conversational Short, friendly, and plain, like talking to a teammate across a desk. Load this before the first draft and write in it from the first word. - + ## Rules every style shares These bind anything posted under the operator's name: review findings, the review summary, replies on their own PR, PR descriptions, commit messages. The preset sets the voice; these set the floor. - + ### Never - **Em or en dashes.** Rephrase, or use parentheses, a colon, or an ellipsis @@ -40,7 +40,7 @@ The preset sets the voice; these set the floor. noticed:", "Took a look", "I just wanted to". Start with the claim. - **Invented precision.** "most" beats "~96%" unless the number was measured. - + ### Always - **Compress before posting.** The first draft is a rough cut. Before posting @@ -73,7 +73,7 @@ The preset sets the voice; these set the floor. notes. It never recaps a finding, lists strengths, or reports what you ran. A finding with no line to anchor to is its own top-level comment. - + ## Voice - **Sentence case** everywhere, with contractions. @@ -88,7 +88,7 @@ The preset sets the voice; these set the floor. Compression target: would this read naturally if you said it out loud to the author? Cut anything you would not say. - + ## Review findings Open with a bolded Conventional Comments label, never a code span @@ -110,13 +110,13 @@ const pageCount = Math.ceil(total / pageSize); A process ask is one line that leads with the approval if there is one: `**suggestion:** Looks good! Could you add a test for the empty-list case?` - + ## Review summary One line: `Looks good to me, no blockers. Left a few comments inline.` Only a blocker joins it. - + ## Replies on your own PR One to three short sentences. No sign-offs; thank someone only if they @@ -127,12 +127,12 @@ matters. - `Good call, switched to Record.` - `I'd skip the lock for now. The job runs on one worker, and a lock adds a round trip per write.` - + ## PR descriptions Read `@writing-style-conversational/pr-description.md` before drafting. - + ## Commit messages - Subject: imperative, sentence case, under 72 characters, with the ticket diff --git a/plugins/mattstack/skills/writing-style-conversational/compiled.json b/plugins/mattstack/skills/writing-style-conversational/compiled.json index 1387d77b49..7bf853f63e 100644 --- a/plugins/mattstack/skills/writing-style-conversational/compiled.json +++ b/plugins/mattstack/skills/writing-style-conversational/compiled.json @@ -1,8 +1,8 @@ { - "id": "mattstack@0.32.32:writing-style-conversational", + "id": "mattstack@0.32.33:writing-style-conversational", "dir": "skills/writing-style-conversational", "covers": [ - "mattstack@0.32.32:writing-style-conversational" + "mattstack@0.32.33:writing-style-conversational" ], "keys": { "writing-style-conversational/pr-description.md": "skills/writing-style-conversational/pr-description.md" diff --git a/plugins/mattstack/skills/writing-style-sparse/SKILL.md b/plugins/mattstack/skills/writing-style-sparse/SKILL.md index 44f52bd5df..e966c83dd7 100644 --- a/plugins/mattstack/skills/writing-style-sparse/SKILL.md +++ b/plugins/mattstack/skills/writing-style-sparse/SKILL.md @@ -2,28 +2,28 @@ name: "writing-style-sparse" description: "Use only when the mattstack writing-style lookup names mattstack:writing-style-sparse. The voice for review comments, replies, PR descriptions and commit messages posted under the operator's name: terse, lowercase technical prose, one tight paragraph per point." metadata: - compiled: "mattstack@0.32.32" + compiled: "mattstack@0.32.33" --- -Pointers here are `@keys`. Resolve them once per run: if you already hold a `skills_resolve` map that covers `mattstack@0.32.32:writing-style-sparse`, use it; otherwise call `skills_resolve {id: "mattstack@0.32.32:writing-style-sparse"}` and use the path it returns for each key, in anything you hand a subagent or a tool too. If it fails, stop and say so; never look for the file another way. +Pointers here are `@keys`. Resolve them once per run: if you already hold a `skills_resolve` map that covers `mattstack@0.32.33:writing-style-sparse`, use it; otherwise call `skills_resolve {id: "mattstack@0.32.33:writing-style-sparse"}` and use the path it returns for each key, in anything you hand a subagent or a tool too. If it fails, stop and say so; never look for the file another way. - + # Sparse Terse and conversational. The reader is a colleague who can follow a chain from one sentence. Load this before the first draft and write in it from the first word; it is not a pass applied to a finished draft. - + ## Rules every style shares These bind anything posted under the operator's name: review findings, the review summary, replies on their own PR, PR descriptions, commit messages. The preset sets the voice; these set the floor. - + ### Never - **Em or en dashes.** Rephrase, or use parentheses, a colon, or an ellipsis @@ -41,7 +41,7 @@ The preset sets the voice; these set the floor. noticed:", "Took a look", "I just wanted to". Start with the claim. - **Invented precision.** "most" beats "~96%" unless the number was measured. - + ### Always - **Compress before posting.** The first draft is a rough cut. Before posting @@ -74,7 +74,7 @@ The preset sets the voice; these set the floor. notes. It never recaps a finding, lists strengths, or reports what you ran. A finding with no line to anchor to is its own top-level comment. - + ## Voice - **Lowercase for technical content**: findings, assertions, code talk. @@ -93,7 +93,7 @@ Compression target: shorter and more conversational. Ask "would a busy teammate send this as written, or trim it first?" If there is any doubt, trim. - + ## Review findings Open with a bolded Conventional Comments label, never a code span: @@ -140,14 +140,14 @@ A brief, specific credit is fine folded in after the worry, never as the opener: `**thought (non-blocking):** only worry here: nothing tests the fallback. the version's pinned now, nice catch.`. A bare compliment is not. - + ## Review summary One line, sentence case: `Looks solid to me, no blockers. Left a few inline notes.` or `Left a few comments!` Only a blocker may join it: `Left one blocker inline.` - + ## Replies on your own PR Very short. No sign-offs, no thanks unless they thanked first. Soften even @@ -162,13 +162,13 @@ blank-line paragraphs. - `i don't think we need a lock here. the job runs on one worker, and a lock adds a round trip per write.` - `👍` - + ## PR descriptions Read `@writing-style-sparse/pr-description.md` before drafting. It carries the length target, the structure, and the anti-patterns. - + ## Commit messages - Subject: lowercase, imperative, under 72 characters, prefixed with the diff --git a/plugins/mattstack/skills/writing-style-sparse/compiled.json b/plugins/mattstack/skills/writing-style-sparse/compiled.json index 5ea3305353..f9aea9b342 100644 --- a/plugins/mattstack/skills/writing-style-sparse/compiled.json +++ b/plugins/mattstack/skills/writing-style-sparse/compiled.json @@ -1,8 +1,8 @@ { - "id": "mattstack@0.32.32:writing-style-sparse", + "id": "mattstack@0.32.33:writing-style-sparse", "dir": "skills/writing-style-sparse", "covers": [ - "mattstack@0.32.32:writing-style-sparse" + "mattstack@0.32.33:writing-style-sparse" ], "keys": { "writing-style-sparse/pr-description.md": "skills/writing-style-sparse/pr-description.md" diff --git a/plugins/mattstack/skills/writing-style-structured/SKILL.md b/plugins/mattstack/skills/writing-style-structured/SKILL.md index e183e0ee19..0caa52d99d 100644 --- a/plugins/mattstack/skills/writing-style-structured/SKILL.md +++ b/plugins/mattstack/skills/writing-style-structured/SKILL.md @@ -2,28 +2,28 @@ name: "writing-style-structured" description: "Use only when the mattstack writing-style lookup names mattstack:writing-style-structured. The voice for review comments, replies, PR descriptions and commit messages posted under the operator's name: labelled lines and short bullets for teams that prefer formal write-ups." metadata: - compiled: "mattstack@0.32.32" + compiled: "mattstack@0.32.33" --- -Pointers here are `@keys`. Resolve them once per run: if you already hold a `skills_resolve` map that covers `mattstack@0.32.32:writing-style-structured`, use it; otherwise call `skills_resolve {id: "mattstack@0.32.32:writing-style-structured"}` and use the path it returns for each key, in anything you hand a subagent or a tool too. If it fails, stop and say so; never look for the file another way. +Pointers here are `@keys`. Resolve them once per run: if you already hold a `skills_resolve` map that covers `mattstack@0.32.33:writing-style-structured`, use it; otherwise call `skills_resolve {id: "mattstack@0.32.33:writing-style-structured"}` and use the path it returns for each key, in anything you hand a subagent or a tool too. If it fails, stop and say so; never look for the file another way. - + # Structured Clear and scannable, for teams that like formal write-ups. Every point is labelled so a reader can triage without reading the whole thing. Load this before the first draft and write in it from the first word. - + ## Rules every style shares These bind anything posted under the operator's name: review findings, the review summary, replies on their own PR, PR descriptions, commit messages. The preset sets the voice; these set the floor. - + ### Never - **Em or en dashes.** Rephrase, or use parentheses, a colon, or an ellipsis @@ -41,7 +41,7 @@ The preset sets the voice; these set the floor. noticed:", "Took a look", "I just wanted to". Start with the claim. - **Invented precision.** "most" beats "~96%" unless the number was measured. - + ### Always - **Compress before posting.** The first draft is a rough cut. Before posting @@ -74,7 +74,7 @@ The preset sets the voice; these set the floor. notes. It never recaps a finding, lists strengths, or reports what you ran. A finding with no line to anchor to is its own top-level comment. - + ## Voice - **Sentence case**, complete but short sentences. @@ -87,7 +87,7 @@ The preset sets the voice; these set the floor. Compression target: every line earns its label. Cut any line a reader could skip without missing the ask. - + ## Review findings Open with a bolded Conventional Comments label, never a code span, then @@ -107,13 +107,13 @@ const pageCount = Math.ceil(total / pageSize); Use only the lines that carry something: a `nitpick` is the label and one line. A process ask is one line. - + ## Review summary One line: `No blockers. Inline notes on paging and tests.` Only a blocker joins it: `One blocker inline (page count).` - + ## Replies on your own PR One or two sentences, plain and direct. No thanks opener. State the outcome @@ -122,12 +122,12 @@ first. - `Changed to Record.` - `Skipping the lock: the job runs on one worker, and a lock adds a round trip per write.` - + ## PR descriptions Read `@writing-style-structured/pr-description.md` before drafting. - + ## Commit messages - Subject: imperative, sentence case, under 72 characters, with the ticket diff --git a/plugins/mattstack/skills/writing-style-structured/compiled.json b/plugins/mattstack/skills/writing-style-structured/compiled.json index 3c521b41b2..3eb3da344a 100644 --- a/plugins/mattstack/skills/writing-style-structured/compiled.json +++ b/plugins/mattstack/skills/writing-style-structured/compiled.json @@ -1,8 +1,8 @@ { - "id": "mattstack@0.32.32:writing-style-structured", + "id": "mattstack@0.32.33:writing-style-structured", "dir": "skills/writing-style-structured", "covers": [ - "mattstack@0.32.32:writing-style-structured" + "mattstack@0.32.33:writing-style-structured" ], "keys": { "writing-style-structured/pr-description.md": "skills/writing-style-structured/pr-description.md"