@rubytech/create-maxy-code 0.1.214 → 0.1.219

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 (89) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/mcp-eager/dist/index.d.ts +0 -55
  3. package/payload/platform/lib/mcp-eager/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/mcp-eager/dist/index.js +0 -76
  5. package/payload/platform/lib/mcp-eager/dist/index.js.map +1 -1
  6. package/payload/platform/lib/mcp-eager/src/index.ts +0 -101
  7. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  8. package/payload/platform/plugins/admin/PLUGIN.md +4 -1
  9. package/payload/platform/plugins/admin/hooks/__tests__/hook-emit-stale-lock-ttl.test.sh +102 -0
  10. package/payload/platform/plugins/admin/hooks/__tests__/post-tool-use-agent.test.sh +97 -1
  11. package/payload/platform/plugins/admin/hooks/__tests__/pre-tool-use-admin-tool-gate.test.sh +55 -74
  12. package/payload/platform/plugins/admin/hooks/lib/hook-emit.sh +58 -0
  13. package/payload/platform/plugins/admin/hooks/post-tool-use-agent.sh +100 -29
  14. package/payload/platform/plugins/admin/hooks/pre-tool-use.sh +0 -55
  15. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.d.ts +2 -0
  16. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.d.ts.map +1 -0
  17. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js +130 -0
  18. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js.map +1 -0
  19. package/payload/platform/plugins/admin/mcp/dist/index.js +63 -0
  20. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  21. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.d.ts +14 -0
  22. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.d.ts.map +1 -0
  23. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.js +50 -0
  24. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.js.map +1 -0
  25. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts +28 -0
  26. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts.map +1 -0
  27. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js +68 -0
  28. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js.map +1 -0
  29. package/payload/platform/plugins/admin/skills/capabilities-here/SKILL.md +31 -0
  30. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +39 -30
  31. package/payload/platform/plugins/browser/mcp/dist/index.js +19 -19
  32. package/payload/platform/plugins/browser/mcp/dist/index.js.map +1 -1
  33. package/payload/platform/plugins/docs/references/platform.md +28 -25
  34. package/payload/platform/plugins/docs/references/plugins-guide.md +2 -0
  35. package/payload/platform/plugins/email/mcp/dist/index.js +12 -12
  36. package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
  37. package/payload/platform/plugins/memory/mcp/dist/index.js +8 -8
  38. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  39. package/payload/platform/plugins/url-get/mcp/dist/index.js +2 -2
  40. package/payload/platform/plugins/url-get/mcp/dist/index.js.map +1 -1
  41. package/payload/platform/scripts/check-architecture-skill-no-drift.mjs +89 -42
  42. package/payload/platform/scripts/check-roles-doc-completeness.mjs +96 -0
  43. package/payload/platform/scripts/check-specialist-tool-surface.mjs +1 -1
  44. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  45. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  46. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  47. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +0 -14
  48. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  49. package/payload/platform/services/claude-session-manager/dist/http-server.js +54 -21
  50. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  51. package/payload/platform/services/claude-session-manager/dist/index.js +20 -9
  52. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  53. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.d.ts +21 -0
  54. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.d.ts.map +1 -1
  55. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.js +118 -1
  56. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.js.map +1 -1
  57. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +1 -1
  58. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +1 -1
  59. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +28 -17
  60. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  61. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +110 -60
  62. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  63. package/payload/platform/services/claude-session-manager/dist/rc-life.d.ts +4 -0
  64. package/payload/platform/services/claude-session-manager/dist/rc-life.d.ts.map +1 -0
  65. package/payload/platform/services/claude-session-manager/dist/rc-life.js +16 -0
  66. package/payload/platform/services/claude-session-manager/dist/rc-life.js.map +1 -0
  67. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.d.ts +80 -0
  68. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.d.ts.map +1 -0
  69. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.js +306 -0
  70. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.js.map +1 -0
  71. package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts +9 -0
  72. package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts.map +1 -1
  73. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js +6 -2
  74. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js.map +1 -1
  75. package/payload/platform/services/claude-session-manager/dist/systemd-scope.d.ts +12 -46
  76. package/payload/platform/services/claude-session-manager/dist/systemd-scope.d.ts.map +1 -1
  77. package/payload/platform/services/claude-session-manager/dist/systemd-scope.js +24 -73
  78. package/payload/platform/services/claude-session-manager/dist/systemd-scope.js.map +1 -1
  79. package/payload/platform/templates/agents/admin/IDENTITY.md +6 -4
  80. package/payload/platform/templates/specialists/agents/content-producer.md +1 -1
  81. package/payload/premium-plugins/writer-craft/mcp/dist/index.d.ts.map +1 -1
  82. package/payload/premium-plugins/writer-craft/mcp/dist/index.js +4 -5
  83. package/payload/premium-plugins/writer-craft/mcp/dist/index.js.map +1 -1
  84. package/payload/premium-plugins/writer-craft/mcp/src/index.ts +4 -5
  85. package/payload/premium-plugins/writer-craft/lib/mcp-eager/dist/index.d.ts +0 -116
  86. package/payload/premium-plugins/writer-craft/lib/mcp-eager/dist/index.d.ts.map +0 -1
  87. package/payload/premium-plugins/writer-craft/lib/mcp-eager/dist/index.js +0 -125
  88. package/payload/premium-plugins/writer-craft/lib/mcp-eager/dist/index.js.map +0 -1
  89. package/payload/premium-plugins/writer-craft/lib/mcp-eager/package.json +0 -7
