Repository navigation
Conversation
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.
# Conflicts: # cron/jobs.py
# 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
Compose reviewed provider reset backoff, task-bound Kanban guidance, and fire-fence terminal durability from cumulative head 7d030ba onto current main 79445a4. Preserve the prior candidate as the second parent while retaining current-main content for separately owned lifecycle and dispatcher workstreams.
Summary: Restores cumulative runtime safeguards on the cron path: task-bound Kanban guidance (fail-closed), clean-worker-exit lifecycle verification with durable read-back, fire-fence contention handling, and a durable provider rate-limit backoff policy. Large PR (~24 files) dominated by new tests (~1.3k lines). Findings (Non-blocking):
Verdict: Looks good. Nothing blocking. |
|
Cumulative P0 provider-health continuation is now pushed on this existing PR branch at exact head |
Summary
7d030bace2240baaacd6ae603f2ccc57fcfa15e6as the merge commit's second parent while retaining current-main content for separately owned lifecycle/dispatcher workProvenance
79445a496c86a19332ad786494b8384d2167e2d07d030bace2240baaacd6ae603f2ccc57fcfa15e6f40e3977a327b8c5c3f3edad7b957d75a0cf6a199b26dcb9fb1f5425b198495b655d7ef54304da3f,51e201b67397fb596cab6af88d5ac799f8d5122e,991095136967b0f2776d451bde02dcc05b5ad0ea,d74a8d157a5a4e3fabac716df2d9c14420ec34ae97ac4a6c5eb661cc963521cd9180db518cb28e01Verification
ruff,compileall, compat-pointer checker, andgit diff --checkpassBoundaries
agent/kanban_stop.py,tools/delegate_tool*.py, andhermes_cli/kanban_db_dispatch.pyare untouched