@rubytech/create-maxy-code 0.1.125 → 0.1.127

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 (78) hide show
  1. package/dist/index.js +23 -1
  2. package/package.json +2 -2
  3. package/payload/platform/config/brand.json +20 -1
  4. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.d.ts +33 -0
  5. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.d.ts.map +1 -0
  6. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.js +119 -0
  7. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.js.map +1 -0
  8. package/payload/platform/lib/aeo-llms-txt-writer/src/index.ts +172 -0
  9. package/payload/platform/lib/aeo-llms-txt-writer/tsconfig.json +8 -0
  10. package/payload/platform/lib/graph-style/dist/index.d.ts +78 -0
  11. package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -0
  12. package/payload/platform/lib/graph-style/dist/index.js +296 -0
  13. package/payload/platform/lib/graph-style/dist/index.js.map +1 -0
  14. package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +114 -0
  15. package/payload/platform/lib/graph-style/src/index.ts +307 -0
  16. package/payload/platform/lib/graph-style/tsconfig.json +9 -0
  17. package/payload/platform/lib/graph-style/vitest.config.ts +9 -0
  18. package/payload/platform/package-lock.json +318 -0
  19. package/payload/platform/package.json +3 -2
  20. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
  21. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  22. package/payload/platform/plugins/admin/PLUGIN.md +4 -1
  23. package/payload/platform/plugins/admin/mcp/dist/index.js +73 -0
  24. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  25. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.d.ts +34 -0
  26. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.d.ts.map +1 -0
  27. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.js +176 -0
  28. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.js.map +1 -0
  29. package/payload/platform/plugins/admin/skills/publish-site/SKILL.md +19 -57
  30. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.d.ts +5 -38
  31. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.d.ts.map +1 -1
  32. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.js +7 -114
  33. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.js.map +1 -1
  34. package/payload/platform/plugins/docs/references/visitor-graph.md +4 -3
  35. package/payload/platform/plugins/graph-viewer/.claude-plugin/plugin.json +8 -0
  36. package/payload/platform/plugins/graph-viewer/PLUGIN.md +56 -0
  37. package/payload/platform/plugins/graph-viewer/mcp/dist/index.d.ts +7 -0
  38. package/payload/platform/plugins/graph-viewer/mcp/dist/index.d.ts.map +1 -0
  39. package/payload/platform/plugins/graph-viewer/mcp/dist/index.js +74 -0
  40. package/payload/platform/plugins/graph-viewer/mcp/dist/index.js.map +1 -0
  41. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.d.ts +5 -0
  42. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.d.ts.map +1 -0
  43. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.js +43 -0
  44. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.js.map +1 -0
  45. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.d.ts +28 -0
  46. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.d.ts.map +1 -0
  47. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.js +73 -0
  48. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.js.map +1 -0
  49. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.d.ts +40 -0
  50. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.d.ts.map +1 -0
  51. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.js +77 -0
  52. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.js.map +1 -0
  53. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.d.ts +45 -0
  54. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.d.ts.map +1 -0
  55. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js +170 -0
  56. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js.map +1 -0
  57. package/payload/platform/plugins/graph-viewer/mcp/package.json +25 -0
  58. package/payload/platform/plugins/graph-viewer/mcp/vitest.config.ts +8 -0
  59. package/payload/platform/plugins/graph-viewer/skills/render-graph/SKILL.md +35 -0
  60. package/payload/platform/scripts/check-plugin-tools-mcp-consistency.mjs +136 -0
  61. package/payload/platform/templates/specialists/agents/content-producer.md +3 -3
  62. package/payload/server/public/assets/{admin-D6IfAzYY.js → admin-FcRHAL-3.js} +7 -7
  63. package/payload/server/public/assets/{data-BGbQyufe.js → data-Ds37mflX.js} +1 -1
  64. package/payload/server/public/assets/{graph-D-1lRTeL.js → graph-CmWRhaiS.js} +1 -1
  65. package/payload/server/public/assets/graph-labels-Ch2r00Gt.js +1 -0
  66. package/payload/server/public/assets/page-BOtNny_4.js +51 -0
  67. package/payload/server/public/assets/page-BcHhJXUt.js +1 -0
  68. package/payload/server/public/consent.css +97 -0
  69. package/payload/server/public/consent.js +259 -0
  70. package/payload/server/public/data.html +3 -3
  71. package/payload/server/public/graph.html +3 -3
  72. package/payload/server/public/index.html +4 -4
  73. package/payload/server/public/privacy.html +68 -5
  74. package/payload/server/public/v.js +53 -0
  75. package/payload/server/server.js +465 -176
  76. package/payload/server/public/assets/graph-labels-BRXJHNYE.js +0 -1
  77. package/payload/server/public/assets/page-B4oirCvn.js +0 -1
  78. package/payload/server/public/assets/page-FmJ7PIYx.js +0 -51
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: render-graph
3
+ description: "Render an inline PNG of a Neo4j subgraph for the operator using the graph-render MCP tool. Use when the operator asks to 'see the graph', 'show me the subgraph around X', 'render the owner subgraph', or any request whose outcome is a picture of nodes-and-edges they can look at in chat. Never substitute Mermaid, ASCII, or any other graph stand-in: graph-render is the only correct surface, and if it refuses (foreign account, missing node, empty neighbourhood, draw error) surface the structured error to the operator and stop. The image uses the same palette and short-label strings as the admin /graph page; node positions will differ because the renderer is d3-force not vis-network."
4
+ ---
5
+
6
+ # render-graph
7
+
8
+ When the operator asks for a picture of a subgraph:
9
+
10
+ 1. Resolve the root node's `elementId` first — usually via `memory-search`
11
+ or another graph tool the operator already pointed you at. Never pass a
12
+ property like `name` as `nodeId`.
13
+ 2. Pick a `hopDepth` between 0 and 3. Default to 1 unless the operator
14
+ asks for the wider neighbourhood. Depth 3 on a busy node will hit the
15
+ 200-node cap and return a `truncated` envelope.
16
+ 3. Call `graph-render` with `{ accountId, nodeId, hopDepth }`.
17
+ 4. If the result is `ok: true`, the image attaches itself to your reply.
18
+ Tell the operator how many nodes are in view and, if `truncated` is
19
+ present, that there were more nodes than the cap.
20
+ 5. If the result is `ok: false`, surface the structured `reason` and
21
+ `message` to the operator verbatim. Do not retry with a different
22
+ nodeId without their input. Do not fall back to Mermaid, ASCII, or any
23
+ other graph substitute.
24
+
25
+ ## Reasons graph-render can refuse
26
+
27
+ - `scope` — the nodeId belongs to a different account, or does not exist.
28
+ - `empty` — the root exists but its neighbourhood is empty after the
29
+ trash filter.
30
+ - `cap-exceeded` — reserved for future use; today subgraphs above 200
31
+ nodes return `ok: true` with a `truncated` envelope.
32
+ - `draw-error` — the canvas renderer failed. The message contains the
33
+ underlying error; if it mentions a missing font, the system font fallback
34
+ is unavailable on this device.
35
+ - `invalid-input` — `hopDepth` was outside the 0-3 range.
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ // Publish-time gate: every PLUGIN.md with a non-empty `tools:` frontmatter
3
+ // block must also declare an `mcp:` block. The `tools:` block populates the
4
+ // `--allowed-tools mcp__<plugin>__*` spawn argv; without a registered MCP
5
+ // server the agent boots with permissions for tools that have no backend.
6
+ //
7
+ // The session manager throws the same defect at boot
8
+ // (tool-surface.ts 'mcp-block-missing'), but boot is on the operator's
9
+ // device — by then the bad payload has already been published and installed.
10
+ // This gate fires before `npm publish`, in the prepublishOnly chain.
11
+ //
12
+ // Live repro: Task 357 added visitor-graph tools to buyers/PLUGIN.md without
13
+ // the matching mcp: block; the slip-through is what motivates Task 368.
14
+
15
+ import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs'
16
+ import { dirname, join, resolve } from 'node:path'
17
+ import { fileURLToPath } from 'node:url'
18
+
19
+ const __dirname = dirname(fileURLToPath(import.meta.url))
20
+ const MAXY_CODE_ROOT = resolve(__dirname, '..', '..')
21
+
22
+ const PLUGIN_ROOTS = [
23
+ // platform/plugins/<plugin>/PLUGIN.md
24
+ { root: join(MAXY_CODE_ROOT, 'platform', 'plugins'), depth: 1 },
25
+ // premium-plugins/<bundle>/PLUGIN.md (shape b)
26
+ { root: join(MAXY_CODE_ROOT, 'premium-plugins'), depth: 1 },
27
+ // premium-plugins/<bundle>/plugins/<sub>/PLUGIN.md (shape a)
28
+ { root: join(MAXY_CODE_ROOT, 'premium-plugins'), depth: 2, mid: 'plugins' },
29
+ ]
30
+
31
+ function collectPluginDirs() {
32
+ const dirs = []
33
+ for (const spec of PLUGIN_ROOTS) {
34
+ if (!existsSync(spec.root)) continue
35
+ for (const entry of readdirSync(spec.root)) {
36
+ if (entry.startsWith('.')) continue
37
+ const lvl1 = join(spec.root, entry)
38
+ if (!statSync(lvl1).isDirectory()) continue
39
+ if (spec.depth === 1) {
40
+ dirs.push(lvl1)
41
+ continue
42
+ }
43
+ const midDir = join(lvl1, spec.mid)
44
+ if (!existsSync(midDir)) continue
45
+ if (!statSync(midDir).isDirectory()) continue
46
+ for (const sub of readdirSync(midDir)) {
47
+ if (sub.startsWith('.')) continue
48
+ const lvl2 = join(midDir, sub)
49
+ if (!statSync(lvl2).isDirectory()) continue
50
+ dirs.push(lvl2)
51
+ }
52
+ }
53
+ }
54
+ return dirs
55
+ }
56
+
57
+ function extractFrontmatter(md) {
58
+ if (!md.startsWith('---')) return null
59
+ const end = md.indexOf('\n---', 3)
60
+ if (end < 0) return null
61
+ return md.slice(3, end)
62
+ }
63
+
64
+ // Detect a top-level key in YAML frontmatter (key at column 0, followed by `:`).
65
+ // The key may be bare (`tools:`) — empty value means "block follows on
66
+ // subsequent indented lines" OR "empty list".
67
+ function findTopLevelKey(frontmatter, key) {
68
+ const re = new RegExp(`^${key}\\s*:`, 'm')
69
+ return re.test(frontmatter)
70
+ }
71
+
72
+ // Returns true when the `tools:` block has at least one list entry. A bare
73
+ // `tools:` with no children, or `tools: []`, is treated as empty (no surface).
74
+ function hasNonEmptyToolsBlock(frontmatter) {
75
+ const lines = frontmatter.split('\n')
76
+ let inTools = false
77
+ for (let i = 0; i < lines.length; i++) {
78
+ const line = lines[i]
79
+ if (/^tools\s*:/.test(line)) {
80
+ const after = line.replace(/^tools\s*:/, '').trim()
81
+ // Inline form: `tools: []` or `tools: [a, b]`
82
+ if (after.startsWith('[')) {
83
+ return /\[\s*[^\]\s]/.test(after)
84
+ }
85
+ if (after) {
86
+ // Single-line scalar (unusual for tools, but treat as non-empty).
87
+ return true
88
+ }
89
+ inTools = true
90
+ continue
91
+ }
92
+ if (inTools) {
93
+ if (/^\S/.test(line) && line.trim() !== '') {
94
+ // Top-level key after tools: — block ended.
95
+ return false
96
+ }
97
+ if (/^\s*-\s+/.test(line)) return true
98
+ }
99
+ }
100
+ return false
101
+ }
102
+
103
+ function checkPlugin(pluginDir) {
104
+ const manifestPath = join(pluginDir, 'PLUGIN.md')
105
+ if (!existsSync(manifestPath)) return null
106
+ const raw = readFileSync(manifestPath, 'utf-8')
107
+ const fm = extractFrontmatter(raw)
108
+ if (fm === null) return null
109
+ if (!hasNonEmptyToolsBlock(fm)) return null
110
+ if (findTopLevelKey(fm, 'mcp')) return null
111
+ return manifestPath
112
+ }
113
+
114
+ function main() {
115
+ const offenders = []
116
+ for (const dir of collectPluginDirs()) {
117
+ const offender = checkPlugin(dir)
118
+ if (offender) offenders.push({ dir, manifestPath: offender })
119
+ }
120
+ if (offenders.length === 0) {
121
+ console.log('[gate] check-plugin-tools-mcp-consistency: PASS')
122
+ return
123
+ }
124
+ for (const { dir, manifestPath } of offenders) {
125
+ const plugin = dir.split('/').pop()
126
+ console.error(
127
+ `[gate] FATAL: plugin=${plugin} has tools: block but no mcp: block.\n` +
128
+ ` manifest: ${manifestPath}\n` +
129
+ ` Spawns would pass --allowed-tools mcp__${plugin}__* with no registered server.\n` +
130
+ ` Add mcp: block or remove tools: entries.`,
131
+ )
132
+ }
133
+ process.exit(1)
134
+ }
135
+
136
+ main()
@@ -3,7 +3,7 @@ name: content-producer
3
3
  description: "Visual production and static-site hosting. Reads from the populated graph to produce visual artifacts (image generation, PDF rendering, component delivery) and hosts already-prepared static sites by extracting attached archives via unzip-attachment then placing the tree under <accountDir>/sites/<slug>/ via publish-site. Delegate for: generating images, saving rendered pages as PDF, or any 'host this website' / 'publish this site' / 'put this online' intent carrying an HTML+assets archive. Not document ingestion: graph ingestion of any kind routes to specialists:database-operator. Static-site zips are extracted to disk for publication, never written to the graph."
