Skip to content

fix: hold the wording path to the same bar as the sentinel path - #5

Open
cannabinoids wants to merge 1 commit into
michelhelsdingen:mainfrom
cannabinoids:fix/completion-detection
Open

fix: hold the wording path to the same bar as the sentinel path#5
cannabinoids wants to merge 1 commit into
michelhelsdingen:mainfrom
cannabinoids:fix/completion-detection

Conversation

@cannabinoids

@cannabinoids cannabinoids commented Aug 13, 2026

Copy link
Copy Markdown

Rebased onto current main. 1782034 covers the case that killed the four-agent
research team — raised idle thresholds plus CONTINUATION_PATTERNS for progress
reports — so this is now scoped to three things that fix does not reach. Reproductions
are in #4.

What changes

The wording path still ends a run on two agents, whatever the team size.
hasTwoRecentCompletionSignals returns true for any two distinct agents, so once a
trio is quiet past TWO_SIGNAL_IDLE_THRESHOLD_MS the third can still be cut off by the
other two — which is what the comment directly above that call warns about. It becomes
hasRecentCompletionSignalsFromAll: same sliding window, every active agent must appear
in it. The sentinel path already holds this bar.

Two guards on the heuristic path, inside isCompletionStatement and placed after
the CLOSING_PATTERNS check, so an unambiguous sign-off still wins outright:

  • a sign-off is short — a 600-character analysis containing "done" is an agent working
  • a sign-off does not quote the machinery

The second came from a review task pointed at scripts/collab-poll.sh: both agents
quoted its own ---STATUS:{ACTIVE,QUIET,DONE,WAITING} sentinel and the run ended
mid-analysis. CONTINUATION_PATTERNS doesn't catch those, because nothing in them
announces further work — they aren't progress reports, they're descriptions of the
protocol.

Completion counts only from the last user message. ensemble steer exists so a user
can redirect a running team, but a sentinel sent before the redirect still counted, so a
team could disband while an agent was answering the new instruction — observed with a 15
second gap between the sentinel and the interjection. "Wrap it up" followed by sentinels
still disbands.

Tests

Nine specs: five in premature-disband.test.ts (machinery-quoting, DONE-protocol talk,
team-say announcements, the long-analysis case, and a genuine short sign-off still
counting), four in ensemble.test.ts (trio needs all three; sentinels before a user
interjection are void; sentinels after it still disband). All nine fail on main and
pass with this change.

tsc --noEmit and eslint clean. The whole suite passes except
onboarding-smoke.test.ts, which times out on my machine at the default 5s and is
untouched here — it's green in your CI, so it looked like my hardware rather than
something to change in your repo.

Not included

Deliberately narrow. A separate branch carries user-interjection ergonomics (durable
per-agent inbox, idle-gated delivery, pause/resume), agent-transcript isolation via
--append-system-prompt-file and a pinned --session-id, and ollama-backed agents via
ollama launch. Those change behaviour rather than fixing defects, so they stay out
unless you want them.

cannabinoids added a commit to cannabinoids/ensemble that referenced this pull request Aug 13, 2026
Upstream moved 16 commits while this branch sat on an old base, and several of
those commits covered the same ground. Rather than replay our history through
the conflicts, this reapplies what is still ours onto upstream's code.

Dropped as superseded: our preflight agent-scoping (upstream's is broader and
covers grok), our trio-aware prompt wording, our sentinel-path disband fix, and
our launcher template flag -- upstream has all four, in some cases better.

Kept, re-applied onto upstream's versions: user interjection with a durable
per-agent inbox and idle-gated delivery, pause/resume, agent transcript pinning
and archiving, the watchdog participation and busy-pane gates, ollama-backed
agents, positional --roles, monitor keys 1-9 and p, the API-key cost guard, and
project-context prompts.

The disband work now sits on upstream's shape: their sentinel path and idle
threshold are untouched, and ours adds the all-agents bar on the wording path,
the sign-off content guards, and the user-redirect cutoff -- the same change
proposed in PR michelhelsdingen#5.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rebased onto main after 1782034. That commit raised the idle thresholds and
added CONTINUATION_PATTERNS, which covers progress reports -- the case that
killed the four-agent research team. Three things it does not cover remain.

The wording path still ends a run on two agents, whatever the team size.
`hasTwoRecentCompletionSignals` returns true for any two distinct agents, so
once a trio is quiet past TWO_SIGNAL_IDLE_THRESHOLD_MS the third can still be
cut off by the other two -- exactly what the comment above the call warns
about. It now requires every active agent, matching the sentinel path.

Two guards on the heuristic path in isCompletionStatement, after the explicit
CLOSING_PATTERNS check so an unambiguous sign-off still wins outright. A
sign-off is short, and it does not quote the machinery: on a review task
pointed at collab-poll.sh both agents quoted its own
---STATUS:{ACTIVE,QUIET,DONE,WAITING} sentinel inside long analysis messages,
and that ended the session. CONTINUATION_PATTERNS does not catch it, because
nothing about those messages announces further work.

Completion is also counted only from the last message the user sent. `ensemble
steer` exists so a user can redirect a running team, but a sentinel from
before the redirect still counted, so a team could disband while an agent was
answering the new instruction -- seen live with a 15s gap between the sentinel
and the interjection. "Wrap it up" followed by sentinels still disbands.

Nine specs added, five in premature-disband.test.ts and four in
ensemble.test.ts. All nine fail on main and pass with the change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@cannabinoids
cannabinoids force-pushed the fix/completion-detection branch from b3c8658 to 1d8a80a Compare August 18, 2026 17:23
cannabinoids added a commit to cannabinoids/ensemble that referenced this pull request Aug 18, 2026
Upstream shipped 8 commits while this branch sat still. Unlike the last sync,
none of it superseded ours -- it is complementary, so everything here is our
work re-applied onto his newer code rather than dropped.

Watchdog: his failed-nudge ceiling (measured 45.088 failed nudges across 7
teams) decides when to stop retrying a vanished session; our two gates decide
which agents may be nudged at all -- one that never received the task prompt,
or one whose pane is mid-generation, is left alone. His runaway fixtures now
set promptInjectedAt, because a spawned agent whose session later vanished has
it in production, and without it the gate correctly refuses to nudge.

Agents: our systemPromptFileFlag / sessionIdFlag / transcriptPathTemplate are
now optional fields on his agent config contract, and the ollama entries sit
beside his glm and grok. His loader rejects unknown agent names instead of
silently spawning a second claude, which is strictly better than what we had.

Disband: carries the same three changes as PR michelhelsdingen#5, on his shape -- the wording
path held to every active agent, the short/no-machinery guards on the
heuristic path, and completion counted only from the last user redirect (here
also honouring lastResumedAt, which the fork has and upstream does not).

Prompt, interjection, pause/resume, transcript archiving and the CLI surface
are re-applied unchanged in behaviour, on his current wording.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant