waymark-hub 1.0.0

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.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +176 -0
  3. package/dashboard/README.md +71 -0
  4. package/dashboard/index.html +520 -0
  5. package/dashboard/server.mjs +343 -0
  6. package/dashboard/vendor/tailwind.js +83 -0
  7. package/dist/cli/benchmark.d.ts +3 -0
  8. package/dist/cli/benchmark.d.ts.map +1 -0
  9. package/dist/cli/benchmark.js +222 -0
  10. package/dist/cli/benchmark.js.map +1 -0
  11. package/dist/cli/waymark.d.ts +3 -0
  12. package/dist/cli/waymark.d.ts.map +1 -0
  13. package/dist/cli/waymark.js +216 -0
  14. package/dist/cli/waymark.js.map +1 -0
  15. package/dist/context/builder.d.ts +67 -0
  16. package/dist/context/builder.d.ts.map +1 -0
  17. package/dist/context/builder.js +270 -0
  18. package/dist/context/builder.js.map +1 -0
  19. package/dist/db/client.d.ts +5 -0
  20. package/dist/db/client.d.ts.map +1 -0
  21. package/dist/db/client.js +67 -0
  22. package/dist/db/client.js.map +1 -0
  23. package/dist/db/migrations/001_initial.sql +85 -0
  24. package/dist/db/migrations/002_usage_experiments.sql +52 -0
  25. package/dist/db/migrations/003_agent_identity.sql +37 -0
  26. package/dist/db/migrations/004_memory_lifecycle.sql +25 -0
  27. package/dist/db/migrations/005_task_coordination.sql +17 -0
  28. package/dist/db/schema.d.ts +132 -0
  29. package/dist/db/schema.d.ts.map +1 -0
  30. package/dist/db/schema.js +3 -0
  31. package/dist/db/schema.js.map +1 -0
  32. package/dist/server.d.ts +12 -0
  33. package/dist/server.d.ts.map +1 -0
  34. package/dist/server.js +164 -0
  35. package/dist/server.js.map +1 -0
  36. package/dist/telemetry/tokens.d.ts +9 -0
  37. package/dist/telemetry/tokens.d.ts.map +1 -0
  38. package/dist/telemetry/tokens.js +23 -0
  39. package/dist/telemetry/tokens.js.map +1 -0
  40. package/dist/tools/agents.d.ts +3 -0
  41. package/dist/tools/agents.d.ts.map +1 -0
  42. package/dist/tools/agents.js +126 -0
  43. package/dist/tools/agents.js.map +1 -0
  44. package/dist/tools/context.d.ts +3 -0
  45. package/dist/tools/context.d.ts.map +1 -0
  46. package/dist/tools/context.js +53 -0
  47. package/dist/tools/context.js.map +1 -0
  48. package/dist/tools/memory.d.ts +3 -0
  49. package/dist/tools/memory.d.ts.map +1 -0
  50. package/dist/tools/memory.js +273 -0
  51. package/dist/tools/memory.js.map +1 -0
  52. package/dist/tools/projects.d.ts +3 -0
  53. package/dist/tools/projects.d.ts.map +1 -0
  54. package/dist/tools/projects.js +92 -0
  55. package/dist/tools/projects.js.map +1 -0
  56. package/dist/tools/sessions.d.ts +3 -0
  57. package/dist/tools/sessions.d.ts.map +1 -0
  58. package/dist/tools/sessions.js +113 -0
  59. package/dist/tools/sessions.js.map +1 -0
  60. package/dist/tools/tasks.d.ts +3 -0
  61. package/dist/tools/tasks.d.ts.map +1 -0
  62. package/dist/tools/tasks.js +304 -0
  63. package/dist/tools/tasks.js.map +1 -0
  64. package/dist/tools/telemetry.d.ts +3 -0
  65. package/dist/tools/telemetry.d.ts.map +1 -0
  66. package/dist/tools/telemetry.js +291 -0
  67. package/dist/tools/telemetry.js.map +1 -0
  68. package/docs/AGENT_IDENTITY.md +67 -0
  69. package/docs/BENCHMARKING.md +161 -0
  70. package/docs/CONTEXT.md +95 -0
  71. package/docs/MEMORY_LIFECYCLE.md +65 -0
  72. package/docs/TASK_COORDINATION.md +27 -0
  73. package/package.json +70 -0
  74. package/scripts/hooks/session-start-resume.cjs +70 -0