@@ -0,0 +1,306 @@
1
+ // Task 562 — isolated rc-spawn path via `systemdSpawn` + `script(1)`.
2
+ //
3
+ // Mirrors the rc-daemon's spawn mechanism (rc-daemon.ts:312) so the
4
+ // manager holds ZERO file descriptors per spawn: stdio:'ignore' on the
5
+ // outer systemd-run child, real TTY allocated by `script -q -f -c` inside
6
+ // the scope, child's stdout/stderr captured to a retained typescript file
7
+ // at `~/.<brand>/logs/spawn-rc-resume-<unitToken>.log`.
8
+ //
9
+ // Shares no mutable state with the legacy node-pty rc-spawn path:
10
+ // - No `spawnPty`, `registerRcSpawnPty`, or `livePtys` interaction.
11
+ // - No master fd in the manager → no `releasePtyMasterFd` lifecycle.
12
+ // - Own `liveScriptScopeRcSpawns` Map keyed on unitToken for census +
13
+ // liveness observability.
14
+ //
15
+ // Observability follows the cross-arm `[rc-life]` schema (see Task 562
16
+ // brief). Every line carries `source=rc-spawn path=script-scope
17
+ // mode=<new|resume> unitToken=<token>` so a `grep source=rc-spawn`
18
+ // directly compares with `grep source=rc-daemon` lines emitted from
19
+ // rc-daemon.ts under the same schema. The capture file is never
20
+ // unlinked by this module — post-mortem is always possible.
21
+ import { dirname, join } from 'node:path';
22
+ import { existsSync } from 'node:fs';
23
+ import { randomUUID } from 'node:crypto';
24
+ import { findExistingJsonlForSessionId } from './jsonl-path.js';
25
+ import { buildRcChildEnv } from './rc-daemon.js';
26
+ const liveScriptScopeRcSpawns = new Map();
27
+ /** For tests + the census sweep. Read-only iteration. */
28
+ export function forEachLiveScriptScopeRcSpawn(cb) {
29
+ for (const e of liveScriptScopeRcSpawns.values())
30
+ cb(e);
31
+ }
32
+ export function liveScriptScopeRcSpawnCount() {
33
+ return liveScriptScopeRcSpawns.size;
34
+ }
35
+ /** Clear the tracker map. Test-only seam — production never calls. */
36
+ export function __resetScriptScopeRcSpawnsForTests() {
37
+ liveScriptScopeRcSpawns.clear();
38
+ }
39
+ /** Schema-tagged line emitter. Every consumer of the cross-arm `[rc-life]`
40
+ * surface must use this so the field order + null-handling stays
41
+ * identical between rc-spawn and rc-daemon. */
42
+ export function emitRcLife(logger, op, source, path, mode, unitToken, fields = {}) {
43
+ const base = `[rc-life] op=${op} source=${source} path=${path} mode=${mode} unitToken=${unitToken}`;
44
+ const extras = Object.entries(fields)
45
+ .map(([k, v]) => `${k}=${v === null ? 'null' : typeof v === 'string' && v.includes(' ') ? JSON.stringify(v) : v}`)
46
+ .join(' ');
47
+ logger(extras ? `${base} ${extras}` : base);
48
+ }
49
+ /** Run the script-scope rc-spawn. Returns once `systemdSpawn` resolves
50
+ * (scope is active, cgroup pid captured). Liveness polling, pid-file
51
+ * binding, and exit observation run in the background — the route
52
+ * responds immediately with `spawnedPid` like the node-pty arm does. */
53
+ export async function handleRcSpawnScriptScope(deps, req) {
54
+ const now = deps.now ?? (() => Date.now());
55
+ const livenessIntervalMs = deps.livenessPollIntervalMs ?? 15_000;
56
+ const start = now();
57
+ const unitToken = `rc-resume-${randomUUID()}`;
58
+ const existingJsonl = req.sessionId
59
+ ? findExistingJsonlForSessionId(deps.claudeConfigDir, req.sessionId)
60
+ : null;
61
+ const mode = existingJsonl ? 'resume' : 'new';
62
+ const argv = ['--remote-control'];
63
+ if (req.name)
64
+ argv.push(req.name);
65
+ if (req.sessionId)
66
+ argv.push(mode === 'resume' ? '--resume' : '--session-id', req.sessionId);
67
+ const env = buildRcChildEnv({
68
+ accountId: deps.accountId,
69
+ uiPort: deps.uiPort,
70
+ platformRoot: deps.platformRoot,
71
+ claudeConfigDir: deps.claudeConfigDir,
72
+ brandedNeo4jUri: deps.brandedNeo4jUri,
73
+ brandedNeo4jPassword: deps.brandedNeo4jPassword,
74
+ });
75
+ const cleanEnv = {};
76
+ for (const [k, v] of Object.entries(env)) {
77
+ if (typeof v === 'string')
78
+ cleanEnv[k] = v;
79
+ }
80
+ // Mirror rc-daemon.ts:323 — capture file under <accountDir>/logs/.
81
+ // dirname(claudeConfigDir) is the accountDir (e.g. /home/<user>/.maxy-code/).
82
+ const captureFilePath = join(dirname(deps.claudeConfigDir), 'logs', `spawn-${unitToken}.log`);
83
+ emitRcLife(deps.logger, 'request', 'rc-spawn', 'script-scope', mode, unitToken, {
84
+ sessionId: req.sessionId ?? 'new',
85
+ name: req.name ?? 'none',
86
+ existingJsonl: existingJsonl ?? 'none',
87
+ });
88
+ emitRcLife(deps.logger, 'argv', 'rc-spawn', 'script-scope', mode, unitToken, {
89
+ cwd: deps.spawnCwd,
90
+ captureFile: captureFilePath,
91
+ argv: JSON.stringify([deps.claudeBin, ...argv]),
92
+ });
93
+ let handle;
94
+ try {
95
+ handle = await deps.systemdSpawn({
96
+ claudeBin: deps.claudeBin,
97
+ claudeArgs: argv,
98
+ env: cleanEnv,
99
+ cwd: deps.spawnCwd,
100
+ unitToken,
101
+ captureFilePath,
102
+ });
103
+ }
104
+ catch (err) {
105
+ const msg = err instanceof Error ? err.message : String(err);
106
+ emitRcLife(deps.logger, 'spawn-failed', 'rc-spawn', 'script-scope', mode, unitToken, {
107
+ err: JSON.stringify(msg),
108
+ });
109
+ throw err;
110
+ }
111
+ emitRcLife(deps.logger, 'spawned', 'rc-spawn', 'script-scope', mode, unitToken, {
112
+ pid: handle.pid,
113
+ scopeUnit: `claude-session-${unitToken}.scope`,
114
+ captureFile: captureFilePath,
115
+ // Manager holds no fd for this child — this is the isolation invariant.
116
+ // A rising value across script-scope spawns is the leak signature.
117
+ managerOpenFds: 'unchanged',
118
+ });
119
+ const entry = {
120
+ unitToken,
121
+ pid: handle.pid,
122
+ sessionId: req.sessionId,
123
+ mode,
124
+ spawnedAt: start,
125
+ captureFilePath,
126
+ handle,
127
+ pidFileSeen: false,
128
+ remoteBound: false,
129
+ exited: false,
130
+ };
131
+ liveScriptScopeRcSpawns.set(unitToken, entry);
132
+ // Capture-file head emit — first ≤1 KB of the script(1) typescript,
133
+ // settled by either reaching 1 KB or by a short post-spawn delay. The
134
+ // child's own words are the signal whose absence cost 5 occasions
135
+ // (Task 562 brief). Read once and forget; subsequent failures land in
136
+ // op=early-exit's captureTail.
137
+ void readCaptureHead(handle, 500, 1_024).then((head) => {
138
+ emitRcLife(deps.logger, 'child-output', 'rc-spawn', 'script-scope', mode, unitToken, {
139
+ pid: handle.pid,
140
+ head: JSON.stringify(head),
141
+ });
142
+ });
143
+ // pid-file binding — claude writes <sessions>/<pid>.json once Remote
144
+ // Control registration finishes. This is the `ready` signal: pid file
145
+ // present means claude is alive and reachable from claude.ai/code.
146
+ void deps.waitForPid(handle.pid, deps.pidFileTimeoutMs)
147
+ .then((row) => {
148
+ entry.pidFileSeen = true;
149
+ entry.remoteBound = Boolean(row.bridgeSessionId);
150
+ emitRcLife(deps.logger, 'alive', 'rc-spawn', 'script-scope', mode, unitToken, {
151
+ pid: handle.pid,
152
+ ranMs: now() - start,
153
+ });
154
+ emitRcLife(deps.logger, 'ready', 'rc-spawn', 'script-scope', mode, unitToken, {
155
+ pid: handle.pid,
156
+ pidFile: row.pidFilePath ?? 'unknown',
157
+ bridgeId: row.bridgeSessionId ?? 'unknown',
158
+ remoteSession: row.bridgeSessionId ?? 'unknown',
159
+ });
160
+ })
161
+ .catch((err) => {
162
+ emitRcLife(deps.logger, 'wait-pid-failed', 'rc-spawn', 'script-scope', mode, unitToken, {
163
+ pid: handle.pid,
164
+ err: JSON.stringify(err instanceof Error ? err.message : String(err)),
165
+ });
166
+ });
167
+ // Liveness poll — runs for the session's whole intended life. Catches
168
+ // a session that dies quietly between events without a reproduction.
169
+ // Both arms emit this so endurance is directly comparable.
170
+ const livenessTimer = setInterval(() => {
171
+ if (entry.exited) {
172
+ clearInterval(livenessTimer);
173
+ return;
174
+ }
175
+ const pidAlive = pidIsAlive(entry.pid);
176
+ emitRcLife(deps.logger, 'liveness', 'rc-spawn', 'script-scope', mode, unitToken, {
177
+ ageMs: now() - start,
178
+ pidAlive,
179
+ // scopeActive is captured from handle.waitForExit's terminal — true
180
+ // means we have not yet observed the scope leave the active set.
181
+ // A pidAlive=false here while exited=false is an early death the
182
+ // event flow missed.
183
+ scopeActive: !entry.exited,
184
+ remoteBound: entry.remoteBound,
185
+ });
186
+ }, livenessIntervalMs);
187
+ // Don't block process exit on the liveness timer.
188
+ livenessTimer.unref?.();
189
+ // Exit observation — `handle.waitForExit` polls systemctl. On exit,
190
+ // tag the lifetime, attach captureTail bytes, and remove from the
191
+ // live tracker.
192
+ void handle.waitForExit()
193
+ .then(async (exit) => {
194
+ entry.exited = true;
195
+ clearInterval(livenessTimer);
196
+ const lifetimeMs = now() - start;
197
+ let tail = '';
198
+ try {
199
+ tail = await handle.readCaptureTail(2_048);
200
+ }
201
+ catch {
202
+ tail = '';
203
+ }
204
+ if (!entry.pidFileSeen && lifetimeMs < 2_000) {
205
+ emitRcLife(deps.logger, 'early-exit', 'rc-spawn', 'script-scope', mode, unitToken, {
206
+ pid: handle.pid,
207
+ ranMs: lifetimeMs,
208
+ exitCode: exit.exitCode ?? 'null',
209
+ signal: exit.code ?? 'null',
210
+ captureTail: JSON.stringify(tail),
211
+ });
212
+ }
213
+ const reason = inferExitReason(exit.result, lifetimeMs, entry.pidFileSeen);
214
+ emitRcLife(deps.logger, 'exit', 'rc-spawn', 'script-scope', mode, unitToken, {
215
+ pid: handle.pid,
216
+ lifetimeMs,
217
+ reason,
218
+ result: exit.result,
219
+ captureTail: JSON.stringify(tail.slice(-512)),
220
+ });
221
+ liveScriptScopeRcSpawns.delete(unitToken);
222
+ })
223
+ .catch((err) => {
224
+ entry.exited = true;
225
+ clearInterval(livenessTimer);
226
+ emitRcLife(deps.logger, 'wait-exit-failed', 'rc-spawn', 'script-scope', mode, unitToken, {
227
+ pid: handle.pid,
228
+ err: JSON.stringify(err instanceof Error ? err.message : String(err)),
229
+ });
230
+ liveScriptScopeRcSpawns.delete(unitToken);
231
+ });
232
+ return {
233
+ spawnedPid: handle.pid,
234
+ sessionId: req.sessionId,
235
+ unitToken,
236
+ mode,
237
+ };
238
+ }
239
+ function inferExitReason(result, lifetimeMs, pidFileSeen) {
240
+ if (result === 'success' && pidFileSeen && lifetimeMs >= 2_000)
241
+ return 'archive';
242
+ if (result !== 'success')
243
+ return 'crash';
244
+ if (!pidFileSeen && lifetimeMs < 2_000)
245
+ return 'crash';
246
+ return 'unknown';
247
+ }
248
+ function pidIsAlive(pid) {
249
+ try {
250
+ process.kill(pid, 0);
251
+ return true;
252
+ }
253
+ catch {
254
+ return false;
255
+ }
256
+ }
257
+ /** Reads the head of the script(1) typescript. Returns at most `maxBytes`
258
+ * from the start of the file; waits up to `settleMs` for the file to
259
+ * appear, since systemd-run + script open the typescript asynchronously
260
+ * after the scope is active. */
261
+ async function readCaptureHead(handle, settleMs, maxBytes) {
262
+ const deadline = Date.now() + settleMs;
263
+ while (Date.now() < deadline) {
264
+ if (existsSync(handle.captureFilePath))
265
+ break;
266
+ await new Promise((resolve) => setTimeout(resolve, 50));
267
+ }
268
+ // readCaptureTail returns the last `maxBytes` bytes; for a small early
269
+ // file (< maxBytes) tail == head. The boot sequence is well under 1 KB.
270
+ try {
271
+ return await handle.readCaptureTail(maxBytes);
272
+ }
273
+ catch {
274
+ return '';
275
+ }
276
+ }
277
+ /** Census sweep — reconciles expected (dashboard-initiated sessions) vs
278
+ * actual (live tracked entries). Detects a leaked entry whose pid is
279
+ * gone but the tracker still holds it, or a tracker whose handle's
280
+ * scope vanished without an exit event. Traffic-independent — runs on
281
+ * a timer in index.ts so a quiet failure surfaces within one interval.
282
+ *
283
+ * The daemon's live handle is supplied via `daemonAlive`; the daemon
284
+ * itself owns the canonical accounting (a single handle reference),
285
+ * but exposing it here keeps the schema unified. */
286
+ export function runRcLifeCensus(logger, daemonAlive) {
287
+ let pidAlive = 0;
288
+ let pidDeadButTracked = 0;
289
+ for (const entry of liveScriptScopeRcSpawns.values()) {
290
+ if (pidIsAlive(entry.pid)) {
291
+ pidAlive += 1;
292
+ }
293
+ else {
294
+ pidDeadButTracked += 1;
295
+ // Independent reconciliation defect — entry exists with a dead pid.
296
+ emitRcLife(logger, 'orphan', 'rc-spawn', 'script-scope', entry.mode, entry.unitToken, {
297
+ pid: entry.pid,
298
+ kind: 'pid-dead-but-tracked',
299
+ ageMs: Date.now() - entry.spawnedAt,
300
+ });
301
+ }
302
+ }
303
+ logger(`[rc-census] source-breakdown=rc-spawn:${liveScriptScopeRcSpawns.size},rc-daemon:${daemonAlive}` +
304
+ ` rcSpawnPidAlive=${pidAlive} rcSpawnPidDead=${pidDeadButTracked}`);
305
+ }
306
+ //# sourceMappingURL=rc-script-spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-script-spawn.js","sourceRoot":"","sources":["../src/rc-script-spawn.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,15 @@ export interface SpecialistDriftResult {
23
23
  * any other defect class refuses boot and the manager never reaches a
