tanuki-telemetry 1.3.7 → 1.3.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tanuki-telemetry",
3
- "version": "1.3.7",
3
+ "version": "1.3.8",
4
4
  "description": "Workflow monitor and telemetry dashboard for Claude Code autonomous agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,87 @@
1
+ ---
2
+ description: |
3
+ Autonomous workspace monitoring. Checks inbox + workspace screens on a recurring interval and takes action when sessions complete — dispatches queued work, restarts stalled sessions, reports status.
4
+ allowed-tools: Bash, Read, Glob, Grep, CronCreate, CronDelete, AskUserQuestion, mcp__telemetry__*
5
+ ---
6
+
7
+ # /monitor — Autonomous Workspace Monitoring
8
+
9
+ You are a monitoring daemon for the coordinator. You check workspace status periodically and take action when needed.
10
+
11
+ ## Arguments
12
+
13
+ - No args → monitor all active workspaces every 5 minutes
14
+ - `<interval>` → custom interval (e.g., `2m`, `10m`)
15
+ - `stop` → cancel all monitoring crons
16
+
17
+ ## On Invoke
18
+
19
+ ### 1. Discover active workspaces
20
+ ```bash
21
+ cmux list-workspaces
22
+ ```
23
+ For each non-coordinator workspace, get the Claude surface:
24
+ ```bash
25
+ cmux list-pane-surfaces --workspace "workspace:N"
26
+ ```
27
+
28
+ ### 2. Set up the monitoring cron
29
+ ```
30
+ CronCreate({
31
+ cron: "*/5 * * * *", // or custom interval
32
+ prompt: "MONITOR CHECK: Read coordinator inbox and check all workspace screens",
33
+ recurring: true
34
+ })
35
+ ```
36
+
37
+ ### 3. On each cron fire
38
+
39
+ #### Check inbox
40
+ ```bash
41
+ cat ~/.claude/coordinator-inbox.jsonl 2>/dev/null | tail -10
42
+ ```
43
+
44
+ #### For each active workspace, check screen
45
+ ```bash
46
+ cmux read-screen --workspace "workspace:N" --surface surface:X --lines 5
47
+ ```
48
+
49
+ #### Determine status
50
+ | Signal | Status | Action |
51
+ |--------|--------|--------|
52
+ | `esc to interrupt` | Working | No action needed |
53
+ | `❯` prompt only (idle) | Finished or stuck | Check inbox for completion event |
54
+ | `session_end` in inbox | Completed | Dispatch next queued task if any |
55
+ | Same screen for 3+ checks | Possibly stuck | Nudge: "Are you still working? If stuck, /clear and retry." |
56
+ | Error visible on screen | Failed | Log error, notify coordinator |
57
+
58
+ #### If a workspace completed
59
+ 1. Read the inbox for details
60
+ 2. Check git log for new commits
61
+ 3. If there's a queued task for that workspace, dispatch it
62
+ 4. Clear processed inbox messages
63
+ 5. Log status to telemetry
64
+
65
+ #### If a workspace seems stuck
66
+ 1. Check if it's waiting on something (Inngest job, API call, build)
67
+ 2. If idle for 3+ checks with no progress, send a nudge
68
+ 3. If nudge doesn't help after 2 more checks, restart the session
69
+
70
+ ### 4. Status report
71
+ Every 30 minutes (or 6 checks), output a summary:
72
+ ```
73
+ MONITOR STATUS:
74
+ - ws:8 (CDD Marathon): Working, 3 commits since last report
75
+ - ws:11 (Import Fix): Completed, dispatched next task
76
+ - Inbox: 2 messages processed
77
+ ```
78
+
79
+ ## Stopping
80
+ To stop monitoring:
81
+ ```
82
+ CronDelete <job-id>
83
+ ```
84
+ Or invoke `/monitor stop` which deletes all monitoring crons.
85
+
86
+ ## Key principle
87
+ **Don't just observe — act.** If a workspace finishes and there's queued work, dispatch it immediately. If a workspace is stuck, nudge it. The coordinator shouldn't have to manually check — that's your job.
package/src/dashboard.ts CHANGED
@@ -489,6 +489,7 @@ app.get("/api/artifacts/by-id/:id", (req, res) => {
489
489
  artifact.stored_path,
490
490
  artifact.file_path,
491
491
  artifact.file_path?.replace(/^.*?outputs\//, "/data/"),
492
+ artifact.file_path?.replace(/^.*?\.tanuki\/data\//, "/data/"),
492
493
  ].filter(Boolean) as string[];
493
494
 
494
495
  for (const candidate of candidates) {
@@ -501,7 +502,7 @@ app.get("/api/artifacts/by-id/:id", (req, res) => {
501
502
  }
502
503
  }
503
504
 
504
- res.status(404).json({ error: "Artifact file not found on disk" });
505
+ res.status(404).json({ error: "Artifact file not found on disk", candidates });
505
506
  });
506
507
 
507
508
  // Serve screenshot by database ID — self-contained, doesn't need volume path mapping
@@ -527,6 +528,7 @@ app.get("/api/screenshots/by-id/:id", (req, res) => {
527
528
  screenshot.stored_path,
528
529
  screenshot.file_path,
529
530
  screenshot.file_path?.replace(/^.*?outputs\//, "/data/"),
531
+ screenshot.file_path?.replace(/^.*?\.tanuki\/data\//, "/data/"),
530
532
  ].filter(Boolean) as string[];
531
533
 
532
534
  for (const candidate of candidates) {