Problem
Interactive skills write artifacts but emit no events, so there is no channel for live lifecycle status (#984). Spike #985 needs a production-track emit helper before skills can be instrumented.
Proposed solution
A bundled skill helper following the derive-session-context pattern: TS at packages/agents/src/emit-event/, a new BundleTarget producing content/skills/emit-event/emit-event.mjs (user-invocable: false), with a smoke test in the existing harness.
Envelope v0: {id, ts, type, repo, branch, session, cwd, harness, payload} — ULID id, nested per-family payload. cwd is included because #984 lists it among the fields (id, timestamp, branch ref, session, cwd) that must align across the lifecycle and KB-curated event stores. Session-lifecycle vocabulary v0: skill.started, skill.progress, skill.completed, artifact.written, input.requested, input.received, pr.created.
Context autofill draws on four sources: repo, branch, and session are each promoted into shared modules under packages/agents/src/shared/ (resolve-repo.ts, branch-helpers.ts, resolve-session.ts) that both capture-event and emit-event consume, rather than either helper duplicating the git-reading and environment-reading logic; cwd comes from the process; harness is not derived at runtime but template-injected at install time, the same way the installer fills capture-event's --harness flag. --session overrides the environment-derived id for the Rovo relay. A single O_APPEND write appends to ~/.codeassembly/events/{owner}/{name}/{sanitized-branch}/{session}.jsonl, with the branch name sanitized the way the branch manifest sanitizes branch names. Never-block contract: any failure warns on stderr and exits 0 — telemetry must not break the skill it observes.
Settled in design review: the payload arrives as --payload '<json>' (a JSON object, default {}); ts is millisecond-precision ISO-8601; an unknown --type warns on stderr but still appends, so the v0 vocabulary is convention rather than a gate; an unresolvable repo, branch, or session falls back to a placeholder path segment (_no-repo/_no-repo, _no-branch, _no-session) instead of dropping the event; the helper always prints a structured {ok, ...} result to stdout. The entrypoint is the skill helper, not an MCP tool (token analysis in comments).
Acceptance criteria
Must have
Part of spike #985 (blocks its observation window).
Problem
Interactive skills write artifacts but emit no events, so there is no channel for live lifecycle status (#984). Spike #985 needs a production-track emit helper before skills can be instrumented.
Proposed solution
A bundled skill helper following the
derive-session-contextpattern: TS atpackages/agents/src/emit-event/, a newBundleTargetproducingcontent/skills/emit-event/emit-event.mjs(user-invocable: false), with a smoke test in the existing harness.Envelope v0:
{id, ts, type, repo, branch, session, cwd, harness, payload}— ULID id, nested per-family payload.cwdis included because #984 lists it among the fields (id, timestamp, branch ref, session, cwd) that must align across the lifecycle and KB-curated event stores. Session-lifecycle vocabulary v0:skill.started,skill.progress,skill.completed,artifact.written,input.requested,input.received,pr.created.Context autofill draws on four sources:
repo,branch, andsessionare each promoted into shared modules underpackages/agents/src/shared/(resolve-repo.ts,branch-helpers.ts,resolve-session.ts) that bothcapture-eventandemit-eventconsume, rather than either helper duplicating the git-reading and environment-reading logic;cwdcomes from the process;harnessis not derived at runtime but template-injected at install time, the same way the installer fillscapture-event's--harnessflag.--sessionoverrides the environment-derived id for the Rovo relay. A singleO_APPENDwrite appends to~/.codeassembly/events/{owner}/{name}/{sanitized-branch}/{session}.jsonl, with the branch name sanitized the way the branch manifest sanitizes branch names. Never-block contract: any failure warns on stderr and exits 0 — telemetry must not break the skill it observes.Settled in design review: the payload arrives as
--payload '<json>'(a JSON object, default{});tsis millisecond-precision ISO-8601; an unknown--typewarns on stderr but still appends, so the v0 vocabulary is convention rather than a gate; an unresolvablerepo,branch, orsessionfalls back to a placeholder path segment (_no-repo/_no-repo,_no-branch,_no-session) instead of dropping the event; the helper always prints a structured{ok, ...}result to stdout. The entrypoint is the skill helper, not an MCP tool (token analysis in comments).Acceptance criteria
Must have
--typeand payload.--sessionoverrides the environment-derived session id.repo,branch, orsessionis appended under placeholder path segments rather than dropped.--typewarns on stderr and the envelope is still appended.Part of spike #985 (blocks its observation window).