nx/skills/rdr-close/SKILL.md
Use when an RDR is done — close it with optional post-mortem, bead status gate, and T3 archival
npx skillsauth add hellblazer/nexus rdr-closeInstall 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.
Gates on open bead status before closing. Archives post-mortem directly via mcp__plugin_nx_nexus__store_put. See registry.yaml.
/nx:rdr-close003Resolve RDR directory from .nexus.yml indexing.rdr_paths[0]; default docs/rdr. Use the Step 0 snippet from the rdr-create skill, stored as RDR_DIR. All file paths below use $RDR_DIR in place of docs/rdr.
--force or explicit user confirmation to proceedAsk: "Did implementation diverge from the plan? If so, describe the divergences."
If diverged:
Branch on what the preamble emitted:
A. If the preamble emitted PROBLEM STATEMENT REPLAY: validation passed (Pass 2 success):
B. If the preamble emitted a Pass 1 gap enumeration (no --pointers was supplied):
Gap1=file.py:123,Gap2=other.py:45/nx:rdr-close NNN --reason implemented --pointers 'Gap1=...,Gap2=...'C. If the preamble emitted a legacy WARN (This RDR predates structured gaps; no action required):
D. If the preamble blocked (sys.exit(0) with error — malformed new RDR or pointer failure):
Mandatory user-facing framing (say this verbatim before continuing to Step 2):
"The replay gate verifies you have committed to a specific file:line pointer per gap. It does NOT verify the pointer is semantically correct. Correctness is your responsibility — review each pointer manually before allowing the close to proceed."
Also clear the T1 scratch rdr-close-active marker after Step 4 (Update State) completes — add a note at Step 4 to run: nx scratch delete <entry-id> where the entry was set by the preamble.
Dispatch /nx:substantive-critique <rdr-id> via the Agent tool and parse the ## Verdict block from the response. This is the authoritative gate signal (CA-1 verified n=4 for outcome-category determinism; finding-level variance is expected).
Verdict extraction — try in order, take the first hit:
- **outcome**: (bullet-dash, bold "outcome", colon, space, value). The value is one of justified, partial, not-justified.outcome:\s*(\S+) within a ## Verdict section. Normalize the captured value case-insensitively: FAILED/FAIL/BLOCKED/NOT-JUSTIFIED → not-justified; PARTIAL/PARTIALLY → partial; PASS/PASSED/APPROVED/JUSTIFIED → justified.### Issue: headers under ## Critical Issues and ## Significant Issues. Derive outcome mechanically: Critical > 0 → not-justified; Critical == 0 AND Significant > 0 → partial; all clear → justified. Surface the fallback path to the user explicitly: "The critic did not emit a canonical Verdict block. Falling back to section counting: <counts>."All three paths map to the same 3-valued enum (justified / partial / not-justified) which is the gate signal branched on below.
Short-circuit: if the preamble surfaced a Force Implemented (audit) line, skip the dispatch entirely — the user has taken explicit responsibility. Write a T2 override audit entry with critic_verdict: skipped (see branch E below) and continue to Step 2.
Relay framing (load-bearing, do not vary): the dispatch relay MUST be fixed-shape and minimal. Pass only {rdr_id} and the standard input artifacts (T2 RDR record, catalog entry, RDR markdown file). NEVER pass session-generated summaries of what was built, what diverged, or what the user intends. Rationalization bias is the exact failure mode RDR-069 addresses — see RDR-069 §Risks "Dispatch isolation risk".
## Relay: substantive-critic
**Task**: Critique RDR {rdr_id} against its Problem Statement for silent scope reduction, retcon, or unjustified-implemented closure.
**Bead**: none
### Input Artifacts
- nx memory: {repo}_rdr/{rdr_id} (status, research records, planning chain)
- Files: docs/rdr/rdr-{rdr_id}-*.md
- Catalog: mcp__plugin_nx_nexus-catalog__search query "RDR-{rdr_id}"
### Deliverable
Critique report with canonical `## Verdict` block (outcome, confidence, critical_count, significant_count, summary).
### Quality Criteria
- [ ] Verdict block uses 5-field canonical format
- [ ] Findings grounded in RDR text (file:line references)
- [ ] No session context consumed beyond the listed input artifacts
Branch on Verdict.outcome:
A. justified → surface the one-line summary to the user and continue to Step 2. No constraint on close_reason.
B. partial → surface all Critical and Significant findings to the user verbatim. Block close_reason: implemented unless --force-implemented "<reason>" was supplied. If no override, prompt the user: "The critic found significant issues. Address them and re-run, or pass --force-implemented '<reason>' to override with audit trail." Do not proceed until the user either resolves findings (recursive loop) or passes the override.
C. not-justified → surface ALL Critical findings verbatim. Block close_reason: implemented unless --force-implemented "<reason>" was supplied. Per RDR-069 §Proposed Solution (line 282) and §Technical Design (line 307), close_reason: reverted and close_reason: partial are legitimate non-override paths on not-justified — a user who genuinely wants to acknowledge failure with reverted should be able to do so without the override flag. User's options: (1) address findings and re-run with --reason implemented (recursive refinement loop), (2) re-run with --reason reverted or --reason partial (honest failure-acknowledgment, no override needed), or (3) pass --force-implemented "<reason>" with a substantive reason to force implemented despite the Critical findings. A one-word reason (e.g., --force-implemented "wontfix") is insufficient — prompt the user to expand it before accepting. Only close_reason: implemented requires the override.
D. Verdict extraction failure → this case should be rare now that the verdict extractor above tries canonical bullet form, code-block key-value form, AND section-counting fallback. Only reach this branch if all three extraction paths fail (e.g. critic response is completely empty or wholly unparseable). Surface explicitly to the user: "Critic response could not be parsed at all. Proceed without critique? (y/N)". Do not silently block; do not silently proceed.
E. Override audit entry (runs for every --force-implemented invocation, regardless of critic outcome):
mcp__plugin_nx_nexus__memory_put(
project="{repo}_rdr",
title="{rdr_id}-close-override-{YYYY-MM-DD}",
content="critic_verdict: {outcome|skipped}\nuser_reason: {force_implemented_reason}\nfinal_close_reason: {close_reason}\ntimestamp: {ISO8601}\nrdr_id: {rdr_id}",
ttl="permanent",
tags="rdr,close-override,rdr-{rdr_id}"
)
The audit entries are the measurement surface for CA-4: if nexus_rdr/*-close-override-* exceeds 20% of closes in any 30-day window, Phase 2 dispatch degrades to advisory mode (see RDR-069 Day 2 Operations).
Scenario 4 — timeout or transport failure: if the Agent tool dispatch fails, times out (>5 minutes without response), or returns an unparseable response (not just a missing Verdict block, but genuinely malformed output), surface the failure to the user explicitly and ask: "Critic dispatch failed. Proceed without critique? (y/N)". Do not silently block and do not silently proceed — the user must choose.
Create $RDR_DIR/post-mortem/NNN-kebab-title.md from the post-mortem template. Populate:
If T2 record has an epic_bead field (set during accept-time planning):
/beads:show <epic-id> to get child bead statusesIf T2 record has no epic_bead field (user skipped planning at accept time):
HARD GATE — if ANY open or in-progress beads exist:
Update T2 record: mcp__plugin_nx_nexus__memory_put(content="... (same fields, status: Implemented, closed: YYYY-MM-DD, close_reason: Implemented, archived: true)", project="{repo}_rdr", title="NNN", ttl="permanent", tags="rdr,{type},closed"
If T3 archive fails, set archived: false — retryable by re-running /nx:rdr-close
Update status in RDR markdown metadata
Regenerate docs/rdr/README.md index
Scoped conditional reindex — if the RDR body changed during close (e.g. divergence notes added, post-mortem link inserted, or any text outside the frontmatter block modified), run nx index rdr scoped to the single RDR file, NOT the whole corpus:
nx index rdr docs/rdr/rdr-NNN-<slug>.md
A frontmatter-only edit (status/closed_date/close_reason flipping) does NOT need a reindex at all — the chunk text is unchanged, so embeddings would not shift. Check with:
# If the diff is wholly inside the frontmatter block, skip the reindex.
git diff HEAD -- docs/rdr/rdr-NNN-*.md | grep -v '^[+-]---' | grep -v '^[+-][a-z_]*: ' | grep -E '^[+-]' | head -1
# Prints nothing → frontmatter-only → skip.
# Prints lines → body changed → run the single-file `nx index rdr <path>`.
Do NOT run the directory form nx index rdr (no argument) at close time — that walks the whole corpus and hash-dedups every file, which is wasteful for a one-file edit. The file form takes only the target RDR.
The RDR already has a catalog entry from the original accept-time indexing. Create links to capture implementation provenance (if catalog is initialized):
Code→RDR links: The indexer hook auto-generates implements-heuristic links via title substring matching. These are created automatically. Review with nx catalog links <rdr-tumbler> --type implements-heuristic — promote high-confidence ones to implements via mcp__plugin_nx_nexus-catalog__link for link-boost scoring benefit (heuristic links have zero search boost weight).
RDR→prior-RDR links: If the RDR's T2 record has a supersedes field, create the catalog link:
mcp__plugin_nx_nexus-catalog__link(from_tumbler="<this-rdr-title>", to_tumbler="<superseded-rdr-title>", link_type="supersedes", created_by="rdr-close")
RDR→research links: If research findings reference indexed papers, create cites links:
mcp__plugin_nx_nexus-catalog__search(query="<source>")mcp__plugin_nx_nexus-catalog__search(query="RDR-NNN")), then: mcp__plugin_nx_nexus-catalog__link(from_tumbler="<rdr-tumbler>", to_tumbler="<paper-tumbler>", link_type="cites", created_by="rdr-close")Skip all catalog steps silently if catalog is not initialized. The T2 record and markdown are the authorities — catalog links are supplementary graph enrichment.
The main RDR was already semantically indexed at accept time (and refreshed in Step 4 only if the body changed during close). Do not duplicate it with store_put tool — that would create non-CCE blob entries in the same collection, degrading search quality.
Per RDR-103 the post-mortem lands in the same conformant knowledge collection as every other knowledge document for this repo, with category="rdr_postmortem" stamped on the chunk metadata so it is queryable as a distinct slice without needing its own collection.
Resolve the conformant target via the catalog (run from the repo root):
KNOWLEDGE_COLL=$(nx catalog collection-name --content-type knowledge)
# → e.g. knowledge__1-7__voyage-context-3__v1
Seed link-context so the post-mortem auto-links to the RDR:
mcp__plugin_nx_nexus__scratch(action="put", content='{"targets": [{"tumbler": "<rdr-tumbler>", "link_type": "relates"}], "source_agent": "rdr-close"}', tags="link-context")
Archive the post-mortem directly (substitute $KNOWLEDGE_COLL from above):
mcp__plugin_nx_nexus__store_put(
content=(contents of $RDR_DIR/post-mortem/NNN-kebab-title.md),
collection="<$KNOWLEDGE_COLL>",
title="PREFIX-NNN Title (post-mortem)",
tags="rdr,post-mortem,{drift-categories}",
category="rdr_postmortem"
)
Post-mortems are then queryable as a slice of the knowledge collection:
mcp__plugin_nx_nexus__search(query="...", corpus="<$KNOWLEDGE_COLL>", where='category=rdr_postmortem')
knowledge__rdr_postmortem__<repo> collections)Operators that previously closed RDRs under the old shape can roll the legacy collection into the conformant target with nx catalog rename-collection. Run once per affected repo:
NEW=$(nx catalog collection-name --content-type knowledge)
nx catalog rename-collection "knowledge__rdr_postmortem__<repo>" "$NEW" --yes
If the target collection already has documents (rare, only when nx index repo ran before the rename), use nx catalog migrate-fallback per-document instead so existing rows survive.
Renamed documents do not automatically gain category="rdr_postmortem" on their chunk metadata, since the chunks were written before the category field was stamped at write time. Pre-RDR-103 post-mortems remain findable via their original tags="rdr,post-mortem,..." field (which is searchable as a string contain). The cleanest backfill is to re-archive each post-mortem by rerunning mcp__plugin_nx_nexus__store_put with category="rdr_postmortem" against the conformant collection, overwriting the legacy chunk by title. Operators that do not need the category-filtered slice can leave the legacy chunks as-is.
nx index rdr docs/rdr/rdr-NNN-<slug>.md (single-file form). A frontmatter-only status: reverted flip does not warrant a reindex. Apply the same diff check from Step 4 of the Implemented flow.nx catalog collection-name --content-type knowledge lookup, same category="rdr_postmortem" stamp.superseded_by: "NNN". In markdown, add "Superseded by RDR-NNN" notesupersedes: "MMM". In markdown, add "Supersedes RDR-MMM" notenx index rdr docs/rdr/rdr-NNN-<slug>.md on the OLD RDR, and separately on the NEW RDR. Two files → two single-file invocations. Do NOT run the whole-corpus form.supersedes link in the catalog so the graph reflects the relationship:
# Find both RDRs by title in catalog
mcp__plugin_nx_nexus-catalog__link(from_tumbler="<new-rdr-title>", to_tumbler="<old-rdr-title>", link_type="supersedes", created_by="rdr-close")
If catalog is not initialized or either RDR is not found, skip silently — the T2 record is the authority.The close operation performs multiple state mutations. If any step fails:
archived flag tracks whether T3 archival succeeded/nx:rdr-close is idempotent: checks T2 state and skips completed stepsOnly one agent is dispatched by this skill: substantive-critic (Step 1.75, implemented close only). All other operations use MCP tools directly (RDR-080).
Post-mortem archival calls mcp__plugin_nx_nexus__store_put directly (RDR-080, no agent spawn needed). Resolve the conformant target collection via nx catalog collection-name --content-type knowledge (Step 6) and stamp category="rdr_postmortem" so the post-mortem is queryable as a slice of the knowledge collection:
mcp__plugin_nx_nexus__store_put(
content=(read $RDR_DIR/post-mortem/NNN-kebab-title.md),
collection="<knowledge collection from `nx catalog collection-name --content-type knowledge`>",
title="RDR-NNN: {title} (post-mortem)",
tags="rdr,post-mortem,{comma-separated drift-categories}",
category="rdr_postmortem"
)
Seed link-context before the store_put call (Step 6) to ensure auto-linker connects the post-mortem to the RDR.
.nexus.yml indexing.rdr_paths[0] (default docs/rdr)nx index rdr only if the RDR body changed during close (divergence notes added, cross-link notes inserted, etc.) — skipped for frontmatter-only closesnx catalog collection-name --content-type knowledge) with category="rdr_postmortem" (if exists)Outputs produced by this skill directly:
Console output: Bead status gate table (if epic_bead in T2)
T2 memory: Close metadata via memory_put tool: project="{repo}_rdr", title="NNN", ttl="permanent", tags="rdr,{type},closed"
T3 semantic index: Conditionally refreshed via nx index rdr (CCE embeddings, section-level chunks) — only when the RDR body changed during close; frontmatter-only edits are skipped
Filesystem: Post-mortem at $RDR_DIR/post-mortem/NNN-kebab-title.md, updated README
T3 knowledge: Post-mortem archive via mcp__plugin_nx_nexus__store_put: content=(post-mortem contents), collection=(conformant knowledge collection resolved via nx catalog collection-name --content-type knowledge), title="RDR-NNN: {title} (post-mortem)", category="rdr_postmortem" (RDR-080, called directly, no agent spawn)
development
Use when critiquing / auditing / reviewing a change set against decision history — tries the review plan library first (catalog lookup → decision-evolution traversal → extract → compare), falls through to /nx:query if nothing matches
documentation
Use when doing design / architecture / planning work that walks from prose (RDRs, docs, knowledge) into the modules implementing a concept
development
Use when surveying the plan library's runtime metrics to propose plans for promotion to a higher scope — advisory-only; dispatches the plan-promote-propose meta-seed (no lifecycle ops — those ship in RDR-079)
business
Use when inspecting plan runtime metrics or enumerating dimension-registry usage — dispatches plan_match with dimensions={verb:plan-inspect}; strategy:default reports per-plan metrics, strategy:dimensions reports registry usage counts