Quickstart — Review/Merge Gate Hardening (3.2.x)
Mission: review-merge-gate-hardening-3-2-x-01KRC57C | Date: 2026-05-12
Operator-facing walkthrough of the new commands and behaviors this mission introduces. Use this as the integration-test plan companion.
1. Running spec-kitty review in the two modes (WP03)
Lightweight mode (default for pre-merge missions)
spec-kitty review --mission <slug>
# or explicitly:
spec-kitty review --mission <slug> --mode lightweight
Output (stdout):
[spec-kitty review] mode=lightweight (not a release gate)
WP lane check: <result>
Report: <path-to-mission-review-report.md>
The persisted report begins with the line:
> Lightweight consistency check; not a release gate.
Post-merge mode (auto-detected once merged)
spec-kitty review --mission <slug>
# auto-detects from meta.json.baseline_merge_commit
Output:
[spec-kitty review] mode=post-merge (release gate)
Gate 1 (wp_lane_check): pass
Gate 2 (dead_code_scan): pass (or skipped with reason)
Gate 3 (ble001_audit): pass
Gate 4 (report_writer): pass
issue_matrix_present: true
mission_exception_present: not_applicable
verdict: pass
Mode mismatch (operator footgun caught)
spec-kitty review --mission <pre-merge-slug> --mode post-merge
Exits non-zero with MISSION_REVIEW_MODE_MISMATCH. The diagnostic body lists three remediation options. Read it; don't bypass.
2. Authoring issue-matrix.md against the canonical schema
Minimal valid matrix:
| issue | verdict | evidence_ref |
|-------|---------|--------------|
| #985 | fixed | WP03; src/specify_cli/cli/commands/review/_mode.py; tests/specify_cli/cli/commands/review/test_mode_resolution.py |
Full canonical (with named-optional columns):
| issue | scope | wp | fr | verdict | evidence_ref |
|-------|-------|----|----|---------|--------------|
| #985 | P1 | WP03 | FR-005 | fixed | <evidence> |
| #987 | P1 | WP01 | FR-001 | fixed | <evidence> |
Verdict allow-list (closed): fixed | verified-already-fixed | deferred-with-followup.
Forbidden: any column outside the mandatory + named-optional set. The validator will tell you which one.
For deferred-with-followup rows, evidence_ref MUST contain a follow-up handle (issue link like #1234, or the substring Follow-up: ...).
3. Reading mission-review-report.md
Frontmatter (machine-readable):
---
verdict: pass
mode: post-merge
reviewed_at: 2026-05-15T14:30:00+00:00
findings: 0
gates_recorded:
- id: gate_1
name: wp_lane_check
command: spec-kitty agent tasks status --mission <slug> --json
exit_code: 0
result: pass
- id: gate_2
name: dead_code_scan
command: ...
exit_code: 0
result: pass
# ... gate_3, gate_4
issue_matrix_present: true
mission_exception_present: not_applicable
---
Consumers (cross-surface harness #992 Phase 0, dashboards, future tooling) read this frontmatter; never infer the mode from filesystem state.
4. Resuming an interrupted merge (WP04)
If spec-kitty merge fails after assigning mission_number:
spec-kitty merge --resume
Behavior:
- Reads
MergeStatefrom.kittify/merge-state.json. - If
mission_number_baked: truewas persisted, the assignment step is skipped on resume — no empty commit, no foot-gun. - Else, the idempotency check reads
meta.json.mission_numberand only writes if the value changed.
Manual reset (only if state is genuinely corrupt):
spec-kitty merge --abort
This clears the merge state file. Use only when you know the merge cannot continue from where it stopped.
5. Verifying a merged SHA from a detached worktree (WP05)
Common pattern after a PR merges:
cd ~/spec-kitty-verifications
git worktree add /tmp/verify-mission-X main
cd /tmp/verify-mission-X
git checkout <merge-sha>
spec-kitty agent tasks status --mission <slug> --json
After WP05 lands, the status reflects this worktree's events, not the primary checkout's potentially-divergent state. Verification is now trustworthy.
If the command intentionally cannot serve from a detached worktree, it fails loudly with a diagnostic naming the constraint — never silently returns stale state.
6. Running spec-kitty migrate charter-encoding (WP08)
Inspect every mission's charter content for non-UTF-8 encoding:
spec-kitty migrate charter-encoding --dry-run
Output: per-file report (detected encoding, action that would be taken).
Apply normalization interactively:
spec-kitty migrate charter-encoding
# prompts before each file that requires action
For CI:
spec-kitty migrate charter-encoding --yes
# applies without prompting; fails non-zero if any file is genuinely ambiguous
Re-running on an already-normalized corpus is a no-op (NFR-006).
7. Bypassing CHARTER_ENCODING_AMBIGUOUS (WP06 escape hatch)
If the chokepoint fails with CHARTER_ENCODING_AMBIGUOUS on a file you've inspected and accept the risk:
spec-kitty charter compile --unsafe
# or whichever entry path you're invoking
This:
- Uses the highest-confidence decode candidate.
- Records
bypass_used: truein.encoding-provenance.jsonl. - The audit trail captures your override — use it sparingly; the chokepoint exists for a reason.
8. Smoke test for the whole mission
After all WPs land, the eat-our-own-dogfood smoke (NFR-003):
# This mission's own review must satisfy the new contract.
spec-kitty review --mission review-merge-gate-hardening-3-2-x-01KRC57C --mode post-merge
# Required artifacts produced by the mission itself:
ls kitty-specs/review-merge-gate-hardening-3-2-x-01KRC57C/issue-matrix.md
ls kitty-specs/review-merge-gate-hardening-3-2-x-01KRC57C/mission-review-report.md
Both files must exist and pass validation when the mission ships.
9. ERROR_CODES.md location reference
If you encounter a diagnostic code, the human-readable explanation is documented next to the code:
MISSION_REVIEW_*→src/specify_cli/cli/commands/review/ERROR_CODES.mdCHARTER_ENCODING_*→src/charter/ERROR_CODES.md
The StrEnum class docstring in the corresponding _diagnostics.py module names the file path. Drift between the enum and the doc is caught by tests/.../test_diagnostic_codes_documented.py (NFR-008 enforcement).