<!-- Generated by gzkit — do not edit manually -->
# docs/design/adr Agent Instructions

> Shared subtree rules. See root `AGENTS.md` for project-wide governance.

<!-- Generated by gz agent sync — do not edit -->

# ADR Audit (gzkit)

Purpose: verify ADR completion claims using reproducible evidence.

## Audit sequence

1. Verify linked OBPI evidence:

```bash
uv run gz adr audit-check ADR-<X.Y.Z>
```

2. Run quality checks:

```bash
uv run gz lint
uv run gz test
uv run gz typecheck
uv run mkdocs build --strict
```

3. Run closeout/audit lifecycle in order:

```bash
uv run gz closeout ADR-<X.Y.Z> --dry-run
uv run gz attest ADR-<X.Y.Z> --status completed
uv run gz audit ADR-<X.Y.Z>
```

4. Emit audit receipt:

```bash
uv run gz adr emit-receipt ADR-<X.Y.Z> --event validated --attestor "<Human Name>" --evidence-json '{"scope":"ADR-<X.Y.Z>","date":"YYYY-MM-DD"}'
```

## Rules

- Do not run `gz audit` before attestation.
- If audit-check fails, diagnose whether the flagged REQ is (a) genuinely uncovered — author a REQ-derived test and decorate with `@covers(REQ-X.Y.Z-NN-MM)` — or (b) covered by a test whose assertion drifted from REQ semantics — re-derive the assertion per `.gzkit/rules/tests.md` § "Tests assert semantics, not strings" (Invariant 6f). Never backfill a cosmetic `@covers` decorator to silence audit-check without re-deriving the assertion.
- Keep `docs/user/runbook.md` and `docs/governance/governance_runbook.md` aligned with runtime behavior.

## Legitimate-authoring exemptions (covers-backfill heuristic)

The same-commit-window backfill heuristic exempts five structurally distinct shapes from the cosmetic-backfill anti-pattern. Each exemption preserves the GHI #272/#309 protection against decorators silencing audit-check without re-derived semantics; if the receipt is anchored to the same commit as the decorator AND the file/block was created in the same commit, the exemption is suppressed (the GHI #309 triple still flags).

| Shape | Source | Source-side annotation | Receipt-coupled flag? |
|-------|--------|------------------------|------------------------|
| Same-commit FILE creation | GHI #382 | none — file went 0→N lines in intro commit | suppressed (still flags) |
| Same-commit BLOCK creation | GHI #466 Component B | none — function `def` line shares decorator's intro SHA | suppressed (still flags) |
| Inline regression-invariant overlay marker | GHI #466 Component A | `# audit-exempt: regression-invariant-overlay <reason>` on decorator line; reason text required | NOT suppressed (operator attestation by design) |
| `Ceremony:` trailer | GHI #386 | trailer in `_EXEMPT_CEREMONIES` (e.g. `Ceremony: gz-git-sync`) | n/a (trailer governs) |
| Subject-suffix marker | GHI #390 | parenthesized suffix at end of subject (e.g. `(gz git-sync)`) | n/a (subject governs) |

**When to use the inline marker (Component A):** A new `@covers(REQ-X)` decorator is being added to an existing test whose assertion structurally IS the REQ being claimed — typical case is a regression-invariant REQ pointing at a test that already enforces the prior invariant (e.g. byte-parity tests covering a "no regression of OBPI-N" REQ). The marker is the operator's explicit attestation that the overlay is legitimate, not cosmetic backfill. Reason text is mechanically required so the exemption can't be a one-token escape hatch — keep it terse but informative (typical form: pointer to the OBPI/REQ relationship). Do NOT use the marker when the right move is to author a new REQ-derived assertion; the marker is reserved for the genuine overlay shape.

<!-- Generated by gz agent sync — do not edit -->

# Brief Heading Conventions (gzkit)

OBPI brief evidence sections MUST use H3 (`###`), not H2 (`##`).

## Canonical evidence sections (H3)

| Heading | Consumer |
|---------|----------|
| `### Implementation Summary` | `gz obpi complete`, closeout evidence pass |
| `### Key Proof` | `gz obpi complete`, closeout evidence pass |
| `### Closing Argument` | `extract_closing_argument`, defense-brief renderer |

`## Acceptance Criteria` (H2) is the canonical top-level brief section and
is deliberately not in the list above — do not conflate it with the per-pass
evidence `### ACCEPTANCE` section (which, if present, is H3).

## Why H3, not H2

Ceremony renderers and completion hooks extract these sections by H3 heading
match. A brief that drifts one of the canonical evidence headings to `##`
silently passes schema validation (the section exists) but the extractor
stops at the next H2 boundary and returns an empty body — triggering
mid-ceremony failures and post-attestation diagnostic noise.

Gate 2 (`## Objective`, `## Acceptance Criteria`, `## ALLOWED PATHS`, etc.)
remains H2: those are top-level brief structure, not per-pass evidence.

## Mechanical check

```bash
uv run gz validate --brief-headings
```

