@thehammer/danx-session-telemetry 0.1.41 → 0.1.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  DX-2962 — the shared Claude Code transcript collector, extracted from
4
4
  danxbot root's `src/agent/session-log-watcher.ts` so the danxbot worker and
5
- the `danx-dashboard-mcp` desktop bridge (DX-2954) run **identical** collector
5
+ the `danx-dashboard-mcp` MCP server's plan event relay (DX-2954) run **identical** collector
6
6
  code, instead of the worker's copy silently diverging from a re-implementation
7
7
  inside the MCP package.
8
8
 
@@ -44,7 +44,7 @@ own header comments for the per-file reasoning.
44
44
  | Consumer | Mechanism | Why |
45
45
  |---|---|---|
46
46
  | **danxbot worker** (root repo, `tsx src/index.ts`) | npm **workspace** link (`"workspaces": ["packages/*"]` in root `package.json`, `"@thehammer/danx-session-telemetry"` in root `dependencies`) | The worker and this package always ship from the SAME repo commit — a workspace link means the worker runs whatever source the current commit carries, with zero drift risk and no dependency on registry propagation timing. The Docker image builds `dist/` for it in a dedicated builder stage (alongside `frontend-builder` in `Dockerfile`) since the final image's `npm ci --omit=dev` never installs this package's own `devDependencies` (`typescript`). |
