Skip to content

Commit 13b4f1b

Browse files
committed
docs: record the B1-uplink — OGAR executor wired behind the hard gate
The hard gate is now wired to the executor in rs-graph-llm's new `graph-flow-action-ogar` seam crate (`GatedOgarHandler` / `run_gated`): `dispatch_via`'s cold floor (`commit_via`: RBAC ∧ state-guard ∧ MUL) lands before the OGAR `CapabilityExecutor` runs. The structural proof is a negative — `take_result()` is `None` whenever the gate refused, so an unauthorized (`Denied`) or MUL-blocked (`Escalated`) action never reaches the executor. OGAR owns the executor; rs-graph-llm owns the gate; the seam crate joins them without OGAR taking a `lance-graph` dep. - ARAGO-ACTIONHANDLER-PARITY: new B1-uplink §3 bullet + scorecard row (SHIPPED), verdict note (gate wired to executor), cross-ref to the seam crate. - DISCOVERY-MAP: new D-ACTIONHANDLER-UPLINK row (G / CODED), cross-ref D-ACTIONHANDLER-PARITY (append-only; existing row untouched). - EPIPHANIES: E-ACTIONHANDLER-UPLINK (FINDING) — the load-bearing proof is the negative test; the coupling lives in the seam, not in graph-flow-action. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYvNjD8M8LMNYbRy3gq2FP
1 parent 0e7c22c commit 13b4f1b

3 files changed

Lines changed: 58 additions & 1 deletion

File tree

.claude/board/EPIPHANIES.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,45 @@
77
88
---
99

10+
## 2026-06-24 — E-ACTIONHANDLER-UPLINK — the hard gate is wired to the executor without OGAR ever taking a `lance-graph` dep: OGAR owns the executor, rs-graph-llm owns the gate, one seam crate joins them
11+
12+
**Status:** FINDING (`[G]`, 3 tests).
13+
14+
Operator directive: "make the hard actionhandler in OGAR as is but also 'uplink'
15+
into rs-graph-llm so there's a hard gated contract before it lands." The shape
16+
that satisfies it without violating either repo's dependency hygiene:
17+
18+
- **OGAR owns the executor.** `CapabilityExecutor` (e.g.
19+
`ogar-action-handler::NativeCommandExecutor`) is the only piece that does real
20+
I/O — it runs the capability and returns `resultParameters`. It carries no
21+
authorization logic and no `lance-graph` dep.
22+
- **rs-graph-llm owns the hard gate.** `graph-flow-action::dispatch_via` runs the
23+
cold floor (`commit_via`: def-match → RBAC `ClassRbac``StateGuard` → MUL) and
24+
reaches the hot path (`handle`) only on `Committed`. Its dep list is
25+
intentionally contract-only (`I-ACTIONHANDLER-IS-KGV-NOT-CHOKEPOINT`).
26+
- **A third crate is the seam.** New `graph-flow-action-ogar`: `GatedOgarHandler`
27+
wraps a `CapabilityExecutor` as a `graph-flow-action::ActionHandler`, so the
28+
executor runs **only after the contract lands**. `run_gated` drives the whole
29+
thing; `take_result()` is `None` iff the gate refused.
30+
31+
**The load-bearing proof is a negative.** The test
32+
`unauthorized_action_is_blocked_before_execution` asserts `result.is_none()` — the
33+
OGAR executor *never ran* because the gate said `Denied`. `mul_block_vetoes_before_execution`
34+
proves the same for a MUL `Block` (`Escalated`, `None`). Only
35+
`authorized_action_passes_the_gate_and_runs_the_command` reaches the real
36+
`echo``{"output":"gated",…}`. The hard contract demonstrably lands *before*
37+
execution, not alongside it.
38+
39+
**Why the coupling lives in the seam, not in `graph-flow-action`:** `ogar-from-schema`
40+
carries no `lance-graph` dependency, so the two sides meet only at the seam crate's
41+
API — no second `lance-graph-contract` enters the graph. The seam is the *only*
42+
place the two repos' types touch. (Toolchain: rs-graph-llm pinned to 1.95.0 to
43+
match the AdaWorldAPI stack it consumes via path deps.) This is the B1-uplink row
44+
in the `ARAGO-ACTIONHANDLER-PARITY` scorecard and `D-ACTIONHANDLER-UPLINK` in the
45+
discovery map.
46+
47+
---
48+
1049
## 2026-06-24 — E-ARAGO-ACTIONHANDLER-PARITY — OGAR is at full *contract + lifecycle* parity with arago's HIRO ActionHandler; the live daemon reduces to two glue bricks
1150

