@titan-design/memory 0.1.2 → 0.1.3

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.
package/dist/index.js CHANGED
@@ -321,13 +321,18 @@ function makeContext(store, options) {
321
321
  nearDup: options.nearDupThreshold ?? 0.85,
322
322
  conflict: options.conflictThreshold ?? 0.5,
323
323
  inversion: { minHarmful: options.inversion?.minHarmful ?? 3, harmfulToHelpfulRatio: options.inversion?.harmfulToHelpfulRatio ?? 2 },
324
- blocked: store.blockedPatterns()
324
+ blocked: store.blockedPatterns(),
325
+ voted: /* @__PURE__ */ new Set()
325
326
  };
326
327
  }
327
328
  function dedupeDeltas(deltas, report) {
328
329
  const seen = /* @__PURE__ */ new Set();
329
330
  const kept = [];
330
331
  for (const delta of deltas) {
332
+ if (delta.type === "helpful" || delta.type === "harmful") {
333
+ kept.push(delta);
334
+ continue;
335
+ }
331
336
  const key = delta.type === "add" ? contentKey(delta.content) : JSON.stringify(delta);
332
337
  if (seen.has(key)) report.skipped.push({ delta, reason: "duplicate delta" });
333
338
  else {
@@ -360,7 +365,8 @@ function applyAdd(ctx, delta) {
360
365
  const live = ctx.store.list();
361
366
  const duplicate = findDuplicate(live, delta.content, ctx.nearDup);
362
367
  if (duplicate) {
363
- reinforce(ctx, duplicate.id, "restated by a new add");
368
+ if (claimVote(ctx, "helpful", duplicate.id)) reinforce(ctx, duplicate.id, "restated by a new add");
369
+ else ctx.report.skipped.push({ delta, reason: "bullet already voted helpful in this batch" });
364
370
  return;
365
371
  }
366
372
  const bullet = ctx.store.add({ ...addFields(delta), sourceSessions: ctx.provenance });
@@ -372,9 +378,19 @@ function applyFeedback(ctx, delta) {
372
378
  ctx.report.skipped.push({ delta, reason: "unknown bullet" });
373
379
  return;
374
380
  }
381
+ if (!claimVote(ctx, delta.type, delta.bulletId)) {
382
+ ctx.report.skipped.push({ delta, reason: `bullet already voted ${delta.type} in this batch` });
383
+ return;
384
+ }
375
385
  ctx.store.recordFeedback(delta.bulletId, delta.type, { sessionRef: ctx.provenance[0]?.sessionRef, reason: delta.reason });
376
386
  (delta.type === "helpful" ? ctx.report.reinforced : ctx.report.penalized).push(delta.bulletId);
377
387
  }
388
+ function claimVote(ctx, type, bulletId) {
389
+ const key = `${type}:${bulletId}`;
390
+ if (ctx.voted.has(key)) return false;
391
+ ctx.voted.add(key);
392
+ return true;
393
+ }
378
394
  function applyReplace(ctx, delta) {
379
395
  const old = ctx.store.get(delta.bulletId);
380
396
  if (!old) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/schema.ts","../src/scoring.ts","../src/text.ts","../src/store.ts","../src/playbook.ts","../src/curate.ts","../src/recall.ts","../src/vectors.ts","../src/reflect.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * The playbook data model, borrowed from cass-memory's `PlaybookBullet`. Counts\n * are never stored: they are derived from the append-only feedback log at read\n * time, so decay parameters can change without re-running reflection.\n */\nexport const BULLET_SCOPES = [\"global\", \"workspace\", \"language\", \"framework\", \"task\"] as const;\nexport const BULLET_TYPES = [\"rule\", \"anti-pattern\"] as const;\nexport const BULLET_KINDS = [\"project_convention\", \"stack_pattern\", \"workflow_rule\", \"anti_pattern\"] as const;\nexport const BULLET_SOURCES = [\"learned\", \"community\", \"manual\", \"custom\"] as const;\nexport const BULLET_STATES = [\"draft\", \"active\", \"retired\"] as const;\nexport const MATURITIES = [\"candidate\", \"established\", \"proven\", \"deprecated\"] as const;\n\nexport type BulletScope = (typeof BULLET_SCOPES)[number];\nexport type BulletType = (typeof BULLET_TYPES)[number];\nexport type BulletKind = (typeof BULLET_KINDS)[number];\nexport type BulletSource = (typeof BULLET_SOURCES)[number];\nexport type BulletState = (typeof BULLET_STATES)[number];\nexport type Maturity = (typeof MATURITIES)[number];\nexport type FeedbackType = \"helpful\" | \"harmful\";\n\n/** Where a bullet's evidence lives: a session ref plus a byte offset into its transcript. */\nexport interface Provenance {\n sessionRef: string;\n byteOffset?: number;\n}\n\nexport interface Bullet {\n id: string;\n content: string;\n category: string;\n tags: string[];\n scope: BulletScope;\n type: BulletType;\n kind: BulletKind;\n isNegative: boolean;\n source: BulletSource;\n state: BulletState;\n maturity: Maturity;\n pinned: boolean;\n pinnedReason: string | null;\n /** Set when retired in favour of another bullet; mirrored by a `supersedes` edge. */\n replacedBy: string | null;\n deprecatedAt: string | null;\n deprecationReason: string | null;\n halfLifeDays: number;\n sourceSessions: Provenance[];\n reasoning: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface NewBullet {\n id?: string;\n content: string;\n category?: string;\n tags?: string[];\n scope?: BulletScope;\n type?: BulletType;\n kind?: BulletKind;\n isNegative?: boolean;\n source?: BulletSource;\n state?: BulletState;\n pinned?: boolean;\n pinnedReason?: string | null;\n halfLifeDays?: number;\n sourceSessions?: Provenance[];\n reasoning?: string | null;\n}\n\n/** One line of the immutable feedback log. */\nexport interface FeedbackEvent {\n id: number;\n bulletId: string;\n type: FeedbackType;\n at: string;\n sessionRef: string | null;\n reason: string | null;\n}\n\nexport interface DecayedCounts {\n helpful: number;\n harmful: number;\n}\n\nexport interface ScoredBullet extends Bullet {\n helpfulCount: number;\n harmfulCount: number;\n decayedHelpful: number;\n decayedHarmful: number;\n effectiveScore: number;\n /** Latest feedback, or creation when there is none; the input to staleness. */\n lastEvidenceAt: string;\n}\n\n/**\n * What a reflector proposes. Provenance is deliberately absent: the curator\n * stamps it from the session it is actually processing, never from the model.\n */\nconst addDelta = z.object({\n type: z.literal(\"add\"),\n content: z.string().min(1),\n category: z.string().min(1).default(\"general\"),\n tags: z.array(z.string()).default([]),\n scope: z.enum(BULLET_SCOPES).default(\"workspace\"),\n kind: z.enum(BULLET_KINDS).default(\"workflow_rule\"),\n isNegative: z.boolean().default(false),\n reasoning: z.string().optional(),\n});\nconst feedbackDelta = (type: FeedbackType) => z.object({ type: z.literal(type), bulletId: z.string().min(1), reason: z.string().optional() });\nconst replaceDelta = z.object({ type: z.literal(\"replace\"), bulletId: z.string().min(1), content: z.string().min(1), reasoning: z.string().optional() });\nconst deprecateDelta = z.object({ type: z.literal(\"deprecate\"), bulletId: z.string().min(1), reason: z.string().min(1) });\nconst mergeDelta = z.object({ type: z.literal(\"merge\"), bulletIds: z.array(z.string().min(1)).min(2), content: z.string().min(1), reasoning: z.string().optional() });\n\nexport const PlaybookDeltaSchema = z.discriminatedUnion(\"type\", [\n addDelta,\n feedbackDelta(\"helpful\"),\n feedbackDelta(\"harmful\"),\n replaceDelta,\n deprecateDelta,\n mergeDelta,\n]);\n/** What callers and reflectors write; defaults may be omitted. */\nexport type PlaybookDelta = z.input<typeof PlaybookDeltaSchema>;\n/** What the curator works on, after parsing fills the defaults in. */\nexport type ParsedDelta = z.output<typeof PlaybookDeltaSchema>;\nexport type AddDelta = z.output<typeof addDelta>;\n","import { SQL_NOW, kitDdl, quoteIdent, type Migration } from \"@titan-design/store-sqlite\";\n\n/**\n * Four kit tables plus one domain table. Bullets are interval entities, the\n * `supersedes` relation lives in the edge table, embeddings in cache_blob keyed\n * by content hash, and per-session progress in the watermark table.\n */\nexport interface MemoryTables {\n entity: string;\n edge: string;\n cacheBlob: string;\n watermark: string;\n feedback: string;\n}\n\nexport const DEFAULT_MEMORY_TABLES: MemoryTables = {\n entity: \"memory_entity\",\n edge: \"memory_edge\",\n cacheBlob: \"memory_cache\",\n watermark: \"memory_watermark\",\n feedback: \"memory_feedback\",\n};\n\nexport const BULLET_KIND = \"bullet\";\nexport const BLOCKED_KIND = \"blocked\";\nexport const SUPERSEDES = \"supersedes\";\n\nexport function feedbackTableDdl(name: string = DEFAULT_MEMORY_TABLES.feedback): string {\n const t = quoteIdent(name);\n return `\n CREATE TABLE IF NOT EXISTS ${t} (\n id INTEGER PRIMARY KEY,\n bullet_ref TEXT NOT NULL,\n type TEXT NOT NULL,\n at TEXT NOT NULL DEFAULT (${SQL_NOW}),\n session_ref TEXT,\n reason TEXT\n );\n CREATE INDEX IF NOT EXISTS ${quoteIdent(`idx_${name}_bullet`)} ON ${t}(bullet_ref, at);\n `;\n}\n\nexport function memoryDdl(tables: MemoryTables = DEFAULT_MEMORY_TABLES): string {\n const kit = kitDdl({ entity: tables.entity, edge: tables.edge, cacheBlob: tables.cacheBlob, watermark: tables.watermark });\n return `${kit}\\n${feedbackTableDdl(tables.feedback)}`;\n}\n\n/** Drop into a product's migration list so the playbook shares its database. */\nexport function memoryMigration(version: number, tables: MemoryTables = DEFAULT_MEMORY_TABLES): Migration {\n return { version, name: `memory:${tables.entity}`, up: (db) => db.exec(memoryDdl(tables)) };\n}\n","import type { DecayedCounts, FeedbackEvent, Maturity } from \"./types.js\";\n\n/** cass-memory's exact numbers; a bullet may override the half-life, nothing else. */\nexport const DEFAULT_HALF_LIFE_DAYS = 90;\nexport const HARMFUL_WEIGHT = 4;\nexport const HARD_DEPRECATE_SCORE = -3;\nexport const MATURITY_MULTIPLIER: Record<Maturity, number> = { candidate: 0.5, established: 1, proven: 1.5, deprecated: 0 };\n\nconst RANK: Record<Maturity, number> = { deprecated: 0, candidate: 1, established: 2, proven: 3 };\nconst BY_RANK: Maturity[] = [\"deprecated\", \"candidate\", \"established\", \"proven\"];\nconst DAY_MS = 86_400_000;\n\nexport function decayedValue(at: string, now: Date, halfLifeDays: number = DEFAULT_HALF_LIFE_DAYS): number {\n const ageDays = Math.max(0, now.getTime() - Date.parse(at)) / DAY_MS;\n return 0.5 ** (ageDays / halfLifeDays);\n}\n\nexport function decayedCounts(events: readonly FeedbackEvent[], now: Date, halfLifeDays: number = DEFAULT_HALF_LIFE_DAYS): DecayedCounts {\n const counts = { helpful: 0, harmful: 0 };\n for (const event of events) counts[event.type] += decayedValue(event.at, now, halfLifeDays);\n return counts;\n}\n\nexport function effectiveScore(counts: DecayedCounts, maturity: Maturity): number {\n return (counts.helpful - HARMFUL_WEIGHT * counts.harmful) * MATURITY_MULTIPLIER[maturity];\n}\n\n/** The maturity the decayed counts alone would assign, ignoring history. */\nexport function maturityFor(counts: DecayedCounts): Maturity {\n const total = counts.helpful + counts.harmful;\n const harmfulRatio = total === 0 ? 0 : counts.harmful / total;\n if (total < 3) return \"candidate\";\n if (harmfulRatio > 0.3) return \"deprecated\";\n if (counts.helpful >= 10 && harmfulRatio < 0.1) return \"proven\";\n return \"established\";\n}\n\n/**\n * Promotion jumps straight to the earned rung; demotion drops one rung per\n * pass, except that a score below the hard floor deprecates outright. Pinned\n * bullets never move.\n */\nexport function nextMaturity(current: Maturity, counts: DecayedCounts, pinned: boolean): Maturity {\n if (pinned || current === \"deprecated\") return current;\n if (effectiveScore(counts, current) < HARD_DEPRECATE_SCORE) return \"deprecated\";\n const target = maturityFor(counts);\n if (RANK[target] > RANK[current]) return target;\n if (RANK[target] < RANK[current]) return BY_RANK[RANK[current] - 1]!;\n return current;\n}\n\nexport interface StalenessOptions {\n /** Days without any feedback before a bullet is flagged for re-validation. */\n staleAfterDays?: number;\n}\n\n/** Staleness is about silence, not decay: a bullet nobody has confirmed or refuted lately. */\nexport function isStale(lastEvidenceAt: string, now: Date, { staleAfterDays = 180 }: StalenessOptions = {}): boolean {\n return now.getTime() - Date.parse(lastEvidenceAt) > staleAfterDays * DAY_MS;\n}\n","import { contentHashOf } from \"@titan-design/store-sqlite\";\n\nconst TOKEN = /[a-z0-9_]+/g;\nconst NEGATION = /\\b(never|don'?t|do not|avoid|not|no|stop|without)\\b/i;\n\n/** Lowercase alphanumeric tokens of two or more characters, as a set. */\nexport function tokenize(text: string): Set<string> {\n const out = new Set<string>();\n for (const match of text.toLowerCase().matchAll(TOKEN)) if (match[0].length >= 2) out.add(match[0]);\n return out;\n}\n\n/** Case- and whitespace-insensitive form used for exact-duplicate detection. */\nexport function normalizeContent(text: string): string {\n return text.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\nexport function contentKey(text: string): string {\n return contentHashOf(normalizeContent(text));\n}\n\nexport function jaccard(a: string, b: string): number {\n const ta = tokenize(a);\n const tb = tokenize(b);\n if (ta.size === 0 && tb.size === 0) return 1;\n let shared = 0;\n for (const token of ta) if (tb.has(token)) shared++;\n return shared / (ta.size + tb.size - shared);\n}\n\n/** Whether a rule is phrased as a prohibition; used only to flag likely conflicts, never to block. */\nexport function isNegated(text: string): boolean {\n return NEGATION.test(text);\n}\n","import { EdgeTable, EntityTable, quoteIdent, refKind, type Db, type EntityRow } from \"@titan-design/store-sqlite\";\nimport { randomUUID } from \"node:crypto\";\nimport { BLOCKED_KIND, BULLET_KIND, DEFAULT_MEMORY_TABLES, SUPERSEDES, type MemoryTables } from \"./schema.js\";\nimport { DEFAULT_HALF_LIFE_DAYS } from \"./scoring.js\";\nimport type { Bullet, FeedbackEvent, FeedbackType, NewBullet } from \"./types.js\";\n\nexport const bulletRef = refKind(\"memory\");\nconst blockedRef = refKind(\"memory-blocked\");\n\nexport interface PlaybookStoreOptions {\n tables?: MemoryTables;\n now?: () => Date;\n}\n\nexport interface FeedbackInput {\n sessionRef?: string | null;\n reason?: string | null;\n at?: string;\n}\n\nexport interface BlockedPattern {\n pattern: string;\n reason: string;\n blockedAt: string;\n}\n\ninterface RawFeedbackRow {\n id: number;\n bullet_ref: string;\n type: FeedbackType;\n at: string;\n session_ref: string | null;\n reason: string | null;\n}\n\ntype Attrs = Omit<Bullet, \"id\" | \"content\" | \"category\">;\n\nexport class BulletNotFound extends Error {\n constructor(id: string) {\n super(`bullet not found: ${id}`);\n this.name = \"BulletNotFound\";\n }\n}\n\n/**\n * Bullets are interval entities (`kind = bullet`, name = category, attrs = the\n * rest), so retirement is an attrs change plus a `supersedes` edge, never a\n * delete. Feedback is an append-only log; nothing here ever updates or removes\n * an event.\n */\nexport class PlaybookStore {\n readonly tables: MemoryTables;\n private readonly entities: EntityTable;\n private readonly edges: EdgeTable;\n private readonly now: () => Date;\n private readonly insertFeedback;\n private readonly feedbackByBullet;\n private readonly allFeedback;\n\n constructor(db: Db, options: PlaybookStoreOptions = {}) {\n this.tables = options.tables ?? DEFAULT_MEMORY_TABLES;\n this.now = options.now ?? (() => new Date());\n this.entities = new EntityTable(db, { name: this.tables.entity });\n this.edges = new EdgeTable(db, { name: this.tables.edge });\n const f = quoteIdent(this.tables.feedback);\n this.insertFeedback = db.prepare(`INSERT INTO ${f} (bullet_ref, type, at, session_ref, reason) VALUES (?, ?, ?, ?, ?)`);\n this.feedbackByBullet = db.prepare(`SELECT * FROM ${f} WHERE bullet_ref = ? ORDER BY at, id`);\n this.allFeedback = db.prepare(`SELECT * FROM ${f} ORDER BY at, id`);\n }\n\n add(input: NewBullet): Bullet {\n const at = this.now().toISOString();\n const bullet = materialize(input, at);\n this.write(bullet);\n return bullet;\n }\n\n get(id: string): Bullet | undefined {\n const row = this.entities.get(bulletRef(id));\n return row === undefined || row.kind !== BULLET_KIND ? undefined : toBullet(row);\n }\n\n require(id: string): Bullet {\n const bullet = this.get(id);\n if (bullet === undefined) throw new BulletNotFound(id);\n return bullet;\n }\n\n /** Live bullets only, unless `includeRetired`; ordered by id for determinism. */\n list({ includeRetired = false }: { includeRetired?: boolean } = {}): Bullet[] {\n const all = this.entities.listByKind(BULLET_KIND).map(toBullet);\n return includeRetired ? all : all.filter((b) => b.state !== \"retired\");\n }\n\n update(id: string, patch: Partial<Omit<Bullet, \"id\" | \"createdAt\">>): Bullet {\n const next = { ...this.require(id), ...patch, updatedAt: this.now().toISOString() };\n this.write(next);\n return next;\n }\n\n /** Retire a bullet. With `replacedBy`, also assert `replacedBy -supersedes-> id`. */\n deprecate(id: string, reason: string, replacedBy: string | null = null): Bullet {\n const at = this.now().toISOString();\n const bullet = this.update(id, { state: \"retired\", maturity: \"deprecated\", replacedBy, deprecatedAt: at, deprecationReason: reason });\n if (replacedBy !== null) this.edges.assert({ sourceRef: bulletRef(replacedBy), relation: SUPERSEDES, targetRef: bulletRef(id), tValid: at });\n return bullet;\n }\n\n /** Ids of the bullets this one replaced, following live `supersedes` edges. */\n supersededBy(id: string): string[] {\n return this.edges.from(bulletRef(id)).filter((e) => e.relation === SUPERSEDES).map((e) => e.targetRef.slice(\"memory:\".length));\n }\n\n recordFeedback(id: string, type: FeedbackType, input: FeedbackInput = {}): FeedbackEvent {\n this.require(id);\n const at = input.at ?? this.now().toISOString();\n const info = this.insertFeedback.run(bulletRef(id), type, at, input.sessionRef ?? null, input.reason ?? null);\n return { id: Number(info.lastInsertRowid), bulletId: id, type, at, sessionRef: input.sessionRef ?? null, reason: input.reason ?? null };\n }\n\n feedbackFor(id: string): FeedbackEvent[] {\n return (this.feedbackByBullet.all(bulletRef(id)) as RawFeedbackRow[]).map(toEvent);\n }\n\n /** Every event grouped by bullet id, one query, for scoring the whole playbook. */\n feedbackByBulletId(): Map<string, FeedbackEvent[]> {\n const grouped = new Map<string, FeedbackEvent[]>();\n for (const event of (this.allFeedback.all() as RawFeedbackRow[]).map(toEvent)) {\n const list = grouped.get(event.bulletId) ?? [];\n list.push(event);\n grouped.set(event.bulletId, list);\n }\n return grouped;\n }\n\n /** A content pattern a human has banned; the curator refuses to re-learn anything near it. */\n block(pattern: string, reason: string): BlockedPattern {\n const blockedAt = this.now().toISOString();\n this.entities.upsert({ ref: blockedRef(randomUUID()), kind: BLOCKED_KIND, name: pattern, attrs: { reason, blockedAt }, tValid: blockedAt });\n return { pattern, reason, blockedAt };\n }\n\n blockedPatterns(): BlockedPattern[] {\n return this.entities.listByKind(BLOCKED_KIND).map((row) => ({\n pattern: row.name ?? \"\",\n reason: String(row.attrs?.reason ?? \"\"),\n blockedAt: String(row.attrs?.blockedAt ?? row.tValid),\n }));\n }\n\n private write(bullet: Bullet): void {\n const { id, content, category, ...attrs } = bullet;\n this.entities.upsert({ ref: bulletRef(id), kind: BULLET_KIND, name: category, attrs: { ...attrs, content }, tValid: bullet.createdAt });\n }\n}\n\nexport function newBulletId(now: Date = new Date()): string {\n return `b-${now.getTime().toString(36)}-${randomUUID().slice(0, 6)}`;\n}\n\nfunction materialize(input: NewBullet, at: string): Bullet {\n return {\n id: input.id ?? newBulletId(new Date(at)),\n content: input.content,\n category: input.category ?? \"general\",\n tags: [...(input.tags ?? [])],\n scope: input.scope ?? \"workspace\",\n type: input.type ?? (input.isNegative ? \"anti-pattern\" : \"rule\"),\n kind: input.kind ?? (input.isNegative ? \"anti_pattern\" : \"workflow_rule\"),\n isNegative: input.isNegative ?? false,\n source: input.source ?? \"learned\",\n state: input.state ?? \"active\",\n maturity: \"candidate\",\n pinned: input.pinned ?? false,\n pinnedReason: input.pinnedReason ?? null,\n replacedBy: null,\n deprecatedAt: null,\n deprecationReason: null,\n halfLifeDays: input.halfLifeDays ?? DEFAULT_HALF_LIFE_DAYS,\n sourceSessions: [...(input.sourceSessions ?? [])],\n reasoning: input.reasoning ?? null,\n createdAt: at,\n updatedAt: at,\n };\n}\n\nfunction toBullet(row: EntityRow): Bullet {\n const attrs = (row.attrs ?? {}) as Attrs & { content: string };\n const { content, ...rest } = attrs;\n return { id: row.ref.slice(\"memory:\".length), content, category: row.name ?? \"general\", ...rest };\n}\n\nfunction toEvent(raw: RawFeedbackRow): FeedbackEvent {\n return { id: raw.id, bulletId: raw.bullet_ref.slice(\"memory:\".length), type: raw.type, at: raw.at, sessionRef: raw.session_ref, reason: raw.reason };\n}\n","import { decayedCounts, effectiveScore, isStale, nextMaturity, type StalenessOptions } from \"./scoring.js\";\nimport type { PlaybookStore } from \"./store.js\";\nimport type { Bullet, FeedbackEvent, Maturity, ScoredBullet } from \"./types.js\";\n\nexport function scoreBullet(bullet: Bullet, events: readonly FeedbackEvent[], now: Date): ScoredBullet {\n const counts = decayedCounts(events, now, bullet.halfLifeDays);\n const last = events[events.length - 1];\n return {\n ...bullet,\n helpfulCount: events.filter((e) => e.type === \"helpful\").length,\n harmfulCount: events.filter((e) => e.type === \"harmful\").length,\n decayedHelpful: counts.helpful,\n decayedHarmful: counts.harmful,\n effectiveScore: effectiveScore(counts, bullet.maturity),\n lastEvidenceAt: last?.at ?? bullet.createdAt,\n };\n}\n\nexport interface ScoreOptions {\n includeRetired?: boolean;\n}\n\n/** Every bullet with its decayed counts and score as of `now`. One feedback query for the whole playbook. */\nexport function scorePlaybook(store: PlaybookStore, now: Date, options: ScoreOptions = {}): ScoredBullet[] {\n const feedback = store.feedbackByBulletId();\n return store.list(options).map((bullet) => scoreBullet(bullet, feedback.get(bullet.id) ?? [], now));\n}\n\nexport interface MaturityChange {\n bulletId: string;\n from: Maturity;\n to: Maturity;\n}\n\n/** The promotion/demotion pass. A bullet that lands on `deprecated` is retired. */\nexport function applyMaturity(store: PlaybookStore, now: Date): MaturityChange[] {\n const changes: MaturityChange[] = [];\n for (const bullet of scorePlaybook(store, now)) {\n const to = nextMaturity(bullet.maturity, { helpful: bullet.decayedHelpful, harmful: bullet.decayedHarmful }, bullet.pinned);\n if (to === bullet.maturity) continue;\n if (to === \"deprecated\") store.deprecate(bullet.id, \"auto-demoted below the confidence floor\");\n else store.update(bullet.id, { maturity: to });\n changes.push({ bulletId: bullet.id, from: bullet.maturity, to });\n }\n return changes;\n}\n\n/** Live bullets nobody has confirmed or refuted lately: candidates for re-validation, not for removal. */\nexport function staleBullets(store: PlaybookStore, now: Date, options: StalenessOptions = {}): ScoredBullet[] {\n return scorePlaybook(store, now).filter((b) => !b.pinned && isStale(b.lastEvidenceAt, now, options));\n}\n","import { applyMaturity, scorePlaybook, type MaturityChange } from \"./playbook.js\";\nimport type { BlockedPattern, PlaybookStore } from \"./store.js\";\nimport { contentKey, isNegated, jaccard, normalizeContent } from \"./text.js\";\nimport { PlaybookDeltaSchema, type AddDelta, type Bullet, type ParsedDelta, type PlaybookDelta, type Provenance, type ScoredBullet } from \"./types.js\";\n\nexport interface InversionOptions {\n /** Decayed harmful mass a rule needs before it can flip into an anti-pattern. */\n minHarmful?: number;\n /** And by how much harmful must outweigh helpful. */\n harmfulToHelpfulRatio?: number;\n}\n\nexport interface CurateOptions {\n /** Stamped onto every bullet this batch creates. Never taken from the deltas themselves. */\n provenance?: Provenance;\n now?: () => Date;\n /** Jaccard similarity at which an `add` folds into a `helpful` on the existing bullet. */\n nearDupThreshold?: number;\n /** Jaccard similarity at which two rules are flagged as possibly contradicting. */\n conflictThreshold?: number;\n inversion?: InversionOptions;\n}\n\nexport interface Conflict {\n bulletId: string;\n otherId: string;\n reason: string;\n}\n\nexport interface CurationReport {\n added: string[];\n reinforced: string[];\n penalized: string[];\n deprecated: string[];\n inverted: { from: string; to: string }[];\n blocked: string[];\n skipped: { delta: ParsedDelta; reason: string }[];\n conflicts: Conflict[];\n maturityChanges: MaturityChange[];\n}\n\ninterface Ctx {\n store: PlaybookStore;\n report: CurationReport;\n now: () => Date;\n provenance: Provenance[];\n nearDup: number;\n conflict: number;\n inversion: Required<InversionOptions>;\n blocked: BlockedPattern[];\n}\n\n/**\n * cass-memory's curator: zero LLM, fully deterministic. Dedup by content hash\n * and near-dup Jaccard, apply the batch, invert rules that keep hurting into\n * `AVOID:` anti-patterns, then run the maturity pass.\n */\nexport function curate(store: PlaybookStore, deltas: readonly PlaybookDelta[], options: CurateOptions = {}): CurationReport {\n const ctx = makeContext(store, options);\n const parsed = deltas.map((delta) => PlaybookDeltaSchema.parse(delta));\n for (const delta of dedupeDeltas(parsed, ctx.report)) applyDelta(ctx, delta);\n invertHarmfulRules(ctx);\n ctx.report.maturityChanges = applyMaturity(store, ctx.now());\n return ctx.report;\n}\n\nfunction makeContext(store: PlaybookStore, options: CurateOptions): Ctx {\n return {\n store,\n report: { added: [], reinforced: [], penalized: [], deprecated: [], inverted: [], blocked: [], skipped: [], conflicts: [], maturityChanges: [] },\n now: options.now ?? (() => new Date()),\n provenance: options.provenance ? [options.provenance] : [],\n nearDup: options.nearDupThreshold ?? 0.85,\n conflict: options.conflictThreshold ?? 0.5,\n inversion: { minHarmful: options.inversion?.minHarmful ?? 3, harmfulToHelpfulRatio: options.inversion?.harmfulToHelpfulRatio ?? 2 },\n blocked: store.blockedPatterns(),\n };\n}\n\nfunction dedupeDeltas(deltas: readonly ParsedDelta[], report: CurationReport): ParsedDelta[] {\n const seen = new Set<string>();\n const kept: ParsedDelta[] = [];\n for (const delta of deltas) {\n const key = delta.type === \"add\" ? contentKey(delta.content) : JSON.stringify(delta);\n if (seen.has(key)) report.skipped.push({ delta, reason: \"duplicate delta\" });\n else {\n seen.add(key);\n kept.push(delta);\n }\n }\n return kept;\n}\n\nfunction applyDelta(ctx: Ctx, delta: ParsedDelta): void {\n switch (delta.type) {\n case \"add\":\n return applyAdd(ctx, delta);\n case \"helpful\":\n case \"harmful\":\n return applyFeedback(ctx, delta);\n case \"replace\":\n return applyReplace(ctx, delta);\n case \"deprecate\":\n return applyDeprecate(ctx, delta);\n case \"merge\":\n return applyMerge(ctx, delta);\n }\n}\n\nfunction applyAdd(ctx: Ctx, delta: AddDelta): void {\n if (isBlocked(ctx, delta.content)) {\n ctx.report.blocked.push(delta.content);\n return;\n }\n const live = ctx.store.list();\n const duplicate = findDuplicate(live, delta.content, ctx.nearDup);\n if (duplicate) {\n reinforce(ctx, duplicate.id, \"restated by a new add\");\n return;\n }\n const bullet = ctx.store.add({ ...addFields(delta), sourceSessions: ctx.provenance });\n ctx.report.added.push(bullet.id);\n detectConflicts(ctx, bullet, live);\n}\n\nfunction applyFeedback(ctx: Ctx, delta: Extract<ParsedDelta,{ type: \"helpful\" | \"harmful\" }>): void {\n if (!ctx.store.get(delta.bulletId)) {\n ctx.report.skipped.push({ delta, reason: \"unknown bullet\" });\n return;\n }\n ctx.store.recordFeedback(delta.bulletId, delta.type, { sessionRef: ctx.provenance[0]?.sessionRef, reason: delta.reason });\n (delta.type === \"helpful\" ? ctx.report.reinforced : ctx.report.penalized).push(delta.bulletId);\n}\n\nfunction applyReplace(ctx: Ctx, delta: Extract<ParsedDelta,{ type: \"replace\" }>): void {\n const old = ctx.store.get(delta.bulletId);\n if (!old) {\n ctx.report.skipped.push({ delta, reason: \"unknown bullet\" });\n return;\n }\n const next = ctx.store.add({ ...inherit(old), content: delta.content, reasoning: delta.reasoning ?? old.reasoning, sourceSessions: [...old.sourceSessions, ...ctx.provenance] });\n ctx.store.deprecate(old.id, \"replaced\", next.id);\n ctx.report.added.push(next.id);\n ctx.report.deprecated.push(old.id);\n}\n\nfunction applyDeprecate(ctx: Ctx, delta: Extract<ParsedDelta,{ type: \"deprecate\" }>): void {\n if (!ctx.store.get(delta.bulletId)) {\n ctx.report.skipped.push({ delta, reason: \"unknown bullet\" });\n return;\n }\n ctx.store.deprecate(delta.bulletId, delta.reason);\n ctx.report.deprecated.push(delta.bulletId);\n}\n\nfunction applyMerge(ctx: Ctx, delta: Extract<ParsedDelta,{ type: \"merge\" }>): void {\n const olds = delta.bulletIds.map((id) => ctx.store.get(id));\n const first = olds[0];\n if (!first || olds.some((b) => b === undefined)) {\n ctx.report.skipped.push({ delta, reason: \"unknown bullet\" });\n return;\n }\n const present = olds as Bullet[];\n const next = ctx.store.add({\n ...inherit(first),\n content: delta.content,\n tags: [...new Set(present.flatMap((b) => b.tags))],\n reasoning: delta.reasoning ?? first.reasoning,\n sourceSessions: [...present.flatMap((b) => b.sourceSessions), ...ctx.provenance],\n });\n ctx.report.added.push(next.id);\n for (const old of present) {\n ctx.store.deprecate(old.id, \"merged\", next.id);\n ctx.report.deprecated.push(old.id);\n }\n}\n\nfunction addFields(delta: AddDelta): Omit<AddDelta, \"type\"> {\n const { content, category, tags, scope, kind, isNegative, reasoning } = delta;\n return { content, category, tags, scope, kind, isNegative, reasoning };\n}\n\nfunction inherit(bullet: Bullet): Pick<Bullet, \"category\" | \"tags\" | \"scope\" | \"type\" | \"kind\" | \"isNegative\" | \"source\" | \"halfLifeDays\"> {\n const { category, tags, scope, type, kind, isNegative, source, halfLifeDays } = bullet;\n return { category, tags, scope, type, kind, isNegative, source, halfLifeDays };\n}\n\nfunction reinforce(ctx: Ctx, id: string, reason: string): void {\n ctx.store.recordFeedback(id, \"helpful\", { sessionRef: ctx.provenance[0]?.sessionRef, reason });\n ctx.report.reinforced.push(id);\n}\n\nfunction isBlocked(ctx: Ctx, content: string): boolean {\n const normalized = normalizeContent(content);\n return ctx.blocked.some((b) => normalizeContent(b.pattern) === normalized || jaccard(b.pattern, content) >= ctx.nearDup);\n}\n\n/** A near-duplicate with flipped polarity is a contradiction, not a restatement, so it never folds. */\nfunction findDuplicate(live: readonly Bullet[], content: string, threshold: number): Bullet | undefined {\n const key = contentKey(content);\n const negated = isNegated(content);\n return (\n live.find((b) => contentKey(b.content) === key) ??\n live.find((b) => isNegated(b.content) === negated && jaccard(b.content, content) >= threshold)\n );\n}\n\n/** Heuristic only: similar wording where exactly one side is a prohibition. Warns, never blocks. */\nfunction detectConflicts(ctx: Ctx, bullet: Bullet, others: readonly Bullet[]): void {\n const negated = isNegated(bullet.content);\n for (const other of others) {\n if (isNegated(other.content) === negated || jaccard(bullet.content, other.content) < ctx.conflict) continue;\n ctx.report.conflicts.push({ bulletId: bullet.id, otherId: other.id, reason: \"similar wording with opposite polarity\" });\n }\n}\n\nfunction shouldInvert(ctx: Ctx, bullet: ScoredBullet): boolean {\n if (bullet.type !== \"rule\" || bullet.pinned || bullet.state !== \"active\") return false;\n return bullet.decayedHarmful >= ctx.inversion.minHarmful && bullet.decayedHarmful > ctx.inversion.harmfulToHelpfulRatio * bullet.decayedHelpful;\n}\n\nfunction invertHarmfulRules(ctx: Ctx): void {\n for (const bullet of scorePlaybook(ctx.store, ctx.now())) {\n if (!shouldInvert(ctx, bullet)) continue;\n const avoid = ctx.store.add({\n ...inherit(bullet),\n content: `AVOID: ${bullet.content}`,\n type: \"anti-pattern\",\n kind: \"anti_pattern\",\n isNegative: true,\n reasoning: \"inverted after repeated harmful feedback\",\n sourceSessions: [...bullet.sourceSessions, ...ctx.provenance],\n });\n ctx.store.deprecate(bullet.id, \"inverted to an anti-pattern\", avoid.id);\n ctx.report.inverted.push({ from: bullet.id, to: avoid.id });\n }\n}\n","import type { Embedder } from \"@titan-design/embed\";\nimport { gatherFailOpen, vectorRetriever, type Degradation, type VectorIndex } from \"@titan-design/retrieval\";\nimport { scorePlaybook } from \"./playbook.js\";\nimport type { PlaybookStore } from \"./store.js\";\nimport { tokenize } from \"./text.js\";\nimport type { BulletScope, ScoredBullet } from \"./types.js\";\n\nexport interface SemanticOptions {\n embedder: Embedder;\n index: VectorIndex;\n /** Share of relevance taken from vector similarity; the rest is keyword score. */\n weight?: number;\n timeoutMs?: number;\n}\n\nexport interface RecallOptions {\n limit?: number;\n /** Extra tags to match on top of the query's own tokens. */\n tags?: string[];\n /** Keep bullets scoped `global` or to this scope. */\n scope?: BulletScope;\n now?: Date;\n /** Filter on relevance, not final score, so a low-confidence but topical bullet still surfaces. */\n minRelevance?: number;\n semantic?: SemanticOptions;\n}\n\nexport interface RecalledBullet extends ScoredBullet {\n keywordScore: number;\n semanticScore: number | null;\n relevanceScore: number;\n finalScore: number;\n}\n\nexport interface RecallResult {\n bullets: RecalledBullet[];\n antiPatterns: RecalledBullet[];\n deprecatedWarnings: RecalledBullet[];\n /** Why semantic scoring fell back to keywords, if it did. Never silent. */\n degraded: Degradation[];\n}\n\nconst EXACT_TOKEN = 3;\nconst SUBSTRING = 1;\nconst TAG_MATCH = 5;\nconst SCORE_FLOOR = 0.1;\n\n/**\n * cass-memory's `cm context`: keyword score blended with optional vector\n * similarity, multiplied by the bullet's floored confidence, so what comes back\n * is topical first and trusted second.\n */\nexport async function recall(store: PlaybookStore, query: string, options: RecallOptions = {}): Promise<RecallResult> {\n const now = options.now ?? new Date();\n const limit = options.limit ?? 10;\n const minRelevance = options.minRelevance ?? 0.1;\n const candidates = scorePlaybook(store, now, { includeRetired: true }).filter((b) => inScope(b, options.scope));\n const semantic = await semanticScores(query, candidates.length, options.semantic);\n const ranked = candidates\n .map((b) => rank(b, query, options, semantic))\n .filter((b) => b.relevanceScore >= minRelevance)\n .sort(byScore);\n const live = ranked.filter((b) => b.state !== \"retired\");\n return {\n bullets: live.filter((b) => !b.isNegative).slice(0, limit),\n antiPatterns: live.filter((b) => b.isNegative).slice(0, limit),\n deprecatedWarnings: ranked.filter((b) => b.state === \"retired\").slice(0, limit),\n degraded: semantic.degraded,\n };\n}\n\nfunction inScope(bullet: ScoredBullet, scope: BulletScope | undefined): boolean {\n return scope === undefined || bullet.scope === \"global\" || bullet.scope === scope;\n}\n\nexport function keywordScore(content: string, tags: readonly string[], query: string, extraTags: readonly string[] = []): number {\n const contentTokens = tokenize(content);\n const lower = content.toLowerCase();\n const tagSet = new Set(tags.map((t) => t.toLowerCase()));\n let score = 0;\n for (const token of tokenize(query)) {\n if (contentTokens.has(token)) score += EXACT_TOKEN;\n else if (lower.includes(token)) score += SUBSTRING;\n if (tagSet.has(token)) score += TAG_MATCH;\n }\n for (const tag of extraTags) if (tagSet.has(tag.toLowerCase())) score += TAG_MATCH;\n return score;\n}\n\ninterface SemanticScores {\n similarity: Map<string, number>;\n weight: number;\n degraded: Degradation[];\n}\n\nasync function semanticScores(query: string, count: number, options: SemanticOptions | undefined): Promise<SemanticScores> {\n if (!options || count === 0) return { similarity: new Map(), weight: 0, degraded: [] };\n const retriever = vectorRetriever(options.embedder, options.index, { name: \"memory-vector\" });\n const { lists, degraded } = await gatherFailOpen([retriever], query, { limit: count, timeoutMs: options.timeoutMs });\n const similarity = new Map<string, number>();\n for (const hit of lists[0]?.hits ?? []) similarity.set(hit.id, hit.score ?? 0);\n return { similarity, weight: degraded.length === 0 ? (options.weight ?? 0.6) : 0, degraded };\n}\n\nfunction rank(bullet: ScoredBullet, query: string, options: RecallOptions, semantic: SemanticScores): RecalledBullet {\n const keyword = keywordScore(bullet.content, bullet.tags, query, options.tags);\n const similarity = semantic.similarity.get(bullet.id);\n const semanticScore = semantic.weight === 0 ? null : (similarity ?? 0);\n const relevanceScore = keyword * (1 - semantic.weight) + (semanticScore ?? 0) * semantic.weight;\n return { ...bullet, keywordScore: keyword, semanticScore, relevanceScore, finalScore: relevanceScore * Math.max(SCORE_FLOOR, bullet.effectiveScore) };\n}\n\nfunction byScore(a: RecalledBullet, b: RecalledBullet): number {\n return b.finalScore - a.finalScore || b.relevanceScore - a.relevanceScore || a.id.localeCompare(b.id);\n}\n","import { fromFloat32Buffer, toFloat32Buffer, type Embedder } from \"@titan-design/embed\";\nimport { BruteForceVectorIndex, type VectorIndex } from \"@titan-design/retrieval\";\nimport { CacheBlobTable, type Db } from \"@titan-design/store-sqlite\";\nimport { DEFAULT_MEMORY_TABLES, type MemoryTables } from \"./schema.js\";\nimport { normalizeContent } from \"./text.js\";\nimport type { Bullet } from \"./types.js\";\n\nexport interface MemoryVectorsOptions {\n tables?: MemoryTables;\n namespace?: string;\n}\n\n/**\n * Bullet embeddings in cache_blob, keyed by normalized content and the\n * embedder's model, so a re-worded bullet re-embeds and everything else is a\n * cache hit. The index is rebuilt from the cache; nothing is stored twice.\n */\nexport class MemoryVectors {\n private readonly cache: CacheBlobTable;\n private readonly namespace: string;\n\n constructor(\n db: Db,\n private readonly embedder: Embedder,\n options: MemoryVectorsOptions = {},\n ) {\n this.cache = new CacheBlobTable(db, { name: (options.tables ?? DEFAULT_MEMORY_TABLES).cacheBlob });\n this.namespace = options.namespace ?? \"memory:bullet\";\n }\n\n /** Embed every bullet the cache does not have, in one call. Returns how many were computed. */\n async ensure(bullets: readonly Bullet[]): Promise<number> {\n const missing = bullets.filter((b) => this.cache.get(this.keyFor(b)) === undefined);\n if (missing.length === 0) return 0;\n const vectors = await this.embedder.embed(missing.map((b) => normalizeContent(b.content)));\n missing.forEach((bullet, i) => {\n const vector = vectors[i];\n if (vector) this.cache.put(this.keyFor(bullet), toFloat32Buffer(vector), { bulletId: bullet.id });\n });\n return missing.length;\n }\n\n /** A searchable index over these bullets, embedding any misses first. */\n async index(bullets: readonly Bullet[]): Promise<VectorIndex> {\n await this.ensure(bullets);\n const index = new BruteForceVectorIndex();\n for (const bullet of bullets) {\n const hit = this.cache.get(this.keyFor(bullet));\n if (hit) index.add(bullet.id, fromFloat32Buffer(hit.value));\n }\n return index;\n }\n\n private keyFor(bullet: Bullet): { namespace: string; model: string; text: string } {\n return { namespace: this.namespace, model: this.embedder.model, text: normalizeContent(bullet.content) };\n }\n}\n","import type { WatermarkTable } from \"@titan-design/store-sqlite\";\nimport { curate, type CurateOptions, type CurationReport } from \"./curate.js\";\nimport type { PlaybookStore } from \"./store.js\";\nimport { normalizeContent } from \"./text.js\";\nimport { PlaybookDeltaSchema, type Bullet, type ParsedDelta } from \"./types.js\";\n\nexport interface ReflectInput {\n sessionRef: string;\n /** Whatever the caller distilled from the session: a diary, a subgraph summary, raw notes. */\n diary: string;\n iteration: number;\n bullets: Bullet[];\n priorDeltas: ParsedDelta[];\n}\n\n/** The one stage that may call a model. Returns anything; the deltas are validated here, not trusted. */\nexport type Reflector = (input: ReflectInput) => Promise<unknown>;\n\nexport interface ReflectSessionInput {\n sessionRef: string;\n diary: string;\n byteOffset?: number;\n}\n\nexport interface ReflectOptions extends Omit<CurateOptions, \"provenance\"> {\n maxIterations?: number;\n maxDeltas?: number;\n}\n\nexport interface RejectedDelta {\n iteration: number;\n index: number;\n reason: string;\n}\n\nexport interface ReflectionResult {\n deltas: ParsedDelta[];\n rejected: RejectedDelta[];\n iterations: number;\n report: CurationReport;\n}\n\nexport interface ReflectDeps {\n store: PlaybookStore;\n /** When present, the session's offset is recorded so incremental runs know where they stopped. */\n watermark?: WatermarkTable;\n}\n\n/**\n * cass-memory's multi-iteration reflect loop: feed the growing playbook and the\n * deltas so far back in, stop early on nothing new or at the cap, then curate\n * with provenance stamped from the input, never from the model.\n */\nexport async function reflectSession(deps: ReflectDeps, input: ReflectSessionInput, reflector: Reflector, options: ReflectOptions = {}): Promise<ReflectionResult> {\n const maxIterations = options.maxIterations ?? 3;\n const maxDeltas = options.maxDeltas ?? 50;\n const deltas: ParsedDelta[] = [];\n const rejected: RejectedDelta[] = [];\n const seen = new Set<string>();\n let iterations = 0;\n while (iterations < maxIterations && deltas.length < maxDeltas) {\n iterations++;\n const raw = await reflector({ sessionRef: input.sessionRef, diary: input.diary, iteration: iterations, bullets: deps.store.list(), priorDeltas: [...deltas] });\n const fresh = parseDeltas(raw, seen, iterations, rejected);\n if (fresh.length === 0) break;\n deltas.push(...fresh.slice(0, maxDeltas - deltas.length));\n }\n const report = curate(deps.store, deltas, { ...curateOptions(options), provenance: { sessionRef: input.sessionRef, byteOffset: input.byteOffset } });\n advanceWatermark(deps.watermark, input);\n return { deltas, rejected, iterations, report };\n}\n\nfunction curateOptions(options: ReflectOptions): Omit<CurateOptions, \"provenance\"> {\n const { now, nearDupThreshold, conflictThreshold, inversion } = options;\n return { now, nearDupThreshold, conflictThreshold, inversion };\n}\n\nexport function parseDeltas(raw: unknown, seen: Set<string>, iteration: number, rejected: RejectedDelta[]): ParsedDelta[] {\n if (!Array.isArray(raw)) {\n rejected.push({ iteration, index: -1, reason: \"reflector did not return an array\" });\n return [];\n }\n const fresh: ParsedDelta[] = [];\n raw.forEach((item, index) => {\n const parsed = PlaybookDeltaSchema.safeParse(item);\n if (!parsed.success) {\n rejected.push({ iteration, index, reason: parsed.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \") });\n return;\n }\n const key = deltaKey(parsed.data);\n if (seen.has(key)) return;\n seen.add(key);\n fresh.push(parsed.data);\n });\n return fresh;\n}\n\nfunction deltaKey(delta: ParsedDelta): string {\n switch (delta.type) {\n case \"add\":\n case \"replace\":\n case \"merge\":\n return `${delta.type}:${normalizeContent(delta.content)}`;\n default:\n return `${delta.type}:${delta.bulletId}`;\n }\n}\n\nfunction advanceWatermark(watermark: WatermarkTable | undefined, input: ReflectSessionInput): void {\n if (!watermark) return;\n watermark.ensure(input.sessionRef);\n watermark.advance(input.sessionRef, { lastOffset: input.byteOffset ?? 0 });\n}\n"],"mappings":"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","names":["quoteIdent","quoteIdent"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/schema.ts","../src/scoring.ts","../src/text.ts","../src/store.ts","../src/playbook.ts","../src/curate.ts","../src/recall.ts","../src/vectors.ts","../src/reflect.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * The playbook data model, borrowed from cass-memory's `PlaybookBullet`. Counts\n * are never stored: they are derived from the append-only feedback log at read\n * time, so decay parameters can change without re-running reflection.\n */\nexport const BULLET_SCOPES = [\"global\", \"workspace\", \"language\", \"framework\", \"task\"] as const;\nexport const BULLET_TYPES = [\"rule\", \"anti-pattern\"] as const;\nexport const BULLET_KINDS = [\"project_convention\", \"stack_pattern\", \"workflow_rule\", \"anti_pattern\"] as const;\nexport const BULLET_SOURCES = [\"learned\", \"community\", \"manual\", \"custom\"] as const;\nexport const BULLET_STATES = [\"draft\", \"active\", \"retired\"] as const;\nexport const MATURITIES = [\"candidate\", \"established\", \"proven\", \"deprecated\"] as const;\n\nexport type BulletScope = (typeof BULLET_SCOPES)[number];\nexport type BulletType = (typeof BULLET_TYPES)[number];\nexport type BulletKind = (typeof BULLET_KINDS)[number];\nexport type BulletSource = (typeof BULLET_SOURCES)[number];\nexport type BulletState = (typeof BULLET_STATES)[number];\nexport type Maturity = (typeof MATURITIES)[number];\nexport type FeedbackType = \"helpful\" | \"harmful\";\n\n/** Where a bullet's evidence lives: a session ref plus a byte offset into its transcript. */\nexport interface Provenance {\n sessionRef: string;\n byteOffset?: number;\n}\n\nexport interface Bullet {\n id: string;\n content: string;\n category: string;\n tags: string[];\n scope: BulletScope;\n type: BulletType;\n kind: BulletKind;\n isNegative: boolean;\n source: BulletSource;\n state: BulletState;\n maturity: Maturity;\n pinned: boolean;\n pinnedReason: string | null;\n /** Set when retired in favour of another bullet; mirrored by a `supersedes` edge. */\n replacedBy: string | null;\n deprecatedAt: string | null;\n deprecationReason: string | null;\n halfLifeDays: number;\n sourceSessions: Provenance[];\n reasoning: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface NewBullet {\n id?: string;\n content: string;\n category?: string;\n tags?: string[];\n scope?: BulletScope;\n type?: BulletType;\n kind?: BulletKind;\n isNegative?: boolean;\n source?: BulletSource;\n state?: BulletState;\n pinned?: boolean;\n pinnedReason?: string | null;\n halfLifeDays?: number;\n sourceSessions?: Provenance[];\n reasoning?: string | null;\n}\n\n/** One line of the immutable feedback log. */\nexport interface FeedbackEvent {\n id: number;\n bulletId: string;\n type: FeedbackType;\n at: string;\n sessionRef: string | null;\n reason: string | null;\n}\n\nexport interface DecayedCounts {\n helpful: number;\n harmful: number;\n}\n\nexport interface ScoredBullet extends Bullet {\n helpfulCount: number;\n harmfulCount: number;\n decayedHelpful: number;\n decayedHarmful: number;\n effectiveScore: number;\n /** Latest feedback, or creation when there is none; the input to staleness. */\n lastEvidenceAt: string;\n}\n\n/**\n * What a reflector proposes. Provenance is deliberately absent: the curator\n * stamps it from the session it is actually processing, never from the model.\n */\nconst addDelta = z.object({\n type: z.literal(\"add\"),\n content: z.string().min(1),\n category: z.string().min(1).default(\"general\"),\n tags: z.array(z.string()).default([]),\n scope: z.enum(BULLET_SCOPES).default(\"workspace\"),\n kind: z.enum(BULLET_KINDS).default(\"workflow_rule\"),\n isNegative: z.boolean().default(false),\n reasoning: z.string().optional(),\n});\nconst feedbackDelta = (type: FeedbackType) => z.object({ type: z.literal(type), bulletId: z.string().min(1), reason: z.string().optional() });\nconst replaceDelta = z.object({ type: z.literal(\"replace\"), bulletId: z.string().min(1), content: z.string().min(1), reasoning: z.string().optional() });\nconst deprecateDelta = z.object({ type: z.literal(\"deprecate\"), bulletId: z.string().min(1), reason: z.string().min(1) });\nconst mergeDelta = z.object({ type: z.literal(\"merge\"), bulletIds: z.array(z.string().min(1)).min(2), content: z.string().min(1), reasoning: z.string().optional() });\n\nexport const PlaybookDeltaSchema = z.discriminatedUnion(\"type\", [\n addDelta,\n feedbackDelta(\"helpful\"),\n feedbackDelta(\"harmful\"),\n replaceDelta,\n deprecateDelta,\n mergeDelta,\n]);\n/** What callers and reflectors write; defaults may be omitted. */\nexport type PlaybookDelta = z.input<typeof PlaybookDeltaSchema>;\n/** What the curator works on, after parsing fills the defaults in. */\nexport type ParsedDelta = z.output<typeof PlaybookDeltaSchema>;\nexport type AddDelta = z.output<typeof addDelta>;\n","import { SQL_NOW, kitDdl, quoteIdent, type Migration } from \"@titan-design/store-sqlite\";\n\n/**\n * Four kit tables plus one domain table. Bullets are interval entities, the\n * `supersedes` relation lives in the edge table, embeddings in cache_blob keyed\n * by content hash, and per-session progress in the watermark table.\n */\nexport interface MemoryTables {\n entity: string;\n edge: string;\n cacheBlob: string;\n watermark: string;\n feedback: string;\n}\n\nexport const DEFAULT_MEMORY_TABLES: MemoryTables = {\n entity: \"memory_entity\",\n edge: \"memory_edge\",\n cacheBlob: \"memory_cache\",\n watermark: \"memory_watermark\",\n feedback: \"memory_feedback\",\n};\n\nexport const BULLET_KIND = \"bullet\";\nexport const BLOCKED_KIND = \"blocked\";\nexport const SUPERSEDES = \"supersedes\";\n\nexport function feedbackTableDdl(name: string = DEFAULT_MEMORY_TABLES.feedback): string {\n const t = quoteIdent(name);\n return `\n CREATE TABLE IF NOT EXISTS ${t} (\n id INTEGER PRIMARY KEY,\n bullet_ref TEXT NOT NULL,\n type TEXT NOT NULL,\n at TEXT NOT NULL DEFAULT (${SQL_NOW}),\n session_ref TEXT,\n reason TEXT\n );\n CREATE INDEX IF NOT EXISTS ${quoteIdent(`idx_${name}_bullet`)} ON ${t}(bullet_ref, at);\n `;\n}\n\nexport function memoryDdl(tables: MemoryTables = DEFAULT_MEMORY_TABLES): string {\n const kit = kitDdl({ entity: tables.entity, edge: tables.edge, cacheBlob: tables.cacheBlob, watermark: tables.watermark });\n return `${kit}\\n${feedbackTableDdl(tables.feedback)}`;\n}\n\n/** Drop into a product's migration list so the playbook shares its database. */\nexport function memoryMigration(version: number, tables: MemoryTables = DEFAULT_MEMORY_TABLES): Migration {\n return { version, name: `memory:${tables.entity}`, up: (db) => db.exec(memoryDdl(tables)) };\n}\n","import type { DecayedCounts, FeedbackEvent, Maturity } from \"./types.js\";\n\n/** cass-memory's exact numbers; a bullet may override the half-life, nothing else. */\nexport const DEFAULT_HALF_LIFE_DAYS = 90;\nexport const HARMFUL_WEIGHT = 4;\nexport const HARD_DEPRECATE_SCORE = -3;\nexport const MATURITY_MULTIPLIER: Record<Maturity, number> = { candidate: 0.5, established: 1, proven: 1.5, deprecated: 0 };\n\nconst RANK: Record<Maturity, number> = { deprecated: 0, candidate: 1, established: 2, proven: 3 };\nconst BY_RANK: Maturity[] = [\"deprecated\", \"candidate\", \"established\", \"proven\"];\nconst DAY_MS = 86_400_000;\n\nexport function decayedValue(at: string, now: Date, halfLifeDays: number = DEFAULT_HALF_LIFE_DAYS): number {\n const ageDays = Math.max(0, now.getTime() - Date.parse(at)) / DAY_MS;\n return 0.5 ** (ageDays / halfLifeDays);\n}\n\nexport function decayedCounts(events: readonly FeedbackEvent[], now: Date, halfLifeDays: number = DEFAULT_HALF_LIFE_DAYS): DecayedCounts {\n const counts = { helpful: 0, harmful: 0 };\n for (const event of events) counts[event.type] += decayedValue(event.at, now, halfLifeDays);\n return counts;\n}\n\nexport function effectiveScore(counts: DecayedCounts, maturity: Maturity): number {\n return (counts.helpful - HARMFUL_WEIGHT * counts.harmful) * MATURITY_MULTIPLIER[maturity];\n}\n\n/** The maturity the decayed counts alone would assign, ignoring history. */\nexport function maturityFor(counts: DecayedCounts): Maturity {\n const total = counts.helpful + counts.harmful;\n const harmfulRatio = total === 0 ? 0 : counts.harmful / total;\n if (total < 3) return \"candidate\";\n if (harmfulRatio > 0.3) return \"deprecated\";\n if (counts.helpful >= 10 && harmfulRatio < 0.1) return \"proven\";\n return \"established\";\n}\n\n/**\n * Promotion jumps straight to the earned rung; demotion drops one rung per\n * pass, except that a score below the hard floor deprecates outright. Pinned\n * bullets never move.\n */\nexport function nextMaturity(current: Maturity, counts: DecayedCounts, pinned: boolean): Maturity {\n if (pinned || current === \"deprecated\") return current;\n if (effectiveScore(counts, current) < HARD_DEPRECATE_SCORE) return \"deprecated\";\n const target = maturityFor(counts);\n if (RANK[target] > RANK[current]) return target;\n if (RANK[target] < RANK[current]) return BY_RANK[RANK[current] - 1]!;\n return current;\n}\n\nexport interface StalenessOptions {\n /** Days without any feedback before a bullet is flagged for re-validation. */\n staleAfterDays?: number;\n}\n\n/** Staleness is about silence, not decay: a bullet nobody has confirmed or refuted lately. */\nexport function isStale(lastEvidenceAt: string, now: Date, { staleAfterDays = 180 }: StalenessOptions = {}): boolean {\n return now.getTime() - Date.parse(lastEvidenceAt) > staleAfterDays * DAY_MS;\n}\n","import { contentHashOf } from \"@titan-design/store-sqlite\";\n\nconst TOKEN = /[a-z0-9_]+/g;\nconst NEGATION = /\\b(never|don'?t|do not|avoid|not|no|stop|without)\\b/i;\n\n/** Lowercase alphanumeric tokens of two or more characters, as a set. */\nexport function tokenize(text: string): Set<string> {\n const out = new Set<string>();\n for (const match of text.toLowerCase().matchAll(TOKEN)) if (match[0].length >= 2) out.add(match[0]);\n return out;\n}\n\n/** Case- and whitespace-insensitive form used for exact-duplicate detection. */\nexport function normalizeContent(text: string): string {\n return text.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\nexport function contentKey(text: string): string {\n return contentHashOf(normalizeContent(text));\n}\n\nexport function jaccard(a: string, b: string): number {\n const ta = tokenize(a);\n const tb = tokenize(b);\n if (ta.size === 0 && tb.size === 0) return 1;\n let shared = 0;\n for (const token of ta) if (tb.has(token)) shared++;\n return shared / (ta.size + tb.size - shared);\n}\n\n/** Whether a rule is phrased as a prohibition; used only to flag likely conflicts, never to block. */\nexport function isNegated(text: string): boolean {\n return NEGATION.test(text);\n}\n","import { EdgeTable, EntityTable, quoteIdent, refKind, type Db, type EntityRow } from \"@titan-design/store-sqlite\";\nimport { randomUUID } from \"node:crypto\";\nimport { BLOCKED_KIND, BULLET_KIND, DEFAULT_MEMORY_TABLES, SUPERSEDES, type MemoryTables } from \"./schema.js\";\nimport { DEFAULT_HALF_LIFE_DAYS } from \"./scoring.js\";\nimport type { Bullet, FeedbackEvent, FeedbackType, NewBullet } from \"./types.js\";\n\nexport const bulletRef = refKind(\"memory\");\nconst blockedRef = refKind(\"memory-blocked\");\n\nexport interface PlaybookStoreOptions {\n tables?: MemoryTables;\n now?: () => Date;\n}\n\nexport interface FeedbackInput {\n sessionRef?: string | null;\n reason?: string | null;\n at?: string;\n}\n\nexport interface BlockedPattern {\n pattern: string;\n reason: string;\n blockedAt: string;\n}\n\ninterface RawFeedbackRow {\n id: number;\n bullet_ref: string;\n type: FeedbackType;\n at: string;\n session_ref: string | null;\n reason: string | null;\n}\n\ntype Attrs = Omit<Bullet, \"id\" | \"content\" | \"category\">;\n\nexport class BulletNotFound extends Error {\n constructor(id: string) {\n super(`bullet not found: ${id}`);\n this.name = \"BulletNotFound\";\n }\n}\n\n/**\n * Bullets are interval entities (`kind = bullet`, name = category, attrs = the\n * rest), so retirement is an attrs change plus a `supersedes` edge, never a\n * delete. Feedback is an append-only log; nothing here ever updates or removes\n * an event.\n */\nexport class PlaybookStore {\n readonly tables: MemoryTables;\n private readonly entities: EntityTable;\n private readonly edges: EdgeTable;\n private readonly now: () => Date;\n private readonly insertFeedback;\n private readonly feedbackByBullet;\n private readonly allFeedback;\n\n constructor(db: Db, options: PlaybookStoreOptions = {}) {\n this.tables = options.tables ?? DEFAULT_MEMORY_TABLES;\n this.now = options.now ?? (() => new Date());\n this.entities = new EntityTable(db, { name: this.tables.entity });\n this.edges = new EdgeTable(db, { name: this.tables.edge });\n const f = quoteIdent(this.tables.feedback);\n this.insertFeedback = db.prepare(`INSERT INTO ${f} (bullet_ref, type, at, session_ref, reason) VALUES (?, ?, ?, ?, ?)`);\n this.feedbackByBullet = db.prepare(`SELECT * FROM ${f} WHERE bullet_ref = ? ORDER BY at, id`);\n this.allFeedback = db.prepare(`SELECT * FROM ${f} ORDER BY at, id`);\n }\n\n add(input: NewBullet): Bullet {\n const at = this.now().toISOString();\n const bullet = materialize(input, at);\n this.write(bullet);\n return bullet;\n }\n\n get(id: string): Bullet | undefined {\n const row = this.entities.get(bulletRef(id));\n return row === undefined || row.kind !== BULLET_KIND ? undefined : toBullet(row);\n }\n\n require(id: string): Bullet {\n const bullet = this.get(id);\n if (bullet === undefined) throw new BulletNotFound(id);\n return bullet;\n }\n\n /** Live bullets only, unless `includeRetired`; ordered by id for determinism. */\n list({ includeRetired = false }: { includeRetired?: boolean } = {}): Bullet[] {\n const all = this.entities.listByKind(BULLET_KIND).map(toBullet);\n return includeRetired ? all : all.filter((b) => b.state !== \"retired\");\n }\n\n update(id: string, patch: Partial<Omit<Bullet, \"id\" | \"createdAt\">>): Bullet {\n const next = { ...this.require(id), ...patch, updatedAt: this.now().toISOString() };\n this.write(next);\n return next;\n }\n\n /** Retire a bullet. With `replacedBy`, also assert `replacedBy -supersedes-> id`. */\n deprecate(id: string, reason: string, replacedBy: string | null = null): Bullet {\n const at = this.now().toISOString();\n const bullet = this.update(id, { state: \"retired\", maturity: \"deprecated\", replacedBy, deprecatedAt: at, deprecationReason: reason });\n if (replacedBy !== null) this.edges.assert({ sourceRef: bulletRef(replacedBy), relation: SUPERSEDES, targetRef: bulletRef(id), tValid: at });\n return bullet;\n }\n\n /** Ids of the bullets this one replaced, following live `supersedes` edges. */\n supersededBy(id: string): string[] {\n return this.edges.from(bulletRef(id)).filter((e) => e.relation === SUPERSEDES).map((e) => e.targetRef.slice(\"memory:\".length));\n }\n\n recordFeedback(id: string, type: FeedbackType, input: FeedbackInput = {}): FeedbackEvent {\n this.require(id);\n const at = input.at ?? this.now().toISOString();\n const info = this.insertFeedback.run(bulletRef(id), type, at, input.sessionRef ?? null, input.reason ?? null);\n return { id: Number(info.lastInsertRowid), bulletId: id, type, at, sessionRef: input.sessionRef ?? null, reason: input.reason ?? null };\n }\n\n feedbackFor(id: string): FeedbackEvent[] {\n return (this.feedbackByBullet.all(bulletRef(id)) as RawFeedbackRow[]).map(toEvent);\n }\n\n /** Every event grouped by bullet id, one query, for scoring the whole playbook. */\n feedbackByBulletId(): Map<string, FeedbackEvent[]> {\n const grouped = new Map<string, FeedbackEvent[]>();\n for (const event of (this.allFeedback.all() as RawFeedbackRow[]).map(toEvent)) {\n const list = grouped.get(event.bulletId) ?? [];\n list.push(event);\n grouped.set(event.bulletId, list);\n }\n return grouped;\n }\n\n /** A content pattern a human has banned; the curator refuses to re-learn anything near it. */\n block(pattern: string, reason: string): BlockedPattern {\n const blockedAt = this.now().toISOString();\n this.entities.upsert({ ref: blockedRef(randomUUID()), kind: BLOCKED_KIND, name: pattern, attrs: { reason, blockedAt }, tValid: blockedAt });\n return { pattern, reason, blockedAt };\n }\n\n blockedPatterns(): BlockedPattern[] {\n return this.entities.listByKind(BLOCKED_KIND).map((row) => ({\n pattern: row.name ?? \"\",\n reason: String(row.attrs?.reason ?? \"\"),\n blockedAt: String(row.attrs?.blockedAt ?? row.tValid),\n }));\n }\n\n private write(bullet: Bullet): void {\n const { id, content, category, ...attrs } = bullet;\n this.entities.upsert({ ref: bulletRef(id), kind: BULLET_KIND, name: category, attrs: { ...attrs, content }, tValid: bullet.createdAt });\n }\n}\n\nexport function newBulletId(now: Date = new Date()): string {\n return `b-${now.getTime().toString(36)}-${randomUUID().slice(0, 6)}`;\n}\n\nfunction materialize(input: NewBullet, at: string): Bullet {\n return {\n id: input.id ?? newBulletId(new Date(at)),\n content: input.content,\n category: input.category ?? \"general\",\n tags: [...(input.tags ?? [])],\n scope: input.scope ?? \"workspace\",\n type: input.type ?? (input.isNegative ? \"anti-pattern\" : \"rule\"),\n kind: input.kind ?? (input.isNegative ? \"anti_pattern\" : \"workflow_rule\"),\n isNegative: input.isNegative ?? false,\n source: input.source ?? \"learned\",\n state: input.state ?? \"active\",\n maturity: \"candidate\",\n pinned: input.pinned ?? false,\n pinnedReason: input.pinnedReason ?? null,\n replacedBy: null,\n deprecatedAt: null,\n deprecationReason: null,\n halfLifeDays: input.halfLifeDays ?? DEFAULT_HALF_LIFE_DAYS,\n sourceSessions: [...(input.sourceSessions ?? [])],\n reasoning: input.reasoning ?? null,\n createdAt: at,\n updatedAt: at,\n };\n}\n\nfunction toBullet(row: EntityRow): Bullet {\n const attrs = (row.attrs ?? {}) as Attrs & { content: string };\n const { content, ...rest } = attrs;\n return { id: row.ref.slice(\"memory:\".length), content, category: row.name ?? \"general\", ...rest };\n}\n\nfunction toEvent(raw: RawFeedbackRow): FeedbackEvent {\n return { id: raw.id, bulletId: raw.bullet_ref.slice(\"memory:\".length), type: raw.type, at: raw.at, sessionRef: raw.session_ref, reason: raw.reason };\n}\n","import { decayedCounts, effectiveScore, isStale, nextMaturity, type StalenessOptions } from \"./scoring.js\";\nimport type { PlaybookStore } from \"./store.js\";\nimport type { Bullet, FeedbackEvent, Maturity, ScoredBullet } from \"./types.js\";\n\nexport function scoreBullet(bullet: Bullet, events: readonly FeedbackEvent[], now: Date): ScoredBullet {\n const counts = decayedCounts(events, now, bullet.halfLifeDays);\n const last = events[events.length - 1];\n return {\n ...bullet,\n helpfulCount: events.filter((e) => e.type === \"helpful\").length,\n harmfulCount: events.filter((e) => e.type === \"harmful\").length,\n decayedHelpful: counts.helpful,\n decayedHarmful: counts.harmful,\n effectiveScore: effectiveScore(counts, bullet.maturity),\n lastEvidenceAt: last?.at ?? bullet.createdAt,\n };\n}\n\nexport interface ScoreOptions {\n includeRetired?: boolean;\n}\n\n/** Every bullet with its decayed counts and score as of `now`. One feedback query for the whole playbook. */\nexport function scorePlaybook(store: PlaybookStore, now: Date, options: ScoreOptions = {}): ScoredBullet[] {\n const feedback = store.feedbackByBulletId();\n return store.list(options).map((bullet) => scoreBullet(bullet, feedback.get(bullet.id) ?? [], now));\n}\n\nexport interface MaturityChange {\n bulletId: string;\n from: Maturity;\n to: Maturity;\n}\n\n/** The promotion/demotion pass. A bullet that lands on `deprecated` is retired. */\nexport function applyMaturity(store: PlaybookStore, now: Date): MaturityChange[] {\n const changes: MaturityChange[] = [];\n for (const bullet of scorePlaybook(store, now)) {\n const to = nextMaturity(bullet.maturity, { helpful: bullet.decayedHelpful, harmful: bullet.decayedHarmful }, bullet.pinned);\n if (to === bullet.maturity) continue;\n if (to === \"deprecated\") store.deprecate(bullet.id, \"auto-demoted below the confidence floor\");\n else store.update(bullet.id, { maturity: to });\n changes.push({ bulletId: bullet.id, from: bullet.maturity, to });\n }\n return changes;\n}\n\n/** Live bullets nobody has confirmed or refuted lately: candidates for re-validation, not for removal. */\nexport function staleBullets(store: PlaybookStore, now: Date, options: StalenessOptions = {}): ScoredBullet[] {\n return scorePlaybook(store, now).filter((b) => !b.pinned && isStale(b.lastEvidenceAt, now, options));\n}\n","import { applyMaturity, scorePlaybook, type MaturityChange } from \"./playbook.js\";\nimport type { BlockedPattern, PlaybookStore } from \"./store.js\";\nimport { contentKey, isNegated, jaccard, normalizeContent } from \"./text.js\";\nimport { PlaybookDeltaSchema, type AddDelta, type Bullet, type ParsedDelta, type PlaybookDelta, type Provenance, type ScoredBullet } from \"./types.js\";\n\nexport interface InversionOptions {\n /** Decayed harmful mass a rule needs before it can flip into an anti-pattern. */\n minHarmful?: number;\n /** And by how much harmful must outweigh helpful. */\n harmfulToHelpfulRatio?: number;\n}\n\nexport interface CurateOptions {\n /** Stamped onto every bullet this batch creates. Never taken from the deltas themselves. */\n provenance?: Provenance;\n now?: () => Date;\n /** Jaccard similarity at which an `add` folds into a `helpful` on the existing bullet. */\n nearDupThreshold?: number;\n /** Jaccard similarity at which two rules are flagged as possibly contradicting. */\n conflictThreshold?: number;\n inversion?: InversionOptions;\n}\n\nexport interface Conflict {\n bulletId: string;\n otherId: string;\n reason: string;\n}\n\nexport interface CurationReport {\n added: string[];\n reinforced: string[];\n penalized: string[];\n deprecated: string[];\n inverted: { from: string; to: string }[];\n blocked: string[];\n skipped: { delta: ParsedDelta; reason: string }[];\n conflicts: Conflict[];\n maturityChanges: MaturityChange[];\n}\n\ninterface Ctx {\n store: PlaybookStore;\n report: CurationReport;\n now: () => Date;\n provenance: Provenance[];\n nearDup: number;\n conflict: number;\n inversion: Required<InversionOptions>;\n blocked: BlockedPattern[];\n /** `type:bulletId` of every vote counted so far in this batch. */\n voted: Set<string>;\n}\n\n/**\n * cass-memory's curator: zero LLM, fully deterministic. Dedup by content hash\n * and near-dup Jaccard, apply the batch, invert rules that keep hurting into\n * `AVOID:` anti-patterns, then run the maturity pass.\n */\nexport function curate(store: PlaybookStore, deltas: readonly PlaybookDelta[], options: CurateOptions = {}): CurationReport {\n const ctx = makeContext(store, options);\n const parsed = deltas.map((delta) => PlaybookDeltaSchema.parse(delta));\n for (const delta of dedupeDeltas(parsed, ctx.report)) applyDelta(ctx, delta);\n invertHarmfulRules(ctx);\n ctx.report.maturityChanges = applyMaturity(store, ctx.now());\n return ctx.report;\n}\n\nfunction makeContext(store: PlaybookStore, options: CurateOptions): Ctx {\n return {\n store,\n report: { added: [], reinforced: [], penalized: [], deprecated: [], inverted: [], blocked: [], skipped: [], conflicts: [], maturityChanges: [] },\n now: options.now ?? (() => new Date()),\n provenance: options.provenance ? [options.provenance] : [],\n nearDup: options.nearDupThreshold ?? 0.85,\n conflict: options.conflictThreshold ?? 0.5,\n inversion: { minHarmful: options.inversion?.minHarmful ?? 3, harmfulToHelpfulRatio: options.inversion?.harmfulToHelpfulRatio ?? 2 },\n blocked: store.blockedPatterns(),\n voted: new Set(),\n };\n}\n\nfunction dedupeDeltas(deltas: readonly ParsedDelta[], report: CurationReport): ParsedDelta[] {\n const seen = new Set<string>();\n const kept: ParsedDelta[] = [];\n for (const delta of deltas) {\n if (delta.type === \"helpful\" || delta.type === \"harmful\") {\n kept.push(delta);\n continue;\n }\n const key = delta.type === \"add\" ? contentKey(delta.content) : JSON.stringify(delta);\n if (seen.has(key)) report.skipped.push({ delta, reason: \"duplicate delta\" });\n else {\n seen.add(key);\n kept.push(delta);\n }\n }\n return kept;\n}\n\nfunction applyDelta(ctx: Ctx, delta: ParsedDelta): void {\n switch (delta.type) {\n case \"add\":\n return applyAdd(ctx, delta);\n case \"helpful\":\n case \"harmful\":\n return applyFeedback(ctx, delta);\n case \"replace\":\n return applyReplace(ctx, delta);\n case \"deprecate\":\n return applyDeprecate(ctx, delta);\n case \"merge\":\n return applyMerge(ctx, delta);\n }\n}\n\nfunction applyAdd(ctx: Ctx, delta: AddDelta): void {\n if (isBlocked(ctx, delta.content)) {\n ctx.report.blocked.push(delta.content);\n return;\n }\n const live = ctx.store.list();\n const duplicate = findDuplicate(live, delta.content, ctx.nearDup);\n if (duplicate) {\n if (claimVote(ctx, \"helpful\", duplicate.id)) reinforce(ctx, duplicate.id, \"restated by a new add\");\n else ctx.report.skipped.push({ delta, reason: \"bullet already voted helpful in this batch\" });\n return;\n }\n const bullet = ctx.store.add({ ...addFields(delta), sourceSessions: ctx.provenance });\n ctx.report.added.push(bullet.id);\n detectConflicts(ctx, bullet, live);\n}\n\nfunction applyFeedback(ctx: Ctx, delta: Extract<ParsedDelta,{ type: \"helpful\" | \"harmful\" }>): void {\n if (!ctx.store.get(delta.bulletId)) {\n ctx.report.skipped.push({ delta, reason: \"unknown bullet\" });\n return;\n }\n if (!claimVote(ctx, delta.type, delta.bulletId)) {\n ctx.report.skipped.push({ delta, reason: `bullet already voted ${delta.type} in this batch` });\n return;\n }\n ctx.store.recordFeedback(delta.bulletId, delta.type, { sessionRef: ctx.provenance[0]?.sessionRef, reason: delta.reason });\n (delta.type === \"helpful\" ? ctx.report.reinforced : ctx.report.penalized).push(delta.bulletId);\n}\n\n/** Whatever the reason or source (explicit feedback or an add folding in), a bullet gets one vote of each kind per batch. */\nfunction claimVote(ctx: Ctx, type: \"helpful\" | \"harmful\", bulletId: string): boolean {\n const key = `${type}:${bulletId}`;\n if (ctx.voted.has(key)) return false;\n ctx.voted.add(key);\n return true;\n}\n\nfunction applyReplace(ctx: Ctx, delta: Extract<ParsedDelta,{ type: \"replace\" }>): void {\n const old = ctx.store.get(delta.bulletId);\n if (!old) {\n ctx.report.skipped.push({ delta, reason: \"unknown bullet\" });\n return;\n }\n const next = ctx.store.add({ ...inherit(old), content: delta.content, reasoning: delta.reasoning ?? old.reasoning, sourceSessions: [...old.sourceSessions, ...ctx.provenance] });\n ctx.store.deprecate(old.id, \"replaced\", next.id);\n ctx.report.added.push(next.id);\n ctx.report.deprecated.push(old.id);\n}\n\nfunction applyDeprecate(ctx: Ctx, delta: Extract<ParsedDelta,{ type: \"deprecate\" }>): void {\n if (!ctx.store.get(delta.bulletId)) {\n ctx.report.skipped.push({ delta, reason: \"unknown bullet\" });\n return;\n }\n ctx.store.deprecate(delta.bulletId, delta.reason);\n ctx.report.deprecated.push(delta.bulletId);\n}\n\nfunction applyMerge(ctx: Ctx, delta: Extract<ParsedDelta,{ type: \"merge\" }>): void {\n const olds = delta.bulletIds.map((id) => ctx.store.get(id));\n const first = olds[0];\n if (!first || olds.some((b) => b === undefined)) {\n ctx.report.skipped.push({ delta, reason: \"unknown bullet\" });\n return;\n }\n const present = olds as Bullet[];\n const next = ctx.store.add({\n ...inherit(first),\n content: delta.content,\n tags: [...new Set(present.flatMap((b) => b.tags))],\n reasoning: delta.reasoning ?? first.reasoning,\n sourceSessions: [...present.flatMap((b) => b.sourceSessions), ...ctx.provenance],\n });\n ctx.report.added.push(next.id);\n for (const old of present) {\n ctx.store.deprecate(old.id, \"merged\", next.id);\n ctx.report.deprecated.push(old.id);\n }\n}\n\nfunction addFields(delta: AddDelta): Omit<AddDelta, \"type\"> {\n const { content, category, tags, scope, kind, isNegative, reasoning } = delta;\n return { content, category, tags, scope, kind, isNegative, reasoning };\n}\n\nfunction inherit(bullet: Bullet): Pick<Bullet, \"category\" | \"tags\" | \"scope\" | \"type\" | \"kind\" | \"isNegative\" | \"source\" | \"halfLifeDays\"> {\n const { category, tags, scope, type, kind, isNegative, source, halfLifeDays } = bullet;\n return { category, tags, scope, type, kind, isNegative, source, halfLifeDays };\n}\n\nfunction reinforce(ctx: Ctx, id: string, reason: string): void {\n ctx.store.recordFeedback(id, \"helpful\", { sessionRef: ctx.provenance[0]?.sessionRef, reason });\n ctx.report.reinforced.push(id);\n}\n\nfunction isBlocked(ctx: Ctx, content: string): boolean {\n const normalized = normalizeContent(content);\n return ctx.blocked.some((b) => normalizeContent(b.pattern) === normalized || jaccard(b.pattern, content) >= ctx.nearDup);\n}\n\n/** A near-duplicate with flipped polarity is a contradiction, not a restatement, so it never folds. */\nfunction findDuplicate(live: readonly Bullet[], content: string, threshold: number): Bullet | undefined {\n const key = contentKey(content);\n const negated = isNegated(content);\n return (\n live.find((b) => contentKey(b.content) === key) ??\n live.find((b) => isNegated(b.content) === negated && jaccard(b.content, content) >= threshold)\n );\n}\n\n/** Heuristic only: similar wording where exactly one side is a prohibition. Warns, never blocks. */\nfunction detectConflicts(ctx: Ctx, bullet: Bullet, others: readonly Bullet[]): void {\n const negated = isNegated(bullet.content);\n for (const other of others) {\n if (isNegated(other.content) === negated || jaccard(bullet.content, other.content) < ctx.conflict) continue;\n ctx.report.conflicts.push({ bulletId: bullet.id, otherId: other.id, reason: \"similar wording with opposite polarity\" });\n }\n}\n\nfunction shouldInvert(ctx: Ctx, bullet: ScoredBullet): boolean {\n if (bullet.type !== \"rule\" || bullet.pinned || bullet.state !== \"active\") return false;\n return bullet.decayedHarmful >= ctx.inversion.minHarmful && bullet.decayedHarmful > ctx.inversion.harmfulToHelpfulRatio * bullet.decayedHelpful;\n}\n\nfunction invertHarmfulRules(ctx: Ctx): void {\n for (const bullet of scorePlaybook(ctx.store, ctx.now())) {\n if (!shouldInvert(ctx, bullet)) continue;\n const avoid = ctx.store.add({\n ...inherit(bullet),\n content: `AVOID: ${bullet.content}`,\n type: \"anti-pattern\",\n kind: \"anti_pattern\",\n isNegative: true,\n reasoning: \"inverted after repeated harmful feedback\",\n sourceSessions: [...bullet.sourceSessions, ...ctx.provenance],\n });\n ctx.store.deprecate(bullet.id, \"inverted to an anti-pattern\", avoid.id);\n ctx.report.inverted.push({ from: bullet.id, to: avoid.id });\n }\n}\n","import type { Embedder } from \"@titan-design/embed\";\nimport { gatherFailOpen, vectorRetriever, type Degradation, type VectorIndex } from \"@titan-design/retrieval\";\nimport { scorePlaybook } from \"./playbook.js\";\nimport type { PlaybookStore } from \"./store.js\";\nimport { tokenize } from \"./text.js\";\nimport type { BulletScope, ScoredBullet } from \"./types.js\";\n\nexport interface SemanticOptions {\n embedder: Embedder;\n index: VectorIndex;\n /** Share of relevance taken from vector similarity; the rest is keyword score. */\n weight?: number;\n timeoutMs?: number;\n}\n\nexport interface RecallOptions {\n limit?: number;\n /** Extra tags to match on top of the query's own tokens. */\n tags?: string[];\n /** Keep bullets scoped `global` or to this scope. */\n scope?: BulletScope;\n now?: Date;\n /** Filter on relevance, not final score, so a low-confidence but topical bullet still surfaces. */\n minRelevance?: number;\n semantic?: SemanticOptions;\n}\n\nexport interface RecalledBullet extends ScoredBullet {\n keywordScore: number;\n semanticScore: number | null;\n relevanceScore: number;\n finalScore: number;\n}\n\nexport interface RecallResult {\n bullets: RecalledBullet[];\n antiPatterns: RecalledBullet[];\n deprecatedWarnings: RecalledBullet[];\n /** Why semantic scoring fell back to keywords, if it did. Never silent. */\n degraded: Degradation[];\n}\n\nconst EXACT_TOKEN = 3;\nconst SUBSTRING = 1;\nconst TAG_MATCH = 5;\nconst SCORE_FLOOR = 0.1;\n\n/**\n * cass-memory's `cm context`: keyword score blended with optional vector\n * similarity, multiplied by the bullet's floored confidence, so what comes back\n * is topical first and trusted second.\n */\nexport async function recall(store: PlaybookStore, query: string, options: RecallOptions = {}): Promise<RecallResult> {\n const now = options.now ?? new Date();\n const limit = options.limit ?? 10;\n const minRelevance = options.minRelevance ?? 0.1;\n const candidates = scorePlaybook(store, now, { includeRetired: true }).filter((b) => inScope(b, options.scope));\n const semantic = await semanticScores(query, candidates.length, options.semantic);\n const ranked = candidates\n .map((b) => rank(b, query, options, semantic))\n .filter((b) => b.relevanceScore >= minRelevance)\n .sort(byScore);\n const live = ranked.filter((b) => b.state !== \"retired\");\n return {\n bullets: live.filter((b) => !b.isNegative).slice(0, limit),\n antiPatterns: live.filter((b) => b.isNegative).slice(0, limit),\n deprecatedWarnings: ranked.filter((b) => b.state === \"retired\").slice(0, limit),\n degraded: semantic.degraded,\n };\n}\n\nfunction inScope(bullet: ScoredBullet, scope: BulletScope | undefined): boolean {\n return scope === undefined || bullet.scope === \"global\" || bullet.scope === scope;\n}\n\nexport function keywordScore(content: string, tags: readonly string[], query: string, extraTags: readonly string[] = []): number {\n const contentTokens = tokenize(content);\n const lower = content.toLowerCase();\n const tagSet = new Set(tags.map((t) => t.toLowerCase()));\n let score = 0;\n for (const token of tokenize(query)) {\n if (contentTokens.has(token)) score += EXACT_TOKEN;\n else if (lower.includes(token)) score += SUBSTRING;\n if (tagSet.has(token)) score += TAG_MATCH;\n }\n for (const tag of extraTags) if (tagSet.has(tag.toLowerCase())) score += TAG_MATCH;\n return score;\n}\n\ninterface SemanticScores {\n similarity: Map<string, number>;\n weight: number;\n degraded: Degradation[];\n}\n\nasync function semanticScores(query: string, count: number, options: SemanticOptions | undefined): Promise<SemanticScores> {\n if (!options || count === 0) return { similarity: new Map(), weight: 0, degraded: [] };\n const retriever = vectorRetriever(options.embedder, options.index, { name: \"memory-vector\" });\n const { lists, degraded } = await gatherFailOpen([retriever], query, { limit: count, timeoutMs: options.timeoutMs });\n const similarity = new Map<string, number>();\n for (const hit of lists[0]?.hits ?? []) similarity.set(hit.id, hit.score ?? 0);\n return { similarity, weight: degraded.length === 0 ? (options.weight ?? 0.6) : 0, degraded };\n}\n\nfunction rank(bullet: ScoredBullet, query: string, options: RecallOptions, semantic: SemanticScores): RecalledBullet {\n const keyword = keywordScore(bullet.content, bullet.tags, query, options.tags);\n const similarity = semantic.similarity.get(bullet.id);\n const semanticScore = semantic.weight === 0 ? null : (similarity ?? 0);\n const relevanceScore = keyword * (1 - semantic.weight) + (semanticScore ?? 0) * semantic.weight;\n return { ...bullet, keywordScore: keyword, semanticScore, relevanceScore, finalScore: relevanceScore * Math.max(SCORE_FLOOR, bullet.effectiveScore) };\n}\n\nfunction byScore(a: RecalledBullet, b: RecalledBullet): number {\n return b.finalScore - a.finalScore || b.relevanceScore - a.relevanceScore || a.id.localeCompare(b.id);\n}\n","import { fromFloat32Buffer, toFloat32Buffer, type Embedder } from \"@titan-design/embed\";\nimport { BruteForceVectorIndex, type VectorIndex } from \"@titan-design/retrieval\";\nimport { CacheBlobTable, type Db } from \"@titan-design/store-sqlite\";\nimport { DEFAULT_MEMORY_TABLES, type MemoryTables } from \"./schema.js\";\nimport { normalizeContent } from \"./text.js\";\nimport type { Bullet } from \"./types.js\";\n\nexport interface MemoryVectorsOptions {\n tables?: MemoryTables;\n namespace?: string;\n}\n\n/**\n * Bullet embeddings in cache_blob, keyed by normalized content and the\n * embedder's model, so a re-worded bullet re-embeds and everything else is a\n * cache hit. The index is rebuilt from the cache; nothing is stored twice.\n */\nexport class MemoryVectors {\n private readonly cache: CacheBlobTable;\n private readonly namespace: string;\n\n constructor(\n db: Db,\n private readonly embedder: Embedder,\n options: MemoryVectorsOptions = {},\n ) {\n this.cache = new CacheBlobTable(db, { name: (options.tables ?? DEFAULT_MEMORY_TABLES).cacheBlob });\n this.namespace = options.namespace ?? \"memory:bullet\";\n }\n\n /** Embed every bullet the cache does not have, in one call. Returns how many were computed. */\n async ensure(bullets: readonly Bullet[]): Promise<number> {\n const missing = bullets.filter((b) => this.cache.get(this.keyFor(b)) === undefined);\n if (missing.length === 0) return 0;\n const vectors = await this.embedder.embed(missing.map((b) => normalizeContent(b.content)));\n missing.forEach((bullet, i) => {\n const vector = vectors[i];\n if (vector) this.cache.put(this.keyFor(bullet), toFloat32Buffer(vector), { bulletId: bullet.id });\n });\n return missing.length;\n }\n\n /** A searchable index over these bullets, embedding any misses first. */\n async index(bullets: readonly Bullet[]): Promise<VectorIndex> {\n await this.ensure(bullets);\n const index = new BruteForceVectorIndex();\n for (const bullet of bullets) {\n const hit = this.cache.get(this.keyFor(bullet));\n if (hit) index.add(bullet.id, fromFloat32Buffer(hit.value));\n }\n return index;\n }\n\n private keyFor(bullet: Bullet): { namespace: string; model: string; text: string } {\n return { namespace: this.namespace, model: this.embedder.model, text: normalizeContent(bullet.content) };\n }\n}\n","import type { WatermarkTable } from \"@titan-design/store-sqlite\";\nimport { curate, type CurateOptions, type CurationReport } from \"./curate.js\";\nimport type { PlaybookStore } from \"./store.js\";\nimport { normalizeContent } from \"./text.js\";\nimport { PlaybookDeltaSchema, type Bullet, type ParsedDelta } from \"./types.js\";\n\nexport interface ReflectInput {\n sessionRef: string;\n /** Whatever the caller distilled from the session: a diary, a subgraph summary, raw notes. */\n diary: string;\n iteration: number;\n bullets: Bullet[];\n priorDeltas: ParsedDelta[];\n}\n\n/** The one stage that may call a model. Returns anything; the deltas are validated here, not trusted. */\nexport type Reflector = (input: ReflectInput) => Promise<unknown>;\n\nexport interface ReflectSessionInput {\n sessionRef: string;\n diary: string;\n byteOffset?: number;\n}\n\nexport interface ReflectOptions extends Omit<CurateOptions, \"provenance\"> {\n maxIterations?: number;\n maxDeltas?: number;\n}\n\nexport interface RejectedDelta {\n iteration: number;\n index: number;\n reason: string;\n}\n\nexport interface ReflectionResult {\n deltas: ParsedDelta[];\n rejected: RejectedDelta[];\n iterations: number;\n report: CurationReport;\n}\n\nexport interface ReflectDeps {\n store: PlaybookStore;\n /** When present, the session's offset is recorded so incremental runs know where they stopped. */\n watermark?: WatermarkTable;\n}\n\n/**\n * cass-memory's multi-iteration reflect loop: feed the growing playbook and the\n * deltas so far back in, stop early on nothing new or at the cap, then curate\n * with provenance stamped from the input, never from the model.\n */\nexport async function reflectSession(deps: ReflectDeps, input: ReflectSessionInput, reflector: Reflector, options: ReflectOptions = {}): Promise<ReflectionResult> {\n const maxIterations = options.maxIterations ?? 3;\n const maxDeltas = options.maxDeltas ?? 50;\n const deltas: ParsedDelta[] = [];\n const rejected: RejectedDelta[] = [];\n const seen = new Set<string>();\n let iterations = 0;\n while (iterations < maxIterations && deltas.length < maxDeltas) {\n iterations++;\n const raw = await reflector({ sessionRef: input.sessionRef, diary: input.diary, iteration: iterations, bullets: deps.store.list(), priorDeltas: [...deltas] });\n const fresh = parseDeltas(raw, seen, iterations, rejected);\n if (fresh.length === 0) break;\n deltas.push(...fresh.slice(0, maxDeltas - deltas.length));\n }\n const report = curate(deps.store, deltas, { ...curateOptions(options), provenance: { sessionRef: input.sessionRef, byteOffset: input.byteOffset } });\n advanceWatermark(deps.watermark, input);\n return { deltas, rejected, iterations, report };\n}\n\nfunction curateOptions(options: ReflectOptions): Omit<CurateOptions, \"provenance\"> {\n const { now, nearDupThreshold, conflictThreshold, inversion } = options;\n return { now, nearDupThreshold, conflictThreshold, inversion };\n}\n\nexport function parseDeltas(raw: unknown, seen: Set<string>, iteration: number, rejected: RejectedDelta[]): ParsedDelta[] {\n if (!Array.isArray(raw)) {\n rejected.push({ iteration, index: -1, reason: \"reflector did not return an array\" });\n return [];\n }\n const fresh: ParsedDelta[] = [];\n raw.forEach((item, index) => {\n const parsed = PlaybookDeltaSchema.safeParse(item);\n if (!parsed.success) {\n rejected.push({ iteration, index, reason: parsed.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \") });\n return;\n }\n const key = deltaKey(parsed.data);\n if (seen.has(key)) return;\n seen.add(key);\n fresh.push(parsed.data);\n });\n return fresh;\n}\n\nfunction deltaKey(delta: ParsedDelta): string {\n switch (delta.type) {\n case \"add\":\n case \"replace\":\n case \"merge\":\n return `${delta.type}:${normalizeContent(delta.content)}`;\n default:\n return `${delta.type}:${delta.bulletId}`;\n }\n}\n\nfunction advanceWatermark(watermark: WatermarkTable | undefined, input: ReflectSessionInput): void {\n if (!watermark) return;\n watermark.ensure(input.sessionRef);\n watermark.advance(input.sessionRef, { lastOffset: input.byteOffset ?? 0 });\n}\n"],"mappings":"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","names":["quoteIdent","quoteIdent"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@titan-design/memory",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Decaying rule playbook: bullets, feedback, deterministic curation, recall",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -33,7 +33,7 @@
33
33
  "dependencies": {
34
34
  "@titan-design/embed": "^0.2.0",
35
35
  "@titan-design/retrieval": "^0.3.0",
36
- "@titan-design/store-sqlite": "^0.3.0"
36
+ "@titan-design/store-sqlite": "^0.3.3"
37
37
  },
38
38
  "devDependencies": {
39
39
  "zod": "^4.4.3"