Embed a machine-readable markdown digest in every HTML plan

High completed
2026-06-10 agentics feature High effort

Ship a machine-readable markdown digest inside every HTML plan — a non-rendering <script type="text/markdown" id="plan-digest"> block as the first element child of <body> — so the implementer, the workflow author, and the 5–7 review-team agents read ~3.7k tokens of spec instead of re-reading ~21k tokens of styled HTML, with zero second source-of-truth file.

Implement Read and implement all steps in the plan at docs/plans/embed-markdown-digest-in-html-plans.md — Embed a machine-readable markdown digest in every HTML plan. Verify against the plan's Tests, Verification, and Acceptance Criteria before reporting done. If everything passed, mark completion in docs/plans/embed-markdown-digest-in-html-plans.md — tick each step's [x] marker and each criterion's - [x], set status: completed — and re-render the HTML from the spec. If any check failed, leave status: in-progress and say which.
More ways to run this plan — goal & workflow prompts, file path
Pursue as goal — optimize for the outcome, in parallel
Achieve this goal: Embed a machine-readable markdown digest in every HTML plan. The plan at docs/plans/embed-markdown-digest-in-html-plans.md describes one approach — use it as reference, but optimize for the outcome. Fan out across parallel subagents where that serves the outcome. Verify against the plan's Tests, Verification, and Acceptance Criteria before reporting done. If everything passed, mark completion in docs/plans/embed-markdown-digest-in-html-plans.md — tick each step's [x] marker and each criterion's - [x], set status: completed — and re-render the HTML from the spec. If any check failed, leave status: in-progress and say which.
Run as workflow — launch parallel subagents
Run a workflow to implement the plan at docs/plans/embed-markdown-digest-in-html-plans.md — Embed a machine-readable markdown digest in every HTML plan. Brief subagents with the plan file at docs/plans/embed-markdown-digest-in-html-plans.md. Reserve a final verification phase for the lead agent, not a subagent. Verify against the plan's Tests, Verification, and Acceptance Criteria before reporting done. If everything passed, mark completion in docs/plans/embed-markdown-digest-in-html-plans.md — tick each step's [x] marker and each criterion's - [x], set status: completed — and re-render the HTML from the spec. If any check failed, leave status: in-progress and say which.
File embed-markdown-digest-in-html-plans.html
Path docs/plans/embed-markdown-digest-in-html-plans.html
Spec docs/plans/embed-markdown-digest-in-html-plans.md
Definition of done 10 / 10 done

Context

The story behind this plan — what prompted the work and why it matters now.

A generated HTML plan is a single self-contained file of ~86–97 KB (~21.5k tokens), but only about 17% of that is plan content — the other ~83% is the fixed skeleton CSS and JS, byte-for-byte identical in every plan. The Read tool cannot skip <style> or <script> blocks, so every consumer that opens a plan pays for the whole file.

That cost is paid repeatedly. The implementer reads it; a Run a workflow… author reads it; and a single review-plan cycle has the lead plus up to 7 reviewer agents each instructed to read the plan — roughly ~170k tokens per review, of which ~140k is the same CSS read eight times. review-plan already says "exclude <style> and <script> " but the Read tool can't honor that — it's aspiration, not mechanism.

This plan embeds a spec-only markdown digest inside the plan rather than writing a sibling .md file. A sibling file is a second source of truth that drifts the moment implementation flips checkboxes or review-plan edits content, and it collides with the plan-interview .md tooling. An embedded <script type="text/markdown"> block keeps the single-file guarantee, never renders, and is extractable in any session — no plugin install required — via a flag-and-exit awk : awk '/<script[^>]*id="plan-digest"/{f=1;next} f&&/<\/script>/{exit} f' <file> (a simple awk range would re-trigger on later mentions of the id, as this very plan demonstrates).

Resolved decisions (from clarification): the block is the first element child of <body> (extracted with awk ); the digest is spec-only so status flips and checkbox ticks never invalidate it; this plan backfills the ~50 existing plans via an idempotent script; and the 7 reviewers read the digest only while the lead keeps full HTML for its selector-based edits.

Files that change

Every file this plan touches, and what happens to each one.

agentics/
  • .claude-plugin/marketplace.json modified bump plan-agent 2.1.0 → 2.2.0
  • kit/plugins/plan-agent/
    • CHANGELOG.md modified add 2.2.0 entry
    • README.md modified document the digest + extraction
  • agents/plan-reviewer-*.md modified 7 defs read the digest, not full HTML
  • skills/implementation-plan/SKILL.md modified contract, generation, refresh, prompts; includes buildImplementPrompt() instruction update
  • reference/SKELETON.html modified add #plan-digest block (first element child of body)
  • skills/review-plan/SKILL.md modified digest-only reviewers, Step 7 refresh
  • references/role-prompts.md modified 7 briefs read the digest
  • scripts/backfill-plan-digests.mjs new idempotent injector over existing plans
  • tests/plugins/
    • test-plan-digest.sh new objective smoke test
    • test-backfill-digest.mjs new backfill unit + integration

