feat(agentic): adopt hero_router agentic-calling pattern; replace MCP framing in vision (final pre-customer engineering item) #8

Closed
opened 2026-05-03 16:44:46 +00:00 by mik-tf · 1 comment
Owner

Summary

Adopt the hero_router agentic calling pattern as hero_assistance's programmable surface for AI-driven workflows. The vision doc currently says "v0.4 will register every method as an MCP tool" (§2.5) and "AI-driven triage and first-pass resolution via MCP tool surface" (§5.4) — that language predates the Hero stack's chosen architecture. hero_router has standardised on OpenRPC spec → router-generated Python interface + sandboxed Python client, not MCP. This issue tracks the work to align hero_assistance with that pattern.

Reference contract: https://forge.ourworld.tf/lhumina_code/hero_router/src/branch/development/docs/agentic_calling.md

Why this matters

Per hero_router's agentic_calling.md:

The LLM does not need access to service data. It only needs the generated interface description.

The router consumes each service's OpenRPC spec, generates two Python artifacts per service (a small interface file sent to the LLM; a full client file executed in a sandbox), MD5-fingerprints the spec to skip regeneration, and routes user-intent requests to the relevant interface(s). The LLM produces a workflow script from interface signatures only; the sandbox executes it; service data never reaches the LLM.

hero_assistance is the natural first non-trivial hero_router consumer:

  • 91 wire-stable RPC methods (mycelium-identity-gated; D-04 / D-08).
  • A complete OpenRPC 1.3.0 spec at crates/hero_assistance_server/openrpc.json (~92 KiB, 17 namespaces).
  • A real workflow surface — triage, comment drafting, presence-aware ticket routing — that benefits more from agentic execution than from a hand-rolled CLI.

Scope

What hero_assistance must contribute

  1. OpenRPC spec conformance audit. Walk every method block in crates/hero_assistance_server/openrpc.json and confirm:

    • params schemas are complete (no missing required lists, no additionalProperties: true where the handler actually rejects extras).
    • result schemas describe what the handler returns, not what an earlier draft thought it returned. (Phase 13b found at least one drift — presence.list returns name without it being declared.)
    • Per-method description is informative enough for an LLM to choose between sibling methods (channel.create vs ticket.create, message.send vs comment.create).
    • errors enumerate the codes the handler actually emits (-32002 PermissionDenied, -32003 NotFound, -32602 InvalidParams, etc.) — D-16's structured RpcCallError discrimination depends on this.
  2. Per-method intent metadata (additive — does not change wire shape). For each method, add an x-hero-intent extension block describing:

    • Side-effect class (read / mutate-own / mutate-others / admin). Sandbox can use this to gate execution paths or require confirmation.
    • Audience scope (self / workspace / project / cross-project). Mirrors the presence-fanout audience model.
    • Identity requirement (anonymous-ok / enrolled-user / support-role / admin-role).
    • Idempotency (safe / idempotent / unsafe). Distinguishes presence.set_status_text (idempotent, replays cheap) from comment.create (unsafe, replays duplicate).
  3. Identity-pinning contract for sandboxed calls. The router's sandbox runs as some identity; the hero_assistance privacy invariant (D-04 three-layer identity + D-20 per-recipient /events filter) requires that every RPC call carry a caller_id that the LLM cannot forge. Document the contract:

    • The sandbox MUST set caller_id from the human-user identity that hero_router authenticated, never from LLM output.
    • The sandbox MUST NOT carry one user's identity into a script generated for another user.
    • The /events TCP route's per-recipient server-side filter (D-20) is the regression gate — any agentic call that subscribes to events MUST hit /events with X-Hero-User: <human-user>, not <sandbox-service-account>.
  4. OpenRPC publishing endpoint. hero_router needs a way to fetch the spec. Decide between:

    • (a) Static URL — _ui serves crates/hero_assistance_server/openrpc.json at /openrpc.json (simplest; spec is already build-time-stable).
    • (b) RPC method — rpc.discover returns the spec inline (OpenRPC 1.3 standard; needs a handler).
    • (c) Both — static URL for cold-discovery, rpc.discover for in-protocol introspection.

    Recommended: (c), mirror what hero_router expects (open question — needs router-side confirmation).

  5. Sandbox-friendly workflow examples. Ship 3–5 example workflows in docs/dev/agentic_workflows.md matching the agentic_calling.md style — e.g., "find every open ticket in this workspace older than 7 days and post a follow-up comment from the assigned support agent." These double as integration-test fixtures and as documentation for what the router-side sandbox must support.

  6. Vision doc + roadmap update. Replace MCP language with hero_router-pattern language:

    • §2.5: "v0.4 will register every method as an MCP tool" → "v0.4 publishes the spec to hero_router for agentic calling per hero_router/docs/agentic_calling.md. Spec is the contract; the router generates the Python interface + sandboxed client."
    • §5.4 M4+ bullet "AI-driven triage and first-pass resolution via MCP tool surface" → "AI-driven triage via hero_router agentic calling — the router selects relevant interfaces based on user intent; the LLM generates a workflow script; the sandbox executes against hero_assistance RPC."
    • Add a new decision file decisions/D-21-agentic-calling-via-hero-router.md recording (a) the choice (hero_router pattern over MCP), (b) the security invariant (LLM sees interface only; sandbox holds identity), (c) the wire contribution (audit + x-hero-intent extension; no new RPC methods).

