opencode-swarm 7.187.0 → 7.187.2

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 (96) hide show
  1. package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
  2. package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
  3. package/dist/background/pr-review-contract.d.ts +2 -2
  4. package/dist/cli/{auto-checkpoint-r69e82bh.js → auto-checkpoint-2xmptd5t.js} +8 -8
  5. package/dist/cli/{checkpoint-1sqwbgra.js → checkpoint-2y7z19y5.js} +14 -13
  6. package/dist/cli/{coder-settlement-b9qx0732.js → coder-settlement-s4d28fa6.js} +9 -9
  7. package/dist/cli/{config-doctor-s4fr5qwr.js → config-doctor-312afzhr.js} +13 -12
  8. package/dist/cli/{core-bezezjy9.js → core-2bywxc4w.js} +2 -2
  9. package/dist/cli/{curation-policy-2x2w3b57.js → curation-policy-sr29thf5.js} +5 -5
  10. package/dist/cli/{curator-drift-785xnxdv.js → curator-drift-xx8pp4g9.js} +6 -6
  11. package/dist/cli/{curator-w4hp7a10.js → curator-dvhf6jex.js} +37 -35
  12. package/dist/cli/{curator-llm-factory-p0wwyswg.js → curator-llm-factory-4g2nvr76.js} +37 -35
  13. package/dist/cli/doctor-knowledge-receipt-phase-id-m239pgbz.js +83 -0
  14. package/dist/cli/{evidence-summary-service-33qcm9xc.js → evidence-summary-service-9et04fjh.js} +17 -16
  15. package/dist/cli/{gate-evidence-9ehj968e.js → gate-evidence-73vj3bgm.js} +6 -6
  16. package/dist/cli/{guardrail-explain-5715fdzv.js → guardrail-explain-8n4fx9zv.js} +38 -36
  17. package/dist/cli/{guardrail-log-k1dfzfzm.js → guardrail-log-9gmfvnd7.js} +7 -7
  18. package/dist/cli/{guardrail-reset-nt88n9dm.js → guardrail-reset-k3mrq25e.js} +37 -35
  19. package/dist/cli/{hive-promoter-c8fjn186.js → hive-promoter-bp3rz0q6.js} +37 -35
  20. package/dist/cli/{index-df2p0k0s.js → index-26zs9wsj.js} +2 -2
  21. package/dist/cli/{index-ectvhv8e.js → index-310h5192.js} +2 -2
  22. package/dist/cli/{index-en7vzpeq.js → index-33345434.js} +4 -4
  23. package/dist/cli/{index-2wgvjwpr.js → index-3ckfawjf.js} +3 -3
  24. package/dist/cli/{index-b2je0z0t.js → index-3g3n9fjq.js} +4 -4
  25. package/dist/cli/{index-ycz8z2db.js → index-3y0nr248.js} +3 -3
  26. package/dist/cli/{index-v08ksq0b.js → index-4g39nne8.js} +2 -2
  27. package/dist/cli/{index-t3hcd6zz.js → index-6t7ygevg.js} +1 -1
  28. package/dist/cli/{index-5m56c5r6.js → index-7fxy1s86.js} +4 -4
  29. package/dist/cli/{index-pymr99as.js → index-85cx1mmb.js} +4 -4
  30. package/dist/cli/{index-2s8wdagg.js → index-9jafghwk.js} +37 -35
  31. package/dist/cli/{index-evy5yrsw.js → index-b308erem.js} +3 -3
  32. package/dist/cli/{index-qzgfheb4.js → index-b5tthmy2.js} +2 -2
  33. package/dist/cli/{index-yw1g78v9.js → index-bstjg81q.js} +1 -1
  34. package/dist/cli/{index-hvr82s1t.js → index-dqberkr3.js} +4 -4
  35. package/dist/cli/{index-jtncfvhe.js → index-dx6bhbd6.js} +1 -1
  36. package/dist/cli/{index-ww8payq9.js → index-e9ry78z5.js} +2 -2
  37. package/dist/cli/{index-1vvr69ka.js → index-efbhea00.js} +1 -1
  38. package/dist/cli/{index-xs96nry2.js → index-exj7czz9.js} +4 -4
  39. package/dist/cli/{index-sztx0vyt.js → index-f6pft90q.js} +3 -3
  40. package/dist/cli/{index-6ersmqjd.js → index-j5db3v56.js} +318 -767
  41. package/dist/cli/{index-pts38j6x.js → index-jh9nrshe.js} +2 -2
  42. package/dist/cli/{index-0yj79yk1.js → index-jyxgkp4a.js} +1 -1
  43. package/dist/cli/index-kc635w60.js +748 -0
  44. package/dist/cli/{index-cppqxjw9.js → index-m1vsqmyr.js} +1 -1
  45. package/dist/cli/index-m9zzj4ee.js +10 -0
  46. package/dist/cli/{index-rm676s0p.js → index-n45kz69m.js} +1 -1
  47. package/dist/cli/{index-dypmvvga.js → index-n55exns2.js} +1 -1
  48. package/dist/cli/{index-pfpnzf6w.js → index-n8kqhxay.js} +1 -1
  49. package/dist/cli/{index-bbqxt1p5.js → index-pqffq9mm.js} +3 -3
  50. package/dist/cli/{index-knbjtqwt.js → index-rtdxyjrg.js} +8 -6
  51. package/dist/cli/{index-r7gt2w1b.js → index-tkm2rj27.js} +1 -1
  52. package/dist/cli/{index-cx4s7cak.js → index-tmp07h7b.js} +39 -37
  53. package/dist/cli/{index-ta48pe8j.js → index-tngc1erw.js} +3 -3
  54. package/dist/cli/{index-akt0arnt.js → index-tq6sbcys.js} +105 -185
  55. package/dist/cli/{index-c8ffgcvz.js → index-v9y0230d.js} +1 -1
  56. package/dist/cli/{index-469xmpd6.js → index-w0bvez8c.js} +1 -1
  57. package/dist/cli/{index-4g6sw4eq.js → index-wpxy7099.js} +1 -1
  58. package/dist/cli/{index-yf0cc6c5.js → index-xs070yr9.js} +2 -2
  59. package/dist/cli/{index-zzxnssy3.js → index-xv0t2sed.js} +4 -4
  60. package/dist/cli/{index-krqq8kbq.js → index-y81jjedn.js} +6 -6
  61. package/dist/cli/{index-d6kvatwp.js → index-z04d01pv.js} +11 -16
  62. package/dist/cli/index.js +38 -36
  63. package/dist/cli/{knowledge-escalator-qttydcx2.js → knowledge-escalator-fnqctvxz.js} +14 -12
  64. package/dist/cli/{knowledge-events-4vf0vj82.js → knowledge-events-mr1vh3nb.js} +12 -10
  65. package/dist/cli/{knowledge-link-p2c8agc8.js → knowledge-link-93nzznwd.js} +4 -4
  66. package/dist/cli/{knowledge-store-bw1dk2eb.js → knowledge-store-dxy4s9k6.js} +5 -5
  67. package/dist/cli/{knowledge-validator-gefcc36h.js → knowledge-validator-gy39attk.js} +7 -7
  68. package/dist/cli/{mcp-d5p0k3p1.js → mcp-bxb59wsq.js} +1 -1
  69. package/dist/cli/{model-preflight-fmx49pwy.js → model-preflight-2kje0sp0.js} +37 -35
  70. package/dist/cli/{pending-delegations-8333cb3y.js → pending-delegations-fm2nx2k0.js} +7 -7
  71. package/dist/cli/{pr-subscriptions-p42ny2sn.js → pr-subscriptions-g4f9rehb.js} +7 -7
  72. package/dist/cli/{pr-workflow-gate-csy32z8w.js → pr-workflow-gate-qtq1wq95.js} +37 -35
  73. package/dist/cli/{runner-cbpr45cs.js → runner-verr6er5.js} +5 -5
  74. package/dist/cli/{scan-cursor-14mwymtz.js → scan-cursor-8taj944f.js} +6 -6
  75. package/dist/cli/{schema-6426g0gw.js → schema-yxq3bjmd.js} +2 -2
  76. package/dist/cli/{scope-persistence-avkv3s4m.js → scope-persistence-jppvjncr.js} +12 -12
  77. package/dist/cli/{server-d9rk2zeb.js → server-2s7wqg9e.js} +37 -35
  78. package/dist/cli/{skill-generator-epdvdsh5.js → skill-generator-pyf95aqw.js} +16 -14
  79. package/dist/cli/{snapshot-coordination-init-35f7wrqb.js → snapshot-coordination-init-8gbxw9sa.js} +37 -35
  80. package/dist/cli/{speckit-checkoff-erwa7fbj.js → speckit-checkoff-x2z0jamv.js} +4 -4
  81. package/dist/cli/{telemetry-2vwb3n42.js → telemetry-xwj899pd.js} +1 -1
  82. package/dist/cli/{worktree-collision-ownership-3tqkw81h.js → worktree-collision-ownership-455bdcnk.js} +7 -7
  83. package/dist/cli/{worktree-isolation-0rrjqypt.js → worktree-isolation-8x4p7tvm.js} +37 -35
  84. package/dist/commands/doctor-knowledge-receipt-phase-id.d.ts +16 -0
  85. package/dist/hooks/extractors.d.ts +15 -0
  86. package/dist/hooks/knowledge-injector.d.ts +5 -0
  87. package/dist/hooks/knowledge-receipt-ledger.d.ts +50 -4
  88. package/dist/hooks/knowledge-receipt-observability.d.ts +1 -1
  89. package/dist/hooks/phase-complete-directive-gate.d.ts +18 -1
  90. package/dist/hooks/phase-directives.d.ts +7 -3
  91. package/dist/index.js +469 -460
  92. package/dist/state.d.ts +26 -3
  93. package/dist/tools/phase-complete.d.ts +2 -2
  94. package/dist/tools/repair-knowledge-receipt-ledger.d.ts +26 -0
  95. package/dist/utils/path.d.ts +23 -0
  96. package/package.json +1 -1