24
24
  * spawn that would consult this map. */
25
25
  stripList: ReadonlyMap<string, ReadonlySet<string>>;
26
+ /** Per-specialist resolved tool surface — keyed by specialist name (the
27
+ * `.md` basename), value is the sorted set of tool names declared on the
28
+ * specialist's `tools:` line (before any strip-list removal). Populated
29
+ * for every specialist with a `tools:` line, regardless of drift outcome.
30
+ * Consumed by the manager-boot `[specialist-surface]` standing log so a
31
+ * payload-twin or bundle drift that drops a tool from a specialist's
32
+ * resolved surface is greppable from server.log without re-running a
33
+ * failing brief (Task 565 observability item 1). */
34
+ surfaces: ReadonlyMap<string, ReadonlySet<string>>;
26
35
  }
27
36
  /** Extract the value of the `tools:` line from a YAML frontmatter block.
28
37
  * Returns the raw value (whitespace-trimmed) or null when no `tools:`
@@ -1 +1 @@
1
- {"version":3,"file":"specialist-drift.d.ts","sourceRoot":"","sources":["../src/specialist-drift.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAwCpD,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EACF,0BAA0B,GAC1B,wBAAwB,GACxB,gBAAgB,GAChB,uBAAuB,CAAA;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC;;;yCAGqC;IACrC,EAAE,EAAE,OAAO,CAAA;IACX;;wCAEoC;IACpC,OAAO,EAAE,qBAAqB,EAAE,CAAA;IAChC,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAA;IACjB;;;;6CAIyC;IACzC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;CACpD;AAED;;;kEAGkE;AAClE,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3E;AA+CD;;;;;;;;;wDASwD;AACxD,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,WAAW,EAAE,WAAW,EACxB,eAAe,GAAE,WAAW,CAAC,MAAM,CAAa,GAC/C,qBAAqB,CAgDvB"}
1
+ {"version":3,"file":"specialist-drift.d.ts","sourceRoot":"","sources":["../src/specialist-drift.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAyCpD,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EACF,0BAA0B,GAC1B,wBAAwB,GACxB,gBAAgB,GAChB,uBAAuB,CAAA;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC;;;yCAGqC;IACrC,EAAE,EAAE,OAAO,CAAA;IACX;;wCAEoC;IACpC,OAAO,EAAE,qBAAqB,EAAE,CAAA;IAChC,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAA;IACjB;;;;6CAIyC;IACzC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;IACnD;;;;;;;yDAOqD;IACrD,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;CACnD;AAED;;;kEAGkE;AAClE,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3E;AA+CD;;;;;;;;;wDASwD;AACxD,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,WAAW,EAAE,WAAW,EACxB,eAAe,GAAE,WAAW,CAAC,MAAM,CAAa,GAC/C,qBAAqB,CAmDvB"}
@@ -35,6 +35,7 @@ const CC_NATIVE_TOOLS = new Set([
35
35
  'Read',
36
36
  'Write',
37
37
  'Edit',
38
+ 'MultiEdit',
38
39
  'Glob',
39
40
  'Grep',
40
41
  'Bash',
@@ -129,6 +130,7 @@ function classifyTool(tool, allSet, excludedPlugins) {
129
130
  export function assertSpecialistDrift(agentDirs, toolSurface, excludedPlugins = new Set()) {
130
131
  const defects = [];
131
132
  const stripList = new Map();
133
+ const surfaces = new Map();
132
134
  let inspected = 0;
133
135
  for (const dir of agentDirs) {
134
136
  let entries;
@@ -168,7 +170,9 @@ export function assertSpecialistDrift(agentDirs, toolSurface, excludedPlugins =
168
170
  continue;
169
171
  inspected += 1;
170
172
  const specialistName = basename(entry, '.md');
171
- for (const tool of splitToolList(toolsLine)) {
173
+ const declaredTools = splitToolList(toolsLine);
174
+ surfaces.set(specialistName, new Set([...declaredTools].sort()));
175
+ for (const tool of declaredTools) {
172
176
  const verdict = classifyTool(tool, toolSurface.all, excludedPlugins);
173
177
  if (verdict === 'ok')
174
178
  continue;
@@ -189,6 +193,6 @@ export function assertSpecialistDrift(agentDirs, toolSurface, excludedPlugins =
189
193
  // logs each and exits non-zero, matching the prior strict contract for
190
194
  // typos / missing plugins / malformed names.
191
195
  const ok = defects.every((d) => d.reason === 'brand-excluded-plugin');
192
- return { ok, defects, inspected, stripList };
196
+ return { ok, defects, inspected, stripList, surfaces };
193
197
  }
194
198
  //# sourceMappingURL=specialist-drift.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"specialist-drift.js","sourceRoot":"","sources":["../src/specialist-drift.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"specialist-drift.js","sourceRoot":"","sources":["../src/specialist-drift.ts"],"names":[],"mappings":"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"}
@@ -50,20 +50,12 @@ export declare function listSurvivingScopes(run: SystemctlRunner): {
50
50
  scopes: SurvivingScope[];
51
51
  result: SystemctlResult;
52
52
  };
53
- /** Stop any orphan non-PTY scope units left over from prior session-manager
53
+ /** Stop any orphan rc scope units left over from prior session-manager
54
54
  * boots. Called from the session-manager startup BEFORE the rc-daemon
55
55
  * supervisor's first spawn and BEFORE the HTTP server begins accepting
56
56
  * /rc-spawn requests, so no in-flight scope can be misidentified as an
57
- * orphan.
58
- *
59
- * Why this exists — Task 554 root cause: pre-554 `systemdSpawn` threw on
60
- * every spawn attempt via the broken MainPID poll, leaving the scope
61
- * registered with systemd. Eight `claude-session-rc-daemon-*.scope` units
62
- * accumulated on the laptop before the fix; the new `systemdSpawn` calls
63
- * `stopScopeUnit` on every terminal failure, so this reaper is one-shot
64
- * in steady-state (post-rollout, the list is empty). The function is
65
- * idempotent and safe to call on every boot — if nothing matches, no
66
- * stop is issued. */
57
+ * orphan. Idempotent and safe to call on every boot — if nothing
58
+ * matches, no stop is issued. */
67
59
  export declare function reapOrphanNonPtyScopes(run: SystemctlRunner, logger: (line: string) => void): Promise<void>;
