Skip to content

Herdr lifecycle contract: event shapes, seq semantics, and coexistence (reference from #750) #1127

Description

@tobias-hui

Why this issue

#750 is blocked on two decisions: where the integration lives (jcode / Herdr / both) and what the stable lifecycle contract is. The Herdr-side half already exists — herdrdev/herdr#2248 adds jcode as an official integration target. This issue records the jcode-side half of the contract as it has been implemented and verified end to end against Herdr 0.8.2, so the decision in #750 has a concrete, tested baseline to accept, amend, or reject.

Reference implementation + full contract doc: branch feat/herdr-lifecycle-integration in my fork, opened as draft PR PR #TBD-pending (crates/jcode-base/src/herdr.rs, docs/HERDR.md). ~1575 lines across 8 files; the emitter is one new module, the rest is small wiring. I am not asking for it to be merged as-is — per CONTRIBUTING I expect it to serve as reference. What I am asking to freeze is the contract below.

The contract

Trigger and scope

When a client's request-scoped environment carries HERDR_ENV=1 + HERDR_SOCKET_PATH + HERDR_PANE_ID, jcode reports lifecycle natively to that pane's Herdr socket (NDJSON, the pi-integration protocol). No user-side hook configuration. JCODE_HERDR_REPORT=0 opts out. On the shared daemon, identity comes from each client's request scope (the same task-local terminal env that scopes shell hooks, #758), never from the daemon process env — one daemon serving many panes does not cross-report.

Events jcode emits

method when key params
pane.report_agent_session session create/attach/resume source: "herdr:jcode", agent: "jcode", monotonic seq, agent_session_id, session_start_source (startup/resume)
pane.report_agent turn start → working; settle → idle; unresolved permission request → blocked; permission resolved/expired → clears blocked same source/agent, seq continues the ramp
pane.release_agent session_end releases the pane's agent slot

Semantics Herdr already accepts (verified against 0.8.2 by direct socket experiments)

  • Reports from any source drive pane label, state, rollups, and waits.
  • pane.release_agent and stale-seq ordering behave per docs: a release with seq below the last accepted state report is ignored — hence the monotonic per-source ramp.
  • agent_session_id is persisted (and later used for restore) only for official sources. herdr:jcode is accepted but the reference is dropped; custom:* stores nothing. This is the single remaining gap and it is exactly what herdr#2248 proposes to close by accepting ("herdr:jcode", "jcode").

Coexistence rule (important for the "where does it live" decision)

If a session_start hook adapter (as proposed in herdr#2248) is installed, it reports under the same herdr:jcode source; two reporters on one source drop each other's updates via the seq ramp. The emitter therefore detects an installed adapter and stands down (hook_adapter_installed). Installing or not installing the adapter is always safe; the emitter and the adapter are mutually exclusive by design, not by configuration discipline.

Boundary with shell hooks

The emitter rides the existing lifecycle observer funnel (dispatch_observer), so turn_start/turn_end/session_start/session_end semantics are shared with shell hooks rather than reinvented. hook_configured() returns true for the four lifecycle events while a Herdr client is watching (so payload construction happens), but tool-hot paths (pre_tool/post_tool) are not consumed and pay nothing. Permission blocked pins come from a new observer on the existing permission queue; it is a non-blocking hot-path observer, no-op when unattached.

What I am asking for

  1. A yes/no on this event shape + seq + coexistence contract as the thing both herdr#2248 and any jcode-side implementation must satisfy.
  2. If yes, whether the jcode half should be my emitter, Jeremy's own version, or folded into the adapter design — I am indifferent whose code lands as long as the contract is the one above.

Validation performed

End to end against Herdr 0.8.2 on Linux: panes running a jcode TUI appear in herdr agent list as jcode with live working/idle/blocked rollups, blocked clears on permission resolution, release on close; daemon process-env isolation is pinned by a regression test in the branch.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    autonomous: noNeeds your brain: a product/design decision is required before anyone acts.enhancementNew feature or requesttriage: needs-decisionNeeds maintainer decision/design thought

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions