kibi-cli 0.16.1 → 0.18.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.
Files changed (229) hide show
  1. package/dist/cli-json-command.d.ts.map +1 -1
  2. package/dist/cli-json-command.js +87 -11
  3. package/dist/cli-register-maintenance.d.ts.map +1 -1
  4. package/dist/cli-register-maintenance.js +8 -0
  5. package/dist/cli-register-reporting.d.ts.map +1 -1
  6. package/dist/cli-register-reporting.js +5 -0
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +2 -1
  9. package/dist/commands/aggregated-checks.d.ts.map +1 -1
  10. package/dist/commands/aggregated-checks.js +1 -0
  11. package/dist/commands/check.d.ts.map +1 -1
  12. package/dist/commands/check.js +1 -1
  13. package/dist/commands/coverage.d.ts +5 -0
  14. package/dist/commands/coverage.d.ts.map +1 -1
  15. package/dist/commands/coverage.js +5 -0
  16. package/dist/commands/discovery-table.d.ts.map +1 -1
  17. package/dist/commands/discovery-table.js +96 -5
  18. package/dist/commands/sync/cache.d.ts +2 -0
  19. package/dist/commands/sync/cache.d.ts.map +1 -1
  20. package/dist/commands/sync/cache.js +8 -0
  21. package/dist/commands/sync/manifest.d.ts +12 -1
  22. package/dist/commands/sync/manifest.d.ts.map +1 -1
  23. package/dist/commands/sync/manifest.js +22 -5
  24. package/dist/commands/sync/persistence.d.ts.map +1 -1
  25. package/dist/commands/sync/persistence.js +76 -2
  26. package/dist/commands/sync.d.ts.map +1 -1
  27. package/dist/commands/sync.js +72 -15
  28. package/dist/commands/usage-metrics.d.ts +66 -2
  29. package/dist/commands/usage-metrics.d.ts.map +1 -1
  30. package/dist/commands/usage-metrics.js +34 -24
  31. package/dist/commands/usage-remediation.d.ts +9 -0
  32. package/dist/commands/usage-remediation.d.ts.map +1 -0
  33. package/dist/commands/usage-remediation.js +52 -0
  34. package/dist/extractors/markdown.d.ts +17 -1
  35. package/dist/extractors/markdown.d.ts.map +1 -1
  36. package/dist/extractors/markdown.js +81 -2
  37. package/dist/logic/ir.d.ts +112 -0
  38. package/dist/logic/ir.d.ts.map +1 -0
  39. package/dist/logic/ir.js +729 -0
  40. package/dist/operations/modeling/logic-modeling.d.ts +22 -0
  41. package/dist/operations/modeling/logic-modeling.d.ts.map +1 -0
  42. package/dist/operations/modeling/logic-modeling.js +120 -0
  43. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  44. package/dist/operations/modeling/model-requirement.js +83 -2
  45. package/dist/operations/modeling/predicate-applyplan.d.ts +1 -1
  46. package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
  47. package/dist/operations/modeling/predicate-applyplan.js +29 -4
  48. package/dist/operations/modeling/predicate-inference.d.ts.map +1 -1
  49. package/dist/operations/modeling/predicate-inference.js +3 -0
  50. package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
  51. package/dist/operations/modeling/predicate-loader.js +7 -1
  52. package/dist/operations/modeling/predicate-ranker.d.ts.map +1 -1
  53. package/dist/operations/modeling/predicate-ranker.js +40 -2
  54. package/dist/operations/modeling/predicate-types.d.ts +12 -1
  55. package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
  56. package/dist/operations/modeling/requirement-types.d.ts +12 -0
  57. package/dist/operations/modeling/requirement-types.d.ts.map +1 -1
  58. package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
  59. package/dist/operations/modeling/suggest-predicates.js +35 -11
  60. package/dist/operations/mutation/audit.js +1 -1
  61. package/dist/operations/mutation/contradictions.d.ts +1 -1
  62. package/dist/operations/mutation/contradictions.d.ts.map +1 -1
  63. package/dist/operations/mutation/contradictions.js +23 -18
  64. package/dist/operations/mutation/relationships.d.ts.map +1 -1
  65. package/dist/operations/mutation/relationships.js +8 -0
  66. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  67. package/dist/operations/mutation/serialization.js +6 -0
  68. package/dist/operations/mutation/strict-fact.d.ts.map +1 -1
  69. package/dist/operations/mutation/strict-fact.js +68 -3
  70. package/dist/operations/mutation/upsert.d.ts +3 -1
  71. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  72. package/dist/operations/mutation/upsert.js +51 -12
  73. package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
  74. package/dist/operations/mutation/validate-upsert.js +18 -2
  75. package/dist/operations/mutation/validation.d.ts.map +1 -1
  76. package/dist/operations/mutation/validation.js +8 -0
  77. package/dist/operations/semantic-advisor/analysis-receipt.d.ts +2 -2
  78. package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
  79. package/dist/operations/semantic-advisor/analysis-receipt.js +30 -16
  80. package/dist/operations/semantic-advisor/analyze-prose.d.ts +1 -1
  81. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  82. package/dist/operations/semantic-advisor/analyze-prose.js +464 -27
  83. package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
  84. package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
  85. package/dist/operations/semantic-advisor/clauses.js +7 -7
  86. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts +18 -0
  87. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -0
  88. package/dist/operations/semantic-advisor/ingestion-boundary.js +167 -0
  89. package/dist/operations/semantic-advisor/observation-plan.d.ts.map +1 -1
  90. package/dist/operations/semantic-advisor/observation-plan.js +15 -3
  91. package/dist/operations/semantic-advisor/shared.d.ts +9 -0
  92. package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
  93. package/dist/operations/semantic-advisor/shared.js +38 -4
  94. package/dist/operations/semantic-advisor/types.d.ts +66 -1
  95. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  96. package/dist/prolog/codec.d.ts.map +1 -1
  97. package/dist/prolog/codec.js +19 -2
  98. package/dist/prolog.d.ts +6 -0
  99. package/dist/prolog.d.ts.map +1 -1
  100. package/dist/prolog.js +247 -63
  101. package/dist/public/diagnostic-usage.d.ts +17 -0
  102. package/dist/public/diagnostic-usage.d.ts.map +1 -0
  103. package/dist/public/diagnostic-usage.js +152 -0
  104. package/dist/public/distribution-parity.d.ts +90 -0
  105. package/dist/public/distribution-parity.d.ts.map +1 -0
  106. package/dist/public/distribution-parity.js +367 -0
  107. package/dist/public/impact/full-kb-quality.d.ts +2 -0
  108. package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
  109. package/dist/public/impact/full-kb-quality.js +53 -1
  110. package/dist/public/impact-diagnostics.d.ts +2 -0
  111. package/dist/public/impact-diagnostics.d.ts.map +1 -1
  112. package/dist/public/impact-diagnostics.js +1 -0
  113. package/dist/public/operations/catalog.d.ts +235 -11
  114. package/dist/public/operations/catalog.d.ts.map +1 -1
  115. package/dist/public/operations/check-executor.d.ts.map +1 -1
  116. package/dist/public/operations/check-executor.js +4 -0
  117. package/dist/public/operations/discovery-executors.d.ts +6 -0
  118. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  119. package/dist/public/operations/discovery-executors.js +18 -2
  120. package/dist/public/operations/index.d.ts +5 -0
  121. package/dist/public/operations/index.d.ts.map +1 -1
  122. package/dist/public/operations/index.js +5 -0
  123. package/dist/public/operations/legacy-migration-plan.d.ts +113 -0
  124. package/dist/public/operations/legacy-migration-plan.d.ts.map +1 -0
  125. package/dist/public/operations/legacy-migration-plan.js +409 -0
  126. package/dist/public/operations/node-ports.d.ts.map +1 -1
  127. package/dist/public/operations/node-ports.js +90 -0
  128. package/dist/public/operations/repair-plan.d.ts +184 -0
  129. package/dist/public/operations/repair-plan.d.ts.map +1 -0
  130. package/dist/public/operations/repair-plan.js +397 -0
  131. package/dist/public/operations/runtime-types.d.ts +7 -0
  132. package/dist/public/operations/runtime-types.d.ts.map +1 -1
  133. package/dist/public/operations/specs/check.d.ts +3 -3
  134. package/dist/public/operations/specs/check.d.ts.map +1 -1
  135. package/dist/public/operations/specs/check.js +5 -2
  136. package/dist/public/operations/specs/discovery.d.ts +1 -1
  137. package/dist/public/operations/specs/discovery.js +1 -1
  138. package/dist/public/operations/specs/modeling.d.ts +35 -1
  139. package/dist/public/operations/specs/modeling.d.ts.map +1 -1
  140. package/dist/public/operations/specs/modeling.js +32 -1
  141. package/dist/public/operations/specs/mutation-schemas.d.ts +133 -3
  142. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  143. package/dist/public/operations/specs/mutation-schemas.js +67 -1
  144. package/dist/public/operations/specs/reporting.d.ts +42 -1
  145. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  146. package/dist/public/operations/specs/reporting.js +70 -6
  147. package/dist/public/operations/specs/semantic.d.ts +30 -2
  148. package/dist/public/operations/specs/semantic.d.ts.map +1 -1
  149. package/dist/public/operations/specs/semantic.js +35 -3
  150. package/dist/public/operations/specs/upsert.d.ts +133 -3
  151. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  152. package/dist/public/operations/workspace-snapshot.d.ts +10 -0
  153. package/dist/public/operations/workspace-snapshot.d.ts.map +1 -0
  154. package/dist/public/operations/workspace-snapshot.js +20 -0
  155. package/dist/public/schemas/entity.d.ts.map +1 -1
  156. package/dist/public/schemas/entity.js +332 -0
  157. package/dist/public/schemas/relationship.d.ts.map +1 -1
  158. package/dist/public/schemas/relationship.js +1 -0
  159. package/dist/public/skills/kibi-traceability/SKILL.md +7 -1
  160. package/dist/public/skills/kibi-usage/SKILL.md +44 -12
  161. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +12 -2
  162. package/dist/public/skills/kibi-usage/resources/logic-ir.md +43 -0
  163. package/dist/public/skills/kibi-usage/resources/operation-access.md +19 -19
  164. package/dist/public/skills/kibi-usage/resources/ui-requirements.md +96 -0
  165. package/dist/public/skills/kibi-usage/resources/workflows.md +40 -8
  166. package/dist/public/symbol-granularity.d.ts +9 -0
  167. package/dist/public/symbol-granularity.d.ts.map +1 -1
  168. package/dist/public/symbol-granularity.js +16 -0
  169. package/dist/public/telemetry-acceptance.d.ts +89 -0
  170. package/dist/public/telemetry-acceptance.d.ts.map +1 -0
  171. package/dist/public/telemetry-acceptance.js +597 -0
  172. package/dist/public/telemetry-remediation.d.ts +33 -0
  173. package/dist/public/telemetry-remediation.d.ts.map +1 -0
  174. package/dist/public/telemetry-remediation.js +257 -0
  175. package/dist/public/verification-receipt.d.ts +75 -0
  176. package/dist/public/verification-receipt.d.ts.map +1 -0
  177. package/dist/public/verification-receipt.js +129 -0
  178. package/dist/schemas/entity.schema.json +401 -4
  179. package/dist/traceability/staged-diagnostics.d.ts +1 -1
  180. package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
  181. package/dist/traceability/staged-diagnostics.js +17 -10
  182. package/dist/traceability/staged-impact-contract.js +1 -1
  183. package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
  184. package/dist/traceability/staged-symbols-manifest.js +28 -10
  185. package/dist/traceability/temp-kb.d.ts.map +1 -1
  186. package/dist/traceability/temp-kb.js +49 -3
  187. package/dist/types/entities.d.ts +1 -0
  188. package/dist/types/entities.d.ts.map +1 -1
  189. package/dist/types/relationships.d.ts +1 -1
  190. package/dist/types/relationships.d.ts.map +1 -1
  191. package/dist/utils/rule-registry.d.ts +2 -0
  192. package/dist/utils/rule-registry.d.ts.map +1 -1
  193. package/dist/utils/rule-registry.js +18 -0
  194. package/dist/utils/schema-version.d.ts +1 -1
  195. package/dist/utils/schema-version.js +1 -1
  196. package/package.json +34 -2
  197. package/src/public/diagnostic-usage.ts +206 -0
  198. package/src/public/distribution-parity.ts +580 -0
  199. package/src/public/impact/full-kb-quality.ts +74 -1
  200. package/src/public/impact-diagnostics.ts +16 -0
  201. package/src/public/operations/check-executor.ts +4 -0
  202. package/src/public/operations/discovery-executors.ts +24 -2
  203. package/src/public/operations/index.ts +5 -0
  204. package/src/public/operations/legacy-migration-plan.ts +688 -0
  205. package/src/public/operations/node-ports.ts +109 -0
  206. package/src/public/operations/repair-plan.ts +562 -0
  207. package/src/public/operations/runtime-types.ts +8 -0
  208. package/src/public/operations/specs/check.ts +5 -2
  209. package/src/public/operations/specs/discovery.ts +1 -1
  210. package/src/public/operations/specs/modeling.ts +39 -1
  211. package/src/public/operations/specs/mutation-schemas.ts +77 -1
  212. package/src/public/operations/specs/reporting.ts +91 -6
  213. package/src/public/operations/specs/semantic.ts +42 -3
  214. package/src/public/operations/workspace-snapshot.ts +28 -0
  215. package/src/public/schemas/entity.ts +340 -1
  216. package/src/public/schemas/relationship.ts +1 -0
  217. package/src/public/skills/kibi-traceability/SKILL.md +7 -1
  218. package/src/public/skills/kibi-usage/SKILL.md +44 -12
  219. package/src/public/skills/kibi-usage/resources/fact-lanes.md +12 -2
  220. package/src/public/skills/kibi-usage/resources/logic-ir.md +43 -0
  221. package/src/public/skills/kibi-usage/resources/operation-access.md +19 -19
  222. package/src/public/skills/kibi-usage/resources/ui-requirements.md +96 -0
  223. package/src/public/skills/kibi-usage/resources/workflows.md +40 -8
  224. package/src/public/symbol-granularity.ts +25 -0
  225. package/src/public/telemetry-acceptance.ts +859 -0
  226. package/src/public/telemetry-remediation.ts +462 -0
  227. package/src/public/verification-receipt.ts +170 -0
  228. package/src/schemas/entity.schema.json +401 -4
  229. package/src/schemas/relationship.schema.json +1 -0
@@ -0,0 +1,409 @@
1
+ import { createHash } from "node:crypto";
2
+ import { requirementSemanticText } from "../../extractors/markdown.js";
3
+ import { buildSuggestion } from "../../operations/modeling/predicate-applyplan.js";
4
+ import { BUILT_IN_PREDICATE_SCHEMAS } from "../../operations/modeling/predicate-catalog.js";
5
+ import { inferSubject } from "../../operations/modeling/predicate-inference.js";
6
+ import { loadExistingPredicateSchemas } from "../../operations/modeling/predicate-loader.js";
7
+ import { scoreSchema } from "../../operations/modeling/predicate-ranker.js";
8
+ import { analyzeSemanticAdvisorInput } from "../../operations/semantic-advisor/analyze-prose.js";
9
+ import { semanticSourceHash } from "../../operations/semantic-advisor/shared.js";
10
+ import { loadMarkdownBody } from "../../search-ranking.js";
11
+ import { loadEntities } from "./discovery-entities.js";
12
+ export const LEGACY_MIGRATION_PLAN_VERSION = "kibi.legacy-migration-plan.v1";
13
+ function isRecord(value) {
14
+ return value !== null && typeof value === "object" && !Array.isArray(value);
15
+ }
16
+ function stringList(value) {
17
+ if (typeof value === "string")
18
+ return [stripKbEntityPrefix(value)];
19
+ if (!Array.isArray(value))
20
+ return [];
21
+ return value.flatMap((item) => typeof item === "string" ? [stripKbEntityPrefix(item)] : []);
22
+ }
23
+ function stripKbEntityPrefix(value) {
24
+ return value.replace(/^kb:entity\//, "");
25
+ }
26
+ function clampInteger(value, fallback, minimum, maximum) {
27
+ if (!Number.isInteger(value))
28
+ return fallback;
29
+ return Math.min(maximum, Math.max(minimum, value ?? fallback));
30
+ }
31
+ function clampScore(value) {
32
+ if (typeof value !== "number" || !Number.isFinite(value))
33
+ return 0.35;
34
+ return Math.min(1, Math.max(0, value));
35
+ }
36
+ function stableValue(value) {
37
+ if (Array.isArray(value))
38
+ return value.map(stableValue);
39
+ if (!isRecord(value))
40
+ return value;
41
+ return Object.fromEntries(Object.entries(value)
42
+ .sort(([left], [right]) => left.localeCompare(right))
43
+ .map(([key, item]) => [key, stableValue(item)]));
44
+ }
45
+ function stableStringify(value) {
46
+ return JSON.stringify(stableValue(value));
47
+ }
48
+ function hash(value) {
49
+ return createHash("sha256").update(stableStringify(value)).digest("hex");
50
+ }
51
+ function migrationRepairBatches(plan) {
52
+ const seen = new Set();
53
+ return plan.batches
54
+ .filter((batch) => batch.phase === "semantic_inventory" && batch.state === "ready")
55
+ .filter((batch) => {
56
+ if (seen.has(batch.requirementId))
57
+ return false;
58
+ seen.add(batch.requirementId);
59
+ return true;
60
+ })
61
+ .sort((left, right) => left.requirementId.localeCompare(right.requirementId));
62
+ }
63
+ function schemaIdentity(schema) {
64
+ return `${schema.predicate_name}(${schema.argument_names.join(",")}):${schema.argument_types.join(",")}`;
65
+ }
66
+ function predicateCatalog(projectSchemas) {
67
+ const result = [];
68
+ const seen = new Set();
69
+ for (const [origin, schemas] of [
70
+ ["project_local", projectSchemas],
71
+ ["built_in", BUILT_IN_PREDICATE_SCHEMAS],
72
+ ]) {
73
+ for (const schema of schemas) {
74
+ const identity = schemaIdentity(schema);
75
+ if (seen.has(identity))
76
+ continue;
77
+ seen.add(identity);
78
+ result.push({ schema, origin });
79
+ }
80
+ }
81
+ return result;
82
+ }
83
+ function rankPredicateCandidates(claimText, catalog, limit, minimumScore) {
84
+ const subject = inferSubject(claimText, undefined);
85
+ return catalog
86
+ .map(({ schema, origin }) => ({
87
+ schema,
88
+ origin,
89
+ score: scoreSchema(schema, claimText),
90
+ }))
91
+ .filter(({ score }) => score >= minimumScore)
92
+ .sort((left, right) => right.score - left.score ||
93
+ (left.origin === right.origin
94
+ ? 0
95
+ : left.origin === "project_local"
96
+ ? -1
97
+ : 1) ||
98
+ left.schema.predicate_name.localeCompare(right.schema.predicate_name) ||
99
+ left.schema.id.localeCompare(right.schema.id))
100
+ .slice(0, limit)
101
+ .map(({ schema, origin, score }) => {
102
+ const suggestion = buildSuggestion(schema, claimText, subject, score);
103
+ return {
104
+ schemaId: schema.id,
105
+ origin,
106
+ predicateName: schema.predicate_name,
107
+ argumentNames: [...schema.argument_names],
108
+ argumentTypes: [...schema.argument_types],
109
+ score,
110
+ bindingStatus: suggestion.binding_status,
111
+ unboundArguments: [...suggestion.unbound_arguments],
112
+ polarity: suggestion.polarity,
113
+ canonicalKey: suggestion.canonical_key,
114
+ writeEligible: false,
115
+ };
116
+ });
117
+ }
118
+ function propositionDisposition(proposition, suggestion, candidates) {
119
+ if (proposition.status === "nonlogical") {
120
+ return { recommendedLane: "nonlogical", disposition: "nonlogical" };
121
+ }
122
+ if (suggestion?.kind === "strict_property") {
123
+ return {
124
+ recommendedLane: "strict_property",
125
+ disposition: "strict_property_candidate",
126
+ };
127
+ }
128
+ if (suggestion?.kind === "rule") {
129
+ return { recommendedLane: "rule", disposition: "rule_candidate" };
130
+ }
131
+ if (suggestion?.kind === "predicate" || candidates.length > 0) {
132
+ return {
133
+ recommendedLane: "predicate",
134
+ disposition: "predicate_candidate",
135
+ };
136
+ }
137
+ if (proposition.status === "ambiguous" ||
138
+ suggestion?.kind === "ambiguity_observation") {
139
+ return {
140
+ recommendedLane: "unresolved",
141
+ disposition: "unresolved_ambiguity",
142
+ };
143
+ }
144
+ return {
145
+ recommendedLane: "unresolved",
146
+ disposition: "unresolved_ontology_gap",
147
+ };
148
+ }
149
+ function claimDelta(existing, expected) {
150
+ const existingSet = new Set(existing);
151
+ const expectedSet = new Set(expected);
152
+ return {
153
+ preserved: expected.filter((claim) => existingSet.has(claim)).sort(),
154
+ added: expected.filter((claim) => !existingSet.has(claim)).sort(),
155
+ stale: existing.filter((claim) => !expectedSet.has(claim)).sort(),
156
+ };
157
+ }
158
+ async function buildBatch(repairBatch, requirement, readSource, catalog, predicateLimit, predicateMinScore) {
159
+ const requirementId = repairBatch.requirementId;
160
+ const sourceFile = typeof requirement?.source === "string" ? requirement.source : null;
161
+ const sourceText = requirement ? await readSource(requirement) : null;
162
+ const existingTextRef = typeof requirement?.text_ref === "string" && requirement.text_ref.trim()
163
+ ? requirement.text_ref.trim()
164
+ : null;
165
+ const existingSemanticText = typeof requirement?.semantic_text === "string" &&
166
+ requirement.semantic_text.trim()
167
+ ? requirement.semantic_text.trim()
168
+ : null;
169
+ const sourceHash = sourceText ? semanticSourceHash(sourceText) : null;
170
+ const sourceMissing = requirement === undefined || !sourceText;
171
+ const sourceConflict = !sourceMissing &&
172
+ existingSemanticText !== null &&
173
+ existingSemanticText !== sourceText;
174
+ const sourceStatus = sourceMissing
175
+ ? "missing"
176
+ : sourceConflict
177
+ ? "conflict"
178
+ : "compatible";
179
+ const diagnostics = [];
180
+ if (requirement === undefined) {
181
+ diagnostics.push(`Requirement ${requirementId} is present in the repair plan but absent from exact KB query results.`);
182
+ }
183
+ else if (!sourceText) {
184
+ diagnostics.push(`Requirement ${requirementId} has no readable authored Markdown body inside the workspace.`);
185
+ }
186
+ else if (sourceConflict) {
187
+ diagnostics.push(`Requirement ${requirementId} has semantic_text that differs from its normalized authored Markdown body; review the source drift before applying this migration.`);
188
+ }
189
+ if (!requirement || !sourceText || !sourceHash) {
190
+ return {
191
+ id: `legacy-migration-${requirementId}`,
192
+ requirementId,
193
+ repairBatchId: repairBatch.id,
194
+ dependsOn: [...repairBatch.dependsOn],
195
+ state: "blocked",
196
+ autoApplicable: false,
197
+ sourceBinding: {
198
+ status: sourceStatus,
199
+ sourceFile,
200
+ sourceKind: "authored_markdown_body",
201
+ sourceHash,
202
+ sourceByteLength: sourceText
203
+ ? Buffer.byteLength(sourceText, "utf8")
204
+ : 0,
205
+ persistedField: null,
206
+ existingTextRef,
207
+ existingSemanticText,
208
+ reason: diagnostics[0] ?? "Authored requirement source is unavailable.",
209
+ },
210
+ sourceText,
211
+ claimDelta: { preserved: [], added: [], stale: [] },
212
+ propositions: [],
213
+ requirementPropertyPatchPreview: null,
214
+ diagnostics,
215
+ };
216
+ }
217
+ const existingLogicClaims = stringList(requirement.logic_claims);
218
+ const analysis = analyzeSemanticAdvisorInput({
219
+ payload: {
220
+ type: "req",
221
+ id: requirementId,
222
+ properties: {
223
+ title: requirement.title,
224
+ status: requirement.status,
225
+ source: sourceFile ?? undefined,
226
+ semantic_text: sourceText,
227
+ logic_claims: existingLogicClaims,
228
+ },
229
+ relationships: [],
230
+ },
231
+ });
232
+ const suggestions = new Map(analysis.receipt.suggestions.map((suggestion) => [
233
+ suggestion.claim_key,
234
+ suggestion,
235
+ ]));
236
+ const propositions = analysis.receipt.propositions.map((proposition) => {
237
+ const predicateCandidates = proposition.status === "nonlogical"
238
+ ? []
239
+ : rankPredicateCandidates(proposition.claim_text, catalog, predicateLimit, predicateMinScore);
240
+ const disposition = propositionDisposition(proposition, suggestions.get(proposition.claim_key), predicateCandidates);
241
+ return {
242
+ claimKey: proposition.claim_key,
243
+ claimText: proposition.claim_text,
244
+ role: proposition.role,
245
+ inventoryStatus: proposition.status,
246
+ span: { ...proposition.span },
247
+ ...disposition,
248
+ predicateCandidates,
249
+ reviewRequired: true,
250
+ };
251
+ });
252
+ const expectedClaimKeys = [
253
+ ...analysis.receipt.logic_coverage.expected_claim_keys,
254
+ ];
255
+ const propertyPatch = sourceConflict
256
+ ? null
257
+ : {
258
+ semantic_text: sourceText,
259
+ logic_claims: expectedClaimKeys,
260
+ semantic_clauses: analysis.receipt.clauses.map((clause) => clause.text),
261
+ semantic_inventory_version: analysis.receipt.inventory_contract.version,
262
+ semantic_source_field: analysis.receipt.inventory_contract.source_field,
263
+ semantic_source_hash: analysis.receipt.inventory_contract.source_hash,
264
+ semantic_inventory: analysis.receipt.propositions.map((proposition) => ({
265
+ claim_key: proposition.claim_key,
266
+ claim_text: proposition.claim_text,
267
+ role: proposition.role,
268
+ status: proposition.status,
269
+ span: { ...proposition.span },
270
+ ...(proposition.reason ? { reason: proposition.reason } : {}),
271
+ })),
272
+ };
273
+ return {
274
+ id: `legacy-migration-${requirementId}`,
275
+ requirementId,
276
+ repairBatchId: repairBatch.id,
277
+ dependsOn: [...repairBatch.dependsOn],
278
+ state: sourceConflict ? "blocked" : "ready_for_review",
279
+ autoApplicable: false,
280
+ sourceBinding: {
281
+ status: sourceStatus,
282
+ sourceFile,
283
+ sourceKind: "authored_markdown_body",
284
+ sourceHash,
285
+ sourceByteLength: Buffer.byteLength(sourceText, "utf8"),
286
+ persistedField: sourceConflict ? null : "semantic_text",
287
+ existingTextRef,
288
+ existingSemanticText,
289
+ reason: sourceConflict
290
+ ? (diagnostics[0] ?? "Existing semantic_text has drifted from source.")
291
+ : existingTextRef
292
+ ? "Authored Markdown can be reviewed in semantic_text while preserving the independent text_ref evidence."
293
+ : "Authored Markdown can be reviewed in the dedicated semantic_text field.",
294
+ },
295
+ sourceText,
296
+ claimDelta: claimDelta(existingLogicClaims, expectedClaimKeys),
297
+ propositions,
298
+ requirementPropertyPatchPreview: propertyPatch,
299
+ diagnostics: [...diagnostics, ...analysis.warnings],
300
+ };
301
+ }
302
+ // implements REQ-kibi-legacy-migration-preview-v2
303
+ export async function buildLegacyMigrationPlan(repairPlan, input, codeSnapshot, dependencies) {
304
+ const offset = clampInteger(input.migrationOffset, 0, 0, Number.MAX_SAFE_INTEGER);
305
+ const limit = clampInteger(input.migrationLimit, 1, 1, 10);
306
+ const predicateLimit = clampInteger(input.migrationPredicateLimit, 5, 1, 20);
307
+ const predicateMinScore = clampScore(input.migrationPredicateMinScore);
308
+ const candidateBatches = migrationRepairBatches(repairPlan);
309
+ const selected = candidateBatches.slice(offset, offset + limit);
310
+ const requirementById = new Map(dependencies.requirements.flatMap((requirement) => typeof requirement.id === "string"
311
+ ? [[requirement.id, requirement]]
312
+ : []));
313
+ const catalog = predicateCatalog(dependencies.projectPredicateSchemas);
314
+ const predicateCatalogHash = hash(catalog.map(({ schema, origin }) => ({ origin, schema })));
315
+ const batches = [];
316
+ for (const repairBatch of selected) {
317
+ batches.push(await buildBatch(repairBatch, requirementById.get(repairBatch.requirementId), dependencies.readSource, catalog, predicateLimit, predicateMinScore));
318
+ }
319
+ const readyBatchCount = batches.filter((batch) => batch.state === "ready_for_review").length;
320
+ const blockedBatchCount = batches.length - readyBatchCount;
321
+ const propositionCount = batches.reduce((count, batch) => count + batch.propositions.length, 0);
322
+ const assertivePropositionCount = batches.reduce((count, batch) => count +
323
+ batch.propositions.filter((proposition) => proposition.disposition !== "nonlogical").length, 0);
324
+ const unresolvedPropositionCount = batches.reduce((count, batch) => count +
325
+ batch.propositions.filter((proposition) => proposition.disposition.startsWith("unresolved_")).length, 0);
326
+ const predicateCandidateCount = batches.reduce((count, batch) => count +
327
+ batch.propositions.reduce((subtotal, proposition) => subtotal + proposition.predicateCandidates.length, 0), 0);
328
+ const nextOffset = offset + selected.length < candidateBatches.length
329
+ ? offset + selected.length
330
+ : null;
331
+ const diagnostics = [...(dependencies.diagnostics ?? [])];
332
+ if (!repairPlan.scope.complete) {
333
+ diagnostics.push("Legacy migration scope is partial because requirement coverage omitted actionable requirements; rerun complete coverage before treating this as a project inventory.");
334
+ }
335
+ if (candidateBatches.length > 0 && selected.length === 0) {
336
+ diagnostics.push(`Migration offset ${offset} is beyond ${candidateBatches.length} ready semantic-inventory requirement batch(es).`);
337
+ }
338
+ const planCore = {
339
+ version: LEGACY_MIGRATION_PLAN_VERSION,
340
+ codeSnapshot,
341
+ repairPlanId: repairPlan.planId,
342
+ predicateCatalogHash,
343
+ scope: {
344
+ repairPlanComplete: repairPlan.scope.complete,
345
+ candidateRequirements: candidateBatches.length,
346
+ selectedRequirements: selected.length,
347
+ offset,
348
+ limit,
349
+ selectionComplete: offset === 0 && selected.length === candidateBatches.length,
350
+ nextOffset,
351
+ },
352
+ batches,
353
+ };
354
+ const planId = `legacy-migration-plan-${hash(planCore).slice(0, 24)}`;
355
+ const status = !repairPlan.scope.complete
356
+ ? "partial"
357
+ : candidateBatches.length === 0
358
+ ? "no_candidates"
359
+ : readyBatchCount === 0
360
+ ? "blocked"
361
+ : "ready";
362
+ return {
363
+ ...planCore,
364
+ planId,
365
+ readOnly: true,
366
+ status,
367
+ applicationPolicy: {
368
+ previewOnly: true,
369
+ reviewEveryProposition: true,
370
+ preserveExistingTextRefs: true,
371
+ exactBindingsBeforeWrite: true,
372
+ validateBeforeEachWrite: true,
373
+ sequentialUpsertsOnly: true,
374
+ recheckContradictionsAfterEachBatch: true,
375
+ },
376
+ summary: {
377
+ batchCount: batches.length,
378
+ readyBatchCount,
379
+ blockedBatchCount,
380
+ propositionCount,
381
+ assertivePropositionCount,
382
+ unresolvedPropositionCount,
383
+ predicateCandidateCount,
384
+ },
385
+ diagnostics,
386
+ };
387
+ }
388
+ // implements REQ-kibi-legacy-migration-preview-v2
389
+ export async function buildLegacyMigrationPlanFromContext(repairPlan, input, codeSnapshot, context) {
390
+ if (!context.prolog) {
391
+ throw new Error("Legacy migration planning requires a Prolog context");
392
+ }
393
+ const requirements = await loadEntities(context.prolog, { type: "req" });
394
+ const schemaDiagnostics = [];
395
+ const projectPredicateSchemas = await loadExistingPredicateSchemas(context.prolog, true, schemaDiagnostics);
396
+ return buildLegacyMigrationPlan(repairPlan, input, codeSnapshot, {
397
+ requirements,
398
+ projectPredicateSchemas,
399
+ diagnostics: schemaDiagnostics,
400
+ readSource: async (requirement) => {
401
+ const source = typeof requirement.source === "string" ? requirement.source : "";
402
+ const body = await loadMarkdownBody(source, context.workspaceRoot);
403
+ if (body === null)
404
+ return null;
405
+ const semanticText = requirementSemanticText(body);
406
+ return semanticText || null;
407
+ },
408
+ });
409
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"node-ports.d.ts","sourceRoot":"","sources":["../../../src/public/operations/node-ports.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE/E,KAAK,kBAAkB,GAAG,cAAc,GAAG;IACzC,QAAQ,CAAC,IAAI,EAAE,CACb,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,OAAO,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,KACjE,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;CACjC,CAAC;AAEF,KAAK,WAAW,GAAG,OAAO,GAAG;IAC3B,QAAQ,CAAC,YAAY,EAAE,CACrB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,SAAS,MAAM,EAAE,KACrB,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;CACjC,CAAC;AAiBF,eAAO,MAAM,cAAc,EAAE,kBAkB5B,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,WAgBrB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,WAEzB,CAAC"}
1
+ {"version":3,"file":"node-ports.d.ts","sourceRoot":"","sources":["../../../src/public/operations/node-ports.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE/E,KAAK,kBAAkB,GAAG,cAAc,GAAG;IACzC,QAAQ,CAAC,IAAI,EAAE,CACb,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,OAAO,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,KACjE,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;CACjC,CAAC;AAEF,KAAK,WAAW,GAAG,OAAO,GAAG;IAC3B,QAAQ,CAAC,YAAY,EAAE,CACrB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,SAAS,MAAM,EAAE,KACrB,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;CACjC,CAAC;AA2HF,eAAO,MAAM,cAAc,EAAE,kBAkB5B,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,WAiBrB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,WAEzB,CAAC"}
@@ -1,9 +1,12 @@
1
1
  import { execFile } from "node:child_process";
2
+ import { createHash } from "node:crypto";
2
3
  import * as fs from "node:fs/promises";
4
+ import path from "node:path";
3
5
  import { promisify } from "node:util";
4
6
  import fg from "fast-glob";
5
7
  import { createRepoIgnorePolicy } from "../ignore-policy.js";
6
8
  const execFileAsync = promisify(execFile);
9
+ const SNAPSHOT_EXCLUDED_PREFIXES = [".changeset/", ".kb/", "docs/"];
7
10
  const ALWAYS_IGNORED_GLOBS = [
8
11
  "**/.git/**",
9
12
  "**/.kb/**",
@@ -17,6 +20,92 @@ const ALWAYS_IGNORED_GLOBS = [
17
20
  "**/coverage/**",
18
21
  "**/target/**",
19
22
  ];
23
+ function includedSnapshotPath(relativePath) {
24
+ return !SNAPSHOT_EXCLUDED_PREFIXES.some((prefix) => relativePath === prefix.slice(0, -1) || relativePath.startsWith(prefix));
25
+ }
26
+ function withoutVerificationReceiptFrontmatter(content) {
27
+ const lines = content.match(/[^\n]*\n|[^\n]+$/g) ?? [];
28
+ if (lines[0]?.trim() !== "---")
29
+ return content;
30
+ let inFrontmatter = true;
31
+ let skippingReceipts = false;
32
+ const retained = [];
33
+ for (const [index, line] of lines.entries()) {
34
+ const trimmed = line.trim();
35
+ if (index > 0 && inFrontmatter && trimmed === "---") {
36
+ inFrontmatter = false;
37
+ skippingReceipts = false;
38
+ retained.push(line);
39
+ continue;
40
+ }
41
+ if (inFrontmatter && /^verification_receipts\s*:/.test(line)) {
42
+ skippingReceipts = true;
43
+ continue;
44
+ }
45
+ if (inFrontmatter &&
46
+ skippingReceipts &&
47
+ /^[A-Za-z_][A-Za-z0-9_-]*\s*:/.test(line)) {
48
+ skippingReceipts = false;
49
+ }
50
+ if (!skippingReceipts)
51
+ retained.push(line);
52
+ }
53
+ return retained.join("");
54
+ }
55
+ function snapshotFileContent(relativePath, content) {
56
+ if (relativePath.startsWith("documentation/") &&
57
+ relativePath.endsWith(".md")) {
58
+ return Buffer.from(withoutVerificationReceiptFrontmatter(content.toString("utf8")));
59
+ }
60
+ return content;
61
+ }
62
+ async function workspaceSnapshot(workspaceRoot) {
63
+ const { stdout: listed } = await execFileAsync("git", [
64
+ "-C",
65
+ workspaceRoot,
66
+ "ls-files",
67
+ "--cached",
68
+ "--others",
69
+ "--exclude-standard",
70
+ "-z",
71
+ ], { encoding: "buffer", maxBuffer: 64 * 1024 * 1024 });
72
+ const paths = listed
73
+ .toString("utf8")
74
+ .split("\0")
75
+ .filter(Boolean)
76
+ .filter(includedSnapshotPath)
77
+ .sort();
78
+ const digest = createHash("sha256");
79
+ digest.update("kibi.workspace-snapshot.v1\0");
80
+ for (const relativePath of paths) {
81
+ digest.update(relativePath);
82
+ digest.update("\0");
83
+ try {
84
+ const content = await fs.readFile(path.join(workspaceRoot, relativePath));
85
+ digest.update(snapshotFileContent(relativePath, content));
86
+ }
87
+ catch (error) {
88
+ const code = typeof error === "object" && error !== null && "code" in error
89
+ ? String(error.code)
90
+ : "unreadable";
91
+ digest.update(`<${code}>`);
92
+ }
93
+ digest.update("\0");
94
+ }
95
+ const { stdout: status } = await execFileAsync("git", [
96
+ "-C",
97
+ workspaceRoot,
98
+ "status",
99
+ "--porcelain=v1",
100
+ "--untracked-files=normal",
101
+ ], { maxBuffer: 16 * 1024 * 1024 });
102
+ return {
103
+ version: "kibi.workspace-snapshot.v1",
104
+ hash: digest.digest("hex"),
105
+ dirty: status.trim().length > 0,
106
+ fileCount: paths.length,
107
+ };
108
+ }
20
109
  export const nodeFilesystem = {
21
110
  readFile: (filePath) => fs.readFile(filePath, "utf8"),
22
111
  writeFile: async (filePath, data) => {
@@ -47,6 +136,7 @@ export const nodeGit = {
47
136
  ]);
48
137
  return stdout.trim();
49
138
  },
139
+ workspaceSnapshot,
50
140
  ignoredPaths: async (workspaceRoot, paths) => {
51
141
  const policy = createRepoIgnorePolicy(workspaceRoot);
52
142
  return paths.filter((candidate) => policy.isIgnored(candidate));