kibi-cli 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-protocol.d.ts.map +1 -1
- package/dist/cli-protocol.js +3 -2
- package/dist/commands/aggregated-checks.d.ts +7 -0
- package/dist/commands/aggregated-checks.d.ts.map +1 -1
- package/dist/commands/aggregated-checks.js +25 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +21 -13
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +105 -24
- package/dist/commands/github-init.d.ts +1 -1
- package/dist/commands/github-init.d.ts.map +1 -1
- package/dist/commands/github-init.js +1 -1
- package/dist/commands/init-helpers.d.ts +17 -2
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +123 -23
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +110 -15
- package/dist/commands/prove.d.ts.map +1 -1
- package/dist/commands/prove.js +10 -18
- package/dist/commands/sync/cache.d.ts +20 -1
- package/dist/commands/sync/cache.d.ts.map +1 -1
- package/dist/commands/sync/cache.js +51 -2
- package/dist/commands/sync/discovery.d.ts.map +1 -1
- package/dist/commands/sync/discovery.js +1 -1
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +8 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +11 -3
- package/dist/engine.d.ts +26 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +126 -29
- package/dist/extractors/manifest.d.ts.map +1 -1
- package/dist/extractors/manifest.js +66 -28
- package/dist/extractors/markdown.d.ts +2 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +14 -3
- package/dist/extractors/relationships.d.ts.map +1 -1
- package/dist/extractors/relationships.js +1 -0
- package/dist/intent-search.d.ts.map +1 -1
- package/dist/intent-search.js +68 -29
- package/dist/operations/bootstrap/generate.d.ts.map +1 -1
- package/dist/operations/bootstrap/generate.js +4 -3
- package/dist/operations/modeling/model-requirement.d.ts +1 -1
- package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
- package/dist/operations/modeling/model-requirement.js +176 -10
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +14 -2
- package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-loader.js +24 -0
- package/dist/operations/modeling/predicate-types.d.ts +4 -0
- package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-vocabulary.d.ts +54 -0
- package/dist/operations/modeling/predicate-vocabulary.d.ts.map +1 -0
- package/dist/operations/modeling/predicate-vocabulary.js +169 -0
- package/dist/operations/modeling/requirement-types.d.ts +5 -0
- package/dist/operations/modeling/requirement-types.d.ts.map +1 -1
- package/dist/operations/modeling/vocabulary-alignment.d.ts +60 -0
- package/dist/operations/modeling/vocabulary-alignment.d.ts.map +1 -0
- package/dist/operations/modeling/vocabulary-alignment.js +178 -0
- package/dist/operations/mutation/contradictions.d.ts +3 -0
- package/dist/operations/mutation/contradictions.d.ts.map +1 -1
- package/dist/operations/mutation/contradictions.js +29 -0
- package/dist/operations/mutation/delete.d.ts.map +1 -1
- package/dist/operations/mutation/delete.js +33 -1
- package/dist/operations/mutation/predicate-vocabulary-guard.d.ts +8 -0
- package/dist/operations/mutation/predicate-vocabulary-guard.d.ts.map +1 -0
- package/dist/operations/mutation/predicate-vocabulary-guard.js +64 -0
- package/dist/operations/mutation/relationships.d.ts +1 -1
- package/dist/operations/mutation/relationships.d.ts.map +1 -1
- package/dist/operations/mutation/relationships.js +1 -0
- package/dist/operations/mutation/saga.d.ts +5 -0
- package/dist/operations/mutation/saga.d.ts.map +1 -1
- package/dist/operations/mutation/saga.js +10 -0
- package/dist/operations/mutation/serialization.d.ts.map +1 -1
- package/dist/operations/mutation/serialization.js +2 -0
- package/dist/operations/mutation/source-authoring.d.ts +6 -0
- package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
- package/dist/operations/mutation/source-authoring.js +65 -26
- package/dist/operations/mutation/strict-fact.d.ts.map +1 -1
- package/dist/operations/mutation/strict-fact.js +5 -0
- package/dist/operations/mutation/types.d.ts +17 -0
- package/dist/operations/mutation/types.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.d.ts +6 -0
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +72 -4
- package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
- package/dist/operations/mutation/validate-upsert.js +24 -1
- package/dist/operations/mutation/validation.d.ts.map +1 -1
- package/dist/operations/mutation/validation.js +16 -3
- package/dist/operations/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +61 -17
- package/dist/operations/planning/compile-intent.d.ts.map +1 -1
- package/dist/operations/planning/compile-intent.js +3 -1
- package/dist/operations/proof/code-scope.d.ts +17 -0
- package/dist/operations/proof/code-scope.d.ts.map +1 -0
- package/dist/operations/proof/code-scope.js +60 -0
- package/dist/operations/proof/ingest-proof.d.ts +4 -2
- package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
- package/dist/operations/proof/ingest-proof.js +207 -74
- package/dist/operations/proof/migrate-legacy-receipts.d.ts.map +1 -1
- package/dist/operations/proof/migrate-legacy-receipts.js +7 -5
- package/dist/operations/proof/prune-receipts.d.ts.map +1 -1
- package/dist/operations/proof/prune-receipts.js +7 -5
- package/dist/plugins/compose-semantic-classifier.d.ts +6 -1
- package/dist/plugins/compose-semantic-classifier.d.ts.map +1 -1
- package/dist/plugins/compose-semantic-classifier.js +8 -3
- package/dist/plugins/compose-vocabulary-alignment.d.ts +23 -0
- package/dist/plugins/compose-vocabulary-alignment.d.ts.map +1 -0
- package/dist/plugins/compose-vocabulary-alignment.js +141 -0
- package/dist/plugins/external-allowlist.d.ts +7 -0
- package/dist/plugins/external-allowlist.d.ts.map +1 -1
- package/dist/plugins/external-allowlist.js +13 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/registry.d.ts +2 -1
- package/dist/plugins/registry.d.ts.map +1 -1
- package/dist/plugins/registry.js +22 -1
- package/dist/prolog/codec.d.ts.map +1 -1
- package/dist/prolog/codec.js +2 -0
- package/dist/prolog.d.ts +36 -0
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +78 -9
- package/dist/public/diagnostic-usage.d.ts.map +1 -1
- package/dist/public/diagnostic-usage.js +7 -25
- package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
- package/dist/public/impact/full-kb-quality.js +4 -12
- package/dist/public/operations/catalog.d.ts +36 -7
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +10 -2
- package/dist/public/operations/check-helpers.d.ts +6 -0
- package/dist/public/operations/check-helpers.d.ts.map +1 -1
- package/dist/public/operations/check-helpers.js +21 -1
- package/dist/public/operations/contracts.d.ts.map +1 -1
- package/dist/public/operations/contracts.js +16 -0
- package/dist/public/operations/discovery-entities.d.ts +42 -2
- package/dist/public/operations/discovery-entities.d.ts.map +1 -1
- package/dist/public/operations/discovery-entities.js +195 -22
- package/dist/public/operations/discovery-executors.d.ts +1 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +75 -46
- package/dist/public/operations/migration-plan.d.ts +2 -0
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +50 -0
- package/dist/public/operations/predicate-schema-conformance.d.ts +41 -0
- package/dist/public/operations/predicate-schema-conformance.d.ts.map +1 -0
- package/dist/public/operations/predicate-schema-conformance.js +242 -0
- package/dist/public/operations/prolog-json.d.ts.map +1 -1
- package/dist/public/operations/prolog-json.js +9 -3
- package/dist/public/operations/result-envelope.d.ts +34 -1
- package/dist/public/operations/result-envelope.d.ts.map +1 -1
- package/dist/public/operations/result-envelope.js +78 -2
- package/dist/public/operations/runtime-types.d.ts +1 -1
- package/dist/public/operations/runtime-types.d.ts.map +1 -1
- package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
- package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
- package/dist/public/operations/specs/check-rules.generated.js +8 -1
- package/dist/public/operations/specs/check.d.ts +1 -1
- package/dist/public/operations/specs/discovery.d.ts +7 -1
- package/dist/public/operations/specs/discovery.d.ts.map +1 -1
- package/dist/public/operations/specs/discovery.js +7 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts +27 -4
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +21 -3
- package/dist/public/operations/specs/reporting.d.ts +8 -0
- package/dist/public/operations/specs/reporting.d.ts.map +1 -1
- package/dist/public/operations/specs/reporting.js +46 -15
- package/dist/public/operations/specs/upsert.d.ts +28 -5
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/specs/upsert.js +1 -1
- package/dist/public/operations/symbol-repair-plan.d.ts.map +1 -1
- package/dist/public/operations/symbol-repair-plan.js +8 -3
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +22 -0
- package/dist/public/schemas/relationship.d.ts.map +1 -1
- package/dist/public/schemas/relationship.js +1 -0
- package/dist/public/skills/kibi-usage/SKILL.md +7 -3
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +4 -0
- package/dist/public/skills/kibi-usage/resources/relationship-directions.md +35 -17
- package/dist/public/skills/kibi-usage/resources/source-authoring.md +36 -0
- package/dist/public/skills/kibi-usage/resources/workflows.md +52 -1
- package/dist/public/telemetry-acceptance.d.ts.map +1 -1
- package/dist/public/telemetry-acceptance.js +21 -5
- package/dist/relationships/shards.d.ts +6 -0
- package/dist/relationships/shards.d.ts.map +1 -1
- package/dist/relationships/shards.js +26 -19
- package/dist/schemas/entity.schema.json +32 -0
- package/dist/traceability/staged-diagnostics.d.ts +1 -1
- package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
- package/dist/traceability/staged-entity-id-style.d.ts +12 -0
- package/dist/traceability/staged-entity-id-style.d.ts.map +1 -0
- package/dist/traceability/staged-entity-id-style.js +68 -0
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +8 -0
- package/dist/traceability/validate.js +1 -1
- package/dist/types/entities.d.ts +2 -0
- package/dist/types/entities.d.ts.map +1 -1
- package/dist/types/relationships.d.ts +1 -1
- package/dist/types/relationships.d.ts.map +1 -1
- package/dist/utils/entity-id-style.d.ts +27 -0
- package/dist/utils/entity-id-style.d.ts.map +1 -0
- package/dist/utils/entity-id-style.js +81 -0
- package/dist/utils/git-repository-context.d.ts +50 -0
- package/dist/utils/git-repository-context.d.ts.map +1 -0
- package/dist/utils/git-repository-context.js +259 -0
- package/dist/utils/rule-registry.d.ts +5 -0
- package/dist/utils/rule-registry.d.ts.map +1 -1
- package/dist/utils/rule-registry.generated.d.ts +37 -0
- package/dist/utils/rule-registry.generated.d.ts.map +1 -1
- package/dist/utils/rule-registry.generated.js +44 -0
- package/dist/utils/strict-modeling.d.ts +7 -0
- package/dist/utils/strict-modeling.d.ts.map +1 -1
- package/dist/utils/strict-modeling.js +11 -0
- package/package.json +4 -4
- package/schema/entities.pl +60 -1
- package/schema/relationships.pl +17 -4
- package/schema/validation.pl +118 -20
- package/src/public/diagnostic-usage.ts +16 -24
- package/src/public/impact/full-kb-quality.ts +4 -16
- package/src/public/operations/check-executor.ts +12 -1
- package/src/public/operations/check-helpers.ts +27 -1
- package/src/public/operations/contracts.ts +19 -0
- package/src/public/operations/discovery-entities.ts +292 -23
- package/src/public/operations/discovery-executors.ts +91 -55
- package/src/public/operations/migration-plan.ts +57 -0
- package/src/public/operations/predicate-schema-conformance.ts +362 -0
- package/src/public/operations/prolog-json.ts +9 -3
- package/src/public/operations/result-envelope.ts +114 -2
- package/src/public/operations/runtime-types.ts +1 -1
- package/src/public/operations/specs/check-rules.generated.ts +8 -1
- package/src/public/operations/specs/discovery.ts +8 -1
- package/src/public/operations/specs/mutation-schemas.ts +23 -3
- package/src/public/operations/specs/reporting.ts +69 -22
- package/src/public/operations/specs/upsert.ts +1 -1
- package/src/public/operations/symbol-repair-plan.ts +13 -3
- package/src/public/schemas/entity.ts +22 -0
- package/src/public/schemas/relationship.ts +1 -0
- package/src/public/skills/kibi-usage/SKILL.md +7 -3
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +4 -0
- package/src/public/skills/kibi-usage/resources/relationship-directions.md +35 -17
- package/src/public/skills/kibi-usage/resources/source-authoring.md +36 -0
- package/src/public/skills/kibi-usage/resources/workflows.md +52 -1
- package/src/public/telemetry-acceptance.ts +37 -6
- package/src/schemas/entity.schema.json +32 -0
- package/src/schemas/relationship.schema.json +1 -0
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
|
-
import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
|
|
18
|
+
import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
|
|
19
19
|
import * as path from "node:path";
|
|
20
20
|
import fg from "fast-glob";
|
|
21
21
|
import { getBranchDiagnostic, resolveActiveBranch, } from "../utils/branch-resolver.js";
|
|
@@ -236,41 +236,141 @@ const KIBI_HOOK_END = "# END kibi-managed";
|
|
|
236
236
|
function escapeRegex(s) {
|
|
237
237
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
238
238
|
}
|
|
239
|
+
function hookIntegrationRecipe(hook) {
|
|
240
|
+
// Recipes must reproduce the exact checks the Kibi template runs for that
|
|
241
|
+
// hook, with failure propagation, or the delegation is weaker than the
|
|
242
|
+
// template it replaces.
|
|
243
|
+
switch (hook) {
|
|
244
|
+
case "pre-commit":
|
|
245
|
+
return "delegate from that hook with 'kibi check-generated --staged --changed-only && kibi check --staged' (both commands must succeed; '&&' propagates the first failure)";
|
|
246
|
+
case "post-checkout":
|
|
247
|
+
return "delegate from that hook to 'kibi sync' on branch checkouts (the template skips file checkouts)";
|
|
248
|
+
case "post-merge":
|
|
249
|
+
return "delegate from that hook to 'kibi sync'";
|
|
250
|
+
case "post-rewrite":
|
|
251
|
+
return "delegate from that hook to 'kibi sync' after rebase/amend rewrites";
|
|
252
|
+
default:
|
|
253
|
+
return "delegate to the matching Kibi template command";
|
|
254
|
+
}
|
|
255
|
+
}
|
|
239
256
|
export function installHook(hookPath, content) {
|
|
240
257
|
// implements REQ-008
|
|
258
|
+
// implements REQ-git-hook-effective-install
|
|
241
259
|
const kibiSection = `${KIBI_HOOK_BEGIN}\n${content}\n${KIBI_HOOK_END}`;
|
|
242
|
-
|
|
260
|
+
let hookStats;
|
|
261
|
+
try {
|
|
262
|
+
hookStats = lstatSync(hookPath);
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
if (error.code === "ENOENT" ||
|
|
266
|
+
error.code === "ENOTDIR") {
|
|
267
|
+
// Missing hook: create it through the parent directory. Refuse when an
|
|
268
|
+
// ancestor is itself a symlink whose target leaves the resolved path
|
|
269
|
+
// (realpath is checked by the caller's hooks-dir guard).
|
|
270
|
+
writeFileSync(hookPath, `#!/bin/sh\n${kibiSection}\n`, { mode: 0o755 });
|
|
271
|
+
chmodSync(hookPath, 0o755);
|
|
272
|
+
return "installed";
|
|
273
|
+
}
|
|
274
|
+
console.error(`! Unable to inspect ${hookPath}: ${error.message}; leaving it untouched.`);
|
|
275
|
+
return "skipped-unsupported";
|
|
276
|
+
}
|
|
277
|
+
if (hookStats.isSymbolicLink()) {
|
|
278
|
+
// Never follow a symlinked hook: read/write/chmod would modify an
|
|
279
|
+
// arbitrary target outside our guard. Dangling symlinks are treated the
|
|
280
|
+
// same (the intended target must not be auto-created either).
|
|
281
|
+
return "skipped-symlink";
|
|
282
|
+
}
|
|
283
|
+
if (!hookStats.isFile()) {
|
|
284
|
+
return "skipped-unsupported";
|
|
285
|
+
}
|
|
286
|
+
try {
|
|
243
287
|
const existing = readFileSync(hookPath, "utf8");
|
|
244
288
|
if (existing.includes(KIBI_HOOK_BEGIN) &&
|
|
245
289
|
existing.includes(KIBI_HOOK_END)) {
|
|
246
290
|
// Replace only the kibi-managed section, preserving any user-authored content
|
|
247
291
|
const updated = existing.replace(new RegExp(`${escapeRegex(KIBI_HOOK_BEGIN)}[\\s\\S]*?${escapeRegex(KIBI_HOOK_END)}`), kibiSection);
|
|
248
292
|
writeFileSync(hookPath, updated, { mode: 0o755 });
|
|
293
|
+
chmodSync(hookPath, 0o755);
|
|
294
|
+
return "updated";
|
|
249
295
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
else {
|
|
254
|
-
const shebang = existing.startsWith("#!/") ? "" : "#!/bin/sh\n";
|
|
255
|
-
writeFileSync(hookPath, `${shebang}${existing.trimEnd()}\n${kibiSection}\n`, { mode: 0o755 });
|
|
296
|
+
if (existing.trim().length > 0) {
|
|
297
|
+
// A hook we did not write: never overwrite foreign enforcement.
|
|
298
|
+
return "skipped-foreign";
|
|
256
299
|
}
|
|
300
|
+
const shebang = existing.startsWith("#!/") ? "" : "#!/bin/sh\n";
|
|
301
|
+
writeFileSync(hookPath, `${shebang}${existing.trimEnd()}\n${kibiSection}\n`, { mode: 0o755 });
|
|
302
|
+
chmodSync(hookPath, 0o755);
|
|
303
|
+
return "installed";
|
|
257
304
|
}
|
|
258
|
-
|
|
259
|
-
|
|
305
|
+
catch (error) {
|
|
306
|
+
console.error(`! Unable to read ${hookPath}: ${error.message}; leaving it untouched.`);
|
|
307
|
+
return "skipped-unsupported";
|
|
260
308
|
}
|
|
261
|
-
// Explicitly ensure hook is executable
|
|
262
|
-
chmodSync(hookPath, 0o755);
|
|
263
309
|
}
|
|
264
|
-
|
|
265
|
-
|
|
310
|
+
/** Kibi-managed hooks in install order, with the template each one installs. */
|
|
311
|
+
const MANAGED_HOOK_TEMPLATES = [
|
|
312
|
+
["post-checkout", POST_CHECKOUT_HOOK],
|
|
313
|
+
["post-merge", POST_MERGE_HOOK],
|
|
314
|
+
["post-rewrite", POST_REWRITE_HOOK],
|
|
315
|
+
["pre-commit", PRE_COMMIT_HOOK],
|
|
316
|
+
];
|
|
317
|
+
function managedHookBody(template) {
|
|
318
|
+
return template.replace("#!/bin/sh\n", "");
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Installed kibi-managed hooks whose managed section differs from what this
|
|
322
|
+
* CLI installs, such as a pre-commit gate written before `check-generated`
|
|
323
|
+
* joined it. User-authored hooks without kibi markers are not reported.
|
|
324
|
+
*/
|
|
325
|
+
// implements REQ-cli-doctor
|
|
326
|
+
export function outdatedManagedHooks(hooksDir) {
|
|
327
|
+
const managed = new RegExp(`${escapeRegex(KIBI_HOOK_BEGIN)}\\n([\\s\\S]*?)\\n${escapeRegex(KIBI_HOOK_END)}`);
|
|
328
|
+
return MANAGED_HOOK_TEMPLATES.filter(([hook, template]) => {
|
|
329
|
+
const hookPath = path.join(hooksDir, hook);
|
|
330
|
+
if (!existsSync(hookPath))
|
|
331
|
+
return false;
|
|
332
|
+
const section = managed.exec(readFileSync(hookPath, "utf8"));
|
|
333
|
+
return section !== null && section[1] !== managedHookBody(template);
|
|
334
|
+
}).map(([hook]) => hook);
|
|
335
|
+
}
|
|
336
|
+
/** Whether any hook in the directory carries a kibi-managed section. */
|
|
337
|
+
// implements REQ-cli-doctor
|
|
338
|
+
export function hasManagedHooks(hooksDir) {
|
|
339
|
+
return MANAGED_HOOK_TEMPLATES.some(([hook]) => {
|
|
340
|
+
const hookPath = path.join(hooksDir, hook);
|
|
341
|
+
return (existsSync(hookPath) &&
|
|
342
|
+
readFileSync(hookPath, "utf8").includes(KIBI_HOOK_BEGIN));
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
export function installGitHooks(hooksDir, options = {}) {
|
|
346
|
+
// implements REQ-git-hook-effective-install
|
|
266
347
|
mkdirSync(hooksDir, { recursive: true });
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
348
|
+
const results = MANAGED_HOOK_TEMPLATES.map(([hook, template]) => ({
|
|
349
|
+
hook,
|
|
350
|
+
result: installHook(path.join(hooksDir, hook), managedHookBody(template)),
|
|
351
|
+
}));
|
|
352
|
+
for (const { hook, result } of results) {
|
|
353
|
+
if (result === "skipped-foreign") {
|
|
354
|
+
console.log(`! ${hook}: existing non-Kibi hook left untouched; Kibi enforcement is NOT installed for this hook. To integrate: ${hookIntegrationRecipe(hook)}.`);
|
|
355
|
+
}
|
|
356
|
+
else if (result === "skipped-symlink") {
|
|
357
|
+
console.log(`! ${hook}: hook is a symlink; Kibi never edits symlink targets. Manage the target manually (${hookIntegrationRecipe(hook)}).`);
|
|
358
|
+
}
|
|
359
|
+
else if (result === "skipped-unsupported") {
|
|
360
|
+
console.log(`! ${hook}: hook path is not a regular file; left untouched.`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
const installedOrUpdated = results.filter((entry) => entry.result === "installed" || entry.result === "updated");
|
|
364
|
+
if (installedOrUpdated.length > 0) {
|
|
365
|
+
console.log(`✓ Installed/updated Kibi git hooks at ${hooksDir} (${installedOrUpdated.map((entry) => entry.hook).join(", ")})`);
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
console.log(`! No Kibi git hooks installed at ${hooksDir} (all hooks were skipped).`);
|
|
369
|
+
}
|
|
370
|
+
if (options.hooksPathOrigin) {
|
|
371
|
+
// Configuration/location reporting stays neutral about what happened:
|
|
372
|
+
// the per-hook lines and the aggregate above carry the install verdict.
|
|
373
|
+
console.log(`! core.hooksPath is configured (${options.hooksPathOrigin}); the effective hooks directory for THIS checkout is ${hooksDir}. Git resolves a relative hooks path separately under every worktree, so coverage of other worktrees is INCOMPLETE/UNVERIFIED: commit a versioned launcher that delegates to kibi, or run 'kibi init' in each checkout. Kibi will not change core.hooksPath.`);
|
|
374
|
+
}
|
|
375
|
+
return results;
|
|
276
376
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAmGA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAoDD,wBAAsB,WAAW,CAC/B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAwI/B"}
|
package/dist/commands/init.js
CHANGED
|
@@ -15,17 +15,74 @@
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
|
-
import { existsSync } from "node:fs";
|
|
18
|
+
import { existsSync, lstatSync, realpathSync } from "node:fs";
|
|
19
19
|
import * as path from "node:path";
|
|
20
20
|
import { fileURLToPath } from "node:url";
|
|
21
21
|
import { classifyActivation } from "../operations/bootstrap/activation.js";
|
|
22
22
|
import { nodeFilesystem } from "../public/operations/node-ports.js";
|
|
23
23
|
import { resolveBranchAttachment } from "../utils/branch-resolver.js";
|
|
24
|
+
import { resolveGitRepository, } from "../utils/git-repository-context.js";
|
|
24
25
|
import { scaffoldGitHubIntegration } from "./github-init.js";
|
|
25
26
|
import { copySchemaFiles, createKbDirectoryStructure, createManifestFile, ensureSymbolsManifestFile, installGitHooks, updateGitIgnore, } from "./init-helpers.js";
|
|
26
27
|
const __filename = fileURLToPath(import.meta.url);
|
|
27
28
|
const __dirname = path.dirname(__filename);
|
|
28
|
-
|
|
29
|
+
/**
|
|
30
|
+
* A hooks directory may be auto-managed only when Git resolves it inside this
|
|
31
|
+
* repository: under the common Git directory (the default hooks location) or
|
|
32
|
+
* under the current worktree root (repository-local relative core.hooksPath).
|
|
33
|
+
* Anything else — global configs, other repositories, external directories —
|
|
34
|
+
* must never receive auto-installed hooks.
|
|
35
|
+
* implements REQ-git-hook-effective-install
|
|
36
|
+
*/
|
|
37
|
+
function isRepositoryManagedHooksDir(context) {
|
|
38
|
+
const realpathAllowMissingTail = (candidate) => {
|
|
39
|
+
let current = path.resolve(candidate);
|
|
40
|
+
const missingSegments = [];
|
|
41
|
+
while (true) {
|
|
42
|
+
try {
|
|
43
|
+
return path.resolve(realpathSync.native(current), ...missingSegments);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const code = error.code;
|
|
47
|
+
if (code !== "ENOENT" && code !== "ENOTDIR")
|
|
48
|
+
return null;
|
|
49
|
+
// A dangling symlink cannot be canonicalized. Do not treat it as an
|
|
50
|
+
// ordinary missing suffix: mkdir could follow it into an external
|
|
51
|
+
// directory when Git's hooks path is created.
|
|
52
|
+
try {
|
|
53
|
+
if (lstatSync(current).isSymbolicLink())
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
catch (statError) {
|
|
57
|
+
const statCode = statError.code;
|
|
58
|
+
if (statCode !== "ENOENT" && statCode !== "ENOTDIR")
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const parent = path.dirname(current);
|
|
62
|
+
if (parent === current)
|
|
63
|
+
return null;
|
|
64
|
+
missingSegments.unshift(path.basename(current));
|
|
65
|
+
current = parent;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const isWithin = (candidate, root) => {
|
|
70
|
+
const relative = path.relative(root, candidate);
|
|
71
|
+
return (relative === "" ||
|
|
72
|
+
(relative !== ".." &&
|
|
73
|
+
!relative.startsWith(`..${path.sep}`) &&
|
|
74
|
+
!path.isAbsolute(relative)));
|
|
75
|
+
};
|
|
76
|
+
const hooksDir = realpathAllowMissingTail(context.effectiveHooksDir);
|
|
77
|
+
const commonGitDir = realpathAllowMissingTail(context.commonGitDir);
|
|
78
|
+
const worktreeRoot = realpathAllowMissingTail(context.worktreeRoot);
|
|
79
|
+
if (!hooksDir || !commonGitDir || !worktreeRoot)
|
|
80
|
+
return false;
|
|
81
|
+
// The default hooks dir in a linked worktree is shared under the common Git
|
|
82
|
+
// directory, which can sit outside the current worktree root.
|
|
83
|
+
return isWithin(hooksDir, commonGitDir) || isWithin(hooksDir, worktreeRoot);
|
|
84
|
+
}
|
|
85
|
+
async function initNextAction(projectRoot) {
|
|
29
86
|
const sourceFiles = await nodeFilesystem.glob([
|
|
30
87
|
".kb/requirements/**/*.md",
|
|
31
88
|
".kb/scenarios/**/*.md",
|
|
@@ -35,9 +92,9 @@ async function initNextAction() {
|
|
|
35
92
|
".kb/flags/**/*.md",
|
|
36
93
|
".kb/events/**/*.md",
|
|
37
94
|
".kb/facts/**/*.md",
|
|
38
|
-
], { cwd:
|
|
95
|
+
], { cwd: projectRoot });
|
|
39
96
|
const activation = await classifyActivation({
|
|
40
|
-
workspaceRoot:
|
|
97
|
+
workspaceRoot: projectRoot,
|
|
41
98
|
signal: new AbortController().signal,
|
|
42
99
|
clock: () => new Date(),
|
|
43
100
|
fs: nodeFilesystem,
|
|
@@ -67,12 +124,35 @@ export async function initCommand(options) {
|
|
|
67
124
|
console.error("Error: --badge-only requires --github. The recommended integration is `kibi init --github` (badge + full report).");
|
|
68
125
|
return { exitCode: 1 };
|
|
69
126
|
}
|
|
70
|
-
|
|
127
|
+
// Resolve the repository once and derive every project path from Git's own
|
|
128
|
+
// answer, so init works from linked worktrees (.git is a file there) and
|
|
129
|
+
// from subdirectories (cwd has no .kb or .git at all). Bare repositories,
|
|
130
|
+
// unreadable contexts, and operational Git refusals are rejected before any
|
|
131
|
+
// workspace write — even when KIBI_BRANCH makes a standalone fallback
|
|
132
|
+
// available for genuinely non-repository directories.
|
|
133
|
+
// implements REQ-git-hook-effective-install
|
|
134
|
+
const resolution = resolveGitRepository(process.cwd());
|
|
135
|
+
if (resolution.status === "git-refused") {
|
|
136
|
+
console.error(`Error: ${resolution.reason}`);
|
|
137
|
+
console.error("Kibi cannot verify this directory's Git context; refusing to create workspace state.");
|
|
138
|
+
return { exitCode: 1 };
|
|
139
|
+
}
|
|
140
|
+
if (resolution.status === "unsupported") {
|
|
141
|
+
console.error(`Error: ${resolution.reason}`);
|
|
142
|
+
console.error("Kibi requires a working-tree checkout; refusing to create workspace state.");
|
|
143
|
+
return { exitCode: 1 };
|
|
144
|
+
}
|
|
145
|
+
const repoContext = resolution.status === "ok" ? resolution.context : null;
|
|
146
|
+
const projectRoot = repoContext?.worktreeRoot ?? process.cwd();
|
|
147
|
+
const kbDir = path.join(projectRoot, ".kb");
|
|
71
148
|
const kbExists = existsSync(kbDir);
|
|
72
|
-
// Resolve the exact active Git branch
|
|
73
|
-
//
|
|
149
|
+
// Resolve the exact active Git branch against the project root (not cwd):
|
|
150
|
+
// recovery journals, legacy stores, and identity manifests are read from
|
|
151
|
+
// the same .kb tree init is about to write.
|
|
152
|
+
// Standalone use must be explicit via KIBI_BRANCH; there is no implicit
|
|
153
|
+
// default branch.
|
|
74
154
|
let currentBranch;
|
|
75
|
-
const result = resolveBranchAttachment();
|
|
155
|
+
const result = resolveBranchAttachment(projectRoot);
|
|
76
156
|
if ("error" in result) {
|
|
77
157
|
const isNonGitError = result.code === "NOT_A_GIT_REPO" || result.code === "GIT_NOT_AVAILABLE";
|
|
78
158
|
console.error("Error: Failed to resolve the active git branch.");
|
|
@@ -90,7 +170,7 @@ export async function initCommand(options) {
|
|
|
90
170
|
if (!kbExists) {
|
|
91
171
|
createKbDirectoryStructure(kbDir, currentBranch);
|
|
92
172
|
createManifestFile(kbDir);
|
|
93
|
-
updateGitIgnore(
|
|
173
|
+
updateGitIgnore(projectRoot);
|
|
94
174
|
const schemaSourceDir = path.resolve(__dirname, "..", "..", "schema");
|
|
95
175
|
await copySchemaFiles(kbDir, schemaSourceDir);
|
|
96
176
|
}
|
|
@@ -104,14 +184,29 @@ export async function initCommand(options) {
|
|
|
104
184
|
createManifestFile(kbDir);
|
|
105
185
|
}
|
|
106
186
|
}
|
|
107
|
-
ensureSymbolsManifestFile(
|
|
187
|
+
ensureSymbolsManifestFile(projectRoot);
|
|
108
188
|
if (options.hooks) {
|
|
109
|
-
|
|
110
|
-
if (!existsSync(gitDir)) {
|
|
189
|
+
if (!repoContext) {
|
|
111
190
|
console.error("Warning: No git repository found, skipping hooks");
|
|
112
191
|
}
|
|
192
|
+
else if (!isRepositoryManagedHooksDir(repoContext)) {
|
|
193
|
+
// core.hooksPath is only the culprit when it is configured; the
|
|
194
|
+
// default hooks directory can also escape the repository through a
|
|
195
|
+
// symlink, and blaming a setting the operator never made misleads.
|
|
196
|
+
const cause = repoContext.hooksPathConfig
|
|
197
|
+
? "core.hooksPath points outside this repository"
|
|
198
|
+
: "The Git hooks directory resolves outside this repository (for example through a symlink)";
|
|
199
|
+
console.error(`Warning: ${cause} (${repoContext.effectiveHooksDir}); refusing to install hooks into unrelated directories. Kibi enforcement stays OFF for this repository until the hooks path is repository-managed.`);
|
|
200
|
+
}
|
|
113
201
|
else {
|
|
114
|
-
installGitHooks(
|
|
202
|
+
installGitHooks(repoContext.effectiveHooksDir, {
|
|
203
|
+
hooksPathOrigin: repoContext.hooksPathOrigin,
|
|
204
|
+
});
|
|
205
|
+
if (repoContext.isLinkedWorktree && !repoContext.hooksPathConfig) {
|
|
206
|
+
// Only the default common hooks directory is shared by Git across
|
|
207
|
+
// worktrees; a configured hooksPath resolves per checkout.
|
|
208
|
+
console.log(`✓ Repository-common hooks directory shared with all worktrees (${repoContext.effectiveHooksDir})`);
|
|
209
|
+
}
|
|
115
210
|
}
|
|
116
211
|
}
|
|
117
212
|
console.log("\n✓ Kibi initialized. Kibi infrastructure is ready for this repository.");
|
|
@@ -119,11 +214,11 @@ export async function initCommand(options) {
|
|
|
119
214
|
if (kbExists) {
|
|
120
215
|
console.log(" Existing Kibi source knowledge was preserved.");
|
|
121
216
|
}
|
|
122
|
-
console.log((await initNextAction()).message);
|
|
217
|
+
console.log((await initNextAction(projectRoot)).message);
|
|
123
218
|
console.log(" Optional diagnostic: run 'kibi doctor' if setup appears degraded.");
|
|
124
219
|
if (options.github === true) {
|
|
125
220
|
scaffoldGitHubIntegration({
|
|
126
|
-
cwd:
|
|
221
|
+
cwd: projectRoot,
|
|
127
222
|
badgeOnly: options.badgeOnly === true,
|
|
128
223
|
});
|
|
129
224
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prove.d.ts","sourceRoot":"","sources":["../../src/commands/prove.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAEzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AASjE,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAYnF,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC;AAGH,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,kBAAkB,CAAC;CACzC,CAAC,CAAC;AAEH,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5C;;;;;GAKG;AAEH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC,GAC1D,MAAM,CAiBR;AAED;;;;GAIG;AAEH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,MAAM,GACf,GAAG,CAAC,MAAM,CAAC,CAUb;AAQD,wBAAgB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAEjD;AAkCD,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,gBAAgB,EAC7B,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,UAAU,CAWnB;
|
|
1
|
+
{"version":3,"file":"prove.d.ts","sourceRoot":"","sources":["../../src/commands/prove.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAEzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AASjE,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AAYnF,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC;AAGH,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,kBAAkB,CAAC;CACzC,CAAC,CAAC;AAEH,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5C;;;;;GAKG;AAEH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC,GAC1D,MAAM,CAiBR;AAED;;;;GAIG;AAEH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,MAAM,GACf,GAAG,CAAC,MAAM,CAAC,CAUb;AAQD,wBAAgB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAEjD;AAkCD,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,gBAAgB,EAC7B,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,UAAU,CAWnB;AAsKD,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,GAAE,wBAA6B,GAClC,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgL/B"}
|
package/dist/commands/prove.js
CHANGED
|
@@ -151,33 +151,25 @@ function markAggregateFailure(results) {
|
|
|
151
151
|
return results.map((result) => ({ ...result, outcome: "failed" }));
|
|
152
152
|
}
|
|
153
153
|
async function selectTests(context, options) {
|
|
154
|
-
//
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
type: "test",
|
|
162
|
-
limit: pageSize,
|
|
163
|
-
offset,
|
|
164
|
-
});
|
|
165
|
-
all.push(...page);
|
|
166
|
-
if (page.length < pageSize)
|
|
167
|
-
return all;
|
|
168
|
-
}
|
|
169
|
-
};
|
|
154
|
+
// Contract plus bindings only. Receipt histories are loaded again at ingest
|
|
155
|
+
// and blow the Prolog output buffer when selected up front. JUnit and TAP
|
|
156
|
+
// conversion needs the bindings before that reload.
|
|
157
|
+
const loadAll = async () => loadEntities(context.prolog, {
|
|
158
|
+
type: "test",
|
|
159
|
+
projection: "proof_contract",
|
|
160
|
+
});
|
|
170
161
|
let candidates = [];
|
|
171
162
|
if (options.testId) {
|
|
172
163
|
const found = await loadEntities(context.prolog, {
|
|
173
164
|
id: options.testId,
|
|
174
165
|
type: "test",
|
|
166
|
+
projection: "proof_contract",
|
|
175
167
|
});
|
|
176
168
|
candidates = found.map(withId);
|
|
177
169
|
}
|
|
178
170
|
else if (options.requirement) {
|
|
179
171
|
const requirementId = options.requirement;
|
|
180
|
-
const scenarioResult = await context.prolog?.query(`findall([S,T], (kb_relationship(specified_by, '${requirementId}', S), (kb_relationship(verified_by, S, T) ; kb_relationship(validates, T, S))
|
|
172
|
+
const scenarioResult = await context.prolog?.query(`findall([S,T], (kb_relationship(specified_by, '${requirementId}', S), (kb_relationship(verified_by, S, T) ; kb_relationship(validates, T, S))), Rows)`);
|
|
181
173
|
const rowsRaw = scenarioResult?.success
|
|
182
174
|
? scenarioResult.bindings.Rows
|
|
183
175
|
: undefined;
|
|
@@ -189,7 +181,7 @@ async function selectTests(context, options) {
|
|
|
189
181
|
ids.add(test.trim());
|
|
190
182
|
}
|
|
191
183
|
}
|
|
192
|
-
const directResult = await context.prolog?.query(`findall(T,
|
|
184
|
+
const directResult = await context.prolog?.query(`findall(T, kb_relationship(validates, T, '${requirementId}'), Rows)`);
|
|
193
185
|
const directRaw = directResult?.success
|
|
194
186
|
? directResult.bindings.Rows
|
|
195
187
|
: undefined;
|
|
@@ -21,6 +21,8 @@ export type SyncCache = {
|
|
|
21
21
|
seenAt: Record<string, string>;
|
|
22
22
|
semanticHashes: Record<string, string>;
|
|
23
23
|
semanticContracts: Record<string, boolean>;
|
|
24
|
+
/** Compiler contract that produced the cached compilation; see below. */
|
|
25
|
+
compilerFingerprint?: string;
|
|
24
26
|
};
|
|
25
27
|
/**
|
|
26
28
|
* v2: cache identities are workspace-root relative instead of process-cwd
|
|
@@ -30,6 +32,20 @@ export type SyncCache = {
|
|
|
30
32
|
*/
|
|
31
33
|
export declare const SYNC_CACHE_VERSION = 2;
|
|
32
34
|
export declare const SYNC_CACHE_TTL_MS: number;
|
|
35
|
+
/**
|
|
36
|
+
* Identity of the entity property contract this CLI compiles against. Sync
|
|
37
|
+
* skips unchanged sources by content hash, so a store compiled by a CLI with a
|
|
38
|
+
* different contract (an older build that drops properties it does not know)
|
|
39
|
+
* would otherwise keep that lossy compilation forever. A cache stamped with a
|
|
40
|
+
* different fingerprint is discarded, which re-imports every source once.
|
|
41
|
+
*/
|
|
42
|
+
export declare const SYNC_COMPILER_FINGERPRINT: string;
|
|
43
|
+
/**
|
|
44
|
+
* Stale reason for a branch store whose last compilation used a different
|
|
45
|
+
* compiler contract than the running CLI. Status reports it so a lossy store is
|
|
46
|
+
* visible before the next sync repairs it.
|
|
47
|
+
*/
|
|
48
|
+
export declare function compilerFingerprintReason(storePath: string, deps?: Partial<SyncCacheDeps>): Record<string, unknown> | null;
|
|
33
49
|
export declare function toCacheKey(workspaceRoot: string, filePath: string): string;
|
|
34
50
|
export declare function hashFile(workspaceRoot: string, filePath: string, deps?: Partial<SyncCacheDeps>): string;
|
|
35
51
|
/** Deterministically hash a JSON-compatible compiler payload. */
|
|
@@ -41,7 +57,10 @@ export declare function hashNormalized(value: unknown): string;
|
|
|
41
57
|
* source hash even though the authored YAML bytes stay identical.
|
|
42
58
|
*/
|
|
43
59
|
export declare function hashManifestWithCoordinates(workspaceRoot: string, manifestPath: string, coordinatesPath: string | null, deps?: Partial<SyncCacheDeps>): string;
|
|
44
|
-
export declare function readSyncCache(cachePath: string, deps?: Partial<SyncCacheDeps
|
|
60
|
+
export declare function readSyncCache(cachePath: string, deps?: Partial<SyncCacheDeps>, options?: {
|
|
61
|
+
/** Discard a cache produced under a different compiler contract. */
|
|
62
|
+
readonly compilerFingerprint?: string;
|
|
63
|
+
}): SyncCache;
|
|
45
64
|
export declare function writeSyncCache(cachePath: string, cache: SyncCache, deps?: Partial<SyncCacheDeps>): void;
|
|
46
65
|
export declare function copySyncCache(livePath: string, stagingPath: string, deps?: Partial<SyncCacheDeps>): void;
|
|
47
66
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/cache.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/cache.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAO7E,UAAU,aAAa;IACrB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,aAAa,EAAE,OAAO,aAAa,CAAC;CACrC;AAaD,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3C,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,iBAAiB,QAA2B,CAAC;AAE1D;;;;;;GAMG;AAEH,eAAO,MAAM,yBAAyB,QAEtB,CAAC;AAEjB;;;;GAIG;AAEH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAyBhC;AAED,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM1E;AAED,wBAAgB,QAAQ,CAEtB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,MAAM,CAIR;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAerD;AAED;;;;;GAKG;AAEH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,MAAM,CA4FR;AAED,wBAAgB,aAAa,CAE3B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,EAC7B,OAAO,GAAE;IACP,oEAAoE;IACpE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAClC,GACL,SAAS,CA8DX;AAED,wBAAgB,cAAc,CAE5B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,SAAS,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,IAAI,CAaN;AAED,wBAAgB,aAAa,CAE3B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,IAAI,CASN"}
|
|
@@ -19,6 +19,9 @@ import { createHash } from "node:crypto";
|
|
|
19
19
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
20
20
|
import * as path from "node:path";
|
|
21
21
|
import { load as parseYAML } from "js-yaml";
|
|
22
|
+
import entitySchema from "../../schemas/entity.schema.json" with {
|
|
23
|
+
type: "json"
|
|
24
|
+
};
|
|
22
25
|
function resolveDeps(overrides) {
|
|
23
26
|
return {
|
|
24
27
|
createHash,
|
|
@@ -37,6 +40,47 @@ function resolveDeps(overrides) {
|
|
|
37
40
|
*/
|
|
38
41
|
export const SYNC_CACHE_VERSION = 2;
|
|
39
42
|
export const SYNC_CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
43
|
+
/**
|
|
44
|
+
* Identity of the entity property contract this CLI compiles against. Sync
|
|
45
|
+
* skips unchanged sources by content hash, so a store compiled by a CLI with a
|
|
46
|
+
* different contract (an older build that drops properties it does not know)
|
|
47
|
+
* would otherwise keep that lossy compilation forever. A cache stamped with a
|
|
48
|
+
* different fingerprint is discarded, which re-imports every source once.
|
|
49
|
+
*/
|
|
50
|
+
// implements REQ-cli-canonical-runtime
|
|
51
|
+
export const SYNC_COMPILER_FINGERPRINT = createHash("sha256")
|
|
52
|
+
.update(JSON.stringify(entitySchema))
|
|
53
|
+
.digest("hex");
|
|
54
|
+
/**
|
|
55
|
+
* Stale reason for a branch store whose last compilation used a different
|
|
56
|
+
* compiler contract than the running CLI. Status reports it so a lossy store is
|
|
57
|
+
* visible before the next sync repairs it.
|
|
58
|
+
*/
|
|
59
|
+
// implements REQ-cli-canonical-runtime
|
|
60
|
+
export function compilerFingerprintReason(storePath, deps) {
|
|
61
|
+
const resolved = resolveDeps(deps);
|
|
62
|
+
const cachePath = path.join(storePath, "sync-cache.json");
|
|
63
|
+
if (!resolved.existsSync(cachePath))
|
|
64
|
+
return null;
|
|
65
|
+
let recorded;
|
|
66
|
+
try {
|
|
67
|
+
recorded = JSON.parse(resolved.readFileSync(cachePath, "utf8")).compilerFingerprint;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
if (recorded === SYNC_COMPILER_FINGERPRINT)
|
|
73
|
+
return null;
|
|
74
|
+
return {
|
|
75
|
+
code: "compiler_changed",
|
|
76
|
+
path: cachePath,
|
|
77
|
+
entityIds: [],
|
|
78
|
+
detail: typeof recorded === "string"
|
|
79
|
+
? "The branch KB was compiled by a Kibi CLI with a different entity property contract, so unchanged sources may lack properties this CLI keeps. The next kibi sync re-imports every source."
|
|
80
|
+
: "The branch KB was compiled by a Kibi CLI that did not record its entity property contract, so unchanged sources may lack properties this CLI keeps. The next kibi sync re-imports every source.",
|
|
81
|
+
remediation: { command_argv: ["kibi", "sync"], applyRequired: false },
|
|
82
|
+
};
|
|
83
|
+
}
|
|
40
84
|
export function toCacheKey(workspaceRoot, filePath) {
|
|
41
85
|
const root = path.resolve(workspaceRoot);
|
|
42
86
|
const target = path.isAbsolute(filePath)
|
|
@@ -165,7 +209,7 @@ export function hashManifestWithCoordinates(workspaceRoot, manifestPath, coordin
|
|
|
165
209
|
}
|
|
166
210
|
export function readSyncCache(
|
|
167
211
|
// implements REQ-003
|
|
168
|
-
cachePath, deps) {
|
|
212
|
+
cachePath, deps, options = {}) {
|
|
169
213
|
const resolved = resolveDeps(deps);
|
|
170
214
|
if (!resolved.existsSync(cachePath)) {
|
|
171
215
|
return {
|
|
@@ -178,7 +222,9 @@ cachePath, deps) {
|
|
|
178
222
|
}
|
|
179
223
|
try {
|
|
180
224
|
const parsed = JSON.parse(resolved.readFileSync(cachePath, "utf8"));
|
|
181
|
-
if (parsed.version !== SYNC_CACHE_VERSION
|
|
225
|
+
if (parsed.version !== SYNC_CACHE_VERSION ||
|
|
226
|
+
(options.compilerFingerprint !== undefined &&
|
|
227
|
+
parsed.compilerFingerprint !== options.compilerFingerprint)) {
|
|
182
228
|
return {
|
|
183
229
|
version: SYNC_CACHE_VERSION,
|
|
184
230
|
hashes: {},
|
|
@@ -206,6 +252,9 @@ cachePath, deps) {
|
|
|
206
252
|
if (parsed.shardRelationships !== undefined) {
|
|
207
253
|
cache.shardRelationships = parsed.shardRelationships;
|
|
208
254
|
}
|
|
255
|
+
if (parsed.compilerFingerprint !== undefined) {
|
|
256
|
+
cache.compilerFingerprint = parsed.compilerFingerprint;
|
|
257
|
+
}
|
|
209
258
|
return cache;
|
|
210
259
|
}
|
|
211
260
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/discovery.ts"],"names":[],"mappings":"AAkCA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,+EAA+E;IAC/E,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/discovery.ts"],"names":[],"mappings":"AAkCA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,+EAA+E;IAC/E,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AA2FH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOlD;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAShE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUxD;AAED,wBAAgB,mCAAmC,CACjD,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,SAAS,4BAA4B,EAAE,GAChD,IAAI,CA6CN;AAsBD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,MAAM,GAAG,IAAI,CAIf;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC;IACT,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,4BAA4B,EAAE,4BAA4B,EAAE,CAAC;CAC9D,CAAC,CA+FD"}
|
|
@@ -67,7 +67,7 @@ function pendingSourcePaths(cwd, recoverMissing) {
|
|
|
67
67
|
});
|
|
68
68
|
continue;
|
|
69
69
|
}
|
|
70
|
-
throw new Error(`Pending source is missing: ${relative}
|
|
70
|
+
throw new Error(`Pending source is missing: ${relative}. If the file was deleted on purpose, run 'kibi branch recover --apply' to rebuild the branch KB from the sources that remain.`);
|
|
71
71
|
}
|
|
72
72
|
const actual = createHash("sha256")
|
|
73
73
|
.update(readFileSync(absolute))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/persistence.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAEV,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/persistence.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAEV,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA0HrD,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;CACrB;AA8CD,iFAAiF;AACjF,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,SAAS,MAAM,EAAE,GAC7B,OAAO,CAAC,MAAM,CAAC,CAkCjB;AAED,0EAA0E;AAC1E,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED,8EAA8E;AAC9E,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,SAAS,qBAAqB,EAAE,GAC9C,OAAO,CAAC,MAAM,CAAC,CAuBjB;AAmCD,wBAAsB,eAAe,CAEnC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EACtB,OAAO,GAAE;IAAE,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAAO,GAChD,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC,CAyPvD;AA4BD,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,MAAM,CAER;AAGD,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,kBAAkB,EAAE,qBAAqB,EAAE,EAC3C,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GACvC,OAAO,CAAC;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAC,CAmO7D"}
|
|
@@ -83,6 +83,14 @@ function serializeTypedFactFields(entity) {
|
|
|
83
83
|
if (ruleIr !== undefined && ruleIr !== null) {
|
|
84
84
|
fields.push(`rule_ir=${toPrologString(JSON.stringify(ruleIr))}`);
|
|
85
85
|
}
|
|
86
|
+
// Predicate-schema vocabularies are objects; like rule_ir they travel as
|
|
87
|
+
// JSON strings and are decoded again at the public boundary.
|
|
88
|
+
for (const field of ["argument_constants", "argument_aliases"]) {
|
|
89
|
+
const value = getEntityField(entity, field);
|
|
90
|
+
if (value !== undefined && value !== null) {
|
|
91
|
+
fields.push(`${field}=${toPrologString(JSON.stringify(value))}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
86
94
|
// Atom fields (possibly unquoted if simple)
|
|
87
95
|
for (const field of ATOM_FIELDS) {
|
|
88
96
|
const value = getEntityField(entity, field);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA6BjE,OAAO,EAEL,yBAAyB,EAE1B,MAAM,gDAAgD,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA6BjE,OAAO,EAEL,yBAAyB,EAE1B,MAAM,gDAAgD,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA0B7C,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AA2BxE,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAmCD,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,EACxB,4BAA4B,UAAQ,EACpC,4BAA4B,GAAE,4BAA4B,EAAO,GAChE,MAAM,EAAE,CAuGV;AAqDD,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,yBAAyB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3E,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,yBAAyB,GAAG;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,KACzD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,aAAa,CAAC;IAC/D,yBAAyB,CAAC,EAAE,OAAO,yBAAyB,CAAC;CAC9D;AA6DD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGvE;AAGD,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,IAAI,GAChB,IAAI,CAMN;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,UAAU,EAAE,EACzB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,IAAI,CAIN;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAMP;AAED,wBAAgB,iCAAiC,CAC/C,WAAW,EAAE,UAAU,EAAE,EACzB,oBAAoB,EAAE,OAAO,EAC7B,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,GAClB,IAAI,CAUN;AAGD,wBAAsB,WAAW,CAC/B,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;CACnB,EACN,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,UAAU,CAAC,CA6nCrB;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
|