Skip to content

fix(ooda,overseer): terminal-quarantine breaker churn + single-open auto-doc PR reconciliation (Problems #1/#5) - #4964

Merged
rysweet merged 6 commits into
mainfrom
review/ooda-churn-autodoc-step17b-1785249692
Jul 28, 2026
Merged

fix(ooda,overseer): terminal-quarantine breaker churn + single-open auto-doc PR reconciliation (Problems #1/#5)#4964
rysweet merged 6 commits into
mainfrom
review/ooda-churn-autodoc-step17b-1785249692

Conversation

@rysweet

@rysweet rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Summary

Additive, non-breaking implementation of the two churn fixes from the Step 2c requirements:

  • Problem Implement the first high-quality version of Simard in /home/azureuser/src/Simard based on the completed spec reviews. This is a development task and must use default-workflow. Required outcomes: (1) u #1 — OODA breaker churn (HIGH). Adds a terminal quarantine rung to the no-progress breaker. Once an evidence-less UNCLEAR-CRITERIA / GENUINELY-STUCK goal exhausts its bounded re-investigation budget (SURFACED_INVESTIGATION_FAILURE_LIMIT), the breaker returns the new NoProgressResolution::QuarantineTerminal, blocks the goal with the surfaced count as real evidence (never evidence=[(none)]), files exactly one deduplicated tracking issue, and writes a durable, injection-safe quarantine_marker (WipRef). reinvestigate_bare_blocked_goals short-circuits quarantined goals before consulting the reasoner, ending the re-schedule/re-file storm. Also stabilizes the recurring_goal_reblock stewardship signature via fold_volatile_goal_ids (folds simard-identity-<slug> and positional goal-<n> to stable placeholders).
  • Problem identity-and-bootstrap-refactor #5 — Stale auto-doc PR churn (LOW). New overseer::doc_pr_reconcile module enforcing a single-open invariant for auto-generated "Update documentation with …" PRs: a pure decision core (reconcile_doc_prs) + a fail-closed, bounded IO executor (run_doc_pr_reconcile) that closes superseded / stale-CONFLICTING drafts via the additive PrGhClient::close_pr. Gated behind the governed roster, the shared gap-scan opt-out, and an every-N cadence.

Validation

  • cargo check --tests — clean (exit 0).
  • New targeted tests green: quarantine (36), doc-PR reconcile (15), reblock signature (8).

Notes

This PR is opened to host the mandatory Step 17b comprehensive code review. See the review comments for findings (one HIGH-severity correctness issue on the Problem #5 identity gate).

Out of scope (merge escalations only): #4939, #4941, #4926.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Automatic checkpoint to preserve work in progress.
Tests and implementation saved before refactoring phase.

@rysweet rysweet left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 17b — Comprehensive Code Review

Scope reviewed: implementation commit f78c26cc0 (Problems #1 & #5). 23 files, +3169/−109. Docs + tests + source.

Verification run during review:

  • cargo check --tests → clean (exit 0).
  • Targeted tests all green: quarantine churn (36), doc_pr_reconcile (15), reblock signature (8).

Overall this is high-quality, well-documented, philosophy-aligned work: pure/IO separation, fail-closed gating, injection-safe durable markers, no print!/println!, no Bridge naming, additive/non-breaking. One HIGH-severity correctness bug makes Problem #5 inert in production, plus a few medium/minor items below.


🔴 HIGH — Problem #5 identity gate pins the WRONG author ⇒ reconciliation is a silent no-op in production

src/overseer/doc_pr_reconcile.rs:35 sets AUTO_DOC_PR_AUTHOR = DEFAULT_OVERSEER_AUTHOR_LOGIN ("simard-overseer[bot]"), and is_auto_doc_pr (line 104) requires pr.author == AUTO_DOC_PR_AUTHOR.

But the real "Update documentation with …" PRs are not authored by the overseer bot. Verified live against this repo:

  • PR #4826 / #4824author.login = "rysweet", isDraft = true, label simard-autonomous.

The codebase’s own config invariant confirms this is the wrong identity: src/overseer/config.rs:510-516 documents that the engineer/goal-advance author (SIMARD_AUTOMERGE_AUTHOR) is DISTINCT from OVERSEER_AUTHOR_LOGIN (the overseer-bot recursion identity) — different logins by design. The auto-doc PRs carry SIMARD_ENGINEER_PR_LABEL (simard-autonomous), which config.rs:574 says is "stamped on EVERY engineer / goal-advance PR" — i.e. they are engineer-authored, never overseer-bot-authored.

Impact: is_auto_doc_pr returns false for every real auto-doc PR, so run_doc_pr_reconcile finds zero candidates and closes nothing. Problem #5 does not actually fix the stale-PR churn in production.

Why tests don’t catch it (test-masks-bug): tests_doc_pr_reconcile.rs:50 builds its auto-doc fixture with author: AUTO_DOC_PR_AUTHOR.to_string() — the fixture is bound to the same constant under test, so no test ever exercises the real-world author. The 15 green tests are internally consistent but validate nothing about the production identity.

Recommended fix (pick one):

  1. Resolve the author from the configured engineer identity — reuse config::automerge_author() (env SIMARD_AUTOMERGE_AUTHOR) rather than hardcoding the overseer-bot default; when unset, fall back to the composite title-marker + simard-autonomous label + draft gate, which already fail-closes against human PRs (a human PR won’t carry simard-autonomous).
  2. Or drop the author-equality clause entirely and rely on title marker + SIMARD_ENGINEER_PR_LABEL + is_draft==Some(true). The label alone is the codebase’s own "this is Simard’s own PR" signal, so it is both correct and sufficient; the current author pin is redundant and actively breaks the gate.

🟠 MEDIUM — Inert-gate failure is silent (no LOUD signal)

Because the pass fail-closes to "0 candidates" and only emits tracing::info! with candidates=0, an identity-gate mismatch (the HIGH finding) produces no warning — exactly why this shipped unnoticed. Per TRUST/zero-BS, a mismatch should be LOUD. Recommend: if open_prs contains ≥1 PR whose title starts with AUTO_DOC_PR_TITLE_MARKER but zero pass is_auto_doc_pr, emit a tracing::warn! ("N title-marker PRs present but none passed the identity gate — reconciliation inert, check author/label config") and add a test asserting that warn path. This turns a silent no-op into an observable defect.

🟠 MEDIUM (verify) — fold_volatile_goal_ids shapes must match real dedup keys

fold_volatile_goal_ids (observer.rs:213) only folds two shapes: simard-identity-<slug> and positional goal-<n>. The dedup relies on the actual production Problem.dedup_key embedding exactly one of these. Tests assert against hand-written shapes ("recurring_goal_reblock simard-identity-…", "…goal-12") rather than a captured real key. Please confirm against a real recurring_goal_reblock dedup_key that the volatile portion matches one of the two folded forms; if the real key embeds the goal id in any other shape (e.g. a UUID, goal_id=<x>, or a ::-joined signature), the fold silently no-ops and dedup does not happen. Add one test built from a captured production key to pin this.

🟡 LOW — Quarantine bound is off-by-one vs. the prior escalate timing

resolution_for_why (no_progress_breaker.rs:657) checks the pre-bump surfaced_failures >= LIMIT, while the SurfaceInvestigationFailure arm bumps the counter afterward. Net effect with LIMIT=3: the goal surfaces 3 times, then quarantines on the 4th terminal pass — whereas the old inline branch escalated on the 3rd. One extra surfaced cycle before terminal action. Likely intentional (and surfaced_count renders as exactly LIMIT), but the docstring says "once the surfaced-failure bound is reached," which reads as fire-at-3. Please either adjust to fire when surfaced_failures + 1 >= LIMIT or tighten the docstring to state the pre-bump semantics, and add a test that pins the exact cycle count at which quarantine fires.

🟡 LOW (style) — let _ = class;

no_progress.rs:1335: the SurfaceInvestigationFailure { class, reason } arm now discards class via let _ = class;. Prefer binding it out in the pattern (SurfaceInvestigationFailure { class: _, reason }) so the discard is expressed at the match site rather than as a statement.

🟡 LOW — close_pr default no-op can hide a mis-wired client

merge_authority.rs: PrGhClient::close_pr defaults to Ok(()) (no-op). The rationale (hygiene, not a correctness gate) is sound and documented, but combined with the HIGH finding it means a client that silently can’t close leaves duplicates open with no signal. The MEDIUM telemetry suggestion above also covers this. No change strictly required.


✅ Strengths (Problem #1)

  • QuarantineTerminal correctly classified terminal by is_terminal(); the quarantined-goal short-circuit in reinvestigate_bare_blocked_goals runs before the reasoner, and the churn test proves it via a PanicReasoner.
  • Injection-safe marker: fixed compile-time ref_id sentinel + kind, never goal-derived; is_quarantine_ref keys on both. Idempotent push (!is_quarantined(g) guard) prevents marker accretion.
  • Never authors a bare evidence=[(none)] block — the surfaced count is rendered as real evidence.

Checklist

  • Code quality and standards — strong; no print!/println!, no Bridge naming.
  • Test coverage — broad and green, but the Problem #5 tests mask the HIGH author bug (fixtures bound to the constant under test).
  • No TODOs, stubs, or swallowed exceptions — none found; per-close errors are collected and logged, not swallowed.
  • No unimplemented functions — none.
  • Logic correctness — HIGH bug: Problem #5 gate is inert in production.
  • Edge-case handling — fail-closed on empty author, is_draft None, list errors, zero/one candidate; bounded closes; canonical never closed.

Verdict: REQUEST CHANGES — fix the HIGH author-gate bug (and add the LOUD-inert telemetry + a real-key reblock test) before merge. Everything else is minor.

Comment thread src/overseer/doc_pr_reconcile.rs Outdated
Comment thread src/overseer/doc_pr_reconcile.rs Outdated
Comment thread src/goal_curation/no_progress_breaker.rs

@rysweet rysweet left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 17c — Security Review (MANDATORY)

Scope: implementation commit f78c26cc0 (Problems #1 & #5). Source files only (docs excluded). Read-only analysis performed via the security-review specialist.

Security checklist

  • Verify all security requirements met — met
  • Check for any new vulnerabilities — none found
  • Confirm sensitive data handling — no secrets logged/exposed
  • Review authentication/authorization — fail-closed identity gate, no priv-esc
  • Check for injection vulnerabilities — none (argv-only gh exec, no shell)

Findings by category

1. Injection / untrusted-input (doc_pr_reconcile.rs) — ✅ CLEAN.
The only mutating command is RealPrGhClient::close_pr (merge_authority.rs:507-514) → run_gh_checked (:337-354), which uses std::process::Command::new("gh").args(args) — positional argv, no shell. The format!("gh pr close …") at :509 is a log label only, not executed. Attacker-influenceable strings (PR title, labels, branch names) are never interpolated into any command, path, or shell. The close comment (doc_pr_reconcile.rs:136-147) interpolates only the canonical PR number (u32). The close set is computed purely from structured OpenPrSummary fields and executed by pr.number (:197), so a crafted title/label cannot redirect a close to the wrong PR.

2. Authorization / identity confusion — ✅ CLEAN.
is_auto_doc_pr (doc_pr_reconcile.rs:101-107) is a fail-closed AND of four signals: title prefix + author == "simard-overseer[bot]" + is_draft == Some(true) + label "simard-autonomous". An external attacker cannot spoof author.login (GitHub-authoritative) nor apply the simard-autonomous label without repo triage/write. Empty/absent author fails closed (:103). A human/attacker PR can never become a candidate, be closed, or be selected as canonical. merge_authority.rs only adds fields + close_pr; no privilege boundary crossed.

3. Destructive-action safety — ✅ CLEAN.
Canonical = candidates…map(number).max() (:119), explicitly excluded from the close set (:128). 0/1 candidates ⇒ zero closes. Deterministic; provably cannot close all candidates nor a non-candidate (human) PR. Bounded: MAX_CLOSES_PER_CYCLE = 25 (:49), DOC_PR_LIST_LIMIT = 200 (:44). Triple runtime gate (overseer/mod.rs:1016, :709-745): wired gh client + gap_scan_enabled + non-empty roster + every-N cadence; disabled by default (None, :577). Per-repo list failure fails closed (no closes); per-close failure is contained.

4. Quarantine-marker integrity (no_progress_breaker.rs/no_progress.rs) — ✅ CLEAN.
Marker key is a fixed compile-time sentinel: NO_PROGRESS_QUARANTINE_MARKER_KIND/_REF_ID (no_progress_breaker.rs:346,354). quarantine_marker() (:361-368) never derives kind/ref_id from goal text; is_quarantine_ref (:377-380) matches BOTH fixed constants. Goal text/evidence/why-strings cannot forge or collide a marker. wip_refs is populated only by internal code + local board JSON, never attacker-crafted issue/PR bodies. Neither denial-of-progress nor quarantine evasion is reachable. Marker write is idempotent (no_progress.rs:1400-1408, guarded by !is_quarantined(g)) — no unbounded accretion.

5. Command execution / secrets / unsafe — ✅ CLEAN.
No unsafe blocks, no sh -c, only the one argv-based gh pr close. No new network calls beyond gh (self-authenticating). No tokens/PR bodies/credentials logged — tracing emits only repo, PR numbers, counts, reasons, error strings.

6. DoS / resource — ✅ bounded. 200-PR list window, 25 closes/cycle, idempotent single marker.

⚠️ Security-adjacent guidance (forward-looking, not a defect)

The known functional gap (author gate on simard-overseer[bot] may match zero real auto-doc PRs) is currently fail-safe: it can only cause under-action (nothing closed), never wrongful closes. Security caveat for the fix: do NOT remediate by loosening the gate to title-marker + label only. Dropping the exact-author conjunct (doc_pr_reconcile.rs:104) would collapse safety onto the simard-autonomous label alone — anyone with repo triage/write could then apply that label to a crafted draft PR titled "Update documentation with…" and get arbitrary PRs auto-closed. Keep the author-identity check as a mandatory conjunct in any future relaxation (resolve the correct author via config::automerge_author() rather than removing the check).

Security verdict: ✅ PASS

No exploitable security issues found across all six categories: no injection (argv-only exec), no spoofable-identity path (fail-closed 4-signal gate), no destructive logic error (canonical=max, bounded batch, triple gate + fail-closed reads), no marker forgery/collision (fixed sentinels), no secret exposure, no unsafe.

Comment thread src/overseer/doc_pr_reconcile.rs Outdated
@rysweet

rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

🟢 SECURITY (injection) — supplementary evidence: merge_authority.rs RealPrGhClient::close_pr (:507) executes via run_gh_checked (:337) using std::process::Command::new("gh").args(args) — positional-argv exec, no shell. Attacker-influenceable PR titles/labels/branch names are never interpolated into a command; the format!("gh pr close …") at :509 is a log label only. No sh -c, no string-built commands in this change. Confirms the ✅ PASS injection verdict.

@rysweet rysweet left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 17b — Comprehensive Code Review

Reviewed all 23 files on review/ooda-churn-autodoc-step17b-1785249692 (base main, +3169/-109). Findings verified against the live repo state via gh pr list, not just the diff.

Verdict: Request changes. Problem #1 (terminal quarantine) is solid and well-tested. Problem #5 (auto-doc PR reconciliation), as written, will not act on any real PR — the identity gate's author constant does not match the actual author of the live auto-doc PRs, and the test suite masks this by hardcoding the expected author.


🔴 HIGH — Problem #5 identity gate is inert against production data

is_auto_doc_pr (src/overseer/doc_pr_reconcile.rs) requires:

pr.author == AUTO_DOC_PR_AUTHOR   // = DEFAULT_OVERSEER_AUTHOR_LOGIN = "simard-overseer[bot]"

But every live auto-doc PR is authored by rysweet, not the bot. Verified:

$ gh pr list --search "Update documentation with in:title" --json number,author,isDraft,labels,mergeable
4826 author=rysweet draft=True  mergeable=MERGEABLE   labels=[simard-autonomous]
4784 author=rysweet draft=True  mergeable=CONFLICTING labels=[simard-autonomous]
4612 author=rysweet draft=True  mergeable=CONFLICTING labels=[]
4528 author=rysweet draft=False mergeable=CONFLICTING labels=[]
...  (19 candidates total, all author=rysweet)

Consequences of the 4-way AND gate against this real data:

  • Author conjunct fails for all 19reconcile_doc_prs finds zero candidates → selects no canonical → closes nothing. The single-open invariant is never enforced in production; Problem #5 is a no-op.
  • Even if author matched: many historical drafts carry no simard-autonomous label (#4612, #4567, #4528, #4490, …) and some are is_draft=false (#4528, #4457). The gate would still exclude exactly the accumulated backlog the module docstring claims to "drain over several cycles."

The PR summary under-states this as "one HIGH-severity correctness issue on the identity gate." Against live data it means the feature does nothing.

Fix options:

  1. Match pr.author against the identity that actually opens these PRs (whatever overseer_author_login() / the publish PAT resolves to — here rysweet), not a hard-coded bot login.
  2. Relax the label conjunct to a non-gating signal (title-marker + author + draft is already a strong positive ID; treat missing label as still-a-candidate), or key on the auto-doc branch pattern.
  3. Add a fixture built from a real gh pr list row (author rysweet, no label) so the suite fails-closed against production shapes.

🔴 HIGH (tied) — Test blind spot hides the above

tests_doc_pr_reconcile.rs::auto_doc_pr fabricates candidates with author: AUTO_DOC_PR_AUTHOR and labels: vec![AUTO_DOC_PR_LABEL]. The suite is green precisely because it never exercises the production author/label combination. All 15 doc-PR tests pass while the feature matches nothing live. Add a production-shaped fixture (see fix #3 above).


🟡 MEDIUM — Off-by-one shift in the quarantine trigger

Old code escalated when the post-bump surfaced count reached SURFACED_INVESTIGATION_FAILURE_LIMIT (3) — i.e. on the 3rd surfaced failure. New code routes on the pre-bump count (tracker.surfaced_failures(goal_id) read before the surface arm calls record_surfaced_failure), so QuarantineTerminal fires only once the stored count is already ≥3 — i.e. on the 4th surfaced failure. Net: one extra surface → re-block → (dedup-suppressed) cycle before terminal quarantine.

Not a correctness bug (the suppression marker prevents a duplicate issue on the extra cycle), but it moves the terminal trigger by one cycle and slightly weakens the churn-reduction intent. The docstring's "byte-for-byte unchanged below the bound" is true for the surface arm but not for the trigger point. Either route on surfaced_failures + 1 >= LIMIT to preserve the original point, or document the shift.

🟢 LOW — reblock fold coverage is intentionally narrow (confirm against live signature)

fold_volatile_goal_ids folds only simard-identity-<slug> (confirmed a real shape — e.g. simard-identity-atelier-industrial-furniture-de) and positional goal-<digits>. Any reblock dedup_key embedding a volatile id in another shape (bare hex board id, overseer-goal-<ts> slugs seen in meeting_ops.rs) would not fold and could still churn. Per requirement R1, confirm the production reblock dedup_key behind signature cfa5358a3b59894c actually uses one of the two folded shapes; otherwise the reblock half is also inert. The design is appropriately conservative — this is a verification ask, not a code defect.

🟢 LOW — mergeable == "CONFLICTING" ignores transient UNKNOWN

CloseReason classification treats a still-computing UNKNOWN PR as SupersededDuplicate. Harmless (both reasons close, and a duplicate should close regardless), so cosmetic only — noting for completeness.


✅ Strengths (verified)

  • Breaker core stays pure (R4 satisfied). quarantine_marker/is_quarantine_ref key on a fixed compile-time sentinel ref_id, never goal-derived — a goal cannot forge its own quarantine (injection-safe); tests pin this.
  • "Exactly one issue" dedup is sound. escalate_with_tracking_issue blocks then short-circuits on an existing suppression marker that lives on the goal board (survives restart); the quarantine arm pushes the marker idempotently behind !is_quarantined(g).
  • Churn short-circuit proven. reinvestigate_bare_blocked_goals skips quarantined goals before consulting the reasoner, and tests_quarantine_churn.rs uses a PanicReasoner to prove the reasoner is never reached — a strong regression guard.
  • Reconcile is fail-closed and injection-safe. close_pr default is a no-op; RealPrGhClient shells argv-only (no shell interpolation). The pass is gated (client wired + gap-scan opt-in + non-empty roster + every-N cadence), max() can never close all candidates, and closes are bounded by MAX_CLOSES_PER_CYCLE. Per-close errors are collected into the report, not silently swallowed.
  • No new TODOs / stubs / println! / swallowed errors in production code; logging is tracing-only (R5 satisfied). Remaining unwrap!/panic!/eprintln! are all in test code or pre-existing.

Checklist

  • Code quality and standards — good; pure/IO split is clean
  • Test coverage — adequate for Problem #1; blind spot for Problem #5 (see HIGH)
  • No TODOs, stubs, or swallowed exceptions in new production code
  • No unimplemented functions
  • Logic correctness — Problem #5 gate does not match production data (HIGH, blocking)
  • Edge case handling — quarantine idempotence, canonical never-closed, restart survival all covered

Bottom line: merge-blocking on the Problem #5 identity gate. Land the quarantine half; fix the auto-doc author gate (and add a production-shaped fixture) before Problem #5 can be considered delivered.

Comment thread src/overseer/doc_pr_reconcile.rs Outdated
Comment thread src/overseer/doc_pr_reconcile.rs
Comment thread src/ooda_loop/no_progress.rs
@rysweet

rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Step 17c — Security Review (read-only specialist)

Security-focused pass over all 23 changed files on review/ooda-churn-autodoc-step17b-1785249692 (base main, head f78c26c, +3169/-109). Scope: exploitable security issues only; correctness/logic findings are covered in the Step 17b review. Every attack surface was traced to actual code at the head commit and verified independently.

✅ Verdict: SECURITY-CLEAN — no Critical/High findings, non-blocking.

# Area Result Evidence
1 Command / argument injection ✅ SAFE All gh calls use Command::new("gh").args([...]) positional argv — no shell, no sh -c, no format!-into-shell. close_pr argv ["pr","close",&pr,"--repo",repo,"--comment",comment] (merge_authority.rs:504-513); list_open_prs (:389-401); GhIssueFiler::file_issue gh issue create --title/--body/--label positional (no_progress.rs:167-176). The label string with interpolation is used only in error messages, never executed (merge_authority.rs:318-337).
2 Untrusted input → dangerous sinks ✅ SAFE PR title/author/labels/mergeable consumed only as boolean comparisons (doc_pr_reconcile.rs:96-103) or to pick canonical (integer max() of PR numbers). No PR/issue free-text reaches a shell, file path, or close comment (which interpolates only the u32 canonical number). No path traversal — quarantine marker is an in-memory WipRef, not a filesystem path.
3 Authorization / destructive auto-close ✅ SAFE reconcile_doc_prs closes only PRs passing the fail-closed composite gate is_auto_doc_pr (doc_pr_reconcile.rs:96-103): title prefix AND author == "simard-overseer[bot]" AND is_draft == true AND simard-autonomous label. The anchoring author check is a GitHub-attested, unforgeable account login — an external contributor cannot open a PR as the bot, so title/label/draft (attacker-settable) can never satisfy the gate alone. canonical = max(number) is never added to to_close, so the newest candidate is always preserved. The gate cannot be made too permissive by an external actor.
4 Sentinel / marker injection ✅ SAFE quarantine_marker() sets both kind and ref_id to fixed compile-time constants (NO_PROGRESS_QUARANTINE_MARKER_KIND / ..._REF_ID), never goal-derived; is_quarantined requires that exact marker. Suppression markers (no_progress.rs:77-121) use the same fixed-sentinel pattern. Attacker-controlled goal id/text cannot forge a quarantine or collide to suppress a legitimate escalation.
5 Secrets / sensitive data ✅ SAFE No tokens/credentials embedded, logged, or persisted. gh uses ambient auth; no GH_TOKEN/env logged. Error paths log gh stderr (standard diagnostics); existing sanitize_detail redactor (unchanged, wiring.rs) still guards the operator feed. Markers/issue bodies carry only goal ids + constant text.
6 DoS / resource abuse ✅ SAFE Closes bounded (MAX_CLOSES_PER_CYCLE = 25), listing bounded (DOC_PR_LIST_LIMIT = 200), issue filing deduped via durable suppression marker before any gh call. No unbounded loop or issue-spam vector introduced.

Notes

  • The over-restrictive author gate flagged in Step 17b is a correctness/inertness issue (the feature currently matches zero live PRs), not a security weakness. From the security angle this is fail-safe: a too-restrictive destructive gate errs toward not closing PRs. Fixing the inertness must not weaken the unforgeable-author anchor.

Bottom line: No security changes required to merge. Subprocess execution is injection-safe (argv-only), the destructive auto-close is anchored on an unforgeable bot-author login, sentinels are forgery-proof compile-time constants, and no secrets leak.

…gate + reblock verify)

Addresses the REQUEST-CHANGES findings from the Step 17b code review and the
security/philosophy reviews on PR #4964.

HIGH (correctness, blocking) — auto-doc PR gate was inert in production:
  `is_auto_doc_pr` hard-coded the expected author to `AUTO_DOC_PR_AUTHOR`
  (= `simard-overseer[bot]`), but real auto-doc PRs are authored under Simard's
  engineer/OODA gh identity (`config::automerge_author`, distinct by design). The
  gate matched ZERO real PRs. Fix: remove the constant, make `is_auto_doc_pr` /
  `reconcile_doc_prs` take an `expected_author`, and resolve it at the I/O
  boundary in `run_doc_pr_reconcile` via `automerge_author()`. The author conjunct
  stays mandatory (security review's requirement — author.login is
  GitHub-authoritative/unspoofable); unset identity => empty => fail-closed inert.
  Split the executor into a thin env-resolving `run_doc_pr_reconcile` wrapper and
  a testable `run_doc_pr_reconcile_with_author` core.

MEDIUM — silent inert gate: `run_doc_pr_reconcile_with_author` now emits a LOUD
  `warn` when title-marker PRs are present but NONE pass the identity gate,
  naming the likely cause so an inert pass never fails silently.

MEDIUM — reblock fold verification: added tests pinning `fold_volatile_goal_ids`
  against the REAL production dedup_key shapes `classify_signal` emits
  (`goal:blocked:<id>`, `goal:stale:<id>`, `loop:<id>`, `drift:<id>`), incl. an
  end-to-end dedup assertion through the Decide seam.

LOW — cleaned `let _ = class;` (use `class: _` in the match arm).

Tests: fixed the test-masks-bug (fixtures bound author to the gate's own
constant). Fixtures now use a realistic engineer author distinct from the
overseer bot; added regression tests: overseer-bot author is NOT a candidate,
empty expected author fails closed, and the executor is inert (no closes) on
author mismatch / unresolved identity. Also updated the API reference doc.

Verified: cargo check/clippy/fmt clean; targeted suites green
(28 doc_pr_reconcile/reblock + 159 no_progress/quarantine).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet

rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Step 17d — Philosophy Guardian Review

Assessed review/ooda-churn-autodoc-step17b-1785249692 (@ f78c26c, +3169/-109, 23 files) against the amplihack philosophy. Findings verified against live GitHub state, not just the diff.

Compliance checklist

  • Ruthless simplicityMostly. Pure breaker logic, focused functions, thin IO wrappers. One deduction: the doc-PR identity gate encodes an assumption (author == bot) that is simpler than reality, so "simple" here masks "wrong."
  • Bricks & studs patternYes. doc_pr_reconcile.rs cleanly separates pure decisions (is_auto_doc_pr, reconcile_doc_prs) from the IO stud (run_doc_pr_reconcile(repo, &dyn PrGhClient)). no_progress_breaker.rs is a pure brick; no_progress.rs owns orchestration/IO. Traits (PrGhClient, dispatchers, healers) are the studs. Good regeneratable boundaries.
  • Zero-BS implementation — ❌ FAIL (blocking). Problem identity-and-bootstrap-refactor #5's fix compiles and passes 15 tests but is inert in production: is_auto_doc_pr gates on author == "simard-overseer[bot]", yet all 19 live auto-doc PRs are authored by rysweet. reconcile_doc_prs therefore matches zero real candidates and closes nothing. Tests hardcode author: AUTO_DOC_PR_AUTHOR, so the suite is green while the feature does nothing real. A feature that "looks delivered but does nothing" is exactly the class of BS the philosophy forbids.
  • No over-engineering⚠️ Minor. The identity gate is an over-constrained conjunction (author AND label AND draft). Against real data, the label/draft conjuncts further shrink an already-empty match set. Loosen to the minimal reliable signal (title marker + owned-bot heuristic) rather than three ANDed conditions.
  • Clean module boundariesYes. Pure vs. IO separation is disciplined, dependency injection via traits throughout, no leakage of IO into decision functions, no new global state. Marker sentinels are injection-safe.

Verdict

NOT COMPLIANT — changes required, driven entirely by the Zero-BS failure.

Strengths worth preserving: no new stubs/TODOs/println! in production code, fail-closed argv-only reconcile, injection-safe sentinels, and disciplined pure/IO separation.

Posted as evidence for Step 17d. Filed as a COMMENT (GitHub blocks non-COMMENT self-reviews for the PR author).

@rysweet

rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Step 17e — Blocking Issues Addressed

All REQUEST-CHANGES findings from the Step 17b code review (plus the security/philosophy review notes) are now fixed. Pushed as 6d325c8 on this branch.

# Sev Finding Resolution
1 🔴 HIGH is_auto_doc_pr pinned author == AUTO_DOC_PR_AUTHOR (simard-overseer[bot]) → matched zero real (engineer-authored) auto-doc PRs; inert in production. Removed the constant. is_auto_doc_pr / reconcile_doc_prs now take expected_author, resolved at the I/O boundary in run_doc_pr_reconcile via config::automerge_author(). The author conjunct stays mandatory (per the security review — author.login is GitHub-authoritative/unspoofable). Unset identity ⇒ empty ⇒ fail-closed inert.
2 🟠 MED Inert-gate failure was silent. New run_doc_pr_reconcile_with_author core emits a LOUD warn when title-marker PRs exist but none pass the gate, naming the likely cause (mis-resolved SIMARD_AUTOMERGE_AUTHOR / missing label / non-draft).
3 🟠 MED fold_volatile_goal_ids unverified vs a real reblock dedup_key. Added tests pinning the fold against the real classify_signal shapes: goal:blocked:<id>, goal:stale:<id>, loop:<id>, drift:<id> — incl. an end-to-end dedup assertion through the Decide seam.
4 🟡 LOW let _ = class; style. Replaced with class: _ in the match arm.
5 🟡 LOW Quarantine bound timing (pre-bump vs old post-bump). Confirmed intentional and pinned by below_the_bound / at_the_bound tests; documented inline (comment at the SurfaceInvestigationFailure arm). No code change needed.

Test-masks-bug (root cause of the HIGH slipping through)

Fixtures bound author to the gate's own constant, so the gate could never fail. Fixtures now use a realistic engineer author distinct from the overseer bot, plus new regression tests:

  • an_overseer_bot_authored_pr_is_not_an_auto_doc_candidate
  • an_empty_expected_author_fails_closed
  • executor_is_inert_when_the_author_identity_mismatches
  • executor_is_inert_when_the_author_is_unresolved

Verification

  • cargo fmt --check, cargo clippy --release -- -D warnings: clean (pre-commit gates passed).
  • Targeted suites green: 28 (doc_pr_reconcile + reblock_signature) + 159 (no_progress + quarantine).
  • API reference (docs/reference/auto-doc-pr-reconciliation-api.md) updated to the author-parameterized contract.

The security review's guidance is honored: the fix keeps the author conjunct (resolving via automerge_author()) rather than loosening the gate to title+label only.

Finding #1 (quarantine off-by-one timing): the pre-bump surfaced-failure
bound in resolution_for_why is deliberate and unit-tested, but nothing
pinned the end-to-end cycle of fire. Add a regression test that drives
reinvestigate_bare_blocked_goals cycle by cycle and asserts the evidence-less
stall surfaces EXACTLY SURFACED_INVESTIGATION_FAILURE_LIMIT times (retriable
each cycle) and terminally quarantines only on the (LIMIT + 1)th observation.

Finding #4 (fold_volatile_goal_ids negative coverage): add explicit edge /
negative cases — goal- without a digit, trailing goal-/simard-identity-
prefixes with empty slugs, partial digit-run folds (goal-12abc -> goal-*abc),
multi-occurrence folds, and UTF-8 multibyte char-boundary safety.

No production behavior change; tests only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet

rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Step 18a — Analyze Review Feedback (MANDATORY)

Analyzed all Step 17 feedback (17b code review · 17c security · 17d philosophy) against the actual fix commit 6d325c8, verified line-by-line at branch HEAD (not just the 17e summary).

Disposition of every blocking / noted finding

# Sev Finding (17b/17d) Verified disposition @ 6d325c8
1 🔴 HIGH Identity gate author prong inert (author == simard-overseer[bot] matched 0 of 19 live PRs) RESOLVED. Constant removed; is_auto_doc_pr(pr, expected_author) + reconcile_doc_prs(_, expected_author); resolved at I/O boundary via config::automerge_author(); !expected_author.is_empty()fail-closed inert on unset identity. Confirmed in doc_pr_reconcile.rs:111-118, 194.
2 🔴 HIGH (tied) Test blind spot hid #1 (fixtures pinned author to the gate constant) RESOLVED. Fixtures now use an engineer author distinct from the bot; 4 new regressions: an_overseer_bot_authored_pr_is_not_an_auto_doc_candidate, an_empty_expected_author_fails_closed, executor_is_inert_when_the_author_identity_mismatches, executor_is_inert_when_the_author_is_unresolved.
3 🟠 MED Inert-gate failure was silent RESOLVED. run_doc_pr_reconcile_with_author emits a LOUD warn! when title-marker PRs exist but none pass the gate, naming the likely cause (doc_pr_reconcile.rs:229-244).
4 🟡 MED Off-by-one: trigger moved from 3rd → 4th surfaced failure (pre-bump read) RESOLVED via documentation (a reviewer-accepted option). Confirmed resolution_for_why routes QuarantineTerminal on surfaced_failures >= LIMIT read pre-bump (no_progress_breaker.rs:657; caller reads at no_progress.rs:1065, bumps at :1334). Behavior pinned by below/at-bound tests; benign (suppression marker prevents a duplicate issue on the extra cycle). Shift documented inline at no_progress.rs:1355-1370.
5 🟢 LOW fold_volatile_goal_ids unverified vs a real reblock dedup_key (R1) RESOLVED. New tests pin the fold against the real classify_signal shapes — goal:blocked:<id>, goal:stale:<id>, loop:<id>, drift:<id> — plus an end-to-end dedup assertion (tests_reblock_signature.rs:159-212).
6 🟡 LOW let _ = class; style RESOLVED (class: _ in the match arm).
7 🟢 LOW mergeable == UNKNOWN classified as duplicate Cosmetic, acknowledged; no code change (acceptable — both reasons close).

Residual (NON-BLOCKING) — one item worth a follow-up

Label + draft prong of the original HIGH is not addressed. is_auto_doc_pr still requires pr.is_draft == Some(true) AND the simard-autonomous label (doc_pr_reconcile.rs:115-117). Against live data this means:

This is a defensible fail-safe (a strict gate avoids ever closing a non-auto-doc PR), so it is not merge-blocking. Recommendation: either (a) narrow the docstring claim to "drain correctly-labeled draft duplicates," or (b) file a follow-up to handle legacy unlabeled/non-draft PRs on the auto-doc branch pattern.

Operational note (delivery dependency)

The fix is fail-closed by design, so Problem #5 only acts in production if SIMARD_AUTOMERGE_AUTHOR is set to the actual auto-doc author (rysweet). If unset, the gate resolves empty ⇒ inert (now with a LOUD warn). Correct engineering — but delivery depends on that deployment config being present.

Verdict

Proceed — all blocking (HIGH) findings resolved; security-clean; philosophy note addressed. Remaining items are one non-blocking safety/docstring residual and one operational reminder. No further code changes required to merge; the two recommendations are follow-ups, not gates.

Step 18b: implement the one actionable non-blocking residual from the
Step 18a review analysis. The auto-doc PR reconciler's identity gate
(is_auto_doc_pr) intentionally acts only on correctly-labeled auto-doc
drafts authored by the resolved auto-doc identity — a security-motivated
fail-safe (Step 17c) so a human/non-auto-doc PR is never auto-closed.

Make that scope boundary explicit instead of implying the whole doc-PR
backlog is drained: add a Scope section to the module docstring and the
reference doc, and tighten the MAX_CLOSES_PER_CYCLE wording to 'backlog
of reconciliation candidates'. Broadening the gate to sweep legacy
unlabeled/non-draft PRs would reintroduce the spoofing risk, so it is
tracked as follow-up #4965 rather than implemented here.

No behavior change (doc-comment/reference only).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet

rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Step 18b — Implement Review Feedback (MANDATORY)

Per the Step 18a disposition, all blocking (HIGH/MED) findings were already resolved by 6d325c8 + 7c9d548. Step 18a left exactly one actionable, non-blocking residual:

The label+draft prong means is_auto_doc_pr ignores the legacy unlabeled/non-draft historical backlog, while the module docstring implies the whole backlog is drained. Recommendation: (a) narrow the docstring, or (b) file a follow-up.

What I implemented (commit 13c3f00d4)

Broadening the gate to sweep legacy non-draft/unlabeled PRs (option b as code) would reintroduce the spoofing risk the Step 17c security review specifically guards against — the strict, fail-closed gate is intentional. So I implemented the safe, correct combination:

(a) Docstring/contract honesty — no behavior change:

  • src/overseer/doc_pr_reconcile.rs: added a "Scope (deliberate fail-safe boundary)" section to the module docstring stating reconciliation acts ONLY on correctly-labeled auto-doc drafts by the resolved identity, and that legacy non-draft/unlabeled PRs are intentionally left untouched (with the LOUD inert-gate warn surfacing the case). Tightened the MAX_CLOSES_PER_CYCLE wording to "backlog of reconciliation candidates".
  • docs/reference/auto-doc-pr-reconciliation-api.md: added a matching "Scope and out-of-scope" section to the full contract.

(b) Follow-up filed: #4965 — "drain legacy unlabeled/non-draft auto-doc PR backlog", with explicit non-goals (MUST NOT relax the label/author conjuncts globally; keep fail-closed + auditable).

Validation

  • cargo fmt --all -- --check ✅ (commit-stage gate)
  • cargo clippy --release --no-deps -- -D warnings ✅ (commit-stage gate)
  • cargo clippy --all-targets --all-features --locked -- -D warnings ✅ (push-stage gate)
  • Doc-comment/reference-only change ⇒ no behavior change; the resolved HIGH/MED fixes and their regression tests are untouched.

Delivered to branch HEAD 13c3f00d4 (remote in sync).

Result

Review feedback fully implemented: every blocking finding resolved (prior commits), and the sole non-blocking residual addressed by making the scope boundary explicit in code+docs and tracking the enhancement as #4965. No open review items remain.

rysweet and others added 2 commits July 28, 2026 16:38
…`goal unblock`

Quality-audit finding on PR #4964 (terminal-quarantine churn suppression).

The runbook (Option B) and the concept/API docs all state that
`simard goal unblock <goal-id>` "clears the quarantine marker" so a
terminally-quarantined UNCLEAR-CRITERIA goal earns a fresh bounded window.
The code never implemented it: `handle_unblock` only reset status to
NotStarted, leaving the durable `ooda-breaker-quarantine` WipRef in place.
No code path anywhere cleared the marker, so a "revived" goal was restored
to NotStarted while `reinvestigate_bare_blocked_goals` still skipped it
forever — the documented recovery contract was unimplemented.

Fixes:
- `handle_unblock` now retains-out the quarantine marker (via
  `is_quarantine_ref`) so a single-id unblock fully revives the goal, and
  logs when a marker was cleared. `unblock-all` is intentionally left
  untouched (scoped to the brain-failure safeguard marker only).
- Corrected `docs/concepts/ooda-breaker-churn-suppression.md`, which
  contradicted the runbook by claiming `simard goal unblock-all` also
  clears quarantines; it does not.
- Added regression test
  `simard_goal_unblock_clears_the_ooda_quarantine_marker`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ep 18a #2/#6)

Tighten the `resolution_for_why` `surfaced_failures` docstring and the ooda
read-site comment to state the pre-bump bound semantics precisely: the
evidence-less stall is surfaced (retriable) for its first LIMIT observations
and terminal quarantine fires on the (LIMIT + 1)th observation — a deliberate
one-observation shift from the old post-bump escalate-at-LIMIT trigger, pinned
end-to-end by `quarantine_fires_on_the_cycle_after_the_limit_th_surface`.

Removes the misleading "byte-for-byte unchanged below the bound" / "once it
reaches LIMIT" phrasing that read as fire-at-LIMIT (Step 18a review findings
on no_progress_breaker.rs and ooda_loop/no_progress.rs). Doc-only; no behavior
change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet
rysweet marked this pull request as ready for review July 28, 2026 17:31
@github-actions

Copy link
Copy Markdown

📊 Coverage Summary

Generated by cargo llvm-cov --workspace --summary-only (nightly, excluding test files)

Module Lines Covered Coverage
Total 211791 178810 84.4%

Coverage data from CI run. Test files matching tests?/ are excluded from line counts.

@rysweet rysweet added the simard-autonomous Simard-authored PR eligible for gated autonomous self-merge label Jul 28, 2026

@rysweet rysweet left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 17b — Comprehensive Code Review

Verdict: APPROVE (no blocking issues). Reviewed all 8 non-test source files, the pure/IO split, wiring, recovery path, and ran the targeted suites. The two churn fixes are additive, fail-closed, and well-tested.

Verification performed

  • cargo test --lib quarantine38 passed
  • cargo test --lib -- doc_pr_reconcile19 passed
  • cargo test --lib -- reblock12 passed
  • Traced the full error/churn path: resolution_for_whyapply_resolution_side_effectsreinvestigate_bare_blocked_goals short-circuit → goal unblock recovery.

Strengths (confirmed correct)

  • Injection-safety is real. quarantine_marker uses a fixed compile-time sentinel ref_id (never goal-derived); is_quarantine_ref keys on both kind and the sentinel, so goal text can neither forge a quarantine nor smuggle content into a marker. Pinned by tests.
  • Single-open invariant cannot close everything. reconcile_doc_prs selects canonical = max(number) and explicitly excludes it from to_close; zero/one candidate ⇒ no closes.
  • Identity gate is fail-closed and spoof-resistant. is_auto_doc_pr requires title marker AND non-empty resolved author AND author == expected_author AND is_draft == Some(true) AND the auto-doc label — every conjunct mandatory. Empty/unresolved author matches nothing. GitHub-authoritative author.login + label (needs triage/write) make a crafted external PR a non-candidate.
  • Churn actually ends. The re-investigation pass short-circuits quarantined goals before consulting the reasoner (verified by the PanicReasoner test), and the marker is durable (persisted in wip_refs), so a restart that re-parks a goal bare still skips it.
  • Never evidence=[(none)]. QuarantineTerminal blocks WITH the surfaced count rendered as concrete evidence; the non-zero-count invariant is pinned.
  • Recovery path exists and is tested. goal unblock clears the marker (wip_refs.retain(!is_quarantine_ref)) and restores NotStarted; unblock-all is deliberately scoped away.
  • No TODOs, stubs, unimplemented functions, or swallowed exceptions. Per-close failures are collected into report.errors and logged (fail-visible), read errors are fail-closed with no mutations.

Non-blocking findings

1. [Info / deployment-assumption] Reconciler effectiveness hinges on SIMARD_AUTOMERGE_AUTHOR matching the real auto-doc PR author.
The flow that creates "Update documentation with …" PRs is not in this repo (confirmed by grep — no pr create with that title). If, in production, those PRs are authored by simard-overseer[bot] (or any login other than automerge_author()), the gate never matches and reconciliation is permanently INERT. This is well-mitigated: run_doc_pr_reconcile_with_author emits a LOUD warn naming the exact cause when title-marker PRs exist but none pass the gate. Action: confirm the actual auto-doc PR author login equals SIMARD_AUTOMERGE_AUTHOR in the deployed env before relying on this pass, and consider an ops alert on that warn.

2. [Nit] DocPrReconcileReport::skipped is noisy.
skipped = open_prs.len() - candidate_count counts all unrelated open PRs (up to the 200 fetch window), not just title-marker-but-rejected ones. The logged number will be dominated by unrelated PRs and won't isolate the interesting "looked like an auto-doc PR but failed a conjunct" case. Consider reporting title_marker_count - candidate_count (already computed) as the meaningful skip signal.

3. [Info, no action] record_progress clears the surfaced-failure counter but intentionally not the quarantine marker.
Only goal unblock clears the marker — documented and correct. Noting for completeness so a future reader doesn't "fix" it.

Checklist

  • Code quality and standards — consistent with existing operator_cli (eprintln!) and overseer (tracing) conventions
  • Test coverage adequate — 69 new targeted tests, all green
  • No TODOs, stubs, or swallowed exceptions
  • No unimplemented functions
  • Logic correctness — quarantine timing shift is deliberate and pinned; invariants hold
  • Edge case handling — empty/unresolved author, zero/one candidate, list error, per-close error, restart re-park, idempotent re-fire all covered

@rysweet

rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Step 17c — Security Review

Verdict: APPROVE — no security-blocking issues found. Reviewed the full change set with a security lens: command construction, authorization/PR-close authority, injection surfaces, sensitive-data handling, and fail-closed behavior. All security-invariant tests pass (45 targeted, incl. the injection-safety and never-close-a-human-PR guards).

Requirements verified ✔

1. Injection vulnerabilities — none (command execution).
Every gh mutation/read shells out via std::process::Command::new("gh").args(argv) with a positional argv array (run_gh_checked / run_gh / close_pr in merge_authority.rs). The format!("gh pr close {pr} …") strings are human-readable labels for error messages only — never executed. No sh -c, no shell interpolation. Malicious repo, author, or comment values cannot break out of argv. The close comment is a fixed format string interpolating only a u32 PR number — no attacker-controlled content reaches the shell.

2. Authorization / PR-close authority — fail-closed, spoof-resistant.
is_auto_doc_pr() requires five mandatory conjuncts (doc_pr_reconcile.rs:127): non-empty resolved expected_author, title marker, non-empty PR author, author == expected_author, isDraft == true, and the auto-doc label. pr.author.login is GitHub-authoritative (unspoofable by an external actor) and the auto-doc label requires repo triage/write, so a crafted PR can never become a close candidate. Any missing/unresolved signal (incl. unset SIMARD_AUTOMERGE_AUTHOR → empty) returns false. Pinned by executor_never_closes_a_human_pr.

3. Injection-safe quarantine marker.
The quarantine WipRef uses fixed compile-time sentinels for both kind (NO_PROGRESS_QUARANTINE_MARKER_KIND) and ref_id (NO_PROGRESS_QUARANTINE_MARKER_REF_ID) — never derived from goal text. is_quarantine_ref() keys on both exact values, so a goal description/activity cannot forge a quarantine for itself or smuggle attacker-controlled content into a marker. Pinned by a_goal_cannot_forge_its_own_quarantine and quarantine_marker_has_the_fixed_kind_and_sentinel_ref_id.

4. Single-open invariant — provably cannot over-close.
reconcile_doc_prs() designates the newest (max number) candidate as canonical and never places it in the close set, so the decision can never close every candidate or the canonical PR. Bounded by MAX_CLOSES_PER_CYCLE; fail-closed on read error (a listing failure performs zero closes that cycle); per-close failures are collected and never abort the batch.

5. Sensitive-data handling — clean.
No tokens/secrets/credentials are introduced, read, or logged by the changed code. The many token references are WHY-class machine tokens (OODA-SAFEGUARD, UNCLEAR-CRITERIA), not secrets. GitHub authentication is delegated entirely to the gh binary's own credential store — the code never touches GITHUB_TOKEN/Authorization headers. Structured tracing logs emit repo/PR-number/author-login only.

6. unsafe code — test-scaffolding only.
The only unsafe blocks in the diff are std::env::set_var/remove_var (edition-2024 requires unsafe for env mutation). All are inside mod tests / #[cfg(test)], single-threaded, serialized, and restored after use, each carrying a // SAFETY: note. No production unsafe.

Non-blocking security observations

  1. [Deployment / least-privilege] PR closes execute under the ambient gh credentials of the daemon host. The identity gate correctly prevents choosing the wrong PR, but the operational blast radius still depends on the daemon's gh token scope. Recommend the deployed token be least-privilege (repo triage/write for close+comment; no admin). The argv builders already structurally exclude --admin/--no-verify (pinned by tests), which is the right defense-in-depth.

  2. [Config integrity] SIMARD_AUTOMERGE_AUTHOR is the load-bearing identity anchor for the whole gate. It is operator-controlled config (not attacker-reachable) and passed argv-only, so it carries no injection risk; but an incorrect value makes the reconciler silently authoritative over a different author's PRs only if that author also draft+labels+title-markers a PR — an extremely narrow, self-inflicted misconfiguration. The existing LOUD inert-gate warn (fires when title-marker PRs exist but none pass the gate) is the correct mitigation. No change required.

Conclusion: The change is injection-safe (argv-only), fail-closed on the authorization gate and on read errors, and free of sensitive-data exposure. No security fix is warranted.

@rysweet

rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Step 17d — Philosophy Guardian Review

Verdict: ✅ COMPLIANT — no philosophy blockers. Reviewed the two changed subsystems (overseer/doc_pr_reconcile.rs new brick + goal_curation/no_progress_breaker.rs terminal-quarantine rung) and their wiring against the amplihack philosophy.

Compliance checklist

  • Ruthless simplicity achieved — The doc-PR reconciler is one small module (309 lines, majority docs) with a single pure decision (reconcile_doc_prs) + one thin IO executor. The quarantine feature reuses existing primitives (WipRef, the persisted surfaced-failure counter) rather than inventing new state stores. Bounded constants (MAX_CLOSES_PER_CYCLE=25, DOC_PR_LIST_LIMIT=200) are pragmatic present-moment limits, not speculative machinery.
  • Bricks & studs pattern followeddoc_pr_reconcile is a self-contained brick with stable public studs: reconcile_doc_prs (pure), run_doc_pr_reconcile (IO), is_auto_doc_pr (gate), and a documented contract in docs/reference/auto-doc-pr-reconciliation-api.md. The pure/IO split means the decision core is regeneratable and unit-testable without touching gh.
  • Zero-BS implementation — No stubs, TODOs, unimplemented!, or dead code introduced. (The lone TODO(brain-wiring) in merge_authority.rs is pre-existing from feat(kgpacks-rs): parameterize knowledge query LIKE search (KGP-Q4) #4349; every panic!/unreachable! flagged is a test assertion.) Errors are surfaced transparently, never swallowed: read failure is fail-closed with the error propagated, per-close failures are collected into report.errors and continue, and an inert identity gate emits a LOUD warn naming the likely misconfiguration.
  • No over-engineering — Draining the legacy unlabeled/non-draft PR backlog is deliberately out of scope with a tracked follow-up, rather than speculatively handled. The reconciler prefers leaving an ambiguous PR open over building fuzzy attribution heuristics — simplest safe behavior.
  • Clean module boundaries — The quarantine marker is a fixed injection-safe sentinel ref_id (never derived from goal text), read only by is_quarantine_ref, so it stays inert to every other subsystem. QuarantineTerminal replaces the adapter's prior inline escalate-at-limit branch (documented "the two must not coexist") — no layering of duplicate logic. The auto-doc author identity is resolved at the IO boundary and injected into the pure gate, keeping env access out of the decision core.

Notes (non-blocking)

  • The composite fail-closed identity gate (is_auto_doc_pr: non-empty expected author ∧ title marker ∧ matching author ∧ draft ∧ label) is a good example of "pragmatic trust with a security guard" — it trusts gh directly but can never auto-close a human PR.
  • Reconciliation being inert unless SIMARD_AUTOMERGE_AUTHOR matches the real auto-doc PR author is a deployment assumption, well-mitigated by the LOUD inert-gate warn (consistent with the "fail loudly, never silently degrade" principle).

Outcome: Philosophy-compliant. No changes required.

@rysweet

rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Step 18a — Analyze Review Feedback (MANDATORY)

Analyzed the latest Step 17 review round against branch HEAD c9e310f25 (remote in sync):

  • Step 17c — Security Review (18:11Z): APPROVE — no security-blocking issues.
  • Step 17d — Philosophy Guardian (18:12Z): ✅ COMPLIANT — no philosophy blockers.

Both reviews evaluated the current HEAD (post-fix: 6d325c87c9d54813c3f00d4ad92af0c9e310f2), i.e. after the HIGH author-gate bug and all MED/LOW items from the 17b round were already resolved. Neither review requests any change.

Disposition of every finding in this round

# Sev Source Finding Disposition @ c9e310f25
1 ✅ APPROVE 17c Injection surface (command construction) No action. All gh calls use positional argv arrays; format!("gh pr close …") strings are error labels only, never executed. Verified — nothing to fix.
2 ✅ APPROVE 17c PR-close authorization (spoof resistance) No action. 5-conjunct fail-closed gate; pr.author.login is GitHub-authoritative; pinned by executor_never_closes_a_human_pr.
3 ✅ APPROVE 17c Injection-safe quarantine marker No action. Fixed compile-time kind + ref_id sentinels; pinned by a_goal_cannot_forge_its_own_quarantine.
4 ✅ APPROVE 17c Single-open invariant (never over-closes) No action. Canonical (max-number) PR never in close set; bounded by MAX_CLOSES_PER_CYCLE; fail-closed on read error.
5 ✅ APPROVE 17c Sensitive-data handling / unsafe No action. No secrets read/logged; the only unsafe is #[cfg(test)] env mutation with // SAFETY: notes.
6 🟢 NON-BLOCKING 17c Deployment least-privilege of daemon gh token No code change. Operational/deploy guidance (repo triage/write, no admin); argv builders already structurally exclude --admin/--no-verify (test-pinned). Captured as a deployment note.
7 🟢 NON-BLOCKING 17c SIMARD_AUTOMERGE_AUTHOR config integrity No code change. Operator-controlled, argv-only (no injection); the existing LOUD inert-gate warn is the accepted mitigation. Reviewer states "No change required."
8 ✅ COMPLIANT 17d Ruthless simplicity / bricks-&-studs / zero-BS / boundaries No action. Pure/IO split, reused primitives, tracked follow-up (#4965) for out-of-scope backlog, LOUD-on-inert.
9 🟢 NON-BLOCKING 17d SIMARD_AUTOMERGE_AUTHOR deployment assumption No code change. Same as #7 — mitigated by the inert-gate warn ("fail loudly, never silently degrade").

Conclusion

No actionable findings in this round. Both the security and philosophy reviews are clean approvals of the current HEAD; the only observations are two non-blocking, deployment-config notes (least-privilege token scope, SIMARD_AUTOMERGE_AUTHOR correctness) — both already mitigated in code by the fail-closed gate + LOUD inert-gate warn, and neither requires a source change.

All previously-blocking findings (17b HIGH author-gate, MED inert-gate telemetry, MED reblock-key verification, LOW timing docstring, LOW style) remain resolved by the commits already on this branch.

Verdict: Proceed — no code changes required from Step 18a. Nothing to implement in 18b beyond the already-filed follow-up #4965.

@rysweet

rysweet commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Step 18b — Implement Review Feedback (MANDATORY)

Implementing the disposition from Step 18a against branch HEAD c9e310f25 (remote in sync, working tree clean, cargo build --lib green).

Actionable code changes required: none

Every review finding across the full 17b→17d rounds is already resolved by commits on this branch. Re-verified each item still holds at HEAD:

Source Finding State @ c9e310f25
17b 🔴 HIGH Author-gate inert (hard-coded simard-overseer[bot]) Resolvedis_auto_doc_pr(pr, expected_author) resolves identity at the I/O boundary, fail-closed on empty.
17b 🔴 HIGH Test blind spot (fixtures pinned to gate constant) Resolved — fixtures use a distinct engineer author + 4 new fail-closed regressions.
17b 🟠 MED Inert gate was silent Resolved — LOUD warn! when title-marker PRs exist but none pass the gate.
17b 🟡 MED Off-by-one in quarantine trigger Resolved — semantics pinned + documented inline; below/at-bound tests.
17b 🟢 LOW Reblock dedup_key fold unverified Resolved — tests pin the fold against real classify_signal shapes + e2e dedup.
17b 🟢 LOW let _ = class; style Resolvedclass: _ in match arm.
17c Security Injection / authz / marker / single-open / secrets APPROVE — no change requested.
17d Philosophy Simplicity / bricks-&-studs / zero-BS ✅ COMPLIANT — no change requested.

Non-blocking items — dispositioned, no source change

  • Legacy unlabeled/non-draft backlog drain (residual of the 17b HIGH): the strict 4-way gate is a deliberate fail-safe; broadening it is out of scope for the merge and is tracked in follow-up Follow-up: drain legacy unlabeled/non-draft auto-doc PR backlog (PR #4964) #4965 (OPEN, verified).
  • Deployment least-privilege gh token scope & SIMARD_AUTOMERGE_AUTHOR correctness (17c/17d): operational/deploy guidance. Already mitigated in code by the fail-closed identity gate + LOUD inert-gate warn. Reviewer stated "No change required."

Verification

Verdict: Step 18b complete — zero code changes required. All actionable feedback was already implemented on the branch; the only open items are non-blocking and tracked in #4965. PR remains MERGEABLE.

rysweet added a commit that referenced this pull request Jul 28, 2026
…o-progress escalation storm (#4973)

* wip: checkpoint after implementation (steps 7-8)

Automatic checkpoint to preserve work in progress.
Tests and implementation saved before refactoring phase.

* fix(overseer): resolve Step 17e blocking review findings (Problem #5 gate + reblock verify)

Addresses the REQUEST-CHANGES findings from the Step 17b code review and the
security/philosophy reviews on PR #4964.

HIGH (correctness, blocking) — auto-doc PR gate was inert in production:
  `is_auto_doc_pr` hard-coded the expected author to `AUTO_DOC_PR_AUTHOR`
  (= `simard-overseer[bot]`), but real auto-doc PRs are authored under Simard's
  engineer/OODA gh identity (`config::automerge_author`, distinct by design). The
  gate matched ZERO real PRs. Fix: remove the constant, make `is_auto_doc_pr` /
  `reconcile_doc_prs` take an `expected_author`, and resolve it at the I/O
  boundary in `run_doc_pr_reconcile` via `automerge_author()`. The author conjunct
  stays mandatory (security review's requirement — author.login is
  GitHub-authoritative/unspoofable); unset identity => empty => fail-closed inert.
  Split the executor into a thin env-resolving `run_doc_pr_reconcile` wrapper and
  a testable `run_doc_pr_reconcile_with_author` core.

MEDIUM — silent inert gate: `run_doc_pr_reconcile_with_author` now emits a LOUD
  `warn` when title-marker PRs are present but NONE pass the identity gate,
  naming the likely cause so an inert pass never fails silently.

MEDIUM — reblock fold verification: added tests pinning `fold_volatile_goal_ids`
  against the REAL production dedup_key shapes `classify_signal` emits
  (`goal:blocked:<id>`, `goal:stale:<id>`, `loop:<id>`, `drift:<id>`), incl. an
  end-to-end dedup assertion through the Decide seam.

LOW — cleaned `let _ = class;` (use `class: _` in the match arm).

Tests: fixed the test-masks-bug (fixtures bound author to the gate's own
constant). Fixtures now use a realistic engineer author distinct from the
overseer bot; added regression tests: overseer-bot author is NOT a candidate,
empty expected author fails closed, and the executor is inert (no closes) on
author mismatch / unresolved identity. Also updated the API reference doc.

Verified: cargo check/clippy/fmt clean; targeted suites green
(28 doc_pr_reconcile/reblock + 159 no_progress/quarantine).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test(ooda,overseer): pin Step 18a review findings #1 and #4

Finding #1 (quarantine off-by-one timing): the pre-bump surfaced-failure
bound in resolution_for_why is deliberate and unit-tested, but nothing
pinned the end-to-end cycle of fire. Add a regression test that drives
reinvestigate_bare_blocked_goals cycle by cycle and asserts the evidence-less
stall surfaces EXACTLY SURFACED_INVESTIGATION_FAILURE_LIMIT times (retriable
each cycle) and terminally quarantines only on the (LIMIT + 1)th observation.

Finding #4 (fold_volatile_goal_ids negative coverage): add explicit edge /
negative cases — goal- without a digit, trailing goal-/simard-identity-
prefixes with empty slugs, partial digit-run folds (goal-12abc -> goal-*abc),
multi-occurrence folds, and UTF-8 multibyte char-boundary safety.

No production behavior change; tests only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(overseer): document deliberate auto-doc reconcile scope boundary

Step 18b: implement the one actionable non-blocking residual from the
Step 18a review analysis. The auto-doc PR reconciler's identity gate
(is_auto_doc_pr) intentionally acts only on correctly-labeled auto-doc
drafts authored by the resolved auto-doc identity — a security-motivated
fail-safe (Step 17c) so a human/non-auto-doc PR is never auto-closed.

Make that scope boundary explicit instead of implying the whole doc-PR
backlog is drained: add a Scope section to the module docstring and the
reference doc, and tighten the MAX_CLOSES_PER_CYCLE wording to 'backlog
of reconciliation candidates'. Broadening the gate to sweep legacy
unlabeled/non-draft PRs would reintroduce the spoofing risk, so it is
tracked as follow-up #4965 rather than implemented here.

No behavior change (doc-comment/reference only).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(ooda,docs): implement the documented quarantine recovery path in `goal unblock`

Quality-audit finding on PR #4964 (terminal-quarantine churn suppression).

The runbook (Option B) and the concept/API docs all state that
`simard goal unblock <goal-id>` "clears the quarantine marker" so a
terminally-quarantined UNCLEAR-CRITERIA goal earns a fresh bounded window.
The code never implemented it: `handle_unblock` only reset status to
NotStarted, leaving the durable `ooda-breaker-quarantine` WipRef in place.
No code path anywhere cleared the marker, so a "revived" goal was restored
to NotStarted while `reinvestigate_bare_blocked_goals` still skipped it
forever — the documented recovery contract was unimplemented.

Fixes:
- `handle_unblock` now retains-out the quarantine marker (via
  `is_quarantine_ref`) so a single-id unblock fully revives the goal, and
  logs when a marker was cleared. `unblock-all` is intentionally left
  untouched (scoped to the brain-failure safeguard marker only).
- Corrected `docs/concepts/ooda-breaker-churn-suppression.md`, which
  contradicted the runbook by claiming `simard goal unblock-all` also
  clears quarantines; it does not.
- Added regression test
  `simard_goal_unblock_clears_the_ooda_quarantine_marker`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(ooda): clarify deliberate pre-bump quarantine trigger timing (Step 18a #2/#6)

Tighten the `resolution_for_why` `surfaced_failures` docstring and the ooda
read-site comment to state the pre-bump bound semantics precisely: the
evidence-less stall is surfaced (retriable) for its first LIMIT observations
and terminal quarantine fires on the (LIMIT + 1)th observation — a deliberate
one-observation shift from the old post-bump escalate-at-LIMIT trigger, pinned
end-to-end by `quarantine_fires_on_the_cycle_after_the_limit_th_surface`.

Removes the misleading "byte-for-byte unchanged below the bound" / "once it
reaches LIMIT" phrasing that read as fire-at-LIMIT (Step 18a review findings
on no_progress_breaker.rs and ooda_loop/no_progress.rs). Doc-only; no behavior
change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(goal): filter tombstones on the OODA board READ path (stop escalation storm)

The `simard ooda run` daemon loads its goal board via
`load_goal_board` -> `read_latest_snapshot`, which read the latest
`goal-board:snapshot` fact from cognitive memory and returned it
**without applying `filter_tombstoned`**. That filter only ran on the
operator-command daemon path (`simard goal list`).

Consequence: a goal that was removed and tombstoned still lingered inside
an older snapshot fact, so every OODA cycle re-materialised it into
`state.active_goals`, the no-progress breaker saw it as
blocked-with-no-progress, and filed a fresh duplicate escalation issue —
then re-persisted the dead goal on the next save-merge. This is why
`simard goal list` showed the goal gone while the OODA loop kept
resurrecting it and storming ~1 GitHub issue every 90 minutes
(`OODA no-progress breaker: goal stuck ... UNCLEAR-CRITERIA`), immune to
30 days of downstream band-aids (dedup guards, done-gate pins, terminal
rungs) that never touched this load-path gap.

Fix: apply `filter_tombstoned` inside `read_latest_snapshot`, the shared
read used by BOTH `load_goal_board` (OODA cycle) and the `save_goal_board`
merge-read, so a tombstoned goal can never be read back from memory on any
path. Single defensive point covering every caller (cycle, journal,
creative-ideas, meeting-backend, status).

Adds a regression test: a snapshot containing a tombstoned goal id is
filtered out of the loaded board while live goals survive.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet
rysweet merged commit 5722ea8 into main Jul 28, 2026
18 checks passed
@rysweet
rysweet deleted the review/ooda-churn-autodoc-step17b-1785249692 branch July 28, 2026 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

simard-autonomous Simard-authored PR eligible for gated autonomous self-merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants