superbee 0.4.3-pre.10 → 0.4.3-pre.11

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.
Files changed (2) hide show
  1. package/dist/superbee.mjs +127 -30
  2. package/package.json +1 -1
package/dist/superbee.mjs CHANGED
@@ -44,7 +44,7 @@ var __toESM = (mod, isNodeMode, target3) => (target3 = mod != null ? __create(__
44
44
  var define_SUPERBEE_BUILD_IDENTITY_default;
45
45
  var init_define_SUPERBEE_BUILD_IDENTITY = __esm({
46
46
  "<define:__SUPERBEE_BUILD_IDENTITY__>"() {
47
- define_SUPERBEE_BUILD_IDENTITY_default = { schema: "superbee.build-identity.v1", package: { name: "superbee", version: "0.4.3-pre.10" }, source: { commit: "d5af6d38ba7c1eb5e47541925a6922606c36bd1a", dirty: false }, artifact: { channel: "npm-package" }, compatibility_contracts: { skill: 1, hook: 1, mcp: 1 } };
47
+ define_SUPERBEE_BUILD_IDENTITY_default = { schema: "superbee.build-identity.v1", package: { name: "superbee", version: "0.4.3-pre.11" }, source: { commit: "747849f327a718d1d5bc11d87450efd90ad9efca", dirty: false }, artifact: { channel: "npm-package" }, compatibility_contracts: { skill: 1, hook: 1, mcp: 1 } };
48
48
  }
49
49
  });
50
50
 
@@ -18068,15 +18068,17 @@ function materializeRecipeForEdition(recipe2, okfVersion) {
18068
18068
  function recipeDocumentForApply(doc2, okfVersion, now) {
18069
18069
  return okfVersion === "0.1" ? { ...doc2, frontmatter: { ...doc2.frontmatter, timestamp: now } } : { ...doc2, frontmatter: { ...doc2.frontmatter } };
18070
18070
  }
18071
- async function createRecipeDocument(bundle, doc2, okfVersion, now) {
18071
+ async function createRecipeDocument(bundle, doc2, okfVersion, now, actor) {
18072
18072
  const result3 = await mutateDocument({
18073
18073
  bundle,
18074
18074
  id: doc2.id,
18075
18075
  mode: "create-only",
18076
18076
  registry: RECIPE_WRITE_REGISTRY,
18077
18077
  strict: false,
18078
+ actor,
18078
18079
  // Installed definitions must stay byte-comparable to their recipe source (sameInstalledDoc
18079
- // strips generated.at but not an engine-seeded generated.by), so never seed a clock here.
18080
+ // preserves upstream generated.by). Record the installer separately as mutation attribution,
18081
+ // without manufacturing content provenance or replacing the recipe producer.
18080
18082
  seedGenerationClock: false,
18081
18083
  now: () => now,
18082
18084
  buildCandidate: (_existing, context) => {
@@ -18091,6 +18093,9 @@ async function createRecipeDocument(bundle, doc2, okfVersion, now) {
18091
18093
  async function installRecipe(bundle, recipe2, options = {}) {
18092
18094
  const now = options.now ?? (/* @__PURE__ */ new Date()).toISOString();
18093
18095
  const okfVersion = await readBundleOkfVersion2(bundle) ?? "0.1";
18096
+ if (okfVersion === "0.2" && options.actor !== void 0 && !isOkfActor(options.actor)) {
18097
+ throw new OkfActorError(options.actor, `OKF v0.2 mutation actor '${options.actor}' must be human:<id>, process:<id>, or <producer>/<version>`);
18098
+ }
18094
18099
  const source = recipe2;
18095
18100
  recipe2 = materializeRecipeForEdition(recipe2, okfVersion);
18096
18101
  const identity = recipeStampIdentity(source, recipe2);
@@ -18126,7 +18131,7 @@ async function installRecipe(bundle, recipe2, options = {}) {
18126
18131
  let changed = true;
18127
18132
  let sourceDiffers2 = false;
18128
18133
  try {
18129
- doc2 = await createRecipeDocument(bundle, doc2, okfVersion, now);
18134
+ doc2 = await createRecipeDocument(bundle, doc2, okfVersion, now, options.actor);
18130
18135
  stamps.push("current");
18131
18136
  } catch (err) {
18132
18137
  if (err instanceof VersionConflict) {
@@ -18156,7 +18161,7 @@ async function installRecipe(bundle, recipe2, options = {}) {
18156
18161
  let changed = true;
18157
18162
  let sourceDiffers2 = false;
18158
18163
  try {
18159
- await createRecipeDocument(bundle, doc2, okfVersion, now);
18164
+ await createRecipeDocument(bundle, doc2, okfVersion, now, options.actor);
18160
18165
  stamps.push("current");
18161
18166
  } catch (err) {
18162
18167
  if (!(err instanceof VersionConflict)) throw err;
@@ -18228,7 +18233,7 @@ async function installRecipe(bundle, recipe2, options = {}) {
18228
18233
  let registry2 = recipeDocumentForApply(page.registry, okfVersion, now);
18229
18234
  let registryChanged = true;
18230
18235
  try {
18231
- registry2 = await createRecipeDocument(bundle, registry2, okfVersion, now);
18236
+ registry2 = await createRecipeDocument(bundle, registry2, okfVersion, now, options.actor);
18232
18237
  } catch (err) {
18233
18238
  if (!(err instanceof VersionConflict)) throw err;
18234
18239
  const existing = await readDoc2(bundle, registry2.id);
@@ -18245,10 +18250,10 @@ async function installRecipe(bundle, recipe2, options = {}) {
18245
18250
  }
18246
18251
  const references = [];
18247
18252
  for (const reference of recipe2.references) {
18248
- let desired = recipeDocumentForApply(reference.doc, okfVersion, now);
18253
+ let desired = withRecipeStamp(recipeDocumentForApply(reference.doc, okfVersion, now), identity);
18249
18254
  let changed = true;
18250
18255
  try {
18251
- desired = await createRecipeDocument(bundle, desired, okfVersion, now);
18256
+ desired = await createRecipeDocument(bundle, desired, okfVersion, now, options.actor);
18252
18257
  } catch (err) {
18253
18258
  if (!(err instanceof VersionConflict)) throw err;
18254
18259
  const existing = await readDoc2(bundle, desired.id);
@@ -18361,6 +18366,9 @@ async function assertPortableTargetsCompatible(bundle, recipe2, now, okfVersion)
18361
18366
  for (const doc2 of referenceDocs) installedReferences.set(doc2.id, doc2);
18362
18367
  }
18363
18368
  for (const reference of recipe2.references) {
18369
+ if (reference.doc.frontmatter.type !== "Reference") {
18370
+ throw new RecipeInputError(`recipe '${recipe2.id}' asset '${reference.doc.id}' must have type 'Reference'`);
18371
+ }
18364
18372
  const existing = installedReferences.get(reference.doc.id);
18365
18373
  if (!existing) continue;
18366
18374
  const desired = recipeDocumentForApply(reference.doc, okfVersion, now);
@@ -18379,6 +18387,9 @@ function sameBytes(a, b) {
18379
18387
  function sameInstalledDoc(existing, desired, okfVersion) {
18380
18388
  const { timestamp: _existingTimestamp, [RECIPE_STAMP_KEY]: _existingStamp, ...existingFrontmatter } = existing.frontmatter;
18381
18389
  const { timestamp: _desiredTimestamp, [RECIPE_STAMP_KEY]: _desiredStamp, ...desiredFrontmatter } = desired.frontmatter;
18390
+ const actorField = okfVersion === "0.2" ? "superbee_updated_by" : "actor";
18391
+ delete existingFrontmatter[actorField];
18392
+ delete desiredFrontmatter[actorField];
18382
18393
  if (desiredFrontmatter.order === void 0) delete existingFrontmatter.order;
18383
18394
  if (okfVersion === "0.2") {
18384
18395
  for (const frontmatter of [existingFrontmatter, desiredFrontmatter]) {
@@ -18419,6 +18430,7 @@ var init_install = __esm({
18419
18430
  init_content_type();
18420
18431
  init_document_mutation();
18421
18432
  init_errors();
18433
+ init_okf_actor();
18422
18434
  init_kinds();
18423
18435
  init_okf_authored_values();
18424
18436
  init_okf_standard_fields();
@@ -18457,8 +18469,9 @@ function setOwn3(record9, key2, value) {
18457
18469
  writable: true
18458
18470
  });
18459
18471
  }
18460
- function additiveConventionCandidate(existing, desired, blockers) {
18472
+ function additiveConventionCandidate(existing, desired, blockers, canReplaceDescriptions) {
18461
18473
  const addedPaths = [];
18474
+ const descriptionReplacements = [];
18462
18475
  const merge2 = (current, next, pointer2) => {
18463
18476
  if (current === void 0) {
18464
18477
  addedPaths.push(pointer2);
@@ -18475,6 +18488,10 @@ function additiveConventionCandidate(existing, desired, blockers) {
18475
18488
  return current;
18476
18489
  }
18477
18490
  if (okfValuesEqual(current, next)) return current;
18491
+ if (canReplaceDescriptions && /^\/frontmatter\/fields\/descriptions\/[^/]+$/.test(pointer2) && typeof current === "string" && typeof next === "string") {
18492
+ descriptionReplacements.push({ path: pointer2, old: current, new: next });
18493
+ return next;
18494
+ }
18478
18495
  if (Array.isArray(current) && Array.isArray(next)) {
18479
18496
  const merged = [...current];
18480
18497
  for (const value of current) {
@@ -18544,10 +18561,11 @@ function additiveConventionCandidate(existing, desired, blockers) {
18544
18561
  }
18545
18562
  return {
18546
18563
  candidate: { id: desired.id, frontmatter: candidateFrontmatter, body },
18547
- addedPaths: [...new Set(addedPaths)].sort()
18564
+ addedPaths: [...new Set(addedPaths)].sort(),
18565
+ descriptionReplacements: descriptionReplacements.sort((a, b) => a.path.localeCompare(b.path))
18548
18566
  };
18549
18567
  }
18550
- function connectorReplacement(existing, desired) {
18568
+ function ownedAssetReplacement(existing, desired) {
18551
18569
  const frontmatter = {};
18552
18570
  for (const [key2, value] of Object.entries(desired.frontmatter)) {
18553
18571
  if (!PRESERVED_ROOT_METADATA.has(key2)) setOwn3(frontmatter, key2, value);
@@ -18751,6 +18769,7 @@ async function prepareRecipeEvolution(bundle, sourceRecipe) {
18751
18769
  ...warning.field ? { field: warning.field } : {}
18752
18770
  }));
18753
18771
  const definitions = [];
18772
+ const references = [];
18754
18773
  const writes = /* @__PURE__ */ new Map();
18755
18774
  const proofs = [];
18756
18775
  const desiredKinds = /* @__PURE__ */ new Map();
@@ -18844,7 +18863,9 @@ async function prepareRecipeEvolution(bundle, sourceRecipe) {
18844
18863
  "governs"
18845
18864
  );
18846
18865
  }
18847
- const merged = additiveConventionCandidate(existing.doc, target3, blockers);
18866
+ const identityState = recipeStampState(existing.doc, identity);
18867
+ const canReplaceDescriptions = (identityState === "current" || identityState === "stale") && conventionStampState(existing.doc) === "current";
18868
+ const merged = additiveConventionCandidate(existing.doc, target3, blockers, canReplaceDescriptions);
18848
18869
  let candidate = merged.candidate;
18849
18870
  if (okfVersion === "0.2") {
18850
18871
  try {
@@ -18883,7 +18904,6 @@ async function prepareRecipeEvolution(bundle, sourceRecipe) {
18883
18904
  }
18884
18905
  const desiredVersion = contentVersion(comparableRecipeDoc(candidate, okfVersion));
18885
18906
  const unchanged2 = sameInstalledDoc(existing.doc, candidate, okfVersion);
18886
- const identityState = recipeStampState(existing.doc, identity);
18887
18907
  const stamp = unchanged2 && identityState === "current" && conventionStampState(existing.doc) === "diverged" && definitionDigest(existing.doc) === definitionDigest(target3) ? "stale" : identityState;
18888
18908
  definitions.push({
18889
18909
  id: target3.id,
@@ -18892,7 +18912,8 @@ async function prepareRecipeEvolution(bundle, sourceRecipe) {
18892
18912
  stamp,
18893
18913
  expected_version: existing.version,
18894
18914
  desired_version: desiredVersion,
18895
- added_paths: unchanged2 ? [] : merged.addedPaths
18915
+ added_paths: unchanged2 ? [] : merged.addedPaths,
18916
+ ...merged.descriptionReplacements.length > 0 ? { description_replacements: merged.descriptionReplacements } : {}
18896
18917
  });
18897
18918
  if (!unchanged2) writes.set(target3.id, withRecipeStamp(candidate, identity));
18898
18919
  else if (stamp === "stale" || stamp === "missing") writes.set(target3.id, withRecipeStamp(existing.doc, identity));
@@ -18958,7 +18979,7 @@ async function prepareRecipeEvolution(bundle, sourceRecipe) {
18958
18979
  );
18959
18980
  continue;
18960
18981
  }
18961
- let candidate = connectorReplacement(existing.doc, target3);
18982
+ let candidate = ownedAssetReplacement(existing.doc, target3);
18962
18983
  if (okfVersion === "0.2") {
18963
18984
  try {
18964
18985
  const withMetadata = applyV02MutationMetadata({
@@ -19016,11 +19037,53 @@ async function prepareRecipeEvolution(bundle, sourceRecipe) {
19016
19037
  blockers,
19017
19038
  "RECIPE_EVOLUTION_ASSET_CHANGE_UNSUPPORTED",
19018
19039
  target3.id,
19019
- `recipe evolution does not replace an existing ${kind2 === "reference" ? "Reference" : "View registry"} asset`
19040
+ "recipe evolution does not replace an existing View registry asset"
19020
19041
  );
19021
19042
  }
19022
19043
  };
19023
- for (const reference of recipe2.references) await assetDocProof("reference", reference.doc);
19044
+ for (const reference of recipe2.references) {
19045
+ const target3 = recipeDocumentForApply({ ...reference.doc, body: normalizeDocumentBodyForStorage(reference.doc.body) }, okfVersion, "1970-01-01T00:00:00.000Z");
19046
+ const existing = await readRecipeDocIfPresent(bundle, target3.id);
19047
+ let candidate = existing ? ownedAssetReplacement(existing.doc, target3) : target3;
19048
+ if (existing && okfVersion === "0.2") {
19049
+ const producer = plainRecord2(existing.doc.frontmatter.generated)?.by;
19050
+ try {
19051
+ candidate = { id: target3.id, ...applyV02MutationMetadata({
19052
+ existing: existing.doc,
19053
+ candidate: { frontmatter: candidate.frontmatter, body: candidate.body },
19054
+ ...typeof producer === "string" ? { producer } : {},
19055
+ meaningfulChangeAt: "1970-01-01T00:00:00.000Z",
19056
+ allowGeneratedProvenanceSeed: false
19057
+ }) };
19058
+ } catch (error51) {
19059
+ if (!(error51 instanceof InvalidInputError)) throw error51;
19060
+ evolutionBlocker(blockers, "RECIPE_EVOLUTION_WRITE_POLICY_INVALID", target3.id, `prospective Reference cannot satisfy the OKF v0.2 write policy: ${error51.message}`);
19061
+ }
19062
+ }
19063
+ const wanted = contentVersion(comparableRecipeDoc(candidate, okfVersion));
19064
+ const stamp = recipeStampState(existing?.doc ?? null, identity);
19065
+ const unchanged2 = existing !== null && sameInstalledDoc(existing.doc, candidate, okfVersion);
19066
+ references.push({ id: target3.id, action: !existing ? "missing" : unchanged2 ? "unchanged" : "update", stamp, expected_version: existing?.version ?? null, desired_version: wanted });
19067
+ proofs.push({ kind: "reference", id: target3.id, current_version: existing?.version ?? null, desired_version: wanted });
19068
+ if (!existing) {
19069
+ evolutionBlocker(blockers, "RECIPE_EVOLUTION_ASSET_MISSING", target3.id, `recipe asset '${target3.id}' is not installed; install the complete recipe with 'recipe add' first`);
19070
+ continue;
19071
+ }
19072
+ let reason;
19073
+ if (existing.doc.frontmatter.type !== "Reference" || target3.frontmatter.type !== "Reference") reason = "is not a Reference";
19074
+ else if (stamp === "foreign") reason = "belongs to another recipe";
19075
+ else if (stamp === "missing") {
19076
+ if (Object.hasOwn(existing.doc.frontmatter, RECIPE_STAMP_KEY)) reason = "has an unreadable recipe stamp";
19077
+ else if (!sameInstalledDoc(existing.doc, target3, okfVersion)) reason = "has no ownership stamp and differs from the selected source";
19078
+ } else if (conventionStampState(existing.doc) !== "current") reason = "has locally changed content or unreadable digest rules";
19079
+ if (reason) {
19080
+ evolutionBlocker(blockers, "RECIPE_EVOLUTION_REFERENCE_UNPROVEN", target3.id, `Reference '${target3.id}' ${reason}; evolution cannot prove recipe ownership and leaves it untouched`);
19081
+ continue;
19082
+ }
19083
+ if (!unchanged2) writes.set(target3.id, withRecipeStamp(candidate, identity));
19084
+ else if (stamp === "missing" || stamp === "stale") writes.set(target3.id, withRecipeStamp(existing.doc, identity));
19085
+ }
19086
+ references.sort((a, b) => a.id.localeCompare(b.id));
19024
19087
  for (const page of recipe2.pages) {
19025
19088
  await assetDocProof("view-registry", page.registry);
19026
19089
  const existing = await readBlob2(bundle, page.entry);
@@ -19120,6 +19183,7 @@ async function prepareRecipeEvolution(bundle, sourceRecipe) {
19120
19183
  recipe: { id: recipe2.id, version: recipe2.version, source: recipe2.source, source_digest: identity.source_digest },
19121
19184
  okfVersion,
19122
19185
  definitions,
19186
+ ...references.length > 0 ? { references } : {},
19123
19187
  proofs,
19124
19188
  blockers
19125
19189
  });
@@ -19135,10 +19199,19 @@ async function prepareRecipeEvolution(bundle, sourceRecipe) {
19135
19199
  source: recipe2.source,
19136
19200
  okf_version: okfVersion,
19137
19201
  ready: blockers.length === 0,
19138
- changed: updates > 0,
19202
+ changed: updates > 0 || references.some((row5) => row5.action === "update"),
19139
19203
  writes: writes.size,
19140
19204
  plan_token: token,
19141
19205
  definitions,
19206
+ ...references.length > 0 ? { reference_assets: {
19207
+ rows: references,
19208
+ counts: {
19209
+ updates: references.filter((row5) => row5.action === "update").length,
19210
+ stamp_writes: references.filter((row5) => writes.has(row5.id) && row5.action !== "update").length,
19211
+ unchanged: references.filter((row5) => row5.action === "unchanged").length,
19212
+ missing: references.filter((row5) => row5.action === "missing").length
19213
+ }
19214
+ } } : {},
19142
19215
  counts: {
19143
19216
  definitions: definitions.length,
19144
19217
  updates,
@@ -19167,15 +19240,18 @@ async function applyRecipeEvolution(bundle, recipe2, expectedPlanToken, options
19167
19240
  throw new RecipeEvolutionBlocked(plan.id, plan.blockers);
19168
19241
  }
19169
19242
  const completed = [];
19170
- const pending = plan.definitions.filter((definition2) => prepared.writes.has(definition2.id)).map((definition2) => definition2.id);
19171
- for (const definition2 of plan.definitions) {
19243
+ const targets = [...plan.definitions, ...(plan.reference_assets?.rows ?? []).map((row5) => ({ ...row5, asset_kind: "reference" }))];
19244
+ const pending = targets.filter((definition2) => prepared.writes.has(definition2.id)).map((definition2) => definition2.id);
19245
+ for (const definition2 of targets) {
19246
+ const asset = "asset_kind" in definition2 ? { asset_kind: definition2.asset_kind } : {};
19172
19247
  const planned = prepared.writes.get(definition2.id);
19173
19248
  if (planned === void 0) {
19174
- completed.push({ id: definition2.id, changed: false, stamped: false, version: definition2.expected_version });
19249
+ completed.push({ id: definition2.id, ...asset, changed: false, stamped: false, version: definition2.expected_version });
19175
19250
  continue;
19176
19251
  }
19177
19252
  const now = (/* @__PURE__ */ new Date()).toISOString();
19178
19253
  const desired = recipeDocumentForApply(planned, plan.okf_version, now);
19254
+ const sourceProducer = "asset_kind" in definition2 ? plainRecord2(desired.frontmatter.generated)?.by : void 0;
19179
19255
  try {
19180
19256
  const result3 = await mutateDocument({
19181
19257
  bundle,
@@ -19190,7 +19266,9 @@ async function applyRecipeEvolution(bundle, recipe2, expectedPlanToken, options
19190
19266
  // explicitly opts out of seeding provenance when the installed definition has none.
19191
19267
  seedGenerationClock: false,
19192
19268
  // Evolution preserves source-comparable attribution; the backend still records its writer.
19193
- persistActor: false,
19269
+ persistActor: "asset_kind" in definition2,
19270
+ // Reference replacement retains its existing content producer; actor is advisory.
19271
+ ...typeof sourceProducer === "string" ? { producer: sourceProducer } : {},
19194
19272
  actor,
19195
19273
  now: () => now,
19196
19274
  buildCandidate: (_existing, context) => {
@@ -19202,6 +19280,7 @@ async function applyRecipeEvolution(bundle, recipe2, expectedPlanToken, options
19202
19280
  });
19203
19281
  completed.push({
19204
19282
  id: definition2.id,
19283
+ ...asset,
19205
19284
  changed: definition2.action === "update" && result3.changed,
19206
19285
  stamped: true,
19207
19286
  version: result3.version
@@ -19247,7 +19326,7 @@ async function applyRecipeEvolution(bundle, recipe2, expectedPlanToken, options
19247
19326
  } catch (error51) {
19248
19327
  throw new RecipeEvolutionPostcondition(
19249
19328
  "unverifiable",
19250
- `recipe evolution wrote ${written} definition(s), but its postcondition could not be verified: ${error51 instanceof Error ? error51.message : String(error51)}`,
19329
+ `recipe evolution wrote ${written} ${plan.reference_assets ? "target(s)" : "definition(s)"}, but its postcondition could not be verified: ${error51 instanceof Error ? error51.message : String(error51)}`,
19251
19330
  completed,
19252
19331
  { cause: error51 }
19253
19332
  );
@@ -19255,7 +19334,7 @@ async function applyRecipeEvolution(bundle, recipe2, expectedPlanToken, options
19255
19334
  if (!postcondition.plan.ready || postcondition.plan.changed || postcondition.plan.writes > 0) {
19256
19335
  throw new RecipeEvolutionPostcondition(
19257
19336
  "changed",
19258
- `recipe evolution wrote ${written} definition(s), but the bundle changed (a definition or its stamp) before the postcondition check; a fresh recipe evolve plan shows the current state`,
19337
+ `recipe evolution wrote ${written} ${plan.reference_assets ? "target(s)" : "definition(s)"}, but the bundle changed (${plan.reference_assets ? "a target" : "a definition"} or its stamp) before the postcondition check; a fresh recipe evolve plan shows the current state`,
19259
19338
  completed,
19260
19339
  { blockers: postcondition.plan.blockers, postcondition_plan: postcondition.plan.plan_token }
19261
19340
  );
@@ -19267,8 +19346,20 @@ async function applyRecipeEvolution(bundle, recipe2, expectedPlanToken, options
19267
19346
  source: plan.source,
19268
19347
  changed: written > 0,
19269
19348
  plan_token: plan.plan_token,
19270
- definitions: completed,
19271
- counts: { updated, stamped, unchanged: completed.length - written }
19349
+ definitions: completed.filter((row5) => row5.asset_kind !== "reference"),
19350
+ ...plan.reference_assets ? { reference_assets: {
19351
+ rows: completed.filter((row5) => row5.asset_kind === "reference"),
19352
+ counts: {
19353
+ updated: completed.filter((row5) => row5.asset_kind === "reference" && row5.changed).length,
19354
+ stamped: completed.filter((row5) => row5.asset_kind === "reference" && row5.stamped && !row5.changed).length,
19355
+ unchanged: completed.filter((row5) => row5.asset_kind === "reference" && !row5.stamped).length
19356
+ }
19357
+ } } : {},
19358
+ counts: {
19359
+ updated: completed.filter((row5) => row5.asset_kind !== "reference" && row5.changed).length,
19360
+ stamped: completed.filter((row5) => row5.asset_kind !== "reference" && row5.stamped && !row5.changed).length,
19361
+ unchanged: completed.filter((row5) => row5.asset_kind !== "reference" && !row5.stamped).length
19362
+ }
19272
19363
  };
19273
19364
  }
19274
19365
  var RECIPE_EVOLUTION_WRITE_REGISTRY, PRESERVED_ROOT_METADATA, BUNDLE_LOCAL_PLACEMENT, RESTRICTION_BLOCKER_DOC_CAP;
@@ -19283,6 +19374,7 @@ var init_evolution = __esm({
19283
19374
  init_document_mutation();
19284
19375
  init_document_write_policy();
19285
19376
  init_errors();
19377
+ init_frontmatter();
19286
19378
  init_kinds();
19287
19379
  init_link_types();
19288
19380
  init_links();
@@ -22372,7 +22464,7 @@ var init_command_spec = __esm({
22372
22464
  {
22373
22465
  id: "recipeAdd",
22374
22466
  leaves: [publicLeaf("recipeAdd", "recipe add", one, 17, DIR_RECIPE_ROOT_SURFACE)],
22375
- usage: "recipe add <name-or-path> [--dir <path>] [--remote <url>]",
22467
+ usage: "recipe add <name-or-path> [--actor <name>] [--dir <path>] [--remote <url>]",
22376
22468
  summary: "Apply a recipe's content-free definitions \u2014 Kinds plus optional declared References and Views \u2014 idempotently"
22377
22469
  },
22378
22470
  {
@@ -96861,6 +96953,7 @@ async function recipeAdd(argv2, stdout) {
96861
96953
  options: {
96862
96954
  dir: { type: "string" },
96863
96955
  remote: { type: "string" },
96956
+ actor: { type: "string" },
96864
96957
  json: { type: "boolean" },
96865
96958
  help: { type: "boolean", short: "h" }
96866
96959
  },
@@ -96878,6 +96971,7 @@ async function recipeAdd(argv2, stdout) {
96878
96971
  help: `${cliInvocation()} recipes`
96879
96972
  });
96880
96973
  }
96974
+ const actor = resolveActor(values.actor);
96881
96975
  const loaded = await resolveRecipe(ref);
96882
96976
  if (!loaded.ok) {
96883
96977
  throw new CliError("USAGE", loaded.error.message, {
@@ -96888,9 +96982,10 @@ async function recipeAdd(argv2, stdout) {
96888
96982
  if (values.remote === void 0) await assertRecipeAllowedInHostedCheckout("recipe add", values.dir, loaded.recipe);
96889
96983
  const remote = await resolveRemoteFlag(values.remote, values.dir);
96890
96984
  const bundle = await openBundle(values.dir, remote);
96985
+ await assertActorAcceptedByBundle(bundle, actor);
96891
96986
  let result3;
96892
96987
  try {
96893
- result3 = await installRecipe(bundle, loaded.recipe);
96988
+ result3 = await installRecipe(bundle, loaded.recipe, { actor });
96894
96989
  } catch (error51) {
96895
96990
  throw classifyBundleError(error51);
96896
96991
  }
@@ -96949,7 +97044,7 @@ var init_recipe = __esm({
96949
97044
  RECIPE_USAGE = `superbee recipe \u2014 apply a recipe to this bundle
96950
97045
 
96951
97046
  Usage:
96952
- superbee recipe add <name-or-path> [--dir <path>] [--remote <url>]
97047
+ superbee recipe add <name-or-path> [--actor <name>] [--dir <path>] [--remote <url>]
96953
97048
  superbee recipe evolve <name-or-path> [--apply <plan-token>] [--actor <name>] [options]
96954
97049
 
96955
97050
  Applies a recipe's definitions to the bundle. <name-or-path> is a built-in name (e.g.
@@ -96991,7 +97086,9 @@ Options:
96991
97086
  --remote <url> Talk to a wire-protocol server instead of a local bundle
96992
97087
  (mutually exclusive with --dir; remote access is always explicit)
96993
97088
  --apply <plan-token> Apply the exact ready token returned by 'recipe evolve' (evolve only)
96994
- --actor <name> Attribute evolved convention writes (evolve only). OKF v0.2 bundles accept
97089
+ --actor <name> Attribute installed or evolved document writes. Add resolves --actor over
97090
+ SUPERBEE_ACTOR, legacy AGENTSTATE_LITE_ACTOR, then absent; conflicting
97091
+ environment values refuse. OKF v0.2 bundles accept
96995
97092
  only an OKF actor: human:<id>, process:<id>, or <producer>/<version>
96996
97093
  (e.g. openai/codex)
96997
97094
  --json Emit compact JSON instead of TOON
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superbee",
3
- "version": "0.4.3-pre.10",
3
+ "version": "0.4.3-pre.11",
4
4
  "type": "module",
5
5
  "description": "Agent-facing Superbee CLI for reading and writing local OKF knowledge bundles: context notes, docs, cross-links, and live bundle Views.",
6
6
  "keywords": [