@@ -1,60 +1,139 @@
1
1
  // @bun
2
+ import {
3
+ sanitizeContextText
4
+ } from "./index-m9zzj4ee.js";
2
5
  import {
3
6
  validateSwarmPath
4
7
  } from "./index-bejxkee0.js";
5
8
  import {
6
9
  observeReceiptTransition
7
- } from "./index-c8ffgcvz.js";
8
- import {
9
- resolveHiveEventsPath
10
- } from "./index-ae75rja9.js";
11
- import {
12
- resolveKnowledgeStoreDir
13
- } from "./index-rm676s0p.js";
14
- import {
15
- atomicWriteFile
16
- } from "./index-t3hcd6zz.js";
10
+ } from "./index-v9y0230d.js";
17
11
  import {
18
12
  assertProjectRoot
19
13
  } from "./index-t7hmqgjy.js";
20
14
  import {
21
15
  emit
22
- } from "./index-jtncfvhe.js";
16
+ } from "./index-dx6bhbd6.js";
23
17
  import {
24
- canonicalRootKey
25
- } from "./index-fzpt2djt.js";
26
- import {
27
- require_proper_lockfile
28
- } from "./index-7g4c7s5r.js";
18
+ resolveActivePhaseId
19
+ } from "./index-gx2vp8gx.js";
29
20
  import {
30
21
  loadPluginConfigWithMeta
31
- } from "./index-469xmpd6.js";
22
+ } from "./index-w0bvez8c.js";
32
23
  import {
33
24
  KnowledgeConfigSchema,
34
25
  init_schema
35
- } from "./index-qzgfheb4.js";
36
- import {
37
- init_logger,
38
- warn
39
- } from "./index-zgwm4ryv.js";
40
- import {
41
- __require,
42
- __toESM
43
- } from "./index-a76rekgs.js";
26
+ } from "./index-b5tthmy2.js";
44
27
 
