feat(overseer): ping_session relay write-tool (Stage 1.5) - #104
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f389c889dc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cfafd32020
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aafac9c6ce
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
b6e6708 to
8d59e9f
Compare
e62cb17 to
55ca5c5
Compare
8d59e9f to
8b9c5d5
Compare
55ca5c5 to
284c12c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 284c12c871
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Gives the Overseer an operator-directed way to ping an individual project session — the delegation brick from the action architecture (R5). - New write tool `ping_session` (sessionId and/or itemId → related session, then resume-if-inactive + enqueue). Wired through SyncEngine's existing resumeSession/sendMessage primitives — never shells out to hapi-ping-peer. - Identity gains `canRelay`; catalog now has 11 tools (2 writes). System prompt updated for Stage 1.5 relay discipline (imperative-only, tombstone). - runOverseerTool is async; HTTP tool surface still 403s writes (converse allowWrites remains the only write path). Also: operator hub URL is now https://hapi-gc-oos.forest-adder.ts.net (svc:hapi-gc-oos; old *.tail9944ee.ts.net MagicDNS is dead). Co-authored-by: Cursor <cursoragent@cursor.com>
get_session_state/get_worker_health/query_events only did exact UUID match, so the brain's truncated 8-char ids returned null and Overseer falsely called live inbox rows "ghost sessions". Shared unique-prefix resolve (same as ping_session); lean inbox keeps full relatedSessionId + summary; prompt clarifies null ≠ deleted. Co-authored-by: Cursor <cursoragent@cursor.com>
Resume can remap the hub session id after spawn+merge; relay now sends to that id. Failed relays mark toolTrace.ok false, and a brain failure after a successful write returns the write audit trail instead of an empty failure. Co-authored-by: Cursor <cursoragent@cursor.com>
…d audit Server-side authorization for write tools from the latest operator utterance (or explicit allowWrites). Reject sessionId/itemId mismatches. Record idempotent dispatched events after successful relays. Co-authored-by: Cursor <cursoragent@cursor.com>
8b9c5d5 to
10e3c26
Compare
Default query_inbox no longer treats sleeping snoozes as visible; write tools bind to operator-named session/item/payload with dedupe; relay refuses fresh-spawn and keeps ok when audit insert fails; OverseerEntity is per-namespace (#107 kill criterion) via SyncEngine.getOverseer(ns). Co-authored-by: Cursor <cursoragent@cursor.com>
caff271 to
b3465a9
Compare
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 483c08815f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const RELAY_INTENT = | ||
| /\b(ping|relay|nudge|wake)\b|\btell\b[\s\S]{0,80}\b(session|worker|peer|agent|him|her|them|it)\b|\b(message|ask|send)\b[\s\S]{0,80}\b(session|worker|peer|agent)\b/i |
There was a problem hiding this comment.
When the latest utterance is do not ping session abcdef12, the bare-keyword regex still grants ping_session, extracts the target, and—because there is no quoted snippet—authorizes any relay payload to that session. A prompt-injected read result can therefore trigger the exact irreversible action the operator prohibited. Fresh evidence after the earlier intent-gate fix is that this regex does not account for negation or distinguish a relay command from discussion of relaying.
Useful? React with 👍 / 👎.
| const hasTargetGrant = auth.sessionIdPrefixes.length > 0 || auth.itemIds.length > 0 | ||
| if (!hasTargetGrant) { |
There was a problem hiding this comment.
Authorize relays resolved from named sessions
For the documented natural-language flow ping the expenses session: please continue, no UUID/item ID appears in the latest utterance, so this branch rejects the eventual ping_session call even after the brain resolves Expenses through list_active_workers. Because writeAuth is fixed before tool execution, project/session names can never become authorized targets; the advertised name-based relay flow only works when the operator supplies a literal ID or an unavailable client override.
Useful? React with 👍 / 👎.
| if (auth.itemIds.length === 0) { | ||
| return { | ||
| ok: false, | ||
| error: 'disposition requires an explicit item id in the operator message (or allowWrites)' | ||
| } |
There was a problem hiding this comment.
Preserve contextual disposition targets
When an operator follows an inbox explanation with the supported command mark that done, the target item exists in conversation history but not in the latest utterance, so this new gate rejects every record_disposition call. This regresses the existing referential disposition flow and contradicts the system prompt's own mark that done example; authorization needs to bind the previously resolved item or request confirmation rather than requiring the operator to repeat its numeric ID.
Useful? React with 👍 / 👎.
| // Bucket to the second so identical retries within the same second collapse. | ||
| const idempotencyKey = `overseer-dispatched:${input.sessionId}:${ts - (ts % 1000)}:${hashRelaySnippet(input.message)}` |
There was a problem hiding this comment.
Record every delivered relay in the audit stream
If two identical relays to the same session are delivered within one second—for example from concurrent converse requests or an immediate intentional repeat—both messages are enqueued, but this shared idempotency key causes the second dispatched insertion to return the first event. The session audit therefore records one dispatch for two actual writes; either make delivery itself idempotent under the same key or give each successful delivery a distinct audit identity.
Useful? React with 👍 / 👎.
Stacked on #103 (admin console). Review/merge after it.
Summary
ping_sessionwrite tool — Overseer can relay an operator-directed message to one worker/project session (resume if inactive, then enqueue). PasssessionId(full or unique prefix) and/oritemId(inbox item →relatedSessionId).resumeSession+sendMessagein-process (R5 — never shellshapi-ping-peer).canRelay: true. Catalog: 11 tools, 2 writes. Conversational path only (allowWrites); HTTP tool dispatch still 403s writes.Hub URL note (ops)
Live operator hub is now https://hapi-gc-oos.forest-adder.ts.net/ (
svc:hapi-gc-oos). Oldhapi.tail9944ee.ts.net/*.tail9944ee.ts.netMagicDNS is dead after the tailnet rename toforest-adder.ts.net.~/.hapi/hub.env+settings.jsonpublicUrlalready updated on the box.Test plan
bun run typecheck(cli + web + hub)/overseertalk-to, say "ping that expenses session to draft the Cursor Pro note" and confirm the target session receives the messageMade with Cursor