@rubytech/create-maxy-code 0.1.144 → 0.1.146

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 (130) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/neo4j/schema.cypher +154 -4
  3. package/payload/platform/plugins/admin/PLUGIN.md +1 -1
  4. package/payload/platform/plugins/admin/hooks/post-turn-graph-pass.sh +251 -0
  5. package/payload/platform/plugins/admin/skills/datetime/SKILL.md +63 -5
  6. package/payload/platform/plugins/docs/references/internals.md +16 -0
  7. package/payload/platform/plugins/docs/references/memory-guide.md +10 -0
  8. package/payload/platform/plugins/docs/references/platform.md +1 -1
  9. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
  10. package/payload/platform/plugins/memory/PLUGIN.md +25 -3
  11. package/payload/platform/plugins/memory/mcp/dist/index.js +309 -11
  12. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  13. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.d.ts +2 -0
  14. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.d.ts.map +1 -0
  15. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js +33 -0
  16. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js.map +1 -0
  17. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-label.test.d.ts +2 -0
  18. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-label.test.d.ts.map +1 -0
  19. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-label.test.js +30 -0
  20. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/graph-write-gate-label.test.js.map +1 -0
  21. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-prune-revisions.test.d.ts +2 -0
  22. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-prune-revisions.test.d.ts.map +1 -0
  23. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-prune-revisions.test.js +51 -0
  24. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-prune-revisions.test.js.map +1 -0
  25. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relative-date.test.d.ts +2 -0
  26. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relative-date.test.d.ts.map +1 -0
  27. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relative-date.test.js +68 -0
  28. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relative-date.test.js.map +1 -0
  29. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.js +41 -0
  30. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/timeline-extractor.test.js.map +1 -1
  31. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.d.ts +43 -0
  32. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.d.ts.map +1 -0
  33. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.js +33 -0
  34. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.js.map +1 -0
  35. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts +18 -5
  36. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.d.ts.map +1 -1
  37. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js +64 -17
  38. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-rewriter.js.map +1 -1
  39. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts +44 -0
  40. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts.map +1 -0
  41. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.js +14 -0
  42. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.js.map +1 -0
  43. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.d.ts +26 -0
  44. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.d.ts.map +1 -0
  45. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.js +219 -0
  46. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-citation-audit.js.map +1 -0
  47. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-dead-edges.d.ts +19 -0
  48. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-dead-edges.d.ts.map +1 -0
  49. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-dead-edges.js +39 -0
  50. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-dead-edges.js.map +1 -0
  51. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-orphans.d.ts +19 -0
  52. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-orphans.d.ts.map +1 -0
  53. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-orphans.js +42 -0
  54. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-orphans.js.map +1 -0
  55. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-prune-revisions.d.ts +21 -0
  56. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-prune-revisions.d.ts.map +1 -0
  57. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-prune-revisions.js +27 -0
  58. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-prune-revisions.js.map +1 -0
  59. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-stale-truth.d.ts +18 -0
  60. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-stale-truth.d.ts.map +1 -0
  61. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-stale-truth.js +60 -0
  62. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-stale-truth.js.map +1 -0
  63. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts +20 -3
  64. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts.map +1 -1
  65. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js +47 -12
  66. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js.map +1 -1
  67. package/payload/platform/plugins/memory/mcp/dist/lib/relative-date.d.ts +13 -0
  68. package/payload/platform/plugins/memory/mcp/dist/lib/relative-date.d.ts.map +1 -0
  69. package/payload/platform/plugins/memory/mcp/dist/lib/relative-date.js +191 -0
  70. package/payload/platform/plugins/memory/mcp/dist/lib/relative-date.js.map +1 -0
  71. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.d.ts +7 -1
  72. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.d.ts.map +1 -1
  73. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.js +37 -9
  74. package/payload/platform/plugins/memory/mcp/dist/lib/timeline-extractor.js.map +1 -1
  75. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.d.ts +2 -0
  76. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.d.ts.map +1 -0
  77. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.js +81 -0
  78. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.js.map +1 -0
  79. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.d.ts +2 -0
  80. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.d.ts.map +1 -0
  81. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js +115 -0
  82. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js.map +1 -0
  83. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js +1 -0
  84. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-emit.test.js.map +1 -1
  85. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js +1 -0
  86. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-write-emit.test.js.map +1 -1
  87. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.d.ts +19 -0
  88. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.d.ts.map +1 -0
  89. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.js +50 -0
  90. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.js.map +1 -0
  91. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts +45 -0
  92. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts.map +1 -0
  93. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js +170 -0
  94. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js.map +1 -0
  95. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-list.d.ts +28 -0
  96. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-list.d.ts.map +1 -0
  97. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-list.js +64 -0
  98. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-list.js.map +1 -0
  99. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-read-latest.d.ts +24 -0
  100. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-read-latest.d.ts.map +1 -0
  101. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-read-latest.js +49 -0
  102. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-read-latest.js.map +1 -0
  103. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.d.ts +34 -0
  104. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.d.ts.map +1 -0
  105. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.js +99 -0
  106. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.js.map +1 -0
  107. package/payload/platform/plugins/memory/mcp/dist/tools/memory-review-queue.d.ts +29 -0
  108. package/payload/platform/plugins/memory/mcp/dist/tools/memory-review-queue.d.ts.map +1 -0
  109. package/payload/platform/plugins/memory/mcp/dist/tools/memory-review-queue.js +66 -0
  110. package/payload/platform/plugins/memory/mcp/dist/tools/memory-review-queue.js.map +1 -0
  111. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -1
  112. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +122 -2
  113. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
  114. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts +49 -13
  115. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
  116. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +184 -16
  117. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
  118. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
  119. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +53 -10
  120. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  121. package/payload/platform/plugins/memory/mcp/vitest.config.ts +6 -0
  122. package/payload/platform/plugins/memory/references/schema-base.md +4 -0
  123. package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +3 -4
  124. package/payload/platform/plugins/scheduling/skills/briefing/SKILL.md +13 -2
  125. package/payload/platform/scripts/seed-neo4j.sh +1 -1
  126. package/payload/platform/templates/agents/admin/IDENTITY.md +9 -1
  127. package/payload/platform/templates/specialists/agents/database-operator.md +30 -2
  128. package/payload/server/server.js +195 -91
  129. package/payload/platform/plugins/admin/hooks/signal-detector-stop.sh +0 -309
  130. package/payload/platform/templates/specialists/agents/signal-detector.md +0 -129
