superbee 0.4.3-pre.19 → 0.4.3-pre.20

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/superbee.mjs CHANGED
@@ -44,7 +44,7 @@ var __toESM = (mod, isNodeMode, target3) => (target3 = mod != null ? __create(__
44
44
  var define_SUPERBEE_BUILD_IDENTITY_default;
45
45
  var init_define_SUPERBEE_BUILD_IDENTITY = __esm({
46
46
  "<define:__SUPERBEE_BUILD_IDENTITY__>"() {
47
- define_SUPERBEE_BUILD_IDENTITY_default = { schema: "superbee.build-identity.v1", package: { name: "superbee", version: "0.4.3-pre.19" }, source: { commit: "029ca1ac24072a5018883159d4d3e2f2de613301", dirty: false }, artifact: { channel: "npm-package" }, compatibility_contracts: { skill: 1, hook: 1, mcp: 1 } };
47
+ define_SUPERBEE_BUILD_IDENTITY_default = { schema: "superbee.build-identity.v1", package: { name: "superbee", version: "0.4.3-pre.20" }, source: { commit: "72beac1bac6d129a9e7792f1a5d5067d5220cf62", dirty: false }, artifact: { channel: "npm-package" }, compatibility_contracts: { skill: 1, hook: 1, mcp: 1 } };
48
48
  }
49
49
  });
50
50
 
@@ -3103,23 +3103,6 @@ var init_frontmatter = __esm({
3103
3103
  }
3104
3104
  });
3105
3105
 
3106
- // ../core/src/meaningful-change-time.ts
3107
- function meaningfulChangeTimeField(frontmatter) {
3108
- const generated = frontmatter.generated;
3109
- if (generated !== null && typeof generated === "object" && !Array.isArray(generated) && generated.at !== void 0) return "generated.at";
3110
- return "timestamp";
3111
- }
3112
- function meaningfulChangeTimeValue(frontmatter) {
3113
- return meaningfulChangeTimeField(frontmatter) === "generated.at" ? frontmatter.generated.at : frontmatter.timestamp;
3114
- }
3115
- var init_meaningful_change_time = __esm({
3116
- "../core/src/meaningful-change-time.ts"() {
3117
- "use strict";
3118
- init_define_SUPERBEE_BUILD_IDENTITY();
3119
- init_define_SUPERBEE_UPDATE_POLICY();
3120
- }
3121
- });
3122
-
3123
3106
  // ../core/src/errors.ts
3124
3107
  var InvalidInputError, OkfActorError, FilesystemIdentityAliasError, ConcurrentReplacementError;
3125
3108
  var init_errors = __esm({
@@ -3167,6 +3150,576 @@ var init_errors = __esm({
3167
3150
  }
3168
3151
  });
3169
3152
 
3153
+ // ../core/src/paths.ts
3154
+ function compareStorageKeys(a, b) {
3155
+ const primary = a.localeCompare(b);
3156
+ if (primary !== 0 || a === b) return primary;
3157
+ const left = Array.from(a, (character) => character.codePointAt(0));
3158
+ const right = Array.from(b, (character) => character.codePointAt(0));
3159
+ for (let i = 0; i < Math.min(left.length, right.length); i++) {
3160
+ if (left[i] !== right[i]) return left[i] - right[i];
3161
+ }
3162
+ return left.length - right.length;
3163
+ }
3164
+ function assertPortablePath(value, label) {
3165
+ if (/[\u0000-\u001f\u007f]/u.test(value) || /^[a-z]:/i.test(value)) {
3166
+ throw new InvalidInputError(`${label} must not contain controls or start with a drive prefix.`);
3167
+ }
3168
+ if (value.includes("\\") || value.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
3169
+ throw new InvalidInputError(`${label} must be canonical and bundle-relative.`);
3170
+ }
3171
+ }
3172
+ function assertSafeReservedFilename(name) {
3173
+ if (!RESERVED_FILENAMES.includes(name)) {
3174
+ throw new InvalidInputError("Reserved filename must be index.md or log.md.");
3175
+ }
3176
+ }
3177
+ function toPosix(p2) {
3178
+ return p2.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
3179
+ }
3180
+ function isReservedFile(relPath) {
3181
+ const base = toPosix(relPath).split("/").pop() ?? "";
3182
+ return RESERVED_FILENAMES.includes(base);
3183
+ }
3184
+ function conceptIdFromPath(relPath) {
3185
+ const norm = toPosix(relPath).replace(/^\.?\//, "").split("/").filter((segment) => segment !== ".").join("/");
3186
+ return norm.endsWith(".md") ? norm.slice(0, -3) : norm;
3187
+ }
3188
+ function pathFromConceptId(id) {
3189
+ assertSafeConceptId(id);
3190
+ return `${id}.md`;
3191
+ }
3192
+ function assertSafeConceptId(id) {
3193
+ if (typeof id !== "string" || id.trim() === "") {
3194
+ throw new InvalidInputError("Concept id must be a non-empty string.");
3195
+ }
3196
+ assertPortablePath(id, "Concept id");
3197
+ const segments = id.split("/");
3198
+ if (segments.slice(0, -1).some((seg) => seg.toLowerCase().endsWith(".md"))) {
3199
+ throw new InvalidInputError(
3200
+ `Concept id must not contain a non-final segment ending in '.md': '${id}' (it collides with a concept file at that path).`
3201
+ );
3202
+ }
3203
+ }
3204
+ function nonCanonicalDocumentId(id) {
3205
+ const segments = id.split("/");
3206
+ if (segments.some((segment) => segment !== segment.trim())) return "segment_whitespace";
3207
+ if (segments.some((segment) => FORMAT_AT_EDGE.test(segment) || FORMAT_INSIDE.test(segment))) return "format_character";
3208
+ if (id !== id.normalize("NFC")) return "not_nfc";
3209
+ return null;
3210
+ }
3211
+ function assertSafeBlobKey(key4) {
3212
+ if (typeof key4 !== "string" || key4.trim() === "") {
3213
+ throw new InvalidInputError("Blob key must be a non-empty string.");
3214
+ }
3215
+ assertPortablePath(key4, "Blob key");
3216
+ const segments = key4.split("/");
3217
+ if (segments.some((seg) => seg.startsWith("."))) {
3218
+ throw new InvalidInputError(`Blob key must not contain dot-prefixed segments: '${key4}'.`);
3219
+ }
3220
+ if (segments.some((seg) => seg.toLowerCase().endsWith(".md"))) {
3221
+ throw new InvalidInputError(
3222
+ `Blob key '${key4}' has a path segment ending in '.md' (checked case-insensitively, at any depth), which collides with the concept-document namespace \u2014 write it as a doc instead.`
3223
+ );
3224
+ }
3225
+ }
3226
+ function assertSafeReservedDir(dir) {
3227
+ if (typeof dir !== "string") {
3228
+ throw new InvalidInputError("Reserved-file directory must be a string.");
3229
+ }
3230
+ if (dir !== "") assertPortablePath(dir, "Reserved-file directory");
3231
+ }
3232
+ var RESERVED_FILENAMES, FORMAT_AT_EDGE, FORMAT_INSIDE;
3233
+ var init_paths = __esm({
3234
+ "../core/src/paths.ts"() {
3235
+ "use strict";
3236
+ init_define_SUPERBEE_BUILD_IDENTITY();
3237
+ init_define_SUPERBEE_UPDATE_POLICY();
3238
+ init_errors();
3239
+ RESERVED_FILENAMES = ["index.md", "log.md"];
3240
+ FORMAT_AT_EDGE = new RegExp("^\\p{Cf}|\\p{Cf}$", "u");
3241
+ FORMAT_INSIDE = new RegExp("(?![\\u200c\\u200d])\\p{Cf}", "u");
3242
+ }
3243
+ });
3244
+
3245
+ // ../core/src/links.ts
3246
+ function normalizeSegments(segments) {
3247
+ const out = [];
3248
+ for (const segment of segments) {
3249
+ if (segment === "" || segment === ".") continue;
3250
+ if (segment === ".." && out.length > 0 && out[out.length - 1] !== "..") {
3251
+ out.pop();
3252
+ continue;
3253
+ }
3254
+ out.push(segment);
3255
+ }
3256
+ return out;
3257
+ }
3258
+ function joinPosix(base, rel) {
3259
+ return normalizeSegments([...base.split("/"), ...rel.split("/")]).join("/");
3260
+ }
3261
+ function relativePosix(from, to) {
3262
+ const fromSegments = normalizeSegments(from.split("/"));
3263
+ const toSegments = normalizeSegments(to.split("/"));
3264
+ let common = 0;
3265
+ while (common < fromSegments.length && common < toSegments.length && fromSegments[common] === toSegments[common]) {
3266
+ common++;
3267
+ }
3268
+ const ups = fromSegments.length - common;
3269
+ return [...Array(ups).fill(".."), ...toSegments.slice(common)].join("/");
3270
+ }
3271
+ function isExternalHref(href) {
3272
+ const h2 = href.trim();
3273
+ return /^[a-z][a-z0-9+.-]*:\/\//i.test(h2) || h2.startsWith("mailto:") || h2.startsWith("#");
3274
+ }
3275
+ function extractMarkdownLinks(source2, options = {}) {
3276
+ const body = options.skipCode ? maskMarkdownCode(source2) : source2;
3277
+ const out = [];
3278
+ let textOpen = -1;
3279
+ let afterClose;
3280
+ let hrefFirst;
3281
+ let hrefRest;
3282
+ for (let cursor = 0; cursor < body.length; cursor++) {
3283
+ const char = body[cursor];
3284
+ if (hrefRest) {
3285
+ if (char === ")") {
3286
+ if (hrefRest.open === 0 || body[hrefRest.open - 1] !== "!") {
3287
+ out.push({
3288
+ text: source2.slice(hrefRest.open + 1, hrefRest.close),
3289
+ href: source2.slice(hrefRest.hrefStart, cursor)
3290
+ });
3291
+ }
3292
+ textOpen = -1;
3293
+ afterClose = void 0;
3294
+ hrefFirst = void 0;
3295
+ hrefRest = void 0;
3296
+ continue;
3297
+ }
3298
+ if (char.trim() === "") hrefRest = void 0;
3299
+ }
3300
+ if (hrefFirst) {
3301
+ if (char !== ")" && char.trim() !== "" && !hrefRest) {
3302
+ hrefRest = hrefFirst;
3303
+ }
3304
+ hrefFirst = void 0;
3305
+ }
3306
+ if (afterClose) {
3307
+ if (char === "(") {
3308
+ hrefFirst = { ...afterClose, hrefStart: cursor + 1 };
3309
+ }
3310
+ afterClose = void 0;
3311
+ }
3312
+ if (textOpen >= 0 && char === "]") {
3313
+ afterClose = { open: textOpen, close: cursor };
3314
+ textOpen = -1;
3315
+ }
3316
+ if (char === "[" && textOpen < 0) textOpen = cursor;
3317
+ }
3318
+ return out;
3319
+ }
3320
+ function leadingIndent(line2, from, startColumn) {
3321
+ let columns = 0;
3322
+ let index2 = from;
3323
+ while (index2 < line2.length) {
3324
+ const char = line2[index2];
3325
+ if (char === " ") columns += 1;
3326
+ else if (char === " ") columns += 4 - (startColumn + columns) % 4;
3327
+ else break;
3328
+ index2++;
3329
+ }
3330
+ return { columns, chars: index2 - from };
3331
+ }
3332
+ function maskMarkdownCode(body) {
3333
+ const out = body.split("");
3334
+ const blank = (from, to) => {
3335
+ for (let index2 = from; index2 < to; index2++) if (out[index2] !== "\n" && out[index2] !== "\r") out[index2] = " ";
3336
+ };
3337
+ const lists = [];
3338
+ let fence = null;
3339
+ let inParagraph = false;
3340
+ let segmentStart = -1;
3341
+ const closeSegment = (end) => {
3342
+ if (segmentStart >= 0) maskCodeSpans(body, segmentStart, end, blank);
3343
+ segmentStart = -1;
3344
+ };
3345
+ let lineStart = 0;
3346
+ while (lineStart <= body.length) {
3347
+ const newline = body.indexOf("\n", lineStart);
3348
+ const lineEnd = newline < 0 ? body.length : newline;
3349
+ const line2 = body.slice(lineStart, lineEnd);
3350
+ let contentAt = 0;
3351
+ let quotes = 0;
3352
+ for (let match = /^ {0,3}> ?/.exec(line2); match; match = /^ {0,3}> ?/.exec(line2.slice(contentAt))) {
3353
+ if (fence && quotes >= fence.quotes) break;
3354
+ contentAt += match[0].length;
3355
+ quotes++;
3356
+ }
3357
+ const { columns: indent2, chars } = leadingIndent(line2, contentAt, contentAt);
3358
+ const rest = line2.slice(contentAt + chars).replace(/\r$/, "");
3359
+ const isBlank = rest.trim() === "";
3360
+ if (fence && (quotes < fence.quotes || !isBlank && indent2 < fence.container)) fence = null;
3361
+ if (fence) {
3362
+ const close = indent2 - fence.container <= 3 ? FENCE_OPEN.exec(rest) : null;
3363
+ if (close && close[1][0] === fence.char && close[1].length >= fence.length && close[2].trim() === "") fence = null;
3364
+ blank(lineStart, lineEnd);
3365
+ } else if (isBlank) {
3366
+ closeSegment(lineStart);
3367
+ inParagraph = false;
3368
+ } else {
3369
+ if (!inParagraph) while (lists.length > 0 && lists[lists.length - 1] > indent2) lists.pop();
3370
+ let container = lists.length > 0 ? lists[lists.length - 1] : 0;
3371
+ let relative3 = indent2 - container;
3372
+ let text5 = rest;
3373
+ let textAt = lineStart + contentAt + chars;
3374
+ const marker = relative3 <= 3 && !THEMATIC_BREAK.test(text5) ? LIST_MARKER.exec(text5) : null;
3375
+ if (marker) {
3376
+ closeSegment(lineStart);
3377
+ const markerEnd = indent2 + marker[1].length;
3378
+ const spacing = leadingIndent(marker[2], 0, contentAt + markerEnd).columns;
3379
+ const wide = marker[2] === "" || spacing >= 5;
3380
+ lists.push(markerEnd + (wide ? 1 : spacing));
3381
+ container = lists[lists.length - 1];
3382
+ text5 = text5.slice(marker[1].length + (wide ? 0 : marker[2].length));
3383
+ textAt += marker[1].length + (wide ? 0 : marker[2].length);
3384
+ relative3 = wide ? Math.max(spacing - 1, 0) : 0;
3385
+ inParagraph = false;
3386
+ }
3387
+ const open5 = relative3 <= 3 ? FENCE_OPEN.exec(text5) : null;
3388
+ if (open5 && !(open5[1][0] === "`" && open5[2].includes("`"))) {
3389
+ closeSegment(lineStart);
3390
+ fence = { char: open5[1][0], length: open5[1].length, container, quotes };
3391
+ blank(textAt, lineEnd);
3392
+ inParagraph = false;
3393
+ } else if (!inParagraph && relative3 >= 4) {
3394
+ closeSegment(lineStart);
3395
+ blank(textAt, lineEnd);
3396
+ } else if (ATX_HEADING.test(text5) || THEMATIC_BREAK.test(text5)) {
3397
+ closeSegment(lineStart);
3398
+ maskCodeSpans(body, textAt, lineEnd, blank);
3399
+ inParagraph = false;
3400
+ } else {
3401
+ if (segmentStart < 0) segmentStart = textAt;
3402
+ inParagraph = text5.trim() !== "";
3403
+ }
3404
+ }
3405
+ if (newline < 0) break;
3406
+ lineStart = newline + 1;
3407
+ }
3408
+ closeSegment(body.length);
3409
+ return out.join("");
3410
+ }
3411
+ function maskCodeSpans(body, from, to, blank) {
3412
+ const runs = [];
3413
+ for (let index2 = from; index2 < to; ) {
3414
+ if (body[index2] !== "`") {
3415
+ index2++;
3416
+ continue;
3417
+ }
3418
+ let end = index2;
3419
+ while (end < to && body[end] === "`") end++;
3420
+ runs.push({ at: index2, length: end - index2 });
3421
+ index2 = end;
3422
+ }
3423
+ const byLength = /* @__PURE__ */ new Map();
3424
+ runs.forEach((run, position2) => {
3425
+ const list6 = byLength.get(run.length);
3426
+ if (list6) list6.push(position2);
3427
+ else byLength.set(run.length, [position2]);
3428
+ });
3429
+ const next = /* @__PURE__ */ new Map();
3430
+ const nextRun = (length, after) => {
3431
+ const list6 = byLength.get(length);
3432
+ if (!list6) return -1;
3433
+ let cursor = next.get(length) ?? 0;
3434
+ while (cursor < list6.length && list6[cursor] <= after) cursor++;
3435
+ next.set(length, cursor);
3436
+ return cursor < list6.length ? list6[cursor] : -1;
3437
+ };
3438
+ let escapeScan = from;
3439
+ let escaped = false;
3440
+ for (let position2 = 0; position2 < runs.length; position2++) {
3441
+ let { at, length } = runs[position2];
3442
+ for (; escapeScan < at; escapeScan++) escaped = body[escapeScan] === "\\" ? !escaped : false;
3443
+ if (escaped) {
3444
+ at += 1;
3445
+ length -= 1;
3446
+ escaped = false;
3447
+ if (length === 0) continue;
3448
+ const list6 = byLength.get(length);
3449
+ if (!list6) continue;
3450
+ }
3451
+ const closer = nextRun(length, position2);
3452
+ if (closer < 0) continue;
3453
+ const close = runs[closer];
3454
+ blank(at, close.at + close.length);
3455
+ position2 = closer;
3456
+ escapeScan = close.at + close.length;
3457
+ escaped = false;
3458
+ }
3459
+ }
3460
+ function resolveConceptId(fromId, href) {
3461
+ const target3 = (href.split("#")[0] ?? "").split("?")[0]?.trim() ?? "";
3462
+ if (target3 === "" || isExternalHref(target3)) return null;
3463
+ if (!target3.endsWith(".md")) return null;
3464
+ let resolved;
3465
+ if (target3.startsWith("/")) {
3466
+ resolved = target3.slice(1);
3467
+ } else {
3468
+ const slash = fromId.lastIndexOf("/");
3469
+ const fromDir = slash >= 0 ? fromId.slice(0, slash) : "";
3470
+ resolved = joinPosix(fromDir, target3);
3471
+ }
3472
+ resolved = resolved.replace(/^(\.\.\/)+/, "");
3473
+ if (isReservedFile(resolved)) return null;
3474
+ const id = resolved.replace(/\.md$/, "");
3475
+ try {
3476
+ assertSafeConceptId(id);
3477
+ return id;
3478
+ } catch (error51) {
3479
+ if (error51 instanceof InvalidInputError) return null;
3480
+ throw error51;
3481
+ }
3482
+ }
3483
+ function relativeHref(fromId, target3) {
3484
+ const t = target3.trim();
3485
+ if (isExternalHref(t)) return t;
3486
+ assertSafeConceptId(fromId);
3487
+ assertSafeConceptId(t);
3488
+ const targetId = t;
3489
+ const slash = fromId.lastIndexOf("/");
3490
+ const fromDir = slash >= 0 ? fromId.slice(0, slash) : "";
3491
+ return relativePosix(fromDir, `${targetId}.md`);
3492
+ }
3493
+ function parseLinksFromDoc(doc2) {
3494
+ const links = [];
3495
+ for (const raw of extractMarkdownLinks(doc2.body)) {
3496
+ const to = resolveConceptId(doc2.id, raw.href);
3497
+ if (to === null) continue;
3498
+ links.push({ from: doc2.id, to, text: raw.text, href: raw.href });
3499
+ }
3500
+ return links;
3501
+ }
3502
+ var FENCE_OPEN, LIST_MARKER, THEMATIC_BREAK, ATX_HEADING;
3503
+ var init_links = __esm({
3504
+ "../core/src/links.ts"() {
3505
+ "use strict";
3506
+ init_define_SUPERBEE_BUILD_IDENTITY();
3507
+ init_define_SUPERBEE_UPDATE_POLICY();
3508
+ init_paths();
3509
+ init_errors();
3510
+ FENCE_OPEN = /^(`{3,}|~{3,})(.*)$/;
3511
+ LIST_MARKER = /^([-+*]|\d{1,9}[.)])([ \t]+|$)/;
3512
+ THEMATIC_BREAK = /^(?:(?:\*[ \t]*){3,}|(?:-[ \t]*){3,}|(?:_[ \t]*){3,})$/;
3513
+ ATX_HEADING = /^#{1,6}(?:[ \t]|$)/;
3514
+ }
3515
+ });
3516
+
3517
+ // ../core/src/body-replace-guards.ts
3518
+ function previewTruncationNotice(omitted) {
3519
+ return `${BODY_PREVIEW_TRUNCATION_MARKER} ${omitted} more character(s) are NOT shown`;
3520
+ }
3521
+ function attachBodyPreview(rec, body, fullBodyHelp) {
3522
+ if (body.length <= BODY_PREVIEW_LIMIT) {
3523
+ rec.body = body;
3524
+ return;
3525
+ }
3526
+ const omitted = body.length - BODY_PREVIEW_LIMIT;
3527
+ rec[BODY_PREVIEW_KEY] = `${body.slice(0, BODY_PREVIEW_LIMIT)}
3528
+
3529
+ ${previewTruncationNotice(omitted)} \u2014 this value is a preview, not the document body; use this record's help to read the complete body before rewriting it.`;
3530
+ rec.body_truncated = true;
3531
+ rec.body_chars = body.length;
3532
+ rec.help = [...fullBodyHelp];
3533
+ }
3534
+ function matchesPreviewSlice(candidate, preview4) {
3535
+ if (candidate === preview4) return true;
3536
+ const trimmed = preview4.trimEnd();
3537
+ return trimmed !== "" && candidate.trimEnd() === trimmed;
3538
+ }
3539
+ function firstForeignNotice(storedBody, nextBody) {
3540
+ const preservesStoredBody = nextBody.includes(storedBody.trimEnd());
3541
+ const every = new RegExp(BODY_PREVIEW_TRUNCATION_SIGNATURE.source, `${BODY_PREVIEW_TRUNCATION_SIGNATURE.flags}g`);
3542
+ for (const match of nextBody.matchAll(every)) {
3543
+ if (!(preservesStoredBody && storedBody.includes(match[0]))) return match[0];
3544
+ }
3545
+ return void 0;
3546
+ }
3547
+ function isSameStoredBody(nextBody, existingBody) {
3548
+ return normalizeDocumentBodyForStorage(nextBody) === normalizeDocumentBodyForStorage(existingBody);
3549
+ }
3550
+ function bodyPreviewFinding(existing, nextBody) {
3551
+ if (isSameStoredBody(nextBody, existing.body)) return;
3552
+ const notice = firstForeignNotice(existing.body, nextBody);
3553
+ if (notice !== void 0) return { reason: "preview_marker", marker: BODY_PREVIEW_TRUNCATION_MARKER, notice };
3554
+ if (existing.body.length > BODY_PREVIEW_LIMIT && matchesPreviewSlice(nextBody, existing.body.slice(0, BODY_PREVIEW_LIMIT))) {
3555
+ return { reason: "stored_body_preview", preview_limit: BODY_PREVIEW_LIMIT, supplied_body_chars: nextBody.length, stored_body_chars: existing.body.length };
3556
+ }
3557
+ }
3558
+ function captureBodyReplacePosture(value) {
3559
+ if (value === void 0) return;
3560
+ if (value === null || typeof value !== "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) {
3561
+ throw new InvalidInputError("bodyReplace must be an object with boolean acceptTruncatedBody and/or replaceLinks fields.");
3562
+ }
3563
+ const captured = {};
3564
+ for (const key4 of Reflect.ownKeys(value)) {
3565
+ if (key4 !== "acceptTruncatedBody" && key4 !== "replaceLinks") throw new InvalidInputError("Unknown bodyReplace field.");
3566
+ const descriptor = Object.getOwnPropertyDescriptor(value, key4);
3567
+ if (!("value" in descriptor) || typeof descriptor.value !== "boolean") throw new InvalidInputError(`bodyReplace.${key4} must be a boolean.`);
3568
+ captured[key4] = descriptor.value;
3569
+ }
3570
+ return captured;
3571
+ }
3572
+ function computeDroppedLinks(existingLinks, nextLinks, mode = "target") {
3573
+ const nextByTarget = /* @__PURE__ */ new Map();
3574
+ for (const l of nextLinks) {
3575
+ const key4 = mode === "exact-edge" ? JSON.stringify([l.from, l.to]) : l.to;
3576
+ const bucket = nextByTarget.get(key4);
3577
+ if (bucket) bucket.push(l);
3578
+ else nextByTarget.set(key4, [l]);
3579
+ }
3580
+ const existingByTarget = /* @__PURE__ */ new Map();
3581
+ for (const l of existingLinks) {
3582
+ const key4 = mode === "exact-edge" ? JSON.stringify([l.from, l.to]) : l.to;
3583
+ const bucket = existingByTarget.get(key4);
3584
+ if (bucket) bucket.push(l);
3585
+ else existingByTarget.set(key4, [l]);
3586
+ }
3587
+ const dropped = [];
3588
+ for (const [target3, oldOccurrences] of existingByTarget) {
3589
+ const available = [...nextByTarget.get(target3) ?? []];
3590
+ const unmatchedExact = [];
3591
+ for (const old of oldOccurrences) {
3592
+ const idx = available.findIndex((n) => n.text === old.text);
3593
+ if (idx >= 0) available.splice(idx, 1);
3594
+ else unmatchedExact.push(old);
3595
+ }
3596
+ for (const old of unmatchedExact) {
3597
+ if (mode === "target" && available.length > 0) available.shift();
3598
+ else dropped.push(old);
3599
+ }
3600
+ }
3601
+ return dropped;
3602
+ }
3603
+ function droppedLinks(_bundle, existing, nextBody) {
3604
+ return computeDroppedLinks(parseLinksFromDoc(existing), parseLinksFromDoc({ ...existing, body: nextBody }));
3605
+ }
3606
+ function guardTruncatedBodyPreview(existing, nextBody, acceptTruncatedBody) {
3607
+ if (acceptTruncatedBody) return;
3608
+ const finding = bodyPreviewFinding(existing, nextBody);
3609
+ if (finding) throw new BodyReplaceError(existing.id, finding, BODY_PREVIEW_TRUNCATION_SIGNATURE.test(existing.body));
3610
+ }
3611
+ function guardDroppedLinks(bundle, existing, nextBody, replaceLinks) {
3612
+ if (replaceLinks || isSameStoredBody(nextBody, existing.body)) return;
3613
+ const dropped = droppedLinks(bundle, existing, nextBody);
3614
+ if (dropped.length) throw new BodyReplaceError(existing.id, { reason: "dropped_links", dropped_links: dropped });
3615
+ }
3616
+ function guardBodyReplace(bundle, existing, nextBody, posture) {
3617
+ if (isSameStoredBody(nextBody, existing.body)) return;
3618
+ guardTruncatedBodyPreview(existing, nextBody, Boolean(posture?.acceptTruncatedBody));
3619
+ guardDroppedLinks(bundle, existing, nextBody, Boolean(posture?.replaceLinks));
3620
+ }
3621
+ function assertTypedListPatch(kind2, storageField) {
3622
+ const types = kind2.fields.types ?? {};
3623
+ const type = Object.hasOwn(types, storageField) ? types[storageField] : void 0;
3624
+ if (type === "string-list" || type === "https-url-list") throw new TypedListPatchError(storageField, type);
3625
+ }
3626
+ var BODY_PREVIEW_LIMIT, BODY_PREVIEW_TRUNCATION_MARKER, BODY_PREVIEW_TRUNCATION_SIGNATURE, BODY_PREVIEW_KEY, BODY_PREVIEW_RESERVED_KEYS, BodyReplaceError, TypedListPatchError;
3627
+ var init_body_replace_guards = __esm({
3628
+ "../core/src/body-replace-guards.ts"() {
3629
+ "use strict";
3630
+ init_define_SUPERBEE_BUILD_IDENTITY();
3631
+ init_define_SUPERBEE_UPDATE_POLICY();
3632
+ init_frontmatter();
3633
+ init_links();
3634
+ init_errors();
3635
+ BODY_PREVIEW_LIMIT = 1e3;
3636
+ BODY_PREVIEW_TRUNCATION_MARKER = "[superbee:body-preview-truncated]";
3637
+ BODY_PREVIEW_TRUNCATION_SIGNATURE = /\[superbee:body-preview-truncated\]\s+\d+\s+more\s+characters?\(?s?\)?\s+are\s+NOT\s+shown/i;
3638
+ BODY_PREVIEW_KEY = "body_preview";
3639
+ BODY_PREVIEW_RESERVED_KEYS = [
3640
+ "body",
3641
+ BODY_PREVIEW_KEY,
3642
+ "body_truncated",
3643
+ "body_chars",
3644
+ "help"
3645
+ ];
3646
+ BodyReplaceError = class extends InvalidInputError {
3647
+ id;
3648
+ finding;
3649
+ storedCarriesNotice;
3650
+ constructor(id, finding, storedCarriesNotice = false) {
3651
+ super(`Body replacement of '${id}' refused: ${finding.reason}.`);
3652
+ this.name = "BodyReplaceError";
3653
+ this.id = id;
3654
+ this.finding = finding;
3655
+ this.storedCarriesNotice = storedCarriesNotice;
3656
+ }
3657
+ };
3658
+ TypedListPatchError = class extends InvalidInputError {
3659
+ field;
3660
+ fieldType;
3661
+ constructor(field, fieldType) {
3662
+ super(`'${field}' is a ${fieldType} field; use an explicit whole-list replacement.`);
3663
+ this.name = "TypedListPatchError";
3664
+ this.field = field;
3665
+ this.fieldType = fieldType;
3666
+ }
3667
+ };
3668
+ }
3669
+ });
3670
+
3671
+ // ../core/src/version-transport.ts
3672
+ function isContentVersion(value) {
3673
+ return typeof value === "string" && /^sha256:[0-9a-f]{64}$/.test(value);
3674
+ }
3675
+ function stripETagWrapper(raw) {
3676
+ let value = raw.trim();
3677
+ if (value.startsWith("W/")) value = value.slice(2);
3678
+ if (value.length >= 2 && value.startsWith('"') && value.endsWith('"')) {
3679
+ value = value.slice(1, -1);
3680
+ }
3681
+ return value;
3682
+ }
3683
+ var VersionConflict;
3684
+ var init_version_transport = __esm({
3685
+ "../core/src/version-transport.ts"() {
3686
+ "use strict";
3687
+ init_define_SUPERBEE_BUILD_IDENTITY();
3688
+ init_define_SUPERBEE_UPDATE_POLICY();
3689
+ VersionConflict = class extends Error {
3690
+ name = "VersionConflict";
3691
+ id;
3692
+ expected;
3693
+ actual;
3694
+ constructor(id, expected, actual) {
3695
+ super(
3696
+ `version conflict on '${id}': expected ${expected ?? "absent"}, found ${actual ?? "none"} (the document changed since you read it \u2014 re-read and retry)`
3697
+ );
3698
+ this.id = id;
3699
+ this.expected = expected;
3700
+ this.actual = actual;
3701
+ }
3702
+ };
3703
+ }
3704
+ });
3705
+
3706
+ // ../core/src/meaningful-change-time.ts
3707
+ function meaningfulChangeTimeField(frontmatter) {
3708
+ const generated = frontmatter.generated;
3709
+ if (generated !== null && typeof generated === "object" && !Array.isArray(generated) && generated.at !== void 0) return "generated.at";
3710
+ return "timestamp";
3711
+ }
3712
+ function meaningfulChangeTimeValue(frontmatter) {
3713
+ return meaningfulChangeTimeField(frontmatter) === "generated.at" ? frontmatter.generated.at : frontmatter.timestamp;
3714
+ }
3715
+ var init_meaningful_change_time = __esm({
3716
+ "../core/src/meaningful-change-time.ts"() {
3717
+ "use strict";
3718
+ init_define_SUPERBEE_BUILD_IDENTITY();
3719
+ init_define_SUPERBEE_UPDATE_POLICY();
3720
+ }
3721
+ });
3722
+
3170
3723
  // ../core/src/okf-actor.ts
3171
3724
  function isOkfActor(value) {
3172
3725
  if (typeof value !== "string" || value.trim() !== value || value.length === 0 || /\s/.test(value)) {
@@ -3786,370 +4339,6 @@ var init_document_write_policy = __esm({
3786
4339
  }
3787
4340
  });
3788
4341
 
3789
- // ../core/src/paths.ts
3790
- function compareStorageKeys(a, b) {
3791
- const primary = a.localeCompare(b);
3792
- if (primary !== 0 || a === b) return primary;
3793
- const left = Array.from(a, (character) => character.codePointAt(0));
3794
- const right = Array.from(b, (character) => character.codePointAt(0));
3795
- for (let i = 0; i < Math.min(left.length, right.length); i++) {
3796
- if (left[i] !== right[i]) return left[i] - right[i];
3797
- }
3798
- return left.length - right.length;
3799
- }
3800
- function assertPortablePath(value, label) {
3801
- if (/[\u0000-\u001f\u007f]/u.test(value) || /^[a-z]:/i.test(value)) {
3802
- throw new InvalidInputError(`${label} must not contain controls or start with a drive prefix.`);
3803
- }
3804
- if (value.includes("\\") || value.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
3805
- throw new InvalidInputError(`${label} must be canonical and bundle-relative.`);
3806
- }
3807
- }
3808
- function assertSafeReservedFilename(name) {
3809
- if (!RESERVED_FILENAMES.includes(name)) {
3810
- throw new InvalidInputError("Reserved filename must be index.md or log.md.");
3811
- }
3812
- }
3813
- function toPosix(p2) {
3814
- return p2.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
3815
- }
3816
- function isReservedFile(relPath) {
3817
- const base = toPosix(relPath).split("/").pop() ?? "";
3818
- return RESERVED_FILENAMES.includes(base);
3819
- }
3820
- function conceptIdFromPath(relPath) {
3821
- const norm = toPosix(relPath).replace(/^\.?\//, "").split("/").filter((segment) => segment !== ".").join("/");
3822
- return norm.endsWith(".md") ? norm.slice(0, -3) : norm;
3823
- }
3824
- function pathFromConceptId(id) {
3825
- assertSafeConceptId(id);
3826
- return `${id}.md`;
3827
- }
3828
- function assertSafeConceptId(id) {
3829
- if (typeof id !== "string" || id.trim() === "") {
3830
- throw new InvalidInputError("Concept id must be a non-empty string.");
3831
- }
3832
- assertPortablePath(id, "Concept id");
3833
- const segments = id.split("/");
3834
- if (segments.slice(0, -1).some((seg) => seg.toLowerCase().endsWith(".md"))) {
3835
- throw new InvalidInputError(
3836
- `Concept id must not contain a non-final segment ending in '.md': '${id}' (it collides with a concept file at that path).`
3837
- );
3838
- }
3839
- }
3840
- function nonCanonicalDocumentId(id) {
3841
- const segments = id.split("/");
3842
- if (segments.some((segment) => segment !== segment.trim())) return "segment_whitespace";
3843
- if (segments.some((segment) => FORMAT_AT_EDGE.test(segment) || FORMAT_INSIDE.test(segment))) return "format_character";
3844
- if (id !== id.normalize("NFC")) return "not_nfc";
3845
- return null;
3846
- }
3847
- function assertSafeBlobKey(key4) {
3848
- if (typeof key4 !== "string" || key4.trim() === "") {
3849
- throw new InvalidInputError("Blob key must be a non-empty string.");
3850
- }
3851
- assertPortablePath(key4, "Blob key");
3852
- const segments = key4.split("/");
3853
- if (segments.some((seg) => seg.startsWith("."))) {
3854
- throw new InvalidInputError(`Blob key must not contain dot-prefixed segments: '${key4}'.`);
3855
- }
3856
- if (segments.some((seg) => seg.toLowerCase().endsWith(".md"))) {
3857
- throw new InvalidInputError(
3858
- `Blob key '${key4}' has a path segment ending in '.md' (checked case-insensitively, at any depth), which collides with the concept-document namespace \u2014 write it as a doc instead.`
3859
- );
3860
- }
3861
- }
3862
- function assertSafeReservedDir(dir) {
3863
- if (typeof dir !== "string") {
3864
- throw new InvalidInputError("Reserved-file directory must be a string.");
3865
- }
3866
- if (dir !== "") assertPortablePath(dir, "Reserved-file directory");
3867
- }
3868
- var RESERVED_FILENAMES, FORMAT_AT_EDGE, FORMAT_INSIDE;
3869
- var init_paths = __esm({
3870
- "../core/src/paths.ts"() {
3871
- "use strict";
3872
- init_define_SUPERBEE_BUILD_IDENTITY();
3873
- init_define_SUPERBEE_UPDATE_POLICY();
3874
- init_errors();
3875
- RESERVED_FILENAMES = ["index.md", "log.md"];
3876
- FORMAT_AT_EDGE = new RegExp("^\\p{Cf}|\\p{Cf}$", "u");
3877
- FORMAT_INSIDE = new RegExp("(?![\\u200c\\u200d])\\p{Cf}", "u");
3878
- }
3879
- });
3880
-
3881
- // ../core/src/links.ts
3882
- function normalizeSegments(segments) {
3883
- const out = [];
3884
- for (const segment of segments) {
3885
- if (segment === "" || segment === ".") continue;
3886
- if (segment === ".." && out.length > 0 && out[out.length - 1] !== "..") {
3887
- out.pop();
3888
- continue;
3889
- }
3890
- out.push(segment);
3891
- }
3892
- return out;
3893
- }
3894
- function joinPosix(base, rel) {
3895
- return normalizeSegments([...base.split("/"), ...rel.split("/")]).join("/");
3896
- }
3897
- function relativePosix(from, to) {
3898
- const fromSegments = normalizeSegments(from.split("/"));
3899
- const toSegments = normalizeSegments(to.split("/"));
3900
- let common = 0;
3901
- while (common < fromSegments.length && common < toSegments.length && fromSegments[common] === toSegments[common]) {
3902
- common++;
3903
- }
3904
- const ups = fromSegments.length - common;
3905
- return [...Array(ups).fill(".."), ...toSegments.slice(common)].join("/");
3906
- }
3907
- function isExternalHref(href) {
3908
- const h2 = href.trim();
3909
- return /^[a-z][a-z0-9+.-]*:\/\//i.test(h2) || h2.startsWith("mailto:") || h2.startsWith("#");
3910
- }
3911
- function extractMarkdownLinks(source2, options = {}) {
3912
- const body = options.skipCode ? maskMarkdownCode(source2) : source2;
3913
- const out = [];
3914
- let textOpen = -1;
3915
- let afterClose;
3916
- let hrefFirst;
3917
- let hrefRest;
3918
- for (let cursor = 0; cursor < body.length; cursor++) {
3919
- const char = body[cursor];
3920
- if (hrefRest) {
3921
- if (char === ")") {
3922
- if (hrefRest.open === 0 || body[hrefRest.open - 1] !== "!") {
3923
- out.push({
3924
- text: source2.slice(hrefRest.open + 1, hrefRest.close),
3925
- href: source2.slice(hrefRest.hrefStart, cursor)
3926
- });
3927
- }
3928
- textOpen = -1;
3929
- afterClose = void 0;
3930
- hrefFirst = void 0;
3931
- hrefRest = void 0;
3932
- continue;
3933
- }
3934
- if (char.trim() === "") hrefRest = void 0;
3935
- }
3936
- if (hrefFirst) {
3937
- if (char !== ")" && char.trim() !== "" && !hrefRest) {
3938
- hrefRest = hrefFirst;
3939
- }
3940
- hrefFirst = void 0;
3941
- }
3942
- if (afterClose) {
3943
- if (char === "(") {
3944
- hrefFirst = { ...afterClose, hrefStart: cursor + 1 };
3945
- }
3946
- afterClose = void 0;
3947
- }
3948
- if (textOpen >= 0 && char === "]") {
3949
- afterClose = { open: textOpen, close: cursor };
3950
- textOpen = -1;
3951
- }
3952
- if (char === "[" && textOpen < 0) textOpen = cursor;
3953
- }
3954
- return out;
3955
- }
3956
- function leadingIndent(line2, from, startColumn) {
3957
- let columns = 0;
3958
- let index2 = from;
3959
- while (index2 < line2.length) {
3960
- const char = line2[index2];
3961
- if (char === " ") columns += 1;
3962
- else if (char === " ") columns += 4 - (startColumn + columns) % 4;
3963
- else break;
3964
- index2++;
3965
- }
3966
- return { columns, chars: index2 - from };
3967
- }
3968
- function maskMarkdownCode(body) {
3969
- const out = body.split("");
3970
- const blank = (from, to) => {
3971
- for (let index2 = from; index2 < to; index2++) if (out[index2] !== "\n" && out[index2] !== "\r") out[index2] = " ";
3972
- };
3973
- const lists = [];
3974
- let fence = null;
3975
- let inParagraph = false;
3976
- let segmentStart = -1;
3977
- const closeSegment = (end) => {
3978
- if (segmentStart >= 0) maskCodeSpans(body, segmentStart, end, blank);
3979
- segmentStart = -1;
3980
- };
3981
- let lineStart = 0;
3982
- while (lineStart <= body.length) {
3983
- const newline = body.indexOf("\n", lineStart);
3984
- const lineEnd = newline < 0 ? body.length : newline;
3985
- const line2 = body.slice(lineStart, lineEnd);
3986
- let contentAt = 0;
3987
- let quotes = 0;
3988
- for (let match = /^ {0,3}> ?/.exec(line2); match; match = /^ {0,3}> ?/.exec(line2.slice(contentAt))) {
3989
- if (fence && quotes >= fence.quotes) break;
3990
- contentAt += match[0].length;
3991
- quotes++;
3992
- }
3993
- const { columns: indent2, chars } = leadingIndent(line2, contentAt, contentAt);
3994
- const rest = line2.slice(contentAt + chars).replace(/\r$/, "");
3995
- const isBlank = rest.trim() === "";
3996
- if (fence && (quotes < fence.quotes || !isBlank && indent2 < fence.container)) fence = null;
3997
- if (fence) {
3998
- const close = indent2 - fence.container <= 3 ? FENCE_OPEN.exec(rest) : null;
3999
- if (close && close[1][0] === fence.char && close[1].length >= fence.length && close[2].trim() === "") fence = null;
4000
- blank(lineStart, lineEnd);
4001
- } else if (isBlank) {
4002
- closeSegment(lineStart);
4003
- inParagraph = false;
4004
- } else {
4005
- if (!inParagraph) while (lists.length > 0 && lists[lists.length - 1] > indent2) lists.pop();
4006
- let container = lists.length > 0 ? lists[lists.length - 1] : 0;
4007
- let relative3 = indent2 - container;
4008
- let text5 = rest;
4009
- let textAt = lineStart + contentAt + chars;
4010
- const marker = relative3 <= 3 && !THEMATIC_BREAK.test(text5) ? LIST_MARKER.exec(text5) : null;
4011
- if (marker) {
4012
- closeSegment(lineStart);
4013
- const markerEnd = indent2 + marker[1].length;
4014
- const spacing = leadingIndent(marker[2], 0, contentAt + markerEnd).columns;
4015
- const wide = marker[2] === "" || spacing >= 5;
4016
- lists.push(markerEnd + (wide ? 1 : spacing));
4017
- container = lists[lists.length - 1];
4018
- text5 = text5.slice(marker[1].length + (wide ? 0 : marker[2].length));
4019
- textAt += marker[1].length + (wide ? 0 : marker[2].length);
4020
- relative3 = wide ? Math.max(spacing - 1, 0) : 0;
4021
- inParagraph = false;
4022
- }
4023
- const open5 = relative3 <= 3 ? FENCE_OPEN.exec(text5) : null;
4024
- if (open5 && !(open5[1][0] === "`" && open5[2].includes("`"))) {
4025
- closeSegment(lineStart);
4026
- fence = { char: open5[1][0], length: open5[1].length, container, quotes };
4027
- blank(textAt, lineEnd);
4028
- inParagraph = false;
4029
- } else if (!inParagraph && relative3 >= 4) {
4030
- closeSegment(lineStart);
4031
- blank(textAt, lineEnd);
4032
- } else if (ATX_HEADING.test(text5) || THEMATIC_BREAK.test(text5)) {
4033
- closeSegment(lineStart);
4034
- maskCodeSpans(body, textAt, lineEnd, blank);
4035
- inParagraph = false;
4036
- } else {
4037
- if (segmentStart < 0) segmentStart = textAt;
4038
- inParagraph = text5.trim() !== "";
4039
- }
4040
- }
4041
- if (newline < 0) break;
4042
- lineStart = newline + 1;
4043
- }
4044
- closeSegment(body.length);
4045
- return out.join("");
4046
- }
4047
- function maskCodeSpans(body, from, to, blank) {
4048
- const runs = [];
4049
- for (let index2 = from; index2 < to; ) {
4050
- if (body[index2] !== "`") {
4051
- index2++;
4052
- continue;
4053
- }
4054
- let end = index2;
4055
- while (end < to && body[end] === "`") end++;
4056
- runs.push({ at: index2, length: end - index2 });
4057
- index2 = end;
4058
- }
4059
- const byLength = /* @__PURE__ */ new Map();
4060
- runs.forEach((run, position2) => {
4061
- const list6 = byLength.get(run.length);
4062
- if (list6) list6.push(position2);
4063
- else byLength.set(run.length, [position2]);
4064
- });
4065
- const next = /* @__PURE__ */ new Map();
4066
- const nextRun = (length, after) => {
4067
- const list6 = byLength.get(length);
4068
- if (!list6) return -1;
4069
- let cursor = next.get(length) ?? 0;
4070
- while (cursor < list6.length && list6[cursor] <= after) cursor++;
4071
- next.set(length, cursor);
4072
- return cursor < list6.length ? list6[cursor] : -1;
4073
- };
4074
- let escapeScan = from;
4075
- let escaped = false;
4076
- for (let position2 = 0; position2 < runs.length; position2++) {
4077
- let { at, length } = runs[position2];
4078
- for (; escapeScan < at; escapeScan++) escaped = body[escapeScan] === "\\" ? !escaped : false;
4079
- if (escaped) {
4080
- at += 1;
4081
- length -= 1;
4082
- escaped = false;
4083
- if (length === 0) continue;
4084
- const list6 = byLength.get(length);
4085
- if (!list6) continue;
4086
- }
4087
- const closer = nextRun(length, position2);
4088
- if (closer < 0) continue;
4089
- const close = runs[closer];
4090
- blank(at, close.at + close.length);
4091
- position2 = closer;
4092
- escapeScan = close.at + close.length;
4093
- escaped = false;
4094
- }
4095
- }
4096
- function resolveConceptId(fromId, href) {
4097
- const target3 = (href.split("#")[0] ?? "").split("?")[0]?.trim() ?? "";
4098
- if (target3 === "" || isExternalHref(target3)) return null;
4099
- if (!target3.endsWith(".md")) return null;
4100
- let resolved;
4101
- if (target3.startsWith("/")) {
4102
- resolved = target3.slice(1);
4103
- } else {
4104
- const slash = fromId.lastIndexOf("/");
4105
- const fromDir = slash >= 0 ? fromId.slice(0, slash) : "";
4106
- resolved = joinPosix(fromDir, target3);
4107
- }
4108
- resolved = resolved.replace(/^(\.\.\/)+/, "");
4109
- if (isReservedFile(resolved)) return null;
4110
- const id = resolved.replace(/\.md$/, "");
4111
- try {
4112
- assertSafeConceptId(id);
4113
- return id;
4114
- } catch (error51) {
4115
- if (error51 instanceof InvalidInputError) return null;
4116
- throw error51;
4117
- }
4118
- }
4119
- function relativeHref(fromId, target3) {
4120
- const t = target3.trim();
4121
- if (isExternalHref(t)) return t;
4122
- assertSafeConceptId(fromId);
4123
- assertSafeConceptId(t);
4124
- const targetId = t;
4125
- const slash = fromId.lastIndexOf("/");
4126
- const fromDir = slash >= 0 ? fromId.slice(0, slash) : "";
4127
- return relativePosix(fromDir, `${targetId}.md`);
4128
- }
4129
- function parseLinksFromDoc(doc2) {
4130
- const links = [];
4131
- for (const raw of extractMarkdownLinks(doc2.body)) {
4132
- const to = resolveConceptId(doc2.id, raw.href);
4133
- if (to === null) continue;
4134
- links.push({ from: doc2.id, to, text: raw.text, href: raw.href });
4135
- }
4136
- return links;
4137
- }
4138
- var FENCE_OPEN, LIST_MARKER, THEMATIC_BREAK, ATX_HEADING;
4139
- var init_links = __esm({
4140
- "../core/src/links.ts"() {
4141
- "use strict";
4142
- init_define_SUPERBEE_BUILD_IDENTITY();
4143
- init_define_SUPERBEE_UPDATE_POLICY();
4144
- init_paths();
4145
- init_errors();
4146
- FENCE_OPEN = /^(`{3,}|~{3,})(.*)$/;
4147
- LIST_MARKER = /^([-+*]|\d{1,9}[.)])([ \t]+|$)/;
4148
- THEMATIC_BREAK = /^(?:(?:\*[ \t]*){3,}|(?:-[ \t]*){3,}|(?:_[ \t]*){3,})$/;
4149
- ATX_HEADING = /^#{1,6}(?:[ \t]|$)/;
4150
- }
4151
- });
4152
-
4153
4342
  // ../core/src/portable-frontmatter.ts
4154
4343
  function parseLeadingFrontmatter(raw, context2) {
4155
4344
  const split = splitLeadingFrontmatter(raw, context2);
@@ -4410,11 +4599,34 @@ async function listBlobs(backend, prefix) {
4410
4599
  async function deleteBlob(backend, key4, options) {
4411
4600
  return backend.deleteBlob(key4, options);
4412
4601
  }
4602
+ async function writeDocVersionedGuarded(backend, doc2, options = {}) {
4603
+ const candidate = structuredClone(doc2);
4604
+ assertWritableConceptDocument(candidate);
4605
+ const posture = captureBodyReplacePosture(options.bodyReplace);
4606
+ const captured = { ...options, ...posture === void 0 ? {} : { bodyReplace: posture } };
4607
+ let existing;
4608
+ try {
4609
+ existing = await backend.read(candidate.id);
4610
+ } catch (error51) {
4611
+ if (error51?.code !== "ENOENT") throw error51;
4612
+ }
4613
+ const observed = existing?.version ?? null;
4614
+ if (captured.expectedVersion !== void 0 && captured.expectedVersion !== observed) {
4615
+ throw new VersionConflict(candidate.id, captured.expectedVersion, observed);
4616
+ }
4617
+ if ((posture?.replaceLinks || posture?.acceptTruncatedBody) && captured.expectedVersion === void 0) {
4618
+ throw new InvalidInputError("bodyReplace overrides require an explicit expected version (If-Match or If-None-Match: *).");
4619
+ }
4620
+ if (existing) guardBodyReplace({ root: "", backend }, existing.doc, candidate.body, posture);
4621
+ return writeDocVersioned(backend, candidate, { ...captured, expectedVersion: observed });
4622
+ }
4413
4623
  var init_engine = __esm({
4414
4624
  "../core/src/engine.ts"() {
4415
4625
  "use strict";
4416
4626
  init_define_SUPERBEE_BUILD_IDENTITY();
4417
4627
  init_define_SUPERBEE_UPDATE_POLICY();
4628
+ init_body_replace_guards();
4629
+ init_version_transport();
4418
4630
  init_document_write_policy();
4419
4631
  init_errors();
4420
4632
  init_frontmatter_contract();
@@ -4422,6 +4634,7 @@ var init_engine = __esm({
4422
4634
  init_paths();
4423
4635
  init_portable_frontmatter();
4424
4636
  init_query_filter();
4637
+ init_body_replace_guards();
4425
4638
  }
4426
4639
  });
4427
4640
 
@@ -5846,41 +6059,6 @@ var init_sha256 = __esm({
5846
6059
  }
5847
6060
  });
5848
6061
 
5849
- // ../core/src/version-transport.ts
5850
- function isContentVersion(value) {
5851
- return typeof value === "string" && /^sha256:[0-9a-f]{64}$/.test(value);
5852
- }
5853
- function stripETagWrapper(raw) {
5854
- let value = raw.trim();
5855
- if (value.startsWith("W/")) value = value.slice(2);
5856
- if (value.length >= 2 && value.startsWith('"') && value.endsWith('"')) {
5857
- value = value.slice(1, -1);
5858
- }
5859
- return value;
5860
- }
5861
- var VersionConflict;
5862
- var init_version_transport = __esm({
5863
- "../core/src/version-transport.ts"() {
5864
- "use strict";
5865
- init_define_SUPERBEE_BUILD_IDENTITY();
5866
- init_define_SUPERBEE_UPDATE_POLICY();
5867
- VersionConflict = class extends Error {
5868
- name = "VersionConflict";
5869
- id;
5870
- expected;
5871
- actual;
5872
- constructor(id, expected, actual) {
5873
- super(
5874
- `version conflict on '${id}': expected ${expected ?? "absent"}, found ${actual ?? "none"} (the document changed since you read it \u2014 re-read and retry)`
5875
- );
5876
- this.id = id;
5877
- this.expected = expected;
5878
- this.actual = actual;
5879
- }
5880
- };
5881
- }
5882
- });
5883
-
5884
6062
  // ../core/src/versioning.ts
5885
6063
  function sha256Hex(input) {
5886
6064
  return sha256HexOfUtf8(input);
@@ -8677,6 +8855,7 @@ function assertJournalGuard(expected, current) {
8677
8855
  if (!equalJournalValue(a, b)) throw new JournalGuardConflict(a.target);
8678
8856
  }
8679
8857
  function captureIntentUpdate(patch, options) {
8858
+ if (Object.hasOwn(patch, "bodyReplace")) throw new JournalGuardConflict("bodyReplace");
8680
8859
  const guard = captureJournalGuardOption(options);
8681
8860
  if (guard !== void 0) captureJournalValue({ patch, options });
8682
8861
  if (options.document && guard === void 0) throw new JournalGuardConflict(options.document.id);
@@ -8747,7 +8926,17 @@ function captureJournalDeleteOptions(target3, options) {
8747
8926
  }
8748
8927
  return captured;
8749
8928
  }
8929
+ function captureNewDocumentIntent(intent) {
8930
+ const captured = captureJournalValue(intent);
8931
+ const posture = captureBodyReplacePosture(captured.bodyReplace);
8932
+ if (posture !== void 0) {
8933
+ if (captured.kind !== "document.write") throw new JournalGuardConflict(captured.target);
8934
+ return { ...captured, bodyReplace: posture };
8935
+ }
8936
+ return captured;
8937
+ }
8750
8938
  function assertDeletionIntent(target3, options) {
8939
+ if (options.intent && Object.hasOwn(options.intent, "bodyReplace")) throw new JournalSnapshotConflict(target3);
8751
8940
  if (options.intent === void 0 && options.supersede === void 0) return;
8752
8941
  if (options.guard !== void 0 || options.intent !== void 0 && (options.intent.kind !== DOCUMENT_DELETE_KIND || options.intent.target !== target3)) {
8753
8942
  throw new JournalSnapshotConflict(target3);
@@ -8782,6 +8971,7 @@ var init_journaled_backend = __esm({
8782
8971
  "use strict";
8783
8972
  init_define_SUPERBEE_BUILD_IDENTITY();
8784
8973
  init_define_SUPERBEE_UPDATE_POLICY();
8974
+ init_body_replace_guards();
8785
8975
  init_paths();
8786
8976
  init_versioning();
8787
8977
  DOCUMENT_DELETE_KIND = "document.delete";
@@ -8906,8 +9096,8 @@ function captureRemoteFrontmatter(frontmatter) {
8906
9096
  };
8907
9097
  return visit3(frontmatter, "frontmatter", 0);
8908
9098
  }
8909
- function encodeRemoteDocument(frontmatter, body) {
8910
- const payload = Object.assign(/* @__PURE__ */ Object.create(null), { frontmatter: captureRemoteFrontmatter(frontmatter), body });
9099
+ function encodeRemoteDocument(frontmatter, body, bodyReplace) {
9100
+ const payload = Object.assign(/* @__PURE__ */ Object.create(null), { frontmatter: captureRemoteFrontmatter(frontmatter), body, ...bodyReplace === void 0 ? {} : { bodyReplace: captureBodyReplacePosture(bodyReplace) } });
8911
9101
  return JSON.stringify(payload);
8912
9102
  }
8913
9103
  var RemoteDocumentValueError;
@@ -8916,6 +9106,7 @@ var init_remote_document_codec = __esm({
8916
9106
  "use strict";
8917
9107
  init_define_SUPERBEE_BUILD_IDENTITY();
8918
9108
  init_define_SUPERBEE_UPDATE_POLICY();
9109
+ init_body_replace_guards();
8919
9110
  init_errors();
8920
9111
  RemoteDocumentValueError = class extends InvalidInputError {
8921
9112
  path;
@@ -9501,7 +9692,7 @@ var init_remote_backend = __esm({
9501
9692
  if (options.expectedVersion === null) headers["If-None-Match"] = "*";
9502
9693
  else if (options.expectedVersion !== void 0) headers["If-Match"] = options.expectedVersion;
9503
9694
  if (options.actor) headers["X-Actor"] = options.actor;
9504
- const body = encodeRemoteDocument(doc2.frontmatter, doc2.body ?? "");
9695
+ const body = encodeRemoteDocument(doc2.frontmatter, doc2.body ?? "", options.bodyReplace);
9505
9696
  let minted = false;
9506
9697
  if (options.requestId !== void 0) {
9507
9698
  assertRequestIdentity(options.requestId);
@@ -9874,7 +10065,11 @@ function buildTransport(remote, options) {
9874
10065
  return { kind: "refused", code: "USAGE", message: `remote operation transport: unsupported intent kind '${intent.kind}'`, executed: false };
9875
10066
  }
9876
10067
  let parsed2;
10068
+ let posture;
9877
10069
  try {
10070
+ const descriptor = Object.getOwnPropertyDescriptor(intent, "bodyReplace");
10071
+ if (descriptor && !("value" in descriptor)) throw new Error("bodyReplace must be an explicit data field.");
10072
+ posture = captureBodyReplacePosture(descriptor?.value);
9878
10073
  parsed2 = parseMarkdown(intent.content, pathFromConceptId(intent.target));
9879
10074
  } catch (error51) {
9880
10075
  return { kind: "refused", code: "USAGE", message: error51 instanceof Error ? error51.message : String(error51), executed: false };
@@ -9883,6 +10078,7 @@ function buildTransport(remote, options) {
9883
10078
  const writeOptions = {
9884
10079
  expectedVersion: intent.base,
9885
10080
  requestId: intent.requestId,
10081
+ ...posture === void 0 ? {} : { bodyReplace: posture },
9886
10082
  ...options.actor === void 0 ? {} : { actor: options.actor }
9887
10083
  };
9888
10084
  try {
@@ -9910,6 +10106,7 @@ var init_remote_operations = __esm({
9910
10106
  "use strict";
9911
10107
  init_define_SUPERBEE_BUILD_IDENTITY();
9912
10108
  init_define_SUPERBEE_UPDATE_POLICY();
10109
+ init_body_replace_guards();
9913
10110
  init_frontmatter();
9914
10111
  init_paths();
9915
10112
  init_remote_backend();
@@ -9973,146 +10170,6 @@ var init_mutation = __esm({
9973
10170
  }
9974
10171
  });
9975
10172
 
9976
- // ../core/src/body-replace-guards.ts
9977
- function previewTruncationNotice(omitted) {
9978
- return `${BODY_PREVIEW_TRUNCATION_MARKER} ${omitted} more character(s) are NOT shown`;
9979
- }
9980
- function attachBodyPreview(rec, body, fullBodyHelp) {
9981
- if (body.length <= BODY_PREVIEW_LIMIT) {
9982
- rec.body = body;
9983
- return;
9984
- }
9985
- const omitted = body.length - BODY_PREVIEW_LIMIT;
9986
- rec[BODY_PREVIEW_KEY] = `${body.slice(0, BODY_PREVIEW_LIMIT)}
9987
-
9988
- ${previewTruncationNotice(omitted)} \u2014 this value is a preview, not the document body; use this record's help to read the complete body before rewriting it.`;
9989
- rec.body_truncated = true;
9990
- rec.body_chars = body.length;
9991
- rec.help = [...fullBodyHelp];
9992
- }
9993
- function matchesPreviewSlice(candidate, preview4) {
9994
- if (candidate === preview4) return true;
9995
- const trimmed = preview4.trimEnd();
9996
- return trimmed !== "" && candidate.trimEnd() === trimmed;
9997
- }
9998
- function firstForeignNotice(storedBody, nextBody) {
9999
- const preservesStoredBody = nextBody.includes(storedBody.trimEnd());
10000
- const every = new RegExp(BODY_PREVIEW_TRUNCATION_SIGNATURE.source, `${BODY_PREVIEW_TRUNCATION_SIGNATURE.flags}g`);
10001
- for (const match of nextBody.matchAll(every)) {
10002
- if (!(preservesStoredBody && storedBody.includes(match[0]))) return match[0];
10003
- }
10004
- return void 0;
10005
- }
10006
- function isSameStoredBody(nextBody, existingBody) {
10007
- return normalizeDocumentBodyForStorage(nextBody) === normalizeDocumentBodyForStorage(existingBody);
10008
- }
10009
- function bodyPreviewFinding(existing, nextBody) {
10010
- if (isSameStoredBody(nextBody, existing.body)) return;
10011
- const notice = firstForeignNotice(existing.body, nextBody);
10012
- if (notice !== void 0) return { reason: "preview_marker", marker: BODY_PREVIEW_TRUNCATION_MARKER, notice };
10013
- if (existing.body.length > BODY_PREVIEW_LIMIT && matchesPreviewSlice(nextBody, existing.body.slice(0, BODY_PREVIEW_LIMIT))) {
10014
- return { reason: "stored_body_preview", preview_limit: BODY_PREVIEW_LIMIT, supplied_body_chars: nextBody.length, stored_body_chars: existing.body.length };
10015
- }
10016
- }
10017
- function computeDroppedLinks(existingLinks, nextLinks, mode = "target") {
10018
- const nextByTarget = /* @__PURE__ */ new Map();
10019
- for (const l of nextLinks) {
10020
- const key4 = mode === "exact-edge" ? JSON.stringify([l.from, l.to]) : l.to;
10021
- const bucket = nextByTarget.get(key4);
10022
- if (bucket) bucket.push(l);
10023
- else nextByTarget.set(key4, [l]);
10024
- }
10025
- const existingByTarget = /* @__PURE__ */ new Map();
10026
- for (const l of existingLinks) {
10027
- const key4 = mode === "exact-edge" ? JSON.stringify([l.from, l.to]) : l.to;
10028
- const bucket = existingByTarget.get(key4);
10029
- if (bucket) bucket.push(l);
10030
- else existingByTarget.set(key4, [l]);
10031
- }
10032
- const dropped = [];
10033
- for (const [target3, oldOccurrences] of existingByTarget) {
10034
- const available = [...nextByTarget.get(target3) ?? []];
10035
- const unmatchedExact = [];
10036
- for (const old of oldOccurrences) {
10037
- const idx = available.findIndex((n) => n.text === old.text);
10038
- if (idx >= 0) available.splice(idx, 1);
10039
- else unmatchedExact.push(old);
10040
- }
10041
- for (const old of unmatchedExact) {
10042
- if (mode === "target" && available.length > 0) available.shift();
10043
- else dropped.push(old);
10044
- }
10045
- }
10046
- return dropped;
10047
- }
10048
- function droppedLinks(_bundle, existing, nextBody) {
10049
- return computeDroppedLinks(parseLinksFromDoc(existing), parseLinksFromDoc({ ...existing, body: nextBody }));
10050
- }
10051
- function guardTruncatedBodyPreview(existing, nextBody, acceptTruncatedBody) {
10052
- if (acceptTruncatedBody) return;
10053
- const finding = bodyPreviewFinding(existing, nextBody);
10054
- if (finding) throw new BodyReplaceError(existing.id, finding, BODY_PREVIEW_TRUNCATION_SIGNATURE.test(existing.body));
10055
- }
10056
- function guardDroppedLinks(bundle, existing, nextBody, replaceLinks) {
10057
- if (replaceLinks || isSameStoredBody(nextBody, existing.body)) return;
10058
- const dropped = droppedLinks(bundle, existing, nextBody);
10059
- if (dropped.length) throw new BodyReplaceError(existing.id, { reason: "dropped_links", dropped_links: dropped });
10060
- }
10061
- function guardBodyReplace(bundle, existing, nextBody, posture) {
10062
- if (isSameStoredBody(nextBody, existing.body)) return;
10063
- guardTruncatedBodyPreview(existing, nextBody, Boolean(posture?.acceptTruncatedBody));
10064
- guardDroppedLinks(bundle, existing, nextBody, Boolean(posture?.replaceLinks));
10065
- }
10066
- function assertTypedListPatch(kind2, storageField) {
10067
- const types = kind2.fields.types ?? {};
10068
- const type = Object.hasOwn(types, storageField) ? types[storageField] : void 0;
10069
- if (type === "string-list" || type === "https-url-list") throw new TypedListPatchError(storageField, type);
10070
- }
10071
- var BODY_PREVIEW_LIMIT, BODY_PREVIEW_TRUNCATION_MARKER, BODY_PREVIEW_TRUNCATION_SIGNATURE, BODY_PREVIEW_KEY, BODY_PREVIEW_RESERVED_KEYS, BodyReplaceError, TypedListPatchError;
10072
- var init_body_replace_guards = __esm({
10073
- "../core/src/body-replace-guards.ts"() {
10074
- "use strict";
10075
- init_define_SUPERBEE_BUILD_IDENTITY();
10076
- init_define_SUPERBEE_UPDATE_POLICY();
10077
- init_frontmatter();
10078
- init_links();
10079
- init_errors();
10080
- BODY_PREVIEW_LIMIT = 1e3;
10081
- BODY_PREVIEW_TRUNCATION_MARKER = "[superbee:body-preview-truncated]";
10082
- BODY_PREVIEW_TRUNCATION_SIGNATURE = /\[superbee:body-preview-truncated\]\s+\d+\s+more\s+characters?\(?s?\)?\s+are\s+NOT\s+shown/i;
10083
- BODY_PREVIEW_KEY = "body_preview";
10084
- BODY_PREVIEW_RESERVED_KEYS = [
10085
- "body",
10086
- BODY_PREVIEW_KEY,
10087
- "body_truncated",
10088
- "body_chars",
10089
- "help"
10090
- ];
10091
- BodyReplaceError = class extends InvalidInputError {
10092
- id;
10093
- finding;
10094
- storedCarriesNotice;
10095
- constructor(id, finding, storedCarriesNotice = false) {
10096
- super(`Body replacement of '${id}' refused: ${finding.reason}.`);
10097
- this.name = "BodyReplaceError";
10098
- this.id = id;
10099
- this.finding = finding;
10100
- this.storedCarriesNotice = storedCarriesNotice;
10101
- }
10102
- };
10103
- TypedListPatchError = class extends InvalidInputError {
10104
- field;
10105
- fieldType;
10106
- constructor(field, fieldType) {
10107
- super(`'${field}' is a ${fieldType} field; use an explicit whole-list replacement.`);
10108
- this.name = "TypedListPatchError";
10109
- this.field = field;
10110
- this.fieldType = fieldType;
10111
- }
10112
- };
10113
- }
10114
- });
10115
-
10116
10173
  // ../core/src/managed-document-metadata.ts
10117
10174
  function isManagedDocumentMetadataField(field) {
10118
10175
  return MANAGED_DOCUMENT_METADATA_FIELDS.has(field);
@@ -11921,7 +11978,8 @@ async function mutateDocument(opts) {
11921
11978
  const { warnings } = validateCandidate(opts.id, candidate, opts.registry, opts.strict, okfVersion, decisionNow);
11922
11979
  const { doc: doc2, version: version4 } = await writeDocVersionedForEdition2(opts.bundle, { id: opts.id, ...candidate }, okfVersion, {
11923
11980
  expectedVersion: null,
11924
- actor: opts.actor
11981
+ actor: opts.actor,
11982
+ bodyReplace: opts.bodyReplace
11925
11983
  });
11926
11984
  return { doc: doc2, changed: true, version: version4, warnings };
11927
11985
  }
@@ -11994,7 +12052,8 @@ async function mutateDocument(opts) {
11994
12052
  write: async (next, expectedVersion) => {
11995
12053
  const written = await writeDocVersionedForEdition2(opts.bundle, next, okfVersion, {
11996
12054
  expectedVersion,
11997
- actor: opts.actor
12055
+ actor: opts.actor,
12056
+ bodyReplace: opts.bodyReplace
11998
12057
  });
11999
12058
  savedDoc2 = written.doc;
12000
12059
  return written.version;
@@ -12036,7 +12095,8 @@ async function mutateDocument(opts) {
12036
12095
  write: async (next, expectedVersion) => {
12037
12096
  const written = await writeDocVersionedForEdition2(opts.bundle, next, okfVersion, {
12038
12097
  expectedVersion: hardCas ? opts.expectedVersion : expectedVersion,
12039
- actor: opts.actor
12098
+ actor: opts.actor,
12099
+ bodyReplace: opts.bodyReplace
12040
12100
  });
12041
12101
  savedDoc = written.doc;
12042
12102
  return written.version;
@@ -29050,7 +29110,7 @@ var init_source_profiles = __esm({
29050
29110
  };
29051
29111
  }
29052
29112
  });
29053
- SOURCE_PLUGIN_CORE_VERSION = "0.2.0-pre.29";
29113
+ SOURCE_PLUGIN_CORE_VERSION = "0.2.0-pre.30";
29054
29114
  SOURCE_PROFILES = Object.freeze([restJsonProfile].map((profile) => Object.freeze({ id: profile.id, version: profile.version, kind: profile.kind })));
29055
29115
  }
29056
29116
  });
@@ -39277,6 +39337,7 @@ var init_indexeddb_backend = __esm({
39277
39337
  "use strict";
39278
39338
  init_define_SUPERBEE_BUILD_IDENTITY();
39279
39339
  init_define_SUPERBEE_UPDATE_POLICY();
39340
+ init_journaled_backend();
39280
39341
  init_content_type();
39281
39342
  init_frontmatter();
39282
39343
  init_mutation_attribution();
@@ -39728,6 +39789,7 @@ var init_indexeddb_backend = __esm({
39728
39789
  }
39729
39790
  assertSafeConceptId(id);
39730
39791
  assertJournalResolutionOptions(id, options);
39792
+ if (options.intent) options = { ...options, intent: captureNewDocumentIntent(options.intent) };
39731
39793
  const raw = stringifyDoc(doc2.frontmatter, doc2.body ?? "");
39732
39794
  const version4 = versionOfBytes(raw);
39733
39795
  if (snapshotGuard && (doc2.id !== id || options.intent && options.intent.target !== id)) throw new JournalGuardConflict(id);
@@ -40590,6 +40652,14 @@ async function bootstrap(remote, local, options = {}) {
40590
40652
  await backend.writeMeta(BOOTSTRAP_KEY, marker);
40591
40653
  return marker;
40592
40654
  }
40655
+ function composedBodyReplace(...postures) {
40656
+ const declarations = postures.map(captureBodyReplacePosture).filter((row5) => row5 !== void 0);
40657
+ if (!declarations.length) return;
40658
+ return {
40659
+ replaceLinks: declarations.some((row5) => row5.replaceLinks === true),
40660
+ acceptTruncatedBody: declarations.some((row5) => row5.acceptTruncatedBody === true)
40661
+ };
40662
+ }
40593
40663
  function supersedingIntent(kind2, superseded, now) {
40594
40664
  const deleting = kind2 === DOCUMENT_DELETE_KIND;
40595
40665
  if (deleting && superseded.base === null) return void 0;
@@ -40600,6 +40670,7 @@ function supersedingIntent(kind2, superseded, now) {
40600
40670
  base: superseded.base,
40601
40671
  baseContent: superseded.baseContent,
40602
40672
  createdAt: now,
40673
+ ...!deleting && superseded.kind === "document.write" && superseded.bodyReplace !== void 0 ? { bodyReplace: composedBodyReplace(superseded.bodyReplace) } : {},
40603
40674
  ...superseded.after !== void 0 ? { after: superseded.after } : {},
40604
40675
  ...!deleting && superseded.recreates !== void 0 && superseded.base === null ? { recreates: superseded.recreates } : {}
40605
40676
  };
@@ -40656,8 +40727,11 @@ function chainedBase(intent) {
40656
40727
  function journalingBackend(backend, id, recorded) {
40657
40728
  const write = async (target3, doc2, options = {}) => {
40658
40729
  if (target3 !== id) throw new Error(`commitLocal for '${id}' cannot write '${target3}'`);
40730
+ const declaredPosture = captureBodyReplacePosture(options.bodyReplace);
40659
40731
  for (let attempt = 0; ; attempt++) {
40660
40732
  const composed = await composeIntent(backend, id, (/* @__PURE__ */ new Date()).toISOString());
40733
+ const posture = composedBodyReplace(composed.intent.bodyReplace, declaredPosture);
40734
+ if (posture !== void 0) composed.intent = { ...composed.intent, bodyReplace: posture };
40661
40735
  try {
40662
40736
  const written = await backend.writeJournaled(id, doc2, { ...options, ...composed });
40663
40737
  recorded.intent = written.intent;
@@ -40887,6 +40961,7 @@ async function resolveConflict(local, remote, reviewed, choice, options = {}) {
40887
40961
  base: shared.base.version,
40888
40962
  baseContent: shared.base.content,
40889
40963
  createdAt: resolvedAt,
40964
+ bodyReplace: { replaceLinks: true },
40890
40965
  ...recreates !== void 0 ? { recreates } : {}
40891
40966
  };
40892
40967
  let written;
@@ -41208,7 +41283,11 @@ async function foldRefusedChain(backend, listed2) {
41208
41283
  if (chain.length !== 2 || !head2 || !successor || !isContentRefusal(head2) || successor.requestId !== listed2.requestId || successor.state !== "pending" || successor.attempts !== 0 || successor.after !== head2.requestId) return null;
41209
41284
  const deleting = successor.kind === DOCUMENT_DELETE_KIND;
41210
41285
  if (deleting ? snapshot4.document !== null : !snapshot4.document || successor.local !== snapshot4.document.version || successor.content !== snapshot4.raw) return null;
41211
- const intent = supersedingIntent(deleting ? DOCUMENT_DELETE_KIND : "document.write", head2, (/* @__PURE__ */ new Date()).toISOString());
41286
+ let intent = supersedingIntent(deleting ? DOCUMENT_DELETE_KIND : "document.write", head2, (/* @__PURE__ */ new Date()).toISOString());
41287
+ if (!deleting && intent) {
41288
+ const posture = composedBodyReplace(intent.bodyReplace, successor.bodyReplace);
41289
+ if (posture !== void 0) intent = { ...intent, bodyReplace: posture };
41290
+ }
41212
41291
  const resolveIntents = { expected: chain };
41213
41292
  try {
41214
41293
  if (deleting) {
@@ -41538,6 +41617,7 @@ var init_local_bundle = __esm({
41538
41617
  "use strict";
41539
41618
  init_define_SUPERBEE_BUILD_IDENTITY();
41540
41619
  init_define_SUPERBEE_UPDATE_POLICY();
41620
+ init_engine();
41541
41621
  init_document_codec();
41542
41622
  init_governed_body_write();
41543
41623
  init_verification();
@@ -41838,6 +41918,13 @@ function validateIntentChanges(changes, format2, file2) {
41838
41918
  for (const change of changes) {
41839
41919
  if (change.family !== "intent" || change.value === null) continue;
41840
41920
  const row5 = change.value;
41921
+ if (!("recordFamily" in row5) && row5.bodyReplace !== void 0) {
41922
+ try {
41923
+ captureNewDocumentIntent(row5);
41924
+ } catch {
41925
+ throw new FileJournalCorruptError(file2, "invalid document edit intent");
41926
+ }
41927
+ }
41841
41928
  if ("recordFamily" in row5) {
41842
41929
  if (row5.recordFamily !== "blob" || format2 < 2) throw new FileJournalCorruptError(file2, "blob intent is not allowed in this format");
41843
41930
  if (blobIntentFormat(row5) > format2) throw new FileJournalCorruptError(file2, "blob not-dispatched evidence is not allowed in this format");
@@ -41958,6 +42045,7 @@ var init_file_journaled_backend = __esm({
41958
42045
  "use strict";
41959
42046
  init_define_SUPERBEE_BUILD_IDENTITY();
41960
42047
  init_define_SUPERBEE_UPDATE_POLICY();
42048
+ init_journaled_backend();
41961
42049
  init_blob_contract();
41962
42050
  init_blob_journal();
41963
42051
  init_content_type();
@@ -42423,6 +42511,7 @@ var init_file_journaled_backend = __esm({
42423
42511
  }
42424
42512
  assertSafeConceptId(id);
42425
42513
  assertJournalResolutionOptions(id, options);
42514
+ if (options.intent) options = { ...options, intent: captureNewDocumentIntent(options.intent) };
42426
42515
  if (snapshotGuard && (doc2.id !== id || options.intent && options.intent.target !== id)) throw new JournalGuardConflict(id);
42427
42516
  const raw = stringifyDoc(doc2.frontmatter, doc2.body ?? "");
42428
42517
  const version4 = versionOfBytes(raw);
@@ -93267,6 +93356,9 @@ function errorFromCaught(err) {
93267
93356
  if (err instanceof RemoteDocumentValueError) {
93268
93357
  return errorResponse(500, "RUNTIME", err.message);
93269
93358
  }
93359
+ if (err instanceof BodyReplaceError) {
93360
+ return errorResponse(400, "USAGE", err.message, { id: err.id, ...err.finding });
93361
+ }
93270
93362
  if (err instanceof InvalidInputError) {
93271
93363
  return errorResponse(400, "USAGE", err.message);
93272
93364
  }
@@ -93544,7 +93636,9 @@ function buildRouter(options) {
93544
93636
  return errorResponse(400, "USAGE", "request body field body must be a string when present");
93545
93637
  }
93546
93638
  const writeOptions = writeOptionsFromRequest(req, attribution);
93547
- const result3 = await writeDocVersioned(
93639
+ const posture = captureBodyReplacePosture(payload.bodyReplace);
93640
+ if (posture !== void 0) writeOptions.bodyReplace = posture;
93641
+ const result3 = await writeDocVersionedGuarded(
93548
93642
  backend,
93549
93643
  { id, frontmatter: payload.frontmatter, body: payload.body ?? "" },
93550
93644
  writeOptions
@@ -152473,20 +152567,35 @@ async function localBundle(dir, cwd = process.cwd(), home2 = homedir49()) {
152473
152567
  if (process.platform !== "darwin" && process.platform !== "linux") throw refuse("unsupported_supervision_platform");
152474
152568
  return target3.canonicalRoot;
152475
152569
  }
152476
- async function toolIdentity(file2) {
152477
- if (typeof file2 !== "string" || !path64.isAbsolute(file2)) throw refuse("absolute_tool_required");
152570
+ function toolSelections(values, home2) {
152571
+ const selections = {};
152572
+ for (const [handle, value] of Object.entries(values)) {
152573
+ if (!key3.test(handle)) throw refuse("tool_handle");
152574
+ let selected2;
152575
+ if (typeof value === "string") selected2 = { path: value, versionFlag: "--version" };
152576
+ else {
152577
+ if (!record16(value) || Object.keys(value).length !== 2 || !Object.hasOwn(value, "path") || !Object.hasOwn(value, "versionFlag") || typeof value.path !== "string" || value.versionFlag !== "--version" && value.versionFlag !== "-version") throw refuse("tool_selection");
152578
+ selected2 = { path: value.path, versionFlag: value.versionFlag };
152579
+ }
152580
+ if (!path64.isAbsolute(selected2.path)) throw refuse("absolute_tool_required");
152581
+ assertPathOutsidePrivateState(selected2.path, home2);
152582
+ selections[handle] = selected2;
152583
+ }
152584
+ return selections;
152585
+ }
152586
+ async function toolIdentity({ path: file2, versionFlag }) {
152478
152587
  const resolved = await realpath15(file2);
152479
152588
  const bytes = await localFileBytes(resolved, 256 * 1024 * 1024);
152480
152589
  const magic = bytes.subarray(0, 4).toString("hex");
152481
152590
  const native = process.platform === "linux" ? magic === "7f454c46" : ["feedface", "cefaedfe", "feedfacf", "cffaedfe", "cafebabe", "bebafeca", "cafebabf", "bfbafeca"].includes(magic);
152482
152591
  if (!native) throw refuse("native_tool_binary_required");
152483
- const version4 = await probeToolVersion(resolved);
152592
+ const version4 = await probeToolVersion(resolved, versionFlag);
152484
152593
  if (await realpath15(resolved) !== resolved || hash2(await localFileBytes(resolved, 256 * 1024 * 1024)) !== hash2(bytes)) throw refuse("tool_changed_rebind_required");
152485
- return { path: resolved, sha256: hash2(bytes), version: version4 };
152594
+ return { path: resolved, sha256: hash2(bytes), version: version4, versionFlag };
152486
152595
  }
152487
- async function probeToolVersion(file2) {
152596
+ async function probeToolVersion(file2, versionFlag) {
152488
152597
  return new Promise((resolve2, reject) => {
152489
- const child = spawn5(file2, ["--version"], { detached: true, env: { PATH: "/usr/bin:/bin" }, stdio: ["ignore", "pipe", "pipe"] });
152598
+ const child = spawn5(file2, [versionFlag], { detached: true, env: { PATH: "/usr/bin:/bin" }, stdio: ["ignore", "pipe", "pipe"] });
152490
152599
  let settled = false, stdout = "", bytes = 0, failureReason;
152491
152600
  const finish = async (reason) => {
152492
152601
  failureReason ??= reason;
@@ -152523,6 +152632,7 @@ async function bindLocalOperation(operation, bundle, config2, accept, home2 = ho
152523
152632
  if (!record16(config2) || !record16(config2.resources) || !record16(config2.tools) || !Object.hasOwn(LOCAL_OPERATION_PROFILES, config2.profile)) throw refuse("binding_config");
152524
152633
  const profile = LOCAL_OPERATION_PROFILES[config2.profile];
152525
152634
  if (Object.keys(config2.resources).length === 0 || Object.keys(config2.resources).length > profile.files || Object.keys(config2.tools).length > 8) throw refuse("binding_count");
152635
+ const selectedTools = toolSelections(config2.tools, home2);
152526
152636
  const resources = {}, tools = {}, expectedInputs = {};
152527
152637
  let total = 0;
152528
152638
  for (const [role, value] of Object.entries(config2.resources)) {
@@ -152534,39 +152644,71 @@ async function bindLocalOperation(operation, bundle, config2, accept, home2 = ho
152534
152644
  resources[role] = { path: selected2, logicalRef: value.logicalRef };
152535
152645
  expectedInputs[role] = hash2(bytes);
152536
152646
  }
152537
- for (const [handle, file2] of Object.entries(config2.tools)) {
152538
- if (typeof file2 !== "string") throw refuse("tool_selection");
152539
- if (!key3.test(handle)) throw refuse("tool_handle");
152540
- assertPathOutsidePrivateState(file2, home2);
152541
- tools[handle] = await toolIdentity(file2);
152542
- }
152647
+ for (const [handle, selected2] of Object.entries(selectedTools)) tools[handle] = await toolIdentity(selected2);
152543
152648
  const outputRoot = await ordinaryDirectory(config2.outputRoot, home2, bundle), rootStatus = await lstat13(outputRoot);
152544
152649
  const binding2 = { v: 1, bundle, operation, pluginDigest: selection.digest, generation: selection.generation, capability: selection.capability, resources, tools, outputRoot, outputRootIdentity: { dev: rootStatus.dev, ino: rootStatus.ino }, profile: config2.profile };
152545
152650
  const digest4 = hash2(canonicalJson3(binding2));
152546
- if (accept === void 0) return { status: "preview", digest: digest4, operation, profile: config2.profile, expectedInputs, resources: Object.keys(resources), tools: Object.fromEntries(Object.entries(tools).map(([name, t]) => [name, { sha256: t.sha256, version: t.version }])), effects: ["trusted code with ambient authority; no OS sandbox", "copies selected inputs; creates private local files; consumes compute", "supported adapter makes no network requests; network is not sandboxed", "HTML export is separate from Artifact publication"], next: `superbee op bind ${commandToken(operation)} --local --resources-file <same-file> --accept ${commandToken(digest4)} --dir <same-bundle>` };
152651
+ if (accept === void 0) return { status: "preview", digest: digest4, operation, profile: config2.profile, expectedInputs, resources: Object.keys(resources), tools: toolEvidence(tools), effects: ["trusted code with ambient authority; no OS sandbox", "copies selected inputs; creates private local files; consumes compute", "supported adapter makes no network requests; network is not sandboxed", "HTML export is separate from Artifact publication"], next: `superbee op bind ${commandToken(operation)} --local --resources-file <same-file> --accept ${commandToken(digest4)} --dir <same-bundle>` };
152547
152652
  if (accept !== digest4) throw refuse("binding_acceptance_changed");
152548
152653
  const id = randomUUID9();
152549
152654
  await writeUserStateFileAtomic0600(home2, path64.join(canonicalUserStateDir(home2), "local-operation-bindings"), `${id}.json`, JSON.stringify(binding2));
152550
152655
  return { status: "bound", binding: id, digest: digest4, operation, expectedInputs, next: `superbee op run ${commandToken(operation)} --local --binding ${commandToken(id)} --input-file <run-input.json> --dir <same-bundle>` };
152551
152656
  }
152552
- async function outputBudget(directory, maximumBytes, maximumFiles) {
152553
- let bytes = 0, count6 = 0;
152554
- const scan3 = async (dir) => {
152555
- const entries = await readdir10(dir, { withFileTypes: true });
152556
- for (const entry of entries) {
152557
- if (++count6 > maximumFiles * 2) return false;
152558
- const file2 = path64.join(dir, entry.name), status2 = await lstat13(file2);
152559
- if (status2.isSymbolicLink() || !status2.isFile() && !status2.isDirectory()) return false;
152560
- if (status2.isDirectory()) {
152561
- if (!await scan3(file2)) return false;
152562
- } else {
152563
- bytes += status2.size;
152564
- if (bytes > maximumBytes) return false;
152657
+ function outputFailure(phase, error51) {
152658
+ return { phase, errno: error51 instanceof OutputScanError ? error51.errno : "unknown", syscall: error51 instanceof OutputScanError ? error51.syscall : "unknown" };
152659
+ }
152660
+ async function outputBudget(directory, maximumBytes, maximumFiles, live = false, io = outputBudgetIo) {
152661
+ for (let attempt = 1; ; attempt++) {
152662
+ let bytes = 0, count6 = 0;
152663
+ const scan3 = async (dir) => {
152664
+ let entries;
152665
+ try {
152666
+ entries = await io.readdir(dir);
152667
+ } catch (error51) {
152668
+ throw new OutputScanError(error51, dir !== directory);
152669
+ }
152670
+ for (const entry of entries) {
152671
+ if (++count6 > maximumFiles * 2) return false;
152672
+ const file2 = path64.join(dir, entry.name);
152673
+ let status2;
152674
+ try {
152675
+ status2 = await io.lstat(file2);
152676
+ } catch (error51) {
152677
+ throw new OutputScanError(error51, true);
152678
+ }
152679
+ if (status2.isSymbolicLink() || !status2.isFile() && !status2.isDirectory()) return false;
152680
+ if (status2.isDirectory()) {
152681
+ if (!await scan3(file2)) return false;
152682
+ } else {
152683
+ bytes += status2.size;
152684
+ if (bytes > maximumBytes) return false;
152685
+ }
152565
152686
  }
152687
+ return true;
152688
+ };
152689
+ try {
152690
+ return await scan3(directory);
152691
+ } catch (error51) {
152692
+ if (live && attempt < 3 && error51 instanceof OutputScanError && error51.vanishedDescendant) continue;
152693
+ throw error51;
152566
152694
  }
152567
- return true;
152695
+ }
152696
+ }
152697
+ function startOutputBudgetPoll(directory, maximumBytes, maximumFiles, report, scan3 = outputBudget) {
152698
+ let pending, stopped = false;
152699
+ const timer = setInterval(() => {
152700
+ if (stopped || pending) return;
152701
+ pending = scan3(directory, maximumBytes, maximumFiles, true).then((ok4) => {
152702
+ if (!ok4) report("output_limit");
152703
+ }).catch((error51) => report("output_validation", error51)).finally(() => {
152704
+ pending = void 0;
152705
+ });
152706
+ }, 50);
152707
+ return async () => {
152708
+ stopped = true;
152709
+ clearInterval(timer);
152710
+ await pending;
152568
152711
  };
152569
- return scan3(directory);
152570
152712
  }
152571
152713
  async function groupPresent(pid) {
152572
152714
  try {
@@ -152635,7 +152777,7 @@ async function runLocalOperation(operation, bundle, bindingId, input, options =
152635
152777
  resources[role] = { path: captured, logicalRef: resource.logicalRef, sha256: sha2562 };
152636
152778
  inputs.push({ role, logicalRef: resource.logicalRef, sha256: sha2562, bytes: bytes.length });
152637
152779
  }
152638
- const manifest2 = { version: 1, invocationId: id, operation, implementationId: selection.capability.implementationId, plugin: { digest: selection.digest, generation: selection.generation, assets: selection.assets }, inputs, settingsDigest: hash2(canonicalJson3(input.settings)), tools: Object.fromEntries(Object.entries(binding2.tools).map(([name, t]) => [name, { sha256: t.sha256, version: t.version }])), profile: binding2.profile, platform: { os: process.platform, arch: process.arch, node: process.version }, startedAt: (/* @__PURE__ */ new Date()).toISOString(), status: "interrupted_unconfirmed", reason: "parent_outcome_unknown", outputs: [], publication: "not_attempted" };
152780
+ const manifest2 = { version: 1, invocationId: id, operation, implementationId: selection.capability.implementationId, plugin: { digest: selection.digest, generation: selection.generation, assets: selection.assets }, inputs, settingsDigest: hash2(canonicalJson3(input.settings)), tools: toolEvidence(binding2.tools), profile: binding2.profile, platform: { os: process.platform, arch: process.arch, node: process.version }, startedAt: (/* @__PURE__ */ new Date()).toISOString(), status: "interrupted_unconfirmed", reason: "parent_outcome_unknown", outputs: [], publication: "not_attempted" };
152639
152781
  const manifestPath = path64.join(workspace, "manifest.json");
152640
152782
  await writeFile3(manifestPath, JSON.stringify(manifest2, null, 2), { mode: 384, flag: "wx" });
152641
152783
  const maximumOutputBytes = Math.min(selection.capability.maximumOutputBytes ?? DEFAULT_MAXIMUM_OUTPUT_BYTES, DEFAULT_MAXIMUM_OUTPUT_BYTES);
@@ -152658,16 +152800,10 @@ async function runLocalOperation(operation, bundle, bindingId, input, options =
152658
152800
  };
152659
152801
  child.stdout.on("data", capture2);
152660
152802
  child.stderr.on("data", capture2);
152661
- let checking = false;
152662
- const budget = setInterval(() => {
152663
- if (checking) return;
152664
- checking = true;
152665
- void outputBudget(outputDirectory, profile.outputBytes, profile.files).then((ok4) => {
152666
- if (!ok4) terminate("output_limit");
152667
- }).catch(() => terminate("output_validation")).finally(() => {
152668
- checking = false;
152669
- });
152670
- }, 50);
152803
+ const stopBudget = startOutputBudgetPoll(outputDirectory, profile.outputBytes, profile.files, (why, error51) => {
152804
+ manifest2.outputValidationFailure ??= outputFailure("live", error51);
152805
+ terminate(why);
152806
+ });
152671
152807
  const deadline = setTimeout(() => terminate("deadline"), profile.deadlineMs);
152672
152808
  const abort = () => terminate("cancelled");
152673
152809
  options.signal?.addEventListener("abort", abort, { once: true });
@@ -152712,9 +152848,10 @@ async function runLocalOperation(operation, bundle, bindingId, input, options =
152712
152848
  child.send({ type: "initialize", entryPath: selection.entryPath, capabilityName: selection.capability.name, maximumOutputBytes, protocolBytes: DEFAULT_MAXIMUM_OUTPUT_BYTES, tools: binding2.tools, resources, profile, invocation: { id, outputDirectory, assetDirectory: selection.rootPath, profile: binding2.profile }, input: input.settings });
152713
152849
  });
152714
152850
  clearTimeout(deadline);
152715
- clearInterval(budget);
152851
+ const budgetStopped = stopBudget();
152716
152852
  options.signal?.removeEventListener("abort", abort);
152717
152853
  const stopped = child.pid !== void 0 ? await stopGroup(child.pid, profile.graceMs) : closed;
152854
+ await budgetStopped;
152718
152855
  for (const [tool, identity] of Object.entries(binding2.tools)) {
152719
152856
  try {
152720
152857
  if (await realpath15(identity.path) !== identity.path || hash2(await localFileBytes(identity.path, 256 * 1024 * 1024)) !== identity.sha256) throw Error();
@@ -152748,9 +152885,10 @@ async function runLocalOperation(operation, bundle, bindingId, input, options =
152748
152885
  for (const entry of all2) if (entry.isFile() && !seen.has(path64.relative(outputDirectory, path64.join(entry.parentPath, entry.name)))) throw refuse("undeclared_output");
152749
152886
  manifest2.settings = result3.settings ?? input.settings;
152750
152887
  manifest2.partialOutputState = "validated";
152751
- } catch {
152888
+ } catch (error51) {
152752
152889
  manifest2.status = "failed";
152753
152890
  manifest2.reason = "output_validation";
152891
+ manifest2.outputValidationFailure = outputFailure("final", error51);
152754
152892
  manifest2.outputs = [];
152755
152893
  }
152756
152894
  }
@@ -152777,7 +152915,7 @@ async function runLocalOperation(operation, bundle, bindingId, input, options =
152777
152915
  await writeFile3(manifestPath, JSON.stringify(manifest2, null, 2), { mode: 384 });
152778
152916
  return { invocationId: id, status: manifest2.status, reason: manifest2.reason, manifest: manifestPath, outputs: manifest2.outputs, export: manifest2.export === void 0 ? void 0 : { ...manifest2.export, ...exportPath ? { path: exportPath } : {} }, publication: "not_attempted" };
152779
152917
  }
152780
- var LOCAL_OPERATION_PROFILES, record16, hash2, refuse, key3, within;
152918
+ var LOCAL_OPERATION_PROFILES, record16, hash2, refuse, key3, within, toolEvidence, outputBudgetIo, OutputScanError;
152781
152919
  var init_local_operation = __esm({
152782
152920
  "../cli/src/local-operation.ts"() {
152783
152921
  "use strict";
@@ -152805,6 +152943,20 @@ var init_local_operation = __esm({
152805
152943
  const rel = path64.relative(root, target3);
152806
152944
  return rel !== "" && !rel.startsWith(`..${path64.sep}`) && rel !== ".." && !path64.isAbsolute(rel);
152807
152945
  };
152946
+ toolEvidence = (tools) => Object.fromEntries(Object.entries(tools).map(([name, t]) => [name, { sha256: t.sha256, version: t.version, versionFlag: t.versionFlag ?? "--version" }]));
152947
+ outputBudgetIo = { readdir: (directory) => readdir10(directory, { withFileTypes: true }), lstat: (file2) => lstat13(file2) };
152948
+ OutputScanError = class extends Error {
152949
+ errno;
152950
+ syscall;
152951
+ vanishedDescendant;
152952
+ constructor(error51, descendant) {
152953
+ super("output_scan_failed");
152954
+ const value = error51;
152955
+ this.errno = typeof value?.code === "string" && /^E[A-Z0-9]{1,30}$/.test(value.code) ? value.code : "unknown";
152956
+ this.syscall = value?.syscall === "lstat" || value?.syscall === "scandir" ? value.syscall : "unknown";
152957
+ this.vanishedDescendant = descendant && this.errno === "ENOENT";
152958
+ }
152959
+ };
152808
152960
  }
152809
152961
  });
152810
152962
 
@@ -153176,15 +153328,18 @@ exports one validated HTML into the selected ordinary output root without publis
153176
153328
  Trusted code has ambient local authority; process supervision is not an OS sandbox.
153177
153329
 
153178
153330
  Local binding resources JSON contains resources (role -> {path, logicalRef}), tools (handle ->
153179
- absolute executable path), outputRoot (existing ordinary directory outside the bundle/private
153331
+ absolute executable path or exact {path, versionFlag}), outputRoot (existing ordinary directory outside the bundle/private
153180
153332
  state), and profile (synthetic-v1: 16 MiB inputs/32 MiB outputs/30 seconds, or comparison-v1:
153181
153333
  128 MiB inputs/128 MiB outputs/120 seconds). Inputs are finite individual regular files; adapters
153182
153334
  must refuse unclosed dependencies. Preview returns expectedInputs hashes. Run input JSON contains
153183
153335
  {expectedInputs: {role: "sha256:..."}, settings: {...}}. Confirm new hashes for changed inputs.
153184
153336
  Tool paths resolve to native physical binaries; executable scripts/wrappers are refused.
153185
153337
  Symlink launcher/virtual-environment semantics are not
153186
- preserved. Use a copied interpreter when needed. Bind pins executable bytes and --version, not
153187
- arbitrary installed libraries or OS dependencies. These profiles are not qualified private-pilot
153338
+ preserved. Use a copied interpreter when needed. String tool paths probe with --version; explicit
153339
+ versionFlag accepts only --version or -version. All selections are validated before any probe;
153340
+ there is no flag fallback or arbitrary probe argv. Bind pins executable bytes, version output
153341
+ and the selected flag, not arbitrary installed libraries or OS dependencies. Existing stored
153342
+ bindings without a flag retain --version in new run evidence; earlier receipts are unchanged. These profiles are not qualified private-pilot
153188
153343
  limits or CPU/RAM/disk isolation.
153189
153344
 
153190
153345
  Without --local, a local or Git bundle has no host operations: op list answers none, and op run is refused