@rubytech/create-maxy-code 0.1.143 → 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 (131) 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/platform/templates/specialists/agents/personal-assistant.md +1 -1
  129. package/payload/server/server.js +195 -91
  130. package/payload/platform/plugins/admin/hooks/signal-detector-stop.sh +0 -309
  131. package/payload/platform/templates/specialists/agents/signal-detector.md +0 -129
@@ -39,24 +39,27 @@
39
39
  /** Compiled-truth cap. ≤2000 chars ≈ 300 words — forces the rewriter to summarise, not transcribe. */
40
40
  export const COMPILED_TRUTH_MAX_CHARS = 2000;
41
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.
42
+ * Property-level write gate (Task 306, extended Task 392). The cap applies
43
+ * to both `compiledTruth` and its public twin `compiledTruthPublic`; either
44
+ * field exceeding COMPILED_TRUTH_MAX_CHARS rejects the write. Used by both
45
+ * `memory-write` and `memory-update`; the rewriter calls it before writing too.
45
46
  *
46
47
  * Pure / synchronous on purpose — no session needed. Loud-fail on
47
48
  * violation so an over-producing rewriter surfaces immediately instead
48
49
  * of silently truncating the operator's summary.
49
50
  */
50
51
  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
- };
52
+ for (const field of ["compiledTruth", "compiledTruthPublic"]) {
53
+ const value = args.properties[field];
54
+ if (typeof value === "string" && value.length > COMPILED_TRUTH_MAX_CHARS) {
55
+ console.log(`[graph-write-gate] reject reason=compiled-truth-too-long field=${field} len=${value.length} cap=${COMPILED_TRUTH_MAX_CHARS}`);
56
+ return {
57
+ ok: false,
58
+ reason: "compiled-truth-too-long",
59
+ message: `${field} length ${value.length} exceeds cap of ${COMPILED_TRUTH_MAX_CHARS} chars. ` +
60
+ `The rewriter must produce a tighter summary.`,
61
+ };
62
+ }
60
63
  }
61
64
  return { ok: true };
62
65
  }
@@ -65,6 +68,38 @@ const EXEMPT_LABELS = new Set([
65
68
  "LocalBusiness",
66
69
  "AdminUser",
67
70
  ]);
71
+ /**
72
+ * Labels the agent must never write directly via memory-write /
73
+ * memory-update. `:CompiledTruthRevision` (compiled-truth rewriter) is read-only after
74
+ * write: the only writer is the rewriter (composed via the revision
75
+ * helper, in the same transaction as the live `compiledTruth` SET), and
76
+ * the only mutation path is the dream-cycle prune. Direct writes from
77
+ * the agent would let an LLM forge or rewrite audit history — defeating
78
+ * the point of having it.
79
+ */
80
+ const FORBIDDEN_LABELS = new Set([
81
+ "CompiledTruthRevision",
82
+ ]);
83
+ /**
84
+ * Label-level write gate (compiled-truth rewriter). Rejects any agent-side write
85
+ * whose labels include a FORBIDDEN_LABEL. Pure / synchronous — no
86
+ * session needed.
87
+ */
88
+ export function checkLabelWriteGate(args) {
89
+ for (const label of args.labels) {
90
+ if (FORBIDDEN_LABELS.has(label)) {
91
+ console.log(`[graph-write-gate] reject reason=forbidden-label label=${label}`);
92
+ return {
93
+ ok: false,
94
+ reason: "forbidden-label",
95
+ forbiddenLabel: label,
96
+ message: `:${label} is read-only and may not be written via memory-write or memory-update. ` +
97
+ `It is produced by the compiled-truth rewriter (compiled-truth rewriter) and pruned by the dream-cycle.`,
98
+ };
99
+ }
100
+ }
101
+ return { ok: true };
102
+ }
68
103
  const NEXT_MOVE = "Run the business-profile skill to establish the admin user and business " +
69
104
  "identity, or complete the personal-profile bootstrap (onboarding step 9 " +
70
105
  "personal mode), before writing this node.";