47
- | **`danx-dashboard-mcp` desktop bridge** (separate npm-published package, DX-2954) | Ordinary npm dependency, **pinned to the exact published version** the worker's commit ships | The bridge is a genuinely separate installable artifact (`npx -y @thehammer/danx-dashboard-mcp`), so it cannot workspace-link into danxbot's own checkout — it needs the real published bytes. Pinning exact (not `^`/`~`) is what makes "worker and MCP run identical collector code for any given release" true: MCP's own version bump is the only thing that ever changes what collector code it runs. |
47
+ | **`danx-dashboard-mcp` MCP server** (separate npm-published package, DX-2954) | Ordinary npm dependency, **pinned to the exact published version** the worker's commit ships | The MCP server is a genuinely separate installable artifact (`npx -y @thehammer/danx-dashboard-mcp`), so it cannot workspace-link into danxbot's own checkout — it needs the real published bytes. Pinning exact (not `^`/`~`) is what makes "worker and MCP run identical collector code for any given release" true: MCP's own version bump is the only thing that ever changes what collector code it runs. |
48
48
  | **Dashboard server** (`src/dashboard/*`) | Same npm dependency shape as the worker (the dashboard server's `src/` is root-repo code, so it resolves through the SAME root workspace link as the worker) | An npm dependency resolves through ordinary node_modules lookup, so no `@backend`-style alias is needed. |
49
49
 
50
50
  ## Release order (DX-2962 AC3)
@@ -52,7 +52,6 @@ own header comments for the per-file reasoning.
52
52
  1. Publish this package (`make publish-danx-session-telemetry`).
53
53
  2. Publish `danx-dashboard-mcp` (only once it depends on this package — DX-2954).
54
54
  3. Deploy the danxbot backend.
55
- 4. Move the plugin's bridge-version pin.
56
55
 
57
56
  Publishing comes before deploying because the publish-drift gate
58
57
  (`src/dispatch/publish-drift-gate.ts`) refuses a finalize whose bumped
package/dist/.source-hash CHANGED
@@ -1 +1 @@
1
- b066d72035e89bbf909f51f078f014e0b3910566bcb2d035c5f469b44573efa6
1
+ 1f7f247f7e5d5039a351835d2525a04c03edbb7a4ddac07cf83d4d599fe7ef07
@@ -31,7 +31,7 @@ export interface ClaimState {
31
31
  export declare function emptyClaimState(): ClaimState;
32
32
  /**
33
33
  * The per-process claim tracker: one state per sub-agent source. Fed every
34
- * transcript line by `DispatchUsage` (operator-bridge mode only — the worker never
34
+ * transcript line by `DispatchUsage` (`operator-bridge` mode only — the worker never
35
35
  * constructs one), seeded from the stored cursor at attach, and snapshotted per
36
36
  * source for the stats write.
37
37
  */
@@ -37,7 +37,7 @@
37
37
  *
38
38
  * The state is the held set PLUS the transitions whose `tool_use` has been read
39
39
  * and whose `tool_result` has not (`pending`). Both are persisted beside the
40
- * source's read cursor (`dispatch_source_cursors.claims`): a bridge that restarts
40
+ * source's read cursor (`dispatch_source_cursors.claims`): a relay that restarts
41
41
  * resumes at its stored `acked` offset, and a pickup that sits before it is never
42
42
  * re-read, so without the state every later reply would go unattributed. The
43
43
  * pending half closes the narrow window where the restart lands between a pickup's
@@ -133,7 +133,7 @@ function transitionOf(block) {
133
133
  }
134
134
  /**
135
135
  * The per-process claim tracker: one state per sub-agent source. Fed every
136
- * transcript line by `DispatchUsage` (operator-bridge mode only — the worker never
136
+ * transcript line by `DispatchUsage` (`operator-bridge` mode only — the worker never
137
137
  * constructs one), seeded from the stored cursor at attach, and snapshotted per
138
138
  * source for the stats write.
139
139
  */
@@ -37,8 +37,9 @@ export type FlushOutcome = "ok" | "failed" | "refused";
37
37
  * dispatch by refusing the WHOLE batch, which would stall the worker's stats,
38
38
  * token ceiling and spend alert on every resend - so a worker is structurally
39
39
  * unable to send one.
40
- * - `"operator-bridge"` - the desktop bridge of an operator session
41
- * (`danx-dashboard-mcp`'s `session-stats.ts`), the only path that attributes.
40
+ * - `"operator-bridge"` - the plan event relay of an operator session
41
+ * (`danx-dashboard-mcp`'s `session-stats.ts`), the only path that attributes. The value keeps its old name on purpose: it is
42
+ * this package's published API (the MCP package passes it), so renaming it is a new telemetry release, not a text fix.
42
43
  */
43
44
  export type DispatchUsageMode = "worker" | "operator-bridge";
44
45
  export declare class DispatchUsage {
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * (small per-reply bookkeeping only, kept in memory for the life of the
7
7
  * process — see `session-log-watcher.ts`'s header). Consumed by the
8
8
  * danxbot worker (Node, workspace-linked — see the README) and, from
9
- * DX-2954, the `danx-dashboard-mcp` desktop bridge (Node, npm-installed at
9
+ * DX-2954, the `danx-dashboard-mcp` MCP server's plan event relay (Node, npm-installed at
10
10
  * a pinned exact version).
11
11
  *
12
12
  * A browser-safe subset with NO `node:` imports lives at the `./browser`
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * (small per-reply bookkeeping only, kept in memory for the life of the
7
7
  * process — see `session-log-watcher.ts`'s header). Consumed by the
8
8
  * danxbot worker (Node, workspace-linked — see the README) and, from
9
- * DX-2954, the `danx-dashboard-mcp` desktop bridge (Node, npm-installed at
9
+ * DX-2954, the `danx-dashboard-mcp` MCP server's plan event relay (Node, npm-installed at
10
10
  * a pinned exact version).
11
11
  *
12
12
  * A browser-safe subset with NO `node:` imports lives at the `./browser`
@@ -28,7 +28,7 @@ export * from "./ledger-timing.js";
28
28
  export * from "./transcript-timing.js";
29
29
  export * from "./pricing.js";
30
30
  // DX-2954 — the ONE stats collector and its wire, shared by the danxbot worker
31
- // and the desktop bridge (operator sessions) so both report the same stats the
31
+ // and the MCP server's relay (operator sessions) so both report the same stats the
32
32
  // same way (epic DX-2958): the stats payload/response schema and its strict
33
33
  // parser, the collector that ships ledger entries + transcript cursors +
34
34
  // running-set changes, the transcript-side running-set producer, and the FIFO
@@ -12,10 +12,10 @@ function emit(level, component, message, error) {
12
12
  else if (error !== undefined) {
13
13
  entry.error = String(error);
14
14
  }
15
- // DX-2954 — every level goes to STDERR. The desktop bridge
16
- // (`danx-dashboard-mcp bridge`) now runs this collector, and its STDOUT is a
17
- // JSON Lines protocol channel the plugin parses record by record; a log line
18
- // there would be read as a bridge record. The worker captures both streams.
15
+ // DX-2954 — every level goes to STDERR. The MCP server's
16
+ // relay and the one-shot subcommands run this collector; the subcommands' STDOUT is a protocol
17
+ // channel the plugin parses (and the MCP server's is JSON-RPC), so a log line there
18
+ // would corrupt it. The worker captures both streams.
19
19
  console.error(JSON.stringify(entry));
20
20
  }
21
21
  export function createLogger(component) {
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * DX-2962: moved unchanged from danxbot root `src/agent/session-log-watcher.ts`
5
5
  * into this shared published package, so the danxbot worker and the
6
- * `danx-dashboard-mcp` desktop bridge (DX-2954) run identical collector
6
+ * `danx-dashboard-mcp` MCP server's relay (DX-2954) run identical collector
7
7
  * code. Only the imports changed — `../logger.js` -> `./internal-logger.js`
8
8
  * (this package's own tiny logging shim, since root's `logger.ts` has ~300
9
9
  * unrelated consumers and does not move), `../types.js` -> `./types.js`
@@ -408,7 +408,7 @@ export declare class SessionLogWatcher {
408
408
  /**
409
409
  * DX-3964 - register a usage-feed consumer: it receives the parsed raw line of every assistant, user,
410
410
  * attachment and system line, in file order, with the same `EntryMeta` as `onEntry`. The ONLY subscribers are
411
- * the collector's two consumers at each of its two sites (the worker and the operator bridge): `DispatchUsage`
411
+ * the collector's two consumers at each of its two sites (the worker and the operator session's relay): `DispatchUsage`
412
412
  * and, DX-4498, the activity observer, which reads the sub-agent's brief and Claude Code's task notifications,
413
413
  * neither of which is an entry. `convertJsonlEntry` and every
414
414
  * `onEntry` subscriber keep seeing exactly what they saw before, because human prompts, attachments (tens of
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * DX-2962: moved unchanged from danxbot root `src/agent/session-log-watcher.ts`
5
5
  * into this shared published package, so the danxbot worker and the
6
- * `danx-dashboard-mcp` desktop bridge (DX-2954) run identical collector
6
+ * `danx-dashboard-mcp` MCP server's relay (DX-2954) run identical collector
7
7
  * code. Only the imports changed — `../logger.js` -> `./internal-logger.js`
8
8
  * (this package's own tiny logging shim, since root's `logger.ts` has ~300
9
9
  * unrelated consumers and does not move), `../types.js` -> `./types.js`
@@ -624,7 +624,7 @@ export class SessionLogWatcher {
624
624
  /**
625
625
  * DX-3964 - register a usage-feed consumer: it receives the parsed raw line of every assistant, user,
626
626
  * attachment and system line, in file order, with the same `EntryMeta` as `onEntry`. The ONLY subscribers are
627
- * the collector's two consumers at each of its two sites (the worker and the operator bridge): `DispatchUsage`
627
+ * the collector's two consumers at each of its two sites (the worker and the operator session's relay): `DispatchUsage`
628
628
  * and, DX-4498, the activity observer, which reads the sub-agent's brief and Claude Code's task notifications,
629
629
  * neither of which is an entry. `convertJsonlEntry` and every
630
630
  * `onEntry` subscriber keep seeing exactly what they saw before, because human prompts, attachments (tens of
@@ -121,7 +121,7 @@ export interface ActivityChange {
121
121
  /**
122
122
  * DX-4508 — the card its spawning `Agent` call names: the first card id in its (redacted) `description`, else the
123
123
  * first anywhere in its brief; null when neither names one. The name stays `briefIssueId` (and the column
124
- * `brief_issue_id`): renaming a required wire field would make every bridge already published fail the strict parser.
124
+ * `brief_issue_id`): renaming a required wire field would make every relay already published fail the strict parser.
125
125
  */
126
126
  briefIssueId: string | null;
127
127
  }
@@ -2,13 +2,13 @@
2
2
  * DX-4508 — a LOCAL live view of a session's sub-agents, for the plugin's plan pane.
3
3
  *
4
4
  * The pane shows one card per sub-agent: what it is, what it is doing, and what it has spent. Its dashboard path
5
- * (`GET /api/plan-sessions/:id/subagents`) lags about 80s behind the transcript (the bridge's 5s poll, its 15s
5
+ * (`GET /api/plan-sessions/:id/subagents`) lags about 80s behind the transcript (the relay's 5s poll, its 15s
6
6
  * heartbeat flush, the pane's 60s read), so the same facts are also computed here, on the operator's own machine, from
7
7
  * the transcript files themselves, and streamed by `danx-dashboard-mcp subagents-live` within a poll of being written.
8
8
  *
9
9
  * ## One place computes each number
10
10
  *
11
- * Nothing here counts or prices on its own. It consumes the SAME two watcher feeds the bridge wires
11
+ * Nothing here counts or prices on its own. It consumes the SAME two watcher feeds the relay wires
12
12
  * (`onSourceDiscovered`, `onUsageLine`) into the SAME producers:
13
13
  *
14
14
  * | Snapshot field | Computed by | As the dashboard read derives it from |
@@ -25,7 +25,7 @@
25
25
  * ## Where the live view differs from the observer's own stamps
26
26
  *
27
27
  * `startedAt` and `lastActivityAt` come from the sub-agent's own transcript lines (its first and newest `assistant` /
28
- * `user` line). The observer stamps a start at the moment its watcher DISCOVERED the file, which is right for the bridge
28
+ * `user` line). The observer stamps a start at the moment its watcher DISCOVERED the file, which is right for the relay
29
29
  * (its first discovery is the real start, and the server keeps the earliest), but this view reads every file from byte
30
30
  * 0 each time it starts, so a discovery stamp would show every finished sub-agent as having started, and been active,
31
31
  * just now. The discovery stamp is used only for a sub-agent that has written no line yet.
@@ -45,7 +45,7 @@ export interface LedgerEntry {
45
45
  toolUseIds: string[];
46
46
  /**
47
47
  * DX-3962 - the card this reply is credited to, or `null`. Fixed by the
48
- * reply's FIRST line and never changed by a later one. Only an operator-bridge
48
+ * reply's FIRST line and never changed by a later one. Only an operator-session
49
49
  * collector (`DispatchUsage`, `"operator-bridge"` mode) ever sets it; every
50
50
  * other producer of an entry carries `null`.
51
51
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@thehammer/danx-session-telemetry",
3
- "version": "0.1.41",
4
- "description": "Shared Claude Code transcript collector (DX-2962) — incremental JSONL tailing for the danxbot worker and the danx-dashboard-mcp desktop bridge, so both run identical collector code.",
3
+ "version": "0.1.43",
4
+ "description": "Shared Claude Code transcript collector (DX-2962) — incremental JSONL tailing for the danxbot worker and the danx-dashboard-mcp MCP server's relay, so both run identical collector code.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -31,6 +31,7 @@
31
31
  "node": ">=20"
32
32
  },
33
33
  "scripts": {
34
+ "prepublishOnly": "bash ../../scripts/assert-tree-contains-origin-main.sh @thehammer/danx-session-telemetry",
34
35
  "build": "tsc -p tsconfig.json",
35
36
  "verify:boot": "bash scripts/verify-boot.sh",
36
37
  "test": "vitest run",