@@ -0,0 +1,49 @@
1
+ /**
2
+ * memory-report-read-latest — fetch the most recent :Report(s) matching a
3
+ * keyword (Task 332). Resolves "what was last night's dream cycle" /
4
+ * "show me the latest briefing" routes by name; default `limit=1`.
5
+ */
6
+ import { getSession } from "../lib/neo4j.js";
7
+ const DEFAULT_LIMIT = 1;
8
+ const MAX_LIMIT = 20;
9
+ export async function memoryReportReadLatest(params) {
10
+ const { accountId, keyword } = params;
11
+ const limit = Math.max(1, Math.min(params.limit ?? DEFAULT_LIMIT, MAX_LIMIT));
12
+ if (!accountId)
13
+ throw new Error("memory-report-read-latest: accountId is required");
14
+ if (!keyword || !keyword.trim()) {
15
+ throw new Error("memory-report-read-latest: keyword is required");
16
+ }
17
+ const session = getSession();
18
+ const t0 = Date.now();
19
+ try {
20
+ const res = await session.run(`MATCH (r:Report {accountId: $accountId})
21
+ WHERE $keyword IN r.keywords
22
+ RETURN elementId(r) AS nodeId,
23
+ r.reportId AS reportId,
24
+ r.title AS title,
25
+ r.body AS body,
26
+ r.keywords AS keywords,
27
+ r.sourceWorkflow AS sourceWorkflow,
28
+ toString(r.occurredAt) AS occurredAt
29
+ ORDER BY r.occurredAt DESC
30
+ LIMIT toInteger($limit)`, { accountId, keyword, limit });
31
+ const results = res.records.map((rec) => ({
32
+ nodeId: rec.get("nodeId"),
33
+ reportId: rec.get("reportId"),
34
+ title: rec.get("title"),
35
+ body: rec.get("body"),
36
+ keywords: rec.get("keywords"),
37
+ sourceWorkflow: rec.get("sourceWorkflow"),
38
+ occurredAt: rec.get("occurredAt"),
39
+ }));
40
+ const ms = Date.now() - t0;
41
+ const firstId = results[0]?.reportId.slice(0, 8) ?? "none";
42
+ process.stderr.write(`[reports] op=read-latest reportId=${firstId} keywords=${keyword} ms=${ms} hits=${results.length}\n`);
43
+ return { results };
44
+ }
45
+ finally {
46
+ await session.close();
47
+ }
48
+ }
49
+ //# sourceMappingURL=memory-report-read-latest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-report-read-latest.js","sourceRoot":"","sources":["../../src/tools/memory-report-read-latest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAsB7C,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAA8B;IAE9B,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;IAE9E,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACpF,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAC3B;;;;;;;;;;+BAUyB,EACzB,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAC9B,CAAC;QAEF,MAAM,OAAO,GAAgB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACrD,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAW;YACnC,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,UAAU,CAAW;YACvC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAW;YACjC,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAW;YAC/B,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,UAAU,CAAa;YACzC,cAAc,EAAE,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAkB;YAC1D,UAAU,EAAE,GAAG,CAAC,GAAG,CAAC,YAAY,CAAW;SAC5C,CAAC,CAAC,CAAC;QAEJ,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC;QAC3D,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,qCAAqC,OAAO,aAAa,OAAO,OAAO,EAAE,SAAS,OAAO,CAAC,MAAM,IAAI,CACrG,CAAC;QAEF,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * memory-report-write — durable, keyword-routed report persistence (Task 332).
3
+ *
4
+ * Idempotent on (accountId, title, occurredAt-within-same-minute) to absorb
5
+ * accidental double-fires from a workflow dispatcher. Two distinct calls in
6
+ * the same minute with the same title return the existing :Report nodeId
7
+ * instead of creating a second row.
8
+ *
9
+ * Hierarchy: every :Report is parented to either the active
10
+ * :AdminConversation (when CONVERSATION_NODE_ID is set — the typical case
11
+ * for operator-initiated writes from chat) or to the account's :AdminUser
12
+ * as a fallback so the report still satisfies the graph-hierarchy doctrine
13
+ * when written from a non-conversation context (scheduled workflows etc.).
14
+ */
15
+ export interface ReportWriteParams {
16
+ accountId: string;
17
+ title: string;
18
+ body: string;
19
+ keywords: string[];
20
+ sourceWorkflow?: string;
21
+ /** ISO timestamp. Defaults to now(). */
22
+ occurredAt?: string;
23
+ /** elementId of the active :AdminConversation when invoked in chat. */
24
+ conversationNodeId?: string;
25
+ }
26
+ export interface ReportWriteResult {
27
+ nodeId: string;
28
+ reportId: string;
29
+ created: boolean;
30
+ /** Reason the existing report was returned, when created=false. */
31
+ idempotencyReason?: "same-title-within-minute";
32
+ }
33
+ export declare function memoryReportWrite(params: ReportWriteParams): Promise<ReportWriteResult>;
34
+ //# sourceMappingURL=memory-report-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-report-write.d.ts","sourceRoot":"","sources":["../../src/tools/memory-report-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAQH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,0BAA0B,CAAC;CAChD;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,iBAAiB,CAAC,CA2G5B"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * memory-report-write — durable, keyword-routed report persistence (Task 332).
3
+ *
4
+ * Idempotent on (accountId, title, occurredAt-within-same-minute) to absorb
5
+ * accidental double-fires from a workflow dispatcher. Two distinct calls in
6
+ * the same minute with the same title return the existing :Report nodeId
7
+ * instead of creating a second row.
8
+ *
9
+ * Hierarchy: every :Report is parented to either the active
10
+ * :AdminConversation (when CONVERSATION_NODE_ID is set — the typical case
11
+ * for operator-initiated writes from chat) or to the account's :AdminUser
12
+ * as a fallback so the report still satisfies the graph-hierarchy doctrine
13
+ * when written from a non-conversation context (scheduled workflows etc.).
14
+ */
15
+ import { randomUUID } from "node:crypto";
16
+ import { getSession } from "../lib/neo4j.js";
17
+ import { embed } from "../lib/embeddings.js";
18
+ const MAX_BODY_CHARS = 10_000;
19
+ export async function memoryReportWrite(params) {
20
+ const { accountId, title, body, keywords, sourceWorkflow, occurredAt, conversationNodeId, } = params;
21
+ if (!accountId)
22
+ throw new Error("memory-report-write: accountId is required");
23
+ if (!title || !title.trim())
24
+ throw new Error("memory-report-write: title is required");
25
+ if (body.length > MAX_BODY_CHARS) {
26
+ throw new Error(`memory-report-write: body exceeds ${MAX_BODY_CHARS} chars (got ${body.length})`);
27
+ }
28
+ const occurredAtIso = occurredAt ?? new Date().toISOString();
29
+ const session = getSession();
30
+ const t0 = Date.now();
31
+ try {
32
+ // Idempotency pre-check: same accountId + title + occurredAt within 1 min.
33
+ const existing = await session.run(`MATCH (r:Report {accountId: $accountId, title: $title})
34
+ WHERE r.occurredAt >= datetime($occurredAt) - duration('PT1M')
35
+ AND r.occurredAt <= datetime($occurredAt) + duration('PT1M')
36
+ RETURN elementId(r) AS nodeId, r.reportId AS reportId
37
+ ORDER BY r.occurredAt DESC
38
+ LIMIT 1`, { accountId, title, occurredAt: occurredAtIso });
39
+ if (existing.records.length > 0) {
40
+ const nodeId = existing.records[0].get("nodeId");
41
+ const reportId = existing.records[0].get("reportId");
42
+ const ms = Date.now() - t0;
43
+ const kwCsv = keywords.join(",");
44
+ process.stderr.write(`[reports] op=write reportId=${reportId.slice(0, 8)} keywords=${kwCsv} ms=${ms} idempotent=1\n`);
45
+ return {
46
+ nodeId,
47
+ reportId,
48
+ created: false,
49
+ idempotencyReason: "same-title-within-minute",
50
+ };
51
+ }
52
+ const embedding = await embed(`${title}\n\n${body}`);
53
+ const reportId = randomUUID();
54
+ // Parent edge: prefer active :AdminConversation, fall back to account's :AdminUser.
55
+ // The MATCH-OPTIONAL pattern picks whichever exists; we COALESCE to a single parent
56
+ // and assert it resolved before CREATEing the Report.
57
+ const writeRes = await session.run(`OPTIONAL MATCH (c:Conversation) WHERE elementId(c) = $conversationNodeId
58
+ OPTIONAL MATCH (au:AdminUser {accountId: $accountId})
59
+ WITH coalesce(c, au) AS parent
60
+ WHERE parent IS NOT NULL
61
+ CREATE (r:Report {
62
+ reportId: $reportId,
63
+ accountId: $accountId,
64
+ title: $title,
65
+ body: $body,
66
+ keywords: $keywords,
67
+ sourceWorkflow: $sourceWorkflow,
68
+ occurredAt: datetime($occurredAt),
69
+ createdAt: datetime(),
70
+ updatedAt: datetime(),
71
+ scope: 'admin',
72
+ embedding: $embedding
73
+ })
74
+ CREATE (parent)-[:PRODUCED]->(r)
75
+ RETURN elementId(r) AS nodeId`, {
76
+ reportId,
77
+ accountId,
78
+ title,
79
+ body,
80
+ keywords,
81
+ sourceWorkflow: sourceWorkflow ?? null,
82
+ occurredAt: occurredAtIso,
83
+ embedding,
84
+ conversationNodeId: conversationNodeId ?? null,
85
+ });
86
+ if (writeRes.records.length === 0) {
87
+ throw new Error(`memory-report-write: no parent resolved (conversationNodeId='${conversationNodeId ?? "<none>"}' and :AdminUser missing for account '${accountId}'). Report not written.`);
88
+ }
89
+ const nodeId = writeRes.records[0].get("nodeId");
90
+ const ms = Date.now() - t0;
91
+ const kwCsv = keywords.join(",");
92
+ process.stderr.write(`[reports] op=write reportId=${reportId.slice(0, 8)} keywords=${kwCsv} ms=${ms}\n`);
93
+ return { nodeId, reportId, created: true };
94
+ }
95
+ finally {
96
+ await session.close();
97
+ }
98
+ }
99
+ //# sourceMappingURL=memory-report-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-report-write.js","sourceRoot":"","sources":["../../src/tools/memory-report-write.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * memory-review-queue — Task 327.
3
+ *
4
+ * Read-only operator surface for the dream-cycle's review queues.
5
+ * Returns counts plus a small sample of `:OrphanCandidate` and
6
+ * `:CitationProposal` rows so the operator can decide whether to triage
7
+ * them. Without this, the dream-cycle's queue nodes are invisible — write-only
8
+ * shape.
9
+ *
10
+ * Phases 5 (backlinks) and 6 (tag consistency) are not in v1, so neither
11
+ * `:BackLinkGap` nor `:TagMergeProposal` appears here yet — when they
12
+ * land, this tool extends to surface them.
13
+ */
14
+ export interface MemoryReviewQueueParams {
15
+ accountId: string;
16
+ /** Sample size per queue. Default 5, max 25. */
17
+ sampleSize?: number;
18
+ }
19
+ export interface QueueSummary {
20
+ label: string;
21
+ count: number;
22
+ sample: Array<Record<string, string>>;
23
+ }
24
+ export interface MemoryReviewQueueResult {
25
+ queues: QueueSummary[];
26
+ totalPending: number;
27
+ }
28
+ export declare function memoryReviewQueue(params: MemoryReviewQueueParams): Promise<MemoryReviewQueueResult>;
29
+ //# sourceMappingURL=memory-review-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-review-queue.d.ts","sourceRoot":"","sources":["../../src/tools/memory-review-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAyBD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,uBAAuB,CAAC,CAiClC"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * memory-review-queue — Task 327.
3
+ *
4
+ * Read-only operator surface for the dream-cycle's review queues.
5
+ * Returns counts plus a small sample of `:OrphanCandidate` and
6
+ * `:CitationProposal` rows so the operator can decide whether to triage
7
+ * them. Without this, the dream-cycle's queue nodes are invisible — write-only
8
+ * shape.
9
+ *
10
+ * Phases 5 (backlinks) and 6 (tag consistency) are not in v1, so neither
11
+ * `:BackLinkGap` nor `:TagMergeProposal` appears here yet — when they
12
+ * land, this tool extends to surface them.
13
+ */
14
+ import { getSession } from "../lib/neo4j.js";
15
+ const QUEUES = [
16
+ {
17
+ label: "OrphanCandidate",
18
+ sampleQuery: `MATCH (o:OrphanCandidate) WHERE o.accountId = $accountId
19
+ RETURN o.orphanCandidateId AS id,
20
+ o.targetLabel AS targetLabel,
21
+ o.targetName AS targetName,
22
+ toString(o.since) AS since
23
+ ORDER BY o.createdAt DESC LIMIT $limit`,
24
+ countQuery: `MATCH (o:OrphanCandidate) WHERE o.accountId = $accountId RETURN count(o) AS c`,
25
+ },
26
+ {
27
+ label: "CitationProposal",
28
+ sampleQuery: `MATCH (p:CitationProposal) WHERE p.accountId = $accountId
29
+ RETURN p.citationProposalId AS id,
30
+ p.timelineEventId AS timelineEventId,
31
+ toString(coalesce(p.updatedAt, p.createdAt)) AS observedAt,
32
+ coalesce(p.reasoning, '') AS reasoning
33
+ ORDER BY coalesce(p.updatedAt, p.createdAt) DESC LIMIT $limit`,
34
+ countQuery: `MATCH (p:CitationProposal) WHERE p.accountId = $accountId RETURN count(p) AS c`,
35
+ },
36
+ ];
37
+ export async function memoryReviewQueue(params) {
38
+ const { accountId } = params;
39
+ const sampleSize = Math.min(Math.max(params.sampleSize ?? 5, 1), 25);
40
+ const session = getSession();
41
+ try {
42
+ const queues = [];
43
+ let totalPending = 0;
44
+ for (const q of QUEUES) {
45
+ const countRes = await session.run(q.countQuery, { accountId });
46
+ const count = Number(countRes.records[0]?.get("c") ?? 0);
47
+ totalPending += count;
48
+ const sampleRes = await session.run(q.sampleQuery, { accountId, limit: sampleSize });
49
+ const sample = sampleRes.records.map((rec) => {
50
+ const row = {};
51
+ for (const key of rec.keys) {
52
+ const value = rec.get(key);
53
+ row[String(key)] = value == null ? "" : String(value);
54
+ }
55
+ return row;
56
+ });
57
+ queues.push({ label: q.label, count, sample });
58
+ }
59
+ process.stderr.write(`[dream-cycle:review-queue] pending=${totalPending} queues=${queues.length}\n`);
60
+ return { queues, totalPending };
61
+ }
62
+ finally {
63
+ await session.close();
64
+ }
65
+ }
66
+ //# sourceMappingURL=memory-review-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-review-queue.js","sourceRoot":"","sources":["../../src/tools/memory-review-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAmB7C,MAAM,MAAM,GAAG;IACb;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE;;;;;yDAKwC;QACrD,UAAU,EAAE,+EAA+E;KAC5F;IACD;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE;;;;;gFAK+D;QAC5E,UAAU,EAAE,gFAAgF;KAC7F;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAA+B;IAE/B,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAErE,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAmB,EAAE,CAAC;QAClC,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;YAChE,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YACzD,YAAY,IAAI,KAAK,CAAC;YAEtB,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;YACrF,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC3C,MAAM,GAAG,GAA2B,EAAE,CAAC;gBACvC,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;oBAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBAC3B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACxD,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sCAAsC,YAAY,WAAW,MAAM,CAAC,MAAM,IAAI,CAC/E,CAAC;QAEF,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAClC,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"memory-search.d.ts","sourceRoot":"","sources":["../../src/tools/memory-search.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,+CAA+C,CAAC;AAmB7G,MAAM,MAAM,kBAAkB,GAC1B,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAC3B;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE1C,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,YAAY,EAAE,CAAC,CAyEzB"}
1
+ {"version":3,"file":"memory-search.d.ts","sourceRoot":"","sources":["../../src/tools/memory-search.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,+CAA+C,CAAC;AA8F7G,MAAM,MAAM,kBAAkB,GAC1B,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAC3B;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE1C,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,YAAY,EAAE,CAAC,CA2GzB"}
@@ -1,6 +1,91 @@
1
1
  import { getSession } from "../lib/neo4j.js";
2
2
  import { embed } from "../lib/embeddings.js";
3
3
  import { hybrid } from "../../../../../lib/graph-search/dist/index.js";
4
+ // ---------------------------------------------------------------------------
5
+ // Memory search — thin adapter over the shared `graph-search` lib.
6
+ // The hybrid pipeline, Lucene escape, BM25 normalisation, and graph expand
7
+ // all live in platform/lib/graph-search; this file threads the MCP tool
8
+ // parameters through and applies the trash-census observability log.
9
+ //
10
+ // Trash filter visibility: when the account holds `:Trashed` nodes we emit
11
+ // `[trash:read-filter-skipped]` so silent over-filtering stays observable.
12
+ // The census lives here (not in the shared lib) because it is MCP-tool-
13
+ // specific context the admin route doesn't share.
14
+ //
15
+ // Response-side `fields` projection (Task 138): narrows `properties` on each
16
+ // returned row to the caller-requested keys. Indexes and ranking are
17
+ // unaffected — hybrid() sees the full text either way. `related[*].properties`
18
+ // is intentionally NOT projected here.
19
+ //
20
+ // Public-scope compiled-truth projection (Task 392): when the caller's
21
+ // `allowedScopes` is exactly `['public']` (i.e. the public-agent spawn),
22
+ // rewrite the property bag on each result so the agent never sees the
23
+ // admin-side compiledTruth on a public-twin label, and never sees any
24
+ // compiledTruth on a :Person row. The Cypher `scope IN $allowedScopes`
25
+ // filter already drops nodes scoped admin/shared/user:X; this layer
26
+ // rewrites the *field shape* for the rows that survived that filter, so
27
+ // a :Organization with scope='public' surfaces compiledTruthPublic in
28
+ // the `compiledTruth` slot the agent already knows how to read.
29
+ // ---------------------------------------------------------------------------
30
+ /** Labels whose admin-side compiledTruth gets swapped for compiledTruthPublic in public projection (Task 392). */
31
+ const PUBLIC_TWIN_LABELS = new Set([
32
+ "Organization",
33
+ "Concept",
34
+ "Project",
35
+ "LocalBusiness",
36
+ ]);
37
+ /**
38
+ * Detect the public-agent read shape: scope filter is exactly `['public']`.
39
+ * Admin reads pass no scope filter or a broader allowedScopes list; either
40
+ * leaves the property bag untouched. Anything narrower than the exact
41
+ * `['public']` shape (e.g. `['public', 'shared']`) is treated as admin —
42
+ * we only project for the verified public-only entry point.
43
+ */
44
+ function isPublicOnlyScope(allowedScopes) {
45
+ return Array.isArray(allowedScopes) && allowedScopes.length === 1 && allowedScopes[0] === "public";
46
+ }
47
+ /**
48
+ * Rewrite the property bag on a single result row to surface the public twin.
49
+ * - Public-twin labels: swap `compiledTruth` → `compiledTruthPublic` (drop the admin field).
50
+ * - :Person: strip `compiledTruth` entirely (no public twin exists by design).
51
+ * - Other labels: no-op.
52
+ * Always strips the public-twin housekeeping fields (`compiledTruthPublicUpdatedAt`,
53
+ * `compiledTruthPublicSource`) — they are operator-side metadata, never customer-facing.
54
+ */
55
+ function projectPublicProperties(labels, properties) {
56
+ const isPublicTwin = labels.some((l) => PUBLIC_TWIN_LABELS.has(l));
57
+ const isPerson = labels.includes("Person");
58
+ const next = {};
59
+ let swapped = false;
60
+ let stripped = false;
61
+ for (const [k, v] of Object.entries(properties)) {
62
+ if (k === "compiledTruthPublicUpdatedAt" || k === "compiledTruthPublicSource") {
63
+ continue;
64
+ }
65
+ if (k === "compiledTruthPublic") {
66
+ if (isPublicTwin) {
67
+ next.compiledTruth = v;
68
+ swapped = true;
69
+ }
70
+ continue;
71
+ }
72
+ if (k === "compiledTruth") {
73
+ if (isPublicTwin) {
74
+ // Drop — the public twin (if present in the bag) will land in
75
+ // `compiledTruth` instead. If the public twin is absent from the
76
+ // bag (caller did not request it), the row loses compiledTruth
77
+ // entirely, which is the correct safe default for public reads.
78
+ continue;
79
+ }
80
+ if (isPerson) {
81
+ stripped = true;
82
+ continue;
83
+ }
84
+ }
85
+ next[k] = v;
86
+ }
87
+ return { properties: next, swapped, stripped };
88
+ }
4
89
  export async function memorySearch(params) {
5
90
  const session = getSession();
6
91
  const limit = params.limit ?? 10;
@@ -37,12 +122,47 @@ export async function memorySearch(params) {
37
122
  catch {
38
123
  // observability-only; never break a search on census failure.
39
124
  }
125
+ // Step 1: public-scope projection (Task 392). Runs before the `fields`
126
+ // narrowing so a caller that asks for `compiledTruth` on a public read
127
+ // gets the public twin in that slot — the narrowing then preserves the
128
+ // already-swapped key. Applied to both the top-level row and every
129
+ // `related[]` entry: graph-search's scope filter drops admin-scoped
130
+ // related nodes, but the property bag on the survivors still carries
131
+ // their compiledTruth, so without this pass a public-scope :Organization
132
+ // result could leak compiledTruth on a related :Person entry.
133
+ let workingResults = res.results;
134
+ const publicProjection = isPublicOnlyScope(params.allowedScopes);
135
+ if (publicProjection) {
136
+ let swappedRows = 0;
137
+ let strippedRows = 0;
138
+ let swappedRelated = 0;
139
+ let strippedRelated = 0;
140
+ workingResults = res.results.map((r) => {
141
+ const top = projectPublicProperties(r.labels, r.properties);
142
+ if (top.swapped)
143
+ swappedRows++;
144
+ if (top.stripped)
145
+ strippedRows++;
146
+ const related = r.related.map((rel) => {
147
+ const out = projectPublicProperties(rel.labels, rel.properties);
148
+ if (out.swapped)
149
+ swappedRelated++;
150
+ if (out.stripped)
151
+ strippedRelated++;
152
+ return { ...rel, properties: out.properties };
153
+ });
154
+ return { ...r, properties: top.properties, related };
155
+ });
156
+ process.stderr.write(`[memory-search:public-projection] accountId=${params.accountId} ` +
157
+ `rows=${workingResults.length} swapped=${swappedRows} stripped=${strippedRows} ` +
158
+ `relatedSwapped=${swappedRelated} relatedStripped=${strippedRelated}\n`);
159
+ }
40
160
  if (fields === undefined)
41
- return res.results;
161
+ return workingResults;
42
162
  const allowed = new Set(fields);
43
163
  let returnedProps = 0;
44
164
  let droppedProps = 0;
45
- const projected = res.results.map((r) => {
165
+ const projected = workingResults.map((r) => {
46
166
  const next = {};
47
167
  for (const [k, v] of Object.entries(r.properties)) {
48
168
  if (allowed.has(k)) {
@@ -1 +1 @@
1
- {"version":3,"file":"memory-search.js","sourceRoot":"","sources":["../../src/tools/memory-search.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory-search.js","sourceRoot":"","sources":["../../src/tools/memory-search.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,20 @@
1
1
  import { COMPILED_TRUTH_MAX_CHARS } from "../lib/graph-write-gate.js";
2
2
  import type { CreatedBy } from "../../../../../lib/graph-write/dist/index.js";
3
+ type RewriterOutcome = {
4
+ kind: "ok";
5
+ charsBefore: number;
6
+ charsAfter: number;
7
+ } | {
8
+ kind: "refused";
9
+ reason: "no-events" | "operator-edit-cooldown";
10
+ daysRemaining?: number;
11
+ } | {
12
+ kind: "too-long";
13
+ attemptedLen: number;
14
+ } | {
15
+ kind: "llm-failure";
16
+ cause: string;
17
+ };
3
18
  interface UpdateParams {
4
19
  nodeId: string;
5
20
  properties: Record<string, unknown>;
@@ -11,34 +26,55 @@ interface UpdateParams {
11
26
  * recent :TimelineEvent rows to recompute `compiledTruth`. Direct writes
12
27
  * to `compiledTruth` / `compiledTruthUpdatedAt` / `compiledTruthSource`
13
28
  * are rejected loudly — this flag is the only path.
29
+ *
30
+ * Task 392: when the target label is in the public-twin set
31
+ * (:Organization | :Concept | :Project | :LocalBusiness) and the admin
32
+ * pass actually changes the truth (not a string-identical no-op), the
33
+ * public-twin rewriter pass auto-fires inline and updates
34
+ * `compiledTruthPublic`. The admin and public passes share the same
35
+ * timeline-event snapshot.
14
36
  */
15
37
  rewriteCompiledTruth?: boolean;
16
38
  /**
17
39
  * Task 306: bypass the 7-day operator-edit cooldown. The cooldown exists
18
40
  * so an automatic rewriter pass does not overwrite an operator-authored
19
41
  * summary within a week of the edit. Only set this when the operator
20
- * explicitly asks for a refresh.
42
+ * explicitly asks for a refresh. Applies to BOTH the admin and public
43
+ * cooldowns when set during a twin-pass.
21
44
  */
22
45
  forceRewrite?: boolean;
46
+ /**
47
+ * Task 392: operator override for the public-twin summary. Bypasses the
48
+ * rewriter, writes the supplied string to `compiledTruthPublic`, stamps
49
+ * `compiledTruthPublicSource = 'operator'`, and resets the public-cooldown
50
+ * timer. Length is enforced via graph-write-gate (≤ COMPILED_TRUTH_MAX_CHARS).
51
+ * Only valid when the target label is in the public-twin set.
52
+ */
53
+ compiledTruthPublic?: string;
23
54
  }
24
55
  interface UpdateResult {
25
56
  nodeId: string;
26
57
  labels: string[];
27
58
  updated: boolean;
28
- rewriter?: {
29
- kind: "ok";
30
- charsBefore: number;
31
- charsAfter: number;
59
+ rewriter?: RewriterOutcome;
60
+ /**
61
+ * Task 392: outcome of the public-twin rewriter pass when it was invoked.
62
+ * Absent when the target label is :Person, when `rewriteCompiledTruth`
63
+ * was false, when the admin pass was a no-op, or when the admin pass
64
+ * itself did not return `ok`.
65
+ */
66
+ publicRewriter?: RewriterOutcome;
67
+ /**
68
+ * Task 392: outcome of the operator direct-write of `compiledTruthPublic`,
69
+ * when supplied. `applied` means the field was written; `refused` carries
70
+ * a reason matching the cooldown / label gates.
71
+ */
72
+ publicOverride?: {
73
+ kind: "applied";
74
+ chars: number;
32
75
  } | {
33
76
  kind: "refused";
34
- reason: "no-events" | "operator-edit-cooldown";
35
- daysRemaining?: number;
36
- } | {
37
- kind: "too-long";
38
- attemptedLen: number;
39
- } | {
40
- kind: "llm-failure";
41
- cause: string;
77
+ reason: "wrong-label" | "too-long";
42
78
  };
43
79
  }
44
80
  export declare function memoryUpdate(params: UpdateParams): Promise<UpdateResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"memory-update.d.ts","sourceRoot":"","sources":["../../src/tools/memory-update.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,wBAAwB,EACzB,MAAM,4BAA4B,CAAC;AAOpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8CAA8C,CAAC;AAE9E,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,SAAS,EAAE,SAAS,CAAC;IACrB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EACL;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GACvD;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,WAAW,GAAG,wBAAwB,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3F;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,GAC1C;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAgBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAO9E;AA2PD,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
1
+ {"version":3,"file":"memory-update.d.ts","sourceRoot":"","sources":["../../src/tools/memory-update.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,wBAAwB,EACzB,MAAM,4BAA4B,CAAC;AAUpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8CAA8C,CAAC;AAE9E,KAAK,eAAe,GAChB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,wBAAwB,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3F;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3C,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,SAAS,EAAE,SAAS,CAAC;IACrB;;;;;;;;;;;;OAYG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC;;;;OAIG;IACH,cAAc,CAAC,EACX;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAClC;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,aAAa,GAAG,UAAU,CAAA;KAAE,CAAC;CAC7D;AAmDD,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAO9E;AAoaD,OAAO,EAAE,wBAAwB,EAAE,CAAC"}