Skip to content

M4 cockpit/background contract fixes, approval-scope honesty, and main CI Lore gate - #100

Merged
johnteee merged 20 commits into
mainfrom
claude/epic-wozniak-i1v4l1
Oct 27, 2026
Merged

johnteee merged 20 commits into
mainfrom
claude/epic-wozniak-i1v4l1

Conversation

@johnteee

@johnteee johnteee commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Summary

Why

Sweeps of the M4 operator-cockpit and background-lifecycle specs, the open ticket plans and the backlog compared each against the code. They found surfaces reporting values that were never loaded: zero counts for failed sources, a hard-coded blocked_count: 0, a review section that nothing feeds, and a fabricated exit code 0 for failed runs. They also found two real bugs and help text that contradicts the runtime. Separately, main CI went red after every GitHub-UI merge, because the Lore-trailer gate read the generated merge commit.

What

  • U-P1-9: cockpit memory, review and skill load failures are logged at ERROR and listed in errors. model_route comes from the latest run.
  • U-P1-10: the cockpit shows counts of running and orphaned background runs.
  • U-P1-11: a repeated stop converges. A dead record with no run_id is orphaned. orphaned is derived and never persisted.
  • U-P1-12: contract tests cover the blocked, no-clear-screen and undo-journal rules. The cockpit gains an undo_command field.
  • U-P1-13: background records gain a derived run_outcome; a paused run reads pending_approval.
    • Bug fix: background commands dropped --approve-scoped; only the deprecated --approve-call-id was forwarded.
  • U-P1-14: the review section reads "unavailable" instead of fabricated zero counts.
  • U-P1-15: approval.blocked_count counts runs with a pending approval (contract: "blocked is loud"). A failed queue load is listed in errors.
  • U-P1-16: cockpit background rows carry run_outcome (BG-001 §3.2).
  • U-P1-17: a reaped run's exit_code falls back to 0 only when its last terminal event is run_completed. Before, a failed run showed exit code 0. The fallback value is marked exit_code_derived and never persisted.
    • Bug fix: stop() used to write the derived 0 to disk.
  • U-P1-18: a failed TUI cockpit refresh keeps the previous state instead of clearing the panel (spec §3.4).
  • U-P1-19: the --git-sandbox help and API docs claimed the sandbox is opt-in. In fact the runtime enables it automatically in git repositories, and nothing reads the flag. This is a wording fix only: whether to keep or remove the flag stays with TASK-DD2-005 human review.
  • G-P1-9 (TASK-DD2-004): the "always for this tool" confirmation states its real scope. The grant matcher fails closed on a rejected path argument.
  • CI: the Lore-trailer step checks the PR head (the merge's second parent) when a merge commit lands on main.
  • Ledgers:
    • Action register rows U-P1-9..19 and G-P1-9 added; totals recounted from the rows (87 total, 82 done).
    • Dated roadmap-status.md entries added.
    • Ticket-plan status lines corrected.
    • Generated docs regenerated.

How

Every code change was test-first: each new assertion failed before its fix. The DR-006 gate is owner-override under the M4 cockpit/background carve-out (dr-006-owner-decision-2026-06-22.md:35). The CI fix and U-P1-19 are governance-gap. There is no audit-schema or event-taxonomy change: BACKGROUND_SUBMITTED/STOPPED stays owner-blocked (ADR-0032).

Done

  • Full suite at 8815edd9: 6930 passed, 34 skipped, 0 failed.
  • Lint, type and repo gates all pass: check_public_docstrings, audit_config_access --max 68, check_complexity --max 99, check_any_count --fail-on-increase, ruff check/format, mypy (teaagent + tests), bandit, audit_test_quality (severe and untyped), check_test_assertion_regression, check_god_modules, check_circular_imports, validate_event_spine_wiring, check_root_module_count.
  • teaagent selftest and teaagent tool lint pass.
  • validate_docs_consistency and report_docs_aging --check pass.
  • check_high_risk_paths passes: no high-risk path is touched.

Open, not in this PR (owner decisions):

  • Whether the cockpit panels answer Q1–Q4 is left to the §5.1 owner walk-through (acceptance spec amendment). That covers the Q3 budget and the Q4 quarantine line. The CLI snapshot labels its cost cost_state: 'unavailable' rather than implying a real value.
  • The v0.1.1 tag (G-P2-21 R0-8) needs a tag push, with owner approval.

Action ID

  • Action: U-P1-15 (also U-P1-9..14, U-P1-16..19, G-P1-9)

Risk Class

Risk class: medium

Self-Review Checklist

General (all PRs)

  • ruff check + ruff format --check pass
  • mypy teaagent/ reports 0 issues
  • python3 scripts/run_test_tier.py --tier smoke passes (full suite run instead)
  • Coverage at least 75% (not measured locally; CI reports it)
  • check_root_module_count.py ≤ 184
  • check_complexity.py ≤ 99
  • No circular imports
  • Event-spine wiring passes
  • Docs consistency passes
  • PR has Why / What / How / Done sections

Documentation

  • No contradiction with current-truth docs
  • Commands in docs are executable
  • Stale dated docs updated or marked as superseded

🤖 Generated with Claude Code

https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq

claude added 20 commits October 27, 2026 09:32
Unmet acceptance criteria in the M4 operator-cockpit and
background-lifecycle specs, schedulable under the DR-006 carve-out
(dr-006-owner-decision-2026-06-22.md:35):
- U-P1-9: cockpit memory/review/skill failures report zeros silently;
  model_route is hard-coded None
- U-P1-10: background runs and orphans are not shown in the cockpit
- U-P1-11: repeated stop rewrites stopped_at; run_id-less dead records
  are never marked orphaned

Action: U-P1-9
Constraint: register rows and counts only
Tested: validate_docs_consistency; docs regeneration
Confidence: high
Roadmap-Status: unchanged

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
The `t` approval choice grants every workspace path for the session but
its confirmation says "current directory", and the grant matcher falls
back to `*` for a rejected (out-of-workspace) path instead of failing
closed. Workspace containment already blocks those writes; the matcher
change is defense in depth.

Action: G-P1-9
Constraint: register row and counts only
Tested: validate_docs_consistency; docs regeneration
Confidence: high
Roadmap-Status: unchanged

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
Re-verified 2026-10-27:
- TASK-DD2-006, TASK-DD2-009, TICKET-15: Complete (plan status was stale)
- TASK-DD2-011, TASK-DD2-012: partial, held under DR-006 (index said Fixed)
- TASK-DD2-004: in progress as G-P1-9 (index said Fixed)
- TICKET-16 Phase 2: partial; observations are not rehydrated on resume
  and the plan requires human review (index said Fixed)

Action: G-P1-9
Constraint: status text only; canonical labels per risk-issue-roadmap-workflow.md
Tested: validate_docs_consistency (ticket index evidence coverage still verified); tests/test_docs_consistency.py
Confidence: high
Roadmap-Status: unchanged

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
main CI has been red after every GitHub-UI merge (#96, #97, #98): on a
push event the Lore-trailer gate read github.sha, the generated "Merge
pull request" commit, which never carries Constraint/Tested/Confidence.
The pull_request path already resolves to the PR head for the same
reason. For a pushed merge commit, check its second parent (the merged
PR head, which passed the gate on the PR). Single-parent pushes,
including web-UI edits, are still checked on their own message.

Simulated with the real history: 34b9643 (#99 merge) -> fc7dec8 and
bf21c9e (#98 merge) -> afe37a9 both pass .githooks/commit-msg; the
other cause of red main, the telemetry test (run 893), was fixed in #97.

Action: G-P2-21
Gate: governance-gap (CI must evaluate the authored commit; red main hides real failures)
Constraint: one workflow step; no gate weakened; merge commits only
Tested: workflow YAML parses; tests/test_ci_governance_flow.py and workflow tests 79 passed; shell resolution simulated on merges 34b9643 and bf21c9e
Confidence: high
Roadmap-Status: unchanged

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
…lent defaults

build_control_cockpit silently substituted zeros/None when the memory,
review, or skill source failed, so a broken memory load showed up as
"total_entries: 0" (false data) with nothing in cockpit.errors and no log.
Those three blocks now log via logger.exception and append a
"<source> load failed" entry to errors, matching the run-context blocks.
The fallback values are kept so the JSON shape stays stable.

model_route was hard-coded to None. It now reads the latest run's
model_route audit event (the same event run_evidence.extract_routes reads)
and sets provider/model/source/reason/estimated_cost_cents. A run with no
route yields None with no error; a read failure logs and reports
"model route load failed".

Action: U-P1-9
Gate: owner-override (co-maintainer dogfood; DR-006 M4 operator-cockpit carve-out, dr-006-owner-decision-2026-06-22.md:35)
Constraint: Edited only the model-route, memory, review and skill regions of build_control_cockpit; no background-run code, no reordering of existing blocks. Review block fallback stays None (its review_ids field is never populated by the goal dict, so the failure path is not reachable from a test and is left structurally identical).
Tested: pytest tests/test_control_cockpit.py tests/acceptance/test_cockpit_snapshot_flow.py tests/test_cockpit_acceptance_spec.py tests/test_silent_exception_cleanup.py -> 50 passed (new: memory/skill failure logged+reported, model route from latest run, no-route None, route read failure reported). All gates in gates.md exit 0.
Confidence: high
Roadmap-Status: unchanged
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
The control cockpit now carries a `background` section built from
BackgroundRunStore (readonly) list(): running_count, orphaned_count and
up to 10 newest-first items {background_id, run_id, alive, orphaned,
liveness_stale}. The TUI [Control Cockpit] panel renders
"Background: N running, M orphaned" beside Undo/Last run. A store failure
records "background runs load failed" and renders "Background: unknown".

The `background list` TTY table gains Orphaned and Liveness Stale columns;
JSON output is unchanged.

Action: U-P1-10
Gate: owner-override (co-maintainer dogfood; DR-006 M4 operator-cockpit carve-out, dr-006-owner-decision-2026-06-22.md:35)
Constraint: Snapshot schema v1 top-level keys untouched; the new field sits inside the control section via the existing asdict() path (additive). Memory/review/skill/model_route regions of build_control_cockpit not modified. No push.
Tested: tests/test_cockpit_background.py (5 new, failed before the change with AttributeError, pass after); tests/test_control_cockpit.py, tests/test_cockpit_acceptance_spec.py, tests/acceptance/test_cockpit_snapshot_flow.py, tests/test_background_*.py, tests/tui/ -> 74 passed. Gates: check_public_docstrings, audit_config_access (68), check_complexity (62<=99), check_any_count (2176<=2177), ruff check, ruff format --check, mypy, audit_test_quality severe/untyped, check_test_assertion_regression, check_god_modules (18 exemptions) all exit 0.
Confidence: high
Roadmap-Status: unchanged
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
…d runs orphaned

BackgroundRunStore.stop() rewrote stopped_at and stop_signal on every call,
so a second stop replaced the first stop's record and could re-signal state.
A repeated stop now returns the existing terminal record unchanged without
sending any signal (BG-001 spec §3.6).

Orphan derivation returned early when a record had no run_id, so a background
process that died without ever writing its run_id was never marked orphaned.
A dead, not-stopped record with a non-zero or unknown exit and no run_id is now
marked orphaned (BG-001 spec §3.3). Live processes are never marked orphaned.

Derived keys (alive, orphaned) are no longer persisted, so stopping an
orphaned record does not store a stale orphan marker.

Action: U-P1-11
Gate: owner-override (co-maintainer dogfood; DR-006 M4 background-lifecycle carve-out, dr-006-owner-decision-2026-06-22.md:35)
Constraint: First-stop semantics unchanged (dead-process first stop still records SIGTERM, pinned by tests/lifecycle); no cockpit.py edits; no push.
Tested: pytest tests/test_background_run.py tests/test_background_orphan_marker.py tests/lifecycle/ tests/acceptance/test_background_attach_resume_notify_flow.py tests/acceptance/test_cloud_background_parity_flow.py -> 60 passed, 1 skipped; new tests failed before fix (3 orphan/stop cases) and pass after; all pre-commit gates exit 0.
Confidence: high
Roadmap-Status: unchanged
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
…l closed on rejected paths

Answering "t" (always for this tool) at an approval prompt registers a
session grant with path_globs=['*'], which matches every path in the
workspace for 8h. Three confirmation messages still said "current
directory", understating the grant to the operator. They now say
"all paths in this workspace, this session, 8h".

_path_matches also let a '*' grant match a path argument that was present
but rejected by _normalize_and_validate_path (absolute paths outside the
workspace, ../ traversal). The rejected value left path_value as None and
the function fell back to "any '*' pattern matches", so such calls were
covered by the grant. It now returns False when a path key was supplied
and none validated. The '*' fallback is kept only when no path argument
is present, so tool-scoped grants for tools without a path still work.

Defense in depth, not a live bypass: workspace containment in
teaagent/approval/manager.py already blocks destructive writes outside
the workspace. This change makes the grant matcher agree with that.

Constraint: no change to grant storage, TTL, or the '*' semantics for tools without a path argument. Empty-string path values now count as a supplied path key, so a '*' grant no longer covers them (previously it did); non-'*' grants are unaffected.
Tested: tests/test_approval_grant_scope.py (new, 7 tests) fails 5 before the change and passes after; tests/acceptance/test_approval_root_cli_flow.py, tests/integration/test_destructive_approval_lifecycle.py, tests/approval/, tests/test_ergonomics.py, tests/test_tui.py -k approv, tests/test_smart_hitl.py, tests/test_policy.py all pass. tests/test_hybrid_approval_queue_performance.py::test_large_scale_queue_performance fails on a wall-clock budget (24-27s vs 15s) on this loaded machine; it exercises the subagent queue, not grant matching. All gates in gates.md exit 0.
Action: G-P1-9
Gate: governance-gap (approval scope shown to the user must match the grant; TASK-DD2-004)
Confidence: high
Roadmap-Status: unchanged
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
- action register: U-P1-9, U-P1-10, U-P1-11 and G-P1-9 done; summary
  recounted (74 done, G-P2-21 in progress)
- TASK-DD2-004: Complete via G-P1-9; ticket index row updated
- roadmap-status: dated entry for the four fixes and the main-CI merge
  fix, plus what stays unscheduled (TICKET-16 Phase 2 human review, the
  cockpit review section's dead `review_ids`, the background event
  taxonomy as an ADR-0032 schema change)

Action: G-P1-9
Constraint: docs and generated files only
Tested: validate_docs_consistency; docs/okf/aging/inventory/roadmap/acceptance-count tests 102 passed
Confidence: high
Roadmap-Status: updated with one dated 2026-10-27 entry; no horizon status moved

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
build_control_cockpit read cockpit.goal['review_ids'], but the goal dict
never carries that key and nothing in production writes GoalRecord.review_ids
or calls record_review_closed. The section therefore always reported
{review_ids_count: 0, latest_review_status: 'unknown'}, which reads as real
data ("0 reviews") when no review source was consulted.

Decision: option (b). No cheap recorded source exists for the latest run's
review status (run_review.review_run is an on-demand report, not a stored
record; review_closed has no production caller). cockpit.review is now None
("unavailable") and the field is kept. The TUI state panel renders None as
"Review: unavailable" instead of printing nothing.

Action: U-P1-14
Gate: owner-override (co-maintainer dogfood; DR-006 M4 operator-cockpit carve-out, dr-006-owner-decision-2026-06-22.md:35)
Constraint: Did not wire a review source (no recorded review event for a run exists to read); goal.review_ids is left as stored data and is not surfaced in the cockpit. Undo/background regions of cockpit.py untouched.
Tested: pytest tests/test_cockpit_review_section.py (2 new, failed before fix, pass after); tests/test_control_cockpit.py tests/test_cockpit.py tests/test_cockpit_run_status.py tests/test_cockpit_acceptance_spec.py tests/acceptance/test_cockpit_snapshot_flow.py tests/acceptance/test_daily_cockpit_parity_flow.py tests/tui/ -> 71 passed; all gates in gates.md exit 0; check_test_assertion_regression reports no weakening (assertion count preserved)
Confidence: high
Roadmap-Status: unchanged
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
Implements the four acceptance tests named in the operator cockpit contract
(docs/specs/operator-cockpit-contract-2026-06-01.md) in a new
tests/test_cockpit_contract.py: single source, shows blocked, no clear
screen, and recoverable matches undo journal.

The cockpit now carries undo_command, the exact command summarize_run
produces for the latest run with an undo journal. It is set only when undo
is available or partial, and the TUI Undo line renders it.

Action: U-P1-12
Gate: owner-override (co-maintainer dogfood; DR-006 M4 operator-cockpit carve-out, dr-006-owner-decision-2026-06-22.md:35)
Constraint: blocked_count is left hardcoded at 0 and the pending approval queue stays the blocked signal; defining blocked versus pending is a product decision, not changed here. The dashboard surface does not exist in this codebase and is not tested.
Tested: pytest tests/test_cockpit_contract.py tests/test_control_cockpit.py tests/test_cockpit_acceptance_spec.py tests/acceptance/test_cockpit_snapshot_flow.py tests/acceptance/test_daily_cockpit_parity_flow.py tests/lifecycle/test_background_lifecycle_spec.py tests/test_cockpit.py tests/test_cockpit_run_status.py tests/test_silent_exception_cleanup.py tests/test_tui.py tests/tui/ -> all pass; all gates in gates.md exit 0
Confidence: high
Roadmap-Status: unchanged
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
Background records exposed process liveness (alive, liveness_stale, orphaned)
but never the run outcome, so an operator could not tell a completed run from
a failed or cancelled one without reading the audit log. BG-001 section 3.2
requires liveness, outcome and staleness to stay distinct and all be surfaced.

BackgroundRunStore now derives run_outcome on every get/list from the last
terminal audit event of the run: run_completed -> completed, run_failed ->
failed (or cancelled when the message is the RunCancelledError text),
run_paused -> pending_approval (the BG-001 §3.2 vocabulary), run_cancelled -> cancelled. A run with no terminal event
is running while its process is alive and unknown otherwise; a record without
a run_id is unknown. run_outcome joins alive and orphaned in the derived-key
set and is stripped before any record write, so it is never persisted.

The background list TTY table gains an Outcome column; JSON output gains the
key (additive).

build_agent_run_command also forwarded only the deprecated --approve-call-id,
so --approve-scoped (the flag agent run actually consumes) never reached a
background child. It is now forwarded, with a test asserting the child argv
carries the parent's approval flags.

Constraint: teaagent/cockpit.py untouched (another agent is editing it). Only
the derived outcome is added; no change to orphan semantics or the audit
taxonomy. No resume/no-re-execution test added: an existing suspension fixture
with a checkpointed scoped approval was not available within the file scope.
Tested: pytest tests/test_background_run_outcome.py (10 new tests: 10 failed
before the change, all pass after; the guard test that run_outcome is never
persisted passes before and after); pytest tests/test_background_*.py
tests/lifecycle/ tests/acceptance/ -k "background or lifecycle or parity or
outcome" (116 passed, 1 skipped); tests/test_cockpit*.py and test_ergonomics.py
(102 passed across the background/cockpit set); all pre-commit gates exit 0.
Confidence: high
Roadmap-Status: unchanged
Action: U-P1-13
Gate: owner-override (co-maintainer dogfood; DR-006 M4 background-lifecycle carve-out, dr-006-owner-decision-2026-06-22.md:35)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
approval.blocked_count was hard-coded to 0, breaking the cockpit
contract's "blocked is loud" rule; it now counts distinct runs with a
pending approval. A failed approval-queue load is listed in errors
instead of silently reporting zero.

Action: U-P1-15
Gate: owner-override (DR-006 M4 cockpit carve-out, dr-006-owner-decision-2026-06-22.md:35)
Constraint: no change to approval policy or the pending-approval store
Tested: tests/test_cockpit_contract.py (blocked_count failed before the fix; new failure-path test); cockpit tests 53 passed
Confidence: high
Roadmap-Status: unchanged

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
Adds the U-P1-12 (contract tests, undo_command), U-P1-13 (run_outcome,
--approve-scoped forwarding), U-P1-14 (review unavailable) and U-P1-15
(blocked_count) rows to the action register, recounted from the rows
(P1 33, total 83, done 78), and a dated roadmap-status entry. Generated
docs regenerated.

Action: U-P1-15
Gate: owner-override (DR-006 M4 cockpit carve-out, dr-006-owner-decision-2026-06-22.md:35)
Constraint: ledger update only; no horizon or milestone status moved
Tested: validate_docs_consistency.py passed; register totals recounted from ID rows
Confidence: high
Roadmap-Status: updated 2026-10-27 cockpit contract round entry (no horizon status moved)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
The cockpit background items exposed process liveness (alive, orphaned,
liveness_stale) but dropped run_outcome, which BackgroundRunStore already
derives from the run's audit log. BG-001 section 3.2 requires liveness,
outcome and staleness to be rendered as distinct facts, so each item now
carries run_outcome alongside them.

Action: U-P1-16
Gate: owner-override (DR-006 M4 cockpit carve-out, dr-006-owner-decision-2026-06-22.md:35)
Constraint: cockpit output only; background_run derivation unchanged
Tested: python -m pytest -q tests/test_cockpit_background.py::test_cockpit_background_item_surfaces_run_outcome failed before the fix (KeyError 'run_outcome'); after the fix python -m pytest -q tests/test_cockpit_background.py tests/test_cockpit_contract.py tests/test_control_cockpit.py -> 40 passed; ruff check and ruff format --check clean; mypy teaagent/cockpit.py tests/test_cockpit_background.py --explicit-package-bases -> no issues
Confidence: high
Roadmap-Status: unchanged

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
A failed _refresh_control_cockpit or _refresh_cockpit_state reset its
attribute to None, so one transient failure wiped the [Control Cockpit]
panel. Both except branches now keep the debug log and leave the previous
state in place. The attributes are already initialized to None in __init__,
so a first-ever failure still yields None.

Action: U-P1-18
Gate: owner-override (DR-006 M4 cockpit carve-out, dr-006-owner-decision-2026-06-22.md:35)
Constraint: refresh triggers and cockpit content unchanged
Tested: python -m pytest -q tests/test_tui_cockpit_refresh_keeps_state.py tests/test_control_cockpit.py tests/test_tui*.py -> 326 passed. Before the fix the two regression tests (control cockpit and cockpit state) failed with the attribute reset to None; the first-failure test passes both before and after. ruff check and ruff format --check clean; mypy --explicit-package-bases clean; scripts/audit_test_quality.py --fail-on untyped exit 0. tests/test_cockpit_contract.py does not exist in this worktree, so it was not run.
Confidence: high
Roadmap-Status: unchanged

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
When another waiter had already reaped the child, any terminal audit event
(including run_failed and run_cancelled) filled a missing exit_code with 0,
so a failed run read as a clean exit. The 0 stand-in is now used only when
the last terminal event is run_completed, it is marked exit_code_derived,
and it is never written to the record file (stop() used to persist it).

Action: U-P1-17
Gate: owner-override (DR-006 M4 background-lifecycle carve-out, dr-006-owner-decision-2026-06-22.md:35)
Constraint: no new supervisor; no audit-schema change; exit-code reaping unchanged
Tested: tests/test_background_exit_code_fallback.py (4 tests, all failed before the fix); tests/test_background_*.py, test_cockpit_background.py, tests/lifecycle: 81 passed, 1 skipped
Confidence: high
Roadmap-Status: unchanged

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
The --git-sandbox help and docs/api said the flag opts in to an isolated
git branch. Runtime enables the sandbox automatically in any git repository
(prompted when interactive, automatic when non-interactive or
git_sandbox_consent=always), and nothing reads the flag. The help and the
API docs now say the flag has no effect and describe the real default.
Flag behavior is unchanged; honoring or removing it is left for human review.

Action: U-P1-19
Gate: governance-gap (help claimed opt-in for the rollback sandbox while runtime auto-enables it; TASK-DD2-005 AC)
Constraint: flag kept and runtime behavior unchanged; honoring or removing --git-sandbox left for human review
Tested: new tests/test_git_sandbox_help_honesty.py failed first (AssertionError: old help "Run agent task in a git sandbox branch..."), then passed after the help change (1 passed). `pytest -q tests -k "parser or help or cli_api"`: 70 passed, 6843 deselected. ruff check and ruff format --check on changed .py files: clean. mypy --explicit-package-bases on changed .py files: no issues. `python scripts/audit_test_quality.py --fail-on untyped`: exit 0. `python scripts/validate_docs_consistency.py`: passed. Docs regeneration chain run in the specified order.
Confidence: high
Roadmap-Status: unchanged

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
…ow-ups

Adds action-register rows for U-P1-16 (cockpit run_outcome), U-P1-17
(exit-code fallback), U-P1-18 (TUI refresh keeps state) and U-P1-19
(git-sandbox help honesty), recounted from the rows (P1 37, total 87,
done 82), plus a dated roadmap-status entry naming what stays open.

Action: U-P1-19
Gate: governance-gap (ledger for the fixes above; no new behavior)
Constraint: ledger update only; no horizon or milestone status moved
Tested: validate_docs_consistency.py passed; register totals recounted from ID rows
Confidence: high
Roadmap-Status: updated 2026-10-27 cockpit and background follow-ups entry (no horizon status moved)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
The entry called the CLI cockpit budget a placeholder. The snapshot labels
its cost unavailable rather than implying a value, the contract's "fake"
budget was the TUI's (now real), and Q1-Q4 coverage is the owner
walk-through's call per the acceptance spec amendment.

Action: U-P1-19
Gate: governance-gap (correct a ledger claim contradicted by the spec)
Constraint: ledger wording only; no code or status change
Tested: validate_docs_consistency.py passed; claim checked against operator-cockpit contract and acceptance spec
Confidence: high
Roadmap-Status: updated 2026-10-27 cockpit and background follow-ups entry wording (no horizon status moved)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
@johnteee
johnteee merged commit b24b9e1 into main Oct 27, 2026
23 checks passed
johnteee pushed a commit that referenced this pull request Oct 27, 2026
pip-audit on main failed after the PR #100 merge: msgpack 1.2.1 carries
CVE-2026-114613, fixed in 1.2.3. The lockfile now resolves 1.2.4 and the
declared floor is raised to >=1.2.3 so unlocked installs cannot pick the
vulnerable release.

Action: S-P1-5
Gate: governance-gap (security: known-vulnerable dependency failing the pip-audit gate on main)
Constraint: only msgpack moved in uv.lock; no other dependency upgraded
Tested: pip-audit on the uv export of the old lockfile reproduced the CVE; base and dev exports of the new lockfile report no known vulnerabilities
Confidence: high
Roadmap-Status: unchanged

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JE5Q9zqTjf7w2PzjzAC2Qq
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants