AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Adr Workflow

skill-ramboz-jig-adr-workflow · by ramboz

>

No reviews yet
0 installs
27 views
0.0% view→install

Install

$ agentstack add skill-ramboz-jig-adr-workflow

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-ramboz-jig-adr-workflow)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Adr Workflow? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

> Spec 005 created this skill from scratch. The mechanics live in adr.py; > Claude owns the judgment (what the decision actually says).

What this skill does

Codifies the ADR lifecycle that ADR-0001 and ADR-0002 were written by hand to exercise. Five deterministic operations:

  • new — scaffold docs/decisions/adr-NNNN-.md from the template, with

auto-numbering and a slug-collision check. The scaffold carries status: Proposed in frontmatter (from the template) alongside the prose Proposed (date) line (spec 073-02 / ADR-0026).

  • accept — flip Status from Proposed (YYYY-MM-DD) to

Accepted (YYYY-MM-DD), and stamp the canonical status: Accepted frontmatter field in the same atomic write (spec 073-02 / ADR-0026 — frontmatter is the canonical status home; prose and frontmatter cannot diverge).

  • supersede — append Superseded by [ADR-NNNN](./adr-NNNN-.md) (date)

to an Accepted ADR's Status block and Supersedes ADR-NNNN to the replacement's Status block, and stamp the old ADR's status: Superseded frontmatter field in the same atomic write (the replacement retains status: Accepted). This is the one edit allowed on an immutable ADR per the Nygard convention. Atomic write on both files.

  • index — regenerate the ## Index section of docs/decisions/README.md

from the actual ADR files present. Idempotent.

  • resolve-todo — strike through a ### Decision: ... heading in

docs/refinement-todo.md and append **Resolved by:** [ADR-NNNN: ...](...).

The script does file mutation deterministically. Claude is responsible for the prose inside the ADR (Context, Options Considered, Recommended Decision, Consequences, Open questions).

How to use

1. Author a new ADR

Reference moved? Reframe first. If this ADR is a reaction to a load-bearing reference changing from outside the system (a design system, vendor / API contract, test infra, compliance regime, platform, or product-positioning / strategic-vision shift), reach for /jig:reframe before hand-authoring — it drafts the keystone reframe-ADR (new reference authoritative, old premise superseded) + the re-baselining manifest for you, so the fallout is dispositioned rather than patched (spec 067 / [ADR-0024](../../docs/decisions/adr-0024-reference-reframe.md)).

Step 0 — confirm the project is scaffolded (spec 066 / ADR-0011). BEFORE reserving an ADR number or drafting ANY docs/decisions/ structure, confirm this project is a scaffolded jig project. If it isn't, route — do not hand-roll directories:

  • Greenfield (no jig structure yet) → tell the user to run

/jig:scaffold-init. It lays down conventions, templates, hooks, the status board, and the docs/decisions/ tree (with its README).

  • Existing spec/docs/decisions/ layout, but not jig-scaffolded (no

scaffold.json) → tell the user to run /jig:migrate. It adopts the existing layout into jig structure.

You don't have to decide the state yourself: adr.py new (below) classifies and routes for you (spec 066-01) — a scaffold.json-bearing project proceeds; a greenfield project is refused naming /jig:scaffold-init; an adoptable spec-driven project is refused naming /jig:migrate. The deterministic gate and this human-readable precondition agree by construction, so don't restate the detection heuristic here — run the helper and let it route. (Bypass for a deliberate out-of-band flow: JIG_SCAFFOLD_PRECONDITION=0.)

The anti-pattern this step exists to kill: an auto-triggered adr-workflow run improvising a loose docs/decisions/ skeleton (folder + README, or just dropping an adr-NNNN-*.md into a hand-made directory) because /jig:scaffold-init was skipped. That produces a non-jig layout that then needs migrating — the ADR-side of the reported failure. When in doubt, route to setup first; never invent the structure by hand.

python3 "${CLAUDE_PLUGIN_ROOT}/skills/adr-workflow/adr.py" new  \
  [--title ""] [--project-dir DIR] [--no-push | --pr]

Run from the project root (the script looks for ./docs/decisions/, or use --project-dir DIR to target a different root). The slug is kebab-case (my-decision). --title is optional — defaults to the title-cased slug.

Reserve-on-origin/main is the default (slice 028-01). The helper fetches origin/main, computes the next free NNNN from the just-fetched view, scaffolds the file, commits as docs(decisions): reserve adr-NNNN-, and pushes to origin/main. If the push is refused by branch protection / permissions, the helper automatically falls back to a reserve/adr-NNNN- branch + gh pr create. This locks the ADR number team-wide before any drafting begins, killing the parallel-worktree numbering-collision failure mode that motivated spec 028.

