kibi-cli 2.16.0 → 2.18.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 +13 -0
- package/dist/cli-register-proof.d.ts +6 -0
- package/dist/cli-register-proof.d.ts.map +1 -1
- package/dist/cli-register-proof.js +46 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +9 -3
- package/dist/commands/sync/untracked-targets.d.ts.map +1 -1
- package/dist/commands/sync/untracked-targets.js +39 -9
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +26 -5
- package/dist/engine.d.ts +4 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +40 -10
- package/dist/operations/modeling/predicate-applicability.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applicability.js +12 -3
- package/dist/operations/modeling/predicate-catalog-4.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-catalog-4.js +4 -0
- package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-loader.js +3 -0
- package/dist/operations/modeling/predicate-score-3.js +1 -1
- package/dist/operations/modeling/predicate-types.d.ts +5 -0
- package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-utils.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-utils.js +2 -3
- package/dist/operations/mutation/source-authoring.d.ts +9 -0
- package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
- package/dist/operations/mutation/source-authoring.js +38 -2
- package/dist/operations/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +33 -8
- package/dist/operations/planning/migration-refusal.d.ts +14 -0
- package/dist/operations/planning/migration-refusal.d.ts.map +1 -0
- package/dist/operations/planning/migration-refusal.js +17 -0
- package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/clauses.js +7 -1
- package/dist/operations/semantic-advisor/shared.d.ts +7 -0
- package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/shared.js +22 -3
- package/dist/prolog/store-lock.d.ts +22 -0
- package/dist/prolog/store-lock.d.ts.map +1 -1
- package/dist/prolog/store-lock.js +45 -1
- package/dist/prolog.d.ts +7 -1
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +21 -3
- package/dist/proof/inspect.d.ts +9 -0
- package/dist/proof/inspect.d.ts.map +1 -1
- package/dist/proof/inspect.js +10 -0
- package/dist/proof/integration-plan.d.ts +2 -1
- package/dist/proof/integration-plan.d.ts.map +1 -1
- package/dist/proof/integration-plan.js +30 -13
- package/dist/public/impact/coverage-depth-quality.d.ts.map +1 -1
- package/dist/public/impact/coverage-depth-quality.js +29 -1
- package/dist/public/operations/contracts.d.ts.map +1 -1
- package/dist/public/operations/contracts.js +3 -0
- package/dist/public/operations/discovery-executors.d.ts +14 -1
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +62 -12
- 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 +31 -0
- package/dist/public/operations/result-envelope.d.ts.map +1 -1
- package/dist/public/operations/result-envelope.js +23 -3
- package/dist/public/operations/source-relationship-parity.d.ts.map +1 -1
- package/dist/public/operations/source-relationship-parity.js +55 -1
- package/dist/public/skills/kibi-usage/SKILL.md +19 -4
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +3 -3
- package/dist/public/skills/kibi-usage/resources/proof.md +44 -3
- package/dist/utils/branch-store.d.ts +8 -0
- package/dist/utils/branch-store.d.ts.map +1 -1
- package/dist/utils/branch-store.js +27 -1
- package/dist/utils/content-freshness.d.ts +13 -0
- package/dist/utils/content-freshness.d.ts.map +1 -0
- package/dist/utils/content-freshness.js +161 -0
- package/package.json +2 -2
- package/src/public/impact/coverage-depth-quality.ts +46 -1
- package/src/public/operations/contracts.ts +3 -0
- package/src/public/operations/discovery-executors.ts +89 -11
- package/src/public/operations/migration-plan.ts +44 -0
- package/src/public/operations/result-envelope.ts +31 -3
- package/src/public/operations/source-relationship-parity.ts +60 -3
- package/src/public/skills/kibi-usage/SKILL.md +19 -4
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +3 -3
- package/src/public/skills/kibi-usage/resources/proof.md +44 -3
|
@@ -80,6 +80,15 @@ export declare function renderYamlRelationshipDeletion(sourcePathValue: string,
|
|
|
80
80
|
* so a plan writes exactly what `kb_upsert` would.
|
|
81
81
|
*/
|
|
82
82
|
export declare function renderSourceDocument(input: UpsertInput, entity: Readonly<Record<string, unknown>>, existingContent: string | undefined, relativePath: string): string;
|
|
83
|
+
/**
|
|
84
|
+
* Whether Git definitely does not track `relative`. Sync reads only tracked
|
|
85
|
+
* sources plus pending-source receipts, so an untracked file (for example the
|
|
86
|
+
* `.kb/symbols.yaml` that `kibi init` creates) needs a receipt on every
|
|
87
|
+
* write, or a new branch store compiles relationships without the entities
|
|
88
|
+
* they connect. Any other Git outcome (not a repository, git missing) is
|
|
89
|
+
* "unknown" and keeps the previous behaviour.
|
|
90
|
+
*/
|
|
91
|
+
export declare function isUntrackedByGit(workspaceRoot: string, relative: string): boolean;
|
|
83
92
|
export declare function writeSourceForUpsert(input: UpsertInput, entity: Readonly<Record<string, unknown>>, existing?: Readonly<Record<string, unknown>>, context?: OperationContext, sourceDocumentOverride?: string): Promise<{
|
|
84
93
|
receipt: SourceWriteReceipt;
|
|
85
94
|
rollback: () => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-authoring.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/source-authoring.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"source-authoring.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/source-authoring.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
1
2
|
import { createHash } from "node:crypto";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
4
|
import fs from "node:fs";
|
|
@@ -462,7 +463,19 @@ function renderSymbolManifest(entity, relationships, existingContent) {
|
|
|
462
463
|
if (!symbols || typeof symbols !== "object" || !("items" in symbols)) {
|
|
463
464
|
throw new OperationError("SOURCE_FORMAT_INVALID", "Symbol manifest must contain a symbols array");
|
|
464
465
|
}
|
|
465
|
-
|
|
466
|
+
// implements REQ-core-persistence
|
|
467
|
+
// `kibi init` writes `symbols: []`, a flow sequence; appending to it kept
|
|
468
|
+
// every symbol on one line. Render the list (and the entries that were
|
|
469
|
+
// written inside it) as block YAML so diffs stay reviewable.
|
|
470
|
+
const sequence = symbols;
|
|
471
|
+
if (sequence.flow === true) {
|
|
472
|
+
sequence.flow = false;
|
|
473
|
+
for (const item of sequence.items) {
|
|
474
|
+
if (item && typeof item === "object" && "flow" in item)
|
|
475
|
+
item.flow = false;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
const items = sequence.items;
|
|
466
479
|
const id = String(entity.id);
|
|
467
480
|
const indices = items.flatMap((item, index) => {
|
|
468
481
|
if (!item || typeof item !== "object" || !("get" in item))
|
|
@@ -670,6 +683,27 @@ export function renderSourceDocument(input, entity, existingContent, relativePat
|
|
|
670
683
|
}
|
|
671
684
|
return renderEntityDocument(input, entity, existingContent);
|
|
672
685
|
}
|
|
686
|
+
/**
|
|
687
|
+
* Whether Git definitely does not track `relative`. Sync reads only tracked
|
|
688
|
+
* sources plus pending-source receipts, so an untracked file (for example the
|
|
689
|
+
* `.kb/symbols.yaml` that `kibi init` creates) needs a receipt on every
|
|
690
|
+
* write, or a new branch store compiles relationships without the entities
|
|
691
|
+
* they connect. Any other Git outcome (not a repository, git missing) is
|
|
692
|
+
* "unknown" and keeps the previous behaviour.
|
|
693
|
+
*/
|
|
694
|
+
// implements REQ-core-persistence
|
|
695
|
+
export function isUntrackedByGit(workspaceRoot, relative) {
|
|
696
|
+
try {
|
|
697
|
+
execFileSync("git", ["-C", workspaceRoot, "ls-files", "--error-unmatch", "--", relative],
|
|
698
|
+
// Bounded: a write must never wait on Git. A timeout reads as
|
|
699
|
+
// "tracked", the pre-receipt behaviour.
|
|
700
|
+
{ stdio: "ignore", timeout: 10_000 });
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
703
|
+
catch (error) {
|
|
704
|
+
return error.status === 1;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
673
707
|
export async function writeSourceForUpsert(input, entity, existing, context, sourceDocumentOverride) {
|
|
674
708
|
if (!context?.fs)
|
|
675
709
|
return null;
|
|
@@ -795,7 +829,9 @@ export async function writeSourceForUpsert(input, entity, existing, context, sou
|
|
|
795
829
|
};
|
|
796
830
|
try {
|
|
797
831
|
if (receipt.afterHash !== null &&
|
|
798
|
-
(before === undefined ||
|
|
832
|
+
(before === undefined ||
|
|
833
|
+
fs.existsSync(pendingReceipt) ||
|
|
834
|
+
isUntrackedByGit(context.workspaceRoot, relative))) {
|
|
799
835
|
writePendingSourceReceipt(context.workspaceRoot, relative, receipt.afterHash);
|
|
800
836
|
}
|
|
801
837
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-plan.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/apply-plan.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apply-plan.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/apply-plan.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAEV,gBAAgB,EAGjB,MAAM,0CAA0C,CAAC;AASlD,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,uBAAuB,CAAC;AAgE/B,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAGhB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAG/B,eAAO,MAAM,yBAAyB,EAAG,2BAAoC,CAAC;AA6G9E,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,IAAI,CAMN;AAED,wBAAgB,mCAAmC,CACjD,SAAS,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EAAE,EACnE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,GAC3B,IAAI,CAaN;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,SAAS,cAAoB,GAC5B,eAAe,EAAE,CA2CnB;AA8zBD;;;;;;GAMG;AAEH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAiCf;AAyqDD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC;IACT,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,iBAAiB,EAAE,eAAe,CAAC;CACpC,CAAC,CAkDD"}
|
|
@@ -7,7 +7,7 @@ import { syncCommand } from "../../commands/sync.js";
|
|
|
7
7
|
import { PROOF_INTEGRATION_CONFIGURE, applyProofIntegrationAction, } from "../../proof/integration-plan.js";
|
|
8
8
|
import { loadEntities } from "../../public/operations/discovery-entities.js";
|
|
9
9
|
import { executeStatus } from "../../public/operations/discovery-executors.js";
|
|
10
|
-
import { PREDICATE_SCHEMA_ALIGNMENT_CODE, migrationPlanHash, } from "../../public/operations/migration-plan.js";
|
|
10
|
+
import { FRESHNESS_RESYNC, PREDICATE_SCHEMA_ALIGNMENT_CODE, migrationPlanHash, } from "../../public/operations/migration-plan.js";
|
|
11
11
|
import { readMigrationConfigStatus } from "../../public/operations/migration-plan.js";
|
|
12
12
|
import { readWorkspaceSnapshot } from "../../public/operations/workspace-snapshot.js";
|
|
13
13
|
import { computeShardPath, renderShardWithRelationship, } from "../../relationships/shards.js";
|
|
@@ -24,6 +24,7 @@ import { canonicalSourcePath, renderSourceDocument, } from "../mutation/source-a
|
|
|
24
24
|
import { assertRelationshipShardContained, executeUpsert, validateUpsertForCommit, } from "../mutation/upsert.js";
|
|
25
25
|
import { acquireWorkspaceMutationLock, releaseWorkspaceMutationLock, } from "../mutation/workspace-mutation-lock.js";
|
|
26
26
|
import { compilePlanHash, isBlockingWitness, parseWhatIfAnalysis, planWhatIfGoal, } from "./compile-intent.js";
|
|
27
|
+
import { MigrationActionRefusedError } from "./migration-refusal.js";
|
|
27
28
|
// implements REQ-kibi-change-to-proof-plan-compiler-v2
|
|
28
29
|
export const PLAN_APPLY_RESULT_VERSION = "kibi.plan-apply-result.v1";
|
|
29
30
|
const ENTITY_TYPES = new Set([
|
|
@@ -2121,6 +2122,9 @@ async function applyMigrationPlan(args, context, onCommitted = () => undefined)
|
|
|
2121
2122
|
}
|
|
2122
2123
|
const results = [];
|
|
2123
2124
|
let failed = false;
|
|
2125
|
+
// Failures that changed nothing (a precondition refused the action).
|
|
2126
|
+
let refusals = 0;
|
|
2127
|
+
let failures = 0;
|
|
2124
2128
|
for (const action of actions) {
|
|
2125
2129
|
if (failed) {
|
|
2126
2130
|
results.push({
|
|
@@ -2141,6 +2145,9 @@ async function applyMigrationPlan(args, context, onCommitted = () => undefined)
|
|
|
2141
2145
|
}
|
|
2142
2146
|
catch (error) {
|
|
2143
2147
|
failed = true;
|
|
2148
|
+
failures += 1;
|
|
2149
|
+
if (error instanceof MigrationActionRefusedError)
|
|
2150
|
+
refusals += 1;
|
|
2144
2151
|
results.push({
|
|
2145
2152
|
actionId: action.id,
|
|
2146
2153
|
outcome: "failed",
|
|
@@ -2190,10 +2197,15 @@ async function applyMigrationPlan(args, context, onCommitted = () => undefined)
|
|
|
2190
2197
|
});
|
|
2191
2198
|
}
|
|
2192
2199
|
}
|
|
2200
|
+
// refused: nothing was applied and every failure was a refusal, so the
|
|
2201
|
+
// workspace is as it was; reconciliation_required: an action failed
|
|
2202
|
+
// without being refused, so its effect must be inspected.
|
|
2193
2203
|
const outcome = failed
|
|
2194
2204
|
? results.some((result) => result.outcome === "applied")
|
|
2195
2205
|
? "partially_applied"
|
|
2196
|
-
:
|
|
2206
|
+
: failures > 0 && refusals === failures
|
|
2207
|
+
? "refused"
|
|
2208
|
+
: "reconciliation_required"
|
|
2197
2209
|
: "applied";
|
|
2198
2210
|
const kbState = finalStatus.branchAttachment?.migrationRequired
|
|
2199
2211
|
? "legacy_compat"
|
|
@@ -2237,7 +2249,7 @@ async function applyMigrationPlan(args, context, onCommitted = () => undefined)
|
|
|
2237
2249
|
closeout: {
|
|
2238
2250
|
taskOutcome: outcome === "applied"
|
|
2239
2251
|
? "complete"
|
|
2240
|
-
: outcome === "reconciliation_required"
|
|
2252
|
+
: outcome === "reconciliation_required" || outcome === "refused"
|
|
2241
2253
|
? "blocked"
|
|
2242
2254
|
: "interim",
|
|
2243
2255
|
kbState,
|
|
@@ -2250,7 +2262,11 @@ async function applyMigrationPlan(args, context, onCommitted = () => undefined)
|
|
|
2250
2262
|
content: [
|
|
2251
2263
|
{
|
|
2252
2264
|
type: "text",
|
|
2253
|
-
text:
|
|
2265
|
+
text: outcome === "applied"
|
|
2266
|
+
? `Applied migration plan ${args.plan.planHash.slice(0, 12)}.`
|
|
2267
|
+
: outcome === "refused"
|
|
2268
|
+
? `Refused migration plan ${args.plan.planHash.slice(0, 12)}; nothing was changed.`
|
|
2269
|
+
: `Stopped after migration plan ${args.plan.planHash.slice(0, 12)}.`,
|
|
2254
2270
|
},
|
|
2255
2271
|
],
|
|
2256
2272
|
structuredContent: payload,
|
|
@@ -2289,6 +2305,15 @@ async function applyMigrationAction(action, context) {
|
|
|
2289
2305
|
throw new Error("Compiling the branch store (kibi sync) did not complete successfully.");
|
|
2290
2306
|
return;
|
|
2291
2307
|
}
|
|
2308
|
+
// implements REQ-cli-status-pre-first-sync
|
|
2309
|
+
case FRESHNESS_RESYNC: {
|
|
2310
|
+
const result = await syncCommand({
|
|
2311
|
+
workspaceRoot: context.workspaceRoot,
|
|
2312
|
+
});
|
|
2313
|
+
if (!result.success)
|
|
2314
|
+
throw new Error("Recompiling changed sources (kibi sync) did not complete successfully.");
|
|
2315
|
+
return;
|
|
2316
|
+
}
|
|
2292
2317
|
case "damaged_exact_branch_store":
|
|
2293
2318
|
await branchRecoverCommand({
|
|
2294
2319
|
apply: true,
|
|
@@ -2327,7 +2352,7 @@ async function applyMigrationAction(action, context) {
|
|
|
2327
2352
|
await applySchema6MigrationAction(action, context);
|
|
2328
2353
|
return;
|
|
2329
2354
|
}
|
|
2330
|
-
throw new
|
|
2355
|
+
throw new MigrationActionRefusedError(`Migration action '${action.code}' has no automatic executor.`);
|
|
2331
2356
|
}
|
|
2332
2357
|
}
|
|
2333
2358
|
/**
|
|
@@ -2338,10 +2363,10 @@ async function applyMigrationAction(action, context) {
|
|
|
2338
2363
|
async function applyPredicateSchemaAlignment(action, context) {
|
|
2339
2364
|
const invocation = action.invocation;
|
|
2340
2365
|
if (invocation.kind !== "operation" || invocation.name !== "kb_upsert")
|
|
2341
|
-
throw new
|
|
2366
|
+
throw new MigrationActionRefusedError("Predicate schema alignment requires its planned kb_upsert invocation.");
|
|
2342
2367
|
const input = asUpsert(invocation.input);
|
|
2343
2368
|
if (input.type !== "fact")
|
|
2344
|
-
throw new
|
|
2369
|
+
throw new MigrationActionRefusedError("Predicate schema alignment only rewrites fact entities.");
|
|
2345
2370
|
const prolog = context.prolog ?? (await context.ensureProlog?.());
|
|
2346
2371
|
if (!prolog)
|
|
2347
2372
|
throw new Error("Predicate schema alignment requires a Prolog runtime.");
|
|
@@ -2363,6 +2388,6 @@ async function applyPredicateSchemaAlignment(action, context) {
|
|
|
2363
2388
|
typeof rewrite.index === "number" &&
|
|
2364
2389
|
currentArgs[rewrite.index] === rewrite.from);
|
|
2365
2390
|
if (!unchanged)
|
|
2366
|
-
throw new
|
|
2391
|
+
throw new MigrationActionRefusedError(`Predicate fact ${input.id} changed since planning; rerun kibi check and approve the new plan.`);
|
|
2367
2392
|
await executeUpsert(input, operationContext);
|
|
2368
2393
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A migration action executor throws this when it refuses to run: a
|
|
3
|
+
* precondition failed before it changed anything (the planned file already
|
|
4
|
+
* exists, a source changed since planning, the action is malformed). An
|
|
5
|
+
* application whose only failures are refusals and that applied nothing
|
|
6
|
+
* reports `outcome: "refused"`, not `reconciliation_required`: there is
|
|
7
|
+
* nothing to reconcile.
|
|
8
|
+
*/
|
|
9
|
+
export declare class MigrationActionRefusedError extends Error {
|
|
10
|
+
constructor(message: string);
|
|
11
|
+
}
|
|
12
|
+
/** Error code of the envelope for a migration plan that was refused. */
|
|
13
|
+
export declare const MIGRATION_PLAN_REFUSED: "MIGRATION_PLAN_REFUSED";
|
|
14
|
+
//# sourceMappingURL=migration-refusal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-refusal.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/migration-refusal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qBAAa,2BAA4B,SAAQ,KAAK;gBACxC,OAAO,EAAE,MAAM;CAI5B;AAED,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,EAAG,wBAAiC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A migration action executor throws this when it refuses to run: a
|
|
3
|
+
* precondition failed before it changed anything (the planned file already
|
|
4
|
+
* exists, a source changed since planning, the action is malformed). An
|
|
5
|
+
* application whose only failures are refusals and that applied nothing
|
|
6
|
+
* reports `outcome: "refused"`, not `reconciliation_required`: there is
|
|
7
|
+
* nothing to reconcile.
|
|
8
|
+
*/
|
|
9
|
+
// implements REQ-kibi-change-to-proof-plan-compiler-v2
|
|
10
|
+
export class MigrationActionRefusedError extends Error {
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = "MigrationActionRefusedError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** Error code of the envelope for a migration plan that was refused. */
|
|
17
|
+
export const MIGRATION_PLAN_REFUSED = "MIGRATION_PLAN_REFUSED";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clauses.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/clauses.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"clauses.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/clauses.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC,CAAC,CAAC;AAkBH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAQD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB,WAAW,GAAG,aAAa,CAG7B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AA4BD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAClC,SAAS,cAAc,EAAE,CA4B3B"}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
|
|
2
|
+
// An explicit grant ("are allowed to", "is permitted to") asserts a
|
|
3
|
+
// permission just as "denied"/"forbidden" assert a prohibition. Bare "can" and
|
|
4
|
+
// "may" are accepted by the predicate applicability gate but not here: stored
|
|
5
|
+
// clause roles are derived from this pattern, and "it can be restricted to …"
|
|
6
|
+
// style capability prose would turn existing descriptive inventories into
|
|
7
|
+
// unmodeled normative clauses.
|
|
8
|
+
const NORMATIVE_ASSERTION_PATTERN = /\b(?:must|shall|should|required|requires?|may\s+only|(?:is|are)\s+(?:not\s+)?(?:allowed|permitted)\s+to|permitted|may\s+(?:not\s+)?(?:be\s+)?\w+\s+only\b|may\s+(?:have\s+)?(?:at\s+most|at\s+least|exactly|no\s+more\s+than|up\s+to)|only\s+.+?\s+(?:may|can)|must\s+not|shall\s+not|cannot|can't|denied|forbidden|prohibited|(?:is|are|be|become|becomes|remain|remains)\s+(?:invalid|rejected|prohibited|forbidden)|(?:reject|rejects|rejected|rejection)\s+(?:invalid|unresolved|ambiguous)|fail(?:s|ed)?\s+(?:clearly|explicitly|with)|expires?\s+(?:after|within|in)|failure\s+(?:behavior|policy|outcome)|error\s+(?:handling|behavior|policy|outcome)|required\s+outcome|defaults?\s+to)\b/i;
|
|
3
9
|
// Conditional/temporal cues help discover clauses but do not by themselves
|
|
4
10
|
// turn explanatory or subjective context into an asserted obligation.
|
|
5
11
|
const NORMATIVE_PATTERN = new RegExp(`${NORMATIVE_ASSERTION_PATTERN.source}|\\b(?:before|unless|when|if)\\b`, "i");
|
|
@@ -19,6 +19,13 @@ export declare function statementOf(payload: Payload): string;
|
|
|
19
19
|
export declare function sourceOf(payload: Payload): string;
|
|
20
20
|
export declare function normalizeKey(value: string): string;
|
|
21
21
|
export declare function normalizePredicateToken(value: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Singularize one lowercase key token: `-ches`/`-shes`/`-sses`/`-xes` drop
|
|
24
|
+
* "es", `-ies` becomes "y", and any other trailing "s" is dropped unless the
|
|
25
|
+
* token ends in "ss", "us" or "is" ("access", "status", "analysis"). Tokens of
|
|
26
|
+
* three letters or fewer and the `keep` exceptions are returned unchanged.
|
|
27
|
+
*/
|
|
28
|
+
export declare function singularizeToken(value: string, keep?: readonly string[]): string;
|
|
22
29
|
export declare function singularize(value: string): string;
|
|
23
30
|
export declare function normalizeSubjectKey(value: string): string;
|
|
24
31
|
export declare function relationship(from: string, to: string, type: string): Record<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/shared.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,0BAA0B,EAE1B,2BAA2B,EAC5B,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACxD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AACvE,eAAO,MAAM,0BAA0B,+BAA+B,CAAC;AACvE,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG,UAAU,GAAG,OAAO,CAAC;AAGzE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAElD;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CASnD;AAGD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAKpD;AAGD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG;IAClD,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAmBA;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,GACf,SAAS,MAAM,EAAE,GAAG,SAAS,CAO/B;AAGD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAGD,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEtE;AAGD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEpD;AAGD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAIjD;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOlD;AAGD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ7D;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/shared.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,0BAA0B,EAE1B,2BAA2B,EAC5B,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACxD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AACvE,eAAO,MAAM,0BAA0B,+BAA+B,CAAC;AACvE,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG,UAAU,GAAG,OAAO,CAAC;AAGzE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAElD;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CASnD;AAGD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAKpD;AAGD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG;IAClD,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAmBA;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,GACf,SAAS,MAAM,EAAE,GAAG,SAAS,CAO/B;AAGD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAGD,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEtE;AAGD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEpD;AAGD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAIjD;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOlD;AAGD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ7D;AAID;;;;;GAKG;AAEH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,SAAS,MAAM,EAAO,GAC3B,MAAM,CAUR;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAGD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB;AAGD,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,2BAA2B,EAClC,SAAS,EAAE,MAAM,EACjB,UAAU,SAAM,GACf,0BAA0B,CA0F5B;AAGD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,QAAQ,GAAG,MAAiB,GACrC,0BAA0B,CA+C5B"}
|
|
@@ -90,11 +90,30 @@ export function normalizePredicateToken(value) {
|
|
|
90
90
|
.replace(/[^A-Za-z0-9_-]+/g, "_")
|
|
91
91
|
.replace(/^_+|_+$/g, "");
|
|
92
92
|
}
|
|
93
|
+
const ES_PLURAL_SUFFIXES = ["ches", "shes", "sses", "xes"];
|
|
94
|
+
/**
|
|
95
|
+
* Singularize one lowercase key token: `-ches`/`-shes`/`-sses`/`-xes` drop
|
|
96
|
+
* "es", `-ies` becomes "y", and any other trailing "s" is dropped unless the
|
|
97
|
+
* token ends in "ss", "us" or "is" ("access", "status", "analysis"). Tokens of
|
|
98
|
+
* three letters or fewer and the `keep` exceptions are returned unchanged.
|
|
99
|
+
*/
|
|
93
100
|
// implements REQ-mcp-semantic-advisor-preflight
|
|
94
|
-
export function
|
|
95
|
-
if (
|
|
101
|
+
export function singularizeToken(value, keep = []) {
|
|
102
|
+
if (value.length <= 3 || keep.includes(value))
|
|
103
|
+
return value;
|
|
104
|
+
if (value.endsWith("ies") && value.length > 4) {
|
|
105
|
+
return `${value.slice(0, -3)}y`;
|
|
106
|
+
}
|
|
107
|
+
if (ES_PLURAL_SUFFIXES.some((suffix) => value.endsWith(suffix))) {
|
|
108
|
+
return value.slice(0, -2);
|
|
109
|
+
}
|
|
110
|
+
if (!value.endsWith("s") || /(?:ss|us|is)$/.test(value))
|
|
96
111
|
return value;
|
|
97
|
-
return value.
|
|
112
|
+
return value.slice(0, -1);
|
|
113
|
+
}
|
|
114
|
+
// implements REQ-mcp-semantic-advisor-preflight
|
|
115
|
+
export function singularize(value) {
|
|
116
|
+
return singularizeToken(value, ["status", "results"]);
|
|
98
117
|
}
|
|
99
118
|
// implements REQ-mcp-semantic-advisor-preflight
|
|
100
119
|
export function normalizeSubjectKey(value) {
|
|
@@ -21,6 +21,28 @@ export declare function readStoreLockOwner(storePath: string): {
|
|
|
21
21
|
* lives at the branch-store root (older builds kept it beside the lock).
|
|
22
22
|
*/
|
|
23
23
|
export declare function breakStoreLock(rdfDirectory: string): void;
|
|
24
|
+
/** Store-root record of the last stale-lock takeover (see below). */
|
|
25
|
+
export declare const STORE_LOCK_TAKEOVER_FILE = ".kibi-lock-takeover.json";
|
|
26
|
+
/**
|
|
27
|
+
* How long a takeover stays visible in kb_status and kibi doctor. A takeover
|
|
28
|
+
* happens inside a detached engine whose output nobody reads, so the record
|
|
29
|
+
* outlives that engine (which may idle out within minutes) long enough to be
|
|
30
|
+
* seen on the next working session; the next takeover replaces it.
|
|
31
|
+
*/
|
|
32
|
+
export declare const STORE_LOCK_TAKEOVER_VISIBLE_MS: number;
|
|
33
|
+
export type StoreLockTakeoverRecord = Readonly<{
|
|
34
|
+
brokenPid: number | null;
|
|
35
|
+
reason: string;
|
|
36
|
+
at: string;
|
|
37
|
+
path: string;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Record that a stale branch-store lock is about to be broken. Best effort:
|
|
41
|
+
* the record is diagnostic and must never block the takeover itself.
|
|
42
|
+
*/
|
|
43
|
+
export declare function recordStoreLockTakeover(storePath: string, brokenPid: number | null, reason: string, at?: Date): void;
|
|
44
|
+
/** The last takeover record of a branch store, or null when none is readable. */
|
|
45
|
+
export declare function readStoreLockTakeover(storePath: string): StoreLockTakeoverRecord | null;
|
|
24
46
|
export interface StoreLockTakeoverDecision {
|
|
25
47
|
readonly action: "break" | "surface";
|
|
26
48
|
readonly reason: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-lock.d.ts","sourceRoot":"","sources":["../../src/prolog/store-lock.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAqB,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAgBhF,8EAA8E;AAC9E,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAa7C;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUnD;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAEzE,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,oBAAoB,GAAG,IAAI,GACjC,oBAAoB,CAYtB;AAED;;;;;GAKG;AAEH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,oBAAoB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA4B7D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAWzD;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,oBAAoB,GAAG,IAAI,GACjC,yBAAyB,CAoB3B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACxD;AAED;;;;;;GAMG;AAEH,wBAAsB,iCAAiC,CACrD,MAAM,EAAE,qBAAqB,EAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"store-lock.d.ts","sourceRoot":"","sources":["../../src/prolog/store-lock.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAqB,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAgBhF,8EAA8E;AAC9E,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAa7C;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUnD;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAEzE,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,oBAAoB,GAAG,IAAI,GACjC,oBAAoB,CAYtB;AAED;;;;;GAKG;AAEH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,oBAAoB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA4B7D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAWzD;AAED,qEAAqE;AACrE,eAAO,MAAM,wBAAwB,6BAA6B,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,QAAsB,CAAC;AAElE,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH;;;GAGG;AAEH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,EAAE,GAAE,IAAiB,GACpB,IAAI,CAUN;AAED,iFAAiF;AAEjF,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,GAChB,uBAAuB,GAAG,IAAI,CAmBhC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,oBAAoB,GAAG,IAAI,GACjC,yBAAyB,CAoB3B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACxD;AAED;;;;;;GAMG;AAEH,wBAAsB,iCAAiC,CACrD,MAAM,EAAE,qBAAqB,EAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,WAAW,CAAC,CAiCtB"}
|
|
@@ -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 { existsSync, rmSync } from "node:fs";
|
|
18
|
+
import { existsSync, rmSync, writeFileSync } from "node:fs";
|
|
19
19
|
import { readFileSync } from "node:fs";
|
|
20
20
|
import { dirname, join } from "node:path";
|
|
21
21
|
import { escapeAtom } from "./codec.js";
|
|
@@ -133,6 +133,49 @@ export function breakStoreLock(rdfDirectory) {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
|
+
/** Store-root record of the last stale-lock takeover (see below). */
|
|
137
|
+
export const STORE_LOCK_TAKEOVER_FILE = ".kibi-lock-takeover.json";
|
|
138
|
+
/**
|
|
139
|
+
* How long a takeover stays visible in kb_status and kibi doctor. A takeover
|
|
140
|
+
* happens inside a detached engine whose output nobody reads, so the record
|
|
141
|
+
* outlives that engine (which may idle out within minutes) long enough to be
|
|
142
|
+
* seen on the next working session; the next takeover replaces it.
|
|
143
|
+
*/
|
|
144
|
+
export const STORE_LOCK_TAKEOVER_VISIBLE_MS = 24 * 60 * 60 * 1000;
|
|
145
|
+
/**
|
|
146
|
+
* Record that a stale branch-store lock is about to be broken. Best effort:
|
|
147
|
+
* the record is diagnostic and must never block the takeover itself.
|
|
148
|
+
*/
|
|
149
|
+
// implements REQ-core-journaled-engine-persistence
|
|
150
|
+
export function recordStoreLockTakeover(storePath, brokenPid, reason, at = new Date()) {
|
|
151
|
+
try {
|
|
152
|
+
writeFileSync(join(storePath, STORE_LOCK_TAKEOVER_FILE), `${JSON.stringify({ brokenPid, reason, at: at.toISOString() })}\n`, { mode: 0o600 });
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// A read-only or vanished store still gets its lock broken.
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** The last takeover record of a branch store, or null when none is readable. */
|
|
159
|
+
// implements REQ-core-journaled-engine-persistence
|
|
160
|
+
export function readStoreLockTakeover(storePath) {
|
|
161
|
+
const recordPath = join(storePath, STORE_LOCK_TAKEOVER_FILE);
|
|
162
|
+
if (!existsSync(recordPath))
|
|
163
|
+
return null;
|
|
164
|
+
try {
|
|
165
|
+
const parsed = JSON.parse(readFileSync(recordPath, "utf8"));
|
|
166
|
+
if (typeof parsed.at !== "string" || Number.isNaN(Date.parse(parsed.at)))
|
|
167
|
+
return null;
|
|
168
|
+
return {
|
|
169
|
+
brokenPid: typeof parsed.brokenPid === "number" ? parsed.brokenPid : null,
|
|
170
|
+
reason: typeof parsed.reason === "string" ? parsed.reason : "",
|
|
171
|
+
at: parsed.at,
|
|
172
|
+
path: recordPath,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
136
179
|
/**
|
|
137
180
|
* Decide whether a store-locked failure may be auto-healed. Only a provably
|
|
138
181
|
* dead holder (or a holder from a previous boot) is broken; live or unknown
|
|
@@ -186,6 +229,7 @@ Store lock holder: ${holderSummary}. Close that session, or run 'kibi engine sto
|
|
|
186
229
|
const lockDirectory = storeLocked.lockDirectory !== ""
|
|
187
230
|
? storeLocked.lockDirectory
|
|
188
231
|
: join(kbPath, "rdf");
|
|
232
|
+
recordStoreLockTakeover(kbPath, storeLocked.owner?.pid ?? null, decision.reason);
|
|
189
233
|
breakStoreLock(lockDirectory);
|
|
190
234
|
const retried = await prolog.query(`kb_attach('${escapeAtom(kbPath)}')`);
|
|
191
235
|
if (retried.success) {
|
package/dist/prolog.d.ts
CHANGED
|
@@ -122,6 +122,12 @@ export declare class PrologProcess {
|
|
|
122
122
|
isRunning(): boolean;
|
|
123
123
|
getPid(): number;
|
|
124
124
|
private lostProcessError;
|
|
125
|
-
|
|
125
|
+
/**
|
|
126
|
+
* Stop the Prolog child. `graceMs` lets the interactive toplevel halt on
|
|
127
|
+
* stdin EOF (running its at_halt hooks) before it is signalled.
|
|
128
|
+
*/
|
|
129
|
+
terminate(options?: {
|
|
130
|
+
graceMs?: number;
|
|
131
|
+
}): Promise<void>;
|
|
126
132
|
}
|
|
127
133
|
//# sourceMappingURL=prolog.d.ts.map
|
package/dist/prolog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prolog.d.ts","sourceRoot":"","sources":["../src/prolog.ts"],"names":[],"mappings":"AA2BA,OAAO,EACL,KAAK,iBAAiB,EAEvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,aAAa,EAGnB,MAAM,4BAA4B,CAAC;AAUpC,wBAAgB,eAAe,IAAI,MAAM,CAsCxC;AACD,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,aAAa,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,IAAI,+BAA+B;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM;CAO3B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC;AAGD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,EAC5B,OAAO,EAAE,MAAM,IAAI,EACnB,EAAE,GAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAChB,GAC5B,MAAM,IAAI,CAIZ;AAGD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,EAC5B,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EACrC,EAAE,GAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAChB,GAC5B,MAAM,IAAI,CAQZ;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,oBAAoB,CAAoC;IAChE,OAAO,CAAC,kBAAkB,CAA8B;IACxD,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC;;;;OAIG;IACH,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,6EAA6E;IAC7E,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,mBAAmB,CAAS;gBAExB,OAAO,GAAE,aAAkB;IAiBvC,wBAAwB,CACtB,EAAE,GAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAChB,GAC5B,IAAI;IAQP;;;OAGG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;;OAGG;IACH,YAAY,IAAI,OAAO;IAIvB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAOd,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAqEd,YAAY;IAgDpB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IA6Q1D,wEAAwE;IAClE,UAAU,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAIhE,eAAe,IAAI,IAAI;IAIvB,OAAO,CAAC,eAAe;IA2BvB,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,kBAAkB;YAIZ,YAAY;IA2C1B,OAAO,CAAC,WAAW;IAiOnB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,gBAAgB;IAcxB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,iBAAiB;YAkBX,oBAAoB;
|
|
1
|
+
{"version":3,"file":"prolog.d.ts","sourceRoot":"","sources":["../src/prolog.ts"],"names":[],"mappings":"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"}
|
package/dist/prolog.js
CHANGED
|
@@ -826,7 +826,7 @@ export class PrologProcess {
|
|
|
826
826
|
// The child may have exited between the group and direct kill attempts.
|
|
827
827
|
}
|
|
828
828
|
}
|
|
829
|
-
async terminateProcessTree(child) {
|
|
829
|
+
async terminateProcessTree(child, graceMs = 0) {
|
|
830
830
|
let closed = false;
|
|
831
831
|
const exited = new Promise((resolve) => {
|
|
832
832
|
const markExited = () => {
|
|
@@ -836,6 +836,20 @@ export class PrologProcess {
|
|
|
836
836
|
child.once("close", markExited);
|
|
837
837
|
child.once("error", markExited);
|
|
838
838
|
});
|
|
839
|
+
if (graceMs > 0 && child.exitCode === null && child.signalCode === null) {
|
|
840
|
+
// implements REQ-core-journaled-engine-persistence
|
|
841
|
+
let graceTimer;
|
|
842
|
+
await Promise.race([
|
|
843
|
+
exited,
|
|
844
|
+
new Promise((resolve) => {
|
|
845
|
+
graceTimer = setTimeout(resolve, graceMs);
|
|
846
|
+
}),
|
|
847
|
+
]);
|
|
848
|
+
if (graceTimer)
|
|
849
|
+
clearTimeout(graceTimer);
|
|
850
|
+
if (closed)
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
839
853
|
if (child.exitCode === null)
|
|
840
854
|
this.signalProcessTree(child, "SIGTERM");
|
|
841
855
|
await Promise.race([
|
|
@@ -992,7 +1006,11 @@ export class PrologProcess {
|
|
|
992
1006
|
}
|
|
993
1007
|
return new PrologProcessTerminatedError(this.terminationReason ?? "process exited");
|
|
994
1008
|
}
|
|
995
|
-
|
|
1009
|
+
/**
|
|
1010
|
+
* Stop the Prolog child. `graceMs` lets the interactive toplevel halt on
|
|
1011
|
+
* stdin EOF (running its at_halt hooks) before it is signalled.
|
|
1012
|
+
*/
|
|
1013
|
+
async terminate(options = {}) {
|
|
996
1014
|
if (this.interactiveStarted) {
|
|
997
1015
|
this.terminationReason ??= "terminated";
|
|
998
1016
|
}
|
|
@@ -1012,7 +1030,7 @@ export class PrologProcess {
|
|
|
1012
1030
|
this.terminationPromise = (async () => {
|
|
1013
1031
|
if (current) {
|
|
1014
1032
|
current.stdin?.end();
|
|
1015
|
-
await this.terminateProcessTree(current);
|
|
1033
|
+
await this.terminateProcessTree(current, options.graceMs ?? 0);
|
|
1016
1034
|
}
|
|
1017
1035
|
await Promise.all(oneShots.map((child) => this.terminateProcessTree(child)));
|
|
1018
1036
|
})();
|
package/dist/proof/inspect.d.ts
CHANGED
|
@@ -5,7 +5,14 @@ export type ProofInspection = Readonly<{
|
|
|
5
5
|
buildSystems: readonly string[];
|
|
6
6
|
detectedRunners: readonly string[];
|
|
7
7
|
ciWorkflows: readonly string[];
|
|
8
|
+
/** Comma-joined ids of the configured integrations (kept for compatibility). */
|
|
8
9
|
currentIntegration: string | null;
|
|
10
|
+
/** Each configured integration with the producer and command it runs. */
|
|
11
|
+
currentIntegrations: readonly Readonly<{
|
|
12
|
+
id: string;
|
|
13
|
+
producer: string;
|
|
14
|
+
command: readonly string[];
|
|
15
|
+
}>[];
|
|
9
16
|
recommendation: string;
|
|
10
17
|
missing: readonly string[];
|
|
11
18
|
/** The integration Kibi proposes for the detected runner, if any. */
|
|
@@ -23,6 +30,8 @@ export type ProofInspection = Readonly<{
|
|
|
23
30
|
export type ProofInspectionOptions = Readonly<{
|
|
24
31
|
/** Plan a replacement of this existing integration id. */
|
|
25
32
|
update?: string;
|
|
33
|
+
/** Command (argv) the proposed integration runs instead of the detected one. */
|
|
34
|
+
command?: readonly string[];
|
|
26
35
|
}>;
|
|
27
36
|
export declare function directoryEntriesMatch(directory: string, regex: RegExp): boolean;
|
|
28
37
|
export declare function inspectProofEnvironment(root: string, options?: ProofInspectionOptions): ProofInspection;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/proof/inspect.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,uBAAuB,CAAC;AAM/B,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,qEAAqE;IACrE,mBAAmB,EAAE,mBAAmB,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAC/D,6EAA6E;IAC7E,gBAAgB,EAAE,mBAAmB,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IACjE;;;OAGG;IACH,eAAe,EAAE,aAAa,GAAG,IAAI,CAAC;IACtC,sDAAsD;IACtD,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/proof/inspect.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,uBAAuB,CAAC;AAM/B,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,gFAAgF;IAChF,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,yEAAyE;IACzE,mBAAmB,EAAE,SAAS,QAAQ,CAAC;QACrC,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;KAC5B,CAAC,EAAE,CAAC;IACL,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,qEAAqE;IACrE,mBAAmB,EAAE,mBAAmB,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAC/D,6EAA6E;IAC7E,gBAAgB,EAAE,mBAAmB,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IACjE;;;OAGG;IACH,eAAe,EAAE,aAAa,GAAG,IAAI,CAAC;IACtC,sDAAsD;IACtD,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,CAAC,CAAC;AAwIH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAMT;AA2BD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,sBAA2B,GACnC,eAAe,CA0GjB"}
|
package/dist/proof/inspect.js
CHANGED
|
@@ -208,6 +208,15 @@ export function inspectProofEnvironment(root, options = {}) {
|
|
|
208
208
|
const currentIntegration = integrations.available
|
|
209
209
|
? integrations.integrations.integrations.map((entry) => entry.id).join(", ")
|
|
210
210
|
: null;
|
|
211
|
+
// implements REQ-kibi-verification-evidence-contract
|
|
212
|
+
// The id alone does not say what `kibi prove` will run; expose the command.
|
|
213
|
+
const currentIntegrations = integrations.available
|
|
214
|
+
? integrations.integrations.integrations.map((entry) => ({
|
|
215
|
+
id: entry.id,
|
|
216
|
+
producer: entry.producer,
|
|
217
|
+
command: [...entry.command],
|
|
218
|
+
}))
|
|
219
|
+
: [];
|
|
211
220
|
const planned = buildProofIntegrationPlan(root, options);
|
|
212
221
|
const applyHint = "review integrationPlan, then apply it with kb_apply_plan (or `kibi apply-plan --input -`) passing plan, approvedPlanHash = plan.planHash and approvedActionIds";
|
|
213
222
|
let recommendation;
|
|
@@ -235,6 +244,7 @@ export function inspectProofEnvironment(root, options = {}) {
|
|
|
235
244
|
detectedRunners: runners,
|
|
236
245
|
ciWorkflows,
|
|
237
246
|
currentIntegration,
|
|
247
|
+
currentIntegrations,
|
|
238
248
|
recommendation,
|
|
239
249
|
missing,
|
|
240
250
|
proposedIntegration: planned.proposal?.integration ?? null,
|
|
@@ -33,7 +33,7 @@ export type ProofIntegrationPlanResult = Readonly<{
|
|
|
33
33
|
* (aggregate-run provenance), so it works for every runner without a
|
|
34
34
|
* reporter; a native producer can replace it later through an update plan.
|
|
35
35
|
*/
|
|
36
|
-
export declare function proposeProofIntegration(root: string, overrideId?: string): ProposedIntegration | null;
|
|
36
|
+
export declare function proposeProofIntegration(root: string, overrideId?: string, overrideCommand?: readonly string[]): ProposedIntegration | null;
|
|
37
37
|
/**
|
|
38
38
|
* Build the hash-bound `kibi.migration-plan.v2` that writes
|
|
39
39
|
* `.kb/proof/integrations.json` through Kibi. Without `update`, a plan is
|
|
@@ -44,6 +44,7 @@ export declare function proposeProofIntegration(root: string, overrideId?: strin
|
|
|
44
44
|
*/
|
|
45
45
|
export declare function buildProofIntegrationPlan(root: string, options?: Readonly<{
|
|
46
46
|
update?: string;
|
|
47
|
+
command?: readonly string[];
|
|
47
48
|
}>): ProofIntegrationPlanResult;
|
|
48
49
|
/**
|
|
49
50
|
* Apply one reviewed `proof_integration_configure` action: write
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration-plan.d.ts","sourceRoot":"","sources":["../../src/proof/integration-plan.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"integration-plan.d.ts","sourceRoot":"","sources":["../../src/proof/integration-plan.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,aAAa,EAGnB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,KAAK,gBAAgB,EAGtB,MAAM,mBAAmB,CAAC;AAE3B,mEAAmE;AACnE,eAAO,MAAM,2BAA2B,gCAAgC,CAAC;AAqCzE,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,WAAW,EAAE,gBAAgB,CAAC;IAC9B,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,gBAAgB,EAAE,QAAQ,CAAC;QACzB,OAAO,EAAE,OAAO,sBAAsB,CAAC;QACvC,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,aAAa,CAAC;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACtE,cAAc,EAAE,4BAA4B,CAAC;KAC9C,CAAC,CAAC;CACJ,CAAC,CAAC;AAEH,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,0EAA0E;IAC1E,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAoHH;;;;;;;GAOG;AAEH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAClC,mBAAmB,GAAG,IAAI,CAoC5B;AAsCD;;;;;;;GAOG;AAEH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,QAAQ,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAM,GACvE,0BAA0B,CAiE5B;AAMD;;;;;;;GAOG;AAEH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,MAAM,GACX,IAAI,CAyDN"}
|