fix(board): nothing_to_propose exit for Board Program explorers + PR checks on slave-based PRs (#712)

* fix(board): give Board Program explorers a nothing_to_propose exit

Every propose_* verb requires at least one item, so an explorer that
legitimately found nothing — Barfly with no worthwhile X conversations,
Coroner with no autopsy subject — had no way to close its exploration
task. It declined, called i_am_idle(), and the task stayed PENDING
forever: the dispatcher re-matched it every tick and respawned the board
agent (~$0.61 a spawn, ~3 per 5-minute respawn-breaker cooldown window,
indefinitely), and BoardProgramEngine's one-open-cycle dedup wedged that
whole program shut, since the ledger row only closes once its exploration
task goes terminal.

nothing_to_propose(task_id, reason) is the explicit exit. task_id is
required rather than inferred: one explorer role owns several
independently-cadenced programs (head_marketing owns six) and each
assigns its exploration task to the same agent, so several are open at
once by design and guessing "the caller's oldest" completes the WRONG
cycle — stamping its reason onto an unrelated program's ledger while the
task actually being worked stays wedged. Resolution validates the named
task exists, carries a registered program source, is assigned to the
caller, and is non-terminal, then gates on the program's declared
explorer role from the registry, so a program registered later needs no
edit here.

The reason lands on board_program_cycles (migration 089) and renders into
the next cycle's LEARN context, replacing a bare "proposed 0, approved 0"
with why. That write runs in its own savepoint: it flushes on the same
session as the completion, and a bare try/except around a same-session
flush leaves the transaction pending-rollback, so a DB blip there would
discard the completion at the post-response commit while the verb
reported success.

All fourteen exploration prompts offer the exit, pinned by a
registry-parametrized test that fails when a future program is unwired.

* ci: fire PR checks on slave-based PRs, not master alone

All five gating workflows declared `pull_request: branches: [master]`,
but every fleet PR targets slave — cell->root, root->slave, and the CEO's
own. So `pull_request` never fired for any of them, and their only
coverage was the `push` trigger, which is gated on branch PREFIX
(feature/bug/chore/docs/hotfix). A branch named anything else got zero
checks — not a red run, an absent one — and a PR with no required check
present merges on a false green. PR #711 shipped that way on a `fix/`
branch.

Basing on the branch a PR merges INTO rather than what its head is named
makes coverage independent of branch naming, so a non-conforming prefix
can only ever cost the redundant push run, never the whole gate.

The same five also omitted slave from `push` (ci.yml aside, which added
it for the release gate's fail-closed CI read), so the panel suite, both
CodeQL analyses, and the e2e smoke never ran on the trunk master is cut
from.

---------

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
Renzo F
2026-07-27 01:28:33 +02:00
committed by GitHub
co-authored by Renn F
parent a7b970a3b2
commit 42f8a5d18e
21 changed files with 1055 additions and 41 deletions
+8
View File
@@ -53,6 +53,14 @@ on:
pull_request:
branches:
- master
# Every fleet PR targets the dev branch, not master (cell->root and
# root->slave alike). Listing master alone meant `pull_request` never
# fired for them, so their ONLY coverage was the `push` trigger above
# — which is branch-PREFIX gated, silently leaving any head outside
# feature/bug/chore/docs/hotfix with zero checks rather than a red
# one. Basing on the target branch (what the PR merges INTO) instead
# of the head's name makes coverage independent of branch naming.
- slave
paths:
- 'roboco/**'
- 'agents/**'
+3 -2
View File
@@ -7,7 +7,7 @@ on:
# merge API (see ci.yml for the live-proven receipts); `push` does, so
# it's the redundant trigger for a required check that must not go
# ABSENT on a fleet-authored PR revision.
branches: [master, 'feature/**', 'bug/**', 'chore/**', 'docs/**', 'hotfix/**']
branches: [master, slave, 'feature/**', 'bug/**', 'chore/**', 'docs/**', 'hotfix/**']
paths:
- 'roboco/**'
- 'agents/**'
@@ -16,7 +16,8 @@ on:
- 'pyproject.toml'
- '.github/workflows/code-ql.yml'
pull_request:
branches: [master]
# Fleet PRs target the dev branch — see ci.yml's pull_request note.
branches: [master, slave]
paths:
- 'roboco/**'
- 'agents/**'
+3 -2
View File
@@ -7,12 +7,13 @@ on:
# merge API (see ci.yml for the live-proven receipts); `push` does, so
# it's the redundant trigger for a required check that must not go
# ABSENT on a fleet-authored PR revision.
branches: [master, 'feature/**', 'bug/**', 'chore/**', 'docs/**', 'hotfix/**']
branches: [master, slave, 'feature/**', 'bug/**', 'chore/**', 'docs/**', 'hotfix/**']
paths:
- 'panel/**'
- '.github/workflows/codeql-js-ts.yml'
pull_request:
branches: [master]
# Fleet PRs target the dev branch — see ci.yml's pull_request note.
branches: [master, slave]
paths:
- 'panel/**'
- '.github/workflows/codeql-js-ts.yml'
+5
View File
@@ -4,6 +4,9 @@ on:
push:
branches:
- master
# The dev branch: every fleet PR merges here, so without it the smoke
# suite never ran on the trunk that master is cut from.
- slave
# Fleet task branches: `pull_request`'s synchronize trigger doesn't
# reliably fire when a revision lands on a PR head via the merge API
# (see ci.yml for the live-proven receipts); `push` does.
@@ -23,6 +26,8 @@ on:
pull_request:
branches:
- master
# Fleet PRs target the dev branch — see ci.yml's pull_request note.
- slave
paths:
- 'roboco/**'
- 'alembic/**'
+5
View File
@@ -4,6 +4,9 @@ on:
push:
branches:
- master
# The dev branch: every fleet PR merges here, so without it the panel
# suite never ran on the trunk that master is cut from.
- slave
# Fleet task branches: `pull_request`'s synchronize trigger doesn't
# reliably fire when a revision lands on a PR head via the merge API
# (see ci.yml for the live-proven receipts); `push` does.
@@ -18,6 +21,8 @@ on:
pull_request:
branches:
- master
# Fleet PRs target the dev branch — see ci.yml's pull_request note.
- slave
paths:
- 'panel/**'
- '.github/workflows/panel-ci.yml'