@rubytech/create-realagent-code 0.1.117 → 0.1.120

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 (137) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/neo4j/schema.cypher +124 -1
  3. package/payload/platform/package-lock.json +141 -125
  4. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
  5. package/payload/platform/plugins/aeo/.claude-plugin/plugin.json +17 -0
  6. package/payload/platform/plugins/aeo/PLUGIN.md +81 -0
  7. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.d.ts +2 -0
  8. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.d.ts.map +1 -0
  9. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.js +121 -0
  10. package/payload/platform/plugins/aeo/mcp/dist/__tests__/audit-heuristics.test.js.map +1 -0
  11. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.d.ts +2 -0
  12. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.d.ts.map +1 -0
  13. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.js +129 -0
  14. package/payload/platform/plugins/aeo/mcp/dist/__tests__/schema-mapping.test.js.map +1 -0
  15. package/payload/platform/plugins/aeo/mcp/dist/index.d.ts +2 -0
  16. package/payload/platform/plugins/aeo/mcp/dist/index.d.ts.map +1 -0
  17. package/payload/platform/plugins/aeo/mcp/dist/index.js +171 -0
  18. package/payload/platform/plugins/aeo/mcp/dist/index.js.map +1 -0
  19. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.d.ts +27 -0
  20. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.d.ts.map +1 -0
  21. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.js +274 -0
  22. package/payload/platform/plugins/aeo/mcp/dist/lib/audit-heuristics.js.map +1 -0
  23. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.d.ts +5 -0
  24. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.d.ts.map +1 -0
  25. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.js +38 -0
  26. package/payload/platform/plugins/aeo/mcp/dist/lib/neo4j.js.map +1 -0
  27. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.d.ts +48 -0
  28. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.d.ts.map +1 -0
  29. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.js +254 -0
  30. package/payload/platform/plugins/aeo/mcp/dist/lib/schema-mapping.js.map +1 -0
  31. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.d.ts +25 -0
  32. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.d.ts.map +1 -0
  33. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.js +78 -0
  34. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-audit-page.js.map +1 -0
  35. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.d.ts +18 -0
  36. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.d.ts.map +1 -0
  37. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.js +56 -0
  38. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-emit-jsonld.js.map +1 -0
  39. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.d.ts +37 -0
  40. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.d.ts.map +1 -0
  41. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.js +94 -0
  42. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.js.map +1 -0
  43. package/payload/platform/plugins/aeo/mcp/package.json +22 -0
  44. package/payload/platform/plugins/aeo/mcp/vitest.config.ts +9 -0
  45. package/payload/platform/plugins/aeo/skills/structured-answer/SKILL.md +53 -0
  46. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.d.ts +12 -1
  47. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.d.ts.map +1 -1
  48. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js +34 -1
  49. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js.map +1 -1
  50. package/payload/platform/plugins/docs/references/aeo.md +87 -0
  51. package/payload/platform/plugins/docs/references/visitor-graph.md +82 -0
  52. package/payload/platform/plugins/email/PLUGIN.md +6 -0
  53. package/payload/platform/plugins/email/skills/email-composition/SKILL.md +180 -0
  54. package/payload/platform/plugins/memory/mcp/dist/index.js +5 -0
  55. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  56. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.d.ts +2 -0
  57. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.d.ts.map +1 -0
  58. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.js +62 -0
  59. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-origin-gate.test.js.map +1 -0
  60. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.d.ts +18 -0
  61. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.d.ts.map +1 -0
  62. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.js +29 -0
  63. package/payload/platform/plugins/memory/mcp/dist/lib/label-origin-gate.js.map +1 -0
  64. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js +2 -0
  65. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js.map +1 -1
  66. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js +1 -1
  67. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js.map +1 -1
  68. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts +3 -0
  69. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
  70. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +9 -1
  71. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
  72. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
  73. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +8 -0
  74. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  75. package/payload/platform/plugins/memory/mcp/vitest.config.ts +2 -0
  76. package/payload/platform/plugins/memory/references/schema-base.md +49 -1
  77. package/payload/platform/scripts/smoke-boot-services.sh +30 -2
  78. package/payload/platform/templates/specialists/agents/signal-detector.md +1 -1
  79. package/payload/premium-plugins/real-agent/plugins/buyers/.claude-plugin/plugin.json +1 -1
  80. package/payload/premium-plugins/real-agent/plugins/buyers/PLUGIN.md +33 -3
  81. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/index.d.ts +2 -0
  82. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/index.d.ts.map +1 -0
  83. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/index.js +97 -0
  84. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/index.js.map +1 -0
  85. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/lib/neo4j.d.ts +5 -0
  86. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/lib/neo4j.d.ts.map +1 -0
  87. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/lib/neo4j.js +40 -0
  88. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/lib/neo4j.js.map +1 -0
  89. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-backfill-from-logs.d.ts +24 -0
  90. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-backfill-from-logs.d.ts.map +1 -0
  91. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-backfill-from-logs.js +156 -0
  92. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-backfill-from-logs.js.map +1 -0
  93. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-engagement-score.d.ts +21 -0
  94. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-engagement-score.d.ts.map +1 -0
  95. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-engagement-score.js +65 -0
  96. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-engagement-score.js.map +1 -0
  97. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-event-ingest.d.ts +26 -0
  98. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-event-ingest.d.ts.map +1 -0
  99. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-event-ingest.js +78 -0
  100. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-event-ingest.js.map +1 -0
  101. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recent-by-page.d.ts +19 -0
  102. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recent-by-page.d.ts.map +1 -0
  103. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recent-by-page.js +41 -0
  104. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recent-by-page.js.map +1 -0
  105. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recent-by-person.d.ts +20 -0
  106. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recent-by-person.d.ts.map +1 -0
  107. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recent-by-person.js +44 -0
  108. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recent-by-person.js.map +1 -0
  109. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recommendation-ctr.d.ts +22 -0
  110. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recommendation-ctr.d.ts.map +1 -0
  111. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recommendation-ctr.js +41 -0
  112. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-recommendation-ctr.js.map +1 -0
  113. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-session-detail.d.ts +32 -0
  114. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-session-detail.d.ts.map +1 -0
  115. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-session-detail.js +87 -0
  116. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/tools/visitor-session-detail.js.map +1 -0
  117. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/package-lock.json +2566 -0
  118. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/package.json +21 -0
  119. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/index.ts +145 -0
  120. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/lib/neo4j.ts +45 -0
  121. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/tools/visitor-backfill-from-logs.ts +189 -0
  122. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/tools/visitor-engagement-score.ts +87 -0
  123. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/tools/visitor-event-ingest.ts +119 -0
  124. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/tools/visitor-recent-by-page.ts +61 -0
  125. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/tools/visitor-recent-by-person.ts +65 -0
  126. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/tools/visitor-recommendation-ctr.ts +67 -0
  127. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/tools/visitor-session-detail.ts +127 -0
  128. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/tsconfig.json +20 -0
  129. package/payload/premium-plugins/real-agent/plugins/buyers/skills/property-recommender/SKILL.md +11 -0
  130. package/payload/premium-plugins/real-agent/plugins/leads/skills/lead-nurturing/SKILL.md +9 -0
  131. package/payload/premium-plugins/real-agent/plugins/leads/skills/morning-round/SKILL.md +11 -0
  132. package/payload/premium-plugins/real-agent/plugins/vendors/skills/vendor-updates/SKILL.md +13 -0
  133. package/payload/server/{chunk-FJCI6X3H.js → chunk-HCYM5FLU.js} +2 -0
  134. package/payload/server/maxy-edge.js +1 -1
  135. package/payload/server/public/privacy.html +66 -0
  136. package/payload/server/public/v.js +191 -0
  137. package/payload/server/server.js +473 -85
