marketplace/bundles/plan-marshall/skills/manage-adr/SKILL.md
Manage Architectural Decision Records (ADRs) with CRUD operations, progressive-disclosure metadata, scan-by-tag/affects, automatic numbering, and AsciiDoc formatting
npx skillsauth add cuioss/plan-marshall manage-adrInstall 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.
Execution mode: Select workflow and execute immediately using documented script commands.
Prohibited actions:
Constraints:
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr ...doc/adr/ directoryManage Architectural Decision Records (ADRs) stored in doc/adr/ directory.
Provide structured management of architectural decisions:
| Workflow | Purpose | Script Used |
|----------|---------|-------------|
| list-adrs | List all ADRs with optional filtering | manage-adr.py list |
| create-adr | Create new ADR from template | manage-adr.py create |
| read-adr | Read ADR content | manage-adr.py read |
| update-adr | Update ADR status | manage-adr.py update |
| delete-adr | Delete ADR (with confirmation) | manage-adr.py delete |
| scan-adrs | List all ADRs with progressive-disclosure metadata | manage-adr.py scan |
| validate-adr | Validate ADR format | ref-asciidoc workflows |
List all ADRs with optional status filtering.
status (optional): Filter by status (Proposed, Accepted, Deprecated, Superseded)Step 1: Execute List
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr list [--status {status}]
Step 2: Parse Output
Parse TOON output containing ADR list with metadata.
status: success
operation: list
count: 2
adrs[2]{number,title,status,path}:
1,Use PostgreSQL,Accepted,doc/adr/0001-Use_PostgreSQL.adoc
2,Adopt Quarkus,Proposed,doc/adr/0002-Adopt_Quarkus.adoc
Create a new ADR with automatic numbering.
title (required): ADR titlestatus (optional, default: "Proposed"): Initial statusStep 1: Create ADR
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr create --title "{title}" [--status "{status}"]
Step 2: Parse Output
Extract created file path from TOON output.
Step 3: Open for Editing
Read the created file and inform user to fill in content sections.
Step 4: Validate Format
Skill: pm-documents:ref-asciidoc
Execute workflow: validate-format
Parameters:
target: {created_path}
ADR Created: doc/adr/0004-{title}.adoc
Number: ADR-0004
Status: Proposed
Next steps:
1. Edit doc/adr/0004-{title}.adoc to fill in:
- Context
- Decision
- Consequences
- Alternatives
2. Update status to "Accepted" when approved
Read ADR content by number.
number (required): ADR number (1, 2, 3, etc.)Step 1: Read ADR
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr read --number {number}
Step 2: Display Content
Show ADR metadata and content to user.
Update ADR status through lifecycle.
number (required): ADR numberstatus (required): New status (Proposed, Accepted, Deprecated, Superseded)Step 1: Update ADR
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr update --number {number} --status {status}
Step 2: Confirm Update
Report updated status to user.
Delete ADR with confirmation.
number (required): ADR numberforce (required): Must be true to confirm deletionStep 1: Delete ADR
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr delete --number {number} --force
Step 2: Confirm Deletion
Report deletion to user.
List all ADRs with their progressive-disclosure metadata so a caller can assess relevance without reading full files. This is the surface lifecycle hooks consume: the phase-3-outline reading hook scans --affects {module} to surface established decisions before deliverable authoring, and the phase-6 adr-propose step scans to avoid double-recording an already-captured decision.
tag (optional): Filter to ADRs whose tags metadata list includes this valueaffects (optional): Filter to ADRs whose affects metadata list includes this valueStep 1: Execute Scan
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr scan [--tag {tag}] [--affects {affects}]
Step 2: Parse Output
Parse the TOON payload — each ADR carries number, title, status, summary, tags, affects, and supersedes. Read the summary fields for relevance scanning before loading any full ADR.
status: success
operation: scan
count: 2
adrs[2]{number,title,status,summary,tags,affects,supersedes}:
1,Use PostgreSQL,Accepted,Relational store for persistence,persistence,plan-marshall,
2,Per-tree derived state,Accepted,Each worktree owns its executor,worktree;executor,plan-marshall,
Validate ADR format using ref-asciidoc skill.
number (required): ADR number to validateStep 1: Find ADR Path
Use list-adrs workflow to get ADR path by number.
Step 2: Validate Format
Skill: pm-documents:ref-asciidoc
Execute workflow: validate-format
Parameters:
target: {adr_path}
Step 3: Report Results
Report validation results to user.
This skill integrates with ref-asciidoc for:
Proposed → Accepted → [Deprecated | Superseded]
| Status | Meaning | |--------|---------| | Proposed | Under discussion, not yet approved | | Accepted | Approved and active | | Deprecated | No longer relevant or applicable | | Superseded | Replaced by another ADR |
Each ADR opens with a progressive-disclosure metadata block, then these sections:
Immediately after the = ADR-NNN: Title line, every ADR carries a machine-readable metadata block delimited by // adr-metadata … // end-adr-metadata. The block is authored as AsciiDoc line comments so it never renders, and is read by manage-adr.py scan to surface ADR relevance cheaply during the planning lifecycle.
// adr-metadata
// summary: One-line statement of the decision
// tags: comma, separated, topic, tags
// affects: comma, separated, modules
// supersedes: 3, 7
// end-adr-metadata
| Field | Type | Purpose |
|-------|------|---------|
| summary | scalar | One-line decision statement for scanning |
| tags | comma-separated list | Topic tags for scan --tag filtering |
| affects | comma-separated list | Affected modules/components for scan --affects filtering |
| supersedes | comma-separated list | ADR numbers this decision supersedes |
create emits an empty block; fill the fields in as part of authoring the ADR. parse_adr_file and scan tolerate absent fields and a missing block (all fields default to empty).
ADRs are durable architectural statements, not incident write-ups. An ADR should still read as a standalone decision record years after the PR that introduced it has scrolled out of memory and the lessons file referenced at write-time has been pruned. CLAUDE.md's project-wide rules — "no version history", "no timestamps", "no duplication", "current state only" — apply to ADR content in the section-specific shapes below.
.plan/local/lessons-learned/...) are ephemeral recurrence-detectors and may be pruned, retired, or superseded; an ADR that cross-references a specific lesson ID can develop a dangling reference. When the lesson is the recurrence-detector that ENFORCES the ADR's principle at retrospective time, link the durable artefact (the retrospective rule, the plugin-doctor check) instead.Lessons capture the recurrence pattern the ADR's principle defends against — the diagnostic signature a future maintainer might see that should remind them of the ADR's guidance. Lessons are explicitly ephemeral; ADRs are durable. If a piece of prose is "we hit this bug, watch for the pattern", it belongs in a lesson. If it's "the architecture is X because alternatives Y/Z fail in ways A/B", it belongs in the ADR.
ADRs follow this naming pattern:
doc/adr/{N…}-{Title_With_Underscores}.adoc
The numeric prefix is zero-padded to the prevailing corpus width — the widest existing ADR prefix in doc/adr/. A new ADR is numbered one past the highest existing number and emitted at that same width, so a 4-digit corpus (0001..0006) yields 0007 and a 3-digit corpus (001..007) yields 008. An empty or absent corpus defaults to width 4 (0001). The parser accepts any prefix width, so mixed-width corpora are read correctly.
Examples (4-digit corpus):
doc/adr/0001-Use_PostgreSQL_for_Persistence.adocdoc/adr/0002-Adopt_Quarkus_Framework.adocdoc/adr/0003-Implement_CQRS_Pattern.adocCross-session numbering is provisional until merge. next-number derives the next value from the numeric prefixes committed on the CURRENT checkout — it cannot see a concurrent session's uncommitted ADR on another branch. Two branches authoring ADRs at the same time can both be handed the same number, and the collision only surfaces at merge. Treat the number create/next-number returns as provisional, not final: when multiple sessions may be authoring ADRs concurrently, number above any known-pending (uncommitted-on-another-branch) range rather than trusting "highest committed + 1" blindly, and be prepared to renumber by hand at merge time. This is inherent to any tool that reads only the local checkout — it is not a bug to fix in next-number itself.
Script: plan-marshall:manage-adr → manage-adr.py
| Subcommand | Description |
|------------|-------------|
| list | List all ADRs with optional status filtering |
| create | Create new ADR from template with automatic numbering |
| read | Read ADR content by number |
| update | Update ADR status through lifecycle |
| delete | Delete ADR (requires --force) |
| scan | List all ADRs with progressive-disclosure metadata (optional --tag / --affects filters) |
Usage Examples:
# List all ADRs
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr list
# Create new ADR
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr create --title "Use PostgreSQL"
# Update ADR status
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr update --number 1 --status Accepted
The canonical argparse surface for manage-adr.py. The plugin-doctor analyzer (_analyze_manage_invocation.py) reads this section as source-of-truth for the manage-invocation-invalid and missing-canonical-block rules. Consuming docs xref this section by name instead of restating the command inline. See pm-plugin-development:plugin-script-architecture cross-skill-integration.md § "Script invocation in documentation".
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr list \
[--status {Proposed,Accepted,Deprecated,Superseded}]
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr create \
--title TITLE [--status {Proposed,Accepted,Deprecated,Superseded}]
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr read --number NUMBER
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr update \
--number NUMBER [--status {Proposed,Accepted,Deprecated,Superseded}]
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr delete --number NUMBER [--force]
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr next-number
python3 .plan/execute-script.py plan-marshall:manage-adr:manage-adr scan \
[--tag TAG] [--affects AFFECTS]
pm-documents:ref-asciidoc - Format validationdevelopment
Domain-owned OpenRewrite log-line finding parser for the java-cui domain — parses the
development
Domain-owned OpenRewrite marker detection for the java-cui domain — scans Java/Kotlin sources for cui-rewrite TODO markers, categorizes them by recipe, and fails the gate on any detected marker
development
Operator control surface for the marshalld build server — enrol/drop a project in the machine-global registry (the opt-in enable signal and anti-laundering wall), manage the daemon lifecycle (start, stop, drain, status, install, upgrade) version-pinned to the verified bundle copy, and inspect the daemon's per-project interaction-audit log (read-only)
tools
The tiny build-consumption client for the marshalld build server — submit a build job, bounded long-poll for its result, ping the daemon identity, and preflight registry-plus-liveness in one call; consumption only, never provisioning or enrolment