| name | lld-docs |
| description | Use when generating, editing, or merging Low-Level Design (LLD) documents at `docs/lld/<component>.md` or `docs/shield/<feature>/lld-<component>.md`. Triggers on /lld command (Path A) and on /plan TRD-driven authoring (Path B, M2 plan). Owns the backend and infra templates, atomic write, provenance stamp, and §14 Changelog convention. |
lld-docs
Author component-scoped Low-Level Design documents in one of two operational
modes:
draft — net-new component. Emit a fresh template (backend or infra
per the resolved type), populate sections from the available context
(PRD, research, TRD, repo evidence), and atomic-write to the target path.
merge — enhancement of an existing canonical LLD. The caller has
already copied docs/lld/<component>.md into the target draft path; this
skill identifies which sections the current work affects, edits those
sections in the draft, and leaves untouched sections verbatim.
Both modes preserve all 14 sections in canonical order (per
shield/schema/lld-sections-<type>.yaml) and emit explicit {#kebab-case}
anchors. The shared header metadata block precedes §1; the §14 Changelog row
is the only mandatory addition on merge runs.
Template selection
type argument | Slug allow-list | Section template |
|---|
backend | shield/schema/lld-sections-backend.yaml | lld-template-backend.md |
infra | shield/schema/lld-sections-infra.yaml | lld-template-infra.md |
type is required. It's resolved by the caller (the /lld command or /plan)
before invoking this skill.
Output paths
| Caller | Target path |
|---|
/lld <component> (Path A) | docs/lld/<component>.md (canonical, direct) |
/plan TRD-driven (Path B, M2 plan) | docs/shield/<feature>/lld-<component>.md (draft) |
This skill does NOT promote drafts to the canonical path — that's /implement's
job at milestone close (M2 plan, step 5h).
Atomic write contract
- Compute the target path.
- Write content to
<target>.tmp.
- Atomic-rename
<target>.tmp → <target> via os.replace() (Python) or
mv (shell).
- On any failure between steps 2 and 3 (write error, signal interrupt),
remove
<target>.tmp and surface the error. Never leave a partial
<target> behind.
- Before the write, apply
shield:writing-style to author-written prose
sections (overview, rationale, narrative). Do NOT alter the provenance
stamp, the §14 Changelog rows, header metadata, code blocks, or
n/a — <reason> escapes.
When emitting Mermaid diagrams, follow shield/skills/general/mermaid-authoring.md
(hard syntax rules — no semicolons, no reserved-word actors, balanced blocks).
Mermaid validation (before write)
Before the atomic write, validate every ```mermaid block:
- Run
python3 shield/scripts/validate_mermaid.py <target>.tmp (or validate
the composed content). If it passes, proceed to the write.
- If it fails, run
python3 shield/scripts/validate_mermaid.py --fix <target>.tmp
to repair the deterministic classes, then re-validate.
- If findings remain, rewrite the offending diagram from the parse error,
re-validate, and retry (bounded — 3 attempts). Never write a file whose
diagrams do not validate.
Diagram syntax rules: shield/skills/general/mermaid-authoring.md.
Provenance stamp
The first line after the document's frontmatter (or after the H1, if no
frontmatter is used) MUST be:
{plugin-version} is read from .claude-plugin/marketplace.json shield entry.
{YYYY-MM-DD} is today's date in UTC.
Header metadata
Populate the header block (above §1) as follows:
| Field | Source |
|---|
| Feature | The active feature folder slug if invoked by /plan; else "manual" (Path A). |
| Owner | git config user.email of the invoking user. |
| Status | draft (new) or unchanged (merge). /implement sets promoted on canonical promotion (M2 plan). |
| Linked PRD | Relative path from the LLD to the active feature folder's prd.md, if it exists; else "n/a". |
| Linked plans | List of relative paths to plan.md(s) — initialised to [<active plan>] for Path B; [] for Path A. |
| Version | 0.1.0 for net-new; bump-patch on merge runs (e.g. 0.1.0 → 0.1.1). |
| Last updated | Today's date YYYY-MM-DD. |
§14 Changelog row format
Every drafting or merge run appends one row to §14:
| <Touch> | <YYYY-MM-DD> | <Summary> | <Story IDs> |
Where:
<Touch> = M<n> (Path B) or manual (Path A).
<Summary> = one-line human-readable. For Path B, derives from the
milestone name or the calling story's name. For Path A, takes the form
"reverse-doc by <owner>" or "edit by <owner>".
<Story IDs> = space-separated for Path B; n/a for Path A.
n/a — <reason> escape
Any section may declare n/a — <reason> when it genuinely doesn't apply.
Vague TBDs (TBD, TODO, to be determined, etc.) in always-on sections
cause the lld-docs eval to fail.
Promote-on-demand sections
Backend §9 + §11 and infra §7 + §11 default to collapsed <details> blocks:
<details>
<summary>§9 Configuration</summary>
(promote-on-demand — lift by replacing `<details>` with `<details open>` and
populating non-vague content)
</details>
Lift them only when the component's nature warrants it; an empty PoD section
is fine, an open-but-vague PoD section is a finding (M3 plan).
Forced subsections
Backend §12 has 8 forced subsections; infra §12 has 6. Each MUST be present
with non-vague content (or n/a — <reason>). The exact subsection list comes
from shield/schema/lld-sections-<type>.yaml (forced_subsections key).
Invocation contract
Callers (M1: /lld command; M2: /plan) invoke this skill with:
| Input | Required | Notes |
|---|
component | yes | kebab-case identifier. |
type | yes | backend or infra. |
mode | yes | draft or merge. |
target_path | yes | Absolute or repo-relative path. |
context | no | Dict of {prd_path, trd_path, research_path, story_design_refs}; populated by Path B. |
The skill returns:
- The number of sections populated (informational; not a contract).
- The §14 Changelog row that was appended.
- Any sections that declared
n/a — <reason> (for the run summary).
Failure modes
| Failure | Behavior |
|---|
| Target directory doesn't exist | Create it (mkdir -p). |
<target>.tmp write fails | Remove .tmp; raise. Hard fail per design §8 row 8. |
<target> already exists in draft mode | Caller's job to decide overwrite vs. abort. If caller passes mode=draft and target exists, default to edit-in-place + Changelog row append (Path A reverse-doc semantics); never silently clobber a populated file's content. |
| Section count after generation ≠ 14 | Raise (template emitter bug). |
| Forced subsection count under §12 ≠ allow-list count | Raise (template emitter bug). |