kibi-cli 2.31.1 → 2.35.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-register-proof.d.ts.map +1 -1
- package/dist/cli-register-proof.js +19 -7
- package/dist/cli-register-reporting.d.ts.map +1 -1
- package/dist/cli-register-reporting.js +2 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +5 -1
- package/dist/commands/check-generated.d.ts +5 -1
- package/dist/commands/check-generated.d.ts.map +1 -1
- package/dist/commands/check-generated.js +24 -35
- package/dist/commands/check.d.ts +1 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +14 -5
- package/dist/commands/discovery-table.d.ts.map +1 -1
- package/dist/commands/discovery-table.js +51 -4
- package/dist/commands/doctor.js +19 -4
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +8 -5
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +109 -5
- package/dist/commands/prove.d.ts +48 -1
- package/dist/commands/prove.d.ts.map +1 -1
- package/dist/commands/prove.js +293 -8
- package/dist/commands/report.d.ts +1 -0
- package/dist/commands/report.d.ts.map +1 -1
- package/dist/commands/report.js +70 -5
- package/dist/commands/signoff.d.ts.map +1 -1
- package/dist/commands/signoff.js +20 -1
- package/dist/commands/sync/manifest.d.ts +10 -1
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +106 -17
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +16 -5
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +19 -0
- package/dist/diagnostics.js +1 -1
- package/dist/engine.js +1 -1
- package/dist/extractors/markdown.d.ts +4 -2
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +17 -0
- package/dist/extractors/symbol-coordinates.js +2 -2
- package/dist/extractors/symbols-coordinator.d.ts +2 -4
- package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
- package/dist/extractors/symbols-coordinator.js +1 -2
- package/dist/operations/bootstrap/candidate-helpers.d.ts +3 -0
- package/dist/operations/bootstrap/candidate-helpers.d.ts.map +1 -1
- package/dist/operations/bootstrap/candidate-helpers.js +4 -0
- package/dist/operations/migration/evidence-floor.d.ts +41 -0
- package/dist/operations/migration/evidence-floor.d.ts.map +1 -0
- package/dist/operations/migration/evidence-floor.js +230 -0
- package/dist/operations/migration/proof-contract-claims.d.ts +72 -0
- package/dist/operations/migration/proof-contract-claims.d.ts.map +1 -0
- package/dist/operations/migration/proof-contract-claims.js +215 -0
- package/dist/operations/migration/schema6.d.ts +6 -0
- package/dist/operations/migration/schema6.d.ts.map +1 -1
- package/dist/operations/migration/schema6.js +92 -0
- package/dist/operations/migration/symbol-coordinates-refresh.d.ts +3 -2
- package/dist/operations/migration/symbol-coordinates-refresh.d.ts.map +1 -1
- package/dist/operations/migration/symbol-coordinates-refresh.js +4 -3
- package/dist/operations/migration/untrack-symbol-coordinates.d.ts +23 -0
- package/dist/operations/migration/untrack-symbol-coordinates.d.ts.map +1 -0
- package/dist/operations/migration/untrack-symbol-coordinates.js +67 -0
- package/dist/operations/modeling/requirement-modeler.d.ts.map +1 -1
- package/dist/operations/modeling/requirement-modeler.js +48 -1
- package/dist/operations/modeling/requirement-types.d.ts +2 -1
- package/dist/operations/modeling/requirement-types.d.ts.map +1 -1
- package/dist/operations/modeling/requirement-utils.d.ts +1 -1
- package/dist/operations/modeling/requirement-utils.d.ts.map +1 -1
- package/dist/operations/modeling/requirement-utils.js +8 -1
- package/dist/operations/mutation/omitted-properties.d.ts +11 -0
- package/dist/operations/mutation/omitted-properties.d.ts.map +1 -0
- package/dist/operations/mutation/omitted-properties.js +76 -0
- package/dist/operations/mutation/serialization.d.ts.map +1 -1
- package/dist/operations/mutation/serialization.js +1 -0
- package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
- package/dist/operations/mutation/source-authoring.js +39 -20
- package/dist/operations/mutation/strict-fact.d.ts.map +1 -1
- package/dist/operations/mutation/strict-fact.js +6 -2
- package/dist/operations/mutation/symbol-granularity.d.ts.map +1 -1
- package/dist/operations/mutation/symbol-granularity.js +5 -3
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +7 -1
- package/dist/operations/mutation/validation.d.ts +2 -0
- package/dist/operations/mutation/validation.d.ts.map +1 -1
- package/dist/operations/mutation/validation.js +4 -0
- package/dist/operations/proof/claim-bindings.d.ts +41 -0
- package/dist/operations/proof/claim-bindings.d.ts.map +1 -0
- package/dist/operations/proof/claim-bindings.js +364 -0
- package/dist/operations/proof/code-certificates.d.ts +155 -0
- package/dist/operations/proof/code-certificates.d.ts.map +1 -0
- package/dist/operations/proof/code-certificates.js +894 -0
- package/dist/operations/proof/code-models.d.ts +96 -0
- package/dist/operations/proof/code-models.d.ts.map +1 -0
- package/dist/operations/proof/code-models.js +601 -0
- package/dist/operations/proof/code-runner.d.ts +40 -0
- package/dist/operations/proof/code-runner.d.ts.map +1 -0
- package/dist/operations/proof/code-runner.js +164 -0
- package/dist/operations/proof/code-scope.d.ts +14 -1
- package/dist/operations/proof/code-scope.d.ts.map +1 -1
- package/dist/operations/proof/code-scope.js +44 -2
- package/dist/operations/proof/compact-receipts.d.ts.map +1 -1
- package/dist/operations/proof/compact-receipts.js +4 -3
- package/dist/operations/proof/explain.d.ts +32 -0
- package/dist/operations/proof/explain.d.ts.map +1 -1
- package/dist/operations/proof/explain.js +91 -0
- package/dist/operations/proof/ingest-proof.d.ts +9 -1
- package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
- package/dist/operations/proof/ingest-proof.js +42 -2
- package/dist/operations/proof/receipt-compaction.d.ts +2 -0
- package/dist/operations/proof/receipt-compaction.d.ts.map +1 -1
- package/dist/operations/proof/receipt-compaction.js +6 -2
- package/dist/operations/proof/regular-language.d.ts +89 -0
- package/dist/operations/proof/regular-language.d.ts.map +1 -0
- package/dist/operations/proof/regular-language.js +943 -0
- package/dist/operations/proof/source-code-readers.d.ts +12 -0
- package/dist/operations/proof/source-code-readers.d.ts.map +1 -0
- package/dist/operations/proof/source-code-readers.js +699 -0
- package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.js +2 -1
- package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/shared.js +4 -0
- package/dist/operations/semantic-advisor/strict-count-rules.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/strict-count-rules.js +8 -2
- package/dist/operations/semantic-advisor/strict-rules.d.ts +8 -0
- package/dist/operations/semantic-advisor/strict-rules.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/strict-rules.js +234 -4
- package/dist/operations/semantic-advisor/types.d.ts +3 -2
- package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
- package/dist/plugins/approved-source-analyzers.generated.d.ts +6 -6
- package/dist/plugins/approved-source-analyzers.generated.js +6 -6
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +13 -3
- package/dist/proof/command-test-report.d.ts +4 -3
- package/dist/proof/command-test-report.d.ts.map +1 -1
- package/dist/proof/command-test-report.js +4 -10
- package/dist/proof/evaluate.d.ts.map +1 -1
- package/dist/proof/evaluate.js +18 -2
- package/dist/proof/inspect.d.ts.map +1 -1
- package/dist/proof/inspect.js +58 -0
- package/dist/proof/producers/playwright-reporter.d.ts +3 -0
- package/dist/proof/producers/playwright-reporter.d.ts.map +1 -1
- package/dist/proof/producers/playwright-reporter.js +25 -2
- package/dist/proof/step-runner.d.ts +36 -0
- package/dist/proof/step-runner.d.ts.map +1 -0
- package/dist/proof/step-runner.js +234 -0
- package/dist/public/evidence-levels.d.ts +12 -0
- package/dist/public/evidence-levels.d.ts.map +1 -0
- package/dist/public/evidence-levels.js +19 -0
- package/dist/public/impact/coverage-depth-quality.d.ts +7 -0
- package/dist/public/impact/coverage-depth-quality.d.ts.map +1 -1
- package/dist/public/impact/coverage-depth-quality.js +59 -0
- package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
- package/dist/public/impact/full-kb-quality.js +3 -1
- package/dist/public/operations/catalog.d.ts +315 -11
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts +2 -0
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +6 -0
- package/dist/public/operations/evidence-floor.d.ts +48 -0
- package/dist/public/operations/evidence-floor.d.ts.map +1 -0
- package/dist/public/operations/evidence-floor.js +143 -0
- package/dist/public/operations/migration-plan.d.ts +19 -5
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +22 -5
- package/dist/public/operations/node-ports.d.ts.map +1 -1
- package/dist/public/operations/node-ports.js +4 -1
- package/dist/public/operations/proof-contract-claims.d.ts +26 -0
- package/dist/public/operations/proof-contract-claims.d.ts.map +1 -0
- package/dist/public/operations/proof-contract-claims.js +71 -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 +3 -1
- package/dist/public/operations/specs/check.d.ts +1 -1
- package/dist/public/operations/specs/composite.d.ts +16 -3
- package/dist/public/operations/specs/composite.d.ts.map +1 -1
- package/dist/public/operations/specs/modeling.d.ts +16 -3
- package/dist/public/operations/specs/modeling.d.ts.map +1 -1
- package/dist/public/operations/specs/modeling.js +22 -3
- package/dist/public/operations/specs/mutation-schemas.d.ts +289 -7
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +28 -4
- package/dist/public/operations/specs/proof.d.ts +9 -0
- package/dist/public/operations/specs/proof.d.ts.map +1 -1
- package/dist/public/operations/specs/reporting.d.ts.map +1 -1
- package/dist/public/operations/specs/reporting.js +19 -10
- package/dist/public/operations/specs/upsert.d.ts +289 -7
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/proof-certificates.d.ts +163 -0
- package/dist/public/proof-certificates.d.ts.map +1 -0
- package/dist/public/proof-certificates.js +419 -0
- package/dist/public/proof-protocol.d.ts +259 -3
- package/dist/public/proof-protocol.d.ts.map +1 -1
- package/dist/public/proof-protocol.js +524 -3
- package/dist/public/proof-receipt.d.ts +90 -6
- package/dist/public/proof-receipt.d.ts.map +1 -1
- package/dist/public/proof-receipt.js +88 -7
- package/dist/public/proof-sources.d.ts +102 -0
- package/dist/public/proof-sources.d.ts.map +1 -0
- package/dist/public/proof-sources.js +1292 -0
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +39 -2
- package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
- package/dist/public/skills/kibi-commit-review/SKILL.md +8 -8
- package/dist/public/skills/kibi-commit-review/resources/staged-gate.md +12 -7
- package/dist/public/skills/kibi-decisions/SKILL.md +13 -2
- package/dist/public/skills/kibi-decisions/resources/decision-records.md +9 -1
- package/dist/public/skills/kibi-freshness/SKILL.md +5 -1
- package/dist/public/skills/kibi-traceability/SKILL.md +12 -1
- package/dist/public/skills/kibi-usage/SKILL.md +8 -4
- package/dist/public/skills/kibi-usage/resources/proof.md +221 -20
- package/dist/public/skills/kibi-usage/resources/workflows.md +4 -4
- package/dist/report/html-report.css +83 -11
- package/dist/report/html-report.d.ts +8 -0
- package/dist/report/html-report.d.ts.map +1 -1
- package/dist/report/html-report.js +214 -22
- package/dist/report/report-view.d.ts +2 -2
- package/dist/report/report-view.d.ts.map +1 -1
- package/dist/report/report-view.js +8 -0
- package/dist/schemas/entity.schema.json +404 -5
- package/dist/search-answer.d.ts.map +1 -1
- package/dist/search-answer.js +1 -0
- package/dist/signoff/html.d.ts.map +1 -1
- package/dist/signoff/html.js +3 -0
- package/dist/signoff/markdown.d.ts.map +1 -1
- package/dist/signoff/markdown.js +3 -0
- package/dist/signoff/model.d.ts +20 -0
- package/dist/signoff/model.d.ts.map +1 -1
- package/dist/signoff/model.js +20 -1
- package/dist/traceability/evidence-model.d.ts +13 -12
- package/dist/traceability/evidence-model.d.ts.map +1 -1
- package/dist/traceability/evidence-model.js +1 -1
- package/dist/traceability/impact-knowledge.d.ts.map +1 -1
- package/dist/traceability/impact-knowledge.js +1 -0
- package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
- package/dist/traceability/staged-diagnostics.js +24 -20
- package/dist/traceability/staged-impact-contract.d.ts +4 -4
- package/dist/traceability/staged-impact-contract.js +9 -9
- package/dist/traceability/staged-symbols-manifest.d.ts +11 -3
- package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
- package/dist/traceability/staged-symbols-manifest.js +47 -140
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +1 -0
- package/dist/types/entities.d.ts +5 -2
- package/dist/types/entities.d.ts.map +1 -1
- package/dist/utils/merge-driver-setup.d.ts +8 -1
- package/dist/utils/merge-driver-setup.d.ts.map +1 -1
- package/dist/utils/merge-driver-setup.js +23 -2
- package/dist/utils/rule-registry.generated.d.ts +10 -0
- package/dist/utils/rule-registry.generated.d.ts.map +1 -1
- package/dist/utils/rule-registry.generated.js +12 -0
- 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 +7 -1
- package/dist/utils/strict-modeling.d.ts +3 -2
- package/dist/utils/strict-modeling.d.ts.map +1 -1
- package/dist/utils/strict-modeling.js +37 -4
- package/dist/workspace-cwd.d.ts +15 -0
- package/dist/workspace-cwd.d.ts.map +1 -0
- package/dist/workspace-cwd.js +86 -0
- package/package.json +6 -2
- package/schema/entities.pl +6 -0
- package/schema/validation.pl +7 -2
- package/src/public/evidence-levels.ts +23 -0
- package/src/public/impact/coverage-depth-quality.ts +73 -0
- package/src/public/impact/full-kb-quality.ts +6 -1
- package/src/public/operations/check-executor.ts +13 -0
- package/src/public/operations/evidence-floor.ts +203 -0
- package/src/public/operations/migration-plan.ts +39 -6
- package/src/public/operations/node-ports.ts +3 -1
- package/src/public/operations/proof-contract-claims.ts +103 -0
- package/src/public/operations/specs/check-rules.generated.ts +3 -1
- package/src/public/operations/specs/modeling.ts +24 -5
- package/src/public/operations/specs/mutation-schemas.ts +30 -4
- package/src/public/operations/specs/reporting.ts +20 -10
- package/src/public/proof-certificates.ts +566 -0
- package/src/public/proof-protocol-types.d.ts +69 -1
- package/src/public/proof-protocol.ts +694 -3
- package/src/public/proof-receipt.ts +133 -7
- package/src/public/proof-sources.ts +1656 -0
- package/src/public/schemas/entity.ts +51 -3
- package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
- package/src/public/skills/kibi-commit-review/SKILL.md +8 -8
- package/src/public/skills/kibi-commit-review/resources/staged-gate.md +12 -7
- package/src/public/skills/kibi-decisions/SKILL.md +13 -2
- package/src/public/skills/kibi-decisions/resources/decision-records.md +9 -1
- package/src/public/skills/kibi-freshness/SKILL.md +5 -1
- package/src/public/skills/kibi-traceability/SKILL.md +12 -1
- package/src/public/skills/kibi-usage/SKILL.md +8 -4
- package/src/public/skills/kibi-usage/resources/proof.md +221 -20
- package/src/public/skills/kibi-usage/resources/workflows.md +4 -4
- package/src/schemas/entity.schema.json +404 -5
- package/dist/commands/proof-impact.d.ts +0 -7
- package/dist/commands/proof-impact.d.ts.map +0 -1
- package/dist/commands/proof-impact.js +0 -39
- package/dist/operations/proof/baseline-diff.d.ts +0 -41
- package/dist/operations/proof/baseline-diff.d.ts.map +0 -1
- package/dist/operations/proof/baseline-diff.js +0 -153
- package/dist/operations/proof/impact.d.ts +0 -51
- package/dist/operations/proof/impact.d.ts.map +0 -1
- package/dist/operations/proof/impact.js +0 -138
- package/dist/traceability/reviewed-coordinate-refresh.d.ts +0 -10
- package/dist/traceability/reviewed-coordinate-refresh.d.ts.map +0 -1
- package/dist/traceability/reviewed-coordinate-refresh.js +0 -49
|
@@ -2,8 +2,23 @@
|
|
|
2
2
|
export const PROOF_RUN_VERSION = "kibi.proof-run.v1" as const;
|
|
3
3
|
// implements REQ-kibi-verification-evidence-contract
|
|
4
4
|
export const PROOF_CONTRACT_VERSION = "kibi.proof-contract.v1" as const;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Receipts Kibi writes. v2 adds the contract's kind, the evidence level the
|
|
7
|
+
* receipt supports, and for certificate kinds the re-checked certificate.
|
|
8
|
+
*/
|
|
9
|
+
// implements REQ-kibi-verification-evidence-contract, REQ-kibi-code-proof-kinds
|
|
10
|
+
export const PROOF_RECEIPT_VERSION = "kibi.proof-receipt.v2" as const;
|
|
11
|
+
/** Receipts written before v2; still read, as e2e evidence at tested. */
|
|
12
|
+
// implements REQ-kibi-code-proof-kinds
|
|
13
|
+
export const PROOF_RECEIPT_V1_VERSION = "kibi.proof-receipt.v1" as const;
|
|
14
|
+
// implements REQ-kibi-code-proof-kinds
|
|
15
|
+
export const PROOF_RECEIPT_VERSIONS = [
|
|
16
|
+
PROOF_RECEIPT_V1_VERSION,
|
|
17
|
+
PROOF_RECEIPT_VERSION,
|
|
18
|
+
] as const;
|
|
19
|
+
/** The certificate a certificate-kind proof leaves for Kibi to re-check. */
|
|
20
|
+
// implements REQ-kibi-code-proof-kinds
|
|
21
|
+
export const CODE_CERTIFICATE_VERSION = "kibi.code-certificate.v1" as const;
|
|
7
22
|
// implements REQ-kibi-verification-evidence-contract
|
|
8
23
|
export const PROOF_INTEGRATION_VERSION = "kibi.proof-integration.v1" as const;
|
|
9
24
|
|
|
@@ -38,7 +53,63 @@ export const RUN_FAILURE_PHASES = [
|
|
|
38
53
|
"infrastructure",
|
|
39
54
|
] as const;
|
|
40
55
|
|
|
41
|
-
|
|
56
|
+
/**
|
|
57
|
+
* `all_required_first_attempt`: the whole run must pass and every obligation's
|
|
58
|
+
* own result must pass on its first attempt.
|
|
59
|
+
* `own_results_first_attempt`: a run whose only failures are other test cases
|
|
60
|
+
* (outcome `failed` in the execution phase) still proves an obligation whose
|
|
61
|
+
* own native-case result passed on its first attempt, so one unrelated
|
|
62
|
+
* failing case does not erase a suite's evidence. Aggregate-run obligations
|
|
63
|
+
* still need the whole run to pass.
|
|
64
|
+
*/
|
|
65
|
+
export const SUCCESS_POLICIES = [
|
|
66
|
+
"all_required_first_attempt",
|
|
67
|
+
"own_results_first_attempt",
|
|
68
|
+
] as const;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* What a proof contract's checker establishes. Runner kinds (e2e, example,
|
|
72
|
+
* property) sample cases and support tested evidence; certificate kinds
|
|
73
|
+
* (exhaustive, typecheck, arithmetic, smt, rule, state_machine, regex,
|
|
74
|
+
* source) cover every case and support proved evidence once Kibi re-checks
|
|
75
|
+
* the certificate the run left. A source certificate is Kibi's own read of a
|
|
76
|
+
* project source (a JSON or YAML file, a glob, an OpenAPI document, the
|
|
77
|
+
* references the code makes, a data schema, a route table, a validator).
|
|
78
|
+
*/
|
|
79
|
+
// implements REQ-kibi-code-proof-kinds
|
|
80
|
+
export const PROOF_KINDS = [
|
|
81
|
+
"e2e",
|
|
82
|
+
"example",
|
|
83
|
+
"property",
|
|
84
|
+
"exhaustive",
|
|
85
|
+
"typecheck",
|
|
86
|
+
"arithmetic",
|
|
87
|
+
"smt",
|
|
88
|
+
"rule",
|
|
89
|
+
"state_machine",
|
|
90
|
+
"regex",
|
|
91
|
+
"source",
|
|
92
|
+
] as const;
|
|
93
|
+
|
|
94
|
+
// implements REQ-kibi-code-proof-kinds, REQ-kibi-non-numeric-proof-kinds, REQ-kibi-source-proof-kinds
|
|
95
|
+
export const CERTIFICATE_PROOF_KINDS = [
|
|
96
|
+
"exhaustive",
|
|
97
|
+
"typecheck",
|
|
98
|
+
"arithmetic",
|
|
99
|
+
"smt",
|
|
100
|
+
"rule",
|
|
101
|
+
"state_machine",
|
|
102
|
+
"regex",
|
|
103
|
+
"source",
|
|
104
|
+
] as const;
|
|
105
|
+
|
|
106
|
+
// implements REQ-kibi-code-proof-kinds
|
|
107
|
+
export type ProofKind = (typeof PROOF_KINDS)[number];
|
|
108
|
+
|
|
109
|
+
// implements REQ-kibi-code-proof-kinds
|
|
110
|
+
export function isCertificateProofKind(kind: unknown): boolean {
|
|
111
|
+
return (CERTIFICATE_PROOF_KINDS as readonly unknown[]).includes(kind);
|
|
112
|
+
}
|
|
42
113
|
|
|
43
114
|
export type {
|
|
44
115
|
AttemptsStatus,
|
|
@@ -67,6 +138,12 @@ import type {
|
|
|
67
138
|
ProofResult,
|
|
68
139
|
ProofRunArtifact,
|
|
69
140
|
} from "./proof-protocol-types.js";
|
|
141
|
+
import {
|
|
142
|
+
SOURCE_READERS,
|
|
143
|
+
type SourceSpec,
|
|
144
|
+
normalizeSourceSpec,
|
|
145
|
+
sourceSpecErrors,
|
|
146
|
+
} from "./proof-sources.js";
|
|
70
147
|
|
|
71
148
|
export const PROOF_RESULT_SCHEMA = {
|
|
72
149
|
type: "object",
|
|
@@ -191,6 +268,64 @@ export const PROOF_RUN_ARTIFACT_SCHEMA = {
|
|
|
191
268
|
type: "array",
|
|
192
269
|
items: { type: "string", minLength: 1 },
|
|
193
270
|
},
|
|
271
|
+
certificates: {
|
|
272
|
+
type: "array",
|
|
273
|
+
description:
|
|
274
|
+
"kibi.code-certificate.v1 objects the run left for certificate-kind contracts, one per test. Kibi re-checks each before a receipt counts as proved.",
|
|
275
|
+
maxItems: 1000,
|
|
276
|
+
items: { type: "object", required: ["version", "kind", "test_id"] },
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
additionalProperties: false,
|
|
280
|
+
} as const;
|
|
281
|
+
|
|
282
|
+
const SOURCE_REFERENCE_SCHEMA = {
|
|
283
|
+
type: "object",
|
|
284
|
+
required: ["symbol_id"],
|
|
285
|
+
properties: {
|
|
286
|
+
symbol_id: { type: "string", minLength: 1 },
|
|
287
|
+
export: { type: "string", minLength: 1 },
|
|
288
|
+
},
|
|
289
|
+
additionalProperties: false,
|
|
290
|
+
} as const;
|
|
291
|
+
|
|
292
|
+
// implements REQ-kibi-source-proof-kinds
|
|
293
|
+
const SOURCE_SPEC_SCHEMA = {
|
|
294
|
+
type: "object",
|
|
295
|
+
description:
|
|
296
|
+
"A project source Kibi reads by itself. reader json or yaml: {file, path?, select?: keys|values|items}. glob: {pattern, capture?, ignore?} (capture true reads what each * matched). openapi: {file, select?: operations|unsecured_operations|security_schemes|responses}. references: {files, extract: env|imports|calls|string_args|thrown|property, callee?, key?, ignore?}. schema: {format: drizzle|prisma|sql, file (drizzle, prisma) or files (sql migrations), exports?, table?, select?: tables|columns|required_columns|nullable_columns|foreign_keys}. routes: {file, export, framework?: hono|express, path_prefix?, names_from?, select?: routes|middleware}. validator: {file, export, select?: fields|required_fields|optional_fields}. Paths are repository-relative. A member Kibi cannot read statically fails the read with its location.",
|
|
297
|
+
required: ["reader"],
|
|
298
|
+
properties: {
|
|
299
|
+
reader: { type: "string", enum: [...SOURCE_READERS] },
|
|
300
|
+
},
|
|
301
|
+
additionalProperties: true,
|
|
302
|
+
} as const;
|
|
303
|
+
|
|
304
|
+
const SOURCE_DOMAIN_SCHEMA = {
|
|
305
|
+
type: "object",
|
|
306
|
+
required: ["source"],
|
|
307
|
+
properties: { source: SOURCE_SPEC_SCHEMA },
|
|
308
|
+
additionalProperties: false,
|
|
309
|
+
} as const;
|
|
310
|
+
|
|
311
|
+
const PREDICATE_SOURCE_SCHEMA = {
|
|
312
|
+
type: "object",
|
|
313
|
+
required: ["symbol_id"],
|
|
314
|
+
properties: {
|
|
315
|
+
symbol_id: { type: "string", minLength: 1 },
|
|
316
|
+
export: {
|
|
317
|
+
type: "string",
|
|
318
|
+
minLength: 1,
|
|
319
|
+
description:
|
|
320
|
+
"The exported function's name in the symbol's source file. Without it Kibi reads the export named by the symbol's title.",
|
|
321
|
+
},
|
|
322
|
+
harness_for: {
|
|
323
|
+
type: "array",
|
|
324
|
+
minItems: 1,
|
|
325
|
+
items: { type: "string", minLength: 1 },
|
|
326
|
+
description:
|
|
327
|
+
"The predicate is a test harness that decides the predicate by driving these code symbols (for example by calling the handler with each role). The symbols must be covered_by the test; a claim the harness proves is bound with scope harness.",
|
|
328
|
+
},
|
|
194
329
|
},
|
|
195
330
|
additionalProperties: false,
|
|
196
331
|
} as const;
|
|
@@ -218,6 +353,109 @@ export const PROOF_CONTRACT_SCHEMA = {
|
|
|
218
353
|
},
|
|
219
354
|
},
|
|
220
355
|
success_policy: { type: "string", enum: [...SUCCESS_POLICIES] },
|
|
356
|
+
kind: {
|
|
357
|
+
type: "string",
|
|
358
|
+
enum: [...PROOF_KINDS],
|
|
359
|
+
description:
|
|
360
|
+
"What the checker establishes; absent means e2e. exhaustive, typecheck, arithmetic, smt, rule, state_machine and regex must leave a kibi.code-certificate.v1 that Kibi re-checks before the receipt counts as proved. source reads the contract's source itself: the run may leave {version, kind: source, test_id, source} or nothing, and Kibi stores its own read as the certificate.",
|
|
361
|
+
},
|
|
362
|
+
source: {
|
|
363
|
+
...SOURCE_SPEC_SCHEMA,
|
|
364
|
+
description: `source: the project source a source proof reads. ${SOURCE_SPEC_SCHEMA.description}`,
|
|
365
|
+
},
|
|
366
|
+
domain_source: {
|
|
367
|
+
type: "object",
|
|
368
|
+
description:
|
|
369
|
+
"exhaustive and typecheck: the symbol that defines the finite domain (typecheck: also the type whose fields a required_fields fact names). state_machine: the transition table or next-state function. The proof must import it from its source file; a hand-listed domain downgrades the receipt to example. Kibi reads the export named `export`, or the symbol's title when `export` is absent.",
|
|
370
|
+
required: ["symbol_id"],
|
|
371
|
+
properties: {
|
|
372
|
+
symbol_id: { type: "string", minLength: 1 },
|
|
373
|
+
export: {
|
|
374
|
+
type: "string",
|
|
375
|
+
minLength: 1,
|
|
376
|
+
description:
|
|
377
|
+
"The name the domain is exported under in the symbol's source file, when the symbol's title is not that name.",
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
additionalProperties: false,
|
|
381
|
+
},
|
|
382
|
+
witness: {
|
|
383
|
+
type: "object",
|
|
384
|
+
description:
|
|
385
|
+
"typecheck: the repository-relative witness file Kibi compiles (an exhaustive switch ending in never, or a mapped type over the domain).",
|
|
386
|
+
required: ["path"],
|
|
387
|
+
properties: { path: { type: "string", minLength: 1 } },
|
|
388
|
+
additionalProperties: false,
|
|
389
|
+
},
|
|
390
|
+
proves: {
|
|
391
|
+
type: "array",
|
|
392
|
+
description:
|
|
393
|
+
"Certificate kinds: the requirement claim keys (CLAIM-...) this certificate proves. Each must be a modeled claim of a current requirement the test reaches through its scenarios. Kibi derives what the certificate must establish from the claim's grounding fact (a set fact for exhaustive or typecheck, a numeric fact for arithmetic or smt, a rule, predicate or set fact for rule and state_machine, a string fact for regex); a claim with no such derivation is only attested and never counts as proved.",
|
|
394
|
+
minItems: 1,
|
|
395
|
+
items: { type: "string", pattern: "^CLAIM-" },
|
|
396
|
+
uniqueItems: true,
|
|
397
|
+
},
|
|
398
|
+
value_source: {
|
|
399
|
+
type: "array",
|
|
400
|
+
description:
|
|
401
|
+
"arithmetic and smt: code constants the assumptions read. Kibi evaluates each export at ingest and requires the certificate to assume the variable equals that value, so the proof is about the code and not only the knowledge base. With measure count the value is the size of a list, set, map or object export, so a count claim reads the collection itself. An entry {source, measure: count} counts the members Kibi reads from a project source (routes, tables, environment variables).",
|
|
402
|
+
minItems: 1,
|
|
403
|
+
items: {
|
|
404
|
+
type: "object",
|
|
405
|
+
properties: {
|
|
406
|
+
symbol_id: { type: "string", minLength: 1 },
|
|
407
|
+
export: { type: "string", minLength: 1 },
|
|
408
|
+
source: SOURCE_SPEC_SCHEMA,
|
|
409
|
+
measure: {
|
|
410
|
+
type: "string",
|
|
411
|
+
enum: ["value", "count"],
|
|
412
|
+
description:
|
|
413
|
+
"value (default for an export): the export is a number. count (the only measure of a source): the number of members of a list, set, map or object export, or of a source.",
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
additionalProperties: false,
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
predicate_source: {
|
|
420
|
+
type: "object",
|
|
421
|
+
description:
|
|
422
|
+
"rule: the code function behind each predicate a claim's rule, predicate or set fact names, keyed by predicate name. Each export takes the predicate's arguments in order and returns a boolean; Kibi calls it on every combination of its argument domains.",
|
|
423
|
+
minProperties: 1,
|
|
424
|
+
additionalProperties: PREDICATE_SOURCE_SCHEMA,
|
|
425
|
+
},
|
|
426
|
+
domains: {
|
|
427
|
+
type: "object",
|
|
428
|
+
description:
|
|
429
|
+
"rule: the finite domain of each argument type, keyed by type name (an array, Set, Map or object export, or a Python list, set, dict or Enum), or {source} for the members Kibi reads from a project source (every route, every table, every environment variable). state_machine with a next-state function: the `state` and `event` domains it is called on.",
|
|
430
|
+
minProperties: 1,
|
|
431
|
+
additionalProperties: {
|
|
432
|
+
anyOf: [SOURCE_REFERENCE_SCHEMA, SOURCE_DOMAIN_SCHEMA],
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
initial_source: {
|
|
436
|
+
...SOURCE_REFERENCE_SCHEMA,
|
|
437
|
+
description:
|
|
438
|
+
"state_machine: the export holding the initial state (or states), needed for initial_states and reachable_states facts.",
|
|
439
|
+
},
|
|
440
|
+
pattern_source: {
|
|
441
|
+
...SOURCE_REFERENCE_SCHEMA,
|
|
442
|
+
description:
|
|
443
|
+
"regex: the export holding the code's pattern (a RegExp, or a Python re.Pattern) or string constant that a string fact is about.",
|
|
444
|
+
},
|
|
445
|
+
constraint_source: {
|
|
446
|
+
type: "object",
|
|
447
|
+
description:
|
|
448
|
+
"arithmetic and smt: the typed numeric property_value facts the certificate's assumptions come from. Kibi checks the assumptions (or the query's assertions) are exactly these facts' constraints, so the proof is about the knowledge base, not numbers the test chose.",
|
|
449
|
+
required: ["fact_ids"],
|
|
450
|
+
properties: {
|
|
451
|
+
fact_ids: {
|
|
452
|
+
type: "array",
|
|
453
|
+
minItems: 1,
|
|
454
|
+
items: { type: "string", minLength: 1 },
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
additionalProperties: false,
|
|
458
|
+
},
|
|
221
459
|
},
|
|
222
460
|
additionalProperties: false,
|
|
223
461
|
} as const;
|
|
@@ -479,6 +717,24 @@ export function proofRunArtifactErrors(value: unknown): string[] {
|
|
|
479
717
|
)
|
|
480
718
|
errors.push("artifact.diagnostics must be an array of non-empty strings");
|
|
481
719
|
}
|
|
720
|
+
if (artifact.certificates !== undefined) {
|
|
721
|
+
if (!Array.isArray(artifact.certificates))
|
|
722
|
+
errors.push("artifact.certificates must be an array when present");
|
|
723
|
+
else
|
|
724
|
+
artifact.certificates.forEach((entry, index) => {
|
|
725
|
+
const row = record(entry);
|
|
726
|
+
if (
|
|
727
|
+
!row ||
|
|
728
|
+
!nonEmptyString(row.version) ||
|
|
729
|
+
!includes(CERTIFICATE_PROOF_KINDS, row.kind) ||
|
|
730
|
+
!nonEmptyString(row.test_id) ||
|
|
731
|
+
!isPlainJson(row)
|
|
732
|
+
)
|
|
733
|
+
errors.push(
|
|
734
|
+
`artifact.certificates[${index}] must be a JSON object with version, a certificate kind (${CERTIFICATE_PROOF_KINDS.join(", ")}) and test_id`,
|
|
735
|
+
);
|
|
736
|
+
});
|
|
737
|
+
}
|
|
482
738
|
return errors;
|
|
483
739
|
}
|
|
484
740
|
|
|
@@ -537,9 +793,444 @@ export function proofContractErrors(value: unknown): string[] {
|
|
|
537
793
|
errors.push(
|
|
538
794
|
`proof_contract.success_policy must be one of: ${SUCCESS_POLICIES.join(", ")}; received ${JSON.stringify(contract.success_policy ?? null)}`,
|
|
539
795
|
);
|
|
796
|
+
errors.push(...proofContractKindErrors(contract));
|
|
540
797
|
return errors;
|
|
541
798
|
}
|
|
542
799
|
|
|
800
|
+
// implements REQ-kibi-code-proof-kinds
|
|
801
|
+
function proofContractKindErrors(contract: Record<string, unknown>): string[] {
|
|
802
|
+
const errors: string[] = [];
|
|
803
|
+
const kind = contract.kind;
|
|
804
|
+
if (kind !== undefined && !includes(PROOF_KINDS, kind))
|
|
805
|
+
errors.push(
|
|
806
|
+
`proof_contract.kind must be one of: ${PROOF_KINDS.join(", ")}; received ${JSON.stringify(kind)}`,
|
|
807
|
+
);
|
|
808
|
+
const domain = contract.domain_source;
|
|
809
|
+
if (domain !== undefined) {
|
|
810
|
+
const row = record(domain);
|
|
811
|
+
if (
|
|
812
|
+
!row ||
|
|
813
|
+
!nonEmptyString(row.symbol_id) ||
|
|
814
|
+
(row.export !== undefined && !nonEmptyString(row.export)) ||
|
|
815
|
+
Object.keys(row).some((key) => key !== "symbol_id" && key !== "export")
|
|
816
|
+
)
|
|
817
|
+
errors.push(
|
|
818
|
+
"proof_contract.domain_source must be {symbol_id, export?} naming the symbol that defines the domain and, when its title is not the export name, the export to read",
|
|
819
|
+
);
|
|
820
|
+
} else if (kind === "exhaustive" || kind === "typecheck")
|
|
821
|
+
errors.push(
|
|
822
|
+
`proof_contract.domain_source is required for kind ${String(kind)}: name the symbol the proof reads its domain from`,
|
|
823
|
+
);
|
|
824
|
+
const witness = contract.witness;
|
|
825
|
+
if (witness !== undefined) {
|
|
826
|
+
const row = record(witness);
|
|
827
|
+
if (!row || !nonEmptyString(row.path) || Object.keys(row).length !== 1)
|
|
828
|
+
errors.push(
|
|
829
|
+
"proof_contract.witness must be {path} naming the repository-relative witness file",
|
|
830
|
+
);
|
|
831
|
+
} else if (kind === "typecheck")
|
|
832
|
+
errors.push(
|
|
833
|
+
"proof_contract.witness is required for kind typecheck: name the file the type checker compiles",
|
|
834
|
+
);
|
|
835
|
+
const source = contract.constraint_source;
|
|
836
|
+
if (source !== undefined) {
|
|
837
|
+
const row = record(source);
|
|
838
|
+
const ids = row?.fact_ids;
|
|
839
|
+
if (
|
|
840
|
+
!row ||
|
|
841
|
+
Object.keys(row).length !== 1 ||
|
|
842
|
+
!Array.isArray(ids) ||
|
|
843
|
+
ids.length === 0 ||
|
|
844
|
+
!ids.every(nonEmptyString)
|
|
845
|
+
)
|
|
846
|
+
errors.push(
|
|
847
|
+
"proof_contract.constraint_source must be {fact_ids: [FACT-...]} naming the facts the assumptions come from",
|
|
848
|
+
);
|
|
849
|
+
} else if (
|
|
850
|
+
(kind === "arithmetic" || kind === "smt") &&
|
|
851
|
+
contract.value_source === undefined
|
|
852
|
+
)
|
|
853
|
+
errors.push(
|
|
854
|
+
`proof_contract.constraint_source or value_source is required for kind ${String(kind)}: name the typed facts or code constants its assumptions come from`,
|
|
855
|
+
);
|
|
856
|
+
const valueSource = contract.value_source;
|
|
857
|
+
if (valueSource !== undefined) {
|
|
858
|
+
if (Array.isArray(valueSource))
|
|
859
|
+
valueSource.forEach((entry, index) => {
|
|
860
|
+
const row = record(entry);
|
|
861
|
+
if (row === null || row.source === undefined) return;
|
|
862
|
+
errors.push(
|
|
863
|
+
...sourceSpecErrors(
|
|
864
|
+
row.source,
|
|
865
|
+
`proof_contract.value_source[${index}].source`,
|
|
866
|
+
),
|
|
867
|
+
);
|
|
868
|
+
if (row.symbol_id !== undefined || row.export !== undefined)
|
|
869
|
+
errors.push(
|
|
870
|
+
`proof_contract.value_source[${index}] names a source, so it takes no symbol_id or export`,
|
|
871
|
+
);
|
|
872
|
+
if (row.measure !== undefined && row.measure !== "count")
|
|
873
|
+
errors.push(
|
|
874
|
+
`proof_contract.value_source[${index}].measure must be count for a source: Kibi counts the members it reads`,
|
|
875
|
+
);
|
|
876
|
+
});
|
|
877
|
+
if (
|
|
878
|
+
!Array.isArray(valueSource) ||
|
|
879
|
+
valueSource.length === 0 ||
|
|
880
|
+
!valueSource.every((entry) => {
|
|
881
|
+
const row = record(entry);
|
|
882
|
+
if (row !== null && row.source !== undefined) return true;
|
|
883
|
+
return (
|
|
884
|
+
row !== null &&
|
|
885
|
+
nonEmptyString(row.symbol_id) &&
|
|
886
|
+
(row.export === undefined || nonEmptyString(row.export)) &&
|
|
887
|
+
(row.measure === undefined ||
|
|
888
|
+
row.measure === "value" ||
|
|
889
|
+
row.measure === "count") &&
|
|
890
|
+
Object.keys(row).every(
|
|
891
|
+
(key) =>
|
|
892
|
+
key === "symbol_id" || key === "export" || key === "measure",
|
|
893
|
+
)
|
|
894
|
+
);
|
|
895
|
+
})
|
|
896
|
+
)
|
|
897
|
+
errors.push(
|
|
898
|
+
"proof_contract.value_source must be [{symbol_id, export?, measure?: value|count} or {source, measure?: count}] naming the code constants or project sources the assumptions read",
|
|
899
|
+
);
|
|
900
|
+
else if (kind !== "arithmetic" && kind !== "smt")
|
|
901
|
+
errors.push(
|
|
902
|
+
`proof_contract.value_source applies only to kind arithmetic or smt, not ${String(kind ?? "e2e")}`,
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
errors.push(...nonNumericContractErrors(contract));
|
|
906
|
+
errors.push(...sourceContractErrors(contract));
|
|
907
|
+
const proves = contract.proves;
|
|
908
|
+
if (proves !== undefined) {
|
|
909
|
+
if (
|
|
910
|
+
!Array.isArray(proves) ||
|
|
911
|
+
proves.length === 0 ||
|
|
912
|
+
!proves.every(
|
|
913
|
+
(key) => typeof key === "string" && /^CLAIM-[A-Za-z0-9]+$/.test(key),
|
|
914
|
+
) ||
|
|
915
|
+
new Set(proves).size !== proves.length
|
|
916
|
+
)
|
|
917
|
+
errors.push(
|
|
918
|
+
"proof_contract.proves must be a non-empty list of distinct claim keys (CLAIM-...) the certificate proves",
|
|
919
|
+
);
|
|
920
|
+
else if (!isCertificateProofKind(kind))
|
|
921
|
+
errors.push(
|
|
922
|
+
`proof_contract.proves applies only to certificate kinds (${CERTIFICATE_PROOF_KINDS.join(", ")}), not ${String(kind ?? "e2e")}`,
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
return errors;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
function isSourceReference(value: unknown): boolean {
|
|
929
|
+
const row = record(value);
|
|
930
|
+
return (
|
|
931
|
+
row !== null &&
|
|
932
|
+
nonEmptyString(row.symbol_id) &&
|
|
933
|
+
(row.export === undefined || nonEmptyString(row.export)) &&
|
|
934
|
+
Object.keys(row).every((key) => key === "symbol_id" || key === "export")
|
|
935
|
+
);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
function isSourceMap(
|
|
939
|
+
value: unknown,
|
|
940
|
+
accepts: (entry: unknown) => boolean = isSourceReference,
|
|
941
|
+
): boolean {
|
|
942
|
+
const row = record(value);
|
|
943
|
+
return (
|
|
944
|
+
row !== null &&
|
|
945
|
+
Object.keys(row).length > 0 &&
|
|
946
|
+
Object.entries(row).every(
|
|
947
|
+
([key, entry]) => key.trim() !== "" && accepts(entry),
|
|
948
|
+
)
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
function isPredicateReference(value: unknown): boolean {
|
|
953
|
+
const row = record(value);
|
|
954
|
+
if (row === null || row.harness_for === undefined)
|
|
955
|
+
return isSourceReference(value);
|
|
956
|
+
const { harness_for: harness, ...reference } = row;
|
|
957
|
+
return (
|
|
958
|
+
isSourceReference(reference) &&
|
|
959
|
+
Array.isArray(harness) &&
|
|
960
|
+
harness.length > 0 &&
|
|
961
|
+
harness.every(nonEmptyString)
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
function isSourceDomain(value: unknown): boolean {
|
|
966
|
+
const row = record(value);
|
|
967
|
+
return (
|
|
968
|
+
row !== null && Object.keys(row).length === 1 && row.source !== undefined
|
|
969
|
+
);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* The source kind and the source-backed rule domains: a well-formed source
|
|
974
|
+
* spec, required for kind source and only there.
|
|
975
|
+
*/
|
|
976
|
+
// implements REQ-kibi-source-proof-kinds
|
|
977
|
+
function sourceContractErrors(contract: Record<string, unknown>): string[] {
|
|
978
|
+
const errors: string[] = [];
|
|
979
|
+
const kind = contract.kind;
|
|
980
|
+
if (contract.source !== undefined) {
|
|
981
|
+
errors.push(...sourceSpecErrors(contract.source, "proof_contract.source"));
|
|
982
|
+
if (kind !== "source")
|
|
983
|
+
errors.push(
|
|
984
|
+
`proof_contract.source applies only to kind source, not ${String(kind ?? "e2e")}`,
|
|
985
|
+
);
|
|
986
|
+
} else if (kind === "source")
|
|
987
|
+
errors.push(
|
|
988
|
+
"proof_contract.source is required for kind source: name the project source Kibi reads (reader json, yaml, glob, openapi, references, schema, routes or validator)",
|
|
989
|
+
);
|
|
990
|
+
const domains = record(contract.domains);
|
|
991
|
+
for (const [type, entry] of Object.entries(domains ?? {}))
|
|
992
|
+
if (isSourceDomain(entry)) {
|
|
993
|
+
errors.push(
|
|
994
|
+
...sourceSpecErrors(
|
|
995
|
+
record(entry)?.source,
|
|
996
|
+
`proof_contract.domains.${type}.source`,
|
|
997
|
+
),
|
|
998
|
+
);
|
|
999
|
+
if (kind !== "rule")
|
|
1000
|
+
errors.push(
|
|
1001
|
+
`proof_contract.domains.${type}.source applies only to kind rule: a state machine's domains are the code's`,
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
return errors;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
/**
|
|
1008
|
+
* The contract fields of the rule, state_machine and regex kinds: where the
|
|
1009
|
+
* code Kibi evaluates lives, and only on the kinds that read it.
|
|
1010
|
+
*/
|
|
1011
|
+
// implements REQ-kibi-non-numeric-proof-kinds
|
|
1012
|
+
function nonNumericContractErrors(contract: Record<string, unknown>): string[] {
|
|
1013
|
+
const errors: string[] = [];
|
|
1014
|
+
const kind = contract.kind;
|
|
1015
|
+
const only = (field: string, kinds: readonly string[]) => {
|
|
1016
|
+
if (contract[field] !== undefined && !kinds.includes(String(kind)))
|
|
1017
|
+
errors.push(
|
|
1018
|
+
`proof_contract.${field} applies only to kind ${kinds.join(" or ")}, not ${String(kind ?? "e2e")}`,
|
|
1019
|
+
);
|
|
1020
|
+
};
|
|
1021
|
+
if (
|
|
1022
|
+
contract.predicate_source !== undefined &&
|
|
1023
|
+
!isSourceMap(contract.predicate_source, isPredicateReference)
|
|
1024
|
+
)
|
|
1025
|
+
errors.push(
|
|
1026
|
+
"proof_contract.predicate_source must map each predicate name to {symbol_id, export?, harness_for?} naming the function that decides it",
|
|
1027
|
+
);
|
|
1028
|
+
if (
|
|
1029
|
+
contract.domains !== undefined &&
|
|
1030
|
+
!isSourceMap(
|
|
1031
|
+
contract.domains,
|
|
1032
|
+
(entry) => isSourceReference(entry) || isSourceDomain(entry),
|
|
1033
|
+
)
|
|
1034
|
+
)
|
|
1035
|
+
errors.push(
|
|
1036
|
+
"proof_contract.domains must map each argument type to {symbol_id, export?} naming the export that lists its values, or {source} naming the project source Kibi reads them from",
|
|
1037
|
+
);
|
|
1038
|
+
for (const field of ["initial_source", "pattern_source"])
|
|
1039
|
+
if (contract[field] !== undefined && !isSourceReference(contract[field]))
|
|
1040
|
+
errors.push(
|
|
1041
|
+
`proof_contract.${field} must be {symbol_id, export?} naming the export Kibi reads`,
|
|
1042
|
+
);
|
|
1043
|
+
only("predicate_source", ["rule"]);
|
|
1044
|
+
only("domains", ["rule", "state_machine"]);
|
|
1045
|
+
only("initial_source", ["state_machine"]);
|
|
1046
|
+
only("pattern_source", ["regex"]);
|
|
1047
|
+
if (kind === "rule") {
|
|
1048
|
+
if (contract.predicate_source === undefined)
|
|
1049
|
+
errors.push(
|
|
1050
|
+
"proof_contract.predicate_source is required for kind rule: name the function behind each predicate the claims use",
|
|
1051
|
+
);
|
|
1052
|
+
if (contract.domains === undefined)
|
|
1053
|
+
errors.push(
|
|
1054
|
+
"proof_contract.domains is required for kind rule: name the export listing each argument type's values",
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
if (kind === "state_machine") {
|
|
1058
|
+
if (contract.domain_source === undefined)
|
|
1059
|
+
errors.push(
|
|
1060
|
+
"proof_contract.domain_source is required for kind state_machine: name the transition table or next-state function",
|
|
1061
|
+
);
|
|
1062
|
+
const domains = record(contract.domains);
|
|
1063
|
+
if (
|
|
1064
|
+
domains !== null &&
|
|
1065
|
+
(Object.keys(domains).length !== 2 ||
|
|
1066
|
+
domains.state === undefined ||
|
|
1067
|
+
domains.event === undefined)
|
|
1068
|
+
)
|
|
1069
|
+
errors.push(
|
|
1070
|
+
"proof_contract.domains for kind state_machine must name exactly the state and event domains a next-state function is called on",
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
if (kind === "regex" && contract.pattern_source === undefined)
|
|
1074
|
+
errors.push(
|
|
1075
|
+
"proof_contract.pattern_source is required for kind regex: name the export holding the pattern or string",
|
|
1076
|
+
);
|
|
1077
|
+
return errors;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* The optional contract fields beyond the v1 core, copied only when present
|
|
1082
|
+
* so existing contracts keep their hash.
|
|
1083
|
+
*/
|
|
1084
|
+
// implements REQ-kibi-code-proof-kinds
|
|
1085
|
+
export function optionalProofContractFields(
|
|
1086
|
+
contract: Record<string, unknown>,
|
|
1087
|
+
): Pick<
|
|
1088
|
+
ProofContract,
|
|
1089
|
+
| "kind"
|
|
1090
|
+
| "domain_source"
|
|
1091
|
+
| "witness"
|
|
1092
|
+
| "constraint_source"
|
|
1093
|
+
| "value_source"
|
|
1094
|
+
| "proves"
|
|
1095
|
+
| "predicate_source"
|
|
1096
|
+
| "domains"
|
|
1097
|
+
| "initial_source"
|
|
1098
|
+
| "pattern_source"
|
|
1099
|
+
| "source"
|
|
1100
|
+
> {
|
|
1101
|
+
const fields: {
|
|
1102
|
+
kind?: ProofKind;
|
|
1103
|
+
domain_source?: { symbol_id: string; export?: string };
|
|
1104
|
+
witness?: { path: string };
|
|
1105
|
+
constraint_source?: { fact_ids: string[] };
|
|
1106
|
+
value_source?: ValueSourceEntry[];
|
|
1107
|
+
proves?: string[];
|
|
1108
|
+
predicate_source?: Record<string, PredicateReference>;
|
|
1109
|
+
domains?: Record<string, SourceReference | { source: SourceSpec }>;
|
|
1110
|
+
initial_source?: SourceReference;
|
|
1111
|
+
pattern_source?: SourceReference;
|
|
1112
|
+
source?: SourceSpec;
|
|
1113
|
+
} = {};
|
|
1114
|
+
if (typeof contract.kind === "string")
|
|
1115
|
+
fields.kind = contract.kind as ProofKind;
|
|
1116
|
+
const domain = record(contract.domain_source);
|
|
1117
|
+
if (domain && typeof domain.symbol_id === "string")
|
|
1118
|
+
fields.domain_source = {
|
|
1119
|
+
symbol_id: domain.symbol_id,
|
|
1120
|
+
...(typeof domain.export === "string" ? { export: domain.export } : {}),
|
|
1121
|
+
};
|
|
1122
|
+
const witness = record(contract.witness);
|
|
1123
|
+
if (witness && typeof witness.path === "string")
|
|
1124
|
+
fields.witness = { path: witness.path };
|
|
1125
|
+
const source = record(contract.constraint_source);
|
|
1126
|
+
if (source && Array.isArray(source.fact_ids))
|
|
1127
|
+
fields.constraint_source = {
|
|
1128
|
+
fact_ids: source.fact_ids.filter(
|
|
1129
|
+
(id): id is string => typeof id === "string",
|
|
1130
|
+
),
|
|
1131
|
+
};
|
|
1132
|
+
if (Array.isArray(contract.value_source))
|
|
1133
|
+
fields.value_source = contract.value_source
|
|
1134
|
+
.map((entry) => record(entry))
|
|
1135
|
+
.map((row): ValueSourceEntry | null => {
|
|
1136
|
+
if (row === null) return null;
|
|
1137
|
+
const spec = normalizeSourceSpec(row.source);
|
|
1138
|
+
if (spec !== undefined) return { source: spec, measure: "count" };
|
|
1139
|
+
if (typeof row.symbol_id !== "string") return null;
|
|
1140
|
+
return {
|
|
1141
|
+
symbol_id: row.symbol_id,
|
|
1142
|
+
...(typeof row.export === "string" ? { export: row.export } : {}),
|
|
1143
|
+
...(row.measure === "value" || row.measure === "count"
|
|
1144
|
+
? { measure: row.measure }
|
|
1145
|
+
: {}),
|
|
1146
|
+
};
|
|
1147
|
+
})
|
|
1148
|
+
.filter((row): row is ValueSourceEntry => row !== null);
|
|
1149
|
+
if (Array.isArray(contract.proves))
|
|
1150
|
+
fields.proves = contract.proves.filter(
|
|
1151
|
+
(key): key is string => typeof key === "string",
|
|
1152
|
+
);
|
|
1153
|
+
const predicates = predicateMap(contract.predicate_source);
|
|
1154
|
+
if (predicates !== undefined) fields.predicate_source = predicates;
|
|
1155
|
+
const domains = domainMap(contract.domains);
|
|
1156
|
+
if (domains !== undefined) fields.domains = domains;
|
|
1157
|
+
const spec = normalizeSourceSpec(contract.source);
|
|
1158
|
+
if (spec !== undefined) fields.source = spec;
|
|
1159
|
+
const initial = sourceReference(contract.initial_source);
|
|
1160
|
+
if (initial !== undefined) fields.initial_source = initial;
|
|
1161
|
+
const pattern = sourceReference(contract.pattern_source);
|
|
1162
|
+
if (pattern !== undefined) fields.pattern_source = pattern;
|
|
1163
|
+
return fields;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
type SourceReference = { symbol_id: string; export?: string };
|
|
1167
|
+
type PredicateReference = SourceReference & { harness_for?: string[] };
|
|
1168
|
+
type ValueSourceEntry =
|
|
1169
|
+
| { symbol_id: string; export?: string; measure?: "value" | "count" }
|
|
1170
|
+
| { source: SourceSpec; measure: "count" };
|
|
1171
|
+
|
|
1172
|
+
function predicateMap(
|
|
1173
|
+
value: unknown,
|
|
1174
|
+
): Record<string, PredicateReference> | undefined {
|
|
1175
|
+
const row = record(value);
|
|
1176
|
+
if (!row) return undefined;
|
|
1177
|
+
const out: Record<string, PredicateReference> = {};
|
|
1178
|
+
for (const [key, entry] of Object.entries(row)) {
|
|
1179
|
+
const reference = sourceReference(entry);
|
|
1180
|
+
if (reference === undefined) continue;
|
|
1181
|
+
const harness = record(entry)?.harness_for;
|
|
1182
|
+
out[key] = Array.isArray(harness)
|
|
1183
|
+
? {
|
|
1184
|
+
...reference,
|
|
1185
|
+
harness_for: harness.filter(
|
|
1186
|
+
(id): id is string => typeof id === "string",
|
|
1187
|
+
),
|
|
1188
|
+
}
|
|
1189
|
+
: reference;
|
|
1190
|
+
}
|
|
1191
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
function domainMap(
|
|
1195
|
+
value: unknown,
|
|
1196
|
+
): Record<string, SourceReference | { source: SourceSpec }> | undefined {
|
|
1197
|
+
const row = record(value);
|
|
1198
|
+
if (!row) return undefined;
|
|
1199
|
+
const out: Record<string, SourceReference | { source: SourceSpec }> = {};
|
|
1200
|
+
for (const [key, entry] of Object.entries(row)) {
|
|
1201
|
+
const spec = normalizeSourceSpec(record(entry)?.source);
|
|
1202
|
+
if (spec !== undefined) {
|
|
1203
|
+
out[key] = { source: spec };
|
|
1204
|
+
continue;
|
|
1205
|
+
}
|
|
1206
|
+
const reference = sourceReference(entry);
|
|
1207
|
+
if (reference !== undefined) out[key] = reference;
|
|
1208
|
+
}
|
|
1209
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
function sourceReference(value: unknown): SourceReference | undefined {
|
|
1213
|
+
const row = record(value);
|
|
1214
|
+
if (!row || typeof row.symbol_id !== "string") return undefined;
|
|
1215
|
+
return {
|
|
1216
|
+
symbol_id: row.symbol_id,
|
|
1217
|
+
...(typeof row.export === "string" ? { export: row.export } : {}),
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
function sourceMap(
|
|
1222
|
+
value: unknown,
|
|
1223
|
+
): Record<string, SourceReference> | undefined {
|
|
1224
|
+
const row = record(value);
|
|
1225
|
+
if (!row) return undefined;
|
|
1226
|
+
const out: Record<string, SourceReference> = {};
|
|
1227
|
+
for (const [key, entry] of Object.entries(row)) {
|
|
1228
|
+
const reference = sourceReference(entry);
|
|
1229
|
+
if (reference !== undefined) out[key] = reference;
|
|
1230
|
+
}
|
|
1231
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
543
1234
|
export function proofBindingsErrors(value: unknown): string[] {
|
|
544
1235
|
if (!Array.isArray(value))
|
|
545
1236
|
return ["proof_bindings must be an array of binding objects"];
|