@rubytech/create-maxy-code 0.1.164 → 0.1.166

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 (47) hide show
  1. package/dist/index.js +17 -9
  2. package/package.json +1 -1
  3. package/payload/platform/neo4j/schema.cypher +3 -5
  4. package/payload/platform/plugins/email/PLUGIN.md +2 -2
  5. package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts +0 -29
  6. package/payload/platform/plugins/email/mcp/dist/lib/credentials.d.ts.map +1 -1
  7. package/payload/platform/plugins/email/mcp/dist/lib/credentials.js +7 -115
  8. package/payload/platform/plugins/email/mcp/dist/lib/credentials.js.map +1 -1
  9. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +7 -44
  10. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
  11. package/payload/platform/plugins/email/mcp/dist/lib/imap.js +24 -177
  12. package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
  13. package/payload/platform/plugins/email/mcp/dist/tools/email-read.d.ts.map +1 -1
  14. package/payload/platform/plugins/email/mcp/dist/tools/email-read.js +4 -1
  15. package/payload/platform/plugins/email/mcp/dist/tools/email-read.js.map +1 -1
  16. package/payload/platform/plugins/email/mcp/dist/tools/email-search.d.ts.map +1 -1
  17. package/payload/platform/plugins/email/mcp/dist/tools/email-search.js +4 -1
  18. package/payload/platform/plugins/email/mcp/dist/tools/email-search.js.map +1 -1
  19. package/payload/platform/plugins/email/skills/email-composition/SKILL.md +1 -1
  20. package/payload/platform/plugins/memory/references/schema-base.md +1 -1
  21. package/payload/platform/plugins/memory/references/schema-estate-agent.md +1 -1
  22. package/payload/platform/scripts/lib/read-brand-json.sh +1 -1
  23. package/payload/platform/scripts/lib/resolve-account-dir.sh +1 -1
  24. package/payload/platform/scripts/seed-neo4j.sh +29 -421
  25. package/payload/platform/scripts/setup-account.sh +370 -0
  26. package/payload/platform/services/claude-session-manager/dist/config.js +2 -2
  27. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  28. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts +9 -1
  29. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
  30. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +74 -38
  31. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
  32. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  33. package/payload/platform/services/claude-session-manager/dist/http-server.js +16 -0
  34. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  35. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +16 -1
  36. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  37. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +21 -7
  38. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  39. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +7 -0
  40. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
  41. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +10 -0
  42. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
  43. package/payload/platform/services/claude-session-manager/dist/systemd-scope.d.ts +52 -10
  44. package/payload/platform/services/claude-session-manager/dist/systemd-scope.d.ts.map +1 -1
  45. package/payload/platform/services/claude-session-manager/dist/systemd-scope.js +73 -13
  46. package/payload/platform/services/claude-session-manager/dist/systemd-scope.js.map +1 -1
  47. package/payload/platform/templates/agents/admin/IDENTITY.md +1 -1
