Skip to content

feat(autonomy): duration-ceiling watch leg, digest job, settled HostServicesOnly (P4) - #305

Merged
IanFrelinger merged 1 commit into
masterfrom
feat/autonomy-watch-digest-decisions
Aug 14, 2026
Merged

feat(autonomy): duration-ceiling watch leg, digest job, settled HostServicesOnly (P4)#305
IanFrelinger merged 1 commit into
masterfrom
feat/autonomy-watch-digest-decisions

Conversation

@IanFrelinger

Copy link
Copy Markdown
Owner

Summary

Phase 4, the final phase of the post-merge plan: three closures that finish what the honest assessment opened. Stacked on #304.

1. Absolute duration ceiling on the watch window

WatchThresholds.MaxInvocationDuration — an absolute per-invocation wall-clock ceiling, judged like the contract-conformance leg: no baseline, no minimum invocation count. The relative legs (error-rate delta, latency factor) judge against the previous generation's baseline, which means a first-generation deploy escapes them entirely, and a pathological single invocation can hide inside a healthy mean until enough samples accumulate. The absolute leg closes both holes.

Scope honesty, stated in the docs: wall clock is the one per-invocation resource genuinely measurable in a shared host process. Per-brick memory/CPU attribution is not, and a fake ceiling would be worse than none. Configured via Nexo:Autonomy:WatchMaxInvocationSeconds (0 = off, the default — additive, no behavior change unconfigured).

2. The digest becomes a host job

AddNexoAutonomyDigestJob — swap provenance retained in a bounded ring (RecordingBrickSwapProvenanceSink, which still logs every event, so R2.1's no-unlogged-path holds) and rendered as the §7 human digest on cadence (DigestIntervalSeconds, default hourly, 0 disables).

  • Order-independent sink takeover: whichever order the host calls AddNexoAutonomy and this, the retaining sink serves — a theory pins both orders, because the failure mode (digest renders an empty history while the loop swaps away) would be silent.
  • Saturation honesty: a full ring names how many events fell off rather than presenting a truncated history as complete.
  • Single-op controls (pause, rollback, demote) stay on the authority services. A rendering job is not a control surface.

3. HostServicesOnly is settled, not pending

The fail-closed refusal in the Docker backends is now documented as the permanent posture. The one workload that ever seemed to need the mode — package restore during the in-session build — was solved without network in P3 (offline restore from SDK packs, cleared sources). A model server, the other imagined consumer, belongs on the proposer side of the boundary, not inside a certification session. The enum member stays declared for a backend that can genuinely realize per-session egress rules; none is planned. Recorded under "Settled decisions" in the evidence doc.

Testing

  • In-container, 32/32 across the four touched suites: GenerationWatchWindowTests (+SlowInvocation_BreachesTheAbsoluteDurationCeiling_WithoutNeedingABaseline), AutonomyDigestJobTests (new: bounded ring, saturation note, both composition orders, interval-0 quiet decline), AutonomyCompositionTests (+2 validator rows), AutonomousIterationHarnessTests (unchanged, regression guard)
  • make kernel-coverage-gate — runs in CI (Infrastructure paths touched)

🤖 Generated with Claude Code

…led HostServicesOnly
The final phase of the post-merge plan - three small closures.
Watch window (R5.2): WatchThresholds.MaxInvocationDuration is an ABSOLUTE
per-invocation wall-clock ceiling, judged like the contract leg - no
baseline, no minimum invocation count - because a first-generation deploy
has no baseline for the relative legs and a pathological single invocation
must not hide inside a healthy mean. Wall clock is the one per-invocation
resource honestly measurable in a shared host process; per-brick memory or
CPU attribution is not, and the doc says so instead of pretending.
Configured via Nexo:Autonomy:WatchMaxInvocationSeconds (0 = off).
Digest (spec 7): AddNexoAutonomyDigestJob retains swap provenance in a
bounded ring (RecordingBrickSwapProvenanceSink - still logs every event,
so R2.1 holds) and renders the human digest on cadence
(DigestIntervalSeconds, 0 disables). The sink takeover is
order-independent with AddNexoAutonomy, and a saturated ring names what
fell off rather than presenting a truncated history as complete.
Single-op controls stay on the authority services - a rendering job is
not a control surface.
HostServicesOnly: the fail-closed refusal is now documented as the settled
posture, not a v1 gap. The one workload that seemed to need the mode -
in-session package restore - was solved offline in P3, and a model server
belongs on the proposer side of the boundary. The enum member stays for a
backend that can genuinely realize per-session egress; none is planned.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursorBot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Base automatically changed from feat/autonomy-session-build to masterAugust 14, 2026 16:04
@IanFrelinger
IanFrelinger merged commit b8b29d3 into masterAug 14, 2026
15 checks passed
@IanFrelinger
IanFrelinger deleted the feat/autonomy-watch-digest-decisions branch August 14, 2026 16:04
Sign up for freeto 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

@IanFrelinger@PlzTouchGrass