docs(overseer): document goal-board health — self-heal + escalate (#2609/#2616)#2620
Merged
rysweet merged 8 commits intoJul 6, 2026
Conversation
/#2616) The goal-board health feature (self-heal false-parked perpetual goals, escalate genuine "needs human review" blocks) merged in #2616 code-only, with no user-facing documentation — unlike its sibling Overseer features (#2611 Whisperer, #2618 Journal), each of which shipped concept + howto + reference docs. This is the missing documentation, grounded in the merged implementation in src/overseer/ and following the repo's Diátaxis structure. Adds (docs-only): - concepts/overseer-goal-board-health.md — the why: the silent-failure gap #2609 left, the observe→signal→decide→act flow, self-heal vs escalate routing, guardrails (dedup, fail-closed identity, opt-out), invariants. - howto/configure-overseer-goal-board-health.md — SIMARD_OVERSEER_GOAL_HEALTH, reading the overseer::goal_health traces / tick counters / activity feed / goal-blocked notifications, and verifying with tests_goal_health. - reference/overseer-goal-board-health-api.md — the exact additive surface: BlockedGoal, blocked_goals_from_board, Signal::GoalBlocked, decide_blocked_goal, Intervention::{UnblockGoal,EscalateBlockedGoal}, ActOutcome variants, OperatorNotification::goal_blocked + OperatorNotifier, goal_health_enabled, the extended OverseerTickReport / OverseerTotals, and wiring. - mkdocs.yml nav entries; an index.md highlight; cross-links from the #2609 perpetual-goal concept and the overseer-activity-feed reference. Verified: scripts/verify-docs.sh (16/16) and mkdocs build --strict both pass; change is docs-only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The goal-board health API reference stated the test suite in src/overseer/tests_goal_health.rs contained 10 tests in two places (the change map and the test-coverage header), but the suite actually has 11 #[test] functions — the list itself enumerates all 11. Correct both counts so the reference matches the merged implementation. Docs-only refinement of #2609/#2616; verified with scripts/verify-docs.sh (17/17) and mkdocs build --strict. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…2609) Step 9 (refactor & simplify) of the goal-board-health work. The two acting paths — act_unblock_goal (self-heal) and act_escalate_blocked_goal — each carried identical SuppressDuplicate / SuppressCapReached match arms: the same tracing::debug! shape and the same GoalHealthSuppressed{reason} construction, differing only by the action label. Extract that shared tail into one private Overseer::goal_health_suppressed(action, goal_id, decision) helper; each act path now handles Deliver inline and routes every non-Deliver decision through the single helper. Behavior-preserving: the emitted reason ("duplicate" / "cap_reached") and the resulting ActOutcome are unchanged; only the two duplicated debug messages collapse into one generic message that keeps the structured action/reason fields. No public API, signal, intervention, or gate semantics change. Verified: cargo fmt --check, cargo clippy --lib --no-deps -D warnings, overseer lib tests (187 passed incl. all 11 tests_goal_health), and the overseer_activity integration test (19 passed). Net -21 lines. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Step 9b performance optimization for the goal-board-health OODA loop added in #2616. The acting Overseer's Observe/Orient pass read Simard's goal board snapshot TWICE every tick: run_cycle() called GoalCurator::blocked_goals() (added by #2616) immediately before the pre-existing in_flight(), and each BoardGoalCurator method independently ran load_goal_board() -> a search_facts("goal-board:snapshot", 64, ..) query plus a full serde_json::from_str::<GoalBoard> deserialize of the same snapshot. Add GoalCurator::observe_board() returning both projections (blocked_goals, in_flight) from a single read: - default impl composes the two existing methods, so fakes that do not model a shared board need no change; - BoardGoalCurator overrides it to load() once and project both via the existing pure blocked_goals_from_board / in_flight_from_board; - run_cycle() uses it, halving per-tick board reads + deserializes from 2 to 1. A board-read failure still degrades BOTH to empty (unwrap_or_default on the pair), preserving the never-abort contract. Additive and behavior-preserving; reuses the shipped projections and the GoalCurator seam. All 189 overseer tests pass (incl. the 11 goal-health tests and run_cycle_populates_observed_blocked_goals); clippy clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
) The perf commit changed run_cycle to enrich via GoalCurator::observe_board() (one board read projecting both blocked_goals + in_flight), but the reference doc still described the old blocked_goals() read path and omitted the new trait method. Update the change map, the ObservedState.blocked_goals read-path note, and the GoalCurator method list so the reference matches the code. Verified: cargo test --lib overseer:: (187 pass), cargo clippy --lib clean, mkdocs build --strict clean (new anchor link resolves). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Step 10b security review remediation (SR-5, High, CWE-93). The goal-blocked escalation path added in #2616 was the first to route board-derived content (a goal_id, via the notification headline/subject) into an email. smtp_send_plaintext() wrote the Subject, From and recipient fields raw into the SMTP DATA headers and the MAIL FROM / RCPT TO envelope, while only the body was CRLF-normalized. A goal_id (or from/to) carrying CR/LF could therefore terminate the header/command line and smuggle arbitrary email headers, an injected body, or an SMTP verb. Fix: sanitize_header_value() strips CR/LF and other control characters (replacing with a space) and length-bounds every header- and envelope-bound field at the single transport choke point, so all callers are covered regardless of how the field was built. Body CRLF normalization is unchanged (multi-line bodies are legitimate). Adds 4 regression tests: CRLF header injection, SMTP command injection, length bounding, and benign-input preservation. Verified: cargo fmt clean; clippy --lib -D warnings clean; 193/193 overseer tests pass (14/14 notify, incl. 4 new). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Review feedback on the SMTP hardening: the header/envelope fix sanitized `from`, recipients and `subject` but left two gaps in the same CWE-93 threat model. - Dot-stuff the DATA body (RFC 5321 §4.5.2). The body was CRLF-normalized but not dot-stuffed, so board-derived content carried into it (a goal id or free-form block `reason`) containing a lone "." line could prematurely close the DATA section and let the server interpret trailing bytes as SMTP commands — the exact injection class the header fix targets, still open via the body vector. `dot_stuff_body` escapes any line beginning with "."; the receiving MTA strips the added dot so benign multi-line content round-trips. - Bound `sanitize_header_value` by bytes, not chars. The old `.take(512)` char cap let multi-byte UTF-8 exceed the RFC 5322 998-octet line limit the doc-comment claimed to stay under. Now accumulates whole chars up to a 512-byte budget without splitting a codepoint. Adds 4 unit tests (lone-dot / leading-dot escaping, benign multi-line + CRLF normalization, multi-byte byte-bounding). overseer suite 193 -> 197, clippy --all-targets clean, fmt clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
📊 Coverage Summary
Coverage data from CI run. Test files matching |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Enhances the Overseer goal-board health capability (feature #2616 /
965c859f, already onmain) with two follow-up layers:NotifyOperatoremail channel that carries genuine "needs human review" escalations.Every symbol described is grounded in the merged code under
src/overseer/.Why
In production the OODA no-progress safeguard hard-blocked the standing research goal ("needs human review") and nothing surfaced it — the Overseer's
ObservedStatehad no goal-board field, so the marker reached no human. #2616 closed that gap (observeBlockedgoals → self-heal false-parked perpetual goals, escalate genuine blocks). Its behaviour was undocumented; operators had no reference forSIMARD_OVERSEER_GOAL_HEALTH, theoverseer::goal_healthtraces, or the escalation notifications. The follow-up code commits harden the escalation email path (which reaches a human) against header/body injection and mailbox corruption.Documentation changes
docs/concepts/overseer-goal-board-health.md: the silent-failure gap fix(ooda): exempt standing/perpetual goals from the no-progress hard-block (#2589) #2609 left, the observe→signal→decide→act flow, self-heal vs escalate routing, guardrails (dedup, fail-closed identity, opt-out), invariants.docs/howto/configure-overseer-goal-board-health.md:SIMARD_OVERSEER_GOAL_HEALTH, reading theoverseer::goal_healthtraces / tick counters / activity feed /goal-blockednotifications, and verifying withtests_goal_health.docs/reference/overseer-goal-board-health-api.md: the exact additive surface (BlockedGoal,blocked_goals_from_board,Signal::GoalBlocked,decide_blocked_goal,Intervention::{UnblockGoal,EscalateBlockedGoal},ActOutcomevariants,OperatorNotification::goal_blocked+OperatorNotifier,goal_health_enabled, the extendedOverseerTickReport/OverseerTotals, and wiring). Synced withobserve_board.mkdocs.ymlnav entries; anindex.mdhighlight; cross-links from the fix(ooda): exempt standing/perpetual goals from the no-progress hard-block (#2589) #2609 perpetual-goal concept and the overseer-activity-feed reference.Code changes (follow-up commits, additive)
src/overseer/notify.rs— SMTP hardening of the escalateNotifyOperatoremail path: sanitize headers against CRLF injection, dot-stuff the message body, and byte-bound headers. This is the channel that carries "needs human review" to a human, so it must not be corruptible by an attacker-influenced goal id/reason.src/overseer/mod.rs— observe the goal board once per tick (was twice) for perf; dedupe the goal-health suppress arms into one helper (refactor, no behaviour change).src/overseer/capabilities.rs/src/overseer/wiring.rs— theobserve_boardAPI(blocked_goals, in_flight)and its wiring.Step 13: Local Testing Results
Detected toolchains:
Cargo.tomlat repo root (name = "simard",edition = "2024",default-run = "simard"),Cargo.lockpresent. All changed source files aresrc/overseer/*.rs; the user/consumer boundary is thesimardCLI (src/operator_cli/goal.rs, which honoursSIMARD_STATE_ROOT) plus the Overseer OODA library. No Node/Python/Go manifests are involved. Per the qa-team skill's repo-type table, aCargo.tomlroot ⇒ nativecargo test, not the gadugi framework.Chosen validation strategy:
simard goalCLI against an isolatedSIMARD_STATE_ROOTtemp dir (never~/.simard, live daemon untouched) to reproduce the exact production false-park and exercise the self-heal's reusedgoal unblockoperation from a user's perspective (Scenario 1), and run the injected-fake goal-health integration suite that exercises sensor →GoalBlockedsignal →GoalHygieneproblem → self-heal/escalate with fakes for goal-store/notify/whisper/clock/identity and no network (Scenario 2). Regression: fulloverseer::andoperator_cli::tests_goalsuites;cargo fmt --check+cargo clippy --all-targets -- -D warningsclean.Scenario 1 — CLI end-to-end: standing goal false-parked by OODA safeguard, then cleared via
goal unblock(the exact op the self-heal reuses)Command:
SIMARD_STATE_ROOT=$(mktemp -d) simard goal add 3 --standing "Standing research goal"; simard goal list; <inject "🔒 [OODA-SAFEGUARD] … needs human review" Blocked marker>; simard goal list; simard goal unblock standing-research-goal; simard goal listResult: PASS
Output (key lines):
Scenario 2 — Injected-fake goal-health integration suite (observe → signal → self-heal + escalate, guardrails, failure isolation)
Command:
cargo test --lib overseer::tests_goal_healthResult: PASS
Output (key lines):
Verification
cargo test --lib overseer::→ 195 passed / 0 failed;cargo test --lib operator_cli::tests_goal→ 28 passed / 0 failed.cargo fmt --checkclean;cargo clippy --all-targets -- -D warnings→ exit 0.--no-verify) — Rust-only gate,cargo fmt --all -- --check,cargo test --release --librace subset, andcargo clippy --all-targets --all-features --locked -- -D warningsall Passed on push.scripts/verify-docs.sh— 17/17 pass;mkdocs build --strictclean (0 broken links / anchors / orphaned nav pages).Deploy note
No redeploy performed by this PR. The operator redeploys the Overseer daemon after merge (
~/.simardand the live daemon were left untouched during development and testing).Relates to #2609; extends #2616. Merged per policy: no
git --no-verify, nogh pr merge --admin.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com