From ca3e0d015769b78f6079010606f02e3ede9c3782 Mon Sep 17 00:00:00 2001 From: tarr1124 Date: Thu, 13 Aug 2026 19:53:51 +0900 Subject: [PATCH] rill-close-handbook-html: aggregated workspace handbook at /close Wire the "workspace completion" read moment from rill-html-output.md into the close skill, and absorb the two HTML-canonical handoffs from the doctrine task's review. - .claude/commands/_close/handbook-agent.md (new): third /close sub-agent template (ADR-073 structure). Fresh context reads _summary.md + all deliverables (MD + HTML-canonical) and authors an aggregated handbook into workspace/{id}/.view/ following the shared design language: start page re-expresses _summary.md with navigation to every artifact; single page (handbook.html) vs multi-page (handbook/ hub + detail pages) is a qualitative size judgment; layer-not-delete; self-contained; provenance comment; stable name (close-time content is final, so the dated-snapshot rule for volatile-phase digests does not apply); output_language injection. - skills/close/SKILL.md: spawn the handbook agent in the Phase 4 background queue alongside distillation; result excluded from the Phase 5 coverage equation; generation failure non-fatal; user skip line; rill book build role distinction; completion-report line. - .claude/commands/_close/distillation-agent.md: cross-deliverable verification now covers HTML-canonical artifacts (glob *.{md,html}, derived .view/ and same-basename twins excluded) instead of *.md only (doctrine review round 13 handoff). - skills/promote/SKILL.md: Phase 2 artifact-reference extraction handles HTML-canonical artifacts ( / first <h1> with filename fallback; HTML class label in place of frontmatter type) (doctrine review round 13 handoff). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --- .claude/commands/_close/distillation-agent.md | 5 +- .claude/commands/_close/handbook-agent.md | 89 +++++++++++++++++++ skills/close/SKILL.md | 33 ++++++- skills/promote/SKILL.md | 2 +- 4 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 .claude/commands/_close/handbook-agent.md diff --git a/.claude/commands/_close/distillation-agent.md b/.claude/commands/_close/distillation-agent.md index 483cfc2..8a7d0f7 100644 --- a/.claude/commands/_close/distillation-agent.md +++ b/.claude/commands/_close/distillation-agent.md @@ -99,9 +99,10 @@ This step exists to catch errors propagated from `_summary.md`. Do not skip it. 1. From `candidate.rationale` and your reading of the source, extract **3-5 key claims** that the note will make 2. For each key claim, run: ``` - Grep(pattern="{claim-keyword}", path="workspace/{workspace_id}/", glob="*.md", output_mode="files_with_matches") + Grep(pattern="{claim-keyword}", path="workspace/{workspace_id}/", glob="*.{md,html}", output_mode="files_with_matches") ``` -3. For each deliverable that matches (excluding the source you already read), `Read` up to **2 additional** deliverables + An `.html` match counts as a verification source only when it is **HTML-canonical** (no same-basename `.md` — check the deliverable MOC above, which lists them). Ignore matches from derived HTML: anything under `.view/`, and same-basename `.html` twins of an MD file (their MD side is already in scope) +3. For each deliverable that matches (excluding the source you already read), `Read` up to **2 additional** deliverables — HTML-canonical deliverables included (their HTML is their only record) 4. Classify what those deliverables say about your claim: - **Consistent** (supports or does not contradict) → OK, continue - **Not mentioned** → OK, continue diff --git a/.claude/commands/_close/handbook-agent.md b/.claude/commands/_close/handbook-agent.md new file mode 100644 index 0000000..76480a6 --- /dev/null +++ b/.claude/commands/_close/handbook-agent.md @@ -0,0 +1,89 @@ +# /close Handbook Sub-agent + +/close Phase 4 sub-agent prompt (spawned in parallel with the Distillation sub-agents). Authors the **aggregated workspace handbook** — the human-readable HTML view of the completed workspace — into `workspace/{workspace_id}/.view/`, implementing the "workspace completion" read moment defined in `rill-html-output.md` ("When HTML Is Generated"). + +**IMPORTANT**: This file is a template. The parent /close skill reads this file, fills in the placeholders (workspace id, summary path, deliverable MOC), and passes the result as the `prompt` parameter when spawning the sub-agent via the Agent tool. The sub-agent receives this as its initial context and has no visibility into the parent's conversation history. + +## Target + +- Workspace ID: `{workspace_id}` +- Workspace path: `workspace/{workspace_id}/` +- `_summary.md` path: `workspace/{workspace_id}/_summary.md` (already written by the Analysis sub-agent) +- All deliverables in this workspace (from the Analysis report): + +``` +{deliverable_moc} +``` + +- `output_language` (optional): ISO 639-1 language code for narrative output (e.g. `"ja"`, `"en"`); when omitted, default to English +- `style_guide` (optional): short vocabulary-boundary rules for narrative output; when omitted, write narrative text in plain English + +## Your job + +Author the workspace handbook: a navigable HTML view that lets a human absorb the whole completed workspace without opening each Markdown artifact. You: + +1. Read `.claude/commands/_view/design-language.md` **first** — it is the authoring procedure and pre-ship checklist this page must follow (message-driven, layer-not-delete, visualization routing, typography/layout, ship check) +2. Read `workspace/{workspace_id}/_summary.md` and every deliverable in full: all `NNN-*.md` files plus committed HTML-canonical artifacts (`NNN-*.html` etc. with no same-basename MD source — their HTML is the only record). Skip derived HTML regenerable from MD sources (`.view/` sidecars, same-basename `.html` twins) +3. Choose the document shape (single page vs multi-page — see below) +4. Write the handbook into `workspace/{workspace_id}/.view/` +5. Return a short structured report to the parent + +You MUST NOT: + +- Create or modify any file outside `workspace/{workspace_id}/.view/` +- Modify `_summary.md`, `_workspace.md`, or any deliverable +- Carry substantive information absent from the MD sources into the handbook (`rill-html-output.md` principle 4 — if a load-bearing explanation is missing, leave it out rather than inventing it; the parent run is completing the workspace and its sources are final) + +## Document shape — qualitative judgment + +Per the design language's "Two document shapes": + +- **Single page** → `workspace/{workspace_id}/.view/handbook.html`. Choose this when the workspace's material fits one navigable page — a handful of artifacts whose full re-expression still reads as one coherent document a reader can scroll. +- **Multi-page** → `workspace/{workspace_id}/.view/handbook/` (hub `index.html` + detail pages, relative links, one shared inline `<style>` replicated verbatim across pages). Choose this when a single page would become an unnavigable wall — many dense artifacts whose re-expression would crowd each other out. Group related artifacts into chapter pages where that reads better than one page per artifact; the hub carries the framework and index (rank table / card grid / links into specific items). + +The judgment is qualitative — decide by whether a reader could actually navigate the single page, not by a file-count threshold. + +## Content requirements + +1. **Start page re-expresses `_summary.md`.** The hub (or the top of the single page) states the workspace's message in one sentence, then re-expresses the summary's Overview, Decisions, Invalidated Approaches, and Open Issues in handbook form, with navigation to every artifact's section or detail page. +2. **Every deliverable is covered.** Each artifact (MD and HTML-canonical) gets a re-expressed section or detail page. Layer, not delete: prefer self-contained re-expression inside the handbook; for the largest workspaces a detail section may condense the artifact's argument, but it must then link the MD original explicitly as the retained full-detail layer (the reader can open it in the GUI's Markdown view). Never drop an artifact silently. +3. **HTML-canonical artifacts** (mocks, diagrams) are covered by linking them from the handbook with a described role (relative path into the workspace directory) — do not duplicate their content into the handbook; they are already human-readable HTML. +4. **Connections explicit.** Decisions link to the artifacts they were adopted from; invalidated approaches link to what invalidated them; every section declares where it belongs (design language, Authoring Procedure step 6). + +## Technical constraints + +- Self-contained: inline styles, no external network dependencies. A multi-page handbook is self-contained at the `handbook/` directory level — relative references to sibling pages are allowed, plus relative links out to the workspace's own MD/HTML sources (`rill-html-output.md` principle 7) +- Provenance: every generated page opens with `<!-- generated from {md_paths} @ {timestamp} by /close -->` (list the pages' actual sources; the hub may list `_summary.md` + the deliverable set) +- No frontmatter; write the HTML files directly (not via `rill mkfile`) +- Stable name, not a dated snapshot: the handbook is the durable view of a completed workspace, regenerated only when the workspace is reopened and re-closed. The parent /close has already deleted any previous handbook output (both `handbook.html` and the `handbook/` directory) before spawning you — write your chosen shape fresh; do not assume or preserve prior files. As a safety net, if either prior output still exists at your paths, delete it before writing (an earlier close may have used the other shape, or a page split yours no longer produces) +- Run the design language's ship check before returning; where no measuring tooling is available in your context, self-review the HTML source against the checklist instead + +## Language + +Use the language specified by `output_language` for all narrative text in the handbook (headings, prose, labels, link text). English exceptions per the vault's language rules: tokens inside backticks/code, proper nouns, ASCII acronyms, file paths and slugs. Follow the inline `style_guide` block for vocabulary boundaries. When omitted, write in English. + +## Output — return to parent + +Return ONE of the following structured reports. Use this exact format: + +```yaml +status: created +shape: single | multi +path: workspace/{workspace_id}/.view/handbook.html # or .view/handbook/index.html +pages: {N} # 1 for single +artifacts_covered: {M} +``` + +```yaml +status: error +reason: "one-line description of what failed" +``` + +Handbook generation is non-fatal to /close (`rill-html-output.md` principle 8): on `error` the parent logs a warning and completes the close with Markdown alone. Do not retry endlessly — report the error and stop. + +## Constraints summary + +- Write only under `workspace/{workspace_id}/.view/` +- `.view/` is gitignored — the handbook is a derived, regenerable render, never committed +- Do not read `knowledge/`, `tasks/`, or other vault layers — the workspace directory, `_summary.md`, and the design language file are your whole world +- Return only the structured YAML report, nothing else diff --git a/skills/close/SKILL.md b/skills/close/SKILL.md index 53491db..ce0f9ea 100644 --- a/skills/close/SKILL.md +++ b/skills/close/SKILL.md @@ -34,6 +34,7 @@ Historically /close ran all phases directly in the parent context (ADR-072). Thi 1. **Parent session** (this skill): orchestration + user interaction + final phases 2. **Analysis sub-agent** (fresh context): reads all deliverables, writes `_summary.md`, enumerates distillation candidates 3. **Distillation sub-agents** (fresh context, launched as one background queue with harness-capped concurrency): one candidate → one atomic note, with mandatory cross-deliverable verification +4. **Handbook sub-agent** (fresh context, launched into the same background queue): authors the aggregated workspace handbook HTML into `workspace/{id}/.view/` — the "workspace completion" read moment of `rill-html-output.md`. Independent of the distillation pipeline; its failure is non-fatal The parent session stays lightweight and never runs out of budget regardless of workspace size. Each sub-agent has a fresh context (independent budget). Narrative consistency is preserved because the Analysis sub-agent reads everything in a single fresh context, and each Distillation sub-agent cross-verifies against other deliverables before writing. @@ -73,7 +74,7 @@ This is the same `rill context-map` preparation /distill Step 1 uses. Hold the r ### Phase 1.5: Build language args -Before launching either the Analysis sub-agent (Phase 2) or the Distillation sub-agents (Phase 4), call `build_language_args()` to decide whether to inject narrative-language args into each sub-agent invocation. The function is intentionally trivial — distribution default is English (sub-agent prompts are written in English), so absence of a personal override means no args are injected and the sub-agent's English default takes over naturally. No fallback logic needed on either side. +Before launching the Analysis sub-agent (Phase 2), the Distillation sub-agents (Phase 4), or the Handbook sub-agent (Phase 4), call `build_language_args()` to decide whether to inject narrative-language args into each sub-agent invocation. The function is intentionally trivial — distribution default is English (sub-agent prompts are written in English), so absence of a personal override means no args are injected and the sub-agent's English default takes over naturally. No fallback logic needed on either side. The top-of-file "Conduct ALL conversation with the user in the language defined by `.claude/rules/personal-language.md`" instruction governs the orchestrator's (main session's) user-facing utterances; this prologue governs argument injection into sub-agent invocations. They share a trigger file but operate on different surfaces — the user-facing rule has no effect on sub-agent output, which is exactly what this prologue closes. @@ -141,7 +142,7 @@ else fi ``` -When `inject_args` is non-empty, append it as additional YAML lines to **each** sub-agent invocation's prompt in Phase 2 and Phase 4, alongside the existing placeholder substitutions (`{workspace_id}`, `{shared_context_placeholder}`, `{candidate_yaml}`, etc.). The `style_guide` string is hardcoded in English on purpose: the public `rillmd/rill` repo stays ASCII-only, and the string is itself an English instruction. The `output_language` value is the only locale-dependent runtime input; broader-locale support (`ko`, `zh`, `fr`, `de`, `es`, `pt`, `it`) extends the detection branch above (and requires a corresponding bin/rill change to mark `personal-language.md` with the chosen locale) without touching the sub-agent prompts or the `style_guide` content. +When `inject_args` is non-empty, append it as additional YAML lines to **each** sub-agent invocation's prompt in Phase 2 and Phase 4 (Distillation and Handbook alike), alongside the existing placeholder substitutions (`{workspace_id}`, `{shared_context_placeholder}`, `{candidate_yaml}`, `{deliverable_moc}`, etc.). The `style_guide` string is hardcoded in English on purpose: the public `rillmd/rill` repo stays ASCII-only, and the string is itself an English instruction. The `output_language` value is the only locale-dependent runtime input; broader-locale support (`ko`, `zh`, `fr`, `de`, `es`, `pt`, `it`) extends the detection branch above (and requires a corresponding bin/rill change to mark `personal-language.md` with the chosen locale) without touching the sub-agent prompts or the `style_guide` content. ### Phase 2: Spawn Analysis Sub-agent @@ -202,7 +203,7 @@ Layer 2 (from per-deliverable scan): {NL2} Then proceed directly to Phase 4 with the full candidate list from the Analysis report — do not call AskUserQuestion. If the result looks wrong, the user fixes it after the run by editing or `git`-reverting the generated `knowledge/notes/` (distillation is reversible). To re-run the analysis from scratch, reopen the workspace (set its metadata `status` from `completed` back to `active` — an allowed transition) and re-invoke `/close`. -### Phase 4: Spawn Distillation Sub-agents (parallel, harness-capped) +### Phase 4: Spawn Distillation + Handbook Sub-agents (parallel, harness-capped) Read `.claude/commands/_close/distillation-agent.md` once. For each candidate from the Analysis report, fill in the placeholders: @@ -225,6 +226,21 @@ After substituting placeholders, append `inject_args` (from Phase 1.5) to the bo candidate_id | status | path_or_justification ``` +#### Handbook sub-agent (parallel, non-fatal) + +**Lifecycle (parent-owned)**: at this step's start — before the skip decision, and regardless of whether a new handbook will be generated — delete any prior handbook output: `workspace/{id}/.view/handbook.html` and/or the `handbook/` directory. A reopened-and-re-closed workspace must not keep the previous close's view (even when the user skips regeneration), and a leftover from an interrupted earlier run is cleared here too. + +Then, alongside the distillation queue, spawn **one Handbook sub-agent** into the same background batch (`subagent_type: general-purpose`, `run_in_background: true`). Read `.claude/commands/_close/handbook-agent.md`, fill in `{workspace_id}` and `{deliverable_moc}` (the same MOC built for the Distillation sub-agents, including HTML-canonical artifacts), append `inject_args` when non-empty, and pass the result as the prompt. + +The agent authors the aggregated workspace handbook into `workspace/{id}/.view/` — a stable-named view (`handbook.html`, or a `handbook/` directory with a hub `index.html` + detail pages for large workspaces; single vs multi-page is the agent's qualitative call per the design language's "Two document shapes"). The start page re-expresses `_summary.md` with navigation to every artifact. Authoring follows `.claude/commands/_view/design-language.md`. + +Operational rules: + +- **Stable name, not a dated snapshot.** Unlike /focus decision digests (volatile-phase snapshots, dated, never regenerated), the handbook aggregates content that is final at close time — the staleness problem that forbids in-place regeneration does not arise. It is regenerated (overwritten) only when the workspace is reopened and re-closed +- **Not `rill book build`.** The handbook is a bespoke authored view generated once at close; `rill book build` is the deterministic reading-view builder for continuously-updated `pages/` books. Do not route the handbook through it +- **Skip line**: if the user asks to skip the handbook (or says the Markdown summary is enough), do not spawn the agent. `--auto-approve` runs spawn it by default +- **Result handling**: the agent returns `status: created` (with shape / path / page count) or `status: error`. The handbook result is **excluded from the Phase 5 coverage equation** — it is not a distillation candidate. On `error` (or a malformed return), delete both output paths (`workspace/{id}/.view/handbook.html` and/or the `handbook/` directory — the agent may have written partial pages before failing), log a one-line warning, and continue; handbook generation failure is non-fatal to /close (`rill-html-output.md` principle 8), and a partial view must not be left for a reader to open later + ### Phase 5: Parent-side Aggregation #### 5.1 Validate justifications @@ -248,7 +264,7 @@ If two sub-agents happened to `create` notes with similar slugs or overlapping c #### 5.3 Self-check -Compute coverage: +Compute coverage over **distillation candidates only** (the Handbook sub-agent's result is tracked separately in Phase 4 and never enters this equation): ``` enumerated = candidates_total (from Analysis sub-agent) @@ -272,6 +288,8 @@ Possible causes: sub-agent timeout, invalid return, race resolution error. Not proceeding to Phase 6+. Please investigate. ``` +**Handbook retraction on an incomplete close**: if the run stops or errors anywhere before Phase 7 sets `status: completed` — the Phase 5 STOP (`uncovered > 0`), a user abort on rejected candidates, or a failure in Phase 5–7 — and the Handbook sub-agent already returned `created`, delete its output (`workspace/{id}/.view/handbook.html` and/or the `handbook/` directory) before exiting. A completion-time view must not survive a close that did not complete; the next successful /close regenerates it. Interruption paths no skill text can catch (a hard crash) are covered by the parent-owned pre-delete at the Phase 4 handbook step, which clears leftovers on the next run. After `status: completed` lands, the handbook is the workspace's legitimate view — later failures do not retract it. + **If `rejected > 0`**: display the rejected candidates and their invalid justifications, ask the user whether to retry, skip them, or abort. **Non-interactive mode** (`--auto-approve`): do not prompt and do not STOP. Leave the rejected candidates undistilled, keep them counted in the `rejected` bucket (the SC-01 equation still balances), surface them in the Phase 9 completion report, and proceed to Phase 6. Their content remains in the workspace deliverables and `_summary.md`, so nothing is lost — they are simply not auto-distilled into notes this run. @@ -353,6 +371,10 @@ Display the following to the user as the final output of /close: ### _summary.md workspace/{id}/_summary.md +### Handbook +{path returned by the Handbook sub-agent — workspace/{id}/.view/handbook.html for single-page, workspace/{id}/.view/handbook/index.html for multi-page} ({shape}, {N} page{s}) +(or: "generation failed — non-fatal; the Markdown summary above is complete" / "skipped at user request") + ### Distillation self-check - Candidates enumerated: {N} - Atomic notes created: {X} @@ -417,11 +439,14 @@ If the /pulse invocation fails, log a 1-line warning to stdout and treat the /cl - **Backward compatibility**: also handle workspaces that only have `_session.md` or `_project.md` (treat as metadata file) - **Forbidden justifications**: parent MUST reject `pragmatic scope reduction`, `to save time`, `not novel enough`, `context budget running low`, `already sufficient coverage`, and any unlabeled reason. See `.claude/commands/_close/distillation-agent.md` for the authoritative list - `uncovered > 0` must trigger a STOP, not a warning. Do not proceed to Phase 6+ with uncovered candidates +- The workspace handbook is a derived `.view/` render (gitignored, regenerable — `rill-html-output.md`); its generation failure never blocks /close, and its result never gates the distillation self-check ## Related files - `.claude/commands/_close/analysis-agent.md` — Phase 2 Analysis sub-agent prompt template - `.claude/commands/_close/distillation-agent.md` — Phase 4 Distillation sub-agent prompt template +- `.claude/commands/_close/handbook-agent.md` — Phase 4 Handbook sub-agent prompt template +- `.claude/commands/_view/design-language.md` — authoring checklist the handbook follows - `.claude/commands/_distill/knowledge-agent.md` — referenced by distillation-agent.md for Evergreen check procedure - `.claude/commands/_distill/task-extraction.md` — referenced by Phase 8.1 for task extraction rules - ADR-073 (private, rill-dev `docs/decisions/`) — two-layer sub-agent delegation rationale diff --git a/skills/promote/SKILL.md b/skills/promote/SKILL.md index 2ced692..82c3769 100644 --- a/skills/promote/SKILL.md +++ b/skills/promote/SKILL.md @@ -101,7 +101,7 @@ By default `/promote` proposes creating a **new project** for the workspace, not Read `workspace/{id}/_summary.md` and the workspace directory's artifacts (`NNN-*.md`, plus committed HTML-canonical artifacts — `NNN-*.html` etc. with no same-basename MD source, whose HTML is the only record; skip derived HTML regenerable from MD sources, per `rill-html-output.md` principle 3). Build three candidate lists: -1. **Artifact references** — every artifact file in the workspace, with its `type` (decision / research / analysis / progress / review) and its `# ` heading. These will be linked from the project, not duplicated +1. **Artifact references** — every artifact file in the workspace, with its `type` (decision / research / analysis / progress / review) and its `# ` heading. HTML-canonical artifacts carry neither frontmatter nor a `# ` heading: take the title from `<title>` or the first `<h1>` (fall back to the filename when both are absent — absence is tolerated, not an error), and in place of `type` label them with their HTML class per `rill-html-output.md` (B primary / C judgment-handoff / D external presentation), judged from content. These will be linked from the project, not duplicated 2. **Key findings** (3–5 items) — pull from `_summary.md`'s Decisions / Key Findings section. The user will confirm before they land in `## Key Facts` 3. **Actionable items** — checkbox items in `_workspace.md` or in artifacts that look like committed actions (`- [ ] do X`). Same extraction rules as `/distill`'s `_distill/task-extraction.md` (see that file for the qualitative test of what counts as an action)