@rubytech/create-maxy-code 0.1.132 → 0.1.138

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 (128) hide show
  1. package/dist/__tests__/installer-specialist-registration.test.js +5 -40
  2. package/dist/index.js +24 -28
  3. package/dist/specialist-registration.js +0 -15
  4. package/package.json +1 -1
  5. package/payload/platform/lib/graph-search/dist/boosts.d.ts +39 -0
  6. package/payload/platform/lib/graph-search/dist/boosts.d.ts.map +1 -0
  7. package/payload/platform/lib/graph-search/dist/boosts.js +57 -0
  8. package/payload/platform/lib/graph-search/dist/boosts.js.map +1 -0
  9. package/payload/platform/lib/graph-search/dist/dedup.d.ts +29 -0
  10. package/payload/platform/lib/graph-search/dist/dedup.d.ts.map +1 -0
  11. package/payload/platform/lib/graph-search/dist/dedup.js +97 -0
  12. package/payload/platform/lib/graph-search/dist/dedup.js.map +1 -0
  13. package/payload/platform/lib/graph-search/dist/index.d.ts +70 -8
  14. package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -1
  15. package/payload/platform/lib/graph-search/dist/index.js +323 -62
  16. package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
  17. package/payload/platform/lib/graph-search/dist/query-expansion.d.ts +37 -0
  18. package/payload/platform/lib/graph-search/dist/query-expansion.d.ts.map +1 -0
  19. package/payload/platform/lib/graph-search/dist/query-expansion.js +101 -0
  20. package/payload/platform/lib/graph-search/dist/query-expansion.js.map +1 -0
  21. package/payload/platform/lib/graph-search/dist/route.d.ts +29 -0
  22. package/payload/platform/lib/graph-search/dist/route.d.ts.map +1 -0
  23. package/payload/platform/lib/graph-search/dist/route.js +53 -0
  24. package/payload/platform/lib/graph-search/dist/route.js.map +1 -0
  25. package/payload/platform/lib/graph-search/dist/rrf-fusion.d.ts +31 -0
  26. package/payload/platform/lib/graph-search/dist/rrf-fusion.d.ts.map +1 -0
  27. package/payload/platform/lib/graph-search/dist/rrf-fusion.js +57 -0
  28. package/payload/platform/lib/graph-search/dist/rrf-fusion.js.map +1 -0
  29. package/payload/platform/lib/graph-search/src/__tests__/boosts.test.ts +59 -0
  30. package/payload/platform/lib/graph-search/src/__tests__/dedup.test.ts +83 -0
  31. package/payload/platform/lib/graph-search/src/__tests__/query-expansion.test.ts +96 -0
  32. package/payload/platform/lib/graph-search/src/__tests__/route.test.ts +62 -0
  33. package/payload/platform/lib/graph-search/src/__tests__/rrf-fusion.test.ts +39 -0
  34. package/payload/platform/lib/graph-search/src/boosts.ts +61 -0
  35. package/payload/platform/lib/graph-search/src/dedup.ts +108 -0
  36. package/payload/platform/lib/graph-search/src/index.ts +407 -65
  37. package/payload/platform/lib/graph-search/src/query-expansion.ts +129 -0
  38. package/payload/platform/lib/graph-search/src/route.ts +70 -0
  39. package/payload/platform/lib/graph-search/src/rrf-fusion.ts +62 -0
  40. package/payload/platform/neo4j/schema.cypher +80 -1
  41. package/payload/platform/plugins/admin/hooks/session-end-retrospective.sh +4 -2
  42. package/payload/platform/plugins/admin/mcp/dist/index.js +6 -4
  43. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  44. package/payload/platform/plugins/docs/references/internals.md +36 -10
  45. package/payload/platform/plugins/docs/references/neo4j.md +63 -0
  46. package/payload/platform/plugins/docs/references/session-retrospective.md +11 -4
  47. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js +2 -2
  48. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js.map +1 -1
  49. package/payload/platform/plugins/memory/mcp/dist/index.js +114 -5
  50. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  51. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.d.ts +2 -0
  52. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.d.ts.map +1 -0
  53. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.js +25 -0
  54. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-property.test.js.map +1 -0
  55. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.d.ts +2 -0
  56. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.d.ts.map +1 -0
  57. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.js +70 -0
  58. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.js.map +1 -0
  59. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.d.ts +2 -0
  60. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.d.ts.map +1 -0
  61. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js +50 -0
  62. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js.map +1 -0
  63. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts +33 -0
  64. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts.map +1 -0
  65. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js +99 -0
  66. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js.map +1 -0
  67. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts +21 -0
  68. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts.map +1 -1
  69. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js +24 -0
  70. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js.map +1 -1
  71. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.d.ts +13 -0
  72. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.d.ts.map +1 -0
  73. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.js +151 -0
  74. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.js.map +1 -0
  75. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +55 -0
  76. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +1 -0
  77. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js +290 -0
  78. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.js.map +1 -0
  79. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts +19 -0
  80. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -0
  81. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +102 -0
  82. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -0
  83. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js +18 -1
  84. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js.map +1 -1
  85. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js +5 -0
  86. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js.map +1 -1
  87. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js +2 -0
  88. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js.map +1 -1
  89. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -1
  90. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +14 -0
  91. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
  92. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +29 -0
  93. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts.map +1 -0
  94. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +22 -0
  95. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js.map +1 -0
  96. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts +31 -1
  97. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
  98. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +182 -50
  99. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
  100. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
  101. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +76 -1
  102. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  103. package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.d.ts +30 -0
  104. package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.d.ts.map +1 -0
  105. package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.js +129 -0
  106. package/payload/platform/plugins/memory/mcp/dist/tools/session-retrospective-skip-rate.js.map +1 -0
  107. package/payload/platform/plugins/memory/mcp/scripts/backfill-typed-edges.ts +72 -0
  108. package/payload/platform/plugins/memory/mcp/scripts/generate-edge-docs.ts +75 -0
  109. package/payload/platform/plugins/memory/mcp/vitest.config.ts +5 -0
  110. package/payload/platform/plugins/memory/references/schema-base.md +44 -0
  111. package/payload/platform/scripts/seed-neo4j.sh +49 -0
  112. package/payload/platform/templates/agents/admin/IDENTITY.md +4 -3
  113. package/payload/platform/templates/specialists/agents/database-operator.md +9 -1
  114. package/payload/server/{adminuser-self-heal-QAWOZ3JV.js → adminuser-self-heal-YC47O34W.js} +2 -1
  115. package/payload/server/{chunk-JSBRDJBE.js → chunk-HYQNUVGO.js} +9 -1
  116. package/payload/server/{chunk-HCYM5FLU.js → chunk-T3DJD5QR.js} +3 -1
  117. package/payload/server/maxy-edge.js +3 -2
  118. package/payload/server/public/assets/{admin-FcRHAL-3.js → admin-BM9aXUUh.js} +1 -1
  119. package/payload/server/public/assets/{data-Ds37mflX.js → data-Ds2ECtfP.js} +1 -1
  120. package/payload/server/public/assets/{graph-CmWRhaiS.js → graph-BzxObKMM.js} +1 -1
  121. package/payload/server/public/assets/{graph-labels-Ch2r00Gt.js → graph-labels-Dwgep_nr.js} +1 -1
  122. package/payload/server/public/assets/{page-BcHhJXUt.js → page-BlkBsjP2.js} +1 -1
  123. package/payload/server/public/assets/page-h_SA5SVQ.js +51 -0
  124. package/payload/server/public/data.html +3 -3
  125. package/payload/server/public/graph.html +3 -3
  126. package/payload/server/public/index.html +4 -4
  127. package/payload/server/server.js +803 -76
  128. package/payload/server/public/assets/page-BOtNny_4.js +0 -51
