bikky 0.3.2 → 0.3.5

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 (145) hide show
  1. package/README.md +83 -34
  2. package/dist/config.d.ts +1 -0
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +6 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/config.test.d.ts +3 -2
  7. package/dist/config.test.d.ts.map +1 -1
  8. package/dist/config.test.js +12 -6
  9. package/dist/config.test.js.map +1 -1
  10. package/dist/daemon/capture-policy.d.ts +4 -4
  11. package/dist/daemon/capture-policy.d.ts.map +1 -1
  12. package/dist/daemon/capture-policy.js +8 -17
  13. package/dist/daemon/capture-policy.js.map +1 -1
  14. package/dist/daemon/capture-policy.test.js +2 -2
  15. package/dist/daemon/capture-policy.test.js.map +1 -1
  16. package/dist/daemon/entity-typing.d.ts +20 -0
  17. package/dist/daemon/entity-typing.d.ts.map +1 -0
  18. package/dist/daemon/entity-typing.js +166 -0
  19. package/dist/daemon/entity-typing.js.map +1 -0
  20. package/dist/daemon/episode-summary.d.ts +4 -6
  21. package/dist/daemon/episode-summary.d.ts.map +1 -1
  22. package/dist/daemon/episode-summary.js +24 -38
  23. package/dist/daemon/episode-summary.js.map +1 -1
  24. package/dist/daemon/episode-summary.test.js +5 -5
  25. package/dist/daemon/episode-summary.test.js.map +1 -1
  26. package/dist/daemon/extraction-quality.test.d.ts +2 -0
  27. package/dist/daemon/extraction-quality.test.d.ts.map +1 -0
  28. package/dist/daemon/extraction-quality.test.js +283 -0
  29. package/dist/daemon/extraction-quality.test.js.map +1 -0
  30. package/dist/daemon/extraction-rules.d.ts +131 -0
  31. package/dist/daemon/extraction-rules.d.ts.map +1 -0
  32. package/dist/daemon/extraction-rules.js +321 -0
  33. package/dist/daemon/extraction-rules.js.map +1 -0
  34. package/dist/daemon/extraction-rules.test.d.ts +2 -0
  35. package/dist/daemon/extraction-rules.test.d.ts.map +1 -0
  36. package/dist/daemon/extraction-rules.test.js +183 -0
  37. package/dist/daemon/extraction-rules.test.js.map +1 -0
  38. package/dist/daemon/extraction.d.ts +19 -1
  39. package/dist/daemon/extraction.d.ts.map +1 -1
  40. package/dist/daemon/extraction.js +169 -21
  41. package/dist/daemon/extraction.js.map +1 -1
  42. package/dist/daemon/extraction.test.js +96 -2
  43. package/dist/daemon/extraction.test.js.map +1 -1
  44. package/dist/daemon/loop.d.ts.map +1 -1
  45. package/dist/daemon/loop.js +14 -0
  46. package/dist/daemon/loop.js.map +1 -1
  47. package/dist/daemon/qdrant.d.ts +15 -1
  48. package/dist/daemon/qdrant.d.ts.map +1 -1
  49. package/dist/daemon/qdrant.js +45 -2
  50. package/dist/daemon/qdrant.js.map +1 -1
  51. package/dist/daemon/relations-vocab.d.ts +44 -0
  52. package/dist/daemon/relations-vocab.d.ts.map +1 -0
  53. package/dist/daemon/relations-vocab.js +168 -0
  54. package/dist/daemon/relations-vocab.js.map +1 -0
  55. package/dist/daemon/relations-vocab.test.d.ts +2 -0
  56. package/dist/daemon/relations-vocab.test.d.ts.map +1 -0
  57. package/dist/daemon/relations-vocab.test.js +69 -0
  58. package/dist/daemon/relations-vocab.test.js.map +1 -0
  59. package/dist/daemon/relations.d.ts +2 -0
  60. package/dist/daemon/relations.d.ts.map +1 -1
  61. package/dist/daemon/relations.js +15 -5
  62. package/dist/daemon/relations.js.map +1 -1
  63. package/dist/daemon/session-index.test.js +1 -1
  64. package/dist/daemon/session-index.test.js.map +1 -1
  65. package/dist/daemon/watcher-health.d.ts +20 -0
  66. package/dist/daemon/watcher-health.d.ts.map +1 -0
  67. package/dist/daemon/watcher-health.js +78 -0
  68. package/dist/daemon/watcher-health.js.map +1 -0
  69. package/dist/daemon/watcher-health.test.d.ts +5 -0
  70. package/dist/daemon/watcher-health.test.d.ts.map +1 -0
  71. package/dist/daemon/watcher-health.test.js +96 -0
  72. package/dist/daemon/watcher-health.test.js.map +1 -0
  73. package/dist/daemon/watcher.test.d.ts +3 -2
  74. package/dist/daemon/watcher.test.d.ts.map +1 -1
  75. package/dist/daemon/watcher.test.js +9 -19
  76. package/dist/daemon/watcher.test.js.map +1 -1
  77. package/dist/daemon/workstream-resolver.d.ts +76 -0
  78. package/dist/daemon/workstream-resolver.d.ts.map +1 -0
  79. package/dist/daemon/workstream-resolver.js +180 -0
  80. package/dist/daemon/workstream-resolver.js.map +1 -0
  81. package/dist/daemon/workstream-resolver.test.d.ts +2 -0
  82. package/dist/daemon/workstream-resolver.test.d.ts.map +1 -0
  83. package/dist/daemon/workstream-resolver.test.js +128 -0
  84. package/dist/daemon/workstream-resolver.test.js.map +1 -0
  85. package/dist/daemon/workstream-summary.d.ts +1 -8
  86. package/dist/daemon/workstream-summary.d.ts.map +1 -1
  87. package/dist/daemon/workstream-summary.js +4 -37
  88. package/dist/daemon/workstream-summary.js.map +1 -1
  89. package/dist/daemon/workstream-summary.test.js +4 -4
  90. package/dist/daemon/workstream-summary.test.js.map +1 -1
  91. package/dist/mcp/helpers.d.ts.map +1 -1
  92. package/dist/mcp/helpers.js +17 -2
  93. package/dist/mcp/helpers.js.map +1 -1
  94. package/dist/mcp/index.d.ts.map +1 -1
  95. package/dist/mcp/index.js +8 -1
  96. package/dist/mcp/index.js.map +1 -1
  97. package/dist/mcp/taxonomy.d.ts +20 -18
  98. package/dist/mcp/taxonomy.d.ts.map +1 -1
  99. package/dist/mcp/taxonomy.js +75 -25
  100. package/dist/mcp/taxonomy.js.map +1 -1
  101. package/dist/mcp/taxonomy.test.js +10 -5
  102. package/dist/mcp/taxonomy.test.js.map +1 -1
  103. package/dist/mcp/tools.d.ts.map +1 -1
  104. package/dist/mcp/tools.js +457 -93
  105. package/dist/mcp/tools.js.map +1 -1
  106. package/dist/mcp/tools.test.js +209 -0
  107. package/dist/mcp/tools.test.js.map +1 -1
  108. package/dist/prompts/distill.d.ts.map +1 -1
  109. package/dist/prompts/distill.js +36 -17
  110. package/dist/prompts/distill.js.map +1 -1
  111. package/dist/prompts/entity-typing.d.ts +18 -0
  112. package/dist/prompts/entity-typing.d.ts.map +1 -0
  113. package/dist/prompts/entity-typing.js +60 -0
  114. package/dist/prompts/entity-typing.js.map +1 -0
  115. package/dist/prompts/episode-summary.d.ts +15 -0
  116. package/dist/prompts/episode-summary.d.ts.map +1 -0
  117. package/dist/prompts/episode-summary.js +74 -0
  118. package/dist/prompts/episode-summary.js.map +1 -0
  119. package/dist/prompts/extraction.d.ts.map +1 -1
  120. package/dist/prompts/extraction.js +138 -6
  121. package/dist/prompts/extraction.js.map +1 -1
  122. package/dist/prompts/index.d.ts +3 -0
  123. package/dist/prompts/index.d.ts.map +1 -1
  124. package/dist/prompts/index.js +3 -0
  125. package/dist/prompts/index.js.map +1 -1
  126. package/dist/prompts/prompts.test.js +1 -1
  127. package/dist/prompts/prompts.test.js.map +1 -1
  128. package/dist/prompts/relations.d.ts.map +1 -1
  129. package/dist/prompts/relations.js +26 -4
  130. package/dist/prompts/relations.js.map +1 -1
  131. package/dist/prompts/workstream-summary.d.ts +17 -0
  132. package/dist/prompts/workstream-summary.d.ts.map +1 -0
  133. package/dist/prompts/workstream-summary.js +72 -0
  134. package/dist/prompts/workstream-summary.js.map +1 -0
  135. package/dist/render.d.ts.map +1 -1
  136. package/dist/render.js +19 -1
  137. package/dist/render.js.map +1 -1
  138. package/dist/render.test.js +37 -5
  139. package/dist/render.test.js.map +1 -1
  140. package/docs/diagrams/architecture.svg +87 -0
  141. package/docs/diagrams/team-memory.svg +250 -0
  142. package/docs/screenshots/dashboard.png +0 -0
  143. package/docs/screenshots/graph.png +0 -0
  144. package/docs/screenshots/memory.png +0 -0
  145. package/package.json +4 -2
