superbee 0.4.6-pre.2 → 0.4.6-pre.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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.6-pre.2" }, source: { commit: "2b1d8f3f0c9e2e556e6f7a7343c3a82b559735db", 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.6-pre.3" }, source: { commit: "1e105cf6a63c34d1d40966ce299ce4087fe7cecd", dirty: false }, artifact: { channel: "npm-package" }, compatibility_contracts: { skill: 1, hook: 1, mcp: 1 } };
48
48
  }
49
49
  });
50
50
 
@@ -82,20 +82,20 @@ var init_errors = __esm({
82
82
  suggestedId;
83
83
  /** The canonical spelling names a document that already exists, so it is not offered as the fix. */
84
84
  existingId;
85
- constructor(id, why, suggestion) {
85
+ constructor(id, why, suggestion2) {
86
86
  const explanation = {
87
87
  segment_whitespace: "a path segment starts or ends with whitespace",
88
88
  format_character: "a path segment holds an invisible format character",
89
89
  not_nfc: "it writes a letter as two characters (a base letter and a separate combining mark) instead of one, and some filesystems treat the two spellings as the same name"
90
90
  }[why];
91
91
  super(
92
- `'${visibleId(id)}' cannot be created: ${explanation}. Ids must have one spelling everywhere, so this one would also fail at publish and sync.` + (suggestion === void 0 ? " Choose a different id." : suggestion.exists ? ` '${suggestion.id}' already exists: choose a different id, or edit that document if you meant it.` : ` Use '${suggestion.id}'.`)
92
+ `'${visibleId(id)}' cannot be created: ${explanation}. Ids must have one spelling everywhere, so this one would also fail at publish and sync.` + (suggestion2 === void 0 ? " Choose a different id." : suggestion2.exists ? ` '${suggestion2.id}' already exists: choose a different id, or edit that document if you meant it.` : ` Use '${suggestion2.id}'.`)
93
93
  );
94
94
  this.name = "NonCanonicalDocumentIdError";
95
95
  this.id = id;
96
96
  this.why = why;
97
- this.suggestedId = suggestion && !suggestion.exists ? suggestion.id : void 0;
98
- this.existingId = suggestion?.exists ? suggestion.id : void 0;
97
+ this.suggestedId = suggestion2 && !suggestion2.exists ? suggestion2.id : void 0;
98
+ this.existingId = suggestion2?.exists ? suggestion2.id : void 0;
99
99
  }
100
100
  };
101
101
  FrontmatterRefusedError = class extends InvalidInputError {
@@ -3960,6 +3960,8 @@ function extractMarkdownLinkSpans(source2, options = {}) {
3960
3960
  const body = options.skipCode ? maskMarkdownCode(source2) : source2;
3961
3961
  const out = [];
3962
3962
  let textOpen = -1;
3963
+ let codeOpen = -1;
3964
+ let masked;
3963
3965
  let afterClose;
3964
3966
  let hrefFirst;
3965
3967
  let hrefRest;
@@ -3978,6 +3980,7 @@ function extractMarkdownLinkSpans(source2, options = {}) {
3978
3980
  image
3979
3981
  });
3980
3982
  textOpen = -1;
3983
+ codeOpen = -1;
3981
3984
  afterClose = void 0;
3982
3985
  hrefFirst = void 0;
3983
3986
  hrefRest = void 0;
@@ -3998,10 +4001,22 @@ function extractMarkdownLinkSpans(source2, options = {}) {
3998
4001
  afterClose = void 0;
3999
4002
  }
4000
4003
  if (textOpen >= 0 && char === "]") {
4001
- afterClose = { open: textOpen, close: cursor };
4004
+ const open7 = codeOpen >= 0 && masked[cursor] !== "]" ? codeOpen : textOpen;
4005
+ afterClose = { open: open7, close: cursor };
4002
4006
  textOpen = -1;
4007
+ codeOpen = -1;
4008
+ }
4009
+ if (char === "[") {
4010
+ if (textOpen >= 0 && !options.skipCode) {
4011
+ masked ??= maskMarkdownCode(source2);
4012
+ if (masked[cursor] !== "[" && masked[textOpen] === "[") {
4013
+ codeOpen = cursor;
4014
+ continue;
4015
+ }
4016
+ }
4017
+ textOpen = cursor;
4018
+ codeOpen = -1;
4003
4019
  }
4004
- if (char === "[" && textOpen < 0) textOpen = cursor;
4005
4020
  }
4006
4021
  return out;
4007
4022
  }
@@ -6015,10 +6030,10 @@ function positiveOption(value, fallback, name) {
6015
6030
  }
6016
6031
  return resolved;
6017
6032
  }
