@mmnto/totem 2.15.0 → 2.16.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.
- package/dist/compile-manifest-mode.test.d.ts +2 -0
- package/dist/compile-manifest-mode.test.d.ts.map +1 -0
- package/dist/compile-manifest-mode.test.js +47 -0
- package/dist/compile-manifest-mode.test.js.map +1 -0
- package/dist/compile-manifest.d.ts +4 -0
- package/dist/compile-manifest.d.ts.map +1 -1
- package/dist/compile-manifest.js +10 -1
- package/dist/compile-manifest.js.map +1 -1
- package/dist/compile-manifest.test.js +37 -0
- package/dist/compile-manifest.test.js.map +1 -1
- package/dist/errors.d.ts +9 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/exporter.d.ts +64 -1
- package/dist/exporter.d.ts.map +1 -1
- package/dist/exporter.js +93 -10
- package/dist/exporter.js.map +1 -1
- package/dist/exporter.test.js +64 -1
- package/dist/exporter.test.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/spine/serving-plan.d.ts +227 -0
- package/dist/spine/serving-plan.d.ts.map +1 -0
- package/dist/spine/serving-plan.js +503 -0
- package/dist/spine/serving-plan.js.map +1 -0
- package/dist/spine/serving-plan.test.d.ts +2 -0
- package/dist/spine/serving-plan.test.d.ts.map +1 -0
- package/dist/spine/serving-plan.test.js +646 -0
- package/dist/spine/serving-plan.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
// ─── The serving writer's planner (B2 of mmnto-ai/totem#3036, S6 step 2) ─────
|
|
2
|
+
//
|
|
3
|
+
// `totem rule serve <input.json>` lowers the records one input file names into
|
|
4
|
+
// `compiled-rules.json`, disposes of each floor rule's legacy row as the file
|
|
5
|
+
// says, and archives the rows the file's `archive[]` names. This module is the
|
|
6
|
+
// PURE half: no IO, no clock. It takes the serving file's rows as PLAIN parsed
|
|
7
|
+
// objects (never re-shaped through `CompiledRulesFileSchema`, which re-orders
|
|
8
|
+
// keys on some rows), the authoring ledger, the ingested records and the
|
|
9
|
+
// validated input, and returns the new rows plus a row-level report. The CLI
|
|
10
|
+
// library `serving-writer.ts` does the reads and the writes around it.
|
|
11
|
+
//
|
|
12
|
+
// Every refusal here is thrown before the caller writes anything.
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { isActiveCompiledRule } from '../compiler.js';
|
|
15
|
+
import { AUTHORED_RULE_ID_RE } from '../compiler-schema.js';
|
|
16
|
+
import { TotemError, TotemParseError } from '../errors.js';
|
|
17
|
+
import { isBlockingRule } from '../rule-tier.js';
|
|
18
|
+
import { foldEffectiveLedgerEntries } from './authoring-ledger.js';
|
|
19
|
+
import { compileRuleRecord } from './record-lower.js';
|
|
20
|
+
import { isRecordPathRule } from './record-runtime.js';
|
|
21
|
+
// ─── The input file (`serving-input/1`) ─────────────────────────────────────
|
|
22
|
+
const LESSON_HASH_RE = /^[0-9a-f]{16}$/;
|
|
23
|
+
const lessonHash = (field) => z.string().regex(LESSON_HASH_RE, { message: `${field} must be 16 lowercase hex characters` });
|
|
24
|
+
const nonEmpty = (field) => z.string().min(1, { message: `${field} must be non-empty` });
|
|
25
|
+
/** The one instant form the writer accepts, as a refusal message names it. */
|
|
26
|
+
export const STRICT_INSTANT_FORM = 'YYYY-MM-DDTHH:MM:SS(.fraction)?(Z|+HH:MM|-HH:MM)';
|
|
27
|
+
const STRICT_INSTANT_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(Z|([+-])(\d{2}):(\d{2}))$/;
|
|
28
|
+
/**
|
|
29
|
+
* True when the instant `ms`, shifted by the written UTC offset, shows exactly
|
|
30
|
+
* the written calendar digits. V8 rolls impossible values over
|
|
31
|
+
* (`2026-02-30` reads as March 2, `T24:00:00` as the next day); this refuses them.
|
|
32
|
+
*/
|
|
33
|
+
function roundTrips(ms, offsetMinutes, digits) {
|
|
34
|
+
const d = new Date(ms + offsetMinutes * 60_000);
|
|
35
|
+
const shown = [
|
|
36
|
+
d.getUTCFullYear(),
|
|
37
|
+
d.getUTCMonth() + 1,
|
|
38
|
+
d.getUTCDate(),
|
|
39
|
+
d.getUTCHours(),
|
|
40
|
+
d.getUTCMinutes(),
|
|
41
|
+
d.getUTCSeconds(),
|
|
42
|
+
];
|
|
43
|
+
return digits.every((v, i) => shown[i] === v);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Epoch milliseconds of a STRICT instant (`STRICT_INSTANT_FORM`: a date-time
|
|
47
|
+
* with seconds and an explicit zone, every component a real calendar value), or
|
|
48
|
+
* `undefined` for anything else.
|
|
49
|
+
*/
|
|
50
|
+
export function parseStrictInstant(s) {
|
|
51
|
+
const m = STRICT_INSTANT_RE.exec(s);
|
|
52
|
+
if (m === null)
|
|
53
|
+
return undefined;
|
|
54
|
+
const ms = Date.parse(s);
|
|
55
|
+
if (Number.isNaN(ms))
|
|
56
|
+
return undefined;
|
|
57
|
+
const offset = m[8] === 'Z' ? 0 : (m[9] === '-' ? -1 : 1) * (Number(m[10]) * 60 + Number(m[11]));
|
|
58
|
+
const digits = [m[1], m[2], m[3], m[4], m[5], m[6]].map(Number);
|
|
59
|
+
return roundTrips(ms, offset, digits) ? ms : undefined;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The serving writer's input: one file, so one sha256 names a run. Strict at
|
|
63
|
+
* every level: an unknown key anywhere is refused. Both dispositions are
|
|
64
|
+
* required, with no default.
|
|
65
|
+
*/
|
|
66
|
+
export const ServingInputSchema = z
|
|
67
|
+
.object({
|
|
68
|
+
schema: z.literal('serving-input/1'),
|
|
69
|
+
/**
|
|
70
|
+
* The `now` for every lowered row and for the manifest, so a re-run is
|
|
71
|
+
* byte-identical. A STRICT instant: a zone-less date-time would read as the
|
|
72
|
+
* machine's local time and make the stale-floor verdict machine-dependent.
|
|
73
|
+
*/
|
|
74
|
+
asOf: z.string().superRefine((s, ctx) => {
|
|
75
|
+
if (parseStrictInstant(s) === undefined) {
|
|
76
|
+
ctx.addIssue({
|
|
77
|
+
code: z.ZodIssueCode.custom,
|
|
78
|
+
message: `asOf '${s}' must be a strict ISO-8601 instant, ${STRICT_INSTANT_FORM}, naming a real calendar date and time`,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}),
|
|
82
|
+
/** Free text naming the runs of record and the ruling; not machine-read. */
|
|
83
|
+
source: nonEmpty('source'),
|
|
84
|
+
dispositions: z
|
|
85
|
+
.object({
|
|
86
|
+
legacyRow: z.enum(['archive', 'remove']),
|
|
87
|
+
stamp: z.enum(['none', 'advisory']),
|
|
88
|
+
})
|
|
89
|
+
.strict(),
|
|
90
|
+
floor: z.array(z
|
|
91
|
+
.object({
|
|
92
|
+
legacyHash: lessonHash('floor[].legacyHash').optional(),
|
|
93
|
+
records: z
|
|
94
|
+
.array(z
|
|
95
|
+
.object({
|
|
96
|
+
path: nonEmpty('floor[].records[].path'),
|
|
97
|
+
ruleId: z.string().regex(AUTHORED_RULE_ID_RE, {
|
|
98
|
+
message: 'floor[].records[].ruleId must be a minted rule id (16 hex, optional -<n>)',
|
|
99
|
+
}),
|
|
100
|
+
/**
|
|
101
|
+
* REQUIRED binding by content: the record's sha256 (64 hex) the
|
|
102
|
+
* floor was scored against, which must equal the effective
|
|
103
|
+
* ledger row's `record.contentHash` (mmnto-ai/totem#3045).
|
|
104
|
+
*/
|
|
105
|
+
contentHash: z
|
|
106
|
+
.string({
|
|
107
|
+
required_error: "floor[].records[].contentHash is required: the floor file must carry the ledger's record.contentHash for each record",
|
|
108
|
+
})
|
|
109
|
+
.regex(/^[0-9a-f]{64}$/, {
|
|
110
|
+
message: 'floor[].records[].contentHash must be 64 lowercase hex characters',
|
|
111
|
+
}),
|
|
112
|
+
})
|
|
113
|
+
.strict())
|
|
114
|
+
.min(1),
|
|
115
|
+
})
|
|
116
|
+
.strict()),
|
|
117
|
+
archive: z.array(z
|
|
118
|
+
.object({
|
|
119
|
+
lessonHash: lessonHash('archive[].lessonHash'),
|
|
120
|
+
reason: nonEmpty('archive[].reason'),
|
|
121
|
+
ref: nonEmpty('archive[].ref'),
|
|
122
|
+
})
|
|
123
|
+
.strict()),
|
|
124
|
+
})
|
|
125
|
+
.strict();
|
|
126
|
+
/**
|
|
127
|
+
* Refuse an input whose mode is not built. `stamp: 'advisory'` waits on the
|
|
128
|
+
* ADR-110 reading; only `none` (unstamped) is implemented. Called by the writer
|
|
129
|
+
* right after the schema check and again by the planner, so neither path can
|
|
130
|
+
* reach a write with it.
|
|
131
|
+
*/
|
|
132
|
+
export function assertServingInputSupported(input) {
|
|
133
|
+
if (input.dispositions.stamp !== 'none') {
|
|
134
|
+
throw new TotemError('SERVING_INPUT_INVALID', `The serving input asks for dispositions.stamp '${input.dispositions.stamp}': the advisory stamp mode waits on the ADR-110 reading and is not built; nothing was written.`, "Set dispositions.stamp to 'none' in the input file.");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
138
|
+
function inputInvalid(message, hint = 'Fix the input file, then re-run.') {
|
|
139
|
+
return new TotemError('SERVING_INPUT_INVALID', `${message}; nothing was written.`, hint);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The two routes out of an inactive named record row, for the input's
|
|
143
|
+
* disposition. Both pass through `--refresh`, because each edits the serving
|
|
144
|
+
* file by hand and the integrity check refuses a hand-edited file otherwise.
|
|
145
|
+
* Under `remove` the legacy row is already gone, so route one must also drop
|
|
146
|
+
* `legacyHash` from the entry, or the absent-legacy refusal fires. Under
|
|
147
|
+
* `archive` route two leaves the legacy row's `served by record` reason naming
|
|
148
|
+
* a row that is gone until `totem lesson archive` re-reasons it.
|
|
149
|
+
*/
|
|
150
|
+
function inactiveRowHint(disposition, legacyHash) {
|
|
151
|
+
const integrity = '(the integrity check refuses a hand-edited file otherwise)';
|
|
152
|
+
if (disposition === 'remove' && legacyHash !== undefined) {
|
|
153
|
+
return `To serve it again, remove the inactive row from compiled-rules.json deliberately AND drop legacyHash ${legacyHash} from its floor[] entry (the legacy row is already gone, so the entry lowers where its remaining rows sit, or at the end of the file), then re-run with --refresh ${integrity}. To keep it out, remove the row and drop its record from its floor[] entry (the whole entry when that record is its only one), then re-run with --refresh.`;
|
|
154
|
+
}
|
|
155
|
+
const reReason = disposition === 'archive' && legacyHash !== undefined
|
|
156
|
+
? `, then run \`totem lesson archive ${legacyHash} --reason <why>\` so the legacy row's "served by record" reason no longer names a row that is gone (that verb rewrites the serving file through its schema and re-orders keys on untouched rows, which the serve path never does)`
|
|
157
|
+
: '';
|
|
158
|
+
return `To serve it again, remove the inactive row from compiled-rules.json deliberately and re-run with --refresh ${integrity}. To keep it out, remove the row and drop its record from its floor[] entry (the whole entry when that record is its only one), re-run with --refresh${reReason}.`;
|
|
159
|
+
}
|
|
160
|
+
function servedByReason(ruleIds) {
|
|
161
|
+
return ruleIds.length === 1
|
|
162
|
+
? `served by record ${ruleIds[0]}`
|
|
163
|
+
: `served by records ${ruleIds.join(', ')}`;
|
|
164
|
+
}
|
|
165
|
+
function serialize(row) {
|
|
166
|
+
return JSON.stringify(row, null, 2);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Archive a row the way `totem lesson archive` does: `status` and
|
|
170
|
+
* `archivedReason` set, `archivedAt` set only on the first transition. Returns
|
|
171
|
+
* the SAME object when nothing would change, else a shallow copy (spread keeps
|
|
172
|
+
* the existing key order; a new key appends, as an in-place assignment would).
|
|
173
|
+
*/
|
|
174
|
+
function archived(row, reason, at) {
|
|
175
|
+
if (row.status === 'archived' && row.archivedReason === reason && row.archivedAt)
|
|
176
|
+
return row;
|
|
177
|
+
const next = { ...row, status: 'archived', archivedReason: reason };
|
|
178
|
+
if (!next.archivedAt)
|
|
179
|
+
next.archivedAt = at;
|
|
180
|
+
return next;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* The top-level fields whose values differ between two rows (either side may
|
|
184
|
+
* lack the key). When only the key ORDER differs, the one entry is `(key order)`.
|
|
185
|
+
*/
|
|
186
|
+
function differingFields(a, b) {
|
|
187
|
+
const ra = a;
|
|
188
|
+
const rb = b;
|
|
189
|
+
const keys = [...new Set([...Object.keys(ra), ...Object.keys(rb)])];
|
|
190
|
+
const diff = keys.filter((k) => JSON.stringify(ra[k]) !== JSON.stringify(rb[k])).sort();
|
|
191
|
+
return diff.length > 0 ? diff : ['(key order)'];
|
|
192
|
+
}
|
|
193
|
+
function blockingSet(rows) {
|
|
194
|
+
return rows
|
|
195
|
+
.filter((r) => isActiveCompiledRule(r) && isBlockingRule(r))
|
|
196
|
+
.map((r) => r.lessonHash)
|
|
197
|
+
.sort();
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Plan one serving write. PURE: no IO, no clock (`input.asOf` is the `now`).
|
|
201
|
+
*
|
|
202
|
+
* Placement. Under `archive` a floor entry's legacy row stays at its index,
|
|
203
|
+
* archived with a reason naming its record ids (or byte-untouched when it was
|
|
204
|
+
* already archived), and the lowered rows follow it in the entry's record order;
|
|
205
|
+
* under `remove` the lowered rows replace it at its index. An entry with no
|
|
206
|
+
* `legacyHash` appends its lowered rows at the end, in floor order. An entry
|
|
207
|
+
* whose lowered rows are already in the file (a re-run) keeps them where they
|
|
208
|
+
* are, so a second run with the same input is a fixpoint that changes nothing.
|
|
209
|
+
*
|
|
210
|
+
* Untouched rows are the same object references in the output.
|
|
211
|
+
*/
|
|
212
|
+
export function planServingWrite(args) {
|
|
213
|
+
const { rows, input } = args;
|
|
214
|
+
assertServingInputSupported(input);
|
|
215
|
+
const asOf = input.asOf;
|
|
216
|
+
if (parseStrictInstant(asOf) === undefined) {
|
|
217
|
+
throw inputInvalid(`The serving input's asOf '${asOf}' is not a strict instant naming a real calendar date and time (expected ${STRICT_INSTANT_FORM})`);
|
|
218
|
+
}
|
|
219
|
+
// ── The serving file: one row per lessonHash ──
|
|
220
|
+
const rowByHash = new Map();
|
|
221
|
+
const duplicates = new Set();
|
|
222
|
+
for (const r of rows) {
|
|
223
|
+
if (rowByHash.has(r.lessonHash))
|
|
224
|
+
duplicates.add(r.lessonHash);
|
|
225
|
+
else
|
|
226
|
+
rowByHash.set(r.lessonHash, r);
|
|
227
|
+
}
|
|
228
|
+
if (duplicates.size > 0) {
|
|
229
|
+
throw new TotemParseError(`The serving file holds more than one row for lessonHash ${[...duplicates].join(', ')}; nothing was written.`, 'Repair compiled-rules.json first (one row per lessonHash), for example by restoring it from git, then re-run.');
|
|
230
|
+
}
|
|
231
|
+
// ── The input's own consistency ──
|
|
232
|
+
const floorLegacy = new Set();
|
|
233
|
+
const floorRuleIds = new Set();
|
|
234
|
+
/** The floor entry's legacy hash for each of its record ruleIds (entries with one). */
|
|
235
|
+
const legacyByRuleId = new Map();
|
|
236
|
+
for (const entry of input.floor) {
|
|
237
|
+
if (entry.legacyHash !== undefined) {
|
|
238
|
+
if (floorLegacy.has(entry.legacyHash)) {
|
|
239
|
+
throw inputInvalid(`The serving input names legacyHash ${entry.legacyHash} in more than one floor entry`);
|
|
240
|
+
}
|
|
241
|
+
floorLegacy.add(entry.legacyHash);
|
|
242
|
+
}
|
|
243
|
+
for (const rec of entry.records) {
|
|
244
|
+
if (floorRuleIds.has(rec.ruleId)) {
|
|
245
|
+
throw inputInvalid(`The serving input names ruleId ${rec.ruleId} more than once in floor[]`);
|
|
246
|
+
}
|
|
247
|
+
floorRuleIds.add(rec.ruleId);
|
|
248
|
+
if (entry.legacyHash !== undefined)
|
|
249
|
+
legacyByRuleId.set(rec.ruleId, entry.legacyHash);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const archiveByHash = new Map();
|
|
253
|
+
for (const a of input.archive) {
|
|
254
|
+
if (archiveByHash.has(a.lessonHash)) {
|
|
255
|
+
throw inputInvalid(`The serving input names archive lessonHash ${a.lessonHash} more than once`);
|
|
256
|
+
}
|
|
257
|
+
if (floorLegacy.has(a.lessonHash)) {
|
|
258
|
+
throw inputInvalid(`The serving input names ${a.lessonHash} in both floor[] (as a legacyHash) and archive[]`);
|
|
259
|
+
}
|
|
260
|
+
// A floor ruleId is a lowered row this run writes; archiving it in the same
|
|
261
|
+
// input contradicts the floor, on a first run and on every re-run alike.
|
|
262
|
+
if (floorRuleIds.has(a.lessonHash)) {
|
|
263
|
+
throw inputInvalid(`The serving input names ${a.lessonHash} in both floor[] (as a record ruleId) and archive[]`);
|
|
264
|
+
}
|
|
265
|
+
archiveByHash.set(a.lessonHash, a);
|
|
266
|
+
}
|
|
267
|
+
// ── Every record-path row in the file must be one the floor names ──
|
|
268
|
+
for (const r of rows) {
|
|
269
|
+
if (isRecordPathRule(r) && !floorRuleIds.has(r.lessonHash)) {
|
|
270
|
+
throw inputInvalid(`The serving file holds a record-path row ${r.lessonHash} that the serving input's floor does not name`, 'Name its record in floor[], or remove the row deliberately, then re-run.');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// A lowered ruleId must not collide with a row that is not a record-path row,
|
|
274
|
+
// and a named record row a human archived after serving is never re-lowered
|
|
275
|
+
// (a `replace` would silently re-activate it).
|
|
276
|
+
for (const id of floorRuleIds) {
|
|
277
|
+
const existing = rowByHash.get(id);
|
|
278
|
+
if (existing !== undefined && !isRecordPathRule(existing)) {
|
|
279
|
+
throw inputInvalid(`The serving input's floor ruleId ${id} collides with a non-record row of the same lessonHash in the serving file`);
|
|
280
|
+
}
|
|
281
|
+
// Any inactive status (archived, untested-against-codebase,
|
|
282
|
+
// pending-verification): a replace would write an active row in its place.
|
|
283
|
+
if (existing !== undefined && !isActiveCompiledRule(existing)) {
|
|
284
|
+
const reason = existing.archivedReason !== undefined ? `, archivedReason: ${existing.archivedReason}` : '';
|
|
285
|
+
throw inputInvalid(`The serving file's record row ${id}, which the floor names, is inactive (status: ${existing.status}${reason}); serving it again would re-activate it`, inactiveRowHint(input.dispositions.legacyRow, legacyByRuleId.get(id)));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// ── Archive targets must be in the file ──
|
|
289
|
+
for (const hash of archiveByHash.keys()) {
|
|
290
|
+
if (!rowByHash.has(hash)) {
|
|
291
|
+
throw inputInvalid(`The serving input's archive[] names lessonHash ${hash}, which is not in the serving file`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// ── Each floor record against the ledger, then lowered ──
|
|
295
|
+
const effective = new Map(foldEffectiveLedgerEntries(args.ledger).map((e) => [e.ruleId, e]));
|
|
296
|
+
const recordById = new Map(args.records.map((r) => [r.ruleId, r]));
|
|
297
|
+
const entries = [];
|
|
298
|
+
for (const entry of input.floor) {
|
|
299
|
+
const plan = {
|
|
300
|
+
...(entry.legacyHash !== undefined ? { legacyHash: entry.legacyHash } : {}),
|
|
301
|
+
ruleIds: entry.records.map((r) => r.ruleId),
|
|
302
|
+
lowered: [],
|
|
303
|
+
};
|
|
304
|
+
for (const ref of entry.records) {
|
|
305
|
+
const row = effective.get(ref.ruleId);
|
|
306
|
+
if (row === undefined) {
|
|
307
|
+
throw new TotemError('SERVING_RECORD_MISMATCH', `Floor record ${ref.path} (ruleId ${ref.ruleId}) has no effective authoring-ledger row; nothing was written.`, 'Re-run the intake (`totem rule author`) so the record is admitted, or fix the ruleId in the input file.');
|
|
308
|
+
}
|
|
309
|
+
if (row.record === undefined) {
|
|
310
|
+
throw new TotemError('SERVING_RECORD_MISMATCH', `The effective authoring-ledger row for ruleId ${ref.ruleId} has no record block (it predates the record path); nothing was written.`, 'Re-run the intake (`totem rule author`) so the rule is admitted from its record, or fix the input file.');
|
|
311
|
+
}
|
|
312
|
+
if (row.record.path !== ref.path) {
|
|
313
|
+
throw new TotemError('SERVING_RECORD_MISMATCH', `Floor record ${ref.path} (ruleId ${ref.ruleId}) differs from its effective ledger row's record.path ${row.record.path}; nothing was written.`, 'Fix the path in the input file, or re-run the intake (`totem rule author`) if the record moved.');
|
|
314
|
+
}
|
|
315
|
+
// mmnto-ai/totem#3045 — the stale-floor check, binding by content. Every
|
|
316
|
+
// floor record names the content hash it was scored against (the ledger's
|
|
317
|
+
// `record.contentHash`, the sha256 of the record's LF text). A record
|
|
318
|
+
// edited and re-admitted after the floor was built carries a new ledger
|
|
319
|
+
// row with a new hash, so the floor's hash no longer matches and the run
|
|
320
|
+
// refuses. A re-admission that leaves the record's bytes unchanged keeps
|
|
321
|
+
// the hash: it serves the same matcher the floor scored and is no hazard.
|
|
322
|
+
// This comparison is the whole check; no clock or commit history is read.
|
|
323
|
+
if (ref.contentHash !== row.record.contentHash) {
|
|
324
|
+
throw new TotemError('SERVING_RECORD_MISMATCH', `Floor record ${ref.path} (ruleId ${ref.ruleId}) names content hash ${ref.contentHash}, but its effective ledger row admitted ${row.record.contentHash}: the floor was built against another revision of this record; nothing was written.`, 'Regenerate the floor file from the current ledger (and re-score the record), then re-run.');
|
|
325
|
+
}
|
|
326
|
+
const rec = recordById.get(ref.ruleId);
|
|
327
|
+
if (rec === undefined || rec.path !== ref.path) {
|
|
328
|
+
throw new Error(`[Totem Error] planServingWrite: floor record ${ref.path} (ruleId ${ref.ruleId}) was not ingested by the caller — a caller bug.`);
|
|
329
|
+
}
|
|
330
|
+
if (rec.contentHash !== row.record.contentHash) {
|
|
331
|
+
throw new TotemError('SERVING_RECORD_MISMATCH', `Record ${ref.path} (ruleId ${ref.ruleId}) has content hash ${rec.contentHash}, but its effective ledger row admitted ${row.record.contentHash}: the record was edited after admission; nothing was written.`, 'Re-admit the record (`totem rule author`) and regenerate the floor file, or restore the admitted record bytes.');
|
|
332
|
+
}
|
|
333
|
+
if (entry.legacyHash !== undefined) {
|
|
334
|
+
const source = rec.parsed.record.curation?.sourceLesson;
|
|
335
|
+
if (source !== `lesson-${entry.legacyHash}`) {
|
|
336
|
+
throw inputInvalid(`Floor entry legacyHash ${entry.legacyHash} disagrees with record ${ref.path}'s curation.sourceLesson (${source ?? 'absent'})`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const outcome = compileRuleRecord(rec.parsed, { ruleId: ref.ruleId, now: asOf });
|
|
340
|
+
if (outcome.kind === 'rejected') {
|
|
341
|
+
throw new TotemError('COMPILE_FAILED', `Record ${ref.path} (ruleId ${ref.ruleId}) is rejected by the lowering: ${outcome.reason}; nothing was written.`, `Fix the record (${outcome.reason}), re-admit it, and re-run.`);
|
|
342
|
+
}
|
|
343
|
+
plan.lowered.push({ rule: outcome.rule, recordPath: ref.path });
|
|
344
|
+
}
|
|
345
|
+
// The legacy row must be in the file. The one exception is a re-run under
|
|
346
|
+
// `remove`: the entry was already served and its legacy row removed, so
|
|
347
|
+
// every one of its ruleIds is present. Under `archive` the legacy row is
|
|
348
|
+
// kept by construction, so its absence always refuses.
|
|
349
|
+
if (entry.legacyHash !== undefined && !rowByHash.has(entry.legacyHash)) {
|
|
350
|
+
const servedUnderRemove = input.dispositions.legacyRow === 'remove' && plan.ruleIds.every((id) => rowByHash.has(id));
|
|
351
|
+
if (!servedUnderRemove) {
|
|
352
|
+
throw inputInvalid(`The serving input's floor names legacyHash ${entry.legacyHash}, which is not in the serving file`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
entries.push(plan);
|
|
356
|
+
}
|
|
357
|
+
// ── Placement ──
|
|
358
|
+
const entryByLegacy = new Map();
|
|
359
|
+
const entryByRuleId = new Map();
|
|
360
|
+
for (const e of entries) {
|
|
361
|
+
if (e.legacyHash !== undefined)
|
|
362
|
+
entryByLegacy.set(e.legacyHash, e);
|
|
363
|
+
for (const id of e.ruleIds)
|
|
364
|
+
entryByRuleId.set(id, e);
|
|
365
|
+
}
|
|
366
|
+
const entriesWithExistingRows = new Set(entries.filter((e) => e.ruleIds.some((id) => rowByHash.has(id))));
|
|
367
|
+
const emitted = new Set();
|
|
368
|
+
const out = [];
|
|
369
|
+
const reportRows = [];
|
|
370
|
+
let removed = 0;
|
|
371
|
+
let loweredExisting = 0;
|
|
372
|
+
const emitLowered = (e) => {
|
|
373
|
+
emitted.add(e);
|
|
374
|
+
for (const { rule, recordPath } of e.lowered) {
|
|
375
|
+
const existing = rowByHash.get(rule.lessonHash);
|
|
376
|
+
let action = 'insert';
|
|
377
|
+
let row = rule;
|
|
378
|
+
let changedFields;
|
|
379
|
+
if (existing !== undefined) {
|
|
380
|
+
loweredExisting++;
|
|
381
|
+
if (serialize(existing) === serialize(rule)) {
|
|
382
|
+
action = 'none';
|
|
383
|
+
row = existing;
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
action = 'replace';
|
|
387
|
+
changedFields = differingFields(existing, rule);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
out.push(row);
|
|
391
|
+
reportRows.push({
|
|
392
|
+
class: 'lowered',
|
|
393
|
+
action,
|
|
394
|
+
lessonHash: rule.lessonHash,
|
|
395
|
+
...(e.legacyHash !== undefined ? { legacyHash: e.legacyHash } : {}),
|
|
396
|
+
ruleId: rule.lessonHash,
|
|
397
|
+
recordPath,
|
|
398
|
+
...(changedFields !== undefined ? { changedFields } : {}),
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
for (const row of rows) {
|
|
403
|
+
const legacyOf = entryByLegacy.get(row.lessonHash);
|
|
404
|
+
if (legacyOf !== undefined) {
|
|
405
|
+
const ids = legacyOf.ruleIds.join(', ');
|
|
406
|
+
if (input.dispositions.legacyRow === 'archive') {
|
|
407
|
+
// A legacy row already archived (by a human, or by an earlier run) stays
|
|
408
|
+
// byte-untouched: its reason and archivedAt stand. The record ids it
|
|
409
|
+
// serves appear in the report row, not in the serving row.
|
|
410
|
+
const already = row.status === 'archived';
|
|
411
|
+
const next = already ? row : archived(row, servedByReason(legacyOf.ruleIds), asOf);
|
|
412
|
+
out.push(next);
|
|
413
|
+
reportRows.push({
|
|
414
|
+
class: 'floor-legacy',
|
|
415
|
+
action: already ? 'already-archived' : 'archive',
|
|
416
|
+
lessonHash: row.lessonHash,
|
|
417
|
+
legacyHash: row.lessonHash,
|
|
418
|
+
ruleId: ids,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
removed++;
|
|
423
|
+
reportRows.push({
|
|
424
|
+
class: 'floor-legacy',
|
|
425
|
+
action: 'remove',
|
|
426
|
+
lessonHash: row.lessonHash,
|
|
427
|
+
legacyHash: row.lessonHash,
|
|
428
|
+
ruleId: ids,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
if (!entriesWithExistingRows.has(legacyOf))
|
|
432
|
+
emitLowered(legacyOf);
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const loweredOf = entryByRuleId.get(row.lessonHash);
|
|
436
|
+
if (loweredOf !== undefined) {
|
|
437
|
+
// An already-lowered row (a re-run): the entry's block is emitted at the
|
|
438
|
+
// first such row; any later one is part of that block.
|
|
439
|
+
if (!emitted.has(loweredOf))
|
|
440
|
+
emitLowered(loweredOf);
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
const archiveEntry = archiveByHash.get(row.lessonHash);
|
|
444
|
+
if (archiveEntry !== undefined) {
|
|
445
|
+
if (row.status === 'archived') {
|
|
446
|
+
out.push(row);
|
|
447
|
+
reportRows.push({ class: 'already-archived', action: 'none', lessonHash: row.lessonHash });
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
out.push(archived(row, `${archiveEntry.reason} (${archiveEntry.ref})`, asOf));
|
|
451
|
+
reportRows.push({ class: 'archive', action: 'archive', lessonHash: row.lessonHash });
|
|
452
|
+
}
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
out.push(row);
|
|
456
|
+
}
|
|
457
|
+
for (const e of entries) {
|
|
458
|
+
if (!emitted.has(e))
|
|
459
|
+
emitLowered(e);
|
|
460
|
+
}
|
|
461
|
+
// ── The report ──
|
|
462
|
+
const totals = {
|
|
463
|
+
'floor-legacy': 0,
|
|
464
|
+
lowered: 0,
|
|
465
|
+
archive: 0,
|
|
466
|
+
'already-archived': 0,
|
|
467
|
+
carried: 0,
|
|
468
|
+
};
|
|
469
|
+
for (const r of reportRows)
|
|
470
|
+
totals[r.class]++;
|
|
471
|
+
const touchedBefore = totals['floor-legacy'] + totals.archive + totals['already-archived'] + loweredExisting;
|
|
472
|
+
totals.carried = rows.length - touchedBefore;
|
|
473
|
+
const keptLegacy = totals['floor-legacy'] - removed;
|
|
474
|
+
const sumAfter = totals.carried + totals.archive + totals['already-archived'] + keptLegacy + totals.lowered;
|
|
475
|
+
if (sumAfter !== out.length) {
|
|
476
|
+
throw new TotemError('SERVING_INVARIANT_BROKEN', `The serving plan's class counts (${sumAfter}) do not add up to its row count (${out.length}); nothing was written.`, 'This is a bug in the serving writer; report it with the input file.');
|
|
477
|
+
}
|
|
478
|
+
const changed = out.length !== rows.length ||
|
|
479
|
+
out.some((r, i) => r !== rows[i] && serialize(r) !== serialize(rows[i]));
|
|
480
|
+
const report = {
|
|
481
|
+
inputSha256: args.inputSha256,
|
|
482
|
+
asOf,
|
|
483
|
+
legacyRow: input.dispositions.legacyRow,
|
|
484
|
+
changed,
|
|
485
|
+
rows: reportRows,
|
|
486
|
+
totals,
|
|
487
|
+
rowsBefore: rows.length,
|
|
488
|
+
rowsAfter: out.length,
|
|
489
|
+
removed,
|
|
490
|
+
loweredExisting,
|
|
491
|
+
active: {
|
|
492
|
+
before: rows.filter(isActiveCompiledRule).length,
|
|
493
|
+
after: out.filter(isActiveCompiledRule).length,
|
|
494
|
+
},
|
|
495
|
+
archived: {
|
|
496
|
+
before: rows.filter((r) => r.status === 'archived').length,
|
|
497
|
+
after: out.filter((r) => r.status === 'archived').length,
|
|
498
|
+
},
|
|
499
|
+
blocking: { before: blockingSet(rows), after: blockingSet(out) },
|
|
500
|
+
};
|
|
501
|
+
return { rows: out, changed, report };
|
|
502
|
+
}
|
|
503
|
+
//# sourceMappingURL=serving-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serving-plan.js","sourceRoot":"","sources":["../../src/spine/serving-plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serving-plan.test.d.ts","sourceRoot":"","sources":["../../src/spine/serving-plan.test.ts"],"names":[],"mappings":""}
|