@@ -0,0 +1,283 @@
1
+ // Golden-set eval for the extraction grounding pipeline (Phase 3 of #46).
2
+ //
3
+ // Each case below is a complete extracted-fact candidate (as the LLM would emit
4
+ // it) plus the verdict we expect from the structural verifier stack. A "bad"
5
+ // case must end up dropped or marked ambiguous; a "good" case must pass through
6
+ // untouched. The suite asserts ≥90% precision and ≥90% recall on this set.
7
+ //
8
+ // Add new cases at the bottom — never delete existing ones, so we have a
9
+ // regression history. The five cases marked as cited are the bad facts called
10
+ // out in the task description.
11
+ import { test } from "node:test";
12
+ import assert from "node:assert/strict";
13
+ import { verifyGrounding, verifyVolatilityCoherence } from "./extraction-rules.js";
14
+ const GOLDEN = [
15
+ // ----- BAD facts cited in the task -----
16
+ {
17
+ id: "cited-pipeline",
18
+ label: "bad",
19
+ source: "task #46",
20
+ fact: {
21
+ content: "The pipeline uses pre-built Docker images pulled from ECR for deployment.",
22
+ subject: "the pipeline",
23
+ subject_specificity: 0.2,
24
+ self_contained: false,
25
+ entities: ["docker", "ecr"],
26
+ },
27
+ expectedVerdict: "ungrounded",
28
+ },
29
+ {
30
+ id: "cited-image-tag",
31
+ label: "bad",
32
+ source: "task #46 (transient)",
33
+ fact: {
34
+ content: "The correct image tag for the SCB init container should be `097873b`.",
35
+ subject: "scb init container image tag",
36
+ subject_specificity: 0.7,
37
+ self_contained: true,
38
+ entities: ["scb", "init-container"],
39
+ volatility: "transient",
40
+ as_of: "2026-04-28",
41
+ },
42
+ expectedVerdict: "grounded",
43
+ expectedForcedCategory: "observations",
44
+ expectedExpiry: "set",
45
+ },
46
+ {
47
+ id: "cited-step-2",
48
+ label: "bad",
49
+ source: "task #46",
50
+ fact: {
51
+ content: "Step 2 is a part of the dbt cronjob.",
52
+ subject: "step 2",
53
+ subject_specificity: 0.15,
54
+ self_contained: false,
55
+ entities: ["dbt"],
56
+ },
57
+ expectedVerdict: "ungrounded",
58
+ },
59
+ {
60
+ id: "cited-deployment-process",
61
+ label: "bad",
62
+ source: "task #46",
63
+ fact: {
64
+ content: "The deployment process involves building locally, pushing to ECR, and restarting on EC2 via SSM.",
65
+ subject: "the deployment process",
66
+ subject_specificity: 0.25,
67
+ self_contained: false,
68
+ entities: ["ecr", "ec2", "ssm"],
69
+ },
70
+ expectedVerdict: "ungrounded",
71
+ },
72
+ {
73
+ id: "cited-cronjob-old-image",
74
+ label: "bad",
75
+ source: "task #46 (transient)",
76
+ fact: {
77
+ content: "The scheduled cronjob `dbt-run-cronjob-v100-29617080` is still running the old image.",
78
+ subject: "dbt-run-cronjob-v100-29617080",
79
+ subject_specificity: 0.9,
80
+ self_contained: true,
81
+ entities: ["dbt-run-cronjob-v100-29617080"],
82
+ volatility: "transient",
83
+ as_of: "2026-04-28",
84
+ },
85
+ expectedVerdict: "grounded",
86
+ expectedForcedCategory: "observations",
87
+ expectedExpiry: "set",
88
+ },
89
+ // ----- GOOD facts -----
90
+ {
91
+ id: "good-makefile-target",
92
+ label: "good",
93
+ source: "synthetic",
94
+ fact: {
95
+ content: "Running `make deploy-prod` in the bikky-infra repo applies the EKS Helm chart.",
96
+ subject: "make deploy-prod",
97
+ subject_specificity: 0.95,
98
+ self_contained: true,
99
+ entities: ["bikky-infra", "eks", "helm"],
100
+ volatility: "stable",
101
+ },
102
+ expectedVerdict: "grounded",
103
+ expectedForcedCategory: null,
104
+ expectedExpiry: "null",
105
+ },
106
+ {
107
+ id: "good-config-path",
108
+ label: "good",
109
+ source: "synthetic",
110
+ fact: {
111
+ content: "The Bikky daemon reads its config from `~/.bikky/config.json`.",
112
+ subject: "~/.bikky/config.json",
113
+ subject_specificity: 1.0,
114
+ self_contained: true,
115
+ entities: ["bikky", "config.json"],
116
+ volatility: "stable",
117
+ },
118
+ expectedVerdict: "grounded",
119
+ },
120
+ {
121
+ id: "good-version-bump",
122
+ label: "good",
123
+ source: "synthetic",
124
+ fact: {
125
+ content: "Bikky package version was bumped to 0.3.5 on the main branch.",
126
+ subject: "bikky package version",
127
+ subject_specificity: 0.85,
128
+ self_contained: true,
129
+ entities: ["bikky"],
130
+ volatility: "evolving",
131
+ },
132
+ expectedVerdict: "grounded",
133
+ },
134
+ {
135
+ id: "good-architecture-decision",
136
+ label: "good",
137
+ source: "synthetic",
138
+ fact: {
139
+ content: "Bikky stores embeddings in a Qdrant collection named `bikky`.",
140
+ subject: "bikky qdrant collection",
141
+ subject_specificity: 0.9,
142
+ self_contained: true,
143
+ entities: ["qdrant", "bikky"],
144
+ volatility: "stable",
145
+ },
146
+ expectedVerdict: "grounded",
147
+ },
148
+ {
149
+ id: "good-ownership",
150
+ label: "good",
151
+ source: "synthetic",
152
+ fact: {
153
+ content: "The bikky-ui repo owns the EntityChip component at `packages/ui/app/src/components/EntityChip.tsx`.",
154
+ subject: "EntityChip.tsx",
155
+ subject_specificity: 0.95,
156
+ self_contained: true,
157
+ entities: ["bikky-ui", "entitychip"],
158
+ volatility: "stable",
159
+ },
160
+ expectedVerdict: "grounded",
161
+ },
162
+ {
163
+ id: "good-ephemeral-status",
164
+ label: "good",
165
+ source: "synthetic (ephemeral)",
166
+ fact: {
167
+ content: "The daemon at PID 39445 is currently consuming 240MB RSS.",
168
+ subject: "daemon pid 39445",
169
+ subject_specificity: 0.9,
170
+ self_contained: true,
171
+ entities: ["bikky-daemon"],
172
+ volatility: "ephemeral",
173
+ as_of: "2026-04-28",
174
+ },
175
+ expectedVerdict: "grounded",
176
+ expectedForcedCategory: "observations",
177
+ expectedExpiry: "set",
178
+ },
179
+ {
180
+ id: "good-typed-token-rescues",
181
+ label: "good",
182
+ source: "synthetic",
183
+ fact: {
184
+ content: "The `extraction-rules.ts` module exports `verifyGrounding`.",
185
+ subject: "extraction-rules.ts",
186
+ subject_specificity: 0.9,
187
+ self_contained: true,
188
+ entities: ["extraction-rules.ts"],
189
+ },
190
+ expectedVerdict: "grounded",
191
+ },
192
+ {
193
+ id: "bad-vague-process",
194
+ label: "bad",
195
+ source: "synthetic",
196
+ fact: {
197
+ content: "The process is faster now.",
198
+ subject: "the process",
199
+ subject_specificity: 0.1,
200
+ self_contained: false,
201
+ entities: [],
202
+ },
203
+ expectedVerdict: "ungrounded",
204
+ },
205
+ {
206
+ id: "bad-no-anchor",
207
+ label: "bad",
208
+ source: "synthetic",
209
+ fact: {
210
+ content: "Things have been improved significantly.",
211
+ subject: "things",
212
+ subject_specificity: 0.05,
213
+ self_contained: false,
214
+ entities: [],
215
+ },
216
+ expectedVerdict: "ungrounded",
217
+ },
218
+ ];
219
+ function evaluate(c) {
220
+ const grounding = verifyGrounding({
221
+ content: c.fact.content,
222
+ subject: c.fact.subject,
223
+ subject_specificity: c.fact.subject_specificity,
224
+ self_contained: c.fact.self_contained,
225
+ entities: c.fact.entities,
226
+ });
227
+ const volatility = verifyVolatilityCoherence({
228
+ volatility: c.fact.volatility,
229
+ as_of: c.fact.as_of,
230
+ category: c.fact.category,
231
+ });
232
+ return {
233
+ verdict: grounding.verdict,
234
+ forcedCategory: volatility.forcedCategory,
235
+ expiresAt: volatility.expiresAt,
236
+ };
237
+ }
238
+ test("golden set: every case meets its expected verdict", () => {
239
+ const failures = [];
240
+ for (const c of GOLDEN) {
241
+ const r = evaluate(c);
242
+ if (c.expectedVerdict && r.verdict !== c.expectedVerdict) {
243
+ failures.push(`${c.id}: expected verdict=${c.expectedVerdict} got ${r.verdict}`);
244
+ }
245
+ if (c.expectedForcedCategory !== undefined && r.forcedCategory !== c.expectedForcedCategory) {
246
+ failures.push(`${c.id}: expected forcedCategory=${c.expectedForcedCategory} got ${r.forcedCategory}`);
247
+ }
248
+ if (c.expectedExpiry === "set" && !r.expiresAt) {
249
+ failures.push(`${c.id}: expected expiresAt to be set`);
250
+ }
251
+ if (c.expectedExpiry === "null" && r.expiresAt) {
252
+ failures.push(`${c.id}: expected expiresAt to be null, got ${r.expiresAt}`);
253
+ }
254
+ }
255
+ assert.equal(failures.length, 0, `Golden-set failures:\n${failures.join("\n")}`);
256
+ });
257
+ test("golden set: precision ≥ 0.9 (good facts not dropped or downgraded)", () => {
258
+ const goods = GOLDEN.filter((c) => c.label === "good");
259
+ let kept = 0;
260
+ for (const c of goods) {
261
+ const { verdict } = evaluate(c);
262
+ if (verdict === "grounded")
263
+ kept++;
264
+ }
265
+ const precision = kept / goods.length;
266
+ assert.ok(precision >= 0.9, `Precision ${precision.toFixed(2)} below 0.9 (${kept}/${goods.length} good facts kept)`);
267
+ });
268
+ test("golden set: recall ≥ 0.9 (bad facts caught — dropped or downgraded or expiring)", () => {
269
+ const bads = GOLDEN.filter((c) => c.label === "bad");
270
+ let caught = 0;
271
+ for (const c of bads) {
272
+ const r = evaluate(c);
273
+ const isCaught = r.verdict === "ungrounded" ||
274
+ r.verdict === "ambiguous" ||
275
+ r.forcedCategory === "observations" ||
276
+ r.expiresAt !== null;
277
+ if (isCaught)
278
+ caught++;
279
+ }
280
+ const recall = caught / bads.length;
281
+ assert.ok(recall >= 0.9, `Recall ${recall.toFixed(2)} below 0.9 (${caught}/${bads.length} bad facts caught)`);
282
+ });
283
+ //# sourceMappingURL=extraction-quality.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction-quality.test.js","sourceRoot":"","sources":["../../src/daemon/extraction-quality.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Subtype rule table.
3
+ *
4
+ * The extraction LLM picks a `memory_subtype` from 8 fact subtypes. A few
5
+ * subtype pairs are easy to confuse:
6
+ *
7
+ * - operational_procedure vs troubleshooting_gotcha
8
+ * - codebase_map vs infra_topology
9
+ * - domain_rule vs preference
10
+ *
11
+ * This module backstops the LLM with a lightweight keyword scorer. It returns a
12
+ * deterministic top-1 subtype + score for a fact's content, so the daemon can:
13
+ *
14
+ * - flag facts where the LLM and the rule table strongly disagree
15
+ * (set `review_status: candidate` so a human can verify)
16
+ * - downgrade confidence when nothing scores above a floor
17
+ *
18
+ * The table is intentionally small. It is NOT the source of truth — the LLM is.
19
+ * The rule table is a cheap consistency check.
20
+ */
21
+ export type FactSubtype = "codebase_map" | "architecture_decision" | "infra_topology" | "access_pattern" | "operational_procedure" | "domain_rule" | "troubleshooting_gotcha" | "preference";
22
+ export interface SubtypeRuleScore {
23
+ subtype: FactSubtype | null;
24
+ score: number;
25
+ scores: Record<FactSubtype, number>;
26
+ }
27
+ /**
28
+ * Score `content` against every subtype's rule terms. Returns the top-1
29
+ * subtype + raw score, plus all scores for inspection.
30
+ */
31
+ export declare const scoreSubtype: (content: string) => SubtypeRuleScore;
32
+ /**
33
+ * Compare the LLM's subtype choice against the rule table.
34
+ *
35
+ * Returns:
36
+ * - `agree` — rule table top-1 matches (or has no opinion)
37
+ * - `disagree` — rule table is confident in a *different* subtype with a
38
+ * margin large enough to suspect the LLM. Caller should mark the fact as
39
+ * `review_status: candidate` and lower confidence.
40
+ */
41
+ export interface SubtypeAgreement {
42
+ verdict: "agree" | "disagree";
43
+ ruleSubtype: FactSubtype | null;
44
+ ruleScore: number;
45
+ margin: number;
46
+ }
47
+ export declare const compareSubtype: (content: string, llmSubtype: string | null | undefined) => SubtypeAgreement;
48
+ export type GroundingVerdict = "grounded" | "ambiguous" | "ungrounded";
49
+ export interface GroundingResult {
50
+ verdict: GroundingVerdict;
51
+ reason: string;
52
+ hasTypedToken: boolean;
53
+ subjectResolves: boolean;
54
+ }
55
+ /**
56
+ * Shape-based typed-token detector. A "typed token" is any substring that an
57
+ * engineer could plausibly grep for and find a unique referent: file paths,
58
+ * URLs, code-formatted spans, version strings, issue/PR refs, identifier-shaped
59
+ * names (kebab-case / snake_case / dotted / camelCase ≥ 3 chars).
60
+ *
61
+ * Intentionally shape-only — no hardcoded tool/service vocabulary.
62
+ */
63
+ export declare const hasTypedToken: (content: string) => boolean;
64
+ /**
65
+ * Returns true iff `subject` either:
66
+ * - looks like a typed token itself, OR
67
+ * - matches (case-insensitively) one of the entities the LLM extracted, OR
68
+ * - is a substring of one of the entities (or vice versa) — handles
69
+ * "the foo cronjob" vs entity "foo".
70
+ *
71
+ * Intentionally permissive — we want to catch the ungrounded cases, not
72
+ * second-guess every wording choice.
73
+ */
74
+ export declare const subjectResolves: (subject: string | null | undefined, entities: ReadonlyArray<string>) => boolean;
75
+ export interface GroundingInput {
76
+ content: string;
77
+ subject?: string | null;
78
+ subject_specificity?: number | null;
79
+ self_contained?: boolean | null;
80
+ entities: ReadonlyArray<string>;
81
+ }
82
+ /**
83
+ * Structural grounding gate. Combines:
84
+ * - typed-token presence in `content`
85
+ * - subject resolution against typed tokens or entities
86
+ * - LLM's own subject_specificity self-grade
87
+ * - LLM's own self_contained self-grade
88
+ *
89
+ * Verdict semantics (consumed by storeFacts):
90
+ * - grounded → no action, store as-is
91
+ * - ambiguous → keep, but lower confidence and flag in metadata
92
+ * - ungrounded → drop entirely
93
+ */
94
+ export declare const verifyGrounding: (input: GroundingInput) => GroundingResult;
95
+ export type Volatility = "stable" | "evolving" | "transient" | "ephemeral";
96
+ export interface VolatilityInput {
97
+ volatility?: Volatility | null;
98
+ as_of?: string | null;
99
+ category?: string | null;
100
+ }
101
+ export interface VolatilityCoherenceResult {
102
+ /** Effective volatility after coherence checks (may be downgraded). */
103
+ effective: Volatility;
104
+ /** Effective category after coherence checks (may be forced to observations). */
105
+ forcedCategory: string | null;
106
+ /** Computed expires_at ISO timestamp, or null for stable/evolving. */
107
+ expiresAt: string | null;
108
+ /** valid_from anchor — `as_of` if supplied, else now. */
109
+ validFrom: string;
110
+ /** Half-life multiplier consumed by the recall ranker (Phase 3). */
111
+ halfLifeMultiplier: number;
112
+ /** Reasons applied during coherence checks, for metadata audit. */
113
+ notes: string[];
114
+ }
115
+ /**
116
+ * Translate the LLM's self-judged volatility into structural decisions:
117
+ * - transient → expires_at = as_of + 30d, force category=observations,
118
+ * half-life × 0.25
119
+ * - ephemeral → expires_at = as_of + 7d, force category=observations,
120
+ * half-life × 0.1
121
+ * - stable → no expiry, half-life × 1.0
122
+ * - evolving → no expiry, half-life × 1.0 (default)
123
+ *
124
+ * If the LLM emitted no volatility, defaults to "evolving" (NOT "stable") —
125
+ * we err on the side of letting decay do its job.
126
+ *
127
+ * If volatility >= transient and `as_of` is missing, we fall back to today
128
+ * and note the synthesis in the audit metadata.
129
+ */
130
+ export declare const verifyVolatilityCoherence: (input: VolatilityInput) => VolatilityCoherenceResult;
131
+ //# sourceMappingURL=extraction-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction-rules.d.ts","sourceRoot":"","sources":["../../src/daemon/extraction-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,WAAW,GACnB,cAAc,GACd,uBAAuB,GACvB,gBAAgB,GAChB,gBAAgB,GAChB,uBAAuB,GACvB,aAAa,GACb,wBAAwB,GACxB,YAAY,CAAC;AAEjB,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;CACrC;AA4DD;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,KAAG,gBAyB9C,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,GAAG,UAAU,CAAC;IAC9B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,eAAO,MAAM,cAAc,GACzB,SAAS,MAAM,EACf,YAAY,MAAM,GAAG,IAAI,GAAG,SAAS,KACpC,gBAcF,CAAC;AAgBF,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,WAAW,GAAG,YAAY,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,OA4B/C,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,UAAU,aAAa,CAAC,MAAM,CAAC,KAC9B,OAcF,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,cAAc,KAAG,eAgEvD,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC;AAE3E,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,yBAAyB;IACxC,uEAAuE;IACvE,SAAS,EAAE,UAAU,CAAC;IACtB,iFAAiF;IACjF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,sEAAsE;IACtE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mEAAmE;IACnE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAYD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,yBAAyB,GAAI,OAAO,eAAe,KAAG,yBA4ClE,CAAC"}