1251
**Status:** FINDING (contract+lifecycle `[G]`) + CONJECTURE (runtime `[H]`, gated

docs/ARAGO-ACTIONHANDLER-PARITY.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,15 @@ downstream. The remaining bricks:
192192
— proven end-to-end by `full_dispatch_runs_a_real_command` ("OGAR running it
193193
here," native). SSH / REST / WinRM targets follow the same trait; rs-graph-llm's
194194
`graph-flow-action` provides the production executors (and runs `commit_via`).
195+
- **B1-uplink — the hard gate before the executor (SHIPPED).** rs-graph-llm's
196+
`graph-flow-action-ogar` crate is the seam: `GatedOgarHandler` wraps an OGAR
197+
`CapabilityExecutor` as a `graph-flow-action::ActionHandler`, so the executor's
198+
`handle` runs **only after** `dispatch_via`'s cold floor commits
199+
(`commit_via`: def-match → RBAC `ClassRbac` → state-guard → MUL). The structural
200+
proof: `take_result()` is `None` whenever the gate refused — `run_gated` with an
201+
unauthorized actor (`Denied`) or a MUL `Block` (`Escalated`) never reaches the
202+
OGAR executor. Three tests pin it; `NativeCommandExecutor` runs the real command
203+
only on the authorized path. OGAR owns the executor; rs-graph-llm owns the gate.
195204
- **B2-transport — the live WebSocket loop.** Wrap `handle_submit` in a
196205
`tokio-tungstenite` client (connect with the `token-$TOKEN` subprotocol, JSON-
197206
codec the six `action_ws` message types, drive the dispatch, retry-on-no-ack).
@@ -219,6 +228,7 @@ transport over them.
219228
| **action-ws protocol core (B2-core)** |`[G]` SHIPPED | `action_ws`: all 6 message types + `submit_to_invocation` / `bind_parameters` / `invocation_to_result` (socket-free, `full_action_ws_roundtrip` proven) |
220229
| **Reactive dispatch + B1 seam** |`[G]` SHIPPED | `action_ws::handle_submit` + the `CapabilityExecutor` trait (validate→ack→bind→execute→result; tested with a mock) |
221230
| **Executor — native target (B1)** |`[G]` SHIPPED | `ogar-action-handler::NativeCommandExecutor` runs `ExecuteCommand` for real; `full_dispatch_runs_a_real_command` |
231+
| **Hard gate before executor (B1-uplink)** |`[G]` SHIPPED | rs-graph-llm `graph-flow-action-ogar::GatedOgarHandler``commit_via` (RBAC ∧ guard ∧ MUL) lands before `handle`; `take_result()` is `None` iff the gate refused (3 tests) |
222232
| **Executor — SSH/REST/WinRM (B1)** |`[H]` | further `CapabilityExecutor` impls (rs-graph-llm `graph-flow-action`) |
223233
| **Live WebSocket transport (B2-transport)** |`[H]` | wrap `handle_submit` in a `tokio-tungstenite` loop + JSON codec (all shapes pinned, §2a) |
224234
| **Instance config lift (B2-lift)** |`[H]` | REST `GET /capabilities`/`/applicabilities``ActionDef`/`ActionParam` |
@@ -227,7 +237,11 @@ transport over them.
227237
reactive-dispatch parity**, and **a working native executor runs real commands
228238
end-to-end** (`handle_submit` + `NativeCommandExecutor`). Every field of the
229239
config, ontology, and protocol has an OGAR type; the gate (`commit_via`), the
230-
binding, the dispatch, and native execution are real and tested. What's left for
240+
binding, the dispatch, and native execution are real and tested — and the gate is
241+
now **wired to the executor**: rs-graph-llm's `graph-flow-action-ogar` runs OGAR's
242+
`CapabilityExecutor` only after `commit_via` commits, so an unauthorized or
243+
MUL-blocked action never executes (proven structurally — `take_result()` is
244+
`None`). What's left for
231245
a **live** drop-in replacement of arago's Python daemon: **B2-transport** (the
232246
WebSocket loop — all shapes/auth pinned), **B2-lift** (the REST registration
233247
parse), and the **non-native executor targets** (SSH/REST). Each is
@@ -258,6 +272,9 @@ is replaceable; the parity claim is certified, not argued.
258272
- `lance-graph-contract::action``ActionInvocation` / `commit_via<ClassRbac>`.
259273
- `lance-graph-ogar::OgarActionProvider` — the `classid → ClassActions` DO surface.
260274
- `rs-graph-llm/graph-flow-action` — the `ActionHandler` executor trait (B1 home).
275+
- `rs-graph-llm/graph-flow-action-ogar` — the **uplink**: OGAR's
276+
`CapabilityExecutor` behind the hard gate (`GatedOgarHandler` / `run_gated`);
277+
`commit_via` lands before any execution.
261278
- arago: `github.com/arago/ActionHandlers`,
262279
`arago/python-hiro-stonebranch-actionhandler`, HIRO 7 Action API tutorial.
263280
- **HIRO 7 Action API machine-readable specs (the authoritative harvest, §2a):**

docs/DISCOVERY-MAP.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ two halves of a cell. ADR‑026 names the cascade that ties them.
211211
| D‑HIRO‑DO | OGIT Automation → DO arm: `into_action_def` lifts `KnowledgeItem``ActionDef` (object_class←`relates`, kausal←`contains Trigger`, body **pointed‑to** not inlined — lossless‑DO §1); schema half of `PROBE‑OGAR‑DO‑ARM‑LIFT` green; lift→`emit_action_def`→SPO triples proven end‑to‑end (`tests/do_arm_emit.rs`, lossless‑DO holds across emit) | G | CODED (schema half) | `ogar-from-schema/src/do_arm.rs` | D‑VOCAB, D‑TTL, D‑ELIXIR, D‑EMIT |
212212
| D‑MARS‑CLASSID | MARS/Automation classids MINTED: `ConceptDomain::Automation` (0x0C), 9 concepts (`mars_application/resource/software/machine` 0x0C01‑04, `knowledge_item` 05, `mars_node_template` 06, `action_handler` 07, `action_applicability` 08, `automation_trigger` 09) — one domain spanning MARS structural CMDB + Automation DO‑arm (Auth precedent); resolves MARS‑TRANSCODING §1 deferral; passed 5+3 hardening (theorem/doctrine/integration/runtime savants + drift‑guards). Reserves the speculative rest | G | CODED | `ogar-vocab/src/lib.rs`, `ogar-class-view/src/lib.rs` | D‑VOCAB, D‑HIRO‑DO |
213213
| D‑ACTIONHANDLER‑PARITY | arago HIRO ActionHandler ⟷ OGAR: `assemble_action_handler` walks the OGIT `provides` graph (`ActionHandler→ActionApplicability→ActionCapability`) into `ActionHandlerSpec`/`CapabilitySlot`/`ApplicabilitySlot`/`ActionParam`. Config+ontology+`action-ws` protocol all map to OGAR types: arago `ModelFilter{Var,Mode,Value}`→`StateGuard`; `Capability.Name`→`predicate`; `resultParameters`→output sig; `action-ws` `submitAction→ack→sendActionResult` ⟷ `ActionInvocation` `Pending→Committed` (`commit_via` is the gate). **B2 protocol core SHIPPED + spec-faithful** (`action_ws`: all 6 `action-ws.yaml` message types — submitAction/sendActionResult/acknowledged/negativeAcknowledged/configChanged/error — + `submit_to_invocation`/`bind_parameters`/`invocation_to_result` (result=JSON string ≤1 MiB per spec) + connection consts (`ACTION_WS_PATH`, `auth_subprotocol`, `validate_id`); socket-free, `full_action_ws_roundtrip` proven; harvested from the HIRO 7.0 dev-portal specs §2a). **Reactive dispatch + B1 native executor SHIPPED**: `action_ws::handle_submit` (validate→ack/nack→bind→execute→result) over the `CapabilityExecutor` trait (the B1 seam); `ogar-action-handler::NativeCommandExecutor` runs `ExecuteCommand` for real (`full_dispatch_runs_a_real_command` — OGAR runs a command end-to-end). Remaining for a live drop-in: B2-transport (WS loop), B2-lift (REST registration parse), SSH/REST executor targets; gated on `PROBE‑OGAR‑ACTIONHANDLER‑RUN` | G (contract+protocol+native exec) / H (live socket) | CODED | `ogar-from-schema/src/{do_arm,action_ws}.rs`, `ogar-action-handler/`, `docs/ARAGO-ACTIONHANDLER-PARITY.md` | D‑HIRO‑DO, D‑MARS‑CLASSID |
214+
| D‑ACTIONHANDLER‑UPLINK | The hard gate wired to the OGAR executor (cross‑repo seam): rs‑graph‑llm `graph-flow-action-ogar::GatedOgarHandler` wraps an OGAR `CapabilityExecutor` as a `graph-flow-action::ActionHandler`, so `dispatch_via`'s cold floor (`commit_via`: def‑match → RBAC `ClassRbac` → `StateGuard` → MUL) lands **before** the executor's `handle`. Structural proof the contract lands first: `take_result()`/`run_gated` returns `None` whenever the gate refused — unauthorized actor → `Denied` (executor never runs), MUL `Block` → `Escalated` (executor never runs); only the authorized path reaches `NativeCommandExecutor` and runs the real command (3 tests). Dependency hygiene held: `graph-flow-action` stays contract‑only (`I‑ACTIONHANDLER‑IS‑KGV‑NOT‑CHOKEPOINT`); `ogar-from-schema` carries no `lance-graph` dep — the two sides meet only at this crate's API (one `lance-graph-contract`). rs‑graph‑llm pinned to toolchain 1.95.0 to match the AdaWorldAPI stack | G | CODED | `rs-graph-llm/graph-flow-action-ogar/src/lib.rs` | D‑ACTIONHANDLER‑PARITY |
214215
| D‑OSM | `ogar-from-osm-pbf` — Node/Way/Relation; quadkey NiblePath from resolved geometry | H | IDEA | (queued) | D‑VOCAB, `[per rt]` D‑OSM‑3 |
215216
| D‑PATTERN | `ogar-pattern` — recognition library + confidence (FMA‑D/FIBO/SKR/PROV‑O) | H | IDEA | (queued) | D‑TTL |
216217
| D‑ACTION | `ogar-actionable` — lifecycle → `ActionDef`/`KausalSpec` | H | IDEA | (queued) | D‑PATTERN |

0 commit comments

Comments
 (0)