Skip to content

OVOS-STOP-1 v1 — stop pipeline plugin specification#33

Merged
JarbasAl merged 21 commits into
devfrom
spec/stop-1-draft
May 27, 2026
Merged

OVOS-STOP-1 v1 — stop pipeline plugin specification#33
JarbasAl merged 21 commits into
devfrom
spec/stop-1-draft

Conversation

@JarbasAl

@JarbasAl JarbasAl commented May 27, 2026

Copy link
Copy Markdown
Member

Summary

New normative spec OVOS-STOP-1 v1 defining the stop pipeline plugin role: the two reserved intent_names stop and global_stop, the ping-pong stoppability discovery, the LIFO cascade across session.active_handlers, and the ovos.stop universal broadcast namespace.

Design highlights

  • Two reserved intent_names (registered against PIPELINE-1 §7.3): stop (skill-directed cascade) and global_stop (universal broadcast).
  • In-match ping-pong as the parallel feasibility filter. Documented exception to PIPELINE-1 §4.4 latency guidance, justified by the stop plugin's escape-hatch pipeline position (first stage).
  • LIFO cascade across session.active_handlers: target = most-recent positive pong responder. Match.skill_id carries the target; dispatch is a standard <target>:stop PIPELINE-1 dispatch with full handler-lifecycle trio.
  • Single broadcast pair ovos.stop.ping / ovos.stop.pong — no dynamic per-skill topic enumeration. Responders include their skill_id in the pong payload.
  • global_stop triggers ovos.stop broadcast — fired on explicit "stop everything" vocab, empty active_handlers, or no positive pong responders.
  • Self-pruning rule: skills SHOULD remove themselves from active_handlers when unstoppable, so future ping rounds bypass them.
  • Session scoping: every stop subscriber (skill handlers and ovos.stop broadcast listeners) MUST cease only the activity keyed to the inbound session_id.
  • 5-topic bus surface: 3 static reserved topics under ovos.stop.* + 2 dispatch shapes.

Companion specs

  • OVOS-MSG-1 — envelope, forward / reply / response.
  • OVOS-PIPELINE-1 — pipeline-plugin contract, dispatch shape, lifecycle trio, reserved-name registry §7.3.
  • OVOS-SESSION-1 — session field registry (no new fields claimed).
  • OVOS-SESSION-2 — mutation boundaries, session-keyed-state projection.
  • OVOS-CONVERSE-1 — session.active_handlers recency list, session.response_mode (cleared via Match.updated_session on stop).

Notes

  • Spec body is implementation-agnostic — no real-project names outside the spec-ID namespace.
  • This PR adds a single file (stop.md) against origin/dev per the standing one-file-per-PR rule.
  • CHANGELOG entry is intentionally deferred until the cross-spec dependency on CONVERSE-1 is reviewed.

Test plan

  • Review §4.1 cascade algorithm against the worked example: TTS speaking + timer ringing + music playing, "stop" cascade.
  • Confirm ovos.stop.* namespace reservation does not clash with any existing or in-flight spec.
  • Confirm in-match bus exchange waiver in §3.2 is acceptable as the documented PIPELINE-1 §4.4 exception.
  • Confirm self-pruning SHOULD (§4.4) aligns with CONVERSE-1's intended active_handlers mutation pathway.
  • Confirm session-scoping rules (§4.3, §5.2, §9 conformance) compose correctly with SESSION-2 §2.4 projection mandate.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Introduced OVOS-STOP-1 specification defining stop pipeline plugins, stop cascade algorithm, active handler management, and conformance requirements
    • Updated orchestrator stack documentation and reading order guidance for plugin authors and orchestrator builders
    • Revised session specification for handler tracking with updated identifier structure

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9e554ccb-10d7-404f-aef0-03d6893cd75b

📥 Commits

Reviewing files that changed from the base of the PR and between 6f90ab9 and 8ef3292.

📒 Files selected for processing (4)
  • README.md
  • ovos-pipeline-1.md
  • ovos-session-1.md
  • ovos-stop-1.md

📝 Walkthrough

Walkthrough