@@ -0,0 +1,99 @@
1
+ // Compiled-truth rewriter (Task 306).
2
+ //
3
+ // Given a node's current `compiledTruth` and its most-recent N :TimelineEvent
4
+ // rows, produce a new compiledTruth ≤ 2000 chars. Strictly OAuth-bearer LLM
5
+ // (admin classifier doctrine — never API key). The skill / agent / backfill
6
+ // caller is responsible for: (a) selecting which node to rewrite, (b)
7
+ // enforcing the 7-day operator-edit cooldown, (c) writing the result back.
8
+ // This library is the prompt + LLM call + cap-enforcement only.
9
+ //
10
+ // Output style baseline (this sprint):
11
+ // - ≤ COMPILED_TRUTH_MAX_CHARS
12
+ // - Neutral, declarative voice. Third person.
13
+ // - No hedging adverbs ("likely", "perhaps", "possibly", "presumably").
14
+ // - No first person ("I", "we"), no second person ("you").
15
+ // - No marketing / superlatives.
16
+ //
17
+ // Voice grafting (no AI tells, IDENTITY alignment, BrainBench eval) is
18
+ // deferred — see follow-up task referenced in the task brief.
19
+ import { callOauthLlm, } from "../../../../../lib/oauth-llm/dist/index.js";
20
+ import { COMPILED_TRUTH_MAX_CHARS } from "./graph-write-gate.js";
21
+ const DEFAULT_MODEL = "claude-haiku-4-5";
22
+ const SYSTEM_PROMPT = [
23
+ "You are the compiled-truth rewriter for a personal knowledge graph.",
24
+ "",
25
+ "Your job: produce a neutral, declarative summary of what the operator knows about a subject right now.",
26
+ "",
27
+ "RULES (all binding, never relaxed):",
28
+ `- Output must be ${COMPILED_TRUTH_MAX_CHARS} characters or fewer. This is a hard cap.`,
29
+ "- Third person only. No 'I', 'we', 'you', 'us'.",
30
+ "- Declarative voice. No hedging adverbs (likely, perhaps, possibly, presumably, apparently, seemingly).",
31
+ "- No marketing, no superlatives, no commentary on the operator's relationship with the subject.",
32
+ "- Restate the most-load-bearing facts from the timeline. Drop trivia.",
33
+ "- If the existing compiledTruth contradicts the timeline, the timeline wins.",
34
+ "- Do not invent details that are not present in either the existing truth or the timeline.",
35
+ "- Do not add a preamble (no 'Here is the summary:'). Output the summary directly.",
36
+ ].join("\n");
37
+ function buildUserMessage(p) {
38
+ const lines = [];
39
+ lines.push(`Subject: ${p.subjectName}`);
40
+ lines.push(`Label: :${p.subjectLabel}`);
41
+ lines.push("");
42
+ lines.push("Current compiledTruth:");
43
+ lines.push(p.currentTruth ? p.currentTruth : "(empty)");
44
+ lines.push("");
45
+ lines.push(`Timeline events (newest-first, ${p.events.length} shown):`);
46
+ for (const e of p.events) {
47
+ lines.push(`- [${e.occurredAt}] kind=${e.kind}: ${e.summary}`);
48
+ }
49
+ lines.push("");
50
+ lines.push("Rewrite the compiledTruth.");
51
+ return lines.join("\n");
52
+ }
53
+ function isOkText(r) {
54
+ return r.kind === "ok";
55
+ }
56
+ export async function rewriteCompiledTruth(p) {
57
+ if (p.events.length === 0) {
58
+ console.log(`[compiled-truth-rewriter] refused subject="${p.subjectName}" reason=no-events`);
59
+ return { kind: "refused", reason: "no-events" };
60
+ }
61
+ const userMessage = buildUserMessage(p);
62
+ const result = await callOauthLlm({
63
+ model: p.model ?? DEFAULT_MODEL,
64
+ system: SYSTEM_PROMPT,
65
+ userMessage,
66
+ maxTokens: 1024,
67
+ });
68
+ if (!isOkText(result)) {
69
+ console.log(`[compiled-truth-rewriter] llm-failure subject="${p.subjectName}" cause=${result.cause}`);
70
+ return { kind: "llm-failure", fallback: result };
71
+ }
72
+ const truth = result.text.trim();
73
+ const before = p.currentTruth.length;
74
+ const after = truth.length;
75
+ console.log(`[compiled-truth-rewriter] subject="${p.subjectName}" charsBefore=${before} charsAfter=${after} events=${p.events.length}`);
76
+ if (after > COMPILED_TRUTH_MAX_CHARS) {
77
+ // One retry with a stricter prompt before surfacing the over-cap failure.
78
+ // Per eng review: avoids losing the rewrite on a single LLM verbosity slip.
79
+ const stricterResult = await callOauthLlm({
80
+ model: p.model ?? DEFAULT_MODEL,
81
+ system: SYSTEM_PROMPT +
82
+ `\n\nPRIOR ATTEMPT WAS ${after} CHARACTERS — TOO LONG. ` +
83
+ `Tighten to fit ${COMPILED_TRUTH_MAX_CHARS}. Drop the lowest-value sentences first.`,
84
+ userMessage,
85
+ maxTokens: 1024,
86
+ });
87
+ if (!isOkText(stricterResult)) {
88
+ return { kind: "llm-failure", fallback: stricterResult };
89
+ }
90
+ const retry = stricterResult.text.trim();
91
+ if (retry.length > COMPILED_TRUTH_MAX_CHARS) {
92
+ console.log(`[compiled-truth-rewriter] still-too-long subject="${p.subjectName}" retryLen=${retry.length}`);
93
+ return { kind: "too-long", attemptedLen: retry.length };
94
+ }
95
+ return { kind: "ok", compiledTruth: retry };
96
+ }
97
+ return { kind: "ok", compiledTruth: truth };
98
+ }
99
+ //# sourceMappingURL=compiled-truth-rewriter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiled-truth-rewriter.js","sourceRoot":"","sources":["../../src/lib/compiled-truth-rewriter.ts"],"names":[],"mappings":"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"}
@@ -34,5 +34,26 @@ export type GateResult = {
34
34
  subReason: "no-admin-user-node" | "admin-user-no-accountid" | "no-business-or-personal-profile";
35
35
  message: string;
36
36
  };
