---
name: bd-close-rationale
description: Close a bd issue with structured rationale (HEAD + timestamp prefix), evidence-path verification, and post-close verification round-trip. Idempotent.
---

# bd close with rationale

## When to invoke

At every bd issue closure that warrants substantive rationale (most non-trivial closures). The primitive's idempotency makes it safe to use as the default closure mechanism — re-running on an already-closed issue is a no-op rather than an error.

## What it does

Invokes `tools/bd-close-rationale.sh` with an issue id, a rationale markdown file, and optional comma-separated evidence paths. The primitive wraps `bd close --reason-file` with five value-adds: (1) idempotency (early-return when status is already `closed`); (2) evidence-path verification (halts on first missing path); (3) HEAD + ISO 8601 UTC timestamp prefix prepended to the rationale body; (4) post-close round-trip via `bd show` confirming `status=closed`; (5) **workspace-db pin** (amnesia-tvpb / Standing #16 R16): every bd read/write is pinned with `bd --db <git-root>/.beads/beads.db`. A `bd note` is also written so the rationale is queryable independent of `bd show --reason`; its failures are surfaced (non-fatal) rather than silently swallowed.

## Database-targeting guarantee (amnesia-tvpb)

The primitive derives the target database from the **git common dir** (`git rev-parse --git-common-dir` → main worktree root) and pins it on every `bd close`/`bd note`/`bd show`. Using the common dir (not `--show-toplevel`) makes it **worktree-safe**: a closure run from a linked git worktree (`.claude/worktrees/agent-*`, whose root has no `.beads`) correctly targets the shared **main-repo** `.beads`. It does **not** rely on bd's cwd auto-discovery, which (when invoked outside a git repo) walks the filesystem up and can silently resolve an ancestor/home `.beads` — closing the **wrong** database. (PYTHONPATH for the adapter still uses the invocation worktree's `tools/` so a worktree runs its own adapter code.) The wrapper **hard-aborts** (exit 1, no silent fallback) when:

- it is run outside a git workspace (`git rev-parse --git-common-dir` fails), or
- the resolved workspace `.beads` directory is absent.

Run it from the main repo or any linked worktree (any depth is fine).

## Contract with primitive

- Primitive: `tools/bd-close-rationale.sh`
- Flags / inputs:
  - `--id <bd-id>` (required)
  - `--rationale <file>` (required)
  - `--evidence-paths <comma-list>` (optional; each path is verified via `test -e`)
- Output:
  - On success: `closed: <id> (HEAD=<sha>)` on stdout.
  - On idempotent no-op: `already closed: <id>` on stderr; exit 0.
  - On failure: error message on stderr; exit 1.
- Exit semantics: 0 on success or idempotent no-op; 1 on missing inputs, missing evidence, or close failure.

## Example invocation

```bash
tools/bd-close-rationale.sh \
  --id amnesia-o4fp.6 \
  --rationale apps/amnesia/docs/perf-evidence/2026-05-11/o4fp.6/rationale.md \
  --evidence-paths apps/amnesia/docs/perf-evidence/2026-05-11/o4fp.6/manifest.json,apps/amnesia/docs/perf-evidence/2026-05-11/o4fp.6/summary.md
```

## Halt conditions

- Not inside a git workspace (`git rev-parse --git-common-dir` fails) — halt + surface "not inside a git workspace — refusing to run" (amnesia-tvpb db-targeting guard).
- Resolved workspace `.beads` absent — halt + surface "workspace bd database not found at <root>/.beads" (amnesia-tvpb db-targeting guard).
- An evidence path passed via `--evidence-paths` does not exist on disk — halt + surface "evidence missing: <path>".
- `bd close` itself fails — halt + surface bd's stderr.
- Post-close `bd show` reports a status other than `closed` — halt + surface "close failed".

## Note

Idempotent. Running on an already-closed issue prints `already closed: <id>` to stderr and exits 0; no rationale is rewritten and no duplicate `bd note` is added. Use this primitive freely in retry loops.

## Related

- Sibling skill: `closure-attest` produces a JSON closureAttestation document that is a natural fit for the rationale body (write closure-attest output to a file, pass that file as `--rationale`).
- ADR-016 §6 Evidence Bundle Schema: when used together, the rationale references evidence paths whose hashes are recorded in the attestation.