@@ -1 +1 @@
1
- {"version":3,"file":"graph-write-gate.js","sourceRoot":"","sources":["../../src/lib/graph-write-gate.ts"],"names":[],"mappings":"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"}
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 type RelativeDateForm = "literal-day" | "weekday" | "ago" | "holiday" | "quarter";
2
+ export interface RelativeDateMatch {
3
+ date: Date;
4
+ form: RelativeDateForm;
5
+ /** The literal phrase that matched, for diagnostics. */
6
+ matched: string;
7
+ }
8
+ /**
9
+ * Parse `text` against `reference`. Returns the first matching form or null.
10
+ * Recurring phrases ("every other Friday") return null by design.
11
+ */
12
+ export declare function parseRelativeDate(text: string, reference: Date): RelativeDateMatch | null;
13
+ //# sourceMappingURL=relative-date.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relative-date.d.ts","sourceRoot":"","sources":["../../src/lib/relative-date.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;AAEzF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;CACjB;AAkJD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,iBAAiB,GAAG,IAAI,CAazF"}
@@ -0,0 +1,191 @@
1
+ // Task 390: deterministic relative-date parser.
2
+ //
3
+ // Parses a free-text date phrase against a reference timestamp and returns
4
+ // the resolved Date plus the form that matched. Used by:
5
+ // - timeline-extractor.ts (sentence-scoped parse during memory-write)
6
+ // - datetime/SKILL.md (operator-facing arithmetic via `node -e`)
7
+ //
8
+ // Both consumers need identical semantics; this is the single source of
9
+ // truth. The parser is deterministic — no LLM, no chrono-node. Forms not
10
+ // listed here return null; the caller decides what to do with that.
11
+ //
12
+ // Recognised forms (priority order — first match wins):
13
+ // 1. Literal day words — yesterday / today / tomorrow
14
+ // 2. Last/next/this <weekday> — "last Tuesday", "next Fri"
15
+ // 3. N units ago — "two weeks ago", "3 days ago"
16
+ // 4. Holiday anchors — "this Christmas", "this New Year"
17
+ // 5. Fiscal quarter, year known — "Q3 2024", "Q1 25"
18
+ // 6. Fiscal quarter, year word — "Q3 last year", "Q1 this year"
19
+ //
20
+ // Recurring forms ("every other Friday") return null intentionally —
21
+ // they belong on :Routine, not :TimelineEvent.
22
+ const WEEKDAYS = {
23
+ sun: 0, sunday: 0,
24
+ mon: 1, monday: 1,
25
+ tue: 2, tues: 2, tuesday: 2,
26
+ wed: 3, weds: 3, wednesday: 3,
27
+ thu: 4, thur: 4, thurs: 4, thursday: 4,
28
+ fri: 5, friday: 5,
29
+ sat: 6, saturday: 6,
30
+ };
31
+ const WORD_NUMBERS = {
32
+ one: 1, two: 2, three: 3, four: 4, five: 5,
33
+ six: 6, seven: 7, eight: 8, nine: 9, ten: 10,
34
+ eleven: 11, twelve: 12,
35
+ };
36
+ function startOfDay(d) {
37
+ const out = new Date(d.getTime());
38
+ out.setUTCHours(0, 0, 0, 0);
39
+ return out;
40
+ }
41
+ function addDays(d, n) {
42
+ const out = new Date(d.getTime());
43
+ out.setUTCDate(out.getUTCDate() + n);
44
+ return out;
45
+ }
46
+ function addMonths(d, n) {
47
+ const out = new Date(d.getTime());
48
+ out.setUTCMonth(out.getUTCMonth() + n);
49
+ return out;
50
+ }
51
+ function addYears(d, n) {
52
+ const out = new Date(d.getTime());
53
+ out.setUTCFullYear(out.getUTCFullYear() + n);
54
+ return out;
55
+ }
56
+ /** Returns null for "every other X" / "every X" — recurring is not a TimelineEvent. */
57
+ function isRecurring(text) {
58
+ return /\bevery(\s+other)?\s+/i.test(text);
59
+ }
60
+ function parseLiteralDay(text, ref) {
61
+ const m = text.match(/\b(yesterday|today|tomorrow)\b/i);
62
+ if (!m)
63
+ return null;
64
+ const word = m[1].toLowerCase();
65
+ const base = startOfDay(ref);
66
+ if (word === "yesterday")
67
+ return { date: addDays(base, -1), form: "literal-day", matched: m[0] };
68
+ if (word === "tomorrow")
69
+ return { date: addDays(base, 1), form: "literal-day", matched: m[0] };
70
+ return { date: base, form: "literal-day", matched: m[0] };
71
+ }
72
+ function parseWeekday(text, ref) {
73
+ // "last Tuesday", "next Fri", "this Monday"
74
+ const m = text.match(/\b(last|next|this)\s+([A-Za-z]+)\b/i);
75
+ if (!m)
76
+ return null;
77
+ const qualifier = m[1].toLowerCase();
78
+ const target = WEEKDAYS[m[2].toLowerCase()];
79
+ if (target === undefined)
80
+ return null;
81
+ const base = startOfDay(ref);
82
+ const refDow = base.getUTCDay();
83
+ let delta;
84
+ if (qualifier === "last") {
85
+ delta = target - refDow;
86
+ if (delta >= 0)
87
+ delta -= 7;
88
+ }
89
+ else if (qualifier === "next") {
90
+ delta = target - refDow;
91
+ if (delta <= 0)
92
+ delta += 7;
93
+ }
94
+ else {
95
+ // "this <weekday>" — the matching day in the current ISO week
96
+ // (Mon-Sun). For ref = Wed, "this Monday" is two days ago;
97
+ // "this Friday" is two days ahead. Always within +/-6 days of ref.
98
+ const isoDow = refDow === 0 ? 7 : refDow; // Mon=1..Sun=7
99
+ const isoTarget = target === 0 ? 7 : target;
100
+ delta = isoTarget - isoDow;
101
+ }
102
+ return { date: addDays(base, delta), form: "weekday", matched: m[0] };
103
+ }
104
+ function parseUnitsAgo(text, ref) {
105
+ // "two weeks ago", "3 days ago", "a month ago"
106
+ const m = text.match(/\b(a|an|\d+|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)\s+(day|week|month|year)s?\s+ago\b/i);
107
+ if (!m)
108
+ return null;
109
+ const numWord = m[1].toLowerCase();
110
+ let n;
111
+ if (numWord === "a" || numWord === "an")
112
+ n = 1;
113
+ else if (WORD_NUMBERS[numWord] !== undefined)
114
+ n = WORD_NUMBERS[numWord];
115
+ else
116
+ n = Number(numWord);
117
+ if (!Number.isFinite(n) || n <= 0)
118
+ return null;
119
+ const unit = m[2].toLowerCase();
120
+ const base = startOfDay(ref);
121
+ let date;
122
+ if (unit === "day")
123
+ date = addDays(base, -n);
124
+ else if (unit === "week")
125
+ date = addDays(base, -7 * n);
126
+ else if (unit === "month")
127
+ date = addMonths(base, -n);
128
+ else
129
+ date = addYears(base, -n);
130
+ return { date, form: "ago", matched: m[0] };
131
+ }
132
+ function parseHoliday(text, ref) {
133
+ // "this Christmas" -> 25 Dec of reference year.
134
+ // "this New Year" -> 1 Jan of reference year.
135
+ const xmas = text.match(/\b(?:this\s+)?Christmas\b/i);
136
+ if (xmas) {
137
+ const d = new Date(Date.UTC(ref.getUTCFullYear(), 11, 25));
138
+ return { date: d, form: "holiday", matched: xmas[0] };
139
+ }
140
+ const ny = text.match(/\b(?:this\s+)?New\s+Year('s)?(\s+Day)?\b/i);
141
+ if (ny) {
142
+ const d = new Date(Date.UTC(ref.getUTCFullYear(), 0, 1));
143
+ return { date: d, form: "holiday", matched: ny[0] };
144
+ }
145
+ return null;
146
+ }
147
+ function quarterStart(year, q) {
148
+ // Q1 -> Jan 1, Q2 -> Apr 1, Q3 -> Jul 1, Q4 -> Oct 1.
149
+ return new Date(Date.UTC(year, (q - 1) * 3, 1));
150
+ }
151
+ function parseQuarter(text, ref) {
152
+ // "Q3 2024", "Q1 25", "Q4 last year", "Q2 this year", "Q1 next year"
153
+ const explicit = text.match(/\bQ([1-4])\s+(\d{2}|\d{4})\b/i);
154
+ if (explicit) {
155
+ const q = Number(explicit[1]);
156
+ let y = Number(explicit[2]);
157
+ if (y < 100)
158
+ y = 2000 + y;
159
+ if (y < 1900 || y > 2099)
160
+ return null;
161
+ return { date: quarterStart(y, q), form: "quarter", matched: explicit[0] };
162
+ }
163
+ const relative = text.match(/\bQ([1-4])\s+(last|this|next)\s+year\b/i);
164
+ if (relative) {
165
+ const q = Number(relative[1]);
166
+ const word = relative[2].toLowerCase();
167
+ const refYear = ref.getUTCFullYear();
168
+ const y = word === "last" ? refYear - 1 : word === "next" ? refYear + 1 : refYear;
169
+ return { date: quarterStart(y, q), form: "quarter", matched: relative[0] };
170
+ }
171
+ return null;
172
+ }
173
+ /**
174
+ * Parse `text` against `reference`. Returns the first matching form or null.
175
+ * Recurring phrases ("every other Friday") return null by design.
176
+ */
177
+ export function parseRelativeDate(text, reference) {
178
+ if (!text || typeof text !== "string")
179
+ return null;
180
+ if (!(reference instanceof Date) || Number.isNaN(reference.getTime()))
181
+ return null;
182
+ if (isRecurring(text))
183
+ return null;
184
+ return (parseLiteralDay(text, reference) ??
185
+ parseWeekday(text, reference) ??
186
+ parseUnitsAgo(text, reference) ??
187
+ parseHoliday(text, reference) ??
188
+ parseQuarter(text, reference) ??
189
+ null);
190
+ }
191
+ //# sourceMappingURL=relative-date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relative-date.js","sourceRoot":"","sources":["../../src/lib/relative-date.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,2EAA2E;AAC3E,yDAAyD;AACzD,wEAAwE;AACxE,mEAAmE;AACnE,EAAE;AACF,wEAAwE;AACxE,yEAAyE;AACzE,oEAAoE;AACpE,EAAE;AACF,wDAAwD;AACxD,kEAAkE;AAClE,gEAAgE;AAChE,mEAAmE;AACnE,uEAAuE;AACvE,wDAAwD;AACxD,oEAAoE;AACpE,EAAE;AACF,qEAAqE;AACrE,+CAA+C;AAW/C,MAAM,QAAQ,GAA2B;IACvC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;IAC3B,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC;IAC7B,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,YAAY,GAA2B;IAC3C,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;IAC1C,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;IAC5C,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE;CACvB,CAAC;AAEF,SAAS,UAAU,CAAC,CAAO;IACzB,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAClC,GAAG,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,OAAO,CAAC,CAAO,EAAE,CAAS;IACjC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAClC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;IACrC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,CAAO,EAAE,CAAS;IACnC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAClC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;IACvC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,QAAQ,CAAC,CAAO,EAAE,CAAS;IAClC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAClC,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7C,OAAO,GAAG,CAAC;AACb,CAAC;AAED,uFAAuF;AACvF,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,GAAS;IAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACxD,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjG,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/F,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,GAAS;IAC3C,4CAA4C;IAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAC5D,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,IAAI,KAAa,CAAC;IAClB,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;QACxB,IAAI,KAAK,IAAI,CAAC;YAAE,KAAK,IAAI,CAAC,CAAC;IAC7B,CAAC;SAAM,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QAChC,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;QACxB,IAAI,KAAK,IAAI,CAAC;YAAE,KAAK,IAAI,CAAC,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,8DAA8D;QAC9D,2DAA2D;QAC3D,mEAAmE;QACnE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,eAAe;QACzD,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5C,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;IAC7B,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACxE,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,GAAS;IAC5C,+CAA+C;IAC/C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,gHAAgH,CAAC,CAAC;IACvI,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACnC,IAAI,CAAS,CAAC;IACd,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI;QAAE,CAAC,GAAG,CAAC,CAAC;SAC1C,IAAI,YAAY,CAAC,OAAO,CAAC,KAAK,SAAS;QAAE,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;;QACnE,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,IAAU,CAAC;IACf,IAAI,IAAI,KAAK,KAAK;QAAE,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;SACxC,IAAI,IAAI,KAAK,MAAM;QAAE,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;SAClD,IAAI,IAAI,KAAK,OAAO;QAAE,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;;QACjD,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9C,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,GAAS;IAC3C,gDAAgD;IAChD,8CAA8C;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IACtD,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAC3D,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;IACnE,IAAI,EAAE,EAAE,CAAC;QACP,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACzD,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,CAAS;IAC3C,sDAAsD;IACtD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,GAAS;IAC3C,qEAAqE;IACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC7D,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,CAAC,GAAG,GAAG;YAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI;YAAE,OAAO,IAAI,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7E,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACvE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAClF,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,SAAe;IAC7D,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnD,IAAI,CAAC,CAAC,SAAS,YAAY,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACnF,IAAI,WAAW,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEnC,OAAO,CACL,eAAe,CAAC,IAAI,EAAE,SAAS,CAAC;QAChC,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC;QAC7B,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC;QAC9B,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC;QAC7B,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC;QAC7B,IAAI,CACL,CAAC;AACJ,CAAC"}
@@ -1,13 +1,19 @@
1
+ export type DateForm = "iso" | "dmy" | "my" | "in-year" | "bare-year" | "relative" | "quarter";
1
2
  export interface DatedStatement {
2
3
  occurredAt: string;
3
4
  summary: string;
4
5
  /** The literal date phrase that triggered the match. Useful for diagnostics. */
5
6
  matched: string;
7
+ /** Which heuristic matched. */
8
+ form: DateForm;
6
9
  }
7
10
  /**
8
11
  * Extract every dated statement from `body`. One row per sentence containing
9
12
  * the first parseable date in that sentence. Sentences without a date are
10
13
  * dropped silently (the diagnostic count is the caller's concern).
14
+ *
15
+ * `reference` anchors relative forms ("yesterday", "two weeks ago", "Q3 last
16
+ * year"). Callers pass the message's createdAt; absent that, current time.
11
17
  */
12
- export declare function extractDatedStatements(body: string | null | undefined): DatedStatement[];
18
+ export declare function extractDatedStatements(body: string | null | undefined, reference?: Date): DatedStatement[];
13
19
  //# sourceMappingURL=timeline-extractor.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"timeline-extractor.d.ts","sourceRoot":"","sources":["../../src/lib/timeline-extractor.ts"],"names":[],"mappings":"AA2BA,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;AAE/F,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,IAAI,EAAE,QAAQ,CAAC;CAChB;AAiJD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,SAAS,GAAE,IAAiB,GAC3B,cAAc,EAAE,CA0BlB"}
@@ -13,12 +13,16 @@
13
13
  // 4. "in YYYY" — "in 2018"
14
14
  // 5. "since YYYY" — "since 2018"
15
15
  // 6. Bare year — 2018 (only when 1900-2099 and surrounded by word boundaries)
16
+ // 7. Relative + quarter — yesterday / last Tuesday / two weeks ago / Q3 2024
17
+ // (Task 390 — delegated to parseRelativeDate against caller-supplied reference)
16
18
  //
17
19
  // Coarse forms (bare year, "in YYYY") parse to YYYY-01-01T00:00:00Z so the
18
20
  // `occurredAt` index is queryable. Day-precision forms parse exactly.
21
+ // Relative forms resolve to a UTC day from the reference timestamp.
19
22
  //
20
23
  // A statement is the sentence containing the parsed date. Summaries
21
24
  // truncate to 500 chars at sentence boundaries when possible.
25
+ import { parseRelativeDate } from "./relative-date.js";
22
26
  const MONTHS = {
23
27
  jan: 1, january: 1,
24
28
  feb: 2, february: 2,
@@ -77,7 +81,7 @@ function clampSummary(s) {
77
81
  * Returns null if the sentence has no parseable date; otherwise the first
78
82
  * matching date and its ISO normalisation.
79
83
  */
80
- function parseFirstDate(sentence) {
84
+ function parseFirstDate(sentence, reference) {
81
85
  // 1. ISO date: 2026-03-10 or 2026/03/10
82
86
  const iso = sentence.match(/\b(\d{4})[-/](\d{1,2})[-/](\d{1,2})\b/);
83
87
  if (iso) {
@@ -85,7 +89,7 @@ function parseFirstDate(sentence) {
85
89
  const m = Number(iso[2]);
86
90
  const d = Number(iso[3]);
87
91
  if (validYear(y) && validMonth(m) && validDay(d)) {
88
- return { occurredAt: isoDay(y, m, d), matched: iso[0] };
92
+ return { occurredAt: isoDay(y, m, d), matched: iso[0], form: "iso" };
89
93
  }
90
94
  }
91
95
  // 2. Day-month-year: "10 March 2026" / "10 Mar 2026"
@@ -95,7 +99,7 @@ function parseFirstDate(sentence) {
95
99
  const m = MONTHS[dmy[2].toLowerCase()];
96
100
  const y = Number(dmy[3]);
97
101
  if (m && validYear(y) && validDay(d)) {
98
- return { occurredAt: isoDay(y, m, d), matched: dmy[0] };
102
+ return { occurredAt: isoDay(y, m, d), matched: dmy[0], form: "dmy" };
99
103
  }
100
104
  }
101
105
  // 3. Month-year: "March 2026" / "Mar 2026"
@@ -104,7 +108,7 @@ function parseFirstDate(sentence) {
104
108
  const m = MONTHS[my[1].toLowerCase()];
105
109
  const y = Number(my[2]);
106
110
  if (m && validYear(y)) {
107
- return { occurredAt: isoMonth(y, m), matched: my[0] };
111
+ return { occurredAt: isoMonth(y, m), matched: my[0], form: "my" };
108
112
  }
109
113
  }
110
114
  // 4 + 5. "in YYYY" / "since YYYY"
@@ -112,17 +116,28 @@ function parseFirstDate(sentence) {
112
116
  if (inYear) {
113
117
  const y = Number(inYear[1]);
114
118
  if (validYear(y)) {
115
- return { occurredAt: isoYear(y), matched: inYear[0] };
119
+ return { occurredAt: isoYear(y), matched: inYear[0], form: "in-year" };
116
120
  }
117
121
  }
118
- // 6. Bare year restrictive: must be 4 digits surrounded by word boundaries
122
+ // 6. Relative + quarter forms (Task 390). Delegated to the shared lib so the
123
+ // datetime skill calls the same code path. Checked before bare-year so that
124
+ // "Q3 2024" parses as the quarter rather than the bare year 2024.
125
+ const rel = parseRelativeDate(sentence, reference);
126
+ if (rel) {
127
+ return {
128
+ occurredAt: rel.date.toISOString().replace(/\.\d{3}Z$/, "Z"),
129
+ matched: rel.matched,
130
+ form: rel.form === "quarter" ? "quarter" : "relative",
131
+ };
132
+ }
133
+ // 7. Bare year — restrictive: must be 4 digits surrounded by word boundaries
119
134
  // and not preceded by "$" (price), ":" (time), or "-" (already part of a
120
135
  // date we would have matched above). Cheap defensive guards.
121
136
  const bareYear = sentence.match(/(?<![$:\d-])\b(\d{4})\b(?!\s*[-/]\d)/);
122
137
  if (bareYear) {
123
138
  const y = Number(bareYear[1]);
124
139
  if (validYear(y)) {
125
- return { occurredAt: isoYear(y), matched: bareYear[0] };
140
+ return { occurredAt: isoYear(y), matched: bareYear[0], form: "bare-year" };
126
141
  }
127
142
  }
128
143
  return null;
@@ -131,21 +146,34 @@ function parseFirstDate(sentence) {
131
146
  * Extract every dated statement from `body`. One row per sentence containing
132
147
  * the first parseable date in that sentence. Sentences without a date are
133
148
  * dropped silently (the diagnostic count is the caller's concern).
149
+ *
150
+ * `reference` anchors relative forms ("yesterday", "two weeks ago", "Q3 last
151
+ * year"). Callers pass the message's createdAt; absent that, current time.
134
152
  */
135
- export function extractDatedStatements(body) {
153
+ export function extractDatedStatements(body, reference = new Date()) {
136
154
  if (!body || typeof body !== "string")
137
155
  return [];
156
+ const ref = reference instanceof Date && !Number.isNaN(reference.getTime())
157
+ ? reference
158
+ : new Date();
138
159
  const out = [];
160
+ const formCounts = {};
139
161
  for (const sentence of splitSentences(body)) {
140
- const hit = parseFirstDate(sentence);
162
+ const hit = parseFirstDate(sentence, ref);
141
163
  if (hit) {
142
164
  out.push({
143
165
  occurredAt: hit.occurredAt,
144
166
  summary: clampSummary(sentence),
145
167
  matched: hit.matched,
168
+ form: hit.form,
146
169
  });
170
+ formCounts[hit.form] = (formCounts[hit.form] ?? 0) + 1;
147
171
  }
148
172
  }
173
+ // Task 390 diagnostic: coverage so the rewriter team can observe parse rate.
174
+ const forms = Object.keys(formCounts).sort().join(",");
175
+ // eslint-disable-next-line no-console
176
+ console.log(`[timeline-extract] coverage body-len=${body.length} dates=${out.length}${forms ? ` forms=[${forms}]` : ""}`);
149
177
  return out;
150
178
  }
151
179
  //# sourceMappingURL=timeline-extractor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeline-extractor.js","sourceRoot":"","sources":["../../src/lib/timeline-extractor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"timeline-extractor.js","sourceRoot":"","sources":["../../src/lib/timeline-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=memory-compiled-truth-history.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-compiled-truth-history.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/memory-compiled-truth-history.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,81 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { readFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ vi.mock("../../lib/neo4j.js", () => {
5
+ const run = vi.fn();
6
+ const close = vi.fn();
7
+ return {
8
+ getSession: () => ({ run, close }),
9
+ __mocks: { run, close },
10
+ };
11
+ });
12
+ import { memoryCompiledTruthHistory } from "../memory-compiled-truth-history.js";
13
+ import * as neo4jMock from "../../lib/neo4j.js";
14
+ const { run, close } = neo4jMock.__mocks;
15
+ function row(props) {
16
+ return { get: (key) => props[key] };
17
+ }
18
+ describe("memoryCompiledTruthHistory", () => {
19
+ beforeEach(() => {
20
+ run.mockReset();
21
+ close.mockReset();
22
+ });
23
+ it("returns revisions newest first, account-scoped", async () => {
24
+ run.mockResolvedValue({
25
+ records: [
26
+ row({
27
+ revisionId: "00000000-0000-0000-0000-000000000002",
28
+ truth: "Newer truth",
29
+ writtenAt: "2026-05-25T10:00:00Z",
30
+ source: "rewriter",
31
+ }),
32
+ row({
33
+ revisionId: "00000000-0000-0000-0000-000000000001",
34
+ truth: "Older truth",
35
+ writtenAt: "2026-05-20T10:00:00Z",
36
+ source: "rewriter",
37
+ }),
38
+ ],
39
+ });
40
+ const result = await memoryCompiledTruthHistory({
41
+ accountId: "acc-1",
42
+ nodeId: "4:abc:1",
43
+ });
44
+ expect(result.entityNodeId).toBe("4:abc:1");
45
+ expect(result.revisions).toHaveLength(2);
46
+ expect(result.revisions[0].truth).toBe("Newer truth");
47
+ expect(result.revisions[1].truth).toBe("Older truth");
48
+ const args = run.mock.calls[0];
49
+ expect(args[0]).toContain("ORDER BY r.writtenAt DESC");
50
+ expect(args[0]).toContain("e.accountId = $accountId");
51
+ expect(args[0]).toContain("r.accountId = $accountId");
52
+ expect(args[1]).toEqual({ accountId: "acc-1", nodeId: "4:abc:1", limit: 20 });
53
+ });
54
+ it("returns an empty list when no revisions exist", async () => {
55
+ run.mockResolvedValue({ records: [] });
56
+ const result = await memoryCompiledTruthHistory({
57
+ accountId: "acc-1",
58
+ nodeId: "4:abc:2",
59
+ });
60
+ expect(result.revisions).toEqual([]);
61
+ });
62
+ it("throws when accountId or nodeId is missing", async () => {
63
+ await expect(memoryCompiledTruthHistory({ accountId: "", nodeId: "4:abc:1" })).rejects.toThrow(/accountId/);
64
+ await expect(memoryCompiledTruthHistory({ accountId: "acc-1", nodeId: "" })).rejects.toThrow(/nodeId/);
65
+ });
66
+ });
67
+ describe("memory-compiled-truth-history registration", () => {
68
+ it("registered in tool server index.ts as an eagerTool", () => {
69
+ const src = readFileSync(resolve(import.meta.dirname, "../../index.ts"), "utf-8");
70
+ expect(src).toMatch(/eagerTool\(server,\s*\n?\s*"memory-compiled-truth-history"/);
71
+ expect(src).toContain('registered tool=memory-compiled-truth-history');
72
+ });
73
+ it("declared in PLUGIN.md with admin allowlist", () => {
74
+ const plugin = readFileSync(resolve(import.meta.dirname, "../../../../PLUGIN.md"), "utf-8");
75
+ expect(plugin).toContain("name: memory-compiled-truth-history");
76
+ // verify admin allowlist line follows shortly after the name
77
+ const idx = plugin.indexOf("name: memory-compiled-truth-history");
78
+ expect(plugin.slice(idx, idx + 120)).toContain("adminAllowlist: true");
79
+ });
80
+ });
81
+ //# sourceMappingURL=memory-compiled-truth-history.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-compiled-truth-history.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/memory-compiled-truth-history.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=memory-report-tools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-report-tools.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/memory-report-tools.test.ts"],"names":[],"mappings":""}