@superbee/core 0.2.0-pre.32 → 0.2.0-pre.34

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 (92) hide show
  1. package/README.md +13 -0
  2. package/dist/backend.d.ts +3 -1
  3. package/dist/backend.d.ts.map +1 -1
  4. package/dist/backend.js +76 -8
  5. package/dist/backend.js.map +1 -1
  6. package/dist/bundle-health/report.d.ts +5 -0
  7. package/dist/bundle-health/report.d.ts.map +1 -1
  8. package/dist/bundle-health/report.js +4 -0
  9. package/dist/bundle-health/report.js.map +1 -1
  10. package/dist/bundle-ops.d.ts +2 -1
  11. package/dist/bundle-ops.d.ts.map +1 -1
  12. package/dist/bundle-ops.js +2 -2
  13. package/dist/bundle-ops.js.map +1 -1
  14. package/dist/bundle.d.ts +1 -3
  15. package/dist/bundle.d.ts.map +1 -1
  16. package/dist/bundle.js +2 -11
  17. package/dist/bundle.js.map +1 -1
  18. package/dist/document-mutation.d.ts +3 -0
  19. package/dist/document-mutation.d.ts.map +1 -1
  20. package/dist/document-mutation.js +24 -2
  21. package/dist/document-mutation.js.map +1 -1
  22. package/dist/engine.d.ts +3 -1
  23. package/dist/engine.d.ts.map +1 -1
  24. package/dist/engine.js +16 -4
  25. package/dist/engine.js.map +1 -1
  26. package/dist/filesystem-identity.d.ts +9 -7
  27. package/dist/filesystem-identity.d.ts.map +1 -1
  28. package/dist/filesystem-identity.js +58 -5
  29. package/dist/filesystem-identity.js.map +1 -1
  30. package/dist/index.d.ts +4 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +2 -0
  33. package/dist/index.js.map +1 -1
  34. package/dist/inventory-guard.d.ts +58 -0
  35. package/dist/inventory-guard.d.ts.map +1 -0
  36. package/dist/inventory-guard.js +169 -0
  37. package/dist/inventory-guard.js.map +1 -0
  38. package/dist/kind-authoring.d.ts.map +1 -1
  39. package/dist/kind-authoring.js +1 -0
  40. package/dist/kind-authoring.js.map +1 -1
  41. package/dist/kind-deprecation.d.ts +32 -0
  42. package/dist/kind-deprecation.d.ts.map +1 -0
  43. package/dist/kind-deprecation.js +141 -0
  44. package/dist/kind-deprecation.js.map +1 -0
  45. package/dist/kinds.d.ts +32 -1
  46. package/dist/kinds.d.ts.map +1 -1
  47. package/dist/kinds.js +13 -0
  48. package/dist/kinds.js.map +1 -1
  49. package/dist/memory-backend.d.ts +3 -0
  50. package/dist/memory-backend.d.ts.map +1 -1
  51. package/dist/memory-backend.js +38 -0
  52. package/dist/memory-backend.js.map +1 -1
  53. package/dist/okf-actor.d.ts +1 -0
  54. package/dist/okf-actor.d.ts.map +1 -1
  55. package/dist/okf-actor.js +1 -0
  56. package/dist/okf-actor.js.map +1 -1
  57. package/dist/okf-authoring.d.ts +4 -0
  58. package/dist/okf-authoring.d.ts.map +1 -0
  59. package/dist/okf-authoring.js +12 -0
  60. package/dist/okf-authoring.js.map +1 -0
  61. package/dist/okf-standard-fields.d.ts +3 -0
  62. package/dist/okf-standard-fields.d.ts.map +1 -1
  63. package/dist/okf-standard-fields.js +3 -0
  64. package/dist/okf-standard-fields.js.map +1 -1
  65. package/dist/recipe-lifecycle/evolution.d.ts +13 -1
  66. package/dist/recipe-lifecycle/evolution.d.ts.map +1 -1
  67. package/dist/recipe-lifecycle/evolution.js +88 -9
  68. package/dist/recipe-lifecycle/evolution.js.map +1 -1
  69. package/dist/recipe-lifecycle/index.d.ts +4 -0
  70. package/dist/recipe-lifecycle/index.d.ts.map +1 -1
  71. package/dist/recipe-lifecycle/index.js +2 -0
  72. package/dist/recipe-lifecycle/index.js.map +1 -1
  73. package/dist/recipe-lifecycle/install.d.ts.map +1 -1
  74. package/dist/recipe-lifecycle/install.js +11 -1
  75. package/dist/recipe-lifecycle/install.js.map +1 -1
  76. package/dist/recipe-lifecycle/retirement-apply.d.ts +59 -0
  77. package/dist/recipe-lifecycle/retirement-apply.d.ts.map +1 -0
  78. package/dist/recipe-lifecycle/retirement-apply.js +165 -0
  79. package/dist/recipe-lifecycle/retirement-apply.js.map +1 -0
  80. package/dist/recipe-lifecycle/retirement.d.ts +89 -0
  81. package/dist/recipe-lifecycle/retirement.d.ts.map +1 -0
  82. package/dist/recipe-lifecycle/retirement.js +347 -0
  83. package/dist/recipe-lifecycle/retirement.js.map +1 -0
  84. package/dist/source-profiles/index.d.ts +1 -1
  85. package/dist/source-profiles/index.js +1 -1
  86. package/dist/storage.d.ts +2 -0
  87. package/dist/storage.d.ts.map +1 -1
  88. package/dist/storage.js +1 -0
  89. package/dist/storage.js.map +1 -1
  90. package/dist/types.d.ts +2 -0
  91. package/dist/types.d.ts.map +1 -1
  92. package/package.json +17 -1