37
+ /** Compiled-truth cap. ≤2000 chars ≈ 300 words — forces the rewriter to summarise, not transcribe. */
38
+ export declare const COMPILED_TRUTH_MAX_CHARS = 2000;
39
+ export type PropertyGateResult = {
40
+ ok: true;
41
+ } | {
42
+ ok: false;
43
+ reason: "compiled-truth-too-long";
44
+ message: string;
45
+ };
46
+ /**
47
+ * Property-level write gate (Task 306). Today: one rule — `compiledTruth`
48
+ * must not exceed COMPILED_TRUTH_MAX_CHARS. Used by both `memory-write`
49
+ * and `memory-update`; the rewriter calls it before writing too.
50
+ *
51
+ * Pure / synchronous on purpose — no session needed. Loud-fail on
52
+ * violation so an over-producing rewriter surfaces immediately instead
53
+ * of silently truncating the operator's summary.
54
+ */
55
+ export declare function checkPropertyWriteGate(args: {
56
+ properties: Record<string, unknown>;
57
+ }): PropertyGateResult;
37
58
  export declare function checkGraphWriteGate(args: GateArgs): Promise<GateResult>;
38
59
  //# sourceMappingURL=graph-write-gate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"graph-write-gate.d.ts","sourceRoot":"","sources":["../../src/lib/graph-write-gate.ts"],"names":[],"mappings":"AAuCA,MAAM,WAAW,WAAW;IAC1B,GAAG,CACD,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,eAAe,GAAG,mBAAmB,CAAC;IAC9C,SAAS,EACL,oBAAoB,GACpB,yBAAyB,GACzB,iCAAiC,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAaN,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAuD7E"}
