@rubytech/create-maxy-code 0.1.212 → 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 (67) 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 +5 -1
  4. package/payload/platform/plugins/admin/hooks/__tests__/hook-emit.test.sh +75 -0
  5. package/payload/platform/plugins/admin/hooks/__tests__/post-tool-use-agent.test.sh +173 -0
  6. package/payload/platform/plugins/admin/hooks/__tests__/pre-tool-use-admin-tool-gate.test.sh +107 -40
  7. package/payload/platform/plugins/admin/hooks/__tests__/pre-tool-use-base64-guard.test.sh +4 -4
  8. package/payload/platform/plugins/admin/hooks/lib/hook-emit.sh +114 -0
  9. package/payload/platform/plugins/admin/hooks/post-tool-use-agent.sh +136 -0
  10. package/payload/platform/plugins/admin/hooks/pre-tool-use.sh +127 -68
  11. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.d.ts +2 -0
  12. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.d.ts.map +1 -0
  13. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js +130 -0
  14. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js.map +1 -0
  15. package/payload/platform/plugins/admin/mcp/dist/index.js +63 -0
  16. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  17. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.d.ts +14 -0
  18. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.d.ts.map +1 -0
  19. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.js +50 -0
  20. package/payload/platform/plugins/admin/mcp/dist/lib/catalogue-census.js.map +1 -0
  21. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts +28 -0
  22. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts.map +1 -0
  23. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js +68 -0
  24. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js.map +1 -0
  25. package/payload/platform/plugins/admin/skills/capabilities-here/SKILL.md +31 -0
  26. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +30 -14
  27. package/payload/platform/plugins/docs/references/platform.md +19 -9
  28. package/payload/platform/plugins/docs/references/plugins-guide.md +2 -0
  29. package/payload/platform/scripts/check-architecture-skill-no-drift.mjs +89 -42
  30. package/payload/platform/scripts/check-roles-doc-completeness.mjs +96 -0
  31. package/payload/platform/scripts/check-specialist-tool-surface.mjs +1 -1
  32. package/payload/platform/scripts/setup-account.sh +6 -0
  33. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  34. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  35. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  36. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  37. package/payload/platform/services/claude-session-manager/dist/http-server.js +77 -0
  38. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  39. package/payload/platform/services/claude-session-manager/dist/index.js +30 -0
  40. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  41. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.d.ts +18 -0
  42. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.d.ts.map +1 -1
  43. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.js +63 -0
  44. package/payload/platform/services/claude-session-manager/dist/jsonl-tail.js.map +1 -1
  45. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +5 -0
  46. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  47. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +29 -0
  48. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  49. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.d.ts +80 -0
  50. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.d.ts.map +1 -0
  51. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.js +306 -0
  52. package/payload/platform/services/claude-session-manager/dist/rc-script-spawn.js.map +1 -0
  53. package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts +9 -0
  54. package/payload/platform/services/claude-session-manager/dist/specialist-drift.d.ts.map +1 -1
  55. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js +6 -2
  56. package/payload/platform/services/claude-session-manager/dist/specialist-drift.js.map +1 -1
  57. package/payload/platform/templates/agents/admin/IDENTITY.md +3 -1
  58. package/payload/platform/templates/specialists/agents/content-producer.md +1 -1
  59. package/payload/server/public/assets/AdminShell-CPWbJ_I8.js +1 -0
  60. package/payload/server/public/assets/{admin-DMo5DWKH.js → admin-DjGGOx2K.js} +1 -1
  61. package/payload/server/public/assets/{data-D6IQdm0R.js → data-WBEvtRV-.js} +1 -1
  62. package/payload/server/public/assets/{graph-PkZKVkWD.js → graph-DsOLsIPf.js} +1 -1
  63. package/payload/server/public/data.html +2 -2
  64. package/payload/server/public/graph.html +2 -2
  65. package/payload/server/public/index.html +2 -2
  66. package/payload/server/server.js +6 -0
  67. package/payload/server/public/assets/AdminShell-BcxEZnpu.js +0 -1