4
4
  summary: "Produces visual output from your graph: generates images, renders pages to PDF, and hosts static websites you upload as a zip."
5
5
  model: claude-sonnet-4-6
6
- tools: Bash, mcp__memory__memory-search, mcp__replicate__image-generate, mcp__plugin_playwright_playwright__browser_navigate, mcp__plugin_playwright_playwright__browser_snapshot, mcp__plugin_playwright_playwright__browser_take_screenshot, mcp__plugin_playwright_playwright__browser_pdf_save, mcp__admin__file-attach, mcp__admin__plugin-read, mcp__admin__public-hostname
6
+ tools: Bash, mcp__memory__memory-search, mcp__replicate__image-generate, mcp__plugin_playwright_playwright__browser_navigate, mcp__plugin_playwright_playwright__browser_snapshot, mcp__plugin_playwright_playwright__browser_take_screenshot, mcp__plugin_playwright_playwright__browser_pdf_save, mcp__admin__file-attach, mcp__admin__plugin-read, mcp__admin__public-hostname, mcp__admin__publish-site
7
7
  ---
8
8
 
9
9
  # Content Producer
@@ -34,9 +34,9 @@ Generate the HTML, navigate the Playwright browser to it, and capture with `brow
34
34
 
35
35
  ## Hosting websites
36
36
 
37
- When a brief carries a "host this website" / "publish this site" / "put this online" intent with a `.zip` of HTML and assets, run the two-skill chain in order: `skill-load skillName=unzip-attachment` then `skill-load skillName=publish-site`. Both ship deterministic Bash entries with mechanically enforced invariants (zip-slip guard, slug regex, refusal taxonomy). Follow the skill, do not paraphrase, do not improvise a fallback server.
37
+ When a brief carries a "host this website" / "publish this site" / "put this online" intent with a `.zip` of HTML and assets, run `skill-load skillName=unzip-attachment` to extract, then call `mcp__admin__publish-site` directly. The tool owns slug validation, the symlink scan, the `mv`, the refusal taxonomy, and the post-publish llms.txt refresh — load `skill-load skillName=publish-site` only if you need the intent-router context. Do not improvise a fallback server.
38
38
 
39
- Confirm the slug with the operator before publishing. The slug is one or more `/`-separated segments under `<accountDir>/sites/`. Refusals are loud-fail; relay the operator message verbatim and stop. On success, emit the canonical path slug (`/sites/<slug>/` or `/sites/<slug>/<file>.html`) as one line for the operator to paste after their public-host root.
39
+ Confirm the slug with the operator before publishing. The slug is one or more `/`-separated segments under `<accountDir>/sites/`. Refusals are loud-fail; relay the tool's `Operator action:` line verbatim and stop. On success, take the `pathSlug` from the tool response, call `mcp__admin__public-hostname`, and surface `https://<hostname><pathSlug>` to the operator as one line.
40
40
 
41
41
  ## File delivery
42
42