What hero_assistance does NOT do

  • No router-side code. hero_router owns the interface generator, the MD5 fingerprint cache, the LLM prompt, the sandbox, the intent classifier. hero_assistance is the spec source and a consumer of the resulting clients.
  • No new wire methods. All 91 methods stay; this issue is a metadata + spec-quality + documentation pass plus optional rpc.discover.
  • No MCP server build. MCP could re-enter post-v1 if a non-Hero-stack agent (Claude Desktop, Cursor, etc.) needs to drive hero_assistance directly — but it would be a separate workstream, not the primary agentic surface.

Acceptance criteria

  • crates/hero_assistance_server/openrpc.json audited end-to-end; every drift between handler behaviour and spec recorded as a fix or as an explicit x-hero-known-drift annotation.
  • Every method has x-hero-intent populated with side-effect class, audience scope, identity requirement, idempotency.
  • _ui serves the spec at /openrpc.json (or whatever path hero_router expects — confirm with router maintainer); response is application/json, Content-Type correct, cacheable with the same MD5 hero_router uses.
  • (If decided) rpc.discover handler returns the embedded spec; covered by a hermetic integration test.
  • Identity-pinning contract documented in docs/dev/agentic_calling.md (hero_assistance side; complements hero_router's doc) with the D-04 + D-20 invariants front-and-centre.
  • 3–5 example workflows in docs/dev/agentic_workflows.md covering: read-only triage, single-user mutate, multi-user fanout, cross-method (presence + comment), error-path ("user not enrolled in workspace").
  • docs/vision/HERO_ASSISTANCE.md §2.5 + §5.4 + roadmap updated; MCP language replaced with hero_router-pattern language.
  • decisions/D-21-agentic-calling-via-hero-router.md filed.
  • docs/dev/e2e_checklist.md Section L (programmable surface) extended with row(s) covering the spec-publish endpoint and the x-hero-intent extension. M2/M3 milestone tag depending on prioritisation.
  • CLAUDE.md "Current state" + prompt.md §1 + tracking issue #1 updated at session-end.
  • L-XX limitation filed if any acceptance criterion is descoped (e.g., live router integration deferred until hero_router exposes a discovery endpoint).

Roadmap framing

Per prompt.md §3, hero_assistance is engineering-complete pre-customer. M3 / v1.0 is customer-gated. This issue is the last engineering-complete item — once it lands:

  • The agentic surface is wired (per Hero-stack convention, not MCP).
  • 91 methods are spec-audited and intent-tagged.
  • Vision doc reflects reality (no orphan MCP language).
  • D-04 / D-20 privacy invariants are explicitly preserved through the sandbox boundary.

After this issue closes, hero_assistance can credibly be called engineering-complete full-stop — including the AI-amenable programmable surface that vision §2.5 promises. Anything beyond is customer-driven (M3) or M4+ aspirational.

Estimated work: 1–2 sessions if hero_router's discovery endpoint contract is already nailed down; 2–3 sessions if router-side coordination surfaces wire shape disagreements.

Open questions

  1. Router-side discovery contract. Does hero_router expect spec at a fixed URL path, registered via a registry RPC, or both? agentic_calling.md §16 shows a services: YAML registry but doesn't say who writes it.
  2. MD5 alignment. agentic_calling.md §3 says the router computes the MD5. Does it want raw bytes of openrpc.json, or a canonicalised form? Critical for cache stability.
  3. x-hero-intent schema. Is this extension already specified somewhere in the Hero stack? If yes, conform. If no, hero_assistance becomes the reference implementation — file the schema as part of D-21.
  4. Sandbox identity-injection mechanism. Does the sandbox already know how to set caller_id per call, or does that need router-side support? Confirm with hero_router maintainer before committing to the contract in (3) above.
  5. Live router integration. Is there a reachable hero_router test instance against which hero_assistance can verify the round-trip end-to-end, or does verification stay docs-only until a deployment surfaces it?

References

## Summary Adopt the hero_router **agentic calling** pattern as hero_assistance's programmable surface for AI-driven workflows. The vision doc currently says "v0.4 will register every method as an MCP tool" (§2.5) and "AI-driven triage and first-pass resolution via MCP tool surface" (§5.4) — that language predates the Hero stack's chosen architecture. hero_router has standardised on **OpenRPC spec → router-generated Python interface + sandboxed Python client**, not MCP. This issue tracks the work to align hero_assistance with that pattern. **Reference contract:** https://forge.ourworld.tf/lhumina_code/hero_router/src/branch/development/docs/agentic_calling.md ## Why this matters Per hero_router's `agentic_calling.md`: > The LLM does not need access to service data. It only needs the generated interface description. The router consumes each service's OpenRPC spec, generates two Python artifacts per service (a small interface file sent to the LLM; a full client file executed in a sandbox), MD5-fingerprints the spec to skip regeneration, and routes user-intent requests to the relevant interface(s). The LLM produces a workflow script from interface signatures only; the sandbox executes it; service data never reaches the LLM. hero_assistance is the natural first non-trivial hero_router consumer: - 91 wire-stable RPC methods (mycelium-identity-gated; D-04 / D-08). - A complete OpenRPC 1.3.0 spec at `crates/hero_assistance_server/openrpc.json` (~92 KiB, 17 namespaces). - A real workflow surface — triage, comment drafting, presence-aware ticket routing — that benefits more from agentic execution than from a hand-rolled CLI. ## Scope ### What hero_assistance must contribute 1. **OpenRPC spec conformance audit.** Walk every method block in `crates/hero_assistance_server/openrpc.json` and confirm: - `params` schemas are complete (no missing `required` lists, no `additionalProperties: true` where the handler actually rejects extras). - `result` schemas describe what the handler returns, not what an earlier draft thought it returned. (Phase 13b found at least one drift — `presence.list` returns `name` without it being declared.) - Per-method `description` is informative enough for an LLM to choose between sibling methods (`channel.create` vs `ticket.create`, `message.send` vs `comment.create`). - `errors` enumerate the codes the handler actually emits (`-32002 PermissionDenied`, `-32003 NotFound`, `-32602 InvalidParams`, etc.) — D-16's structured `RpcCallError` discrimination depends on this. 2. **Per-method intent metadata** (additive — does not change wire shape). For each method, add an `x-hero-intent` extension block describing: - **Side-effect class** (`read` / `mutate-own` / `mutate-others` / `admin`). Sandbox can use this to gate execution paths or require confirmation. - **Audience scope** (`self` / `workspace` / `project` / `cross-project`). Mirrors the presence-fanout audience model. - **Identity requirement** (`anonymous-ok` / `enrolled-user` / `support-role` / `admin-role`). - **Idempotency** (`safe` / `idempotent` / `unsafe`). Distinguishes `presence.set_status_text` (idempotent, replays cheap) from `comment.create` (unsafe, replays duplicate). 3. **Identity-pinning contract for sandboxed calls.** The router's sandbox runs as some identity; the hero_assistance privacy invariant (D-04 three-layer identity + D-20 per-recipient `/events` filter) requires that every RPC call carry a `caller_id` that the LLM cannot forge. Document the contract: - The sandbox MUST set `caller_id` from the human-user identity that hero_router authenticated, never from LLM output. - The sandbox MUST NOT carry one user's identity into a script generated for another user. - The `/events` TCP route's per-recipient server-side filter (D-20) is the regression gate — any agentic call that subscribes to events MUST hit `/events` with `X-Hero-User: <human-user>`, not `<sandbox-service-account>`. 4. **OpenRPC publishing endpoint.** hero_router needs a way to fetch the spec. Decide between: - **(a)** Static URL — `_ui` serves `crates/hero_assistance_server/openrpc.json` at `/openrpc.json` (simplest; spec is already build-time-stable). - **(b)** RPC method — `rpc.discover` returns the spec inline (OpenRPC 1.3 standard; needs a handler). - **(c)** Both — static URL for cold-discovery, `rpc.discover` for in-protocol introspection. Recommended: **(c)**, mirror what hero_router expects (open question — needs router-side confirmation). 5. **Sandbox-friendly workflow examples.** Ship 3–5 example workflows in `docs/dev/agentic_workflows.md` matching the `agentic_calling.md` style — e.g., "find every open ticket in this workspace older than 7 days and post a follow-up comment from the assigned support agent." These double as integration-test fixtures and as documentation for what the router-side sandbox must support. 6. **Vision doc + roadmap update.** Replace MCP language with hero_router-pattern language: - §2.5: "v0.4 will register every method as an MCP tool" → "v0.4 publishes the spec to hero_router for agentic calling per [hero_router/docs/agentic_calling.md](...). Spec is the contract; the router generates the Python interface + sandboxed client." - §5.4 M4+ bullet "AI-driven triage and first-pass resolution via MCP tool surface" → "AI-driven triage via hero_router agentic calling — the router selects relevant interfaces based on user intent; the LLM generates a workflow script; the sandbox executes against hero_assistance RPC." - Add a new decision file `decisions/D-21-agentic-calling-via-hero-router.md` recording (a) the choice (hero_router pattern over MCP), (b) the security invariant (LLM sees interface only; sandbox holds identity), (c) the wire contribution (audit + `x-hero-intent` extension; no new RPC methods). ### What hero_assistance does NOT do - **No router-side code.** hero_router owns the interface generator, the MD5 fingerprint cache, the LLM prompt, the sandbox, the intent classifier. hero_assistance is the *spec source* and a *consumer* of the resulting clients. - **No new wire methods.** All 91 methods stay; this issue is a metadata + spec-quality + documentation pass plus optional `rpc.discover`. - **No MCP server build.** MCP could re-enter post-v1 if a non-Hero-stack agent (Claude Desktop, Cursor, etc.) needs to drive hero_assistance directly — but it would be a separate workstream, not the primary agentic surface. ## Acceptance criteria - [ ] `crates/hero_assistance_server/openrpc.json` audited end-to-end; every drift between handler behaviour and spec recorded as a fix or as an explicit `x-hero-known-drift` annotation. - [ ] Every method has `x-hero-intent` populated with side-effect class, audience scope, identity requirement, idempotency. - [ ] `_ui` serves the spec at `/openrpc.json` (or whatever path hero_router expects — confirm with router maintainer); response is `application/json`, `Content-Type` correct, cacheable with the same MD5 hero_router uses. - [ ] (If decided) `rpc.discover` handler returns the embedded spec; covered by a hermetic integration test. - [ ] Identity-pinning contract documented in `docs/dev/agentic_calling.md` (hero_assistance side; complements hero_router's doc) with the D-04 + D-20 invariants front-and-centre. - [ ] 3–5 example workflows in `docs/dev/agentic_workflows.md` covering: read-only triage, single-user mutate, multi-user fanout, cross-method (presence + comment), error-path ("user not enrolled in workspace"). - [ ] `docs/vision/HERO_ASSISTANCE.md` §2.5 + §5.4 + roadmap updated; MCP language replaced with hero_router-pattern language. - [ ] `decisions/D-21-agentic-calling-via-hero-router.md` filed. - [ ] `docs/dev/e2e_checklist.md` Section L (programmable surface) extended with row(s) covering the spec-publish endpoint and the `x-hero-intent` extension. M2/M3 milestone tag depending on prioritisation. - [ ] CLAUDE.md "Current state" + `prompt.md` §1 + tracking issue #1 updated at session-end. - [ ] L-XX limitation filed if any acceptance criterion is descoped (e.g., live router integration deferred until hero_router exposes a discovery endpoint). ## Roadmap framing Per `prompt.md` §3, hero_assistance is **engineering-complete pre-customer**. M3 / v1.0 is customer-gated. This issue is the *last engineering-complete item* — once it lands: - The agentic surface is wired (per Hero-stack convention, not MCP). - 91 methods are spec-audited and intent-tagged. - Vision doc reflects reality (no orphan MCP language). - D-04 / D-20 privacy invariants are explicitly preserved through the sandbox boundary. After this issue closes, hero_assistance can credibly be called **engineering-complete full-stop** — including the AI-amenable programmable surface that vision §2.5 promises. Anything beyond is customer-driven (M3) or M4+ aspirational. **Estimated work:** 1–2 sessions if hero_router's discovery endpoint contract is already nailed down; 2–3 sessions if router-side coordination surfaces wire shape disagreements. ## Open questions 1. **Router-side discovery contract.** Does hero_router expect spec at a fixed URL path, registered via a registry RPC, or both? `agentic_calling.md` §16 shows a `services:` YAML registry but doesn't say who writes it. 2. **MD5 alignment.** `agentic_calling.md` §3 says the router computes the MD5. Does it want raw bytes of `openrpc.json`, or a canonicalised form? Critical for cache stability. 3. **`x-hero-intent` schema.** Is this extension already specified somewhere in the Hero stack? If yes, conform. If no, hero_assistance becomes the reference implementation — file the schema as part of D-21. 4. **Sandbox identity-injection mechanism.** Does the sandbox already know how to set `caller_id` per call, or does that need router-side support? Confirm with hero_router maintainer before committing to the contract in (3) above. 5. **Live router integration.** Is there a reachable hero_router test instance against which hero_assistance can verify the round-trip end-to-end, or does verification stay docs-only until a deployment surfaces it? ## References - **hero_router contract:** https://forge.ourworld.tf/lhumina_code/hero_router/src/branch/development/docs/agentic_calling.md - **hero_assistance OpenRPC spec:** `crates/hero_assistance_server/openrpc.json` - **Vision doc:** `docs/vision/HERO_ASSISTANCE.md` §2.5, §5.4 - **D-04 three-layer identity:** `decisions/D-04-three-layer-identity.md` - **D-20 events-over-TCP per-recipient filter:** `decisions/D-20-events-over-tcp-transport.md` - **Master tracking issue:** #1 - **Customer-readiness gate (sibling open issue):** #7
Author
Owner

Closed in session 37 (2026-05-06). Two source commits: 62a7fb3 (Phase 23 part 1 — spec audit + 3 phase23 regression tests + D-21) + d2d0cac (Phase 23 part 2 — docs/dev/agentic_calling.md + docs/dev/agentic_workflows.md + vision-doc MCP-language reframe + e2e_checklist Section L update) + 857e52e (handoff).

Acceptance-criteria walk

  • OpenRPC spec audit end-to-end — all 91 methods got summary (one-line lift) + structured errors[] (framework codes -32600/-32601/-32602/-32603 always; identity-bearing methods add -32001/-32002/-32005; lookup-shaped .get/.update/.delete add -32003; conflict-prone heuristically -32004) + x-hero-intent block.
  • Per-method intent metadata populated: {side_effect_class, audience_scope, identity_requirement, idempotency} on all 91 methods. Schema declared at info.x-hero-intent-schema in the spec itself; consumers tolerate unknown values (open enums) so future hero_router-side rework is non-breaking. Distribution: 41 read / 40 mutate-others / 6 mutate-self / 4 admin; 82 enrolled-user / 6 anonymous / 3 admin-role; 41 safe / 30 replay-safe / 20 replay-unsafe.
  • OpenRPC publishing endpointrpc.discover over UDS (Hero convention; matches hero_supervisor/hero_aibroker/ping/hero_auth/hero_books/hero_indexer) AND HTTP GET /openrpc.json (developer-experience parity). Both pre-existing in the snapshot from hero_collab; Phase 4 reduced to adding regression tests. Note: original acceptance-criterion text said _ui serves the spec at /openrpc.json; revised to _server serves it (which is what the router actually consumes via UDS) — _ui HTTP proxy is dev-ergonomic only and tracked as a discretionary follow-up.
  • rpc.discover handler returns embedded spec; covered by hermetic integration test — three tests landed: phase23_rpc_discover_returns_openrpc_spec_with_self_listed, phase23_rpc_discover_byte_stable_across_calls (FNV cache invariant), phase23_http_openrpc_returns_spec_over_uds_rpc_sock.
  • Identity-pinning contract documented in docs/dev/agentic_calling.md. Sandbox MUST set X-Hero-User from the human-user identity hero_router authenticated, NEVER from LLM output. Same surface as /rpc and /events (D-04, D-20) — zero new identity code paths. The phase22_events_tcp_per_user_filter_excludes_non_recipient per-recipient /events filter doubles as the agentic-calling privacy regression gate.
  • 5 example workflows in docs/dev/agentic_workflows.md covering: read-only triage / single-user mutate / multi-user fanout (canonical confirmation flow for mutate-others + replay-unsafe) / cross-method (presence + read-cursor + status text) / error-path (-32004 Conflict recovery + abort-before-mutation on user-not-enrolled). Each annotated with x-hero-intent classifications + sandbox runtime author guidance. Doubles as router-integration test fixtures.
  • docs/vision/HERO_ASSISTANCE.md §2.5 + §5.4 + roadmap updated — six surgical edits replace inherited "every method as MCP tool" / "OpenRPC + MCP" language with hero_router-pattern language. MCP retained as a post-v1 candidate for non-Hero-stack agents but no longer the primary surface. hero_browser MCP refs (visual-regression tooling) preserved — those are unrelated.
  • decisions/D-21-agentic-calling-via-hero-router.md filed — locks: (a) hero_router pattern over MCP; (b) wire facts settled by precedent + upstream doc (rpc.discover over UDS, FNV-1a-64 hash over raw bytes, unauthenticated by Hero convention); (c) x-hero-intent schema as reference impl with open-enum semantics; (d) identity-pinning contract preserving D-04 + D-20 invariants.
  • docs/dev/e2e_checklist.md Section L extended — full s37 audit-log entry; "MCP?" column doc broadened to include hero_router agentic-calling sandbox scripts (column name kept stable to avoid 90+ row churn); M1-L-88 (rpc.discover) Wired? flips from [skip: NO-COVERAGE-YET] to via the 3 phase23 tests; Section L summary updated (wired count 26 → 27).
  • CLAUDE.md "Current state" + prompt.md §1 + tracking issue #1 updated at session-end857e52e lands the handoff doc updates; tracking issue #1 §0 patched in-place via Forgejo API.
  • [n/a] L-XX limitation if any acceptance criterion descoped — none descoped. Live router round-trip verification deferred to issue #7 customer-readiness gate (already tracked there, not a new L). The _ui /openrpc.json HTTP proxy is documented as a discretionary DX follow-up in D-21 + prompt.md §3.

B.5 adversarial review

Ran at session-start. Caught 3 load-bearing problems before code landed:

  1. Hash-algorithm error. Original §3 + draft plan said MD5; agentic_calling.md §3 explicit on FNV-1a 64-bit. Corrected — D-21 records the actual algorithm; prompt.md §3 errata implicitly carried forward (old text doesn't reappear).
  2. Publish-surface error. Original plan mounted /openrpc.json on _ui (HTTP) — but router fetches via UDS rpc.discover on _server. _ui route would have bypassed D-04's identity surface if implementation drifted. Corrected: pre-existing rpc.discover at rpc.rs:46 + state.openrpc_spec via include_str! at main.rs:375 + HTTP /openrpc.json at main.rs:486 are sufficient.
  3. Axiom-growth risk on x-hero-intent. Would have been invented unilaterally without open-enum semantics, risking cache poisoning if hero_router later defined its own shape. Corrected: D-21 documents the schema as an open-enum reference impl with explicit "consumers tolerate unknown values" semantics; future tightening is non-breaking.

Mechanical pre-deploy checks all clear: (1) no time-sensitive RPC params added; (2) no test-script phase mirroring concern; (3) no cross-node state-locality concern.

Cost of B.5: 1 subagent + 1 WebFetch. Saved cost: ≥1 session of post-merge cleanup + cache-poisoning recovery.

Open follow-ups (NOT v1.0-gating)

  • Live hero_router round-trip verification — gated on a reachable hero_router test instance + sandbox runtime. Tracked under issue #7 (customer-readiness gate).
  • _ui /openrpc.json HTTP proxy — developer-experience nicety (router uses UDS so this is dev-ergonomic only).
  • Tightening x-hero-intent.identity_requirement per-method — today's audit ships every authenticated method as enrolled-user; future deployments may want support-role for channel.delete / attachment.cleanup_pending / group.rights.set / etc. Schema permits this additive change; do it when a customer policy surfaces.
  • x-hero-known-drift annotation surface — this session's audit found no per-method drift requiring deferred annotation. If a future audit surfaces one, the convention is "x-hero-known-drift": "<one-line description with file:line>" at the method level.
  • Lifting handler-specific error codes into per-method errors[].data schemas — today's audit ships framework codes; per-method-specific error messages still live in description prose. A future audit can promote them; not load-bearing for v1.

Test posture

222 → 225 native passing (+3 phase23 tests) / 32 _ui_wasm lib unchanged / 13 ignored unchanged / 0 net failed. cargo build --release green; cargo test --no-fail-fast green end-to-end.

Session manifest

Full s37 manifest at sessions/37.yml.

Closed in session 37 (2026-05-06). Two source commits: `62a7fb3` (Phase 23 part 1 — spec audit + 3 phase23 regression tests + D-21) + `d2d0cac` (Phase 23 part 2 — `docs/dev/agentic_calling.md` + `docs/dev/agentic_workflows.md` + vision-doc MCP-language reframe + e2e_checklist Section L update) + `857e52e` (handoff). ## Acceptance-criteria walk - [x] **OpenRPC spec audit end-to-end** — all 91 methods got `summary` (one-line lift) + structured `errors[]` (framework codes -32600/-32601/-32602/-32603 always; identity-bearing methods add -32001/-32002/-32005; lookup-shaped .get/.update/.delete add -32003; conflict-prone heuristically -32004) + `x-hero-intent` block. - [x] **Per-method intent metadata** populated: `{side_effect_class, audience_scope, identity_requirement, idempotency}` on all 91 methods. Schema declared at `info.x-hero-intent-schema` in the spec itself; consumers tolerate unknown values (open enums) so future hero_router-side rework is non-breaking. Distribution: 41 read / 40 mutate-others / 6 mutate-self / 4 admin; 82 enrolled-user / 6 anonymous / 3 admin-role; 41 safe / 30 replay-safe / 20 replay-unsafe. - [x] **OpenRPC publishing endpoint** — `rpc.discover` over UDS (Hero convention; matches `hero_supervisor`/`hero_aibroker/ping`/`hero_auth`/`hero_books`/`hero_indexer`) AND HTTP `GET /openrpc.json` (developer-experience parity). Both pre-existing in the snapshot from `hero_collab`; Phase 4 reduced to adding regression tests. **Note:** original acceptance-criterion text said `_ui` serves the spec at `/openrpc.json`; revised to **`_server` serves it** (which is what the router actually consumes via UDS) — `_ui` HTTP proxy is dev-ergonomic only and tracked as a discretionary follow-up. - [x] **`rpc.discover` handler returns embedded spec; covered by hermetic integration test** — three tests landed: `phase23_rpc_discover_returns_openrpc_spec_with_self_listed`, `phase23_rpc_discover_byte_stable_across_calls` (FNV cache invariant), `phase23_http_openrpc_returns_spec_over_uds_rpc_sock`. - [x] **Identity-pinning contract documented** in `docs/dev/agentic_calling.md`. Sandbox MUST set `X-Hero-User` from the human-user identity hero_router authenticated, NEVER from LLM output. Same surface as `/rpc` and `/events` (D-04, D-20) — zero new identity code paths. The `phase22_events_tcp_per_user_filter_excludes_non_recipient` per-recipient `/events` filter doubles as the agentic-calling privacy regression gate. - [x] **5 example workflows** in `docs/dev/agentic_workflows.md` covering: read-only triage / single-user mutate / multi-user fanout (canonical confirmation flow for `mutate-others` + `replay-unsafe`) / cross-method (presence + read-cursor + status text) / error-path (`-32004` Conflict recovery + abort-before-mutation on user-not-enrolled). Each annotated with x-hero-intent classifications + sandbox runtime author guidance. Doubles as router-integration test fixtures. - [x] **`docs/vision/HERO_ASSISTANCE.md` §2.5 + §5.4 + roadmap updated** — six surgical edits replace inherited "every method as MCP tool" / "OpenRPC + MCP" language with hero_router-pattern language. MCP retained as a post-v1 candidate for non-Hero-stack agents but no longer the primary surface. `hero_browser` MCP refs (visual-regression tooling) preserved — those are unrelated. - [x] **`decisions/D-21-agentic-calling-via-hero-router.md` filed** — locks: (a) hero_router pattern over MCP; (b) wire facts settled by precedent + upstream doc (`rpc.discover` over UDS, FNV-1a-64 hash over raw bytes, unauthenticated by Hero convention); (c) `x-hero-intent` schema as reference impl with open-enum semantics; (d) identity-pinning contract preserving D-04 + D-20 invariants. - [x] **`docs/dev/e2e_checklist.md` Section L extended** — full s37 audit-log entry; "MCP?" column doc broadened to include hero_router agentic-calling sandbox scripts (column name kept stable to avoid 90+ row churn); M1-L-88 (`rpc.discover`) Wired? flips from `[skip: NO-COVERAGE-YET]` to ✅ via the 3 phase23 tests; Section L summary updated (wired count 26 → 27). - [x] **CLAUDE.md "Current state" + `prompt.md` §1 + tracking issue #1 updated at session-end** — `857e52e` lands the handoff doc updates; tracking issue #1 §0 patched in-place via Forgejo API. - [n/a] **L-XX limitation if any acceptance criterion descoped** — none descoped. Live router round-trip verification deferred to issue #7 customer-readiness gate (already tracked there, not a new L). The `_ui` `/openrpc.json` HTTP proxy is documented as a discretionary DX follow-up in D-21 + prompt.md §3. ## B.5 adversarial review Ran at session-start. Caught 3 load-bearing problems before code landed: 1. **Hash-algorithm error.** Original §3 + draft plan said MD5; agentic_calling.md §3 explicit on FNV-1a 64-bit. Corrected — D-21 records the actual algorithm; prompt.md §3 errata implicitly carried forward (old text doesn't reappear). 2. **Publish-surface error.** Original plan mounted `/openrpc.json` on `_ui` (HTTP) — but router fetches via UDS `rpc.discover` on `_server`. `_ui` route would have bypassed D-04's identity surface if implementation drifted. Corrected: pre-existing `rpc.discover` at `rpc.rs:46` + `state.openrpc_spec` via `include_str!` at `main.rs:375` + HTTP `/openrpc.json` at `main.rs:486` are sufficient. 3. **Axiom-growth risk on `x-hero-intent`.** Would have been invented unilaterally without open-enum semantics, risking cache poisoning if hero_router later defined its own shape. Corrected: D-21 documents the schema as an open-enum reference impl with explicit "consumers tolerate unknown values" semantics; future tightening is non-breaking. Mechanical pre-deploy checks all clear: (1) no time-sensitive RPC params added; (2) no test-script phase mirroring concern; (3) no cross-node state-locality concern. Cost of B.5: 1 subagent + 1 WebFetch. Saved cost: ≥1 session of post-merge cleanup + cache-poisoning recovery. ## Open follow-ups (NOT v1.0-gating) - **Live hero_router round-trip verification** — gated on a reachable hero_router test instance + sandbox runtime. Tracked under issue #7 (customer-readiness gate). - **`_ui` `/openrpc.json` HTTP proxy** — developer-experience nicety (router uses UDS so this is dev-ergonomic only). - **Tightening `x-hero-intent.identity_requirement` per-method** — today's audit ships every authenticated method as `enrolled-user`; future deployments may want `support-role` for `channel.delete` / `attachment.cleanup_pending` / `group.rights.set` / etc. Schema permits this additive change; do it when a customer policy surfaces. - **`x-hero-known-drift` annotation surface** — this session's audit found no per-method drift requiring deferred annotation. If a future audit surfaces one, the convention is `"x-hero-known-drift": "<one-line description with file:line>"` at the method level. - **Lifting handler-specific error codes into per-method `errors[].data` schemas** — today's audit ships framework codes; per-method-specific error messages still live in description prose. A future audit can promote them; not load-bearing for v1. ## Test posture 222 → 225 native passing (+3 phase23 tests) / 32 `_ui_wasm` lib unchanged / 13 ignored unchanged / 0 net failed. `cargo build --release` green; `cargo test --no-fail-fast` green end-to-end. ## Session manifest Full s37 manifest at `sessions/37.yml`.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_assistance#8
No description provided.