68
60
  /** Outcome surface for a scope-stop attempt.
69
61
  *
@@ -141,48 +133,22 @@ export interface BuildSystemdRunArgvParams {
141
133
  /** Working directory passed via `--working-directory=`. The manager's
142
134
  * prior node-pty spawn passed `cwd`; the scope receives it the same way. */
143
135
  cwd: string;
144
- /** Task 556 — when supplied, wraps the inner command in
145
- * `script -q -f -c "<cmd>" "<captureFilePath>"`. `script(1)` allocates a
146
- * real pty (so claude has a TTY) and writes its typescript to the
147
- * captureFilePath, which survives scope reaping for post-mortem reads.
148
- * The non-PTY `systemdSpawn` path REQUIRES this (without a TTY,
149
- * `claude --remote-control --resume` and `claude rc --spawn`
150
- * early-exit in ~50 ms because `--scope` inherits the launcher's
151
- * `stdio: 'ignore'` fds). The PTY spawn path (`spawnPtyAdapter`)
152
- * OMITS it — node-pty already allocates a TTY for the child, and
153
- * adding script on top would interpose a second pty layer between
154
- * node-pty's master and the operator's keystrokes. The parent
155
- * directory of captureFilePath must exist before systemd-run is
156
- * spawned; the manager creates it. */
157
- captureFilePath?: string;
158
136
  }
159
- /** POSIX shell single-quote: wrap in `'…'` and escape any embedded `'` as
160
- * `'\''`. The inner sh command uses `"$1"` to receive the claude
161
- * invocation as a single shell-evaluated string (so `script -c "$1"`
162
- * sees the full command line); the joined string is built here and
163
- * every component is single-quoted so claude args containing spaces,
164
- * `$`, `*`, backticks, etc. survive the round trip unchanged. */
165
- export declare function shellSingleQuote(s: string): string;
166
137
  /** Build the systemd-run argv that node-pty wraps for one claude spawn.
167
- * Inside the scope, `/bin/sh -c 'trap "" HUP; exec script -q -f -c "$1" "$2"' sh <cmd> <cap>`
138
+ * Inside the scope, `/bin/sh -c 'trap "" HUP; exec "$@"' sh <claudeBin> <claudeArgs...>`
168
139
  * wraps the launch so:
169
140
  *
170
141
  * - **claude ignores SIGHUP** when the manager closes the PTY master fd
171
142
  * on restart. Without the trap, master-close → kernel SIGHUP →
172
143
  * claude exits.
173
- * - **claude runs on a real TTY** allocated by `script(1)` (util-linux,
174
- * present on Debian/Ubuntu). A `--scope` unit execs its command with
175
- * the *launcher's* file descriptors systemd does not allocate stdio
176
- * for scopes — so without a wrapper claude inherits `/dev/null` on all
177
- * three streams from the manager's `stdio: 'ignore'` spawn, and
178
- * `claude --remote-control --resume` plus `claude rc --spawn …` hit
179
- * their no-input early-exit branch in ~50 ms. `script` opens its own
180
- * pty master + slave, runs claude on the slave, and writes the
181
- * typescript to `<cap>` (the captureFilePath) so the child's real
182
- * stdout/stderr survive scope reaping.
183
- * - **`exec` keeps the pid stable** through the chain (sh → script →
184
- * claude all reuse the original pid via execve), preserving the
185
- * `pty.pid == claude.pid` invariant the PTY spawn path depends on. */
144
+ * - **`exec` keeps the pid stable** through the chain (sh → claude
145
+ * reuse the original pid via execve), preserving the
146
+ * `pty.pid == claude.pid` invariant the watcher.waitForPid path
147
+ * depends on.
148
+ *
149
+ * Task 573 — node-pty allocates the TTY for the child. The earlier
150
+ * script(1) wrap (Task 556) plus the non-PTY scope primitive it served
151
+ * are gone. */
186
152
  export declare function buildSystemdRunArgv(p: BuildSystemdRunArgvParams): SystemdRunArgv;
187
153
  /** Query `systemctl --user show -p MainPID claude-session-<token>.scope`
188
154
  * and return the main pid (the claude process). Boot-seed uses this to
@@ -1 +1 @@
1
- {"version":3,"file":"systemd-scope.d.ts","sourceRoot":"","sources":["../src/systemd-scope.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"systemd-scope.d.ts","sourceRoot":"","sources":["../src/systemd-scope.ts"],"names":[],"mappings":"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"}
@@ -109,26 +109,18 @@ export function listSurvivingScopes(run) {
109
109
  }
110
110
  return { scopes: parseSurvivingScopes(result.stdout), result };
111
111
  }
112
- /** Task 554 — non-PTY scope unit-token prefixes. PTY operator scopes use
113
- * the bare `claude-session-<uuid>.scope` shape and are explicitly excluded:
114
- * the boot-seed reconciler claims them as live operator sessions. The
115
- * reaper only sweeps tokens emitted by `systemdSpawn` callers
116
- * (rc-daemon supervisor, /rc-spawn HTTP route). */
112
+ /** Task 554 — rc-spawn / rc-daemon scope unit-token prefixes. PTY operator
113
+ * scopes use the bare `claude-session-<uuid>.scope` shape and are
114
+ * explicitly excluded: the boot-seed reconciler claims them as live
115
+ * operator sessions. The reaper only sweeps tokens emitted by the
116
+ * rc-daemon supervisor and the `/rc-spawn` HTTP route. */
117
117
  const NON_PTY_TOKEN_PREFIXES = ['rc-daemon-', 'rc-resume-'];
118
- /** Stop any orphan non-PTY scope units left over from prior session-manager
118
+ /** Stop any orphan rc scope units left over from prior session-manager
119
119
  * boots. Called from the session-manager startup BEFORE the rc-daemon
120
120
  * supervisor's first spawn and BEFORE the HTTP server begins accepting
121
121
  * /rc-spawn requests, so no in-flight scope can be misidentified as an
122
- * orphan.
123
- *
124
- * Why this exists — Task 554 root cause: pre-554 `systemdSpawn` threw on
125
- * every spawn attempt via the broken MainPID poll, leaving the scope
126
- * registered with systemd. Eight `claude-session-rc-daemon-*.scope` units
127
- * accumulated on the laptop before the fix; the new `systemdSpawn` calls
128
- * `stopScopeUnit` on every terminal failure, so this reaper is one-shot
129
- * in steady-state (post-rollout, the list is empty). The function is
130
- * idempotent and safe to call on every boot — if nothing matches, no
131
- * stop is issued. */
122
+ * orphan. Idempotent and safe to call on every boot — if nothing
123
+ * matches, no stop is issued. */
132
124
  export async function reapOrphanNonPtyScopes(run, logger) {
133
125
  const { scopes, result } = listSurvivingScopes(run);
134
126
  if (result.exitCode !== 0) {
@@ -222,42 +214,23 @@ export async function stopScopeUnit(run, unitToken, opts = {}) {
222
214
  }
223
215
  return { outcome: 'failed-pid-survives', exitCode: 0, stderr: result.stderr };
224
216
  }
225
- /** POSIX shell single-quote: wrap in `'…'` and escape any embedded `'` as
226
- * `'\''`. The inner sh command uses `"$1"` to receive the claude
227
- * invocation as a single shell-evaluated string (so `script -c "$1"`
228
- * sees the full command line); the joined string is built here and
229
- * every component is single-quoted so claude args containing spaces,
230
- * `$`, `*`, backticks, etc. survive the round trip unchanged. */
231
- export function shellSingleQuote(s) {
232
- return `'${s.replace(/'/g, "'\\''")}'`;
233
- }
234
217
  /** Build the systemd-run argv that node-pty wraps for one claude spawn.
235
- * Inside the scope, `/bin/sh -c 'trap "" HUP; exec script -q -f -c "$1" "$2"' sh <cmd> <cap>`
218
+ * Inside the scope, `/bin/sh -c 'trap "" HUP; exec "$@"' sh <claudeBin> <claudeArgs...>`
236
219
  * wraps the launch so:
237
220
  *
238
221
  * - **claude ignores SIGHUP** when the manager closes the PTY master fd
239
222
  * on restart. Without the trap, master-close → kernel SIGHUP →
240
223
  * claude exits.
241
- * - **claude runs on a real TTY** allocated by `script(1)` (util-linux,
242
- * present on Debian/Ubuntu). A `--scope` unit execs its command with
243
- * the *launcher's* file descriptors systemd does not allocate stdio
244
- * for scopes — so without a wrapper claude inherits `/dev/null` on all
245
- * three streams from the manager's `stdio: 'ignore'` spawn, and
246
- * `claude --remote-control --resume` plus `claude rc --spawn …` hit
247
- * their no-input early-exit branch in ~50 ms. `script` opens its own
248
- * pty master + slave, runs claude on the slave, and writes the
249
- * typescript to `<cap>` (the captureFilePath) so the child's real
250
- * stdout/stderr survive scope reaping.
251
- * - **`exec` keeps the pid stable** through the chain (sh → script →
252
- * claude all reuse the original pid via execve), preserving the
253
- * `pty.pid == claude.pid` invariant the PTY spawn path depends on. */
224
+ * - **`exec` keeps the pid stable** through the chain (sh → claude
225
+ * reuse the original pid via execve), preserving the
226
+ * `pty.pid == claude.pid` invariant the watcher.waitForPid path
227
+ * depends on.
228
+ *
229
+ * Task 573 — node-pty allocates the TTY for the child. The earlier
230
+ * script(1) wrap (Task 556) plus the non-PTY scope primitive it served
231
+ * are gone. */
254
232
  export function buildSystemdRunArgv(p) {
255
233
  const unit = scopeUnitName(p.unitToken);
256
- // Task 556 — the `-p Standard{Output,Error}=journal` + SyslogIdentifier
257
- // properties Task 555 added here are `Exec*=` *service-unit* properties;
258
- // systemd silently ignores them on `--scope` units, which inherit the
259
- // launcher's fds. The real capture is `script`'s typescript file
260
- // (captureFilePath), retrievable after the scope is reaped.
261
234
  const args = [
262
235
  '--user',
263
236
  '--scope',
@@ -279,35 +252,13 @@ export function buildSystemdRunArgv(p) {
279
252
  // following positional argv (the sh wrapper) doesn't get swallowed
280
253
  // by `--setenv=` etc.
281
254
  args.push('--');
282
- if (p.captureFilePath !== undefined) {
283
- // Task 556 non-PTY path. The claude invocation must reach
284
- // `script -c "$1"` as ONE shell-evaluated string (script's -c flag
285
- // takes a single command line). Build that line by single-quoting
286
- // claudeBin + every claudeArg and joining with spaces — argv
287
- // elements containing spaces, `$`, `*`, backticks, etc. survive
288
- // the round trip unchanged.
289
- const claudeCmdString = [p.claudeBin, ...p.claudeArgs].map(shellSingleQuote).join(' ');
290
- // `sh` as $0 leaves $1 = <claude cmd string>, $2 = <captureFilePath>.
291
- // `exec` replaces the sh process image with script in-place so the
292
- // pid is preserved; `script` then execs claude on its pty slave
293
- // (claude is script's child but holds the same controlling TTY).
294
- // `-q` suppresses script's start/end banner; `-f` flushes the
295
- // typescript on every write so a fast-exiting child's last bytes
296
- // hit disk before the scope is reaped.
297
- args.push('/bin/sh', '-c', 'trap "" HUP; exec script -q -f -c "$1" "$2"', 'sh', claudeCmdString, p.captureFilePath);
298
- }
299
- else {
300
- // PTY path (`spawnPtyAdapter` in index.ts). node-pty already
301
- // allocates a TTY for the child; the script wrap is omitted so the
302
- // pty.pid == claude.pid invariant the `watcher.waitForPid` path
303
- // depends on stays intact. The `exec "$@"` shell wrap keeps the
304
- // SIGHUP trap and the in-place exec; `$@` expands every argv from
305
- // $0 onwards inside the shell, so passing 'sh' as $0 lets `"$@"`
306
- // resolve to `<claudeBin> <claudeArgs...>` after the trap.
307
- args.push('/bin/sh', '-c', 'trap "" HUP; exec "$@"', 'sh', p.claudeBin);
308
- for (const a of p.claudeArgs)
309
- args.push(a);
310
- }
255
+ // POSIX `sh -c <script> <$0> <$1> <$2>...` — `"$@"` expands to the
256
+ // positionals starting at $1. Passing 'sh' as $0 (the script name)
257
+ // makes claudeBin the first positional and claudeArgs the remainder,
258
+ // so `exec "$@"` runs `<claudeBin> <claudeArgs...>` after the trap.
259
+ args.push('/bin/sh', '-c', 'trap "" HUP; exec "$@"', 'sh', p.claudeBin);
260
+ for (const a of p.claudeArgs)
261
+ args.push(a);
311
262
  return { cmd: 'systemd-run', args };
312
263
  }
313
264
  /** Query `systemctl --user show -p MainPID claude-session-<token>.scope`