@@ -0,0 +1,130 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { resolveCapabilitiesHere } from "../tools/capabilities-here.js";
6
+ function writeFile(path, body) {
7
+ mkdirSync(join(path, ".."), { recursive: true });
8
+ writeFileSync(path, body);
9
+ }
10
+ function seedTree(root, spec) {
11
+ const accountConfigPath = join(root, "accounts", spec.accountId, "account.json");
12
+ const brandConfigPath = join(root, "platform", "config", "brand.json");
13
+ const platformRoot = join(root, "platform");
14
+ const premiumPluginsRoot = join(root, "premium-plugins");
15
+ const claudeConfigDir = join(root, "claude-config");
16
+ writeFile(accountConfigPath, JSON.stringify({
17
+ accountId: spec.accountId,
18
+ enabledPlugins: spec.enabledPlugins ?? [],
19
+ tier: spec.tier,
20
+ adminModel: spec.adminModel,
21
+ publicModel: spec.publicModel,
22
+ }));
23
+ writeFile(brandConfigPath, JSON.stringify({
24
+ productName: spec.productName,
25
+ shipsPremiumBundles: spec.shipsPremiumBundles ?? [],
26
+ }));
27
+ const specialistsDir = join(platformRoot, "templates", "specialists", "agents");
28
+ mkdirSync(specialistsDir, { recursive: true });
29
+ for (const name of spec.platformSpecialists) {
30
+ writeFileSync(join(specialistsDir, `${name}.md`), `---\nname: ${name}\n---\n`);
31
+ }
32
+ for (const [bundle, names] of Object.entries(spec.premiumSpecialists ?? {})) {
33
+ const dir = join(premiumPluginsRoot, bundle, "agents");
34
+ mkdirSync(dir, { recursive: true });
35
+ for (const name of names) {
36
+ writeFileSync(join(dir, `${name}.md`), `---\nname: ${name}\n---\n`);
37
+ }
38
+ }
39
+ const agentsDir = join(claudeConfigDir, "agents");
40
+ mkdirSync(agentsDir, { recursive: true });
41
+ for (const name of spec.registeredAgents ?? []) {
42
+ writeFileSync(join(agentsDir, `${name}.md`), `---\nname: ${name}\n---\n`);
43
+ }
44
+ return {
45
+ input: {
46
+ accountId: spec.accountId,
47
+ accountConfigPath,
48
+ brandConfigPath,
49
+ platformRoot,
50
+ premiumPluginsRoot,
51
+ claudeConfigDir,
52
+ },
53
+ };
54
+ }
55
+ describe("resolveCapabilitiesHere", () => {
56
+ let root;
57
+ beforeEach(() => { root = mkdtempSync(join(tmpdir(), "cap-here-")); });
58
+ afterEach(() => { rmSync(root, { recursive: true, force: true }); });
59
+ it("returns Maxy install set with no premium bundles", async () => {
60
+ const { input } = seedTree(root, {
61
+ accountId: "acct-maxy",
62
+ enabledPlugins: ["business-assistant", "sales", "teaching"],
63
+ tier: "pro",
64
+ adminModel: "claude-opus-4-7",
65
+ publicModel: "claude-haiku-4-5",
66
+ productName: "Maxy",
67
+ shipsPremiumBundles: [],
68
+ platformSpecialists: ["personal-assistant", "project-manager", "librarian"],
69
+ registeredAgents: ["plugin:admin:librarian", "plugin:admin:project-manager"],
70
+ });
71
+ const result = await resolveCapabilitiesHere(input, "2026-05-31T07:00:00Z");
72
+ expect(result.accountId).toBe("acct-maxy");
73
+ expect(result.tier).toBe("pro");
74
+ expect(result.enabledPlugins).toEqual(["business-assistant", "sales", "teaching"]);
75
+ expect(result.installedPlatformSpecialists).toEqual(["librarian", "personal-assistant", "project-manager"]);
76
+ expect(result.installedPremiumSpecialists).toEqual([]);
77
+ expect(result.registeredAgentTypes).toEqual(["plugin:admin:librarian", "plugin:admin:project-manager"]);
78
+ expect(result.brand.productName).toBe("Maxy");
79
+ expect(result.brand.shipsPremiumBundles).toEqual([]);
80
+ expect(result.capturedAt).toBe("2026-05-31T07:00:00Z");
81
+ });
82
+ it("returns Real Agent install set including premium specialists from each shipped bundle", async () => {
83
+ const { input } = seedTree(root, {
84
+ accountId: "acct-ra",
85
+ enabledPlugins: ["loop", "property-data", "estate-sales"],
86
+ tier: "agency",
87
+ productName: "Real Agent",
88
+ shipsPremiumBundles: ["real-agent"],
89
+ platformSpecialists: ["coding-assistant", "database-operator"],
90
+ premiumSpecialists: {
91
+ "real-agent": ["negotiator", "valuer", "compliance", "listing-curator"],
92
+ },
93
+ registeredAgents: ["plugin:real-agent:negotiator"],
94
+ });
95
+ const result = await resolveCapabilitiesHere(input, "2026-05-31T07:00:00Z");
96
+ expect(result.brand.productName).toBe("Real Agent");
97
+ expect(result.brand.shipsPremiumBundles).toEqual(["real-agent"]);
98
+ expect(result.installedPlatformSpecialists).toEqual(["coding-assistant", "database-operator"]);
99
+ expect(result.installedPremiumSpecialists).toEqual([
100
+ { bundle: "real-agent", name: "compliance" },
101
+ { bundle: "real-agent", name: "listing-curator" },
102
+ { bundle: "real-agent", name: "negotiator" },
103
+ { bundle: "real-agent", name: "valuer" },
104
+ ]);
105
+ expect(result.registeredAgentTypes).toEqual(["plugin:real-agent:negotiator"]);
106
+ });
107
+ it("handles missing fields and missing directories gracefully", async () => {
108
+ const accountConfigPath = join(root, "account.json");
109
+ const brandConfigPath = join(root, "brand.json");
110
+ writeFileSync(accountConfigPath, JSON.stringify({ accountId: "x" }));
111
+ writeFileSync(brandConfigPath, JSON.stringify({}));
112
+ const result = await resolveCapabilitiesHere({
113
+ accountId: "x",
114
+ accountConfigPath,
115
+ brandConfigPath,
116
+ platformRoot: join(root, "absent-platform"),
117
+ premiumPluginsRoot: join(root, "absent-premium"),
118
+ claudeConfigDir: join(root, "absent-claude"),
119
+ }, "2026-05-31T07:00:00Z");
120
+ expect(result.tier).toBeNull();
121
+ expect(result.adminModel).toBeNull();
122
+ expect(result.publicModel).toBeNull();
123
+ expect(result.enabledPlugins).toEqual([]);
124
+ expect(result.installedPlatformSpecialists).toEqual([]);
125
+ expect(result.installedPremiumSpecialists).toEqual([]);
126
+ expect(result.registeredAgentTypes).toEqual([]);
127
+ expect(result.brand.productName).toBeNull();
128
+ });
129
+ });
130
+ //# sourceMappingURL=capabilities-here.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities-here.test.js","sourceRoot":"","sources":["../../src/__tests__/capabilities-here.test.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,8 @@ import { getSession, closeDriver } from "./lib/neo4j.js";
21
21
  import { findSkillOwners, computePluginReadHint, loadSkill, parseRequiredInputs, adminAuthoringSkillBlock, skillSlugFromReadArgs, AUTHORING_DISPATCH_HINT } from "./skill-resolution.js";