@@ -0,0 +1,165 @@
1
+ /** One explicitly selected actual-source retirement stage; storage remains the commit authority. */
2
+ import { InvalidInputError } from "../errors.js";
3
+ import { compareStorageKeys } from "../paths.js";
4
+ import { VersionConflict } from "../versioning.js";
5
+ import { backendFor } from "../bundle-ops.js";
6
+ import { DocumentNotFoundError, mutateDocument } from "../document-mutation.js";
7
+ import { captureInventoryGuardRequest, INVENTORY_GUARD_DOMAIN, InventoryGuardConflict, InventoryGuardUnsupported, inventoryGuardFor } from "../inventory-guard.js";
8
+ import { buildKindRegistry } from "../kinds.js";
9
+ import { recipePreflightDigest } from "../recipe-set-preflight.js";
10
+ import { prepareRecipeRetirementStage } from "./evolution.js";
11
+ import { inspectRecipeInstallTarget, recipeDocumentForApply } from "./install.js";
12
+ import { definitionDigest } from "./stamp.js";
13
+ import { prepareRecipeDeclarationRetirement } from "./retirement.js";
14
+ export class RecipeRetirementApplyError extends Error {
15
+ reason;
16
+ plan;
17
+ completed = [];
18
+ failed;
19
+ pending_definitions;
20
+ constructor(reason, plan, cause) {
21
+ super(`Recipe retirement ${reason}; inspect a fresh stage plan before continuing.`, cause === undefined ? undefined : { cause });
22
+ this.name = "RecipeRetirementApplyError";
23
+ this.reason = reason;
24
+ this.plan = plan;
25
+ this.failed = { id: plan.next_definition, reason };
26
+ this.pending_definitions = [...(plan.next_definition ? [plan.next_definition] : []), ...plan.pending_definitions];
27
+ }
28
+ }
29
+ const compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
30
+ async function prepareStage(bundle, source, options) {
31
+ source = structuredClone(source);
32
+ options = { ...options };
33
+ if (Object.hasOwn(options, "consumerEvidence")) {
34
+ try {
35
+ options.consumerEvidence = structuredClone(options.consumerEvidence);
36
+ }
37
+ catch { /* The owning preflight returns unsupported input as a refusal. */ }
38
+ }
39
+ const bound = { root: bundle.root, backend: backendFor(bundle) };
40
+ let target, guardIssue;
41
+ try {
42
+ target = await inventoryGuardFor(bound.backend).observeTarget();
43
+ }
44
+ catch (error) {
45
+ guardIssue = error instanceof Error ? error.message : String(error);
46
+ }
47
+ const prepared = await prepareRecipeDeclarationRetirement(bound, source, options);
48
+ const report = prepared.report;
49
+ const ids = [...new Set(report.declarations.map(row => row.definition))].sort(compareStorageKeys);
50
+ const next = options.definitionId ?? ids[0] ?? null;
51
+ const selected = report.declarations.filter(row => row.definition === next);
52
+ const blockers = [...report.blockers];
53
+ const block = (code, message) => blockers.push({ code, id: next ?? report.id, message });
54
+ if (options.scope !== INVENTORY_GUARD_DOMAIN)
55
+ block("RETIREMENT_SCOPE_REQUIRED", "Explicit exact-root cooperating-local-writers-v1, local-only and consumer-unassessed limits are required.");
56
+ if (!next || !selected.length)
57
+ block("RETIREMENT_NO_ELIGIBLE_STAGE", "No eligible deprecated omission exists in the selected definition.");
58
+ if (!report.local.complete || report.local.issues.length)
59
+ block("RETIREMENT_LOCAL_UNKNOWN", "Complete readable stable local inventory is required.");
60
+ if (selected.some(row => row.usage.some(usage => usage.unknown || usage.count > 0)))
61
+ block("RETIREMENT_DECLARATION_USED_OR_UNKNOWN", "The selected definition has used or unknown retired coordinates.");
62
+ if (guardIssue || !target)
63
+ block("RETIREMENT_GUARD_UNAVAILABLE", guardIssue ?? "The actual backend has no supported guard.");
64
+ if (target && (target.edition !== report.local.okf_version || target.root_version !== report.local.root_index_version))
65
+ block("RETIREMENT_TARGET_CHANGED", "Guard target metadata differs from the inspected local scope.");
66
+ const inventory = report.local.inventory.filter((row) => row.version !== null).sort((a, b) => compareStorageKeys(a.id, b.id));
67
+ let candidate;
68
+ if (next && selected.length && report.local.complete) {
69
+ try {
70
+ const stage = await prepareRecipeRetirementStage(bound, prepared.source, next, selected);
71
+ blockers.push(...stage.plan.blockers);
72
+ candidate = stage.writes.get(next);
73
+ if (!candidate)
74
+ block("RETIREMENT_STAGE_UNCHANGED", "No actual-source retirement write was prepared.");
75
+ if (stage.plan.definitions.some(row => row.id === next && row.expected_version !== prepared.snapshots.get(next)?.version))
76
+ block("RETIREMENT_TARGET_CHANGED", "The stage target changed after the scan.");
77
+ }
78
+ catch (error) {
79
+ block("RETIREMENT_STAGE_UNAVAILABLE", error instanceof Error ? error.message : String(error));
80
+ }
81
+ }
82
+ if (Object.hasOwn(options, "consumerEvidence")) {
83
+ if (report.consumers.status === "partial" || report.consumers.status === "refused" || report.consumers.binding_issues.length || report.consumers.result?.verdict !== "valid")
84
+ block("RETIREMENT_CONSUMER_EVIDENCE_UNSUPPORTED", "Supplied consumer evidence must be valid and exactly bound; it cannot be downgraded to unassessed.");
85
+ // B assessed the final source. It certifies this stage only when all other owned concepts
86
+ // already match, and this actual evolution-owned candidate matches its assessed projection.
87
+ const owned = prepared.installation ? [...prepared.installation.docs, ...prepared.installation.connectors.map(row => row.doc), ...prepared.installation.references.map(row => row.doc), ...prepared.installation.pages.map(row => row.registry)] : [];
88
+ if (!candidate || !owned.length || owned.some(wanted => {
89
+ const actual = wanted.id === next ? candidate : prepared.snapshots.get(wanted.id)?.doc;
90
+ if (!actual || !prepared.installation)
91
+ return true;
92
+ const inspection = inspectRecipeInstallTarget(actual, wanted, prepared.installation);
93
+ return !inspection.sameContent || inspection.stamp !== "current" || inspection.stampIntegrity !== "current";
94
+ }))
95
+ block("RETIREMENT_STAGE_CONSUMER_UNREPRESENTABLE", "Final-source evidence does not represent this concrete intermediate stage; supply an actual staged source/evidence or inspect a later stage.");
96
+ }
97
+ if (target) {
98
+ try {
99
+ if (recipePreflightDigest(await inventoryGuardFor(bound.backend).observeTarget()) !== recipePreflightDigest(target))
100
+ block("RETIREMENT_TARGET_CHANGED", "Guard target changed while planning.");
101
+ }
102
+ catch (error) {
103
+ block("RETIREMENT_GUARD_UNAVAILABLE", error instanceof Error ? error.message : String(error));
104
+ }
105
+ }
106
+ if (target && candidate && next) {
107
+ try {
108
+ captureInventoryGuardRequest({ target, domain: INVENTORY_GUARD_DOMAIN, inventory, id: next,
109
+ expectedVersion: prepared.snapshots.get(next).version, doc: candidate });
110
+ }
111
+ catch (error) {
112
+ block("RETIREMENT_GUARD_UNAVAILABLE", error instanceof Error ? error.message : String(error));
113
+ }
114
+ }
115
+ blockers.sort((a, b) => compare(JSON.stringify(a), JSON.stringify(b)));
116
+ const plan = {
117
+ recipe: "declaration retirement apply", id: report.id, version: report.version, source: report.source, source_digest: report.source_digest,
118
+ scope: INVENTORY_GUARD_DOMAIN, ready_for_next_stage: blockers.length === 0,
119
+ next_definition: next, pending_definitions: ids.filter(id => id !== next), declarations: selected, blockers,
120
+ ...(target ? { target } : {}), consumers: report.consumers, external_consumers: report.external_consumers,
121
+ };
122
+ if (plan.ready_for_next_stage && candidate) {
123
+ plan.plan_token = `retirement-apply/v1:${recipePreflightDigest({ plan, inventory, observation_digest: report.local.observation_digest,
124
+ candidate: definitionDigest(candidate), stamp: candidate.frontmatter.x_recipe })}`;
125
+ }
126
+ return { plan, bundle: bound, candidate, inventory, expectedVersion: next ? prepared.snapshots.get(next)?.version : undefined };
127
+ }
128
+ export async function planRecipeDeclarationRetirementApply(bundle, source, options = {}) {
129
+ return (await prepareStage(bundle, source, options)).plan;
130
+ }
131
+ export async function applyRecipeDeclarationRetirement(bundle, source, expectedApplyToken, options = {}) {
132
+ options = { ...options };
133
+ const stage = await prepareStage(bundle, source, options);
134
+ const { plan } = stage;
135
+ if (!plan.ready_for_next_stage)
136
+ throw new RecipeRetirementApplyError("blocked", plan);
137
+ if (!/^retirement-apply\/v1:sha256:[0-9a-f]{64}$/.test(expectedApplyToken) || expectedApplyToken !== plan.plan_token)
138
+ throw new RecipeRetirementApplyError("plan_changed", plan);
139
+ const now = new Date().toISOString();
140
+ const desired = recipeDocumentForApply(stage.candidate, plan.target.edition, now);
141
+ try {
142
+ const result = await mutateDocument({ bundle: stage.bundle, id: plan.next_definition, mode: "replace-document", onAbsent: "fail",
143
+ expectedVersion: stage.expectedVersion, maxAttempts: 1, registry: buildKindRegistry([], [], { okfVersion: plan.target.edition }), strict: false,
144
+ seedGenerationClock: false, persistActor: false, actor: options.actor, now: () => now,
145
+ inventoryGuard: { target: plan.target, domain: plan.scope, inventory: stage.inventory },
146
+ buildCandidate: (_existing, context) => {
147
+ if (context.okfVersion !== plan.target.edition)
148
+ throw new InventoryGuardConflict("edition");
149
+ return { frontmatter: desired.frontmatter, body: desired.body };
150
+ },
151
+ });
152
+ return { recipe: "declaration retirement apply", id: plan.id, version: plan.version, scope: plan.scope,
153
+ completed: [{ id: plan.next_definition, version: result.version, changed: result.changed, stamped: true }],
154
+ pending_definitions: plan.pending_definitions, complete: plan.pending_definitions.length === 0, refresh_needed: plan.pending_definitions.length > 0,
155
+ consumers: plan.consumers, external_consumers: plan.external_consumers };
156
+ }
157
+ catch (error) {
158
+ // These owning typed refusals establish that publication did not occur. Keep their
159
+ // authority; only an unclassified persistence failure has an uncertain outcome.
160
+ if (error instanceof InventoryGuardUnsupported || error instanceof InvalidInputError || error instanceof VersionConflict || error instanceof DocumentNotFoundError)
161
+ throw error;
162
+ throw new RecipeRetirementApplyError(error instanceof InventoryGuardConflict ? "interrupted" : "outcome_unknown", plan, error);
163
+ }
164
+ }
165
+ //# sourceMappingURL=retirement-apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retirement-apply.js","sourceRoot":"","sources":["../../src/recipe-lifecycle/retirement-apply.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import { type LoadedRecipe } from "../recipes.js";
2
+ import { type PreflightResult } from "../recipe-set-preflight.js";
3
+ import type { Bundle, ReadResult } from "../types.js";
4
+ import { type PreparedRecipeInstall } from "./install.js";
5
+ export interface RetirementIssue {
6
+ code: string;
7
+ id: string;
8
+ message: string;
9
+ field?: string;
10
+ }
11
+ export interface RetirementDeclaration {
12
+ definition: string;
13
+ kind: string;
14
+ coordinate: "field" | "value" | "link";
15
+ name: string;
16
+ value?: string;
17
+ installed_version: string;
18
+ proposed_definition_digest: string;
19
+ usage: Array<{
20
+ id: string;
21
+ count: number;
22
+ unknown?: true;
23
+ }>;
24
+ }
25
+ export interface RecipeDeclarationRetirementPlan {
26
+ recipe: "declaration retirement inspection";
27
+ id: string;
28
+ version: string;
29
+ source: string;
30
+ source_digest: string;
31
+ scope: "observed-local-concepts-and-supplied-structural-consumers";
32
+ can_apply: false;
33
+ apply_blocker: "RETIREMENT_APPLY_NOT_IMPLEMENTED";
34
+ analysis: "complete" | "partial" | "refused";
35
+ declarations: RetirementDeclaration[];
36
+ blockers: RetirementIssue[];
37
+ local: {
38
+ verdict: "complete-clean" | "used" | "unknown";
39
+ complete: boolean;
40
+ consistency: "observed-stable-reads-not-an-atomic-snapshot";
41
+ target_root: string;
42
+ bundle_id?: string;
43
+ okf_version: string;
44
+ root_index_version: string | null;
45
+ initial_ids: string[];
46
+ final_ids: string[];
47
+ inventory: Array<{
48
+ id: string;
49
+ version: string | null;
50
+ }>;
51
+ observation_digest: string;
52
+ issues: RetirementIssue[];
53
+ };
54
+ consumers: {
55
+ status: "unassessed" | "valid" | "partial" | "refused";
56
+ scope: "supplied-declared-structural-only";
57
+ model: "final-selected-source-hypothesis";
58
+ evidence_digest?: string;
59
+ binding_issues: Array<{
60
+ level: "partial" | "refused";
61
+ code: string;
62
+ at: string;
63
+ }>;
64
+ result?: PreflightResult;
65
+ unsupported_semantics: readonly ["enum-value-compatibility", "type-compatibility", "write-intent-compatibility"];
66
+ };
67
+ external_consumers: "unknown-unenumerated-offline-and-arbitrary-code";
68
+ proposed_definitions: Array<{
69
+ id: string;
70
+ definition_digest: string;
71
+ hypothetical_content_version: string;
72
+ }>;
73
+ }
74
+ /** Internal reusable preparation for future guarded lifecycle application. The report alone
75
+ * remains non-authoritative; this data carries no permission or committing operation. */
76
+ export interface PreparedRecipeDeclarationRetirement {
77
+ report: RecipeDeclarationRetirementPlan;
78
+ source: LoadedRecipe;
79
+ installation?: PreparedRecipeInstall;
80
+ snapshots: ReadonlyMap<string, ReadResult>;
81
+ bundle: Bundle;
82
+ }
83
+ export declare function prepareRecipeDeclarationRetirement(bundle: Bundle, recipe: LoadedRecipe, options?: {
84
+ consumerEvidence?: unknown;
85
+ }): Promise<PreparedRecipeDeclarationRetirement>;
86
+ export declare function planRecipeDeclarationRetirement(bundle: Bundle, source: LoadedRecipe, options?: {
87
+ consumerEvidence?: unknown;
88
+ }): Promise<RecipeDeclarationRetirementPlan>;
89
+ //# sourceMappingURL=retirement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retirement.d.ts","sourceRoot":"","sources":["../../src/recipe-lifecycle/retirement.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,347 @@
1
+ /** Read-only retirement evidence. No plan returned here is an instruction or token for mutation. */
2
+ import { backendFor, readBundleOkfVersion, readDocVersioned } from "../bundle-ops.js";
3
+ import { declaredBundleId, BUNDLE_NAME_DOC_ID } from "../dependencies.js";
4
+ import { parseMarkdown } from "../frontmatter.js";
5
+ import { buildKindRegistry, isConventionId, kindDeprecationProblems, parseConventionDoc, inspectKindDeprecatedUsage } from "../kinds.js";
6
+ import { isOkfRecord, okfValuesEqual } from "../okf-authored-values.js";
7
+ import { parseRecipeFiles } from "../recipes.js";
8
+ import { preflightRecipeSet, recipePreflightDigest } from "../recipe-set-preflight.js";
9
+ import { contentVersion } from "../versioning.js";
10
+ import { materializeRecipeForEdition, prepareRecipeInstall, sameInstalledDoc } from "./install.js";
11
+ import { planRecipeEvolution } from "./evolution.js";
12
+ import { conventionStampState, definitionDigest, readRecipeStamp, recipeSourceDigest } from "./stamp.js";
13
+ const compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
14
+ const sorted = (ids) => [...ids].sort(compare);
15
+ const record = (value) => isOkfRecord(value) ? value : {};
16
+ const own = (value, key) => Object.hasOwn(value, key) ? value[key] : undefined;
17
+ function put(target, key, value) {
18
+ Object.defineProperty(target, key, { value, enumerable: true, configurable: true, writable: true });
19
+ }
20
+ /** Restore only each approved omission for the existing additive engine to inspect every OTHER
21
+ * change. This comparison recipe is never returned as an apply plan or passed to an apply API. */
22
+ function restoreOmission(target, current, coordinate, name, value) {
23
+ const child = (parent, key) => {
24
+ const next = { ...record(own(parent, key)) };
25
+ put(parent, key, next);
26
+ return next;
27
+ };
28
+ const restoreMap = (parent, key, previous, field) => {
29
+ const old = record(previous);
30
+ if (!Object.hasOwn(old, field))
31
+ return;
32
+ const next = child(parent, key);
33
+ if (!Object.hasOwn(next, field))
34
+ put(next, field, structuredClone(old[field]));
35
+ };
36
+ const append = (parent, key, entry) => {
37
+ const list = own(parent, key);
38
+ put(parent, key, [...(Array.isArray(list) ? list : []), structuredClone(entry)]);
39
+ };
40
+ const currentFields = record(current.frontmatter.fields);
41
+ const fields = child(target.frontmatter, "fields");
42
+ const deprecated = child(target.frontmatter, "deprecated");
43
+ if (coordinate === "field") {
44
+ append(fields, "optional", name);
45
+ for (const key of ["values", "types", "descriptions", "value_descriptions"])
46
+ restoreMap(fields, key, own(currentFields, key), name);
47
+ append(deprecated, "fields", name);
48
+ restoreMap(deprecated, "values", record(current.frontmatter.deprecated).values, name);
49
+ }
50
+ else if (coordinate === "value") {
51
+ const values = child(fields, "values");
52
+ const original = own(record(currentFields.values), name);
53
+ const member = Array.isArray(original) ? original.find(v => String(v) === value) : value;
54
+ append(values, name, member);
55
+ const descriptions = record(own(record(currentFields.value_descriptions), name));
56
+ if (Object.hasOwn(descriptions, value))
57
+ restoreMap(child(fields, "value_descriptions"), name, descriptions, value);
58
+ append(child(deprecated, "values"), name, value);
59
+ }
60
+ else {
61
+ restoreMap(target.frontmatter, "links", current.frontmatter.links, name);
62
+ restoreMap(target.frontmatter, "link_descriptions", current.frontmatter.link_descriptions, name);
63
+ append(deprecated, "links", name);
64
+ }
65
+ }
66
+ function candidateOwned(prepared) {
67
+ return [...prepared.docs, ...prepared.connectors.map(c => c.doc), ...prepared.references.map(r => r.doc)];
68
+ }
69
+ /** Optional supplied evidence is evaluated by the existing preflight, then bound to THIS source
70
+ * and this observed local store. A plausible but unrelated preflight cannot certify this report. */
71
+ async function consumersFor(supplied, present, source, prepared, snapshots, local) {
72
+ const out = { status: "unassessed", scope: "supplied-declared-structural-only", model: "final-selected-source-hypothesis", binding_issues: [],
73
+ unsupported_semantics: ["enum-value-compatibility", "type-compatibility", "write-intent-compatibility"] };
74
+ if (!present)
75
+ return out;
76
+ const issue = (level, code, at) => { out.binding_issues.push({ level, code, at }); };
77
+ out.result = await preflightRecipeSet(supplied);
78
+ try {
79
+ out.evidence_digest = recipePreflightDigest(supplied);
80
+ }
81
+ catch {
82
+ issue("refused", "RETIREMENT_EVIDENCE_SHAPE", "input");
83
+ }
84
+ if (out.result.issues.some(i => i.code === "INPUT_SHAPE")) {
85
+ out.status = "refused";
86
+ return out;
87
+ }
88
+ const input = supplied;
89
+ if (!prepared || local.okf_version !== "0.2")
90
+ issue("partial", "RETIREMENT_PREFLIGHT_EDITION_UNSUPPORTED", local.okf_version);
91
+ if (!local.complete)
92
+ issue("partial", "RETIREMENT_LOCAL_INVENTORY_UNKNOWN", "local");
93
+ const providers = input.selected.filter(s => s.recipeId === source.id && s.release === source.version);
94
+ if (providers.length !== 1)
95
+ issue("refused", "RETIREMENT_CANDIDATE_PROVIDER", source.id);
96
+ const provider = providers[0];
97
+ if (provider && !provider.artifact)
98
+ issue("partial", "RETIREMENT_CANDIDATE_ARTIFACT_UNAVAILABLE", provider.key);
99
+ else if (provider?.artifact) {
100
+ const parsed = parseRecipeFiles(provider.artifact.files, "retirement:supplied-candidate", { okfVersion: "0.2" });
101
+ if (!parsed.ok || recipeSourceDigest(parsed.recipe) !== recipeSourceDigest(source))
102
+ issue("refused", "RETIREMENT_CANDIDATE_SOURCE_MISMATCH", provider.key);
103
+ }
104
+ if (provider && prepared) {
105
+ const observations = input.observations.filter(o => o.provider === provider.key && o.scope === "local");
106
+ if (observations.length !== 1)
107
+ issue(observations.length ? "refused" : "partial", "RETIREMENT_CANDIDATE_OBSERVATION", provider.key);
108
+ for (const observed of observations) {
109
+ if (observed.availability !== "available" || !observed.complete) {
110
+ issue("partial", "RETIREMENT_CANDIDATE_OBSERVATION_UNKNOWN", observed.id);
111
+ continue;
112
+ }
113
+ const expected = candidateOwned(prepared);
114
+ if (!okfValuesEqual(sorted(observed.definitions.map(d => d.id)), sorted(expected.map(d => d.id))))
115
+ issue("refused", "RETIREMENT_CANDIDATE_DEFINITION_SET", observed.id);
116
+ for (const def of observed.definitions) {
117
+ const wanted = expected.find(d => d.id === def.id);
118
+ try {
119
+ const actual = { id: def.id, ...parseMarkdown(def.bytes, def.id, { okfVersion: "0.2" }) };
120
+ if (!wanted || definitionDigest(actual) !== definitionDigest(wanted))
121
+ issue("refused", "RETIREMENT_CANDIDATE_DEFINITION", `${observed.id}:${def.id}`);
122
+ }
123
+ catch {
124
+ issue("refused", "RETIREMENT_CANDIDATE_DEFINITION", `${observed.id}:${def.id}`);
125
+ }
126
+ }
127
+ }
128
+ const expected = new Map([...snapshots].map(([id, read]) => [`${id}.md`, read.doc]));
129
+ for (const doc of [...candidateOwned(prepared), ...prepared.pages.map(p => p.registry)])
130
+ expected.set(`${doc.id}.md`, doc);
131
+ const placements = (input.placementInventories ?? []).filter(p => p.scope === "local");
132
+ if (placements.length !== 1)
133
+ issue(placements.length ? "refused" : "partial", "RETIREMENT_LOCAL_PLACEMENT", "local");
134
+ for (const placement of placements) {
135
+ if (placement.availability !== "available" || !placement.complete)
136
+ issue("partial", "RETIREMENT_LOCAL_PLACEMENT_UNKNOWN", placement.id);
137
+ const docs = placement.files.filter(f => f.path.endsWith(".md"));
138
+ if (!okfValuesEqual(sorted(docs.map(f => f.path)), sorted([...expected.keys()])))
139
+ issue("refused", "RETIREMENT_LOCAL_PLACEMENT_SET", placement.id);
140
+ for (const file of docs) {
141
+ const wanted = expected.get(file.path);
142
+ try {
143
+ const actual = { id: file.path.slice(0, -3), ...parseMarkdown(file.bytes, undefined, { okfVersion: "0.2" }) };
144
+ const candidate = candidateOwned(prepared).some(d => `${d.id}.md` === file.path);
145
+ if (!wanted || (candidate ? !sameInstalledDoc(actual, wanted, "0.2") : contentVersion(actual) !== contentVersion(wanted)))
146
+ issue("refused", "RETIREMENT_LOCAL_PLACEMENT_CONTENT", file.path);
147
+ }
148
+ catch {
149
+ issue("refused", "RETIREMENT_LOCAL_PLACEMENT_CONTENT", file.path);
150
+ }
151
+ }
152
+ // Concept inventory does not establish ordinary blob bytes. Preserve that missing scope.
153
+ if (placement.files.some(f => !f.path.endsWith(".md")))
154
+ issue("partial", "RETIREMENT_BLOB_BINDING_UNSUPPORTED", placement.id);
155
+ }
156
+ }
157
+ for (const row of [...input.observations, ...(input.placementInventories ?? [])].filter(row => row.scope === "local")) {
158
+ if (!row.observedVersion)
159
+ issue("partial", "RETIREMENT_OBSERVATION_VERSION_UNKNOWN", row.id);
160
+ else if (row.observedVersion !== local.observation_digest)
161
+ issue("refused", "RETIREMENT_OBSERVATION_VERSION_MISMATCH", row.id);
162
+ if (row.bundleId && row.bundleId !== local.bundle_id)
163
+ issue("refused", "RETIREMENT_BUNDLE_IDENTITY", row.id);
164
+ }
165
+ out.binding_issues.sort((a, b) => compare(JSON.stringify(a), JSON.stringify(b)));
166
+ out.status = out.result.verdict === "refused" || out.binding_issues.some(i => i.level === "refused") ? "refused"
167
+ : out.result.verdict === "partial" || out.binding_issues.length ? "partial" : input.consumers.length ? "valid" : "unassessed";
168
+ return out;
169
+ }
170
+ export async function prepareRecipeDeclarationRetirement(bundle, recipe, options = {}) {
171
+ const source = structuredClone(recipe);
172
+ const backend = backendFor(bundle), selected = { root: bundle.root, backend };
173
+ const evidencePresent = Object.hasOwn(options, "consumerEvidence");
174
+ let evidence = options.consumerEvidence;
175
+ try {
176
+ if (evidencePresent)
177
+ evidence = structuredClone(evidence);
178
+ }
179
+ catch { /* Existing preflight returns the shape refusal. */ }
180
+ const issues = [], blockers = [];
181
+ const snapshots = new Map();
182
+ const inventory = [];
183
+ let initial = [], final = [], indexVersion = null, edition = "0.1";
184
+ const unknown = (code, id, error) => { issues.push({ code, id, message: error instanceof Error ? error.message : String(error) }); };
185
+ try {
186
+ indexVersion = (await backend.readReserved("", "index.md"))?.version ?? null;
187
+ edition = await readBundleOkfVersion(selected) ?? "0.1";
188
+ }
189
+ catch (error) {
190
+ unknown("RETIREMENT_EDITION_UNREADABLE", "index.md", error);
191
+ }
192
+ try {
193
+ initial = sorted(await backend.list());
194
+ }
195
+ catch (error) {
196
+ unknown("RETIREMENT_INVENTORY_UNAVAILABLE", "*", error);
197
+ }
198
+ if (new Set(initial).size !== initial.length)
199
+ unknown("RETIREMENT_INVENTORY_AMBIGUOUS", "*", "duplicate concept IDs");
200
+ for (const id of [...new Set(initial)]) {
201
+ try {
202
+ const read = await readDocVersioned(selected, id);
203
+ if (read.doc.id !== id || typeof read.version !== "string" || !read.version)
204
+ throw new Error("backend returned an invalid concept identity/version");
205
+ snapshots.set(id, read);
206
+ inventory.push({ id, version: read.version });
207
+ }
208
+ catch (error) {
209
+ inventory.push({ id, version: null });
210
+ unknown("RETIREMENT_CONCEPT_UNREADABLE", id, error);
211
+ }
212
+ }
213
+ const currentDocs = [...snapshots.values()].map(r => r.doc);
214
+ const registry = buildKindRegistry(currentDocs.filter(d => isConventionId(d.id) && d.frontmatter.type === "Convention"), [], { okfVersion: edition });
215
+ for (const warning of registry.warnings)
216
+ blockers.push({ code: warning.code, id: "conventions/", message: warning.message, ...(warning.field ? { field: warning.field } : {}) });
217
+ const declarations = [];
218
+ let prepared;
219
+ try {
220
+ if (edition !== "0.1" && edition !== "0.2")
221
+ throw new Error(`unsupported bundle edition '${edition}'`);
222
+ prepared = prepareRecipeInstall(source, { okfVersion: edition, now: "1970-01-01T00:00:00.000Z" });
223
+ const comparison = materializeRecipeForEdition(structuredClone(source), edition);
224
+ const proposed = buildKindRegistry(prepared.docs, [], { okfVersion: edition });
225
+ for (const warning of proposed.warnings)
226
+ blockers.push({ code: warning.code, id: source.id, message: warning.message, ...(warning.field ? { field: warning.field } : {}) });
227
+ for (const target of comparison.docs) {
228
+ const installed = snapshots.get(target.id), current = installed?.doc;
229
+ const next = parseConventionDoc(target, { okfVersion: edition });
230
+ if (!current || !installed || !next.ok) {
231
+ blockers.push({ code: "RETIREMENT_DEFINITION_UNAVAILABLE", id: target.id, message: "retirement requires a readable installed and proposed convention" });
232
+ continue;
233
+ }
234
+ const parsed = parseConventionDoc(current, { okfVersion: edition });
235
+ if (!parsed.ok || current.frontmatter.type !== "Convention" || parsed.kind.governs !== next.kind.governs) {
236
+ blockers.push({ code: "RETIREMENT_DEFINITION_IDENTITY", id: target.id, message: "installed and proposed convention identities differ" });
237
+ continue;
238
+ }
239
+ const kind = parsed.kind;
240
+ if (readRecipeStamp(current)?.id !== source.id || conventionStampState(current) !== "current") {
241
+ blockers.push({ code: "RETIREMENT_OWNERSHIP_UNPROVEN", id: target.id, message: "an unchanged readable same-recipe ownership stamp is required" });
242
+ continue;
243
+ }
244
+ if (kindDeprecationProblems(kind, registry).length)
245
+ continue;
246
+ const retiredFields = new Set();
247
+ const add = (coordinate, name, value) => {
248
+ const candidate = { definition: target.id, kind: kind.governs, coordinate, name, ...(value === undefined ? {} : { value }), installed_version: installed.version,
249
+ proposed_definition_digest: definitionDigest(prepared.docs.find(d => d.id === target.id)), usage: [] };
250
+ for (const doc of currentDocs.filter(d => d.frontmatter.type === kind.governs)) {
251
+ for (const row of inspectKindDeprecatedUsage(doc, kind)) {
252
+ if (row.field !== name || row.code !== (coordinate === "field" ? "KIND_DEPRECATED_FIELD" : coordinate === "value" ? "KIND_DEPRECATED_VALUE" : "KIND_DEPRECATED_LINK"))
253
+ continue;
254
+ if (coordinate === "value" && row.value !== value)
255
+ continue;
256
+ candidate.usage.push({ id: doc.id, count: row.count, ...(row.unknown ? { unknown: true } : {}) });
257
+ }
258
+ }
259
+ declarations.push(candidate);
260
+ restoreOmission(target, current, coordinate, name, value);
261
+ };
262
+ const desiredFields = new Set([...next.kind.fields.required, ...next.kind.fields.optional]);
263
+ for (const name of kind.fields.optional)
264
+ if (!desiredFields.has(name) && kind.deprecated?.fields.includes(name)) {
265
+ if (Object.hasOwn(kind.fields.terminal, name) && kind.fields.terminal[name].length) {
266
+ blockers.push({ code: "RETIREMENT_TERMINAL_CHANGE_UNSUPPORTED", id: target.id, field: name, message: "terminal coordinates require a separate migration" });
267
+ continue;
268
+ }
269
+ retiredFields.add(name);
270
+ add("field", name);
271
+ }
272
+ for (const [name, values] of Object.entries(kind.fields.values))
273
+ if (!retiredFields.has(name)) {
274
+ const remaining = Object.hasOwn(next.kind.fields.values, name) ? next.kind.fields.values[name] : undefined;
275
+ if (!remaining)
276
+ continue; // Whole vocabulary removal remains the additive owner's unsupported omission.
277
+ const deprecatedValues = kind.deprecated && Object.hasOwn(kind.deprecated.values, name) ? kind.deprecated.values[name] : [];
278
+ for (const value of values)
279
+ if (!remaining.includes(value) && deprecatedValues.includes(value))
280
+ add("value", name, value);
281
+ }
282
+ for (const name of Object.keys(kind.links ?? {}))
283
+ if (!Object.hasOwn(next.kind.links ?? {}, name) && kind.deprecated?.links.includes(name))
284
+ add("link", name);
285
+ const restored = parseConventionDoc(target, { okfVersion: edition });
286
+ if (restored.ok)
287
+ for (const [field, before, after] of [
288
+ ["fields.types", kind.fields.types ?? {}, restored.kind.fields.types ?? {}],
289
+ ["fields.required", sorted(kind.fields.required), sorted(restored.kind.fields.required)],
290
+ ["fields.terminal", kind.fields.terminal, restored.kind.fields.terminal], ["claim", kind.claim ?? {}, restored.kind.claim ?? {}],
291
+ ["sections", kind.sections ?? [], restored.kind.sections ?? []],
292
+ ])
293
+ if (!okfValuesEqual(before, after))
294
+ blockers.push({ code: "RETIREMENT_MIGRATION_UNSUPPORTED", id: target.id, field, message: "retirement inspection does not authorize unrelated type, required, terminal or claim migrations" });
295
+ }
296
+ for (const doc of currentDocs.filter(d => isConventionId(d.id) && readRecipeStamp(d)?.id === source.id)) {
297
+ if (!comparison.docs.some(d => d.id === doc.id))
298
+ blockers.push({ code: "RETIREMENT_DEFINITION_OMISSION_UNSUPPORTED", id: doc.id, message: "whole convention removal is not declaration retirement" });
299
+ }
300
+ // Existing evolution owns all non-retirement omissions, replacements, source warnings and instance validation.
301
+ const compatibility = await planRecipeEvolution(selected, comparison);
302
+ blockers.push(...compatibility.blockers);
303
+ }
304
+ catch (error) {
305
+ blockers.push({ code: "RETIREMENT_SOURCE_UNVERIFIABLE", id: source.id, message: error instanceof Error ? error.message : String(error) });
306
+ }
307
+ try {
308
+ final = sorted(await backend.list());
309
+ if (!okfValuesEqual(initial, final))
310
+ unknown("RETIREMENT_INVENTORY_CHANGED", "*", "concept membership changed while scanning");
311
+ for (const row of inventory)
312
+ if (row.version !== null) {
313
+ try {
314
+ if ((await readDocVersioned(selected, row.id)).version !== row.version)
315
+ unknown("RETIREMENT_CONCEPT_CHANGED", row.id, "concept version changed while scanning");
316
+ }
317
+ catch (error) {
318
+ unknown("RETIREMENT_CONCEPT_CHANGED", row.id, error);
319
+ }
320
+ }
321
+ if (((await backend.readReserved("", "index.md"))?.version ?? null) !== indexVersion)
322
+ unknown("RETIREMENT_EDITION_CHANGED", "index.md", "root index changed while scanning");
323
+ }
324
+ catch (error) {
325
+ unknown("RETIREMENT_INVENTORY_UNVERIFIABLE", "*", error);
326
+ }
327
+ issues.sort((a, b) => compare(JSON.stringify(a), JSON.stringify(b)));
328
+ blockers.sort((a, b) => compare(JSON.stringify(a), JSON.stringify(b)));
329
+ const bundleId = declaredBundleId(snapshots.get(BUNDLE_NAME_DOC_ID)?.doc);
330
+ const complete = issues.length === 0;
331
+ const localBase = { complete, consistency: "observed-stable-reads-not-an-atomic-snapshot", target_root: selected.root,
332
+ ...(bundleId ? { bundle_id: bundleId } : {}), okf_version: edition, root_index_version: indexVersion, initial_ids: initial, final_ids: final, inventory, issues };
333
+ const local = { ...localBase,
334
+ verdict: declarations.some(d => d.usage.some(u => !u.unknown)) ? "used" : !complete || blockers.length > 0 || declarations.some(d => d.usage.some(u => u.unknown)) ? "unknown" : "complete-clean",
335
+ observation_digest: recipePreflightDigest(localBase) };
336
+ const consumers = await consumersFor(evidence, evidencePresent, source, prepared, snapshots, local);
337
+ const report = { recipe: "declaration retirement inspection", id: source.id, version: source.version, source: source.source, source_digest: recipeSourceDigest(source),
338
+ scope: "observed-local-concepts-and-supplied-structural-consumers", can_apply: false, apply_blocker: "RETIREMENT_APPLY_NOT_IMPLEMENTED",
339
+ analysis: blockers.length || consumers.status === "refused" ? "refused" : !complete || local.verdict === "unknown" || consumers.status === "partial" ? "partial" : "complete",
340
+ declarations, blockers, local, consumers, external_consumers: "unknown-unenumerated-offline-and-arbitrary-code",
341
+ proposed_definitions: (prepared ? candidateOwned(prepared) : []).map(doc => ({ id: doc.id, definition_digest: definitionDigest(doc), hypothetical_content_version: contentVersion(doc) })) };
342
+ return { report, source, ...(prepared ? { installation: prepared } : {}), snapshots, bundle: selected };
343
+ }
344
+ export async function planRecipeDeclarationRetirement(bundle, source, options = {}) {
345
+ return (await prepareRecipeDeclarationRetirement(bundle, source, options)).report;
346
+ }
347
+ //# sourceMappingURL=retirement.js.map