Steps

The step-by-step work, in order — each step says what to do, why it matters, and how to check it worked.

1
done Add the #plan-digest block to SKELETON.html as the first element child of <body>
Why
Every generated plan inherits structure from the skeleton, so the block must live there once. Place it immediately after <body> (before the icon sprite) as <script type="text/markdown" id="plan-digest">{plan-digest}</script> — a non-executable script type the browser never renders or fetches, preserving the no-CDN, single-file guarantee. Add a guiding HTML comment above it documenting the spec-only rule and the flag-and-exit awk extraction — the comment is a comment node, not an element, so the script remains the first element child of <body> (the property the smoke test asserts, mirroring DOM firstElementChild semantics).
Verify
grep -n 'id="plan-digest"' SKELETON.html shows the block within the first lines after <body> ; open the skeleton in a browser and confirm the block produces no visible output and no console error. Also confirm the placeholder token used (e.g. {plan-digest} ) is documented in a comment or in implementation-plan/SKILL.md Step 2 so the generator knows exactly what string to replace when filling the block.
2
done Define the digest content + escaping contract in implementation-plan/SKILL.md
Why
A precise, stable contract is what lets the generator, every consumer, and the backfill script agree on shape. Specify the digest as the authored spec only — title, objective, context, file list, steps (action/why/verify), tests, acceptance-criteria text, verification — and explicitly exclude live state (status, checkbox states, completion report, copy buttons, CSS/JS). Insert markdown raw (not HTML-escaped); the only guard is to replace any literal closing-script sequence with a backslashed form ( <\/script ) so it cannot terminate the block early. Define the canonical extractor as the flag-and-exit awk '/<script[^>]*id="plan-digest"/{f=1;next} f&&/<\/script>/{exit} f' — a simple awk range re-triggers on any later line that mentions the id, so it must not be the documented form.
Verify
Re-read SKILL.md ; the new subsection enumerates the included fields, the excluded live-state fields, the "raw markdown, not HTML-escaped" rule, and the <\/script guard.
3
done Wire digest generation + content-edit refresh into the generation workflow
Why
In SKILL.md Step 2, after the sections are drafted, build {plan-digest} from the final content and fill the skeleton placeholder. Add a rule to HTML Output Requirements : any later Edit that changes spec content (Step 5b interview findings, the Step 8 "Edit the plan" loop) must regenerate the block in the same pass; status flips (Step 6) and acceptance-criteria checks must not touch it. This keeps the digest authoritative without coupling it to progress churn. The digest carries no checksum or timestamp — staleness is prevented by this refresh rule plus the CI guard in Next Steps, not by an integrity field.
Verify
SKILL.md Step 2 and HTML Output Requirements name the digest fill and the refresh-on-content-edit rule; Step 6 and the acceptance-criteria gate explicitly state they do not regenerate the digest. Generate a throwaway plan and confirm the digest matches the visible spec.
4
done Add the digest-extraction clause to the implement & workflow prompts
Why
The implementer and the workflow author are the primary beneficiaries — they start in a fresh session with no context. Update the {implement-prompt} / {workflow-prompt} templates and the buildImplementPrompt() instruction list to direct the consumer to start from the digest, e.g. append: "Start from the markdown spec in the #plan-digest block (extract: awk '/<script[^>]*id="plan-digest"/{f=1;next} f&&/<\/script>/{exit} f' <file> ) before opening the full HTML."
Verify
Generate a sample plan; both the implement <code> row and the workflow prompt carry the extraction one-liner, and the copied prompt from buildImplementPrompt() includes the "start from the digest" instruction.
5
done Switch the 7 review-plan reviewers to digest-only reads
Why
This is the largest token win (~120k per review cycle) and reviewers only emit prose findings, so they never need the DOM. In references/role-prompts.md , change every "Read the implementation plan at <ABSOLUTE_PATH> " to extract and read the #plan-digest block; mirror the change in all 7 individual agents/plan-reviewer-*.md defs ( plan-reviewer-architecture.md , plan-reviewer-completeness.md , plan-reviewer-testability.md , plan-reviewer-risk.md , plan-reviewer-conventions.md , plan-reviewer-ux.md , plan-reviewer-accessibility.md ) that say "Read the plan's full content." In review-plan/SKILL.md Step 4, state the split: reviewers get the digest, the lead reads full HTML for Step 7 selector edits. When a plan has no digest yet (e.g. an old plan not backfilled), reviewers fall back to reading the full HTML for that run so reviews never break.
Verify
grep -L plan-digest kit/plugins/plan-agent/agents/plan-reviewer-*.md returns nothing (all 7 defs updated); role-prompts.md references the digest for all 7 roles plus the no-digest full-HTML fallback; SKILL.md Step 4 documents the lead-vs-reviewer read split.
6
done Add a digest-refresh pass to review-plan Step 7
Why
Step 7 mutates spec content by CSS selector (Pass 1 inline edits), which makes the embedded digest stale for the next consumer. Add a "Pass 3 — refresh the digest": after the inline edits and the review-append, regenerate the #plan-digest block from the now-updated plan content. Skip it when output mode is "review only" (no content was changed).
Verify
review-plan/SKILL.md Step 7 lists Pass 3; a dry walk-through confirms it runs only after Pass 1 applied edits in "update plan in place" mode and is skipped in "review only".
7
done Create the backfill injector scripts/backfill-plan-digests.mjs
Why
The chosen scope backfills the ~50 existing plans. Write an idempotent Node script (matching the repo's existing scripts/*.mjs convention) that scans docs/plans/*.html (skipping index.html and any file already containing #plan-digest ), parses title/objective/files/steps/tests/criteria/verification from the stable skeleton structure (IDs/classes: #objective , .step-card , #tests , #criteria-list , #verification , .file-tree ), builds the digest (with the <\/script guard), and inserts it as the first element child of <body> . It must never touch status, checkboxes, or progress state, must only inject when all expected sections parse — skipping and reporting any plan it cannot fully parse rather than writing a partial digest — and must support --dry-run , printing injected / skipped / failed counts.
Verify
node scripts/backfill-plan-digests.mjs --dry-run reports counts with zero failures; a real run injects digests; a second real run injects 0 (all skipped). Plans that cannot be fully parsed are listed as skipped, not partially injected; git diff on a completed plan shows only the added digest block, no status/checkbox changes.
8
done Bump version, changelog, and README (plan-agent 2.1.0 → 2.2.0)
Why
Adding new behavior is a minor bump per the project versioning rules, and CLAUDE.md requires docs/changelog updates with any plugin change — the new value must be higher than main's, and 2.1.0 was taken on main by the findings-walkthrough feature. Set plan-agent version to 2.2.0 in marketplace.json , add a 2.2.0 CHANGELOG.md entry describing the digest + backfill, and add a "Machine-readable digest" subsection to the plugin README.md showing the awk extraction one-liner.
Verify
marketplace.json shows plan-agent at 2.2.0 (and the .claude/settings.json JSON-validation hook passes); CHANGELOG.md top entry is 2.2.0 ; the README has the digest subsection with the extraction command.

Tests

The tests that prove the change does what it promises.

Tier 1 — Code-touching plan
Objective Every generated plan carries an extractable, accurate digest File: tests/plugins/test-plan-digest.sh Type: smoke test (shell, matching the repo's tests/<area>/*.sh convention) Asserts: (1) SKELETON.html wraps the {plan-digest} placeholder in a <script type="text/markdown" id="plan-digest"> that is the first element child of <body> (comment nodes before it are allowed — match the first tag after <body> , skipping comments); (2) running the awk extractor against a committed fixture plan returns non-empty markdown containing the fixture's objective and at least one step action; (3) review-plan role-prompts.md and all 7 agents/plan-reviewer-*.md files reference plan-digest and the no-digest full-HTML fallback. Run: bash tests/plugins/test-plan-digest.sh
Unit Backfill pure functions File: tests/plugins/test-backfill-digest.mjs Targets: buildDigest() , hasDigest() , extractSections() exported from scripts/backfill-plan-digests.mjs Key cases: extractSections() pulls objective/steps/criteria from a sample plan string; buildDigest() emits the spec fields and applies the <\/script guard; hasDigest() is true for a plan already containing the block and false otherwise.
Integration Backfill over a temp copy of docs/plans File: tests/plugins/test-backfill-digest.mjs Targets: the backfill-plan-digests.mjs CLI end-to-end against a throwaway temp directory Key cases: a todo, an in-progress, and a completed fixture plan each gain a digest; a pre-seeded plan is skipped (idempotency); a plan missing a parseable section is skipped and listed (no partial digest); the bytes of data-status , <meta name="plan-status"> , and every acceptance-criteria checkbox are byte-identical before and after; a fixture plan whose content contains the literal string </script in a code block is injected and the guard fires correctly (closing tag does not terminate the digest block early).
Integration Digest refresh after review-plan Step 7 edits File: tests/plugins/test-plan-digest.sh Targets: the digest-refresh pass (Pass 3) in review-plan/SKILL.md Step 7 Key cases: after a spec-content edit is applied to a fixture plan via review-plan update-in-place mode, the #plan-digest block reflects the updated content; in "review only" mode, the digest is unchanged; status/checkbox bytes are unaffected by either mode.
Integration No-digest fallback in review-plan File: tests/plugins/test-plan-digest.sh Targets: reviewer fallback path in review-plan/SKILL.md Step 4 and each agents/plan-reviewer-*.md Key cases: when a plan has no #plan-digest block, the reviewer defs and role-prompts instruct fallback to full HTML; the smoke test asserts that every agents/plan-reviewer-*.md file contains both the digest-extraction clause and the fallback clause.

Definition of done

The plan counts as done when every statement below is true — check each one off as you verify it.

Final check

One last pass to confirm the whole change works end to end.

Generation path: run /plan-agent:implementation-plan on a throwaway objective and confirm the resulting plan has a #plan-digest block as the first element child of <body> , that its markdown matches the visible objective/steps/criteria/verification, that the block renders nothing in a browser, and that the canonical flag-and-exit awk extractor returns the spec. Confirm both the implement and workflow prompts carry the extraction clause.

Backfill path: run node scripts/backfill-plan-digests.mjs --dry-run then a real run over docs/plans/ ; spot-check one completed, one in-progress, and one todo plan — each must gain a digest while git diff shows no change to data-status , <meta name="plan-status"> , or any criteria checkbox. Re-run and confirm 0 injected.

Review path: run review-plan on a sample plan; confirm each reviewer was briefed with the digest (not full HTML), that a digest-less plan falls back to full HTML, and that Step 7 regenerated the digest after applying inline edits.

Tests: bash tests/plugins/test-plan-digest.sh and node tests/plugins/test-backfill-digest.mjs both exit 0.

Wrapping up

Three gates that must all pass before this plan is marked completed.

Required

Completion Report

Version criterion — planned 2.2.0, shipped 2.3.0
PR #317 (markdown plan conversion) took 2.2.0 on main while this plan was in flight. The criterion's intent — bump plan-agent above the value on main with a matching CHANGELOG entry — is met at 2.3.0.

Next steps

Follow-up ideas that came up along the way — none of them are required to finish this plan.

Add a CI guard so new plans must ship a digest

Paste this prompt into Claude to execute this follow-up:

Add a CI check to the agentics repo that fails a PR when any added or modified file under docs/plans/ ending in .html (excluding index.html) does not contain a `<script type="text/markdown" id="plan-digest">` block as the first element child of <body> (skip comment nodes when checking). Implement it as a small Node script under scripts/ plus a step in the existing GitHub Actions workflow, mirroring the style of scripts/merge-marketplace.mjs and the tests/ shell smoke tests. Skip plans whose frontmatter meta plan-status is "completed" only if they predate the digest feature; otherwise require the block. Report the files you changed.
Slice the digest per-step for workflow subagents

Paste this prompt into Claude to execute this follow-up:

In kit/plugins/plan-agent/skills/implementation-plan/SKILL.md, update the generated workflow prompt so that when a plan is implemented via /workflows, the orchestrator passes each subagent only its relevant slice of the #plan-digest markdown (the specific step plus shared objective/verification context) instead of having every workflow agent re-read the whole plan file. Define how the workflow script extracts and partitions the digest by step heading, and document the token rationale. Do not change the single-session implement path. Report the SKILL.md sections you edited.
Teach the plan-interview markdown tooling about the digest

Paste this prompt into Claude to execute this follow-up:

The plan-interview plugin's markdown-to-html and plan-status skills operate on .md plan files. Update them to be digest-aware: when markdown-to-html converts a plan to HTML, emit a #plan-digest block as the first element child of <body> using the same spec-only contract defined in plan-agent's implementation-plan SKILL.md; and when plan-status reads a plan, prefer the digest for status-independent spec inspection. Keep the two contracts in sync by referencing plan-agent's definition rather than duplicating it. Report which skills you changed and any contract divergences you had to resolve.
A /plan-agent:plan-digest utility command Wish List

Speculative / blue-sky idea — not on the critical path. Paste into Claude when ready to explore:

Paste this prompt into Claude to execute this follow-up:

Design a command-only skill /plan-agent:plan-digest <file> that prints the #plan-digest markdown for any HTML plan to stdout (extracting it with the canonical awk one-liner), and, when the block is missing, falls back to generating an ephemeral digest from the plan's live DOM structure without writing to the file. Cover path-safety (basename resolution under the plans roots), a --raw flag to keep the script wrapper, and a clear error when the file is not a plan. Provide the SKILL.md and an allowed-tools line.