22
22
  import { resolvePublicHostname } from "./lib/public-hostname.js";
23
23
  import { publishSite } from "./tools/publish-site.js";
24
+ import { resolveCapabilitiesHere } from "./tools/capabilities-here.js";
25
+ import { runCatalogueCensus } from "./lib/catalogue-census.js";
24
26
  function refusalGuidance(kind) {
25
27
  switch (kind) {
26
28
  case "unsafe-slug":
@@ -130,6 +132,33 @@ function resolveBrandConfig() {
130
132
  const BRAND_CONFIG = resolveBrandConfig();
131
133
  const CONFIG_DIR = resolve(homedir(), BRAND_CONFIG.configDir);
132
134
  const BRAND_NAME = BRAND_CONFIG.productName;
135
+ // Boot-time catalogue census — emits one [catalogue-census] line per spawn
136
+ // naming any specialist on disk that has no matching reference row in the
137
+ // shipped platform-architecture skill body. Closes the F5 silent-drift
138
+ // blind spot (template added, doc row missed). 24h periodic tick is
139
+ // deferred to Task 562.
140
+ try {
141
+ const brandPath = resolve(PLATFORM_ROOT, "config", "brand.json");
142
+ const brandJson = JSON.parse(readFileSync(brandPath, "utf-8"));
143
+ const shipsBundles = Array.isArray(brandJson.shipsPremiumBundles) ? brandJson.shipsPremiumBundles : [];
144
+ // Census against the shipped skill body — only bundles whose docs/references/
145
+ // tree is baked into the per-brand corpus contribute specialists that the
146
+ // body is expected to row. Bundles without docs/references/ (e.g. writer-craft,
147
+ // venture-studio, teaching today) ship agents but no SKILL body rows, so
148
+ // including them produces F5 false-positives.
149
+ const premiumRoot = resolve(PLATFORM_ROOT, "..", "premium-plugins");
150
+ const enabledBundles = shipsBundles.filter((b) => existsSync(resolve(premiumRoot, b, "docs", "references")));
151
+ const census = runCatalogueCensus({
152
+ platformRoot: PLATFORM_ROOT,
153
+ premiumPluginsRoot: premiumRoot,
154
+ enabledBundles,
155
+ shippedSkillPath: resolve(PLATFORM_ROOT, "plugins", "admin", "skills", "platform-architecture", "SKILL.md"),
156
+ });
157
+ process.stderr.write(`[catalogue-census] disk=${census.diskCount} documented=${census.documentedCount} missing=${census.missing.join(",")} stale=${census.stale.join(",")}\n`);
158
+ }
159
+ catch (err) {
160
+ process.stderr.write(`[catalogue-census] error reason=${err.message}\n`);
161
+ }
133
162
  // Entitlement input shape for the verifier. configDir is rooted under $HOME
134
163
  // (where entitlement.json is delivered post-purchase). platformRoot is needed
135
164
  // because the verifier runs in two bundle contexts (CJS dist for MCP, ESM tsup
@@ -616,6 +645,40 @@ eagerTool(server, "account-manage", "Read the account configuration (tier, domai
616
645
  };
617
646
  }
618
647
  });
