SummaryOne Row Per Transition Key, Detection and Prerequisites Co-Located
Six declared transitions cover the mode-discipline cycle and its two guarded escalations: opening planning after exploration, opening execution after planning, reverting from execution to exploration when the plan needs rethinking, declaring completion when execution produces a validated artifact, and — the guarded ones — handing anything off to the captain. The dispatch-to-captain-handoff transition exists because of the offload trip-wire in klappy://canon/constraints/dispatcher-dispatches-never-executes: a seat about to ask the captain to run/launch/commit/push/deploy anything runs its draft ask through the gate, and the gate demands proof that delegation to a subagent was attempted and that a human-only class (secret / voice / irreversible / approval) is named. Its detection vocabulary is deliberately rich in second-person tokens (you, your, captain) so BM25 routes offload phrasings here rather than to execution-to-completion, whose vocabulary shares operational verbs like deploy and push but carries no second-person signal. The settled-direction-ratification transition exists because of the let-the-gates-govern clause of the same canon constraint: a seat about to ask the captain to approve/ratify/bless/sign-off/green-light anything runs the draft ask through the gate, and the gate demands open_fork_cited — the ask must affirmatively name the genuinely-open fork the gates cannot resolve, because an ask that ratifies an already-recorded decision has no open fork to name and comes back NOT_READY. Its detection vocabulary is rich in approval stems (ratify, approve, bless, sign-off) and settled-record markers (already decided, per the ruling, settled call) that appear in neither the offload row (operational verbs) nor execution-to-completion (shipping verbs), so BM25 routes approval-shaped asks here. The word proceed appears exactly once in this row (in shall I proceed), deliberately: proceed is also a detection term of exploration-to-planning, and listing it more than once would let term frequency hijack a bare "proceed" input away from the planning transition — with a single occurrence, BM25 length normalization and row-order tiebreak keep bare "proceed" routing to exploration-to-planning as before. Each row carries its own detection vocabulary and prerequisite-id list, so consumers reading this file can answer "what fires this transition, and what must be true for it to pass?" in one lookup. Prerequisite ids resolve against odd/gate/prerequisites.md — that file defines each id's description, check vocabulary, and gap message. Detection terms are matched via BM25 over stemmed tokens; the specific-phrase-beats-single-word property of BM25 scoring means that ready to build outscores the bare word ready when both appear in the input, so the specific transition wins on score rather than relying on regex cascade order.
Transitions
| Transition Key | From | To | Prerequisites | Detection Terms |
|---|---|---|---|---|
planning-to-execution | planning | execution | decisions_locked, dod_defined, irreversibility_assessed, constraints_satisfied | ready to build, ready to implement, start building, let's code, start coding, moving to execution, moving to build |
exploration-to-planning | exploration | planning | problem_defined, constraints_reviewed, world_prior_cited, house_install_cited, house_canon_cited | ready to plan, start planning, let's plan, time to plan, move to planning, moving to planning, ready, let's go, proceed, move forward, next step |
execution-to-exploration | execution | exploration | back to exploration, need to rethink, step back, stepped back, stepping back, reconsider | |
execution-to-completion | execution | completion | dod_met, artifacts_present | ship, shipping, shipped, deploy, release, go live, push to prod |
dispatch-to-captain-handoff | execution | captain-escalation | delegation_attempted, human_only_class_named | you run it, you push, you commit, you deploy, you launch, you merge, can you run, please run this, over to you, your turn, on your machine, run this yourself, hand off to the captain, captain to run, for you to merge, leave the push to you |
settled-direction-ratification | execution | captain-escalation | open_fork_cited | ratify, ratification, rubber stamp, bless the decision, your blessing, do you approve, please approve, approve the direction, approve the plan, approve the decision, awaiting your approval, ready for your approval, your sign-off, sign off on, green-light this, re-approve, re-confirm, shall I proceed, already decided, already settled, per the ruling, settled call, direction is set |
Notes
Row order is the tiebreaker priority when two transitions score identically under BM25. BM25 naturally prefers specific-phrase matches over single-word matches — an input like "ready to build my feature" scores the multi-term match against planning-to-execution above the single-term match against exploration-to-planning — so row order rarely decides the winner. The ordering is kept stable regardless to produce deterministic output on genuine ties.
Detection terms are stemmed at parse time using the Porter-style stemmer in the server. Stemming covers the common inflection suffixes ies, ied, ed, ing, tion, ment, ness, able, ible, and s, which means variations like deploying, released, started building, building, and reconsidering match their canonical transitions even though the exact phrases are not listed. Terms that already appear in their stemmed base form — build, reconsider — match themselves directly.
The stemmer does not currently handle doubled-consonant gemination — shipping stems to shipp rather than ship, and stepped stems to stepp rather than step. For the small number of geminating words gate cares about (ship, step), the inflected forms are listed in the detection column directly so the match is by direct vocabulary rather than relying on the stemmer. This is a deliberate choice: adding a handful of explicit inflections is cheaper and more auditable than extending the stemmer, and keeps the vocabulary editable at canon rather than at the code level.
The execution-to-exploration transition has no prerequisites because reversion is explicitly permitted under the mode-discipline contract at klappy://canon/constraints/mode-discipline-and-bottleneck-respect. Reversion requires only that the operator name the specific unknown that drove the reversion, which is a behavioral expectation enforced by the operator's own discipline rather than by a gated prereq check.
When no row's detection terms score above zero against the user input, the server reports the transition as unknown → unknown. In this case no prerequisites are looked up and the gate returns PASS — the convention being that an unrecognized input is not a gate crossing at all, so there is nothing to block. This matches the pre-refactor behavior encoded in the previous hardcoded detection cascade.
Prereq-ids listed in the Prerequisites column are resolved against odd/gate/prerequisites.md. An id that appears in this table but not in that file is a governance error; the server's minimal fallback tier carries a hardcoded vocabulary snapshot that keeps gate functional in this case, but the canon-level fix is to update one file or the other.
When the server cannot reach this file at runtime, oddkit_gate falls back to a hardcoded minimal vocabulary that mirrors the row order and detection terms above. The minimal tier is identified in the response envelope via governance_source: "minimal"; the canon tier via governance_source: "knowledge_base". Both tiers run the same BM25 matcher; they differ only in whether the vocabulary is editable by updating this file or locked to the deployed worker version.
The exploration-to-planning row (2026-09-21) lists five prerequisite ids: the original pair plus world_prior_cited, house_install_cited, house_canon_cited. Those ids are defined in odd/gate/prerequisites.md. Planning-to-execution is unchanged.