| name | docs-hero |
| description | Generate or update full project documentation suite (SRS / API / DB / system-architecture / code-standards / codebase-summary / design-guidelines — user picks via /morkit:init multi-select gate). Orchestrates 7 sub-skills with conflict-minimal updates from OpenSpec changes, brainstorm plans, or codebase scans. Standards: BrSE ITO Japan (SRS), arc42-lite (arch), Conventional Commits (standards), MADR (guidelines). Supports init / update / sync. |
| category | documentation |
| keywords | ["docs","srs","api","database","arch","standards","codebase","adr","brse","openspec","arc42","madr","conventional-commits","ito","japan"] |
| argument-hint | init|update|sync|apply-sync|rebuild-meta [options] |
| metadata | {"author":"docs-hero","version":"2.0.0"} |
Docs Hero Orchestrator
Single entry point for the documentation generation pipeline. Coordinates seven
sub-skills (generate-srs, generate-api-docs, generate-db-design,
generate-system-architecture, generate-code-standards,
generate-codebase-summary, generate-design-guidelines) with shared parsers,
the diff engine, atomic write, and a session lock.
Outputs at a glance
| Flag | Doc | Standard | Update | Sync |
|---|
srs | docs/srs.md (+ screen-specs/SCREEN-*.md) | BrSE ITO Japan | ✅ | ❌ |
api | docs/api-docs.md | REST + cURL + errors | ✅ | ✅ |
db | docs/database-design.md | Tables + Mermaid ERD | ✅ | ✅ |
arch | docs/system-architecture.md | arc42-lite + Mermaid | ✅ | ✅ |
standards | docs/code-standards.md | Conventional Commits + auto-style | ✅ | ✅ |
summary | docs/codebase-summary.md | README-style | ✅ | ✅ |
guidelines | docs/design-guidelines.md (+ adr/{id}-{slug}.md) | MADR | ✅ | ❌ (manual) |
guidelines does not participate in update flow's auto-iteration (it's
omitted from _DOC_FILES); use explicit --from-plan / --from-openspec
deltas with entity_type ∈ {DPR, PTN, ADR} to push changes manually.
Environment (plugin context)
This skill runs as a Claude Code plugin. Path resolution uses these variables:
CLAUDE_PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:?must be set by Claude Code}"
VENV="${HOME}/.claude/plugins/data/docs-hero/.venv"
PY="${VENV}/bin/python3"
ORCH_SCRIPTS="${CLAUDE_PLUGIN_ROOT}/skills/docs-hero-orchestrator/scripts"
SRS_SCRIPTS="${CLAUDE_PLUGIN_ROOT}/skills/generate-srs/scripts"
API_SCRIPTS="${CLAUDE_PLUGIN_ROOT}/skills/generate-api-docs/scripts"
DB_SCRIPTS="${CLAUDE_PLUGIN_ROOT}/skills/generate-db-design/scripts"
ARCH_SCRIPTS="${CLAUDE_PLUGIN_ROOT}/skills/generate-system-architecture/scripts"
STD_SCRIPTS="${CLAUDE_PLUGIN_ROOT}/skills/generate-code-standards/scripts"
SUM_SCRIPTS="${CLAUDE_PLUGIN_ROOT}/skills/generate-codebase-summary/scripts"
GUI_SCRIPTS="${CLAUDE_PLUGIN_ROOT}/skills/generate-design-guidelines/scripts"
PROJECT_DOCS_DIR="${PWD}/docs"
PROJECT_META="${PWD}/.docs-hero-meta.json"
PROJECT_LOCK="${PWD}/.docs-hero.lock"
PROJECT_TMP="${PWD}/.tmp"
Pre-flight check every mutating operation must perform:
test -d "$VENV" || { echo "ERROR: venv missing. Run /morkit:setup first." >&2; exit 1; }
Operations
| Command | Purpose |
|---|
/docs-hero init | Create docs from inputs (PDF/Excel/Docx/OpenSpec + codebase) |
/docs-hero update --from-plan {path} | Apply changes from a brainstorm plan.md |
/docs-hero update --from-openspec [name] | Apply 1 OpenSpec change |
/docs-hero sync | Generate sync proposals (codebase → docs) — read-only |
/docs-hero apply-sync --proposal {path} | Apply approved sync proposal |
/docs-hero rebuild-meta | Bootstrap .docs-hero-meta.json from existing docs |
Routing Logic
Parse first arg:
init → init flow (collect inputs → parse → user picks subset of 7 outputs → render)
update → parse --from-{plan,openspec} → Delta → diff engine → apply (iterates _DOC_FILES; guidelines is intentionally excluded)
sync → fan out to sub-skills' *_sync_propose.py for api/db/arch/standards/summary (no doc mutation; srs and guidelines skip)
apply-sync → call sub-skill's *_sync_apply.py to convert proposal → Delta → run update
rebuild-meta → meta-manager rebuild
- empty → AskUserQuestion to pick one operation.
AskUserQuestion caps at 4 options/question, so present the 4 primary ops (init / update / sync / apply-sync); rebuild-meta is a maintenance op reachable via the Other field or by invoking it explicitly.
Allowed --outputs values: srs, api, db, arch, standards, summary, guidelines (comma-separated, multi-select).
Init Flow
Doc-type selection (REQUIRED before dispatch): when invoked via /docs-hero:init
without an explicit --outputs flag, the caller (slash command) MUST ask the user
via AskUserQuestion which of the 7 doc types to generate and pass the resolved
comma-separated list as --outputs. Because AskUserQuestion caps at 4
options/question, the 7 types are split across two multiSelect questions sent
in one call (spec docs / standards docs) and the answers are unioned. Never default
silently — the user picks. See commands/init.md for the exact question template.
test -d "$VENV" || { echo "ERROR: run /morkit:setup first." >&2; exit 1; }
mkdir -p "$PROJECT_TMP"
"$PY" "$ORCH_SCRIPTS/parse_inputs.py" \
--inputs "$INPUT_DIR" \
--output "$PROJECT_TMP/raw-bundle.json"
STAGING="$PROJECT_TMP/staged"
mkdir -p "$STAGING"
"$PY" "$ORCH_SCRIPTS/dispatch_coordinator.py" init \
--project-model "$PROJECT_TMP/project-model.json" \
--language EN \
--outputs "$DIRECT_OUTPUTS" \
--docs-dir "$PROJECT_DOCS_DIR"
"$PY" "$ORCH_SCRIPTS/dispatch_coordinator.py" init \
--project-model "$PROJECT_TMP/project-model.json" \
--language EN \
--outputs "$STAGED_OUTPUTS" \
--docs-dir "$STAGING"
"$PY" "$ORCH_SCRIPTS/aggregate_report.py" \
--docs-dir "$PROJECT_DOCS_DIR" \
--output "$PROJECT_TMP/init-report.md"
Review Gate (per-doc loop)
A human review gate sits between staged render and docs/. It is the single
source of truth for the loop — brownfield init (step 3c above) and greenfield
G7 both reference this section instead of duplicating it.
Scope: the 5 code-derived docs — api, db, arch, standards, summary.
srs renders directly (out of scope; greenfield G6 already gates requirements).
design-guidelines gets the light confirm at the end, not the full loop.
Policy: warn-only. Skipping review never blocks coding — an un-approved doc
simply is not promoted into docs/, and the run ends with a warning. There is
NO PreToolUse hook and no hard block.
State + baseline live in .docs-hero-meta.json (same sidecar as
section_hashes): review.<doc> = {status, baseline_hashes, baseline_order}.
This is what makes the loop resumable and edit-preserving.
The review_gate.py mechanics (each runs against the staging dir):
RG="$ORCH_SCRIPTS/review_gate.py"
STAGING="$PROJECT_TMP/staged"
"$PY" "$RG" snapshot --staged "$STAGING/<doc>" --doc-name "<doc>" --meta "$PROJECT_META"
"$PY" "$RG" surface --staged "$STAGING/<doc>" --doc-name "<doc>" --docs-dir "$PROJECT_DOCS_DIR"
"$PY" "$RG" promote --staged "$STAGING/<doc>" --doc-name "<doc>" \
--docs-dir "$PROJECT_DOCS_DIR" --meta "$PROJECT_META"
Keystone: snapshot records the hash of the pre-edit render, and
promote writes that pre-edit hash into section_hashes. So any section the
reviewer edits while reviewing registers as manual_edit and survives later
update/sync (locked by tests/test_review_edit_preservation.py). NEVER
snapshot after the reviewer edits.
LLM-driven loop (Claude orchestrates; Python only does the mechanics):
pending = meta_manager.list_pending(PROJECT_META, STAGED_OUTPUTS_FILES) # resume-aware
for doc in pending: # approved docs from a prior run are skipped
review_gate snapshot <doc> # pre-edit baseline
loop:
surface <doc> → present sections + ⚠ flags via AskUserQuestion [Approve | Sửa tiếp]
Approve → review_gate promote <doc> → next doc
Sửa tiếp → reviewer edits $STAGING/<doc> and saves, OR gives feedback
→ re-render that one doc into staging → snapshot again → surface again
- ⚠ low-confidence flags: when
surface returns an empty diff (doc has no
ID-anchored sections) or large churn, Claude flags it ⚠ in the question so the
reviewer looks closer.
- Anchorless-doc caveat: prose-only docs with no ID-anchored sections (e.g.
codebase-summary.md) have an empty section-hash baseline, so a review-time
prose edit is NOT auto-flagged as manual_edit by update/sync. For those
docs the ⚠ flag + reviewer judgement is the protection, not the diff engine.
- design-guidelines confirm (light): after its direct render, ask ONE
AskUserQuestion
[OK | Sửa | Bỏ]. OK keeps it; Sửa → reviewer edits
docs/design-guidelines.md directly; Bỏ → note it was skipped. No per-section loop.
- Warn-only summary (end of run): after the loop, report any doc still
pending — "N docs chưa review (chưa promote vào docs/): …". Coding is NOT blocked.
- Resume: re-running
init calls list_pending first, so already-approved
docs are skipped and only un-approved docs re-enter the loop.
Update Flow
test -d "$VENV" || { echo "ERROR: run /morkit:setup first." >&2; exit 1; }
"$PY" "$ORCH_SCRIPTS/lock_manager.py" acquire --lock "$PROJECT_LOCK" || exit 1
trap '"$PY" "$ORCH_SCRIPTS/lock_manager.py" release --lock "$PROJECT_LOCK"' EXIT
"$PY" "$ORCH_SCRIPTS/parse_plan.py" --plan "$PLAN_PATH" --output "$PROJECT_TMP/delta.json"
"$PY" "$ORCH_SCRIPTS/parse_openspec.py" --change-dir "$OPENSPEC_DIR" --output "$PROJECT_TMP/delta.json"
"$PY" "$ORCH_SCRIPTS/dispatch_coordinator.py" update \
--delta "$PROJECT_TMP/delta.json" \
--docs-dir "$PROJECT_DOCS_DIR" \
--meta "$PROJECT_META"
Sync Flow (2-step)
Step 1 — propose (read-only, no lock). All 5 code-derived docs; each
*_sync_propose.py scans the codebase for its own signals and writes a checkbox
proposal:
"$PY" "$API_SCRIPTS/api_sync_propose.py" \
--codebase-paths "$CODEBASE_PATHS" \
--existing-doc "$PROJECT_DOCS_DIR/api-docs.md" \
--output "$PROJECT_TMP/api-sync-proposal.md"
"$PY" "$DB_SCRIPTS/db_sync_propose.py" \
--codebase-paths "$CODEBASE_PATHS" \
--existing-doc "$PROJECT_DOCS_DIR/database-design.md" \
--output "$PROJECT_TMP/db-sync-proposal.md"
"$PY" "$SUM_SCRIPTS/codebase_summary_sync_propose.py" \
--codebase-paths "$CODEBASE_PATHS" \
--existing-doc "$PROJECT_DOCS_DIR/codebase-summary.md" \
--output "$PROJECT_TMP/codebase-summary-sync-proposal.md"
"$PY" "$ARCH_SCRIPTS/system_architecture_sync_propose.py" \
--codebase-paths "$CODEBASE_PATHS" \
--existing-doc "$PROJECT_DOCS_DIR/system-architecture.md" \
--output "$PROJECT_TMP/system-architecture-sync-proposal.md"
"$PY" "$STD_SCRIPTS/code_standards_sync_propose.py" \
--codebase-paths "$CODEBASE_PATHS" \
--existing-doc "$PROJECT_DOCS_DIR/code-standards.md" \
--output "$PROJECT_TMP/code-standards-sync-proposal.md"
Step 2 — apply-sync (after user ticks checkboxes). Run only for proposals the
user actually edited. Map each proposal to its apply script:
| Proposal | Apply script |
|---|
api-sync-proposal.md | $API_SCRIPTS/api_sync_apply.py |
db-sync-proposal.md | $DB_SCRIPTS/db_sync_apply.py |
codebase-summary-sync-proposal.md | $SUM_SCRIPTS/codebase_summary_sync_apply.py |
system-architecture-sync-proposal.md | $ARCH_SCRIPTS/system_architecture_sync_apply.py |
code-standards-sync-proposal.md | $STD_SCRIPTS/code_standards_sync_apply.py |
"$PY" "$API_SCRIPTS/api_sync_apply.py" \
--proposal "$PROJECT_TMP/api-sync-proposal.md" \
--output "$PROJECT_TMP/api-delta.json"
"$PY" "$ORCH_SCRIPTS/dispatch_coordinator.py" update \
--delta "$PROJECT_TMP/api-delta.json" \
--docs-dir "$PROJECT_DOCS_DIR" \
--meta "$PROJECT_META"
Lock Acquisition (mutating ops only)
Before any mutate:
"$PY" "$ORCH_SCRIPTS/lock_manager.py" acquire --lock "$PROJECT_LOCK"
- If lock exists + valid (PID alive, < 1h) → exit
- If stale → cleanup + acquire
- On exit → release
Read-only ops (sync propose, rebuild-meta verify) skip the lock.
File Ownership
The orchestrator owns:
.docs-hero-meta.json (sidecar, gitignored)
.docs-hero.lock (transient, gitignored)
- Coordination scripts in
scripts/
Sub-skills own their respective doc files (see each SKILL.md).
References
- Templates: each sub-skill's
templates/
- Phase specs:
plans/260503-2222-generate-prd-skill/phase-*.md
- Schema:
scripts/lib/normalized_schema.py (Pydantic single source of truth)
- Diff engine:
scripts/compute_diff.py + scripts/apply_patch.py