diff --git a/packages/agents/content/_partials/voice-checklist.md b/packages/agents/content/_partials/voice-checklist.md index 2f7fc32c..1682e7d0 100644 --- a/packages/agents/content/_partials/voice-checklist.md +++ b/packages/agents/content/_partials/voice-checklist.md @@ -1,6 +1,6 @@ Before saving, audit your draft against the two rules below. -These two rules are what this checklist tests. They do **not** cover register (change-narrating voice — `introduces`, `now`, `no longer`) or jargon discipline (define-while-naming). Those judgments aren't checklist-able and need the worked examples — read the `## Voice` and `## Jargon at the lede` sections of [`lede-voice.md`](../_data/lede-voice.md) before drafting. +These two rules are what this checklist tests. They do **not** cover register (change-narrating voice — `introduces`, `now`, `no longer`) or jargon discipline (define-while-naming). Those judgments aren't checklist-able and need the worked examples — read the `## Voice` and `## Jargon at the lede` sections of [`lede-voice.md`](../_data/lede-voice.md) before drafting. For a documentation change, also read the doc-PR carve-out under Rule 1: the outcome is what readers of the doc will now do or know, not what the doc says. **Rule 1: Each sentence must be one of the following:** diff --git a/packages/agents/content/skills/_data/lede-voice.md b/packages/agents/content/skills/_data/lede-voice.md index 59379ebf..d68673e3 100644 --- a/packages/agents/content/skills/_data/lede-voice.md +++ b/packages/agents/content/skills/_data/lede-voice.md @@ -70,6 +70,18 @@ If a sentence describes how the change was implemented (mechanism, internal data **For `fix:` entries specifically.** Sentences after the opening symptom-frame must add user-relevant content beyond the implicit "bug fixed"; specifically, user-facing behavior change or migration info. Each such sentence describes what the user can now do (or no longer needs to do), not how the fix works internally. "The CLIs now read their version from `package.json`" is mechanism. "A fresh `pnpm install` or rebuild is no longer required" is migration info. The test: Could the same sentence be true after a different implementation of the change? If yes, it is user-facing behavior; if no, it is mechanism. This counterfactual applies to any sentence in any work type, not just `fix:`. +**For documentation changes specifically.** The outcome is not the change to the documentation; the outcome is what readers of the doc will now know, be able to do, or be guided away from. + +**Bad** (mechanism: names the edit site and the refactor move): + +> The stale one-line mention of table-driven tests in the `code-patterns` skill is replaced by a pointer to the new canonical source. + +**Good:** + +> Guidance on table-driven tests is now consolidated in one place, so readers no longer follow a stale stub to outdated advice. + +The Bad version describes a refactor move ("X is replaced by a pointer") and names the internal edit site — both mechanism. The Good version names what readers now get (current guidance, no stale stub) and survives the counterfactual: A different restructuring that still routed readers to current guidance would yield the same sentence. + ### Rule 2: Identifier ban The only identifiers that may appear are **top-level user-configurable surface**: diff --git a/packages/agents/content/skills/summarize-change/SKILL.md b/packages/agents/content/skills/summarize-change/SKILL.md index b0624e8f..2fae90ac 100644 --- a/packages/agents/content/skills/summarize-change/SKILL.md +++ b/packages/agents/content/skills/summarize-change/SKILL.md @@ -35,12 +35,18 @@ Check commit messages for additional context. type: {resolved type} tier: {tier from step 5} scope: {resolved scope, if available} - description: | - {1-3 sentence factual summary of what changed — derived from the substance composed in step 4} + outcome: | + {What the reader will experience, do, or know differently — outcome-framed, not a diff enumeration. Derived from the substance composed in step 4.} + context: | + {Optional supporting facts the subagent may need for accuracy.} ``` + Lead with the outcome before naming files: `outcome` is the reader-facing delta the lede must carry; `context` is supplementary material the subagent may draw on for accuracy. + Use the subagent's returned text verbatim as the content of the `## What` section. Do not edit, prepend to, or append to it. The subagent owns voice; you own facts. If the subagent returns an error message (missing-field or similar), correct the dispatch inputs and retry. + Verbatim governs voice ownership, not quality acceptance. If the returned text fails the doctrine — a banned identifier, a mechanism-shaped sentence, or generic puffery — correct the dispatch inputs (chiefly re-articulating `outcome`) and redispatch rather than shipping the failure. Correct the inputs and redispatch; do not hand-edit the subagent's output. + 7. **Save** per the [Saving](#saving) section. If expected information is missing, stop and ask the developer. @@ -56,7 +62,7 @@ The body following the frontmatter has this structure: ## What -{Content returned by the `changelog-writer` dispatch in Process step 6. Use the returned text verbatim; do not edit, prepend, or append.} +{Content returned by the `changelog-writer` dispatch in Process step 6. Use the returned text verbatim; do not edit, prepend, or append. If it fails the doctrine, correct the dispatch inputs and redispatch (see step 6).} ## Why diff --git a/packages/agents/content/subagents/changelog-writer.md b/packages/agents/content/subagents/changelog-writer.md index 3d2b9864..f2083571 100644 --- a/packages/agents/content/subagents/changelog-writer.md +++ b/packages/agents/content/subagents/changelog-writer.md @@ -15,20 +15,21 @@ The voice substance lives in `{platform_home_dir}/skills/_data/lede-voice.md`. R The dispatch prompt contains a structured set of fields: -| Field | Required for | Description | -| ---------------- | ------------------ | ----------------------------------------------------------------------------------------------- | -| `mode` | all | One of `write`, `rewrite`, `audit`. | -| `type` | all | Work type (e.g., `feat`, `fix`, `refactor`, `internal`). | -| `tier` | all | One of `public`, `internal`, `process`. Caller resolves from `work-types.json` based on `type`. | -| `scope` | optional | Package or surface scope. | -| `description` | `write`, `rewrite` | Prose description of what changed. The factual substance you compose voice around. | -| `existing_draft` | `rewrite`, `audit` | Text to be rewritten or audited. | +| Field | Required for | Description | +| ---------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | +| `mode` | all | One of `write`, `rewrite`, `audit`. | +| `type` | all | Work type (e.g., `feat`, `fix`, `refactor`, `internal`). | +| `tier` | all | One of `public`, `internal`, `process`. Caller resolves from `work-types.json` based on `type`. | +| `scope` | optional | Package or surface scope. | +| `outcome` | `write`, `rewrite` | The reader-facing delta — what the reader will experience, do, or know differently. The ground-truth substance you compose voice around. | +| `context` | optional | Supporting facts the caller supplies for accuracy. Supplementary to `outcome`, not a substitute for it. | +| `existing_draft` | `rewrite`, `audit` | Text to be rewritten or audited. | ## Modes -**`write`**: Compose a new entry from scratch using `description` as ground truth. Return a single Markdown entry suitable for placement under a `## What` heading. Do not return the heading itself. +**`write`**: Compose a new entry from scratch using `outcome` as ground truth, drawing on `context` for supporting accuracy. Return a single Markdown entry suitable for placement under a `## What` heading. Do not return the heading itself. -**`rewrite`**: Replace `existing_draft` with text that fixes its doctrinal failures while preserving its factual content. Use `description` (when provided) as additional ground truth; if absent, infer facts from `existing_draft` — but do not rescue facts the draft does not already contain. Return shape matches `write`. +**`rewrite`**: Replace `existing_draft` with text that fixes its doctrinal failures while preserving its factual content. Use `outcome` (and `context`, when provided) as additional ground truth; if absent, infer facts from `existing_draft` — but do not rescue facts the draft does not already contain. Return shape matches `write`. **`audit`**: Check `existing_draft` against the doctrine. Return a structured failure list (see [Audit output](#audit-output)) or the literal text `No failures.` Do not modify the draft. @@ -60,7 +61,7 @@ Do not produce a per-sentence pass/fail table. The empty list — i.e., the `No ## Constraints - **Read-only.** Your tools are {tool:Read} and {tool:Grep}. You never write files or run shell. -- **Authorship of facts stays with the caller.** Your job is voice (how to phrase), not substance (what to say). If `description` is wrong or incomplete, your output will be voice-compliant but factually wrong; that is the caller's responsibility, not yours. +- **Authorship of facts stays with the caller.** Your job is voice (how to phrase), not substance (what to say). If `outcome` is wrong or incomplete, your output will be voice-compliant but factually wrong; that is the caller's responsibility, not yours. - **No invented facts.** Do not add details not present in the inputs. - **One mode per invocation.** Process in the mode specified; do not switch. - **Tier register, not gating.** `tier` shifts the register (public/internal/process) per `lede-voice.md`'s reader-routing section; it does not change the rules.