648
+ eagerTool(server, "capabilities-here", "Returns the live install set on the current account as a single JSON object: enabledPlugins (account config), tier, adminModel, publicModel, installedPlatformSpecialists (disk), installedPremiumSpecialists (disk, gated by brand.shipsPremiumBundles), registeredAgentTypes (Claude Code agent registry under $CLAUDE_CONFIG_DIR/agents/), and the brand block. Call this whenever you are about to make a claim about what this account can do, what is enabled, or what specialists are dispatchable. Do not infer install state from the platform-architecture skill — that skill is the catalogue of what the platform can ship, not what is enabled here.", {}, async () => {
649
+ if (!ACCOUNT_ID)
650
+ return refuseNoAccount("capabilities-here");
651
+ const requestId = randomUUID();
652
+ const t0 = Date.now();
653
+ process.stderr.write(`[capabilities-here] op=invoke accountId=${ACCOUNT_ID} requestId=${requestId}\n`);
654
+ try {
655
+ const accountConfigPath = join(getAccountDir(), "account.json");
656
+ const brandConfigPath = resolve(PLATFORM_ROOT, "config", "brand.json");
657
+ const premiumPluginsRoot = resolve(PLATFORM_ROOT, "..", "premium-plugins");
658
+ const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude");
659
+ const result = await resolveCapabilitiesHere({
660
+ accountId: ACCOUNT_ID,
661
+ accountConfigPath,
662
+ brandConfigPath,
663
+ platformRoot: PLATFORM_ROOT,
664
+ premiumPluginsRoot,
665
+ claudeConfigDir,
666
+ }, new Date().toISOString());
667
+ const elapsed = Date.now() - t0;
668
+ process.stderr.write(`[capabilities-here] op=resolve requestId=${requestId} enabledPlugins=${result.enabledPlugins.length} platformSpecialists=${result.installedPlatformSpecialists.length} premiumSpecialists=${result.installedPremiumSpecialists.length} agentTypes=${result.registeredAgentTypes.length} elapsedMs=${elapsed}\n`);
669
+ const body = JSON.stringify(result, null, 2);
670
+ process.stderr.write(`[capabilities-here] op=return requestId=${requestId} bytesOut=${body.length}\n`);
671
+ return { content: [{ type: "text", text: body }] };
672
+ }
673
+ catch (err) {
674
+ const msg = err instanceof Error ? err.message : String(err);
675
+ process.stderr.write(`[capabilities-here] op=error requestId=${requestId} reason=${msg}\n`);
676
+ return {
677
+ content: [{ type: "text", text: `capabilities-here failed: ${msg}` }],
678
+ isError: true,
679
+ };
680
+ }
681
+ });
619
682
  eagerTool(server, "account-update", "Update a user-configurable setting in account.json. Valid fields: outputStyle (default|explanatory), thinkingView (default|expanded|collapsed), effort (low|medium|high|max|auto), adminModel (any Anthropic model ID), publicModel (any Anthropic model ID), defaultAgent (slug of an existing public agent, or empty string to clear). Changes take effect on the next session.", {
620
683
  field: z.enum(["outputStyle", "thinkingView", "effort", "adminModel", "publicModel", "defaultAgent"]),
621
684
  value: z.string(),