This PR introduces OVOS-STOP-1, a complete stop pipeline plugin specification, and integrates it across the architecture by updating session field contracts, pipeline dispatch mechanics, and documentation indices to support the stop cascade mechanism.

Changes

Stop Pipeline Plugin Specification and Integration

Layer / File(s) Summary
Session active_handlers field contract
ovos-session-1.md
session.active_handlers field changes from array of {id, activated_at} owned by OVOS-CONVERSE-1 to array of {skill_id, activated_at, ...} owned by OVOS-PIPELINE-1, establishing the data contract for handler tracking.
Pipeline dispatch handler tracking and stop intent
ovos-pipeline-1.md
Orchestrator pushes {skill_id, activated_at} entries to session.active_handlers at dispatch time with skill_id-based eviction; suppresses this push for reserved-intent dispatches; reserves new stop intent name to OVOS-STOP-1 alongside existing converse and response reserved names.
Stop pipeline specification
ovos-stop-1.md
Comprehensive v1 specification defining stop (directed) and global_stop (broadcast) intents, ping/pong stoppability discovery with timeout, LIFO handler selection by activated_at timestamp, Match.updated_session requirements for draining active_handlers/converse_handlers and clearing response_mode, universal ovos.stop broadcast obligations, conformance checklists, and deployment positioning guidance.
Documentation index update
README.md
Adds OVOS-STOP-1 to orchestration spec table and includes STOP-1 in the "Reading order by role" guidance for pipeline plugin authors and orchestrator builders.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • OpenVoiceOS/architecture#22: Updates session specification and active_handlers registry alongside the main PR's active_handlers field shape and ownership change.
  • OpenVoiceOS/architecture#11: Updates OVOS-PIPELINE-1 reserved intent_name dispatch semantics and session.active_handlers handler lifecycle that the main PR extends to support the new stop reserved intent.
  • OpenVoiceOS/architecture#9: Establishes the OVOS-INTENT-4 "reserved intent_names are malformed and not indexed" contract that the main PR uses to register the stop and global_stop reserved intent names.

Poem

🐰 A stop in every pipeline,
Handlers halt in perfect line,
Ping then pong, the waltz divine,
Session drains, all tasks align.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely summarizes the primary change: introduction of the stop pipeline plugin specification (OVOS-STOP-1 v1).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch spec/stop-1-draft

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 and usage tips.

@JarbasAl JarbasAl marked this pull request as draft May 27, 2026 00:54

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@stop.md`:
- Around line 265-269: The stop plugin selection logic must explicitly handle
blacklisted intents/skills: update the algorithm in sections §4.1 and §6.3 to
state that when evaluating a stop candidate (a handler with an intent of form
"<target_skill_id>:stop" or pipeline-local "<own_pipeline_id>:global_stop"),
first check session.blacklisted_skills and session.blacklisted_intents; if the
handler.owner_id or the intent string is present in the denylist, treat that
candidate as ineligible and skip to the next candidate, and if no eligible
candidates remain return None (no dispatch) rather than escalating or
dispatching anyway; document this precedence and the fallback (skip -> next
candidate -> return None) so behavior for stop() and global_stop() selection is
deterministic.
- Around line 286-296: The fenced code block showing the session.pipeline array
lacks a language tag which triggers MD040; update the fence to include a
language (use "yaml") for the block containing session.pipeline and its entries
(e.g., "stop_high", "converse", "intent_matcher_high", "stop_medium",
"intent_matcher_medium", "stop_low", "intent_matcher_low") so tooling/linters
recognize the language and the MD040 warning is resolved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7a5f250f-0c85-4b8e-bd67-536bd58718cd

📥 Commits

Reviewing files that changed from the base of the PR and between 7dba0e5 and 6f90ab9.

📒 Files selected for processing (1)
  • stop.md

Comment thread ovos-stop-1.md
Comment on lines +265 to +269
A stop plugin MUST honour `session.blacklisted_skills` and
`session.blacklisted_intents` (PIPELINE-1 §5.3–§5.4). A handler
whose `owner_id` appears in `blacklisted_skills` MUST NOT be
pinged or selected as a stop target.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Resolve denylist behavior conflict for stop/global_stop dispatch selection.

The spec says stop plugins MUST honor session.blacklisted_intents, but the algorithm doesn’t define what to do when <target_skill_id>:stop or <own_pipeline_id>:global_stop is blacklisted. Different implementations could either return None, escalate, or still dispatch. Please add explicit precedence/fallback rules in §4.1/§6.3 so behavior is deterministic.

Proposed normative patch
 ## 6.3 Denylists

 A stop plugin MUST honour `session.blacklisted_skills` and
 `session.blacklisted_intents` (PIPELINE-1 §5.3–§5.4). A handler
 whose `owner_id` appears in `blacklisted_skills` MUST NOT be
 pinged or selected as a stop target.
+For candidate selection, the plugin MUST also exclude any target
+whose dispatch identity `<owner_id>:stop` appears in
+`blacklisted_intents`.
+If explicit "stop everything" or cascade fallback would produce
+`<own_pipeline_id>:global_stop` and that identity is blacklisted,
+the plugin MUST return `None` (decline) for that utterance.

Also applies to: 319-330

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@stop.md` around lines 265 - 269, The stop plugin selection logic must
explicitly handle blacklisted intents/skills: update the algorithm in sections
§4.1 and §6.3 to state that when evaluating a stop candidate (a handler with an
intent of form "<target_skill_id>:stop" or pipeline-local
"<own_pipeline_id>:global_stop"), first check session.blacklisted_skills and
session.blacklisted_intents; if the handler.owner_id or the intent string is
present in the denylist, treat that candidate as ineligible and skip to the next
candidate, and if no eligible candidates remain return None (no dispatch) rather
than escalating or dispatching anyway; document this precedence and the fallback
(skip -> next candidate -> return None) so behavior for stop() and global_stop()
selection is deterministic.