@@ -0,0 +1,25 @@
1
+ import { type AuditResult } from "../lib/audit-heuristics.js";
2
+ export interface AuditPageInput {
3
+ accountId: string;
4
+ /** Provide one of `url` or `html`. */
5
+ url?: string;
6
+ html?: string;
7
+ /**
8
+ * When true, the audit result is persisted as an `:AEOAudit` node
9
+ * with `HAS_AEO_AUDIT` edge from `targetKnowledgeDocumentId` (if
10
+ * given) or the synthetic `targetUrl` audit history.
11
+ */
12
+ persist?: boolean;
13
+ targetKnowledgeDocumentId?: string;
14
+ agentSlug?: string;
15
+ sessionId?: string;
16
+ }
17
+ export interface AuditPageResult extends AuditResult {
18
+ target: string;
19
+ audit: {
20
+ elementId?: string;
21
+ runAt: string;
22
+ };
23
+ }
24
+ export declare function auditPage(input: AuditPageInput): Promise<AuditPageResult>;
25
+ //# sourceMappingURL=aeo-audit-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-audit-page.d.ts","sourceRoot":"","sources":["../../src/tools/aeo-audit-page.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGzE,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAgB,SAAQ,WAAW;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QACL,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAeD,wBAAsB,SAAS,CAC7B,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,eAAe,CAAC,CA2E1B"}
@@ -0,0 +1,78 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { auditHtml } from "../lib/audit-heuristics.js";
3
+ import { getSession } from "../lib/neo4j.js";
4
+ async function fetchHtml(url) {
5
+ const res = await fetch(url, {
6
+ redirect: "follow",
7
+ headers: { "User-Agent": "maxy-aeo-audit/0.1" },
8
+ });
9
+ if (!res.ok) {
10
+ throw new Error(`aeo-audit-page: GET ${url} returned HTTP ${res.status}`);
11
+ }
12
+ return await res.text();
13
+ }
14
+ export async function auditPage(input) {
15
+ if (!input.url && !input.html) {
16
+ throw new Error("aeo-audit-page requires one of url or html");
17
+ }
18
+ if (input.url && input.html) {
19
+ throw new Error("aeo-audit-page: pass exactly one of url or html, not both");
20
+ }
21
+ const html = input.html ?? (await fetchHtml(input.url));
22
+ const target = input.url ?? "(inline html)";
23
+ const result = auditHtml(html);
24
+ const runAt = new Date().toISOString();
25
+ const fails = result.heuristics
26
+ .filter((h) => h.status === "fail")
27
+ .map((h) => h.name);
28
+ const warns = result.heuristics
29
+ .filter((h) => h.status === "warn")
30
+ .map((h) => h.name);
31
+ process.stderr.write(`[aeo-audit] target=${target} score=${result.score} fails=${fails.join(",") || "-"} warns=${warns.join(",") || "-"}\n`);
32
+ let elementId;
33
+ if (input.persist) {
34
+ const auditId = randomUUID();
35
+ const session = getSession();
36
+ try {
37
+ const r = await session.run(`CREATE (a:AEOAudit {
38
+ accountId: $accountId,
39
+ auditId: $auditId,
40
+ target: $target,
41
+ score: $score,
42
+ heuristicsJson: $heuristicsJson,
43
+ runAt: $runAt,
44
+ createdByAgent: $agent,
45
+ createdBySession: $session,
46
+ createdAt: $runAt
47
+ })
48
+ WITH a
49
+ OPTIONAL MATCH (d:KnowledgeDocument)
50
+ WHERE elementId(d) = $kdocId AND d.accountId = $accountId
51
+ FOREACH (_ IN CASE WHEN d IS NULL THEN [] ELSE [1] END |
52
+ MERGE (d)-[:HAS_AEO_AUDIT]->(a)
53
+ )
54
+ RETURN elementId(a) AS id`, {
55
+ accountId: input.accountId,
56
+ auditId,
57
+ target,
58
+ score: result.score,
59
+ heuristicsJson: JSON.stringify(result.heuristics),
60
+ runAt,
61
+ agent: input.agentSlug ?? "system",
62
+ session: input.sessionId ?? null,
63
+ kdocId: input.targetKnowledgeDocumentId ?? null,
64
+ });
65
+ elementId = r.records[0]?.get("id");
66
+ process.stderr.write(`[aeo-audit] persisted auditId=${auditId} elementId=${elementId ?? "-"}\n`);
67
+ }
68
+ finally {
69
+ await session.close();
70
+ }
71
+ }
72
+ return {
73
+ ...result,
74
+ target,
75
+ audit: { elementId, runAt },
76
+ };
77
+ }
78
+ //# sourceMappingURL=aeo-audit-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-audit-page.js","sourceRoot":"","sources":["../../src/tools/aeo-audit-page.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { MissingPropertyError, type JsonLdObject } from "../lib/schema-mapping.js";
2
+ export interface EmitJsonLdInput {
3
+ accountId: string;
4
+ /** Pull entity from the graph by Neo4j elementId. */
5
+ entityId?: string;
6
+ /** Or render a JSON-LD block from an inline label + property bag. */
7
+ label?: string;
8
+ properties?: Record<string, unknown>;
9
+ }
10
+ export interface EmitJsonLdResult {
11
+ jsonLd: JsonLdObject;
12
+ scriptBlock: string;
13
+ schemaType: string;
14
+ source: "graph" | "inline";
15
+ }
16
+ export declare function emitJsonLd(input: EmitJsonLdInput): Promise<EmitJsonLdResult>;
17
+ export { MissingPropertyError };
18
+ //# sourceMappingURL=aeo-emit-jsonld.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-emit-jsonld.d.ts","sourceRoot":"","sources":["../../src/tools/aeo-emit-jsonld.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,oBAAoB,EACpB,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC5B;AAMD,wBAAsB,UAAU,CAC9B,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,gBAAgB,CAAC,CA8D3B;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ import { buildJsonLd, renderJsonLdScript, MissingPropertyError, } from "../lib/schema-mapping.js";
3
+ function isPropertyBag(v) {
4
+ return typeof v === "object" && v !== null && !Array.isArray(v);
5
+ }
6
+ export async function emitJsonLd(input) {
7
+ if (!input.entityId && !input.label) {
8
+ throw new Error("aeo-emit-jsonld requires either entityId or label+properties");
9
+ }
10
+ if (input.entityId) {
11
+ const session = getSession();
12
+ try {
13
+ const r = await session.run(`MATCH (n) WHERE elementId(n) = $id AND n.accountId = $accountId
14
+ RETURN labels(n) AS labels, properties(n) AS props, elementId(n) AS id LIMIT 1`, { id: input.entityId, accountId: input.accountId });
15
+ if (r.records.length === 0) {
16
+ throw new Error(`aeo-emit-jsonld: no node with elementId=${input.entityId} in account=${input.accountId}`);
17
+ }
18
+ const rec = r.records[0];
19
+ const labels = rec.get("labels");
20
+ const props = rec.get("props");
21
+ const id = rec.get("id");
22
+ const primaryLabel = labels.find((l) => l !== "Resource") ?? labels[0];
23
+ const obj = buildJsonLd({
24
+ label: primaryLabel,
25
+ elementId: id,
26
+ properties: props,
27
+ });
28
+ process.stderr.write(`[aeo-emit-jsonld] entityId=${id} schemaType=${obj["@type"]} source=graph\n`);
29
+ return {
30
+ jsonLd: obj,
31
+ scriptBlock: renderJsonLdScript(obj),
32
+ schemaType: obj["@type"],
33
+ source: "graph",
34
+ };
35
+ }
36
+ finally {
37
+ await session.close();
38
+ }
39
+ }
40
+ if (!input.label || !isPropertyBag(input.properties)) {
41
+ throw new Error("aeo-emit-jsonld: label requires a properties object");
42
+ }
43
+ const obj = buildJsonLd({
44
+ label: input.label,
45
+ properties: input.properties,
46
+ });
47
+ process.stderr.write(`[aeo-emit-jsonld] label=${input.label} schemaType=${obj["@type"]} source=inline\n`);
48
+ return {
49
+ jsonLd: obj,
50
+ scriptBlock: renderJsonLdScript(obj),
51
+ schemaType: obj["@type"],
52
+ source: "inline",
53
+ };
54
+ }
55
+ export { MissingPropertyError };
56
+ //# sourceMappingURL=aeo-emit-jsonld.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-emit-jsonld.js","sourceRoot":"","sources":["../../src/tools/aeo-emit-jsonld.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Generates the `llms.txt` and `llms-full.txt` pair for an account's
3
+ * published content. Format follows the current llmstxt.org draft:
4
+ *
5
+ * # <Site name>
6
+ * > <Short description>
7
+ *
8
+ * ## <Section name>
9
+ * - [<Title>](<URL>): <Summary>
10
+ *
11
+ * `llms-full.txt` concatenates the full text of every listed page in
12
+ * the same order, separated by a blank line and the page's title as an
13
+ * H1.
14
+ *
15
+ * Source: `KnowledgeDocument` nodes for the account that have a `url`
16
+ * property. `summary` and `body` properties feed the index and the
17
+ * concatenated dump respectively. Pages without a `url` are skipped
18
+ * (they aren't reachable from a public site), and the count of skipped
19
+ * pages is returned so the operator can audit completeness.
20
+ */
21
+ export interface WriteLlmsTxtInput {
22
+ accountId: string;
23
+ siteName: string;
24
+ siteDescription?: string;
25
+ }
26
+ export interface WriteLlmsTxtResult {
27
+ llmsTxt: string;
28
+ llmsFullTxt: string;
29
+ pageCount: number;
30
+ skippedNoUrl: number;
31
+ sizeBytes: {
32
+ index: number;
33
+ full: number;
34
+ };
35
+ }
36
+ export declare function writeLlmsTxt(input: WriteLlmsTxtInput): Promise<WriteLlmsTxtResult>;
37
+ //# sourceMappingURL=aeo-write-llms-txt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-write-llms-txt.d.ts","sourceRoot":"","sources":["../../src/tools/aeo-write-llms-txt.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAqBD,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,kBAAkB,CAAC,CA4F7B"}
@@ -0,0 +1,94 @@
1
+ import { getSession } from "../lib/neo4j.js";
2
+ const HEADER_RX = /^#\s/m;
3
+ function escapeMarkdown(text) {
4
+ return text.replace(/[\[\]\(\)\n\r]/g, " ").trim();
5
+ }
6
+ function summariseBody(body) {
7
+ const flat = body.replace(/\s+/g, " ").trim();
8
+ if (flat.length <= 200)
9
+ return flat;
10
+ return flat.slice(0, 197).trimEnd() + "…";
11
+ }
12
+ export async function writeLlmsTxt(input) {
13
+ const session = getSession();
14
+ let rows = [];
15
+ let skippedNoUrl = 0;
16
+ try {
17
+ const r = await session.run(`MATCH (d:KnowledgeDocument {accountId: $accountId})
18
+ RETURN d.title AS title, d.url AS url, d.summary AS summary,
19
+ coalesce(d.body, d.abstract, '') AS body
20
+ ORDER BY d.title ASC`, { accountId: input.accountId });
21
+ for (const rec of r.records) {
22
+ const title = rec.get("title") ?? "";
23
+ const url = rec.get("url") ?? "";
24
+ const summary = rec.get("summary") ?? "";
25
+ const body = rec.get("body") ?? "";
26
+ if (!url || !title) {
27
+ skippedNoUrl += 1;
28
+ continue;
29
+ }
30
+ rows.push({
31
+ title: escapeMarkdown(title),
32
+ url: url.trim(),
33
+ summary: escapeMarkdown(summary) || summariseBody(body) || "(no summary)",
34
+ body: body.trim(),
35
+ });
36
+ }
37
+ }
38
+ finally {
39
+ await session.close();
40
+ }
41
+ const indexLines = [];
42
+ indexLines.push(`# ${escapeMarkdown(input.siteName)}`);
43
+ indexLines.push("");
44
+ if (input.siteDescription) {
45
+ indexLines.push(`> ${escapeMarkdown(input.siteDescription)}`);
46
+ indexLines.push("");
47
+ }
48
+ indexLines.push("## Pages");
49
+ indexLines.push("");
50
+ for (const row of rows) {
51
+ indexLines.push(`- [${row.title}](${row.url}): ${row.summary}`);
52
+ }
53
+ indexLines.push("");
54
+ indexLines.push("<!-- generated by @maxy/aeo aeo-write-llms-txt; spec: https://llmstxt.org/ -->");
55
+ const llmsTxt = indexLines.join("\n");
56
+ const fullLines = [];
57
+ fullLines.push(`# ${escapeMarkdown(input.siteName)}`);
58
+ fullLines.push("");
59
+ if (input.siteDescription) {
60
+ fullLines.push(`> ${escapeMarkdown(input.siteDescription)}`);
61
+ fullLines.push("");
62
+ }
63
+ for (const row of rows) {
64
+ fullLines.push(`# ${row.title}`);
65
+ fullLines.push("");
66
+ fullLines.push(`Source: ${row.url}`);
67
+ fullLines.push("");
68
+ if (row.body) {
69
+ // Demote any in-body H1s to H2 so a single H1 hierarchy holds.
70
+ const safeBody = row.body.replace(HEADER_RX, "## ");
71
+ fullLines.push(safeBody);
72
+ }
73
+ else {
74
+ fullLines.push(row.summary);
75
+ }
76
+ fullLines.push("");
77
+ fullLines.push("---");
78
+ fullLines.push("");
79
+ }
80
+ const llmsFullTxt = fullLines.join("\n");
81
+ const sizeBytes = {
82
+ index: Buffer.byteLength(llmsTxt, "utf-8"),
83
+ full: Buffer.byteLength(llmsFullTxt, "utf-8"),
84
+ };
85
+ process.stderr.write(`[aeo-llms-txt] site=${input.siteName} pages=${rows.length} skippedNoUrl=${skippedNoUrl} indexBytes=${sizeBytes.index} fullBytes=${sizeBytes.full}\n`);
86
+ return {
87
+ llmsTxt,
88
+ llmsFullTxt,
89
+ pageCount: rows.length,
90
+ skippedNoUrl,
91
+ sizeBytes,
92
+ };
93
+ }
94
+ //# sourceMappingURL=aeo-write-llms-txt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aeo-write-llms-txt.js","sourceRoot":"","sources":["../../src/tools/aeo-write-llms-txt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@maxy/aeo",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "start": "node dist/index.js",
10
+ "test": "vitest run"
11
+ },
12
+ "dependencies": {
13
+ "@modelcontextprotocol/sdk": "^1.12.1",
14
+ "neo4j-driver": "^5.28.1",
15
+ "zod": "^3.24.0"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^5.7.0",
19
+ "@types/node": "^22.0.0",
20
+ "vitest": "^4.1.2"
21
+ }
22
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: "node",
6
+ include: ["src/**/__tests__/**/*.test.ts"],
7
+ testTimeout: 10_000,
8
+ },
9
+ });
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: structured-answer
3
+ description: Use when authoring or auditing a page whose primary purpose is to answer a single question — service pages, FAQ entries, "what is X" pages, comparison pages. Defines the page shape that answer engines lift verbatim. Triggers include "make this AEO-friendly", "structure this for Claude / ChatGPT", "audit this page for answer-engine pickup".
4
+ ---
5
+
6
+ # Structured-answer page template
7
+
8
+ Answer engines (Claude, ChatGPT, Perplexity, Google AI Overviews, Bing Copilot) lift a single short span when they cite a page. That span is almost always the first paragraph after the H1, when it is short and direct. Every other element on the page either supports the lift or gets ignored.
9
+
10
+ ## The shape
11
+
12
+ ```
13
+ <head>
14
+ <title>{question or topic} — {site name}</title>
15
+ <meta name="description" content="{80–160 char summary of the answer}">
16
+ <link rel="canonical" href="{this page's URL}">
17
+ <meta property="og:title" content="{question or topic}">
18
+ <meta property="og:description" content="{same as meta description}">
19
+ <script type="application/ld+json">{ emit via aeo-emit-jsonld }</script>
20
+ </head>
21
+
22
+ <body>
23
+ <h1>{question or topic}</h1>
24
+ <p>{≤280 characters. The answer. One sentence preferred. Names the entity, states the answer, ends on a fact.}</p>
25
+
26
+ <h2>{follow-up section}</h2>
27
+ <p>{details, examples, links}</p>
28
+
29
+ <h2>Frequently asked questions</h2>
30
+ <!-- emit FAQPage JSON-LD with 3–5 Question / Answer pairs -->
31
+ </body>
32
+ ```
33
+
34
+ ## Why this works
35
+
36
+ - The H1 names the question; the first `<p>` is the answer. Engines treat that pair as a structured Q/A.
37
+ - The `<p>` is short enough to be lifted whole. Longer paragraphs get truncated mid-sentence.
38
+ - The JSON-LD repeats the structured data in a parser-friendly form so engines that index pre-render don't have to scrape the DOM.
39
+ - The FAQ section adds a second class of lift target — engines often cite an FAQ answer when the page's main question is too broad.
40
+
41
+ ## What breaks the lift
42
+
43
+ - A multi-sentence first paragraph. The engine truncates and the citation reads like a fragment.
44
+ - Marketing prose before the answer ("In today's fast-moving world…"). The engine lifts the marketing prose, not the answer.
45
+ - The H1 stating the brand instead of the question. "Acme Plumbing" is not a question; "How much does a boiler service cost?" is.
46
+ - Missing JSON-LD. Engines that pre-render the page still index the DOM, but they down-weight pages without structured data.
47
+ - Skipped heading levels. Engines use heading hierarchy to decide which content is the answer and which is supporting detail.
48
+
49
+ ## How to audit
50
+
51
+ Run `aeo-audit-page` against the URL or HTML. Eight heuristics return pass / warn / fail. Treat any `fail` as a blocker — the rewrite suggestion in the response is concrete. Treat `warn` as a polish target.
52
+
53
+ To record the audit on the document for trend analysis, pass `persist: true` with the document's `elementId` as `targetKnowledgeDocumentId`. The plugin writes an `:AEOAudit` node linked via `HAS_AEO_AUDIT`.
@@ -6,7 +6,12 @@
6
6
  * 2. Conversations left empty after message removal
