Skip to content

spec: stop-1.md — recency-targeted stop (no escalation on silence), RECOMMENDED timeouts, shared_pipeline_id defined - #117

Open
JarbasAl wants to merge 1 commit into
devfrom
spec/stop-1
Open

spec: stop-1.md — recency-targeted stop (no escalation on silence), RECOMMENDED timeouts, shared_pipeline_id defined#117
JarbasAl wants to merge 1 commit into
devfrom
spec/stop-1

Conversation

@JarbasAl

@JarbasAl JarbasAl commented Jul 4, 2026

Copy link
Copy Markdown
Member

🤖 Auto-generated by Claude Fable 5 (claude-fable-5) via Claude Code — NOT human-reviewed. Verify before acting. Cross-spec citations were model-verified against dev source; behavior-change sections need owner judgment.

Refines OVOS-STOP-1 for internal purity and self-consistency (per-file split of the consistency audit).

Owner decision needed — coverage gap left open (F5)

Removing escalation-on-silence closes a destructive failure mode, but it opens a reachability gap that this PR does not close.

Non-skill actors — media playback, TTS, GUI — are reachable only through the ovos.stop broadcast (§5.3). They are not skills, so they never appear in active_handlers and never answer the ping. Before this change, a silent ping round escalated to global_stop and the broadcast reached them. Now, if any skill is nominally listed in active_handlers and stays silent, the stop targets that skill instead, and TTS keeps speaking.

Two mitigations exist. Neither is implemented here; pick one and it goes into a follow-up.

  1. Require user-visible-activity components in active_handlers. Media, TTS and GUI would register activity in active_handlers under their own identifiers, making them ordinary recency candidates and ordinary ping responders. This changes what active_handlers means — it stops being a skill-activation record and becomes an activity record — and it touches PIPELINE-1 §7.1 stamping.
  2. Define a second-chance broadcast rule. A generic stop that produced no positive responder targets by recency as specified here, and additionally emits ovos.stop (or a narrower broadcast) so non-skill actors still hear it. This keeps active_handlers as it is but weakens the "silence is never destructive" property this PR establishes.

Changes

Selection (§4.1)

  • Step 4 selects only among positive pong responders. A silent but recent handler can no longer outrank a handler that answered the ping. In the previous text this was left implicit and the literal reading let recency win.
  • An explicit candidate filter runs before any recency comparison: an entry is skipped when its skill_id is in session.blacklisted_skills, or when it names the stop plugin's own pipeline_id. If no candidate survives at step 4 or step 5, match returns None and the orchestrator continues to the next stage.
  • An explicit recency rule: highest activated_at wins; on a tie, the entry nearest the head of active_handlers — the most recently pushed. OVOS-PIPELINE-1 §7.1 is named as the single normative home of both the push mechanics and the tie-break; this spec only applies them. This replaces the previous "entry appearing latest in the list", which inverted PIPELINE-1's model.
  • Exactly one skill is stopped per stop utterance, stated normatively for the first time.

Recency-targeted stop, never escalation-by-silence (§4.1 step 5, §4.2, §5.1)

A generic stop with no positive pong responder falls back to the most recently activated remaining active_handlers entry and MUST NOT escalate to global_stop. global_stop keeps exactly two triggers: explicit global-stop vocabulary, and an active_handlers list that is empty or holds only the stop plugin's own entry.

Pong validity (§4.2)

  • A pong is valid only with a skill_id string and a can_handle boolean. Missing or non-boolean can_handle (no truthy coercion) and a skill_id that does not match the emitting handler both mean not stoppable.
  • First valid pong from a skill_id wins; later pongs from that skill_id are ignored; post-timeout pongs are ignored and the selection is final.
  • This is what OVOS-FALLBACK-1 already claims uniformity with. The claim is now true.
  • "MUST respond can_handle: false or remain silent" becomes "MUST NOT respond can_handle: true" — the prohibition is the invariant; the two permitted behaviours are not.
  • The ping is derived via reply from the inbound utterance Message, and the pong via reply from the ping (OVOS-MSG-1 §5.2). Both were previously left to inference.

