Herdr lifecycle contract: event shapes, seq semantics, and coexistence (reference from #750)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19.9k
- Forks
- 2.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 30
Description
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
sourcedrive pane label, state, rollups, and waits. pane.release_agentand stale-seqordering behave per docs: a release withseqbelow the last accepted state report is ignored — hence the monotonic per-source ramp.agent_session_idis persisted (and later used for restore) only for official sources.herdr:jcodeis 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
- A yes/no on this event shape + seq + coexistence contract as the thing both herdr#2248 and any jcode-side implementation must satisfy.
- 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reference implementation in crates/jcode-base/src/herdr.rs and its contract documentation in docs/HERDR.md, then review the lifecycle observer and permission-queue behavior described here. Compare the reference against Herdr 0.8.2 and #750; done means the event shapes, sequence semantics, and coexistence decision are explicitly accepted, amended, or rejected.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100