Add the reroute gate and the reroute landing with the REROUTE block #873
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Blocks
Depends on
Reference
jared/cc-os#873
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
ADR-0259 decision 9, as amended by ADR-0260: map-router runs
os-sdlc-gate DISPATCH_IDin-turn, before it stops. The chosenmap:andnode:exist only in its stop handoff, so thereroutegate has nothing to check. The fix: map-router records a draft reroute with a new CLI,os-sdlc-implementation-map-update. Thereroutegate confirms a valid draft exists. The landing turns the draft into an applied reroute and positions the run at the chosen entry node. The reply carries the REROUTE block (ADR-0258 decision 4). TodayGate::Name::ALL(model/gate/name.rb:12) has noreroute,Gate::Commands#to_h(query/gate/commands.rb:13) has no command for it,Landing#land!(command/implementation/landing.rb:13) always followsdecision, andImplementation#current_map(model/implementation.rb:70-72) readsreroutes_dataset.first, so a draft row would switch the map.Reproduce
n/a: design change, nothing to reproduce.
Approach
REROUTE = "reroute"toGate::Name::ALLandName::REROUTE => "os-sdlc-reroute-check #{dispatch id}"toGate::Commands#to_h. Addbin/os-sdlc-reroute-check DISPATCH_ID(Boot commandreroute-check, same shape asbin/os-sdlc-required-work-check). The gate signature does not change.bin/os-sdlc-implementation-map-update DISPATCH_ID --map NAME --node NODE --situation S --misfit M(Boot commandimplementation-map-update). It requires the dispatch to be pending (Dispatch.pending!) and owned by agent type map-router, with the same checks as the other dispatch CLIs.Reroute::Draftvalidates. It loads the map withMap::Catalog.default.load(map); loading runs the validator, so the entry-gates rule (#870) holds. It fails, with an error text that names the cause, exits nonzero, and writes nothing, when:situationormisfitis missing; the map does not load; the map has noentries:;nodeis not inentries(the message names the node and lists the allowed entries); the implementation already has 3 applied reroutes (cap, ADR-0258 decision 4).map,node,situation,misfit,draft: true, anddispatch_id= the requesting dispatch, found as the map-router dispatch'sreceived_handoff.creating_dispatch(nil when the orchestrator wrote the handoff). A second call in the same map-router dispatch replaces the draft, so one row exists per dispatch.Reroute::Check(the gate) only confirms that a valid draft exists for this dispatch. It fails with a message that names the cause when none exists.draft: false) changeImplementation#current_mapand count toward the 3-reroute cap.current_mapreads the newest applied reroute. A draft never switches the map.Landing#land!, when the routed dispatch's node has thereroutegate and the verdict ispass, the landing ignoresdecision, turns the draft into an applied reroute (draft: false), callsadvance!(position: <that reroute node>)(that node is in the new current map), and stamps the map-router created handoff target with that node's agent.Implementation::Transitionstays the only caller (ADR-0168).Reroute::Blockfrom the newest applied reroute row:by <agent_type> (dispatch N)replacesby orchestratorwhendispatch_idis set. The landing reply carries it asreroute:. The orchestrator does not read gate replies, so the NextStep dispatch payload that follows the reroute landing also carriesreroute:.8. The orchestrator path does not change:
os-sdlc-reroute-request ID --situation --misfit(no dispatch id) atneeds-orchestrator.9. Agent prompt:
agents/map-router.mdalready names the map-update step (ADR-0260).Required work:
REROUTE = "reroute"inplugins/os-sdlc/lib/os_sdlc/model/gate/name.rbName::REROUTEinplugins/os-sdlc/lib/os_sdlc/query/gate/commands.rbreroute-checkinplugins/os-sdlc/bin/os-sdlc-reroute-checkimplementation-map-updateinplugins/os-sdlc/bin/os-sdlc-implementation-map-updateentriesinplugins/os-sdlc/lib/os_sdlc/reroute/draft.rbdraftinplugins/os-sdlc/lib/os_sdlc/model/implementation.rbrerouteinplugins/os-sdlc/lib/os_sdlc/command/implementation/landing.rbREROUTE byinplugins/os-sdlc/lib/os_sdlc/presenter/**/*.rbAcceptance criteria
entries), when the gate passes and NextStep lands the dispatch, then one applied reroutes row exists (draft: false,dispatch_idnil after an orchestrator request), and the reply holds the REROUTE block withby orchestrator,resume at: <node>, and the map'sfits:text inwhy.current_mapis the chosen map, and the dispatch payload names that node's agent and carries the REROUTE block.entries, when it runs, then it exits nonzero, names the node and the allowed entries, and writes no row.entries, when it runs, then it exits nonzero and writes no row.misfit, when it runs, then it exits nonzero, namesmisfit, and writes no row.Implementation#current_mapis read, then it returns the implementation's own map.reroutegate runs, then it fails and names the missing draft.Owner sketch
Origin
Parent: #859
Blocked by: #871, #885, #886
Add os-sdlc-reroute-request, out-of-map map-router dispatch, and reroute gateto Add the reroute gate and the reroute landing with the REROUTE blockWork started on branch ticket-873 (os-sdlc pipeline, map poodr-ticket-implementation).
Waiting for a ruling: where does the
reroutegate get the router'smapandnodeat gate time?Implementation 4 stopped at the change-auditor (dispatch 28, verdict fail). The run waits at
needs-orchestrator(escalation 1).The conflict. ADR-0259 decision 9 says the
reroutegate validates the router handoff.agents/map-router.mdtells map-router to runos-sdlc-gate DISPATCH_IDuntil green, then stop with a YAML handoff that holdsmap:andnode:. ButDispatch#complete!records the handoff only at stop (model/dispatch.rb:92-104), andbin/os-sdlc-gatetakes only a dispatch id. At gate timemapandnodeexist nowhere;received_handoffholds only the requester'ssituationandmisfit. AC 1, 4, 5 and 6 cannot work on the real pipeline as written.Options
A. The agent passes them to the gate:
The gate CLI and
Boot::Inputschange; the stop handoff still carriesmap:andnode:.B. The agent stops first, the gate runs on the stored handoff, and a red gate returns the run to map-router. This changes the in-turn gate model.
C. The agent writes a draft handoff to a store before the gate; the gate reads the draft.
Recommendation: A, about 70% confidence. Deciding reason: it is the smallest change, keeps the in-turn gate model, and needs no new store. Every option amends ADR-0259 decision 9 and
agents/map-router.md.After the ruling: amend ADR-0259 with
/os-adr:create, updatemap-router.mdand this ticket (Approach 2-3; Required work also needs the Boot/Inputs wiring, the HandoffContent readers, the dedup rule, the cap owner, and a home forReroute::CheckandReroute::Block), then open a new implementation. #874 stays blocked until then.Default if no answer: nothing moves; #873 and #874 stay open.
User ruling 2026-10-01 (recorded in ADR-0260, amends ADR-0259 decision 9). The reroute gate had nothing to check: map and node exist only in the map-router stop handoff. Resolution: new CLI os-sdlc-implementation-map-update DISPATCH_ID --map --node --situation --misfit validates (map in catalog, node in entries, situation and misfit present, fewer than 3 applied reroutes) and writes a draft Reroute, one per dispatch. The reroute gate only confirms a valid draft exists. The landing applies the draft and positions the run. Only applied reroutes change current_map and count toward the cap. Orchestrator path (os-sdlc-reroute-request) is unchanged. Rejected: args on os-sdlc-gate, gate after stop, a new store. Body rewritten to match. #874 needs no change.
Work started on branch ticket-873 (os-sdlc pipeline, map poodr-ticket-implementation).
Resolution
Done: os-sdlc-implementation-map-update writes a draft reroute per map-router dispatch; reroute gate (os-sdlc-reroute-check) confirms it; Landing applies it; only applied reroutes change current_map and count to cap 3 (ADR-0260)
Evidence: commit
d3f4888f; bin/test: '9 suites passed' (PASS os-sdlc (minitest)); implementation 6 completeFollow-ups: #890, #891