superbee 0.4.4-pre.1 → 0.4.4-pre.2

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.
@@ -3,6 +3,11 @@ import { createHash } from "node:crypto";
3
3
  import { mkdir, mkdtemp, realpath, rm, writeFile } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
 
6
+ // ../core/src/path-fold.ts
7
+ function foldPath(path2) {
8
+ return path2.normalize("NFC").toLowerCase().toUpperCase().toLowerCase().normalize("NFC");
9
+ }
10
+
6
11
  // ../core/src/errors.ts
7
12
  var InvalidInputError = class extends Error {
8
13
  constructor(message) {
@@ -175,7 +180,6 @@ function readStoredZip(archive) {
175
180
  return entries;
176
181
  }
177
182
  var WINDOWS_DEVICE_NAMES = /* @__PURE__ */ new Set(["CON", "PRN", "AUX", "NUL", ...Array.from({ length: 9 }, (_, i) => `COM${i + 1}`), ...Array.from({ length: 9 }, (_, i) => `LPT${i + 1}`)]);
178
- var fold = (segment) => segment.normalize("NFC").toLowerCase();
179
183
  function classifyEntryPath(entryPath) {
180
184
  const unsafe = (why) => new ExportArchiveError("unsafe_path", `the archive holds a path a bundle cannot keep (${why}): ${JSON.stringify(entryPath.slice(0, 200))}`);
181
185
  if (entryPath === "" || entryPath.length > 4096) throw unsafe("empty or too long");
@@ -209,13 +213,13 @@ function findEntryCollision(paths) {
209
213
  const dirs = /* @__PURE__ */ new Map();
210
214
  for (const entryPath of paths) {
211
215
  const segments = entryPath.split("/");
212
- const key = segments.map(fold).join("/");
216
+ const key = segments.map(foldPath).join("/");
213
217
  const file = files.get(key) ?? dirs.get(key)?.by;
214
218
  if (file !== void 0) return [file, entryPath];
215
219
  files.set(key, entryPath);
216
220
  for (let depth = 1; depth < segments.length; depth += 1) {
217
221
  const spelling = segments.slice(0, depth).join("/");
218
- const dirKey = segments.slice(0, depth).map(fold).join("/");
222
+ const dirKey = segments.slice(0, depth).map(foldPath).join("/");
219
223
  const asFile = files.get(dirKey);
220
224
  if (asFile !== void 0) return [asFile, entryPath];
221
225
  const seen = dirs.get(dirKey);
@@ -5440,6 +5440,11 @@ async function queryEdges2(bundle, filter = {}, options = {}) {
5440
5440
  // ../core/src/bundle.ts
5441
5441
  setDefaultBackendFactory((root) => new FilesystemBackend(root));
5442
5442
 
5443
+ // ../core/src/code-unit-order.ts
5444
+ function compareCodeUnits(a, b) {
5445
+ return a < b ? -1 : a > b ? 1 : 0;
5446
+ }
5447
+
5443
5448
  // ../core/src/managed-document-metadata.ts
5444
5449
  var MANAGED_DOCUMENT_METADATA_FIELDS = /* @__PURE__ */ new Set([
5445
5450
  "generated",
@@ -6328,7 +6333,7 @@ function compareByMeaningfulChange(a, b) {
6328
6333
  } else if (b.timestampMs !== null) {
6329
6334
  return 1;
6330
6335
  }
6331
- return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
6336
+ return compareCodeUnits(a.id, b.id);
6332
6337
  }
6333
6338
  function sortByMeaningfulChange(rows, okfVersion) {
6334
6339
  return rows.map((row) => ({ row, key: meaningfulChangeOrderKey(row.id, row.frontmatter, okfVersion) })).sort((a, b) => compareByMeaningfulChange(a.key, b.key)).map(({ row }) => row);
@@ -33424,6 +33424,11 @@ async function queryEdges2(bundle, filter = {}, options = {}) {
33424
33424
  // ../core/src/bundle.ts
33425
33425
  setDefaultBackendFactory((root) => new FilesystemBackend(root));
33426
33426
 
33427
+ // ../core/src/code-unit-order.ts
33428
+ function compareCodeUnits(a, b) {
33429
+ return a < b ? -1 : a > b ? 1 : 0;
33430
+ }
33431
+
33427
33432
  // ../core/src/managed-document-metadata.ts
33428
33433
  var MANAGED_DOCUMENT_METADATA_FIELDS = /* @__PURE__ */ new Set([
33429
33434
  "generated",
@@ -43543,7 +43548,7 @@ function compareByMeaningfulChange(a, b) {
43543
43548
  } else if (b.timestampMs !== null) {
43544
43549
  return 1;
43545
43550
  }
43546
- return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
43551
+ return compareCodeUnits(a.id, b.id);
43547
43552
  }
43548
43553
  function sortByMeaningfulChange(rows, okfVersion) {
43549
43554
  return rows.map((row) => ({ row, key: meaningfulChangeOrderKey(row.id, row.frontmatter, okfVersion) })).sort((a, b) => compareByMeaningfulChange(a.key, b.key)).map(({ row }) => row);
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.4-pre.1" }, source: { commit: "6eb9c66ad2b6ba73122b5431ffe50a194c0e844f", 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.4-pre.2" }, source: { commit: "008e00fa04d0ff726dfa3d6da80343cbcf230309", dirty: false }, artifact: { channel: "npm-package" }, compatibility_contracts: { skill: 1, hook: 1, mcp: 1 } };
48
48
  }
49
49
  });
50
50
 
@@ -9508,9 +9508,21 @@ var init_remote_error = __esm({
9508
9508
  }
9509
9509
  });
9510
9510
 
9511
+ // ../core/src/code-unit-order.ts
9512
+ function compareCodeUnits(a, b) {
9513
+ return a < b ? -1 : a > b ? 1 : 0;
9514
+ }
9515
+ var init_code_unit_order = __esm({
9516
+ "../core/src/code-unit-order.ts"() {
9517
+ "use strict";
9518
+ init_define_SUPERBEE_BUILD_IDENTITY();
9519
+ init_define_SUPERBEE_UPDATE_POLICY();
9520
+ }
9521
+ });
9522
+
9511
9523
  // ../core/src/heads-digest.ts
9512
9524
  function sortHeads(heads) {
9513
- return [...heads].sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
9525
+ return [...heads].sort((a, b) => compareCodeUnits(a.id, b.id));
9514
9526
  }
9515
9527
  function headsDigest(heads) {
9516
9528
  let input = "";
@@ -9528,6 +9540,7 @@ var init_heads_digest = __esm({
9528
9540
  "use strict";
9529
9541
  init_define_SUPERBEE_BUILD_IDENTITY();
9530
9542
  init_define_SUPERBEE_UPDATE_POLICY();
9543
+ init_code_unit_order();
9531
9544
  init_sha256();
9532
9545
  HEADS_DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
9533
9546
  }
@@ -12567,8 +12580,9 @@ function onceNow(now) {
12567
12580
  }
12568
12581
  function prepareDocumentMutationCandidate(existing, rawCandidate, opts) {
12569
12582
  const persistActor = resolvePersistActor(opts);
12583
+ const mode = opts.mode ?? "patch";
12570
12584
  const decisionNow = onceNow(opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString()));
12571
- const comparison = withV02Metadata(
12585
+ const withMetadata = withV02Metadata(
12572
12586
  structuredClone(rawCandidate),
12573
12587
  existing,
12574
12588
  opts.okfVersion,
@@ -12579,19 +12593,23 @@ function prepareDocumentMutationCandidate(existing, rawCandidate, opts) {
12579
12593
  opts.compareTimestamp ?? false,
12580
12594
  opts.producer
12581
12595
  );
12582
- assertDeprecation(opts.id, comparison, opts.registry, existing);
12583
- if (existing && isNoopMutation(
12596
+ const comparison = mode === "overwrite" ? attributeCandidate(withMetadata, opts.actor, persistActor, opts.okfVersion, opts.registry) : withMetadata;
12597
+ if (mode !== "create-only") assertDeprecation(opts.id, comparison, opts.registry, existing);
12598
+ if (mode !== "create-only" && existing && isNoopMutation(
12584
12599
  existing,
12585
12600
  comparison,
12586
12601
  opts.compareTimestamp ?? false,
12587
12602
  opts.okfVersion,
12588
- opts.okfVersion === "0.2" && persistActor && opts.actor !== void 0,
12603
+ (mode === "overwrite" || opts.okfVersion === "0.2") && persistActor && opts.actor !== void 0,
12589
12604
  opts.registry.kinds.get(String(comparison.frontmatter.type))?.fields.required.includes("actor") ?? false
12590
12605
  )) {
12591
12606
  return { candidate: { frontmatter: structuredClone(existing.frontmatter), body: existing.body }, changed: false, warnings: validateUnchangedDocument(existing, opts.registry, opts.strict, opts.okfVersion), guidance: [] };
12592
12607
  }
12593
- const candidate = attributeCandidate(comparison, opts.actor, persistActor, opts.okfVersion, opts.registry);
12594
- const { warnings } = validateCandidate(opts.id, candidate, opts.registry, opts.strict, opts.okfVersion, decisionNow, existing);
12608
+ const candidate = mode === "overwrite" ? comparison : attributeCandidate(comparison, opts.actor, persistActor, opts.okfVersion, opts.registry);
12609
+ const { warnings, kind: kind2 } = validateCandidate(opts.id, candidate, opts.registry, opts.strict, opts.okfVersion, decisionNow, existing);
12610
+ if (mode === "overwrite" && !opts.strict && existing && warnings.length > 0 && conforms(existing, opts.registry)) {
12611
+ throw new KindConformanceError(opts.id, kind2.governs, warnings, opts.okfVersion);
12612
+ }
12595
12613
  return { candidate, changed: true, warnings, guidance: writeGuidance(opts.registry, opts.okfVersion, existing, candidate) };
12596
12614
  }
12597
12615
  function conforms(existing, registry2) {
@@ -12603,6 +12621,9 @@ function resolvePersistActor(opts) {
12603
12621
  return opts.persistActor ?? opts.actor !== void 0;
12604
12622
  }
12605
12623
  async function mutateDocument(opts) {
12624
+ if (opts.expectedVersion !== void 0 && opts.mode !== "patch" && opts.mode !== "replace-document") {
12625
+ throw new InvalidInputError("expectedVersion requires patch or replace-document mode.");
12626
+ }
12606
12627
  opts = { ...opts, bundle: { ...opts.bundle, backend: backendFor(opts.bundle) } };
12607
12628
  if (opts.inventoryGuard !== void 0) {
12608
12629
  if (opts.mode !== "replace-document" || opts.onAbsent !== "fail" || typeof opts.expectedVersion !== "string" || opts.maxAttempts !== void 0 && opts.maxAttempts !== 1) {
@@ -12682,6 +12703,19 @@ async function mutateDocument(opts) {
12682
12703
  await opts.assertCandidate?.(existing === void 0 ? void 0 : structuredClone(existing), structuredClone(candidate), context3);
12683
12704
  return candidate;
12684
12705
  };
12706
+ const prepare = async (existing, decisionNow) => prepareDocumentMutationCandidate(existing, await build2(existing, decisionNow), {
12707
+ mode: opts.mode,
12708
+ id: opts.id,
12709
+ registry: opts.registry,
12710
+ strict: opts.strict,
12711
+ okfVersion,
12712
+ now: decisionNow,
12713
+ actor: opts.actor,
12714
+ producer: opts.producer,
12715
+ persistActor,
12716
+ compareTimestamp,
12717
+ seedGenerationClock: seedClock
12718
+ });
12685
12719
  if (opts.mode === "create-only") {
12686
12720
  if (opts.preconditions !== void 0 && opts.preconditions.length > 0) {
12687
12721
  throw new InvalidInputError(
@@ -12689,25 +12723,7 @@ async function mutateDocument(opts) {
12689
12723
  );
12690
12724
  }
12691
12725
  const decisionNow = onceNow(now);
12692
- const withMetadata = withV02Metadata(
12693
- await build2(void 0, decisionNow),
12694
- void 0,
12695
- okfVersion,
12696
- opts.registry,
12697
- decisionNow,
12698
- seedClock,
12699
- opts.actor,
12700
- compareTimestamp,
12701
- opts.producer
12702
- );
12703
- const candidate = attributeCandidate(
12704
- withMetadata,
12705
- opts.actor,
12706
- persistActor,
12707
- okfVersion,
12708
- opts.registry
12709
- );
12710
- const { warnings } = validateCandidate(opts.id, candidate, opts.registry, opts.strict, okfVersion, decisionNow);
12726
+ const { candidate, warnings } = await prepare(void 0, decisionNow);
12711
12727
  const { doc: doc2, version: version5 } = await writeDocVersionedForEdition2(opts.bundle, { id: opts.id, ...candidate }, okfVersion, {
12712
12728
  expectedVersion: null,
12713
12729
  actor: opts.actor,
@@ -12739,49 +12755,12 @@ async function mutateDocument(opts) {
12739
12755
  const decisionNow = onceNow(now);
12740
12756
  decidedExisting = existing;
12741
12757
  assertFieldPreconditions(opts.id, existing?.frontmatter, opts.preconditions, lastReadVersion);
12742
- const withMetadata = withV02Metadata(
12743
- await build2(existing, decisionNow),
12744
- existing,
12745
- okfVersion,
12746
- opts.registry,
12747
- decisionNow,
12748
- seedClock,
12749
- opts.actor,
12750
- compareTimestamp,
12751
- opts.producer
12752
- );
12753
- const candidate = attributeCandidate(
12754
- withMetadata,
12755
- opts.actor,
12756
- persistActor,
12757
- okfVersion,
12758
- opts.registry
12759
- );
12760
- assertDeprecation(opts.id, candidate, opts.registry, existing);
12761
- if (existing && isNoopMutation(
12762
- existing,
12763
- candidate,
12764
- compareTimestamp,
12765
- okfVersion,
12766
- persistActor && opts.actor !== void 0,
12767
- opts.registry.kinds.get(String(candidate.frontmatter.type))?.fields.required.includes("actor") ?? false
12768
- )) {
12769
- warnings = validateUnchangedDocument(existing, opts.registry, opts.strict, okfVersion);
12758
+ const prepared2 = await prepare(existing, decisionNow);
12759
+ const { candidate, changed } = prepared2;
12760
+ warnings = prepared2.warnings;
12761
+ if (!changed) {
12770
12762
  return { action: "done", result: { doc: existing } };
12771
12763
  }
12772
- const validated = validateCandidate(
12773
- opts.id,
12774
- candidate,
12775
- opts.registry,
12776
- opts.strict,
12777
- okfVersion,
12778
- decisionNow,
12779
- existing
12780
- );
12781
- warnings = validated.warnings;
12782
- if (!opts.strict && existing && warnings.length > 0 && conforms(existing, opts.registry)) {
12783
- throw new KindConformanceError(opts.id, validated.kind.governs, warnings, okfVersion);
12784
- }
12785
12764
  return { action: "write", next: { id: opts.id, ...candidate }, result: {} };
12786
12765
  },
12787
12766
  write: async (next, expectedVersion) => {
@@ -12811,19 +12790,7 @@ async function mutateDocument(opts) {
12811
12790
  if (hardCas && lastReadVersion !== opts.expectedVersion) {
12812
12791
  throw new VersionConflict(opts.id, opts.expectedVersion, lastReadVersion);
12813
12792
  }
12814
- const rawCandidate = await build2(existing, decisionNow);
12815
- const { candidate, changed, warnings, guidance } = prepareDocumentMutationCandidate(existing, rawCandidate, {
12816
- id: opts.id,
12817
- registry: opts.registry,
12818
- strict: opts.strict,
12819
- okfVersion,
12820
- now: decisionNow,
12821
- actor: opts.actor,
12822
- producer: opts.producer,
12823
- persistActor,
12824
- compareTimestamp,
12825
- seedGenerationClock: seedClock
12826
- });
12793
+ const { candidate, changed, warnings, guidance } = await prepare(existing, decisionNow);
12827
12794
  if (!changed && opts.inventoryGuard) throw new InvalidInputError("Inventory-guarded replacement requires a meaningful change.");
12828
12795
  if (!changed) return { action: "done", result: { doc: existing, warnings, guidance } };
12829
12796
  return { action: "write", next: { id: opts.id, ...candidate }, result: { warnings, guidance } };
@@ -13387,6 +13354,18 @@ var init_code_point_order = __esm({
13387
13354
  }
13388
13355
  });
13389
13356
 
13357
+ // ../core/src/path-fold.ts
13358
+ function foldPath(path71) {
13359
+ return path71.normalize("NFC").toLowerCase().toUpperCase().toLowerCase().normalize("NFC");
13360
+ }
13361
+ var init_path_fold = __esm({
13362
+ "../core/src/path-fold.ts"() {
13363
+ "use strict";
13364
+ init_define_SUPERBEE_BUILD_IDENTITY();
13365
+ init_define_SUPERBEE_UPDATE_POLICY();
13366
+ }
13367
+ });
13368
+
13390
13369
  // ../core/src/governed-body-write.ts
13391
13370
  function fail2(message) {
13392
13371
  throw new Error(`Invalid body delivery: ${message}`);
@@ -13917,6 +13896,7 @@ __export(src_exports, {
13917
13896
  claimCoordinates: () => claimCoordinates,
13918
13897
  collectLinkDeclarations: () => collectLinkDeclarations,
13919
13898
  compareCodePoints: () => compareCodePoints,
13899
+ compareCodeUnits: () => compareCodeUnits,
13920
13900
  compareReadingOrder: () => compareReadingOrder,
13921
13901
  compareStorageKeys: () => compareStorageKeys,
13922
13902
  computeDroppedLinks: () => computeDroppedLinks,
@@ -13938,6 +13918,7 @@ __export(src_exports, {
13938
13918
  extensionOfDocKey: () => extensionOfDocKey,
13939
13919
  extractMarkdownLinks: () => extractMarkdownLinks,
13940
13920
  filesystemMutationLockPath: () => filesystemMutationLockPath,
13921
+ foldPath: () => foldPath,
13941
13922
  freshness: () => freshness,
13942
13923
  freshnessHorizonMs: () => freshnessHorizonMs,
13943
13924
  guardBodyReplace: () => guardBodyReplace,
@@ -14112,6 +14093,8 @@ var init_src = __esm({
14112
14093
  init_kinds();
14113
14094
  init_kinds_load();
14114
14095
  init_code_point_order();
14096
+ init_code_unit_order();
14097
+ init_path_fold();
14115
14098
  init_content_type();
14116
14099
  init_okf_timestamps();
14117
14100
  init_okf_lifecycle();
@@ -23471,11 +23454,11 @@ var init_evolution = __esm({
23471
23454
  // ../core/src/recipe-set-preflight.ts
23472
23455
  function canonicalJson2(value) {
23473
23456
  if (Array.isArray(value)) {
23474
- const ordered = value.every((v) => record5(v) && typeof v.path === "string") ? [...value].sort((a, b) => compareCodeUnits(a.path, b.path)) : value;
23457
+ const ordered = value.every((v) => record5(v) && typeof v.path === "string") ? [...value].sort((a, b) => compareCodeUnits2(a.path, b.path)) : value;
23475
23458
  return "[" + ordered.map(canonicalJson2).join(",") + "]";
23476
23459
  }
23477
23460
  if (record5(value)) {
23478
- return "{" + Object.keys(value).sort(compareCodeUnits).map((key4) => JSON.stringify(key4) + ":" + canonicalJson2(value[key4])).join(",") + "}";
23461
+ return "{" + Object.keys(value).sort(compareCodeUnits2).map((key4) => JSON.stringify(key4) + ":" + canonicalJson2(value[key4])).join(",") + "}";
23479
23462
  }
23480
23463
  return JSON.stringify(value);
23481
23464
  }
@@ -23648,7 +23631,7 @@ async function preflightRecipeSet(value) {
23648
23631
  malformed6 = ["input"];
23649
23632
  }
23650
23633
  if (malformed6.length)
23651
- return { schema: "recipe-set-preflight-result/v1", verdict: "refused", structuralComplete: false, scope: "declared-structural-input-only", digestScheme: RECIPE_PREFLIGHT_DIGEST_SCHEME, inputs: { selected: [], consumers: [], observations: [], placementInventories: [] }, externalConsumers: "unknown-out-of-scope", issues: malformed6.sort(compareCodeUnits).map((at) => ({ level: "refused", code: "INPUT_SHAPE", at })), parserWarnings: [] };
23634
+ return { schema: "recipe-set-preflight-result/v1", verdict: "refused", structuralComplete: false, scope: "declared-structural-input-only", digestScheme: RECIPE_PREFLIGHT_DIGEST_SCHEME, inputs: { selected: [], consumers: [], observations: [], placementInventories: [] }, externalConsumers: "unknown-out-of-scope", issues: malformed6.sort(compareCodeUnits2).map((at) => ({ level: "refused", code: "INPUT_SHAPE", at })), parserWarnings: [] };
23652
23635
  const input = value;
23653
23636
  const issues = [], parserWarnings = [];
23654
23637
  const recipes2 = /* @__PURE__ */ new Map();
@@ -23865,7 +23848,7 @@ async function preflightRecipeSet(value) {
23865
23848
  const c = input.consumers.find((x) => x.id === consumer);
23866
23849
  const requirements = c?.requirements?.filter((r) => r.provider === provider && r.kind === kind2) ?? [];
23867
23850
  const targets = requirements.flatMap((r) => endpoint2(consumer, r.id)).map((e) => e.placement === "local" ? kind2 : `${e.alias}:${kind2}`);
23868
- return [...new Set(targets)].sort(compareCodeUnits);
23851
+ return [...new Set(targets)].sort(compareCodeUnits2);
23869
23852
  };
23870
23853
  for (const s of input.selected)
23871
23854
  if (s.role === "extension" && !input.consumers.some((c) => c.owner === s.key))
@@ -23948,11 +23931,11 @@ async function preflightRecipeSet(value) {
23948
23931
  if (!c?.requirements?.some((r) => r.id === e.requirement))
23949
23932
  issue2("refused", "ORPHAN_ENDPOINT", e.id);
23950
23933
  }
23951
- const dedup = [...new Map(issues.map((i) => [JSON.stringify(i), i])).values()].sort((a, b) => compareCodeUnits(JSON.stringify(a), JSON.stringify(b)));
23934
+ const dedup = [...new Map(issues.map((i) => [JSON.stringify(i), i])).values()].sort((a, b) => compareCodeUnits2(JSON.stringify(a), JSON.stringify(b)));
23952
23935
  const verdict = dedup.some((i) => i.level === "refused") ? "refused" : dedup.length ? "partial" : "valid";
23953
- return { schema: "recipe-set-preflight-result/v1", verdict, structuralComplete: verdict === "valid", scope: "declared-structural-input-only", digestScheme: "fixture-envelope-v1/utf16-code-unit-sorted-keys-and-file-paths/sha256", inputs: { selected: input.selected.map(({ key: key4, publisher, recipeId, release: release2, artifactDigest }) => ({ key: key4, publisher, recipeId, release: release2, artifactDigest })), consumers: input.consumers.map(({ id, descriptorDigest }) => ({ id, descriptorDigest })), observations: input.observations.map(({ id, observedVersion }) => ({ id, ...observedVersion ? { observedVersion } : {} })), placementInventories: (input.placementInventories ?? []).map(({ id, observedVersion }) => ({ id, ...observedVersion ? { observedVersion } : {} })) }, externalConsumers: "unknown-out-of-scope", issues: dedup, parserWarnings: parserWarnings.sort((a, b) => compareCodeUnits(JSON.stringify(a), JSON.stringify(b))) };
23936
+ return { schema: "recipe-set-preflight-result/v1", verdict, structuralComplete: verdict === "valid", scope: "declared-structural-input-only", digestScheme: "fixture-envelope-v1/utf16-code-unit-sorted-keys-and-file-paths/sha256", inputs: { selected: input.selected.map(({ key: key4, publisher, recipeId, release: release2, artifactDigest }) => ({ key: key4, publisher, recipeId, release: release2, artifactDigest })), consumers: input.consumers.map(({ id, descriptorDigest }) => ({ id, descriptorDigest })), observations: input.observations.map(({ id, observedVersion }) => ({ id, ...observedVersion ? { observedVersion } : {} })), placementInventories: (input.placementInventories ?? []).map(({ id, observedVersion }) => ({ id, ...observedVersion ? { observedVersion } : {} })) }, externalConsumers: "unknown-out-of-scope", issues: dedup, parserWarnings: parserWarnings.sort((a, b) => compareCodeUnits2(JSON.stringify(a), JSON.stringify(b))) };
23954
23937
  }
23955
- var RECIPE_PREFLIGHT_DIGEST_SCHEME, MALFORMED_MODEL_DIAGNOSTICS, modelDiagnosticLevel, compareCodeUnits, text, pin, strings;
23938
+ var RECIPE_PREFLIGHT_DIGEST_SCHEME, MALFORMED_MODEL_DIAGNOSTICS, modelDiagnosticLevel, compareCodeUnits2, text, pin, strings;
23956
23939
  var init_recipe_set_preflight = __esm({
23957
23940
  "../core/src/recipe-set-preflight.ts"() {
23958
23941
  "use strict";
@@ -23985,7 +23968,7 @@ var init_recipe_set_preflight = __esm({
23985
23968
  "OKF_WORKFLOW_STATUS_COLLISION"
23986
23969
  ]);
23987
23970
  modelDiagnosticLevel = (code3) => MALFORMED_MODEL_DIAGNOSTICS.has(code3) ? "refused" : "partial";
23988
- compareCodeUnits = (a, b) => a < b ? -1 : a > b ? 1 : 0;
23971
+ compareCodeUnits2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
23989
23972
  text = (v) => typeof v === "string" && v.trim().length > 0;
23990
23973
  pin = (v) => typeof v === "string" && /^sha256:[0-9a-f]{64}$/.test(v);
23991
23974
  strings = (v) => Array.isArray(v) && v.every(text);
@@ -27497,7 +27480,7 @@ var init_command_spec = __esm({
27497
27480
  {
27498
27481
  id: "docDelete",
27499
27482
  leaves: [publicLeaf("docDelete", "doc delete", one, void 0, DIR_SURFACE)],
27500
- usage: "doc delete <id> [--expected-version <v>] [--dir <path>] [--remote <url>]",
27483
+ usage: "doc delete <id> [--expected-version <v>] [--actor <name>] [--dir <path>] [--remote <url>]",
27501
27484
  summary: "Hard-delete a doc (idempotent: absent -> deleted:false, exit 0)"
27502
27485
  },
27503
27486
  {
@@ -27554,7 +27537,7 @@ var init_command_spec = __esm({
27554
27537
  {
27555
27538
  id: "delete",
27556
27539
  leaves: [publicLeaf("delete", "delete", zero, 8, DIR_SURFACE)],
27557
- usage: "delete --doc-key <key> [--expected-version <v>] [--dir <path>] [--remote <url>]",
27540
+ usage: "delete --doc-key <key> [--expected-version <v>] [--actor <name>] [--dir <path>] [--remote <url>]",
27558
27541
  summary: "Hard-delete a doc or blob by key (outside a hosted checkout, idempotent: absent -> deleted:false, exit 0). Hosted ordinary files require clean preserved version+MIME pins and frozen exact-request delivery; they may remain incomplete"
27559
27542
  }
27560
27543
  ]
@@ -31366,7 +31349,7 @@ var init_source_profiles = __esm({
31366
31349
  };
31367
31350
  }
31368
31351
  });
31369
- SOURCE_PLUGIN_CORE_VERSION = "0.2.0-pre.36";
31352
+ SOURCE_PLUGIN_CORE_VERSION = "0.2.0-pre.37";
31370
31353
  SOURCE_PROFILES = Object.freeze([restJsonProfile].map((profile) => Object.freeze({ id: profile.id, version: profile.version, kind: profile.kind })));
31371
31354
  }
31372
31355
  });
@@ -32413,6 +32396,8 @@ stops resolving on the next graph walk) and does NOT append a log.md entry.
32413
32396
  Options:
32414
32397
  --expected-version <v> Compare-and-swap token from a prior read/write receipt (a stale token is a
32415
32398
  CONFLICT, exit 5; omit for an unconditional delete)
32399
+ --actor <name> Advisory board attribution (flag > actor environment). v0.2 requires an
32400
+ OKF actor; invalid configured attribution refuses before deletion.
32416
32401
  ${COMMON_OPTIONS}
32417
32402
 
32418
32403
  Examples:
@@ -32548,6 +32533,20 @@ async function firePostPersist(hook2) {
32548
32533
  } catch {
32549
32534
  }
32550
32535
  }
32536
+ async function deleteMutatedDoc(opts) {
32537
+ try {
32538
+ const deleted = await deleteDoc2(
32539
+ opts.bundle,
32540
+ opts.id,
32541
+ opts.expectedVersion === void 0 ? void 0 : { expectedVersion: opts.expectedVersion }
32542
+ );
32543
+ if (deleted) await firePostPersist(opts.onPersisted);
32544
+ return deleted;
32545
+ } catch (error51) {
32546
+ if (error51 instanceof VersionConflict) throw opts.staleHead(error51);
32547
+ throw classifyBundleError(error51, opts.remoteUrl);
32548
+ }
32549
+ }
32551
32550
  async function docExistsForMode(bundle, id, mode) {
32552
32551
  if (mode === "patch") return true;
32553
32552
  if (mode === "create-only") return false;
@@ -38885,13 +38884,13 @@ function findEntryCollision(paths) {
38885
38884
  const dirs = /* @__PURE__ */ new Map();
38886
38885
  for (const entryPath of paths) {
38887
38886
  const segments = entryPath.split("/");
38888
- const key4 = segments.map(fold3).join("/");
38887
+ const key4 = segments.map(foldPath).join("/");
38889
38888
  const file2 = files.get(key4) ?? dirs.get(key4)?.by;
38890
38889
  if (file2 !== void 0) return [file2, entryPath];
38891
38890
  files.set(key4, entryPath);
38892
38891
  for (let depth2 = 1; depth2 < segments.length; depth2 += 1) {
38893
38892
  const spelling = segments.slice(0, depth2).join("/");
38894
- const dirKey = segments.slice(0, depth2).map(fold3).join("/");
38893
+ const dirKey = segments.slice(0, depth2).map(foldPath).join("/");
38895
38894
  const asFile = files.get(dirKey);
38896
38895
  if (asFile !== void 0) return [asFile, entryPath];
38897
38896
  const seen = dirs.get(dirKey);
@@ -39050,12 +39049,13 @@ function exportProvenance(verified3) {
39050
39049
  manifests: state.provenance.manifests.map((manifest2) => ({ ...manifest2 }))
39051
39050
  };
39052
39051
  }
39053
- var EXPORT_MANIFEST, EXPORT_FORMAT, MAX_EXPORT_ENTRIES, MAX_EXPORT_BYTES, LOCAL, CENTRAL, END, UTF8_NAMES, ExportArchiveError, CRC_TABLE, sha256Hex2, utf8, WINDOWS_DEVICE_NAMES, fold3, ExportPageChain, verifiedStates;
39052
+ var EXPORT_MANIFEST, EXPORT_FORMAT, MAX_EXPORT_ENTRIES, MAX_EXPORT_BYTES, LOCAL, CENTRAL, END, UTF8_NAMES, ExportArchiveError, CRC_TABLE, sha256Hex2, utf8, WINDOWS_DEVICE_NAMES, ExportPageChain, verifiedStates;
39054
39053
  var init_portable_export = __esm({
39055
39054
  "../core/src/portable-export.ts"() {
39056
39055
  "use strict";
39057
39056
  init_define_SUPERBEE_BUILD_IDENTITY();
39058
39057
  init_define_SUPERBEE_UPDATE_POLICY();
39058
+ init_path_fold();
39059
39059
  init_paths();
39060
39060
  EXPORT_MANIFEST = "superbee-export.json";
39061
39061
  EXPORT_FORMAT = "superbee-export/1";
@@ -39085,7 +39085,6 @@ var init_portable_export = __esm({
39085
39085
  sha256Hex2 = (bytes2) => createHash8("sha256").update(bytes2).digest("hex");
39086
39086
  utf8 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
39087
39087
  WINDOWS_DEVICE_NAMES = /* @__PURE__ */ new Set(["CON", "PRN", "AUX", "NUL", ...Array.from({ length: 9 }, (_, i) => `COM${i + 1}`), ...Array.from({ length: 9 }, (_, i) => `LPT${i + 1}`)]);
39088
- fold3 = (segment) => segment.normalize("NFC").toLowerCase();
39089
39088
  ExportPageChain = class {
39090
39089
  #pages = [];
39091
39090
  #from = 0;
@@ -39277,7 +39276,7 @@ async function replaceGuarded(file2, expected, next) {
39277
39276
  await syncDir(path21.dirname(file2));
39278
39277
  return { placed: true };
39279
39278
  }
39280
- function fold4(segment) {
39279
+ function fold3(segment) {
39281
39280
  return segment.normalize("NFKD").toLowerCase().toUpperCase().toLowerCase();
39282
39281
  }
39283
39282
  async function projectionPathExact(folder, rel) {
@@ -39296,7 +39295,7 @@ function findFilePathCollision(files) {
39296
39295
  const segments = file2.split("/");
39297
39296
  for (let depth2 = 1; depth2 <= segments.length; depth2 += 1) {
39298
39297
  const spelling = segments.slice(0, depth2).join("/") + (depth2 < segments.length ? "/" : "");
39299
- const key4 = segments.slice(0, depth2).map(fold4).join("/");
39298
+ const key4 = segments.slice(0, depth2).map(fold3).join("/");
39300
39299
  const seen = spelled.get(key4);
39301
39300
  if (seen !== void 0 && seen !== spelling) return { first: seen, second: spelling };
39302
39301
  spelled.set(key4, spelling);
@@ -48903,7 +48902,7 @@ function sameAsStored(bytes2, id, doc2, okfVersion) {
48903
48902
  }
48904
48903
  }
48905
48904
  function foldedPath(id) {
48906
- return id.split("/").map(fold4).join("/");
48905
+ return id.split("/").map(fold3).join("/");
48907
48906
  }
48908
48907
  function documentInputBound(stated) {
48909
48908
  return stated ?? WHOLE_DOCUMENT_BOUNDS.payloadBytes;
@@ -54821,12 +54820,12 @@ async function caseCollidingCreates(store) {
54821
54820
  if (creates.length === 0) return [];
54822
54821
  const byFold = /* @__PURE__ */ new Map();
54823
54822
  for (const id of await store.readHeads({ project: (head2) => head2.id })) {
54824
- const key4 = id.split("/").map(fold4).join("/");
54823
+ const key4 = id.split("/").map(fold3).join("/");
54825
54824
  byFold.set(key4, [...byFold.get(key4) ?? [], id]);
54826
54825
  }
54827
54826
  const out = [];
54828
54827
  for (const row5 of creates) {
54829
- const twin = byFold.get(row5.target.split("/").map(fold4).join("/"))?.find((id) => id !== row5.target);
54828
+ const twin = byFold.get(row5.target.split("/").map(fold3).join("/"))?.find((id) => id !== row5.target);
54830
54829
  if (twin !== void 0) {
54831
54830
  out.push({ id: row5.target, path: `${row5.target}.md`, reason: "case_collision", message: `'${row5.target}' differs only in letter case from the host's '${twin}', which a case-insensitive disk treats as the same file; rename your file` });
54832
54831
  }
@@ -95245,6 +95244,7 @@ async function docDelete(argv2, deps2) {
95245
95244
  args: argv2,
95246
95245
  options: {
95247
95246
  "expected-version": { type: "string" },
95247
+ actor: { type: "string" },
95248
95248
  dir: { type: "string" },
95249
95249
  remote: { type: "string" },
95250
95250
  json: { type: "boolean" },
@@ -95280,7 +95280,10 @@ async function docDelete(argv2, deps2) {
95280
95280
  { help: `${cliInvocation()} doc delete ${commandToken(id)} --expected-version <v>` }
95281
95281
  );
95282
95282
  }
95283
- const bundle = await openBundle(values.dir, await resolveRemoteFlag(values.remote, values.dir));
95283
+ const remote = await resolveRemoteFlag(values.remote, values.dir);
95284
+ const route = remote === void 0 ? await resolveLocalBundleRoute(values.dir) : void 0;
95285
+ const bundle = route?.bundle ?? await openBundle(values.dir, remote);
95286
+ if (route) await assertResolvedLocalRouteIdentity(route);
95284
95287
  id = await resolveConceptIdCliArgument(bundle, rawId);
95285
95288
  if (isReservedFile(pathFromConceptId(id))) {
95286
95289
  throw new CliError(
@@ -95291,22 +95294,29 @@ async function docDelete(argv2, deps2) {
95291
95294
  }
95292
95295
  const mode = resolveMode(values);
95293
95296
  const expectedVersion = rawExpected?.trim();
95294
- let deleted;
95297
+ const actor = resolveActor(values.actor, { help: `${cliInvocation()} doc delete ${commandToken(id)} --actor <name>` });
95295
95298
  try {
95296
- deleted = await deleteDoc2(bundle, id, expectedVersion ? { expectedVersion } : void 0);
95297
- } catch (err) {
95298
- if (err instanceof VersionConflict) {
95299
- throw new CliError(
95300
- "STALE_HEAD",
95301
- `'${id}' has moved since --expected-version ${commandToken(String(err.expected))} was read (current: ${err.actual ?? "absent"}) \u2014 re-read and retry with the current version.`,
95302
- {
95303
- help: `${cliInvocation()} doc read ${commandToken(id)}`,
95304
- details: { expected: err.expected, actual: err.actual }
95305
- }
95306
- );
95307
- }
95308
- throw classifyBundleError(err, values.remote);
95299
+ await assertActorAcceptedByBundle(bundle, actor);
95300
+ } catch (error51) {
95301
+ throw classifyBundleError(error51, values.remote);
95309
95302
  }
95303
+ const onPersisted = boardPostPersistHook(route ? boardAttributionForRoute(route) : { kind: "none" }, actor);
95304
+ if (route) await assertResolvedLocalRouteIdentity(route);
95305
+ const deleted = await deleteMutatedDoc({
95306
+ bundle,
95307
+ id,
95308
+ expectedVersion,
95309
+ remoteUrl: values.remote,
95310
+ onPersisted,
95311
+ staleHead: (err) => new CliError(
95312
+ "STALE_HEAD",
95313
+ `'${id}' has moved since --expected-version ${commandToken(String(err.expected))} was read (current: ${err.actual ?? "absent"}) \u2014 re-read and retry with the current version.`,
95314
+ {
95315
+ help: `${cliInvocation()} doc read ${commandToken(id)}`,
95316
+ details: { expected: err.expected, actual: err.actual }
95317
+ }
95318
+ )
95319
+ });
95310
95320
  const receipt5 = { doc: "deleted", id, deleted };
95311
95321
  receipt5.help = [`${cliInvocation()} list`];
95312
95322
  stdout(render(receipt5, mode));
@@ -95320,6 +95330,9 @@ var init_delete = __esm({
95320
95330
  init_src();
95321
95331
  init_bundle2();
95322
95332
  init_errors6();
95333
+ init_actor();
95334
+ init_board_attribution();
95335
+ init_mutate();
95323
95336
  init_args();
95324
95337
  init_command_spec();
95325
95338
  init_output2();
@@ -97556,7 +97569,7 @@ function compareByMeaningfulChange(a, b) {
97556
97569
  } else if (b.timestampMs !== null) {
97557
97570
  return 1;
97558
97571
  }
97559
- return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
97572
+ return compareCodeUnits(a.id, b.id);
97560
97573
  }
97561
97574
  function sortByMeaningfulChange(rows, okfVersion) {
97562
97575
  return rows.map((row5) => ({ row: row5, key: meaningfulChangeOrderKey(row5.id, row5.frontmatter, okfVersion) })).sort((a, b) => compareByMeaningfulChange(a.key, b.key)).map(({ row: row5 }) => row5);
@@ -97566,6 +97579,7 @@ var init_query_order = __esm({
97566
97579
  "use strict";
97567
97580
  init_define_SUPERBEE_BUILD_IDENTITY();
97568
97581
  init_define_SUPERBEE_UPDATE_POLICY();
97582
+ init_code_unit_order();
97569
97583
  init_freshness();
97570
97584
  init_meaningful_change_time();
97571
97585
  }
@@ -101922,6 +101936,7 @@ async function deleteCommand(argv2, deps2 = {}) {
101922
101936
  options: {
101923
101937
  "doc-key": { type: "string" },
101924
101938
  "expected-version": { type: "string" },
101939
+ actor: { type: "string" },
101925
101940
  dir: { type: "string" },
101926
101941
  remote: { type: "string" },
101927
101942
  json: { type: "boolean" },
@@ -101961,16 +101976,29 @@ async function deleteCommand(argv2, deps2 = {}) {
101961
101976
  return;
101962
101977
  }
101963
101978
  }
101964
- const bundle = await openBundle(values.dir, remote);
101979
+ const docRoute = isDocRouteKey3(key4);
101980
+ const route = docRoute && remote === void 0 ? await resolveLocalBundleRoute(values.dir) : void 0;
101981
+ const bundle = route?.bundle ?? await openBundle(values.dir, remote);
101982
+ if (route) await assertResolvedLocalRouteIdentity(route);
101965
101983
  const mode = resolveMode(values);
101966
101984
  const expectedVersion = rawExpected?.trim();
101967
- const docRoute = isDocRouteKey3(key4);
101968
101985
  let deleted;
101969
101986
  try {
101970
101987
  if (docRoute) {
101971
101988
  const canonicalPath = key4.slice(0, -3) + ".md";
101972
101989
  const id = conceptIdFromPath(canonicalPath);
101973
- deleted = await deleteDoc2(bundle, id, expectedVersion ? { expectedVersion } : void 0);
101990
+ const actor = resolveActor(values.actor, { help: `${cliInvocation()} delete --doc-key ${commandToken(key4)} --actor <name>` });
101991
+ await assertActorAcceptedByBundle(bundle, actor);
101992
+ const onPersisted = boardPostPersistHook(route ? boardAttributionForRoute(route) : { kind: "none" }, actor);
101993
+ if (route) await assertResolvedLocalRouteIdentity(route);
101994
+ deleted = await deleteMutatedDoc({
101995
+ bundle,
101996
+ id,
101997
+ expectedVersion,
101998
+ remoteUrl: values.remote,
101999
+ onPersisted,
102000
+ staleHead: (error51) => deleteErrorToCliError(error51, key4, values.remote)
102001
+ });
101974
102002
  } else {
101975
102003
  deleted = await deleteBlob2(bundle, key4, expectedVersion ? { expectedVersion } : void 0);
101976
102004
  }
@@ -102011,6 +102039,9 @@ var init_delete2 = __esm({
102011
102039
  init_output2();
102012
102040
  init_src();
102013
102041
  init_bundle2();
102042
+ init_actor();
102043
+ init_board_attribution();
102044
+ init_mutate();
102014
102045
  init_errors6();
102015
102046
  init_args();
102016
102047
  init_command_spec();
@@ -102048,6 +102079,8 @@ Options:
102048
102079
  --expected-version <v> Compare-and-swap token from a prior read/write/pull receipt (a stale
102049
102080
  token is a CONFLICT, exit 5; outside a hosted checkout omit for an
102050
102081
  unconditional delete; hosted blobs always use preserved version+MIME pins)
102082
+ --actor <name> Document route only: advisory board attribution (flag > actor environment).
102083
+ v0.2 requires an OKF actor; blob deletion ignores this option/environment.
102051
102084
  --dir <path> Bundle directory (default: discovered from the cwd)
102052
102085
  --remote <url> Talk to a wire-protocol server instead of a local bundle (mutually
102053
102086
  exclusive with --dir; remote access is always explicit)
@@ -154051,7 +154084,7 @@ async function planPublish(folder, options) {
154051
154084
  } else {
154052
154085
  const claimed = /* @__PURE__ */ new Map();
154053
154086
  for (const file2 of [...documents.map((doc2) => `${doc2.id}.md`), ...reserved.map((r) => r.dir === "" ? r.name : `${r.dir}/${r.name}`), ...blobs2.map((b) => b.key)]) {
154054
- const key4 = file2.split("/").map(fold4).join("/");
154087
+ const key4 = file2.split("/").map(fold3).join("/");
154055
154088
  const other = claimed.get(key4);
154056
154089
  if (other !== void 0) {
154057
154090
  blockers.push({ path: file2, reason: "path_collision", message: `'${other}' and '${file2}' would be one file on a case-insensitive disk` });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superbee",
3
- "version": "0.4.4-pre.1",
3
+ "version": "0.4.4-pre.2",
4
4
  "type": "module",
5
5
  "description": "Agent-facing Superbee CLI for reading and writing local OKF knowledge bundles: context notes, docs, cross-links, and live bundle Views.",
6
6
  "keywords": [