# Grill Report: Orca v0.8 — Coverage & Trust Hardening

**Date:** 2026-08-04
**Reviewer:** ci-griller (red-team, adversarial)
**Plan under review:** `.ciagent/PLAN_v0.8.md` (commit 4780e4d)
**Branch:** `phase/00-specify` (milestone `milestone/v0.8-coverage-trust-hardening`)
**Mode:** Full autonomy

---

## Methodology

Every material claim in `PLAN_v0.8.md` and `RESEARCH_v0.8.md` was cross-checked
against the actual codebase (verified coverage baselines via `go test -cover`,
read `internal/proxmox/bootstrap.go:75-234`, `internal/security/ca.go`,
`internal/doctor/doctor.go`, `.ciagent/ROADMAP.md`, `.ciagent/REQUIREMENTS.md`,
PERSONAS, ARCHITECTURE) AND the `golang.org/x/crypto` v0.54.0 source for
`knownhosts.New` / `checkAddr` behavior. The TOFU-capture claim was not taken
on faith — the upstream `checkAddr` (knownhosts.go:370-385) was read directly.

Findings are scored on the 9 axes. Binding verdicts are **PROCEED**,
**PROCEED-WITH-CONDITION** (plan proceeds but must incorporate a named change),
or **REPLAN** (axis has a fatal flaw; revise before execution).

---

## Summary Verdict

| Verdict | Count |
|---------|-------|
| PROCEED | 7 |
| PROCEED-WITH-CONDITION | 4 |
| REPLAN | 0 |

**Overall verdict: PROCEED-WITH-CONDITION**

The v0.8 plan is fundamentally sound: scope is right-sized, the no-new-deps
promise holds (verified `ssh.FingerprintSHA256` + `knownhosts.Line` are in the
existing `golang.org/x/crypto` v0.54.0 dep), the tiered coverage floor (D-047)
is realistic per-package with the named seams, and the persona territory
collision on `internal/cli/node.go` is explicitly adjudicated in PERSONAS.md
(backend owns implementation, lead owns `_test.go`). The 4 conditions below are
**targeted correctness fixes**, not scope expansions:

1. **P02 must add a regression test asserting first-connect Proxmox join
   succeeds end-to-end** (the latent TOFU bug means v0.6's first-connect has
   been broken since ship; the fix in T02.6 is correct but must be proven by a
   test that would have failed pre-fix).
2. **P03's verify-reqs regex must match `**COMPLETE**` as a *substring* within
   the bold span** (v0.2's header `**COMPLETE (merged to main via v0.3)**` is
   not matched by the current `\*\*COMPLETE\*\*` literal — a silent blind spot).
3. **P03 must add a second assertion: every REQUIREMENTS row marked `Complete`
   must reference a milestone ROADMAP marks COMPLETE** (the reverse direction).
   The v0.7 `cert_repo_test.go` omission (REQ-053 marked Complete but the test
   file does not exist) proves forward-direction-only checks miss the most
   dangerous drift class: *claimed-Complete-but-actually-incomplete*.
4. **P02 T02.6's TOFU fix must be reviewed against `doctor proxmox`'s callback
   (T02.9) as a paired change, not a follow-on** — they share the exact
   `knownhosts.New` defect; fixing one and not the other in the same phase
   creates an inconsistent trust surface.

With these 4 conditions applied, this plan is ready to execute. No REPLAN.

---

## Per-Axis Findings

### Axis 1 — Business Case

#### A1-F1 — Is v0.8 the right next milestone, or polish-for-polish's-sake?

**Evidence:**
- v0.7 P03 (REQ-055) shipped a ≥50% coverage floor; v0.8 re-baselines six
  packages still under 50% (engine 8.3%, proxmox 5.1%, cli 27.6%, transport
  26.3%, store 47.2%, jobspec 47.6%) — **verified identical via `go test
  -cover`**.
