@kanadego/dsh-heartbeat 1.9.3 → 2.0.0

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 (57) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +103 -110
  3. package/client.js +12 -0
  4. package/config/policy.json +74 -74
  5. package/config/profile-schema.json +306 -306
  6. package/dist/{bindings-225SI7KC.js → bindings-U2M3CO2D.js} +3 -3
  7. package/dist/{chunk-TY6UP74X.js → chunk-3DNGY4DS.js} +2 -2
  8. package/dist/{chunk-CUOSICYJ.js → chunk-544QOJN5.js} +397 -23
  9. package/dist/chunk-544QOJN5.js.map +1 -0
  10. package/dist/{chunk-TRO4E6WG.js → chunk-6MVKWICX.js} +587 -139
  11. package/dist/chunk-6MVKWICX.js.map +1 -0
  12. package/dist/{chunk-WLZSABBH.js → chunk-6XM6KY7M.js} +27 -10
  13. package/dist/chunk-6XM6KY7M.js.map +1 -0
  14. package/dist/chunk-AKIJ4LS2.js +680 -0
  15. package/dist/chunk-AKIJ4LS2.js.map +1 -0
  16. package/dist/{chunk-KB5SMG3F.js → chunk-DC5HMCJC.js} +3 -3
  17. package/dist/{chunk-3MDBU6WY.js → chunk-DZ7YCFGX.js} +37 -7
  18. package/dist/chunk-DZ7YCFGX.js.map +1 -0
  19. package/dist/{chunk-WRUTATW4.js → chunk-IBBAISSW.js} +13 -2
  20. package/dist/chunk-IBBAISSW.js.map +1 -0
  21. package/dist/{chunk-XYYEJK3W.js → chunk-IFRMKVIC.js} +82 -21
  22. package/dist/chunk-IFRMKVIC.js.map +1 -0
  23. package/dist/{chunk-XFNCTOW7.js → chunk-NCPKOWS7.js} +52 -4
  24. package/dist/chunk-NCPKOWS7.js.map +1 -0
  25. package/dist/{chunk-JDH2LDFS.js → chunk-TVX4HV4Y.js} +4 -6
  26. package/dist/{chunk-JDH2LDFS.js.map → chunk-TVX4HV4Y.js.map} +1 -1
  27. package/dist/cli/index.js +149 -26
  28. package/dist/cli/index.js.map +1 -1
  29. package/dist/{inbox-P26DDMWC.js → inbox-OWBK6PE2.js} +8 -7
  30. package/dist/index.d.ts +48 -315
  31. package/dist/index.js +259 -918
  32. package/dist/index.js.map +1 -1
  33. package/dist/migrate-TQ5PB2DI.js +27 -0
  34. package/dist/{orchestrator-ZPRGVDCB.js → orchestrator-P7AEWVYR.js} +23 -12
  35. package/dist/{pool-UTXQJJ5C.js → pool-2T6TVS2L.js} +4 -5
  36. package/dist/{snapshot-K5VHETTK.js → snapshot-F5B2DD56.js} +5 -5
  37. package/package.json +84 -83
  38. package/dist/chunk-3MDBU6WY.js.map +0 -1
  39. package/dist/chunk-CUOSICYJ.js.map +0 -1
  40. package/dist/chunk-IV2ZWQA3.js +0 -56
  41. package/dist/chunk-IV2ZWQA3.js.map +0 -1
  42. package/dist/chunk-K5Y6JP2B.js +0 -399
  43. package/dist/chunk-K5Y6JP2B.js.map +0 -1
  44. package/dist/chunk-TRO4E6WG.js.map +0 -1
  45. package/dist/chunk-WLZSABBH.js.map +0 -1
  46. package/dist/chunk-WRUTATW4.js.map +0 -1
  47. package/dist/chunk-XFNCTOW7.js.map +0 -1
  48. package/dist/chunk-XYYEJK3W.js.map +0 -1
  49. package/dist/migrate-D4VKAKYT.js +0 -21
  50. /package/dist/{bindings-225SI7KC.js.map → bindings-U2M3CO2D.js.map} +0 -0
  51. /package/dist/{chunk-TY6UP74X.js.map → chunk-3DNGY4DS.js.map} +0 -0
  52. /package/dist/{chunk-KB5SMG3F.js.map → chunk-DC5HMCJC.js.map} +0 -0
  53. /package/dist/{inbox-P26DDMWC.js.map → inbox-OWBK6PE2.js.map} +0 -0
  54. /package/dist/{migrate-D4VKAKYT.js.map → migrate-TQ5PB2DI.js.map} +0 -0
  55. /package/dist/{orchestrator-ZPRGVDCB.js.map → orchestrator-P7AEWVYR.js.map} +0 -0
  56. /package/dist/{pool-UTXQJJ5C.js.map → pool-2T6TVS2L.js.map} +0 -0
  57. /package/dist/{snapshot-K5VHETTK.js.map → snapshot-F5B2DD56.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/audit-log.ts","../src/profile/store.ts","../src/profile/types.ts","../src/profile/schema.ts","../src/profile/shapes.ts"],"sourcesContent":["// Append-only JSONL audit log with age-based retention pruning.\n// Audit files are plaintext by charter (transparency), and must never contain\n// sensitive raw observations (window titles, conversation text).\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { atomicWriteFileSync } from './atomic-fs.js';\n\nexport interface AuditEvent {\n ts: string;\n [key: string]: unknown;\n}\n\n/**\n * H-15: audit is best-effort by contract — a full disk, a locked log file or an\n * unserialisable payload must never abort a beat (one caller inside a catch\n * block turning a handled failure into an unhandled one is the worst case).\n * Failures go to stderr so they stay visible instead of silently vanishing.\n */\nexport function appendAuditLine(file: string, event: Omit<AuditEvent, 'ts'> & { ts?: string }): void {\n try {\n fs.mkdirSync(path.dirname(file), { recursive: true });\n const line = JSON.stringify({ ts: event.ts ?? new Date().toISOString(), ...event });\n fs.appendFileSync(file, line + '\\n', 'utf8');\n } catch (e) {\n process.stderr.write(`[heartbeat] audit append failed: ${file}: ${String(e)}\\n`);\n }\n}\n\nexport function readAuditLines<T = AuditEvent>(file: string): T[] {\n if (!fs.existsSync(file)) return [];\n const out: T[] = [];\n const raw = fs.readFileSync(file, 'utf8');\n for (const line of raw.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n out.push(JSON.parse(trimmed) as T);\n } catch {\n // Skip corrupt lines; the log is diagnostic, not authoritative data.\n out.push({ ts: '', corrupt: true, raw: trimmed.slice(0, 200) } as unknown as T);\n }\n }\n return out;\n}\n\n/**\n * Drop entries older than maxAgeMs. Returns the number of removed lines.\n * Rewrites the file atomically; on rewrite failure the original is untouched.\n */\nexport function pruneAuditFile(file: string, maxAgeMs: number, now = Date.now()): number {\n if (!fs.existsSync(file)) return 0;\n const lines = readAuditLines(file);\n const kept = lines.filter((e) => {\n const ev = e as unknown as AuditEvent;\n const ts = Date.parse(ev.ts ?? '');\n if (!Number.isFinite(ts)) return true; // keep unparseable lines, never lose audit data silently\n return now - ts <= maxAgeMs;\n });\n const removed = lines.length - kept.length;\n if (removed === 0) return 0;\n const body = kept.map((e) => JSON.stringify(e)).join('\\n');\n atomicWriteFileSync(file, body ? body + '\\n' : '');\n return removed;\n}\n","// Profile store: materialized view + journal (the journal is the ONLY\n// authority; profile.json is a pure projection - r2 §14 verify/rebuild).\n// Every LLM-proposed op passes deterministic guards here (LLM nominates,\n// code decides - §3.3).\n\nimport path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport type { PathGuard } from '../core/path-guard.js';\nimport { loadJson, saveJson, readText, writeText } from '../vault/vault.js';\nimport type { Policy } from '../config/schema.js';\nimport {\n CONFIDENCE_CAP,\n emptyProfile,\n JOURNAL_VERSION,\n PARTITIONS,\n type ApplyReport,\n type Evidence,\n type EvidenceKind,\n type InboxItem,\n type JournalRecord,\n type Partition,\n type ProfileDoc,\n type ProfileEntry,\n type ProfileOp,\n} from './types.js';\nimport { checkAddAgainstSchema, type ProfileSchema } from './schema.js';\nimport { tryParseJournalRecord } from './shapes.js';\nimport { matchFilesRecursive } from '../core/fs-walk.js';\n\nconst DAY_MS = 86_400_000;\n\nexport function profileFilePath(dataDir: string): string {\n return path.join(dataDir, 'profile.json');\n}\n\nexport function journalFilePath(dataDir: string): string {\n return path.join(dataDir, 'profile_journal.jsonl');\n}\n\n// ── snapshot basepoint (v1.8.0, design doc §14 ③) ─────────────────────────\n// The journal grows forever; the snapshot folds its history into one DPAPI\n// document and moves the folded records into a timestamped archive shard.\n// Replay order: snapshot → archives (name order) → live journal, skipping\n// records at or before the snapshot baseline — so verify/rebuild stay correct\n// without knowing whether a snapshot exists.\n\nexport const SNAPSHOT_FILE = 'profile_snapshot.json';\nexport const ARCHIVE_PREFIX = 'profile_journal.archive-';\n\nexport interface ProfileSnapshot {\n version: 1;\n /** ts of the LAST journal record folded into `doc`. */\n baselineTs: string;\n recordsFolded: number;\n doc: ProfileDoc;\n}\n\nexport function snapshotFilePath(dataDir: string): string {\n return path.join(dataDir, SNAPSHOT_FILE);\n}\n\nfunction loadSnapshot(guard: PathGuard, dataDir: string): ProfileSnapshot | null {\n const snap = loadJson<ProfileSnapshot>(guard, snapshotFilePath(dataDir));\n if (!snap || snap.version !== 1 || typeof snap.baselineTs !== 'string' || !snap.doc?.partitions) return null;\n return snap;\n}\n\nfunction listArchiveFiles(guard: PathGuard, dataDir: string): string[] {\n try {\n return fs.readdirSync(guard.assert(dataDir))\n .filter((f) => f.startsWith(ARCHIVE_PREFIX) && f.endsWith('.jsonl'))\n .sort(); // timestamped names sort chronologically\n } catch {\n return [];\n }\n}\n\n/** Replay one JSONL text into `doc`, skipping records at/before the baseline. */\nfunction replayText(\n doc: ProfileDoc,\n text: string,\n baselineTs: string,\n stats: { records: number; truncatedTail: number; badRecords: number; isLive: boolean },\n): void {\n const lines = text.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i]!.trim();\n if (!trimmed) continue;\n // A torn tail only counts on the LIVE journal — archives are closed files.\n const tornTail = (): boolean => {\n const isLast = lines.slice(i + 1).every((l) => !l.trim());\n if (stats.isLive && isLast) {\n stats.truncatedTail = lines.length - i;\n return true;\n }\n return false;\n };\n let rec: JournalRecord | null = null;\n try {\n rec = tryParseJournalRecord(JSON.parse(trimmed));\n } catch {\n rec = null;\n }\n if (!rec) {\n if (tornTail()) break;\n // mid-file unreadable record: count it and keep going (the journal is\n // append-only/immutable, so a bad line is never rewritten).\n stats.badRecords += 1;\n continue;\n }\n // Baseline skip: only records CARRYING a ts can be proven folded. A\n // ts-less record is always applied (applyOpPermissive tolerates it).\n if (baselineTs && rec.ts && String(rec.ts) <= baselineTs) continue;\n try {\n if (rec.v === JOURNAL_VERSION && rec.entries) {\n // v2 (③A): the record carries each touched entry's FULL final state,\n // so replay is an upsert; live and replay share one state machine (HB-09).\n for (const entry of rec.entries) upsertEntry(doc, entry);\n } else {\n for (const op of rec.applied ?? []) applyOpPermissive(doc, op, rec.ts);\n }\n stats.records += 1;\n } catch {\n stats.badRecords += 1;\n }\n }\n}\n\nfunction bucketFor(doc: ProfileDoc, partition: Partition): { entries: ProfileEntry[] } {\n let bucket = doc.partitions[partition];\n if (!bucket) {\n bucket = { entries: [] };\n doc.partitions[partition] = bucket;\n }\n return bucket;\n}\n\n/** Journal v2 replay: `entry` is the entry's final state, so replay is an\n * upsert by id (position preserved for updates, appended for new entries). */\nfunction upsertEntry(doc: ProfileDoc, entry: ProfileEntry): void {\n const next = structuredClone(entry);\n for (const p of PARTITIONS) {\n const list = doc.partitions[p]?.entries;\n if (!list) continue;\n const at = list.findIndex((e) => e.id === next.id);\n if (at < 0) continue;\n if (p === next.partition) {\n list[at] = next;\n } else {\n list.splice(at, 1);\n bucketFor(doc, next.partition).entries.push(next);\n }\n return;\n }\n bucketFor(doc, next.partition).entries.push(next);\n}\n\n/** Full replay: snapshot basepoint + archive shards + live journal. */\nexport function replayJournal(guard: PathGuard, dataDir: string): ReplayResult {\n const snap = loadSnapshot(guard, dataDir);\n const doc = snap ? snap.doc : emptyProfile();\n const baselineTs = snap?.baselineTs ?? '';\n const stats = { records: snap?.recordsFolded ?? 0, truncatedTail: 0, badRecords: 0, isLive: false };\n for (const file of listArchiveFiles(guard, dataDir)) {\n try {\n // shard record counts are not reported (the snapshot already folded\n // them); only the live journal's torn tail is meaningful.\n replayText(doc, fs.readFileSync(path.join(dataDir, file), 'utf8'), baselineTs, { records: 0, truncatedTail: 0, badRecords: 0, isLive: false });\n } catch { /* unreadable shard: skip */ }\n }\n stats.isLive = true;\n replayText(doc, readText(guard, journalFilePath(dataDir), ''), baselineTs, stats);\n return { doc, truncatedTail: stats.truncatedTail, records: stats.records, badRecords: stats.badRecords };\n}\n\n/** Every plaintext journal text in chronological order: archive shards first,\n * then the live journal — the RAW record timeline, for callers that need the\n * history itself rather than the accumulated doc (the weekly report counts\n * the week's ADD ops). A rotation must not hide history from them (H-01). */\nexport function readJournalTexts(guard: PathGuard, dataDir: string): string[] {\n const texts: string[] = [];\n for (const file of listArchiveFiles(guard, dataDir)) {\n try {\n texts.push(fs.readFileSync(path.join(dataDir, file), 'utf8'));\n } catch { /* unreadable shard: skip */ }\n }\n texts.push(readText(guard, journalFilePath(dataDir), ''));\n return texts;\n}\n\nexport function loadProfile(guard: PathGuard, file: string): ProfileDoc {\n const doc = loadJson<ProfileDoc>(guard, file);\n if (!doc || !doc.partitions) return emptyProfile();\n // ensure all partitions exist\n for (const p of PARTITIONS) {\n if (!doc.partitions[p]) doc.partitions[p] = { entries: [] };\n }\n return doc;\n}\n\nfunction parseIso(v: string): number {\n const t = Date.parse(v);\n return Number.isFinite(t) ? t : 0;\n}\n\n/** ref format \"<datafile>#<locator>\": the referenced file must exist under data/. */\nfunction refExists(guard: PathGuard, dataDir: string, ref: string): boolean {\n const base = ref.split('#')[0] ?? '';\n if (!base) return false;\n const target = path.join(dataDir, base);\n try {\n return fs.existsSync(guard.assert(target));\n } catch {\n return false;\n }\n}\n\nfunction capForKinds(kinds: EvidenceKind[]): number {\n if (kinds.length === 0) return 0.4;\n return Math.min(...kinds.map((k) => CONFIDENCE_CAP[k] ?? 0.4));\n}\n\nfunction findActive(doc: ProfileDoc, id: string): ProfileEntry | undefined {\n for (const p of PARTITIONS) {\n const hit = doc.partitions[p]!.entries.find((e) => e.id === id && e.validTo === null);\n if (hit) return hit;\n }\n return undefined;\n}\n\n/**\n * Apply validated ops to the doc (mutates). Returns applied/rejected.\n * Guards (§3.3): whitelist, evidence gate, per-run ops cap is enforced by the\n * caller, confidence caps by evidence kind, psy gating, INVALIDATE ownership:\n * volatile expiry is code-driven (LLM may not), stable invalidation needs a\n * contradicting observation attached.\n */\nexport function applyOpsToDoc(\n guard: PathGuard,\n dataDir: string,\n doc: ProfileDoc,\n ops: ProfileOp[],\n schema: ProfileSchema | undefined,\n policy: Policy,\n now: number,\n): ApplyReport {\n const applied: ProfileOp[] = [];\n const rejected: { op: ProfileOp; reason: string }[] = [];\n // Journal v2 events: one FULL snapshot per touched entry (HB-09).\n const entries: ProfileEntry[] = [];\n const nowIso = new Date(now).toISOString();\n\n for (const op of ops) {\n if (op.op === 'NOOP') {\n applied.push(op);\n continue;\n }\n if (op.op === 'ADD') {\n if (op.partition === 'psy' && !policy.profile.psyEnabled) {\n rejected.push({ op, reason: 'psy partition is disabled' });\n continue;\n }\n let temporal: 'stable' | 'volatile' = 'stable';\n if (schema) {\n const check = checkAddAgainstSchema(schema, op.partition, op.topic, op.subTopic, op.temporal);\n if (!check.ok) {\n rejected.push({ op, reason: check.reason! });\n continue;\n }\n temporal = check.temporal;\n } else if (!(op.partition in doc.partitions)) {\n // H-17: no usable schema — the partition set is the only boundary left.\n rejected.push({ op, reason: `unknown partition: ${op.partition}` });\n continue;\n } else {\n temporal = op.temporal === 'volatile' ? 'volatile' : 'stable';\n }\n if (!op.evidence || op.evidence.length === 0) {\n rejected.push({ op, reason: 'ADD without evidence (no provenance, axiom 1)' });\n continue;\n }\n const badRef = op.evidence.find((e) => !refExists(guard, dataDir, e.ref));\n if (badRef) {\n rejected.push({ op, reason: `evidence ref does not resolve: ${badRef.ref}` });\n continue;\n }\n const cap = capForKinds(op.evidence.map((e) => e.kind));\n const active = doc.partitions[op.partition]!.entries.filter((e) => e.validTo === null);\n if (active.length >= policy.profile.partitionCap) {\n rejected.push({ op, reason: `partition ${op.partition} at cap (${policy.profile.partitionCap}); converge first` });\n continue;\n }\n dbSeq += 1;\n const entry: ProfileEntry = {\n id: `p${dbSeq.toString(36)}${randomUUID().slice(0, 4)}`,\n partition: op.partition,\n topic: op.topic,\n subTopic: op.subTopic,\n content: op.content.trim(),\n confidence: Math.min(op.confidence ?? cap, cap),\n temporal,\n validFrom: nowIso,\n validTo: null,\n supersededBy: null,\n evidence: op.evidence,\n createdAt: nowIso,\n updatedAt: nowIso,\n updateCount: 0,\n };\n op.assignedId = entry.id; // journal replay must reproduce this id\n doc.partitions[op.partition]!.entries.push(entry);\n entries.push(structuredClone(entry));\n applied.push(op);\n continue;\n }\n if (op.op === 'UPDATE') {\n const entry = findActive(doc, op.id);\n if (!entry) {\n rejected.push({ op, reason: `unknown or inactive entry: ${op.id}` });\n continue;\n }\n // HB-04 (2026-10-17): validate BEFORE mutating. The old order wrote\n // `content` first and then bailed out on the confidence rule, so an\n // UPDATE that was reported as REJECTED had already changed the text.\n let nextConfidence: number | null = null;\n if (op.changes.confidence !== undefined) {\n const cap = capForKinds(entry.evidence.map((e) => e.kind));\n // confidence upgrades need a second confirming observation (§3.3):\n // only allowed up to cap, and only when the entry already has 2+ evidence\n if (op.changes.confidence > entry.confidence && entry.evidence.length < 2) {\n rejected.push({ op, reason: 'confidence upgrade requires a second confirming observation' });\n continue;\n }\n nextConfidence = Math.min(op.changes.confidence, cap);\n }\n if (op.changes.content !== undefined) entry.content = op.changes.content.trim();\n if (nextConfidence !== null) entry.confidence = nextConfidence;\n entry.updatedAt = nowIso;\n entry.updateCount += 1;\n entries.push(structuredClone(entry));\n applied.push(op);\n continue;\n }\n if (op.op === 'INVALIDATE') {\n const entry = findActive(doc, op.id);\n if (!entry) {\n rejected.push({ op, reason: `unknown or inactive entry: ${op.id}` });\n continue;\n }\n if (entry.temporal === 'volatile') {\n rejected.push({ op, reason: 'volatile expiry is code-owned (time-driven), not LLM-nominated' });\n continue;\n }\n // stable: rebuttal-driven; requires a contradicting observation attached\n const hasNewObservation = (op.evidence ?? []).length > 0\n && (op.evidence ?? []).some((e) => parseIso(e.at) > parseIso(entry.evidence[entry.evidence.length - 1]?.at ?? ''));\n if (!hasNewObservation) {\n rejected.push({ op, reason: 'stable INVALIDATE requires a newer contradicting observation' });\n continue;\n }\n entry.validTo = nowIso;\n entry.supersededBy = null;\n entry.updatedAt = nowIso;\n entry.updateCount += 1;\n if (op.evidence) entry.evidence.push(...op.evidence);\n entries.push(structuredClone(entry));\n applied.push(op);\n continue;\n }\n }\n return { applied, rejected, entries };\n}\n\nlet dbSeq = 0;\n\n/** Deterministic aging (D9): volatile expiry + stable low-activity marking. */\nexport function runDeterministicAging(\n doc: ProfileDoc,\n policy: Policy,\n now: number,\n): { volatileExpired: number; lowActivityMarked: number; entries: ProfileEntry[] } {\n const nowIso = new Date(now).toISOString();\n const entries: ProfileEntry[] = [];\n let volatileExpired = 0;\n let lowActivityMarked = 0;\n for (const p of PARTITIONS) {\n for (const e of doc.partitions[p]!.entries) {\n if (e.validTo !== null) continue;\n const lastEvidence = Math.max(...e.evidence.map((x) => parseIso(x.at)), parseIso(e.updatedAt));\n if (e.temporal === 'volatile') {\n if (now - lastEvidence > policy.profile.volatileDays * DAY_MS) {\n e.validTo = nowIso;\n e.updatedAt = nowIso;\n e.updateCount += 1;\n volatileExpired += 1;\n entries.push(structuredClone(e));\n }\n } else if (!e.lowActivity && now - lastEvidence > policy.profile.stableLowActivityDays * DAY_MS) {\n e.lowActivity = true;\n lowActivityMarked += 1;\n entries.push(structuredClone(e));\n }\n }\n }\n return { volatileExpired, lowActivityMarked, entries };\n}\n\n/** Persist the materialized view atomically + append the journal record.\n * A record carrying `entries` (every touched entry's final state) is written\n * as v2 so replay is an upsert; a record without them stays v1 and replays\n * permissively, so old journals keep working unchanged. */\nexport function persistWithJournal(\n guard: PathGuard,\n dataDir: string,\n doc: ProfileDoc,\n record: Omit<JournalRecord, 'ts'>,\n): void {\n saveJson(guard, profileFilePath(dataDir), doc);\n const v = record.entries === undefined ? undefined : JOURNAL_VERSION;\n const line = JSON.stringify({ ts: new Date().toISOString(), ...record, v });\n const journal = journalFilePath(dataDir);\n try {\n fs.appendFileSync(guard.assert(journal), line + '\\n', 'utf8');\n } catch {\n fs.mkdirSync(dataDir, { recursive: true });\n fs.appendFileSync(guard.assert(journal), line + '\\n', 'utf8');\n }\n}\n\n// ── journal replay (verify / rebuild, r2 §14) ───────────────────────────\n\nfunction applyOpPermissive(doc: ProfileDoc, op: ProfileOp, ts: string): void {\n // Journal is trusted history: replay applies without revalidation.\n if (op.op === 'ADD') {\n dbSeq += 1;\n doc.partitions[op.partition]!.entries.push({\n id: op.assignedId ?? `r${dbSeq.toString(36)}${randomUUID().slice(0, 4)}`,\n partition: op.partition,\n topic: op.topic,\n subTopic: op.subTopic,\n content: op.content,\n confidence: op.confidence ?? 0.5,\n temporal: op.temporal ?? 'stable',\n validFrom: ts,\n validTo: null,\n supersededBy: null,\n evidence: op.evidence,\n createdAt: ts,\n updatedAt: ts,\n updateCount: 0,\n });\n return;\n }\n if (op.op === 'UPDATE') {\n const e = [...PARTITIONS].flatMap((p) => doc.partitions[p]!.entries).find((x) => x.id === op.id);\n if (e) {\n if (op.changes.content !== undefined) e.content = op.changes.content;\n if (op.changes.confidence !== undefined) e.confidence = op.changes.confidence;\n e.updatedAt = ts;\n e.updateCount += 1;\n }\n return;\n }\n if (op.op === 'INVALIDATE') {\n const e = [...PARTITIONS].flatMap((p) => doc.partitions[p]!.entries).find((x) => x.id === op.id);\n if (e) {\n e.validTo = ts;\n e.updatedAt = ts;\n e.updateCount += 1;\n }\n }\n // NOOP: nothing\n}\n\nexport interface ReplayResult {\n doc: ProfileDoc;\n truncatedTail: number;\n records: number;\n /** Journal lines that neither parsed nor replayed (counted, never fatal). */\n badRecords?: number;\n}\n\nexport interface VerifyReport {\n ok: boolean;\n firstDivergence?: { id: string; expected: string; actual: string };\n truncatedTail: number;\n records: number;\n}\n\n/** profile verify: replay vs disk, report first divergence, never fix. */\nexport function verifyProfile(guard: PathGuard, dataDir: string): VerifyReport {\n const replayed = replayJournal(guard, dataDir);\n const onDisk = loadProfile(guard, profileFilePath(dataDir));\n // Timestamps legitimately differ (journal record ts >= op ts); identity\n // fields are also normalized. Compare semantic content only.\n const strip = (doc: ProfileDoc): string =>\n JSON.stringify(doc.partitions, (k, v) => (['id', 'supersededBy', 'validFrom', 'createdAt', 'updatedAt', 'retiredAt'].includes(k) ? '<norm>' : v));\n const ok = strip(replayed.doc) === strip(onDisk);\n if (ok) return { ok: true, truncatedTail: replayed.truncatedTail, records: replayed.records };\n // first divergence: first entry id present in only one view\n const diskIds = new Set([...PARTITIONS].flatMap((p) => onDisk.partitions[p]!.entries.map((e) => e.content))); const replayIds = new Set([...PARTITIONS].flatMap((p) => replayed.doc.partitions[p]!.entries.map((e) => e.content)));\n const onlyDisk = [...diskIds].find((c) => !replayIds.has(c));\n const onlyReplay = [...replayIds].find((c) => !diskIds.has(c));\n return {\n ok: false,\n firstDivergence: {\n id: onlyDisk ?? onlyReplay ?? '(content)',\n expected: onlyReplay ? 'absent in journal replay' : 'present in journal replay',\n actual: onlyDisk ? 'present on disk' : 'absent on disk',\n },\n truncatedTail: replayed.truncatedTail,\n records: replayed.records,\n };\n}\n\nexport interface RebuildReport {\n ok: boolean;\n truncatedTail: number;\n records: number;\n wrote: boolean;\n}\n\n/** profile rebuild: journal is authoritative; atomic replace; torn tail reported. */\nexport function rebuildProfile(\n guard: PathGuard,\n dataDir: string,\n opts: { check?: boolean } = {},\n): RebuildReport & { diffSummary?: string } {\n const replayed = replayJournal(guard, dataDir);\n const target = profileFilePath(dataDir);\n if (opts.check) {\n const onDisk = loadProfile(guard, target);\n const same = JSON.stringify(onDisk) === JSON.stringify(replayed.doc);\n return {\n ok: same,\n truncatedTail: replayed.truncatedTail,\n records: replayed.records,\n wrote: false,\n diffSummary: same ? 'no diff' : 'materialized view differs from journal replay',\n };\n }\n saveJson(guard, target, replayed.doc);\n if (replayed.truncatedTail > 0) {\n // explicit audit: never silently rebuild a view that lost its tail\n writeText(\n guard,\n path.join(dataDir, 'logs', 'rebuild-report.txt'),\n `rebuild truncated ${replayed.truncatedTail} torn line(s) at journal tail; ${replayed.records} records applied\\n`,\n );\n }\n return { ok: true, truncatedTail: replayed.truncatedTail, records: replayed.records, wrote: true };\n}\n\n// ── wipe (HB-21, 2026-10-17) ───────────────────────────────────────────────\n// `profile wipe` used to delete three files: the materialized view, the inbox\n// and the live journal. The journal is the authority, and its history lives on\n// in profile_snapshot.json plus the archive shards — so a rebuild after a wipe\n// replayed the whole memory back, and a user who asked to forget got the\n// profile regrown instead. Migration backups (HB-07) and crash leftovers carry\n// copies of the same data.\n//\n// Wipe therefore removes every file the profile can be rebuilt from, and only\n// that: settings, seeds, weekly reports and audit logs are not profile data and\n// stay (burn is the tool for a full shred). Shredding remains burn's job — wipe\n// is a delete, not a destroy.\n\nconst WIPE_FILES = ['profile.json', 'profile_inbox.jsonl', 'profile_journal.jsonl', SNAPSHOT_FILE];\nconst WIPE_PATTERNS: RegExp[] = [\n /^profile_journal\\.archive-/,\n /\\.bak-migrate-\\d{14}$/,\n /\\.incoming-\\d{14}$/,\n];\n\n/** Delete every file the profile can be rebuilt from; returns what was removed\n * (relative to dataDir, sorted per family). */\nexport function wipeProfile(guard: PathGuard, dataDir: string): string[] {\n const removed: string[] = [];\n for (const f of WIPE_FILES) {\n const abs = guard.assert(path.join(dataDir, f));\n if (fs.existsSync(abs)) {\n fs.rmSync(abs, { force: true });\n removed.push(f);\n }\n }\n for (const re of WIPE_PATTERNS) {\n let rels: string[] = [];\n try {\n rels = matchFilesRecursive(guard.assert(dataDir), re);\n } catch {\n rels = [];\n }\n for (const rel of rels) {\n try {\n fs.rmSync(guard.assert(path.join(dataDir, rel)), { force: true });\n removed.push(rel);\n } catch {\n /* already gone */\n }\n }\n }\n return removed;\n}\n","// User profile types (design doc §3). Fourth store: warm, structured,\n// slow-evolving model of the user. Not the material pool (hot cache), not\n// DSH long-term memory (conversation-validated layer).\n\nexport type Partition = 'interest' | 'projects' | 'comm' | 'psy';\nexport type Temporal = 'volatile' | 'stable';\nexport type EvidenceKind = 'chat' | 'screen' | 'browse' | 'hand' | 'ledger';\n\nexport interface Evidence {\n kind: EvidenceKind;\n at: string;\n /** Pointer to an existing audit/log location, e.g. \"heartbeat.jsonl#2026-09-06T12:00:00Z\". */\n ref: string;\n /** At most ONE short quote (<=1 sentence). Never raw conversation/screen text. */\n quote?: string;\n}\n\nexport interface ProfileEntry {\n id: string;\n partition: Partition;\n topic: string;\n subTopic: string;\n content: string;\n /** 0..1; capped per source kind (chat .6 / screen .4 / browse .4). */\n confidence: number;\n temporal: Temporal;\n validFrom: string;\n validTo: string | null;\n supersededBy: string | null;\n evidence: Evidence[];\n createdAt: string;\n updatedAt: string;\n updateCount: number;\n /** stable-tier audit flag (180d without observation): digest deprioritizes. */\n lowActivity?: boolean;\n}\n\nexport interface ProfileDoc {\n version: number;\n partitions: Record<Partition, { entries: ProfileEntry[] }>;\n}\n\nexport interface InboxItem {\n id?: string;\n kind: EvidenceKind;\n at: string;\n ref: string;\n /** <= 1 short sentence; never raw conversation/screen text (truncated by writer). */\n note: string;\n}\n\nexport type ProfileOp =\n | {\n op: 'ADD';\n partition: Partition;\n topic: string;\n subTopic: string;\n content: string;\n temporal?: Temporal;\n confidence?: number;\n why: string;\n evidence: Evidence[];\n /** Assigned by the store at apply time so journal replay preserves ids. */\n assignedId?: string;\n }\n | { op: 'UPDATE'; id: string; changes: { content?: string; confidence?: number }; why: string }\n | { op: 'INVALIDATE'; id: string; why: string; evidence?: Evidence[] }\n | { op: 'NOOP'; why: string };\n\n/**\n * Journal line schema version. Absent = v1: replay applies the applied ops\n * permissively. v2 adds entries — the canonical, code-written post-run entry\n * states (aging included) — and replay upserts those verbatim. That is what\n * makes the live write path and replay ONE state machine (review ③A / HB-09).\n */\nexport const JOURNAL_VERSION = 2;\n\nexport interface JournalRecord {\n v?: number;\n ts: string;\n runId: string;\n /** The model's original intent: audit mirror + the v1 replay path. */\n applied: ProfileOp[];\n rejected: { op: unknown; reason: string }[];\n /** v2 replay path: one full entry snapshot per entry this run touched.\n * Written by code; the model can never reach this field. */\n entries?: ProfileEntry[];\n}\n\nexport interface ApplyReport {\n applied: ProfileOp[];\n rejected: { op: unknown; reason: string }[];\n /** v2 journal events: the full post-state of every entry this run touched. */\n entries?: ProfileEntry[];\n}\n\nexport const PARTITIONS: readonly Partition[] = ['interest', 'projects', 'comm', 'psy'];\n\nexport const CONFIDENCE_CAP: Record<EvidenceKind, number> = {\n chat: 0.6,\n screen: 0.4,\n browse: 0.4,\n hand: 1.0,\n ledger: 0.6,\n};\n\nexport function emptyProfile(): ProfileDoc {\n return {\n version: 1,\n partitions: { interest: { entries: [] }, projects: { entries: [] }, comm: { entries: [] }, psy: { entries: [] } },\n };\n}\n","// profile-schema.json loading + ADD validation (r4 B10: temporal tier is an\n// ENTRY-level attribute; the schema declares, per sub_topic, the ALLOWED tier\n// set and the DEFAULT. Unlisted defaults to 'stable'.)\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { Partition, Temporal } from './types.js';\n\nexport interface SubTopicDecl {\n allowed?: Temporal[];\n default?: Temporal;\n}\n\nexport interface ProfileSchema {\n version: number;\n partitions: Partial<Record<Partition, {\n topics: Record<string, { subtopics: Record<string, SubTopicDecl> }>;\n }>>;\n}\n\nexport interface SchemaLoad {\n /** The schema to use, or undefined when even the factory copy is unusable. */\n schema?: ProfileSchema;\n /** Where the returned schema came from. */\n source: 'user' | 'factory' | 'none';\n /** Set when the chosen schema is not the first choice (H-17 fallback). */\n fallbackReason?: string;\n}\n\n/**\n * H-17: three-tier load. This file is user-editable by design, so a broken\n * comma used to throw on every beat — `runConsolidation` aborted before\n * `inboxClear`, the inbox grew forever and the profile froze with no way back.\n * Now: a bad user copy falls back to the factory copy (audited by the caller);\n * an unusable factory copy yields `undefined`, which callers read as \"no\n * whitelist\" instead of a fatal error.\n */\nexport function loadProfileSchema(paths: { configDir: string; settingsDir: string }): SchemaLoad {\n const userPath = path.join(paths.settingsDir, 'profile-schema.json');\n const factoryPath = path.join(paths.configDir, 'profile-schema.json');\n const read = (file: string): { schema?: ProfileSchema; error: string } => {\n try {\n const raw = JSON.parse(fs.readFileSync(file, 'utf8')) as ProfileSchema;\n if (!raw.partitions) return { error: 'partitions missing' };\n return { schema: raw, error: '' };\n } catch (e) {\n return { error: String(e) };\n }\n };\n const user = fs.existsSync(userPath) ? read(userPath) : null;\n if (user?.schema) return { schema: user.schema, source: 'user' };\n const factory = read(factoryPath);\n if (factory.schema) {\n return user\n ? {\n schema: factory.schema,\n source: 'factory',\n fallbackReason: `user profile-schema.json unusable (${user.error}) — fell back to the factory copy`,\n }\n : { schema: factory.schema, source: 'factory' };\n }\n return {\n source: 'none',\n fallbackReason: `no usable profile-schema.json (user: ${user?.error ?? 'absent'}; factory: ${factory.error})`,\n };\n}\n\nexport interface SchemaCheck {\n ok: boolean;\n reason?: string;\n temporal: Temporal;\n}\n\n/**\n * Validate an ADD against the whitelist and resolve the entry's temporal tier:\n * LLM nominates within the sub_topic's allowed set; missing nomination falls\n * back to the declared default; fully unlisted -> reject (charter boundary).\n */\nexport function checkAddAgainstSchema(\n schema: ProfileSchema,\n partition: Partition,\n topic: string,\n subTopic: string,\n nominated?: Temporal,\n): SchemaCheck {\n const p = schema.partitions[partition];\n if (!p) return { ok: false, reason: `partition not in schema: ${partition}`, temporal: 'stable' };\n const t = p.topics[topic];\n if (!t) return { ok: false, reason: `topic not in schema: ${partition}/${topic}`, temporal: 'stable' };\n const st = t.subtopics[subTopic];\n if (!st) return { ok: false, reason: `sub_topic not in schema: ${partition}/${topic}/${subTopic}`, temporal: 'stable' };\n const allowed: Temporal[] = st.allowed && st.allowed.length > 0 ? st.allowed : ['stable'];\n const def: Temporal = st.default && allowed.includes(st.default) ? st.default : allowed[0]!;\n if (!nominated) return { ok: true, temporal: def };\n if (!allowed.includes(nominated)) {\n return {\n ok: false,\n reason: `temporal \"${nominated}\" not allowed for ${partition}/${topic}/${subTopic} (allowed: ${allowed.join('|')})`,\n temporal: def,\n };\n }\n return { ok: true, temporal: nominated };\n}\n","// Foreign-shape boundaries (review 2026-10-17 ⑧A). Every place that accepts\n// data this code did not just build itself — the model's op array, journal\n// lines, inbox lines, migration packages, RPC payloads — is checked against\n// ONE schemastery definition here, instead of poking at properties ad hoc at\n// each call site (HB-12: a malformed op used to reach the guards and throw\n// somewhere in the middle of apply).\n//\n// schemastery objects are permissive on purpose: an absent field is simply\n// absent (no error) and unknown keys ride through. Profile boundaries need the\n// opposite, so closed() adds the two rules schemastery leaves out — required\n// keys and a closed key set — and check() applies them before field types run.\n\nimport z from '@deepseek-ai/schemastery';\nimport {\n JOURNAL_VERSION,\n PARTITIONS,\n type Evidence,\n type EvidenceKind,\n type InboxItem,\n type JournalRecord,\n type Partition,\n type ProfileEntry,\n type ProfileOp,\n type Temporal,\n} from './types.js';\n\nexport class ShapeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ShapeError';\n }\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\nfunction describe(v: unknown): string {\n if (v === null) return 'null';\n if (Array.isArray(v)) return 'an array';\n return typeof v;\n}\n\n/** A required key. A nullable one accepts `null` as a real value (validTo /\n * supersededBy) instead of reading it as absent. */\ntype Req = string | { key: string; nullable: true };\n\ninterface Closed {\n schema: Schemastery<any, any>;\n keys: readonly string[];\n required: readonly Req[];\n}\n\nfunction closed(\n schema: Schemastery<any, any>,\n keys: readonly string[],\n required: readonly Req[] = keys,\n): Closed {\n return { schema, keys, required };\n}\n\n/** object-ness -> required keys -> closed key set -> schemastery field types. */\nfunction check(shape: Closed, value: unknown, label: string): Record<string, unknown> {\n if (!isPlainObject(value)) throw new ShapeError(`${label}: expected an object, got ${describe(value)}`);\n for (const req of shape.required) {\n const key = typeof req === 'string' ? req : req.key;\n const nullable = typeof req !== 'string' && req.nullable;\n if (value[key] === undefined || (value[key] === null && !nullable)) {\n throw new ShapeError(`${label}.${key}: missing required value`);\n }\n }\n for (const k of Object.keys(value)) {\n if (!shape.keys.includes(k)) throw new ShapeError(`${label}.${k}: unknown field`);\n }\n try {\n return shape.schema(value) as Record<string, unknown>;\n } catch (e) {\n throw new ShapeError(`${label}: ${e instanceof Error ? e.message : String(e)}`);\n }\n}\n\nconst Str = z.string().required();\nconst Num = z.number().required();\n// No .required() on this one: schemastery reads null as \"absent\", but null is\n// a real value for validTo / supersededBy. check() enforces presence instead.\nconst NullableStr = z.union([z.string(), z.const(null)]);\nconst PartitionEnum = z.union(PARTITIONS.map((p) => z.const(p))).required();\nconst TemporalEnum = z.union([z.const('stable'), z.const('volatile')]).required();\n/** Same set, optional: the model may omit temporal and take the schema default. */\nconst OptionalTemporal = z.union([z.const('stable'), z.const('volatile')]);\nconst KindEnum = z.union([\n z.const('chat'),\n z.const('screen'),\n z.const('browse'),\n z.const('hand'),\n z.const('ledger'),\n]).required();\nconst ConfidenceNum = z.number().min(0).max(1).required();\n\n// ── evidence ────────────────────────────────────────────────────────────────\n\nconst EvidenceShape = closed(\n z.object({ kind: KindEnum, at: Str, ref: Str, quote: z.string() }),\n ['kind', 'at', 'ref', 'quote'],\n ['kind', 'at', 'ref'],\n);\n\nexport function parseEvidence(value: unknown, label = 'evidence'): Evidence {\n const o = check(EvidenceShape, value, label);\n return {\n kind: o.kind as EvidenceKind,\n at: String(o.at),\n ref: String(o.ref),\n ...(o.quote === undefined ? {} : { quote: String(o.quote) }),\n };\n}\n\nfunction parseEvidenceList(value: unknown, label: string): Evidence[] {\n if (!Array.isArray(value)) throw new ShapeError(`${label}: expected an array`);\n return value.map((v, i) => parseEvidence(v, `${label}[${i}]`));\n}\n\n// ── stored entry (journal v2 / migration packages) ──────────────────────────\n\nconst EntryShape = closed(\n z.object({\n id: Str,\n partition: PartitionEnum,\n topic: Str,\n subTopic: Str,\n content: Str,\n confidence: ConfidenceNum,\n temporal: TemporalEnum,\n validFrom: Str,\n validTo: NullableStr,\n supersededBy: NullableStr,\n evidence: z.array(z.any()).required(),\n createdAt: Str,\n updatedAt: Str,\n updateCount: Num,\n lowActivity: z.boolean(),\n }),\n ['id', 'partition', 'topic', 'subTopic', 'content', 'confidence', 'temporal', 'validFrom', 'validTo',\n 'supersededBy', 'evidence', 'createdAt', 'updatedAt', 'updateCount', 'lowActivity'],\n ['id', 'partition', 'topic', 'subTopic', 'content', 'confidence', 'temporal', 'validFrom',\n { key: 'validTo', nullable: true }, { key: 'supersededBy', nullable: true },\n 'evidence', 'createdAt', 'updatedAt', 'updateCount'],\n);\n\nexport function parseProfileEntry(value: unknown, label = 'entry'): ProfileEntry {\n const o = check(EntryShape, value, label);\n return {\n id: String(o.id),\n partition: o.partition as Partition,\n topic: String(o.topic),\n subTopic: String(o.subTopic),\n content: String(o.content),\n confidence: Number(o.confidence),\n temporal: o.temporal as Temporal,\n validFrom: String(o.validFrom),\n validTo: o.validTo === null ? null : String(o.validTo),\n supersededBy: o.supersededBy === null ? null : String(o.supersededBy),\n evidence: parseEvidenceList(o.evidence, `${label}.evidence`),\n createdAt: String(o.createdAt),\n updatedAt: String(o.updatedAt),\n updateCount: Number(o.updateCount),\n ...(o.lowActivity === undefined ? {} : { lowActivity: Boolean(o.lowActivity) }),\n };\n}\n\n// ── inbox line ──────────────────────────────────────────────────────────────\n\nconst InboxShape = closed(\n z.object({ id: z.string(), kind: KindEnum, at: Str, ref: Str, note: z.string() }),\n ['id', 'kind', 'at', 'ref', 'note'],\n ['kind', 'at', 'ref'],\n);\n\nexport function parseInboxItem(value: unknown, label = 'inbox item'): InboxItem {\n const o = check(InboxShape, value, label);\n return {\n ...(o.id === undefined ? {} : { id: String(o.id) }),\n kind: o.kind as EvidenceKind,\n at: String(o.at),\n ref: String(o.ref),\n note: o.note === undefined ? '' : String(o.note),\n };\n}\n\n// ── the model's op array (③A: ids in, evidence out) ─────────────────────────\n//\n// The model never supplies refs, timestamps or evidence kinds any more — it\n// cites observation ids from THIS batch (o1, o2, …) and the caller turns them\n// into Evidence objects. HB-05's forged provenance (a made-up \"hand\" ref used\n// to pin confidence at 1.0) is unreachable by construction.\n\nexport type ProposedOp =\n | {\n op: 'ADD';\n partition: Partition;\n topic: string;\n subTopic: string;\n content: string;\n temporal?: Temporal;\n confidence?: number;\n why: string;\n evidenceRefs: string[];\n }\n | { op: 'UPDATE'; id: string; changes: { content?: string; confidence?: number }; why: string }\n | { op: 'INVALIDATE'; id: string; why: string; evidenceRefs: string[] }\n | { op: 'NOOP'; why: string };\n\nconst AddShape = closed(\n z.object({\n op: z.const('ADD').required(),\n partition: PartitionEnum,\n topic: Str,\n subTopic: Str,\n content: Str,\n temporal: OptionalTemporal,\n confidence: z.number().min(0).max(1),\n why: z.string(),\n evidence: z.array(z.any()).required(),\n }),\n ['op', 'partition', 'topic', 'subTopic', 'content', 'temporal', 'confidence', 'why', 'evidence'],\n ['op', 'partition', 'topic', 'subTopic', 'content', 'evidence'],\n);\n\nconst UpdateShape = closed(\n z.object({\n op: z.const('UPDATE').required(),\n id: Str,\n changes: z.object({ content: z.string(), confidence: z.number().min(0).max(1) }),\n why: z.string(),\n }),\n ['op', 'id', 'changes', 'why'],\n ['op', 'id', 'changes'],\n);\n\nconst InvalidateShape = closed(\n z.object({\n op: z.const('INVALIDATE').required(),\n id: Str,\n why: z.string(),\n evidence: z.array(z.any()),\n }),\n ['op', 'id', 'why', 'evidence'],\n ['op', 'id'],\n);\n\nconst NoopShape = closed(\n z.object({ op: z.const('NOOP').required(), why: z.string() }),\n ['op', 'why'],\n ['op'],\n);\n\nfunction parseObservationRefs(value: unknown, label: string): string[] {\n if (value === undefined) return [];\n if (!Array.isArray(value)) throw new ShapeError(`${label}: expected an array of observation ids`);\n return value.map((v, i) => {\n if (typeof v !== 'string' || !v.trim()) {\n throw new ShapeError(`${label}[${i}]: expected an observation id like \"o1\" (refs, timestamps and kinds are code-generated)`);\n }\n return v.trim();\n });\n}\n\nfunction parseProposedOp(raw: unknown, label: string): ProposedOp {\n if (!isPlainObject(raw)) throw new ShapeError(`${label}: expected an object, got ${describe(raw)}`);\n const tag = raw.op;\n if (tag === 'ADD') {\n const o = check(AddShape, raw, label);\n const evidenceRefs = parseObservationRefs(o.evidence, `${label}.evidence`);\n if (evidenceRefs.length === 0) {\n throw new ShapeError(`${label}.evidence: ADD needs at least one observation id (axiom 1: no provenance, no memory)`);\n }\n return {\n op: 'ADD',\n partition: o.partition as Partition,\n topic: String(o.topic),\n subTopic: String(o.subTopic),\n content: String(o.content),\n ...(o.temporal === undefined ? {} : { temporal: o.temporal as Temporal }),\n ...(o.confidence === undefined ? {} : { confidence: Number(o.confidence) }),\n why: typeof o.why === 'string' ? o.why : '',\n evidenceRefs,\n };\n }\n if (tag === 'UPDATE') {\n const o = check(UpdateShape, raw, label);\n const changes = o.changes as Record<string, unknown>;\n const out: { content?: string; confidence?: number } = {};\n if (changes.content !== undefined) out.content = String(changes.content);\n if (changes.confidence !== undefined) out.confidence = Number(changes.confidence);\n if (out.content === undefined && out.confidence === undefined) {\n throw new ShapeError(`${label}.changes: needs content or confidence`);\n }\n return { op: 'UPDATE', id: String(o.id), changes: out, why: typeof o.why === 'string' ? o.why : '' };\n }\n if (tag === 'INVALIDATE') {\n const o = check(InvalidateShape, raw, label);\n return {\n op: 'INVALIDATE',\n id: String(o.id),\n why: typeof o.why === 'string' ? o.why : '',\n evidenceRefs: parseObservationRefs(o.evidence, `${label}.evidence`),\n };\n }\n if (tag === 'NOOP') {\n const o = check(NoopShape, raw, label);\n return { op: 'NOOP', why: typeof o.why === 'string' ? o.why : '' };\n }\n throw new ShapeError(`${label}.op: unknown op ${JSON.stringify(tag)}`);\n}\n\nexport interface OpParseResult {\n ops: ProposedOp[];\n /** One malformed row never discards the rest of the batch, but it is always\n * reported — silence here used to look like \"the model proposed nothing\". */\n rejected: { op: unknown; reason: string }[];\n}\n\nexport function parseProposedOps(list: unknown[]): OpParseResult {\n const ops: ProposedOp[] = [];\n const rejected: { op: unknown; reason: string }[] = [];\n list.forEach((raw, i) => {\n try {\n ops.push(parseProposedOp(raw, `op[${i}]`));\n } catch (e) {\n rejected.push({ op: raw, reason: e instanceof Error ? e.message : String(e) });\n }\n });\n return { ops, rejected };\n}\n\n/** Turn cited observation ids into code-built evidence. Unknown ids are a\n * rejection, never a silent drop: the op then has no provenance. */\nexport function materializeEvidence(\n refs: string[],\n observations: Map<string, InboxItem>,\n label: string,\n): { evidence: Evidence[]; reason?: string } {\n const evidence: Evidence[] = [];\n for (const ref of refs) {\n const item = observations.get(ref);\n if (!item) return { evidence: [], reason: `${label}: ${ref} does not match any observation in this batch` };\n evidence.push({ kind: item.kind, at: item.at, ref: item.ref });\n }\n return { evidence };\n}\n\n// ── journal line reader (replay path) ───────────────────────────────────────\n//\n// Lenient on purpose: a line this code did not write is skipped by the caller,\n// never fatal. The journal is append-only and immutable, so one bad line must\n// not freeze the profile — but it IS counted (ReplayResult.badRecords) so a\n// silent data loss is visible in profile verify.\n\nexport function tryParseJournalRecord(value: unknown): JournalRecord | null {\n try {\n if (!isPlainObject(value)) return null;\n const rec: JournalRecord = {\n ts: typeof value.ts === 'string' ? value.ts : '',\n runId: typeof value.runId === 'string' ? value.runId : '',\n applied: Array.isArray(value.applied) ? (value.applied as ProfileOp[]) : [],\n rejected: Array.isArray(value.rejected) ? (value.rejected as { op: unknown; reason: string }[]) : [],\n };\n if (value.v === JOURNAL_VERSION) {\n if (!Array.isArray(value.entries)) return null;\n rec.v = JOURNAL_VERSION;\n rec.entries = value.entries.map((e, i) => parseProfileEntry(e, `entries[${i}]`));\n }\n return rec;\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":["path","fs","fs","path","path","fs","check"]}