Exits 3 on drift. Recovery: rewrite the heading as H3 and re-run
completion. Do not "accept both levels" at the hook — the hook is the
contract; the brief is the defect.

## Related

- GHI #238 — promotion of this rule from hook-level silent failure to a
  `gz validate --brief-headings` scope.
- `.gzkit/rules/gate5-runbook-code-covenant.md` — documentation is a
  first-class deliverable; evidence-section heading drift is the same
  class of failure as runbook drift.
- `docs/governance/advisory-rules-audit.md` — scorecard entry.

<!-- Generated by gz agent sync — do not edit -->

<!-- rule-version: 0.2.0 -->

# GitHub CLI Guardrails (gzkit)

> **Rule version:** `0.2.0` — diet pass under GHI #327; compressed cross-repo filing section.

Use `gh` for defect tracking, ADR closeout, release ceremony, or active brief / explicit user request.

## Allowed commands

```bash
gh issue create --label defect --title "..." --body "..."
gh issue list --search "ADR-X.Y.Z" --state open
gh issue close <number> --comment "Resolved by ADR-X.Y.Z closeout."
gh release create vX.Y.Z --title "vX.Y.Z" --notes-file RELEASE_NOTES.md
```

## Prohibited without explicit approval

- Repository/org settings mutations
- Secret/token management
- Force pushes
- Merging PRs without explicit human authorization

## Cross-repo filing

Defects against gzkit-owned surfaces (`gz <verb>`, `.gzkit/`, `src/gzkit/`, `gzkit.<module>`) filed from consuming repos MUST go to `tvproductions/gzkit` via `gz issue file`. The wrapper auto-stamps provenance, validates surface references, and hard-rejects bodies referencing no gzkit surface. Consumer-repo-only defects go to the consumer's tracker.

Operator PII: the wrapper stamps only repo slug + gz version, never operator email.

<!-- Generated by gz agent sync — do not edit -->

<!-- rule-version: 0.3.2 -->

# Security Sensitivity (gzkit)

> **Rule version:** `0.3.2` — renamed prohibited `## Anti-patterns` heading → `## Do Not` (OBPI-0.0.54-04 shape conformance pass).

## Invariant

**Security work needs heightened review regardless of lane or kind.** A brief carrying `sensitivity: security` always requires human attestation for completion — consistent with the universal attestation rule in ADR-0.0.36. The axis is additive: heavy lane, foundation kind, and security sensitivity each independently determine which gates fire; Gate 5 brief-level human attestation is universal for every OBPI regardless of kind, lane, or sensitivity.

## Registry contract

Security surfaces are named in [`data/security_surfaces.json`](../../data/security_surfaces.json). The registry is self-bootstrapping: edits require the editing brief to declare `sensitivity: security`.

## `gz validate --sensitivity` (binding)

1. **Auto-detect floor.** Briefs whose allowed-paths overlap a registered security surface MUST declare `sensitivity: security` (exit 3 on violation).
2. **Escalate-not-escape.** A brief MAY declare sensitivity without overlap (escalation). A brief MAY NOT omit sensitivity while overlapping (escape is fail-closed).

## Heightened walkthrough

`gz obpi complete` on a `sensitivity: security` brief fires an extended Gate 5 walkthrough: surface enumeration, `arb-step-security-scan-*` receipt confirmation, classification confirmation, and co-presence proxy gate. Scanner-unavailable is fail-closed (no degradation).

## Do Not

- Declaring `sensitivity: absent` while touching a registered surface
- Editing `data/security_surfaces.json` without declaring `sensitivity: security`
- Narrative substitution for the security-scan receipt
- Bundling security work into a non-security parent OBPI

> See [`docs/governance/security-sensitivity-rationale.md`](../../docs/governance/security-sensitivity-rationale.md) for walkthrough enumeration details, scanner-unavailable failure mode rationale, and related references.

<!-- Generated by gz agent sync — do not edit -->

<!-- rule-version: 0.2.0 -->

# TASK Discovery (gzkit)

> **Rule version:** `0.2.0` — OBPI-0.0.64-03: `gz task start --seq next|N` CLI surface implemented; subdivision sub-invariant now mechanically enforced via the new CLI surface rather than prose-only.

## Invariant

**Every unit of labor traceable to a TASK MUST surface that attribution through at least one of four discovery channels.** Layer-drift across the channels (different TASK IDs for the same logical unit) is itself a fail-close signature, not a tolerable inconsistency. The four-channel design ensures no single channel can become the silent bypass surface that GHI #553 named.

## The Four Channels

