superbee 0.4.2 → 0.4.3-pre.1

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/README.md CHANGED
@@ -53,7 +53,11 @@ Requires a supported Node.js 22, 24, or 26 release (22.14.0 minimum) on macOS or
53
53
  npm install -g superbee
54
54
  ```
55
55
 
56
- Stable releases publish on npm's `latest` tag and prereleases on `next`.
56
+ Stable releases publish on npm's `latest` tag and prereleases on `next`. To try the prerelease:
57
+
58
+ ```sh
59
+ npm install -g superbee@next
60
+ ```
57
61
 
58
62
  Windows adapters and the `superbee-windows` executable live in a separate repository and are
59
63
  not included in `superbee`. Most Windows users should run Superbee in WSL2, where npm sees a
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.2" }, source: { commit: "069a42092f39d8261ccd4322c0dc7ff5488aa2c8", 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.1" }, source: { commit: "0c5c7f2b2437d3e33a4aa707f13704e9896482a6", dirty: false }, artifact: { channel: "npm-package" }, compatibility_contracts: { skill: 1, hook: 1, mcp: 1 } };
48
48
  }
49
49
  });
50
50
 
@@ -6070,15 +6070,15 @@ function lexicalPosixHookTokens(command) {
6070
6070
  const raw = command.slice(start, i);
6071
6071
  const current = renderGeneratedHookToken(token);
6072
6072
  const historical = renderHistoricalDoubleQuotedHookToken(token);
6073
- const envelope2 = raw === current ? "current" : raw === historical ? "historical_double" : void 0;
6074
- if (!envelope2) return void 0;
6075
- tokens.push({ raw, value: token, envelope: envelope2 });
6073
+ const envelope3 = raw === current ? "current" : raw === historical ? "historical_double" : void 0;
6074
+ if (!envelope3) return void 0;
6075
+ tokens.push({ raw, value: token, envelope: envelope3 });
6076
6076
  if (i < command.length) {
6077
6077
  i += 1;
6078
6078
  if (i === command.length || command[i] === " ") return void 0;
6079
6079
  }
6080
6080
  }
6081
- if (tokens.some(({ envelope: envelope2 }) => envelope2 === "historical_double")) {
6081
+ if (tokens.some(({ envelope: envelope3 }) => envelope3 === "historical_double")) {
6082
6082
  const exactHistoricalCommand = tokens.length === 2 && tokens[0]?.envelope === "historical_double" && tokens[1]?.envelope === "current" && tokens[1]?.raw === "session-start";
6083
6083
  if (!exactHistoricalCommand) return void 0;
6084
6084
  }
@@ -7980,8 +7980,8 @@ function render(value, mode) {
7980
7980
  `;
7981
7981
  }
7982
7982
  }