1
+ {"version":3,"file":"graph-write-gate.d.ts","sourceRoot":"","sources":["../../src/lib/graph-write-gate.ts"],"names":[],"mappings":"AAuCA,MAAM,WAAW,WAAW;IAC1B,GAAG,CACD,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,eAAe,GAAG,mBAAmB,CAAC;IAC9C,SAAS,EACL,oBAAoB,GACpB,yBAAyB,GACzB,iCAAiC,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,sGAAsG;AACtG,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,yBAAyB,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC,GAAG,kBAAkB,CAerB;AAaD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAuD7E"}
@@ -36,6 +36,30 @@
36
36
  // account, add a composite index on Person(accountId, role) so the
37
37
  // hasPersonalProfile subquery doesn't full-scan. Same scaling concern applies
38
38
  // to LocalBusiness(accountId) and AdminUser(accountId). Not in 704 scope.
39
+ /** Compiled-truth cap. ≤2000 chars ≈ 300 words — forces the rewriter to summarise, not transcribe. */
40
+ export const COMPILED_TRUTH_MAX_CHARS = 2000;
41
+ /**
42
+ * Property-level write gate (Task 306). Today: one rule — `compiledTruth`
43
+ * must not exceed COMPILED_TRUTH_MAX_CHARS. Used by both `memory-write`
44
+ * and `memory-update`; the rewriter calls it before writing too.
45
+ *
46
+ * Pure / synchronous on purpose — no session needed. Loud-fail on
47
+ * violation so an over-producing rewriter surfaces immediately instead
48
+ * of silently truncating the operator's summary.
49
+ */
50
+ export function checkPropertyWriteGate(args) {
51
+ const truth = args.properties.compiledTruth;
52
+ if (typeof truth === "string" && truth.length > COMPILED_TRUTH_MAX_CHARS) {
53
+ console.log(`[graph-write-gate] reject reason=compiled-truth-too-long len=${truth.length} cap=${COMPILED_TRUTH_MAX_CHARS}`);
54
+ return {
55
+ ok: false,
56
+ reason: "compiled-truth-too-long",
57
+ message: `compiledTruth length ${truth.length} exceeds cap of ${COMPILED_TRUTH_MAX_CHARS} chars. ` +
58
+ `The rewriter must produce a tighter summary.`,
59
+ };
60
+ }
61
+ return { ok: true };
62
+ }
39
63
  const EXEMPT_LABELS = new Set([
40
64
  "Person",
41
65
  "LocalBusiness",
@@ -1 +1 @@
1
- {"version":3,"file":"graph-write-gate.js","sourceRoot":"","sources":["../../src/lib/graph-write-gate.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,EAAE;AACF,yEAAyE;AACzE,iEAAiE;AACjE,2EAA2E;AAC3E,4EAA4E;AAC5E,uEAAuE;AACvE,8EAA8E;AAC9E,sEAAsE;AACtE,gDAAgD;AAChD,EAAE;AACF,2BAA2B;AAC3B,uDAAuD;AACvD,mEAAmE;AACnE,EAAE;AACF,8EAA8E;AAC9E,uEAAuE;AACvE,uEAAuE;AACvE,0DAA0D;AAC1D,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,0EAA0E;AAC1E,6EAA6E;AAC7E,+CAA+C;AAC/C,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,qCAAqC;AACrC,EAAE;AACF,4EAA4E;AAC5E,0EAA0E;AAC1E,+DAA+D;AAC/D,EAAE;AACF,4EAA4E;AAC5E,mEAAmE;AACnE,8EAA8E;AAC9E,0EAA0E;AA2C1E,MAAM,aAAa,GAAwB,IAAI,GAAG,CAAC;IACjD,QAAQ;IACR,eAAe;IACf,WAAW;CACZ,CAAC,CAAC;AAEH,MAAM,SAAS,GACb,0EAA0E;IAC1E,0EAA0E;IAC1E,2CAA2C,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAc;IACtD,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE5C,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAED,mEAAmE;IACnE,oEAAoE;IACpE,sEAAsE;IACtE,yDAAyD;IACzD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B;;;;4GAIwG,EACxG,EAAE,SAAS,EAAE,CACd,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;IAClD,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAChE,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IACxD,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAEtE,IAAI,QAAQ,IAAI,CAAC,WAAW,IAAI,kBAAkB,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAED,8DAA8D;IAC9D,qEAAqE;IACrE,yEAAyE;IACzE,4EAA4E;IAC5E,wEAAwE;IACxE,wCAAwC;IACxC,IAAI,MAA6C,CAAC;IAClD,IAAI,SAGiC,CAAC;IACtC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,GAAG,eAAe,CAAC;QACzB,SAAS,GAAG,eAAe,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,oBAAoB,CAAC;IACjF,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,mBAAmB,CAAC;QAC7B,SAAS,GAAG,iCAAiC,CAAC;IAChD,CAAC;IAED,OAAO,CAAC,GAAG,CACT,uCAAuC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI;QAC9D,UAAU,MAAM,cAAc,SAAS,eAAe,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAC3E,CAAC;IAEF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"graph-write-gate.js","sourceRoot":"","sources":["../../src/lib/graph-write-gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface DatedStatement {
2
+ occurredAt: string;
3
+ summary: string;
4
+ /** The literal date phrase that triggered the match. Useful for diagnostics. */
5
+ matched: string;
6
+ }
7
+ /**
8
+ * Extract every dated statement from `body`. One row per sentence containing
9
+ * the first parseable date in that sentence. Sentences without a date are
10
+ * dropped silently (the diagnostic count is the caller's concern).
11
+ */
12
+ export declare function extractDatedStatements(body: string | null | undefined): DatedStatement[];
13
+ //# sourceMappingURL=timeline-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-extractor.d.ts","sourceRoot":"","sources":["../../src/lib/timeline-extractor.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;CACjB;AAkID;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,EAAE,CAcxF"}
@@ -0,0 +1,151 @@
1
+ // Deterministic dated-statement extractor for Task 306.
2
+ //
3
+ // Reads a free-text body and returns one row per parseable dated statement.
4
+ // Strictly deterministic — no LLM, no heuristics that could collapse to a
5
+ // catch-all. The 305 typed-edge post-write hook upgrades `kind` from the
6
+ // default "mentioned" to a more specific value asynchronously; until then
7
+ // rows land as `mentioned`, which is the most-faithful default.
8
+ //
9
+ // Date forms recognised (in priority order):
10
+ // 1. ISO date — 2026-03-10, 2026/03/10
11
+ // 2. Day-month-year — 10 March 2026, 10 Mar 2026
12
+ // 3. Month-year — March 2026, Mar 2026
13
+ // 4. "in YYYY" — "in 2018"
14
+ // 5. "since YYYY" — "since 2018"
15
+ // 6. Bare year — 2018 (only when 1900-2099 and surrounded by word boundaries)
16
+ //
17
+ // Coarse forms (bare year, "in YYYY") parse to YYYY-01-01T00:00:00Z so the
18
+ // `occurredAt` index is queryable. Day-precision forms parse exactly.
19
+ //
20
+ // A statement is the sentence containing the parsed date. Summaries
21
+ // truncate to 500 chars at sentence boundaries when possible.
22
+ const MONTHS = {
23
+ jan: 1, january: 1,
24
+ feb: 2, february: 2,
25
+ mar: 3, march: 3,
26
+ apr: 4, april: 4,
27
+ may: 5,
28
+ jun: 6, june: 6,
29
+ jul: 7, july: 7,
30
+ aug: 8, august: 8,
31
+ sep: 9, sept: 9, september: 9,
32
+ oct: 10, october: 10,
33
+ nov: 11, november: 11,
34
+ dec: 12, december: 12,
35
+ };
36
+ const SUMMARY_MAX = 500;
37
+ function pad(n) {
38
+ return n < 10 ? `0${n}` : String(n);
39
+ }
40
+ function isoDay(year, month, day) {
41
+ return `${year}-${pad(month)}-${pad(day)}T00:00:00Z`;
42
+ }
43
+ function isoMonth(year, month) {
44
+ return `${year}-${pad(month)}-01T00:00:00Z`;
45
+ }
46
+ function isoYear(year) {
47
+ return `${year}-01-01T00:00:00Z`;
48
+ }
49
+ function validYear(y) {
50
+ return y >= 1900 && y <= 2099;
51
+ }
52
+ function validMonth(m) {
53
+ return m >= 1 && m <= 12;
54
+ }
55
+ function validDay(d) {
56
+ return d >= 1 && d <= 31;
57
+ }
58
+ /** Split body into sentences (period / question / exclamation followed by space or end). */
59
+ function splitSentences(body) {
60
+ return body
61
+ .split(/(?<=[.?!])\s+/)
62
+ .map((s) => s.trim())
63
+ .filter((s) => s.length > 0);
64
+ }
65
+ function clampSummary(s) {
66
+ if (s.length <= SUMMARY_MAX)
67
+ return s;
68
+ // Truncate at the last sentence boundary inside the cap, else hard-truncate.
69
+ const sliced = s.slice(0, SUMMARY_MAX);
70
+ const lastBoundary = Math.max(sliced.lastIndexOf(". "), sliced.lastIndexOf("? "), sliced.lastIndexOf("! "));
71
+ if (lastBoundary > SUMMARY_MAX * 0.5) {
72
+ return sliced.slice(0, lastBoundary + 1);
73
+ }
74
+ return sliced.slice(0, SUMMARY_MAX - 1) + "…";
75
+ }
76
+ /**
77
+ * Returns null if the sentence has no parseable date; otherwise the first
78
+ * matching date and its ISO normalisation.
79
+ */
80
+ function parseFirstDate(sentence) {
81
+ // 1. ISO date: 2026-03-10 or 2026/03/10
82
+ const iso = sentence.match(/\b(\d{4})[-/](\d{1,2})[-/](\d{1,2})\b/);
83
+ if (iso) {
84
+ const y = Number(iso[1]);
85
+ const m = Number(iso[2]);
86
+ const d = Number(iso[3]);
87
+ if (validYear(y) && validMonth(m) && validDay(d)) {
88
+ return { occurredAt: isoDay(y, m, d), matched: iso[0] };
89
+ }
90
+ }
91
+ // 2. Day-month-year: "10 March 2026" / "10 Mar 2026"
92
+ const dmy = sentence.match(/\b(\d{1,2})\s+([A-Za-z]+)\s+(\d{4})\b/);
93
+ if (dmy) {
94
+ const d = Number(dmy[1]);
95
+ const m = MONTHS[dmy[2].toLowerCase()];
96
+ const y = Number(dmy[3]);
97
+ if (m && validYear(y) && validDay(d)) {
98
+ return { occurredAt: isoDay(y, m, d), matched: dmy[0] };
99
+ }
100
+ }
101
+ // 3. Month-year: "March 2026" / "Mar 2026"
102
+ const my = sentence.match(/\b([A-Za-z]+)\s+(\d{4})\b/);
103
+ if (my) {
104
+ const m = MONTHS[my[1].toLowerCase()];
105
+ const y = Number(my[2]);
106
+ if (m && validYear(y)) {
107
+ return { occurredAt: isoMonth(y, m), matched: my[0] };
108
+ }
109
+ }
110
+ // 4 + 5. "in YYYY" / "since YYYY"
111
+ const inYear = sentence.match(/\b(?:in|since)\s+(\d{4})\b/i);
112
+ if (inYear) {
113
+ const y = Number(inYear[1]);
114
+ if (validYear(y)) {
115
+ return { occurredAt: isoYear(y), matched: inYear[0] };
116
+ }
117
+ }
118
+ // 6. Bare year — restrictive: must be 4 digits surrounded by word boundaries
119
+ // and not preceded by "$" (price), ":" (time), or "-" (already part of a
120
+ // date we would have matched above). Cheap defensive guards.
121
+ const bareYear = sentence.match(/(?<![$:\d-])\b(\d{4})\b(?!\s*[-/]\d)/);
122
+ if (bareYear) {
123
+ const y = Number(bareYear[1]);
124
+ if (validYear(y)) {
125
+ return { occurredAt: isoYear(y), matched: bareYear[0] };
126
+ }
127
+ }
128
+ return null;
129
+ }
130
+ /**
131
+ * Extract every dated statement from `body`. One row per sentence containing
132
+ * the first parseable date in that sentence. Sentences without a date are
133
+ * dropped silently (the diagnostic count is the caller's concern).
134
+ */
135
+ export function extractDatedStatements(body) {
136
+ if (!body || typeof body !== "string")
137
+ return [];
138
+ const out = [];
139
+ for (const sentence of splitSentences(body)) {
140
+ const hit = parseFirstDate(sentence);
141
+ if (hit) {
142
+ out.push({
143
+ occurredAt: hit.occurredAt,
144
+ summary: clampSummary(sentence),
145
+ matched: hit.matched,
146
+ });
147
+ }
148
+ }
149
+ return out;
150
+ }
151
+ //# sourceMappingURL=timeline-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-extractor.js","sourceRoot":"","sources":["../../src/lib/timeline-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Typed-edge auto-extraction pass.
3
+ *
4
+ * Runs once per session at the retrospective turn (admin-spawned via
5
+ * database-operator), or as a one-off backfill. Reads prose-bearing
6
+ * nodes (Message/Page/Meeting/Email/Idea/Note/Post/Report) the operator's
7
+ * account wrote since `sinceIso`, batches them, asks Haiku for typed-edge
8
+ * proposals against the `TYPED_EDGE_ALLOWLIST` schema, validates each
9
+ * proposal inline, and MERGEs accepted edges directly via Cypher with
10
+ * `createdBy` provenance.
11
+ *
12
+ * Continue-on-error: per-batch Haiku failure increments `failed`; per-edge
13
+ * MERGE failure increments `rejected`. A single bad batch never bricks the
14
+ * pass — partial results are returned to the caller.
15
+ *
16
+ * The pass does NOT route through `graph-write-gate`: that gate is a
17
+ * node-precondition surface (AdminUser + LocalBusiness must exist), not
18
+ * an edge-schema validator. Edge validation is owned here against
19
+ * `TYPED_EDGE_ALLOWLIST`.
20
+ *
21
+ * Auth: Haiku is called via Claude Code OAuth — never the Anthropic API key.
22
+ */
23
+ import type { Session } from "neo4j-driver";
24
+ export interface RunTypedEdgePassArgs {
25
+ /** Neo4j session — caller owns the lifecycle. */
26
+ session: Session;
27
+ /** Account scope. Required: cross-account writes are impossible by query design. */
28
+ accountId: string;
29
+ /**
30
+ * Lower bound on `node.updatedAt` for the enumeration. The session-end
31
+ * retrospective passes the session-start timestamp; backfill passes null
32
+ * to mean "all prose nodes ever written in this account".
33
+ */
34
+ sinceIso: string | null;
35
+ /** Nodes per Haiku call. Default 8. */
36
+ batchSize?: number;
37
+ /** Conversation id to stamp on `createdBy` provenance. Optional (backfill mode has none). */
38
+ conversationId?: string | null;
39
+ /**
40
+ * Cap on total nodes processed in one invocation. The backfill pages
41
+ * through Neo4j in 500-node chunks; the retrospective passes its session's
42
+ * worth of nodes and never trips this. Default 500.
43
+ */
44
+ maxNodes?: number;
45
+ }
46
+ export interface TypedEdgePassResult {
47
+ nodes: number;
48
+ proposed: number;
49
+ accepted: number;
50
+ rejected: number;
51
+ failed: number;
52
+ ms: number;
53
+ }
54
+ export declare function runTypedEdgePass(args: RunTypedEdgePassArgs): Promise<TypedEdgePassResult>;
55
+ //# sourceMappingURL=typed-edge-pass.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typed-edge-pass.d.ts","sourceRoot":"","sources":["../../src/lib/typed-edge-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAc5C,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6FAA6F;IAC7F,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;CACZ;AA4SD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAiF/F"}