45
- // src/hooks/knowledge-events.ts
46
- var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
47
- import { randomUUID as randomUUID3 } from "crypto";
48
- import { existsSync as existsSync3 } from "fs";
49
- import { appendFile, mkdir as mkdir2, readFile as readFile2, stat as stat2 } from "fs/promises";
50
- import * as path2 from "path";
51
- init_logger();
28
+ // src/utils/context-decisions.ts
29
+ function extractContextDecisions(content) {
30
+ const decisions = [];
31
+ const MAX_CONTENT_CHARS = 1e6;
32
+ const bounded = content.length > MAX_CONTENT_CHARS ? content.slice(0, MAX_CONTENT_CHARS) : content;
33
+ const lines = bounded.split(`
34
+ `);
35
+ let inDecisionsSection = false;
36
+ let currentPhase = null;
37
+ let lineNumber = 0;
38
+ for (let i = 0;i < lines.length; i++) {
39
+ const line = lines[i];
40
+ lineNumber = i + 1;
41
+ const phaseMatch = line.match(/^## Phase (\d+)/);
42
+ if (phaseMatch) {
43
+ currentPhase = parseInt(phaseMatch[1], 10);
44
+ }
45
+ if (line.trim() === "## Decisions") {
46
+ inDecisionsSection = true;
47
+ continue;
48
+ }
49
+ if (inDecisionsSection && line.startsWith("## ")) {
50
+ break;
51
+ }
52
+ if (inDecisionsSection && line.trim().startsWith("- ")) {
53
+ const text = line.trim().substring(2);
54
+ const confirmed = text.includes("\u2705") || text.includes("[confirmed]");
55
+ const timestampMatch = text.match(/\[(\d{4}-\d{2}-\d{2}T[\d:.]+Z?)\]/);
56
+ const timestamp = timestampMatch ? timestampMatch[1] : null;
57
+ const decisionPhaseMatch = text.match(/Phase (\d+)/);
58
+ const decisionPhase = decisionPhaseMatch ? parseInt(decisionPhaseMatch[1], 10) : currentPhase;
59
+ decisions.push({
60
+ raw: line,
61
+ text: text.replace(/\s*\[.*?\]\s*/g, "").trim(),
62
+ phase: decisionPhase,
63
+ confirmed,
64
+ timestamp,
65
+ line: lineNumber
66
+ });
67
+ }
68
+ }
69
+ return decisions;
70
+ }
52
71
 
53
72
  // src/hooks/knowledge-receipt-ledger.ts
54
73
  import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
55
74
  import { existsSync as existsSync2 } from "fs";
56
75
  init_schema();
57
76
 
77
+ // src/hooks/extractors.ts
78
+ function extractCurrentPhase(planContent) {
79
+ if (!planContent) {
80
+ return null;
81
+ }
82
+ planContent = sanitizeContextText(planContent);
83
+ const lines = planContent.split(`
84
+ `);
85
+ for (let i = 0;i < Math.min(20, lines.length); i++) {
86
+ const line = lines[i].trim();
87
+ const progressMatch = line.match(/^## Phase (\d+):?\s*(.*?)\s*\[IN PROGRESS\]/i);
88
+ if (progressMatch) {
89
+ const phaseNum = progressMatch[1];
90
+ const description = progressMatch[2]?.trim() || "";
91
+ return `Phase ${phaseNum}: ${description} [IN PROGRESS]`;
92
+ }
93
+ }
94
+ for (let i = 0;i < Math.min(20, lines.length); i++) {
95
+ const line = lines[i].trim();
96
+ const blockedMatch = line.match(/^## Phase (\d+):?\s*(.*?)\s*\[BLOCKED\]/i);
97
+ if (blockedMatch) {
98
+ const phaseNum = blockedMatch[1];
99
+ const description = blockedMatch[2]?.trim() || "";
100
+ return `Phase ${phaseNum}: ${description} [BLOCKED]`;
101
+ }
102
+ }
103
+ for (let i = 0;i < Math.min(3, lines.length); i++) {
104
+ const line = lines[i].trim();
105
+ const phaseMatch = line.match(/Phase:\s*(\d+)/i);
106
+ if (phaseMatch) {
107
+ const phaseNum = phaseMatch[1];
108
+ return `Phase ${phaseNum} [PENDING]`;
109
+ }
110
+ }
111
+ return null;
112
+ }
113
+ function extractCurrentPhaseFromPlan(plan) {
114
+ const phaseId = resolveActivePhaseId(plan);
115
+ const phase = plan.phases.find((p) => p.id === phaseId);
116
+ if (!phase)
117
+ return null;
118
+ const statusMap = {
119
+ pending: "PENDING",
120
+ in_progress: "IN PROGRESS",
121
+ complete: "COMPLETE",
122
+ blocked: "BLOCKED"
123
+ };
124
+ const statusText = statusMap[phase.status] || "PENDING";
125
+ return sanitizeContextText(`Phase ${phase.id}: ${phase.name} [${statusText}]`);
126
+ }
127
+ function extractPhaseIdFromLabel(label) {
128
+ if (!label)
129
+ return;
130
+ const m = /^Phase\s+(\d+)/i.exec(label);
131
+ if (!m)
132
+ return;
133
+ const id = Number(m[1]);
134
+ return Number.isSafeInteger(id) && id >= 1 ? id : undefined;
135
+ }
136
+
58
137
  // src/hooks/knowledge-receipt-ledger-storage.ts
59
138
  import { createHash, randomUUID } from "crypto";
60
139
  import * as fs from "fs";
@@ -504,6 +583,7 @@ var TRANSITIONS = new Set([
504
583
  "gate_release_committed",
505
584
  "phase_close_intent",
506
585
  "phase_closed",
586
+ "phase_id_backfilled",
507
587
  "repair_uncertainty_installed",
508
588
  "repair_uncertainty_cleared",
509
589
  "legacy_imported",
@@ -621,6 +701,29 @@ var keyOf = (traceId, entryId) => `${traceId.length}:${traceId}${entryId}`;
621
701
  var emptyKeyOf = (traceId, sessionId) => `${traceId.length}:${traceId}${sessionId}`;
622
702
  var phaseLifecycleKey = (phase, sessionId, taskId) => `${sessionId.length}:${sessionId}${phase.length}:${phase}${taskId === undefined ? "u:" : `s:${taskId.length}:${taskId}`}`;
623
703
  var repairUncertaintyKey = (phase, sessionId) => `${sessionId.length}:${sessionId}${phase.length}:${phase}`;
704
+ function membershipMatchesPhaseIdentity(membership, phase, phaseId) {
705
+ if (phaseId === undefined)
706
+ return membership.phase === phase;
707
+ if (membership.phase_id === phaseId)
708
+ return true;
709
+ if (membership.phase_id === undefined && extractPhaseIdFromLabel(membership.phase) === phaseId)
710
+ return true;
711
+ return membership.phase === phase;
712
+ }
713
+ function findClosedLifecycleForPhase(state, scope) {
714
+ const labelKey = phaseLifecycleKey(scope.phase ?? "", scope.session_id, scope.task_id);
715
+ const byLabel = state.phaseLifecycle.get(labelKey);
716
+ if (byLabel !== undefined && (scope.phase_id === undefined || byLabel.phase_id === undefined || byLabel.phase_id === scope.phase_id))
717
+ return byLabel;
718
+ if (scope.phase_id === undefined)
719
+ return;
720
+ for (const lifecycle of state.phaseLifecycle.values()) {
721
+ if (lifecycle.session_id === scope.session_id && lifecycle.task_id === scope.task_id && (lifecycle.phase_id === scope.phase_id || lifecycle.phase_id === undefined && extractPhaseIdFromLabel(lifecycle.phase) === scope.phase_id)) {
722
+ return lifecycle;
723
+ }
724
+ }
725
+ return;
726
+ }
624
727
  function nowIso() {
625
728
  return new Date(_internals3.nowMs()).toISOString();
626
729
  }
@@ -801,6 +904,7 @@ function parseMembership(value) {
801
904
  "entry_id",
802
905
  "session_id",
803
906
  "phase",
907
+ "phase_id",
804
908
  "task_id",
805
909
  "agent",
806
910
  "critical",
@@ -819,7 +923,7 @@ function parseMembership(value) {
819
923
  "source_link_id",
820
924
  "exposure_kind",
821
925
  "origin"
822
- ]) || typeof value.trace_id !== "string" || !value.trace_id || typeof value.entry_id !== "string" || !value.entry_id || typeof value.session_id !== "string" || !value.session_id || !isOptionalString(value.phase) || !isOptionalString(value.task_id) || !isOptionalString(value.agent) || typeof value.critical !== "boolean" || value.rank !== undefined && !Number.isFinite(value.rank) || value.score !== undefined && !Number.isFinite(value.score) || !isValidTimestamp(value.committed_at) || typeof value.membership_event_id !== "string" || !value.membership_event_id || !Number.isFinite(value.grace_days) || value.grace_days < 0 || value.phase_close_intent_at !== undefined && !isValidTimestamp(value.phase_close_intent_at) || value.phase_closed_at !== undefined && !isValidTimestamp(value.phase_closed_at) || !isOptionalString(value.cohort_id) || !isOptionalString(value.source_link_id) || !isReceiptExposureKind(value.exposure_kind) || value.origin !== "v2" && value.origin !== "legacy") {
926
+ ]) || typeof value.trace_id !== "string" || !value.trace_id || typeof value.entry_id !== "string" || !value.entry_id || typeof value.session_id !== "string" || !value.session_id || !isOptionalString(value.phase) || value.phase_id !== undefined && (!Number.isSafeInteger(value.phase_id) || value.phase_id < 1) || !isOptionalString(value.task_id) || !isOptionalString(value.agent) || typeof value.critical !== "boolean" || value.rank !== undefined && !Number.isFinite(value.rank) || value.score !== undefined && !Number.isFinite(value.score) || !isValidTimestamp(value.committed_at) || typeof value.membership_event_id !== "string" || !value.membership_event_id || !Number.isFinite(value.grace_days) || value.grace_days < 0 || value.phase_close_intent_at !== undefined && !isValidTimestamp(value.phase_close_intent_at) || value.phase_closed_at !== undefined && !isValidTimestamp(value.phase_closed_at) || !isOptionalString(value.cohort_id) || !isOptionalString(value.source_link_id) || !isReceiptExposureKind(value.exposure_kind) || value.origin !== "v2" && value.origin !== "legacy") {
823
927
  return null;
824
928
  }
825
929
  const terminal = value.terminal === undefined ? undefined : parseTerminal(value.terminal);
@@ -848,6 +952,7 @@ function parseMembership(value) {
848
952
  entry_id: value.entry_id,
849
953
  session_id: value.session_id,
850
954
  phase: value.phase,
955
+ phase_id: value.phase_id,
851
956
  task_id: value.task_id,
852
957
  agent: value.agent,
853
958
  critical: value.critical,
@@ -924,17 +1029,19 @@ function parsePhaseLifecycle(value) {
924
1029
  return null;
925
1030
  if (!hasOnlyKeys(value, [
926
1031
  "phase",
1032
+ "phase_id",
927
1033
  "session_id",
928
1034
  "task_id",
929
1035
  "intent_event_id",
930
1036
  "intent_at",
931
1037
  "closed_event_id",
932
1038
  "closed_at"
933
- ]) || typeof value.phase !== "string" || !value.phase || typeof value.session_id !== "string" || !value.session_id || !isOptionalString(value.task_id) || !isOptionalString(value.intent_event_id) || value.intent_at !== undefined && !isValidTimestamp(value.intent_at) || !isOptionalString(value.closed_event_id) || value.closed_at !== undefined && !isValidTimestamp(value.closed_at)) {
1039
+ ]) || typeof value.phase !== "string" || !value.phase || value.phase_id !== undefined && (!Number.isSafeInteger(value.phase_id) || value.phase_id < 1) || typeof value.session_id !== "string" || !value.session_id || !isOptionalString(value.task_id) || !isOptionalString(value.intent_event_id) || value.intent_at !== undefined && !isValidTimestamp(value.intent_at) || !isOptionalString(value.closed_event_id) || value.closed_at !== undefined && !isValidTimestamp(value.closed_at)) {
934
1040
  return null;
935
1041
  }
936
1042
  return {
937
1043
  phase: value.phase,
1044
+ phase_id: value.phase_id,
938
1045
  session_id: value.session_id,
939
1046
  task_id: value.task_id,
940
1047
  intent_event_id: value.intent_event_id,
@@ -971,6 +1078,7 @@ function parseAuditSummary(value) {
971
1078
  "gate_release_committed",
972
1079
  "phase_close_intent",
973
1080
  "phase_closed",
1081
+ "phase_id_backfilled",
974
1082
  "repair_uncertainty_installed",
975
1083
  "repair_uncertainty_cleared",
976
1084
  "legacy_imported",
@@ -998,7 +1106,8 @@ function summarizeRecord(record) {
998
1106
  payload.memberships,
999
1107
  payload.transitions,
1000
1108
  payload.markers,
1001
- payload.rejected
1109
+ payload.rejected,
1110
+ payload.items
1002
1111
  ]) {
1003
1112
  if (!Array.isArray(collection))
1004
1113
  continue;
@@ -1181,13 +1290,30 @@ function applyRecord(state, record) {
1181
1290
  const phase = record.payload.phase;
1182
1291
  const sessionId = record.payload.session_id;
1183
1292
  const taskId = record.payload.task_id;
1293
+ const rawPhaseId = record.payload.phase_id;
1294
+ const phaseId = Number.isSafeInteger(rawPhaseId) && rawPhaseId >= 1 ? rawPhaseId : undefined;
1184
1295
  if (typeof phase === "string" && typeof sessionId === "string" && isOptionalString(taskId)) {
1185
- const lifecycleKey = phaseLifecycleKey(phase, sessionId, taskId);
1186
- const lifecycle = state.phaseLifecycle.get(lifecycleKey) ?? {
1187
- phase,
1188
- session_id: sessionId,
1189
- task_id: taskId
1190
- };
1296
+ let lifecycleKey = phaseLifecycleKey(phase, sessionId, taskId);
1297
+ let lifecycle = state.phaseLifecycle.get(lifecycleKey);
1298
+ if (lifecycle === undefined && phaseId !== undefined) {
1299
+ for (const [candidateKey, candidate] of state.phaseLifecycle) {
1300
+ if (candidate.session_id === sessionId && candidate.task_id === taskId && (candidate.phase_id === phaseId || candidate.phase_id === undefined && extractPhaseIdFromLabel(candidate.phase) === phaseId)) {
1301
+ lifecycleKey = candidateKey;
1302
+ lifecycle = candidate;
1303
+ break;
1304
+ }
1305
+ }
1306
+ }
1307
+ if (lifecycle === undefined) {
1308
+ lifecycle = {
1309
+ phase,
1310
+ session_id: sessionId,
1311
+ task_id: taskId
1312
+ };
1313
+ }
1314
+ if (lifecycle.phase_id === undefined && phaseId !== undefined) {
1315
+ lifecycle.phase_id = phaseId;
1316
+ }
1191
1317
  if (record.kind === "phase_close_intent" && !lifecycle.intent_event_id) {
1192
1318
  lifecycle.intent_event_id = record.event_id;
1193
1319
  lifecycle.intent_at = record.timestamp;
@@ -1197,7 +1323,7 @@ function applyRecord(state, record) {
1197
1323
  }
1198
1324
  state.phaseLifecycle.set(lifecycleKey, lifecycle);
1199
1325
  for (const membership of state.memberships.values()) {
1200
- if (membership.phase !== phase || membership.session_id !== sessionId || membership.task_id !== taskId)
1326
+ if (!membershipMatchesPhaseIdentity(membership, phase, phaseId) || membership.session_id !== sessionId || membership.task_id !== taskId)
1201
1327
  continue;
1202
1328
  if (record.kind === "phase_close_intent" && !membership.phase_close_intent_at)
1203
1329
  membership.phase_close_intent_at = record.timestamp;
@@ -1214,6 +1340,16 @@ function applyRecord(state, record) {
1214
1340
  }
1215
1341
  }
1216
1342
  }
1343
+ } else if (record.kind === "phase_id_backfilled") {
1344
+ for (const item of Array.isArray(record.payload.items) ? record.payload.items : []) {
1345
+ const candidate = item;
1346
+ if (typeof candidate.trace_id !== "string" || typeof candidate.entry_id !== "string" || !Number.isSafeInteger(candidate.phase_id) || candidate.phase_id < 1)
1347
+ continue;
1348
+ const membership = state.memberships.get(keyOf(candidate.trace_id, candidate.entry_id));
1349
+ if (membership && membership.phase_id === undefined) {
1350
+ membership.phase_id = candidate.phase_id;
1351
+ }
1352
+ }
1217
1353
  } else if (record.kind === "repair_uncertainty_installed") {
1218
1354
  const uncertainty = parseRepairUncertainty(record.payload.uncertainty);
1219
1355
  if (uncertainty) {
@@ -1314,7 +1450,9 @@ function validateRecordPayload(row) {
1314
1450
  return hasOnlyKeys(payload, ["trace_id", "rejected"]) && typeof payload.trace_id === "string" && Array.isArray(payload.rejected) && payload.rejected.every((item) => isPlainRecord(item) && hasOnlyKeys(item, ["entry_id", "reason"]) && typeof item.entry_id === "string" && typeof item.reason === "string");
1315
1451
  case "phase_close_intent":
1316
1452
  case "phase_closed":
1317
- return hasOnlyKeys(payload, ["phase", "session_id", "task_id"]) && typeof payload.phase === "string" && !!payload.phase && typeof payload.session_id === "string" && !!payload.session_id && isOptionalString(payload.task_id);
1453
+ return hasOnlyKeys(payload, ["phase", "phase_id", "session_id", "task_id"]) && typeof payload.phase === "string" && !!payload.phase && (payload.phase_id === undefined || Number.isSafeInteger(payload.phase_id) && payload.phase_id >= 1) && typeof payload.session_id === "string" && !!payload.session_id && isOptionalString(payload.task_id);
1454
+ case "phase_id_backfilled":
1455
+ return hasOnlyKeys(payload, ["items"]) && Array.isArray(payload.items) && payload.items.length > 0 && payload.items.every((item) => isPlainRecord(item) && hasOnlyKeys(item, ["trace_id", "entry_id", "phase_id"]) && typeof item.trace_id === "string" && !!item.trace_id && typeof item.entry_id === "string" && !!item.entry_id && Number.isSafeInteger(item.phase_id) && item.phase_id >= 1);
1318
1456
  case "repair_uncertainty_installed":
1319
1457
  return hasOnlyKeys(payload, ["uncertainty"]) && parseRepairUncertainty(payload.uncertainty) !== null;
1320
1458
  case "repair_uncertainty_cleared":
@@ -1360,6 +1498,7 @@ function validateRecord(value, state) {
1360
1498
  "gate_release_committed",
1361
1499
  "phase_close_intent",
1362
1500
  "phase_closed",
1501
+ "phase_id_backfilled",
1363
1502
  "repair_uncertainty_installed",
1364
1503
  "repair_uncertainty_cleared",
1365
1504
  "legacy_imported",
@@ -1816,15 +1955,28 @@ async function commitDisplayedMembership(directory, input) {
1816
1955
  return runLocked(directory, input.grace_days, async (paths, state, graceDays) => {
1817
1956
  if (!input.trace_id || !input.session_id || input.entries.length === 0)
1818
1957
  throw new ReceiptStoreError("store_unavailable", "invalid displayed membership");
1958
+ if (input.phase_id !== undefined && (!Number.isSafeInteger(input.phase_id) || input.phase_id < 1))
1959
+ throw new ReceiptStoreError("store_unavailable", "invalid displayed membership: phase_id must be a safe integer >= 1");
1819
1960
  const eventId = randomUUID2();
1820
1961
  const committedAt = nowIso();
1821
1962
  const exposureKind = normalizeExposureKind(input.exposure_kind);
1822
1963
  const memberships = [];
1823
1964
  const newMemberships = [];
1965
+ const closedLifecycle = findClosedLifecycleForPhase(state, {
1966
+ phase: input.phase,
1967
+ phase_id: input.phase_id,
1968
+ session_id: input.session_id,
1969
+ task_id: input.task_id
1970
+ }) ?? (input.task_id !== undefined ? findClosedLifecycleForPhase(state, {
1971
+ phase: input.phase,
1972
+ phase_id: input.phase_id,
1973
+ session_id: input.session_id,
1974
+ task_id: undefined
1975
+ }) : undefined);
1824
1976
  for (const entry of input.entries) {
1825
1977
  const existing = state.memberships.get(keyOf(input.trace_id, entry.entry_id));
1826
1978
  if (existing) {
1827
- if (existing.session_id !== input.session_id || existing.phase !== input.phase || existing.task_id !== input.task_id || existing.critical !== entry.critical || existing.cohort_id !== input.cohort_id || existing.source_link_id !== input.source_link_id || existing.exposure_kind !== exposureKind) {
1979
+ if (existing.session_id !== input.session_id || existing.phase !== input.phase || existing.phase_id !== undefined && input.phase_id !== undefined && existing.phase_id !== input.phase_id || existing.task_id !== input.task_id || existing.critical !== entry.critical || existing.cohort_id !== input.cohort_id || existing.source_link_id !== input.source_link_id || existing.exposure_kind !== exposureKind) {
1828
1980
  throw new ReceiptStoreError("store_unavailable", `conflicting immutable membership for ${input.trace_id}/${entry.entry_id}`);
1829
1981
  }
1830
1982
  memberships.push({
@@ -1833,7 +1985,6 @@ async function commitDisplayedMembership(directory, input) {
1833
1985
  });
1834
1986
  continue;
1835
1987
  }
1836
- const closedLifecycle = state.phaseLifecycle.get(phaseLifecycleKey(input.phase ?? "", input.session_id, input.task_id)) ?? (input.task_id !== undefined ? state.phaseLifecycle.get(phaseLifecycleKey(input.phase ?? "", input.session_id)) : undefined);
1837
1988
  if (input.phase && closedLifecycle?.closed_event_id) {
1838
1989
  throw new ReceiptStoreError("store_unavailable", `cannot add receipt membership to closed lifecycle ${input.session_id}/${input.phase}`);
1839
1990
  }
@@ -1842,6 +1993,7 @@ async function commitDisplayedMembership(directory, input) {
1842
1993
  entry_id: entry.entry_id,
1843
1994
  session_id: input.session_id,
1844
1995
  phase: input.phase,
1996
+ phase_id: input.phase_id,
1845
1997
  task_id: input.task_id,
1846
1998
  agent: input.agent,
1847
1999
  critical: entry.critical,
@@ -2060,7 +2212,7 @@ async function queryLiveMemberships(directory, filters = {}) {
2060
2212
  throw new ReceiptStoreError("store_unavailable", repairUncertaintyUnavailable(overlaps).detail);
2061
2213
  }
2062
2214
  return {
2063
- memberships: [...state.memberships.values()].filter((m) => (!filters.phase || m.phase === filters.phase) && (!filters.task_id || m.task_id === filters.task_id) && (!filters.session_id || m.session_id === filters.session_id) && (filters.include_terminal !== false || !m.terminal) && (filters.include_phase_closed !== false || !m.phase_closed_at) && (!filters.exposure_kind || m.exposure_kind === filters.exposure_kind)).map((m) => ({
2215
+ memberships: [...state.memberships.values()].filter((m) => (filters.phase_id === undefined || membershipMatchesPhaseIdentity(m, filters.phase ?? "", filters.phase_id)) && (!filters.phase || filters.phase_id !== undefined || m.phase === filters.phase) && (!filters.task_id || m.task_id === filters.task_id) && (!filters.session_id || m.session_id === filters.session_id) && (filters.include_terminal !== false || !m.terminal) && (filters.include_phase_closed !== false || !m.phase_closed_at) && (!filters.exposure_kind || m.exposure_kind === filters.exposure_kind)).map((m) => ({
2064
2216
  ...m,
2065
2217
  terminal: m.terminal ? { ...m.terminal } : undefined
2066
2218
  }))
@@ -2097,11 +2249,12 @@ async function queryHistoricalOutcomes(directory, entryIds, graceDays) {
2097
2249
  return { memberships: [...memberships.values()] };
2098
2250
  }, { compact: false, writeSnapshot: false });
2099
2251
  }
2100
- async function phaseTransition(directory, phase, kind, sessionId, taskId, graceDays) {
2252
+ async function phaseTransition(directory, phase, kind, sessionId, taskId, graceDays, phaseId) {
2101
2253
  return runLocked(directory, graceDays, async (paths, state) => {
2102
2254
  if (!phase.trim()) {
2103
2255
  throw new ReceiptStoreError("store_unavailable", "phase is required");
2104
2256
  }
2257
+ const effectivePhaseId = phaseId !== undefined && Number.isSafeInteger(phaseId) && phaseId >= 1 ? phaseId : undefined;
2105
2258
  const scopeKeys = new Map;
2106
2259
  const addScope = (scopeSessionId, scopeTaskId) => {
2107
2260
  if (sessionId !== undefined && scopeSessionId !== sessionId || taskId !== undefined && scopeTaskId !== taskId)
@@ -2112,7 +2265,7 @@ async function phaseTransition(directory, phase, kind, sessionId, taskId, graceD
2112
2265
  });
2113
2266
  };
2114
2267
  for (const membership of state.memberships.values()) {
2115
- if (membership.phase === phase)
2268
+ if (membershipMatchesPhaseIdentity(membership, phase, effectivePhaseId))
2116
2269
  addScope(membership.session_id, membership.task_id);
2117
2270
  }
2118
2271
  for (const trace of state.emptyTraces.values()) {
@@ -2120,9 +2273,20 @@ async function phaseTransition(directory, phase, kind, sessionId, taskId, graceD
2120
2273
  addScope(trace.session_id, trace.task_id);
2121
2274
  }
2122
2275
  for (const lifecycle of state.phaseLifecycle.values()) {
2123
- if (lifecycle.phase === phase)
2276
+ if (effectivePhaseId !== undefined ? (lifecycle.phase_id === effectivePhaseId || lifecycle.phase_id === undefined && extractPhaseIdFromLabel(lifecycle.phase) === effectivePhaseId) && (sessionId === undefined || lifecycle.session_id === sessionId) : lifecycle.phase === phase)
2124
2277
  addScope(lifecycle.session_id, lifecycle.task_id);
2125
2278
  }
2279
+ if (scopeKeys.size === 0 && sessionId !== undefined) {
2280
+ const closedLifecycle = findClosedLifecycleForPhase(state, {
2281
+ phase,
2282
+ phase_id: effectivePhaseId,
2283
+ session_id: sessionId,
2284
+ task_id: taskId
2285
+ });
2286
+ if (closedLifecycle) {
2287
+ addScope(closedLifecycle.session_id, closedLifecycle.task_id);
2288
+ }
2289
+ }
2126
2290
  if (scopeKeys.size === 0 && sessionId !== undefined) {
2127
2291
  addScope(sessionId, taskId);
2128
2292
  }
@@ -2134,14 +2298,45 @@ async function phaseTransition(directory, phase, kind, sessionId, taskId, graceD
2134
2298
  }
2135
2299
  let eventId = "";
2136
2300
  for (const [key, scope] of scopeKeys) {
2137
- const lifecycle = state.phaseLifecycle.get(key);
2301
+ const lifecycle = findClosedLifecycleForPhase(state, {
2302
+ phase,
2303
+ phase_id: effectivePhaseId,
2304
+ session_id: scope.session_id,
2305
+ task_id: scope.task_id
2306
+ }) ?? state.phaseLifecycle.get(key);
2138
2307
  const existingEventId = kind === "phase_close_intent" ? lifecycle?.intent_event_id : lifecycle?.closed_event_id;
2139
2308
  if (existingEventId) {
2140
2309
  eventId ||= existingEventId;
2141
2310
  continue;
2142
2311
  }
2143
- const row = makeRecord(state, kind, { phase, ...scope });
2312
+ const row = makeRecord(state, kind, {
2313
+ phase,
2314
+ ...effectivePhaseId !== undefined ? { phase_id: effectivePhaseId } : {},
2315
+ ...scope
2316
+ });
2144
2317
  await appendRecord(paths, state, row);
2318
+ if (lifecycle === undefined) {
2319
+ state.phaseLifecycle.set(key, {
2320
+ phase,
2321
+ ...effectivePhaseId !== undefined ? { phase_id: effectivePhaseId } : {},
2322
+ session_id: scope.session_id,
2323
+ task_id: scope.task_id,
2324
+ intent_event_id: kind === "phase_close_intent" ? row.event_id : undefined,
2325
+ intent_at: kind === "phase_close_intent" ? row.timestamp : undefined,
2326
+ closed_event_id: kind === "phase_closed" ? row.event_id : undefined,
2327
+ closed_at: kind === "phase_closed" ? row.timestamp : undefined
2328
+ });
2329
+ } else {
2330
+ if (lifecycle.phase_id === undefined && effectivePhaseId !== undefined)
2331
+ lifecycle.phase_id = effectivePhaseId;
2332
+ if (kind === "phase_close_intent" && !lifecycle.intent_event_id) {
2333
+ lifecycle.intent_event_id = row.event_id;
2334
+ lifecycle.intent_at = row.timestamp;
2335
+ } else if (kind === "phase_closed" && !lifecycle.closed_event_id) {
2336
+ lifecycle.closed_event_id = row.event_id;
2337
+ lifecycle.closed_at = row.timestamp;
2338
+ }
2339
+ }
2145
2340
  eventId ||= row.event_id;
2146
2341
  }
2147
2342
  if (kind === "phase_closed")
@@ -2149,12 +2344,12 @@ async function phaseTransition(directory, phase, kind, sessionId, taskId, graceD
2149
2344
  return { event_id: eventId };
2150
2345
  });
2151
2346
  }
2152
- var recordPhaseCloseIntent = (directory, phase, sessionId, taskId) => phaseTransition(directory, phase, "phase_close_intent", sessionId, taskId);
2153
- var commitPhaseClosed = (directory, phase, sessionId, taskId) => phaseTransition(directory, phase, "phase_closed", sessionId, taskId);
2154
- async function reconcilePhaseClose(directory, phase, durablePlanClosed, sessionId, taskId) {
2347
+ var recordPhaseCloseIntent = (directory, phase, sessionId, taskId, phaseId) => phaseTransition(directory, phase, "phase_close_intent", sessionId, taskId, undefined, phaseId);
2348
+ var commitPhaseClosed = (directory, phase, sessionId, taskId, phaseId) => phaseTransition(directory, phase, "phase_closed", sessionId, taskId, undefined, phaseId);
2349
+ async function reconcilePhaseClose(directory, phase, durablePlanClosed, sessionId, taskId, phaseId) {
2155
2350
  if (!durablePlanClosed)
2156
2351
  return { ok: true, reconciled: false };
2157
- const result = await commitPhaseClosed(directory, phase, sessionId, taskId);
2352
+ const result = await commitPhaseClosed(directory, phase, sessionId, taskId, phaseId);
2158
2353
  return result.ok ? { ok: true, reconciled: true } : result;
2159
2354
  }
2160
2355
  async function compactIfNeeded(paths, state) {
@@ -2258,729 +2453,85 @@ function serializeArchive(summaries) {
2258
2453
  `)}
2259
2454
  ` : "";
2260
2455
  }
2261
- var _internals3 = {
2262
- nowMs: () => Date.now(),
2263
- writeSnapshot,
2264
- atomicWriteFsynced,
2265
- appendFsynced,
2266
- commitApplicationMarkerBatch,
2267
- maxJournalRecords: MAX_JOURNAL_RECORDS,
2268
- maxArchiveRecords: MAX_ARCHIVE_RECORDS,
2269
- maxArchiveBytes: MAX_ARCHIVE_BYTES,
2270
- maxRepairQuarantineRecords: MAX_REPAIR_QUARANTINE_RECORDS
2271
- };
2272
-
2273
- // src/hooks/knowledge-events.ts
2274
- var KNOWLEDGE_EVENT_SCHEMA_VERSION = 1;
2275
- var MAX_EVENT_LOG_ENTRIES = 5000;
2276
- var counterRollupCache = new Map;
2277
- var MAX_COUNTER_ROLLUP_CACHE_DIRS = 32;
2278
- var RECEIPT_EVENT_TYPES = new Set([
2279
- "acknowledged",
2280
- "applied",
2281
- "ignored",
2282
- "contradicted",
2283
- "violated",
2284
- "n_a",
2285
- "override",
2286
- "no_relevant"
2287
- ]);
2288
- function resolveKnowledgeEventsPath(directory) {
2289
- return path2.join(resolveKnowledgeStoreDir(directory), "knowledge-events.jsonl");
2290
- }
2291
- function resolveKnowledgeCounterBaselinePath(directory) {
2292
- return path2.join(resolveKnowledgeStoreDir(directory), "knowledge-counter-baseline.json");
2293
- }
2294
- var resolveHiveEventsPath2 = resolveHiveEventsPath;
2295
- function resolveLegacyApplicationLogPath(directory) {
2296
- return path2.join(resolveKnowledgeStoreDir(directory), "knowledge-application.jsonl");
2297
- }
2298
- function newTraceId() {
2299
- return randomUUID3();
2300
- }
2301
- function newEventId() {
2302
- return randomUUID3();
2303
- }
2304
- function withDefaults(event) {
2305
- return {
2306
- schema_version: KNOWLEDGE_EVENT_SCHEMA_VERSION,
2307
- ...event,
2308
- event_id: event.event_id || newEventId(),
2309
- timestamp: event.timestamp || new Date().toISOString()
2310
- };
2311
- }
2312
- async function appendKnowledgeEvent(directory, event) {
2313
- const [populated] = await appendKnowledgeEventsBatch(directory, [event]);
2314
- return populated;
2315
- }
2316
- async function appendKnowledgeEventsBatch(directory, events) {
2317
- if (events.length === 0)
2318
- return [];
2319
- const populated = events.map(withDefaults);
2320
- const filePath = resolveKnowledgeEventsPath(directory);
2321
- const dirPath = path2.dirname(filePath);
2322
- await mkdir2(dirPath, { recursive: true });
2323
- let release;
2324
- try {
2325
- release = await import_proper_lockfile.default.lock(dirPath, {
2326
- retries: { retries: 200, minTimeout: 10, maxTimeout: 100 }
2327
- });
2328
- await appendFile(filePath, `${populated.map((e) => JSON.stringify(e)).join(`
2329
- `)}
2330
- `, "utf-8");
2331
- try {
2332
- const content = await readFile2(filePath, "utf-8");
2333
- const lines = content.split(`
2334
- `).filter((line) => line.trim().length > 0);
2335
- if (lines.length > MAX_EVENT_LOG_ENTRIES) {
2336
- const evicted = lines.slice(0, lines.length - MAX_EVENT_LOG_ENTRIES);
2337
- const trimmed = lines.slice(lines.length - MAX_EVENT_LOG_ENTRIES);
2338
- await foldEvictedEventsIntoBaseline(directory, evicted, filePath);
2339
- await atomicWriteFile(filePath, `${trimmed.join(`
2340
- `)}
2341
- `);
2342
- }
2343
- } catch (err) {
2344
- warn(`[knowledge-events] local cap trim failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
2345
- }
2346
- } finally {
2347
- if (release)
2348
- await release().catch(() => {});
2349
- }
2350
- return populated;
2351
- }
2352
- async function recordKnowledgeEvent(directory, event) {
2353
- try {
2354
- return await appendKnowledgeEvent(directory, event);
2355
- } catch (err) {
2356
- warn(`[knowledge-events] recordKnowledgeEvent failed: ${err instanceof Error ? err.message : String(err)}`);
2357
- return null;
2358
- }
2359
- }
2360
- async function recordKnowledgeEventsBatch(directory, events) {
2361
- try {
2362
- return await appendKnowledgeEventsBatch(directory, events);
2363
- } catch (err) {
2364
- warn(`[knowledge-events] recordKnowledgeEventsBatch failed: ${err instanceof Error ? err.message : String(err)}`);
2365
- return null;
2366
- }
2367
- }
2368
- async function appendHiveKnowledgeEvent(event) {
2369
- const populated = withDefaults(event);
2370
- const filePath = resolveHiveEventsPath2();
2371
- const dirPath = path2.dirname(filePath);
2372
- await mkdir2(dirPath, { recursive: true });
2373
- let release;
2374
- try {
2375
- release = await import_proper_lockfile.default.lock(dirPath, {
2376
- retries: { retries: 200, minTimeout: 10, maxTimeout: 100 },
2377
- stale: 5000
2378
- });
2379
- await appendFile(filePath, `${JSON.stringify(populated)}
2380
- `, "utf-8");
2381
- try {
2382
- const content = await readFile2(filePath, "utf-8");
2383
- const lines = content.split(`
2384
- `).filter((line) => line.trim().length > 0);
2385
- if (lines.length > MAX_EVENT_LOG_ENTRIES) {
2386
- const trimmed = lines.slice(lines.length - MAX_EVENT_LOG_ENTRIES);
2387
- await atomicWriteFile(filePath, `${trimmed.join(`
2388
- `)}
2389
- `);
2390
- }
2391
- } catch (err) {
2392
- warn(`[knowledge-events] hive cap trim failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
2393
- }
2394
- } finally {
2395
- if (release)
2396
- await release().catch(() => {});
2397
- }
2398
- return populated;
2399
- }
2400
- async function recordHiveKnowledgeEvent(event) {
2401
- try {
2402
- return await appendHiveKnowledgeEvent(event);
2403
- } catch (err) {
2404
- warn(`[knowledge-events] recordHiveKnowledgeEvent failed: ${err instanceof Error ? err.message : String(err)}`);
2405
- return null;
2406
- }
2407
- }
2408
- async function readKnowledgeEvents(directory, maxEvents) {
2409
- const filePath = resolveKnowledgeEventsPath(directory);
2410
- if (!existsSync3(filePath))
2411
- return [];
2412
- const content = await readFile2(filePath, "utf-8");
2413
- const out = [];
2414
- const max = maxEvents !== undefined && maxEvents > 0 ? maxEvents : Infinity;
2415
- for (const line of content.split(`
2416
- `)) {
2417
- if (out.length >= max)
2418
- break;
2419
- const trimmed = line.trim();
2420
- if (!trimmed)
2421
- continue;
2422
- try {
2423
- out.push(JSON.parse(trimmed));
2424
- } catch {
2425
- warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
2426
- }
2427
- }
2428
- return out;
2429
- }
2430
- async function readHiveKnowledgeEvents() {
2431
- const filePath = resolveHiveEventsPath2();
2432
- if (!existsSync3(filePath))
2433
- return [];
2434
- const content = await readFile2(filePath, "utf-8");
2435
- return parseEventLines(content.split(`
2436
- `), filePath);
2437
- }
2438
- async function readLegacyApplicationRecords(directory) {
2439
- const filePath = resolveLegacyApplicationLogPath(directory);
2440
- if (!existsSync3(filePath))
2441
- return [];
2442
- const content = await readFile2(filePath, "utf-8");
2443
- const out = [];
2444
- for (const line of content.split(`
2445
- `)) {
2446
- const trimmed = line.trim();
2447
- if (!trimmed)
2448
- continue;
2449
- try {
2450
- out.push(JSON.parse(trimmed));
2451
- } catch {
2452
- warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
2453
- }
2454
- }
2455
- return out;
2456
- }
2457
- var MAX_VIOLATION_TIMESTAMPS = 10;
2458
- function emptyRollup() {
2459
- return {
2460
- shown_count: 0,
2461
- acknowledged_count: 0,
2462
- applied_explicit_count: 0,
2463
- ignored_count: 0,
2464
- violated_count: 0,
2465
- contradicted_count: 0,
2466
- n_a_count: 0,
2467
- succeeded_after_shown_count: 0,
2468
- failed_after_shown_count: 0,
2469
- partial_after_shown_count: 0,
2470
- violation_timestamps: []
2471
- };
2472
- }
2473
- function cloneRollup(input) {
2474
- return {
2475
- ...emptyRollup(),
2476
- ...input,
2477
- violation_timestamps: [...input.violation_timestamps ?? []]
2478
- };
2479
- }
2480
- function cloneRollupMap(input) {
2481
- const out = new Map;
2482
- for (const [id, rollup] of input) {
2483
- out.set(id, cloneRollup(rollup));
2484
- }
2485
- return out;
2486
- }
2487
- function normalizeRollupTimestamps(rollup) {
2488
- if (rollup.violation_timestamps.length > 1) {
2489
- rollup.violation_timestamps.sort((a, b) => a < b ? 1 : a > b ? -1 : 0);
2490
- }
2491
- if (rollup.violation_timestamps.length > MAX_VIOLATION_TIMESTAMPS) {
2492
- rollup.violation_timestamps = rollup.violation_timestamps.slice(0, MAX_VIOLATION_TIMESTAMPS);
2493
- }
2494
- return rollup;
2495
- }
2496
- function mergeRollupInto(target, source) {
2497
- target.shown_count += source.shown_count ?? 0;
2498
- target.acknowledged_count += source.acknowledged_count ?? 0;
2499
- target.applied_explicit_count += source.applied_explicit_count ?? 0;
2500
- target.ignored_count += source.ignored_count ?? 0;
2501
- target.violated_count += source.violated_count ?? 0;
2502
- target.contradicted_count += source.contradicted_count ?? 0;
2503
- target.n_a_count += source.n_a_count ?? 0;
2504
- target.succeeded_after_shown_count += source.succeeded_after_shown_count ?? 0;
2505
- target.failed_after_shown_count += source.failed_after_shown_count ?? 0;
2506
- target.partial_after_shown_count += source.partial_after_shown_count ?? 0;
2507
- if (source.last_applied_at) {
2508
- target.last_applied_at = maxIso(target.last_applied_at, source.last_applied_at);
2509
- }
2510
- if (source.last_acknowledged_at) {
2511
- target.last_acknowledged_at = maxIso(target.last_acknowledged_at, source.last_acknowledged_at);
2512
- }
2513
- target.violation_timestamps.push(...source.violation_timestamps ?? []);
2514
- normalizeRollupTimestamps(target);
2515
- }
2516
- function get(map, id) {
2517
- let r = map.get(id);
2518
- if (!r) {
2519
- r = emptyRollup();
2520
- map.set(id, r);
2521
- }
2522
- return r;
2523
- }
2524
- function maxIso(current, candidate) {
2525
- if (!current)
2526
- return candidate;
2527
- return candidate > current ? candidate : current;
2528
- }
2529
- async function readCounterBaseline(directory) {
2530
- const filePath = resolveKnowledgeCounterBaselinePath(directory);
2531
- if (!existsSync3(filePath))
2532
- return new Map;
2533
- let raw;
2534
- try {
2535
- raw = JSON.parse(await readFile2(filePath, "utf-8"));
2536
- } catch (err) {
2537
- warn(`[knowledge-events] corrupted counter baseline at ${filePath}; ignoring folded baseline and replaying live events only: ${err instanceof Error ? err.message : String(err)}`);
2538
- return new Map;
2539
- }
2540
- const map = new Map;
2541
- for (const [id, rollup] of Object.entries(raw)) {
2542
- map.set(id, normalizeRollupTimestamps(cloneRollup(rollup)));
2543
- }
2544
- return map;
2545
- }
2546
- async function writeCounterBaseline(directory, baseline) {
2547
- const filePath = resolveKnowledgeCounterBaselinePath(directory);
2548
- const out = {};
2549
- for (const [id, rollup] of [...baseline.entries()].sort(([a], [b]) => a.localeCompare(b))) {
2550
- out[id] = normalizeRollupTimestamps(cloneRollup(rollup));
2551
- }
2552
- await atomicWriteFile(filePath, `${JSON.stringify(out, null, 2)}
2553
- `);
2554
- }
2555
- async function statCacheKey(filePath) {
2556
- try {
2557
- const fileStat = await stat2(filePath);
2558
- return `${fileStat.mtimeMs}:${fileStat.ctimeMs}:${fileStat.size}`;
2559
- } catch (err) {
2560
- if (err?.code === "ENOENT")
2561
- return "missing";
2562
- throw err;
2563
- }
2564
- }
2565
- async function buildCounterRollupCacheKey(directory) {
2566
- const [eventsKey, legacyKey, baselineKey] = await Promise.all([
2567
- statCacheKey(resolveKnowledgeEventsPath(directory)),
2568
- statCacheKey(resolveLegacyApplicationLogPath(directory)),
2569
- statCacheKey(resolveKnowledgeCounterBaselinePath(directory))
2570
- ]);
2571
- return `${eventsKey}|${legacyKey}|${baselineKey}`;
2572
- }
2573
- function setCounterRollupCache(directory, key, rollups) {
2574
- const cacheKey = canonicalRootKey(directory);
2575
- if (counterRollupCache.has(cacheKey)) {
2576
- counterRollupCache.delete(cacheKey);
2577
- }
2578
- counterRollupCache.set(cacheKey, {
2579
- key,
2580
- rollups: cloneRollupMap(rollups)
2581
- });
2582
- while (counterRollupCache.size > MAX_COUNTER_ROLLUP_CACHE_DIRS) {
2583
- const oldestKey = counterRollupCache.keys().next().value;
2584
- if (oldestKey === undefined)
2585
- break;
2586
- counterRollupCache.delete(oldestKey);
2587
- }
2588
- }
2589
- function parseEventLines(lines, filePath) {
2590
- const out = [];
2591
- for (const line of lines) {
2592
- const trimmed = line.trim();
2593
- if (!trimmed)
2594
- continue;
2595
- try {
2596
- out.push(JSON.parse(trimmed));
2597
- } catch {
2598
- warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
2599
- }
2600
- }
2601
- return out;
2602
- }
2603
- async function foldEvictedEventsIntoBaseline(directory, evictedLines, filePath) {
2604
- const evictedEvents = parseEventLines(evictedLines, filePath);
2605
- if (evictedEvents.length === 0)
2606
- return;
2607
- const baseline = await readCounterBaseline(directory);
2608
- for (const [id, rollup] of recomputeCounters(evictedEvents)) {
2609
- mergeRollupInto(get(baseline, id), rollup);
2610
- }
2611
- await writeCounterBaseline(directory, baseline);
2612
- }
2613
- function recomputeCounters(events, legacyRecords = [], baseline = new Map) {
2614
- const map = new Map;
2615
- const retrievedIds = new Set;
2616
- for (const [id, rollup] of baseline) {
2617
- map.set(id, cloneRollup(rollup));
2618
- if ((rollup.shown_count ?? 0) > 0)
2619
- retrievedIds.add(id);
2620
- }
2621
- for (const e of events) {
2622
- switch (e.type) {
2623
- case "retrieved": {
2624
- for (const id of e.result_ids) {
2625
- retrievedIds.add(id);
2626
- get(map, id).shown_count += 1;
2627
- }
2628
- break;
2629
- }
2630
- case "acknowledged": {
2631
- if (!e.knowledge_id)
2632
- break;
2633
- const r = get(map, e.knowledge_id);
2634
- r.acknowledged_count += 1;
2635
- r.last_acknowledged_at = maxIso(r.last_acknowledged_at, e.timestamp);
2636
- break;
2637
- }
2638
- case "applied": {
2639
- if (!e.knowledge_id)
2640
- break;
2641
- const r = get(map, e.knowledge_id);
2642
- r.applied_explicit_count += 1;
2643
- r.last_applied_at = maxIso(r.last_applied_at, e.timestamp);
2644
- break;
2645
- }
2646
- case "ignored":
2647
- if (!e.knowledge_id)
2648
- break;
2649
- get(map, e.knowledge_id).ignored_count += 1;
2650
- break;
2651
- case "violated": {
2652
- if (!e.knowledge_id)
2653
- break;
2654
- const r = get(map, e.knowledge_id);
2655
- r.violated_count += 1;
2656
- r.violation_timestamps.push(e.timestamp);
2657
- break;
2658
- }
2659
- case "contradicted":
2660
- if (!e.knowledge_id)
2661
- break;
2662
- get(map, e.knowledge_id).contradicted_count += 1;
2663
- break;
2664
- case "n_a":
2665
- if (!e.knowledge_id)
2666
- break;
2667
- get(map, e.knowledge_id).n_a_count += 1;
2668
- break;
2669
- case "no_relevant":
2670
- break;
2671
- case "unacknowledged":
2672
- break;
2673
- case "outcome": {
2674
- if (!e.knowledge_id)
2675
- break;
2676
- const r = get(map, e.knowledge_id);
2677
- if (e.outcome === "success")
2678
- r.succeeded_after_shown_count += 1;
2679
- else if (e.outcome === "failure")
2680
- r.failed_after_shown_count += 1;
2681
- else if (e.outcome === "partial")
2682
- r.partial_after_shown_count += 1;
2683
- break;
2684
- }
2685
- }
2686
- }
2687
- for (const rec of legacyRecords) {
2688
- const r = get(map, rec.knowledgeId);
2689
- switch (rec.result) {
2690
- case "shown":
2691
- if (!retrievedIds.has(rec.knowledgeId))
2692
- r.shown_count += 1;
2693
- break;
2694
- case "acknowledged":
2695
- r.acknowledged_count += 1;
2696
- r.last_acknowledged_at = maxIso(r.last_acknowledged_at, rec.timestamp);
2697
- break;
2698
- case "applied":
2699
- r.applied_explicit_count += 1;
2700
- r.last_applied_at = maxIso(r.last_applied_at, rec.timestamp);
2701
- break;
2702
- case "ignored":
2703
- r.ignored_count += 1;
2704
- break;
2705
- case "contradicted":
2706
- r.contradicted_count += 1;
2707
- break;
2708
- case "violated":
2709
- r.violated_count += 1;
2710
- r.violation_timestamps.push(rec.timestamp);
2711
- break;
2712
- }
2713
- }
2714
- for (const r of map.values()) {
2715
- normalizeRollupTimestamps(r);
2716
- }
2717
- return map;
2718
- }
2719
- function countViolationsInWindow(timestamps, windowDays, now = new Date) {
2720
- const cutoff = now.getTime() - windowDays * 24 * 60 * 60 * 1000;
2721
- let count = 0;
2722
- for (const ts of timestamps) {
2723
- const t = Date.parse(ts);
2724
- if (!Number.isNaN(t) && t >= cutoff)
2725
- count += 1;
2726
- }
2727
- return count;
2728
- }
2729
- function countEmptyTraceTerminals(events) {
2730
- let n = 0;
2731
- for (const e of events) {
2732
- if (e.type === "no_relevant")
2733
- n += 1;
2734
- }
2735
- return n;
2736
- }
2737
- async function countEntryViolationsInWindow(directory, entryId, windowDays, now = new Date) {
2738
- try {
2739
- const cutoff = now.getTime() - windowDays * 24 * 60 * 60 * 1000;
2740
- const [events, legacyRecords] = await Promise.all([
2741
- readKnowledgeEvents(directory),
2742
- readLegacyApplicationRecords(directory)
2743
- ]);
2744
- let count = 0;
2745
- for (const e of events) {
2746
- if (e.type !== "violated" || e.knowledge_id !== entryId)
2456
+ async function inspectMembershipPhaseIds(directory) {
2457
+ return runLocked(directory, undefined, async (_paths, state) => {
2458
+ let backfillable = 0;
2459
+ const unparsable = [];
2460
+ let missing = 0;
2461
+ for (const membership of state.memberships.values()) {
2462
+ if (membership.phase_id !== undefined)
2747
2463
  continue;
2748
- const t = Date.parse(e.timestamp);
2749
- if (!Number.isNaN(t) && t >= cutoff)
2750
- count += 1;
2751
- }
2752
- for (const rec of legacyRecords) {
2753
- if (rec.result !== "violated" || rec.knowledgeId !== entryId)
2464
+ missing++;
2465
+ if (membership.phase === undefined) {
2466
+ unparsable.push({
2467
+ trace_id: membership.trace_id,
2468
+ entry_id: membership.entry_id
2469
+ });
2754
2470
  continue;
2755
- const t = Date.parse(rec.timestamp);
2756
- if (!Number.isNaN(t) && t >= cutoff)
2757
- count += 1;
2471
+ }
2472
+ if (extractPhaseIdFromLabel(membership.phase) !== undefined) {
2473
+ backfillable++;
2474
+ } else {
2475
+ unparsable.push({
2476
+ trace_id: membership.trace_id,
2477
+ entry_id: membership.entry_id,
2478
+ label: membership.phase
2479
+ });
2480
+ }
2758
2481
  }
2759
- return count;
2760
- } catch {
2761
- return 0;
2762
- }
2482
+ return { missing, backfillable, unparsable };
2483
+ }, { compact: false, writeSnapshot: false });
2763
2484
  }
2764
- async function countEntryContradictionsInWindow(directory, entryId, windowDays, now = new Date) {
2765
- try {
2766
- const cutoff = now.getTime() - windowDays * 24 * 60 * 60 * 1000;
2767
- const events = await readKnowledgeEvents(directory);
2768
- let count = 0;
2769
- for (const e of events) {
2770
- if (e.type !== "contradicted" || e.knowledge_id !== entryId)
2485
+ async function backfillMembershipPhaseIds(directory) {
2486
+ return runLocked(directory, undefined, async (paths, state) => {
2487
+ const items = [];
2488
+ const skipped = [];
2489
+ for (const membership of state.memberships.values()) {
2490
+ if (membership.phase_id !== undefined)
2771
2491
  continue;
2772
- const t = Date.parse(e.timestamp);
2773
- if (!Number.isNaN(t) && t >= cutoff)
2774
- count += 1;
2775
- }
2776
- return count;
2777
- } catch {
2778
- return 0;
2779
- }
2780
- }
2781
- async function readKnowledgeCounterRollups(directory) {
2782
- try {
2783
- const cacheKey = await buildCounterRollupCacheKey(directory);
2784
- const directoryKey = canonicalRootKey(directory);
2785
- const cached = counterRollupCache.get(directoryKey);
2786
- if (cached?.key === cacheKey) {
2787
- counterRollupCache.delete(directoryKey);
2788
- counterRollupCache.set(directoryKey, cached);
2789
- return cloneRollupMap(cached.rollups);
2790
- }
2791
- const [events, legacyRecords, baseline] = await Promise.all([
2792
- readKnowledgeEvents(directory),
2793
- readLegacyApplicationRecords(directory),
2794
- readCounterBaseline(directory)
2795
- ]);
2796
- const rollups = recomputeCounters(events, legacyRecords, baseline);
2797
- setCounterRollupCache(directory, cacheKey, rollups);
2798
- return cloneRollupMap(rollups);
2799
- } catch (err) {
2800
- warn(`[knowledge-events] readKnowledgeCounterRollups failed: ${err instanceof Error ? err.message : String(err)}`);
2801
- return new Map;
2802
- }
2803
- }
2804
- async function readAuthoritativeKnowledgeCounterRollups(directory) {
2805
- const history = await queryHistoricalOutcomes(directory);
2806
- if (!history.ok)
2807
- return new Map;
2808
- const rollups = new Map;
2809
- for (const membership of history.memberships) {
2810
- const rollup = get(rollups, membership.entry_id);
2811
- rollup.shown_count += 1;
2812
- if (membership.application_marker) {
2813
- rollup.acknowledged_count += 1;
2814
- rollup.last_acknowledged_at = maxIso(rollup.last_acknowledged_at, membership.application_marker.committed_at);
2815
- }
2816
- const compatible = membership;
2817
- const seen = new Set;
2818
- for (const terminal of [
2819
- ...compatible.terminal_history ?? [],
2820
- ...compatible.historical_terminals ?? [],
2821
- ...membership.terminal ? [membership.terminal] : []
2822
- ]) {
2823
- if (seen.has(terminal.event_id))
2492
+ const phaseId = extractPhaseIdFromLabel(membership.phase);
2493
+ if (phaseId === undefined) {
2494
+ skipped.push({
2495
+ trace_id: membership.trace_id,
2496
+ entry_id: membership.entry_id,
2497
+ label: membership.phase
2498
+ });
2824
2499
  continue;
2825
- seen.add(terminal.event_id);
2826
- switch (terminal.outcome) {
2827
- case "applied":
2828
- rollup.applied_explicit_count += 1;
2829
- rollup.last_applied_at = maxIso(rollup.last_applied_at, terminal.committed_at);
2830
- break;
2831
- case "ignored":
2832
- rollup.ignored_count += 1;
2833
- break;
2834
- case "violated":
2835
- rollup.violated_count += 1;
2836
- rollup.violation_timestamps.push(terminal.committed_at);
2837
- break;
2838
- case "contradicted":
2839
- rollup.contradicted_count += 1;
2840
- break;
2841
- case "n_a":
2842
- rollup.n_a_count += 1;
2843
- break;
2844
2500
  }
2845
- }
2846
- normalizeRollupTimestamps(rollup);
2847
- }
2848
- return rollups;
2849
- }
2850
- function effectiveRetrievalOutcomes(stored, rollup) {
2851
- const base = stored ?? {
2852
- applied_count: 0,
2853
- succeeded_after_count: 0,
2854
- failed_after_count: 0
2855
- };
2856
- if (!rollup)
2857
- return base;
2858
- const { n_a_count: _na, ...rollupWithoutNa } = rollup;
2859
- return {
2860
- ...base,
2861
- ...rollupWithoutNa,
2862
- succeeded_after_shown_count: (base.succeeded_after_shown_count ?? 0) + (rollup.succeeded_after_shown_count ?? 0),
2863
- failed_after_shown_count: (base.failed_after_shown_count ?? 0) + (rollup.failed_after_shown_count ?? 0)
2864
- };
2865
- }
2866
- var VERDICT_CONFIDENCE_BOOST = 0.03;
2867
- var VERDICT_CONFIDENCE_DECAY = 0.05;
2868
- async function applyKnowledgeVerdictFeedback(directory, options) {
2869
- try {
2870
- const history = await _internals4.queryHistoricalOutcomes(directory);
2871
- if (!history.ok)
2872
- return { processed: 0, bumps: 0 };
2873
- const seenEventIds = new Set;
2874
- const events = history.memberships.flatMap((membership) => {
2875
- const compatible = membership;
2876
- const terminals = [
2877
- ...compatible.terminal_history ?? [],
2878
- ...compatible.historical_terminals ?? [],
2879
- ...membership.terminal ? [membership.terminal] : []
2880
- ];
2881
- return terminals.flatMap((terminal) => {
2882
- if (terminal.outcome !== "applied" && terminal.outcome !== "violated" && terminal.outcome !== "ignored" || seenEventIds.has(terminal.event_id)) {
2883
- return [];
2884
- }
2885
- seenEventIds.add(terminal.event_id);
2886
- return [
2887
- {
2888
- type: terminal.outcome,
2889
- event_id: terminal.event_id,
2890
- knowledge_id: membership.entry_id,
2891
- timestamp: terminal.committed_at
2892
- }
2893
- ];
2501
+ items.push({
2502
+ trace_id: membership.trace_id,
2503
+ entry_id: membership.entry_id,
2504
+ phase_id: phaseId
2894
2505
  });
2895
- }).sort((a, b) => a.timestamp === b.timestamp ? a.event_id.localeCompare(b.event_id) : a.timestamp.localeCompare(b.timestamp));
2896
- const markerIndex = options?.sinceTimestamp && options.sinceEventId ? events.findIndex((e) => e.timestamp === options.sinceTimestamp && e.event_id === options.sinceEventId) : -1;
2897
- const actionable = events.filter((e, index) => {
2898
- if (options?.sinceTimestamp && e.timestamp < options.sinceTimestamp) {
2899
- return false;
2900
- }
2901
- if (options?.sinceTimestamp && e.timestamp === options.sinceTimestamp) {
2902
- if (!options.sinceEventId) {
2903
- return false;
2904
- }
2905
- if (markerIndex < 0) {
2906
- return false;
2506
+ }
2507
+ if (items.length > 0) {
2508
+ const eventId = randomUUID2();
2509
+ const row = makeRecord(state, "phase_id_backfilled", { items }, eventId);
2510
+ await appendRecord(paths, state, row);
2511
+ for (const item of items) {
2512
+ const membership = state.memberships.get(keyOf(item.trace_id, item.entry_id));
2513
+ if (membership && membership.phase_id === undefined) {
2514
+ membership.phase_id = item.phase_id;
2907
2515
  }
2908
- return index > markerIndex;
2909
2516
  }
2910
- return true;
2911
- });
2912
- if (actionable.length === 0) {
2913
- return { processed: 0, bumps: 0 };
2914
- }
2915
- const groups = new Map;
2916
- let lastProcessedTimestamp;
2917
- let lastProcessedEventId;
2918
- for (const event of actionable) {
2919
- if (typeof event.timestamp === "string" && (!lastProcessedTimestamp || event.timestamp >= lastProcessedTimestamp)) {
2920
- lastProcessedTimestamp = event.timestamp;
2921
- lastProcessedEventId = event.event_id;
2922
- }
2923
- const kid = event.knowledge_id;
2924
- if (!kid)
2925
- continue;
2926
- const group = groups.get(kid) ?? [];
2927
- group.push(event);
2928
- groups.set(kid, group);
2929
- }
2930
- const deltas = [];
2931
- for (const [id, group] of groups) {
2932
- const positives = group.filter((event) => event.type === "applied").length;
2933
- const negatives = group.length - positives;
2934
- if (positives === 0 && negatives === 0)
2935
- continue;
2936
- const delta = positives > negatives ? VERDICT_CONFIDENCE_BOOST : -VERDICT_CONFIDENCE_DECAY;
2937
- deltas.push({
2938
- id,
2939
- delta,
2940
- receipt_events: group.map((event) => ({
2941
- event_id: event.event_id,
2942
- timestamp: event.timestamp,
2943
- outcome: event.type
2944
- }))
2945
- });
2946
- }
2947
- let bumps = 0;
2948
- if (deltas.length > 0) {
2949
- const { bumpKnowledgeConfidenceBatch } = await import("./knowledge-store-bw1dk2eb.js");
2950
- bumps = await bumpKnowledgeConfidenceBatch(directory, deltas, options?.floorOptions);
2951
2517
  }
2952
2518
  return {
2953
- processed: groups.size,
2954
- bumps,
2955
- lastProcessedTimestamp,
2956
- lastProcessedEventId
2519
+ backfilled: items.length,
2520
+ skipped,
2521
+ journal_records: items.length > 0 ? 1 : 0
2957
2522
  };
2958
- } catch (err) {
2959
- warn(`[knowledge-events] applyKnowledgeVerdictFeedback failed (fail-open): ${err instanceof Error ? err.message : String(err)}`);
2960
- return { processed: 0, bumps: 0 };
2961
- }
2962
- }
2963
- var _internals4 = {
2964
- resolveKnowledgeEventsPath,
2965
- resolveKnowledgeCounterBaselinePath,
2966
- appendKnowledgeEvent,
2967
- recordKnowledgeEvent,
2968
- readKnowledgeEvents,
2969
- queryHistoricalOutcomes,
2970
- readCounterBaseline,
2971
- readLegacyApplicationRecords,
2972
- readKnowledgeCounterRollups,
2973
- readAuthoritativeKnowledgeCounterRollups,
2974
- effectiveRetrievalOutcomes,
2975
- recomputeCounters,
2976
- applyKnowledgeVerdictFeedback,
2977
- newTraceId,
2978
- newEventId,
2979
- resolveHiveEventsPath: resolveHiveEventsPath2,
2980
- appendHiveKnowledgeEvent,
2981
- recordHiveKnowledgeEvent,
2982
- readHiveKnowledgeEvents,
2983
- mergeRollupInto
2523
+ });
2524
+ }
2525
+ var _internals3 = {
2526
+ nowMs: () => Date.now(),
2527
+ writeSnapshot,
2528
+ atomicWriteFsynced,
2529
+ appendFsynced,
2530
+ commitApplicationMarkerBatch,
2531
+ maxJournalRecords: MAX_JOURNAL_RECORDS,
2532
+ maxArchiveRecords: MAX_ARCHIVE_RECORDS,
2533
+ maxArchiveBytes: MAX_ARCHIVE_BYTES,
2534
+ maxRepairQuarantineRecords: MAX_REPAIR_QUARANTINE_RECORDS
2984
2535
  };
2985
2536
 
2986
- export { commitDisplayedMembership, commitEmptyRetrieval, commitGateReleaseBatch, queryLiveMemberships, queryHistoricalOutcomes, recordPhaseCloseIntent, reconcilePhaseClose, KNOWLEDGE_EVENT_SCHEMA_VERSION, MAX_EVENT_LOG_ENTRIES, RECEIPT_EVENT_TYPES, resolveKnowledgeEventsPath, resolveKnowledgeCounterBaselinePath, resolveHiveEventsPath2 as resolveHiveEventsPath, resolveLegacyApplicationLogPath, newTraceId, newEventId, appendKnowledgeEvent, appendKnowledgeEventsBatch, recordKnowledgeEvent, recordKnowledgeEventsBatch, appendHiveKnowledgeEvent, recordHiveKnowledgeEvent, readKnowledgeEvents, readHiveKnowledgeEvents, readLegacyApplicationRecords, MAX_VIOLATION_TIMESTAMPS, recomputeCounters, countViolationsInWindow, countEmptyTraceTerminals, countEntryViolationsInWindow, countEntryContradictionsInWindow, readKnowledgeCounterRollups, readAuthoritativeKnowledgeCounterRollups, effectiveRetrievalOutcomes, applyKnowledgeVerdictFeedback, _internals4 as _internals };
2537
+ export { extractContextDecisions, extractCurrentPhase, extractCurrentPhaseFromPlan, extractPhaseIdFromLabel, commitDisplayedMembership, commitEmptyRetrieval, commitGateReleaseBatch, queryLiveMemberships, queryHistoricalOutcomes, recordPhaseCloseIntent, reconcilePhaseClose, inspectMembershipPhaseIds, backfillMembershipPhaseIds };