diff --git a/plugins/chalk/.claude-plugin/plugin.json b/plugins/chalk/.claude-plugin/plugin.json index 833e585..d1a25ca 100644 --- a/plugins/chalk/.claude-plugin/plugin.json +++ b/plugins/chalk/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { "name": "chalk", - "version": "0.13.0", + "version": "0.14.0", "description": "Capture intent across issues, commits, and PRs — why, not just what" } diff --git a/plugins/chalk/README.md b/plugins/chalk/README.md index 3b181ae..a3aa6cb 100644 --- a/plugins/chalk/README.md +++ b/plugins/chalk/README.md @@ -57,8 +57,13 @@ Chalk also auto-activates when you mention a GitHub issue number (e.g. "#123"). - **Skill** (`issue`): Problem-focused issue descriptions, and keeping them accurate - **Skill** (`commit`): Contextual commits that capture the why, with chalk integration - **Skill** (`pr`): Pull requests with intent-driven descriptions +- **Skill** (`voice`): The shared writing voice — Diataxis quadrants, universal principles, the issue/PR section palette +- **Skill** (`mindmap`): The shape of anything the reader has to follow — nested bullets whose parents are claims and whose children back them up +- **Skill** (`goal-tree`): Goal trees, where children accomplish their parent rather than argue for it, and each node is tested for sufficiency - **Agent** (`github`): Handles all GitHub API interaction, keeping the main context clean +The writing skills are loaded by the others rather than run directly, though you can read any of them yourself with `/chalk:voice`, `/chalk:mindmap` or `/chalk:goal-tree`. + ## Permissions Chalk needs permission to run `gh` commands. diff --git a/plugins/chalk/skills/chalk/SKILL.md b/plugins/chalk/skills/chalk/SKILL.md index 89fbeb8..c71a328 100644 --- a/plugins/chalk/skills/chalk/SKILL.md +++ b/plugins/chalk/skills/chalk/SKILL.md @@ -15,8 +15,14 @@ Interpret MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, etc. per RFC 2119. Every chalk comment, progress section, issue description, and PR description you touch in this session MUST be drafted in the chalk voice — not your own default prose habits, which read wrong and lose the reasoning the reader needs. `chalk` carries the issue-tracking mechanics, not the writing voice. -Before drafting any such prose, **load the `chalk:voice` skill** (via the Skill tool) — it holds the Diataxis framing, the universal principles, and the issue/PR section palette. -Then structure the body into sections drawn from that palette, choosing the ones the artefact needs. +Before drafting any such prose, load these (via the Skill tool): + +- **`chalk:voice`** — the Diataxis framing, the universal principles, and the issue/PR section palette. Structure the body into sections drawn from that palette, choosing the ones the artefact needs. +- **`chalk:mindmap`** — the shape of the content inside each section, and of each `
` block, which behaves like a bullet. +- **`chalk:goal-tree`** — when the artefact carries the direction of the work rather than its history. + +**Your audience is the next session on this issue** — a teammate, or you, or an agent starting cold with only the issue in front of it. +That's the most literal case of the rule in "Name your audience" (`chalk:voice`): a comment written for whoever already sat through this session is a comment that helps nobody, because by definition they've gone. Two artefacts have their own skill carrying rules beyond the voice — load it instead of drafting from here: @@ -218,7 +224,7 @@ No date in the header — GitHub timestamps the comment itself. - Add new items as work emerges. - Keep details blocks focused — one per theme or work item. -**Writing style**: each `
` block is an **explanation** chunk — what was explored, decided, tried. The checklist above is navigation, not a separate quadrant. Follow the explanation-quadrant voice in the `chalk:voice` skill. +**Writing style**: each `
` block is an **explanation** chunk — what was explored, decided, tried. The checklist above is navigation, not a separate quadrant. Follow the explanation-quadrant voice in the `chalk:voice` skill, and shape the contents as a mindmap per `chalk:mindmap` — the summary line is the block's subject line and carries the same contract, so a reader who only reads the summaries still follows the session. Details blocks should read like knowledge-sharing, not a changelog. ## Lifecycle of a Comment @@ -260,4 +266,4 @@ See `examples/implementation-comment.md` for a realistic filled-in example. - All GitHub interaction MUST go through the chalk agent. The main context MUST NOT call `gh` directly for chalk updates. - The issue description MUST be kept accurate — update facts when they change, but preserve the user's framing and intent. - `
` blocks MUST contain enough context that a future session can pick up where you left off. -- All writing MUST follow the voice in the `chalk:voice` skill — issues, PRs, and chalk comments are explanation artefacts. +- All writing MUST follow the voice in the `chalk:voice` skill — issues, PRs, and chalk comments are explanation artefacts — and MUST be shaped per `chalk:mindmap`. diff --git a/plugins/chalk/skills/commit/SKILL.md b/plugins/chalk/skills/commit/SKILL.md index 85d5abe..9c2a963 100644 --- a/plugins/chalk/skills/commit/SKILL.md +++ b/plugins/chalk/skills/commit/SKILL.md @@ -14,8 +14,14 @@ The user will provide the commit headline as an argument to this command (e.g., ## Before you draft The commit body is an **explanation** artefact and MUST be drafted in the chalk voice, not your own default prose habits. -`chalk:commit` loads on its own and does **not** pull the shared voice into context, so before writing the body, **load the `chalk:voice` skill** (via the Skill tool) for the Diataxis framing and the concrete-over-abstract examples. -Unlike a PR, a commit body is a single explanation, not a sectioned document — there's no palette to apply, just the voice. +`chalk:commit` loads on its own and pulls in neither, so before writing the body, load both (via the Skill tool): + +- **`chalk:voice`** — the Diataxis framing, the universal principles, and the concrete-over-abstract examples. +- **`chalk:mindmap`** — the shape of the body. A commit body is not prose. + +**A commit body is a lead-in line, then a mindmap** — the rules are under "Commit bodies" in `chalk:mindmap`. +What's specific to this skill is *why* it has no palette to apply: unlike a PR, a commit covers one atomic change, so it's a single explanation rather than a sectioned document. +Needing sections is a signal the commit is too big, or that you're writing the PR description in the wrong place. **Line format: paragraph-per-line** by default. A commit body is read rendered (`git log`, GitHub, a PR commit list), never as a `git diff`, so put each paragraph on a single line and separate paragraphs with a blank line — sentence-per-line would fragment into `
` staccato when rendered. @@ -39,9 +45,10 @@ Some projects override this and ask for sentence-per-line in commit messages; fo A commit body is an **explanation** artefact (see the `chalk:voice` skill). The diff is the code change; the body explains *why* it exists — decisions, alternatives rejected, constraints, dead ends, counter-intuitive findings, scope boundaries. - Open with the problem or context, then the reasoning. Embed concrete examples (code snippets, call sites, specific scenarios) as illustrative material. + Open with the lead-in line, then shape the reasoning per "Commit bodies" in `chalk:mindmap`. + 4. **Ask clarifying questions** if you can't reconstruct the *why* from the conversation history — particularly around whether something was a deliberate choice vs. a constraint, or intentionally out-of-scope vs. overlooked. 5. **Make the commit** directly with the commit body you've drafted: @@ -71,7 +78,8 @@ When chalk is active (tracking a GitHub issue), the commit is part of a larger s ## Constraints -- The commit body MUST follow the explanation-quadrant voice in the `chalk:voice` skill. +- The commit body MUST follow the explanation-quadrant voice in the `chalk:voice` skill, and MUST be shaped as a mindmap per `chalk:mindmap` — a lead-in line, then the tree. +- The commit body MUST NOT contain headings. A tl;dr is optional — the subject line normally serves as one. - Each commit MUST be an atomic, cohesive unit of change. - Unrelated changes MUST NOT be staged together. - The commit body MUST NOT describe what changed — the diff shows that. diff --git a/plugins/chalk/skills/goal-tree/SKILL.md b/plugins/chalk/skills/goal-tree/SKILL.md new file mode 100644 index 0000000..64b6747 --- /dev/null +++ b/plugins/chalk/skills/goal-tree/SKILL.md @@ -0,0 +1,90 @@ +--- +name: goal-tree +description: Structure a goal as a tree whose children accomplish their parent rather than argue for it, and test each node for sufficiency. Load whenever writing something with a goal structure in it — the direction or target end state of a piece of work, an issue's Implementation or Future state section, the shape of a problem, or a plan. Covers the sufficiency test, the three kinds of leaf, and the named moves for closing a gap. The chalk, chalk:issue and chalk:pr skills load it alongside chalk:mindmap. +user-invocable: true +--- + +# Chalk Goal Trees + +Interpret MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, etc. per RFC 2119. + +A goal tree is a mindmap whose relation is **serves**, not **supports**. +Load `chalk:mindmap` first — subject lines, bolding, shallow nesting, tags and typed IDs all apply here unchanged. +What this skill adds is the completeness test that only a goal tree can support. + +## The shape + +**The root is the goal.** +Each node's children are what it takes to achieve it, recursively, down to leaves that are directly actionable. + +The distinction from an argument tree is the whole reason this is a separate skill: **children don't argue for a parent goal, they accomplish it.** +An argument tree's children are evidence, and you can only ever check whether they're *sound*. +A goal tree's children are work, and a goal states what its children have to add up to — so completeness becomes a real question with a real answer. + +## The test at each node is sufficiency + +**Assume every child is done, then ask whether the parent is thereby achieved.** + +Not "do these look related to the parent?" but "do these, **plus what we already know about this system**, get us there?" + +- **The domain knowledge is part of the test.** Half the children in a real tree are only sufficient because of something existing behaviour already guarantees — say that out loud rather than leaning on it silently, because it's exactly the assumption that stops holding. +- **Read bottom-up it's induction.** If each child achieves its part and the children are sufficient, the parent holds, and the root goal is sound. +- **Reason about it explicitly at each node** rather than assuming. `check:` any node where you're unsure the children cover it. +- **This is why goal trees don't need the decomposition note** an argument tree needs (see `chalk:mindmap`). There the split rule is the only thing standing in for completeness; here the parent *is* the yardstick. + +**To find a missing child, ask what would stop the parent** rather than what would achieve it. +Enumerating the obstacles to a goal surfaces children that "how do we achieve this?" doesn't. + +## Every leaf is one of three things — say which + +- **Something we do.** The ordinary case. +- **Something expected of someone or something else** — the user, CI, another team, an upstream library, existing behaviour. +- **A plain fact about the world** we're relying on. + +**The middle one is where plans quietly fail**, because an expectation written like a task is a dependency nobody owns. +It reads as covered, it sits in the tree looking like work, and nothing happens until someone notices it was never assigned. + +`assumption:` covers whether a leaf has been *verified*; this is the separate question of who's *on the hook*. +A leaf can be both — a verified fact about an upstream library is still someone else's to keep true. + +## A gap anywhere invalidates everything above it + +Surface it rather than patching around it. +A tree that looks complete because a hole got papered over is worse than one that admits the hole: the next reader trusts it. + +**Closing a gap has named moves — pick one deliberately** rather than reflexively adding a task: + +- **Achieve the parent a different way.** +- **Reassign it** to someone or something that won't fail like that. +- **Add a step that prevents it.** +- **Make it less likely** without eliminating it. +- **Let it happen and recover afterwards.** +- **Let it happen and limit the damage.** +- **Weaken the goal** so the gap no longer matters. +- **Accept the risk** and move on. + +**"Weaken the goal" and "accept the risk" are real answers**, and both MUST be recorded rather than dropped — in **Out of scope** or **Decision rationale**, per the palette in `chalk:voice`. +Scope that was deliberately cut is a decision someone will want the reasoning for later. +Scope that silently evaporated reads as an oversight, and a reader can't tell the two apart. + +## In an issue description + +**An issue's goal tree sits higher than a plan's.** +The issue answers what has to be true for this to be done; a plan answers which files to touch in what order. +Granular execution — which sub-task is next, what was tried — stays in the chalk comment, per the line the palette already draws. + +- **A child may be a link to another issue that owns that part.** This is how the tree stays high-level: `- [ ] Secondaries serve stale reads without blocking the primary — #412`. +- **If a child is doing real work, it probably wants to be a sub-issue.** Then the tree is a readable map *of* the sub-issue graph rather than a second copy of it that drifts. Wire the relationship, don't just write the link — see `chalk:issue`. +- **Palette placement**: **Implementation** for the direction, **Future state** for the target end state — and anywhere else a section has a goal structure to express. +- **A goal tree of the proposed solution is earned, not default.** The rule in `chalk:issue` applies unchanged: include it when the session genuinely worked the direction, and leave it out when the session was about noticing the problem. A speculative solution tree is the most authoritative-looking guess you can put on a card. +- **The `## Progress` checklist is not a goal tree.** It's chalk's flat record of work items and their status. Don't merge them, and don't restructure one into the other. + +## Constraints + +- Every node's children MUST be work that accomplishes it, not evidence that argues for it. If they argue, it's an argument tree — see `chalk:mindmap`. +- Each node MUST be tested for sufficiency, and any node whose children are not clearly sufficient MUST be marked `check:` rather than left to read as settled. +- A leaf MUST declare which of the three kinds it is where that isn't obvious. An expectation of someone else MUST NOT be written as though it were our own task. +- A gap MUST be surfaced rather than papered over. Closing it MUST be a deliberate choice from the named moves. +- Weakening the goal or accepting a risk MUST be recorded in Out of scope or Decision rationale — these are the two moves that leave no trace in the tree itself. +- A goal tree proposing a solution MUST NOT be written into an issue description the session didn't earn, per `chalk:issue`. +- A goal tree MUST NOT be written into or merged with the `## Progress` section. diff --git a/plugins/chalk/skills/issue/SKILL.md b/plugins/chalk/skills/issue/SKILL.md index a6f4063..0b43377 100644 --- a/plugins/chalk/skills/issue/SKILL.md +++ b/plugins/chalk/skills/issue/SKILL.md @@ -26,11 +26,20 @@ It does not track a session against the issue. An issue description is an **explanation** artefact, and it MUST be drafted against the chalk voice — not your own default prose habits, which read wrong and lose the reasoning the reader needs. -`chalk:issue` loads on its own and does **not** pull the shared voice into context. -Before drafting the body, **load the `chalk:voice` skill** (via the Skill tool) — it carries the Diataxis framing, the universal principles, and the issue/PR section palette. -Then **structure the body into sections drawn from that palette**, choosing the ones this issue needs. +`chalk:issue` loads on its own and pulls in none of the shared skills. +Before drafting the body, load these (via the Skill tool): + +- **`chalk:voice`** — the Diataxis framing, the universal principles, and the issue/PR section palette. +- **`chalk:mindmap`** — the shape of the content inside each section. +- **`chalk:goal-tree`** — wherever a section has a goal structure to express, and its children accomplish their parent rather than argue for it. + +Then **structure the body into sections drawn from that palette**, choosing the ones this issue needs, and **write each section as a mindmap** — a short tl;dr opening it, then the tree. A wall of undifferentiated prose is the wrong shape; if you've written one, you skipped this step. +**Your audience is whoever triages this card and whoever picks it up** — most often not you, and often months from now. +They are deciding whether it applies to them and whether it's workable today, from the description alone. +Write for someone who wasn't in the session that found the problem; see "Name your audience" in `chalk:voice`. + **Line format: paragraph-per-line.** An issue body is read rendered on GitHub, never as a `git diff`. GitHub renders single newlines as `
`, so sentence-per-line fragments into staccato — put each paragraph on a single line, separate paragraphs with a blank line, and let the rendering wrap. @@ -70,6 +79,10 @@ GitHub renders single newlines as `
`, so sentence-per-line fragments into st - **Leave them out** when the session was about *noticing* the problem. A guess at the fix, written up as though it were a decision, is worse than no section at all — the next reader can't tell your speculation from a conclusion. - **When a fix is obvious but unconsidered**, one line under the problem ("probably wants X") is enough. Don't inflate it into an Implementation section. + **Where you do include them, they take a goal tree** (`chalk:goal-tree`) rather than a flat list of tasks. + An issue's goal tree sits higher than a plan's — it answers what has to be true for this to be done, not which files to touch — and a child may be a link to the issue that owns that part, which is what keeps it high-level. + Wire that link as a sub-issue relationship too (step 6), so the tree maps the issue graph rather than duplicating it. + **The description is the source of truth.** A developer MUST be able to understand the current state of the issue by reading the description alone, without trawling the comments. @@ -111,7 +124,8 @@ The description is the source of truth, so it MUST be kept accurate as facts cha ## Constraints -- The issue body MUST follow the explanation-quadrant voice in the `chalk:voice` skill. +- The issue body MUST follow the explanation-quadrant voice in the `chalk:voice` skill, and each section MUST be shaped per `chalk:mindmap`. +- A section whose items accomplish their parent rather than argue for it MUST be shaped as a goal tree per `chalk:goal-tree` — Implementation and Future state, where earned, always are. - The body MUST be drafted in the main context and handed to the github agent ready to post verbatim. Passing bullet points and asking the agent to "write this up" is not acceptable — it pushes an explanation-quadrant job onto a model that can't do it well. - All GitHub interaction MUST go through the github agent. The main context MUST NOT call `gh issue` directly. - The description MUST be understandable on its own, without reading the comments. @@ -126,7 +140,7 @@ The description is the source of truth, so it MUST be kept accurate as facts cha 2. Establish the *why* and *why now*; ask if either is unclear 3. Search for an existing issue covering this 4. Gather the concrete evidence -5. Load `chalk:voice`, then draft the title and body against the problem-focused sections of the palette +5. Load `chalk:voice` and `chalk:mindmap` (and `chalk:goal-tree` if any section has a goal structure), then draft the title and body against the problem-focused sections of the palette 6. Ask any clarifying questions if needed 7. Delegate to the github agent to create the issue, and wire up any parent / blocked-by relationships 8. Report the issue number back to the user diff --git a/plugins/chalk/skills/mindmap/SKILL.md b/plugins/chalk/skills/mindmap/SKILL.md new file mode 100644 index 0000000..a1d6311 --- /dev/null +++ b/plugins/chalk/skills/mindmap/SKILL.md @@ -0,0 +1,143 @@ +--- +name: mindmap +description: How to structure anything the reader has to follow — a mindmap of nested bullets whose parents are claims and whose children back them up. Load before drafting any commit body, issue, PR description, chalk comment, code comment or docs section with more than a couple of steps of reasoning in it; the chalk, chalk:issue, chalk:commit, chalk:pr and chalk:tend-docs skills load it alongside chalk:voice. Also covers tags, typed cross-reference IDs, tl;dr placement, and the per-artefact rules for commit bodies and code comments. +user-invocable: true +--- + +# Chalk Mindmaps — Structuring What the Reader Must Follow + +Interpret MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, etc. per RFC 2119. + +You're reading this because you're about to write something with structure the reader has to follow. +This skill covers the *shape*; `chalk:voice` covers the register and the section palette. +Load both. + +## The default + +Anything the reader has to *follow* — a sequence of events, a multi-step rationale, a set of conditions, a decision and its grounds — **defaults to a mindmap: nested bullets forming a tree**, not a prose paragraph. + +Focus is the reader's scarce resource. +A tree lets them checkpoint their understanding as they go and jump straight to the branch they care about. +A dense paragraph makes them hold the whole chain in their head and trust they reassembled it the way you meant. + +Reserve prose for a short causal argument where the connectives ("because", "so", "but only when") carry the meaning and the chain is only two or three links long. +This is about the *followable* parts, not the tone — an explanation can still read discursively and lay its reasoning out as a tree. + +## The tree is a support structure + +**A parent is a claim; its direct children are what back it up.** + +- **Read downwards it's a summary** that expands on demand — the reader stops at whatever depth answers their question. +- **Read upwards it's an argument** — if each child holds, and the children are enough, the parent holds. +- **If the relation is *serves* rather than *supports*, you're writing a goal tree** — load `chalk:goal-tree`, which has its own completeness test. + +**An arbitrary bullet list is not a mindmap.** +The test: pick any node and ask whether its children *back it up*. +If they're merely *related* to it, you've written a flat list with indentation, and the reader gets no argument out of it. + +## Subject lines carry the reasoning + +Same contract as a git commit subject: **reading only the top line of each bullet must be enough to follow the whole argument.** +A paragraph underneath is *elaboration* — always an optional read, never load-bearing. +If the point only lands once the reader reaches the third sentence of the elaboration, the subject line has failed and the bullet needs rewriting, not expanding. + +- **One checkpoint per bullet.** Each bullet is a place the reader stops, confirms they've followed, and moves on. +- **Bold the load-bearing words.** The tree should be graspable from the bolded phrases alone, before a word of the surrounding prose is read. +- **Nest for sub-points, but stay shallow** — about two levels. A third level of indentation is usually its own wall, so promote it or flatten it. +- **Cut hard.** Less text beats better-formatted text — a bullet the reader doesn't need is noise, and noise hides the ones that matter. + +## Say how you decomposed a node + +Where a node's children aren't obviously exhaustive, **name the rule you split on** — "one per subsystem", "one per failure mode", "one per call site". + +An argument tree can demonstrate soundness but not completeness. +With nothing to test the child set against, **a missing sibling looks exactly like no sibling** — naming the rule at least makes the gap visible to the reader. + +This pays off most in the palette sections where a reader's next question is "is that all of them?": **Alternatives considered**, **Out of scope**, **Symptoms**. +Goal trees don't need it — there the parent *is* the yardstick (see `chalk:goal-tree`). + +## Tags + +**Prefix a bullet with a tag where it sharpens the point** — `goal:`, `pro:`, `con:`, `idea:`, `assumption:`, `check:`. + +- **The vocabulary is open.** These are the common ones; invent others where they carry meaning, and expect readers to do the same. +- **Tag a bullet and you've made a claim** — mean it precisely, per RFC 2119. `assumption:` says you haven't verified it. `check:` says it needs verifying before anyone relies on it. +- **The verification tags earn their place fastest in an issue.** An `assumption:` on a line in **Root cause** tells the reader it's unverified at a fraction of what prose would spend, and stops the next person building on it as though it were established. +- **Don't tag for the sake of it.** An untagged bullet is the norm; a tag is a signal, and signals dilute. + +## Cross-references + +**Give a node a typed ID where a reader might want to point at it in reply.** +The letter comes from the tag — `G1` for a goal, `D1` for a decision, `I1` for an idea — so the scheme extends itself as new tags appear. +Nest them to mirror the tree: `D2.1` is the first child of `D2`. + +- **Use them where reply-by-reference actually happens**: **Alternatives considered**, **Decision rationale**, **Open Questions**. Not every bullet everywhere — IDs on scaffolding are noise. +- **The reason they're worth it on GitHub**: there's no way to deep-link a bullet, so without IDs a reviewer has to quote your text back to you to disagree with one branch. With them they can answer `D2`, accept the rest, and the thread stays legible. +- **Where IDs already exist, cite them.** If an issue or PR numbers its nodes, refer back by ID rather than re-describing the node. +- **IDs beat numbered lists.** Inserting a sibling renumbers an ordered list and silently breaks every reference into it; an ID stays pinned to its node. + +## tl;dr + +**A tl;dr goes at the top.** +Every chalk artefact is read top-to-bottom — putting it at the bottom is a chat convention, where the reader scrolls upward. + +**The tl;dr is a mindmap too**, optionally opening with a single summary sentence: one top-level bullet per takeaway, subject lines carrying the point. +It's a summary of the argument, so it gets the same treatment as the argument. +"tl;dr" conventionally means a paragraph, which is the one reason this needs saying out loud. + +**Summarise the artefact for its audience, not the work for its author.** +This is the most common way a tl;dr fails, and it fails invisibly: recapping what you did and what changed since some earlier state is accurate, and useless to a reader who never saw that state. + +- **The tell**: the tl;dr only parses if you already know the history — a prior commit by SHA, a decision from the session, a "the missing half" that assumes the reader knows which half landed first. +- **The fix**: make the first bullet tell a cold reader what this *is* and what it means for them, and push the provenance down into the body where someone who wants it will find it. +- **Who that reader is** is settled in "Name your audience" in `chalk:voice` — for chalk artefacts, nearly always a teammate, which includes you in six months and a future agent session with no context. + +**In a commit body it's optional.** +The subject line usually does the job, so most bodies don't want one — but a long body whose argument needs summarising MAY open with a tl;dr, and then it's a mindmap like any other. +A code comment never wants one: the first line is it, per the subject-line rule. + +## Per artefact + +### Issues, PRs and chalk comments + +- **The palette decides which sections exist; the mindmap shapes what's inside them.** Draw sections from `chalk:voice`; then per section it's the heading, the mindmap, and a short tl;dr as its opening. +- **A `
` block behaves like a bullet** — its summary line is the subject line, and it carries the same contract. +- **Not every section wants a tree.** Two sentences of causal argument shouldn't be forced into one; the default is strong, not absolute. + +### Commit bodies + +- **No headings.** The tree's top-level bullets already partition the body, so a heading layer is a second, coarser structure doing the same job. Needing one is a signal the commit is too big. +- **Lead-in line, then the tree.** The lead-in sets up the problem or context; the tree carries the reasoning. +- **A tl;dr is optional and usually unnecessary** — the subject line normally covers it. Reach for one only when the body is long enough that its argument needs summarising before the reader starts it. +- **The tell that this was missed** is the same material coming out bulleted in a PR description and as prose in the commit that carries it. If you've just written the PR, the commit gets the same shape. + +### Code comments + +- **Only where the comment has structure to show** — more than two or three sentences, or an enumeration the reader has to work through. Most comments are one line and should stay one line: `// volatile — reads race with the flush thread` doesn't want a bullet. +- **Match the markup to what the language's tooling renders.** KDoc, Javadoc and docstrings are rendered, so bullets and emphasis land as intended. A bare `//` or `;;` comment is read raw — use plain `-` and indentation, and drop the bold, because `**like this**` is just noise in a source buffer. +- **No tl;dr** — the first line is it, per the subject-line rule. +- **`chalk:voice` still decides *what* belongs in the comment**: the current contract, not the story of how the code got here. The mindmap only shapes it. + +### Docs pages + +- **Same default, applied per section.** A section's steps, conditions or failure modes are followable content and take the tree. +- **The tree doesn't let a section straddle quadrants.** A how-to's numbered steps and an explainer's reasoning are both trees; they still belong in different sections. + +## Line format inside a bullet + +**Whatever line-break rule the calling skill states, it applies inside a bullet too** — this is where it's most often forgotten. +Like `chalk:voice`, this skill doesn't decide the rule: the skill you came from does, including any project override. + +- **Where it's paragraph-per-line**, a bullet's elaboration stays on **one line**. Breaking it sentence-per-line fragments into `
` staccato exactly as it would in a paragraph — same trap, new shape. +- **Where it's sentence-per-line**, break inside the bullet as normal. + +## Constraints + +- Followable content MUST default to a mindmap; prose MUST be a deliberate exception, not a fallback. +- Every parent node MUST be a claim its children back up. A bullet list whose children are merely *related* to the parent MUST be restructured. +- Subject lines MUST carry the argument on their own. Elaboration MUST NOT be load-bearing. +- A tag MUST be meant precisely — `assumption:` and `check:` are claims about verification status, not decoration. +- Typed IDs MUST be stable once published. Renaming or renumbering a node breaks inbound references and MUST be avoided. +- A tl;dr MUST go at the top of the artefact, never the bottom. It is optional in a commit body and MUST NOT appear in a code comment. +- A tl;dr MUST summarise the artefact for its audience, not the work for its author. It MUST be readable by someone who did not see the session, the branch or the prior state. +- Bold emphasis MUST NOT be used in comment markup that is read raw rather than rendered. diff --git a/plugins/chalk/skills/pr/SKILL.md b/plugins/chalk/skills/pr/SKILL.md index 424765c..15d7dc0 100644 --- a/plugins/chalk/skills/pr/SKILL.md +++ b/plugins/chalk/skills/pr/SKILL.md @@ -16,11 +16,22 @@ If no title is provided, draft one from the branch's commits. A PR description is an **explanation** artefact, and it MUST be drafted against the chalk voice — not your own default prose habits, which read wrong and lose the reasoning the reviewer needs. -`chalk:pr` loads on its own and does **not** pull the shared voice into context. -Before drafting the description, **load the `chalk:voice` skill** (via the Skill tool) — it carries the Diataxis framing, the universal principles, and the issue/PR section palette. -Then **structure the description into sections drawn from that palette**, choosing the ones this change needs. +`chalk:pr` loads on its own and pulls in neither of the shared skills. +Before drafting the description, load both (via the Skill tool): + +- **`chalk:voice`** — the Diataxis framing, the universal principles, and the issue/PR section palette. +- **`chalk:mindmap`** — the shape of the content inside each section. + +Then **structure the description into sections drawn from that palette**, choosing the ones this change needs, and **write each section as a mindmap** — a short tl;dr opening it, then the tree. A wall of undifferentiated prose is the wrong shape; if you've written one, you skipped this step. +**Also load `chalk:goal-tree`** where a section states what the work has to achieve rather than what it did — a Future state section, or the remaining steps of a change landing in pieces. +A PR's Implementation section is retrospective ("what landed") and doesn't want one. + +**Your audience is the team, not the author.** +A PR is the moment the rest of the team learns the change exists, so the reader arrives with none of your session's context and is deciding two things: whether this affects them, and whether the approach holds. +Write the summary for someone who has not seen the branch, the issue or the conversation — see "Name your audience" in `chalk:voice`, and the tl;dr rules in `chalk:mindmap`, which is where this most often goes wrong. + **Line format: paragraph-per-line.** A PR description is read rendered on GitHub, never as a `git diff`. GitHub renders single newlines as `
`, so sentence-per-line fragments into staccato — put each paragraph on a single line, separate paragraphs with a blank line, and let the rendering wrap. @@ -42,7 +53,7 @@ GitHub renders single newlines as `
`, so sentence-per-line fragments into st A PR description is an **explanation** artefact (see the `chalk:voice` skill) — reasoning distilled across the branch: context, decisions, tradeoffs, dead ends, scope boundaries. Usage examples, test-plan checklists and commit lists have a reference *shape* but they're illustrations inside the explanation, not separate reference sections. - Draw the sections from the palette in the `chalk:voice` skill you loaded in **Before you draft** above — don't default to flat prose. + Draw the sections from the palette in the `chalk:voice` skill you loaded in **Before you draft** above, and shape each one as a mindmap per `chalk:mindmap` — don't default to flat prose. **Issue references come first.** If there's a related issue, reference it at the top (`Resolves #123` or `Part of #123`). @@ -73,7 +84,7 @@ When chalk is tracking an issue: ## Constraints -- The PR description MUST follow the explanation-quadrant voice in the `chalk:voice` skill. +- The PR description MUST follow the explanation-quadrant voice in the `chalk:voice` skill, and each section MUST be shaped per `chalk:mindmap`. - The PR description MUST NOT just list what changed — the diff shows that. - Behaviour-preserving changes (refactorings) SHOULD be called out explicitly so the reviewer knows the change is supposed to behave exactly the same as before. diff --git a/plugins/chalk/skills/tend-docs/SKILL.md b/plugins/chalk/skills/tend-docs/SKILL.md index 4fa7c95..b652a32 100644 --- a/plugins/chalk/skills/tend-docs/SKILL.md +++ b/plugins/chalk/skills/tend-docs/SKILL.md @@ -104,7 +104,8 @@ If the user asks for those, decline politely and suggest a different approach. 5. **Apply the chalk voice.** **Load the `chalk:voice` skill** (via the Skill tool) for the Diataxis framing and universal principles, then apply the quadrant-specific voice to each section. - Don't restate those rules inline — they live in `chalk:voice`. + **Load `chalk:mindmap`** too, for the shape of anything the reader has to follow — a how-to's steps, an explainer's reasoning, a failure-mode section. Note its line-format rule: on a docs page the bullets are sentence-per-line like the rest of the file. + Don't restate those rules inline — they live in those skills. **Line format: sentence-per-line.** A docs page is checked into the repo and reviewed as a `git diff`, so put each sentence on its own line — it keeps diffs minimal (a one-sentence edit touches one line) and the structure scannable in source. @@ -124,7 +125,7 @@ If the user asks for those, decline politely and suggest a different approach. ## Constraints -- The audience MUST be named (to the user or in a code comment on the draft) before the page is written. +- The audience MUST be named (to the user or in a code comment on the draft) before the page is written. This is the general rule in `chalk:voice` ("Name your audience"), made explicit here because a docs page is the one artefact whose audience is *not* the team by default. - Each section MUST commit to one Diataxis quadrant. Sections MUST NOT blur quadrants. - The page MUST follow the `chalk:voice` skill — universal principles plus the quadrant-specific voice — and be written sentence-per-line (a docs page is reviewed as a diff). @@ -144,7 +145,7 @@ If the user asks for those, decline politely and suggest a different approach. 4. Identify the quadrant of the page (and each section). 5. Pull the *why* from chalk context — tracked issue, one-hop neighbourhood (parent/sub/blocked-by), landing PR(s) including review discussion, and landing commit body(ies). 6. Draft. - Apply the `chalk:voice` skill — universal principles plus per-quadrant voice; write sentence-per-line. + Apply the `chalk:voice` and `chalk:mindmap` skills — universal principles, per-quadrant voice, and the tree for anything followable; write sentence-per-line. 7. Match discovered project conventions (frontmatter, version markers, changelog, callouts, cross-links). 8. Ask clarifying questions if the audience, quadrant, or a material project convention is unclear. diff --git a/plugins/chalk/skills/voice/SKILL.md b/plugins/chalk/skills/voice/SKILL.md index 90ae4b8..1556a53 100644 --- a/plugins/chalk/skills/voice/SKILL.md +++ b/plugins/chalk/skills/voice/SKILL.md @@ -1,6 +1,6 @@ --- name: voice -description: Shared chalk writing voice — Diataxis quadrants, universal principles, and the issue/PR section palette. The chalk, chalk:issue, chalk:commit, chalk:pr and chalk:tend-docs skills load this before drafting any GitHub-bound or docs prose; a human may run it to read the guide. +description: Shared chalk writing voice — Diataxis quadrants, universal principles, and the issue/PR section palette. The chalk, chalk:issue, chalk:commit, chalk:pr and chalk:tend-docs skills load this before drafting any GitHub-bound or docs prose; a human may run it to read the guide. Companion skills chalk:mindmap (the shape of followable content) and chalk:goal-tree (goal trees) carry the structure this one deliberately leaves out. user-invocable: true --- @@ -16,7 +16,12 @@ Whatever you're writing, the reader is trying to do one of four things: acquire What follows: **universal principles** (apply everywhere), **the four quadrants** (what each is for), **artefacts as compositions** (which quadrants each chalk artefact occupies), and the **issue/PR section palette**. -One thing this skill deliberately does *not* cover: **line-break style** — sentence-per-line vs paragraph-per-line. +Two things this skill deliberately leaves to a companion skill: + +- **The shape of followable content** — nested bullets, subject lines, tags, cross-reference IDs, tl;dr placement — is in `chalk:mindmap`. Load it too: it's the default for anything the reader has to follow, and it applies in every quadrant. +- **Goal trees**, where a node's children *accomplish* it rather than argue for it, are in `chalk:goal-tree`. Load that when writing the direction of a piece of work. + +And one it doesn't cover at all: **line-break style** — sentence-per-line vs paragraph-per-line. That depends on the artefact's destination — whether it's read as a `git diff` or rendered — so the skill you came from (`chalk:commit`, `chalk:issue`, `chalk:pr`, `chalk`, `chalk:tend-docs`) states its own rule. ## Universal principles @@ -39,6 +44,21 @@ Everything else does, and one answer serves every artefact: the issue descriptio *Why now* is the half that goes missing, and its absence is what leaves an issue un-triageable in the backlog and a commit unexplainable six months on. +### Name your audience + +"Optimise for the reader" is only actionable once you've said who the reader is. + +**For everything in this plugin it's nearly always your teammates** — including the two who are easiest to forget and who between them are most of the readership: + +- **You in six months**, with none of the context you have while writing. +- **A future agent session**, starting cold from the artefact and nothing else. + +Both read the artefact without the conversation that produced it, so: + +- **Lead with what they need, not with what you did.** The two diverge most sharply in summaries: a summary of the *work* reads as a session changelog, where a summary for the *reader* states what's true now and what it means for them. +- **Assume none of your session's shared context.** A sentence that only parses if you know which files were touched, which commit came before, or what was said in chat is a sentence the audience can't use. +- **Name the audience explicitly whenever it isn't the default** — a docs page for end users, an issue aimed at another team, a comment for whoever next debugs this function. `chalk:tend-docs` requires this before a page is written; the same test is worth applying to any artefact. + ### Concrete over abstract Ground the reasoning in specific scenarios, code snippets, data, real identifiers — not placeholders. @@ -66,14 +86,38 @@ When the reasoning is complex but the change is simple, say so. ### Structure what the reader must follow -Anything the reader has to *follow* — a sequence of events, a multi-step rationale, a set of conditions — **defaults to a bullet-point tree, one logical checkpoint per bullet**, not a prose paragraph. This is the single highest-leverage habit in this guide; reach for it first, and drop to prose only deliberately. +Anything the reader has to *follow* — a sequence of events, a multi-step rationale, a set of conditions — **defaults to a mindmap: nested bullets whose parents are claims and whose children back them up**, not a prose paragraph. +This is the single highest-leverage habit in this guide; reach for it first, and drop to prose only deliberately. + +**The rules are in `chalk:mindmap` — load it rather than improvising the shape.** +Getting the format roughly right and the *relation* wrong produces a tidy bullet list that carries no argument, which is the common failure and the one this guide can't catch for you. + +Reserve prose for a short causal argument where the connectives ("because", "so", "but only when") carry the meaning and the chain is only two or three links long. +This is about the *followable* parts, not the tone — an explanation can still read discursively and lay its reasoning out as a tree. + +### Write in specification register + +**Every sentence carries a fact, a constraint or a decision.** +None exists to convey that a person is delivering it. + +**You're not writing to impress anyone.** +Your reader is a teammate trying to get something done, not an assessor — so there's nothing here to reward the motive that produces flourishes, alternatives nobody would take, and caveats that change nothing. +Drop it and most of the rest of this section follows. + +- **No filler in headings or lead-ins.** "Caveat:" not "One honest caveat"; "Agreed:" not "Agreed — and here's why that's the stronger design". +- **Personality is fine exactly where removing it would change how the reader acts on the sentence.** Otherwise it's decoration they have to read past to reach the claim. +- **Depth isn't the problem.** Expand a section as far as it needs; every sentence in it earns its place on the same test. +- **The tells**: an opening reaction line, a sign-off offer, an aside carrying attitude rather than a fact, a frame wrapped around a claim instead of the claim. + +### One word, one meaning + +Aim for what [ASD-STE100](https://www.asd-ste100.org) aims for — the reader gets the meaning with minimum effort and no ambiguity — but get there by **technical precision rather than a restricted vocabulary**. -- **One checkpoint per bullet.** Each bullet is a place the reader stops, confirms they've followed, and moves on. A dense paragraph makes them hold the whole chain in their head and trust they reassembled it the way you meant. -- **Lead each bullet with its point, and bold the load-bearing words** — the tree should be graspable from the bolded phrases alone, before a word of the surrounding prose is read. -- **Nest for sub-steps, but stay shallow** — about two levels. A checkpoint can have its own checkpoints; a third level of indentation is usually its own wall, so promote or flatten it. -- **Cut ruthlessly.** Less text beats better-formatted text — a bullet the reader doesn't need is noise, and noise hides the checkpoints that matter. +`sufficient` and `necessary` each carry an exact meaning that a paraphrase spends a clause on and still blurs. +So **precision beats simplicity where the two conflict**: what gets cut is the decorative metaphor, not the exact term. -Reserve prose for a short causal argument where the connectives ("because", "so", "but only when") carry the meaning and the chain is only two or three links long. This is about the *followable* parts, not the tone — an explanation can still read discursively and lay its reasoning out as a tree. +Use one word for one concept throughout an artefact. +Synonym variation reads as elegant and costs the reader a re-check every time they have to ask whether you meant something different. ### Transitions vs. current state @@ -235,6 +279,7 @@ The code is the *what*; the comment carries the *why* the code can't show: the r A comment that restates the code — echoing the function name, narrating the steps — is noise; delete it. Comments describe the *current contract* (see "Transitions vs. current state" above): the story of what the code used to do belongs in the commit that changed it, not in a comment that will rot. The line-break rules the calling skill states don't apply — comments are read in-source, not rendered — but terse, why-first and concrete all do. +A comment with real structure in it takes a mindmap like anything else, but the threshold is higher and the markup depends on whether the language's tooling renders it — see the code-comment rules in `chalk:mindmap`. **Docs pages** play all four. Each page leans toward one quadrant at the top level; sections within it may hit other quadrants. @@ -257,12 +302,12 @@ Common sections — all explanation, with reference-shaped evidence embedded whe - **Root cause / Analysis** (bugs / incidents) — why it's happening, grounded in evidence (log excerpts, stack traces, block file analysis, annotated offset tables). - **Evidence** (bugs / incidents) — concrete artefacts: replica log dumps, application log excerpts with timestamps, block file contents, message type distributions. Annotate them — raw dumps without explanation are noise. - **Current state** (refactors / features) — a concrete sketch of what exists today, in enough detail that the gap to the future state is visible. Reference-shaped: name the specific types, functions, flags, or files that the change touches. -- **Future state** (refactors / features) — the target end state. What the new world looks like once the change is shipped. Concrete and structural — the reader should be able to picture the resulting code or system shape from this section alone. +- **Future state** (refactors / features) — the target end state. What the new world looks like once the change is shipped. Concrete and structural — the reader should be able to picture the resulting code or system shape from this section alone. This section and Implementation both want a **goal tree** rather than a plain list — see `chalk:goal-tree`. - **Invariants / Constraints** — non-obvious things the solution must preserve. - **Out of scope** — what's explicitly not in this change, with reasons. Reference related issues/PRs that pick those pieces up. - **Alternatives considered** — other designs or approaches at the same level of abstraction as the chosen one, with a sketch of each and the trade-offs that ruled it in or out. Dated rejections ("Rejected on 2026-05-23 because …") help the next reader who's tempted to reopen the question. Implementation-strategy choices (refactor-in-place vs. parallel impl, big-bang vs. incremental) aren't alternatives at this level — they belong in Implementation. - **Decision rationale** — compare the chosen approach against each alternative on the points that differentiate them. Reads as a side-by-side, not a re-summary of the chosen approach. -- **Implementation** — direction and high-level plan for an issue; what landed for a PR. Step-by-step granular execution (which sub-task next, what files to touch) belongs in the chalk comment, not here. +- **Implementation** — direction and high-level plan for an issue; what landed for a PR. Step-by-step granular execution (which sub-task next, what files to touch) belongs in the chalk comment, not here. Shape it as a **goal tree** (`chalk:goal-tree`), and name whose each item is: **an expectation of someone else, written like a task, is a dependency nobody owns** — the most common way a plan in an issue quietly fails. PRs additionally draw from: