---
mode: CREATE
adr_id: ADR-0.0.65
branch: main
timestamp: "2026-05-30T00:26:31Z"
agent: claude-code
obpi_id: OBPI-0.0.65-01
session_id: handoff-system-consolidation-promotion-and-brief-authoring
continues_from: .gzkit/handoffs/20260529T132534Z-obpi05-done-obpi04-06-next.md
---

## Current State Summary

(Updated 2026-05-30T00:45Z after a direct-fix landed for the skill-canon doctrine drift discovered during this session's handoff write. See the Decisions Made section for the unilateral-conflict-resolution failure mode that triggered the correction.) ADR-pool.handoff-system-consolidation promoted to ADR-0.0.65 (foundation, heavy, Proposed) with four OBPI briefs scaffolded by `gz adr promote`. The pool ADR was refined with both a `## Target Scope` section (path-2 bullets) and a `## Proposed OBPI Decomposition` table (path-1 preferred form) before promotion landed; pool file now carries `status: Superseded` and `promoted_to: ADR-0.0.65-handoff-system-consolidation`. Ledger recorded `artifact_renamed` plus four `obpi_created` events at timestamp `2026-05-30T00:10:50Z`; `adr-status.md` regenerated with 89 ADRs and ADR-0.0.65 indexed as `foundation / heavy / Proposed / 2026-05-29`.

Two OBPI briefs were authored to authored-readiness via `gz-obpi-specify` and validated via `gz obpi validate --authored` (both PASS):

- `OBPI-0.0.65-01-canonical-location-migration`: 10 fail-closed requirements covering the 24-file migration, `continues_from:` chain preservation, `.gzkit/skills/gz-session-handoff/SKILL.md` output-path doctrine amendment, `skill-version` and `last_reviewed` bumps, and `gz agent sync control-surfaces`. Five REQs (four BEHAVIOR + one SUPPORT). Allowed Paths verified per ground-truth check.
- `OBPI-0.0.65-04-orientation-single-location-scan`: 8 fail-closed requirements covering `_candidate_handoff_dirs()` collapse to a single-element sequence, deletion of the GHI #529 dual-scan workaround, and preservation of the existing orientation output shape. Three BEHAVIOR REQs.

`OBPI-0.0.65-02-programmatic-api-implementation` and `OBPI-0.0.65-03-gz-handoff-cli-verb` remain in scaffold-Draft state with template defaults; they were created by the promotion but are deferred scope per operator pacing decision.

Plan-audit ran for `OBPI-0.0.65-01` with verdict PASS on ADR-to-OBPI alignment across all seven check categories (objective match, scope match, requirements coverage, lane consistency, attestation rule, no scope creep, no scope gap). The CLI structural verdict was FAIL because no plan file exists in `.claude/plans/` — expected condition; the receipt was written to `.claude/plans/.plan-audit-receipt-OBPI-0.0.65-01-canonical-location-migration.json`. An advisory scope-collision was flagged against `OBPI-0.0.42-04-story-md-scaffolding` on the shared directory tree `docs/design/adr/foundation/`; manual review confirmed disjoint file-level overlap (OBPI-0.0.42-04 creates `STORY.md` stubs inside ADR packages; OBPI-0.0.65-01 only touches `handoffs/` subdirectories).

`tests/governance/test_handoff_migration.py` was created as an empty stub so the OBPI-01 brief's Allowed Paths validate against on-disk reality; the real `@covers`-decorated tests get authored during the Stage-2 TDD red-green cycle inside the pipeline.

## Important Context

The operator's binding decision under ADR-0.0.65 § Decision item 1 is `.gzkit/handoffs/` wins as the canonical handoff write location per ADR-0.0.41 / OBPI-0.0.41-03. The `gz-session-handoff` skill SKILL.md output-path doctrine has now been amended via direct fix landed in the same session (skill-version 6.3.1 → 6.4.0, `last_reviewed` 2026-05-30, mirrors regenerated via `gz agent sync control-surfaces`). This handoff at `.gzkit/handoffs/` is now retroactively correct per the amended skill canon.

The orientation hook at `scripts/session_orientation.py::_candidate_handoff_dirs` currently scans BOTH locations (the GHI #529 dual-scan workaround landed in commit `2ab33914` as `fix(orientation): … (GHI #529)`). This forward-compatible read posture means a handoff written at either location is discovered at session start; OBPI-04 collapses the union scan back to single-location after OBPI-01 empties the per-ADR sources. Until OBPI-01 lands, both locations remain valid for reads.

Routing decision: Operator selected Route A (OBPI ceremony) for the handoff system consolidation in response to the routing question raised after the "Resolve the split-brain" instruction. The four routes presented were (A) full ceremony, (B) direct fix override, (C) pause and finish OBPI-0.0.63-04 first, (D) file a GHI and defer; choice A binds the resuming agent to the promote → specify → plan-audit → pipeline sequence per OBPI rather than freelancing the migration.

Order: OBPI-01 must complete before OBPI-04 runs. OBPI-04's `_candidate_handoff_dirs()` collapse cannot land until OBPI-01 has emptied `docs/design/adr/**/handoffs/`; collapsing the scan beforehand would hide the unmigrated handoffs from auto-orientation. The OBPI-04 brief encodes this as a STOP-on-BLOCKERS gate at REQ-04-04: "if the per-ADR `handoffs/` directories still hold `.md` files at implementation time, HALT".

The five "structural errors" the promoter reported on ledger emission were scaffold-default complaints against the OBPI brief Allowed Paths sections (the path-extraction heuristic in `gz adr promote` pulled path-shaped tokens from the OBPI descriptions into Allowed Paths without prefix-correction). Those have been resolved in the OBPI-01 and OBPI-04 briefs by the `gz-obpi-specify` authored pass; OBPI-02 and OBPI-03 still carry the scaffold defaults and will need the same pass when prioritized.

Three operator corrections recorded in `.gzkit/insights/agent-insights.jsonl` over the prior four days name the canonical failure mode this session avoided: hand-authoring an OBPI brief via raw Write instead of routing through `Skill(gz-obpi-specify)`. The lesson encoded as the most recent next_action: "HARD GATE: any OBPI brief authoring routes through Skill(gz-obpi-specify) before the first Write; any task with a named skill in the handoff invokes that skill in the SAME turn (CLAUDE.md Invariant 10a)."

A doctrine drift was surfaced during promotion and is not yet fixed: `.gzkit/skills/gz-adr-promote/SKILL.md` (line 28) claims promotion is fail-closed unless the pool ADR contains EITHER actionable `## Target Scope` bullets OR a `## Proposed OBPI Decomposition` table; `src/gzkit/commands/adr_promote_utils.py:315` calls `_required_pool_section(pool_content, "Target Scope")` unconditionally, requiring `## Target Scope` even when the Decomposition table is the slug source. This is a candidate direct-fix per AGENTS.md § Defect-fix routing thresholds (one-file edit to the SKILL.md to match code reality, or a parallel edit to make the code accept either path).

## Decisions Made

- **Decision:** Promote ADR-pool.handoff-system-consolidation as foundation kind, heavy lane, Proposed status, ADR-0.0.65.
  **Rationale:** Pool ADR's Notes section flagged foundation kind on grounds that the canonical-location decision shapes a system invariant; heavy lane was already declared in pool frontmatter. Next-free foundation integer was 65 (no gaps).
  **Alternatives rejected:** Promoting as feature kind (would require non-`0.0.x` semver and decouples from the foundation invariant); leaving in pool (rejected by the operator's "Route A" choice).

- **Decision:** Four-OBPI decomposition matching the pool ADR's existing Notes plan, with operator-driven canonicalization captured in OBPI-01 directly.
  **Rationale:** Pool ADR's Notes already prescribed the four-unit split (canonical-location-migration / programmatic-api-implementation / gz-handoff-cli-verb / orientation-single-location-scan); Rule-of-Three baseline mapped to 1+1+2 across Registry/Core-Execution/Lifecycle-Operations layers; Matrix-of-Four (single-narrative, testability-ceiling, state-anchor, surface-boundary) passed per unit without forcing further split.
  **Alternatives rejected:** Three-OBPI variant (folding OBPI-04 into OBPI-01) — rejected because OBPI-04 has a distinct surface (orientation hook) and a hard sequencing dependency that justifies the firing-point boundary; five-OBPI variant (splitting OBPI-02 across runtime-helpers and SKILL.md amendments) — rejected because the SKILL.md amendments naturally co-locate with the canonization step in OBPI-01.

- **Decision (corrected post-hoc):** Initially wrote this handoff to `.gzkit/handoffs/` per the operator's `.gzkit/handoffs/` canonical decision, bypassing the skill's then-current `{ADR-package}/handoffs/` SKILL.md path. Operator caught this as a Behavior-Rule-9 violation (silently resolving a doctrine conflict instead of stopping and surfacing it) and authorized a direct fix to the skill SKILL.md instead.
  **Rationale (revised):** The skill SKILL.md was drifted from ADR-0.0.41 / OBPI-0.0.41-03 canonical doctrine — a coupled-surface-coherence failure under AGENTS.md §1a that has been in the repo since OBPI-0.0.41-03 landed. The right structural move was to fix the skill canon (the actual defect) rather than work around it. Direct-fix routes per AGENTS.md § Defect-fix routing thresholds: 6-line edit to a single SKILL.md plus version bump plus agent sync = within direct-fix bounds.
  **Alternatives rejected:** (1) Move the handoff to `{ADR-package}/handoffs/` per skill SKILL.md as-shipped — rejected because the SKILL.md is the defect; following it just propagates the drift. (2) Leave the handoff at `.gzkit/handoffs/` and wait for OBPI-01 to amend the SKILL.md — rejected because the SKILL.md drift continues affecting any subsequent handoffs in this session and OBPI-01 won't land for another session.

- **Decision:** Use `git mv` for the 24-file relocation in OBPI-01 implementation, with a Python migration helper for `continues_from:` frontmatter chain-pointer rewriting.
  **Rationale:** `git mv` preserves rename-detection in git history (cleaner blame chain across the 24 files), but `continues_from:` rewriting requires YAML frontmatter parsing that needs Python.
  **Alternatives rejected:** Pure-Python `pathlib.shutil.move` (loses git rename detection); pure shell `find | xargs git mv` (chain-pointer rewriting still needs Python anyway).

- **Decision:** Defer OBPI-02 (programmatic API) and OBPI-03 (`gz handoff` CLI verb) authoring until OBPI-01 + OBPI-04 land.
  **Rationale:** Operator's three concrete asks in the "Resolve the split-brain" instruction map cleanly to OBPI-01 (migration + SKILL.md amendment) and OBPI-04 (scan collapse + workaround deletion); OBPI-02 and OBPI-03 are scope expansions from the pool ADR's plan that don't unblock the immediate split-brain resolution.
  **Alternatives rejected:** Full four-OBPI authoring in this session — rejected because the session was already long after pool refinement + promotion + two brief-authoring passes + plan-audit.

- **Decision:** Cut a handoff via `gz-session-handoff` instead of running `gz obpi pipeline OBPI-0.0.65-01` directly in this session.
  **Rationale:** Operator chose this option after Pocock's `/handoff` thesis surfaced the "dumb zone past 120k tokens" framing earlier in the conversation; pipeline OBPI-01 execution involves the full TDD red-green cycle plus five gates, which warrants a clean session.
  **Alternatives rejected:** Continue into the pipeline in this same session (smaller context budget); enter plan mode to author a formal plan file first (more ceremonial but adds another step before resumable progress).

## Immediate Next Steps

1. Claim the OBPI lock for OBPI-01 via `uv run gz obpi lock claim OBPI-0.0.65-01-canonical-location-migration --agent claude-code`. Confirm no other agent holds the lock via `uv run gz obpi lock list`.
2. Invoke `uv run gz obpi pipeline OBPI-0.0.65-01-canonical-location-migration` to enter the runtime-owned implement → verify → ceremony → guarded-git-sync → completion sequence per AGENTS.md § OBPI Acceptance Protocol. Do not freeform any stage; the prior session insights logged this as the canonical failure mode under Behavior Always #16.
3. Inside Stage 2 (implement), author `tests/governance/test_handoff_migration.py` with four `@covers`-decorated BEHAVIOR tests (one per REQ-01 through REQ-04) plus the REQ-05 SUPPORT assertion (`gz agent sync control-surfaces` clean). Follow TDD red-green per REQ — write the test, observe RED, perform the relevant migration step, observe GREEN.
4. Inside Stage 2 (implement), perform the 24-file migration. Use `git mv` for the relocations to preserve rename-detection. Author a Python helper (inline in the test module is acceptable for one-shot migration) that walks each migrated handoff's frontmatter, rewrites `continues_from:` pointers from `docs/design/adr/.../handoffs/...` to `.gzkit/handoffs/...`, and re-serializes the YAML. Delete the now-empty `docs/design/adr/foundation/*/handoffs/` and `docs/design/adr/pre-release/*/handoffs/` directories.
5. Amend `.gzkit/skills/gz-session-handoff/SKILL.md` output-path doctrine at every reference (audit identified lines 32, 83, 248 and likely the asset template at `.gzkit/skills/gz-session-handoff/assets/handoff-template.md`). Bump `skill-version:` per the skill-surface-sync rule's bump table (this is a governance-rule change so a minor bump fits) and set `last_reviewed:` to `2026-05-30` in the same edit. Run `uv run gz agent sync control-surfaces` to regenerate mirror copies at `.claude/skills/`, `.agents/skills/`, `.github/skills/`, and `src/gzkit/skills/`.
6. After OBPI-01 reaches `attested_completed` in the ledger, pick up OBPI-0.0.65-04 via `gz-plan-audit OBPI-0.0.65-04-orientation-single-location-scan` followed by `gz obpi pipeline OBPI-0.0.65-04-orientation-single-location-scan`. The OBPI-04 brief is already authored and validated — no additional authoring pass needed.
7. After OBPI-04 reaches `attested_completed`, surface deferred-scope status to the operator: OBPI-02 (programmatic API at `src/gzkit/handoff_api.py`) and OBPI-03 (`gz handoff` CLI verb with manpage and behave coverage) remain scaffold-Draft and need authoring via `gz-obpi-specify` when prioritized.

## Pending Work / Open Loops

- OBPI-0.0.65-02 (programmatic API): scaffold-Draft state; author via `gz-obpi-specify` when prioritized. Will implement the `create_handoff` / `scaffold_handoff` / `list_handoffs` / `resume_handoff` / `load_handoff_chain` functions documented as NOT IMPLEMENTED in the current SKILL.md.
- OBPI-0.0.65-03 (`gz handoff` CLI verb): scaffold-Draft state; author via `gz-obpi-specify` when prioritized. Adds the missing CLI surface so handoff authoring routes through the validation gate instead of hand-authored markdown.
- OBPI-0.0.63-04 (closeout-skill-reverify-wording-fix): the original active-handoff resume action from the session-start orientation that this session context-switched away from. Still pending; the prior handoff at `docs/design/adr/foundation/ADR-0.0.63-closeout-ceremony-runtime-engine-parity/handoffs/20260529T132534Z-obpi05-done-obpi04-06-next.md` remains the source of truth for its scope.
- Doctrine drift fix (still pending): `.gzkit/skills/gz-adr-promote/SKILL.md` line 28 claims `## Target Scope` OR `## Proposed OBPI Decomposition` either satisfies promotion; `src/gzkit/commands/adr_promote_utils.py:315` requires `## Target Scope` unconditionally. Candidate direct-fix under AGENTS.md § Defect-fix routing thresholds (single file edit, scope bounded to skill canon or code reconciliation). Routes via `fix(skill): align gz-adr-promote skill canon with code requirement (GHI #...)` after filing the GHI via `/ghi-author`.
- Doctrine drift fix (LANDED this session via direct fix): `.gzkit/skills/gz-session-handoff/SKILL.md` amended from `{ADR-package}/handoffs/` to `.gzkit/handoffs/` matching ADR-0.0.41 / OBPI-0.0.41-03 canonical doctrine. Skill-version 6.3.1 → 6.4.0; last_reviewed 2026-05-30; mirrors regenerated. OBPI-0.0.65-01 brief scope-amended to record this as already-done (Requirements #5, #6, #7 reframed as non-regression assertions; new REQ-7a bans re-touching SKILL.md in the pipeline).

## Verification Checklist

- [ ] OBPI-0.0.65-01 brief still validates authored-readiness: `uv run gz obpi validate --authored docs/design/adr/foundation/ADR-0.0.65-handoff-system-consolidation/obpis/OBPI-0.0.65-01-canonical-location-migration.md`
- [ ] OBPI-0.0.65-04 brief still validates authored-readiness: `uv run gz obpi validate --authored docs/design/adr/foundation/ADR-0.0.65-handoff-system-consolidation/obpis/OBPI-0.0.65-04-orientation-single-location-scan.md`
- [ ] OBPI lock state clean: `uv run gz obpi lock list` shows no claim on OBPI-0.0.65-01 by another agent
- [ ] Working tree state matches handoff: `git status` shows only this session's authored briefs, the test stub, the pool ADR Superseded edit, and this handoff file
- [ ] Branch matches: `git branch --show-current` returns `main`
- [ ] ADR-0.0.65 indexed: `grep "ADR-0.0.65" docs/governance/GovZero/adr-status.md` returns the row created during promotion
- [ ] Ledger trail intact: `grep "ADR-0.0.65\|OBPI-0.0.65" .gzkit/ledger.jsonl` returns one `artifact_renamed` plus four `obpi_created` events
- [ ] Plan-audit receipt freshness: `.claude/plans/.plan-audit-receipt-OBPI-0.0.65-01-canonical-location-migration.json` exists and is newer than the OBPI-01 brief mtime

## Evidence / Artifacts

- `docs/design/adr/foundation/ADR-0.0.65-handoff-system-consolidation/ADR-0.0.65-handoff-system-consolidation.md` — promoted ADR with Persona, Intent, Decision items 1-4, Decomposition Scorecard, Checklist, Target Scope, and Notes inherited from the pool ADR
- `docs/design/adr/foundation/ADR-0.0.65-handoff-system-consolidation/obpis/OBPI-0.0.65-01-canonical-location-migration.md` — authored brief covering the 24-file migration plus SKILL.md amendment plus skill-version bump plus agent sync
- `docs/design/adr/foundation/ADR-0.0.65-handoff-system-consolidation/obpis/OBPI-0.0.65-04-orientation-single-location-scan.md` — authored brief covering the `_candidate_handoff_dirs()` collapse plus workaround deletion
- `docs/design/adr/foundation/ADR-0.0.65-handoff-system-consolidation/obpis/OBPI-0.0.65-02-programmatic-api-implementation.md` — scaffold-Draft brief; needs authoring before pipeline invocation
- `docs/design/adr/foundation/ADR-0.0.65-handoff-system-consolidation/obpis/OBPI-0.0.65-03-gz-handoff-cli-verb.md` — scaffold-Draft brief; needs authoring before pipeline invocation
- `docs/design/adr/pool/ADR-pool.handoff-system-consolidation.md` — Superseded; retained as historical intake context
- `tests/governance/test_handoff_migration.py` — empty stub created so the OBPI-01 Allowed Paths validate against on-disk reality; real tests authored at Stage-2 TDD red-green time
- `.claude/plans/.plan-audit-receipt-OBPI-0.0.65-01-canonical-location-migration.json` — plan-audit receipt with verdict FAIL (no plan file) but ADR-to-OBPI alignment PASS recorded in the manual audit narrative
- `docs/governance/GovZero/adr-status.md` — regenerated with 89 ADRs by the post-promotion register-adrs invocation
- `.gzkit/ledger.jsonl` — recorded one artifact_renamed event (pool ADR to ADR-0.0.65, reason pool_promotion, kind foundation, semver 0.0.65) plus four obpi_created events parented to ADR-0.0.65

## Environment State

Python runtime via `uv` (project standard); current HEAD on branch `main`. Working tree carries uncommitted edits from this session: the promoted ADR package directory under `docs/design/adr/foundation/ADR-0.0.65-handoff-system-consolidation/`, the pool ADR's Superseded edit at `docs/design/adr/pool/ADR-pool.handoff-system-consolidation.md`, the test stub at `tests/governance/test_handoff_migration.py`, the regenerated `docs/governance/GovZero/adr-status.md`, the appended ledger events, and this handoff file at `.gzkit/handoffs/`. No commits were made during this session; the resuming agent inherits all changes in working-tree state and runs the OBPI-01 pipeline against the current HEAD plus working tree.
