1jehuang / 1jehuang/jcode

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

Open
#1,127 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no enhancement triage: needs-decision
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 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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.