@synap-core/cli 1.12.2 → 1.13.1-next.20261102.ec3d166
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/LICENSE +21 -0
- package/README.md +38 -11
- package/dist/build-info.json +2 -3
- package/dist/commands/agents.d.ts +0 -1
- package/dist/commands/agents.js +13 -3
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/app.js +2 -1
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/automation.js +46 -41
- package/dist/commands/automation.js.map +1 -1
- package/dist/commands/box.d.ts +42 -0
- package/dist/commands/box.js +89 -0
- package/dist/commands/box.js.map +1 -0
- package/dist/commands/bridge-setup.js +3 -1
- package/dist/commands/bridge-setup.js.map +1 -1
- package/dist/commands/capability.d.ts +87 -1
- package/dist/commands/capability.js +174 -64
- package/dist/commands/capability.js.map +1 -1
- package/dist/commands/close-questions.d.ts +27 -0
- package/dist/commands/close-questions.js +49 -0
- package/dist/commands/close-questions.js.map +1 -0
- package/dist/commands/close-questions.test.d.ts +1 -0
- package/dist/commands/close-questions.test.js +52 -0
- package/dist/commands/close-questions.test.js.map +1 -0
- package/dist/commands/connect.d.ts +1 -3
- package/dist/commands/connect.js +2 -2
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/context.js +72 -43
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.d.ts +13 -0
- package/dist/commands/data-extra.js +35 -6
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.js +2 -1
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/doctor.d.ts +39 -0
- package/dist/commands/doctor.js +136 -14
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/hooks.d.ts +19 -0
- package/dist/commands/hooks.js +70 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/import.d.ts +25 -0
- package/dist/commands/import.js +98 -12
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.js +63 -21
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/keys-request.d.ts +48 -0
- package/dist/commands/keys-request.js +236 -0
- package/dist/commands/keys-request.js.map +1 -0
- package/dist/commands/keys-request.test.d.ts +1 -0
- package/dist/commands/keys-request.test.js +176 -0
- package/dist/commands/keys-request.test.js.map +1 -0
- package/dist/commands/knowledge.d.ts +6 -0
- package/dist/commands/knowledge.js +13 -3
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/lens.js +2 -1
- package/dist/commands/lens.js.map +1 -1
- package/dist/commands/market-authoring.js +1 -1
- package/dist/commands/market-authoring.js.map +1 -1
- package/dist/commands/market.d.ts +61 -4
- package/dist/commands/market.js +106 -48
- package/dist/commands/market.js.map +1 -1
- package/dist/commands/mcp.d.ts +1 -1
- package/dist/commands/mcp.js +14 -9
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/observe.category.test.d.ts +1 -0
- package/dist/commands/observe.category.test.js +59 -0
- package/dist/commands/observe.category.test.js.map +1 -0
- package/dist/commands/observe.d.ts +3 -0
- package/dist/commands/observe.js +7 -5
- package/dist/commands/observe.js.map +1 -1
- package/dist/commands/observe.title.test.d.ts +1 -0
- package/dist/commands/observe.title.test.js +37 -0
- package/dist/commands/observe.title.test.js.map +1 -0
- package/dist/commands/playbook.js +9 -0
- package/dist/commands/playbook.js.map +1 -1
- package/dist/commands/pods.d.ts +6 -1
- package/dist/commands/pods.js +38 -17
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proposals-actions.js +7 -1
- package/dist/commands/proposals-actions.js.map +1 -1
- package/dist/commands/proton-setup.js +3 -1
- package/dist/commands/proton-setup.js.map +1 -1
- package/dist/commands/providers.d.ts +22 -6
- package/dist/commands/providers.js +39 -32
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/raycast.d.ts +15 -0
- package/dist/commands/raycast.js +36 -10
- package/dist/commands/raycast.js.map +1 -1
- package/dist/commands/session-feed-wait.d.ts +48 -0
- package/dist/commands/session-feed-wait.js +261 -0
- package/dist/commands/session-feed-wait.js.map +1 -0
- package/dist/commands/session-post.d.ts +40 -0
- package/dist/commands/session-post.js +96 -0
- package/dist/commands/session-post.js.map +1 -0
- package/dist/commands/session-wait.d.ts +9 -4
- package/dist/commands/session-wait.js +20 -5
- package/dist/commands/session-wait.js.map +1 -1
- package/dist/commands/sessions.d.ts +2 -0
- package/dist/commands/sessions.js +23 -0
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/skills-commands.d.ts +2 -0
- package/dist/commands/skills-commands.js +9 -1
- package/dist/commands/skills-commands.js.map +1 -1
- package/dist/commands/skills-commands.test.d.ts +1 -0
- package/dist/commands/skills-commands.test.js +57 -0
- package/dist/commands/skills-commands.test.js.map +1 -0
- package/dist/commands/status.js +13 -7
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/statusline.backoff.test.js +13 -3
- package/dist/commands/statusline.backoff.test.js.map +1 -1
- package/dist/commands/statusline.d.ts +104 -9
- package/dist/commands/statusline.js +392 -148
- package/dist/commands/statusline.js.map +1 -1
- package/dist/commands/statusline.line2.test.d.ts +15 -0
- package/dist/commands/statusline.line2.test.js +226 -0
- package/dist/commands/statusline.line2.test.js.map +1 -0
- package/dist/commands/statusline.needs-you.test.d.ts +1 -0
- package/dist/commands/statusline.needs-you.test.js +17 -0
- package/dist/commands/statusline.needs-you.test.js.map +1 -0
- package/dist/commands/statusline.now.test.d.ts +10 -0
- package/dist/commands/statusline.now.test.js +250 -0
- package/dist/commands/statusline.now.test.js.map +1 -0
- package/dist/commands/tracks.d.ts +68 -6
- package/dist/commands/tracks.js +272 -16
- package/dist/commands/tracks.js.map +1 -1
- package/dist/commands/upload.js +12 -0
- package/dist/commands/upload.js.map +1 -1
- package/dist/commands/wait.d.ts +124 -0
- package/dist/commands/wait.js +384 -0
- package/dist/commands/wait.js.map +1 -0
- package/dist/commands/wait.test.d.ts +8 -0
- package/dist/commands/wait.test.js +308 -0
- package/dist/commands/wait.test.js.map +1 -0
- package/dist/commands/whoami.d.ts +7 -0
- package/dist/commands/whoami.js +17 -0
- package/dist/commands/whoami.js.map +1 -1
- package/dist/commands/worker-accounts.d.ts +149 -0
- package/dist/commands/worker-accounts.js +339 -0
- package/dist/commands/worker-accounts.js.map +1 -0
- package/dist/commands/worker-accounts.test.d.ts +1 -0
- package/dist/commands/worker-accounts.test.js +224 -0
- package/dist/commands/worker-accounts.test.js.map +1 -0
- package/dist/commands/worker-github-app.d.ts +63 -0
- package/dist/commands/worker-github-app.js +161 -0
- package/dist/commands/worker-github-app.js.map +1 -0
- package/dist/commands/worker-github-app.test.d.ts +1 -0
- package/dist/commands/worker-github-app.test.js +102 -0
- package/dist/commands/worker-github-app.test.js.map +1 -0
- package/dist/commands/worker-github-broker.d.ts +39 -0
- package/dist/commands/worker-github-broker.js +106 -0
- package/dist/commands/worker-github-broker.js.map +1 -0
- package/dist/commands/worker-github-broker.test.d.ts +1 -0
- package/dist/commands/worker-github-broker.test.js +90 -0
- package/dist/commands/worker-github-broker.test.js.map +1 -0
- package/dist/commands/worker-runs.test.d.ts +1 -0
- package/dist/commands/worker-runs.test.js +150 -0
- package/dist/commands/worker-runs.test.js.map +1 -0
- package/dist/commands/worker-worktrees.d.ts +34 -0
- package/dist/commands/worker-worktrees.js +87 -0
- package/dist/commands/worker-worktrees.js.map +1 -0
- package/dist/commands/worker.d.ts +406 -10
- package/dist/commands/worker.js +1180 -126
- package/dist/commands/worker.js.map +1 -1
- package/dist/commands/worker.test.js +588 -11
- package/dist/commands/worker.test.js.map +1 -1
- package/dist/index.js +220 -28
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-door.d.ts +1 -3
- package/dist/lib/agent-door.js +10 -7
- package/dist/lib/agent-door.js.map +1 -1
- package/dist/lib/agents-config.d.ts +9 -0
- package/dist/lib/agents-config.js +20 -0
- package/dist/lib/agents-config.js.map +1 -1
- package/dist/lib/atomic-file.d.ts +20 -1
- package/dist/lib/atomic-file.js +100 -2
- package/dist/lib/atomic-file.js.map +1 -1
- package/dist/lib/auth.d.ts +28 -2
- package/dist/lib/auth.js +52 -12
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/box/egress.d.ts +82 -0
- package/dist/lib/box/egress.js +264 -0
- package/dist/lib/box/egress.js.map +1 -0
- package/dist/lib/box/evidence.d.ts +86 -0
- package/dist/lib/box/evidence.js +121 -0
- package/dist/lib/box/evidence.js.map +1 -0
- package/dist/lib/box/job-server.d.ts +72 -0
- package/dist/lib/box/job-server.js +250 -0
- package/dist/lib/box/job-server.js.map +1 -0
- package/dist/lib/box/provisioner.d.ts +83 -0
- package/dist/lib/box/provisioner.js +312 -0
- package/dist/lib/box/provisioner.js.map +1 -0
- package/dist/lib/box/proxmox.d.ts +112 -0
- package/dist/lib/box/proxmox.js +211 -0
- package/dist/lib/box/proxmox.js.map +1 -0
- package/dist/lib/box/wire.d.ts +98 -0
- package/dist/lib/box/wire.js +70 -0
- package/dist/lib/box/wire.js.map +1 -0
- package/dist/lib/bridge-invocation.test.d.ts +1 -0
- package/dist/lib/bridge-invocation.test.js +75 -0
- package/dist/lib/bridge-invocation.test.js.map +1 -0
- package/dist/lib/bridge-status.d.ts +144 -0
- package/dist/lib/bridge-status.js +227 -0
- package/dist/lib/bridge-status.js.map +1 -0
- package/dist/lib/bridge-status.test.d.ts +6 -0
- package/dist/lib/bridge-status.test.js +197 -0
- package/dist/lib/bridge-status.test.js.map +1 -0
- package/dist/lib/client-header.test.d.ts +1 -0
- package/dist/lib/client-header.test.js +103 -0
- package/dist/lib/client-header.test.js.map +1 -0
- package/dist/lib/conversation-headers.d.ts +89 -9
- package/dist/lib/conversation-headers.js +156 -3
- package/dist/lib/conversation-headers.js.map +1 -1
- package/dist/lib/conversation-headers.test.d.ts +1 -0
- package/dist/lib/conversation-headers.test.js +78 -0
- package/dist/lib/conversation-headers.test.js.map +1 -0
- package/dist/lib/credential-class.d.ts +40 -2
- package/dist/lib/credential-class.js +48 -6
- package/dist/lib/credential-class.js.map +1 -1
- package/dist/lib/device-connect.d.ts +45 -0
- package/dist/lib/device-connect.js +60 -0
- package/dist/lib/device-connect.js.map +1 -1
- package/dist/lib/exporter-coverage.d.ts +1 -1
- package/dist/lib/exporter-coverage.js +1 -1
- package/dist/lib/goal-words.d.ts +38 -0
- package/dist/lib/goal-words.js +115 -0
- package/dist/lib/goal-words.js.map +1 -0
- package/dist/lib/hub-client.d.ts +87 -8
- package/dist/lib/hub-client.js +205 -70
- package/dist/lib/hub-client.js.map +1 -1
- package/dist/lib/init-handoff.d.ts +8 -0
- package/dist/lib/init-handoff.js +9 -2
- package/dist/lib/init-handoff.js.map +1 -1
- package/dist/lib/key-locations.d.ts +3 -3
- package/dist/lib/key-locations.js +3 -39
- package/dist/lib/key-locations.js.map +1 -1
- package/dist/lib/key-source.d.ts +3 -1
- package/dist/lib/key-source.js +7 -4
- package/dist/lib/key-source.js.map +1 -1
- package/dist/lib/knowledge-title.d.ts +3 -2
- package/dist/lib/knowledge-title.js +3 -2
- package/dist/lib/knowledge-title.js.map +1 -1
- package/dist/lib/machine-instance.d.ts +7 -5
- package/dist/lib/machine-instance.js +7 -5
- package/dist/lib/machine-instance.js.map +1 -1
- package/dist/lib/mcp-bridge.d.ts +50 -0
- package/dist/lib/mcp-bridge.js +232 -11
- package/dist/lib/mcp-bridge.js.map +1 -1
- package/dist/lib/mcp-bridge.test.js +224 -4
- package/dist/lib/mcp-bridge.test.js.map +1 -1
- package/dist/lib/mcp-call.d.ts +5 -1
- package/dist/lib/mcp-call.js +7 -6
- package/dist/lib/mcp-call.js.map +1 -1
- package/dist/lib/mcp-connector-url.test.d.ts +1 -0
- package/dist/lib/mcp-connector-url.test.js +13 -0
- package/dist/lib/mcp-connector-url.test.js.map +1 -0
- package/dist/lib/mcp-snippets.d.ts +16 -0
- package/dist/lib/mcp-snippets.js +20 -2
- package/dist/lib/mcp-snippets.js.map +1 -1
- package/dist/lib/now-line.d.ts +66 -0
- package/dist/lib/now-line.js +193 -0
- package/dist/lib/now-line.js.map +1 -0
- package/dist/lib/now-line.test.d.ts +5 -0
- package/dist/lib/now-line.test.js +177 -0
- package/dist/lib/now-line.test.js.map +1 -0
- package/dist/lib/package-updates.d.ts +66 -0
- package/dist/lib/package-updates.js +76 -0
- package/dist/lib/package-updates.js.map +1 -0
- package/dist/lib/pod-moved.d.ts +70 -0
- package/dist/lib/pod-moved.js +146 -0
- package/dist/lib/pod-moved.js.map +1 -0
- package/dist/lib/pod-reach.d.ts +39 -0
- package/dist/lib/pod-reach.js +117 -0
- package/dist/lib/pod-reach.js.map +1 -0
- package/dist/lib/pod-reach.test.d.ts +1 -0
- package/dist/lib/pod-reach.test.js +67 -0
- package/dist/lib/pod-reach.test.js.map +1 -0
- package/dist/lib/pod.d.ts +8 -4
- package/dist/lib/pod.js +12 -10
- package/dist/lib/pod.js.map +1 -1
- package/dist/lib/register-claude-code-mcp.test.d.ts +1 -0
- package/dist/lib/register-claude-code-mcp.test.js +97 -0
- package/dist/lib/register-claude-code-mcp.test.js.map +1 -0
- package/dist/lib/review-credential.js +3 -1
- package/dist/lib/review-credential.js.map +1 -1
- package/dist/lib/safe-open.d.ts +5 -3
- package/dist/lib/safe-open.js +9 -8
- package/dist/lib/safe-open.js.map +1 -1
- package/dist/lib/self-host.d.ts +17 -0
- package/dist/lib/self-host.js +24 -0
- package/dist/lib/self-host.js.map +1 -0
- package/dist/lib/session-feed.d.ts +185 -0
- package/dist/lib/session-feed.js +257 -0
- package/dist/lib/session-feed.js.map +1 -0
- package/dist/lib/targets.d.ts +52 -3
- package/dist/lib/targets.js +150 -209
- package/dist/lib/targets.js.map +1 -1
- package/dist/lib/term.d.ts +24 -0
- package/dist/lib/term.js +52 -0
- package/dist/lib/term.js.map +1 -0
- package/dist/lib/term.test.d.ts +1 -0
- package/dist/lib/term.test.js +29 -0
- package/dist/lib/term.test.js.map +1 -0
- package/dist/lib/transcript-index.d.ts +94 -0
- package/dist/lib/transcript-index.js +321 -0
- package/dist/lib/transcript-index.js.map +1 -0
- package/dist/lib/transcript-index.test.d.ts +10 -0
- package/dist/lib/transcript-index.test.js +200 -0
- package/dist/lib/transcript-index.test.js.map +1 -0
- package/dist/lib/wait-help.d.ts +11 -0
- package/dist/lib/wait-help.js +25 -0
- package/dist/lib/wait-help.js.map +1 -0
- package/dist/lib/wait-state.d.ts +57 -0
- package/dist/lib/wait-state.js +114 -0
- package/dist/lib/wait-state.js.map +1 -0
- package/dist/lib/wake-hook-settings.d.ts +57 -0
- package/dist/lib/wake-hook-settings.js +153 -0
- package/dist/lib/wake-hook-settings.js.map +1 -0
- package/dist/lib/wake-state.d.ts +65 -0
- package/dist/lib/wake-state.js +122 -0
- package/dist/lib/wake-state.js.map +1 -0
- package/package.json +5 -2
- package/skills/README.md +1 -1
- package/skills/agent-os/SKILL.md +8 -8
- package/skills/synap/SKILL.md +178 -88
- package/skills/synap/code-skills.md +84 -0
- package/skills/synap/concepts.md +38 -20
- package/skills/synap/creative-loop.md +1 -1
- package/skills/synap/document-embeds.md +17 -1
- package/skills/synap/focus-sessions.md +17 -8
- package/skills/synap/from-intent.md +33 -17
- package/skills/synap/governance-rules.md +3 -1
- package/skills/synap/lenses.md +4 -4
- package/skills/synap/linking.md +2 -2
- package/skills/synap/mental-model.md +1 -1
- package/skills/synap/operating-mode-rules.md +1 -1
- package/skills/synap/quick-reference.md +2 -1
- package/skills/synap/reflexes.md +8 -8
- package/skills/synap/viewframe-cells.md +1 -1
- package/skills/synap/work-model.md +24 -10
- package/skills/synap/workspace-design.md +5 -5
- package/skills/synap/writes.md +16 -9
- package/skills/synap/writing-titles.md +7 -0
- package/skills/synap-app/SKILL.md +148 -66
- package/skills/synap-app/creating-the-base-app.md +12 -7
- package/skills/synap-app/governance.md +27 -16
- package/skills/synap-app/install-commands.md +18 -9
- package/skills/synap-app/overview.md +16 -9
- package/skills/synap-app/using-the-sdk.md +75 -25
- package/skills/synap-market/SKILL.md +1 -1
- package/skills/synap-market/governance-and-catalog.md +1 -1
- package/skills/synap-schema/SKILL.md +24 -21
- package/skills/synap-schema/intent-vocabulary-ssot.md +24 -21
- package/templates/box/runner.py +206 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The status line's 4th line from the pod, through the synap-bridge plugin's
|
|
3
|
+
* per-conversation status file (bridge 0.10, plan P3.3).
|
|
4
|
+
*
|
|
5
|
+
* After each read of the bound session the bridge writes
|
|
6
|
+
* `~/.synap/bridge/status/<Claude Code session id>.json`, whole (tmp + `mv -f`,
|
|
7
|
+
* so a reader never sees half a file): `{ v: 1, writtenAt, sessionId, title,
|
|
8
|
+
* live, nextMove, waitingOn, workUnits }`, each from the session's
|
|
9
|
+
* continuation packet. A section the pod could not read is `null`, never
|
|
10
|
+
* empty; `sessionId: null` = nothing is bound. The writer is the bridge's
|
|
11
|
+
* `statusFile` (synap-bridge `hooks/lib.ts`).
|
|
12
|
+
*
|
|
13
|
+
* The file is the FIRST source of what the conversation waits on; the
|
|
14
|
+
* transcript index (lib/now-line.ts) stays the fallback whenever the file is
|
|
15
|
+
* absent, unbound, stale or unreadable. The turn state itself (working /
|
|
16
|
+
* needs you / stopped) stays Claude Code's registry when it is readable: the
|
|
17
|
+
* pod's `live` is the bridge's relay of that same registry, smoothed by the
|
|
18
|
+
* pod's 5-minute rule, so it is used only when the registry is not there.
|
|
19
|
+
*
|
|
20
|
+
* ▶ working · 4m · ⏳ 2 · other work (2) · synap-cli#52 open ✗
|
|
21
|
+
* ⏳ waiting on 3 · other work (2) · approval · synap-cli#52 open ✓
|
|
22
|
+
* ■ stopped · next: Produce "Wave 2 report" · pod 40m ago
|
|
23
|
+
*
|
|
24
|
+
* Local files only, no network. `readBridgeStatus` never throws;
|
|
25
|
+
* `buildBridgeLine` is pure.
|
|
26
|
+
*/
|
|
27
|
+
import { type RegistryEntry } from "./now-line.js";
|
|
28
|
+
/** The pod's working window (`SESSION_WORKING_WINDOW_MS`), for a file whose `live` carries none. */
|
|
29
|
+
export declare const POD_WORKING_WINDOW_MS: number;
|
|
30
|
+
/**
|
|
31
|
+
* A file older than this is stale even when no registry says when this
|
|
32
|
+
* Claude Code process started: beyond half a day nothing shows its writer
|
|
33
|
+
* still runs. A quiet file younger than this is still true (the bridge
|
|
34
|
+
* rewrites it on every change the pod's feed sends), and its age is shown.
|
|
35
|
+
*/
|
|
36
|
+
export declare const BRIDGE_STATUS_MAX_AGE_MS: number;
|
|
37
|
+
export interface WaitingOnMark {
|
|
38
|
+
reason: string;
|
|
39
|
+
count: number;
|
|
40
|
+
refs?: Array<{
|
|
41
|
+
kind?: string;
|
|
42
|
+
id?: string;
|
|
43
|
+
label?: string;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
export interface BridgeWorkUnit {
|
|
47
|
+
key: string | null;
|
|
48
|
+
label: string;
|
|
49
|
+
kind: string;
|
|
50
|
+
url: string | null;
|
|
51
|
+
state: string;
|
|
52
|
+
/** `{ status: "ok", label, state, checks? }` or `{ status: "unavailable", reason }`; null = none recorded. */
|
|
53
|
+
prState: {
|
|
54
|
+
status?: string;
|
|
55
|
+
label?: string;
|
|
56
|
+
state?: string;
|
|
57
|
+
checks?: string;
|
|
58
|
+
} | null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Version 1 of the file, as the status line reads it. `live` is normalised on
|
|
62
|
+
* read: a field the bridge wrote malformed (bridge ≤ 0.11 wrote
|
|
63
|
+
* `measuredAt: "undefined"` and `windowMs: NaN`, which JSON stores as null
|
|
64
|
+
* when the pod sent none) is null here, never a reason to drop the file.
|
|
65
|
+
*/
|
|
66
|
+
export interface BridgeStatusFile {
|
|
67
|
+
v: 1;
|
|
68
|
+
writtenAt: string;
|
|
69
|
+
sessionId: string | null;
|
|
70
|
+
title: string | null;
|
|
71
|
+
live: {
|
|
72
|
+
state: "working" | "idle";
|
|
73
|
+
turnInFlight: boolean;
|
|
74
|
+
since: string | null;
|
|
75
|
+
lastActivityAt: string | null;
|
|
76
|
+
measuredAt: string | null;
|
|
77
|
+
windowMs: number | null;
|
|
78
|
+
} | null;
|
|
79
|
+
nextMove: {
|
|
80
|
+
kind: string;
|
|
81
|
+
actor: string;
|
|
82
|
+
label: string;
|
|
83
|
+
reason: string;
|
|
84
|
+
} | null;
|
|
85
|
+
waitingOn: WaitingOnMark[] | null;
|
|
86
|
+
workUnits: BridgeWorkUnit[] | null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* What reading the file found. Only `fresh` is drawn; every other answer falls
|
|
90
|
+
* back to the transcript index. `absent` and `unbound` are normal (no bridge,
|
|
91
|
+
* nothing bound) and say nothing; `failed` (unreadable or malformed) is a
|
|
92
|
+
* failed read the line marks, never folded into "absent".
|
|
93
|
+
*/
|
|
94
|
+
export type BridgeStatusRead = {
|
|
95
|
+
status: "fresh";
|
|
96
|
+
file: BridgeStatusFile;
|
|
97
|
+
writtenAt: number;
|
|
98
|
+
} | {
|
|
99
|
+
status: "absent";
|
|
100
|
+
} | {
|
|
101
|
+
status: "unbound";
|
|
102
|
+
} | {
|
|
103
|
+
status: "stale";
|
|
104
|
+
why: string;
|
|
105
|
+
} | {
|
|
106
|
+
status: "failed";
|
|
107
|
+
why: string;
|
|
108
|
+
};
|
|
109
|
+
export declare function bridgeStatusPath(claudeSessionId: string, home?: string): string;
|
|
110
|
+
/**
|
|
111
|
+
* The parsed JSON as a version-1 file, or why it is not one. Every string in
|
|
112
|
+
* it is scrubbed of control characters first (term.ts): the file carries pod
|
|
113
|
+
* words (titles, labels, PR names) that are printed as they are.
|
|
114
|
+
*/
|
|
115
|
+
export declare function parseBridgeStatus(raw: unknown): BridgeStatusFile | string;
|
|
116
|
+
/**
|
|
117
|
+
* This conversation's status file, judged. Stale when it was written before
|
|
118
|
+
* this Claude Code process started (`startedAt`, from the registry: the
|
|
119
|
+
* bridge of an earlier process wrote it, and this one has not confirmed the
|
|
120
|
+
* binding yet), or is older than BRIDGE_STATUS_MAX_AGE_MS. Never throws.
|
|
121
|
+
*/
|
|
122
|
+
export declare function readBridgeStatus(claudeSessionId: string, opts: {
|
|
123
|
+
now: number;
|
|
124
|
+
startedAt?: number;
|
|
125
|
+
home?: string;
|
|
126
|
+
}): BridgeStatusRead;
|
|
127
|
+
/**
|
|
128
|
+
* The pod's rule (`isSessionWorkingNow`) on the file's `live`, judged now.
|
|
129
|
+
*
|
|
130
|
+
* `turnInFlight` is the pod's word AT `measuredAt` (else when the file was
|
|
131
|
+
* written, `writtenAt`), not now: it holds for one working window after that
|
|
132
|
+
* and no longer. Read as "now", a file the bridge last wrote mid-turn said
|
|
133
|
+
* "working" for as long as the file stayed fresh (12 h).
|
|
134
|
+
*/
|
|
135
|
+
export declare function podWorking(live: NonNullable<BridgeStatusFile["live"]>, now: number, writtenAt?: number): boolean;
|
|
136
|
+
export interface BridgeLineInput {
|
|
137
|
+
now: number;
|
|
138
|
+
file: BridgeStatusFile;
|
|
139
|
+
writtenAt: number;
|
|
140
|
+
registry: RegistryEntry | null;
|
|
141
|
+
width?: number;
|
|
142
|
+
}
|
|
143
|
+
/** The 4th line from a fresh status file. */
|
|
144
|
+
export declare function buildBridgeLine(input: BridgeLineInput): string;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The status line's 4th line from the pod, through the synap-bridge plugin's
|
|
3
|
+
* per-conversation status file (bridge 0.10, plan P3.3).
|
|
4
|
+
*
|
|
5
|
+
* After each read of the bound session the bridge writes
|
|
6
|
+
* `~/.synap/bridge/status/<Claude Code session id>.json`, whole (tmp + `mv -f`,
|
|
7
|
+
* so a reader never sees half a file): `{ v: 1, writtenAt, sessionId, title,
|
|
8
|
+
* live, nextMove, waitingOn, workUnits }`, each from the session's
|
|
9
|
+
* continuation packet. A section the pod could not read is `null`, never
|
|
10
|
+
* empty; `sessionId: null` = nothing is bound. The writer is the bridge's
|
|
11
|
+
* `statusFile` (synap-bridge `hooks/lib.ts`).
|
|
12
|
+
*
|
|
13
|
+
* The file is the FIRST source of what the conversation waits on; the
|
|
14
|
+
* transcript index (lib/now-line.ts) stays the fallback whenever the file is
|
|
15
|
+
* absent, unbound, stale or unreadable. The turn state itself (working /
|
|
16
|
+
* needs you / stopped) stays Claude Code's registry when it is readable: the
|
|
17
|
+
* pod's `live` is the bridge's relay of that same registry, smoothed by the
|
|
18
|
+
* pod's 5-minute rule, so it is used only when the registry is not there.
|
|
19
|
+
*
|
|
20
|
+
* ▶ working · 4m · ⏳ 2 · other work (2) · synap-cli#52 open ✗
|
|
21
|
+
* ⏳ waiting on 3 · other work (2) · approval · synap-cli#52 open ✓
|
|
22
|
+
* ■ stopped · next: Produce "Wave 2 report" · pod 40m ago
|
|
23
|
+
*
|
|
24
|
+
* Local files only, no network. `readBridgeStatus` never throws;
|
|
25
|
+
* `buildBridgeLine` is pure.
|
|
26
|
+
*/
|
|
27
|
+
import fs from "node:fs";
|
|
28
|
+
import os from "node:os";
|
|
29
|
+
import path from "node:path";
|
|
30
|
+
import { WAITING_ON_REASON_LABELS, goalWord } from "./goal-words.js";
|
|
31
|
+
import { age, capped, clip, DEFAULT_WIDTH } from "./now-line.js";
|
|
32
|
+
import { AMBER as A, BOLD_YELLOW as Y, CYAN as C, DIM as D, GREEN as G, RED as R, RESET as X, osc8, scrubStrings } from "./term.js";
|
|
33
|
+
/** The pod's working window (`SESSION_WORKING_WINDOW_MS`), for a file whose `live` carries none. */
|
|
34
|
+
export const POD_WORKING_WINDOW_MS = 5 * 60_000;
|
|
35
|
+
/**
|
|
36
|
+
* A file older than this is stale even when no registry says when this
|
|
37
|
+
* Claude Code process started: beyond half a day nothing shows its writer
|
|
38
|
+
* still runs. A quiet file younger than this is still true (the bridge
|
|
39
|
+
* rewrites it on every change the pod's feed sends), and its age is shown.
|
|
40
|
+
*/
|
|
41
|
+
export const BRIDGE_STATUS_MAX_AGE_MS = 12 * 60 * 60_000;
|
|
42
|
+
export function bridgeStatusPath(claudeSessionId, home = os.homedir()) {
|
|
43
|
+
return path.join(home, ".synap", "bridge", "status", `${claudeSessionId}.json`);
|
|
44
|
+
}
|
|
45
|
+
const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
46
|
+
const isTime = (v) => typeof v === "string" && Number.isFinite(Date.parse(v));
|
|
47
|
+
const isStrOrNull = (v) => v === null || typeof v === "string";
|
|
48
|
+
/**
|
|
49
|
+
* The file's `live`, normalised. One malformed field costs that field (null),
|
|
50
|
+
* and a `live` that is no object at all reads as "not measured" (null): the
|
|
51
|
+
* rest of the file is still true, so it is never a failed read.
|
|
52
|
+
*/
|
|
53
|
+
function readLive(v) {
|
|
54
|
+
if (!isObj(v))
|
|
55
|
+
return null;
|
|
56
|
+
const windowMs = typeof v.windowMs === "number" && Number.isFinite(v.windowMs) && v.windowMs > 0 ? v.windowMs : null;
|
|
57
|
+
return {
|
|
58
|
+
state: v.state === "working" ? "working" : "idle",
|
|
59
|
+
turnInFlight: v.turnInFlight === true,
|
|
60
|
+
since: isTime(v.since) ? v.since : null,
|
|
61
|
+
lastActivityAt: isTime(v.lastActivityAt) ? v.lastActivityAt : null,
|
|
62
|
+
measuredAt: isTime(v.measuredAt) ? v.measuredAt : null,
|
|
63
|
+
windowMs,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The parsed JSON as a version-1 file, or why it is not one. Every string in
|
|
68
|
+
* it is scrubbed of control characters first (term.ts): the file carries pod
|
|
69
|
+
* words (titles, labels, PR names) that are printed as they are.
|
|
70
|
+
*/
|
|
71
|
+
export function parseBridgeStatus(raw) {
|
|
72
|
+
const json = scrubStrings(raw);
|
|
73
|
+
if (!isObj(json))
|
|
74
|
+
return "not an object";
|
|
75
|
+
if (json.v !== 1)
|
|
76
|
+
return `version ${JSON.stringify(json.v)} is not 1`;
|
|
77
|
+
if (!isTime(json.writtenAt))
|
|
78
|
+
return "no writtenAt time";
|
|
79
|
+
if (!isStrOrNull(json.sessionId))
|
|
80
|
+
return "sessionId is not a string";
|
|
81
|
+
if (!isStrOrNull(json.title ?? null))
|
|
82
|
+
return "title is not a string";
|
|
83
|
+
const live = readLive(json.live);
|
|
84
|
+
const next = json.nextMove ?? null;
|
|
85
|
+
if (next !== null && (!isObj(next) || typeof next.label !== "string"))
|
|
86
|
+
return "nextMove is malformed";
|
|
87
|
+
const waits = json.waitingOn ?? null;
|
|
88
|
+
if (waits !== null && (!Array.isArray(waits) || !waits.every((m) => isObj(m) && typeof m.reason === "string" && typeof m.count === "number")))
|
|
89
|
+
return "waitingOn is malformed";
|
|
90
|
+
const units = json.workUnits ?? null;
|
|
91
|
+
if (units !== null && (!Array.isArray(units) || !units.every((u) => isObj(u) && typeof u.label === "string" && typeof u.state === "string")))
|
|
92
|
+
return "workUnits is malformed";
|
|
93
|
+
return {
|
|
94
|
+
v: 1,
|
|
95
|
+
writtenAt: json.writtenAt,
|
|
96
|
+
sessionId: json.sessionId,
|
|
97
|
+
title: json.title ?? null,
|
|
98
|
+
live,
|
|
99
|
+
nextMove: next,
|
|
100
|
+
waitingOn: waits,
|
|
101
|
+
workUnits: units,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* This conversation's status file, judged. Stale when it was written before
|
|
106
|
+
* this Claude Code process started (`startedAt`, from the registry: the
|
|
107
|
+
* bridge of an earlier process wrote it, and this one has not confirmed the
|
|
108
|
+
* binding yet), or is older than BRIDGE_STATUS_MAX_AGE_MS. Never throws.
|
|
109
|
+
*/
|
|
110
|
+
export function readBridgeStatus(claudeSessionId, opts) {
|
|
111
|
+
// A session id becomes a file name: anything that could leave the directory is no file.
|
|
112
|
+
if (!/^[A-Za-z0-9_-]+$/.test(claudeSessionId))
|
|
113
|
+
return { status: "absent" };
|
|
114
|
+
let raw;
|
|
115
|
+
try {
|
|
116
|
+
raw = fs.readFileSync(bridgeStatusPath(claudeSessionId, opts.home), "utf-8");
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
if (e.code === "ENOENT")
|
|
120
|
+
return { status: "absent" };
|
|
121
|
+
return { status: "failed", why: `unreadable (${e.code ?? "error"})` };
|
|
122
|
+
}
|
|
123
|
+
let json;
|
|
124
|
+
try {
|
|
125
|
+
json = JSON.parse(raw);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return { status: "failed", why: "not JSON" };
|
|
129
|
+
}
|
|
130
|
+
const file = parseBridgeStatus(json);
|
|
131
|
+
if (typeof file === "string")
|
|
132
|
+
return { status: "failed", why: file };
|
|
133
|
+
const writtenAt = Date.parse(file.writtenAt);
|
|
134
|
+
if (opts.startedAt && writtenAt < opts.startedAt)
|
|
135
|
+
return { status: "stale", why: "written before this Claude Code process started" };
|
|
136
|
+
if (opts.now - writtenAt > BRIDGE_STATUS_MAX_AGE_MS)
|
|
137
|
+
return { status: "stale", why: `written ${age(opts.now - writtenAt)} ago` };
|
|
138
|
+
if (file.sessionId === null)
|
|
139
|
+
return { status: "unbound" };
|
|
140
|
+
return { status: "fresh", file, writtenAt };
|
|
141
|
+
}
|
|
142
|
+
// ── The line ───────────────────────────────────────────────────────────
|
|
143
|
+
/** One mark: `other work (2)`, words through the vocabulary's table (goal-words.ts). */
|
|
144
|
+
function markText(m) {
|
|
145
|
+
const reason = goalWord(WAITING_ON_REASON_LABELS, m.reason).toLowerCase();
|
|
146
|
+
return m.count > 1 ? `${reason} (${m.count})` : reason;
|
|
147
|
+
}
|
|
148
|
+
/** A pull request still under way: `synap-cli#52 open ✗`, its name a link to it. */
|
|
149
|
+
function unitText(u) {
|
|
150
|
+
const isPr = u.kind === "pull_request" || /\/pull\/\d+/.test(u.url ?? "");
|
|
151
|
+
if (!isPr || (u.state !== "open" && u.state !== "claimed"))
|
|
152
|
+
return null;
|
|
153
|
+
const name = osc8(u.url, /^\S+#\d+/.exec(u.label)?.[0] ?? clip(u.label, 30));
|
|
154
|
+
const p = u.prState;
|
|
155
|
+
if (!p)
|
|
156
|
+
return name; // the pod recorded nothing about it: draw nothing, never a guess
|
|
157
|
+
if (p.status !== "ok")
|
|
158
|
+
return `${name} ${D}⚑ not read${X}`;
|
|
159
|
+
const word = (p.label ?? p.state ?? "").toLowerCase();
|
|
160
|
+
const checks = p.checks === "passed" ? ` ${G}✓${X}` : p.checks === "failed" ? ` ${R}✗${X}` : "";
|
|
161
|
+
return `${name}${word ? ` ${D}${word}${X}` : ""}${checks}`;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The pod's rule (`isSessionWorkingNow`) on the file's `live`, judged now.
|
|
165
|
+
*
|
|
166
|
+
* `turnInFlight` is the pod's word AT `measuredAt` (else when the file was
|
|
167
|
+
* written, `writtenAt`), not now: it holds for one working window after that
|
|
168
|
+
* and no longer. Read as "now", a file the bridge last wrote mid-turn said
|
|
169
|
+
* "working" for as long as the file stayed fresh (12 h).
|
|
170
|
+
*/
|
|
171
|
+
export function podWorking(live, now, writtenAt) {
|
|
172
|
+
const window = live.windowMs ?? POD_WORKING_WINDOW_MS;
|
|
173
|
+
const last = live.lastActivityAt ? Date.parse(live.lastActivityAt) : NaN;
|
|
174
|
+
if (Number.isFinite(last) && now - last <= window)
|
|
175
|
+
return true;
|
|
176
|
+
if (!live.turnInFlight)
|
|
177
|
+
return false;
|
|
178
|
+
const measured = live.measuredAt ? Date.parse(live.measuredAt) : writtenAt ?? NaN;
|
|
179
|
+
return Number.isFinite(measured) && now - measured <= window;
|
|
180
|
+
}
|
|
181
|
+
/** The 4th line from a fresh status file. */
|
|
182
|
+
export function buildBridgeLine(input) {
|
|
183
|
+
const { now, file, registry } = input;
|
|
184
|
+
const width = input.width && input.width > 20 ? input.width : DEFAULT_WIDTH;
|
|
185
|
+
if (registry?.status === "waiting") {
|
|
186
|
+
return `${Y}✋ needs you${X} ${D}·${X} ${clip(registry.waitingFor || "your answer", width - 16)}`;
|
|
187
|
+
}
|
|
188
|
+
const marks = (file.waitingOn ?? []).filter((m) => m.count > 0);
|
|
189
|
+
const waited = marks.reduce((n, m) => n + m.count, 0);
|
|
190
|
+
const units = (file.workUnits ?? []).map(unitText).filter((t) => t !== null);
|
|
191
|
+
const unread = [file.waitingOn === null && "waits", file.workUnits === null && "PRs"].filter(Boolean);
|
|
192
|
+
// The registry's turn state when there is one; the pod's relay of it otherwise.
|
|
193
|
+
let working = false;
|
|
194
|
+
let since;
|
|
195
|
+
if (registry) {
|
|
196
|
+
working = registry.status === "busy";
|
|
197
|
+
since = registry.statusUpdatedAt;
|
|
198
|
+
}
|
|
199
|
+
else if (file.live) {
|
|
200
|
+
working = podWorking(file.live, now, input.writtenAt);
|
|
201
|
+
const at = Date.parse((working ? file.live.since : file.live.lastActivityAt) ?? "");
|
|
202
|
+
since = Number.isFinite(at) ? at : undefined;
|
|
203
|
+
}
|
|
204
|
+
const items = [...marks.map(markText), ...units];
|
|
205
|
+
if (!working && file.nextMove?.label)
|
|
206
|
+
items.push(`${D}next:${X} ${clip(file.nextMove.label, 60)}`);
|
|
207
|
+
if (unread.length)
|
|
208
|
+
items.push(`${D}⚑ not read: ${unread.join(", ")}${X}`);
|
|
209
|
+
// A quiet file is still true, but say how old the pod's word is.
|
|
210
|
+
if (now - input.writtenAt > POD_WORKING_WINDOW_MS)
|
|
211
|
+
items.push(`${D}pod ${age(now - input.writtenAt)} ago${X}`);
|
|
212
|
+
let head;
|
|
213
|
+
if (working) {
|
|
214
|
+
head = `${C}▶ working${X}${since ? ` ${D}· ${age(now - since)}${X}` : ""}${waited ? ` ${D}·${X} ⏳ ${waited}` : ""}`;
|
|
215
|
+
}
|
|
216
|
+
else if (waited) {
|
|
217
|
+
head = `${Y}⏳ waiting on ${waited}${X}`;
|
|
218
|
+
}
|
|
219
|
+
else if (!registry && !file.live) {
|
|
220
|
+
head = `${D}○ no session status${X}`;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
head = `${A}■ stopped${X}${since ? ` ${D}· ${age(now - since)}${X}` : ""}`;
|
|
224
|
+
}
|
|
225
|
+
return capped(head, items, width);
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=bridge-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-status.js","sourceRoot":"","sources":["../../src/lib/bridge-status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bridge's status file as the status line reads it: judged (fresh /
|
|
3
|
+
* absent / unbound / stale / failed) and drawn. Files go under a temp HOME
|
|
4
|
+
* passed as `home`; time, registry and width are arguments.
|
|
5
|
+
*/
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
10
|
+
import { BRIDGE_STATUS_MAX_AGE_MS, bridgeStatusPath, buildBridgeLine, readBridgeStatus, } from "./bridge-status.js";
|
|
11
|
+
const NOW = Date.parse("2026-10-30T22:00:00Z");
|
|
12
|
+
const min = (m) => NOW - m * 60_000;
|
|
13
|
+
const iso = (ms) => new Date(ms).toISOString();
|
|
14
|
+
// eslint-disable-next-line no-control-regex
|
|
15
|
+
const plain = (s) => s.replace(/\x1b\[[0-9;]*m|\x1b\]8;;[^\x1b]*\x1b\\/g, "");
|
|
16
|
+
const CONV = "11111111-2222-3333-4444-555555555555";
|
|
17
|
+
/** A file as the bridge's `statusFile` writes it (synap-bridge hooks/lib.ts). */
|
|
18
|
+
const file = (over = {}) => ({
|
|
19
|
+
v: 1,
|
|
20
|
+
writtenAt: iso(min(1)),
|
|
21
|
+
sessionId: "54436c32-783f-4a9d-9322-16ff18f448f7",
|
|
22
|
+
title: "Lane cli-statusfile",
|
|
23
|
+
live: { state: "idle", turnInFlight: false, since: iso(min(20)), lastActivityAt: iso(min(20)), measuredAt: iso(min(1)), windowMs: 300_000 },
|
|
24
|
+
nextMove: { kind: "agent_slot", actor: "ai", label: 'Produce "Wave 2 report"', reason: "Declared deliverable with no output yet" },
|
|
25
|
+
waitingOn: [],
|
|
26
|
+
workUnits: [],
|
|
27
|
+
...over,
|
|
28
|
+
});
|
|
29
|
+
const reg = (status, extra = {}) => ({
|
|
30
|
+
sessionId: CONV,
|
|
31
|
+
pid: 1,
|
|
32
|
+
status,
|
|
33
|
+
statusUpdatedAt: min(4),
|
|
34
|
+
startedAt: min(600),
|
|
35
|
+
...extra,
|
|
36
|
+
});
|
|
37
|
+
let home;
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
home = fs.mkdtempSync(path.join(os.tmpdir(), "bridge-status-"));
|
|
40
|
+
});
|
|
41
|
+
const write = (content) => {
|
|
42
|
+
const p = bridgeStatusPath(CONV, home);
|
|
43
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
44
|
+
fs.writeFileSync(p, content);
|
|
45
|
+
};
|
|
46
|
+
const read = (opts = {}) => readBridgeStatus(CONV, { now: NOW, home, ...opts });
|
|
47
|
+
describe("reading the file", () => {
|
|
48
|
+
it("is where the bridge writes it", () => {
|
|
49
|
+
expect(bridgeStatusPath(CONV, "/home/x")).toBe(`/home/x/.synap/bridge/status/${CONV}.json`);
|
|
50
|
+
});
|
|
51
|
+
it("a fresh file of a bound session is drawn", () => {
|
|
52
|
+
write(JSON.stringify(file()));
|
|
53
|
+
const r = read({ startedAt: min(600) });
|
|
54
|
+
expect(r.status).toBe("fresh");
|
|
55
|
+
if (r.status === "fresh")
|
|
56
|
+
expect(r.writtenAt).toBe(min(1));
|
|
57
|
+
});
|
|
58
|
+
it("no file is absent (no bridge, or it has not written yet)", () => {
|
|
59
|
+
expect(read()).toEqual({ status: "absent" });
|
|
60
|
+
});
|
|
61
|
+
it("nothing bound (`sessionId: null`, /bridge unbind) is unbound, not drawn", () => {
|
|
62
|
+
write(JSON.stringify(file({ sessionId: null, title: null })));
|
|
63
|
+
expect(read()).toEqual({ status: "unbound" });
|
|
64
|
+
});
|
|
65
|
+
it("a file written before this Claude Code process started is stale", () => {
|
|
66
|
+
write(JSON.stringify(file({ writtenAt: iso(min(90)) })));
|
|
67
|
+
expect(read({ startedAt: min(60) })).toEqual({ status: "stale", why: "written before this Claude Code process started" });
|
|
68
|
+
});
|
|
69
|
+
it("a file older than the max age is stale, even with no registry", () => {
|
|
70
|
+
write(JSON.stringify(file({ writtenAt: iso(NOW - BRIDGE_STATUS_MAX_AGE_MS - 60_000) })));
|
|
71
|
+
expect(read()).toMatchObject({ status: "stale" });
|
|
72
|
+
});
|
|
73
|
+
it("a quiet file younger than the max age is still fresh", () => {
|
|
74
|
+
write(JSON.stringify(file({ writtenAt: iso(min(45)) })));
|
|
75
|
+
expect(read({ startedAt: min(600) }).status).toBe("fresh");
|
|
76
|
+
});
|
|
77
|
+
it("malformed JSON is a failed read, never absent, and never throws", () => {
|
|
78
|
+
write('{"v":1,"writtenAt":');
|
|
79
|
+
expect(read()).toEqual({ status: "failed", why: "not JSON" });
|
|
80
|
+
});
|
|
81
|
+
it("another version, a missing time or a malformed section is a failed read", () => {
|
|
82
|
+
write(JSON.stringify({ ...file(), v: 2 }));
|
|
83
|
+
expect(read()).toMatchObject({ status: "failed", why: "version 2 is not 1" });
|
|
84
|
+
write(JSON.stringify({ ...file(), writtenAt: "soon" }));
|
|
85
|
+
expect(read()).toMatchObject({ status: "failed", why: "no writtenAt time" });
|
|
86
|
+
write(JSON.stringify({ ...file(), waitingOn: { status: "ok", marks: [] } }));
|
|
87
|
+
expect(read()).toMatchObject({ status: "failed", why: "waitingOn is malformed" });
|
|
88
|
+
write("[]");
|
|
89
|
+
expect(read()).toMatchObject({ status: "failed", why: "not an object" });
|
|
90
|
+
});
|
|
91
|
+
it("a malformed `live` costs only its own fields, never the file (bridge ≤ 0.11 wrote NaN and \"undefined\")", () => {
|
|
92
|
+
// What `String(undefined)` and `Number(undefined)` (NaN → null in JSON) leave in the file.
|
|
93
|
+
write(JSON.stringify({ ...file(), live: { state: "idle", turnInFlight: false, since: null, lastActivityAt: null, measuredAt: "undefined", windowMs: null } }));
|
|
94
|
+
const r = read({ startedAt: min(600) });
|
|
95
|
+
expect(r.status).toBe("fresh");
|
|
96
|
+
if (r.status === "fresh")
|
|
97
|
+
expect(r.file.live).toEqual({ state: "idle", turnInFlight: false, since: null, lastActivityAt: null, measuredAt: null, windowMs: null });
|
|
98
|
+
write(JSON.stringify({ ...file(), live: { state: "working" } }));
|
|
99
|
+
expect(read().status).toBe("fresh");
|
|
100
|
+
write(JSON.stringify({ ...file(), live: "undefined" }));
|
|
101
|
+
const s = read();
|
|
102
|
+
expect(s.status).toBe("fresh");
|
|
103
|
+
if (s.status === "fresh")
|
|
104
|
+
expect(s.file.live).toBeNull();
|
|
105
|
+
});
|
|
106
|
+
it("every string in the file is scrubbed of control characters", () => {
|
|
107
|
+
write(JSON.stringify(file({
|
|
108
|
+
nextMove: { kind: "agent_slot", actor: "ai", label: "Open\x1b]8;;https://evil.test\x1b\\ the PR\x07", reason: "" },
|
|
109
|
+
workUnits: [{ key: "a", label: "backend#7\x1b[2J x", kind: "pull_request", url: "https://github.com/Synap-core/backend/pull/7\x1b\\", state: "open", prState: null }],
|
|
110
|
+
})));
|
|
111
|
+
const r = read({ startedAt: min(600) });
|
|
112
|
+
expect(r.status).toBe("fresh");
|
|
113
|
+
if (r.status !== "fresh")
|
|
114
|
+
return;
|
|
115
|
+
const raw = buildBridgeLine({ now: NOW, file: r.file, writtenAt: r.writtenAt, registry: reg("idle") });
|
|
116
|
+
expect(raw).not.toContain("https://evil.test\x1b");
|
|
117
|
+
expect(raw).not.toContain("\x1b[2J");
|
|
118
|
+
expect(raw).not.toContain("\x07");
|
|
119
|
+
// The URL's own ESC is gone (its backslash is left, inert); our link around the PR name is intact.
|
|
120
|
+
expect(raw).toContain("\x1b]8;;https://github.com/Synap-core/backend/pull/7\\\x1b\\backend#7\x1b]8;;\x1b\\");
|
|
121
|
+
expect(plain(raw)).toContain("next: Open]8;;https://evil.test\\ the PR");
|
|
122
|
+
});
|
|
123
|
+
it("an unreadable file (here a directory) is a failed read", () => {
|
|
124
|
+
fs.mkdirSync(bridgeStatusPath(CONV, home), { recursive: true });
|
|
125
|
+
expect(read()).toMatchObject({ status: "failed", why: expect.stringContaining("unreadable") });
|
|
126
|
+
});
|
|
127
|
+
it("a session id that could leave the directory reads no file", () => {
|
|
128
|
+
expect(readBridgeStatus("../../etc/passwd", { now: NOW, home })).toEqual({ status: "absent" });
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
const line = (f, registry = reg("idle"), width) => plain(buildBridgeLine({ now: NOW, file: f, writtenAt: Date.parse(f.writtenAt), registry, width }));
|
|
132
|
+
describe("drawing the line", () => {
|
|
133
|
+
it("idle with nothing waited on: stopped, with the pod's next move", () => {
|
|
134
|
+
expect(line(file())).toBe('■ stopped · 4m · next: Produce "Wave 2 report"');
|
|
135
|
+
});
|
|
136
|
+
it("idle and waiting: the pod's marks, in the vocabulary's words, and the open PRs", () => {
|
|
137
|
+
const f = file({
|
|
138
|
+
waitingOn: [
|
|
139
|
+
{ reason: "another_work", count: 2, refs: [{ kind: "session", id: "s2" }] },
|
|
140
|
+
{ reason: "approval", count: 1 },
|
|
141
|
+
],
|
|
142
|
+
workUnits: [
|
|
143
|
+
{ key: "pr-synap-cli-52", label: "synap-cli#52 feat(statusline): read the bridge file", kind: "pull_request", url: "https://github.com/Synap-core/synap-cli/pull/52", state: "open", prState: { status: "ok", label: "Open", state: "open", checks: "failed" } },
|
|
144
|
+
{ key: "pr-backend-9", label: "backend#9 done already", kind: "pull_request", url: "https://github.com/Synap-core/backend/pull/9", state: "met", prState: { status: "ok", label: "Merged", state: "merged" } },
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
expect(line(f)).toBe('⏳ waiting on 3 · other work (2) · approval · synap-cli#52 open ✗ · next: Produce "Wave 2 report"');
|
|
148
|
+
});
|
|
149
|
+
it("working (the registry says busy): the marks follow, the next move does not", () => {
|
|
150
|
+
const f = file({ waitingOn: [{ reason: "input", count: 1 }] });
|
|
151
|
+
expect(line(f, reg("busy", { statusUpdatedAt: min(3) }))).toBe("▶ working · 3m · ⏳ 1 · input");
|
|
152
|
+
});
|
|
153
|
+
it("the registry's permission prompt beats everything", () => {
|
|
154
|
+
expect(line(file(), reg("waiting", { waitingFor: "permission prompt" }))).toBe("✋ needs you · permission prompt");
|
|
155
|
+
});
|
|
156
|
+
it("no registry: the pod's live, re-judged now by its own window", () => {
|
|
157
|
+
const working = file({ live: { state: "working", turnInFlight: false, since: iso(min(2)), lastActivityAt: iso(min(2)), measuredAt: iso(min(1)), windowMs: 300_000 } });
|
|
158
|
+
expect(line(working, null)).toBe("▶ working · 2m");
|
|
159
|
+
// Measured as working, but its last activity is now past the window: idle.
|
|
160
|
+
const lapsed = file({ live: { state: "working", turnInFlight: false, since: iso(min(8)), lastActivityAt: iso(min(8)), measuredAt: iso(min(1)), windowMs: 300_000 } });
|
|
161
|
+
expect(line(lapsed, null)).toBe('■ stopped · 8m · next: Produce "Wave 2 report"');
|
|
162
|
+
expect(line(file({ live: null }), null)).toBe('○ no session status · next: Produce "Wave 2 report"');
|
|
163
|
+
});
|
|
164
|
+
it("a turn in flight is the pod's word at `measuredAt`: it lapses one window later, never 12 h later", () => {
|
|
165
|
+
const inFlight = (measured, windowMs = 300_000) => file({ live: { state: "working", turnInFlight: true, since: iso(min(700)), lastActivityAt: iso(min(700)), measuredAt: iso(measured), windowMs } });
|
|
166
|
+
expect(line(inFlight(min(1)), null)).toBe("▶ working · 11h40");
|
|
167
|
+
// Written mid-turn 6 h ago and never rewritten: not "working".
|
|
168
|
+
expect(line(inFlight(min(360)), null)).toBe('■ stopped · 11h40 · next: Produce "Wave 2 report"');
|
|
169
|
+
// No usable measurement time: the time the file was written bounds it, and the pod's default window applies.
|
|
170
|
+
const unmeasured = file({ writtenAt: iso(min(30)), live: { ...inFlight(min(1)).live, measuredAt: null, windowMs: null } });
|
|
171
|
+
expect(line(unmeasured, null)).toBe('■ stopped · 11h40 · next: Produce "Wave 2 report" · pod 30m ago');
|
|
172
|
+
expect(line({ ...unmeasured, writtenAt: iso(min(2)) }, null)).toBe("▶ working · 11h40");
|
|
173
|
+
});
|
|
174
|
+
it("a section the pod could not read is said, never drawn as nothing", () => {
|
|
175
|
+
expect(line(file({ waitingOn: null, workUnits: null, nextMove: null }))).toBe("■ stopped · 4m · ⚑ not read: waits, PRs");
|
|
176
|
+
});
|
|
177
|
+
it("a PR whose state the pod could not read is marked; one with nothing recorded is just named", () => {
|
|
178
|
+
const f = file({
|
|
179
|
+
nextMove: null,
|
|
180
|
+
workUnits: [
|
|
181
|
+
{ key: "a", label: "backend#7 x", kind: "pull_request", url: "https://github.com/Synap-core/backend/pull/7", state: "open", prState: { status: "unavailable" } },
|
|
182
|
+
{ key: "b", label: "relay-app#3 y", kind: "pull_request", url: null, state: "claimed", prState: null },
|
|
183
|
+
],
|
|
184
|
+
});
|
|
185
|
+
expect(line(f)).toBe("■ stopped · 4m · backend#7 ⚑ not read · relay-app#3");
|
|
186
|
+
});
|
|
187
|
+
it("a quiet file says how old the pod's word is", () => {
|
|
188
|
+
expect(line(file({ writtenAt: iso(min(40)), nextMove: null }))).toBe("■ stopped · 4m · pod 40m ago");
|
|
189
|
+
});
|
|
190
|
+
it("caps itself to the width", () => {
|
|
191
|
+
const f = file({ waitingOn: Array.from({ length: 6 }, (_, i) => ({ reason: `reason_${i}`, count: 1 })) });
|
|
192
|
+
const out = line(f, reg("idle"), 50);
|
|
193
|
+
expect(out.length).toBeLessThanOrEqual(50);
|
|
194
|
+
expect(out).toMatch(/\+\d+ more$/);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
//# sourceMappingURL=bridge-status.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-status.test.js","sourceRoot":"","sources":["../../src/lib/bridge-status.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|