Works from any branch or worktree (ADR-0015 / spec 051, mirroring workflow.py new). The helper routes on the current branch: on main it runs the proven in-place flow (clean tree required); off main — a feature branch or a linked .claude/worktrees/* worktree — it reserves via an ephemeral detached worktree at origin/main, never touching your branch, cwd, or working tree. No need to switch to main (a linked worktree can't, anyway).

Flags:

  • --no-push — commit locally only; skip fetch / push entirely. On

main it commits on main; off main it commits a provisional reservation on the current branch (the number is local-view and may collide at merge — treat it as provisional). Pathspec-scoped, so unrelated staged work is not swept into the reservation commit.

  • --pr — skip the direct-push attempt; go straight to branch + PR.

Useful when you already know main is protection-locked. Mutually exclusive with --no-push.

Race-on-push (someone advanced origin/main while you were reserving) surfaces as race-on-push: ... and drops the stranded local commit + the stranded ADR file from your working tree. Re-run the same adr.py new to pick the next free number — there is no auto-renumber.

Then Claude fills in Context / Options Considered / Recommended Decision / Consequences. Keep it tight: one decision per ADR.

2. Accept the ADR

Once the prose is settled and the human (or the workflow gate) approves:

python3 "${CLAUDE_PLUGIN_ROOT}/skills/adr-workflow/adr.py" accept 

This flips Proposed (date) to Accepted (date) and stamps the canonical status: Accepted frontmatter field in the same atomic write (spec 073-02 / ADR-0026). Refuses if the Status is already Accepted (ADRs are immutable; supersede instead — see below).

Frame-critique gate (spec 064-05 / ADR-0020 OQ2/OQ3). accept also gates the flip on a passing adversarial frame-critique verdict — the ADR's pre-commitment moment to catch a wrong premise (the ADR-0011 / ADR-0008 failure mode). It applies iff the ADR carries a truthy frame_review flag: new stamps frame_review: true on every ADR it creates (OQ3 — ADRs always-on), so new ADRs are gated; a legacy markerless Proposed ADR is grandfathered (no refusal). To clear it: build the prompt with review.py frame-critique docs/decisions/adr-NNNN-*.md, run a reviewer, then review.py record-review --adr NNNN --pass frame-critique --verdict pass … (writes docs/decisions/reviews/adr-NNNN-frame-critique.md). Soft / bypassable with JIG_REVIEW_EVIDENCE_GATE=0 (a deliberateness signal, ADR-0011 — not human-only enforcement).

3. Supersede an Accepted ADR

When a previously-Accepted decision is replaced by a newer one, don't edit the old ADR's prose — write a new ADR (per new above), accept it, then run:

python3 "${CLAUDE_PLUGIN_ROOT}/skills/adr-workflow/adr.py" \
  supersede  

Both ADRs must already be Accepted. The helper:

  • appends Superseded by [ADR-](./adr--.md) (today) to the

old ADR's ## Status block,

  • appends Supersedes ADR- (plain text, no link, no date) to the new

ADR's ## Status block,

  • preserves both Accepted (date) lines (this is the one edit allowed on

an immutable ADR per the Nygard convention),

  • stamps the old ADR's status: Superseded frontmatter field in the same

atomic write (the replacement keeps status: Accepted) — spec 073-02 / ADR-0026, so a dependency on a superseded ADR correctly fails,

  • writes both files atomically.

Refuses (exit 2) if either ADR is Proposed (accept it first), if either ADR is already Superseded, if == (self-supersession), or if either NNNN is malformed. Re-run adr.py index docs/decisions after to refresh the index entries.

4. Regenerate the index

python3 "${CLAUDE_PLUGIN_ROOT}/skills/adr-workflow/adr.py" index docs/decisions

Reads every adr-NNNN-*.md (skipping README.md) and rewrites only the ## Index section of docs/decisions/README.md. Everything else in the README (header, format spec, "When to write" section) is preserved. Re-running on a current README is a no-op.

5. Resolve a deferred decision

If the new ADR resolves a ### Decision: ... entry in docs/refinement-todo.md:

python3 "${CLAUDE_PLUGIN_ROOT}/skills/adr-workflow/adr.py" \
  resolve-todo  ""

The fragment is a case-insensitive substring (same lenient style as workflow.py's slice fragment). The helper:

  • wraps the heading line in ~~strikethrough~~,
  • appends — RESOLVED YYYY-MM-DD,
  • wraps the first **Deferred:** line in strikethrough,
  • appends a **Resolved by:** [ADR-NNNN: ...](decisions/adr-...) line at the end of

the section.

Refuses (exit 2) if the fragment is ambiguous, the section is already struck through, or the ADR hasn't been Accepted yet.

Immutability rule

Never edit an Accepted ADR. The Nygard convention treats ADRs as historical record — if the decision changes, write a new ADR that supersedes the old one. The supersession lines (one on each side) are the only edit allowed on an immutable ADR. Use the supersede subcommand (section "3. Supersede an Accepted ADR" above) — adr.py supersede writes those lines deterministically on both ADRs and refuses self-supersession, Proposed-ADR inputs, or double-supersession.

What the helper does (so you can spot-check the result):

  1. Old ADR's ## Status block gains a line appended after the existing

Accepted (date) line: Superseded by [ADR-](./adr--.md) (today).

  1. New ADR's ## Status block gains a plain-text line after its

Accepted (date): Supersedes ADR- (no link, no date).

  1. Both Accepted (date) lines are preserved.

If a user asks to "supersede ADR-NNNN", route them to the supersede subcommand — both ADRs must already be Accepted; if the replacement isn't drafted yet, walk them through new + accept for the new ADR first.

End-to-end example (full lifecycle)

The canonical lifecycle is new → edit → index (preview) → accept → index (final). The preview-index pass surfaces a truncated or ugly first-bullet line while the ADR is still mutable (per [ADR-0006](../../docs/decisions/adr-0006-adr-accept-then-index-ordering.md)). Skip the preview only if the Context first sentence is known to be index-friendly (no abbreviations outside the helper's allowlist, fits in one short clause).

# 1. Identify the deferred decision in docs/refinement-todo.md.
#    Fragment: "scaffold-stable" (matches "### Decision: scaffold-stable …").

# 2. Scaffold the ADR.
python3 .../adr.py new scaffold-stable --title "scaffold-stable trigger"
# → docs/decisions/adr-0003-scaffold-stable.md

# 3. Claude edits the file: fills Context, Options, Recommended, Consequences.

# 4. Preview the index BEFORE accept, while the ADR is still mutable.
python3 .../adr.py index docs/decisions
# Inspect the new bullet line. If it looks wrong (truncated mid-
# abbreviation, missing the key noun, etc.), edit the ADR's first
# Context sentence and re-run this command. Iterate freely.

# 5. Accept.
python3 .../adr.py accept 0003
# → flips Proposed → Accepted (today).

# 6. Final index regen (idempotent re-run; updates only the Accepted line).
python3 .../adr.py index docs/decisions

# 7. Mark the refinement-todo entry resolved.
python3 .../adr.py resolve-todo 0003 "scaffold-stable"

Boundary-change nudge

A PostToolUse hook (jig-boundary-change-warn) fires on Edit/Write/MultiEdit of a canonical external-interface contract-artifact file (OpenAPI openapi.yaml/.yml/.json, AsyncAPI asyncapi.yaml/.yml/.json, *.proto, *.graphql/*.graphqls, or *.schema.json). It emits a soft additionalContext nudge pointing the author at /jig:adr-workflow new (capture the rationale if the change is breaking) plus the surface-appropriate breaking-change ecosystem tool (buf breaking, graphql-inspector diff, redocly diff / spectral, AsyncAPI parser diff, JSON-Schema diff). The nudge is informational, never a gate — set JIG_BOUNDARY_CHECK=0 to silence it. The filename + tool list is sourced manually from the [contracts skill's per-surface table](../contracts/SKILL.md); the contracts skill is the source of truth for which artifact governs which surface.

Gotchas

  • Auto-numbering does not fill gaps. If 0001 and 0003 exist (no

0002), the next new ADR is 0004. The gap is preserved as historical record.

  • Slug collisions refuse regardless of number. adr-0001-foo.md exists →

adr.py new foo exits 2. Either pick a different slug or write a superseding ADR.

  • resolve-todo touches only three lines. Heading, first **Deferred:**

line, and one new **Resolved by:** line appended at the section end. Other fields (**Resolution trigger:**, **Mitigation idea:**, **Watch-list:**, etc.) are left intact. If a section needs more intricate updates, edit it by hand.

  • Index description extraction may produce ugly first lines. The helper

takes the first non-empty paragraph from ## Context, truncating at the first sentence-ending punctuation when the paragraph is multi-line or >120 chars. Common abbreviations (e.g., i.e., etc., Mr., Dr., …) are skipped by an explicit allowlist; abbreviations outside that list may still cause a mid-word cut. If the resulting bullet reads oddly, edit the ADR's first Context sentence to be index-friendly. Per [ADR-0006](../../docs/decisions/adr-0006-adr-accept-then-index-ordering.md), edits to Context-section prose to fix index-rendering are NOT decision-content and do not violate the immutability rule. Edits to Status, Recommended Decision, or Consequences DO violate immutability and require a superseding ADR. Run index BEFORE accept as a preview pass to catch this while the ADR is still freely mutable.

  • The helper does NOT spawn a Task or commit anything. It only mutates

files. Claude is responsible for orchestration (e.g. running workflow.py status-board afterward, writing commit messages, invoking the reviewer subagent).

  • Substring matching mirrors workflow.py. 0001-01 does not collide

with 0001 since ADR numbers are matched as exact 4-digit prefixes, not free-form substrings (unlike slice fragments).

  • adr.py new is worktree-aware (ADR-0015 / spec 051). It routes on

the current branch: on main it runs the proven 028-01 in-place flow (clean tree required); off main — a feature branch or a linked worktree — it reserves via an ephemeral detached worktree at origin/main (push mode) or commits a provisional reservation on the current branch (--no-push), without disturbing your branch or tree. You no longer need to git checkout main first (and a linked worktree can't, since the primary worktree holds main). The earlier off-main/dirty-tree refusal — and its impossible git checkout main workaround — is gone.

Reconciliation checklist

After using this skill in a real session:

  • [ ] Did the index regen produce sensible descriptions? If not, edit the

ADR's first Context sen

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.