Comment thread ovos-stop-1.md
Comment on lines +286 to +296
```
session.pipeline: [
"stop_high", # escape hatch
"converse",
"intent_matcher_high",
"stop_medium",
"intent_matcher_medium",
"stop_low",
"intent_matcher_low"
]
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language tag to the fenced code block.

The example fence should declare a language to satisfy MD040 and keep docs tooling clean.

Proposed fix
-```
+```yaml
 session.pipeline: [
   "stop_high",            # escape hatch
   "converse",
   "intent_matcher_high",
   "stop_medium",
   "intent_matcher_medium",
   "stop_low",
   "intent_matcher_low"
 ]
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>

[warning] 286-286: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @stop.md around lines 286 - 296, The fenced code block showing the
session.pipeline array lacks a language tag which triggers MD040; update the
fence to include a language (use "yaml") for the block containing
session.pipeline and its entries (e.g., "stop_high", "converse",
"intent_matcher_high", "stop_medium", "intent_matcher_medium", "stop_low",
"intent_matcher_low") so tooling/linters recognize the language and the MD040
warning is resolved.


</details>

<!-- fingerprinting:phantom:triton:hawk -->

<!-- This is an auto-generated comment by CodeRabbit -->

JarbasAl added a commit that referenced this pull request May 27, 2026
Aligns with the project-wide filename convention (filename matches
the lowercase spec identifier), matching the recent rename of the
other spec files. Adds a new entry to the README's
"Utterance lifecycle and matching" spec table under
OVOS-CONVERSE-1 with a link to the in-review PR #33.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
JarbasAl and others added 18 commits May 27, 2026 18:19
New normative spec defining the stop pipeline plugin role, the
two reserved intent_names `stop` and `global_stop`, the
broadcast ping-pong stoppability discovery, the LIFO cascade
across `session.active_handlers`, and the `ovos.stop` universal
broadcast namespace.

Five-topic bus surface:
- `ovos.stop.ping` / `ovos.stop.pong` — single-broadcast
  feasibility query with shared shared response topic
- `<target_skill_id>:stop` — standard PIPELINE-1 dispatch to
  the LIFO head of positive responders
- `<stop_plugin_id>:global_stop` — fallback / explicit
  "stop everything" dispatch; handler emits `ovos.stop`
- `ovos.stop` — universal broadcast every component subscribes
  to, session-scoped cleanup obligation

Skills SHOULD self-prune from `active_handlers` when
unstoppable; stop subscribers MUST cease only activity keyed to
the inbound `session_id`. Spec body is implementation-agnostic;
no real-project names appear outside the spec-ID namespace.

Depends on: OVOS-MSG-1, OVOS-PIPELINE-1, OVOS-SESSION-1,
OVOS-SESSION-2, OVOS-CONVERSE-1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ternal

Only the intent_name `stop` is reserved at PIPELINE-1 §7.3,
because skills are dispatched on `<skill_id>:stop` and a
competing skill-level match would bypass the §4 cascade.

`global_stop` is the stop plugin's escalation self-dispatch and
remains namespaced under `<stop_plugin_id>:global_stop` —
collision-free regardless of any other skill registering the
same name. Drop its reservation from §2 and from the orchestrator
conformance MUST.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The stop plugin's match-phase mutation of session.active_handlers
is part of the cascade's correctness story: removing the
dispatched target via Match.updated_session propagates the
post-stop state through the rest of the utterance lifecycle
without waiting for TTL pruning or size-cap eviction, keeping
downstream reads of the list accurate.

Reverses the prior §6.2 prohibition for the dispatch-target case
only; CONVERSE-1's other mutation pathways (TTL, size cap,
activation, self-pruning §4.4) continue to own the remaining
lifecycle. A global_stop Match MUST NOT touch active_handlers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ten to both topics

Two correctness clarifications:

1. A global_stop Match MUST empty session.active_handlers
   entirely via Match.updated_session (§5.1, §6.2). Previously
   global_stop was specified as not touching the list; on
   reflection, global stop terminates every handler the session
   is tracking, so the cleared list is the accurate post-stop
   state and must propagate through the rest of the utterance
   lifecycle for the same reason §4.1 propagates the single-
   target removal.

2. Skills MUST subscribe to BOTH <own_skill_id>:stop and
   ovos.stop. The two are not alternatives — depending on the
   cascade outcome a skill receives one or the other, and must
   be ready for either. Lifted the subscription requirements
   from SHOULD to MUST and split the skill conformance into
   MUST (subscriptions, session-scoped cleanup, idempotency)
   and SHOULD (ping-pong participation, self-pruning).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Aligns with the project-wide filename convention (filename matches
the lowercase spec identifier), matching the recent rename of the
other spec files. Adds a new entry to the README's
"Utterance lifecycle and matching" spec table under
OVOS-CONVERSE-1 with a link to the in-review PR #33.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
STOP-1 was added to the spec index table but missing from the
role-based reading-order lists. Adds it alongside CONVERSE-1 /
CONTEXT-1 / TRANSFORM-1 in the "Building a pipeline plugin?" and
"Building an orchestrator?" lines.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…strator

Resolves STOP-1's CONVERSE-1 dependency by relocating
active_handlers to PIPELINE-1, with reserved-name suppression
of the stamping push.

PIPELINE-1 §7.1 — new dispatch-time stamping bullet: the
orchestrator MUST push {skill_id} onto the head of
session.active_handlers, evicting prior entries with the same
skill_id. The push is suppressed in two cases:

  1. pipeline-plugin self-dispatches (skill_id == pipeline_id),
     which record no skill activity;
  2. dispatches on reserved intent_names listed in §7.3 —
     converse, response, stop — which represent continuation
     or termination of an already-active skill's participation,
     not fresh activation.

The push is applied AFTER Match.updated_session is committed,
so a plugin that needs to remove the target ahead of the
dispatch (the stop cascade) does so via updated_session and
the suppressed push leaves the removal in effect. This makes
pre-dispatch the single, well-defined mutation boundary — no
consumer-side removal protocol, no race between optimistic
pre-removal and a failed handler.

PIPELINE-1 §7.3 — amend the "stamping fires identically" claim
to except the active_handlers push for reserved-name dispatches.

SESSION-1 field registry — active_handlers owner moved from
CONVERSE-1 §2.1 to PIPELINE-1 §7.1; entry shape generalised to
{skill_id, ...} so future specs can extend without
re-registering.

STOP-1 §4.1 / §5.1 / §6.2 — restore the Match.updated_session
removal of the dispatch target on stop matches; global_stop
wipes active_handlers entirely. §6.2 explains the pre-dispatch
boundary: orchestrator commits updated_session, suppresses the
push (reserved-name dispatch), downstream lifecycle sees the
post-stop list. The earlier consumer-removal rule is dropped.

STOP-1 §6.1 — response_mode clearing made conditional ("if
present"); semantics owned elsewhere (CONVERSE-1 when it lands).

STOP-1 §3.4 self-pruning — no longer references CONVERSE-1's
mutation pathway; communicated via any session-carrying Message.

STOP-1 preamble — drop CONVERSE-1 from the dependency list;
add the PIPELINE-1 §7.1 source-of-truth pointer.

APPENDIX preamble + §1.2 narrative updated by user to include
CONVERSE-1, STOP-1, COMMON-QUERY-1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…f reserved names

The §7.1 active_handlers stamping rule no longer special-cases
pipeline-plugin self-dispatches. The orchestrator applies the
§7.0 polymorphism rule uniformly — it does not distinguish
skill from pipeline-plugin dispatches — and the push is
suppressed strictly on the reserved-name registry.

To preserve the architectural intent (the stop plugin's
pipeline_id must not land in active_handlers on global stop),
global_stop is now a reserved intent_name alongside stop,
converse, and response:

PIPELINE-1 §7.3 — global_stop added to the reservations table
with the stop-plugin escalation semantics. stop also added
(was previously implicit from STOP-1's reservation claim).

STOP-1 §2 — restore both reservations, with an explicit note
that reserving global_stop is what gates the active_handlers
suppression. Drops the prior "global_stop is plugin-internal
and not reserved" framing; the architectural cost of the new
suppression rule is one reserved name, paid back by a cleaner
orchestrator contract.

STOP-1 §5 / §5.1 / §9 — rewording for the restored reservation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…utcome

Reverts the prior ordering flip and the global_stop reservation.
The stop plugin landing in active_handlers on its own
global_stop dispatch is not a problem to engineer around — it
is the ordinary behaviour of the recency-ordered dispatch
record, and it composes correctly with subsequent ping rounds
(the stop plugin doesn't subscribe to ovos.stop.ping, so it
silently times out as can_handle:false on the next stop).

PIPELINE-1 §7.1 — restore "stamp applied after updated_session
is committed". The dispatched skill_id always lands at the
head of active_handlers unless the intent_name is reserved.

PIPELINE-1 §7.3 — global_stop is not in the reservation table
(only stop, converse, response).

STOP-1 §2 — single reservation (stop). global_stop framed as
"plugin-internal and not reserved" with the note that the stop
plugin's pipeline_id landing in active_handlers via the normal
stamp is the ordinary behaviour, not a special case.

STOP-1 §5.1 — global_stop's updated_session wipes the inbound
active_handlers (so prior active skills are correctly cleared);
the post-dispatch state is [{skill_id: stop_plugin_id}] via the
normal stamp on top. This is the expected outcome.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e picks by timestamp

Replaces the LIFO-by-position cascade selection with explicit
MRU-by-timestamp. The active_handlers list is a set keyed by
skill_id with eviction, not an insertion-ordered list — its
"recency" is properly determined by the activated_at timestamp
each entry carries, not by where it happens to sit in the
array.

SESSION-1 field registry — entry shape restored to
{skill_id, activated_at, ...}.

PIPELINE-1 §7.1 — orchestrator stamps {skill_id, activated_at:
<orchestrator-stamped Unix timestamp in seconds>} on dispatch.
The list is described as "a recency record keyed by
activated_at" rather than "MRU by list position".

STOP-1 §2 reservation table, §3.2, §4.1 step 4 — cascade
selection rewritten as "the most recently activated (highest
activated_at) positive pong responder" instead of "LIFO head
among positives". Wording consistent across the spec.

APPENDIX §4.8 — same fix in the rationale paragraph.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…onale asides, tighten to normative skeleton

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…T, timeout bound, multi-tier global_stop, drop stop.response

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s not affect converse eligibility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…top drains converse_handlers

- Dependencies: active_handlers owned by PIPELINE-1, not SESSION-1
- global_stop updated_session: empty converse_handlers (CONVERSE-1 §2.1) as well as active_handlers
- §6.2: explain global_stop rationale for draining converse_handlers
- §9 MUST list: move empty-on-no-active into MUST; fix pong-timeout grammar; split SHOULD out
- §9 SHOULD: add skip-ping-when-empty and 1s-timeout bullets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…onverse re-entry

- §5.2: explicit Match construction block clearing active_handlers,
  converse_handlers, and response_mode atomically; prose asserting stop
  plugin owns all three cleanups
- §5.2: note that global_stop stamp onto active_handlers is intentional —
  stop plugin MAY converse for follow-up clarifications
- §6.1: collapse to targeted-stop-only obligation; cross-ref §5.2 for
  global_stop case to eliminate duplication

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…gaps

- §3.1: drop confusing multi-tier shared-pipeline_id prose; replace with
  single MUST (exactly one ovos.stop per global stop event per session);
  fold §3.2 match obligations into §3.1
- §3.2 (was §3.3): tighten vocabulary SHOULD to normative form
- §4.1 step 2: drop non-RFC-2119 "RECOMMENDED"; use plain "default"
- §4.2: add explicit rule that non-responding handlers are treated as
  can_handle: false and are ineligible as stop targets; note cascade
  escalates to global_stop — closes the legacy-skill gap
- §4.3: define idempotency — duplicate stop MUST be treated as no-op,
  not a second stop sequence
- §6.1: cut rationale sentence
- §6.2: cut rationale sentences; keep normative drain rules
- §6.3: add blacklisted_intents scope rule — applies to dispatched
  intent_name, not to the ping broadcast
- §5.2: cut "stop plugin owns cleanup" rationale sentence
- §9: remove inconsistent SHOULD (step-1 skip is already a MUST in
  algorithm); remove redundant multi-tier SHOULD; add non-responding
  handler MUST to plugin conformance; tighten idempotency wording

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- §4.1 step 4: add tie-breaking rule — equal activated_at selects the
  latest list position (most recently stamped)
- §4.2 ping: note session_id carried in Message context per MSG-1
- §4.2 pong: MUST use reply derivation so routing metadata is preserved
  for remote/client-side skills; source/destination are layer-2 only
- §4.3: note that updated_session is not rolled back on handler .error
- §5.3: reference MSG-1 for session_id on ovos.stop broadcast
- §6.1: add "if no matching entry, field is left unchanged"
- §6.3: clarify blacklisted_intents applies to the resolved intent_name;
  a stop utterance escalated to global_stop is gated by the global_stop
  entry, not the stop entry
- §9 Skill SHOULD: tighten pong wording to match reply-derivation MUST

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@JarbasAl JarbasAl force-pushed the spec/stop-1-draft branch from 49b70f3 to 0a96972 Compare May 27, 2026 17:20
JarbasAl and others added 3 commits May 27, 2026 18:25
§7.3 previously cited '§7.1 routing' but routing (subscription discipline)
is §7.2; §7.1 covers context stamping and the active_handlers push.
Expand to list all three affected subsections explicitly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@JarbasAl JarbasAl marked this pull request as ready for review May 27, 2026 17:40
@JarbasAl JarbasAl merged commit 23ae502 into dev May 27, 2026
JarbasAl added a commit that referenced this pull request May 27, 2026
…TOP-1

- README: remove 'in review' PR links for CONVERSE-1 (#25) and STOP-1
  (#33); both now merged; add STOP-1 to reading-order bullets
- appendix/divergences: replace stale 'response-mode counter' reference
  with current session.response_mode field name

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
JarbasAl added a commit that referenced this pull request May 27, 2026
…TOP-1

- README: remove 'in review' PR links for CONVERSE-1 (#25) and STOP-1
  (#33); both now merged; add STOP-1 to reading-order bullets
- appendix/divergences: replace stale 'response-mode counter' reference
  with current session.response_mode field name

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