7
7
  * 3. Emails matching the contact's email (fromAddress or toAddresses)
8
8
  * 4. AccessGrants via (Person)-[:HAS_ACCESS]->(AccessGrant)
9
- * 5. Person node itself (DETACH DELETE)
9
+ * 5. Visitor-graph data (Task 357):
10
+ * - :Session reachable via (Person)-[:VISITED]->(Session)
11
+ * - all :HAS_EVENT children (PageView/Click/ScrollMilestone)
12
+ * - :AnonVisitor via (Person)-[:OWNS_VISITOR]->(AnonVisitor)
13
+ * :Page and :Listing are content metadata and are intentionally preserved.
14
+ * 6. Person node itself (DETACH DELETE)
10
15
  *
11
16
  * Requires `confirm: true` to execute. Without it, returns a preview
12
17
  * of what would be deleted (counts per node type) but does not delete.
@@ -33,6 +38,12 @@ interface EraseCounts {
33
38
  conversations: number;
34
39
  emails: number;
35
40
  accessGrants: number;
41
+ /** Visitor-graph Sessions removed (Task 357). */
42
+ visitorSessions: number;
43
+ /** Visitor-graph event nodes removed (PageView + Click + ScrollMilestone). */
44
+ visitorEvents: number;
45
+ /** AnonVisitor nodes owned by this Person and removed. */
46
+ anonVisitors: number;
36
47
  person: number;
37
48
  }
