Update documentation with 18 changed files (#4474) - #4487
Conversation
Automatic checkpoint to preserve work in progress. Tests and implementation saved before refactoring phase.
…ror to io::Error The label self-heal executor uses .output(), which folds spawn+wait into a single io::Error, so the single-variant LabelEnsureExecutionError enum and its one-arm formatter label_ensure_execution_reason were pure ceremony (unlike the multi-stage CreateIssueExecutor whose 3-variant enum carries distinct failure modes). The injectable fn-pointer seam is preserved; it now returns Result<Output, io::Error> directly. No behavior change; 24 gh_client / 114 no_progress / 23 spawn tests still pass, clippy + fmt clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The three real-executor `ensure_label` tests write a throwaway `gh` script
and immediately exec it via `execute_ensure_label`. Under parallel test
execution a sibling thread's `fork()` (from another `Command::spawn`) can
transiently hold the just-written script's fd open, so the exec races with
ETXTBSY ("text file busy"). `ensure_label_with` maps that `Err` to
`LabelDisposition::Omit`, which non-deterministically breaks the
`already exists -> Attach` assertion (~1-in-3 failures under the multi-threaded
`ensure_label` filter; always green single-threaded).
Absorb the transient at the test-harness layer via a retry-on-ETXTBSY wrapper
(`execute_ensure_label_no_etxtbsy`) rather than complicating the production
executor — a long-installed production `gh` is never written-then-exec'd.
Verified: single-threaded always passed; multi-threaded now 9+/9 green (was
failing ~1-in-3). clippy -D warnings clean, fmt clean.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
📊 Coverage Summary
Coverage data from CI run. Test files matching |
rysweet
left a comment
There was a problem hiding this comment.
Step 17b — Comprehensive Code Review ✅ Approve (non-blocking nits)
Reviewed the full diff for #4474 (label self-heal for the OODA no-progress escalation). The core fix is well-designed, correct, and thoroughly tested. Summary below.
Verdict: Approve. No blocking issues. Two low-severity nits + one accepted edge case.
What's good
- Correct fail-safe design.
ensure_label→LabelDispositionnever errors:Attachon success/idempotent-exists,Omit{reason}on any failure, so a blocked goal is always escalated (issue filed with or without the label). This is exactly the requirement. - Idempotency. Case-insensitive
"already exists"stderr match treats the non-zero "label already present" exit as success. Existing one-issue-per-stall dedup (already_tracked) is untouched. - Single source of truth for label argv.
LabelDisposition::label_args()+ per-site*_issue_argvbuilders keep--labelsplicing consistent across all three filer sites. - No silent fallbacks. Every degrade path emits structured
tracing::warn!(targetssimard::ooda/simard::ooda_brainper site);open_tracking_issuewas upgraded from.status()(which swallowed non-zero exits) to.output()with a surfaced, bounded failure note — fixing the latent second bug. - Injectable seams.
LabelEnsureExecutorfn-pointer mirrors the provenCreateIssueExecutorpattern; the three failure classes (create-ok, already-exists, unauthorized, spawn-fail, huge-stderr) are all unit-tested without realgh, plus real-subprocess tests viafake_gh. - Hygiene. No new
print!/println!, no TODOs/stubs/unimplemented!; allunwrap()/panic!are test-only. Ambient repo scoping (no-R) documented sogh label createandgh issue createcan't target different repos.
Nits (non-blocking)
N1 — truncate_for_log is now a third copy. This PR adds gh_client::truncate_for_log (2048 B cap) alongside the pre-existing spawn.rs local (256 B) and ooda_brain::rustyclawd (8 KiB) copies. It's consistent with the repo's existing per-module convention, so not blocking — but note the two escalation failure-note paths now truncate at different bounds: spawn::tracking_issue_failure_note uses the 256 B local helper, while gh_client::ensure_label_with uses the 2048 B one. Worth a future consolidation into one shared helper (e.g. a logfmt util) with a single agreed cap.
N2 — Over-broad visibility. gh_client::truncate_for_log and GH_STDERR_LOG_LIMIT are pub(crate) but only referenced within gh_client. Could be module-private (fn / const) to keep the surface minimal. Trivial.
Accepted edge case (no action needed)
- TOCTOU between
gh label createandgh issue create. If the label were deleted in the sub-second window afterensure_labelreturnsAttach,gh issue create --labelwould exit non-zero. This is surfaced (not swallowed) via theOk(out)non-success branches and is astronomically unlikely; documenting here for completeness rather than as a defect. - Pre-existing: the
no_progress::file_issueOk(out)error branch logsghstderr unbounded (stderr = %String::from_utf8_lossy(...)), unlike the new bounded paths. Pre-existing code, out of scope for this PR, but a candidate to route through the same truncation for consistency.
Checklist
- Code quality and standards — idiomatic, well-documented, matches existing patterns
- Test coverage adequate — create / already-exists / unauthorized / spawn-fail / huge-stderr / degrade + real-subprocess argv, at all three sites
- No TODOs, stubs, or swallowed exceptions —
.status()→.output()fix removes the swallow - No unimplemented functions
- Logic correctness — never-error contract verified; idempotent-exists handled
- Edge case handling — bounded logs, UTF-8-safe truncation, degrade-not-fail; TOCTOU noted as accepted
Build + full suite were green in Step 11b (9219 passed; 0 failed). LGTM to merge.
rysweet
left a comment
There was a problem hiding this comment.
Step 17c — Security Review ✅ No high-confidence vulnerabilities
Threat-modeled the full diff for #4474 (label self-heal for OODA no-progress escalation) across the three source files. The change is defensively designed; no blocking findings.
Checklist
- Security requirements met — fail-safe degrade preserves escalation; no new privileged surface
- No new vulnerabilities — see analysis below
- Sensitive-data handling — no tokens/secrets read, logged, or passed anywhere in the diff
- AuthN/AuthZ — relies on
ghCLI ambient auth; degrades correctly on insufficient scope - Injection — argv-only subprocess execution; no shell, no interpolation
Analysis
1. Command / shell injection — SAFE.
Every gh call is Command::new("gh").args(&argv) — a real argv vector, never sh -c/string interpolation (confirmed: no sh -c, /bin/sh, or Command::new("sh") in production diff). title/body are passed as discrete argv elements (--title <title>, --body <body>/--body-file -), so goal-derived content containing shell metacharacters (;, $(), backticks) is delivered literally and never interpreted.
2. Label injection — SAFE.
OODA_STUCK_LABEL is a compile-time constant ("ooda-stuck"). label_args splices ["--label", "ooda-stuck"] unconditionally or nothing — no attacker-controlled label value ever reaches argv.
3. Sensitive-data handling — SAFE.
No GH_TOKEN/GITHUB_TOKEN/.env()/credential references in the diff (confirmed by grep). Auth is entirely delegated to the gh binary's own credential store; the code never touches the token. Logged fields are limited to goal_id, the constant label, truncated gh stderr, title, issue number, and degrade reason — no secret material.
4. Log-flood / DoS — MITIGATED.
GH_STDERR_LOG_LIMIT = 2048 + truncate_for_log bound hostile/runaway gh stderr on a UTF-8 boundary before it is folded into a degrade reason or tracing field. Explicitly tested (label_huge_stderr injects 100 KB → truncated). Good defensive control.
5. AuthZ degrade — SAFE (fail-safe, no priv-esc).
A token with issue-write but not label-write does not fail the escalation: ensure_label returns LabelDisposition::Omit and the issue is still filed (without the label), with the reason surfaced via tracing::warn. Non-zero exits and spawn errors are logged (tracing::error), never silently swallowed — the .status()→.output() upgrade is the mechanism. No privilege escalation path is introduced.
Non-blocking observations (accepted / out of scope)
- Log-injection (low): goal-derived
titleandghstderrare logged with%formatting. In a plaintext log sink, embedded newlines could forge log lines. Pre-existing pattern, structuredtracingfields, low severity — no action required here. - TOCTOU (low): a label deleted between
ensure_labelandgh issue createre-triggers the same missing-label failure, which the design already degrades around safely. Accepted.
Verdict: No high-confidence security findings. argv-only gh invocation, constant label, bounded stderr logging, no secret handling, and fail-safe authz degrade. Approve from a security standpoint.
Step 17d — Philosophy Guardian Review ✅ PASS (non-blocking nits)Assessed the #4474 label self-heal against Compliance checklist
Philosophy highlight — "fail loudly / skip visibly"This is the standout. Non-blocking nits (consistent with Step 17b)
Verdict: PASS. No philosophy violations. Nits are cosmetic and non-blocking; build + full suite (9219 passed) already green. |
Summary
Concise workflow-generated PR for documentation.
Issue
Closes #4474
Changed files
Diff stat
Behavior
Implemented behavior through these branch commits:
e6e9e31 test(stewardship): fix ETXTBSY flake in ooda-stuck label self-heal tests
b54cc07 refactor(stewardship): collapse single-variant LabelEnsureExecutionError to io::Error
2031589 wip: checkpoint after implementation (steps 7-8)
Validation
ℹ NODE_OPTIONS=--max-old-space-size=32768 (saved preference). To change: /home/azureuser/.amplihack/config
I'll start by understanding the current state — branch, changes made, and toolchain.
● Get branch, status, and diff stat (shell)
│ cd /home/azureuser/src/Simard-deploy-4049/worktrees/feat/issue-4474-ooda-no-progress-breaker-esc
│ alation-is-broken-when && git branch --show-current && echo "---STATUS---" && git status --short
│ && echo "---DIFF STAT---" && git --no-pager diff --stat HEAD
└ 4 lines…
No working-tree changes. Let me check recent commits to see the implemented fix.
● Show recent commits and diff vs main (shell)
Risk
No high-risk subsystem pattern detected from changed paths.
Checklist
This PR was created as a draft for review before merging.
Step 16b: Outside-In Testing Results
Detected toolchain: Rust CLI (
Cargo.tomlat repo root, edition 2024, cratesimardv0.35.0). Package manager:cargo. Escalation surface shells out to theghCLI. No Node/Python manifests → gadugi-agentic-test not required; per the qa-team Rust-CLI guidance,cargo testis the outside-in harness and theghsubprocess boundary is exercised via stub-ghscripts.Chosen strategy: (1) Run the crate's real-subprocess tests for the three changed modules (
gh_client,no_progress,spawn) — these driveensure_labelthrough the actualghsubprocess via injected fake-ghscripts. (2) Add an independent end-to-end reproduction with a hand-written stubghonPATHthat reproduces the exact reported journal signature and proves the fixed two-step flow (gh label create→gh issue create) escalates successfully across the create / already-exists / unauthorized paths. (3)cargo clippyfor CI-green.Scenarios
--label ooda-stuckand filecargo test --lib -- gh_client no_progress spawn(ensure_label_runs_gh_label_create_argv_via_real_executor,ensure_label_attaches_when_create_succeeds)ensure_label_attaches_idempotently_when_label_already_exists,ensure_label_treats_real_already_exists_stderr_as_attach)gh label createfails (403 / not-found) → degrade toOmit, file issue without label so escalation still proceedsensure_label_omits_with_reason_when_unauthorized,ensure_label_degrades_when_real_executor_reports_other_failure,ensure_label_omits_when_spawn_fails_and_never_errs)ghonPATHreproducescould not add label: 'ooda-stuck' not found(old path fails), then fixed two-step flow files the issue across create/already-exists/unauthorizedghKey output
cargo test --lib -- gh_client no_progress spawn→ 263 passed; 0 failed; 8963 filtered out (46s).cargo clippy --lib --all-features→ Finished, 0 warnings (CI-green).ghharness:could not add label: 'ooda-stuck' not found→ escalation silently fails (reproduces the bug).✓ Created label ooda-stuck→ issue filed → escalation SUCCEEDS.already existstreated as Attach → issue filed, no duplicate → SUCCEEDS.Omit,--labeldropped → issue still filed → escalation SUCCEEDS.tracing::warn!(targetssimard::ooda/simard::ooda_brain) on degrade; noprint!/println!added by this PR (verified viagit diff origin/main...HEAD).Fix count: 0. All scenarios passed on the first run; no code changes were required during outside-in testing. The implementation self-heals the
ooda-stucklabel idempotently (create-if-missing), treats "already exists" as success, and gracefully degrades to filing without the label when the label cannot be ensured — so a Blocked goal is always escalated. Existing one-issue-per-stall dedup is preserved.