kibi-cli 2.4.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-json-command.d.ts +6 -0
- package/dist/cli-json-command.d.ts.map +1 -1
- package/dist/cli-json-command.js +37 -9
- package/dist/cli-operation-loader.d.ts.map +1 -1
- package/dist/cli-operation-loader.js +7 -0
- package/dist/cli-operation-metadata.d.ts +12 -4
- package/dist/cli-operation-metadata.d.ts.map +1 -1
- package/dist/cli-operation-metadata.js +14 -4
- package/dist/cli-protocol.d.ts +14 -0
- package/dist/cli-protocol.d.ts.map +1 -1
- package/dist/cli-protocol.js +31 -2
- package/dist/cli-register-proof.d.ts.map +1 -1
- package/dist/cli-register-proof.js +13 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +11 -2
- package/dist/commands/discovery-shared.d.ts.map +1 -1
- package/dist/commands/discovery-shared.js +8 -2
- package/dist/commands/engine.d.ts.map +1 -1
- package/dist/commands/engine.js +4 -2
- package/dist/commands/gc.d.ts.map +1 -1
- package/dist/commands/gc.js +7 -0
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +38 -12
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +10 -15
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +281 -14
- package/dist/commands/proof-compact.d.ts +9 -0
- package/dist/commands/proof-compact.d.ts.map +1 -0
- package/dist/commands/proof-compact.js +58 -0
- package/dist/commands/prove.d.ts +38 -0
- package/dist/commands/prove.d.ts.map +1 -1
- package/dist/commands/prove.js +222 -47
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +61 -16
- package/dist/commands/sync.d.ts +8 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +42 -16
- package/dist/diagnostics.js +1 -1
- package/dist/engine-limits.d.ts +74 -0
- package/dist/engine-limits.d.ts.map +1 -0
- package/dist/engine-limits.js +201 -0
- package/dist/engine.d.ts +10 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +57 -9
- package/dist/extractors/manifest.d.ts +8 -0
- package/dist/extractors/manifest.d.ts.map +1 -1
- package/dist/extractors/manifest.js +34 -5
- package/dist/extractors/markdown.d.ts +8 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +57 -0
- package/dist/extractors/relationships.d.ts.map +1 -1
- package/dist/extractors/relationships.js +2 -0
- package/dist/intent-search.d.ts +4 -1
- package/dist/intent-search.d.ts.map +1 -1
- package/dist/intent-search.js +186 -33
- package/dist/operations/bootstrap/candidate-helpers.d.ts.map +1 -1
- package/dist/operations/bootstrap/candidate-helpers.js +8 -1
- package/dist/operations/bootstrap/candidates.d.ts.map +1 -1
- package/dist/operations/bootstrap/candidates.js +54 -38
- package/dist/operations/bootstrap/generate.d.ts +2 -0
- package/dist/operations/bootstrap/generate.d.ts.map +1 -1
- package/dist/operations/bootstrap/generate.js +87 -33
- package/dist/operations/bootstrap/intent-claims.d.ts.map +1 -1
- package/dist/operations/bootstrap/intent-claims.js +12 -4
- package/dist/operations/bootstrap/markdown-candidates.d.ts +2 -0
- package/dist/operations/bootstrap/markdown-candidates.d.ts.map +1 -1
- package/dist/operations/bootstrap/markdown-candidates.js +32 -10
- package/dist/operations/bootstrap/presentation.d.ts.map +1 -1
- package/dist/operations/bootstrap/presentation.js +6 -2
- package/dist/operations/bootstrap/requirement-claims.d.ts +1 -0
- package/dist/operations/bootstrap/requirement-claims.d.ts.map +1 -1
- package/dist/operations/bootstrap/requirement-claims.js +13 -1
- package/dist/operations/bootstrap/validation.d.ts +4 -0
- package/dist/operations/bootstrap/validation.d.ts.map +1 -0
- package/dist/operations/bootstrap/validation.js +20 -0
- package/dist/operations/migration/inventory-rederive.d.ts +81 -0
- package/dist/operations/migration/inventory-rederive.d.ts.map +1 -0
- package/dist/operations/migration/inventory-rederive.js +484 -0
- package/dist/operations/migration/kb-sources.d.ts +53 -0
- package/dist/operations/migration/kb-sources.d.ts.map +1 -0
- package/dist/operations/migration/kb-sources.js +233 -0
- package/dist/operations/migration/origin-backfill.d.ts +39 -0
- package/dist/operations/migration/origin-backfill.d.ts.map +1 -0
- package/dist/operations/migration/origin-backfill.js +164 -0
- package/dist/operations/migration/polarity-values.d.ts +10 -0
- package/dist/operations/migration/polarity-values.d.ts.map +1 -0
- package/dist/operations/migration/polarity-values.js +60 -0
- package/dist/operations/migration/schema6.d.ts +59 -0
- package/dist/operations/migration/schema6.d.ts.map +1 -0
- package/dist/operations/migration/schema6.js +379 -0
- package/dist/operations/migration/source-paths.d.ts +131 -0
- package/dist/operations/migration/source-paths.d.ts.map +1 -0
- package/dist/operations/migration/source-paths.js +308 -0
- package/dist/operations/migration/superseded-closure.d.ts +54 -0
- package/dist/operations/migration/superseded-closure.d.ts.map +1 -0
- package/dist/operations/migration/superseded-closure.js +187 -0
- package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
- package/dist/operations/modeling/logic-modeling.js +3 -5
- package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
- package/dist/operations/modeling/model-requirement.js +225 -67
- package/dist/operations/mutation/contradictions.d.ts +16 -0
- package/dist/operations/mutation/contradictions.d.ts.map +1 -1
- package/dist/operations/mutation/contradictions.js +32 -0
- package/dist/operations/mutation/delete.d.ts.map +1 -1
- package/dist/operations/mutation/delete.js +15 -7
- package/dist/operations/mutation/origin.d.ts +21 -0
- package/dist/operations/mutation/origin.d.ts.map +1 -0
- package/dist/operations/mutation/origin.js +78 -0
- package/dist/operations/mutation/plan-apply-journal.d.ts +182 -0
- package/dist/operations/mutation/plan-apply-journal.d.ts.map +1 -0
- package/dist/operations/mutation/plan-apply-journal.js +613 -0
- package/dist/operations/mutation/predicate-vocabulary-guard.d.ts +3 -1
- package/dist/operations/mutation/predicate-vocabulary-guard.d.ts.map +1 -1
- package/dist/operations/mutation/predicate-vocabulary-guard.js +13 -2
- package/dist/operations/mutation/relationships.d.ts +5 -5
- package/dist/operations/mutation/relationships.d.ts.map +1 -1
- package/dist/operations/mutation/relationships.js +31 -11
- package/dist/operations/mutation/serialization.d.ts.map +1 -1
- package/dist/operations/mutation/serialization.js +3 -1
- 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 +7 -1
- package/dist/operations/mutation/types.d.ts +14 -0
- package/dist/operations/mutation/types.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.d.ts +30 -3
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +105 -35
- package/dist/operations/mutation/validate-upsert.d.ts +6 -0
- package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
- package/dist/operations/mutation/validate-upsert.js +34 -30
- package/dist/operations/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +753 -145
- package/dist/operations/planning/compile-intent.d.ts +34 -1
- package/dist/operations/planning/compile-intent.d.ts.map +1 -1
- package/dist/operations/planning/compile-intent.js +314 -98
- package/dist/operations/proof/code-scope.d.ts +28 -0
- package/dist/operations/proof/code-scope.d.ts.map +1 -1
- package/dist/operations/proof/code-scope.js +72 -0
- package/dist/operations/proof/compact-receipts.d.ts +49 -0
- package/dist/operations/proof/compact-receipts.d.ts.map +1 -0
- package/dist/operations/proof/compact-receipts.js +160 -0
- package/dist/operations/proof/ingest-proof.d.ts +2 -0
- package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
- package/dist/operations/proof/ingest-proof.js +44 -23
- package/dist/operations/proof/prune-receipts.d.ts.map +1 -1
- package/dist/operations/proof/prune-receipts.js +5 -9
- package/dist/operations/proof/receipt-compaction.d.ts +48 -0
- package/dist/operations/proof/receipt-compaction.d.ts.map +1 -0
- package/dist/operations/proof/receipt-compaction.js +121 -0
- package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analysis-receipt.js +12 -1
- package/dist/operations/semantic-advisor/analyze-prose.d.ts +2 -1
- package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.js +51 -5
- package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
- package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/clauses.js +11 -1
- package/dist/operations/semantic-advisor/conditional-rules.d.ts +33 -0
- package/dist/operations/semantic-advisor/conditional-rules.d.ts.map +1 -0
- package/dist/operations/semantic-advisor/conditional-rules.js +262 -0
- package/dist/operations/semantic-advisor/ingestion-boundary.d.ts +3 -1
- package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/ingestion-boundary.js +14 -6
- package/dist/operations/semantic-advisor/plugin-orchestration.js +1 -1
- package/dist/prolog/codec.d.ts.map +1 -1
- package/dist/prolog/codec.js +2 -1
- package/dist/prolog.d.ts +9 -0
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +56 -10
- package/dist/proof/command-test-report.d.ts +74 -0
- package/dist/proof/command-test-report.d.ts.map +1 -0
- package/dist/proof/command-test-report.js +206 -0
- package/dist/public/branch-resolver.d.ts +1 -0
- package/dist/public/branch-resolver.d.ts.map +1 -1
- package/dist/public/branch-resolver.js +1 -0
- package/dist/public/entity-origin.d.ts +69 -0
- package/dist/public/entity-origin.d.ts.map +1 -0
- package/dist/public/entity-origin.js +142 -0
- package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
- package/dist/public/impact/full-kb-quality.js +1 -0
- package/dist/public/impact/requirement-quality.js +1 -1
- package/dist/public/operations/catalog.d.ts +130 -19
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/catalog.js +3 -0
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +8 -0
- package/dist/public/operations/contracts.d.ts +0 -5
- package/dist/public/operations/contracts.d.ts.map +1 -1
- package/dist/public/operations/contracts.js +63 -14
- package/dist/public/operations/discovery-entities.d.ts +15 -0
- package/dist/public/operations/discovery-entities.d.ts.map +1 -1
- package/dist/public/operations/discovery-entities.js +59 -0
- package/dist/public/operations/discovery-executors.d.ts +6 -1
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +65 -6
- package/dist/public/operations/index.d.ts +1 -0
- package/dist/public/operations/index.d.ts.map +1 -1
- package/dist/public/operations/index.js +1 -0
- package/dist/public/operations/migration-plan.d.ts +5 -0
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +26 -1
- package/dist/public/operations/node-ports.d.ts.map +1 -1
- package/dist/public/operations/node-ports.js +24 -3
- package/dist/public/operations/origin-review.d.ts +51 -0
- package/dist/public/operations/origin-review.d.ts.map +1 -0
- package/dist/public/operations/origin-review.js +307 -0
- package/dist/public/operations/predicate-schema-conformance.js +1 -1
- package/dist/public/operations/repair-plan.d.ts.map +1 -1
- package/dist/public/operations/repair-plan.js +4 -0
- package/dist/public/operations/result-envelope.d.ts.map +1 -1
- package/dist/public/operations/result-envelope.js +17 -5
- package/dist/public/operations/runtime-types.d.ts +9 -0
- package/dist/public/operations/runtime-types.d.ts.map +1 -1
- package/dist/public/operations/schema6-check-actions.d.ts +127 -0
- package/dist/public/operations/schema6-check-actions.d.ts.map +1 -0
- package/dist/public/operations/schema6-check-actions.js +575 -0
- package/dist/public/operations/source-path-dangling.d.ts +17 -0
- package/dist/public/operations/source-path-dangling.d.ts.map +1 -0
- package/dist/public/operations/source-path-dangling.js +66 -0
- 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 +15 -1
- package/dist/public/operations/specs/check.d.ts +2 -2
- package/dist/public/operations/specs/check.js +1 -1
- package/dist/public/operations/specs/composite.d.ts +351 -0
- package/dist/public/operations/specs/composite.d.ts.map +1 -0
- package/dist/public/operations/specs/composite.js +96 -0
- package/dist/public/operations/specs/discovery.d.ts +8 -3
- package/dist/public/operations/specs/discovery.d.ts.map +1 -1
- package/dist/public/operations/specs/discovery.js +8 -3
- package/dist/public/operations/specs/modeling.d.ts +2 -2
- package/dist/public/operations/specs/modeling.js +2 -2
- package/dist/public/operations/specs/mutation-schemas.d.ts +73 -8
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +43 -7
- package/dist/public/operations/specs/mutation.d.ts +1 -1
- package/dist/public/operations/specs/mutation.js +1 -1
- package/dist/public/operations/specs/planning.d.ts +2 -2
- package/dist/public/operations/specs/planning.js +4 -4
- package/dist/public/operations/specs/reporting.d.ts.map +1 -1
- package/dist/public/operations/specs/reporting.js +13 -26
- package/dist/public/operations/specs/upsert.d.ts +79 -9
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/specs/upsert.js +6 -1
- package/dist/public/operations/types.d.ts +1 -1
- package/dist/public/operations/types.d.ts.map +1 -1
- package/dist/public/proof-receipt.d.ts +1 -0
- package/dist/public/proof-receipt.d.ts.map +1 -1
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +52 -0
- package/dist/public/schemas/relationship.d.ts.map +1 -1
- package/dist/public/schemas/relationship.js +2 -0
- package/dist/public/skills/kibi-bootstrap/SKILL.md +35 -67
- package/dist/public/skills/kibi-bootstrap/resources/bootstrap.md +6 -0
- package/dist/public/skills/kibi-usage/SKILL.md +68 -18
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +5 -5
- package/dist/public/skills/kibi-usage/resources/kb-improvement.md +1 -1
- package/dist/public/skills/kibi-usage/resources/logic-ir.md +2 -2
- package/dist/public/skills/kibi-usage/resources/operation-access.md +25 -1
- package/dist/public/skills/kibi-usage/resources/ui-requirements.md +4 -4
- package/dist/public/skills/kibi-usage/resources/workflows.md +42 -25
- package/dist/public/telemetry-acceptance.d.ts +58 -2
- package/dist/public/telemetry-acceptance.d.ts.map +1 -1
- package/dist/public/telemetry-acceptance.js +136 -10
- package/dist/public/telemetry-remediation.d.ts.map +1 -1
- package/dist/public/telemetry-remediation.js +26 -10
- package/dist/relationships/shards.d.ts +13 -0
- package/dist/relationships/shards.d.ts.map +1 -1
- package/dist/relationships/shards.js +54 -28
- package/dist/runtime/cli-runtime.d.ts.map +1 -1
- package/dist/runtime/cli-runtime.js +44 -3
- package/dist/runtime/detached-snapshot.d.ts +38 -0
- package/dist/runtime/detached-snapshot.d.ts.map +1 -0
- package/dist/runtime/detached-snapshot.js +92 -0
- package/dist/schemas/entity.schema.json +122 -0
- package/dist/search-answer.d.ts +157 -0
- package/dist/search-answer.d.ts.map +1 -0
- package/dist/search-answer.js +846 -0
- package/dist/traceability/impact-knowledge.d.ts.map +1 -1
- package/dist/traceability/impact-knowledge.js +7 -0
- package/dist/traceability/symbol-extract.js +3 -3
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +12 -0
- package/dist/types/entities.d.ts +13 -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/branch-resolver.d.ts +37 -1
- package/dist/utils/branch-resolver.d.ts.map +1 -1
- package/dist/utils/branch-resolver.js +130 -3
- package/dist/utils/repo-relative-path.d.ts +18 -0
- package/dist/utils/repo-relative-path.d.ts.map +1 -0
- package/dist/utils/repo-relative-path.js +58 -0
- package/dist/utils/rule-registry.generated.d.ts +75 -3
- package/dist/utils/rule-registry.generated.d.ts.map +1 -1
- package/dist/utils/rule-registry.generated.js +89 -3
- package/dist/utils/schema-version.d.ts +1 -1
- package/dist/utils/schema-version.d.ts.map +1 -1
- package/dist/utils/schema-version.js +4 -3
- package/dist/utils/strict-modeling.d.ts +1 -1
- package/dist/utils/strict-modeling.d.ts.map +1 -1
- package/dist/utils/strict-modeling.js +23 -3
- package/package.json +3 -3
- package/schema/entities.pl +22 -0
- package/schema/relationships.pl +14 -0
- package/schema/validation.pl +45 -1
- package/src/public/branch-resolver.ts +1 -0
- package/src/public/entity-origin.ts +175 -0
- package/src/public/impact/full-kb-quality.ts +1 -0
- package/src/public/impact/requirement-quality.ts +1 -1
- package/src/public/operations/catalog.ts +3 -0
- package/src/public/operations/check-executor.ts +15 -0
- package/src/public/operations/contracts.ts +75 -15
- package/src/public/operations/discovery-entities.ts +74 -0
- package/src/public/operations/discovery-executors.ts +88 -10
- package/src/public/operations/index.ts +1 -0
- package/src/public/operations/migration-plan.ts +30 -1
- package/src/public/operations/node-ports.ts +24 -3
- package/src/public/operations/origin-review.ts +375 -0
- package/src/public/operations/predicate-schema-conformance.ts +1 -1
- package/src/public/operations/repair-plan.ts +4 -0
- package/src/public/operations/result-envelope.ts +18 -6
- package/src/public/operations/runtime-types.ts +9 -0
- package/src/public/operations/schema6-check-actions.ts +699 -0
- package/src/public/operations/source-path-dangling.ts +81 -0
- package/src/public/operations/specs/check-rules.generated.ts +15 -1
- package/src/public/operations/specs/check.ts +1 -1
- package/src/public/operations/specs/composite.ts +141 -0
- package/src/public/operations/specs/discovery.ts +9 -3
- package/src/public/operations/specs/modeling.ts +2 -2
- package/src/public/operations/specs/mutation-schemas.ts +49 -7
- package/src/public/operations/specs/mutation.ts +1 -1
- package/src/public/operations/specs/planning.ts +4 -4
- package/src/public/operations/specs/reporting.ts +13 -38
- package/src/public/operations/specs/upsert.ts +7 -1
- package/src/public/operations/types.ts +2 -0
- package/src/public/proof-receipt.ts +1 -0
- package/src/public/schemas/entity.ts +57 -0
- package/src/public/schemas/relationship.ts +2 -0
- package/src/public/skills/kibi-bootstrap/SKILL.md +35 -67
- package/src/public/skills/kibi-bootstrap/resources/bootstrap.md +6 -0
- package/src/public/skills/kibi-usage/SKILL.md +68 -18
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +5 -5
- package/src/public/skills/kibi-usage/resources/kb-improvement.md +1 -1
- package/src/public/skills/kibi-usage/resources/logic-ir.md +2 -2
- package/src/public/skills/kibi-usage/resources/operation-access.md +25 -1
- package/src/public/skills/kibi-usage/resources/ui-requirements.md +4 -4
- package/src/public/skills/kibi-usage/resources/workflows.md +42 -25
- package/src/public/telemetry-acceptance-types.d.ts +4 -1
- package/src/public/telemetry-acceptance.ts +204 -10
- package/src/public/telemetry-remediation.ts +39 -10
- package/src/schemas/entity.schema.json +122 -0
- package/src/schemas/relationship.schema.json +2 -0
package/dist/diagnostics.js
CHANGED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/** Envelope error code for a read stopped at its limit. */
|
|
2
|
+
export declare const QUERY_LIMIT_EXCEEDED_CODE = "QUERY_LIMIT_EXCEEDED";
|
|
3
|
+
/** Environment opt-in for read limits on every engine client. */
|
|
4
|
+
export declare const ENGINE_READ_TIME_LIMIT_ENV = "KIBI_ENGINE_READ_TIME_LIMIT_MS";
|
|
5
|
+
export declare const ENGINE_READ_INFERENCE_LIMIT_ENV = "KIBI_ENGINE_READ_INFERENCE_LIMIT";
|
|
6
|
+
/**
|
|
7
|
+
* Upper bound for a requested time limit. The daemon's SWI process kills a
|
|
8
|
+
* query at 120 s and recycles the session; a bounded read must end first.
|
|
9
|
+
*/
|
|
10
|
+
export declare const ENGINE_READ_TIME_LIMIT_CAP_MS = 115000;
|
|
11
|
+
export type EngineQueryLimits = Readonly<{
|
|
12
|
+
/** Wall-clock budget for the Prolog goal, in milliseconds. */
|
|
13
|
+
timeMs?: number;
|
|
14
|
+
/** Logical-inference budget for the Prolog goal. */
|
|
15
|
+
inferences?: number;
|
|
16
|
+
}>;
|
|
17
|
+
export type EngineLimitExceeded = Readonly<{
|
|
18
|
+
kind: "time" | "inferences";
|
|
19
|
+
limit: number;
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Validate limits received over the engine socket. Out-of-range values are
|
|
23
|
+
* dropped (the read runs unbounded, as before); a time limit is capped below
|
|
24
|
+
* the hard per-query timeout.
|
|
25
|
+
*/
|
|
26
|
+
export declare function normalizeQueryLimits(value: unknown): EngineQueryLimits | undefined;
|
|
27
|
+
/** Read limits configured through the environment, if any. */
|
|
28
|
+
export declare function queryLimitsFromEnv(env?: NodeJS.ProcessEnv): EngineQueryLimits | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Clauses the engine session defines at boot (and after a recycle) so a
|
|
31
|
+
* bounded read needs one call and one answer binding. Helper variables stay
|
|
32
|
+
* clause-local, so the toplevel prints only the goal's own bindings plus the
|
|
33
|
+
* outcome, whose compound value cannot be grouped with a goal's binding.
|
|
34
|
+
*
|
|
35
|
+
* A goal that swallows the limit exception itself (a catch-all inside a
|
|
36
|
+
* predicate) could otherwise return a partial answer or fail; measuring the
|
|
37
|
+
* elapsed time and inferences around the goal reports the limit regardless.
|
|
38
|
+
*/
|
|
39
|
+
export declare const BOUNDED_READ_HELPER_DEFINITION: string;
|
|
40
|
+
/**
|
|
41
|
+
* Wrap a read-only goal in its limits. The goal's own variables keep their
|
|
42
|
+
* names, so its answer bindings are unchanged; the outcome arrives in the
|
|
43
|
+
* KibiReadOutcome binding that settleBoundedRead strips. The surrounding
|
|
44
|
+
* parentheses keep PrologProcess from caching a bounded answer.
|
|
45
|
+
*/
|
|
46
|
+
export declare function boundedReadGoal(goal: string, limits: EngineQueryLimits): string;
|
|
47
|
+
type BoundedResult = {
|
|
48
|
+
readonly success: boolean;
|
|
49
|
+
readonly bindings: Readonly<Record<string, string>>;
|
|
50
|
+
readonly error?: string;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Turn a bounded read's answer back into the unbounded answer shape, or into
|
|
54
|
+
* an explicit limitExceeded failure when a limit stopped the goal.
|
|
55
|
+
*/
|
|
56
|
+
export declare function settleBoundedRead<T extends BoundedResult>(result: T, limits: EngineQueryLimits): T | (BoundedResult & {
|
|
57
|
+
readonly limitExceeded: EngineLimitExceeded;
|
|
58
|
+
});
|
|
59
|
+
/** A read the engine stopped at its limit; never an empty answer. */
|
|
60
|
+
export declare class EngineQueryLimitError extends Error {
|
|
61
|
+
readonly limitExceeded: EngineLimitExceeded;
|
|
62
|
+
readonly code = "QUERY_LIMIT_EXCEEDED";
|
|
63
|
+
readonly retryable = false;
|
|
64
|
+
constructor(limitExceeded: EngineLimitExceeded);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The limit that stopped a read, from the typed error or from the message an
|
|
68
|
+
* executor rewrapped it into; null for every other error.
|
|
69
|
+
*/
|
|
70
|
+
export declare function queryLimitExceededOf(error: unknown): EngineLimitExceeded | null;
|
|
71
|
+
/** Reject an engine answer that reports a limit hit. */
|
|
72
|
+
export declare function assertWithinQueryLimits(value: unknown): void;
|
|
73
|
+
export {};
|
|
74
|
+
//# sourceMappingURL=engine-limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-limits.d.ts","sourceRoot":"","sources":["../src/engine-limits.ts"],"names":[],"mappings":"AA6BA,2DAA2D;AAE3D,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAEhE,iEAAiE;AAEjE,eAAO,MAAM,0BAA0B,mCAAmC,CAAC;AAE3E,eAAO,MAAM,+BAA+B,qCACR,CAAC;AAErC;;;GAGG;AAEH,eAAO,MAAM,6BAA6B,SAAU,CAAC;AAIrD,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC,CAAC;AAGH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,IAAI,EAAE,MAAM,GAAG,YAAY,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAWH;;;;GAIG;AAEH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,GACb,iBAAiB,GAAG,SAAS,CAiB/B;AAED,8DAA8D;AAE9D,wBAAgB,kBAAkB,CAChC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,iBAAiB,GAAG,SAAS,CAW/B;AAED;;;;;;;;;GASG;AAEH,eAAO,MAAM,8BAA8B,QAI5B,CAAC;AAKhB;;;;;GAKG;AAEH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,iBAAiB,GACxB,MAAM,CAMR;AAED,KAAK,aAAa,GAAG;IACnB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;;GAGG;AAEH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,aAAa,EACvD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,iBAAiB,GACxB,CAAC,GAAG,CAAC,aAAa,GAAG;IAAE,QAAQ,CAAC,aAAa,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAiBvE;AAiBD,qEAAqE;AAErE,qBAAa,qBAAsB,SAAQ,KAAK;IAIlC,QAAQ,CAAC,aAAa,EAAE,mBAAmB;IAHvD,QAAQ,CAAC,IAAI,0BAA6B;IAC1C,QAAQ,CAAC,SAAS,SAAS;gBAEN,aAAa,EAAE,mBAAmB;CAIxD;AAED;;;GAGG;AAEH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,GACb,mBAAmB,GAAG,IAAI,CAkB5B;AAED,wDAAwD;AAExD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAQ5D"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Kibi — repo-local, per-branch, queryable long-term memory for software projects
|
|
3
|
+
Copyright (C) 2026 Piotr Franczyk
|
|
4
|
+
|
|
5
|
+
This program is free software: you can redistribute it and/or modify
|
|
6
|
+
it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU Affero General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
18
|
+
/*
|
|
19
|
+
* Per-request bounds for read-only engine work.
|
|
20
|
+
*
|
|
21
|
+
* The engine serves every client from one serialized SWI-Prolog queue, and a
|
|
22
|
+
* goal already running inside SWI cannot be cancelled from outside. A read
|
|
23
|
+
* that carries limits runs under call_with_time_limit/2 and
|
|
24
|
+
* call_with_inference_limit/3, so a runaway read ends inside Prolog and frees
|
|
25
|
+
* the queue. Hitting a limit is reported explicitly (limitExceeded) and is
|
|
26
|
+
* never presented as an empty or partial answer.
|
|
27
|
+
*/
|
|
28
|
+
/** Envelope error code for a read stopped at its limit. */
|
|
29
|
+
// implements REQ-core-engine-read-limits
|
|
30
|
+
export const QUERY_LIMIT_EXCEEDED_CODE = "QUERY_LIMIT_EXCEEDED";
|
|
31
|
+
/** Environment opt-in for read limits on every engine client. */
|
|
32
|
+
// implements REQ-core-engine-read-limits
|
|
33
|
+
export const ENGINE_READ_TIME_LIMIT_ENV = "KIBI_ENGINE_READ_TIME_LIMIT_MS";
|
|
34
|
+
// implements REQ-core-engine-read-limits
|
|
35
|
+
export const ENGINE_READ_INFERENCE_LIMIT_ENV = "KIBI_ENGINE_READ_INFERENCE_LIMIT";
|
|
36
|
+
/**
|
|
37
|
+
* Upper bound for a requested time limit. The daemon's SWI process kills a
|
|
38
|
+
* query at 120 s and recycles the session; a bounded read must end first.
|
|
39
|
+
*/
|
|
40
|
+
// implements REQ-core-engine-read-limits
|
|
41
|
+
export const ENGINE_READ_TIME_LIMIT_CAP_MS = 115_000;
|
|
42
|
+
const ENGINE_READ_INFERENCE_LIMIT_CAP = 1_000_000_000_000;
|
|
43
|
+
function boundedInteger(value, max) {
|
|
44
|
+
return typeof value === "number" &&
|
|
45
|
+
Number.isSafeInteger(value) &&
|
|
46
|
+
value > 0 &&
|
|
47
|
+
value <= max
|
|
48
|
+
? value
|
|
49
|
+
: undefined;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Validate limits received over the engine socket. Out-of-range values are
|
|
53
|
+
* dropped (the read runs unbounded, as before); a time limit is capped below
|
|
54
|
+
* the hard per-query timeout.
|
|
55
|
+
*/
|
|
56
|
+
// implements REQ-core-engine-read-limits
|
|
57
|
+
export function normalizeQueryLimits(value) {
|
|
58
|
+
if (value === null || typeof value !== "object")
|
|
59
|
+
return undefined;
|
|
60
|
+
const raw = value;
|
|
61
|
+
const requestedTime = boundedInteger(raw.timeMs, Number.MAX_SAFE_INTEGER);
|
|
62
|
+
const timeMs = requestedTime === undefined
|
|
63
|
+
? undefined
|
|
64
|
+
: Math.min(requestedTime, ENGINE_READ_TIME_LIMIT_CAP_MS);
|
|
65
|
+
const inferences = boundedInteger(raw.inferences, ENGINE_READ_INFERENCE_LIMIT_CAP);
|
|
66
|
+
if (timeMs === undefined && inferences === undefined)
|
|
67
|
+
return undefined;
|
|
68
|
+
return {
|
|
69
|
+
...(timeMs !== undefined ? { timeMs } : {}),
|
|
70
|
+
...(inferences !== undefined ? { inferences } : {}),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** Read limits configured through the environment, if any. */
|
|
74
|
+
// implements REQ-core-engine-read-limits
|
|
75
|
+
export function queryLimitsFromEnv(env = process.env) {
|
|
76
|
+
const parse = (name) => {
|
|
77
|
+
const raw = env[name]?.trim();
|
|
78
|
+
if (!raw)
|
|
79
|
+
return undefined;
|
|
80
|
+
const parsed = Number(raw);
|
|
81
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
|
|
82
|
+
};
|
|
83
|
+
return normalizeQueryLimits({
|
|
84
|
+
timeMs: parse(ENGINE_READ_TIME_LIMIT_ENV),
|
|
85
|
+
inferences: parse(ENGINE_READ_INFERENCE_LIMIT_ENV),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Clauses the engine session defines at boot (and after a recycle) so a
|
|
90
|
+
* bounded read needs one call and one answer binding. Helper variables stay
|
|
91
|
+
* clause-local, so the toplevel prints only the goal's own bindings plus the
|
|
92
|
+
* outcome, whose compound value cannot be grouped with a goal's binding.
|
|
93
|
+
*
|
|
94
|
+
* A goal that swallows the limit exception itself (a catch-all inside a
|
|
95
|
+
* predicate) could otherwise return a partial answer or fail; measuring the
|
|
96
|
+
* elapsed time and inferences around the goal reports the limit regardless.
|
|
97
|
+
*/
|
|
98
|
+
// implements REQ-core-engine-read-limits
|
|
99
|
+
export const BOUNDED_READ_HELPER_DEFINITION = `(current_predicate(kibi_engine_bounded_read/4) -> true ; ${[
|
|
100
|
+
"assertz((kibi_engine_bounded_read(Goal, Seconds, Inferences, kibi_read_outcome(Outcome)) :- get_time(T0), statistics(inferences, I0), (catch(kibi_engine_bounded_call(Goal, Seconds, Inferences, Inner), time_limit_exceeded, Inner = time) -> Failed = false ; Failed = true), get_time(T1), statistics(inferences, I1), (Inner == time -> Outcome = time ; Inner == inferences -> Outcome = inferences ; number(Seconds), T1 - T0 >= Seconds -> Outcome = time ; integer(Inferences), I1 - I0 >= Inferences -> Outcome = inferences ; Failed == true -> fail ; Outcome = none)))",
|
|
101
|
+
"assertz((kibi_engine_bounded_call(Goal, Seconds, Inferences, Inner) :- (number(Seconds) -> call_with_time_limit(Seconds, kibi_engine_inference_call(Goal, Inferences, Inner)) ; kibi_engine_inference_call(Goal, Inferences, Inner))))",
|
|
102
|
+
"assertz((kibi_engine_inference_call(Goal, Inferences, Inner) :- (integer(Inferences) -> call_with_inference_limit(Goal, Inferences, Result), (Result == inference_limit_exceeded -> Inner = inferences ; Inner = none) ; once(Goal), Inner = none)))",
|
|
103
|
+
].join(", ")})`;
|
|
104
|
+
/** Answer binding that carries a bounded read's outcome. */
|
|
105
|
+
const OUTCOME_BINDING = "KibiReadOutcome";
|
|
106
|
+
/**
|
|
107
|
+
* Wrap a read-only goal in its limits. The goal's own variables keep their
|
|
108
|
+
* names, so its answer bindings are unchanged; the outcome arrives in the
|
|
109
|
+
* KibiReadOutcome binding that settleBoundedRead strips. The surrounding
|
|
110
|
+
* parentheses keep PrologProcess from caching a bounded answer.
|
|
111
|
+
*/
|
|
112
|
+
// implements REQ-core-engine-read-limits
|
|
113
|
+
export function boundedReadGoal(goal, limits) {
|
|
114
|
+
const seconds = limits.timeMs === undefined ? "none" : (limits.timeMs / 1000).toFixed(3);
|
|
115
|
+
const inferences = limits.inferences === undefined ? "none" : String(limits.inferences);
|
|
116
|
+
return `(kibi_engine_bounded_read((${goal}), ${seconds}, ${inferences}, ${OUTCOME_BINDING}))`;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Turn a bounded read's answer back into the unbounded answer shape, or into
|
|
120
|
+
* an explicit limitExceeded failure when a limit stopped the goal.
|
|
121
|
+
*/
|
|
122
|
+
// implements REQ-core-engine-read-limits
|
|
123
|
+
export function settleBoundedRead(result, limits) {
|
|
124
|
+
if (!result.success)
|
|
125
|
+
return result;
|
|
126
|
+
const { [OUTCOME_BINDING]: rawOutcome, ...bindings } = result.bindings;
|
|
127
|
+
const outcome = rawOutcome?.match(/^kibi_read_outcome\((\w+)\)$/)?.[1];
|
|
128
|
+
const hit = outcome === "time" && limits.timeMs !== undefined
|
|
129
|
+
? { kind: "time", limit: limits.timeMs }
|
|
130
|
+
: outcome === "inferences" && limits.inferences !== undefined
|
|
131
|
+
? { kind: "inferences", limit: limits.inferences }
|
|
132
|
+
: null;
|
|
133
|
+
if (hit === null)
|
|
134
|
+
return { ...result, bindings };
|
|
135
|
+
return {
|
|
136
|
+
success: false,
|
|
137
|
+
bindings: {},
|
|
138
|
+
error: queryLimitMessage(hit),
|
|
139
|
+
limitExceeded: hit,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* The message names the limit in a fixed form, so the signal survives an
|
|
144
|
+
* executor that rewraps the error with its own prefix.
|
|
145
|
+
*/
|
|
146
|
+
function queryLimitMessage(hit) {
|
|
147
|
+
const budget = hit.kind === "time"
|
|
148
|
+
? `time limit of ${hit.limit} ms (${ENGINE_READ_TIME_LIMIT_ENV})`
|
|
149
|
+
: `inference limit of ${hit.limit} (${ENGINE_READ_INFERENCE_LIMIT_ENV})`;
|
|
150
|
+
return `${QUERY_LIMIT_EXCEEDED_CODE}: read stopped at its ${budget} before computing an answer. Narrow the query or raise the limit.`;
|
|
151
|
+
}
|
|
152
|
+
const QUERY_LIMIT_MESSAGE = /QUERY_LIMIT_EXCEEDED: read stopped at its (time|inference) limit of (\d+)/;
|
|
153
|
+
/** A read the engine stopped at its limit; never an empty answer. */
|
|
154
|
+
// implements REQ-core-engine-read-limits
|
|
155
|
+
export class EngineQueryLimitError extends Error {
|
|
156
|
+
limitExceeded;
|
|
157
|
+
code = QUERY_LIMIT_EXCEEDED_CODE;
|
|
158
|
+
retryable = false;
|
|
159
|
+
constructor(limitExceeded) {
|
|
160
|
+
super(queryLimitMessage(limitExceeded));
|
|
161
|
+
this.limitExceeded = limitExceeded;
|
|
162
|
+
this.name = "EngineQueryLimitError";
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* The limit that stopped a read, from the typed error or from the message an
|
|
167
|
+
* executor rewrapped it into; null for every other error.
|
|
168
|
+
*/
|
|
169
|
+
// implements REQ-core-engine-read-limits
|
|
170
|
+
export function queryLimitExceededOf(error) {
|
|
171
|
+
if (!(error instanceof Error))
|
|
172
|
+
return null;
|
|
173
|
+
const typed = error.limitExceeded;
|
|
174
|
+
if (error.code === QUERY_LIMIT_EXCEEDED_CODE &&
|
|
175
|
+
typed !== null &&
|
|
176
|
+
typeof typed === "object") {
|
|
177
|
+
const { kind, limit } = typed;
|
|
178
|
+
if ((kind === "time" || kind === "inferences") && typeof limit === "number")
|
|
179
|
+
return { kind, limit };
|
|
180
|
+
}
|
|
181
|
+
const match = error.message.match(QUERY_LIMIT_MESSAGE);
|
|
182
|
+
if (match?.[1] === undefined || match[2] === undefined)
|
|
183
|
+
return null;
|
|
184
|
+
return {
|
|
185
|
+
kind: match[1] === "time" ? "time" : "inferences",
|
|
186
|
+
limit: Number(match[2]),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/** Reject an engine answer that reports a limit hit. */
|
|
190
|
+
// implements REQ-core-engine-read-limits
|
|
191
|
+
export function assertWithinQueryLimits(value) {
|
|
192
|
+
if (value === null || typeof value !== "object")
|
|
193
|
+
return;
|
|
194
|
+
const hit = value.limitExceeded;
|
|
195
|
+
if (hit === null || typeof hit !== "object")
|
|
196
|
+
return;
|
|
197
|
+
const { kind, limit } = hit;
|
|
198
|
+
if ((kind !== "time" && kind !== "inferences") || typeof limit !== "number")
|
|
199
|
+
return;
|
|
200
|
+
throw new EngineQueryLimitError({ kind, limit });
|
|
201
|
+
}
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { type EngineQueryLimits } from "./engine-limits.js";
|
|
1
2
|
import type { EngineAttachmentIdentity, EngineCommandV1 } from "./engine-types.js";
|
|
2
3
|
import { PrologProcess } from "./prolog.js";
|
|
3
4
|
import type { PrologQueryResult } from "./public/operations/runtime-types.js";
|
|
4
5
|
import type { PrologEntityQueryInput, PrologEntityQueryResult, PrologSearchQueryInput, PrologSearchQueryResult } from "./public/operations/runtime-types.js";
|
|
5
6
|
export type { EngineAttachmentIdentity, EngineCommandV1, EngineRequest, } from "./engine-types.js";
|
|
7
|
+
export { EngineQueryLimitError, QUERY_LIMIT_EXCEEDED_CODE, queryLimitExceededOf, } from "./engine-limits.js";
|
|
8
|
+
export type { EngineLimitExceeded, EngineQueryLimits, } from "./engine-limits.js";
|
|
6
9
|
export declare const ENGINE_PROTOCOL_VERSION = 1;
|
|
7
10
|
export declare const ENGINE_IDLE_TIMEOUT_MS: number;
|
|
8
11
|
export declare const ENGINE_PACKAGE_VERSIONS: string;
|
|
@@ -46,6 +49,12 @@ export type EngineClientOptions = {
|
|
|
46
49
|
readonly timeout?: number;
|
|
47
50
|
/** Internal stop-before-publish client may attach while it owns the lease. */
|
|
48
51
|
readonly allowPublicationLock?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Bounds for this client's read-only requests. Defaults to
|
|
54
|
+
* KIBI_ENGINE_READ_TIME_LIMIT_MS / KIBI_ENGINE_READ_INFERENCE_LIMIT; null
|
|
55
|
+
* sends none (sync and other maintenance clients).
|
|
56
|
+
*/
|
|
57
|
+
readonly readLimits?: EngineQueryLimits | null;
|
|
49
58
|
};
|
|
50
59
|
/** PrologPort-compatible client used by CLI and MCP operation runtimes. */
|
|
51
60
|
export declare class EngineClient {
|
|
@@ -53,6 +62,7 @@ export declare class EngineClient {
|
|
|
53
62
|
private readonly branch;
|
|
54
63
|
private readonly timeout;
|
|
55
64
|
private readonly allowPublicationLock;
|
|
65
|
+
private readonly readLimits;
|
|
56
66
|
private socket;
|
|
57
67
|
private daemon;
|
|
58
68
|
private inputBuffer;
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EACV,wBAAwB,EACxB,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAmB,MAAM,aAAa,CAAC;AAK7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,sCAAsC,CAAC;AAQ9C,YAAY,EACV,wBAAwB,EACxB,eAAe,EACf,aAAa,GACd,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.js
CHANGED
|
@@ -13,6 +13,7 @@ import * as os from "node:os";
|
|
|
13
13
|
import * as path from "node:path";
|
|
14
14
|
import { performance } from "node:perf_hooks";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
|
+
import { BOUNDED_READ_HELPER_DEFINITION, assertWithinQueryLimits, boundedReadGoal, normalizeQueryLimits, queryLimitsFromEnv, settleBoundedRead, } from "./engine-limits.js";
|
|
16
17
|
import { writePerformanceTraceEvent } from "./performance-trace.js";
|
|
17
18
|
import { PrologProcess, resolveKbPlPath } from "./prolog.js";
|
|
18
19
|
import { parseEntityFromList, parseListOfLists } from "./prolog/codec.js";
|
|
@@ -22,6 +23,14 @@ import { queryEntityChunks } from "./public/operations/discovery-entities.js";
|
|
|
22
23
|
import { isValidBranchName } from "./utils/branch-resolver.js";
|
|
23
24
|
import { branchStorePath, ensureBranchStoreManifest, } from "./utils/branch-store-locator.js";
|
|
24
25
|
import { canonicalFilesystemPath } from "./utils/canonical-path.js";
|
|
26
|
+
export { EngineQueryLimitError, QUERY_LIMIT_EXCEEDED_CODE, queryLimitExceededOf, } from "./engine-limits.js";
|
|
27
|
+
/** Request methods whose read-only work may carry per-request limits. */
|
|
28
|
+
const READ_LIMITED_METHODS = new Set([
|
|
29
|
+
"query",
|
|
30
|
+
"command",
|
|
31
|
+
"entities",
|
|
32
|
+
"search",
|
|
33
|
+
]);
|
|
25
34
|
export const ENGINE_PROTOCOL_VERSION = 1;
|
|
26
35
|
export const ENGINE_IDLE_TIMEOUT_MS = 10 * 60 * 1000;
|
|
27
36
|
export const ENGINE_PACKAGE_VERSIONS = process.env.KIBI_PACKAGE_VERSIONS ?? "unknown";
|
|
@@ -727,6 +736,7 @@ export class EngineClient {
|
|
|
727
736
|
branch;
|
|
728
737
|
timeout;
|
|
729
738
|
allowPublicationLock;
|
|
739
|
+
readLimits;
|
|
730
740
|
socket = null;
|
|
731
741
|
daemon = null;
|
|
732
742
|
inputBuffer = Buffer.alloc(0);
|
|
@@ -743,6 +753,10 @@ export class EngineClient {
|
|
|
743
753
|
this.branch = options.branch;
|
|
744
754
|
this.timeout = options.timeout ?? 120_000;
|
|
745
755
|
this.allowPublicationLock = options.allowPublicationLock ?? false;
|
|
756
|
+
this.readLimits =
|
|
757
|
+
options.readLimits === undefined
|
|
758
|
+
? queryLimitsFromEnv()
|
|
759
|
+
: (options.readLimits ?? undefined);
|
|
746
760
|
}
|
|
747
761
|
async start(allowSpawn = true) {
|
|
748
762
|
const wasConnected = this.socket !== null && !this.socket.destroyed;
|
|
@@ -948,7 +962,11 @@ export class EngineClient {
|
|
|
948
962
|
if (socket === null || socket.destroyed)
|
|
949
963
|
throw new Error("Kibi engine is not connected");
|
|
950
964
|
const id = ++this.requestId;
|
|
951
|
-
|
|
965
|
+
const limits = this.readLimits !== undefined &&
|
|
966
|
+
READ_LIMITED_METHODS.has(request.method)
|
|
967
|
+
? { limits: this.readLimits }
|
|
968
|
+
: {};
|
|
969
|
+
const value = await new Promise((resolve, reject) => {
|
|
952
970
|
this.pending.set(id, {
|
|
953
971
|
resolve: resolve,
|
|
954
972
|
reject,
|
|
@@ -957,6 +975,7 @@ export class EngineClient {
|
|
|
957
975
|
try {
|
|
958
976
|
socket.write(frame({
|
|
959
977
|
...request,
|
|
978
|
+
...limits,
|
|
960
979
|
id,
|
|
961
980
|
protocolVersion: ENGINE_PROTOCOL_VERSION,
|
|
962
981
|
packageVersions: ENGINE_PACKAGE_VERSIONS,
|
|
@@ -988,6 +1007,10 @@ export class EngineClient {
|
|
|
988
1007
|
signal.addEventListener("abort", abort, { once: true });
|
|
989
1008
|
}
|
|
990
1009
|
});
|
|
1010
|
+
// A bounded read stopped at its limit has no answer; never let it pass
|
|
1011
|
+
// as an empty or failed lookup.
|
|
1012
|
+
assertWithinQueryLimits(value);
|
|
1013
|
+
return value;
|
|
991
1014
|
}
|
|
992
1015
|
finally {
|
|
993
1016
|
release();
|
|
@@ -1621,6 +1644,20 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
1621
1644
|
let queue = Promise.resolve();
|
|
1622
1645
|
let idleCompactionQueued = false;
|
|
1623
1646
|
const queryCache = new Map();
|
|
1647
|
+
// The bounded-read helper lives in the Prolog session; a recycled session
|
|
1648
|
+
// (new pid) defines it again before its first bounded read.
|
|
1649
|
+
let boundedReadHelperPid = null;
|
|
1650
|
+
const runBoundedRead = async (goal, limits) => {
|
|
1651
|
+
const pid = prolog.getPid();
|
|
1652
|
+
if (boundedReadHelperPid !== pid) {
|
|
1653
|
+
const defined = await prolog.query(BOUNDED_READ_HELPER_DEFINITION);
|
|
1654
|
+
if (!defined.success) {
|
|
1655
|
+
throw new Error(defined.error ?? "Failed to define the bounded-read helper");
|
|
1656
|
+
}
|
|
1657
|
+
boundedReadHelperPid = pid;
|
|
1658
|
+
}
|
|
1659
|
+
return settleBoundedRead(await prolog.query(boundedReadGoal(goal, limits)), limits);
|
|
1660
|
+
};
|
|
1624
1661
|
let freshnessCache = null;
|
|
1625
1662
|
const clients = new Set();
|
|
1626
1663
|
let shuttingDown = false;
|
|
@@ -1727,6 +1764,11 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
1727
1764
|
freshnessCache = null;
|
|
1728
1765
|
attachedIdentity = readEngineAttachmentIdentity(branchPath);
|
|
1729
1766
|
}
|
|
1767
|
+
// Read-only work runs inside the request's limits, when it has any.
|
|
1768
|
+
const readLimits = normalizeQueryLimits(request.limits);
|
|
1769
|
+
const runRead = (goal) => readLimits === undefined
|
|
1770
|
+
? prolog.query(goal)
|
|
1771
|
+
: runBoundedRead(goal, readLimits);
|
|
1730
1772
|
switch (request.method) {
|
|
1731
1773
|
case "entities": {
|
|
1732
1774
|
const limit = request.limit ?? 100;
|
|
@@ -1750,8 +1792,8 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
1750
1792
|
const source = request.sourceFile === undefined
|
|
1751
1793
|
? "none"
|
|
1752
1794
|
: `'${quoteProlog(request.sourceFile)}'`;
|
|
1753
|
-
const result = await
|
|
1754
|
-
if (!result.success) {
|
|
1795
|
+
const result = await runRead(`kb_query_entities(${type}, ${id}, ${tags}, ${source}, ${limit}, ${offset}, Rows, Count)`);
|
|
1796
|
+
if (!result.success && result.limitExceeded === undefined) {
|
|
1755
1797
|
throw new Error(result.error ?? "Indexed entity query failed");
|
|
1756
1798
|
}
|
|
1757
1799
|
return result;
|
|
@@ -1773,8 +1815,8 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
1773
1815
|
const type = request.type === undefined
|
|
1774
1816
|
? "none"
|
|
1775
1817
|
: `'${quoteProlog(request.type)}'`;
|
|
1776
|
-
const result = await
|
|
1777
|
-
if (!result.success) {
|
|
1818
|
+
const result = await runRead(`kb_search_entities(${type}, '${quoteProlog(request.searchQuery)}', ${limit}, ${offset}, Rows, Count)`);
|
|
1819
|
+
if (!result.success && result.limitExceeded === undefined) {
|
|
1778
1820
|
throw new Error(result.error ?? "Indexed search candidate query failed");
|
|
1779
1821
|
}
|
|
1780
1822
|
return result;
|
|
@@ -1814,7 +1856,7 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
1814
1856
|
}
|
|
1815
1857
|
// Rule selection is intentionally resolved inside the engine. A
|
|
1816
1858
|
// caller never supplies a Prolog goal over the command boundary.
|
|
1817
|
-
return
|
|
1859
|
+
return runRead("checks:check_all_json(JsonString)");
|
|
1818
1860
|
}
|
|
1819
1861
|
case "relationship": {
|
|
1820
1862
|
if (!command.type || !command.from || !command.to) {
|
|
@@ -1888,7 +1930,7 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
1888
1930
|
const source = command.sourceFile === undefined
|
|
1889
1931
|
? "none"
|
|
1890
1932
|
: `'${quoteProlog(command.sourceFile)}'`;
|
|
1891
|
-
return
|
|
1933
|
+
return runRead(`kb_query_entities(${type}, ${id}, ${tags}, ${source}, ${command.limit}, ${command.offset}, Rows, Count)`);
|
|
1892
1934
|
}
|
|
1893
1935
|
case "search": {
|
|
1894
1936
|
if (!command.query.trim())
|
|
@@ -1903,7 +1945,7 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
1903
1945
|
const type = command.type === undefined
|
|
1904
1946
|
? "none"
|
|
1905
1947
|
: `'${quoteProlog(command.type)}'`;
|
|
1906
|
-
return
|
|
1948
|
+
return runRead(`kb_search_entities(${type}, '${quoteProlog(command.query)}', ${command.limit}, ${command.offset}, Rows, Count)`);
|
|
1907
1949
|
}
|
|
1908
1950
|
default:
|
|
1909
1951
|
throw new Error("engine.command kind is unsupported");
|
|
@@ -1950,7 +1992,13 @@ export async function runEngineDaemon(requestedOptions) {
|
|
|
1950
1992
|
return cached;
|
|
1951
1993
|
}
|
|
1952
1994
|
}
|
|
1953
|
-
|
|
1995
|
+
// Writes and module loads always run to completion; a limit may
|
|
1996
|
+
// only stop a read.
|
|
1997
|
+
const boundable = !mutatingEngineGoal(request.goal) &&
|
|
1998
|
+
!/\b(?:use_module|consult|load_files|ensure_loaded)\s*\(/.test(request.goal);
|
|
1999
|
+
const result = boundable
|
|
2000
|
+
? await runRead(request.goal)
|
|
2001
|
+
: await prolog.query(request.goal);
|
|
1954
2002
|
session.recordModuleLoad(request.goal, result);
|
|
1955
2003
|
if (result.success && mutatingEngineGoal(request.goal)) {
|
|
1956
2004
|
fsyncJournaledBranchStore(branchPath);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type EntityOrigin } from "../public/entity-origin.js";
|
|
1
2
|
export interface ExtractedEntity {
|
|
2
3
|
id: string;
|
|
3
4
|
type: string;
|
|
@@ -12,6 +13,7 @@ export interface ExtractedEntity {
|
|
|
12
13
|
severity?: string;
|
|
13
14
|
text_ref?: string;
|
|
14
15
|
granularity_reason?: string;
|
|
16
|
+
origin?: EntityOrigin;
|
|
15
17
|
}
|
|
16
18
|
export interface ExtractedRelationship {
|
|
17
19
|
type: string;
|
|
@@ -71,5 +73,11 @@ export interface ReceiptCodeScopeEntry {
|
|
|
71
73
|
readonly symbolId: string;
|
|
72
74
|
readonly sourceHash: string;
|
|
73
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Scope hash of a symbol whose recorded source file lies outside the
|
|
78
|
+
* repository. Only repository content can be compared between a CI checkout
|
|
79
|
+
* and a developer machine, so such a file is never read.
|
|
80
|
+
*/
|
|
81
|
+
export declare const OUTSIDE_WORKSPACE_SCOPE_HASH = "outside-workspace";
|
|
74
82
|
export declare function resolveBoundSymbolScope(manifestPath: string, symbolIds: readonly string[]): ReceiptCodeScopeEntry[];
|
|
75
83
|
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/extractors/manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/extractors/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,9 @@ import { createHash } from "node:crypto";
|
|
|
19
19
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
20
20
|
import * as path from "node:path";
|
|
21
21
|
import { load as parseYAML } from "js-yaml";
|
|
22
|
+
import { normalizeEntityOrigin, } from "../public/entity-origin.js";
|
|
22
23
|
import { DEFAULT_COORDINATES_PATH } from "../utils/manifest-paths.js";
|
|
24
|
+
import { normalizeRepoRelativePath } from "../utils/repo-relative-path.js";
|
|
23
25
|
import { mergeCoordinatesWithManifest, parseCoordinateArtifact, } from "./symbol-coordinates.js";
|
|
24
26
|
const VALID_RELATIONSHIP_TYPES = new Set([
|
|
25
27
|
"depends_on",
|
|
@@ -38,6 +40,8 @@ const VALID_RELATIONSHIP_TYPES = new Set([
|
|
|
38
40
|
"consumes",
|
|
39
41
|
"supersedes",
|
|
40
42
|
"restates",
|
|
43
|
+
"assumes",
|
|
44
|
+
"exempts",
|
|
41
45
|
"relates_to",
|
|
42
46
|
]);
|
|
43
47
|
const VALID_RELATIONSHIP_DIRECTIONS = [
|
|
@@ -62,6 +66,8 @@ const VALID_RELATIONSHIP_DIRECTIONS = [
|
|
|
62
66
|
{ type: "supersedes", from: "adr", to: "adr" },
|
|
63
67
|
{ type: "supersedes", from: "req", to: "req" },
|
|
64
68
|
{ type: "restates", from: "req", to: "req" },
|
|
69
|
+
{ type: "assumes", from: "scenario", to: "fact" },
|
|
70
|
+
{ type: "exempts", from: "req", to: "req" },
|
|
65
71
|
];
|
|
66
72
|
const RELATIONSHIP_TYPE_DISPLAY_LIST = Array.from(VALID_RELATIONSHIP_TYPES)
|
|
67
73
|
.sort()
|
|
@@ -183,6 +189,15 @@ export function extractManifestSymbolRecords(manifestSymbols, filePath) {
|
|
|
183
189
|
throw new ManifestError("Missing required field: title", filePath);
|
|
184
190
|
}
|
|
185
191
|
const id = symbol.id || generateId(filePath, symbol.title);
|
|
192
|
+
// implements REQ-004
|
|
193
|
+
let origin;
|
|
194
|
+
if (symbol.origin !== undefined) {
|
|
195
|
+
const normalized = normalizeEntityOrigin(symbol.origin);
|
|
196
|
+
if ("error" in normalized) {
|
|
197
|
+
throw new ManifestError(`Invalid origin for symbol ${id}: ${normalized.error}`, filePath);
|
|
198
|
+
}
|
|
199
|
+
origin = normalized.origin;
|
|
200
|
+
}
|
|
186
201
|
const entity = {
|
|
187
202
|
id,
|
|
188
203
|
type: "symbol",
|
|
@@ -199,6 +214,7 @@ export function extractManifestSymbolRecords(manifestSymbols, filePath) {
|
|
|
199
214
|
...(symbol.granularity_reason !== undefined
|
|
200
215
|
? { granularity_reason: symbol.granularity_reason }
|
|
201
216
|
: {}),
|
|
217
|
+
...(origin !== undefined ? { origin } : {}),
|
|
202
218
|
...(typeof symbol.symbol_kind === "string"
|
|
203
219
|
? { symbol_kind: symbol.symbol_kind }
|
|
204
220
|
: {}),
|
|
@@ -386,23 +402,36 @@ function scopeFileHash(absolutePath) {
|
|
|
386
402
|
scopeFileHashCache.set(absolutePath, { stamp, hash });
|
|
387
403
|
return hash;
|
|
388
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* Scope hash of a symbol whose recorded source file lies outside the
|
|
407
|
+
* repository. Only repository content can be compared between a CI checkout
|
|
408
|
+
* and a developer machine, so such a file is never read.
|
|
409
|
+
*/
|
|
410
|
+
// implements REQ-kibi-fresh-verification-receipts-v2
|
|
411
|
+
export const OUTSIDE_WORKSPACE_SCOPE_HASH = "outside-workspace";
|
|
412
|
+
// implements REQ-kibi-fresh-verification-receipts-v2
|
|
389
413
|
export function resolveBoundSymbolScope(manifestPath, symbolIds) {
|
|
390
414
|
const wanted = [...new Set(symbolIds)];
|
|
391
415
|
if (wanted.length === 0)
|
|
392
416
|
return [];
|
|
393
417
|
const sourceFiles = scopeSourceFiles(manifestPath);
|
|
394
418
|
// The manifest lives at <workspace>/.kb/symbols.yaml; source files are
|
|
395
|
-
// workspace-relative.
|
|
419
|
+
// workspace-relative. Every recorded path is normalized to its
|
|
420
|
+
// repo-relative form first, so `./a.ts`, `a\b.ts` and an absolute path
|
|
421
|
+
// inside this checkout hash the same file wherever the checkout lives.
|
|
396
422
|
const workspaceRoot = path.dirname(path.dirname(path.resolve(manifestPath)));
|
|
397
423
|
const scope = [];
|
|
398
424
|
for (const symbolId of wanted) {
|
|
399
425
|
const sourceFile = sourceFiles.get(symbolId);
|
|
400
426
|
if (sourceFile === undefined)
|
|
401
427
|
continue;
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
428
|
+
const relative = normalizeRepoRelativePath(workspaceRoot, sourceFile);
|
|
429
|
+
scope.push({
|
|
430
|
+
symbolId,
|
|
431
|
+
sourceHash: relative === null
|
|
432
|
+
? OUTSIDE_WORKSPACE_SCOPE_HASH
|
|
433
|
+
: scopeFileHash(path.join(workspaceRoot, relative)),
|
|
434
|
+
});
|
|
406
435
|
}
|
|
407
436
|
scope.sort((left, right) => left.symbolId.localeCompare(right.symbolId));
|
|
408
437
|
return scope;
|