- RESEARCH §2.1 surfaces a **latent v0.6 defect**: `knownhosts.New` returns
  `KeyError{Want:[]}` on first connect and does NOT auto-write. Verified
  directly in `golang.org/x/crypto@v0.54.0/ssh/knownhosts/knownhosts.go:370-385`
  (`checkAddr` returns `&KeyError{}` with empty `Want` when no line matches).
  `bootstrap.go:140-142` treats this as a dial failure. **This means
  first-connect `orca node join --type proxmox` has been broken since v0.6
  shipped** (the v0.6 RESEARCH §A.5 claim that `knownhosts.New` "handles both
  capture and verify" was wrong).
- `bootstrap.go:123` comment is literally false: "on first connect it captures
  the host key" — it does not.

**Confidence:** 0.90 that v0.8 is the right next milestone.
**Verdict:** **PROCEED**. v0.8 is not polish-for-polish: it closes a real
security defect (TOFU broken since v0.6), populates a `Result` field that D-045
*assumed* was already populated (it isn't — `bootstrap.go:195-198`), and lifts
coverage off floors that v0.7 explicitly under-shot. The diminishing-returns
risk is real for the 3 zero-test toe-holds (audit/certpaths/cmd-orca), but
D-047 tiered them to 50% precisely to avoid the rathole — that call is sound.

---

### Axis 2 — Scope and Requirements

#### A2-F1 — Is the TOFU bugfix correctly scoped into P02, or should it be a hotfix on main?

**Evidence:**
- The TOFU capture bug (RESEARCH §2.1, PLAN T02.6) is a v0.6 latent defect,
  not a v0.8 feature. First-connect Proxmox join is broken **today on main**.
- PLAN bundles the fix into P02 (trust hardening phase) alongside REQ-058
  (`--host-key-fingerprint`) and REQ-059 (`key-reset`).
- ROADMAP tags run on the v0.7.x patch line: `v0.7.0` (P0) … `v0.7.4` (P04).
  P02 ships as `v0.7.2` — i.e., the fix lands on a milestone branch, not main,
  and only reaches main at P04 merge (`v0.7.4`).

**Confidence:** 0.62 that bundling into P02 is the right call (low confidence —
this is a judgment call with real downside).
**Verdict:** **PROCEED-WITH-CONDITION.** The fix is correctly designed (T02.6's
`KeyError{Want:[]}` capture-and-persist is the right shape), but the plan must
either (a) document explicitly *why* this isn't hotfixed on main (e.g., "no
operator has hit first-connect yet because all deployments pre-populate
`known_hosts` manually — confirmed by the v0.6 ship audit"), OR (b) flag the
bug in the P04 audit as a v0.6 ship-defect with a post-mortem note. **The plan
currently treats T02.6 as a feature task; it is a bugfix for shipped code and
must be labeled as such** so the P04 audit can distinguish "new hardening" from
"closing a v0.6 gap." Blast radius if T02.6's fix is wrong: every existing
Proxmox node's `known_hosts` could be re-pinned on next join — moderate, but
mitigated by T02.10 case 3/4/5 integration tests.

**Condition:** Add a note to T02.6 in PLAN marking it as a **v0.6 ship-defect
bugfix** (not a v0.8 feature), and ensure P04 audit (T04.2) records it as such.

#### A2-F2 — Are the 3 zero-test packages worth a 50% toe-hold, or scope creep?

**Evidence:**
- `cmd/orca` is 15 LOC of glue (`main()` → `cli.Execute()`). 50% coverage = ~7
  lines. RESEARCH §1.1, §5 pitfall #6 explicitly flags the effort:coverage
  ratio as poor.
- `internal/certpaths` is 64 LOC of pure path-join functions. 50% is trivial.
- `internal/audit` is 125 LOC, 4 exported funcs. 50% is trivial.
- D-047 explicitly tiered these to 50% to avoid a coverage rathole; v0.9 can
  raise the floor.

**Confidence:** 0.85.
**Verdict:** **PROCEED.** The tiered floor is the right call. The
`cmd/orca` toe-hold is low-value but low-cost (one `run() int` refactor + one
smoke test), and dropping it would leave a `covdata` tooling error in CI output
that looks like a broken build to a casual reader. Keeping it at 50% is
defensible.

#### A2-F3 — Scope size: 4 REQs, 37 tasks — too lean, too fat, or right?

**Evidence:**
- 37 tasks, 36 must-haves, 4 phases each shipping a patch. Comparable to v0.7
  (5 phases, similar task density).
- P01 is the heaviest (12 tasks, 9 packages) — the risk concentration is here.

**Confidence:** 0.80.
**Verdict:** **PROCEED.** Right-sized for an NFR milestone. P01 density is the
watch item (see Axis 5).

---

### Axis 3 — Architecture and Technical Feasibility

#### A3-F1 — Do the proxmox `sessionRunner` and engine `peerDispatcher` seams leak test concerns into production?

**Evidence:**
- T01.1 `sessionRunner` (`internal/proxmox/bootstrap.go`): 1 interface,
  ~10 LOC, `CombinedOutput(cmd) ([]byte, error)`. Default impl wraps
  `*ssh.Client.NewSession().CombinedOutput(...)`. Backward compatible —
  existing callers unchanged. This is the **same pattern as the existing
  `sshDialer` seam** (`bootstrap.go:201-213`), which shipped in v0.6 without
  concern. The seam is a standard testability extraction, not a test concern
  leak.
- T01.2 `peerDispatcher` (`internal/engine/dispatcher.go`): **conditional** —
  only added if T01.4 cannot hit 70% via `httptest.NewTLSServer` alone. Plan
  explicitly prefers `httptest.NewTLSServer` (RESEARCH §1.3 gap #2, §5 pitfall
  #8). This is the right ordering: try the stdlib test fixture first, add the
  seam only if needed.

**Confidence:** 0.88.
**Verdict:** **PROCEED.** Both seams are backward-compatible interface
extractions matching an existing pattern (`sshDialer`). No test-concern leak.
The conditional-gate on T01.2 is correctly conservative.

#### A3-F2 — Does P02's trust work stay within the existing security boundary?

**Evidence:**
- P02 touches `internal/proxmox/bootstrap.go` (pinned callback, TOFU fix),
  `internal/cli/node.go` (flag + subcommand), `internal/security/sshkey.go`
  (fingerprint helper), `internal/doctor/doctor.go` (T02.9 TOFU fix). All
  within the existing SSH trust surface established in v0.6.
- No new crypto, no new CA, no new X.509. `ssh.FingerprintSHA256` is in the
  existing `golang.org/x/crypto` v0.54.0 dep (verified: not a new direct dep).
- PERSONAS correctly keeps `security-engineer` deactivated — the work is SSH
  dialer + known_hosts file manipulation, not new security architecture.

**Confidence:** 0.90.
**Verdict:** **PROCEED.** Boundary is respected.

#### A3-F3 — T02.9 (doctor proxmox TOFU fix) is a paired change with T02.6, not a follow-on

**Evidence:**
- `internal/doctor/doctor.go:412` uses the **exact same** `knownhosts.New(...)`
  callback pattern as `bootstrap.go:125`. Both share the latent defect.
- T02.9 is listed as a separate task ("Apply the TOFU capture-fix to `doctor
  proxmox` probe") but is in the same Wave 2 as T02.6. If T02.6 lands and T02.9
  doesn't (e.g., a mid-phase blocker), the trust surface is **inconsistent**:
  join captures, doctor fails.

**Confidence:** 0.75.
**Verdict:** **PROCEED-WITH-CONDITION.** T02.6 and T02.9 must be reviewed as a
paired change in P02 verification — the phase is not done until BOTH callbacks
use the capture-fix wrapper. Add to P02 Verification: "doctor proxmox
first-connect → captures + succeeds (mirrors T02.10 case 3 for bootstrap)."

**Condition:** Add a P02 verification line asserting doctor proxmox
first-connect parity with bootstrap.

---

### Axis 4 — People, Skills, and Organization

#### A4-F1 — Territory collision on `internal/cli/node.go`

**Evidence:**
- PERSONAS.md line 62: lead-developer territory = `internal/cli/**`.
- PERSONAS.md line 70: backend-engineer territory = `internal/cli/node.go`.
- PERSONAS.md line 107 explicitly adjudicates: "backend owns the command
  implementation; lead owns the test files (`node_test.go`)."
- Territory mode is `warn` (not `block`) — collisions log but don't fail.

**Confidence:** 0.82.
**Verdict:** **PROCEED.** The collision is **explicitly adjudicated** in
PERSONAS.md with a clean boundary (impl vs test files). This is the right
answer. The `warn` mode means a backend commit touching `node_test.go` (or a
lead commit touching `node.go` impl) would log — acceptable for a 3-persona
team. No replan.

#### A4-F2 — Key-person dependency: is the 3-persona roster sufficient?

**Evidence:**
- 3 active personas, all retained from v0.7. No phase-specific personas.
- backend-engineer owns 60%+ of P02 (the security-critical phase). If
  backend-engineer is unavailable, P02 stalls entirely.

**Confidence:** 0.70.
**Verdict:** **PROCEED.** Key-person risk is real but inherent to a 3-persona
NFR milestone. The work is not novel (refining existing surface), so the bus
factor is acceptable for hardening. Flagged, not blocking.

---

### Axis 5 — Timeline and Estimates

#### A5-F1 — Is the 70% coverage target for 6 packages in one phase (P01) realistic?

**Evidence:**
- RESEARCH §1.1 + §1.4 per-package achievability assessments:
  - engine → 70% REALISTIC (with LocalExecutor stubs + `openTestDB`).
  - proxmox → 70% REALISTIC **but requires the `sessionRunner` seam (T01.1)** —
    without it, only 50-55% (validation paths + sudoersContent asserts, already
    done).
  - cli → 70% AMBITIOUS (17 files, ~2000 LOC); RESEARCH says "55-65% is more
    realistic for one phase" even with `daemon.go` excluded.
  - transport → 70% REALISTIC (`httptest.NewTLSServer` is standard).
  - store → 70% REALISTIC (cert_repo_test.go gap is the main lift).
  - jobspec → 70% REALISTIC (easiest of the six).
- **`internal/cli` is the swing package.** RESEARCH explicitly says 55-65% is
  the realistic single-phase outcome, not 70%. The plan sets the floor at 70%
  "excluding daemon.go" — but even excluding daemon.go, RESEARCH's own evidence
  says 70% is a stretch.

**Confidence:** 0.65 (split: 5 of 6 packages at 0.85, cli at 0.45).
**Verdict:** **PROCEED-WITH-CONDITION.** The plan must add an explicit fallback
for `internal/cli`: if T01.6 hits ≥65% (excluding daemon.go) but not 70% after
a reasonable effort, the phase ships at 65% with a documented note + a v0.9
follow-up to lift to 70%. **Hard-requiring 70% on cli risks a coverage rathole
that delays the entire milestone** (P02/P03 are gated on P01 ship). The other 5
packages at 70% is realistic.

**Condition:** Add to T01.6 acceptance criterion: "If ≥65% (excluding
daemon.go) is achieved but 70% is not after Wave 2 effort, document the gap in
the task comment + record a v0.9 follow-up; ship at 65%. Do NOT block P02/P03
on the last 5% of cli coverage." (This mirrors RESEARCH §1.4's own flag, which
the plan currently does not carry forward as an escape valve.)

---

### Axis 6 — Budget and Financial Realism

#### A6-F1 — Zero new deps: is that realistic given P02's needs?

**Evidence:**
- `ssh.FingerprintSHA256`: verified in `golang.org/x/crypto/ssh` (direct dep
  since v0.6 D-030).
- `knownhosts.Line` / `Normalize` / `KeyError`: same `golang.org/x/crypto`
  module (already imported in `bootstrap.go:32` and `doctor.go:29`).
- `verify-reqs`: stdlib only (`regexp`, `os`, `fmt`).
- `go.mod` unchanged by v0.8 (PLAN line 62).

**Confidence:** 0.95.
**Verdict:** **PROCEED.** Zero-new-deps is verified and realistic.

---

### Axis 7 — Risks, Assumptions, and Dependencies

#### A7-F1 — The 10 pitfalls: are mitigations real or hand-waves?

**Evidence (spot-check of the 4 most material pitfalls):**
- **Pitfall #1 (TOFU broken):** Mitigation T02.6 is **concrete and correct** —
  wrap `knownhosts.New`, capture on `KeyError{Want:[]}` via `knownhosts.Line` +
  `security.WriteAtomic`, return nil. Verified against x/crypto v0.54.0
  `checkAddr` semantics. **Real mitigation.**
- **Pitfall #2 (Result.HostKeyFingerprint never populated):** T02.7 adds
  `ssh.FingerprintSHA256(hostKey)`. 1-line once host key is available. **Real.**
- **Pitfall #3 (no sessionRunner seam):** T01.1 adds it, ~10 LOC. **Real.**
- **Pitfall #10 (writeAtomic unexported):** T02.2 exports it. Verified
  `ca.go:305` — `func writeAtomic(...)` is indeed unexported. **Real.**

**Confidence:** 0.88.
**Verdict:** **PROCEED.** Mitigations are concrete, not hand-waves.

#### A7-F2 — TOFI bugfix blast radius if P02's fix is wrong

**Evidence:**
- T02.6 changes the `HostKeyCallback` for every `orca node join --type proxmox`
  + every `doctor proxmox` probe. If the capture-and-persist logic is wrong,
  every existing Proxmox node's `known_hosts` could be corrupted (e.g.,
  duplicate entries, wrong-format lines, partial writes on crash).
- Mitigations: T02.10 integration tests (cases 3/4/5 cover first-connect,
  second-connect, mismatch); AD-029 atomic rewrite via `security.WriteAtomic`.
- **Gap:** no test for "known_hosts already has an entry, join re-connects" —
  i.e., the idempotent re-run path after the fix. T02.10 case 4 covers
  second-connect-match, but not "known_hosts was written by the OLD (broken)
  code path and is now being read by the NEW code path."

**Confidence:** 0.70.
**Verdict:** **PROCEED-WITH-CONDITION.** T02.10 must add a case for
"known_hosts pre-populated in the expected format (e.g., from a manual
`ssh-keyscan` or a prior v0.6 deployment that somehow succeeded) →
second-connect matches + succeeds." This covers the migration path from
v0.6's (broken) state to v0.8's fixed state.

**Condition:** Add T02.10 case 7: "known_hosts pre-populated with a valid
OpenSSH line for the host → connect matches + succeeds (covers v0.6→v0.8
migration)."

---

### Axis 8 — Governance, Decision-Making, and Communication

#### A8-F1 — Does `make verify-reqs` actually prevent drift, or is it cosmetic?

**Evidence:**
- T03.1 regex (PLAN line 216):
  - ROADMAP milestone-complete: `^##\s*Milestone\s+v0\.\d+:.*—\s*\*\*COMPLETE\*\*`
  - REQUIREMENTS row: `^\|\s*(REQ-\d+)\s*\|.*?\|\s*\*\*(Complete|Pending)\*\*\s*\|`
- **ROADMAP v0.2 header (line 23):** `## Milestone v0.2: Networking,
  Observability, Security Hardening — **COMPLETE (merged to main via v0.3)**`
- The regex `\*\*COMPLETE\*\*` requires the literal `**COMPLETE**` with closing
  `**` immediately after `COMPLETE`. v0.2's header has `**COMPLETE (merged to
  main via v0.3)**` — the `**` closes after the parenthetical, NOT after
  `COMPLETE`. **The regex does NOT match v0.2 as complete.**
- **Consequence:** all v0.2 REQs (REQ-011, 014, 023, 025-040) are **silently
  exempted** from the check. A stale v0.2 REQ-035 row (marked Pending) would
  NOT fail the gate.
- **ROADMAP v0.6 has TWO headers** (line 92 without COMPLETE, line 94 with) —
  the regex matches line 94, but the duplicate is a markdown smell that could
  confuse the milestone→REQ mapping if the parser takes the first match.

**Confidence:** 0.92 (high — the regex mismatch is verifiable).
**Verdict:** **PROCEED-WITH-CONDITION.** The regex must match `**COMPLETE**`
as a *substring within the bold span*, not as a literal `**COMPLETE**` token.
Change to `—\s*\*\*[^*]*COMPLETE[^*]*\*\*` (matches `**COMPLETE**`,
`**COMPLETE (merged to main via v0.3)**`, and any future variant). Add a
golden-file test case (T03.2) with the v0.2-style parenthetical header to
prevent regression.

**Condition:** T03.1 regex changed to substring-match COMPLETE within the bold
span; T03.2 adds a golden fixture with `**COMPLETE (merged to main via v0.3)**`.

#### A8-F2 — Is the single-direction check (ROADMAP→REQUIREMENTS) enough?

**Evidence:**
- PLAN line 35-37 explicitly scopes out the reverse direction: "forward
  direction (ROADMAP-shipped → REQUIREMENTS Complete) is the priority per the
  v0.7 drift that motivated REQ-060."
- **But the v0.7 drift had TWO symptoms:**
  1. ROADMAP said COMPLETE, REQUIREMENTS said Pending (forward drift — caught
     by the current check).
  2. **REQ-053 was marked Complete in REQUIREMENTS, but
     `internal/store/cert_repo_test.go` was never written** — verified: only
     `cert_repo.go` exists in `internal/store/`. The "Complete" status was
     false. **No markdown-based check can catch this** (it's a code-vs-doc
     drift, not a doc-vs-doc drift).
- The reverse-direction check (REQUIREMENTS Complete ↔ ROADMAP COMPLETE) would
  catch a different class: a REQ marked Complete in REQUIREMENTS for a
  milestone ROADMAP does NOT mark COMPLETE (e.g., premature marking). This is
  a cheaper class of drift but still real.

**Confidence:** 0.78.
**Verdict:** **PROCEED-WITH-CONDITION.** Add the reverse-direction assertion
to T03.1 (it's ~10 LOC on top of the existing parser — same maps, just diff
both ways). Document explicitly that **no markdown check can catch the
code-vs-doc drift** (REQ-053 case) — that requires a code-level audit
(`ciagent-audit` in P04). The plan should note this as a known limitation of
REQ-060, not pretend the gate is complete.

**Condition:** T03.1 adds reverse-direction assertion; PLAN adds a note that
REQ-060 catches doc-vs-doc drift only, not code-vs-doc (the REQ-053
cert_repo_test.go case).

#### A8-F3 — Is there a "stop the project" trigger?

**Evidence:** P04 (T04.1-T04.9) is the final review + ship. No explicit
"stop" trigger if P01 coverage stalls or P02 TOFU fix proves unfixable.

**Confidence:** 0.60.
**Verdict:** **PROCEED.** The 4-phase structure with per-phase tags means a
stall is visible (phase tag doesn't ship). Acceptable for an NFR milestone.

---

### Axis 9 — Change, Adoption, and Operational Readiness

#### A9-F1 — Who benefits from v0.8? Is there operator pull for `--host-key-fingerprint`?

**Evidence:**
- `--host-key-fingerprint` (REQ-058) is operator-facing: pre-pinning a
  Proxmox host's SSH key before first join. This is the standard
  high-security-deployment pattern (the v0.6 D-035 caveat explicitly promised
  it as a "future enhancement").
- `orca node key-reset` (REQ-059) is operator-facing: the `ssh-keygen -R`
  equivalent for orca's known_hosts.
- The TOFU bugfix (T02.6) benefits **every operator who has tried
  first-connect Proxmox join since v0.6** — i.e., it fixes a feature that was
  advertised as working but wasn't.
- Coverage uplift (REQ-057) is developer-facing (no operator pull).
- verify-reqs (REQ-060) is internal-governance (no operator pull).

**Confidence:** 0.82.
**Verdict:** **PROCEED.** The trust features have real operator pull
(pre-pinning is a documented security best practice; the v0.6 caveat promised
it). The coverage + hygiene work is internal-debt paydown — justified by the
v0.7 under-shot, not by operator demand. The mix is appropriate for an NFR
milestone.

#### A9-F2 — Rollback plan if P02's trust changes go wrong

**Evidence:**
- P02 changes `HostKeyCallback` for all Proxmox joins + doctor probes. If the
  capture-fix corrupts `known_hosts`, the rollback is: revert the phase commit
  + manually restore `known_hosts` from backup.
- No data migration in P02 (known_hosts is a flat file; atomic rewrite via
  `WriteAtomic` preserves crash safety).
- `key-reset` (T02.8) is local-only (D-046) — no remote side effects to
  reverse.

**Confidence:** 0.80.
**Verdict:** **PROCEED.** Rollback is straightforward (revert + file restore).
The atomic-rewrite requirement (AD-029) is the right mitigation.

---

## Binding Verdicts Table

| # | Axis | Finding | Verdict | Condition | Confidence |
|---|------|---------|---------|-----------|------------|
| A2-F1 | Scope | TOFU bugfix is a v0.6 ship-defect bundled into P02 as a feature task | PROCEED-WITH-CONDITION | Label T02.6 as a v0.6 bugfix in PLAN; P04 audit records it as a ship-defect closure | 0.62 |
| A2-F2 | Scope | 3 zero-test packages at 50% toe-hold | PROCEED | — | 0.85 |
| A2-F3 | Scope | 37 tasks / 4 phases size | PROCEED | — | 0.80 |
| A1-F1 | Business | v0.8 is the right next milestone (not polish) | PROCEED | — | 0.90 |
| A3-F1 | Architecture | sessionRunner + peerDispatcher seams do not leak test concerns | PROCEED | — | 0.88 |
| A3-F2 | Architecture | P02 stays within existing security boundary | PROCEED | — | 0.90 |
| A3-F3 | Architecture | T02.6 + T02.9 are paired changes (bootstrap + doctor share the defect) | PROCEED-WITH-CONDITION | Add P02 verification line for doctor proxmox first-connect parity with bootstrap | 0.75 |
| A4-F1 | People | internal/cli/node.go territory collision adjudicated | PROCEED | — | 0.82 |
| A4-F2 | People | Key-person risk on backend-engineer in P02 | PROCEED | — | 0.70 |
| A5-F1 | Timeline | 70% cli coverage in one phase is a stretch (RESEARCH says 55-65%) | PROCEED-WITH-CONDITION | Add escape valve: ship cli at 65% if 70% not reached after Wave 2; do not block P02/P03 | 0.65 |
| A6-F1 | Budget | Zero new deps verified | PROCEED | — | 0.95 |
| A7-F1 | Risks | 10 pitfalls mitigations are concrete | PROCEED | — | 0.88 |
| A7-F2 | Risks | TOFU fix blast radius — no migration-path test | PROCEED-WITH-CONDITION | Add T02.10 case 7: known_hosts pre-populated → second-connect matches (v0.6→v0.8 migration) | 0.70 |
| A8-F1 | Governance | verify-reqs regex does not match v0.2's `**COMPLETE (merged...)**` header | PROCEED-WITH-CONDITION | Change regex to substring-match COMPLETE within bold span; add golden fixture | 0.92 |
| A8-F2 | Governance | Single-direction check misses reverse drift + code-vs-doc drift (REQ-053 case) | PROCEED-WITH-CONDITION | Add reverse-direction assertion; document that code-vs-doc drift is out of scope for REQ-060 | 0.78 |
| A8-F3 | Governance | No explicit "stop" trigger | PROCEED | — | 0.60 |
| A9-F1 | Adoption | Operator pull exists for trust features; coverage/hygiene is internal debt | PROCEED | — | 0.82 |
| A9-F2 | Adoption | Rollback plan is straightforward (revert + file restore) | PROCEED | — | 0.80 |

---

## Required Plan Changes (4 conditions)

1. **T02.6 labeling (A2-F1):** Add a note to T02.6 in `PLAN_v0.8.md` marking
   it as a **v0.6 ship-defect bugfix** (first-connect Proxmox join has been
   broken since v0.6 shipped due to `knownhosts.New` returning
   `KeyError{Want:[]}` with no capture-and-persist). P04 audit (T04.2) must
   record it as a ship-defect closure, not a v0.8 feature.

2. **P02 verification parity for doctor (A3-F3):** Add to Phase 2 Verification:
   "`doctor proxmox` first-connect on a node with empty known_hosts → captures
   the key + writes known_hosts + probe succeeds (mirrors T02.10 case 3 for
   bootstrap). T02.6 and T02.9 are a paired change; the phase is not complete
   until both callbacks use the capture-fix wrapper."

3. **T01.6 cli coverage escape valve (A5-F1):** Add to T01.6 acceptance
   criterion: "If ≥65% (excluding `daemon.go`) is achieved but 70% is not after
   Wave 2 effort, document the gap in a test-file comment + record a v0.9
   follow-up; ship P01 at 65% for cli. Do NOT block P02/P03 on the last 5% of
   cli coverage." (Carries forward RESEARCH §1.4's own flag as an explicit
   escape valve.)

4. **verify-reqs regex + reverse direction (A8-F1 + A8-F2):**
   - Change T03.1 ROADMAP-complete regex from
     `^##\s*Milestone\s+v0\.\d+:.*—\s*\*\*COMPLETE\*\*` to
     `^##\s*Milestone\s+v0\.\d+:.*—\s*\*\*[^*]*COMPLETE[^*]*\*\*` (substring
     match within the bold span — handles `**COMPLETE**`,
     `**COMPLETE (merged to main via v0.3)**`, and future variants).
   - Add T03.2 golden fixture: a ROADMAP with
     `**COMPLETE (merged to main via v0.3)**` → assert the milestone is
     detected as complete.
   - Add reverse-direction assertion to T03.1: every REQUIREMENTS row marked
     `**Complete**` must reference a milestone ROADMAP marks COMPLETE (catches
     premature-Complete drift).
   - Add a PLAN note: "REQ-060 catches doc-vs-doc drift only. Code-vs-doc
     drift (e.g., REQ-053 marked Complete but `cert_repo_test.go` missing —
     verified missing in v0.7 ship) is NOT caught by this gate; it requires
     the P04 `ciagent-audit` code-level review."

Additionally (lower-priority, from A7-F2):

5. **T02.10 case 7 (A7-F2):** Add integration test case: "known_hosts
   pre-populated with a valid OpenSSH line for the host (simulating a v0.6
   deployment or manual `ssh-keyscan`) → connect matches + succeeds. Covers
   the v0.6→v0.8 migration path."

---

## Escalations

None. All 9 axes resolved at confidence ≥ 0.60. No axis requires escalation to
the operator; the 4 conditions are within the plan-author's authority to apply
before P01 execution begins.

---

## What the Plan Is NOT Doing (and should it?)

- **Not lifting the 3 zero-test packages to 70%.** Correct per D-047 — deferred
  to v0.9. Not a gap.
- **Not adding a `peerDispatcher` seam unless needed.** Correct — conditional
  on T01.4's 70% via `httptest.NewTLSServer`. Not a gap.
- **Not pre-populating `known_hosts` from a remote keyscan API.** Correct —
  TOFU + manual `--host-key-fingerprint` cover the v0.8 surface. Not a gap.
- **Not catching code-vs-doc drift in verify-reqs.** **Known limitation** —
  REQ-060 is a markdown-vs-markdown check. The REQ-053
  `cert_repo_test.go`-missing case proves this class of drift is real. P04
  `ciagent-audit` is the backstop. Documented in condition #4.

---

## Simplest 80%-of-the-value version

If forced to cut v0.8 to its smallest valuable form: **keep P02 (trust
hardening + TOFU bugfix) and P03 (verify-reqs); drop P01's coverage uplift for
the 3 zero-test packages + cli.** The TOFU bugfix alone (T02.6 + T02.9) fixes a
shipped security defect — that's the highest-value work. The verify-reqs gate
prevents the v0.7 drift from recurring. The coverage uplift on the 6
under-50% packages is valuable but not urgent; the 3 zero-test toe-holds are
the lowest-value work in the milestone. **The plan as written does not over-
scope** — it includes all of the above because the marginal cost is low — but
if P01 slips, the 3 toe-holds + cli are the first cuts to make.

---

## What Would Have to Be True for v0.8 to Succeed in the Next 90 Days

1. The `sessionRunner` seam (T01.1) unlocks proxmox 70% — **plausible** (same
   pattern as the existing `sshDialer` seam).
2. `httptest.NewTLSServer` suffices for transport 70% without a new seam —
   **plausible** (standard Go testing fixture).
3. The TOFU capture-fix (T02.6) is correct — **plausible** (verified against
   x/crypto v0.54.0 semantics; integration tests T02.10 cover the cases).
4. `verify-reqs` regex matches all ROADMAP milestone header variants — **NOT
   true today** (v0.2 header mismatch — condition #4 fixes this).
5. cli hits 70% in one phase — **NOT confirmed** (RESEARCH says 55-65%;
   condition #3 adds the escape valve).

(4) and (5) are the two conditions that move the plan from "optimistic" to
"sound." Both are addressed by the 4 required changes.

---

**End of grill report.** Apply the 4 conditions to `PLAN_v0.8.md` before P01
execution. No REPLAN; no escalations. Overall verdict: **PROCEED-WITH-
CONDITION** (confidence 0.78).