Skip to content
Back to skills

Close

ASecurity

Use to formally close a slice once its phases are complete, audited, and reconciled — confirm the rollup, verify spec-coherence, harvest durable findings, reconcile lifecycle status, and land a clean final commit. Routed to from /reconcile.

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 19, 2026
developmentgobashgit

Works with

  • terminal

Security analysis

A100/100

Scanned September 29, 2026

npx -y skills add davidlee/doctrine --skill close --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Close?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Close
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/davidlee-close/badge)](https://www.skillsdirectory.com/skills/davidlee-close)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: close
description: Use to formally close a slice once its phases are complete, audited, and reconciled — confirm the rollup, verify spec-coherence, harvest durable findings, reconcile lifecycle status, and land a clean final commit. Routed to from /reconcile.
---

# Close

You are executing formal closure, not just marking work done.

Inputs:

- completed, audited, reconciled implementation phases
- the reconciliation review (RV) with every finding terminal and the
  `## Reconciliation Outcome` recorded (see `/reconcile`)
- the governing slice id

## Process

1. **Pre-check:**
   - Phase exit criteria (`EX-`) and verification (`VT-`) are met. Confirm the
     rollup: `doctrine slice list` should show the slice as `X/X complete` with
     no `!N` blocked, no `?N` anomalous, no `—` untracked.
   - `/reconcile` is done (via `/audit → /reconcile`): the RV ledger is resolved,
     every governance/spec finding is dispositioned, and the RV carries a
     `## Reconciliation Outcome` section. If the reconciliation brief was empty
     (no-op), the outcome confirms that explicitly.
   - Durable findings from the slice are harvested per
     `lib:reference/harvest.md` before
     closure — or **consciously rejected**. A clean slice may harvest nothing;
     the conscious-rejection gate is what closure checks.
   - `doctrine check gate` is green.
2. **Spec-coherence gate — confirm reconciliation is complete before `done`:**
   Before the terminal transition, verify every item from the audit's
   reconciliation brief is resolved through one of four paths:
   * **REV done** — governance/spec items covered by a `done` REV
     (`revision status REV-N done`). The REV rationale (`revision-NNN.md`)
     carries the reconcile narrative.
   * **Withdrawn** — finding withdrawn in the RV with rationale.
   * **Tolerated** — finding tolerated in the RV with rationale.
   * **Escalated to design** — slice transitioned back to `design` via the
     design back-edge (`reconcile → design`).
   Additionally:
   * Every per-slice direct-edit item is applied to `design.md` /
     `slice-NNN.md` and recorded in the `## Reconciliation Outcome`.
   * The RV ledger is resolved (`done · await=none`): every finding terminal
     **and** the pass concluded (`review conclude RV-NNN --basis …`). A ledger
     whose findings are all terminal — a zero-finding ledger included — reads
     `active · await=raiser` until the raiser concludes it; conclude it, do not
     raise a token finding. The absence of unresolved blockers is what gates the
     transition, never the status string (a display summary, never a gate).
   * The reconcile outcome is recorded (REV rationale and/or RV
     `## Reconciliation Outcome`).
   No free-floating "rejected" disposition is permitted — every finding
   must land in one of the terminal states above.
   If any item is unresolved, **refuse close** and return to `/reconcile`.
   (The structural closure seam is the mechanical backstop; this gate is the
   substantive check — the verb enforces; the skill verifies.)
3. **Commit cleanly:** land `.doctrine/**` workflow artefacts in small, clean
   conventional commits scoped with the slice id, rather than letting them
   accumulate. Code and workflow edits go together or separately, whichever
   commits cleanly first.
   > **Stage the slug symlink.** `*/new` verbs lay out `<kind>/NNN/` **and** a
   > sibling slug symlink `<kind>/NNN-slug -> NNN` (slice, review, revision, rec, …).
   > A path-scoped `git add <kind>/NNN/` stages the dir but misses the symlink,
   > stranding it uncommitted. Stage both — `git add <kind>/NNN*` — or add the
   > symlink explicitly. Check `git status` for a dangling `NNN-slug` before the
   > final commit.
3a. **Dispatched slice — integrate the admitted OID (post-audit only).** If the
   slice was driven by `/dispatch`, project the audited units now:

   ```bash
   # 0. Resolve the trunk delivery ref once (config-driven; default refs/heads/main):
   trunk=$(doctrine dispatch deliver-to)

   # 1. Admit a close_target candidate (if not already done during /reconcile):
   doctrine dispatch candidate create --slice <N> --label close-001 \
     --role close_target --payload code --base "$trunk" \
     --source refs/heads/review/<N>
   doctrine dispatch candidate admit --slice <N> --role close_target \
     --candidate refs/heads/candidate/<N>/close-001 --review RV-NNN

   # 2. Project onto trunk (--trunk is REQUIRED; omitting it is a dry run):
   doctrine dispatch sync --slice <N> --integrate --trunk "$trunk"
   ```

   When a candidate workflow is active this targets the immutable **admitted
   `close_target` OID** (and `--edge` the admitted `review_surface` OID) under a
   fast-forward-only CAS row — **never a raw `phase/*`/`review/*` tip or the
   mutable candidate ref**, and never a close-time merge. A moved trunk refuses
   (admit a superseding close-target candidate on the new base). This is the
   **only** place `--integrate` runs — never at `/dispatch` conclude, only here,
   post-audit.

   **Verify (tree-true).** After `--integrate --trunk`, both checks
   below must pass — do **not** proceed to step 4 unless they do:
   ```bash
   # (a) No phantom reverse-diff: the tracked working tree matches HEAD. A nonzero
   #     exit means integrate advanced the ref but desynced the live checkout — STOP.
   git diff --quiet HEAD

   # (b) The projected delta genuinely landed (not a silent dry-run): the committed
   #     journal's trunk row holds the planned tip; it must equal the trunk ref.
   trunk=$(doctrine dispatch deliver-to)
   planned=$(doctrine dispatch sync --slice <N> --show-journal-trunk-oid \
     --trunk "$trunk")
   git diff --quiet "$planned" "$trunk"
   ```
   (a) is the phantom-reverse-diff detector — the **whole tracked tree**, not
   path-limited (a phantom reverse-diff can span any file the slice projected,
   not just `src/`).
   (b) reads the trunk row's `planned_new_oid` from the committed `dispatch/<N>`
   journal — a tree-read, stable from this checkout — and diffs it against
   the resolved trunk delivery ref (`doctrine dispatch deliver-to`, default
   `refs/heads/main`); a difference means trunk does not hold the projected tip, so
   integration did not land.

3b. **Split lineage — the payload reached trunk out-of-band
   (`--record-integration`).** See `lib:reference/dispatch-mechanics.md` §
   Split lineage — record an already-landed payload, don't advance trunk.
   The close gate still refuses `done` ("dispatched but no
   trunk row"). Record the earned row instead of hand-editing `journal.toml`:

   ```bash
   trunk=$(doctrine dispatch deliver-to)
   doctrine dispatch sync --slice <N> --record-integration --trunk "$trunk"
   ```

   Per `lib:reference/dispatch-mechanics.md` § Split lineage,
   `--record-integration` asserts the payload is already an ancestor of trunk
   and commits a single Verified trunk row. Then `slice status <N> done` reads
   that row and passes. This is the
   sanctioned replacement for a hand-written journal row; land the payload
   out-of-band as `git merge --no-ff phase/<N>-NN` (or
   the admitted candidate), not `review/<N>`.

4. **Transition lifecycle:** confirm the slice is in `reconcile` (flip it with
   `doctrine slice status <id> reconcile` if `/audit` didn't), then
   `doctrine slice status <id> done` (`<id>` is the bare number, e.g. `40`).
   The closure seam enforces the order and refuses while an RV targeting the
   slice carries an unresolved blocker. Re-run `doctrine slice list` and confirm
   the `⚠` divergence marker is gone — authored status now agrees with the
   rollup. (The terminal set is `{done, abandoned}`; closure here is the `done`
   path — abandoning a slice is a separate decision, not this skill.)
5. **Close the originating backlog item:** if a backlog item (ISS/IMP/CHR/RSK)
   spawned this slice, transition it too — `doctrine backlog edit <ID>
   --status resolved --resolution fixed` (or the resolution that fits). A closed
   slice with its origin still open is hygiene debt.
6. If a blocking finding remains unresolved, do **not** close — return to
   `/reconcile`. If closure depends on tolerated drift with material
   tradeoffs, `/consult` before normalising around it.

### Drift discharge recipe

When `slice status <id> done` refuses with *undischarged residual drift*, each
flagged requirement needs an `accept` REC **owned by the closing slice** that
satisfies all three clauses:

- **(a)** `move = accept` — an affirm, not `revise`/`redesign`.
- **(b)** a `[[status_delta]]` naming the requirement whose `to` equals its
  current authored status (the status the refusal prints).
- **(c)** the REC's `[[evidence_ref]]` set ⊇ every distinct coverage key feeding
  that requirement's composite, so fresh contradictory evidence cannot be excused
  by a stale REC.

Author it, then hand-edit the two tables:

```bash
doctrine rec new --move accept --owning-slice SL-NNN --title "accept REQ-NNN"
# then hand-author the [[status_delta]] and [[evidence_ref]] tables
```

Full predicate, rationale, and a worked example:
`doctrine memory show mem.pattern.doctrine.close-drift-discharge-rec`.

## Outcomes

- The slice is `done`, with the rollup in agreement.
- The originating backlog item (if any) is resolved.
- Durable guidance is captured in memory or consciously rejected.
- The tree is clean and the workflow artefacts are committed.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.