/** * Ports — the contracts between layers. * * This file contains no executable code, only type definitions. That is * deliberate: it is the one place to read to understand what flows between the * pure core and the impure edge, without reading either. * * The dependency rule this project enforces: * * core/ imports nothing outside core/ (pure, testable, portable) * ports/ imports nothing at all (contracts only) * adapters/ may import ports/ and core/ (impure: DOM, network, storage) * ui/ may import ports/ and core/ (rendering only, no I/O) * app/ may import everything (composition root, wires it up) * * The arrow never points from core/ outward. dependency-cruiser enforces this * mechanically on every commit; see .dependency-cruiser.cjs. */ /** * A single piece of work in the corpus. * @typedef {object} Item * @property {string} id * @property {string} url * @property {string} title * @property {string} topic One of the corpus topic partitions. * @property {string} kind chapter | concept | post | page * @property {string} summary * @property {number} wordCount * @property {number} publishedMs * @property {Float32Array} [embedding] 384-dim, unit length. Absent until loaded. */ /** * A Beta posterior over "will this visitor engage with this topic". * @typedef {object} Posterior * @property {number} alpha Evidence for. * @property {number} beta Evidence against. */ /** * Everything the recommender knows about the current visitor. * Held in memory, optionally mirrored to sessionStorage. Never transmitted. * @typedef {object} VisitorState * @property {Float32Array} interest The interest vector. * @property {Record} topics Per-topic posteriors. * @property {Record} impressions Times each item was shown. */ /** * An observed interaction, normalised out of the DOM. * @typedef {object} SignalEvent * @property {string} kind A value from Signal. * @property {string} itemId * @property {number} [completion] Ratio in [0,1]; only for COMPLETION. */ /** * Persistence port. Implemented by adapters/storage.js; swapped for an * in-memory stub in tests. The core never sees it. * @typedef {object} StatePort * @property {() => VisitorState | null} load * @property {(s: VisitorState) => void} save * @property {() => void} clear */ export {};