@@ -0,0 +1,370 @@
1
+ #!/usr/bin/env bash
2
+ # ============================================================
3
+ # setup-account.sh — Phase 0 account setup
4
+ # Creates the account directory from templates, writes the
5
+ # Claude Code project settings file (hooks only — no permission
6
+ # allowlist; native agent frontmatter is the permission surface),
7
+ # installs specialist plugin templates, seeds account.json
8
+ # defaults, and resolves the owner userId. Neo4j seeding lives
9
+ # in `seed-neo4j.sh`; this script does no Neo4j work.
10
+ # ============================================================
11
+
12
+ set -euo pipefail
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
16
+ TEMPLATES_DIR="$PROJECT_DIR/templates"
17
+ # Accounts live at {installDir}/data/accounts/ — outside the platform/ wipe zone.
18
+ INSTALL_DIR="$(dirname "$PROJECT_DIR")"
19
+ ACCOUNTS_DIR="$INSTALL_DIR/data/accounts"
20
+
21
+ # ------------------------------------------------------------------
22
+ # 1. Resolve / create account directory
23
+ # ------------------------------------------------------------------
24
+ # Resolve existing account by identity (users.json[0].userId) or mint a new one on fresh install.
25
+ # Orphan siblings under data/accounts/ — non-matching dirs left behind by the userId
26
+ # regeneration — are swept to data/accounts/.trash/<uuid>-<ISO8601-ts>/. Multi-candidate with
27
+ # no identity match aborts loud; .trash/ is operator-emptied, never auto-cleaned.
28
+ # shellcheck source=lib/resolve-account-dir.sh
29
+ . "$SCRIPT_DIR/lib/resolve-account-dir.sh"
30
+ # shellcheck source=lib/read-brand-json.sh
31
+ . "$SCRIPT_DIR/lib/read-brand-json.sh"
32
+ # Resolve brand-aware persistent users.json path before the resolver runs.
33
+ _RESOLVER_CONFIG_DIR_NAME=".maxy"
34
+ read_brand_json_key "$PROJECT_DIR/config/brand.json" "configDir"
35
+ [ -n "$BRAND_JSON_VALUE" ] && _RESOLVER_CONFIG_DIR_NAME="$BRAND_JSON_VALUE"
36
+ USERS_FILE="$HOME/$_RESOLVER_CONFIG_DIR_NAME/users.json" resolve_and_sweep_account_dir
37
+
38
+ mkdir -p "$ACCOUNT_DIR/agents/admin" "$ACCOUNT_DIR/agents/public" "$ACCOUNT_DIR/.claude" "$ACCOUNT_DIR/specialists/.claude-plugin" "$ACCOUNT_DIR/specialists/agents"
39
+
40
+ # Claude Code discovers project-level .claude/ (agents, settings) relative to the
41
+ # nearest .git root. Without a .git in the account directory, Claude Code traverses
42
+ # up to ~/maxy/.git and misses everything in accountDir/.claude/. Initialise a git
43
+ # repo so the account directory IS the project root for Claude Code.
44
+ [ -d "$ACCOUNT_DIR/.git" ] || git init -q "$ACCOUNT_DIR"
45
+
46
+ # ------------------------------------------------------------------
47
+ # 2. Write project-level .claude/settings.json (HOOKS ONLY)
48
+ # ------------------------------------------------------------------
49
+ # Task 453: no `permissions.allow` block. The previous short-prefix
50
+ # allowlist (mcp__memory__*, mcp__contacts__*, …) never matched the
51
+ # plugin-manifest long-prefix tool names Claude Code actually emits
52
+ # (mcp__plugin_memory_memory__…), so every Task-subagent plugin call
53
+ # was denied at use-time. Permission enforcement comes from each agent's
54
+ # frontmatter `tools:` list (native CC permission surface) and from the
55
+ # PreToolUse approval hooks below for review-gated tools.
56
+ #
57
+ # Hook commands use $PLATFORM_ROOT (set by claude-agent.ts at spawn time)
58
+ # to locate scripts relative to the platform installation, not the account dir.
59
+ ACCOUNT_SETTINGS="$ACCOUNT_DIR/.claude/settings.json"
60
+ HOOKS_PATH="\$PLATFORM_ROOT/plugins/admin/hooks"
61
+ cat > "$ACCOUNT_SETTINGS" << SETTINGS_EOF
62
+ {
63
+ "hooks": {
64
+ "PreToolUse": [
65
+ {
66
+ "matcher": "Write",
67
+ "hooks": [
68
+ { "type": "command", "command": "bash $HOOKS_PATH/pre-tool-use.sh admin" },
69
+ { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" }
70
+ ]
71
+ },
72
+ {
73
+ "matcher": "Edit",
74
+ "hooks": [
75
+ { "type": "command", "command": "bash $HOOKS_PATH/pre-tool-use.sh admin" },
76
+ { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" }
77
+ ]
78
+ },
79
+ {
80
+ "matcher": "NotebookEdit",
81
+ "hooks": [
82
+ { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" }
83
+ ]
84
+ },
85
+ {
86
+ "matcher": "Bash",
87
+ "hooks": [
88
+ { "type": "command", "command": "bash $HOOKS_PATH/pre-tool-use.sh admin" },
89
+ { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" }
90
+ ]
91
+ },
92
+ {
93
+ "matcher": "mcp__plugin_memory_memory__memory-write",
94
+ "hooks": [
95
+ { "type": "command", "command": "bash $HOOKS_PATH/pre-tool-use.sh admin" }
96
+ ]
97
+ },
98
+ {
99
+ "matcher": "mcp__plugin_memory_memory__memory-update",
100
+ "hooks": [
101
+ { "type": "command", "command": "bash $HOOKS_PATH/pre-tool-use.sh admin" }
102
+ ]
103
+ },
104
+ {
105
+ "hooks": [
106
+ { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" }
107
+ ]
108
+ },
109
+ {
110
+ "matcher": "mcp__plugin_playwright_playwright__browser_navigate",
111
+ "hooks": [
112
+ { "type": "command", "command": "bash $HOOKS_PATH/playwright-file-guard.sh" }
113
+ ]
114
+ },
115
+ {
116
+ "matcher": "WebFetch",
117
+ "hooks": [
118
+ { "type": "command", "command": "node $HOOKS_PATH/webfetch-preflight.mjs" }
119
+ ]
120
+ },
121
+ {
122
+ "matcher": "AskUserQuestion",
123
+ "hooks": [
124
+ { "type": "command", "command": "bash $HOOKS_PATH/askuserquestion-investigate-gate.sh" }
125
+ ]
126
+ }
127
+ ],
128
+ "PostToolUse": [
129
+ {
130
+ "matcher": "mcp__.*__.*-(export|import)-parse$",
131
+ "hooks": [
132
+ { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" }
133
+ ]
134
+ }
135
+ ],
136
+ "UserPromptSubmit": [
137
+ {
138
+ "hooks": [
139
+ { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" }
140
+ ]
141
+ }
142
+ ],
143
+ "Stop": [
144
+ {
145
+ "hooks": [
146
+ { "type": "command", "command": "bash $HOOKS_PATH/session-end-retrospective.sh" }
147
+ ]
148
+ }
149
+ ]
150
+ }
151
+ }
152
+ SETTINGS_EOF
153
+
154
+ # ------------------------------------------------------------------
155
+ # 3. Install agent identities and specialist plugin templates
156
+ # ------------------------------------------------------------------
157
+ # Always overwrite IDENTITY.md — Rubytech-controlled, pure behaviour.
158
+ cp "$TEMPLATES_DIR/agents/admin/IDENTITY.md" "$ACCOUNT_DIR/agents/admin/IDENTITY.md"
159
+ cp "$TEMPLATES_DIR/agents/public/IDENTITY.md" "$ACCOUNT_DIR/agents/public/IDENTITY.md"
160
+ echo " agents/public/IDENTITY.md installed"
161
+
162
+ # Always overwrite specialist plugin — Rubytech-controlled, not user-editable.
163
+ # Specialists are a Claude Code plugin loaded via --plugin-dir. The plugin lives at
164
+ # accountDir/specialists/ with .claude-plugin/plugin.json and agents/*.md.
165
+ # The admin agent dispatches them as specialists:{name} via the Agent tool.
166
+ cp "$TEMPLATES_DIR/specialists/.claude-plugin/plugin.json" "$ACCOUNT_DIR/specialists/.claude-plugin/plugin.json"
167
+
168
+ # Remove orphaned core specialist files before copying fresh templates.
169
+ # Core specialists (no '--' in filename) are Rubytech-controlled and fully replaced
170
+ # on every seed. Premium plugin agents (filename contains '--') are preserved —
171
+ # they are managed by the admin agent when plugins are activated/deactivated.
172
+ for _existing in "$ACCOUNT_DIR/specialists/agents/"*.md; do
173
+ [ -f "$_existing" ] || continue
174
+ case "$(basename "$_existing")" in
175
+ *--*) continue ;; # Premium plugin agent — preserve
176
+ esac
177
+ rm -f "$_existing"
178
+ done
179
+
180
+ for specialist in "$TEMPLATES_DIR/specialists/agents/"*.md; do
181
+ [ -f "$specialist" ] && cp "$specialist" "$ACCOUNT_DIR/specialists/agents/$(basename "$specialist")"
182
+ done
183
+
184
+ # Clean up stale .claude/agents/*.md from previous seed format.
185
+ # The old format placed specialists here as slash-command agents — that never worked
186
+ # for programmatic dispatch. Safe to remove; .claude/ dir stays for settings.json.
187
+ rm -f "$ACCOUNT_DIR/.claude/agents/"*.md 2>/dev/null || true
188
+
189
+ # SOUL.md — user-controlled personalisation. Only create if missing. Never overwrite.
190
+ [ -f "$ACCOUNT_DIR/agents/admin/SOUL.md" ] || cp "$TEMPLATES_DIR/agents/admin/SOUL.md" "$ACCOUNT_DIR/agents/admin/SOUL.md"
191
+
192
+ # Public agent SOUL.md + config.json — create if missing, never overwrite.
193
+ # IDENTITY.md is handled in the Rubytech-controlled block above.
194
+ [ -f "$ACCOUNT_DIR/agents/public/SOUL.md" ] || cp "$TEMPLATES_DIR/agents/public/SOUL.md" "$ACCOUNT_DIR/agents/public/SOUL.md"
195
+ [ -f "$ACCOUNT_DIR/agents/public/config.json" ] || cp "$TEMPLATES_DIR/agents/public/config.json" "$ACCOUNT_DIR/agents/public/config.json"
196
+
197
+ # AGENTS.md — specialist registry. Pre-populated from templates, maintained by admin agent at runtime.
198
+ # Always overwrite on re-seed (Rubytech-controlled initial state, like IDENTITY.md).
199
+ # Dispatch format: specialists:{name} via the Agent tool.
200
+ printf '# Installed Roles\n\nDispatch via the Agent tool with `subagent_type: "specialists:{name}"`.\n\n' > "$ACCOUNT_DIR/agents/admin/AGENTS.md"
201
+ for specialist in "$ACCOUNT_DIR/specialists/agents/"*.md; do
202
+ [ -f "$specialist" ] || continue
203
+ # Extract name and description from YAML frontmatter
204
+ _name=$(sed -n 's/^name: *//p' "$specialist" | head -1)
205
+ _desc=$(sed -n 's/^description: *"*//p' "$specialist" | sed 's/"$//' | head -1)
206
+ [ -z "$_name" ] && continue
207
+ # Skip Phase 1 stubs — not yet functional
208
+ echo "$_desc" | grep -qi "Phase 1" && continue
209
+ printf -- '- **specialists:%s**: %s\n' "$_name" "$_desc" >> "$ACCOUNT_DIR/agents/admin/AGENTS.md"
210
+ done
211
+
212
+ # ------------------------------------------------------------------
213
+ # 4. Create / backfill account.json
214
+ # ------------------------------------------------------------------
215
+ # Create account.json only if it doesn't exist (business config is in the graph).
216
+ # Reads defaults from the template so there is a single source of truth.
217
+ if [ ! -f "$ACCOUNT_DIR/account.json" ]; then
218
+ TEMPLATE="$TEMPLATES_DIR/account.json"
219
+ if [ -f "$TEMPLATE" ]; then
220
+ sed "s/\"accountId\": *\"[^\"]*\"/\"accountId\":\"$ACCOUNT_ID\"/" "$TEMPLATE" \
221
+ | sed "s/\"tier\": *\"[^\"]*\"/\"tier\":\"solo\"/" \
222
+ > "$ACCOUNT_DIR/account.json"
223
+ else
224
+ echo "ERROR: account.json template not found at $TEMPLATE" >&2
225
+ exit 1
226
+ fi
227
+ fi
228
+
229
+ # Backfill defaultAgent in account.json if missing (existing accounts earlier).
230
+ # Uses the first non-admin agent directory that has a config.json.
231
+ if [ -f "$ACCOUNT_DIR/account.json" ] && ! grep -q '"defaultAgent"' "$ACCOUNT_DIR/account.json"; then
232
+ _DEFAULT_SLUG=""
233
+ for _AGENT_DIR in "$ACCOUNT_DIR/agents"/*/; do
234
+ _AGENT_NAME="$(basename "$_AGENT_DIR")"
235
+ [ "$_AGENT_NAME" = "admin" ] && continue
236
+ [ -f "$_AGENT_DIR/config.json" ] && { _DEFAULT_SLUG="$_AGENT_NAME"; break; }
237
+ done
238
+ if [ -n "$_DEFAULT_SLUG" ]; then
239
+ # Insert defaultAgent before the closing brace
240
+ sed -i'' "s/}$/,\"defaultAgent\":\"$_DEFAULT_SLUG\"}/" "$ACCOUNT_DIR/account.json"
241
+ echo " Backfilled defaultAgent=$_DEFAULT_SLUG in account.json"
242
+ fi
243
+ fi
244
+
245
+ # ------------------------------------------------------------------
246
+ # 5. Seed enabledPlugins from brand.json plugins.defaultEnabled
247
+ # ------------------------------------------------------------------
248
+ # Fresh accounts: replaces the template's empty [] with defaultEnabled.
249
+ # Existing accounts: additive merge — adds missing defaultEnabled entries,
250
+ # never removes plugins the user enabled manually.
251
+ # Dependency validation: skips any defaultEnabled plugin whose PLUGIN.md
252
+ # `requires:` dependencies are not satisfied by core or defaultEnabled.
253
+ BRAND_JSON="$PROJECT_DIR/config/brand.json"
254
+ if [ -f "$BRAND_JSON" ] && [ -f "$ACCOUNT_DIR/account.json" ]; then
255
+ python3 -c "
256
+ import json, os, sys
257
+
258
+ brand_path = '$BRAND_JSON'
259
+ account_path = '$ACCOUNT_DIR/account.json'
260
+ plugins_dir = '$PROJECT_DIR/plugins'
261
+
262
+ with open(brand_path) as f:
263
+ brand = json.load(f)
264
+
265
+ plugins_cfg = brand.get('plugins', {})
266
+ default_enabled = plugins_cfg.get('defaultEnabled', [])
267
+ core = set(plugins_cfg.get('core', []))
268
+
269
+ if not default_enabled:
270
+ print(' [setup] no defaultEnabled plugins in brand.json — skipping')
271
+ sys.exit(0)
272
+
273
+ # Dependency validation: check each plugin's PLUGIN.md requires field.
274
+ # A dependency is satisfied if it appears in core or in defaultEnabled.
275
+ satisfied = core | set(default_enabled)
276
+ validated = []
277
+ for plugin in default_enabled:
278
+ plugin_md = os.path.join(plugins_dir, plugin, 'PLUGIN.md')
279
+ requires = []
280
+ if os.path.isfile(plugin_md):
281
+ in_frontmatter = False
282
+ in_requires = False
283
+ with open(plugin_md) as f:
284
+ for line in f:
285
+ stripped = line.rstrip()
286
+ if stripped == '---':
287
+ if in_frontmatter:
288
+ break
289
+ in_frontmatter = True
290
+ continue
291
+ if not in_frontmatter:
292
+ continue
293
+ if stripped.startswith('requires:'):
294
+ # Handle inline list: requires: [a, b]
295
+ inline = stripped.split(':', 1)[1].strip()
296
+ if inline.startswith('['):
297
+ requires = [x.strip().strip('\"').strip(\"'\") for x in inline.strip('[]').split(',') if x.strip()]
298
+ in_requires = False
299
+ else:
300
+ in_requires = True
301
+ continue
302
+ if in_requires:
303
+ if stripped.startswith(' - '):
304
+ requires.append(stripped.lstrip(' -').strip())
305
+ else:
306
+ in_requires = False
307
+ unmet = [r for r in requires if r not in satisfied]
308
+ if unmet:
309
+ print(f' [setup] WARNING: skipping defaultEnabled plugin \"{plugin}\" — unmet requires: {unmet}')
310
+ else:
311
+ validated.append(plugin)
312
+
313
+ with open(account_path) as f:
314
+ account = json.load(f)
315
+
316
+ existing = account.get('enabledPlugins', [])
317
+ existing_set = set(existing)
318
+ added = [p for p in validated if p not in existing_set]
319
+ account['enabledPlugins'] = existing + added
320
+
321
+ with open(account_path, 'w') as f:
322
+ json.dump(account, f, indent=2)
323
+ f.write('\n')
324
+
325
+ if not existing:
326
+ print(f' [setup] seeded enabledPlugins: {validated}')
327
+ elif added:
328
+ print(f' [setup] merged into enabledPlugins: +{added} (existing: {existing})')
329
+ else:
330
+ print(f' [setup] enabledPlugins already contains all defaultEnabled entries')
331
+ "
332
+ fi
333
+
334
+ # ------------------------------------------------------------------
335
+ # 6. Stamp first admin userId into account.json (if users.json present)
336
+ # ------------------------------------------------------------------
337
+ # users.json is created by the set-pin POST during onboarding. This
338
+ # script reads it to stamp the owner into account.json admins[]; the
339
+ # matching :AdminUser graph node is created by seed-neo4j.sh.
340
+ CONFIG_DIR="$PROJECT_DIR/config"
341
+ _CONFIG_DIR_NAME=".maxy"
342
+ read_brand_json_key "$CONFIG_DIR/brand.json" "configDir"
343
+ [ -n "$BRAND_JSON_VALUE" ] && _CONFIG_DIR_NAME="$BRAND_JSON_VALUE"
344
+ USERS_FILE="$HOME/$_CONFIG_DIR_NAME/users.json"
345
+ mkdir -p "$HOME/$_CONFIG_DIR_NAME"
346
+
347
+ if [ -f "$USERS_FILE" ]; then
348
+ USER_ID=$(python3 -c "import json; print(json.load(open('$USERS_FILE'))[0]['userId'])" 2>/dev/null || true)
349
+ [ -n "$USER_ID" ] && echo " Existing users.json found, userId=$USER_ID"
350
+
351
+ # Ensure account.json admins[] contains the owner. Idempotent.
352
+ if [ -n "$USER_ID" ] && [ -f "$ACCOUNT_DIR/account.json" ]; then
353
+ python3 -c "
354
+ import json
355
+ with open('$ACCOUNT_DIR/account.json', 'r') as f:
356
+ config = json.load(f)
357
+ config.setdefault('admins', [])
358
+ if not any(a.get('userId') == '$USER_ID' for a in config['admins']):
359
+ config['admins'].append({'userId': '$USER_ID', 'role': 'owner'})
360
+ with open('$ACCOUNT_DIR/account.json', 'w') as f:
361
+ json.dump(config, f, indent=2)
362
+ f.write('\n')
363
+ print(' Stamped userId=$USER_ID as owner in account.json admins')
364
+ "
365
+ fi
366
+ else
367
+ echo " No users.json found — skipping owner stamp (set-pin POST creates it)"
368
+ fi
369
+
370
+ echo " Account $ACCOUNT_ID at $ACCOUNT_DIR"
@@ -177,12 +177,12 @@ export function loadConfig(env = process.env) {
177
177
  const accountDir = resolveAccountDir(platformRoot);
178
178
  if (!accountDir) {
179
179
  throw new Error(`[claude-session-manager] account-dir-unresolved: no <installDir>/data/accounts/<uuid>/account.json under ${dirname(platformRoot)}/data/accounts. ` +
180
- 'The installer (seed-neo4j.sh / writeInstallDefaults) must run before manager start.');
180
+ 'The installer (setup-account.sh / writeInstallDefaults) must run before manager start.');
181
181
  }
182
182
  // Claude Code walks `.claude/settings.json` from cwd to .git root. Defaulting
183
183
  // spawnCwd to process.cwd() — i.e. the manager service directory — strands
184
184
  // the account-scoped settings.json (and its Stop hook) outside that walk.
185
- // Default to accountDir so seed-neo4j.sh's `<accountDir>/.claude/settings.json`
185
+ // Default to accountDir so setup-account.sh's `<accountDir>/.claude/settings.json`
186
186
  // is on the discovery path. Env-var override is preserved for tests.
187
187
  const spawnCwd = env.CLAUDE_SESSION_MANAGER_SPAWN_CWD ?? accountDir;
188
188
  const lan = resolveLanIPv4();
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { Logger, Role, Channel } from './types.js';
2
- import { type SystemctlRunner } from './systemd-scope.js';
2
+ import { type ProcessSignals, type SystemctlRunner } from './systemd-scope.js';
3
3
  export type RowState = 'live' | 'ended' | 'archived';
4
4
  /** Task 250 — `detached` is reached only via the boot-seed reconciler.
5
5
  * When the manager restarts and finds a surviving `claude-session-*.scope`
@@ -130,5 +130,13 @@ export declare function createFsWatcher(opts: {
130
130
  * user manager (macOS dev hosts), the default runner returns non-zero
131
131
  * exit codes and the boot-seed degrades to "0 survivors" gracefully. */
132
132
  runSystemctl?: SystemctlRunner;
133
+ /** Task 451 — injectable kill/alive-check primitives for the boot-seed
134
+ * orphan-stop post-flight verify. Default delegates to `process.kill`.
135
+ * Tests inject a recording stub to assert SIGTERM/SIGKILL escalation. */
136
+ processSignals?: ProcessSignals;
137
+ /** Task 451 — grace period between SIGTERM and SIGKILL during boot-seed
138
+ * orphan-stop escalation. Default 5_000 ms (matches the scope's
139
+ * `TimeoutStopSec`). Tests pass small values to keep run time bounded. */
140
+ killGraceMs?: number;
133
141
  }): FsWatcher;
134
142
  //# sourceMappingURL=fs-watcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fs-watcher.d.ts","sourceRoot":"","sources":["../src/fs-watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fs-watcher.d.ts","sourceRoot":"","sources":["../src/fs-watcher.ts"],"names":[],"mappings":"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"}
@@ -36,7 +36,7 @@
36
36
  import { existsSync, mkdirSync, openSync, closeSync, readSync, readFileSync, readdirSync, statSync, watch } from 'node:fs';
37
37
  import { dirname, join } from 'node:path';
38
38
  import { readSidecar } from './session-sidecar.js';
39
- import { defaultSystemctlRunner, getScopeMainPid, listSurvivingScopes, stopScopeUnit, } from './systemd-scope.js';
39
+ import { defaultProcessSignals, defaultSystemctlRunner, getScopeMainPid, listSurvivingScopes, stopScopeUnit, } from './systemd-scope.js';
40
40
  const DEBOUNCE_MS = 200;
41
41
  // First `agent-setting` record sits near the JSONL head (Claude Code writes
42
42
  // it after env+meta, before the first user turn). 32 KiB is enough to cover
@@ -121,6 +121,8 @@ function parsePidFile(path) {
121
121
  export function createFsWatcher(opts) {
122
122
  const { sessionsDir, projectsDir, logger } = opts;
123
123
  const runSystemctl = opts.runSystemctl ?? defaultSystemctlRunner;
124
+ const processSignals = opts.processSignals ?? defaultProcessSignals;
125
+ const killGraceMs = opts.killGraceMs ?? 5_000;
124
126
  // Transient row cache, keyed on sessionId. Built by bootSeed and kept
125
127
  // in sync by fs event reconciliation. Not the source of truth — disk is.
126
128
  const rowsBySessionId = new Map();
@@ -219,6 +221,10 @@ export function createFsWatcher(opts) {
219
221
  effectivePermissionMode: sidecar.effectivePermissionMode,
220
222
  hidden: sidecar.hidden,
221
223
  sidecarSpecialist: sidecar.specialist,
224
+ // Task 451 — carry the scope token from the sidecar onto the row so
225
+ // boot-seed's reconcileSurvivingScopes can find the row by token,
226
+ // even when the unit token does not equal sessionId (fresh spawns).
227
+ scopeUnitToken: sidecar.scopeUnitToken ?? row.scopeUnitToken,
222
228
  };
223
229
  }
224
230
  /** Find the pid file (if any) whose content names `sessionId`. Used at
@@ -631,52 +637,82 @@ export function createFsWatcher(opts) {
631
637
  let orphaned = 0;
632
638
  let orphanedStopped = 0;
633
639
  for (const scope of scopes) {
634
- const decision = reattachOrOrphan(scope);
635
- if (decision === 'reattached') {
640
+ const decision = classifyScope(scope);
641
+ if (decision.match === 'reattach') {
642
+ reattach(scope, decision.row);
636
643
  reattached += 1;
644
+ continue;
637
645
  }
638
- else {
639
- orphaned += 1;
640
- try {
641
- const stop = stopScopeUnit(runSystemctl, scope.unitToken);
642
- if (stop.outcome === 'ok' || stop.outcome === 'already-gone') {
643
- orphanedStopped += 1;
644
- }
645
- logger(`[boot-seed] orphan-stop unit=${scope.unitName} outcome=${stop.outcome} exit-code=${stop.exitCode}`);
646
- }
647
- catch (err) {
648
- const msg = err instanceof Error ? err.message : String(err);
649
- logger(`[boot-seed] orphan-stop-threw unit=${scope.unitName} err=${JSON.stringify(msg)}`);
650
- }
651
- }
646
+ orphaned += 1;
647
+ // Task 451 — orphan-stop is fire-and-forget so a single slow scope
648
+ // with a stuck pid does not block the rest of the boot-seed loop.
649
+ // The `[boot-seed] orphan-stop` line lands when the promise resolves;
650
+ // `orphaned-stopped` counts entries whose stop request was issued,
651
+ // not entries whose verify completed (the verify path is hundreds of
652
+ // ms when escalation runs and we don't want to serialise boot on it).
653
+ const pidForStop = decision.match === 'orphan-pid-dead'
654
+ ? null
655
+ : getScopeMainPid(runSystemctl, scope.unitToken);
656
+ orphanedStopped += 1;
657
+ void stopScopeUnit(runSystemctl, scope.unitToken, {
658
+ pid: pidForStop,
659
+ killGraceMs,
660
+ signals: processSignals,
661
+ })
662
+ .then((stop) => {
663
+ logger(`[boot-seed] orphan-stop unit=${scope.unitName} outcome=${stop.outcome} exit-code=${stop.exitCode}`);
664
+ })
665
+ .catch((err) => {
666
+ const msg = err instanceof Error ? err.message : String(err);
667
+ logger(`[boot-seed] orphan-stop-threw unit=${scope.unitName} err=${JSON.stringify(msg)}`);
668
+ });
652
669
  }
653
670
  logger(`[boot-seed] survived-scopes=${scopes.length} reattached=${reattached} orphaned=${orphaned} orphaned-stopped=${orphanedStopped}`);
654
671
  }
655
- function reattachOrOrphan(scope) {
656
- const mainPid = getScopeMainPid(runSystemctl, scope.unitToken);
657
- if (mainPid === null)
658
- return 'orphan';
659
- // Look up PID file at `<sessionsDir>/<mainPid>.json`. Claude Code's
660
- // own session-init writes this file with `pid` + `sessionId` fields.
661
- const pidPath = join(sessionsDir, `${mainPid}.json`);
662
- const parsed = parsePidFile(pidPath);
663
- if (!parsed)
664
- return 'orphan';
665
- if (parsed.pid !== mainPid)
666
- return 'orphan';
667
- const row = rowsBySessionId.get(parsed.sessionId);
668
- if (!row)
669
- return 'orphan';
670
- // Found a matching row — mark it detached and stamp the scope token.
671
- // Use unindexRow/indexRow to keep the reverse indexes consistent (we
672
- // are not changing the sessionId or pid keys, only mutable fields, so
673
- // re-indexing is defensive).
672
+ function classifyScope(scope) {
673
+ // Resolve the row two ways:
674
+ // 1. The unit token matches a sessionId directly (resume spawns,
675
+ // where unitToken === claude's intrinsic sessionId).
676
+ // 2. The unit token matches a sidecar-recorded scopeUnitToken on
677
+ // some row (fresh spawns, where unitToken is a random UUID
678
+ // minted at spawn time).
679
+ // Both paths are tried because we cannot tell at this point which
680
+ // type of spawn produced the scope; iterating rows is fine because
681
+ // the inner loop runs once per surviving scope at boot.
682
+ let row = rowsBySessionId.get(scope.unitToken) ?? null;
683
+ if (!row) {
684
+ for (const r of rowsBySessionId.values()) {
685
+ if (r.scopeUnitToken === scope.unitToken) {
686
+ row = r;
687
+ break;
688
+ }
689
+ }
690
+ }
691
+ const sessionId = row?.sessionId ?? 'none';
692
+ if (!row) {
693
+ logger(`[boot-seed] scope-classify unit=${scope.unitName} sessionId=${sessionId} match=orphan reason=no-row-on-disk`);
694
+ return { match: 'orphan', reason: 'no-row-on-disk' };
695
+ }
696
+ // Task 451 — only reattach when the row's pid is still alive. Without
697
+ // this check we would mark a row `detached` for a process that has
698
+ // already exited, and the operator's End click would route to the
699
+ // row-scope branch and stop a unit whose pid is long dead.
700
+ if (row.pid === null || !processSignals.isAlive(row.pid)) {
701
+ logger(`[boot-seed] scope-classify unit=${scope.unitName} sessionId=${sessionId.slice(0, 8)} match=orphan-pid-dead reason=pid-already-dead`);
702
+ return { match: 'orphan-pid-dead', reason: 'pid-already-dead' };
703
+ }
704
+ logger(`[boot-seed] scope-classify unit=${scope.unitName} sessionId=${sessionId.slice(0, 8)} match=reattach reason=row-on-disk`);
705
+ return { match: 'reattach', row, reason: 'row-on-disk' };
706
+ }
707
+ function reattach(scope, row) {
708
+ // unindex/indexRow keeps the reverse indexes consistent (sessionId
709
+ // and pid keys are unchanged; the re-index is defensive against
710
+ // future field-change ordering).
674
711
  unindexRow(row);
675
712
  row.status = 'detached';
676
713
  row.scopeUnitToken = scope.unitToken;
677
714
  indexRow(row);
678
- logger(`[boot-seed] reattached sessionId=${parsed.sessionId} unit=${scope.unitName} pid=${mainPid}`);
679
- return 'reattached';
715
+ logger(`[boot-seed] reattached sessionId=${row.sessionId} unit=${scope.unitName} pid=${row.pid ?? 'unknown'}`);
680
716
  }
681
717
  function arm() {
682
718
  if (armed)