| Channel | Surface | Authoring contract | Discovery mechanism |
|---------|---------|--------------------|--------------------|
| Python `@advances` | Source functions in `src/gzkit/**` | `@advances("TASK-X.Y.Z-NN-MM-PP")` decorator on functions that materially advance the named TASK | Import-time decoration registers `TaskAttributionRecord`; module-level registry queried via `get_task_registry()` (ADR-0.0.64 / OBPI-02) |
| Frontmatter `tasks:` | Structured artifacts (OBPI briefs, ADR packages where applicable) | `tasks: list[str]` YAML frontmatter field listing TASK IDs this artifact advances | YAML parser walks frontmatter; schema enforcement deferred to OBPI-0.0.64-04 (`gz validate --task-envelope-coherence`) |
| Commit trailer | Git commit messages | `Task: TASK-X.Y.Z-NN-MM-PP` trailer in the final paragraph | `parse_task_trailers()` in `gzkit.tasks`; validated by `gz validate --commit-trailers` |
| Ledger `task_id` | Worklog event types in `.gzkit/ledger.jsonl` | Optional `task_id: str | None` field on the 8 worklog event types (OBPI-0.0.64-01) | JSON deserialization via `gzkit.events`; validator scope per OBPI-04 |

## Convention: Python `@advances`

```python
from gzkit.tasks import advances

@advances("TASK-0.0.64-02-01-01")
def my_function() -> None:
    """Function body unchanged — the decorator is metadata-only."""
    ...
```

**Decoration-time fail-close:**

- Invalid TASK ID format → `ValueError` at import (typos cannot ship)
- Unknown parent REQ → `ValueError` at import (TASK IDs whose `REQ-X.Y.Z-NN-MM` parent isn't in any extracted brief cannot ship)

The validation surface mirrors `@covers`'s precedent: typos that would silently pass at runtime instead block at import.

## Convention: Frontmatter `tasks:`

```yaml
---
id: OBPI-0.0.64-02-advances-decorator-and-discovery-convention
parent: ADR-0.0.64-task-envelope-and-planning-decomposition
tasks:
  - TASK-0.0.64-02-01-01
  - TASK-0.0.64-02-02-01
---
```

The `tasks:` channel is the structured-artifact equivalent of the `@advances` decorator — it declares which TASKs an artifact advances when the artifact itself is the deliverable (vs. when source functions are). Use this channel on briefs and ADR-package frontmatter when the work is documentation-shaped rather than code-shaped.

Schema enforcement for `tasks:` (rejecting malformed TASK IDs and unknown parents) is on the OBPI-0.0.64-04 work surface; this rule documents the channel.

## Convention: Commit trailer

```
fix(tasks): wire @advances decorator (GHI #553)

Task: TASK-0.0.64-02-01-01
```

The commit trailer is the freeform fallback for labor that does not produce a Python function or a structured artifact — chore work, sync ceremonies, documentation drift fixes. The `gz validate --commit-trailers` validator already enforces this surface; the `parse_task_trailers()` function accepts both the formal four-tier ID and the slug-form `TASK-<slug>-#<ghi>` for direct-fix work outside OBPI scope.

## Convention: Ledger `task_id`

The 8 worklog event types in `src/gzkit/events.py` carry an optional `task_id: str | None = None` field (OBPI-0.0.64-01). Worklog events emitted under an active TASK SHOULD populate this field. The validator signature for missing `task_id` under an active TASK is on the OBPI-0.0.64-04 work surface.

## Subdivision sub-invariant

A single REQ may have multiple TASKs (labor-subdivision via `seq=01`, `seq=02`, …). When work subdivides, each labor unit MUST get its own TASK ID — not a shared coarse-default-bucket TASK. The `seq` component is the subdivision axis; the OBPI pipeline mints `seq=01` per REQ as the coarse-default bucket, and operators/agents must `gz task start --seq next` to subdivide further.

Default-bucket-only OBPIs (every REQ has only `seq=01`) without a `req_atomic: list[str]` exemption in brief frontmatter are themselves a fail-close signature (OBPI-04 validator scope).

## Layer-drift fail-close

When a single logical unit of labor surfaces across multiple channels with different TASK IDs — `@advances` decorator names TASK-A, frontmatter `tasks:` names TASK-B, commit trailer names TASK-C — the divergence IS the signal. The OBPI-04 validator will fail Heavy lane closeouts on layer-drift; Lite lane warns.

## Do Not

- Do not use `@advances` as a comment marker (`# @advances: TASK-...`) — the decorator is the contract; comments have no AST node, no decoration-time validation, no typo defense
- Do not pre-register full TASK IDs in a closed set — TASKs are minted by the pipeline at runtime; validation is via the parent REQ
- Do not coarse-bucket subdivisible labor under a single `seq=01` TASK — subdivision via `seq=02`, `seq=03`, … is the mechanism, not an option
- Do not silently rewrite TASK IDs across channels to "make the validator happy" — layer-drift is the signal, not the defect to suppress

## Related

- ADR-0.0.64-task-envelope-and-planning-decomposition (parent)
- OBPI-0.0.64-01-task-id-worklog-schema-additive (Ledger `task_id` channel)
- OBPI-0.0.64-04-gz-validate-task-envelope-coherence (validator)
- `.gzkit/rules/skill-surface-sync.md` (rule version-discipline convention)
- `src/gzkit/tasks.py` (`@advances`, `TaskAttributionRecord`, registry)
