Skip to content

fix(agent): compose task-bound cron protocol gate with fleet fixes - #102988

Open
jayleaton wants to merge 17 commits into
NousResearch:mainfrom
jayleaton:wt/t_cc6ebc69
Open

jayleaton wants to merge 17 commits into
NousResearch:mainfrom
jayleaton:wt/t_cc6ebc69

Conversation

@jayleaton

Copy link
Copy Markdown

Summary

Verification

  • focused protocol + cumulative behavior matrix: 196 passed
  • broad cron + Kanban regression matrix: 1623 passed, 4 Windows-only skipped
  • Python compileall passed
  • git diff --check passed

Rollout guard

No merge. Managed gateway replacement remains gated on RSI last_tick.json unix > 1788535090.

jayleaton and others added 14 commits September 3, 2026 03:59
A decomposed child with workspace_kind=worktree and no explicit path got
workspace_path=NULL. Dispatch then tried to anchor it on the board's
default_workdir and, when the board had none, failed the spawn with
'no default_workdir set' — twice, tripping the failure-limit circuit
breaker (live: t_ab2a7ce8, t_2dd0f5b7, 2026-09-02).

The root of a decomposed callback graph is usually itself a
dispatcher-materialized worktree <repo>/.worktrees/<root-id>, so the
repo is recoverable from the root row: when the root path is a linked
worktree checkout, stamp each pathless worktree child with the root's
git common-dir parent (the main repo) as its explicit anchor. Children
still get per-task worktrees (never the root's literal checkout), so
sibling isolation is unchanged; a repo that can't be recovered keeps
the anchorless row and the board-default dispatch path; scratch roots
are untouched.

Regression tests cover anchor inheritance + end-to-end child spawn
resolution with no board default_workdir, the unrecoverable-root
fallback, and scratch-root non-leakage.
A task whose title/body carries the durable PRODUCT_SIGNOFF marker defines
its job as reporting back for human sign-off rather than driving to a
terminal lifecycle transition. Repeated clean exits without one are a
property of that workflow, so _account_protocol_violation now classifies
such tasks at accounting time (read from the task row, so the exemption
survives retries, reclaims, and dispatcher restarts) and never auto-blocks
them — the violation is still recorded and the task retried, but the
gave_up breaker never fires across any number of limit-reaching runs.

Review round 1 correction for t_4067fdf1: the one-run PRODUCT_SIGNOFF test
could not reach the breaker; it is replaced by a regression that drives the
task through the full violation limit and proves it stays ready with no
gave_up event, while ordinary coder/QA omissions keep their bounded
retry/block behavior (covered by the existing limit test).
…wnership loss (c-027)

heartbeat_fire_claim() collapsed fire-fence acquisition failure into
False. During slow fenced delivery the worker's own heartbeat thread
cannot acquire the same process-local RLock, so a successfully
delivering run was misclassified as ownership loss and terminalled as
'Interrupted by shutdown before terminal completion.' (TrustMRR exec
4219b48d while RSI recovery exec f502e929 was settling).

Tri-state contract:
- True  = renewed/confirmed owner
- False = authoritatively inspected: owner mismatch / absent claim
- None  = fence unavailable/unconfirmed (contention or store error)

- initial validation stays fail-closed: run starts only on exactly True
- heartbeat loop: None rides the existing grace window (180s prod vs
  30s fence wait); immediate cancel only on explicit False
- post-run probes (_fire_claim_ownership_lost, both interrupted blocks,
  terminal owner-CAS read): None can never adjudicate a confirmed loss;
  uncertain outcomes get distinct ledger errors
- mark_job_run also tri-state: None = fence unavailable (CAS never ran),
  False stays reserved for confirmed owner mismatch
- _side_effect_fence unchanged: still the exactly-once save/delivery
  barrier

Tests (all written red-first, verified failing on unfixed code):
slow_owned_delivery (parent handoff), sustained fence-contention grace,
pre/post-delivery None probes, grace-exhausted None probe, terminal
write None, mark_job_run fence-unavailable None, RSI recovery dispatch
fails closed during original's fenced delivery, TrustMRR slow-owned
delivery terminal success. Managed-gateway restart E2E (systemd scope)
passes on host: one gateway, single side effect, single delivery.
@alt-glitch alt-glitch added invalid This doesn't seem right comp/cron Cron scheduler and job management comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have labels Sep 4, 2026
# Conflicts:
#	agent/agent_init.py
#	agent/system_prompt.py
#	cron/jobs.py
#	cron/scheduler.py
#	cron/scheduler_provider.py
#	hermes_cli/kanban_db.py
#	hermes_cli/web_server.py
#	plugins/cron_providers/chronos/__init__.py
#	tools/cronjob_tools.py

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard comp/cron Cron scheduler and job management invalid This doesn't seem right P3 Low — cosmetic, nice to have

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants