@rubytech/create-realagent-code 0.1.214 → 0.1.216

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 (71) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  3. package/payload/platform/plugins/admin/PLUGIN.md +4 -1
  4. package/payload/platform/plugins/admin/hooks/__tests__/post-tool-use-agent.test.sh +97 -1
  5. package/payload/platform/plugins/admin/hooks/__tests__/pre-tool-use-admin-tool-gate.test.sh +53 -12
  6. package/payload/platform/plugins/admin/hooks/lib/hook-emit.sh +30 -0
  7. package/payload/platform/plugins/admin/hooks/post-tool-use-agent.sh +81 -29
  8. package/payload/platform/plugins/admin/hooks/pre-tool-use.sh +34 -17
  9. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.d.ts +2 -0
  10. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.d.ts.map +1 -0
  11. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js +130 -0
  12. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js.map +1 -0
  13. package/payload/platform/plugins/admin/mcp/dist/index.js +63 -0
  14. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  15. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.d.ts +14 -0
  16. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.d.ts.map +1 -0
  17. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.js +50 -0
  18. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.js.map +1 -0
  19. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts +28 -0
  20. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts.map +1 -0
  21. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js +68 -0
  22. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js.map +1 -0
  23. package/payload/platform/plugins/admin/skills/capabilities-here/SKILL.md +31 -0
  24. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +170 -16
  25. package/payload/platform/plugins/docs/references/platform.md +19 -9
  26. package/payload/platform/plugins/docs/references/plugins-guide.md +2 -0
  27. package/payload/platform/scripts/check-architecture-skill-no-drift.mjs +89 -42
  28. package/payload/platform/scripts/check-roles-doc-completeness.mjs +96 -0
  29. package/payload/platform/scripts/check-specialist-tool-surface.mjs +1 -1
  30. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  31. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  32. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  33. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  34. package/payload/platform/services/claude-session-manager/dist/http-server.js +77 -0
  35. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  36. package/payload/platform/services/claude-session-manager/dist/index.js +30 -0
  37. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  38. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.d.ts +18 -0
  39. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.d.ts.map +1 -1
  40. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.js +63 -0
  41. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.js.map +1 -1
  42. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +5 -0
  43. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  44. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +29 -0
  45. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  46. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.d.ts +80 -0
  47. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.d.ts.map +1 -0
  48. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.js +306 -0
  49. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.js.map +1 -0
  50. package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts +9 -0
  51. package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts.map +1 -1
  52. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js +6 -2
  53. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js.map +1 -1
  54. package/payload/platform/templates/agents/admin/IDENTITY.md +3 -1
  55. package/payload/platform/templates/specialists/agents/content-producer.md +1 -1
  56. package/payload/premium-plugins/real-agent/BUNDLE.md +7 -0
  57. package/payload/premium-plugins/real-agent/PLUGIN.md +6 -0
  58. package/payload/premium-plugins/real-agent/docs/nav.json +35 -0
  59. package/payload/premium-plugins/real-agent/docs/references/real-agent-architecture.md +39 -0
  60. package/payload/premium-plugins/real-agent/docs/references/real-agent-plugins.md +22 -0
  61. package/payload/premium-plugins/real-agent/docs/references/real-agent-roles.md +15 -0
  62. package/payload/premium-plugins/real-agent/docs/references/real-agent-workflows.md +42 -0
  63. package/payload/server/public/assets/AdminShell-CPWbJ_I8.js +1 -0
  64. package/payload/server/public/assets/{admin-DMo5DWKH.js → admin-DjGGOx2K.js} +1 -1
  65. package/payload/server/public/assets/{data-D6IQdm0R.js → data-WBEvtRV-.js} +1 -1
  66. package/payload/server/public/assets/{graph-PkZKVkWD.js → graph-DsOLsIPf.js} +1 -1
  67. package/payload/server/public/data.html +2 -2
  68. package/payload/server/public/graph.html +2 -2
  69. package/payload/server/public/index.html +2 -2
  70. package/payload/server/server.js +6 -0
  71. package/payload/server/public/assets/AdminShell-BcxEZnpu.js +0 -1
@@ -1,20 +1,21 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * check-architecture-skill-no-drift.mjs — prepublishOnly gate.
4
- *
5
- * The platform-architecture skill at
6
- * maxy-code/platform/plugins/admin/skills/platform-architecture/SKILL.md
7
- * is a generated artefact. Its body is the verbatim content of
8
- * `docs/public/llms-full.txt`, wrapped in a short header that carries a
9
- * sha256 of the body. The generator lives at
10
- * maxy-code/scripts/assemble-architecture-skill.mjs
11
- *
12
- * This gate runs the generator against the current tree (after first
13
- * regenerating `docs/public/llms-full.txt` via `docs/scripts/copy-docs.mjs`
14
- * so the source is fresh) and asserts the bytes match the checked-in
15
- * SKILL.md. Fails if someone hand-edited the SKILL.md or updated the
16
- * source docs without re-running the release flow.
17
- */
2
+ // check-architecture-skill-no-drift.mjs — prepublishOnly gate.
3
+ //
4
+ // The per-brand platform-architecture skill body is a generated artefact.
5
+ // Source: docs/public/llms-full.<brand>.txt (emitted by copy-docs.mjs).
6
+ // Generator: maxy-code/scripts/assemble-architecture-skill.mjs --brand <brand>.
7
+ //
8
+ // For brand=maxy-code, the gate also asserts byte-equality with the
9
+ // checked-in skill source at platform/plugins/admin/skills/platform-architecture/SKILL.md
10
+ // (back-compat with the existing release flow).
11
+ //
12
+ // For other brands, the gate asserts the assembled cache body exists and
13
+ // contains the brand product name + the catalogue-boundary sentence.
14
+ //
15
+ // Usage:
16
+ // node platform/scripts/check-architecture-skill-no-drift.mjs # all brands
17
+ // node platform/scripts/check-architecture-skill-no-drift.mjs --brand maxy-code
18
+ // node platform/scripts/check-architecture-skill-no-drift.mjs --brand realagent-code
18
19
 
19
20
  import { readFileSync, existsSync } from 'node:fs';
20
21
  import { dirname, resolve } from 'node:path';
@@ -25,43 +26,89 @@ import { assemble } from '../../scripts/assemble-architecture-skill.mjs';
25
26
  const __dirname = dirname(fileURLToPath(import.meta.url));
26
27
  const MAXY_CODE_ROOT = resolve(__dirname, '..', '..');
27
28
  const REPO_ROOT = resolve(MAXY_CODE_ROOT, '..');
28
- const LLMS_FULL = resolve(REPO_ROOT, 'docs/public/llms-full.txt');
29
29
  const COPY_DOCS = resolve(REPO_ROOT, 'docs/scripts/copy-docs.mjs');
30
- const SKILL_PATH = resolve(
31
- MAXY_CODE_ROOT,
32
- 'platform/plugins/admin/skills/platform-architecture/SKILL.md',
33
- );
30
+
31
+ const args = process.argv.slice(2);
32
+ const brandIdx = args.indexOf('--brand');
33
+ const REQUESTED_BRAND = brandIdx === -1 ? null : args[brandIdx + 1];
34
+
35
+ const CATALOGUE_BOUNDARY_SUBSTRING = 'not evidence of what is installed on the current account';
36
+
37
+ const BRANDS = [
38
+ {
39
+ key: 'maxy-code',
40
+ productName: 'Maxy',
41
+ docsUrl: 'https://docs.getmaxy.com',
42
+ sourceSkillPath: resolve(
43
+ MAXY_CODE_ROOT,
44
+ 'platform/plugins/admin/skills/platform-architecture/SKILL.md',
45
+ ),
46
+ },
47
+ {
48
+ key: 'realagent-code',
49
+ productName: 'Real Agent',
50
+ docsUrl: 'https://docs.realagent.network',
51
+ sourceSkillPath: null,
52
+ },
53
+ ];
34
54
 
35
55
  function fail(msg) {
36
56
  console.error(`[check-architecture-skill-no-drift] ERROR: ${msg}`);
37
57
  process.exit(1);
38
58
  }
39
59
 
40
- if (!existsSync(COPY_DOCS)) {
41
- fail(`docs mirror script missing: ${COPY_DOCS}`);
42
- }
60
+ if (!existsSync(COPY_DOCS)) fail(`docs mirror script missing: ${COPY_DOCS}`);
43
61
 
44
- // Regenerate the docs corpus so the comparison runs against current sources.
45
62
  execFileSync('node', [COPY_DOCS], { stdio: 'pipe' });
46
63
 
47
- if (!existsSync(LLMS_FULL)) {
48
- fail(`expected ${LLMS_FULL} after running copy-docs.mjs`);
49
- }
50
- if (!existsSync(SKILL_PATH)) {
51
- fail(`expected ${SKILL_PATH} (run scripts/assemble-architecture-skill.mjs)`);
52
- }
64
+ const ASSEMBLER = resolve(MAXY_CODE_ROOT, 'scripts/assemble-architecture-skill.mjs');
53
65
 
54
- const body = readFileSync(LLMS_FULL, 'utf8');
55
- const expected = assemble(body);
56
- const actual = readFileSync(SKILL_PATH, 'utf8');
66
+ const brandsToCheck = REQUESTED_BRAND
67
+ ? BRANDS.filter((b) => b.key === REQUESTED_BRAND)
68
+ : BRANDS;
57
69
 
58
- if (expected !== actual) {
59
- fail(
60
- `${SKILL_PATH} is out of sync with docs/public/llms-full.txt. ` +
61
- `Run \`node maxy-code/scripts/assemble-architecture-skill.mjs\` and commit the result.`,
62
- );
70
+ if (REQUESTED_BRAND && brandsToCheck.length === 0) {
71
+ fail(`unknown brand: ${REQUESTED_BRAND}`);
63
72
  }
64
73
 
65
- console.log(
66
- `[check-architecture-skill-no-drift] ok (${actual.length} bytes match)`,
67
- );
74
+ for (const brand of brandsToCheck) {
75
+ const corpus = resolve(REPO_ROOT, `docs/public/llms-full.${brand.key}.txt`);
76
+ if (!existsSync(corpus)) fail(`expected ${corpus} after running copy-docs.mjs`);
77
+
78
+ // Re-run assembler for this brand. The assembler writes the cache file;
79
+ // we then compare its body to a fresh in-process assemble() call to catch
80
+ // drift between the assembler module and the cache write.
81
+ execFileSync('node', [ASSEMBLER, '--brand', brand.key], { stdio: 'pipe' });
82
+
83
+ const body = readFileSync(corpus, 'utf8');
84
+ const expected = assemble(body, {
85
+ productName: brand.productName,
86
+ brand: brand.key,
87
+ docsUrl: brand.docsUrl,
88
+ });
89
+
90
+ if (!expected.includes(CATALOGUE_BOUNDARY_SUBSTRING)) {
91
+ fail(`brand=${brand.key}: assembled body missing catalogue-boundary sentence`);
92
+ }
93
+ if (!expected.includes(brand.productName)) {
94
+ fail(`brand=${brand.key}: assembled body missing product name ${brand.productName}`);
95
+ }
96
+
97
+ if (brand.sourceSkillPath) {
98
+ if (!existsSync(brand.sourceSkillPath)) {
99
+ fail(
100
+ `brand=${brand.key}: source skill missing at ${brand.sourceSkillPath}; ` +
101
+ `run \`node maxy-code/scripts/assemble-architecture-skill.mjs\``,
102
+ );
103
+ }
104
+ const actual = readFileSync(brand.sourceSkillPath, 'utf8');
105
+ if (expected !== actual) {
106
+ fail(
107
+ `brand=${brand.key}: ${brand.sourceSkillPath} out of sync. ` +
108
+ `Run \`node maxy-code/scripts/assemble-architecture-skill.mjs\` and commit.`,
109
+ );
110
+ }
111
+ }
112
+
113
+ console.log(`[check-architecture-skill-no-drift] ok brand=${brand.key} (${expected.length} bytes)`);
114
+ }
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ // check-roles-doc-completeness.mjs
3
+ // Asserts every specialist on disk has a row in the authoritative roles doc.
4
+ // Brands: --brand maxy (default) | --brand real-agent
5
+ import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
6
+ import { resolve, join, dirname } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+
9
+ const here = dirname(fileURLToPath(import.meta.url));
10
+ const maxyCodeRoot = resolve(here, '..', '..');
11
+
12
+ const args = process.argv.slice(2);
13
+ const brandIdx = args.indexOf('--brand');
14
+ const brand = brandIdx === -1 ? 'maxy' : args[brandIdx + 1];
15
+
16
+ const config = {
17
+ maxy: {
18
+ diskDir: resolve(maxyCodeRoot, 'platform/templates/specialists/agents'),
19
+ docPath: resolve(maxyCodeRoot, 'platform/plugins/docs/references/platform.md'),
20
+ },
21
+ 'real-agent': {
22
+ diskDir: resolve(maxyCodeRoot, 'premium-plugins/real-agent/agents'),
23
+ docPath: resolve(maxyCodeRoot, 'premium-plugins/real-agent/docs/references/real-agent-roles.md'),
24
+ },
25
+ };
26
+
27
+ if (!config[brand]) {
28
+ console.error(`[check-roles-doc] unknown brand: ${brand}`);
29
+ process.exit(2);
30
+ }
31
+
32
+ const { diskDir, docPath } = config[brand];
33
+ const TABLE_HEADER = '| Role | What it does |';
34
+
35
+ if (!existsSync(diskDir)) {
36
+ console.error(`[check-roles-doc] disk dir missing: ${diskDir}`);
37
+ process.exit(2);
38
+ }
39
+
40
+ function listSpecialists(dir) {
41
+ const out = [];
42
+ for (const entry of readdirSync(dir)) {
43
+ const full = join(dir, entry);
44
+ const st = statSync(full);
45
+ if (st.isFile() && entry.endsWith('.md')) {
46
+ out.push(entry.replace(/\.md$/, ''));
47
+ } else if (st.isDirectory()) {
48
+ if (existsSync(join(full, 'IDENTITY.md'))) out.push(entry);
49
+ }
50
+ }
51
+ return out.sort();
52
+ }
53
+
54
+ const diskSpecialists = listSpecialists(diskDir);
55
+
56
+ if (!existsSync(docPath)) {
57
+ console.error(`[check-roles-doc] doc missing: ${docPath}`);
58
+ console.error(`[check-roles-doc] disk specialists (${diskSpecialists.length}): ${diskSpecialists.join(', ')}`);
59
+ process.exit(1);
60
+ }
61
+
62
+ const docBody = readFileSync(docPath, 'utf8');
63
+
64
+ function extractRoleRows(body, header) {
65
+ const lines = body.split(/\r?\n/);
66
+ const start = lines.findIndex((l) => l.trim() === header.trim());
67
+ if (start === -1) return [];
68
+ const rows = [];
69
+ for (let i = start + 2; i < lines.length; i++) {
70
+ const ln = lines[i];
71
+ if (!ln.startsWith('|')) break;
72
+ const cells = ln.split('|').map((c) => c.trim()).filter(Boolean);
73
+ if (cells.length >= 2) rows.push(cells[0]);
74
+ }
75
+ return rows;
76
+ }
77
+
78
+ const rowLabels = extractRoleRows(docBody, TABLE_HEADER);
79
+
80
+ const slugify = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
81
+ const rowSlugs = new Set(rowLabels.map(slugify));
82
+
83
+ const missing = diskSpecialists.filter((s) => !rowSlugs.has(slugify(s)));
84
+ const stale = rowLabels.filter((r) => !diskSpecialists.some((s) => slugify(s) === slugify(r)));
85
+
86
+ if (missing.length === 0 && stale.length === 0) {
87
+ console.log(`[check-roles-doc] brand=${brand} ok — ${diskSpecialists.length} specialists documented`);
88
+ process.exit(0);
89
+ }
90
+
91
+ console.error(`[check-roles-doc] brand=${brand} FAIL`);
92
+ console.error(` disk specialists (${diskSpecialists.length}): ${diskSpecialists.join(', ')}`);
93
+ console.error(` doc rows (${rowLabels.length}): ${rowLabels.join(', ')}`);
94
+ if (missing.length) console.error(` MISSING from doc: ${missing.join(', ')}`);
95
+ if (stale.length) console.error(` STALE in doc (no template): ${stale.join(', ')}`);
96
+ process.exit(1);
@@ -50,7 +50,7 @@ function rootsFor(maxyCodeRoot) {
50
50
  // Mirrors CC_NATIVE_TOOLS in specialist-drift.ts. Listed exhaustively so a
51
51
  // new CC-native tool forces an explicit ledger update in both surfaces.
52
52
  const CC_NATIVE_TOOLS = new Set([
53
- 'Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash', 'BashOutput', 'KillShell',
53
+ 'Read', 'Write', 'Edit', 'MultiEdit', 'Glob', 'Grep', 'Bash', 'BashOutput', 'KillShell',
54
54
  'Skill', 'WebSearch', 'WebFetch', 'Task', 'TodoWrite', 'NotebookEdit',
55
55
  'NotebookRead', 'AskUserQuestion',
56
56
  ]);
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-tool-names.generated.d.ts","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"AAQA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAiB7C,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EA+KtD,CAAA"}
1
+ {"version":3,"file":"canonical-tool-names.generated.d.ts","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"AAQA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAiB7C,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAgLtD,CAAA"}
@@ -39,6 +39,7 @@ export const CANONICAL_MAXY_TOOL_NAMES = [
39
39
  "mcp__plugin_admin_admin__agent-config-read",
40
40
  "mcp__plugin_admin_admin__agent-list",
41
41
  "mcp__plugin_admin_admin__brand-settings",
42
+ "mcp__plugin_admin_admin__capabilities-here",
42
43
  "mcp__plugin_admin_admin__logs-read",
43
44
  "mcp__plugin_admin_admin__plugin-read",
44
45
  "mcp__plugin_admin_admin__public-hostname",
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-tool-names.generated.js","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canonical-tool-names.generated.js","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAM3B,OAAO,EAgBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAa5D,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,iBAAiB,CAAA;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AA+E9E,eAAO,MAAM,kBAAkB,QAA2B,CAAA;AAI1D,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7E,OAAO,EAAE,SAAS,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,WAAW,CAAA;IAC/B,eAAe,EAAE,aAAa,CAAA;IAC9B;kFAC8E;IAC9E,cAAc,EAAE,cAAc,CAAA;IAC9B;;;;2DAIuD;IACvD,YAAY,EAAE,CAAC,MAAM,EAAE;QACrB,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;QAC7B,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;QACrC,GAAG,EAAE,MAAM,CAAA;QACX,SAAS,EAAE,MAAM,CAAA;QACjB,eAAe,EAAE,MAAM,CAAA;KACxB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAA;CAClC;AA4LD;;;kEAGkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAC3B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;+CAG2C;IAC3C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD,CAAA;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAm2CpD"}
1
+ {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAM3B,OAAO,EAgBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAc5D,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,iBAAiB,CAAA;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AA+E9E,eAAO,MAAM,kBAAkB,QAA2B,CAAA;AAI1D,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7E,OAAO,EAAE,SAAS,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,WAAW,CAAA;IAC/B,eAAe,EAAE,aAAa,CAAA;IAC9B;kFAC8E;IAC9E,cAAc,EAAE,cAAc,CAAA;IAC9B;;;;2DAIuD;IACvD,YAAY,EAAE,CAAC,MAAM,EAAE;QACrB,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;QAC7B,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;QACrC,GAAG,EAAE,MAAM,CAAA;QACX,SAAS,EAAE,MAAM,CAAA;QACjB,eAAe,EAAE,MAAM,CAAA;KACxB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAA;CAClC;AA4LD;;;kEAGkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAC3B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;+CAG2C;IAC3C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD,CAAA;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAo7CpD"}
@@ -26,6 +26,7 @@ import { randomUUID } from 'node:crypto';
26
26
  import { buildRcChildEnv } from './rc-daemon.js';
27
27
  import { spawnClaudeSession, stopSession, writeInputToPty, isLive, onPtyExit, livePtyCount, getPtyTrackerForTests, livePidForSession, priorExitedCountForSession, PERMISSION_MODES, resolveLiveMemory, openFdCount, registerRcSpawnPty, } from './pty-spawner.js';
28
28
  import { readSidecar, updateSidecar, appendBridgeId } from './session-sidecar.js';
29
+ import { handleRcSpawnScriptScope, emitRcLife } from './rc-script-spawn.js';
29
30
  import { readJsonlSession } from './jsonl-enumerator.js';
30
31
  import { claudeStateRoot, projectSlugForCwd, jsonlPathForSessionId, sidecarPathForSessionId, permissionModeLogPathForSessionId, findExistingJsonlForSessionId, } from './jsonl-path.js';
31
32
  import { basename, join } from 'node:path';
@@ -1440,6 +1441,44 @@ export function buildHttpApp(deps) {
1440
1441
  timed(deps.logger, 'POST', '/rc-spawn', 400, Date.now() - start);
1441
1442
  return c.json({ error: 'sessionId must be a v4 UUID' }, 400);
1442
1443
  }
1444
+ // Task 562 — temporary A/B selector. Default `node-pty` keeps current
1445
+ // behaviour byte-identical (the diagnostic toggle in the dashboard
1446
+ // sidebar is opt-in). `script-scope` delegates to the isolated
1447
+ // systemdSpawn + script(1) path that holds zero fds in the manager.
1448
+ const spawnPathRaw = body.spawnPath;
1449
+ const spawnPath = spawnPathRaw === 'script-scope' ? 'script-scope' : 'node-pty';
1450
+ if (spawnPathRaw !== undefined && spawnPathRaw !== 'node-pty' && spawnPathRaw !== 'script-scope') {
1451
+ timed(deps.logger, 'POST', '/rc-spawn', 400, Date.now() - start);
1452
+ return c.json({ error: `spawnPath must be 'node-pty' or 'script-scope' (got ${JSON.stringify(spawnPathRaw)})` }, 400);
1453
+ }
1454
+ if (spawnPath === 'script-scope') {
1455
+ try {
1456
+ const result = await handleRcSpawnScriptScope({
1457
+ claudeBin: deps.claudeBin,
1458
+ spawnCwd: deps.spawnCwd,
1459
+ accountId: deps.accountId,
1460
+ platformRoot: deps.platformRoot,
1461
+ claudeConfigDir: deps.claudeConfigDir,
1462
+ brandedNeo4jUri: deps.brandedNeo4jUri ?? process.env.NEO4J_URI ?? '',
1463
+ brandedNeo4jPassword: deps.brandedNeo4jPassword ?? process.env.NEO4J_PASSWORD ?? '',
1464
+ uiPort: process.env.MAXY_UI_INTERNAL_PORT ?? '',
1465
+ pidFileTimeoutMs: deps.pidFileTimeoutMs,
1466
+ logger: deps.logger,
1467
+ systemdSpawn: deps.systemdSpawn,
1468
+ waitForPid: (pid, timeoutMs) => deps.watcher.waitForPid(pid, timeoutMs).then((r) => ({
1469
+ pidFilePath: r.pidFilePath ?? null,
1470
+ bridgeSessionId: r.bridgeSessionId ?? null,
1471
+ })),
1472
+ }, { sessionId, name });
1473
+ timed(deps.logger, 'POST', '/rc-spawn', 200, Date.now() - start);
1474
+ return c.json({ spawnedPid: result.spawnedPid, sessionId: result.sessionId, unitToken: result.unitToken });
1475
+ }
1476
+ catch (err) {
1477
+ const msg = err instanceof Error ? err.message : String(err);
1478
+ timed(deps.logger, 'POST', '/rc-spawn', 500, Date.now() - start);
1479
+ return c.json({ error: msg }, 500);
1480
+ }
1481
+ }
1443
1482
  // Task 547 — when a JSONL already exists for the requested sessionId,
1444
1483
  // resume the existing conversation instead of forking a fresh one
1445
1484
  // under the same id. `--session-id` is claude's fresh-spawn flag;
@@ -1461,16 +1500,29 @@ export function buildHttpApp(deps) {
1461
1500
  });
1462
1501
  const unitToken = `rc-resume-${randomUUID()}`;
1463
1502
  const sessionIdForLog = sessionId ? sessionId.slice(0, 8) : 'new';
1503
+ const rcLifeMode = mode === 'resume' ? 'resume' : 'new';
1464
1504
  // Step 1 — request received, before any spawn work. The argv-resolved
1465
1505
  // line (step 2) emits next, so a 500 between them isolates resolution
1466
1506
  // failures from spawn failures.
1467
1507
  deps.logger(`[rc-spawn] op=request unitToken=${unitToken} sessionId=${sessionIdForLog} name=${name ?? 'none'} mode=${mode} jsonl=${existingJsonlPath ?? 'none'}`);
1508
+ // Task 562 — cross-arm schema mirror so `grep '[rc-life]'` covers
1509
+ // both node-pty and script-scope rc-spawn arms and rc-daemon under
1510
+ // one shape.
1511
+ emitRcLife(deps.logger, 'request', 'rc-spawn', 'node-pty', rcLifeMode, unitToken, {
1512
+ sessionId: sessionId ?? 'new',
1513
+ name: name ?? 'none',
1514
+ existingJsonl: existingJsonlPath ?? 'none',
1515
+ });
1468
1516
  // Step 2 — the exact claude argv (the inner command). The systemd-run
1469
1517
  // wrap is composed by the spawnPty adapter; logging the inner argv
1470
1518
  // here is enough for an operator to reproduce by hand. The wrapped
1471
1519
  // argv is fully reconstructible from this line + the spawn adapter
1472
1520
  // source (Task 250 / 556).
1473
1521
  deps.logger(`[rc-spawn] op=argv unitToken=${unitToken} cwd=${deps.spawnCwd} argv=${JSON.stringify([deps.claudeBin, ...argv])}`);
1522
+ emitRcLife(deps.logger, 'argv', 'rc-spawn', 'node-pty', rcLifeMode, unitToken, {
1523
+ cwd: deps.spawnCwd,
1524
+ argv: JSON.stringify([deps.claudeBin, ...argv]),
1525
+ });
1474
1526
  let pty;
1475
1527
  try {
1476
1528
  pty = deps.spawnPty(deps.claudeBin, argv, env, unitToken);
@@ -1485,6 +1537,10 @@ export function buildHttpApp(deps) {
1485
1537
  // Step 3 — PTY spawned. fd baseline at this instant; the fd-release
1486
1538
  // line later in the lifecycle is read relative to this value.
1487
1539
  deps.logger(`[rc-spawn] op=pty-spawned unitToken=${unitToken} pid=${pty.pid} openFds=${openFdCount()}`);
1540
+ emitRcLife(deps.logger, 'spawned', 'rc-spawn', 'node-pty', rcLifeMode, unitToken, {
1541
+ pid: pty.pid,
1542
+ managerOpenFds: openFdCount(),
1543
+ });
1488
1544
  // Tracker registration — closes the leak gap the Task 552 path opened.
1489
1545
  // For fresh spawns without a caller-supplied sessionId we register the
1490
1546
  // tracker under the unitToken so the entry has a stable key; the
@@ -1530,8 +1586,20 @@ export function buildHttpApp(deps) {
1530
1586
  const ranMs = Date.now() - start;
1531
1587
  if (!pidFileSeen) {
1532
1588
  deps.logger(`[rc-spawn] op=early-exit unitToken=${unitToken} pid=${pty.pid} ranMs=${ranMs} exitCode=${e.exitCode} signal=${e.signal ?? 'none'}`);
1589
+ emitRcLife(deps.logger, 'early-exit', 'rc-spawn', 'node-pty', rcLifeMode, unitToken, {
1590
+ pid: pty.pid,
1591
+ ranMs,
1592
+ exitCode: e.exitCode ?? 'null',
1593
+ signal: e.signal ?? 'none',
1594
+ });
1533
1595
  }
1534
1596
  deps.logger(`[rc-spawn] op=exit unitToken=${unitToken} pid=${pty.pid} ranMs=${ranMs}`);
1597
+ emitRcLife(deps.logger, 'exit', 'rc-spawn', 'node-pty', rcLifeMode, unitToken, {
1598
+ pid: pty.pid,
1599
+ lifetimeMs: ranMs,
1600
+ exitCode: e.exitCode ?? 'null',
1601
+ signal: e.signal ?? 'none',
1602
+ });
1535
1603
  // Flush any buffered child output that never reached 1 KB nor the
1536
1604
  // 500 ms idle deadline before the child exited.
1537
1605
  if (!outputEmitted)
@@ -1554,6 +1622,15 @@ export function buildHttpApp(deps) {
1554
1622
  const aliveMs = Date.now() - start;
1555
1623
  deps.logger(`[rc-spawn] op=alive unitToken=${unitToken} pid=${pty.pid} ranMs=${aliveMs}`);
1556
1624
  deps.logger(`[rc-spawn] op=session-ready unitToken=${unitToken} pid=${pty.pid} pidFile=${row.pidFilePath ?? 'unknown'} bridgeId=${row.bridgeSessionId ?? 'unknown'}`);
1625
+ emitRcLife(deps.logger, 'alive', 'rc-spawn', 'node-pty', rcLifeMode, unitToken, {
1626
+ pid: pty.pid,
1627
+ ranMs: aliveMs,
1628
+ });
1629
+ emitRcLife(deps.logger, 'ready', 'rc-spawn', 'node-pty', rcLifeMode, unitToken, {
1630
+ pid: pty.pid,
1631
+ pidFile: row.pidFilePath ?? 'unknown',
1632
+ bridgeId: row.bridgeSessionId ?? 'unknown',
1633
+ });
1557
1634
  })
1558
1635
  .catch((err) => {
1559
1636
  deps.logger(`[rc-spawn] op=wait-pid-failed unitToken=${unitToken} pid=${pty.pid} err=${err instanceof Error ? err.message : String(err)}`);