6018
- function isPrivateFilesystemMutationLockRoot(facts) {
6019
- const wrongOwner = facts.expectedUid !== void 0 && facts.ownerUid !== facts.expectedUid;
6020
- const unsafeMode = facts.enforcePrivateMode && (facts.mode & 511) !== 448;
6021
- return facts.directory && !facts.symbolicLink && !wrongOwner && !unsafeMode;
6033
+ function isPrivateFilesystemMutationLockRoot(facts2) {
6034
+ const wrongOwner = facts2.expectedUid !== void 0 && facts2.ownerUid !== facts2.expectedUid;
6035
+ const unsafeMode = facts2.enforcePrivateMode && (facts2.mode & 511) !== 448;
6036
+ return facts2.directory && !facts2.symbolicLink && !wrongOwner && !unsafeMode;
6022
6037
  }
6023
6038
  async function ensurePrivateLockRoot(root, policy) {
6024
6039
  try {
@@ -6364,18 +6379,28 @@ var init_filesystem_lock = __esm({
6364
6379
  }
6365
6380
  });
6366
6381
 
6382
+ // ../core/src/path-fold.ts
6383
+ function foldPath(path81) {
6384
+ return path81.normalize("NFD").toLowerCase().toUpperCase().toLowerCase().normalize("NFC");
6385
+ }
6386
+ var init_path_fold = __esm({
6387
+ "../core/src/path-fold.ts"() {
6388
+ "use strict";
6389
+ init_define_SUPERBEE_BUILD_IDENTITY();
6390
+ init_define_SUPERBEE_UPDATE_POLICY();
6391
+ }
6392
+ });
6393
+
6367
6394
  // ../core/src/identity-fold.ts
6368
6395
  function foldSegment(segment) {
6369
- return segment.normalize("NFKD").toLowerCase().toUpperCase().toLowerCase();
6370
- }
6371
- function foldIdentityPath(rel) {
6372
- return rel.split("/").map(foldSegment).join("/");
6396
+ return foldPath(segment).normalize("NFD");
6373
6397
  }
6374
6398
  var init_identity_fold = __esm({
6375
6399
  "../core/src/identity-fold.ts"() {
6376
6400
  "use strict";
6377
6401
  init_define_SUPERBEE_BUILD_IDENTITY();
6378
6402
  init_define_SUPERBEE_UPDATE_POLICY();
6403
+ init_path_fold();
6379
6404
  }
6380
6405
  });
6381
6406
 
@@ -6442,7 +6467,10 @@ async function existingAnchor(resolved) {
6442
6467
  async function foldedPhysicalRoot(root) {
6443
6468
  const { anchor: anchor2, tail } = await existingAnchor(path2.resolve(root));
6444
6469
  const anchorSegments = anchor2.split(path2.sep).filter((segment, index2) => index2 === 0 || segment !== "");
6445
- return [...anchorSegments, ...tail].map(foldSegment).join("/");
6470
+ return [...anchorSegments, ...tail].map(foldRootSegment).join("/");
6471
+ }
6472
+ function foldRootSegment(segment) {
6473
+ return segment.normalize("NFKD").toLowerCase().toUpperCase().toLowerCase();
6446
6474
  }
6447
6475
  async function identityKey(root, rel) {
6448
6476
  const foldedRel = relSegments(rel).map(foldSegment).join("/");
@@ -12320,6 +12348,145 @@ var init_uncertain_write = __esm({
12320
12348
  }
12321
12349
  });
12322
12350
 
12351
+ // ../core/src/bundle-health/legacy-page.ts
12352
+ function isLegacyPageDoc(frontmatter) {
12353
+ return frontmatter["type"] === LEGACY_PAGE_TYPE_NAME;
12354
+ }
12355
+ var LEGACY_PAGE_TYPE_NAME, LEGACY_PAGE_MIGRATION_SCRIPT_URL, LEGACY_PAGE_MIGRATION_HELP;
12356
+ var init_legacy_page = __esm({
12357
+ "../core/src/bundle-health/legacy-page.ts"() {
12358
+ "use strict";
12359
+ init_define_SUPERBEE_BUILD_IDENTITY();
12360
+ init_define_SUPERBEE_UPDATE_POLICY();
12361
+ LEGACY_PAGE_TYPE_NAME = "Page";
12362
+ LEGACY_PAGE_MIGRATION_SCRIPT_URL = "https://github.com/Holaxis-ai/superbee/blob/v0.4.3/scripts/migrate-legacy-view-names.mjs";
12363
+ LEGACY_PAGE_MIGRATION_HELP = "to migrate existing content in place, check out tag v0.4.3, run `npm ci && npm run build` there, then run `node scripts/migrate-legacy-view-names.mjs --dir <bundle-root>` from that checkout: " + LEGACY_PAGE_MIGRATION_SCRIPT_URL;
12364
+ }
12365
+ });
12366
+
12367
+ // ../core/src/page.ts
12368
+ function resolveBridgeCapability(value) {
12369
+ return value === "bundle-read" || value === "bundle-propose" ? value : "none";
12370
+ }
12371
+ function declaredAccessValue(frontmatter) {
12372
+ return Object.hasOwn(frontmatter, "access") ? frontmatter.access : void 0;
12373
+ }
12374
+ function resolveDeclaredAccess(frontmatter) {
12375
+ return resolveBridgeCapability(declaredAccessValue(frontmatter));
12376
+ }
12377
+ function isPageTypeName(value) {
12378
+ return value === "View";
12379
+ }
12380
+ function hasSafePageSegments(value, prefix) {
12381
+ if (!value.startsWith(prefix) || value.length === prefix.length) return false;
12382
+ if (value.startsWith("/") || /[\\%?#]/.test(value)) return false;
12383
+ const segments = value.slice(prefix.length).split("/");
12384
+ return segments.every(
12385
+ (segment) => !segment.startsWith(".") && PAGE_SEGMENT.test(segment) && !segment.toLowerCase().endsWith(".md")
12386
+ );
12387
+ }
12388
+ function isRegistryIdUnder(id, prefix) {
12389
+ if (typeof id !== "string" || !hasSafePageSegments(id, prefix)) {
12390
+ return false;
12391
+ }
12392
+ try {
12393
+ assertSafeConceptId(id);
12394
+ return true;
12395
+ } catch {
12396
+ return false;
12397
+ }
12398
+ }
12399
+ function isEntryKeyUnder(entry, prefix) {
12400
+ if (typeof entry !== "string" || !hasSafePageSegments(entry, prefix)) return false;
12401
+ try {
12402
+ assertSafeBlobKey(entry);
12403
+ return true;
12404
+ } catch {
12405
+ return false;
12406
+ }
12407
+ }
12408
+ function isPageRegistryId(id) {
12409
+ return isRegistryIdUnder(id, PAGE_REGISTRY_PREFIX);
12410
+ }
12411
+ function isViewRegistryId(id) {
12412
+ return isRegistryIdUnder(id, VIEW_REGISTRY_PREFIX);
12413
+ }
12414
+ function isAnyRegistryId(id) {
12415
+ return isPageRegistryId(id) || isViewRegistryId(id);
12416
+ }
12417
+ function isPageEntryKey(entry) {
12418
+ return isEntryKeyUnder(entry, PAGE_ENTRY_PREFIX);
12419
+ }
12420
+ function isViewEntryKey(entry) {
12421
+ return isEntryKeyUnder(entry, VIEW_ENTRY_PREFIX);
12422
+ }
12423
+ function isAnyEntryKey(entry) {
12424
+ return isPageEntryKey(entry) || isViewEntryKey(entry);
12425
+ }
12426
+ function isViewEntryVersion(value) {
12427
+ return isContentVersion(value);
12428
+ }
12429
+ function parseRegistration(id, frontmatter) {
12430
+ if (!isAnyRegistryId(id) || !isPageTypeName(frontmatter.type) || !isAnyEntryKey(frontmatter.entry)) return null;
12431
+ const rawEntryVersion = Object.hasOwn(frontmatter, "entry_version") ? frontmatter.entry_version : void 0;
12432
+ if (rawEntryVersion !== void 0 && !isViewEntryVersion(rawEntryVersion)) {
12433
+ return null;
12434
+ }
12435
+ return {
12436
+ id,
12437
+ type: frontmatter.type,
12438
+ entry: frontmatter.entry,
12439
+ ...rawEntryVersion ? { entryVersion: rawEntryVersion } : {}
12440
+ };
12441
+ }
12442
+ var PAGE_REGISTRY_PREFIX, PAGE_ENTRY_PREFIX, VIEW_REGISTRY_PREFIX, VIEW_ENTRY_PREFIX, PAGE_SEGMENT;
12443
+ var init_page = __esm({
12444
+ "../core/src/page.ts"() {
12445
+ "use strict";
12446
+ init_define_SUPERBEE_BUILD_IDENTITY();
12447
+ init_define_SUPERBEE_UPDATE_POLICY();
12448
+ init_paths();
12449
+ init_version_transport();
12450
+ PAGE_REGISTRY_PREFIX = "pages-registry/";
12451
+ PAGE_ENTRY_PREFIX = "pages/";
12452
+ VIEW_REGISTRY_PREFIX = "views-registry/";
12453
+ VIEW_ENTRY_PREFIX = "views/";
12454
+ PAGE_SEGMENT = /^[A-Za-z0-9._-]+$/;
12455
+ }
12456
+ });
12457
+
12458
+ // ../core/src/system-documents.ts
12459
+ function typeOf(doc2) {
12460
+ return typeof doc2.frontmatter.type === "string" ? doc2.frontmatter.type : "";
12461
+ }
12462
+ function isGraphDefinitionDocument(doc2) {
12463
+ const type = typeOf(doc2);
12464
+ return type === CONVENTION_TYPE || isPageTypeName(type) || isLegacyPageDoc(doc2.frontmatter) || type === "Reference" && doc2.id.startsWith("references/") || type === BUNDLE_NAME_DOC_TYPE && doc2.id === BUNDLE_NAME_DOC_ID || type === DEPENDENCIES_DOC_TYPE && doc2.id === DEPENDENCIES_DOC_ID;
12465
+ }
12466
+ function isSystemDocument(doc2) {
12467
+ return isGraphDefinitionDocument(doc2) || OWNED_INSTANCE_TYPES.has(typeOf(doc2));
12468
+ }
12469
+ var OWNED_INSTANCE_TYPES, OWNED_INSTANCE_TYPE_NAMES;
12470
+ var init_system_documents = __esm({
12471
+ "../core/src/system-documents.ts"() {
12472
+ "use strict";
12473
+ init_define_SUPERBEE_BUILD_IDENTITY();
12474
+ init_define_SUPERBEE_UPDATE_POLICY();
12475
+ init_legacy_page();
12476
+ init_dependencies();
12477
+ init_kinds();
12478
+ init_page();
12479
+ OWNED_INSTANCE_TYPES = /* @__PURE__ */ new Set([
12480
+ "Connector",
12481
+ "Site",
12482
+ "Promotion",
12483
+ // An OKF standard type, validated by `okf-standard-fields.ts`.
12484
+ "Attested Computation"
12485
+ ]);
12486
+ OWNED_INSTANCE_TYPE_NAMES = [...OWNED_INSTANCE_TYPES];
12487
+ }
12488
+ });
12489
+
12323
12490
  // ../core/src/kind-undeclared-fields.ts
12324
12491
  function isKindEnvelopeField(key4) {
12325
12492
  return isOkfStandardField(key4) || isManagedDocumentMetadataField(key4) || key4.startsWith("superbee_") && key4 !== SUPERBEE_PROGRESS_STATUS_FIELD;
@@ -12340,9 +12507,51 @@ function undeclaredFieldWarnings(okfVersion, kind2, candidate, existing) {
12340
12507
  const list6 = declared.length > 0 ? declared.join(", ") : "none";
12341
12508
  const progress = progressStatusCoordinate(okfVersion, kind2);
12342
12509
  const message = (key4) => progress && key4 === progress.logicalField && key4 !== progress.storageField ? `'${key4}' is the field name, not its stored key in this bundle; write it in frontmatter as '${progress.storageField}'.` : `'${key4}' is not declared by kind '${kind2.governs}' (declared: ${list6}).`;
12343
- return undeclaredFrontmatterKeys(okfVersion, kind2, candidate).filter((key4) => !existing || !Object.hasOwn(existing, key4) || !okfValuesEqual(existing[key4], candidate[key4])).sort().map((key4) => ({ code: KIND_FIELD_UNDECLARED, message: message(key4), field: key4, severity: "warning" }));
12510
+ return undeclaredFrontmatterKeys(okfVersion, kind2, candidate).filter((key4) => !existing || !Object.hasOwn(existing, key4) || !okfValuesEqual(existing[key4], candidate[key4])).sort().map((key4) => ({
12511
+ code: KIND_FIELD_UNDECLARED,
12512
+ message: message(key4),
12513
+ field: key4,
12514
+ severity: "warning",
12515
+ details: { kind: kind2.governs, fields: [key4], declared: [...declared] }
12516
+ }));
12517
+ }
12518
+ function unknownKindFieldNames(okfVersion, kind2, fields2) {
12519
+ return [...fields2].filter((field) => resolveKindFieldCoordinate(okfVersion, kind2, field) === void 0);
12520
+ }
12521
+ function kindFieldsUndeclaredFinding(okfVersion, kind2, fields2) {
12522
+ if (fields2.length === 0) return void 0;
12523
+ return {
12524
+ code: KIND_FIELD_UNDECLARED,
12525
+ message: "The document's Kind does not declare one or more of the named fields.",
12526
+ ...fields2.length === 1 ? { field: fields2[0] } : {},
12527
+ severity: "warning",
12528
+ details: { kind: kind2.governs, fields: [...fields2], declared: kindDeclaredFieldNames(okfVersion, kind2) }
12529
+ };
12530
+ }
12531
+ function typeKey(type) {
12532
+ return type.replace(/[\s_-]+/g, "").toLowerCase();
12533
+ }
12534
+ function undeclaredTypeFinding(registry2, doc2) {
12535
+ const type = doc2.frontmatter.type;
12536
+ if (typeof type !== "string" || type.trim() === "" || registry2.kinds.size === 0) return void 0;
12537
+ if (registry2.kinds.has(type) || isSystemDocument(doc2)) return void 0;
12538
+ const declaredTypes = [...registry2.kinds.keys()].sort();
12539
+ const suggestedType = declaredTypes.find((declared) => typeKey(declared) === typeKey(type));
12540
+ return suggestedType === void 0 ? {
12541
+ code: KIND_TYPE_UNDECLARED,
12542
+ message: "No Kind in this bundle governs this document's type, so the document is not checked against a Kind.",
12543
+ field: "type",
12544
+ severity: "info",
12545
+ details: { type, declaredTypes }
12546
+ } : {
12547
+ code: KIND_TYPE_UNDECLARED,
12548
+ message: "No Kind governs this document's type, but a declared type differs from it only in case or spacing.",
12549
+ field: "type",
12550
+ severity: "warning",
12551
+ details: { type, declaredTypes, suggestedType }
12552
+ };
12344
12553
  }
12345
- var KIND_FIELD_UNDECLARED;
12554
+ var KIND_FIELD_UNDECLARED, KIND_TYPE_UNDECLARED;
12346
12555
  var init_kind_undeclared_fields = __esm({
12347
12556
  "../core/src/kind-undeclared-fields.ts"() {
12348
12557
  "use strict";
@@ -12351,8 +12560,10 @@ var init_kind_undeclared_fields = __esm({
12351
12560
  init_managed_document_metadata();
12352
12561
  init_okf_authored_values();
12353
12562
  init_okf_standard_fields();
12563
+ init_system_documents();
12354
12564
  init_kinds();
12355
12565
  KIND_FIELD_UNDECLARED = "KIND_FIELD_UNDECLARED";
12566
+ KIND_TYPE_UNDECLARED = "KIND_TYPE_UNDECLARED";
12356
12567
  }
12357
12568
  });
12358
12569
 
@@ -13203,7 +13414,7 @@ async function readSource(binding2) {
13203
13414
  const docs = new Map(results.map((result3) => [result3.doc.id, result3]));
13204
13415
  const ids = /* @__PURE__ */ new Set([...docs.keys(), ...malformed6.keys()]);
13205
13416
  const dependencies = parseDependencies(docs.get(DEPENDENCIES_DOC_ID)?.doc ?? null, { selfBundleId: binding2.identity });
13206
- const folds = new Set([...ids].map(foldIdentityPath));
13417
+ const folds = new Set([...ids].map(foldPath));
13207
13418
  return { ids, folds, docs, malformed: malformed6, dependencies, registry: await loadKinds(bundle), bundle };
13208
13419
  }
13209
13420
  async function readTarget(target3) {
@@ -13278,7 +13489,7 @@ function planLink(ctx, sourceId, targetId, span, conflicts) {
13278
13489
  const resolved = resolveConceptId(sourceId, pathPart);
13279
13490
  if (resolved === null) return keep("non_document");
13280
13491
  const present = ctx.source.ids.has(resolved);
13281
- if (!present && ctx.source.folds.has(foldIdentityPath(resolved))) return keep("case_variant", { source_target: resolved });
13492
+ if (!present && ctx.source.folds.has(foldPath(resolved))) return keep("case_variant", { source_target: resolved });
13282
13493
  const withFragment = fragment === void 0 ? {} : { fragment };
13283
13494
  const mapped = ctx.mapping.get(resolved);
13284
13495
  if (mapped !== void 0) {
@@ -13364,18 +13575,18 @@ function assertImportableTargetId(id, newTarget) {
13364
13575
  assertSafeConceptId(id);
13365
13576
  if (newTarget) assertCanonicalNewDocumentId(id, newTarget.exists);
13366
13577
  if (isReservedFile(pathFromConceptId(id))) throw new InvalidInputError("index.md and log.md are reserved files, not documents");
13367
- const fold2 = foldIdentityPath(id);
13578
+ const fold2 = foldPath(id);
13368
13579
  if (PROTECTED_TARGET_FOLDS.has(fold2)) throw new InvalidInputError("it is the bundle's own identity or dependency declaration");
13369
13580
  if (fold2.startsWith(CONVENTIONS_FOLD)) throw new InvalidInputError("an import never installs a Kind convention");
13370
13581
  }
13371
13582
  function checkTargetIds(planned, existing, conflicts) {
13372
13583
  const folds = /* @__PURE__ */ new Map();
13373
13584
  const remember = (id) => {
13374
- const keys2 = [[`${foldIdentityPath(id)}.md`, `${id}.md`]];
13585
+ const keys2 = [[`${foldPath(id)}.md`, `${id}.md`]];
13375
13586
  const segments = id.split("/");
13376
13587
  for (let i = 1; i < segments.length; i++) {
13377
13588
  const dir = segments.slice(0, i).join("/");
13378
- keys2.push([`${foldIdentityPath(dir)}/`, `${dir}/`]);
13589
+ keys2.push([`${foldPath(dir)}/`, `${dir}/`]);
13379
13590
  }
13380
13591
  return keys2;
13381
13592
  };
@@ -14251,7 +14462,7 @@ var init_document_transfer = __esm({
14251
14462
  init_document_mutation();
14252
14463
  init_engine();
14253
14464
  init_errors();
14254
- init_identity_fold();
14465
+ init_path_fold();
14255
14466
  init_kinds_load();
14256
14467
  init_kinds();
14257
14468
  init_link_emit();
@@ -14319,8 +14530,8 @@ var init_document_transfer = __esm({
14319
14530
  SOURCE_SELF_DOCS = /* @__PURE__ */ new Set([BUNDLE_NAME_DOC_ID, DEPENDENCIES_DOC_ID]);
14320
14531
  ANY_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
14321
14532
  REFERENCE_DEFINITION = /^ {0,3}\[[^\]\n]+\]:[ \t]*<?([^\s>]+)/gm;
14322
- PROTECTED_TARGET_FOLDS = new Set([BUNDLE_NAME_DOC_ID, DEPENDENCIES_DOC_ID].map(foldIdentityPath));
14323
- CONVENTIONS_FOLD = `${foldIdentityPath(CONVENTIONS_PREFIX.replace(/\/$/, ""))}/`;
14533
+ PROTECTED_TARGET_FOLDS = new Set([BUNDLE_NAME_DOC_ID, DEPENDENCIES_DOC_ID].map(foldPath));
14534
+ CONVENTIONS_FOLD = `${foldPath(CONVENTIONS_PREFIX.replace(/\/$/, ""))}/`;
14324
14535
  DOCUMENT_REFRESH_TOKEN_PREFIX = `${DOCUMENT_TRANSFER_CONTRACT}:refresh`;
14325
14536
  }
14326
14537
  });
@@ -14346,6 +14557,13 @@ function localEdgeQualifiedDeclaration(declared, sourceType) {
14346
14557
  const matched = declarationFor(declared, sourceType);
14347
14558
  return parseQualifiedKindTarget(matched.target) === null ? null : matched;
14348
14559
  }
14560
+ function localEdgeViolation(declared, sourceType, targetType) {
14561
+ if (!declared || declared.length === 0) return null;
14562
+ const matched = declarationFor(declared, sourceType);
14563
+ const sourceOk = declared.some((d) => d.governs === sourceType);
14564
+ const targetOk = targetType === void 0 || targetType === matched.target;
14565
+ return sourceOk && targetOk ? null : matched;
14566
+ }
14349
14567
  function qualifiedEdgeViolation(declared, sourceType, alias, actualTargetType) {
14350
14568
  if (!declared || declared.length === 0) return null;
14351
14569
  const matched = declarationFor(declared, sourceType);
@@ -14363,6 +14581,222 @@ var init_link_types = __esm({
14363
14581
  }
14364
14582
  });
14365
14583
 
14584
+ // ../core/src/link-findings.ts
14585
+ function docType(doc2) {
14586
+ return typeof doc2?.frontmatter.type === "string" ? doc2.frontmatter.type : "";
14587
+ }
14588
+ function hrefPath(href) {
14589
+ return (href.split("#")[0] ?? "").split("?")[0]?.trim() ?? "";
14590
+ }
14591
+ function suggestion(fromId, href) {
14592
+ if (UNREGISTRABLE.test(href)) return {};
14593
+ const suggestedTo = resolveConceptId(fromId, href);
14594
+ if (suggestedTo === null) return {};
14595
+ if (!href.startsWith("/")) {
14596
+ const slash = fromId.lastIndexOf("/");
14597
+ const fromDir = slash >= 0 ? fromId.slice(0, slash) : "";
14598
+ if (normalizeSegments([...fromDir.split("/"), ...hrefPath(href).split("/")])[0] === "..") {
14599
+ return { suggestedHref: `/${suggestedTo}.md`, suggestedTo };
14600
+ }
14601
+ }
14602
+ return { suggestedHref: href, suggestedTo };
14603
+ }
14604
+ function isBareRelative(path81) {
14605
+ return !path81.startsWith("/") && !path81.startsWith("./") && !path81.startsWith("../");
14606
+ }
14607
+ function notRecognized(reason, fields2) {
14608
+ return {
14609
+ code: LINK_NOT_RECOGNIZED,
14610
+ message: NOT_RECOGNIZED_MESSAGES[reason],
14611
+ field: "body",
14612
+ severity: "warning",
14613
+ details: { reason, ...fields2 }
14614
+ };
14615
+ }
14616
+ function classifyUnresolved(fromId, text7, href, at) {
14617
+ if (isQualifiedHref(href)) return void 0;
14618
+ const path81 = hrefPath(href);
14619
+ if (path81 === "" || isExternalHref(path81) || ANY_SCHEME2.test(path81)) return void 0;
14620
+ if (path81.endsWith(".md")) {
14621
+ const resolved = path81.startsWith("/") ? path81.slice(1) : path81;
14622
+ return notRecognized(isReservedFile(resolved.replace(/^(\.\.?\/)+/, "")) ? "reserved-target" : "invalid-target", { text: text7, href, ...at });
14623
+ }
14624
+ const last = path81.slice(path81.lastIndexOf("/") + 1);
14625
+ if (last === "" || last.includes(".")) return void 0;
14626
+ return notRecognized("missing-md-extension", { text: text7, href, ...at, ...suggestion(fromId, `${path81}.md`) });
14627
+ }
14628
+ function wikilinkFindings(doc2) {
14629
+ const masked = maskMarkdownCode(doc2.body);
14630
+ const out = [];
14631
+ for (const match of masked.matchAll(WIKILINK)) {
14632
+ const start = match.index;
14633
+ const end = start + match[0].length;
14634
+ const inner = doc2.body.slice(start + 2, end - 2);
14635
+ const bar = inner.indexOf("|");
14636
+ const target3 = (bar >= 0 ? inner.slice(0, bar) : inner).trim();
14637
+ const text7 = (bar >= 0 ? inner.slice(bar + 1) : inner).trim();
14638
+ const path81 = hrefPath(target3).replace(/^\/+/, "");
14639
+ out.push(notRecognized("wikilink", {
14640
+ text: text7,
14641
+ href: target3,
14642
+ start,
14643
+ end,
14644
+ ...path81 === "" ? {} : suggestion(doc2.id, `/${path81.endsWith(".md") ? path81 : `${path81}.md`}`)
14645
+ }));
14646
+ }
14647
+ return out;
14648
+ }
14649
+ function inspectDocumentLinks(doc2) {
14650
+ const links = [];
14651
+ const findings = [];
14652
+ const outsideCode = new Set(extractMarkdownLinkSpans(doc2.body, { skipCode: true }).map((span) => span.start));
14653
+ for (const span of extractMarkdownLinkSpans(doc2.body)) {
14654
+ if (span.image) continue;
14655
+ const to = resolveConceptId(doc2.id, span.href);
14656
+ if (to !== null) {
14657
+ links.push({ from: doc2.id, to, text: span.text, href: span.href });
14658
+ continue;
14659
+ }
14660
+ if (!outsideCode.has(span.start)) continue;
14661
+ const finding = classifyUnresolved(doc2.id, span.text, span.href, { start: span.start, end: span.end });
14662
+ if (finding) findings.push(finding);
14663
+ }
14664
+ findings.push(...wikilinkFindings(doc2));
14665
+ findings.sort((a, b) => (a.details.start ?? 0) - (b.details.start ?? 0));
14666
+ return { links, findings };
14667
+ }
14668
+ async function linkTargetAbsentFinding(link4, readTarget2) {
14669
+ if (await readTarget2(link4.to) !== void 0) return void 0;
14670
+ return { code: LINK_TARGET_ABSENT, message: TARGET_ABSENT_MESSAGE, field: "body", severity: "warning", details: { ...link4 } };
14671
+ }
14672
+ async function typeFinding(declarations, link4, readTarget2) {
14673
+ if (declarations.size === 0) return void 0;
14674
+ const { sourceType, ...where } = link4;
14675
+ const exact = declarations.get(link4.text);
14676
+ if (exact && exact.length > 0) {
14677
+ const target3 = await readTarget2(link4.to);
14678
+ const targetType = target3 === void 0 ? null : docType(target3);
14679
+ const qualified = localEdgeQualifiedDeclaration(exact, sourceType);
14680
+ if (qualified) {
14681
+ return {
14682
+ code: LINK_TYPE_VIOLATION,
14683
+ message: TYPE_QUALIFIED_MESSAGE,
14684
+ field: "body",
14685
+ severity: "warning",
14686
+ details: {
14687
+ ...where,
14688
+ declaredBy: qualified.governs,
14689
+ declaredTarget: qualified.target,
14690
+ sourceType,
14691
+ targetType,
14692
+ targetAlias: parseQualifiedKindTarget(qualified.target).alias
14693
+ }
14694
+ };
14695
+ }
14696
+ const violated = localEdgeViolation(exact, sourceType, targetType ?? void 0);
14697
+ if (!violated) return void 0;
14698
+ return {
14699
+ code: LINK_TYPE_VIOLATION,
14700
+ message: TYPE_VIOLATION_MESSAGE,
14701
+ field: "body",
14702
+ severity: "warning",
14703
+ details: { ...where, declaredBy: violated.governs, declaredTarget: violated.target, sourceType, targetType }
14704
+ };
14705
+ }
14706
+ const lower = link4.text.toLowerCase();
14707
+ for (const declaredText of declarations.keys()) {
14708
+ if (declaredText.toLowerCase() === lower) {
14709
+ return {
14710
+ code: LINK_TYPE_CASE_VARIANT,
14711
+ message: TYPE_CASE_VARIANT_MESSAGE,
14712
+ field: "body",
14713
+ severity: "warning",
14714
+ details: { ...where, declaredText }
14715
+ };
14716
+ }
14717
+ }
14718
+ return void 0;
14719
+ }
14720
+ function linkTypeFinding(registry2, link4, readTarget2) {
14721
+ return typeFinding(collectLinkDeclarations(registry2), link4, readTarget2);
14722
+ }
14723
+ async function documentLinkReport(doc2, opts) {
14724
+ const { links, findings } = inspectDocumentLinks(doc2);
14725
+ const cache = /* @__PURE__ */ new Map();
14726
+ const read = (id) => {
14727
+ let pending = cache.get(id);
14728
+ if (!pending) {
14729
+ pending = opts.readTarget(id);
14730
+ cache.set(id, pending);
14731
+ }
14732
+ return pending;
14733
+ };
14734
+ const exists3 = async (id) => await read(id) !== void 0;
14735
+ const rootReading = (path81) => isBareRelative(path81) ? resolveConceptId(doc2.id, `/${path81}`) : null;
14736
+ for (const finding of findings) {
14737
+ if (finding.code !== LINK_NOT_RECOGNIZED || finding.details.reason !== "missing-md-extension") continue;
14738
+ const relative2 = finding.details.suggestedTo;
14739
+ if (relative2 !== void 0 && await exists3(relative2)) continue;
14740
+ const path81 = `${hrefPath(finding.details.href)}.md`;
14741
+ const root = rootReading(path81);
14742
+ if (root !== null && root !== relative2 && !UNREGISTRABLE.test(path81) && await exists3(root)) {
14743
+ finding.details.suggestedHref = `/${path81}`;
14744
+ finding.details.suggestedTo = root;
14745
+ }
14746
+ }
14747
+ const declarations = opts.registry ? collectLinkDeclarations(opts.registry) : /* @__PURE__ */ new Map();
14748
+ const sourceType = docType(doc2);
14749
+ const spans = extractMarkdownLinkSpans(doc2.body).filter((span) => !span.image && resolveConceptId(doc2.id, span.href) !== null);
14750
+ for (const [index2, link4] of links.entries()) {
14751
+ if (isQualifiedHref(link4.href)) continue;
14752
+ const span = spans[index2];
14753
+ const where = { start: span.start, end: span.end };
14754
+ const absent = await linkTargetAbsentFinding({ to: link4.to, href: link4.href, text: link4.text, ...where }, read);
14755
+ if (absent) {
14756
+ const path81 = hrefPath(link4.href);
14757
+ const root = rootReading(path81);
14758
+ if (root !== null && root !== link4.to && await exists3(root)) {
14759
+ absent.details.suggestedHref = `/${path81}`;
14760
+ absent.details.suggestedTo = root;
14761
+ }
14762
+ findings.push(absent);
14763
+ }
14764
+ const typed = await typeFinding(declarations, { sourceType, text: link4.text, to: link4.to, ...where }, read);
14765
+ if (typed) findings.push(typed);
14766
+ }
14767
+ findings.sort((a, b) => (a.details.start ?? 0) - (b.details.start ?? 0));
14768
+ return { links, findings };
14769
+ }
14770
+ var LINK_NOT_RECOGNIZED, LINK_TARGET_ABSENT, LINK_TYPE_VIOLATION, LINK_TYPE_CASE_VARIANT, NOT_RECOGNIZED_MESSAGES, TARGET_ABSENT_MESSAGE, TYPE_VIOLATION_MESSAGE, TYPE_QUALIFIED_MESSAGE, TYPE_CASE_VARIANT_MESSAGE, WIKILINK, ANY_SCHEME2, UNREGISTRABLE;
14771
+ var init_link_findings = __esm({
14772
+ "../core/src/link-findings.ts"() {
14773
+ "use strict";
14774
+ init_define_SUPERBEE_BUILD_IDENTITY();
14775
+ init_define_SUPERBEE_UPDATE_POLICY();
14776
+ init_link_types();
14777
+ init_links();
14778
+ init_paths();
14779
+ init_qualified_links();
14780
+ LINK_NOT_RECOGNIZED = "LINK_NOT_RECOGNIZED";
14781
+ LINK_TARGET_ABSENT = "LINK_TARGET_ABSENT";
14782
+ LINK_TYPE_VIOLATION = "LINK_TYPE_VIOLATION";
14783
+ LINK_TYPE_CASE_VARIANT = "LINK_TYPE_CASE_VARIANT";
14784
+ NOT_RECOGNIZED_MESSAGES = {
14785
+ wikilink: "A [[wikilink]] is plain text, not a link; write a markdown link whose target ends in .md.",
14786
+ "missing-md-extension": "This link's target does not end in .md, so it is not a link to a document.",
14787
+ "reserved-target": "This link's target is a reserved file (index.md or log.md), which is never a document.",
14788
+ "invalid-target": "This link's target is not a valid document id, so it is not a link to a document."
14789
+ };
14790
+ TARGET_ABSENT_MESSAGE = "No document exists at this link's target yet; the link is kept as a forward declaration.";
14791
+ TYPE_VIOLATION_MESSAGE = "This link's text is a declared link type, but its source or target is not the declared kind.";
14792
+ TYPE_QUALIFIED_MESSAGE = "This link's text is declared as a link into another bundle, but it points inside this bundle.";
14793
+ TYPE_CASE_VARIANT_MESSAGE = "This link's text differs only in case from a declared link type.";
14794
+ WIKILINK = /\[\[([^[\]\n]+)\]\]/g;
14795
+ ANY_SCHEME2 = /^[a-z][a-z0-9+.-]*:/i;
14796
+ UNREGISTRABLE = /[\s()<>[\]]/;
14797
+ }
14798
+ });
14799
+
14366
14800
  // ../core/src/cross-bundle.ts
14367
14801
  function isRecordReason(reason) {
14368
14802
  return RECORD_REASONS.includes(reason);
@@ -14538,18 +14972,6 @@ var init_code_point_order = __esm({
14538
14972
  }
14539
14973
  });
14540
14974
 
14541
- // ../core/src/path-fold.ts
14542
- function foldPath(path81) {
14543
- return path81.normalize("NFC").toLowerCase().toUpperCase().toLowerCase().normalize("NFC");
14544
- }
14545
- var init_path_fold = __esm({
14546
- "../core/src/path-fold.ts"() {
14547
- "use strict";
14548
- init_define_SUPERBEE_BUILD_IDENTITY();
14549
- init_define_SUPERBEE_UPDATE_POLICY();
14550
- }
14551
- });
14552
-
14553
14975
  // ../core/src/governed-body-write.ts
14554
14976
  function fail2(message) {
14555
14977
  throw new Error(`Invalid body delivery: ${message}`);
@@ -15036,8 +15458,13 @@ __export(src_exports, {
15036
15458
  KIND_FIELD_TYPES: () => KIND_FIELD_TYPES,
15037
15459
  KIND_FIELD_TYPE_DESCRIPTIONS: () => KIND_FIELD_TYPE_DESCRIPTIONS,
15038
15460
  KIND_FIELD_UNDECLARED: () => KIND_FIELD_UNDECLARED,
15461
+ KIND_TYPE_UNDECLARED: () => KIND_TYPE_UNDECLARED,
15039
15462
  KindConformanceError: () => KindConformanceError,
15040
15463
  KindFieldMutationConflict: () => KindFieldMutationConflict,
15464
+ LINK_NOT_RECOGNIZED: () => LINK_NOT_RECOGNIZED,
15465
+ LINK_TARGET_ABSENT: () => LINK_TARGET_ABSENT,
15466
+ LINK_TYPE_CASE_VARIANT: () => LINK_TYPE_CASE_VARIANT,
15467
+ LINK_TYPE_VIOLATION: () => LINK_TYPE_VIOLATION,
15041
15468
  MALFORMED_ANSWER: () => MALFORMED_ANSWER,
15042
15469
  MalformedAnswer: () => MalformedAnswer,
15043
15470
  MalformedDocumentError: () => MalformedDocumentError,
@@ -15114,6 +15541,7 @@ __export(src_exports, {
15114
15541
  deleteBlob: () => deleteBlob2,
15115
15542
  deleteDoc: () => deleteDoc2,
15116
15543
  docVersions: () => docVersions2,
15544
+ documentLinkReport: () => documentLinkReport,
15117
15545
  droppedLinks: () => droppedLinks,
15118
15546
  emitLinkHref: () => emitLinkHref,
15119
15547
  escapeHostJson: () => escapeHostJson,
@@ -15134,6 +15562,7 @@ __export(src_exports, {
15134
15562
  inferContentTypeForNewBlob: () => inferContentTypeForNewBlob,
15135
15563
  inferContentTypeFromDocKey: () => inferContentTypeFromDocKey,
15136
15564
  initBundle: () => initBundle,
15565
+ inspectDocumentLinks: () => inspectDocumentLinks,
15137
15566
  inspectKindDeprecatedUsage: () => inspectKindDeprecatedUsage,
15138
15567
  invalidLegacyTimestamp: () => invalidLegacyTimestamp,
15139
15568
  invalidOkfTimestamps: () => invalidOkfTimestamps,
@@ -15142,6 +15571,7 @@ __export(src_exports, {
15142
15571
  isContentVersion: () => isContentVersion,
15143
15572
  isConventionId: () => isConventionId,
15144
15573
  isExternalHref: () => isExternalHref,
15574
+ isGraphDefinitionDocument: () => isGraphDefinitionDocument,
15145
15575
  isHeadsDigest: () => isHeadsDigest,
15146
15576
  isHostedBundleId: () => isHostedBundleId,
15147
15577
  isHumanActor: () => isHumanActor,
@@ -15161,6 +15591,7 @@ __export(src_exports, {
15161
15591
  isRecordReason: () => isRecordReason,
15162
15592
  isReservedFile: () => isReservedFile,
15163
15593
  isStandardDocumentSetField: () => isStandardDocumentSetField,
15594
+ isSystemDocument: () => isSystemDocument,
15164
15595
  isTerminal: () => isTerminal,
15165
15596
  isUsableTimestamp: () => isUsableTimestamp,
15166
15597
  kindConventionDoc: () => kindConventionDoc,
@@ -15171,14 +15602,18 @@ __export(src_exports, {
15171
15602
  kindDeprecationTransition: () => kindDeprecationTransition,
15172
15603
  kindFieldInputValue: () => kindFieldInputValue,
15173
15604
  kindFieldTypeProblem: () => kindFieldTypeProblem,
15605
+ kindFieldsUndeclaredFinding: () => kindFieldsUndeclaredFinding,
15174
15606
  kindInputFieldNames: () => kindInputFieldNames,
15175
15607
  kindValueGuidance: () => kindValueGuidance,
15176
15608
  latestVerifiedAt: () => latestVerifiedAt,
15609
+ linkTargetAbsentFinding: () => linkTargetAbsentFinding,
15610
+ linkTypeFinding: () => linkTypeFinding,
15177
15611
  list: () => list,
15178
15612
  listBlobs: () => listBlobs2,
15179
15613
  loadBoundedYaml: () => loadBoundedYaml,
15180
15614
  loadKinds: () => loadKinds,
15181
15615
  localEdgeQualifiedDeclaration: () => localEdgeQualifiedDeclaration,
15616
+ localEdgeViolation: () => localEdgeViolation,
15182
15617
  matchesFilter: () => matchesFilter,
15183
15618
  matchesSourceIdentity: () => matchesSourceIdentity,
15184
15619
  mutateDocument: () => mutateDocument,
@@ -15252,6 +15687,8 @@ __export(src_exports, {
15252
15687
  trustTierCounts: () => trustTierCounts,
15253
15688
  undeclaredFieldWarnings: () => undeclaredFieldWarnings,
15254
15689
  undeclaredFrontmatterKeys: () => undeclaredFrontmatterKeys,
15690
+ undeclaredTypeFinding: () => undeclaredTypeFinding,
15691
+ unknownKindFieldNames: () => unknownKindFieldNames,
15255
15692
  validateAgainstKind: () => validateAgainstKind,
15256
15693
  validateBodyReceipt: () => validateBodyReceipt,
15257
15694
  validatePreparedBodyDelivery: () => validatePreparedBodyDelivery,
@@ -15302,6 +15739,7 @@ var init_src = __esm({
15302
15739
  init_document_transfer();
15303
15740
  init_qualified_links();
15304
15741
  init_link_types();
15742
+ init_link_findings();
15305
15743
  init_dependencies();
15306
15744
  init_cross_bundle();
15307
15745
  init_freshness();
@@ -15327,6 +15765,7 @@ var init_src = __esm({
15327
15765
  init_managed_document_metadata();
15328
15766
  init_kind_coverage();
15329
15767
  init_kind_undeclared_fields();
15768
+ init_system_documents();
15330
15769
  init_body_pages();
15331
15770
  init_body_replace_guards();
15332
15771
  init_kind_deprecation();
@@ -18448,22 +18887,6 @@ var init_nofollow_read = __esm({
18448
18887
  }
18449
18888
  });
18450
18889
 
18451
- // ../core/src/bundle-health/legacy-page.ts
18452
- function isLegacyPageDoc(frontmatter) {
18453
- return frontmatter["type"] === LEGACY_PAGE_TYPE_NAME;
18454
- }
18455
- var LEGACY_PAGE_TYPE_NAME, LEGACY_PAGE_MIGRATION_SCRIPT_URL, LEGACY_PAGE_MIGRATION_HELP;
18456
- var init_legacy_page = __esm({
18457
- "../core/src/bundle-health/legacy-page.ts"() {
18458
- "use strict";
18459
- init_define_SUPERBEE_BUILD_IDENTITY();
18460
- init_define_SUPERBEE_UPDATE_POLICY();
18461
- LEGACY_PAGE_TYPE_NAME = "Page";
18462
- LEGACY_PAGE_MIGRATION_SCRIPT_URL = "https://github.com/Holaxis-ai/superbee/blob/v0.4.3/scripts/migrate-legacy-view-names.mjs";
18463
- LEGACY_PAGE_MIGRATION_HELP = "to migrate existing content in place, check out tag v0.4.3, run `npm ci && npm run build` there, then run `node scripts/migrate-legacy-view-names.mjs --dir <bundle-root>` from that checkout: " + LEGACY_PAGE_MIGRATION_SCRIPT_URL;
18464
- }
18465
- });
18466
-
18467
18890
  // ../../node_modules/graphql/jsutils/devAssert.mjs
18468
18891
  function devAssert(condition, message) {
18469
18892
  if (!condition) {
@@ -22575,97 +22998,6 @@ var init_connectors = __esm({
22575
22998
  }
22576
22999
  });
22577
23000
 
22578
- // ../core/src/page.ts
22579
- function resolveBridgeCapability(value) {
22580
- return value === "bundle-read" || value === "bundle-propose" ? value : "none";
22581
- }
22582
- function declaredAccessValue(frontmatter) {
22583
- return Object.hasOwn(frontmatter, "access") ? frontmatter.access : void 0;
22584
- }
22585
- function resolveDeclaredAccess(frontmatter) {
22586
- return resolveBridgeCapability(declaredAccessValue(frontmatter));
22587
- }
22588
- function isPageTypeName(value) {
22589
- return value === "View";
22590
- }
22591
- function hasSafePageSegments(value, prefix) {
22592
- if (!value.startsWith(prefix) || value.length === prefix.length) return false;
22593
- if (value.startsWith("/") || /[\\%?#]/.test(value)) return false;
22594
- const segments = value.slice(prefix.length).split("/");
22595
- return segments.every(
22596
- (segment) => !segment.startsWith(".") && PAGE_SEGMENT.test(segment) && !segment.toLowerCase().endsWith(".md")
22597
- );
22598
- }
22599
- function isRegistryIdUnder(id, prefix) {
22600
- if (typeof id !== "string" || !hasSafePageSegments(id, prefix)) {
22601
- return false;
22602
- }
22603
- try {
22604
- assertSafeConceptId(id);
22605
- return true;
22606
- } catch {
22607
- return false;
22608
- }
22609
- }
22610
- function isEntryKeyUnder(entry, prefix) {
22611
- if (typeof entry !== "string" || !hasSafePageSegments(entry, prefix)) return false;
22612
- try {
22613
- assertSafeBlobKey(entry);
22614
- return true;
22615
- } catch {
22616
- return false;
22617
- }
22618
- }
22619
- function isPageRegistryId(id) {
22620
- return isRegistryIdUnder(id, PAGE_REGISTRY_PREFIX);
22621
- }
22622
- function isViewRegistryId(id) {
22623
- return isRegistryIdUnder(id, VIEW_REGISTRY_PREFIX);
22624
- }
22625
- function isAnyRegistryId(id) {
22626
- return isPageRegistryId(id) || isViewRegistryId(id);
22627
- }
22628
- function isPageEntryKey(entry) {
22629
- return isEntryKeyUnder(entry, PAGE_ENTRY_PREFIX);
22630
- }
22631
- function isViewEntryKey(entry) {
22632
- return isEntryKeyUnder(entry, VIEW_ENTRY_PREFIX);
22633
- }
22634
- function isAnyEntryKey(entry) {
22635
- return isPageEntryKey(entry) || isViewEntryKey(entry);
22636
- }
22637
- function isViewEntryVersion(value) {
22638
- return isContentVersion(value);
22639
- }
22640
- function parseRegistration(id, frontmatter) {
22641
- if (!isAnyRegistryId(id) || !isPageTypeName(frontmatter.type) || !isAnyEntryKey(frontmatter.entry)) return null;
22642
- const rawEntryVersion = Object.hasOwn(frontmatter, "entry_version") ? frontmatter.entry_version : void 0;
22643
- if (rawEntryVersion !== void 0 && !isViewEntryVersion(rawEntryVersion)) {
22644
- return null;
22645
- }
22646
- return {
22647
- id,
22648
- type: frontmatter.type,
22649
- entry: frontmatter.entry,
22650
- ...rawEntryVersion ? { entryVersion: rawEntryVersion } : {}
22651
- };
22652
- }
22653
- var PAGE_REGISTRY_PREFIX, PAGE_ENTRY_PREFIX, VIEW_REGISTRY_PREFIX, VIEW_ENTRY_PREFIX, PAGE_SEGMENT;
22654
- var init_page = __esm({
22655
- "../core/src/page.ts"() {
22656
- "use strict";
22657
- init_define_SUPERBEE_BUILD_IDENTITY();
22658
- init_define_SUPERBEE_UPDATE_POLICY();
22659
- init_paths();
22660
- init_version_transport();
22661
- PAGE_REGISTRY_PREFIX = "pages-registry/";
22662
- PAGE_ENTRY_PREFIX = "pages/";
22663
- VIEW_REGISTRY_PREFIX = "views-registry/";
22664
- VIEW_ENTRY_PREFIX = "views/";
22665
- PAGE_SEGMENT = /^[A-Za-z0-9._-]+$/;
22666
- }
22667
- });
22668
-
22669
23001
  // ../core/src/recipes.ts
22670
23002
  function nonEmptyString2(v) {
22671
23003
  return typeof v === "string" ? v.trim() : "";
@@ -24258,7 +24590,7 @@ function linkTypeAdditionBlockers(docs, addedTexts, currentRegistry, registry2,
24258
24590
  const declarations = collectLinkDeclarations(registry2);
24259
24591
  const currentDeclarations = collectLinkDeclarations(currentRegistry);
24260
24592
  const docsById = new Map(docs.map((doc2) => [doc2.id, doc2]));
24261
- const docType3 = (doc2) => typeof doc2.frontmatter.type === "string" ? doc2.frontmatter.type : "";
24593
+ const docType4 = (doc2) => typeof doc2.frontmatter.type === "string" ? doc2.frontmatter.type : "";
24262
24594
  const checked = [];
24263
24595
  for (const doc2 of docs) {
24264
24596
  let carries = false;
@@ -24267,11 +24599,11 @@ function linkTypeAdditionBlockers(docs, addedTexts, currentRegistry, registry2,
24267
24599
  carries = true;
24268
24600
  const target3 = docsById.get(link4.to);
24269
24601
  if (!target3) continue;
24270
- const sourceType = docType3(doc2);
24602
+ const sourceType = docType4(doc2);
24271
24603
  const violates = (declared) => {
24272
24604
  if (declared.length === 0) return null;
24273
24605
  const matched = declared.find((declaration) => declaration.governs === sourceType);
24274
- return matched && docType3(target3) === matched.target ? null : matched ?? declared[0];
24606
+ return matched && docType4(target3) === matched.target ? null : matched ?? declared[0];
24275
24607
  };
24276
24608
  const expected = violates(declarations.get(link4.text) ?? []);
24277
24609
  if (!expected) continue;
@@ -24280,7 +24612,7 @@ function linkTypeAdditionBlockers(docs, addedTexts, currentRegistry, registry2,
24280
24612
  blockers,
24281
24613
  "RECIPE_EVOLUTION_INSTANCE_INVALID",
24282
24614
  doc2.id,
24283
- `declaring link type '${link4.text}' would make the edge to '${link4.to}' a violation (expected ${expected.governs} -> ${expected.target}, found ${sourceType || "untyped"} -> ${docType3(target3) || "untyped"})`,
24615
+ `declaring link type '${link4.text}' would make the edge to '${link4.to}' a violation (expected ${expected.governs} -> ${expected.target}, found ${sourceType || "untyped"} -> ${docType4(target3) || "untyped"})`,
24284
24616
  `links.${link4.text}`
24285
24617
  );
24286
24618
  }
@@ -26063,15 +26395,15 @@ var init_recipe_lifecycle = __esm({
26063
26395
 
26064
26396
  // ../cli/src/actor-guidance.ts
26065
26397
  function actorRefusal(actor, options = {}) {
26066
- const suggestion = suggestOkfActor(actor);
26067
- let options_ = [suggestion.primary, ...suggestion.alternatives];
26398
+ const suggestion2 = suggestOkfActor(actor);
26399
+ let options_ = [suggestion2.primary, ...suggestion2.alternatives];
26068
26400
  if (options.preferHuman) {
26069
26401
  const human = options_.find((candidate) => candidate.startsWith("human:"));
26070
26402
  if (human) options_ = [human, ...options_.filter((candidate) => candidate !== human)];
26071
26403
  }
26072
26404
  const spelled = options_.length > 1 ? `${options_.slice(0, -1).join(", ")} or ${options_[options_.length - 1]}` : options_[0];
26073
26405
  const message = `actor '${actor}' is not an OKF actor, so this v0.2 bundle refuses to record it as provenance. Use ${spelled} \u2014 ${OKF_ACTOR_FORMS}.`;
26074
- if (suggestion.placeholder) {
26406
+ if (suggestion2.placeholder) {
26075
26407
  return {
26076
26408
  message,
26077
26409
  help: `rerun with --actor ${commandLiteral("<actor>")} in one of those forms, or set it once: export SUPERBEE_ACTOR=${commandLiteral("<actor>")}`
@@ -28631,22 +28963,51 @@ function definitionFindingsText(details) {
28631
28963
  }
28632
28964
  return more && text7 !== "" ? `${text7}; and more` : text7;
28633
28965
  }
28966
+ function listOf(value, item) {
28967
+ if (!Array.isArray(value)) return void 0;
28968
+ const items = value.flatMap((entry) => {
28969
+ const read = isRecord8(entry) ? item(entry) : void 0;
28970
+ return read === void 0 ? [] : [read];
28971
+ });
28972
+ return items;
28973
+ }
28974
+ function writeLinks(value) {
28975
+ if (!isRecord8(value) || !Number.isSafeInteger(value.count) || value.count < 0 || !Array.isArray(value.targets) || !value.targets.every(isText)) return void 0;
28976
+ if (value.truncated !== void 0 && typeof value.truncated !== "boolean") return void 0;
28977
+ return { count: value.count, targets: [...value.targets], ...value.truncated !== void 0 ? { truncated: value.truncated } : {} };
28978
+ }
28979
+ function writeReport(data) {
28980
+ const links = writeLinks(data.links);
28981
+ const warnings = listOf(data.warnings, writeWarning);
28982
+ const guidance = listOf(data.guidance, writeGuidance2);
28983
+ return { ...links ? { links } : {}, ...warnings?.length ? { warnings } : {}, ...guidance?.length ? { guidance } : {} };
28984
+ }
28634
28985
  function parseWriteResult(raw, expected) {
28635
28986
  const refuse3 = () => new HostedAnswerError("the write result envelope is not one the client admits");
28636
- if (!isRecord8(raw) || !onlyKeys2(raw, ["ok", "operationId", "data", "error"]) || typeof raw.operationId !== "string" || !expected.operationIds.includes(raw.operationId)) throw refuse3();
28987
+ if (!isRecord8(raw) || typeof raw.operationId !== "string" || !expected.operationIds.includes(raw.operationId)) throw refuse3();
28637
28988
  const { operationId } = raw;
28638
28989
  if (raw.ok === true) {
28639
28990
  const data = raw.data;
28640
28991
  const deletion = operationId === DELETE_OPERATION_ID;
28641
- if (raw.error !== void 0 || !isRecord8(data) || !onlyKeys2(data, deletion ? DELETE_DATA_KEYS : DATA_KEYS) || typeof data.bundleId !== "string" || data.bundleId.length === 0 || data.documentId !== expected.documentId || expected.bundleId !== void 0 && data.bundleId !== expected.bundleId || !isContentVersion(data.version) || typeof data.changed !== "boolean" || deletion && (!isContentVersion(data.deletedVersion) || data.deleted !== true)) throw refuse3();
28642
- const accepted = data;
28643
- return { ok: true, operationId, data: { ...accepted } };
28992
+ if (raw.error !== void 0 || !isRecord8(data) || typeof data.bundleId !== "string" || data.bundleId.length === 0 || data.documentId !== expected.documentId || expected.bundleId !== void 0 && data.bundleId !== expected.bundleId || !isContentVersion(data.version) || typeof data.changed !== "boolean" || (deletion ? !isContentVersion(data.deletedVersion) || data.deleted !== true : data.deletedVersion !== void 0 || data.deleted !== void 0)) throw refuse3();
28993
+ const accepted = pick(data, deletion ? DELETE_DATA_KEYS : DATA_KEYS);
28994
+ return { ok: true, operationId, data: { ...accepted, ...writeReport(data) } };
28644
28995
  }
28645
28996
  if (raw.ok !== false) throw refuse3();
28646
28997
  const error62 = raw.error;
28647
- if (raw.data !== void 0 || !isRecord8(error62) || !onlyKeys2(error62, ERROR_KEYS) || !WRITE_ERROR_CODES.includes(error62.code) || typeof error62.message !== "string" || error62.retryable !== false || error62.writeState !== "not_applied" && error62.writeState !== "unknown" || error62.currentVersion !== void 0 && !isContentVersion(error62.currentVersion) || error62.code === "write_outcome_unknown" && error62.writeState !== "unknown" || (error62.code === "request_capacity" ? error62.scope !== "principal" && error62.scope !== "bundle" || error62.writeState !== "not_applied" || error62.resetAt !== void 0 && (typeof error62.resetAt !== "string" || !Number.isFinite(Date.parse(error62.resetAt))) : error62.scope !== void 0 || error62.resetAt !== void 0) || (error62.code === "deletions_held" ? operationId !== DELETE_OPERATION_ID || error62.writeState !== "not_applied" || !count3(error62.deletions) || !count3(error62.baseline) : error62.deletions !== void 0 || error62.baseline !== void 0) || // A model-change refusal says nothing was applied; its findings ride on it alone.
28998
+ if (raw.data !== void 0 || !isRecord8(error62) || !WRITE_ERROR_CODES.includes(error62.code) || typeof error62.message !== "string" || error62.retryable !== false || error62.writeState !== "not_applied" && error62.writeState !== "unknown" || error62.currentVersion !== void 0 && !isContentVersion(error62.currentVersion) || error62.code === "write_outcome_unknown" && error62.writeState !== "unknown" || (error62.code === "request_capacity" ? error62.scope !== "principal" && error62.scope !== "bundle" || error62.writeState !== "not_applied" || error62.resetAt !== void 0 && (typeof error62.resetAt !== "string" || !Number.isFinite(Date.parse(error62.resetAt))) : error62.scope !== void 0 || error62.resetAt !== void 0) || (error62.code === "deletions_held" ? operationId !== DELETE_OPERATION_ID || error62.writeState !== "not_applied" || !count3(error62.deletions) || !count3(error62.baseline) : error62.deletions !== void 0 || error62.baseline !== void 0) || // A model-change refusal says nothing was applied; its findings ride on it alone.
28648
28999
  error62.code === "definition_incompatible" && error62.writeState !== "not_applied" || error62.definitionDetails !== void 0 && error62.code !== "definition_incompatible") throw refuse3();
28649
- return { ok: false, operationId, error: { ...error62 } };
29000
+ const diagnostics = writeDiagnostics(error62.diagnostics);
29001
+ const inputIssues = listOf(error62.inputIssues, inputIssue);
29002
+ return {
29003
+ ok: false,
29004
+ operationId,
29005
+ error: {
29006
+ ...pick(error62, ERROR_KEYS),
29007
+ ...diagnostics ? { diagnostics } : {},
29008
+ ...inputIssues?.length ? { inputIssues } : {}
29009
+ }
29010
+ };
28650
29011
  }
28651
29012
  function updateRow(answer2) {
28652
29013
  const row5 = rowsByAnswer.get(answer2);
@@ -28772,7 +29133,7 @@ function decodeBlobOutcomeAnswer(value, expected) {
28772
29133
  if (value.status === "refused" && !result3.ok && result3.error.writeState === "not_applied") return { status: "refused", result: result3 };
28773
29134
  throw malformed6();
28774
29135
  }
28775
- var CAPACITY_REFUSAL_CODES, DELETIONS_HELD_REFUSAL_CODE, UPDATE_ANSWER_ROWS, OUTCOME_ANSWER_ROWS, READ_ANSWER_ROWS, WRITE_ERROR_CODES, DELETE_OPERATION_ID, FINDING_IDS_SHOWN, DEFINITION_FINDINGS_TEXT_BYTES, findingText, HostedAnswerError, isRecord8, onlyKeys2, DATA_KEYS, DELETE_DATA_KEYS, ERROR_KEYS, count3, BEFORE_DISPATCH, rowsByAnswer, HostedOutcomeError, OUTCOME_CONTENT_BYTES;
29136
+ var CAPACITY_REFUSAL_CODES, DELETIONS_HELD_REFUSAL_CODE, UPDATE_ANSWER_ROWS, OUTCOME_ANSWER_ROWS, READ_ANSWER_ROWS, WRITE_ERROR_CODES, DELETE_OPERATION_ID, FINDING_IDS_SHOWN, DEFINITION_FINDINGS_TEXT_BYTES, findingText, HostedAnswerError, isRecord8, onlyKeys2, DATA_KEYS, DELETE_DATA_KEYS, ERROR_KEYS, count3, pick, isText, writeWarning, writeGuidance2, inputIssue, writeDiagnostics, BEFORE_DISPATCH, rowsByAnswer, HostedOutcomeError, OUTCOME_CONTENT_BYTES;
28776
29137
  var init_answer_rows = __esm({
28777
29138
  "../core/src/hosted-transport/answer-rows.ts"() {
28778
29139
  "use strict";
@@ -28901,8 +29262,18 @@ var init_answer_rows = __esm({
28901
29262
  onlyKeys2 = (value, allowed) => Object.keys(value).every((key4) => allowed.includes(key4));
28902
29263
  DATA_KEYS = ["bundleId", "documentId", "version", "changed", "scope"];
28903
29264
  DELETE_DATA_KEYS = [...DATA_KEYS, "deletedVersion", "deleted"];
28904
- ERROR_KEYS = ["code", "message", "retryable", "writeState", "currentVersion", "diagnostics", "fieldActionDetails", "definitionDetails", "candidate", "retentionUnavailable", "scope", "resetAt", "deletions", "baseline"];
29265
+ ERROR_KEYS = ["code", "message", "retryable", "writeState", "currentVersion", "fieldActionDetails", "definitionDetails", "candidate", "retentionUnavailable", "scope", "resetAt", "deletions", "baseline"];
28905
29266
  count3 = (value) => Number.isSafeInteger(value) && value >= 1;
29267
+ pick = (value, keys2) => {
29268
+ const picked = {};
29269
+ for (const key4 of keys2) if (Object.hasOwn(value, key4) && value[key4] !== void 0) picked[key4] = value[key4];
29270
+ return picked;
29271
+ };
29272
+ isText = (value) => typeof value === "string";
29273
+ writeWarning = (entry) => isText(entry.code) && (entry.severity === "error" || entry.severity === "warning") && (entry.field === void 0 || isText(entry.field)) ? { code: entry.code, severity: entry.severity, ...entry.field !== void 0 ? { field: entry.field } : {} } : void 0;
29274
+ writeGuidance2 = (entry) => isText(entry.field) && isText(entry.value) && isText(entry.description) ? { field: entry.field, value: entry.value, description: entry.description } : void 0;
29275
+ inputIssue = (entry) => isText(entry.path) && isText(entry.message) ? { path: entry.path, message: entry.message } : void 0;
29276
+ writeDiagnostics = (value) => isRecord8(value) && Number.isSafeInteger(value.version) && Array.isArray(value.items) && value.items.every((item) => isRecord8(item) && isText(item.code)) ? value : void 0;
28906
29277
  BEFORE_DISPATCH = /* @__PURE__ */ new Map([
28907
29278
  [429, { code: "request_capacity", lenient: true }],
28908
29279
  [428, { code: "deletions_held", lenient: false }]
@@ -29956,7 +30327,7 @@ function rootWriteRequest(bundleId2, content3, base) {
29956
30327
  function rootSuccess(body, bundleId2) {
29957
30328
  if (!isRecord10(body) || body.ok !== true || body.operationId !== ROOT_OPERATION_ID || body.error !== void 0) return null;
29958
30329
  const data = body.data;
29959
- if (!isRecord10(data) || !Object.keys(data).every((key4) => key4 === "bundleId" || key4 === "version" || key4 === "changed")) return null;
30330
+ if (!isRecord10(data)) return null;
29960
30331
  if (data.bundleId !== bundleId2 || !isContentVersion(data.version) || typeof data.changed !== "boolean") return null;
29961
30332
  return { version: data.version, changed: data.changed };
29962
30333
  }
@@ -33736,23 +34107,23 @@ async function inspectBundleHomeAt(canonicalRoot, options = {}) {
33736
34107
  }
33737
34108
  }
33738
34109
  async function unboundLocalCopyAt(canonicalRoot, options = {}) {
33739
- const facts = await bundleHomeAt(canonicalRoot, options);
33740
- return facts.home === "local" && facts.copy ? facts.copy : null;
34110
+ const facts2 = await bundleHomeAt(canonicalRoot, options);
34111
+ return facts2.home === "local" && facts2.copy ? facts2.copy : null;
33741
34112
  }
33742
- function unboundCopyOf(facts) {
33743
- if (facts.home === "hosted" || !facts.copy) return {};
33744
- return unboundCopyDetail(facts.copy.folder, facts.copy.marker);
34113
+ function unboundCopyOf(facts2) {
34114
+ if (facts2.home === "hosted" || !facts2.copy) return {};
34115
+ return unboundCopyDetail(facts2.copy.folder, facts2.copy.marker);
33745
34116
  }
33746
- function homeDetail(facts) {
33747
- if (facts.home === "hosted") {
33748
- const { binding: binding2 } = facts;
34117
+ function homeDetail(facts2) {
34118
+ if (facts2.home === "hosted") {
34119
+ const { binding: binding2 } = facts2;
33749
34120
  return { hosted: { host: binding2.origin, bundle_id: binding2.bundle_id, workspace: binding2.workspace, principal: binding2.principal_id } };
33750
34121
  }
33751
- if (facts.home === "git") {
33752
- const { board } = facts;
33753
- return { board: { channel: board.channel, branch: board.branch, upstream: board.upstream, shared: board.shared }, ...unboundCopyOf(facts) };
34122
+ if (facts2.home === "git") {
34123
+ const { board } = facts2;
34124
+ return { board: { channel: board.channel, branch: board.branch, upstream: board.upstream, shared: board.shared }, ...unboundCopyOf(facts2) };
33754
34125
  }
33755
- return unboundCopyOf(facts);
34126
+ return unboundCopyOf(facts2);
33756
34127
  }
33757
34128
  function count5(dir, args) {
33758
34129
  const text7 = gitText(dir, args);
@@ -34204,9 +34575,9 @@ async function entryAvailable(entry) {
34204
34575
  }
34205
34576
  async function entryView(entry, available, home2) {
34206
34577
  if (!available) return { ...entry, available, home: "local" };
34207
- const facts = await bundleHomeAt(entry.locator.path, { home: home2 });
34208
- if (facts.home !== "hosted") return { ...entry, available, home: facts.home };
34209
- const { binding: binding2 } = facts;
34578
+ const facts2 = await bundleHomeAt(entry.locator.path, { home: home2 });
34579
+ if (facts2.home !== "hosted") return { ...entry, available, home: facts2.home };
34580
+ const { binding: binding2 } = facts2;
34210
34581
  return { ...entry, available, home: "hosted", hosted: { host: binding2.origin, bundle_id: binding2.bundle_id, checked_out_at: binding2.created_at } };
34211
34582
  }
34212
34583
  async function listCatalogEntries(home2 = homedir8()) {
@@ -42335,15 +42706,15 @@ function missingMetadataError(target3) {
42335
42706
  const hostname5 = new URL(target3.origin).hostname;
42336
42707
  const parent = parentDomain(hostname5);
42337
42708
  const label = hostname5.split(".")[0];
42338
- const suggestion = parent !== null && label !== "mcp" && isWorkspaceSlug(label) ? { host: `https://mcp.${parent}`, workspace: label } : null;
42709
+ const suggestion2 = parent !== null && label !== "mcp" && isWorkspaceSlug(label) ? { host: `https://mcp.${parent}`, workspace: label } : null;
42339
42710
  return new CliError("RUNTIME", `protected-resource metadata at ${target3.metadataUrl} returned HTTP 404`, {
42340
42711
  details: {
42341
42712
  status: 404,
42342
42713
  reason: "no_protected_resource_metadata",
42343
42714
  host: target3.origin,
42344
- ...suggestion ? { suggested_host: suggestion.host, suggested_workspace: suggestion.workspace } : {}
42715
+ ...suggestion2 ? { suggested_host: suggestion2.host, suggested_workspace: suggestion2.workspace } : {}
42345
42716
  },
42346
- help: suggestion ? `${target3.origin} may be a workspace address rather than the sign-in host; if so, re-run with --host ${commandToken(suggestion.host)} --workspace ${commandToken(suggestion.workspace)} (--workspace only where the command takes it)` : `${target3.origin} publishes no Superbee sign-in metadata; check the URL, or ask the host's operator which Superbee host to use`
42717
+ help: suggestion2 ? `${target3.origin} may be a workspace address rather than the sign-in host; if so, re-run with --host ${commandToken(suggestion2.host)} --workspace ${commandToken(suggestion2.workspace)} (--workspace only where the command takes it)` : `${target3.origin} publishes no Superbee sign-in metadata; check the URL, or ask the host's operator which Superbee host to use`
42347
42718
  });
42348
42719
  }
42349
42720
  async function readWorkspacePointer(fetchImpl, target3) {
@@ -43032,10 +43403,10 @@ function decodeJwtClaims(token) {
43032
43403
  }
43033
43404
  function subjectFrom(tokens, previous3) {
43034
43405
  const claims = decodeJwtClaims(tokens.id_token) ?? decodeJwtClaims(tokens.access_token) ?? {};
43035
- const pick2 = (key4) => typeof claims[key4] === "string" ? claims[key4] : void 0;
43036
- const sub = pick2("sub") ?? previous3?.sub;
43037
- const email3 = pick2("email") ?? previous3?.email;
43038
- const name = pick2("name") ?? previous3?.name;
43406
+ const pick3 = (key4) => typeof claims[key4] === "string" ? claims[key4] : void 0;
43407
+ const sub = pick3("sub") ?? previous3?.sub;
43408
+ const email3 = pick3("email") ?? previous3?.email;
43409
+ const name = pick3("name") ?? previous3?.name;
43039
43410
  return { ...sub ? { sub } : {}, ...email3 ? { email: email3 } : {}, ...name ? { name } : {} };
43040
43411
  }
43041
43412
  function expiresAt(tokens, now) {
@@ -43902,9 +44273,9 @@ function parseOwnedOrUsage(parse7, command, recovery = {}) {
43902
44273
  if (retiredFlagInParse({ error: err })) throw retiredInputRefusal("--remote");
43903
44274
  const translated = translateParseArgsError(err);
43904
44275
  const raw = err instanceof Error ? err.message : String(err);
43905
- const suggestion = err?.code === "ERR_PARSE_ARGS_UNKNOWN_OPTION" ? nearestLongOption(QUOTED.exec(raw)?.[1], recovery.optionNames) : void 0;
44276
+ const suggestion2 = err?.code === "ERR_PARSE_ARGS_UNKNOWN_OPTION" ? nearestLongOption(QUOTED.exec(raw)?.[1], recovery.optionNames) : void 0;
43906
44277
  const baseMessage = translated ?? stripAdvisory(raw);
43907
- const message = suggestion ? `${baseMessage} \u2014 did you mean '${suggestion}'?` : baseMessage;
44278
+ const message = suggestion2 ? `${baseMessage} \u2014 did you mean '${suggestion2}'?` : baseMessage;
43908
44279
  throw new CliError("USAGE", message, { help: `${cliInvocation()} ${commandWords(command)} --help` });
43909
44280
  }
43910
44281
  if (retiredFlagInParse({ values: parsed2.values })) throw retiredInputRefusal("--remote");
@@ -45921,6 +46292,153 @@ var init_kind_write = __esm({
45921
46292
  }
45922
46293
  });
45923
46294
 
46295
+ // ../cli/src/write-findings.ts
46296
+ function bundleTargetReader(bundle) {
46297
+ return async (id) => {
46298
+ try {
46299
+ return await readDoc2(bundle, id);
46300
+ } catch (err) {
46301
+ if (err?.code === "ENOENT") return void 0;
46302
+ throw err;
46303
+ }
46304
+ };
46305
+ }
46306
+ function facts(details) {
46307
+ const { start: _start, end: _end, ...rest } = details;
46308
+ return rest;
46309
+ }
46310
+ function linkWarning(finding, body) {
46311
+ if (finding.code === "LINK_NOT_RECOGNIZED") {
46312
+ const d = finding.details;
46313
+ const written = body.slice(d.start, d.end);
46314
+ const fix = d.suggestedHref !== void 0 ? `; write [${d.text || d.suggestedTo}](${d.suggestedHref})` : "";
46315
+ return {
46316
+ code: finding.code,
46317
+ message: `${written} will not register as a link: ${REASONS[d.reason] ?? "it is not a link to a document"}${fix}.`,
46318
+ field: "body",
46319
+ severity: finding.severity,
46320
+ details: facts(d)
46321
+ };
46322
+ }
46323
+ if (finding.code === "LINK_TARGET_ABSENT") {
46324
+ const d = finding.details;
46325
+ const fix = d.suggestedHref !== void 0 ? `; did you mean ${d.suggestedHref} ('${d.suggestedTo}' exists)?` : ` (kept as a forward declaration); create it with \`${cliInvocation()} doc write ${commandToken(d.to)} --type <t>\`.`;
46326
+ return {
46327
+ code: finding.code,
46328
+ message: `target '${d.to}' has no document yet${fix}`,
46329
+ field: "body",
46330
+ severity: finding.severity,
46331
+ details: facts(d)
46332
+ };
46333
+ }
46334
+ return void 0;
46335
+ }
46336
+ function findingKey(finding) {
46337
+ const d = finding.details;
46338
+ return JSON.stringify([finding.code, d.reason ?? null, d.href ?? null, d.text ?? null, d.to ?? null]);
46339
+ }
46340
+ function cachedReader(bundle, failures) {
46341
+ const read = bundleTargetReader(bundle);
46342
+ const cache = /* @__PURE__ */ new Map();
46343
+ return (id) => {
46344
+ const held3 = cache.get(id);
46345
+ if (held3) return held3;
46346
+ const pending = read(id).catch((err) => {
46347
+ failures.set(id, errorText(err));
46348
+ return { id, frontmatter: { type: "" }, body: "" };
46349
+ });
46350
+ cache.set(id, pending);
46351
+ return pending;
46352
+ };
46353
+ }
46354
+ async function linkFindings(bundle, doc2, prior) {
46355
+ const failures = /* @__PURE__ */ new Map();
46356
+ const readTarget2 = cachedReader(bundle, failures);
46357
+ let findings;
46358
+ let unavailable3;
46359
+ try {
46360
+ ({ findings } = await documentLinkReport(doc2, { readTarget: readTarget2 }));
46361
+ } catch (err) {
46362
+ ({ findings } = inspectDocumentLinks(doc2));
46363
+ unavailable3 = errorText(err);
46364
+ }
46365
+ const linkedBefore = new Set(prior === void 0 ? [] : inspectDocumentLinks({ ...prior, id: doc2.id }).links.map((link4) => link4.to));
46366
+ const unreadable = [...failures].filter(([to]) => !linkedBefore.has(to));
46367
+ const before = /* @__PURE__ */ new Map();
46368
+ if (prior !== void 0 && findings.length > 0) {
46369
+ let old;
46370
+ try {
46371
+ ({ findings: old } = await documentLinkReport({ ...prior, id: doc2.id }, { readTarget: readTarget2 }));
46372
+ } catch {
46373
+ ({ findings: old } = inspectDocumentLinks({ ...prior, id: doc2.id }));
46374
+ }
46375
+ for (const finding of old) before.set(findingKey(finding), (before.get(findingKey(finding)) ?? 0) + 1);
46376
+ }
46377
+ const links = findings.flatMap((finding) => {
46378
+ const key4 = findingKey(finding);
46379
+ const seen = before.get(key4) ?? 0;
46380
+ if (seen > 0) {
46381
+ before.set(key4, seen - 1);
46382
+ return [];
46383
+ }
46384
+ const warning = linkWarning(finding, doc2.body);
46385
+ return warning ? [warning] : [];
46386
+ });
46387
+ const out = links.slice(0, LINK_FINDINGS_SHOWN);
46388
+ if (links.length > LINK_FINDINGS_SHOWN) {
46389
+ const last = out[out.length - 1];
46390
+ out[out.length - 1] = { ...last, message: `${last.message} (${links.length - LINK_FINDINGS_SHOWN} more link findings not shown)` };
46391
+ }
46392
+ for (const [to, reason] of unreadable.slice(0, LINK_FINDINGS_SHOWN)) {
46393
+ out.push({ code: "LINK_LINT_UNAVAILABLE", message: `the link to '${to}' could not be checked: ${reason}`, field: "body", severity: "warning", details: { to } });
46394
+ }
46395
+ if (unavailable3 !== void 0) {
46396
+ out.push({ code: "LINK_LINT_UNAVAILABLE", message: `the document was written, but its links to other documents could not be checked: ${unavailable3}`, field: "body", severity: "warning" });
46397
+ }
46398
+ return out;
46399
+ }
46400
+ async function writeFindings(bundle, doc2, registry2, prior) {
46401
+ const out = prior === void 0 || prior.body !== doc2.body ? await linkFindings(bundle, doc2, prior) : [];
46402
+ const type = prior === void 0 || prior.frontmatter.type !== doc2.frontmatter.type ? undeclaredTypeFinding(registry2, doc2) : void 0;
46403
+ if (type?.details.suggestedType !== void 0) {
46404
+ const { type: written, suggestedType } = type.details;
46405
+ out.push({
46406
+ code: type.code,
46407
+ message: `no Kind declares type '${written}'; did you mean '${suggestedType}'?`,
46408
+ field: "type",
46409
+ severity: type.severity,
46410
+ details: { type: written, suggestedType }
46411
+ });
46412
+ }
46413
+ return out;
46414
+ }
46415
+ function writeFindingsHelp(findings) {
46416
+ const help2 = [];
46417
+ if (findings.some((f) => f.code === "LINK_NOT_RECOGNIZED")) help2.push(LINK_FORM_HELP);
46418
+ if (findings.some((f) => f.code === "KIND_TYPE_UNDECLARED")) help2.push(`${cliInvocation()} kinds`);
46419
+ return help2;
46420
+ }
46421
+ var LINK_FINDINGS_SHOWN, LINK_FORM_HELP, REASONS, errorText;
46422
+ var init_write_findings = __esm({
46423
+ "../cli/src/write-findings.ts"() {
46424
+ "use strict";
46425
+ init_define_SUPERBEE_BUILD_IDENTITY();
46426
+ init_define_SUPERBEE_UPDATE_POLICY();
46427
+ init_src();
46428
+ init_invocation();
46429
+ init_command_text();
46430
+ LINK_FINDINGS_SHOWN = 10;
46431
+ LINK_FORM_HELP = "a link registers only as [Text](/folder/id.md) from the bundle root or [Text](./id.md) beside this document";
46432
+ REASONS = {
46433
+ wikilink: "a [[wikilink]] is plain text in OKF",
46434
+ "missing-md-extension": "its target does not end in .md",
46435
+ "reserved-target": "index.md and log.md are never documents",
46436
+ "invalid-target": "its target is not a valid document id"
46437
+ };
46438
+ errorText = (err) => err instanceof Error ? err.message : String(err);
46439
+ }
46440
+ });
46441
+
45924
46442
  // ../cli/src/mutate.ts
45925
46443
  async function firePostPersist(hook2) {
45926
46444
  if (!hook2) return;
@@ -46014,7 +46532,7 @@ var init_mutate = __esm({
46014
46532
  });
46015
46533
 
46016
46534
  // ../core/src/bundle-health/report.ts
46017
- function docType(doc2) {
46535
+ function docType2(doc2) {
46018
46536
  return typeof doc2.frontmatter.type === "string" ? doc2.frontmatter.type : "";
46019
46537
  }
46020
46538
  function diagnosticValue(value) {
@@ -46024,17 +46542,13 @@ function diagnosticValue(value) {
46024
46542
  return `<non-JSON ${Array.isArray(value) ? "array" : typeof value}: circular or too deeply nested>`;
46025
46543
  }
46026
46544
  }
46027
- function isGraphDefinition(doc2) {
46028
- const type = docType(doc2);
46029
- return type === "Convention" || isPageTypeName(type) || isLegacyPageDoc(doc2.frontmatter) || type === "Reference" && doc2.id.startsWith("references/") || type === BUNDLE_NAME_DOC_TYPE && doc2.id === BUNDLE_NAME_DOC_ID || type === DEPENDENCIES_DOC_TYPE && doc2.id === DEPENDENCIES_DOC_ID;
46030
- }
46031
46545
  function okfV02WorkflowStatusCollisions(registry2, docs) {
46032
46546
  const affectedByKind = /* @__PURE__ */ new Map();
46033
46547
  const observedValuesByKind = /* @__PURE__ */ new Map();
46034
46548
  for (const doc2 of docs) {
46035
46549
  const value = doc2.frontmatter.status;
46036
46550
  if (value === void 0 || isOkfLifecycleStatus(value)) continue;
46037
- const type = docType(doc2);
46551
+ const type = docType2(doc2);
46038
46552
  affectedByKind.set(type, (affectedByKind.get(type) ?? 0) + 1);
46039
46553
  const display = typeof value === "string" ? value : `<${Array.isArray(value) ? "array" : typeof value}>`;
46040
46554
  const observed = observedValuesByKind.get(type) ?? /* @__PURE__ */ new Set();
@@ -46085,13 +46599,13 @@ async function bundleHealth(bundle, options = {}) {
46085
46599
  const deprecatedUsage = [];
46086
46600
  const conformanceDebtDocs = /* @__PURE__ */ new Map();
46087
46601
  for (const doc2 of docs) {
46088
- const kind2 = registry2.kinds.get(docType(doc2));
46602
+ const kind2 = registry2.kinds.get(docType2(doc2));
46089
46603
  if (!kind2) continue;
46090
46604
  deprecatedUsage.push(...inspectKindDeprecatedUsage(doc2, kind2).map((row5) => ({ id: doc2.id, ...row5 })));
46091
46605
  for (const w of projectKindValidationWarnings(okfVersion, kind2, validateAgainstKind(doc2, kind2))) {
46092
46606
  kindLint.push({ id: doc2.id, field: w.field ?? "", code: w.code });
46093
46607
  if (isKindFieldValidationWarning(w) && !conformanceDebtDocs.has(doc2.id)) {
46094
- conformanceDebtDocs.set(doc2.id, docType(doc2));
46608
+ conformanceDebtDocs.set(doc2.id, docType2(doc2));
46095
46609
  }
46096
46610
  }
46097
46611
  }
@@ -46105,7 +46619,7 @@ async function bundleHealth(bundle, options = {}) {
46105
46619
  for (const doc2 of docs) {
46106
46620
  for (const l of parseLinksFromDoc(doc2)) {
46107
46621
  if (isQualifiedHref(l.href)) continue;
46108
- const qualifiedDeclaration = localEdgeQualifiedDeclaration(linkTypeDeclarations.get(l.text), docType(doc2));
46622
+ const qualifiedDeclaration = localEdgeQualifiedDeclaration(linkTypeDeclarations.get(l.text), docType2(doc2));
46109
46623
  if (qualifiedDeclaration) {
46110
46624
  crossLinkTypeViolations.push({
46111
46625
  from: doc2.id,
@@ -46122,24 +46636,17 @@ async function bundleHealth(bundle, options = {}) {
46122
46636
  if (l.to !== doc2.id) {
46123
46637
  inbound.add(l.to);
46124
46638
  const list6 = inboundEdges.get(l.to) ?? [];
46125
- list6.push({ text: l.text, sourceType: docType(doc2) });
46639
+ list6.push({ text: l.text, sourceType: docType2(doc2) });
46126
46640
  inboundEdges.set(l.to, list6);
46127
46641
  }
46128
- const declared = linkTypeDeclarations.get(l.text);
46129
- if (declared && declared.length > 0 && !qualifiedDeclaration) {
46130
- const sourceType = docType(doc2);
46131
- const targetType = docType(docsById.get(l.to));
46132
- const matched = declared.find((d) => d.governs === sourceType) ?? declared[0];
46133
- const sourceOk = declared.some((d) => d.governs === sourceType);
46134
- const targetOk = targetType === matched.target;
46135
- if (!sourceOk || !targetOk) {
46136
- linkTypeViolations.push({
46137
- from: doc2.id,
46138
- to: l.to,
46139
- text: l.text,
46140
- expected: `${matched.governs} -> ${matched.target}`
46141
- });
46142
- }
46642
+ const matched = qualifiedDeclaration ? null : localEdgeViolation(linkTypeDeclarations.get(l.text), docType2(doc2), docType2(docsById.get(l.to)));
46643
+ if (matched) {
46644
+ linkTypeViolations.push({
46645
+ from: doc2.id,
46646
+ to: l.to,
46647
+ text: l.text,
46648
+ expected: `${matched.governs} -> ${matched.target}`
46649
+ });
46143
46650
  }
46144
46651
  }
46145
46652
  }
@@ -46149,7 +46656,7 @@ async function bundleHealth(bundle, options = {}) {
46149
46656
  for (const q of parseQualifiedLinks(doc2)) {
46150
46657
  qualifiedLinks.push(q);
46151
46658
  if (!q.ref) continue;
46152
- const violation = qualifiedEdgeViolation(linkTypeDeclarations.get(q.text), docType(doc2), q.ref.alias);
46659
+ const violation = qualifiedEdgeViolation(linkTypeDeclarations.get(q.text), docType2(doc2), q.ref.alias);
46153
46660
  if (violation) {
46154
46661
  metadataViolations.add(q);
46155
46662
  crossLinkTypeViolations.push({
@@ -46193,9 +46700,9 @@ async function bundleHealth(bundle, options = {}) {
46193
46700
  if (!metadataViolations.has(link4)) {
46194
46701
  const violation = qualifiedEdgeViolation(
46195
46702
  linkTypeDeclarations.get(link4.text),
46196
- docType(docsById.get(link4.from)),
46703
+ docType2(docsById.get(link4.from)),
46197
46704
  resolution.ref.alias,
46198
- docType(resolution.document)
46705
+ docType2(resolution.document)
46199
46706
  );
46200
46707
  if (violation) crossLinkTypeViolations.push({
46201
46708
  from: link4.from,
@@ -46229,8 +46736,8 @@ async function bundleHealth(bundle, options = {}) {
46229
46736
  const orphans = [];
46230
46737
  if (inbound.size > 0) {
46231
46738
  for (const doc2 of docs) {
46232
- if (!inbound.has(doc2.id) && !outbound.has(doc2.id) && !isGraphDefinition(doc2)) {
46233
- orphans.push({ id: doc2.id, type: docType(doc2) });
46739
+ if (!inbound.has(doc2.id) && !outbound.has(doc2.id) && !isGraphDefinitionDocument(doc2)) {
46740
+ orphans.push({ id: doc2.id, type: docType2(doc2) });
46234
46741
  }
46235
46742
  }
46236
46743
  }
@@ -46243,25 +46750,25 @@ async function bundleHealth(bundle, options = {}) {
46243
46750
  for (const doc2 of docs) {
46244
46751
  const invalidLegacy = invalidLegacyTimestamp(doc2.frontmatter, okfVersion);
46245
46752
  if (invalidLegacy) {
46246
- invalidLegacyTimestamps.push({ id: doc2.id, type: docType(doc2), field: invalidLegacy.field, value: diagnosticValue(invalidLegacy.value) });
46753
+ invalidLegacyTimestamps.push({ id: doc2.id, type: docType2(doc2), field: invalidLegacy.field, value: diagnosticValue(invalidLegacy.value) });
46247
46754
  }
46248
46755
  if (okfVersion === "0.2") {
46249
46756
  for (const { field, value } of invalidOkfTimestamps(doc2.frontmatter)) {
46250
- invalidTimestamps.push({ id: doc2.id, type: docType(doc2), field, value: diagnosticValue(value) });
46757
+ invalidTimestamps.push({ id: doc2.id, type: docType2(doc2), field, value: diagnosticValue(value) });
46251
46758
  }
46252
46759
  }
46253
- const kind2 = registry2.kinds.get(docType(doc2));
46760
+ const kind2 = registry2.kinds.get(docType2(doc2));
46254
46761
  const horizonMs = kind2 ? freshnessHorizonMs(kind2) : void 0;
46255
46762
  const hasStaleAfter = okfVersion === "0.2" && Object.hasOwn(doc2.frontmatter, "stale_after");
46256
46763
  const staleAfterIsInvalid = hasStaleAfter && staleAfterInstant(doc2.frontmatter.stale_after) === null;
46257
46764
  if (staleAfterIsInvalid) {
46258
- invalidStaleAfter.push({ id: doc2.id, type: docType(doc2), value: diagnosticValue(doc2.frontmatter.stale_after) });
46765
+ invalidStaleAfter.push({ id: doc2.id, type: docType2(doc2), value: diagnosticValue(doc2.frontmatter.stale_after) });
46259
46766
  }
46260
46767
  const staleAfter = hasStaleAfter && !staleAfterIsInvalid ? doc2.frontmatter.stale_after : void 0;
46261
46768
  if (horizonMs === void 0 && staleAfter === void 0) continue;
46262
46769
  const result3 = freshness(doc2, { maxAgeMs: horizonMs, now, okfVersion });
46263
46770
  if (result3.verdict === "empty" && horizonMs !== void 0) {
46264
- noTimestamp.push({ id: doc2.id, type: docType(doc2) });
46771
+ noTimestamp.push({ id: doc2.id, type: docType2(doc2) });
46265
46772
  } else if (result3.verdict === "stale") {
46266
46773
  stale.push({
46267
46774
  id: doc2.id,
@@ -46275,7 +46782,7 @@ async function bundleHealth(bundle, options = {}) {
46275
46782
  const missingExpectedRanked = [];
46276
46783
  let terminalSkipped = 0;
46277
46784
  for (const doc2 of docs) {
46278
- const kind2 = registry2.kinds.get(docType(doc2));
46785
+ const kind2 = registry2.kinds.get(docType2(doc2));
46279
46786
  if (!kind2?.expectsInbound) continue;
46280
46787
  const terminalDeclared = Object.keys(kind2.fields.terminal).length > 0;
46281
46788
  if (terminalDeclared && isTerminal(kind2, doc2.frontmatter)) {
@@ -46366,7 +46873,7 @@ var init_report = __esm({
46366
46873
  init_page();
46367
46874
  init_qualified_links();
46368
46875
  init_verification();
46369
- init_legacy_page();
46876
+ init_system_documents();
46370
46877
  }
46371
46878
  });
46372
46879
 
@@ -46706,6 +47213,12 @@ replacement. Kind validation is advisory by default: violations appear as warnin
46706
47213
  no-ops. --strict rejects violations without writing. A changed replacement of a previously conforming
46707
47214
  document cannot be nonconforming, even in advisory mode.
46708
47215
 
47216
+ After a changed write, warnings also name what it introduced that will not work as meant: a link
47217
+ that will not register (LINK_NOT_RECOGNIZED, with the href that would), a link to a document that
47218
+ does not exist yet (LINK_TARGET_ABSENT; still allowed) and a type that misses a declared Kind's
47219
+ type only by case, spacing, hyphens or underscores (KIND_TYPE_UNDECLARED, naming the declared
47220
+ one). They never refuse the write.
47221
+
46709
47222
  Options:
46710
47223
  --type <t> OKF concept type (non-empty) [required]
46711
47224
  --title <t> Display title
@@ -46772,6 +47285,7 @@ timestamp) converges to changed:false (no write, no timestamp refresh).
46772
47285
  Standard-field patches use advisory Kind validation by default, returning warnings even on no-ops;
46773
47286
  --strict rejects violations without writing. Dynamic declared fields are always strict: passing a
46774
47287
  --<field> flag requires the whole resulting document to satisfy its Kind, even for a same-value patch.
47288
+ A changed body or type also gets the post-write link and type warnings 'doc write' describes.
46775
47289
 
46776
47290
  Options:
46777
47291
  --title <t> Replace the title
@@ -47201,6 +47715,7 @@ async function docUpdate(argv2, deps2) {
47201
47715
  const mode = resolveMode({ json: p.json });
47202
47716
  const registry2 = await loadKinds(bundle);
47203
47717
  const strict = p.strict || p.kindFields.size > 0;
47718
+ let prior;
47204
47719
  if (route) await assertResolvedLocalRouteIdentity(route);
47205
47720
  const result3 = await mutateDoc({
47206
47721
  bundle,
@@ -47223,6 +47738,7 @@ async function docUpdate(argv2, deps2) {
47223
47738
  input: async (existingDoc, context3) => {
47224
47739
  assertStaleAfterEdition(staleAfter, context3.okfVersion);
47225
47740
  const existing = existingDoc;
47741
+ prior = existing;
47226
47742
  const nextFrontmatter = {};
47227
47743
  if (staleAfter !== void 0) nextFrontmatter.stale_after = staleAfter;
47228
47744
  if (p.title !== void 0) nextFrontmatter.title = p.title;
@@ -47244,21 +47760,24 @@ async function docUpdate(argv2, deps2) {
47244
47760
  { help: `${cliInvocation()} kinds` }
47245
47761
  );
47246
47762
  }
47247
- const authoringKind = projectKindForAuthoring(context3.okfVersion, kind2);
47248
47763
  const progressCoordinate = progressStatusCoordinate(context3.okfVersion, kind2);
47249
- const declared = [...authoringKind.fields.required, ...authoringKind.fields.optional];
47250
- const resolvedFields = /* @__PURE__ */ new Map();
47251
- for (const field of p.kindFields.keys()) {
47252
- resolvedFields.set(field, resolveKindFieldCoordinate(context3.okfVersion, kind2, field));
47253
- }
47254
- const unknown3 = [...resolvedFields.entries()].filter(([, coordinate]) => coordinate === void 0).map(([field]) => field);
47255
- if (unknown3.length > 0) {
47764
+ const undeclared = kindFieldsUndeclaredFinding(
47765
+ context3.okfVersion,
47766
+ kind2,
47767
+ unknownKindFieldNames(context3.okfVersion, kind2, p.kindFields.keys())
47768
+ );
47769
+ if (undeclared) {
47770
+ const { kind: governs, fields: unknown3, declared } = undeclared.details;
47256
47771
  throw new CliError(
47257
47772
  "USAGE",
47258
- `unknown field(s) for kind '${kind2.governs}': ${unknown3.join(", ")} (declared: ${declared.length > 0 ? declared.join(", ") : "none"}; standard patch flags: title, description, type, body, body-file) \u2014 to ADD a field to the '${kind2.governs}' kind: \`${cliInvocation()} kind field ${commandToken(kind2.governs)} add <name>\`. Flags address declared fields only; an undeclared key written in frontmatter follows the kind's undeclared_fields setting (warn by default).`,
47773
+ `unknown field(s) for kind '${governs}': ${unknown3.join(", ")} (declared: ${declared.length > 0 ? declared.join(", ") : "none"}; standard patch flags: title, description, type, body, body-file) \u2014 to ADD a field to the '${governs}' kind: \`${cliInvocation()} kind field ${commandToken(governs)} add <name>\`. Flags address declared fields only; an undeclared key written in frontmatter follows the kind's undeclared_fields setting (warn by default).`,
47259
47774
  { help: `${cliInvocation()} kinds` }
47260
47775
  );
47261
47776
  }
47777
+ const resolvedFields = /* @__PURE__ */ new Map();
47778
+ for (const field of p.kindFields.keys()) {
47779
+ resolvedFields.set(field, resolveKindFieldCoordinate(context3.okfVersion, kind2, field));
47780
+ }
47262
47781
  const suppliedByStorageField = /* @__PURE__ */ new Map();
47263
47782
  if (staleAfter !== void 0) suppliedByStorageField.set("stale_after", "stale-after");
47264
47783
  for (const [field, value] of p.kindFields) {
@@ -47298,10 +47817,12 @@ async function docUpdate(argv2, deps2) {
47298
47817
  // subsequent `--expected-version` compare-and-swap.
47299
47818
  version: result3.version
47300
47819
  };
47301
- if (result3.warnings.length > 0) receipt5.warnings = result3.warnings;
47820
+ const findings = result3.changed ? await writeFindings(bundle, result3.doc, registry2, prior) : [];
47821
+ const warnings = [...result3.warnings, ...findings];
47822
+ if (warnings.length > 0) receipt5.warnings = warnings;
47302
47823
  if (result3.guidance.length > 0) receipt5.guidance = result3.guidance;
47303
47824
  if (isLegacyPageDoc(result3.doc.frontmatter)) receipt5.hint = LEGACY_PAGE_TYPE_HINT;
47304
- receipt5.help = [`${cliInvocation()} doc read ${commandToken(result3.doc.id)}`];
47825
+ receipt5.help = [`${cliInvocation()} doc read ${commandToken(result3.doc.id)}`, ...writeFindingsHelp(findings)];
47305
47826
  stdout(render(receipt5, mode));
47306
47827
  }
47307
47828
  var DOC_UPDATE_FIELD_FLAGS, DOC_UPDATE_VALUE_FLAGS, DOC_UPDATE_BOOLEAN_FLAGS;
@@ -47320,6 +47841,7 @@ var init_update2 = __esm({
47320
47841
  init_errors6();
47321
47842
  init_output2();
47322
47843
  init_invocation();
47844
+ init_write_findings();
47323
47845
  init_mutate();
47324
47846
  init_legacy_page2();
47325
47847
  init_board_attribution();
@@ -47451,6 +47973,7 @@ async function docWrite(argv2, deps2) {
47451
47973
  const acceptTruncatedBody = Boolean(values["accept-truncated-body"]);
47452
47974
  const registry2 = await loadKinds(bundle);
47453
47975
  let droppedFields = [];
47976
+ let prior;
47454
47977
  if (route) await assertResolvedLocalRouteIdentity(route);
47455
47978
  const result3 = await mutateDoc({
47456
47979
  bundle,
@@ -47467,6 +47990,7 @@ async function docWrite(argv2, deps2) {
47467
47990
  // refused/failed one — and only for the conventional board bundle (see board-attribution.ts).
47468
47991
  onPersisted: boardPostPersistHook(route ? boardAttributionForRoute(route) : { kind: "none" }, actor),
47469
47992
  buildCandidate: (fresh, context3) => {
47993
+ prior = fresh;
47470
47994
  assertStaleAfterEdition(staleAfter, context3.okfVersion);
47471
47995
  assertAuthoredLegacyTimestamp(values.timestamp?.trim(), context3.okfVersion);
47472
47996
  const legacyTimestamp = values.timestamp?.trim();
@@ -47527,10 +48051,12 @@ async function docWrite(argv2, deps2) {
47527
48051
  receipt5.note = receipt5.note ? `${receipt5.note}
47528
48052
  ${STDIN_SILENT_NOTE}` : STDIN_SILENT_NOTE;
47529
48053
  }
47530
- if (result3.warnings.length > 0) receipt5.warnings = result3.warnings;
48054
+ const findings = result3.changed ? await writeFindings(bundle, saved, registry2, prior) : [];
48055
+ const warnings = [...result3.warnings, ...findings];
48056
+ if (warnings.length > 0) receipt5.warnings = warnings;
47531
48057
  if (result3.guidance.length > 0) receipt5.guidance = result3.guidance;
47532
48058
  if (isLegacyPageDoc(saved.frontmatter)) receipt5.hint = LEGACY_PAGE_TYPE_HINT;
47533
- receipt5.help = [`${cliInvocation()} doc read ${commandToken(saved.id)}`];
48059
+ receipt5.help = [`${cliInvocation()} doc read ${commandToken(saved.id)}`, ...writeFindingsHelp(findings)];
47534
48060
  stdout(render(receipt5, resolveMode(values)));
47535
48061
  }
47536
48062
  var init_write2 = __esm({
@@ -47546,6 +48072,7 @@ var init_write2 = __esm({
47546
48072
  init_command_spec();
47547
48073
  init_output2();
47548
48074
  init_invocation();
48075
+ init_write_findings();
47549
48076
  init_mutate();
47550
48077
  init_legacy_page2();
47551
48078
  init_board_attribution();
@@ -48501,9 +49028,9 @@ async function sharedGitBoardAt(dir, home2 = homedir16()) {
48501
49028
  } catch {
48502
49029
  return null;
48503
49030
  }
48504
- const facts = await bundleHomeAt(root, { home: home2 });
48505
- if (facts.home !== "git") return null;
48506
- const board = facts.board;
49031
+ const facts2 = await bundleHomeAt(root, { home: home2 });
49032
+ if (facts2.home !== "git") return null;
49033
+ const board = facts2.board;
48507
49034
  if (board.channel !== "branch" || !board.shared) return null;
48508
49035
  const block = await gitBoardSyncBlock(board);
48509
49036
  return {
@@ -57421,14 +57948,14 @@ async function defaultSummarizeBundle(dir, route) {
57421
57948
  const docs = await queryHeads2(bundle, {}, { onSkip: ({ id, reason }) => malformed6.push({ id, reason }) });
57422
57949
  const { name, source: source2 } = await deriveBundleDisplayName(bundle);
57423
57950
  const okfVersion = await readBundleOkfVersion2(bundle);
57424
- const facts = await bundleHomeAt(await realpath6(bundle.root).catch(() => bundle.root));
57425
- const copy = unboundCopyOf(facts).copy_of_checkout;
57951
+ const facts2 = await bundleHomeAt(await realpath6(bundle.root).catch(() => bundle.root));
57952
+ const copy = unboundCopyOf(facts2).copy_of_checkout;
57426
57953
  return {
57427
57954
  name,
57428
57955
  nameSource: source2,
57429
57956
  ...summarizeDocs(docs, collapseHomeDirectory(bundle.root), { okfVersion }),
57430
- home: facts.home,
57431
- ...facts.home === "hosted" ? { hostedDefinitionWrites: facts.binding.definition_writes ?? null } : {},
57957
+ home: facts2.home,
57958
+ ...facts2.home === "hosted" ? { hostedDefinitionWrites: facts2.binding.definition_writes ?? null } : {},
57432
57959
  ...copy ? { copyOfCheckout: copy } : {},
57433
57960
  ...malformed6.length > 0 ? { malformed: malformed6.sort((a, b) => a.id.localeCompare(b.id)) } : {}
57434
57961
  };
@@ -60131,7 +60658,7 @@ async function driveObservation(options) {
60131
60658
  const sourceComplete = bound2.source.completeness === "complete";
60132
60659
  let stop;
60133
60660
  let stopUrl;
60134
- const errorText = (error62) => error62 instanceof Error ? error62.message : String(error62);
60661
+ const errorText2 = (error62) => error62 instanceof Error ? error62.message : String(error62);
60135
60662
  const store = async (next) => {
60136
60663
  try {
60137
60664
  if ((qualified || options.prepareCommit || hasProtectedSourcePending(state)) && ((qualified ? Object.keys(next.pending ?? {}).length : Object.values(next.pending ?? {}).filter((p) => p.establishment).length) > 100 || new TextEncoder().encode(JSON.stringify(next)).length > 4194304)) throw new Error("source establishment state limit");
@@ -60188,7 +60715,7 @@ async function driveObservation(options) {
60188
60715
  })));
60189
60716
  } catch (error62) {
60190
60717
  receipt5.held += ids.length;
60191
- stop = { outcome: "failed", reason: "establishment_pending", retry: true, detail: errorText(error62) };
60718
+ stop = { outcome: "failed", reason: "establishment_pending", retry: true, detail: errorText2(error62) };
60192
60719
  return;
60193
60720
  }
60194
60721
  if (ids.some((id) => result3.hold.has(id) || result3.retry.has(id))) {
@@ -60229,7 +60756,7 @@ async function driveObservation(options) {
60229
60756
  ...marked.length ? { establishments } : {}
60230
60757
  })));
60231
60758
  } catch (error62) {
60232
- failure4 = errorText(error62);
60759
+ failure4 = errorText2(error62);
60233
60760
  }
60234
60761
  }
60235
60762
  if (marked.some((id) => failure4 !== void 0 || result3.retry.has(id) || result3.hold.has(id))) {
@@ -60306,7 +60833,7 @@ async function driveObservation(options) {
60306
60833
  if (!stop && signal.aborted) stop = { outcome: "deferred", reason: "deadline", retry: true };
60307
60834
  if (!stop) {
60308
60835
  const code3 = record12(error62) ? error62.code : void 0;
60309
- stop = code3 === UNSUPPORTED_CONTENT ? { outcome: "unsupported_content", retry: false, detail: String(error62.detail ?? "") } : { outcome: "failed", reason: "profile_error", retry: false, detail: errorText(error62) };
60836
+ stop = code3 === UNSUPPORTED_CONTENT ? { outcome: "unsupported_content", retry: false, detail: String(error62.detail ?? "") } : { outcome: "failed", reason: "profile_error", retry: false, detail: errorText2(error62) };
60310
60837
  }
60311
60838
  stopUrl = lastRequestUrl();
60312
60839
  break;
@@ -60326,7 +60853,7 @@ async function driveObservation(options) {
60326
60853
  }
60327
60854
  page = JSON.parse(JSON.stringify(raw));
60328
60855
  } catch (error62) {
60329
- stop = { outcome: "failed", reason: "page_invalid", retry: false, detail: errorText(error62) };
60856
+ stop = { outcome: "failed", reason: "page_invalid", retry: false, detail: errorText2(error62) };
60330
60857
  break;
60331
60858
  }
60332
60859
  const nextCursor = page.nextCursor ?? null;
@@ -60416,7 +60943,7 @@ async function driveObservation(options) {
60416
60943
  return;
60417
60944
  }
60418
60945
  } catch (error62) {
60419
- stop = { outcome: "failed", reason: "commit_failed", retry: true, detail: errorText(error62) };
60946
+ stop = { outcome: "failed", reason: "commit_failed", retry: true, detail: errorText2(error62) };
60420
60947
  break;
60421
60948
  }
60422
60949
  const notWritten = (id) => byId2.has(id) && (result3.hold.has(id) || result3.retry.has(id));
@@ -60593,7 +61120,7 @@ async function observeSource(options) {
60593
61120
  stop = { outcome: "refused", reason, retry: false, ...detail2 !== void 0 ? { detail: detail2 } : {} };
60594
61121
  return finish();
60595
61122
  };
60596
- const errorText = (error62) => error62 instanceof Error ? error62.message : String(error62);
61123
+ const errorText2 = (error62) => error62 instanceof Error ? error62.message : String(error62);
60597
61124
  if (bound2.source.request?.read_policy !== void 0) {
60598
61125
  try {
60599
61126
  const inspected = inspectSourceReadPolicy(connector, bound2);
@@ -60627,7 +61154,7 @@ async function observeSource(options) {
60627
61154
  spec = checked.spec;
60628
61155
  hosts = profile.hostsFor(spec, structuredClone(bound2));
60629
61156
  } catch (error62) {
60630
- stop = { outcome: "failed", reason: "profile_error", retry: false, detail: errorText(error62) };
61157
+ stop = { outcome: "failed", reason: "profile_error", retry: false, detail: errorText2(error62) };
60631
61158
  return finish();
60632
61159
  }
60633
61160
  if (!Array.isArray(hosts) || !hosts.every((host) => typeof host === "string")) return refuse3("hosts_invalid");
@@ -60646,7 +61173,7 @@ async function observeSource(options) {
60646
61173
  version5 = stored?.version ?? null;
60647
61174
  state = stored?.state ?? emptyState2(profile);
60648
61175
  } catch (error62) {
60649
- stop = { outcome: "failed", reason: "state_unreadable", retry: true, detail: errorText(error62) };
61176
+ stop = { outcome: "failed", reason: "state_unreadable", retry: true, detail: errorText2(error62) };
60650
61177
  return finish();
60651
61178
  }
60652
61179
  const baseline = version5 === null;
@@ -62060,9 +62587,9 @@ function capacityFacts(bound2, snapshot3, state, input2) {
62060
62587
  complete_observations: Number.MAX_SAFE_INTEGER,
62061
62588
  last_complete_at: time3
62062
62589
  }) + bytes({ v: 1, entries: candidates });
62063
- const facts = { retainedIds: bags.size, acceptedTuples: tupleKeys.size, upperBoundBytes, maxEnvelopeBytes: input2.maxEnvelopeBytes };
62064
- if (facts.retainedIds > SNAPSHOT_MAX_RECORDS || facts.acceptedTuples > SNAPSHOT_MAX_RECORDS || facts.upperBoundBytes > facts.maxEnvelopeBytes) return refuse("SNAPSHOT_CAPACITY_EXCEEDED");
62065
- return facts;
62590
+ const facts2 = { retainedIds: bags.size, acceptedTuples: tupleKeys.size, upperBoundBytes, maxEnvelopeBytes: input2.maxEnvelopeBytes };
62591
+ if (facts2.retainedIds > SNAPSHOT_MAX_RECORDS || facts2.acceptedTuples > SNAPSHOT_MAX_RECORDS || facts2.upperBoundBytes > facts2.maxEnvelopeBytes) return refuse("SNAPSHOT_CAPACITY_EXCEEDED");
62592
+ return facts2;
62066
62593
  }
62067
62594
  function snapshotStateValid(value) {
62068
62595
  if (!isSourceState(value) || !isJsonData(value) || value.pending_commit !== void 0) return false;
@@ -62511,7 +63038,7 @@ var init_source_profiles = __esm({
62511
63038
  };
62512
63039
  }
62513
63040
  });
62514
- SOURCE_PLUGIN_CORE_VERSION = "0.2.0-pre.41";
63041
+ SOURCE_PLUGIN_CORE_VERSION = "0.2.0-pre.43";
62515
63042
  SOURCE_PROFILES = Object.freeze([restJsonProfile].map((profile) => Object.freeze({ id: profile.id, version: profile.version, kind: profile.kind })));
62516
63043
  }
62517
63044
  });
@@ -63184,6 +63711,9 @@ Options:
63184
63711
  --json Emit compact JSON instead of TOON
63185
63712
  -h, --help Show this help without reading a bundle
63186
63713
 
63714
+ A changed type is checked as 'doc write' checks it: a near miss of a declared Kind's type
63715
+ is named in the receipt's warnings (KIND_TYPE_UNDECLARED). It never refuses the write.
63716
+
63187
63717
  Literal strings are never split on commas or parsed as key/value pairs. Put flags
63188
63718
  before -- when passing a dash-leading literal. Field actions never read stdin.
63189
63719
  Resource selection refuses an ID-bearing entry and directs you to its ID.
@@ -63268,6 +63798,7 @@ async function docField(argv2, deps2) {
63268
63798
  const operation = action === "edit" ? { action, field, selector: selector2, patch: value } : action === "remove" && field === "sources" ? { action, field, selector: selector2 } : { action, field, value };
63269
63799
  const registry2 = await loadKinds(bundle);
63270
63800
  const edition = await readBundleOkfVersion2(bundle) === "0.2" ? "0.2" : "0.1";
63801
+ let prior;
63271
63802
  if (route) await assertResolvedLocalRouteIdentity(route);
63272
63803
  try {
63273
63804
  const result3 = await mutateDoc({
@@ -63282,6 +63813,7 @@ async function docField(argv2, deps2) {
63282
63813
  persistActor: true,
63283
63814
  expectedVersion: expectedVersion?.trim(),
63284
63815
  input: (existing, context3) => {
63816
+ prior = existing;
63285
63817
  if (context3.okfVersion !== edition) fail4("The bundle edition changed; retry against its current declaration.");
63286
63818
  if (action === "set") {
63287
63819
  const kind2 = registry2.kinds.get(String(existing.frontmatter.type));
@@ -63299,6 +63831,8 @@ async function docField(argv2, deps2) {
63299
63831
  });
63300
63832
  const scope = result3.scope;
63301
63833
  const { affectedSourceIds, ...boundedScope } = scope;
63834
+ const findings = result3.changed ? await writeFindings(bundle, result3.doc, registry2, prior) : [];
63835
+ const warnings = [...result3.warnings, ...findings];
63302
63836
  stdout(render({
63303
63837
  doc: "field",
63304
63838
  id: result3.doc.id,
@@ -63307,9 +63841,9 @@ async function docField(argv2, deps2) {
63307
63841
  changed: result3.changed,
63308
63842
  version: result3.version,
63309
63843
  scope: { ...boundedScope, ...affectedSourceIds === void 0 ? {} : { affectedSourceIds: affectedSourceIds.slice(0, 20), affectedSourceIdCount: affectedSourceIds.length } },
63310
- ...result3.warnings.length ? { warnings: result3.warnings } : {},
63844
+ ...warnings.length ? { warnings } : {},
63311
63845
  ...result3.guidance.length ? { guidance: result3.guidance } : {},
63312
- help: [`${cliInvocation()} doc read ${commandToken(result3.doc.id)}${routeFlag}`]
63846
+ help: [`${cliInvocation()} doc read ${commandToken(result3.doc.id)}${routeFlag}`, ...writeFindingsHelp(findings)]
63313
63847
  }, resolveMode(values)));
63314
63848
  } catch (error62) {
63315
63849
  if (error62 instanceof CliError && error62.code === "USAGE" && !error62.help) {
@@ -63341,6 +63875,7 @@ var init_field = __esm({
63341
63875
  init_command_spec();
63342
63876
  init_command_text();
63343
63877
  init_invocation();
63878
+ init_write_findings();
63344
63879
  init_errors6();
63345
63880
  init_external_file();
63346
63881
  init_bundle2();
@@ -109924,64 +110459,30 @@ Options:
109924
110459
 
109925
110460
  // ../cli/src/commands/link.ts
109926
110461
  import { parseArgs as parseArgs21 } from "node:util";
109927
- function docType2(doc2) {
110462
+ function docType3(doc2) {
109928
110463
  return typeof doc2.frontmatter.type === "string" ? doc2.frontmatter.type : "";
109929
110464
  }
109930
110465
  async function lintLinkType(bundle, args, registry2) {
109931
- const declarations = collectLinkDeclarations(registry2);
109932
- if (declarations.size === 0) return [];
109933
- const exact = declarations.get(args.text);
109934
- if (exact && exact.length > 0) {
109935
- let targetType;
109936
- let targetResolved = true;
109937
- try {
109938
- targetType = docType2(await readDoc2(bundle, args.to));
109939
- } catch (err) {
109940
- if (err?.code === "ENOENT") {
109941
- targetResolved = false;
109942
- } else {
109943
- throw classifyBundleError(err);
109944
- }
109945
- }
109946
- const matched = exact.find((d) => d.governs === args.sourceType) ?? exact[0];
109947
- const qualified = parseQualifiedKindTarget(matched.target);
109948
- if (qualified) {
109949
- return [
109950
- {
109951
- code: "LINK_TYPE_VIOLATION",
109952
- message: `'${args.text}' is declared by '${matched.governs}' -> ${matched.target}, a link into the bundle aliased '${qualified.alias}'; write it with --bundle ${commandToken(qualified.alias)}.`,
109953
- field: "text",
109954
- severity: "warning"
109955
- }
109956
- ];
109957
- }
109958
- const sourceOk = exact.some((d) => d.governs === args.sourceType);
109959
- const targetOk = !targetResolved || targetType === matched.target;
109960
- if (!sourceOk || !targetOk) {
109961
- return [
109962
- {
109963
- code: "LINK_TYPE_VIOLATION",
109964
- message: `'${args.text}' is declared by '${matched.governs}' -> ${matched.target}; this link is ${args.sourceType || "(untyped)"} -> ${targetResolved ? targetType || "(untyped)" : "(unresolved)"}.`,
109965
- field: "text",
109966
- severity: "warning"
109967
- }
109968
- ];
109969
- }
109970
- return [];
110466
+ let finding;
110467
+ try {
110468
+ finding = await linkTypeFinding(registry2, args, bundleTargetReader(bundle));
110469
+ } catch (err) {
110470
+ throw classifyBundleError(err);
109971
110471
  }
109972
- for (const declaredText of declarations.keys()) {
109973
- if (declaredText.toLowerCase() === args.text.toLowerCase()) {
109974
- return [
109975
- {
109976
- code: "LINK_TYPE_CASE_VARIANT",
109977
- message: `'${args.text}' is a case-variant of the declared link type '${declaredText}' \u2014 did you mean --text ${commandQuoted(declaredText)}?`,
109978
- field: "text",
109979
- severity: "warning"
109980
- }
109981
- ];
109982
- }
110472
+ if (!finding) return [];
110473
+ if (finding.code === "LINK_TYPE_CASE_VARIANT") {
110474
+ return [
110475
+ {
110476
+ code: finding.code,
110477
+ message: `'${args.text}' is a case-variant of the declared link type '${finding.details.declaredText}' \u2014 did you mean --text ${commandQuoted(finding.details.declaredText)}?`,
110478
+ field: "text",
110479
+ severity: "warning"
110480
+ }
110481
+ ];
109983
110482
  }
109984
- return [];
110483
+ const d = finding.details;
110484
+ const message = d.targetAlias !== void 0 ? `'${args.text}' is declared by '${d.declaredBy}' -> ${d.declaredTarget}, a link into the bundle aliased '${d.targetAlias}'; write it with --bundle ${commandToken(d.targetAlias)}.` : `'${args.text}' is declared by '${d.declaredBy}' -> ${d.declaredTarget}; this link is ${d.sourceType || "(untyped)"} -> ${d.targetType === null ? "(unresolved)" : d.targetType || "(untyped)"}.`;
110485
+ return [{ code: finding.code, message, field: "text", severity: "warning" }];
109985
110486
  }
109986
110487
  async function assertTargetNotAlias(bundle, to) {
109987
110488
  try {
@@ -109991,18 +110492,14 @@ async function assertTargetNotAlias(bundle, to) {
109991
110492
  }
109992
110493
  }
109993
110494
  async function targetAbsentWarning(bundle, to) {
109994
- try {
109995
- await readDoc2(bundle, to);
109996
- return void 0;
109997
- } catch (err) {
109998
- if (err?.code !== "ENOENT") throw err;
109999
- return {
110000
- code: "LINK_TARGET_ABSENT",
110001
- message: `target '${to}' has no document yet \u2014 this link is a forward-declaration (dangling links stay allowed); create it with \`${cliInvocation()} doc write ${commandToken(to)} --type <t>\`.`,
110002
- field: "to",
110003
- severity: "warning"
110004
- };
110005
- }
110495
+ const finding = await linkTargetAbsentFinding({ to }, bundleTargetReader(bundle));
110496
+ if (!finding) return void 0;
110497
+ return {
110498
+ code: finding.code,
110499
+ message: `target '${to}' has no document yet \u2014 this link is a forward-declaration (dangling links stay allowed); create it with \`${cliInvocation()} doc write ${commandToken(to)} --type <t>\`.`,
110500
+ field: "to",
110501
+ severity: "warning"
110502
+ };
110006
110503
  }
110007
110504
  async function link2(argv2, deps2 = {}) {
110008
110505
  const stdout = deps2.stdout ?? ((s) => void process.stdout.write(s));
@@ -110073,7 +110570,7 @@ async function addLink(bundle, from, to, opts = {}) {
110073
110570
  maxAttempts: LINK_ADD_MAX_ATTEMPTS,
110074
110571
  buildCandidate: (source2, context3) => {
110075
110572
  const existing = source2;
110076
- sourceTypeAtWrite = docType2(existing);
110573
+ sourceTypeAtWrite = docType3(existing);
110077
110574
  const already = parseLinks2(bundle, existing).some((l) => l.to === normalizedTo && l.text === text7);
110078
110575
  if (already) return { frontmatter: { ...existing.frontmatter }, body: existing.body };
110079
110576
  const trimmed = existing.body.replace(/\s*$/, "");
@@ -110188,7 +110685,7 @@ async function addQualifiedLink(bundle, from, to, opts = {}) {
110188
110685
  maxAttempts: LINK_ADD_MAX_ATTEMPTS,
110189
110686
  buildCandidate: (source2, context3) => {
110190
110687
  const existing = source2;
110191
- sourceTypeAtWrite = docType2(existing);
110688
+ sourceTypeAtWrite = docType3(existing);
110192
110689
  const already = parseQualifiedLinks(existing).some(
110193
110690
  (l) => l.ref?.alias === finalAlias && l.ref.id === id && l.text === text7
110194
110691
  );
@@ -110570,6 +111067,7 @@ var init_link = __esm({
110570
111067
  init_command_spec();
110571
111068
  init_output2();
110572
111069
  init_invocation();
111070
+ init_write_findings();
110573
111071
  init_src();
110574
111072
  init_bundle_bindings();
110575
111073
  init_actor();
@@ -112630,8 +113128,6 @@ async function newCommand(argv2, deps2 = {}) {
112630
113128
  stdout(renderKindHelp(projectKindForAuthoring(okfVersion, kind2), registry2, cliInvocation()));
112631
113129
  return;
112632
113130
  }
112633
- const authoringKind = projectKindForAuthoring(okfVersion, kind2);
112634
- const declaredFields = [...authoringKind.fields.required, ...authoringKind.fields.optional];
112635
113131
  const fieldNames = kindInputFieldNames(okfVersion, kind2).filter((f) => f !== "actor" && f !== "link");
112636
113132
  const fieldOptions = Object.fromEntries(
112637
113133
  fieldNames.map((f) => [f, { type: "string", multiple: true }])
@@ -112649,9 +113145,10 @@ async function newCommand(argv2, deps2 = {}) {
112649
113145
  if (err?.code === "ERR_PARSE_ARGS_UNKNOWN_OPTION") {
112650
113146
  const raw = /'([^']+)'/.exec(err.message)?.[1] ?? "";
112651
113147
  const field = raw.replace(/^--?/, "");
113148
+ const { kind: governs, declared } = kindFieldsUndeclaredFinding(okfVersion, kind2, [field]).details;
112652
113149
  throw new CliError(
112653
113150
  "USAGE",
112654
- `unknown field(s) for kind '${kind2.governs}': ${field}` + (declaredFields.length > 0 ? ` (declared: ${declaredFields.join(", ")})` : " (this kind declares no fields)") + ` \u2014 to ADD it to the '${kind2.governs}' kind: \`${cliInvocation()} kind field ${commandToken(kind2.governs)} add ${commandToken(field)}\` (then re-run).`,
113151
+ `unknown field(s) for kind '${governs}': ${field}` + (declared.length > 0 ? ` (declared: ${declared.join(", ")})` : " (this kind declares no fields)") + ` \u2014 to ADD it to the '${governs}' kind: \`${cliInvocation()} kind field ${commandToken(governs)} add ${commandToken(field)}\` (then re-run).`,
112655
113152
  { help: `${cliInvocation()} kinds` }
112656
113153
  );
112657
113154
  }
@@ -112774,7 +113271,9 @@ async function newCommand(argv2, deps2 = {}) {
112774
113271
  const conventionWarnings = registry2.warnings.filter(
112775
113272
  (warning) => warning.message.startsWith(conventionWarningPrefix)
112776
113273
  );
112777
- if (conventionWarnings.length > 0) receipt5.warnings = conventionWarnings;
113274
+ const findings = await writeFindings(bundle, saved, registry2, void 0);
113275
+ const warnings = [...conventionWarnings, ...findings];
113276
+ if (warnings.length > 0) receipt5.warnings = warnings;
112778
113277
  if (result3.guidance.length > 0) receipt5.guidance = result3.guidance;
112779
113278
  if (targetId !== id) {
112780
113279
  receipt5.note = `id prefixed with the '${kind2.governs}' kind's path \u2192 '${targetId}' (you passed '${id}')`;
@@ -112784,9 +113283,9 @@ async function newCommand(argv2, deps2 = {}) {
112784
113283
  let finalVersion = result3.version;
112785
113284
  let firstLinkFailure;
112786
113285
  for (const { type, target: target3 } of parsedLinks) {
112787
- const warnings = [];
113286
+ const warnings2 = [];
112788
113287
  if (kind2.links && Object.keys(kind2.links).length > 0 && !hasOwn4(kind2.links, type)) {
112789
- warnings.push({
113288
+ warnings2.push({
112790
113289
  code: "LINK_TYPE_UNDECLARED_FOR_KIND",
112791
113290
  message: `'${type}' is not declared in the '${kind2.governs}' kind's link vocabulary (declared: ${Object.keys(kind2.links).join(", ")}) \u2014 added anyway.`,
112792
113291
  field: "text",
@@ -112796,13 +113295,13 @@ async function newCommand(argv2, deps2 = {}) {
112796
113295
  try {
112797
113296
  const added = await addLink(bundle, saved.id, target3, { text: type, actor });
112798
113297
  finalVersion = added.version;
112799
- if (added.warnings) warnings.push(...added.warnings);
113298
+ if (added.warnings) warnings2.push(...added.warnings);
112800
113299
  linkResults.push({
112801
113300
  type,
112802
113301
  target: target3,
112803
113302
  changed: added.changed,
112804
113303
  href: added.href,
112805
- ...warnings.length > 0 ? { warnings } : {}
113304
+ ...warnings2.length > 0 ? { warnings: warnings2 } : {}
112806
113305
  });
112807
113306
  satisfiedOutboundTypes.add(type);
112808
113307
  } catch (err) {
@@ -112811,7 +113310,7 @@ async function newCommand(argv2, deps2 = {}) {
112811
113310
  type,
112812
113311
  target: target3,
112813
113312
  error: { code: classified.code, message: classified.message },
112814
- ...warnings.length > 0 ? { warnings } : {}
113313
+ ...warnings2.length > 0 ? { warnings: warnings2 } : {}
112815
113314
  });
112816
113315
  if (!firstLinkFailure) firstLinkFailure = classified;
112817
113316
  }
@@ -112819,7 +113318,7 @@ async function newCommand(argv2, deps2 = {}) {
112819
113318
  if (parsedLinks.length > 0) receipt5.links = linkResults;
112820
113319
  receipt5.version = finalVersion;
112821
113320
  if (isLegacyPageDoc(saved.frontmatter)) receipt5.hint = LEGACY_PAGE_TYPE_HINT;
112822
- const help2 = [`${cliInvocation()} doc read ${commandToken(saved.id)}`];
113321
+ const help2 = [`${cliInvocation()} doc read ${commandToken(saved.id)}`, ...writeFindingsHelp(findings)];
112823
113322
  const HINTS_PER_DIRECTION = 3;
112824
113323
  for (const { source: source2, linkType } of inboundLinkDecls(registry2, kind2).slice(0, HINTS_PER_DIRECTION)) {
112825
113324
  help2.push(
@@ -112861,6 +113360,7 @@ var init_new = __esm({
112861
113360
  init_command_spec();
112862
113361
  init_output2();
112863
113362
  init_invocation();
113363
+ init_write_findings();
112864
113364
  init_mutate();
112865
113365
  init_kind_authoring();
112866
113366
  init_legacy_page2();
@@ -112885,6 +113385,8 @@ The kind's declared body 'sections' (if any) are scaffolded as empty '# Heading'
112885
113385
  'path' prefix (if any) is prepended onto <id> unless <id> already carries it. Validation is
112886
113386
  STRICT: a missing required field, a disallowed enum value, or a value that does not match the
112887
113387
  field's declared type (fields.types) rejects the write (exit 2) rather than writing-with-a-warning.
113388
+ Links in the body that will not register, or whose target does not exist yet, are named in the
113389
+ receipt's warnings (LINK_NOT_RECOGNIZED, LINK_TARGET_ABSENT) without refusing the create.
112888
113390
  A typed number, integer, latitude, longitude, or boolean field is stored as that YAML type
112889
113391
  (--latitude 43.1 stores the number 43.1; pass a negative number as --longitude=-77.4); a
112890
113392
  string-list or https-url-list field is always stored as a list, even from one flag. An integer
@@ -114852,8 +115354,8 @@ async function ordinaryDirectory(value, home2, bundle) {
114852
115354
  async function localBundle(dir, cwd = process.cwd(), home2 = homedir37()) {
114853
115355
  const target3 = await resolveLocalBundleTarget(dir, cwd);
114854
115356
  assertBundleOutsidePrivateState(target3.canonicalRoot, home2);
114855
- const facts = await bundleHomeAt(target3.canonicalRoot, { home: typeof home2 === "string" ? home2 : homedir37() });
114856
- if (facts.home === "hosted") throw refuse2("hosted_local_execution_not_supported");
115357
+ const facts2 = await bundleHomeAt(target3.canonicalRoot, { home: typeof home2 === "string" ? home2 : homedir37() });
115358
+ if (facts2.home === "hosted") throw refuse2("hosted_local_execution_not_supported");
114857
115359
  if (process.platform !== "darwin" && process.platform !== "linux") throw refuse2("unsupported_supervision_platform");
114858
115360
  return target3.canonicalRoot;
114859
115361
  }
@@ -116980,12 +117482,12 @@ async function status(argv2, deps2 = {}) {
116980
117482
  stdout(render(record19, resolveMode(values)));
116981
117483
  return;
116982
117484
  }
116983
- const facts = await bundleHomeAt(await realpath13(bundle.root), { home: home2 });
116984
- if (facts.home === "git") {
116985
- const block = await gitBoardSyncBlock(facts.board);
116986
- const record19 = { home: "git", sync: block, ...unboundCopyOf(facts), ...out };
117485
+ const facts2 = await bundleHomeAt(await realpath13(bundle.root), { home: home2 });
117486
+ if (facts2.home === "git") {
117487
+ const block = await gitBoardSyncBlock(facts2.board);
117488
+ const record19 = { home: "git", sync: block, ...unboundCopyOf(facts2), ...out };
116987
117489
  if (block.state !== "clean") {
116988
- const first = block.conflicts ? (await unsettledConflicts(facts.board.top, resolveBundleKey(facts.board.top)))[0] : void 0;
117490
+ const first = block.conflicts ? (await unsettledConflicts(facts2.board.top, resolveBundleKey(facts2.board.top)))[0] : void 0;
116989
117491
  const row5 = first ? unsettledRow(first, cliInvocation(), values.dir) : void 0;
116990
117492
  const onlySaved = block.state === "needs_decision" && !block.ahead && !block.uncommitted;
116991
117493
  record19.help = [
@@ -116996,7 +117498,7 @@ async function status(argv2, deps2 = {}) {
116996
117498
  stdout(render(record19, resolveMode(values)));
116997
117499
  return;
116998
117500
  }
116999
- stdout(render({ home: "local", sync: "none (local only)", ...unboundCopyOf(facts), ...out }, resolveMode(values)));
117501
+ stdout(render({ home: "local", sync: "none (local only)", ...unboundCopyOf(facts2), ...out }, resolveMode(values)));
117000
117502
  }
117001
117503
  var STATUS_USAGE, DEFAULT_LIMIT4;
117002
117504
  var init_status2 = __esm({
@@ -117359,7 +117861,7 @@ __export(util_exports, {
117359
117861
  own: () => own4,
117360
117862
  parsedType: () => parsedType,
117361
117863
  partial: () => partial,
117362
- pick: () => pick,
117864
+ pick: () => pick2,
117363
117865
  prefixIssues: () => prefixIssues,
117364
117866
  primitiveTypes: () => primitiveTypes,
117365
117867
  promiseAllObject: () => promiseAllObject,
@@ -117659,7 +118161,7 @@ function optionalKeys(shape3) {
117659
118161
  return shape3[k]._zod.optin !== void 0 && shape3[k]._zod.optout === "optional";
117660
118162
  });
117661
118163
  }
117662
- function pick(schema, mask) {
118164
+ function pick2(schema, mask) {
117663
118165
  const currDef = schema._zod.def;
117664
118166
  const checks = currDef.checks;
117665
118167
  const hasChecks = checks && checks.length > 0;
@@ -154496,10 +154998,10 @@ function unboundCopyGuard(copy, home2, folder, options) {
154496
154998
  freshen: async () => adopted?.freshen(),
154497
154999
  async admit(method, args) {
154498
155000
  if (!adopted) {
154499
- const facts = await bundleHomeAt(copy.folder, { home: home2 });
154500
- if (facts.home === "hosted") adopted = checkoutGuard(facts.binding, home2, folder, options);
154501
- else if (facts.home === "local" && facts.copy) {
154502
- throw unboundCopyRefusal(facts.copy, "FORBIDDEN", `'mcp write' refused: ${copy.folder} is a copy of a hosted checkout of '${facts.copy.marker.bundle_id}' that is not bound here, so nothing written in it reaches the host`, { command: "mcp write" });
155001
+ const facts2 = await bundleHomeAt(copy.folder, { home: home2 });
155002
+ if (facts2.home === "hosted") adopted = checkoutGuard(facts2.binding, home2, folder, options);
155003
+ else if (facts2.home === "local" && facts2.copy) {
155004
+ throw unboundCopyRefusal(facts2.copy, "FORBIDDEN", `'mcp write' refused: ${copy.folder} is a copy of a hosted checkout of '${facts2.copy.marker.bundle_id}' that is not bound here, so nothing written in it reaches the host`, { command: "mcp write" });
154503
155005
  } else return;
154504
155006
  }
154505
155007
  return adopted.admit(method, args);
@@ -154762,8 +155264,8 @@ function createCatalogMcpWorkspaceResolver(options = {}) {
154762
155264
  };
154763
155265
  const checkoutOf2 = async (selector2) => {
154764
155266
  const { target: target3 } = await select(selector2, async () => void 0);
154765
- const facts = await bundleHomeAt(target3.canonicalRoot, { home: home2 });
154766
- return facts.home === "hosted" ? facts.binding : { stop: "no_host_operations", home: facts.home };
155267
+ const facts2 = await bundleHomeAt(target3.canonicalRoot, { home: home2 });
155268
+ return facts2.home === "hosted" ? facts2.binding : { stop: "no_host_operations", home: facts2.home };
154767
155269
  };
154768
155270
  const connect = async (binding2) => {
154769
155271
  const resume2 = commandFragment`${cliInvocation()} login --host ${commandToken(bindingHostArgument(binding2))}`;
@@ -157439,17 +157941,17 @@ import { homedir as homedir46 } from "node:os";
157439
157941
  import { parseArgs as parseArgs33 } from "node:util";
157440
157942
  import path66 from "node:path";
157441
157943
  async function bundleFreshness(root, userHome, now, signIn, env) {
157442
- const facts = await bundleHomeAt(root, { home: userHome });
157443
- if (facts.home === "hosted") {
157444
- const age = ageMs((await readFreshness(userHome, facts.binding.checkout_id).catch(() => null))?.pulled_at ?? null, now);
157944
+ const facts2 = await bundleHomeAt(root, { home: userHome });
157945
+ if (facts2.home === "hosted") {
157946
+ const age = ageMs((await readFreshness(userHome, facts2.binding.checkout_id).catch(() => null))?.pulled_at ?? null, now);
157445
157947
  const pulled = age === null ? "never pulled" : `pulled ${describeAge(age)} ago`;
157446
- const key4 = `${facts.binding.origin} ${facts.binding.audience}`;
157447
- if (!signIn.has(key4)) signIn.set(key4, storedSessionMayNeedSignIn(userHome, facts.binding, env, now.getTime()).catch(() => false));
157948
+ const key4 = `${facts2.binding.origin} ${facts2.binding.audience}`;
157949
+ if (!signIn.has(key4)) signIn.set(key4, storedSessionMayNeedSignIn(userHome, facts2.binding, env, now.getTime()).catch(() => false));
157448
157950
  return { home: "hosted", freshness: await signIn.get(key4) ? `${pulled}; may need sign-in` : pulled };
157449
157951
  }
157450
- if (facts.home === "git") {
157451
- if (!facts.board.shared) return { home: "git", freshness: "not shared yet" };
157452
- const age = ageMs(await lastFetch(facts.board.top).catch(() => null), now);
157952
+ if (facts2.home === "git") {
157953
+ if (!facts2.board.shared) return { home: "git", freshness: "not shared yet" };
157954
+ const age = ageMs(await lastFetch(facts2.board.top).catch(() => null), now);
157453
157955
  return { home: "git", freshness: age === null ? "never fetched" : `fetched ${describeAge(age)} ago` };
157454
157956
  }
157455
157957
  return { home: "local", freshness: "local only" };
@@ -159184,10 +159686,10 @@ function homeOf(deps2) {
159184
159686
  }
159185
159687
  async function locate(sub, rawId, dir, deps2) {
159186
159688
  const target3 = await resolveLocalBundleTarget(dir, deps2.cwd ?? process.cwd());
159187
- const facts = await bundleHomeAt(target3.canonicalRoot, { home: homeOf(deps2) });
159188
- if (facts.home !== "hosted") {
159189
- throw new CliError("USAGE", `view ${sub} reaches a hosted checkout's host; this is a ${facts.home} bundle, whose View pages are plain files: ${sub === "read" ? "read" : "edit"} the file directly`, {
159190
- details: { reason: "not_a_hosted_checkout", home: facts.home },
159689
+ const facts2 = await bundleHomeAt(target3.canonicalRoot, { home: homeOf(deps2) });
159690
+ if (facts2.home !== "hosted") {
159691
+ throw new CliError("USAGE", `view ${sub} reaches a hosted checkout's host; this is a ${facts2.home} bundle, whose View pages are plain files: ${sub === "read" ? "read" : "edit"} the file directly`, {
159692
+ details: { reason: "not_a_hosted_checkout", home: facts2.home },
159191
159693
  help: `${cliInvocation()} view list --dir ${commandToken(target3.canonicalRoot)} names each View; its page is the registration's entry file`
159192
159694
  });
159193
159695
  }
@@ -159195,10 +159697,10 @@ async function locate(sub, rawId, dir, deps2) {
159195
159697
  const registryId = await resolveConceptIdCliArgument(bundle, rawId);
159196
159698
  if (!isAnyRegistryId(registryId)) {
159197
159699
  throw new CliError("USAGE", `'${registryId}' is not a View registration id (views-registry/<name>)`, {
159198
- help: `${cliInvocation()} view list --dir ${commandToken(facts.binding.path)}`
159700
+ help: `${cliInvocation()} view list --dir ${commandToken(facts2.binding.path)}`
159199
159701
  });
159200
159702
  }
159201
- return { binding: facts.binding, root: target3.canonicalRoot, registryId };
159703
+ return { binding: facts2.binding, root: target3.canonicalRoot, registryId };
159202
159704
  }
159203
159705
  async function hostRegistration(connection, located) {
159204
159706
  const { binding: binding2, registryId } = located;
@@ -163602,8 +164104,8 @@ async function op(argv2, deps2 = {}) {
163602
164104
  }
163603
164105
  async function homeOf2(dir, deps2) {
163604
164106
  const target3 = await resolveLocalBundleTarget(dir, deps2.cwd ?? process.cwd());
163605
- const facts = await bundleHomeAt(target3.canonicalRoot, { home: deps2.hosted?.auth?.home ?? homedir56() });
163606
- return facts.home === "hosted" ? { home: "hosted", binding: facts.binding } : { home: facts.home };
164107
+ const facts2 = await bundleHomeAt(target3.canonicalRoot, { home: deps2.hosted?.auth?.home ?? homedir56() });
164108
+ return facts2.home === "hosted" ? { home: "hosted", binding: facts2.binding } : { home: facts2.home };
163607
164109
  }
163608
164110
  function noHostOperations(home2) {
163609
164111
  return `no host operations for a ${home2} bundle; use the typed verbs (${TYPED_VERBS}, ...)`;
@@ -163915,8 +164417,8 @@ async function checkoutOf(scope, deps2) {
163915
164417
  if (scope.dir === void 0 && error62 instanceof CliError && error62.code === "NOT_FOUND") return null;
163916
164418
  throw error62;
163917
164419
  }
163918
- const facts = await bundleHomeAt(canonicalRoot, { home: deps2.hosted?.auth?.home ?? homedir57() });
163919
- return facts.home === "hosted" ? facts.binding : null;
164420
+ const facts2 = await bundleHomeAt(canonicalRoot, { home: deps2.hosted?.auth?.home ?? homedir57() });
164421
+ return facts2.home === "hosted" ? facts2.binding : null;
163920
164422
  }
163921
164423
  async function openInboxSession(command, scope, deps2, resumeFor, options = {}) {
163922
164424
  const explicit = scope.host !== void 0 || scope.workspace !== void 0 || scope.bundle !== void 0;
@@ -164037,7 +164539,7 @@ async function inboxFailure(error62, session2, extra = {}) {
164037
164539
  case "invalid_input":
164038
164540
  return new CliError("USAGE", message, { details, help: `${cliInvocation()} notify --help` });
164039
164541
  case "attention_disabled":
164040
- return new CliError("FORBIDDEN", message, { details, help: "a workspace admin turns the inbox on for the workspace" });
164542
+ return new CliError("FORBIDDEN", message, { details, help: "the inbox is turned off for this workspace: ask Superbee support to turn it on" });
164041
164543
  case "insufficient_scope":
164042
164544
  case "workspace_not_available":
164043
164545
  case "workspace_unsupported":
@@ -164397,17 +164899,17 @@ function itemIdOf(value, sub) {
164397
164899
  if (!ITEM_ID.test(value)) throw usage3(`'${value}' is not an item id as inbox list reports it`, sub);
164398
164900
  return value;
164399
164901
  }
164400
- function sender(facts, display, you) {
164401
- const yours = facts.principalId === you;
164902
+ function sender(facts2, display, you) {
164903
+ const yours = facts2.principalId === you;
164402
164904
  return {
164403
164905
  person: yours ? "you" : display.personName ?? "a workspace member",
164404
- principal: facts.principalId ?? null,
164405
- ...facts.surface ? { surface: facts.surface } : {},
164906
+ principal: facts2.principalId ?? null,
164907
+ ...facts2.surface ? { surface: facts2.surface } : {},
164406
164908
  ...display.firstPartyName ? { app: display.firstPartyName } : {},
164407
164909
  ...display.clientName ? { client: display.clientName } : {},
164408
164910
  ...display.agentName ? { agent: display.agentName } : {},
164409
- ...facts.via ? { tool_label: facts.via } : {},
164410
- ...facts.job ? { job: facts.job } : {}
164911
+ ...facts2.via ? { tool_label: facts2.via } : {},
164912
+ ...facts2.job ? { job: facts2.job } : {}
164411
164913
  };
164412
164914
  }
164413
164915
  function labelOf(entry) {
@@ -166056,28 +166558,28 @@ async function rootTitle(folder) {
166056
166558
  function cleanName(name) {
166057
166559
  return stripHostText(name, 128);
166058
166560
  }
166059
- async function assertPublishable(canonical2, facts) {
166060
- if (facts.home === "hosted") {
166061
- throw new CliError("FORBIDDEN", `${canonical2} is already a hosted checkout of '${facts.binding.bundle_id}' on ${facts.binding.origin}`, {
166062
- details: { reason: "already_hosted", folder: canonical2, bundle_id: facts.binding.bundle_id, host: facts.binding.origin },
166561
+ async function assertPublishable(canonical2, facts2) {
166562
+ if (facts2.home === "hosted") {
166563
+ throw new CliError("FORBIDDEN", `${canonical2} is already a hosted checkout of '${facts2.binding.bundle_id}' on ${facts2.binding.origin}`, {
166564
+ details: { reason: "already_hosted", folder: canonical2, bundle_id: facts2.binding.bundle_id, host: facts2.binding.origin },
166063
166565
  help: `${cliInvocation()} sync --dir ${commandToken(canonical2)}`
166064
166566
  });
166065
166567
  }
166066
- if (facts.copy) {
166067
- throw unboundCopyRefusal(facts.copy, "FORBIDDEN", `${canonical2} is a copy of a hosted checkout of '${facts.copy.marker.bundle_id}'; adopt it instead of publishing a second bundle`);
166568
+ if (facts2.copy) {
166569
+ throw unboundCopyRefusal(facts2.copy, "FORBIDDEN", `${canonical2} is a copy of a hosted checkout of '${facts2.copy.marker.bundle_id}'; adopt it instead of publishing a second bundle`);
166068
166570
  }
166069
- if (facts.home === "git" && facts.board.channel === "in-tree") {
166070
- throw new CliError("FORBIDDEN", `${canonical2} is committed with the code on ${facts.board.branch ?? "this branch"}; publishing it would leave two authorities`, {
166571
+ if (facts2.home === "git" && facts2.board.channel === "in-tree") {
166572
+ throw new CliError("FORBIDDEN", `${canonical2} is committed with the code on ${facts2.board.branch ?? "this branch"}; publishing it would leave two authorities`, {
166071
166573
  details: { reason: "in_tree_board", folder: canonical2 },
166072
166574
  help: `move it to its own board branch first: ${cliInvocation()} sync --establish`
166073
166575
  });
166074
166576
  }
166075
166577
  const dotGit = await lstat17(path79.join(canonical2, ".git")).catch(() => null);
166076
166578
  if (dotGit) {
166077
- const linkedBoard = facts.home === "git" && facts.board.channel === "branch" && dotGit.isFile() && isLinkedWorktree2(canonical2);
166579
+ const linkedBoard = facts2.home === "git" && facts2.board.channel === "branch" && dotGit.isFile() && isLinkedWorktree2(canonical2);
166078
166580
  if (!linkedBoard) {
166079
- throw new CliError("FORBIDDEN", `${canonical2} is a Git ${dotGit.isFile() ? "worktree" : "repository"} that publish cannot unbind${facts.home === "git" ? " (a clone of the board branch, not a project's board worktree)" : ""}`, {
166080
- details: { reason: facts.home === "git" ? "board_clone" : "git_working_tree", folder: canonical2 },
166581
+ throw new CliError("FORBIDDEN", `${canonical2} is a Git ${dotGit.isFile() ? "worktree" : "repository"} that publish cannot unbind${facts2.home === "git" ? " (a clone of the board branch, not a project's board worktree)" : ""}`, {
166582
+ details: { reason: facts2.home === "git" ? "board_clone" : "git_working_tree", folder: canonical2 },
166081
166583
  help: "copy the bundle's files (without .git) into a new folder and publish that, or publish from the project whose board worktree this is"
166082
166584
  });
166083
166585
  }
@@ -166316,10 +166818,10 @@ async function publish(argv2, partial2 = {}) {
166316
166818
  const located = await resolveLocalBundleTarget(values.dir, deps2.cwd);
166317
166819
  const canonical2 = located.canonicalRoot;
166318
166820
  assertBundleOutsidePrivateState(canonical2, home2);
166319
- const facts = await bundleHomeAt(canonical2, { home: home2 });
166320
- await assertPublishable(canonical2, facts);
166821
+ const facts2 = await bundleHomeAt(canonical2, { home: home2 });
166822
+ await assertPublishable(canonical2, facts2);
166321
166823
  refuseTreePrivateState(canonical2, "publish --to hosted", String(commandFragment`${cliInvocation()} publish --to hosted${values.dir !== void 0 ? commandFragment` --dir ${commandToken(canonical2)}` : commandFragment``}`));
166322
- const board = facts.home === "git" ? facts.board : null;
166824
+ const board = facts2.home === "git" ? facts2.board : null;
166323
166825
  if (values.yes && board?.channel === "branch") {
166324
166826
  try {
166325
166827
  fetchOrigin(board.top);
@@ -166375,7 +166877,7 @@ async function publish(argv2, partial2 = {}) {
166375
166877
  publish: "preview",
166376
166878
  ready: blockers.length === 0,
166377
166879
  folder: canonical2,
166378
- home: facts.home,
166880
+ home: facts2.home,
166379
166881
  to: {
166380
166882
  host: target3?.origin ?? null,
166381
166883
  ...chosen ? { host_from: chosen.source } : ambiguous ? { signed_in_hosts: ambiguous.details?.hosts } : {},
@@ -166459,7 +166961,7 @@ async function publish(argv2, partial2 = {}) {
166459
166961
  provenance: { carried: plan.provenance.carried, dropped: plan.provenance.dropped }
166460
166962
  },
166461
166963
  folder: canonical2,
166462
- home: facts.home,
166964
+ home: facts2.home,
166463
166965
  checkout: `not converted: ${uncheckable}`,
166464
166966
  diverges: `this folder${board ? " and its Git board" : ""} and the hosted bundle '${bundleId2}' are now separate copies: edits here do not reach the hosted bundle`,
166465
166967
  help: [hostedListCommand(target3)]