<shared_pipeline_id> and the post-global_stop state (§3.1, §5.2, §6.2)

  • §5.2 is the single normative home of the definition. §3.1 cross-references it instead of restating the dedup obligation.
  • §5.2 and §6.2 are reconciled. global_stop is not a reserved intent_name, so PIPELINE-1 §7.1 stamps the stop plugin's own entry after the wipe. The committed post-dispatch state is active_handlers == [<shared_pipeline_id> entry], not []. §6.2 said "empty entirely", which was never the observable outcome.
  • Because §4.1 excludes that entry from candidacy and step 1 treats such a list as empty, a following generic stop resolves to global_stop again instead of dispatching <stop_plugin_id>:stop forever.

Denylists (§6.3)

blacklisted_intents entries are qualified <skill_id>:<intent_name> pairs (PIPELINE-1 §5.4); the bare-intent_name lead-in is corrected. The plugin-side MUST is noted as a deliberate strengthening of the orchestrator-side filter — it keeps a blacklisted target out of the recency selection instead of discarding the Match afterwards.

Timeouts (§4.1)

Ping-pong window is a RECOMMENDED default of 0.5 s, SHOULD NOT exceed 1 s. The hardcoded window value no longer appears in prose.

Editorial

Rationale prose is removed from the normative sections (step-5 justification, the §5.2 converse aside, the §7 example pipeline listing). A cross-protocol note records that the pong boolean's field name is protocol-local: can_handle here and in FALLBACK-1, result in CONVERSE-1, can_answer in COMMON-QUERY-1.

Compatibility

Version stays 2. VERSIONING.md defines the field as the V0-compatibility class, which these edits do not change. The removal of escalation-on-silence is a behaviour change within version 2 and the CHANGELOG says so explicitly: an implementation built against the earlier text wiped active_handlers, converse_handlers and response_mode whenever a pong was late; it now stops one skill instead.

Cross-spec

Depends on OVOS-PIPELINE-1 landing the activated_at tie-break in §7.1 (nearest-the-head), which this spec cites rather than restates. GLOSSARY rows for the stop family follow this PR's final wording.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@JarbasAl, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: da57902b-6148-4733-9f31-70389eae5b44

📥 Commits

Reviewing files that changed from the base of the PR and between 1d3622b and ec8f670.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • stop-1.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch spec/stop-1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@JarbasAl
JarbasAl marked this pull request as ready for review July 16, 2026 07:21
@JarbasAl
JarbasAl marked this pull request as draft July 24, 2026 02:07
JarbasAl added a commit that referenced this pull request Aug 4, 2026
…1.1 cites

- divergences.md: drop the STOP-1 no-escalation entry — current dev
  stop-1.md §4.1 step 5 still escalates to global_stop on a silent
  poll; the entry described PR #117's proposed (draft, unmerged)
  behavior as if it were the shipped spec. Fix the dangling §9.4 cite
  for ovos.intent.unmatched to §9.3.
- gaps.md: tighten the audio-inbound gap with an explicit
  AUDIO-IN-1 §1 capture-out-of-scope cite; narrow the bridge
  managing-mode race entry — BRIDGE-1 §3.4.2 already defines a
  MAY-fallback (inject on last known session), only the
  queue-vs-drop policy for a second overlapping utterance is open.
- patterns.md / reference.md: fix the nonexistent
  <owner_id>.converse.response citation to the real
  <skill_id>.converse.pong (CONVERSE-1 §4.2).
- rationale.md / reference.md §6.1: restore the MSG-1 v2 §2.1.1
  section tag for the topic-naming-convention citation instead of
  the bare §2.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@JarbasAl
JarbasAl marked this pull request as ready for review August 4, 2026 12:46
…ECOMMENDED timeouts, shared_pipeline_id defined

Squashed from:
- spec: stop-1.md — positive-responder selection, head tie-break, self-exclusion, pong validity
- spec: OVOS-STOP-1 — recency fallback instead of global escalation, RECOMMENDED ping timeout, shared_pipeline_id defined

Co-Authored-By: Claude Fable 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