plugins/base/skills/generate-user-docs/SKILL.md
Synchronizes user-facing documentation with the current knowledge base through validate -> stale gate -> scan -> approval -> process orchestration.
npx skillsauth add rp1-run/rp1 generate-user-docsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
§ROLE: User-doc sync orchestrator. Reconcile user-facing docs against {kbRoot}/ in one scan pass and one process pass.
§OBJ
{workRoot}/§DO
rp1-base:scribe only for file batchesscan_results.json; do NOT delete it automatically§DONT
§PATHS
RUN_ID from the generated Workflow Bootstrap sectionRUN_NAME as "Docs: sync user docs" (max 60 chars)DATESTAMP to the current date in YYYY-MM-DDSESSION_DIR=docs-sync/{DATESTAMP}-{RUN_ID}SCAN_RESULTS_REL={SESSION_DIR}/scan_results.jsonSCAN_RESULTS_PATH={workRoot}/{SCAN_RESULTS_REL}stateDiagram-v2
[*] --> discover
discover --> validate_kb : docs_ready
discover --> failed : no_docs
validate_kb --> scan : kb_current
validate_kb --> stale_kb_gate : kb_stale
validate_kb --> failed : kb_invalid
stale_kb_gate --> scan : continue_with_stale
stale_kb_gate --> cancelled : rebuild_requested
stale_kb_gate --> cancelled : rejected
scan --> approve : results_written
scan --> failed : scan_failed
approve --> process : approved
approve --> cancelled : rejected
process --> finalize : processing_done
process --> failed : process_failed
finalize --> [*] : done
failed --> [*] : stopped
cancelled --> [*] : stopped
First emit:
rp1 agent-tools emit \
--workflow generate-user-docs \
--type status_change \
--run-id {RUN_ID} \
--name "{RUN_NAME}" \
--step discover \
--data '{"status": "running"}'
State progression:
discover, validate_kb, stale_kb_gate, scan, approve, process, and finalize with {"status": "running"}failed with {"status": "failed"}emit end-run --run-id {RUN_ID} --outcome cancelled --reason "..." for intentional stops from stale_kb_gate or approve. Do not use skipped as the run-level cancellation status.finalize with {"status": "completed"}{% plan_tool "Track workflow: discover, validate_kb, stale_kb_gate, scan, approve, process, finalize. Keep exactly one step in progress." %}
Discover candidate user docs via Glob:
README.mddocs/**/*.mddocs/**/*.mdx**/*.md**/*.mdxDedupe by path. Keep project-relative paths only.
Exclude common generated, dependency, build, and internal metadata paths:
.rp1/**, node_modules/**, .git/**, vendor/**, .venv/**, venv/**dist/**, **/dist/**, build/**, out/**, coverage/**, **/target/**, **/__pycache__/**.cache/**, .next/**, .nuxt/**, .svelte-kit/**, .idea/**, .vscode/**, .github/**Exclude non-user-doc basenames:
AGENTS.mdDEVELOPMENT.mdCHANGELOG.mdLICENSELICENSE.mdCODE_OF_CONDUCT.mdSECURITY.mdCONTRIBUTING.md:
Set DOC_FILES to the remaining paths.
If DOC_FILES is empty:
ERROR: No user-facing documentation files discovered.
Searched:
- README.md
- docs/**/*.md
- docs/**/*.mdx
- **/*.md
- **/*.mdx
failedLog:
Discovered {DOC_FILES.length} documentation files
Pick up to 3 sample files for style inference:
README.md if presentdocs/ fileRead each sample and infer:
heading_style: atx | setextlist_marker: dash | asterisk | plus | numberedcode_fence: backtick | tilde | indentlink_style: inline | referencemax_line_length: p90 line length rounded to nearest 10 and clamped to 80..120Build STYLE_CONFIG:
{
"heading_style": "atx",
"list_marker": "dash",
"list_style": "dash",
"code_fence": "backtick",
"link_style": "inline",
"max_line_length": 100
}
Rules:
list_marker is canonicallist_style is a compatibility alias; keep it equal to list_markerLog the inferred style in one short block.
Use Glob to confirm {kbRoot}/state.json exists.
If missing:
ERROR: Knowledge base not found.
Run /rp1-base:knowledge-build, then retry.
failedRead {kbRoot}/state.json.
Extract:
generated_atgit_commitIf git_commit missing or empty:
ERROR: Invalid KB state.
state.json is missing git_commit.
Run /rp1-base:knowledge-build, then retry.
failedVerify the commit exists:
git cat-file -e {KB_GIT_COMMIT}^{commit} 2>/dev/null || echo "INVALID"
If output is INVALID:
ERROR: KB references unknown git commit.
Run /rp1-base:knowledge-build, then retry.
failedCompute:
git rev-parse HEAD
git rev-list --count {KB_GIT_COMMIT}..HEAD
Store:
HEAD_COMMITCOMMITS_SINCE_KBCompute repo changes since KB build:
git diff --name-only {KB_GIT_COMMIT} HEAD
Derive STALE_CHANGES:
.rp1/work/**DOC_FILESBuild:
{
"state": "current",
"generated_at": "ISO-8601 timestamp",
"git_commit": "commit sha",
"head_commit": "commit sha",
"commits_behind": 0,
"stale_paths": []
}
Rules:
state = "current" when STALE_CHANGES is emptystate = "stale" when STALE_CHANGES is non-emptycommits_behind = COMMITS_SINCE_KBstale_paths = STALE_CHANGESThis filter is intentionally strict about non-doc-output changes and intentionally permissive about changes inside DOC_FILES; those docs are the workflow outputs being reconciled.
If STALE_CHANGES is empty:
KB sync verified
Commit: {KB_GIT_COMMIT}
Built: {generated_at}
If STALE_CHANGES is non-empty:
WARNING: Knowledge base is out of sync for this workflow.
KB Generated: {generated_at}
KB Commit: {KB_GIT_COMMIT}
Current HEAD: {HEAD_COMMIT}
Behind by: {COMMITS_SINCE_KB} commits
KB-affecting changes since KB build (showing up to 30):
{first 30 stale paths}
rp1 agent-tools emit \
--workflow generate-user-docs \
--type waiting_for_user \
--run-id {RUN_ID} \
--step stale_kb_gate \
--data '{"prompt": "Knowledge base is stale. Continue with the stale KB, rebuild the KB first, or cancel?", "context": "KB is {COMMITS_SINCE_KB} commits behind HEAD with {STALE_CHANGES.length} KB-affecting changed paths"}'
KB_DECISION = {% ask_user "Knowledge base is stale. Continue with the stale KB, rebuild the KB first, or cancel?", options: "Continue with stale KB", "Rebuild KB first", "Cancel" %}KB_DECISION == "Continue with stale KB":
Proceeding with a stale KB by user choice.
KB is {COMMITS_SINCE_KB} commits behind HEAD.
KB_DECISION == "Rebuild KB first":
Documentation update stopped before scan.
Rebuild the KB with /rp1-base:knowledge-build, then re-run this command.
rp1 agent-tools emit end-run \
--run-id {RUN_ID} \
--outcome cancelled \
--reason "User chose to rebuild the KB before scanning docs"
KB_DECISION == "Cancel":
Documentation update cancelled before scan.
KB is stale by {COMMITS_SINCE_KB} commits.
rp1 agent-tools emit end-run \
--run-id {RUN_ID} \
--outcome cancelled \
--reason "User cancelled docs sync at the stale KB gate"
Create the session directory:
mkdir -p {workRoot}/{SESSION_DIR}
Batch DOC_FILES into groups of 5.
Spawn one background rp1-base:scribe per batch:
{% dispatch_agent "rp1-base:scribe", background %} MODE: scan FILES: {actual JSON array of project-relative paths for this batch} KB_INDEX_PATH: {kbRoot}/index.md
Task: return JSON only with:
modeclassificationssummaryerrors
{% enddispatch_agent %}Wait for all scan agents to finish.
For each response:
mode == "scan"classifications is an arraysummary is presenterrors when presentAGGREGATED.errorsTOTAL_BATCHES and FAILED_BATCHESFailure policy:
failedfailed_batches / total_batches >= 0.5: transition to failedCarry KB_STATUS into AGGREGATED.kb unchanged.
Aggregate successful results into AGGREGATED:
{
"generated_at": "ISO-8601 timestamp",
"kb": {
"state": "current",
"generated_at": "ISO-8601 timestamp",
"git_commit": "commit sha",
"head_commit": "commit sha",
"commits_behind": 0,
"stale_paths": []
},
"style": {
"heading_style": "atx",
"list_marker": "dash",
"list_style": "dash",
"code_fence": "backtick",
"link_style": "inline",
"max_line_length": 100
},
"files": {
"README.md": {
"sections": [
{
"heading": "Quick Start",
"line": 10,
"level": 2,
"scenario": "fix",
"kb_match": "modules.md:20"
}
]
}
},
"summary": {
"total_files": 1,
"verify": 0,
"add": 0,
"fix": 1
},
"errors": [
{
"file": "README.md",
"error": "Could not read one heading body cleanly"
}
],
"scan_failures": [
{
"batch": 2,
"error": "Invalid JSON"
}
]
}
Write SCAN_RESULTS_PATH.
Compute:
TOTAL_SECTIONS = AGGREGATED.summary.verify + AGGREGATED.summary.add + AGGREGATED.summary.fix
Show the scan summary:
Documentation Scan Complete
{AGGREGATED.summary.total_files} files, {TOTAL_SECTIONS} sections: {AGGREGATED.summary.verify} verify, {AGGREGATED.summary.add} add, {AGGREGATED.summary.fix} fix
If AGGREGATED.kb.state == "stale":
Using stale KB by user choice: {AGGREGATED.kb.commits_behind} commits behindIf scan_failures is non-empty:
If errors is non-empty:
scan_results.json for process/reportingEmit the approval gate:
rp1 agent-tools emit \
--workflow generate-user-docs \
--type waiting_for_user \
--run-id {RUN_ID} \
--step approve \
--data '{"prompt": "Proceed with documentation updates?", "context": "Docs sync approval after scan phase"}'
APPROVAL = {% ask_user "Proceed with documentation updates?", options: "Yes", "No" %}
If APPROVAL == "No":
Documentation update cancelled.
Scan results preserved at: {workRoot}/{SCAN_RESULTS_REL}
rp1 agent-tools emit end-run \
--run-id {RUN_ID} \
--outcome cancelled \
--reason "User declined to apply documentation updates after the scan"
If APPROVAL == "Yes", continue.
Set PROCESS_FILES = Object.keys(AGGREGATED.files).
Batch into groups of 5.
Spawn one background rp1-base:scribe per batch:
{% dispatch_agent "rp1-base:scribe", background %} MODE: process FILES: {actual JSON array of project-relative paths for this batch} SCAN_RESULTS_PATH: {workRoot}/{SCAN_RESULTS_REL} STYLE: {actual JSON.stringify(STYLE_CONFIG)}
Task: return JSON only with:
moderesultssummaryerrors
{% enddispatch_agent %}Wait for all process agents to finish.
For each response:
mode == "process"results is an arrayIf no process batch response is valid:
ERROR: Process phase failed before any valid result was returned.failedAggregate file outcomes:
SUCCESSFUL_FILES: status == "success"PARTIAL_FILES: status == "partial"FAILED_FILES: status == "failed"Rules:
success and partial both count as processedpartial means useful edits landed, but some edits failed or review markers were insertedfailed means the file was not usefully updatedBuild:
{
"files_processed": 0,
"files_succeeded": 0,
"files_partial": 0,
"files_failed": 0,
"total_sections_verified": 0,
"total_sections_added": 0,
"total_sections_fixed": 0,
"total_edits_applied": 0,
"failed_files": []
}
Count section and edit totals from both SUCCESSFUL_FILES and PARTIAL_FILES.
Final report:
Documentation Sync Complete
KB used: {AGGREGATED.kb.state}
- Commits behind at scan start: {AGGREGATED.kb.commits_behind}
Files processed: {files_processed}
- Succeeded: {files_succeeded}
- Partial: {files_partial}
- Failed: {files_failed}
Changes applied:
- Sections verified: {total_sections_verified}
- Sections added: {total_sections_added}
- Sections fixed: {total_sections_fixed}
- Total edits: {total_edits_applied}
Scan results: {workRoot}/{SCAN_RESULTS_REL}
Git-ready: docs: sync {files_succeeded + files_partial} files with KB ({total_edits_applied} edits)
If failed_files is non-empty:
{path}: {first error or fallback message}If files_succeeded + files_partial == 0:
failedDo NOT delete SCAN_RESULTS_PATH.
Transition to finalize.
data-ai
Capture session context as a structured, frontmatter-rich markdown note under .rp1/work/notes/ with auto-maintained index and log.
tools
Plan and execute splitting a large PR or branch into a reviewable stacked PR sequence.
development
Write maximally terse agent prompts from scratch. Use when creating new agent specs, command prompts, or instruction sets. Teaches structure-first composition with compression-by-default patterns. Extended with constitutional governance, epistemic stance selection, and a six-stage prompt pipeline.
development
Interactive speedrun loop for small, low-risk changes. Delegates each request to a general sub-agent. Redirects larger work to /build-fast or /build.