@@ -0,0 +1,67 @@
1
+ # Agent identity
2
+
3
+ Waymark supports provider-neutral agent identities while retaining legacy
4
+ surface fields for existing clients.
5
+
6
+ ## Identity fields
7
+
8
+ - `agent_id`: stable logical agent identity;
9
+ - `provider`: model provider, such as OpenAI, Anthropic, Google, or local;
10
+ - `model`: provider model identifier;
11
+ - `client`: application or integration, such as Codex CLI or a browser agent;
12
+ - `client_version`: optional client version;
13
+ - `capabilities`: declared abilities such as `code`, `browser`, or `documents`;
14
+ - `client_session_id`: session identifier supplied by the client.
15
+
16
+ Provider, model, client, agent, and session are separate concepts. Changing a
17
+ model or client does not require changing project data.
18
+
19
+ ## Registering an agent
20
+
21
+ Use `agent_register` with a stable caller-controlled id when possible:
22
+
23
+ ```json
24
+ {
25
+ "id": "codex-primary",
26
+ "display_name": "Primary coding agent",
27
+ "provider": "openai",
28
+ "model": "<model-id>",
29
+ "client": "codex",
30
+ "capabilities": ["code", "shell", "review"]
31
+ }
32
+ ```
33
+
34
+ When no id is supplied, the Hub generates a UUID.
35
+
36
+ Available tools:
37
+
38
+ - `agent_register`;
39
+ - `agent_get`;
40
+ - `agent_list`;
41
+ - `agent_set_status`.
42
+
43
+ ## Linking work
44
+
45
+ The following tools accept registered agent identities:
46
+
47
+ - `session_log.agent_id`;
48
+ - `usage_report.agent_id`;
49
+ - `memory_write.agent_id`;
50
+ - `task_create.created_by_agent`;
51
+ - `task_create.assigned_agent_id`;
52
+ - `task_list.created_by_agent`;
53
+ - `task_list.assigned_agent_id`.
54
+
55
+ When `usage_report` references a linked session, it inherits the session agent,
56
+ project, provider, model, and client. Conflicting explicit values are rejected.
57
+
58
+ ## Backward compatibility
59
+
60
+ Legacy fields remain supported:
61
+
62
+ - `surface`;
63
+ - `created_by`;
64
+ - `assigned_to`.
65
+
66
+ New clients should send agent identity fields. Existing clients can continue
67
+ using legacy fields until the v2 migration is complete.
@@ -0,0 +1,161 @@
1
+ # Token usage benchmarking
2
+
3
+ This document defines the Stage 1 measurement protocol for comparing agent work
4
+ with and without the Hub.
5
+
6
+ ## Measurement rule
7
+
8
+ The primary metric is total model usage for the complete task:
9
+
10
+ ```text
11
+ total_model_tokens =
12
+ input_tokens
13
+ + output_tokens
14
+ + hub_llm_input_tokens
15
+ + hub_llm_output_tokens
16
+ ```
17
+
18
+ `input_tokens` already includes tool schemas, prompts, retrieved context and
19
+ memory-write requests sent to the agent model. Do not add `context_tokens` or
20
+ tool-schema tokens to the total a second time.
21
+
22
+ `cached_input_tokens` is diagnostic metadata. It is not subtracted unless a
23
+ future cost-specific metric explicitly defines provider cache pricing.
24
+
25
+ ## Exact and estimated data
26
+
27
+ - Use `measurement=exact` only when token counts come from the provider or
28
+ client usage report.
29
+ - Use `measurement=estimated` for locally calculated counts.
30
+ - Never combine exact and estimated runs in one result.
31
+ - Never combine different providers, models or clients in one result.
32
+
33
+ The `experiment_summary` tool enforces these cohort boundaries.
34
+
35
+ ## Running an experiment
36
+
37
+ 1. Create an experiment with `experiment_create`.
38
+ 2. Freeze the repository state and task instructions.
39
+ 3. Run the scenario without the Hub.
40
+ 4. Restore the same initial state.
41
+ 5. Run the scenario with the Hub.
42
+ 6. Submit each result with `usage_report`.
43
+ 7. Repeat both variants at least five times.
44
+ 8. Read the grouped result with `experiment_summary`.
45
+ 9. Mark the experiment completed with `experiment_update`.
46
+
47
+ The same workflow is available from the command line:
48
+
49
+ ```powershell
50
+ # Create an experiment
51
+ npm run benchmark -- create `
52
+ --name "Continuation benchmark" `
53
+ --scenario "continue-bugfix" `
54
+ --project-id "D--Projects-ClaudePlus" `
55
+ --target-runs 5
56
+
57
+ # Record one run from flags
58
+ npm run benchmark -- record `
59
+ --experiment-id "<experiment-id>" `
60
+ --variant without_hub `
61
+ --provider openai `
62
+ --model "<model-id>" `
63
+ --client codex `
64
+ --measurement exact `
65
+ --input-tokens 12000 `
66
+ --output-tokens 1800 `
67
+ --duration-ms 90000 `
68
+ --success true
69
+
70
+ # Record a richer run from JSON
71
+ npm run benchmark -- record --file .\run-with-hub.json
72
+
73
+ # Read the report and close the experiment
74
+ npm run benchmark -- summary --id "<experiment-id>"
75
+ npm run benchmark -- complete --id "<experiment-id>"
76
+ ```
77
+
78
+ Use `DB_PATH` to run against a separate benchmark database:
79
+
80
+ ```powershell
81
+ $env:DB_PATH = "D:\tmp\waymark-benchmark.db"
82
+ npm run benchmark -- list
83
+ ```
84
+
85
+ The installed package exposes the same CLI as `waymark-benchmark`.
86
+ For repository development, run `npm run build` after source changes before
87
+ using `npm run benchmark`. The benchmark command itself does not rebuild
88
+ `dist`, so it can run while the MCP server is active on Windows.
89
+
90
+ Example JSON run:
91
+
92
+ ```json
93
+ {
94
+ "experiment_id": "<experiment-id>",
95
+ "variant": "with_hub",
96
+ "provider": "openai",
97
+ "model": "<model-id>",
98
+ "client": "codex",
99
+ "measurement": "exact",
100
+ "input_tokens": 8500,
101
+ "output_tokens": 1400,
102
+ "hub_llm_input_tokens": 0,
103
+ "hub_llm_output_tokens": 0,
104
+ "context_tokens": 900,
105
+ "tool_calls": 14,
106
+ "files_read": ["src/server.ts", "src/tools/memory.ts"],
107
+ "repeated_files": 1,
108
+ "clarification_count": 0,
109
+ "duration_ms": 62000,
110
+ "result_quality": 95,
111
+ "success": true
112
+ }
113
+ ```
114
+
115
+ ## Required controls
116
+
117
+ - Same provider, model and client within a cohort.
118
+ - Same task statement and acceptance test.
119
+ - Same initial repository state.
120
+ - Same tool availability except for the Hub itself.
121
+ - Separate sessions for every run.
122
+ - Record failures instead of silently discarding them.
123
+
124
+ ## Recommended fields
125
+
126
+ Every run should provide:
127
+
128
+ - `experiment_id`;
129
+ - `variant`;
130
+ - `provider`;
131
+ - `model`;
132
+ - `client`;
133
+ - `measurement`;
134
+ - `input_tokens`;
135
+ - `output_tokens`;
136
+ - `hub_llm_input_tokens` and `hub_llm_output_tokens` when applicable;
137
+ - `context_tokens` or `context_text`;
138
+ - `tool_calls`;
139
+ - `files_read`;
140
+ - `repeated_files`;
141
+ - `clarification_count`;
142
+ - `duration_ms`;
143
+ - `result_quality`;
144
+ - `success`;
145
+ - notes about deviations.
146
+
147
+ ## Interpreting the result
148
+
149
+ ```text
150
+ net_token_saving =
151
+ median_without_hub
152
+ - median_with_hub
153
+
154
+ net_token_saving_percent =
155
+ net_token_saving / median_without_hub * 100
156
+ ```
157
+
158
+ A positive result means the Hub reduced model usage. Token reduction is not
159
+ sufficient by itself: result quality and success rate must remain comparable.
160
+
161
+ The MVP target is at least 20% median net token saving on continuation tasks.
@@ -0,0 +1,95 @@
1
+ # Token-budgeted context
2
+
3
+ The Hub provides two high-level read-only tools for restoring project context
4
+ without loading all memory into the agent prompt.
5
+
6
+ ## `workspace_resume`
7
+
8
+ Use once at the beginning of a session:
9
+
10
+ ```json
11
+ {
12
+ "project_id": "D--Projects-ClaudePlus",
13
+ "task": "Continue implementation of compact context",
14
+ "agent_id": "codex-primary",
15
+ "client_id": "codex",
16
+ "max_tokens": 1200
17
+ }
18
+ ```
19
+
20
+ The task is optional. When supplied, it improves memory ranking.
21
+
22
+ **When to use which:** `workspace_resume` is the session opener — call it exactly
23
+ once, at the start, to restore the whole workspace picture (tasks, sessions,
24
+ handoffs, top memories). `context_get` is the mid-session refiner — call it when
25
+ you hit a *new sub-task* and want memories re-ranked for it (optionally filtered
26
+ by `memory_types` or with bodies via `include_sources`). If you only need one
27
+ known record, use `memory_read(id)` instead of either.
28
+
29
+ The packet may include `notices` — short protocol nudges (for example, an
30
+ unregistered `agent_id`). They cost a few tokens and appear only when relevant.
31
+
32
+ ## `context_get`
33
+
34
+ Use when the agent needs context for a specific task:
35
+
36
+ ```json
37
+ {
38
+ "project_id": "D--Projects-ClaudePlus",
39
+ "task": "Investigate SQLite write contention",
40
+ "agent_id": "codex-primary",
41
+ "max_tokens": 800,
42
+ "memory_types": ["decision", "handoff", "project"],
43
+ "include_sources": false
44
+ }
45
+ ```
46
+
47
+ `include_sources=true` includes truncated memory bodies and therefore consumes
48
+ more of the budget. By default only compact summaries and record ids are
49
+ returned.
50
+
51
+ ## Packet contents
52
+
53
+ - compact project metadata;
54
+ - the current task;
55
+ - active pending and in-progress tasks;
56
+ - ranked project and global memories;
57
+ - recent session summaries;
58
+ - counts of records omitted because of the budget;
59
+ - estimated serialized response tokens.
60
+
61
+ ## Ranking
62
+
63
+ The deterministic ranking uses:
64
+
65
+ - memory type;
66
+ - project records over global records;
67
+ - term overlap with the requested task;
68
+ - update recency.
69
+
70
+ The core does not call an LLM or external service.
71
+
72
+ ## Budget behavior
73
+
74
+ - Accepted budget: 200–20,000 estimated tokens.
75
+ - Default budget: 1,200.
76
+ - The estimate is calculated from the pretty-printed JSON returned to the
77
+ client.
78
+ - Candidates are added one at a time and removed if they exceed the budget.
79
+ - For very small budgets, optional project metadata is trimmed first.
80
+ - Detailed bodies are omitted unless explicitly requested.
81
+
82
+ The estimate uses the current deterministic fallback of approximately four
83
+ UTF-8 bytes per token. Future model-specific tokenizers can replace this
84
+ adapter without changing the context API.
85
+
86
+ ## Recommended session start
87
+
88
+ New clients should use:
89
+
90
+ 1. `agent_register` or a previously assigned stable `agent_id`;
91
+ 2. one `workspace_resume` call;
92
+ 3. low-level tools only for details referenced by record or task id.
93
+
94
+ This replaces the legacy requirement to always call `project_list`,
95
+ `memory_list`, and `task_list` at session start.
@@ -0,0 +1,65 @@
1
+ # Memory lifecycle
2
+
3
+ Memory records are durable project knowledge, not an append-only transcript.
4
+ The lifecycle prevents obsolete records from polluting future agent context.
5
+
6
+ ## Statuses
7
+
8
+ - `active`: eligible for normal search and context packets;
9
+ - `superseded`: replaced by a newer record;
10
+ - `stale`: known to require verification;
11
+ - `archived`: retained for audit but excluded from normal work.
12
+
13
+ Existing records migrate as `active`.
14
+
15
+ ## Quality and provenance
16
+
17
+ `memory_write` supports:
18
+
19
+ - `importance`: 0–100;
20
+ - `confidence`: 0–100;
21
+ - `source_type`: file, commit, task, URL, user, or another source class;
22
+ - `source_ref`: path, SHA, URL, task id, or other source identifier;
23
+ - `valid_from` and `valid_until`;
24
+ - `last_verified_at`;
25
+ - `supersedes_id`.
26
+
27
+ Context ranking uses importance, confidence, recency, task relevance, memory
28
+ type, project scope, and feedback.
29
+
30
+ ## Replacing a record
31
+
32
+ Create the new record with `supersedes_id` referencing the old record. The Hub
33
+ uses one SQLite transaction to:
34
+
35
+ 1. write the new record;
36
+ 2. mark the old record `superseded`.
37
+
38
+ This prevents both versions from appearing as active context.
39
+
40
+ ## Feedback
41
+
42
+ Use `memory_feedback` after consuming a context packet:
43
+
44
+ - `used`;
45
+ - `not_used`;
46
+ - `helpful`;
47
+ - `irrelevant`;
48
+ - `stale`;
49
+ - `incorrect`;
50
+ - `too_verbose`.
51
+
52
+ Positive feedback increases ranking. Negative feedback reduces ranking.
53
+ Feedback does not automatically delete or rewrite memory.
54
+
55
+ Use `memory_set_status` when a record is known to be stale, archived, or active
56
+ again after verification.
57
+
58
+ ## Read behavior
59
+
60
+ - `context_get` and `workspace_resume` include only active and currently valid
61
+ records.
62
+ - `memory_search` excludes inactive and expired records by default.
63
+ - `memory_search(include_inactive=true)` supports audit and historical lookup.
64
+ - `memory_read(id=...)` can always retrieve a known record regardless of status.
65
+ - `memory_list` can filter by status and returns lifecycle metadata.
@@ -0,0 +1,27 @@
1
+ # Task Coordination
2
+
3
+ The task queue supports coordinated work by multiple registered agents.
4
+
5
+ ## Claim protocol
6
+
7
+ 1. Create tasks with `required_capabilities` and optional `dependency_ids`.
8
+ 2. An agent calls `task_claim` with its registered `agent_id`.
9
+ 3. The hub validates that the task is pending, dependencies are done, the
10
+ assignment matches, and the agent has every required capability.
11
+ 4. The claim changes the task to `in_progress` in an immediate SQLite
12
+ transaction. A competing claim cannot take the same task.
13
+ 5. Update `progress` and `blocker` with `task_update`.
14
+ 6. Mark the task `done`, or return it to the queue with `task_release`.
15
+
16
+ ## Tools
17
+
18
+ - `task_create`: accepts `required_capabilities` and `dependency_ids`.
19
+ - `task_add_dependency`: adds a prerequisite to an existing task.
20
+ - `task_claim`: atomically assigns available work to one agent.
21
+ - `task_update`: updates status, progress, blocker, notes, and context.
22
+ - `task_release`: releases work only when called by the claiming agent.
23
+ - `task_list`: filters by claiming agent and blocker state.
24
+
25
+ Task dependencies prevent premature work, and cyclic dependency graphs are
26
+ rejected. Capabilities describe functional requirements such as `code`,
27
+ `browser`, or `review`; they are not tied to a specific provider or model.
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "waymark-hub",
3
+ "version": "1.0.0",
4
+ "description": "Shared context and coordination MCP hub for AI agents",
5
+ "main": "dist/server.js",
6
+ "bin": {
7
+ "waymark-hub": "dist/cli/waymark.js",
8
+ "waymark-benchmark": "dist/cli/benchmark.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "dashboard",
13
+ "scripts/hooks",
14
+ "README.md",
15
+ "docs/BENCHMARKING.md",
16
+ "docs/AGENT_IDENTITY.md",
17
+ "docs/CONTEXT.md",
18
+ "docs/MEMORY_LIFECYCLE.md",
19
+ "docs/TASK_COORDINATION.md"
20
+ ],
21
+ "engines": {
22
+ "node": ">=22"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/SerjMihashin/waymark.git"
27
+ },
28
+ "homepage": "https://github.com/SerjMihashin/waymark#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/SerjMihashin/waymark/issues"
31
+ },
32
+ "scripts": {
33
+ "build": "tsc && node -e \"const fs=require('fs');const path=require('path');fs.mkdirSync('dist/db/migrations',{recursive:true});fs.readdirSync('src/db/migrations').forEach(f=>fs.copyFileSync('src/db/migrations/'+f,'dist/db/migrations/'+f));console.log('Migrations copied.')\"",
34
+ "test": "npm run build && node --test --test-concurrency=1 tests/*.test.js",
35
+ "dev": "tsx src/server.ts",
36
+ "dev:http": "tsx src/server.ts --http",
37
+ "start": "node dist/server.js",
38
+ "start:http": "node dist/server.js --http",
39
+ "benchmark": "node dist/cli/benchmark.js",
40
+ "dashboard": "node dashboard/server.mjs",
41
+ "backup:db": "tsx scripts/backup-db.ts",
42
+ "import:memory": "tsx scripts/import-existing-memory.ts"
43
+ },
44
+ "keywords": [
45
+ "mcp",
46
+ "mcp-server",
47
+ "ai-agents",
48
+ "agent-memory",
49
+ "handoff",
50
+ "shared-context",
51
+ "claude",
52
+ "codex",
53
+ "sqlite"
54
+ ],
55
+ "author": "Serj",
56
+ "license": "MIT",
57
+ "dependencies": {
58
+ "@modelcontextprotocol/sdk": "^1.29.0",
59
+ "better-sqlite3": "^12.10.0",
60
+ "express": "^5.2.1",
61
+ "zod": "^4.4.3"
62
+ },
63
+ "devDependencies": {
64
+ "@types/better-sqlite3": "^7.6.13",
65
+ "@types/express": "^5.0.6",
66
+ "@types/node": "^25.8.0",
67
+ "tsx": "^4.22.0",
68
+ "typescript": "^6.0.3"
69
+ }
70
+ }
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ // Claude Code SessionStart hook: injects a compact workspace resume from the hub
3
+ // into the new session's context, so the agent starts already knowing what other
4
+ // agents did — without spending a single tool call on it.
5
+ //
6
+ // Wiring (user or project settings.json):
7
+ // "hooks": {
8
+ // "SessionStart": [
9
+ // { "hooks": [ { "type": "command",
10
+ // "command": "node D:\\Projects\\ClaudePlus\\scripts\\hooks\\session-start-resume.cjs" } ] }
11
+ // ]
12
+ // }
13
+ //
14
+ // Prints nothing (exit 0) when the current directory is not a hub project, so it
15
+ // is safe to enable globally.
16
+
17
+ const path = require('path');
18
+
19
+ function readStdin() {
20
+ return new Promise((resolve) => {
21
+ let data = '';
22
+ process.stdin.setEncoding('utf8');
23
+ process.stdin.on('data', (chunk) => { data += chunk; });
24
+ process.stdin.on('end', () => resolve(data));
25
+ setTimeout(() => resolve(data), 2000).unref();
26
+ });
27
+ }
28
+
29
+ function projectIdFromPath(dir) {
30
+ return path.resolve(dir).replace(/[^A-Za-z0-9]/g, '-');
31
+ }
32
+
33
+ async function main() {
34
+ let input = {};
35
+ try {
36
+ input = JSON.parse(await readStdin() || '{}');
37
+ } catch {
38
+ // no/invalid stdin — fall back to cwd
39
+ }
40
+ const cwd = input.cwd || process.cwd();
41
+ const projectId = projectIdFromPath(cwd);
42
+
43
+ // dist/ is CommonJS; db path is anchored to the hub install dir by db/client.
44
+ const { buildContextPacket } = require(path.join(__dirname, '..', '..', 'dist', 'context', 'builder.js'));
45
+
46
+ let packet;
47
+ try {
48
+ packet = buildContextPacket({ projectId, maxTokens: 1200 });
49
+ } catch {
50
+ process.exit(0); // hub db unavailable — stay silent, never break session start
51
+ }
52
+ if (!packet) process.exit(0); // not a hub project
53
+
54
+ const context = [
55
+ 'Shared agent-hub resume for this project (from the hub DB; other agents may have worked here).',
56
+ 'Read memory bodies on demand via memory_read(id). End significant work with session_log',
57
+ '(outcome + next_steps) so the next agent resumes without retelling.',
58
+ '',
59
+ JSON.stringify(packet),
60
+ ].join('\n');
61
+
62
+ process.stdout.write(JSON.stringify({
63
+ hookSpecificOutput: {
64
+ hookEventName: 'SessionStart',
65
+ additionalContext: context,
66
+ },
67
+ }));
68
+ }
69
+
70
+ main();