38
49
  export type ContactEraseResult = ErasePreview | EraseReceipt;
@@ -1 +1 @@
1
- {"version":3,"file":"contact-erase.d.ts","sourceRoot":"","sources":["../../src/tools/contact-erase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,UAAU,kBAAkB;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,YAAY;IACpB,SAAS,EAAE,KAAK,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,UAAU,YAAY;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,UAAU,WAAW;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,YAAY,CAAC;AAE7D,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CAsL7B"}
1
+ {"version":3,"file":"contact-erase.d.ts","sourceRoot":"","sources":["../../src/tools/contact-erase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,UAAU,kBAAkB;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,YAAY;IACpB,SAAS,EAAE,KAAK,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,UAAU,YAAY;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,UAAU,WAAW;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,eAAe,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,YAAY,CAAC;AAE7D,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CA6N7B"}
@@ -6,7 +6,12 @@
6
6
  * 2. Conversations left empty after message removal
7
7
  * 3. Emails matching the contact's email (fromAddress or toAddresses)
8
8
  * 4. AccessGrants via (Person)-[:HAS_ACCESS]->(AccessGrant)
9
- * 5. Person node itself (DETACH DELETE)
9
+ * 5. Visitor-graph data (Task 357):
10
+ * - :Session reachable via (Person)-[:VISITED]->(Session)
11
+ * - all :HAS_EVENT children (PageView/Click/ScrollMilestone)
12
+ * - :AnonVisitor via (Person)-[:OWNS_VISITOR]->(AnonVisitor)
13
+ * :Page and :Listing are content metadata and are intentionally preserved.
14
+ * 6. Person node itself (DETACH DELETE)
10
15
  *
11
16
  * Requires `confirm: true` to execute. Without it, returns a preview
12
17
  * of what would be deleted (counts per node type) but does not delete.
@@ -45,8 +50,27 @@ export async function contactErase(params) {
45
50
  conversations: 0,
46
51
  emails: 0,
47
52
  accessGrants: 0,
53
+ visitorSessions: 0,
54
+ visitorEvents: 0,
55
+ anonVisitors: 0,
48
56
  person: 1,
49
57
  };
58
+ // Count visitor-graph data — Sessions, events, AnonVisitors (Task 357)
59
+ {
60
+ const visitorCounts = await session.run(`MATCH (p:Person) WHERE elementId(p) = $personNodeId
61
+ OPTIONAL MATCH (p)-[:VISITED]->(vs:Session)
62
+ OPTIONAL MATCH (vs)-[:HAS_EVENT]->(ev)
63
+ OPTIONAL MATCH (p)-[:OWNS_VISITOR]->(av:AnonVisitor)
64
+ RETURN count(DISTINCT vs) AS visitorSessions,
65
+ count(DISTINCT ev) AS visitorEvents,
66
+ count(DISTINCT av) AS anonVisitors`, { personNodeId });
67
+ if (visitorCounts.records.length > 0) {
68
+ const row = visitorCounts.records[0];
69
+ counts.visitorSessions = Number(row.get("visitorSessions")?.valueOf?.() ?? row.get("visitorSessions") ?? 0);
70
+ counts.visitorEvents = Number(row.get("visitorEvents")?.valueOf?.() ?? row.get("visitorEvents") ?? 0);
71
+ counts.anonVisitors = Number(row.get("anonVisitors")?.valueOf?.() ?? row.get("anonVisitors") ?? 0);
72
+ }
73
+ }
50
74
  // Count Messages + Conversations via sessionId
51
75
  if (sessionId) {
52
76
  const convCountResult = await session.run(`MATCH (c:Conversation {conversationId: $sessionId, accountId: $accountId})
@@ -107,6 +131,15 @@ export async function contactErase(params) {
107
131
  await tx.run(`MATCH (p:Person)-[:HAS_ACCESS]->(g:AccessGrant)
108
132
  WHERE elementId(p) = $personNodeId
109
133
  DELETE g`, { personNodeId });
134
+ // 3d-bis. Visitor-graph cascade (Task 357). :Page and :Listing are
135
+ // content metadata and intentionally preserved — they have no PII.
136
+ await tx.run(`MATCH (p:Person) WHERE elementId(p) = $personNodeId
137
+ OPTIONAL MATCH (p)-[:VISITED]->(vs:Session)
138
+ OPTIONAL MATCH (vs)-[:HAS_EVENT]->(ev)
139
+ DETACH DELETE ev, vs`, { personNodeId });
140
+ await tx.run(`MATCH (p:Person)-[:OWNS_VISITOR]->(av:AnonVisitor)
141
+ WHERE elementId(p) = $personNodeId
142
+ DETACH DELETE av`, { personNodeId });
110
143
  // 3e. Delete Person node (DETACH DELETE to remove any remaining relationships)
111
144
  await tx.run(`MATCH (p:Person) WHERE elementId(p) = $personNodeId
112
145
  DETACH DELETE p`, { personNodeId });
@@ -1 +1 @@
1
- {"version":3,"file":"contact-erase.js","sourceRoot":"","sources":["../../src/tools/contact-erase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contact-erase.js","sourceRoot":"","sources":["../../src/tools/contact-erase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ # AEO (Answer Engine Optimisation) — user guide
2
+
3
+ The AEO plugin shapes the site for answer engines (Claude, ChatGPT, Perplexity, Google AI Overviews, Bing Copilot). It does three things: emits schema.org JSON-LD from typed graph entities, generates `/llms.txt` and `/llms-full.txt`, and audits any page against eight heuristics.
4
+
5
+ ## When to use it
6
+
7
+ - A new page is being authored and you want it to be cited when customers ask an answer engine about your service.
8
+ - An existing page is not being cited. Audit it to find the structural reasons.
9
+ - You're standing up a new site and want the `llms.txt` pair generated so answer engines can index your content directly.
10
+
11
+ ## The tools
12
+
13
+ ### `aeo-emit-jsonld`
14
+
15
+ Generates a `<script type="application/ld+json">` block for a typed entity. Two modes:
16
+
17
+ - **From the graph.** Pass `entityId` (Neo4j elementId of an `Organization`, `Person`, `Service`, `Product`, `CreativeWork`, `FAQPage`, `RealEstateListing`, or `Event`). The tool resolves the entity, maps the label to its schema.org type, and emits the block.
18
+ - **Inline.** Pass `label` (one of the supported page types) plus a `properties` object. Use this when the page isn't backed by a stored entity (yet) but you want the JSON-LD shape.
19
+
20
+ Returns the parsed JSON-LD object and a ready-to-inline script block string. Inline the script in your page `<head>`.
21
+
22
+ ### `aeo-write-llms-txt`
23
+
24
+ Generates the `llms.txt` / `llms-full.txt` pair for the account. Source is every `KnowledgeDocument` for the account that has a `url` property. Returns both files as strings plus a count of pages skipped because they had no URL.
25
+
26
+ Wire the output to your site host. Convention: `/llms.txt` (index) and `/llms-full.txt` (concatenated content), served as `text/plain`. Format follows the current draft at `https://llmstxt.org/`.
27
+
28
+ ### `aeo-audit-page`
29
+
30
+ Runs the eight-heuristic audit. Pass either `url` (the tool fetches) or `html` (you supply the rendered content). Returns:
31
+
32
+ ```
33
+ {
34
+ "score": 0–100,
35
+ "heuristics": [
36
+ {
37
+ "name": "structured-answer",
38
+ "status": "pass" | "warn" | "fail",
39
+ "detail": "first <p> after <h1> is 142 chars",
40
+ "suggestion": "Add one ≤280-character <p> immediately after the <h1>…"
41
+ },
42
+
43
+ ],
44
+ "target": "<url or '(inline html)'>",
45
+ "audit": { "runAt": "<iso>", "elementId": "<set when persisted>" }
46
+ }
47
+ ```
48
+
49
+ Pass `persist: true` plus `targetKnowledgeDocumentId` to write the result as an `:AEOAudit` node linked to the document.
50
+
51
+ ## The eight heuristics
52
+
53
+ | Heuristic | What it checks |
54
+ |---|---|
55
+ | `h1-present` | exactly one `<h1>` |
56
+ | `jsonld-present` | at least one parseable JSON-LD block |
57
+ | `structured-answer` | first `<p>` after `<h1>` is ≤280 chars |
58
+ | `faq-section` | `FAQPage` JSON-LD on the page |
59
+ | `meta-description` | 80–160 char `<meta name="description">` |
60
+ | `canonical-url` | `<link rel="canonical">` present |
61
+ | `og-tags` | `og:title` and `og:description` both set |
62
+ | `heading-hierarchy` | no level skips (h1→h3 etc.) |
63
+
64
+ `structured-answer` is the highest-impact: that one paragraph is what gets lifted into the engine's answer. A page can fail every other heuristic and still be cited if this one passes.
65
+
66
+ ## Observability
67
+
68
+ Every tool emits a single log line per invocation:
69
+
70
+ - `[aeo-emit-jsonld] entityId=… schemaType=… source=graph|inline`
71
+ - `[aeo-llms-txt] site=… pages=… skippedNoUrl=… indexBytes=… fullBytes=…`
72
+ - `[aeo-audit] target=… score=… fails=… warns=…`
73
+
74
+ Diagnostic path: `grep -E '^\[aeo-' platform-logs/*.log | grep <urlOrEntityId>`.
75
+
76
+ ## What this plugin does not do
77
+
78
+ - **No citation monitor — out of scope.** Tracking whether your brand is cited by Claude / ChatGPT / Perplexity / Gemini would require multi-engine answer harvesting that doesn't fit maxy-code's no-API-key architecture. Archived without sprinting (Task 363). Check citation manually when needed.
79
+ - **No auto-emission on page render.** `aeo-emit-jsonld` is callable on demand. Wiring it into the platform's page-generator render path is per-renderer work, filed as a follow-up.
80
+ - **No publish-hook regeneration of `llms.txt`.** The tool runs on demand. Hooking it into the publish event is a follow-up.
81
+
82
+ ## See also
83
+
84
+ - Plugin manifest: `platform/plugins/aeo/PLUGIN.md`
85
+ - Structured-answer template: `platform/plugins/aeo/skills/structured-answer/SKILL.md`
86
+ - Schema declaration: `platform/neo4j/schema.cypher` (search `AEOAudit`)
87
+ - Spec source: `https://llmstxt.org/`