7983
- function renderErrorEnvelope(envelope2) {
7984
- return `${encode(envelope2)}
7983
+ function renderErrorEnvelope(envelope3) {
7984
+ return `${encode(envelope3)}
7985
7985
  `;
7986
7986
  }
7987
7987
  function renderUsage(usage3) {
@@ -8892,8 +8892,8 @@ function assertValidExpectedVersion(expectedVersion) {
8892
8892
  }
8893
8893
  async function refusesIdentity(res) {
8894
8894
  try {
8895
- const envelope2 = await res.json();
8896
- return envelope2?.error?.code === "USAGE" && envelope2.error.message === IDENTITY_UNSUPPORTED;
8895
+ const envelope3 = await res.json();
8896
+ return envelope3?.error?.code === "USAGE" && envelope3.error.message === IDENTITY_UNSUPPORTED;
8897
8897
  } catch {
8898
8898
  return false;
8899
8899
  }
@@ -8911,8 +8911,8 @@ function etagForm(token) {
8911
8911
  async function namesMalformedDocument(res) {
8912
8912
  if (res.status !== 500) return false;
8913
8913
  try {
8914
- const envelope2 = await res.clone().json();
8915
- return typeof envelope2?.error?.details?.malformed?.reason === "string";
8914
+ const envelope3 = await res.clone().json();
8915
+ return typeof envelope3?.error?.details?.malformed?.reason === "string";
8916
8916
  } catch {
8917
8917
  return false;
8918
8918
  }
@@ -9006,26 +9006,26 @@ var init_remote_backend = __esm({
9006
9006
  }
9007
9007
  /** Parse a non-2xx response into the typed error the engine expects. */
9008
9008
  async toError(res, fallbackId) {
9009
- let envelope2 = null;
9009
+ let envelope3 = null;
9010
9010
  try {
9011
- envelope2 = await res.json();
9011
+ envelope3 = await res.json();
9012
9012
  } catch {
9013
- envelope2 = null;
9013
+ envelope3 = null;
9014
9014
  }
9015
9015
  if (res.status === 412) {
9016
- const expected = envelope2?.error?.details?.expected ?? null;
9017
- const actual = envelope2?.error?.details?.actual ?? null;
9016
+ const expected = envelope3?.error?.details?.expected ?? null;
9017
+ const actual = envelope3?.error?.details?.actual ?? null;
9018
9018
  return new VersionConflict(fallbackId, expected, actual);
9019
9019
  }
9020
- const malformedDoc = envelope2?.error?.details?.malformed;
9020
+ const malformedDoc = envelope3?.error?.details?.malformed;
9021
9021
  if (malformedDoc && typeof malformedDoc.reason === "string") {
9022
9022
  return new MalformedDocumentError(
9023
9023
  typeof malformedDoc.id === "string" ? malformedDoc.id : fallbackId,
9024
9024
  new Error(malformedDoc.reason)
9025
9025
  );
9026
9026
  }
9027
- const message = envelope2?.error?.message ?? `wire request failed with status ${res.status}`;
9028
- const code3 = envelope2?.error?.code ?? (res.status === 401 ? "AUTH_REQUIRED" : res.status >= 500 ? "RUNTIME" : "USAGE");
9027
+ const message = envelope3?.error?.message ?? `wire request failed with status ${res.status}`;
9028
+ const code3 = envelope3?.error?.code ?? (res.status === 401 ? "AUTH_REQUIRED" : res.status >= 500 ? "RUNTIME" : "USAGE");
9029
9029
  return new RemoteError(message, code3, res.status);
9030
9030
  }
9031
9031
  async read(id) {
@@ -9048,8 +9048,8 @@ var init_remote_backend = __esm({
9048
9048
  if (res.status === 404) {
9049
9049
  let missing2 = [];
9050
9050
  try {
9051
- const envelope2 = await res.json();
9052
- missing2 = envelope2.error.details?.missing ?? [];
9051
+ const envelope3 = await res.json();
9052
+ missing2 = envelope3.error.details?.missing ?? [];
9053
9053
  } catch {
9054
9054
  }
9055
9055
  throw notFound3(missing2[0] ?? ids[0]);
@@ -11728,6 +11728,184 @@ var init_governed_body_write = __esm({
11728
11728
  }
11729
11729
  });
11730
11730
 
11731
+ // ../core/src/kind-coverage.ts
11732
+ function bodyProse(body) {
11733
+ let relatedLevel;
11734
+ for (const line2 of body.split("\n")) {
11735
+ const text5 = line2.trim();
11736
+ const heading = /^(#{1,6})[ \t]+(.+?)\s*#*\s*$/.exec(text5);
11737
+ if (heading) {
11738
+ const level2 = heading[1].length;
11739
+ if (relatedLevel !== void 0 && level2 <= relatedLevel) relatedLevel = void 0;
11740
+ if (heading[2].trim().toLowerCase() === "related" && relatedLevel === void 0) relatedLevel = level2;
11741
+ continue;
11742
+ }
11743
+ if (relatedLevel !== void 0) continue;
11744
+ const prose = text5.replace(/^[-*] +/, "");
11745
+ if (!prose) continue;
11746
+ const links = extractMarkdownLinks(prose);
11747
+ if (!(links.length === 1 && prose === `[${links[0].text}](${links[0].href})`)) return true;
11748
+ }
11749
+ return false;
11750
+ }
11751
+ function fieldStats(docs, value) {
11752
+ let present = 0, sentinels = 0, used = 0;
11753
+ for (const doc2 of docs) {
11754
+ const v2 = value(doc2);
11755
+ if (v2 !== void 0) used++;
11756
+ if (filled(v2)) present++;
11757
+ else if (sentinel(v2)) sentinels++;
11758
+ }
11759
+ return { present: used, filled: present, sentinel: sentinels, empty: docs.length - present - sentinels, rate: ratio(present, docs.length) };
11760
+ }
11761
+ function checkedOn(kind2, docs, now) {
11762
+ const buckets = { future: 0, "0-7d": 0, "8-30d": 0, "31-90d": 0, "91-180d": 0, "181-365d": 0, ">365d": 0 };
11763
+ let missing2 = 0, invalid = 0, older = 0;
11764
+ const horizon = freshnessHorizonMs(kind2);
11765
+ for (const doc2 of docs) {
11766
+ const value = doc2.frontmatter.checked_on;
11767
+ if (!filled(value)) {
11768
+ missing2++;
11769
+ continue;
11770
+ }
11771
+ const ms = typeof value === "string" ? parseTimestamp(/^\d{4}-\d{2}-\d{2}$/.test(value) ? `${value}T00:00:00Z` : value, "0.2") : null;
11772
+ if (ms === null) {
11773
+ invalid++;
11774
+ continue;
11775
+ }
11776
+ const ageMs2 = now.getTime() - ms;
11777
+ const days = Math.floor(ageMs2 / DAY);
11778
+ const bucket = days < 0 ? "future" : days <= 7 ? "0-7d" : days <= 30 ? "8-30d" : days <= 90 ? "31-90d" : days <= 180 ? "91-180d" : days <= 365 ? "181-365d" : ">365d";
11779
+ buckets[bucket]++;
11780
+ if (horizon !== void 0 && ageMs2 > horizon) older++;
11781
+ }
11782
+ return { clock: "checked_on", horizon: kind2.freshnessHorizon ?? null, horizon_ms: horizon ?? null, missing: missing2, invalid, buckets, older_than_horizon: horizon === void 0 ? null : older };
11783
+ }
11784
+ function sourceStats(docs) {
11785
+ const domains = /* @__PURE__ */ new Map();
11786
+ const distribution2 = { "0": 0, "1": 0, "2": 0, "3": 0, "4": 0, "5+": 0 };
11787
+ let total = 0, zero2 = 0, invalid = 0, nonUrl = 0;
11788
+ for (const doc2 of docs) {
11789
+ const raw = doc2.frontmatter.sources;
11790
+ const list4 = Array.isArray(raw) ? raw : raw == null ? [] : [raw];
11791
+ let count5 = 0;
11792
+ for (const item of list4) {
11793
+ const resource = typeof item === "string" ? item : item && typeof item === "object" && !Array.isArray(item) ? item.resource : void 0;
11794
+ if (typeof resource !== "string" || !filled(resource)) {
11795
+ invalid++;
11796
+ continue;
11797
+ }
11798
+ count5++;
11799
+ try {
11800
+ const domain3 = new URL(resource).hostname.toLowerCase().replace(/^www\./, "");
11801
+ if (!domain3) {
11802
+ nonUrl++;
11803
+ continue;
11804
+ }
11805
+ domains.set(domain3, (domains.get(domain3) ?? 0) + 1);
11806
+ } catch {
11807
+ nonUrl++;
11808
+ }
11809
+ }
11810
+ if (!count5) zero2++;
11811
+ total += count5;
11812
+ distribution2[count5 >= 5 ? "5+" : String(count5)]++;
11813
+ }
11814
+ const ordered = [...domains].sort((a, b) => b[1] - a[1] || compare(a[0], b[0]));
11815
+ return { zero: zero2, total, invalid_entries: invalid, non_url_resources: nonUrl, per_record: distribution2, distinct_domains: domains.size, domains_shown: Math.min(domains.size, DOMAIN_LIMIT), top_domains: ordered.slice(0, DOMAIN_LIMIT).map(([domain3, sources]) => ({ domain: domain3, sources })) };
11816
+ }
11817
+ function kindCoverage(registry2, documents, options) {
11818
+ if (!Number.isFinite(options.now.getTime())) throw new TypeError("Coverage now must be a valid date");
11819
+ const docs = [...documents].sort((a, b) => compare(a.id, b.id));
11820
+ const index2 = new Map(docs.map((doc2) => [doc2.id, doc2]));
11821
+ const edges = new Map(docs.map((doc2) => [doc2.id, parseLinksFromDoc(doc2)]));
11822
+ const inbound = new Set([...edges.values()].flat().map((link4) => link4.to));
11823
+ const groups = /* @__PURE__ */ new Map();
11824
+ for (const doc2 of docs) {
11825
+ const type = doc2.frontmatter.type;
11826
+ const group = groups.get(type) ?? [];
11827
+ group.push(doc2);
11828
+ groups.set(type, group);
11829
+ }
11830
+ const kinds2 = [...registry2.kinds.values()].filter((kind2) => options.kind === void 0 || kind2.governs === options.kind).map((kind2) => {
11831
+ const records = groups.get(kind2.governs) ?? [];
11832
+ const authoring = projectKindForAuthoring(options.okfVersion, kind2);
11833
+ const fields2 = [.../* @__PURE__ */ new Set([...authoring.fields.required, ...authoring.fields.optional])].sort(compare);
11834
+ const stats = fields2.map((field) => ({ field, required: authoring.fields.required.includes(field), ...fieldStats(records, (doc2) => readKindField(options.okfVersion, kind2, doc2.frontmatter, field)) }));
11835
+ const declaredStorage = new Set(fields2.map((field) => resolveKindFieldCoordinate(options.okfVersion, kind2, field)?.storageField ?? field));
11836
+ const undeclared = /* @__PURE__ */ new Map(), envelopes = /* @__PURE__ */ new Map();
11837
+ for (const doc2 of records) for (const key2 of Object.keys(doc2.frontmatter)) {
11838
+ if (envelope(key2)) {
11839
+ envelopes.set(key2, (envelopes.get(key2) ?? 0) + 1);
11840
+ continue;
11841
+ }
11842
+ if (!declaredStorage.has(key2)) {
11843
+ const ids = undeclared.get(key2) ?? [];
11844
+ ids.push(doc2.id);
11845
+ undeclared.set(key2, ids);
11846
+ }
11847
+ }
11848
+ const relations = /* @__PURE__ */ new Map();
11849
+ let citations = 0, dangling = 0, withLinks = 0;
11850
+ const danglingExamples = [];
11851
+ for (const doc2 of records) {
11852
+ const links = edges.get(doc2.id);
11853
+ if (links.length) withLinks++;
11854
+ for (const link4 of links) {
11855
+ const target3 = index2.get(link4.to);
11856
+ if (!target3) {
11857
+ dangling++;
11858
+ if (danglingExamples.length < EXAMPLES) danglingExamples.push(doc2.id);
11859
+ }
11860
+ if (!Object.hasOwn(kind2.links ?? {}, link4.text)) {
11861
+ citations++;
11862
+ continue;
11863
+ }
11864
+ const targetKind = target3?.frontmatter.type ?? null;
11865
+ const key2 = JSON.stringify([link4.text, targetKind]);
11866
+ const row4 = relations.get(key2) ?? { relation: link4.text, target_kind: targetKind, target_matches: targetKind === null ? null : targetKind === kind2.links[link4.text], records: /* @__PURE__ */ new Set(), links: 0 };
11867
+ row4.records.add(doc2.id);
11868
+ row4.links++;
11869
+ relations.set(key2, row4);
11870
+ }
11871
+ }
11872
+ const used = new Set([...relations.values()].map((row4) => row4.relation));
11873
+ return {
11874
+ governs: kind2.governs,
11875
+ records: records.length,
11876
+ coverage: { fields: stats, body_prose: { filled: records.filter((doc2) => bodyProse(doc2.body)).length, rate: ratio(records.filter((doc2) => bodyProse(doc2.body)).length, records.length) } },
11877
+ drift: { undeclared: [...undeclared].sort(([a], [b]) => compare(a, b)).map(([key2, ids]) => ({ key: key2, records: ids.length, rate: ratio(ids.length, records.length), examples: ids.slice(0, EXAMPLES), examples_total: ids.length })), declared_unused: stats.filter((row4) => row4.present === 0).map((row4) => row4.field), envelope: [...envelopes].sort(([a], [b]) => compare(a, b)).map(([key2, records2]) => ({ key: key2, records: records2 })) },
11878
+ links: { with_links: withLinks, typed: [...relations.values()].sort((a, b) => compare(a.relation, b.relation) || compare(a.target_kind ?? "", b.target_kind ?? "")).map((row4) => ({ relation: row4.relation, target_kind: row4.target_kind, target_matches: row4.target_matches, records: row4.records.size, links: row4.links, rate: ratio(row4.records.size, records.length) })), untyped_citations: citations, declared_never_used: Object.keys(kind2.links ?? {}).filter((relation) => !used.has(relation)).sort(compare), dangling, dangling_examples: danglingExamples, no_inbound: records.filter((doc2) => !inbound.has(doc2.id)).length },
11879
+ freshness: checkedOn(kind2, records, options.now),
11880
+ sources: sourceStats(records)
11881
+ };
11882
+ });
11883
+ return { now: options.now.toISOString(), documents: docs.length, undeclared_kinds: [...groups.keys()].filter((type) => !registry2.kinds.has(type)).sort(compare), kinds: kinds2 };
11884
+ }
11885
+ var SENTINELS, EXAMPLES, DOMAIN_LIMIT, DAY, compare, ratio, empty, sentinel, filled, envelope;
11886
+ var init_kind_coverage = __esm({
11887
+ "../core/src/kind-coverage.ts"() {
11888
+ "use strict";
11889
+ init_define_SUPERBEE_BUILD_IDENTITY();
11890
+ init_define_SUPERBEE_UPDATE_POLICY();
11891
+ init_document_field_actions();
11892
+ init_kinds();
11893
+ init_links();
11894
+ init_managed_document_metadata();
11895
+ init_freshness();
11896
+ SENTINELS = /* @__PURE__ */ new Set(["unknown", "n/a", "na", "none", "tbd", "null", "-", "?"]);
11897
+ EXAMPLES = 3;
11898
+ DOMAIN_LIMIT = 15;
11899
+ DAY = 864e5;
11900
+ compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
11901
+ ratio = (n, total) => total ? Math.round(n / total * 1e4) / 1e4 : null;
11902
+ empty = (value) => value == null || typeof value === "string" && value.trim() === "" || (Array.isArray(value) ? value.length === 0 : typeof value === "object" && Object.keys(value).length === 0);
11903
+ sentinel = (value) => typeof value === "string" && SENTINELS.has(value.trim().toLowerCase());
11904
+ filled = (value) => !empty(value) && !sentinel(value);
11905
+ envelope = (key2) => isManagedDocumentMetadataField(key2) || isStandardDocumentSetField(key2, "0.2") || key2 === "sources" || key2 === "tags";
11906
+ }
11907
+ });
11908
+
11731
11909
  // ../core/src/index.ts
11732
11910
  var init_src = __esm({
11733
11911
  "../core/src/index.ts"() {
@@ -11771,6 +11949,7 @@ var init_src = __esm({
11771
11949
  init_document_mutation();
11772
11950
  init_kind_field_mutation();
11773
11951
  init_managed_document_metadata();
11952
+ init_kind_coverage();
11774
11953
  }
11775
11954
  });
11776
11955
 
@@ -15822,12 +16001,12 @@ function resolveCompatibleScalarEnv(opts) {
15822
16001
  const env = opts.env ?? process.env;
15823
16002
  const present = [opts.canonical, opts.legacy].filter((name) => hasOwn4(env, name)).map((name) => ({ name, value: (env[name] ?? "").trim() }));
15824
16003
  if (!present.length) return void 0;
15825
- const empty2 = present.filter((entry) => entry.value === "");
15826
- if (opts.requireNonEmpty && empty2.length) {
15827
- const sources = empty2.map((entry) => entry.name).join(" and ");
16004
+ const empty3 = present.filter((entry) => entry.value === "");
16005
+ if (opts.requireNonEmpty && empty3.length) {
16006
+ const sources = empty3.map((entry) => entry.name).join(" and ");
15828
16007
  throw new CliError(
15829
16008
  "USAGE",
15830
- `${sources} ${empty2.length === 1 ? "was" : "were"} given an empty value - pass a ${opts.label} or unset the environment variable.`,
16009
+ `${sources} ${empty3.length === 1 ? "was" : "were"} given an empty value - pass a ${opts.label} or unset the environment variable.`,
15831
16010
  opts.help ? { help: opts.help } : {}
15832
16011
  );
15833
16012
  }
@@ -17513,7 +17692,7 @@ var init_command_spec = __esm({
17513
17692
  {
17514
17693
  id: "kinds",
17515
17694
  leaves: [publicLeaf("kinds", "kinds", zero, 14, DIR_SURFACE)],
17516
- usage: "kinds [--dir <path>] [--remote <url>]",
17695
+ usage: "kinds [--coverage [--kind <Kind>] [--now <ISO>]] [--dir <path>] [--remote <url>]",
17517
17696
  summary: "List the kind conventions this bundle declares (purpose, described fields, exact required body headings, typed-link vocabulary, horizon)"
17518
17697
  },
17519
17698
  {
@@ -25772,10 +25951,10 @@ function boundedLines(body, maximum) {
25772
25951
  );
25773
25952
  }
25774
25953
  function decodeDocumentRead(id, body, route) {
25775
- const envelope2 = body;
25776
- const data = envelope2?.data;
25954
+ const envelope3 = body;
25955
+ const data = envelope3?.data;
25777
25956
  const document4 = data?.document;
25778
- if (envelope2?.operationId !== "documents.read.v1" || envelope2.ok !== true || typeof data !== "object" || data === null || !isContentVersion(data.version) || typeof document4 !== "object" || document4 === null || document4.id !== id || typeof document4.frontmatter !== "object" || document4.frontmatter === null || Array.isArray(document4.frontmatter) || typeof document4.body !== "string")
25957
+ if (envelope3?.operationId !== "documents.read.v1" || envelope3.ok !== true || typeof data !== "object" || data === null || !isContentVersion(data.version) || typeof document4 !== "object" || document4 === null || document4.id !== id || typeof document4.frontmatter !== "object" || document4.frontmatter === null || Array.isArray(document4.frontmatter) || typeof document4.body !== "string")
25779
25958
  throw malformed("document read answered an envelope that is not documents.read.v1's result for this document", route);
25780
25959
  return { doc: { id, frontmatter: document4.frontmatter, body: document4.body }, version: data.version };
25781
25960
  }
@@ -25792,9 +25971,9 @@ function decodeDocumentHistory(request3, body, route) {
25792
25971
  const fail4 = (why) => {
25793
25972
  throw malformed(`history answered ${why}`, route);
25794
25973
  };
25795
- const envelope2 = body;
25796
- if (envelope2?.operationId !== HISTORY_OPERATION_ID || envelope2.ok !== true) fail4(`an envelope that is not ${HISTORY_OPERATION_ID}'s result`);
25797
- const data = envelope2.data;
25974
+ const envelope3 = body;
25975
+ if (envelope3?.operationId !== HISTORY_OPERATION_ID || envelope3.ok !== true) fail4(`an envelope that is not ${HISTORY_OPERATION_ID}'s result`);
25976
+ const data = envelope3.data;
25798
25977
  if (typeof data !== "object" || data === null || Array.isArray(data)) fail4("without its data");
25799
25978
  if (data.documentId !== request3.documentId) fail4("for another document");
25800
25979
  if (!Array.isArray(data.versions) || data.versions.length > request3.limit) fail4("more versions than asked for, or none as a list");
@@ -25836,10 +26015,10 @@ function decodeDocumentHistory(request3, body, route) {
25836
26015
  return Object.freeze({ documentId: request3.documentId, versions: Object.freeze(versions), more: data.more, ...total === void 0 ? {} : { total } });
25837
26016
  }
25838
26017
  function operationRefusal(body, operationId, route) {
25839
- const envelope2 = body;
25840
- if (envelope2?.ok !== false) return void 0;
25841
- const error51 = envelope2.error;
25842
- if (envelope2.operationId !== operationId || typeof error51 !== "object" || error51 === null || typeof error51.code !== "string" || !REFUSAL_CODE.test(error51.code))
26018
+ const envelope3 = body;
26019
+ if (envelope3?.ok !== false) return void 0;
26020
+ const error51 = envelope3.error;
26021
+ if (envelope3.operationId !== operationId || typeof error51 !== "object" || error51 === null || typeof error51.code !== "string" || !REFUSAL_CODE.test(error51.code))
25843
26022
  throw malformed(`answered a refusal that is not ${operationId}'s`, route);
25844
26023
  return refusalOf(error51.code, error51.message, error51.retryable);
25845
26024
  }
@@ -30216,10 +30395,10 @@ function ffSwallowToError(reason, inv, boardPath) {
30216
30395
  function syncEnvelope(home2, counts = {}) {
30217
30396
  return { home: home2, sent: counts.sent ?? 0, received: counts.received ?? 0, conflicts: counts.conflicts ?? 0, held: counts.held ?? 0, next: counts.next ?? [] };
30218
30397
  }
30219
- function withSyncEnvelope(receipt3, envelope2) {
30398
+ function withSyncEnvelope(receipt3, envelope3) {
30220
30399
  const out = { ...receipt3 };
30221
30400
  if (!("schema_version" in out)) out.schema_version = SYNC_RECEIPT_SCHEMA_VERSION;
30222
- for (const key2 of SYNC_ENVELOPE_KEYS) if (!(key2 in out)) out[key2] = envelope2[key2];
30401
+ for (const key2 of SYNC_ENVELOPE_KEYS) if (!(key2 in out)) out[key2] = envelope3[key2];
30223
30402
  return out;
30224
30403
  }
30225
30404
  function syncVerbNotApplicable(flags, home2, why, help2) {
@@ -31141,8 +31320,8 @@ async function showIncoming(id, values, deps, route) {
31141
31320
  try {
31142
31321
  await run();
31143
31322
  } catch (err) {
31144
- const { envelope: envelope2 } = toExit(err);
31145
- stderr(renderErrorEnvelope(envelope2));
31323
+ const { envelope: envelope3 } = toExit(err);
31324
+ stderr(renderErrorEnvelope(envelope3));
31146
31325
  throw asHandled(err);
31147
31326
  }
31148
31327
  }
@@ -35607,8 +35786,8 @@ async function sync(argv2, deps = {}) {
35607
35786
  try {
35608
35787
  await run();
35609
35788
  } catch (err) {
35610
- const { envelope: envelope2, handled } = toExit(err);
35611
- if (!handled) stderr(renderErrorEnvelope(envelope2));
35789
+ const { envelope: envelope3, handled } = toExit(err);
35790
+ if (!handled) stderr(renderErrorEnvelope(envelope3));
35612
35791
  throw handled ? err : asHandled(err);
35613
35792
  }
35614
35793
  }
@@ -35958,8 +36137,8 @@ async function failGate(run, board, commitResult, delta, reason, details) {
35958
36137
  );
35959
36138
  partial2.code = "GATE_FAILED";
35960
36139
  partial2.help = help2;
35961
- const envelope2 = syncEnvelope("git", { received: delta.originDelta.length, next: [`${run.inv} sync`] });
35962
- run.stdout(render(withSyncEnvelope(partial2, envelope2), run.mode));
36140
+ const envelope3 = syncEnvelope("git", { received: delta.originDelta.length, next: [`${run.inv} sync`] });
36141
+ run.stdout(render(withSyncEnvelope(partial2, envelope3), run.mode));
35963
36142
  await writeAwarenessCache(board.key, board.boardPath, delta.changes, delta.reanchorNote);
35964
36143
  throw new CliError("GATE_FAILED", `the sync gate ${reason}; nothing was pushed`, {
35965
36144
  help: help2,
@@ -36003,8 +36182,8 @@ function reportHeld(run, board, delta, held2, where, notPulled) {
36003
36182
  receipt3.held_documents = held2.map((doc2) => ({ id: doc2.id, path: doc2.relPath, reason: doc2.reason, detail: doc2.detail }));
36004
36183
  const fix = `fix the lines between the --- markers of ${held2.map((doc2) => doc2.relPath).join(", ")} (quote any value that contains ': '), check with ${run.inv} status, then run ${run.inv} sync`;
36005
36184
  receipt3.held_help = `not published: the YAML frontmatter of these documents does not parse, and publishing it would break every reader of the board, so this sync sent nothing. Your files are untouched; ${fix}` + (where === "committed locally" ? " (the fix is committed on top and both go out together)" : "");
36006
- const envelope2 = syncEnvelope("git", { received: delta.originDelta.length, held: held2.length, next: [`${run.inv} sync`] });
36007
- run.stdout(render(withSyncEnvelope(receipt3, envelope2), run.mode));
36185
+ const envelope3 = syncEnvelope("git", { received: delta.originDelta.length, held: held2.length, next: [`${run.inv} sync`] });
36186
+ run.stdout(render(withSyncEnvelope(receipt3, envelope3), run.mode));
36008
36187
  throw new CliError(
36009
36188
  "CONFLICT",
36010
36189
  `${held2.length} document(s) have invalid frontmatter (${held2.map((doc2) => doc2.id).join(", ")}); nothing was published`,
@@ -47352,7 +47531,7 @@ function visitParents(tree, test, visitor, reverse) {
47352
47531
  }
47353
47532
  return visit2;
47354
47533
  function visit2() {
47355
- let result3 = empty;
47534
+ let result3 = empty2;
47356
47535
  let subresult;
47357
47536
  let offset;
47358
47537
  let grandparents;
@@ -47391,16 +47570,16 @@ function toResult(value) {
47391
47570
  if (typeof value === "number") {
47392
47571
  return [CONTINUE, value];
47393
47572
  }
47394
- return value === null || value === void 0 ? empty : [value];
47573
+ return value === null || value === void 0 ? empty2 : [value];
47395
47574
  }
47396
- var empty, CONTINUE, EXIT2, SKIP;
47575
+ var empty2, CONTINUE, EXIT2, SKIP;
47397
47576
  var init_lib5 = __esm({
47398
47577
  "../../node_modules/unist-util-visit-parents/lib/index.js"() {
47399
47578
  init_define_SUPERBEE_BUILD_IDENTITY();
47400
47579
  init_define_SUPERBEE_UPDATE_POLICY();
47401
47580
  init_unist_util_is();
47402
47581
  init_color_node();
47403
- empty = [];
47582
+ empty2 = [];
47404
47583
  CONTINUE = true;
47405
47584
  EXIT2 = false;
47406
47585
  SKIP = "skip";
@@ -48375,11 +48554,11 @@ var require_react_production = __commonJS({
48375
48554
  _init: lazyInitializer
48376
48555
  };
48377
48556
  };
48378
- exports.memo = function(type, compare) {
48557
+ exports.memo = function(type, compare2) {
48379
48558
  return {
48380
48559
  $$typeof: REACT_MEMO_TYPE,
48381
48560
  type,
48382
- compare: void 0 === compare ? null : compare
48561
+ compare: void 0 === compare2 ? null : compare2
48383
48562
  };
48384
48563
  };
48385
48564
  exports.startTransition = function(scope) {
@@ -49307,18 +49486,18 @@ var require_react_development = __commonJS({
49307
49486
  lazyType2._debugInfo = [{ awaited: ioInfo }];
49308
49487
  return lazyType2;
49309
49488
  };
49310
- exports.memo = function(type, compare) {
49489
+ exports.memo = function(type, compare2) {
49311
49490
  null == type && console.error(
49312
49491
  "memo: The first argument must be a component. Instead received: %s",
49313
49492
  null === type ? "null" : typeof type
49314
49493
  );
49315
- compare = {
49494
+ compare2 = {
49316
49495
  $$typeof: REACT_MEMO_TYPE,
49317
49496
  type,
49318
- compare: void 0 === compare ? null : compare
49497
+ compare: void 0 === compare2 ? null : compare2
49319
49498
  };
49320
49499
  var ownName;
49321
- Object.defineProperty(compare, "displayName", {
49500
+ Object.defineProperty(compare2, "displayName", {
49322
49501
  enumerable: false,
49323
49502
  configurable: true,
49324
49503
  get: function() {
@@ -49329,7 +49508,7 @@ var require_react_development = __commonJS({
49329
49508
  type.name || type.displayName || (Object.defineProperty(type, "name", { value: name }), type.displayName = name);
49330
49509
  }
49331
49510
  });
49332
- return compare;
49511
+ return compare2;
49333
49512
  };
49334
49513
  exports.startTransition = function(scope) {
49335
49514
  var prevTransition = ReactSharedInternals.T, currentTransition = {};
@@ -76362,8 +76541,8 @@ async function docRead(argv2, deps) {
76362
76541
  try {
76363
76542
  await docReadInner(argv2, deps);
76364
76543
  } catch (err) {
76365
- const { envelope: envelope2, handled } = toExit(err);
76366
- if (!handled) stderr(renderErrorEnvelope(envelope2));
76544
+ const { envelope: envelope3, handled } = toExit(err);
76545
+ if (!handled) stderr(renderErrorEnvelope(envelope3));
76367
76546
  throw handled ? err : asHandled(err);
76368
76547
  }
76369
76548
  }
@@ -76558,8 +76737,8 @@ async function docReadInner(argv2, deps) {
76558
76737
  }
76559
76738
  stdout(formatFieldValue(resolveField(parsed2, version4, field, id)));
76560
76739
  } catch (err) {
76561
- const { envelope: envelope2 } = toExit(err);
76562
- stderr(renderErrorEnvelope(envelope2));
76740
+ const { envelope: envelope3 } = toExit(err);
76741
+ stderr(renderErrorEnvelope(envelope3));
76563
76742
  throw asHandled(err);
76564
76743
  }
76565
76744
  return;
@@ -77164,7 +77343,7 @@ function fields(value, required2, optional2 = []) {
77164
77343
  requireValue(required2.every((key2) => Object.hasOwn(value, key2)));
77165
77344
  requireValue(Object.keys(value).every((key2) => required2.includes(key2) || optional2.includes(key2)));
77166
77345
  }
77167
- function envelope(value, schema) {
77346
+ function envelope2(value, schema) {
77168
77347
  const data = record3(value);
77169
77348
  requireValue(typeof data.schemaVersion === "string");
77170
77349
  requireValue(data.schemaVersion === schema, "unsupported_version");
@@ -77182,7 +77361,7 @@ function nullableVersion(value) {
77182
77361
  return value === null ? null : version2(value);
77183
77362
  }
77184
77363
  function target2(value) {
77185
- const data = envelope(value, "superbee.document-target.v1");
77364
+ const data = envelope2(value, "superbee.document-target.v1");
77186
77365
  fields(data, ["schemaVersion", "authority", "bundleKey", "documentId"]);
77187
77366
  const authority = record3(data.authority);
77188
77367
  let parsedAuthority;
@@ -77221,12 +77400,12 @@ function provenance(value) {
77221
77400
  return data.state === "local-pending" ? { state: "local-pending", ...common } : { state: "local-conflict", ...common, remote: nullableVersion(data.remote) };
77222
77401
  }
77223
77402
  function observation(value) {
77224
- const data = envelope(value, "superbee.document-observation.v1");
77403
+ const data = envelope2(value, "superbee.document-observation.v1");
77225
77404
  fields(data, ["schemaVersion", "target", "provenance", "lifecycle"]);
77226
77405
  return { schemaVersion: "superbee.document-observation.v1", target: target2(data.target), provenance: provenance(data.provenance), lifecycle: lifecycle(data.lifecycle) };
77227
77406
  }
77228
77407
  function request2(value) {
77229
- const data = envelope(value, "superbee.present-document.v1");
77408
+ const data = envelope2(value, "superbee.present-document.v1");
77230
77409
  fields(data, ["schemaVersion", "operation", "invocationId", "target"], ["referenceVersion", "expectedLifecycle"]);
77231
77410
  requireValue(data.operation === "present_document");
77232
77411
  const expectedLifecycle = Object.hasOwn(data, "expectedLifecycle") ? lifecycle(data.expectedLifecycle) : void 0;
@@ -77258,7 +77437,7 @@ function presentation(value) {
77258
77437
  }
77259
77438
  }
77260
77439
  function receipt(value, expected) {
77261
- const data = envelope(value, "superbee.present-document-receipt.v1");
77440
+ const data = envelope2(value, "superbee.present-document-receipt.v1");
77262
77441
  requireValue(typeof data.ok === "boolean");
77263
77442
  fields(data, ["schemaVersion", "operation", "invocationId", "target", "ok", data.ok ? "presentation" : "error"]);
77264
77443
  requireValue(data.operation === "present_document");
@@ -83519,8 +83698,8 @@ async function pull2(argv2, deps = {}) {
83519
83698
  try {
83520
83699
  await runToTarget();
83521
83700
  } catch (err) {
83522
- const { envelope: envelope2 } = toExit(err);
83523
- stderr(renderErrorEnvelope(envelope2));
83701
+ const { envelope: envelope3 } = toExit(err);
83702
+ stderr(renderErrorEnvelope(envelope3));
83524
83703
  throw asHandled(err);
83525
83704
  }
83526
83705
  }
@@ -85425,6 +85604,9 @@ async function kinds(argv2, deps = {}) {
85425
85604
  () => parseArgs20({
85426
85605
  args: argv2,
85427
85606
  options: {
85607
+ coverage: { type: "boolean" },
85608
+ kind: { type: "string" },
85609
+ now: { type: "string" },
85428
85610
  dir: { type: "string" },
85429
85611
  remote: { type: "string" },
85430
85612
  json: { type: "boolean" },
@@ -85438,6 +85620,13 @@ async function kinds(argv2, deps = {}) {
85438
85620
  stdout(renderUsage(KINDS_USAGE));
85439
85621
  return;
85440
85622
  }
85623
+ if (!values.coverage && (values.kind !== void 0 || values.now !== void 0)) {
85624
+ throw new CliError("USAGE", "--kind and --now require --coverage");
85625
+ }
85626
+ if (values.coverage && values.remote !== void 0) throw new CliError("USAGE", "Kind coverage reads local bundles only; omit --remote");
85627
+ const nowText = values.now;
85628
+ const nowMs = nowText === void 0 ? Date.now() : parseTimestamp(/^\d{4}-\d{2}-\d{2}$/.test(nowText) ? `${nowText}T00:00:00Z` : nowText, "0.2");
85629
+ if (nowMs === null) throw new CliError("USAGE", "--now requires a valid ISO date or explicit-zone instant");
85441
85630
  const bundle = await openBundle(values.dir, await resolveRemoteFlag(values.remote, values.dir));
85442
85631
  const [registry2, okfVersion] = await Promise.all([
85443
85632
  loadKinds(bundle),
@@ -85446,7 +85635,20 @@ async function kinds(argv2, deps = {}) {
85446
85635
  const declared = [...registry2.kinds.values()];
85447
85636
  const ordered = declared.some((kind2) => kind2.order !== void 0) ? declared : declared.sort((a, b) => a.governs.localeCompare(b.governs));
85448
85637
  const rows = ordered.map((kind2) => toRow(kind2, okfVersion));
85638
+ if (values.coverage && values.kind !== void 0 && !registry2.kinds.has(values.kind)) {
85639
+ throw new CliError("USAGE", "--kind must name an exact declared Kind");
85640
+ }
85449
85641
  const out = { count: rows.length, kinds: rows };
85642
+ if (values.coverage) {
85643
+ const skipped = [];
85644
+ const documents = await query2(bundle, {}, { onSkip: ({ id }) => skipped.push(id) });
85645
+ const measurements = kindCoverage(registry2, documents, { now: new Date(nowMs), okfVersion, kind: values.kind });
85646
+ const byKind = new Map(measurements.kinds.map((row4) => [row4.governs, row4]));
85647
+ const selected2 = rows.filter((row4) => byKind.has(String(row4.governs))).map((row4) => ({ ...row4, ...byKind.get(String(row4.governs)) }));
85648
+ out.count = selected2.length;
85649
+ out.kinds = selected2;
85650
+ out.coverage = { now: measurements.now, documents: measurements.documents, complete: skipped.length === 0, skipped_documents: skipped.length, skipped_examples: skipped.sort().slice(0, 3), undeclared_kinds: measurements.undeclared_kinds };
85651
+ }
85450
85652
  if (registry2.warnings.length > 0) out.warnings = registry2.warnings;
85451
85653
  if (rows.length === 0) {
85452
85654
  out.help = [`${cliInvocation()} new "<Kind>" <id> --<field> <value> (once a kind is declared)`];
@@ -85459,6 +85661,7 @@ var init_kinds2 = __esm({
85459
85661
  "use strict";
85460
85662
  init_define_SUPERBEE_BUILD_IDENTITY();
85461
85663
  init_define_SUPERBEE_UPDATE_POLICY();
85664
+ init_errors4();
85462
85665
  init_output2();
85463
85666
  init_src();
85464
85667
  init_bundle2();
@@ -85470,6 +85673,7 @@ var init_kinds2 = __esm({
85470
85673
 
85471
85674
  Usage:
85472
85675
  superbee kinds [--dir <path>] [--remote <url>]
85676
+ superbee kinds --coverage [--kind <Kind>] [--now <ISO instant or date>] [--dir <path>] [--json]
85473
85677
 
85474
85678
  A kind convention is a plain OKF doc (type: Convention) under conventions/ declaring a document
85475
85679
  kind's purpose, required/optional fields and their descriptions, allowed enum values, typed-link vocabulary, expected body
@@ -85528,7 +85732,22 @@ A misshaped or misplaced key here is a non-fatal registry warning (visible in 'k
85528
85732
  output), never a silent no-op. See 'superbee doc read conventions/context-note' on any
85529
85733
  --init'd bundle for a full worked example with a values: enum and sections:.
85530
85734
 
85735
+ Coverage is local and read-only: group all readable concepts by actual type, using the same
85736
+ registry, logical field aliases and concept-link resolver. Filled excludes null, blank strings,
85737
+ empty lists/maps and case-insensitive unknown/n/a/na/none/tbd/null/-/? sentinels; it is a measurement,
85738
+ not required-field validation. Zero-record rates are null. Body prose excludes headings, standalone
85739
+ links and Related sections at any ATX heading level (including descendants until the next same
85740
+ or higher-level heading). This is line measurement, not Markdown rendering. Drift separates standard/envelope fields. Typed links use exact
85741
+ Kind-declared labels; other concept links are untyped citations, not undeclared relation violations.
85742
+ Freshness measures checked_on domain date metadata against the Kind's minute/hour/day horizon,
85743
+ not its meaningful-change clock. Missing/invalid dates and absent horizons remain explicit.
85744
+ Examples are capped at 3 per drift field; source domains at 15 with total/shown counts. A skipped
85745
+ malformed document makes coverage partial; no remote, sync or network access is performed.
85746
+
85531
85747
  Options:
85748
+ --coverage Add per-Kind field, drift, link, freshness and source measurements
85749
+ --kind <Kind> Select one exact declared type (requires --coverage)
85750
+ --now <ISO> Fixed UTC date or explicit-zone instant for coverage (requires --coverage)
85532
85751
  --dir <path> Bundle directory (default: discovered from the cwd)
85533
85752
  --remote <url> Talk to a wire-protocol server instead of a local bundle
85534
85753
  (mutually exclusive with --dir; remote access is always explicit)
@@ -92145,12 +92364,12 @@ function cleanRegex(source) {
92145
92364
  return source.slice(start, end);
92146
92365
  }
92147
92366
  function floatSafeRemainder2(val, step) {
92148
- const ratio = val / step;
92149
- const roundedRatio = Math.round(ratio);
92150
- const tolerance = Number.EPSILON * Math.max(Math.abs(ratio), 1);
92151
- if (Math.abs(ratio - roundedRatio) < tolerance)
92367
+ const ratio2 = val / step;
92368
+ const roundedRatio = Math.round(ratio2);
92369
+ const tolerance = Number.EPSILON * Math.max(Math.abs(ratio2), 1);
92370
+ if (Math.abs(ratio2 - roundedRatio) < tolerance)
92152
92371
  return 0;
92153
- return ratio - roundedRatio;
92372
+ return ratio2 - roundedRatio;
92154
92373
  }
92155
92374
  function defineLazy(object5, key2, getter) {
92156
92375
  let value = void 0;
@@ -119053,8 +119272,8 @@ var require_formats = __commonJS({
119053
119272
  init_define_SUPERBEE_UPDATE_POLICY();
119054
119273
  Object.defineProperty(exports, "__esModule", { value: true });
119055
119274
  exports.formatNames = exports.fastFormats = exports.fullFormats = void 0;
119056
- function fmtDef(validate, compare) {
119057
- return { validate, compare };
119275
+ function fmtDef(validate, compare2) {
119276
+ return { validate, compare: compare2 };
119058
119277
  }
119059
119278
  exports.fullFormats = {
119060
119279
  // date: http://tools.ietf.org/html/rfc3339#section-5.6
@@ -125440,8 +125659,8 @@ async function mcp(argv2, deps = {}) {
125440
125659
  try {
125441
125660
  await mcpInner(argv2, deps);
125442
125661
  } catch (error51) {
125443
- const { envelope: envelope2, handled } = toExit(error51);
125444
- if (!handled) stderr(renderErrorEnvelope(envelope2));
125662
+ const { envelope: envelope3, handled } = toExit(error51);
125663
+ if (!handled) stderr(renderErrorEnvelope(envelope3));
125445
125664
  throw handled ? error51 : asHandled(error51);
125446
125665
  }
125447
125666
  }
@@ -128894,8 +129113,8 @@ async function postRoute(context, route, body, writeRequest) {
128894
129113
  }
128895
129114
  throw hostedFailure(error52, target3, resume2);
128896
129115
  }
128897
- const envelope2 = answer2.body ?? {};
128898
- const error51 = envelope2.error;
129116
+ const envelope3 = answer2.body ?? {};
129117
+ const error51 = envelope3.error;
128899
129118
  const code3 = typeof error51 === "string" ? error51 : typeof error51?.code === "string" ? error51.code : null;
128900
129119
  const message = typeof error51?.message === "string" ? error51.message : "";
128901
129120
  if (answer2.status === 503 && code3 === "write_outcome_unknown") throw unknown3();
@@ -128905,10 +129124,10 @@ async function postRoute(context, route, body, writeRequest) {
128905
129124
  help: "a later release of the host offers it; until then do this in the Superbee app"
128906
129125
  });
128907
129126
  }
128908
- if (answer2.status === 200 && envelope2.ok === true && typeof envelope2.data === "object" && envelope2.data !== null && !Array.isArray(envelope2.data)) {
128909
- return { ok: true, data: envelope2.data };
129127
+ if (answer2.status === 200 && envelope3.ok === true && typeof envelope3.data === "object" && envelope3.data !== null && !Array.isArray(envelope3.data)) {
129128
+ return { ok: true, data: envelope3.data };
128910
129129
  }
128911
- if (answer2.status === 200 && envelope2.ok === false && code3 !== null) return { ok: false, code: code3, message };
129130
+ if (answer2.status === 200 && envelope3.ok === false && code3 !== null) return { ok: false, code: code3, message };
128912
129131
  throw hostedFailure(new RemoteError(`hosted ${route} answered ${answer2.status}`, code3 ?? "RUNTIME", answer2.status), target3, resume2);
128913
129132
  }
128914
129133
  function accessRefusal(code3, hostMessage, subject) {
@@ -129280,8 +129499,8 @@ async function catalog(argv2, deps = {}) {
129280
129499
  try {
129281
129500
  await catalogInner(argv2, deps);
129282
129501
  } catch (err) {
129283
- const { envelope: envelope2, handled } = toExit(err);
129284
- if (!handled) stderr(renderErrorEnvelope(envelope2));
129502
+ const { envelope: envelope3, handled } = toExit(err);
129503
+ if (!handled) stderr(renderErrorEnvelope(envelope3));
129285
129504
  throw handled ? err : asHandled(err);
129286
129505
  }
129287
129506
  return;
@@ -134510,7 +134729,7 @@ function packParts(content3, versions) {
134510
134729
  const parts = [];
134511
134730
  let part = null;
134512
134731
  let size = 0;
134513
- const envelope2 = 512;
134732
+ const envelope3 = 512;
134514
134733
  for (const version4 of new Set(versions)) {
134515
134734
  const object5 = content3.objects.get(version4);
134516
134735
  if (!object5) continue;
@@ -134518,7 +134737,7 @@ function packParts(content3, versions) {
134518
134737
  if (part === null || part.versions.length >= bounds.partObjects || size + bytes > bounds.partTargetBytes) {
134519
134738
  part = { documents: [], reserved: [], history: [], versions: [] };
134520
134739
  parts.push(part);
134521
- size = envelope2;
134740
+ size = envelope3;
134522
134741
  }
134523
134742
  if (object5.kind === "documents") part.documents.push(object5.value);
134524
134743
  else if (object5.kind === "reserved") part.reserved.push(object5.value);
@@ -134642,19 +134861,19 @@ async function runStagedCreate(request3) {
134642
134861
  }
134643
134862
  }
134644
134863
  function read(name, answer2) {
134645
- const envelope2 = answer2.body ?? {};
134646
- const code3 = typeof envelope2.error?.code === "string" ? envelope2.error.code : null;
134647
- const message = typeof envelope2.error?.message === "string" ? envelope2.error.message : "";
134648
- if (answer2.status === 200 && envelope2.ok === true && typeof envelope2.data === "object" && envelope2.data !== null) return envelope2.data;
134649
- if (answer2.status === 200 && envelope2.ok === false && code3 === "staged_manifest_missing") return "no_manifest";
134650
- if (answer2.status === 200 && envelope2.ok === false && code3 === "request_conflict" && envelope2.error?.retryable === true) return "busy";
134651
- if (answer2.status === 200 && envelope2.ok === false && code3 === "validation_failed" && VERSION_MISMATCH.test(message)) {
134864
+ const envelope3 = answer2.body ?? {};
134865
+ const code3 = typeof envelope3.error?.code === "string" ? envelope3.error.code : null;
134866
+ const message = typeof envelope3.error?.message === "string" ? envelope3.error.message : "";
134867
+ if (answer2.status === 200 && envelope3.ok === true && typeof envelope3.data === "object" && envelope3.data !== null) return envelope3.data;
134868
+ if (answer2.status === 200 && envelope3.ok === false && code3 === "staged_manifest_missing") return "no_manifest";
134869
+ if (answer2.status === 200 && envelope3.ok === false && code3 === "request_conflict" && envelope3.error?.retryable === true) return "busy";
134870
+ if (answer2.status === 200 && envelope3.ok === false && code3 === "validation_failed" && VERSION_MISMATCH.test(message)) {
134652
134871
  throw new CliError("RUNTIME", `${client.target.origin} stores an object differently from this CLI (client/host contract mismatch)`, {
134653
134872
  details: { reason: "staged_mismatch", route: name, host_message: message, host: client.target.origin, request_id: requestId2, retryable: false },
134654
134873
  help: `upgrade Superbee (npm install -g superbee), then re-run the same command, which resumes this creation: ${request3.resume}`
134655
134874
  });
134656
134875
  }
134657
- if (answer2.status === 200 && envelope2.ok === false && code3 !== null) throw new StagedRefusal(code3, message, reserved, name);
134876
+ if (answer2.status === 200 && envelope3.ok === false && code3 !== null) throw new StagedRefusal(code3, message, reserved, name);
134658
134877
  if (answer2.status === 429 && code3 === "bundle_create_limit") throw new StagedRefusal(code3, message, reserved, name);
134659
134878
  if (answer2.status === 400 && !reserved) throw new StagedRefusal(code3 ?? "invalid_input", message || `the host refused ${name} as malformed`, false, name);
134660
134879
  throw hostedFailure(new RemoteError(`hosted ${name} answered ${answer2.status}`, code3 ?? "RUNTIME", answer2.status), client.target, request3.resume);
@@ -135049,9 +135268,9 @@ async function sendCreation(plan, context) {
135049
135268
  }
135050
135269
  throw hostedFailure(error51, target3, yesCommand);
135051
135270
  }
135052
- const envelope2 = answer2.body ?? {};
135053
- const code3 = typeof envelope2.error?.code === "string" ? envelope2.error.code : null;
135054
- const hostMessage = typeof envelope2.error?.message === "string" ? envelope2.error.message : "";
135271
+ const envelope3 = answer2.body ?? {};
135272
+ const code3 = typeof envelope3.error?.code === "string" ? envelope3.error.code : null;
135273
+ const hostMessage = typeof envelope3.error?.message === "string" ? envelope3.error.message : "";
135055
135274
  if (answer2.status === 503 && code3 === "write_outcome_unknown") {
135056
135275
  throw new CliError("TRANSIENT", `${target3.origin} may have partly created '${bundleId}'`, {
135057
135276
  details: { reason: "write_outcome_unknown", bundle_id: bundleId, workspace, host: target3.origin, request_id: requestId2, retryable: true },
@@ -135063,16 +135282,16 @@ async function sendCreation(plan, context) {
135063
135282
  if (forgettable) await clearPendingCreate(home2, canonical2, bundleId);
135064
135283
  throw createRefusal(code3, hostMessage, refusalContext);
135065
135284
  }
135066
- if (answer2.status === 200 && envelope2.ok === false && code3 !== null) {
135285
+ if (answer2.status === 200 && envelope3.ok === false && code3 !== null) {
135067
135286
  if (code3 !== "request_conflict" && forgettable) await clearPendingCreate(home2, canonical2, bundleId);
135068
135287
  throw createRefusal(code3, hostMessage, refusalContext);
135069
135288
  }
135070
- if (answer2.status !== 200 || envelope2.ok !== true || typeof envelope2.data !== "object" || envelope2.data === null) {
135289
+ if (answer2.status !== 200 || envelope3.ok !== true || typeof envelope3.data !== "object" || envelope3.data === null) {
135071
135290
  if (answer2.status === 400 && forgettable) await clearPendingCreate(home2, canonical2, bundleId);
135072
135291
  throw hostedFailure(new RemoteError(`hosted bundle-create answered ${answer2.status}`, code3 ?? "RUNTIME", answer2.status), target3, yesCommand);
135073
135292
  }
135074
135293
  await clearPendingCreate(home2, canonical2, bundleId);
135075
- return envelope2.data;
135294
+ return envelope3.data;
135076
135295
  }
135077
135296
  async function publish(argv2, partial2 = {}) {
135078
135297
  const deps = publishDeps(partial2);
@@ -135800,7 +136019,7 @@ async function main(argv2) {
135800
136019
  await main(hoisted);
135801
136020
  return;
135802
136021
  }
135803
- const envelope2 = toEnvelope(
136022
+ const envelope3 = toEnvelope(
135804
136023
  new CliError(
135805
136024
  "USAGE",
135806
136025
  `options must follow the command (e.g. '${cliInvocation()} ${commandWords(command)} \u2026').`,
@@ -135809,7 +136028,7 @@ async function main(argv2) {
135809
136028
  }
135810
136029
  )
135811
136030
  );
135812
- process.stdout.write(renderErrorEnvelope(envelope2));
136031
+ process.stdout.write(renderErrorEnvelope(envelope3));
135813
136032
  process.exitCode = 2;
135814
136033
  return;
135815
136034
  }
@@ -135829,8 +136048,8 @@ async function main(argv2) {
135829
136048
  },
135830
136049
  renderUnknownCommand: (cmd) => renderErrorEnvelope(toEnvelope(unknownCommandError(cmd))),
135831
136050
  formatError: (err) => {
135832
- const { exitCode, envelope: envelope2, handled } = toExit(err);
135833
- return { output: handled ? "" : renderErrorEnvelope(envelope2), exitCode };
136051
+ const { exitCode, envelope: envelope3, handled } = toExit(err);
136052
+ return { output: handled ? "" : renderErrorEnvelope(envelope3), exitCode };
135834
136053
  }
135835
136054
  });
135836
136055
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superbee",
3
- "version": "0.4.2",
3
+ "version": "0.4.3-pre.1",
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": [
@@ -90,6 +90,6 @@
90
90
  "darwin",
91
91
  "linux"
92
92
  ],
93
- "readme": "# superbee\n\nShared, versioned, conflict-safe knowledge for AI coding agents, stored as plain markdown in\nyour repo.\n\nSuperbee is pre-1.0. Commands and formats may change between releases.\n\n## What is Superbee?\n\nAgents forget everything between sessions, overwrite each other's work, and keep what they know\ninvisible to the humans they work for. Superbee fixes all three with a **knowledge bundle**: a\nfolder of markdown documents, by convention `.superbee/` at your project root, that agents read\nand write through a small command-line tool.\n\n- **Context that persists.** Agents write context notes, decisions, plans, and research into the\n bundle. The next session, or a different agent, picks up where the last one left off. An\n optional `SessionStart` hook for Claude Code, Codex, and OpenCode orients every new session\n automatically.\n- **Safe for many writers.** Each write can carry the actor that made it. A writer can name the\n version it last read; if anyone changed the document since, the write fails with a typed\n conflict error instead of silently overwriting their work.\n- **Visible to humans.** The bundle is plain markdown. Open it in any editor, render it on\n GitHub, diff it in git. `superbee ui` serves it locally as cross-linked pages with backlinks and\n a live activity feed. No bundle content leaves your machine until you run `superbee sync`, which\n shares the bundle with teammates through the board: a copy of the bundle kept on its own git\n branch, separate from your code.\n- **Views on demand.** Ask your agent for a dashboard, a timeline, a filtered task queue, or a\n reading view of one dense document. It builds a self-contained HTML page, stores it in the bundle\n as a View, and `superbee ui` hosts it in a sandboxed frame. A View reads the bundle live and can\n change it only through a write you confirm. Views are bundle content, so they travel with `sync`.\n- **Built for agents.** Output is structured and token-lean, and errors carry a small, stable set\n of exit codes. Agents act on responses without parsing prose or flooding their context window.\n- **Yours, and portable.** Bundles follow the Open Knowledge Format (OKF), a convention of\n markdown with frontmatter, so they outlive the tool: hand the folder to someone else, or read it\n with anything that speaks markdown. New bundles are written as OKF v0.2, and existing v0.1\n bundles keep working as they are. Reading and writing the bundle works offline; only sharing\n needs a network. The document schemas, called kinds, live inside the bundle, so it describes\n its own structure.\n\nBees build comb one cell at a time. The comb holds what the colony gathers, and its shape shows\nthe next bee where to build and what belongs where. Superbee works the same way: people and\nagents record what they learn in a structure that fits their domain, and that structure guides\nwhoever works next. Each session builds on the last instead of starting over.\n\nThe npm package is one self-contained executable with zero runtime dependencies, plus an Agent\nSkill, an instruction file your agent loads, that teaches it how to use the tool.\n\n## Install\n\nRequires a supported Node.js 22, 24, or 26 release (22.14.0 minimum) on macOS or Linux. Native Windows is not supported by this package.\n\n```sh\nnpm install -g superbee\n```\n\nStable releases publish on npm's `latest` tag and prereleases on `next`.\n\nWindows adapters and the `superbee-windows` executable live in a separate repository and are\nnot included in `superbee`. Most Windows users should run Superbee in WSL2, where npm sees a\nLinux platform and the normal installation applies. An experimental, unsupported native Windows\nbuild is available as open source, with build-from-source instructions: https://github.com/Holaxis-ai/superbee-windows-cli\n\n### Upgrading an existing Windows installation\n\nThe first release containing the Windows extraction removes native Windows support from this\npackage. Its npm `os` metadata permits only `darwin` and `linux`, so a Windows upgrade to an affected\nversion is rejected with `EBADPLATFORM`. This applies to existing prerelease users too. Forcing the\ninstallation does not restore support: the executable refuses commands on unsupported hosts\nbefore running them (the bare `--version` flag can still identify the installed build).\n\nThere is no supported Windows replacement on npm. The alternatives are WSL2 or the experimental\nbuild from source at https://github.com/Holaxis-ai/superbee-windows-cli; neither carries a\nfirst-party support promise for native Windows. An older installed version is not converted or\nremoved by this source change, and existing bundle files are not migrated by it. Review the affected release's notes before changing an existing\nWindows installation. macOS/Linux users can continue using the normal installation and setup flow.\n\nRun `superbee version --check` to compare your install with the current stable release.\n\n## First run: let your agent finish setup\n\n`npm install` gives you the CLI. The integrations (the Agent Skill, the `SessionStart` hook, and\nMCP server registration, where MCP is the Model Context Protocol) are installed by your agent,\nnot by hand. Ask it:\n\n> Run `superbee setup` and follow its instructions.\n\nSetup itself changes nothing. It inspects your configuration and returns one safe next command at\na time, and the agent runs each with your approval. Setup knows Claude Code, Codex, and OpenCode,\nplus Claude Desktop for the MCP registration only.\n\n## Everyday use\n\nYou rarely type Superbee commands yourself. You ask your agent, and the Agent Skill translates the\nrequest into CLI calls:\n\n- \"Set up a Superbee bundle for this project and track our tasks in it.\"\n- \"Write up what we decided about the auth design as a doc, and link it to the task.\"\n- \"What did the last session leave off on? Check the context notes.\"\n- \"Sync the board so my teammate's agent sees this.\"\n- \"Give me a view of the open tasks grouped by owner.\"\n\nBehind those requests the agent uses a small set of commands: `init --dir .superbee` creates the\nbundle, `new` creates a document of a declared kind, `doc write` writes a free-form one,\n`doc update` changes a document, `link add` connects two, `list` and `doc read` query them, and\n`sync` shares the board. `superbee --help` lists the commands, and `superbee <command> --help`\ngives each one's full reference.\n\nThe two commands meant for you are the ones that show you the knowledge:\n\n```sh\nsuperbee ui --open # the whole bundle, rendered in your browser\nsuperbee doc open <id> # one document, by an id from `superbee list`\n```\n\n## Upgrading from aslite\n\nIf you installed the earlier `@holaxis/aslite` package or its marketplace plugin: install\n`superbee` alongside it, have your agent run `superbee setup` to migrate the integrations, then\nrun `npm uninstall -g @holaxis/aslite`. Existing `.agentstate-lite/` bundles and\n`.agentstate.json` bindings keep working with no migration.\n\n## Learn more\n\nThe [repository](https://github.com/Holaxis-ai/superbee) holds the source, the\n[CLI contract](https://github.com/Holaxis-ai/superbee/blob/main/packages/superbee/AXI-CONTRACT.md),\nand the [wire protocol](https://github.com/Holaxis-ai/superbee/blob/main/docs/WIRE-PROTOCOL.md).\n\n## License\n\nApache-2.0 © 2026 Holaxis\n",
93
+ "readme": "# superbee\n\nShared, versioned, conflict-safe knowledge for AI coding agents, stored as plain markdown in\nyour repo.\n\nSuperbee is pre-1.0. Commands and formats may change between releases.\n\n## What is Superbee?\n\nAgents forget everything between sessions, overwrite each other's work, and keep what they know\ninvisible to the humans they work for. Superbee fixes all three with a **knowledge bundle**: a\nfolder of markdown documents, by convention `.superbee/` at your project root, that agents read\nand write through a small command-line tool.\n\n- **Context that persists.** Agents write context notes, decisions, plans, and research into the\n bundle. The next session, or a different agent, picks up where the last one left off. An\n optional `SessionStart` hook for Claude Code, Codex, and OpenCode orients every new session\n automatically.\n- **Safe for many writers.** Each write can carry the actor that made it. A writer can name the\n version it last read; if anyone changed the document since, the write fails with a typed\n conflict error instead of silently overwriting their work.\n- **Visible to humans.** The bundle is plain markdown. Open it in any editor, render it on\n GitHub, diff it in git. `superbee ui` serves it locally as cross-linked pages with backlinks and\n a live activity feed. No bundle content leaves your machine until you run `superbee sync`, which\n shares the bundle with teammates through the board: a copy of the bundle kept on its own git\n branch, separate from your code.\n- **Views on demand.** Ask your agent for a dashboard, a timeline, a filtered task queue, or a\n reading view of one dense document. It builds a self-contained HTML page, stores it in the bundle\n as a View, and `superbee ui` hosts it in a sandboxed frame. A View reads the bundle live and can\n change it only through a write you confirm. Views are bundle content, so they travel with `sync`.\n- **Built for agents.** Output is structured and token-lean, and errors carry a small, stable set\n of exit codes. Agents act on responses without parsing prose or flooding their context window.\n- **Yours, and portable.** Bundles follow the Open Knowledge Format (OKF), a convention of\n markdown with frontmatter, so they outlive the tool: hand the folder to someone else, or read it\n with anything that speaks markdown. New bundles are written as OKF v0.2, and existing v0.1\n bundles keep working as they are. Reading and writing the bundle works offline; only sharing\n needs a network. The document schemas, called kinds, live inside the bundle, so it describes\n its own structure.\n\nBees build comb one cell at a time. The comb holds what the colony gathers, and its shape shows\nthe next bee where to build and what belongs where. Superbee works the same way: people and\nagents record what they learn in a structure that fits their domain, and that structure guides\nwhoever works next. Each session builds on the last instead of starting over.\n\nThe npm package is one self-contained executable with zero runtime dependencies, plus an Agent\nSkill, an instruction file your agent loads, that teaches it how to use the tool.\n\n## Install\n\nRequires a supported Node.js 22, 24, or 26 release (22.14.0 minimum) on macOS or Linux. Native Windows is not supported by this package.\n\n```sh\nnpm install -g superbee\n```\n\nStable releases publish on npm's `latest` tag and prereleases on `next`. To try the prerelease:\n\n```sh\nnpm install -g superbee@next\n```\n\nWindows adapters and the `superbee-windows` executable live in a separate repository and are\nnot included in `superbee`. Most Windows users should run Superbee in WSL2, where npm sees a\nLinux platform and the normal installation applies. An experimental, unsupported native Windows\nbuild is available as open source, with build-from-source instructions: https://github.com/Holaxis-ai/superbee-windows-cli\n\n### Upgrading an existing Windows installation\n\nThe first release containing the Windows extraction removes native Windows support from this\npackage. Its npm `os` metadata permits only `darwin` and `linux`, so a Windows upgrade to an affected\nversion is rejected with `EBADPLATFORM`. This applies to existing prerelease users too. Forcing the\ninstallation does not restore support: the executable refuses commands on unsupported hosts\nbefore running them (the bare `--version` flag can still identify the installed build).\n\nThere is no supported Windows replacement on npm. The alternatives are WSL2 or the experimental\nbuild from source at https://github.com/Holaxis-ai/superbee-windows-cli; neither carries a\nfirst-party support promise for native Windows. An older installed version is not converted or\nremoved by this source change, and existing bundle files are not migrated by it. Review the affected release's notes before changing an existing\nWindows installation. macOS/Linux users can continue using the normal installation and setup flow.\n\nRun `superbee version --check` to compare your install with the current stable release.\n\n## First run: let your agent finish setup\n\n`npm install` gives you the CLI. The integrations (the Agent Skill, the `SessionStart` hook, and\nMCP server registration, where MCP is the Model Context Protocol) are installed by your agent,\nnot by hand. Ask it:\n\n> Run `superbee setup` and follow its instructions.\n\nSetup itself changes nothing. It inspects your configuration and returns one safe next command at\na time, and the agent runs each with your approval. Setup knows Claude Code, Codex, and OpenCode,\nplus Claude Desktop for the MCP registration only.\n\n## Everyday use\n\nYou rarely type Superbee commands yourself. You ask your agent, and the Agent Skill translates the\nrequest into CLI calls:\n\n- \"Set up a Superbee bundle for this project and track our tasks in it.\"\n- \"Write up what we decided about the auth design as a doc, and link it to the task.\"\n- \"What did the last session leave off on? Check the context notes.\"\n- \"Sync the board so my teammate's agent sees this.\"\n- \"Give me a view of the open tasks grouped by owner.\"\n\nBehind those requests the agent uses a small set of commands: `init --dir .superbee` creates the\nbundle, `new` creates a document of a declared kind, `doc write` writes a free-form one,\n`doc update` changes a document, `link add` connects two, `list` and `doc read` query them, and\n`sync` shares the board. `superbee --help` lists the commands, and `superbee <command> --help`\ngives each one's full reference.\n\nThe two commands meant for you are the ones that show you the knowledge:\n\n```sh\nsuperbee ui --open # the whole bundle, rendered in your browser\nsuperbee doc open <id> # one document, by an id from `superbee list`\n```\n\n## Upgrading from aslite\n\nIf you installed the earlier `@holaxis/aslite` package or its marketplace plugin: install\n`superbee` alongside it, have your agent run `superbee setup` to migrate the integrations, then\nrun `npm uninstall -g @holaxis/aslite`. Existing `.agentstate-lite/` bundles and\n`.agentstate.json` bindings keep working with no migration.\n\n## Learn more\n\nThe [repository](https://github.com/Holaxis-ai/superbee) holds the source, the\n[CLI contract](https://github.com/Holaxis-ai/superbee/blob/main/packages/superbee/AXI-CONTRACT.md),\nand the [wire protocol](https://github.com/Holaxis-ai/superbee/blob/main/docs/WIRE-PROTOCOL.md).\n\n## License\n\nApache-2.0 © 2026 Holaxis\n",
94
94
  "readmeFilename": "README.md"
95
95
  }