kibi-cli 2.36.0 → 2.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-json-command.d.ts.map +1 -1
- package/dist/cli-json-command.js +4 -0
- package/dist/cli-operation-metadata.d.ts +1 -1
- package/dist/cli-operation-metadata.js +1 -1
- package/dist/cli-register-foundation.d.ts.map +1 -1
- package/dist/cli-register-foundation.js +2 -1
- package/dist/cli-register-maintenance.d.ts.map +1 -1
- package/dist/cli-register-maintenance.js +5 -0
- package/dist/cli-register-reporting.d.ts.map +1 -1
- package/dist/cli-register-reporting.js +1 -0
- package/dist/cli-validate.d.ts.map +1 -1
- package/dist/cli-validate.js +21 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +19 -1
- package/dist/commands/aggregated-checks.d.ts.map +1 -1
- package/dist/commands/aggregated-checks.js +89 -16
- package/dist/commands/coverage.d.ts +1 -0
- package/dist/commands/coverage.d.ts.map +1 -1
- package/dist/commands/coverage.js +40 -0
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +70 -35
- package/dist/commands/github-init.d.ts.map +1 -1
- package/dist/commands/github-init.js +4 -2
- package/dist/commands/hook-managers.d.ts +43 -0
- package/dist/commands/hook-managers.d.ts.map +1 -0
- package/dist/commands/hook-managers.js +426 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +40 -5
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +9 -3
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +49 -1
- package/dist/commands/telemetry.d.ts +7 -0
- package/dist/commands/telemetry.d.ts.map +1 -0
- package/dist/commands/telemetry.js +23 -0
- package/dist/decision-firmness.d.ts.map +1 -1
- package/dist/decision-firmness.js +11 -14
- package/dist/engine-limits.d.ts.map +1 -1
- package/dist/engine-limits.js +8 -10
- package/dist/entity-body-context.d.ts.map +1 -1
- package/dist/entity-body-context.js +39 -36
- package/dist/extractors/markdown.d.ts +6 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +21 -0
- package/dist/extractors/symbol-coordinates.d.ts.map +1 -1
- package/dist/extractors/symbol-coordinates.js +23 -4
- package/dist/firm-decision-edit.d.ts.map +1 -1
- package/dist/firm-decision-edit.js +1 -3
- package/dist/intent-search.d.ts +5 -1
- package/dist/intent-search.d.ts.map +1 -1
- package/dist/intent-search.js +118 -33
- package/dist/logic/ir.d.ts.map +1 -1
- package/dist/logic/ir.js +82 -108
- package/dist/operations/bootstrap/discovery-evidence.d.ts.map +1 -1
- package/dist/operations/bootstrap/discovery-evidence.js +44 -2
- package/dist/operations/bootstrap/discovery.d.ts.map +1 -1
- package/dist/operations/bootstrap/discovery.js +1 -0
- package/dist/operations/bootstrap/guidance-actions.d.ts.map +1 -1
- package/dist/operations/bootstrap/guidance-actions.js +2 -1
- package/dist/operations/bootstrap/plugin-offers.d.ts +11 -2
- package/dist/operations/bootstrap/plugin-offers.d.ts.map +1 -1
- package/dist/operations/bootstrap/plugin-offers.js +48 -9
- package/dist/operations/proof/claim-bindings.d.ts.map +1 -1
- package/dist/operations/proof/claim-bindings.js +1 -0
- package/dist/operations/proof/code-certificates.d.ts +2 -0
- package/dist/operations/proof/code-certificates.d.ts.map +1 -1
- package/dist/operations/proof/code-certificates.js +34 -14
- package/dist/operations/proof/code-models.d.ts.map +1 -1
- package/dist/operations/proof/code-models.js +19 -5
- package/dist/operations/proof/code-runner.d.ts +16 -0
- package/dist/operations/proof/code-runner.d.ts.map +1 -1
- package/dist/operations/proof/code-runner.js +42 -6
- package/dist/operations/proof/explain.d.ts +63 -0
- package/dist/operations/proof/explain.d.ts.map +1 -1
- package/dist/operations/proof/explain.js +162 -0
- package/dist/operations/semantic-advisor/analyze-prose.d.ts +9 -1
- package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.js +21 -0
- package/dist/operations/semantic-advisor/case-preview.d.ts +24 -0
- package/dist/operations/semantic-advisor/case-preview.d.ts.map +1 -0
- package/dist/operations/semantic-advisor/case-preview.js +216 -0
- package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/shared.js +3 -0
- package/dist/operations/semantic-advisor/types.d.ts +23 -0
- package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
- package/dist/plugins/approved-source-analyzers.generated.d.ts +11 -8
- package/dist/plugins/approved-source-analyzers.generated.d.ts.map +1 -1
- package/dist/plugins/approved-source-analyzers.generated.js +11 -8
- package/dist/plugins/compose-search-hints.d.ts +29 -0
- package/dist/plugins/compose-search-hints.d.ts.map +1 -0
- package/dist/plugins/compose-search-hints.js +94 -0
- package/dist/plugins/external-allowlist.d.ts +7 -0
- package/dist/plugins/external-allowlist.d.ts.map +1 -1
- package/dist/plugins/external-allowlist.js +11 -0
- package/dist/plugins/registry.d.ts +8 -1
- package/dist/plugins/registry.d.ts.map +1 -1
- package/dist/plugins/registry.js +22 -3
- package/dist/plugins/source-classification.d.ts +2 -2
- package/dist/plugins/source-classification.d.ts.map +1 -1
- package/dist/plugins/source-classification.js +25 -1
- package/dist/prolog/codec.d.ts.map +1 -1
- package/dist/prolog/codec.js +10 -20
- package/dist/public/impact/coverage-depth-quality.d.ts.map +1 -1
- package/dist/public/impact/coverage-depth-quality.js +32 -16
- package/dist/public/impact/full-kb-quality.d.ts +6 -0
- package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
- package/dist/public/impact/full-kb-quality.js +8 -3
- package/dist/public/impact/requirement-quality.d.ts.map +1 -1
- package/dist/public/impact/requirement-quality.js +56 -29
- package/dist/public/operations/catalog.d.ts +44 -4
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts +6 -0
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +34 -2
- package/dist/public/operations/discovery-executors.d.ts +5 -1
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +65 -4
- package/dist/public/operations/evidence-floor.d.ts +8 -1
- package/dist/public/operations/evidence-floor.d.ts.map +1 -1
- package/dist/public/operations/evidence-floor.js +3 -4
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +41 -10
- package/dist/public/operations/node-ports.d.ts.map +1 -1
- package/dist/public/operations/node-ports.js +3 -1
- package/dist/public/operations/repair-plan.d.ts +46 -0
- package/dist/public/operations/repair-plan.d.ts.map +1 -1
- package/dist/public/operations/repair-plan.js +110 -1
- package/dist/public/operations/schema6-check-actions.js +1 -1
- package/dist/public/operations/source-analysis-cache.d.ts +22 -0
- package/dist/public/operations/source-analysis-cache.d.ts.map +1 -0
- package/dist/public/operations/source-analysis-cache.js +157 -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 +2 -1
- package/dist/public/operations/specs/check.d.ts +1 -1
- package/dist/public/operations/specs/discovery.d.ts +7 -2
- package/dist/public/operations/specs/discovery.d.ts.map +1 -1
- package/dist/public/operations/specs/discovery.js +7 -2
- package/dist/public/operations/specs/mutation-schemas.d.ts +36 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +30 -0
- package/dist/public/operations/specs/upsert.d.ts +36 -1
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/symbol-granularity-check.d.ts +3 -1
- package/dist/public/operations/symbol-granularity-check.d.ts.map +1 -1
- package/dist/public/operations/symbol-granularity-check.js +21 -7
- package/dist/public/proof-protocol.d.ts +6 -1
- package/dist/public/proof-protocol.d.ts.map +1 -1
- package/dist/public/proof-protocol.js +12 -3
- package/dist/public/proof-sources.d.ts +2 -0
- package/dist/public/proof-sources.d.ts.map +1 -1
- package/dist/public/proof-sources.js +32 -6
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +59 -0
- package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
- package/dist/public/skills/kibi-commit-review/SKILL.md +6 -2
- package/dist/public/skills/kibi-decisions/SKILL.md +7 -2
- package/dist/public/skills/kibi-decisions/resources/signoff-views.md +3 -1
- package/dist/public/skills/kibi-usage/SKILL.md +50 -3
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +34 -0
- package/dist/public/skills/kibi-usage/resources/proof.md +13 -5
- package/dist/public/skills/kibi-usage/resources/workflows.md +10 -0
- package/dist/relationships/shards.d.ts +2 -0
- package/dist/relationships/shards.d.ts.map +1 -1
- package/dist/relationships/shards.js +25 -1
- package/dist/schemas/entity.schema.json +98 -1
- package/dist/search-answer.d.ts +3 -2
- package/dist/search-answer.d.ts.map +1 -1
- package/dist/search-answer.js +57 -4
- package/dist/search-hints.d.ts +58 -0
- package/dist/search-hints.d.ts.map +1 -0
- package/dist/search-hints.js +187 -0
- package/dist/search-ranking.d.ts +7 -0
- package/dist/search-ranking.d.ts.map +1 -1
- package/dist/search-ranking.js +54 -56
- package/dist/search-token-cache.d.ts +30 -0
- package/dist/search-token-cache.d.ts.map +1 -0
- package/dist/search-token-cache.js +86 -0
- package/dist/traceability/impact-knowledge.d.ts.map +1 -1
- package/dist/traceability/impact-knowledge.js +2 -0
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +11 -1
- package/dist/types/entities.d.ts +12 -0
- package/dist/types/entities.d.ts.map +1 -1
- package/dist/usage-telemetry.d.ts +20 -0
- package/dist/usage-telemetry.d.ts.map +1 -0
- package/dist/usage-telemetry.js +93 -0
- package/dist/utils/branch-resolver.d.ts.map +1 -1
- package/dist/utils/branch-resolver.js +1 -0
- package/dist/utils/rule-registry.generated.d.ts +5 -0
- package/dist/utils/rule-registry.generated.d.ts.map +1 -1
- package/dist/utils/rule-registry.generated.js +6 -0
- package/package.json +5 -4
- package/schema/entities.pl +12 -0
- package/src/public/impact/coverage-depth-quality.ts +59 -21
- package/src/public/impact/full-kb-quality.ts +15 -1
- package/src/public/impact/requirement-quality.ts +95 -38
- package/src/public/operations/check-executor.ts +41 -1
- package/src/public/operations/discovery-executors.ts +92 -4
- package/src/public/operations/evidence-floor.ts +15 -3
- package/src/public/operations/migration-plan.ts +41 -9
- package/src/public/operations/node-ports.ts +3 -1
- package/src/public/operations/repair-plan.ts +152 -1
- package/src/public/operations/schema6-check-actions.ts +1 -1
- package/src/public/operations/source-analysis-cache.ts +196 -0
- package/src/public/operations/specs/check-rules.generated.ts +2 -1
- package/src/public/operations/specs/discovery.ts +8 -2
- package/src/public/operations/specs/mutation-schemas.ts +34 -0
- package/src/public/operations/symbol-granularity-check.ts +25 -5
- package/src/public/proof-protocol-types.d.ts +1 -1
- package/src/public/proof-protocol.ts +18 -4
- package/src/public/proof-sources.ts +37 -6
- package/src/public/schemas/entity.ts +65 -0
- package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
- package/src/public/skills/kibi-commit-review/SKILL.md +6 -2
- package/src/public/skills/kibi-decisions/SKILL.md +7 -2
- package/src/public/skills/kibi-decisions/resources/signoff-views.md +3 -1
- package/src/public/skills/kibi-usage/SKILL.md +50 -3
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +34 -0
- package/src/public/skills/kibi-usage/resources/proof.md +13 -5
- package/src/public/skills/kibi-usage/resources/workflows.md +10 -0
- package/src/schemas/entity.schema.json +98 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-json-command.d.ts","sourceRoot":"","sources":["../src/cli-json-command.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-json-command.d.ts","sourceRoot":"","sources":["../src/cli-json-command.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAIlE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAIpE;AAGD;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAW7E;AAGD,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS;QAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;KACpC,EAAE,CAAC;CACL,CAAC;AAmDF,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,cAAc,GACzB,OAAO,CAAC,IAAI,CAAC,CAgHf"}
|
package/dist/cli-json-command.js
CHANGED
|
@@ -6,6 +6,7 @@ import { executeOperation as executeProtocolOperation, openFailureResult, } from
|
|
|
6
6
|
import { prepareOperationInput } from "./cli-validate.js";
|
|
7
7
|
import { appendCliDiagnosticUsage, diagnosticEnvOptIn, } from "./public/diagnostic-usage.js";
|
|
8
8
|
import { createCliRuntime } from "./runtime/cli-runtime.js";
|
|
9
|
+
import { noteCliErrorCategory, noteCliResultError } from "./usage-telemetry.js";
|
|
9
10
|
export function writeOptionalStderr(stderr) {
|
|
10
11
|
if (stderr !== undefined) {
|
|
11
12
|
process.stderr.write(stderr);
|
|
@@ -31,6 +32,7 @@ export async function withConsoleOnStderr(fn) {
|
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
function writeInputError(error) {
|
|
35
|
+
noteCliErrorCategory(error.code);
|
|
34
36
|
process.stderr.write(`Error [${error.code}]: ${error.detail}\n`);
|
|
35
37
|
process.exitCode = error.exitCode;
|
|
36
38
|
}
|
|
@@ -173,5 +175,7 @@ export async function runJsonInvocation(invocation) {
|
|
|
173
175
|
await writeAndWaitForDrain(process.stdout, result.stdout);
|
|
174
176
|
}
|
|
175
177
|
writeOptionalStderr(result.stderr);
|
|
178
|
+
if (result.exitCode !== 0)
|
|
179
|
+
noteCliResultError(result.stdout);
|
|
176
180
|
process.exitCode = result.exitCode;
|
|
177
181
|
}
|
|
@@ -27,7 +27,7 @@ export declare const CLI_OPERATION_METADATA: readonly [{
|
|
|
27
27
|
}, {
|
|
28
28
|
readonly name: "kb_search";
|
|
29
29
|
readonly cliName: "search";
|
|
30
|
-
readonly description: "Ask the KB a question or search it. Default intent-v1 ranking accepts questions, host-agent semantic facets and changed-code source locations, returns evidence, abstains below its confidence threshold and adds an answer layer: the current requirements that govern the topic, what must stay true (linked facts), why (ADRs) and what verifies it (scenarios, tests). Use before changing behavior, then kb_query for exact follow-up. No mutation side effects.";
|
|
30
|
+
readonly description: "Ask the KB a question or search it. Default intent-v1 ranking accepts questions, host-agent semantic facets and changed-code source locations, returns evidence, abstains below its confidence threshold and adds an answer layer: the current requirements that govern the topic, what must stay true (linked facts), why (ADRs) and what verifies it (scenarios, tests). A weak answer may add queryAnalysis.hints from a search-hints plugin: requirements the question may mean, to re-ask with. Use before changing behavior, then kb_query for exact follow-up. No mutation side effects.";
|
|
31
31
|
}, {
|
|
32
32
|
readonly name: "kb_status";
|
|
33
33
|
readonly cliName: "status";
|
|
@@ -30,7 +30,7 @@ export const CLI_OPERATION_METADATA = [
|
|
|
30
30
|
{
|
|
31
31
|
name: "kb_search",
|
|
32
32
|
cliName: "search",
|
|
33
|
-
description: "Ask the KB a question or search it. Default intent-v1 ranking accepts questions, host-agent semantic facets and changed-code source locations, returns evidence, abstains below its confidence threshold and adds an answer layer: the current requirements that govern the topic, what must stay true (linked facts), why (ADRs) and what verifies it (scenarios, tests). Use before changing behavior, then kb_query for exact follow-up. No mutation side effects.",
|
|
33
|
+
description: "Ask the KB a question or search it. Default intent-v1 ranking accepts questions, host-agent semantic facets and changed-code source locations, returns evidence, abstains below its confidence threshold and adds an answer layer: the current requirements that govern the topic, what must stay true (linked facts), why (ADRs) and what verifies it (scenarios, tests). A weak answer may add queryAnalysis.hints from a search-hints plugin: requirements the question may mean, to re-ask with. Use before changing behavior, then kb_query for exact follow-up. No mutation side effects.",
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
name: "kb_status",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-register-foundation.d.ts","sourceRoot":"","sources":["../src/cli-register-foundation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"cli-register-foundation.d.ts","sourceRoot":"","sources":["../src/cli-register-foundation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAezC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiKjE"}
|
|
@@ -12,7 +12,8 @@ export function registerFoundationCommands(program) {
|
|
|
12
12
|
.option("--no-hooks", "Do not install git hooks (hooks installed by default)")
|
|
13
13
|
.option("--github", "Scaffold the GitHub Pages badge + requirement-health report workflow")
|
|
14
14
|
.option("--badge-only", "With --github, publish only the badge (opt out of the full report)")
|
|
15
|
-
.option("--print-hook <hook>", "Print a snippet that delegates an existing hook (pre-commit, post-checkout, post-merge, post-rewrite) to kibi, and write nothing")
|
|
15
|
+
.option("--print-hook <hook>", "Print a snippet that delegates an existing hook (pre-commit, post-checkout, post-merge, post-rewrite, or all) to kibi, and write nothing")
|
|
16
|
+
.option("--format <format>", "With --print-hook: shell (default), lefthook, husky or pre-commit")
|
|
16
17
|
.action(withExitCode(async (options) => (await import("./commands/init.js")).initCommand(options)));
|
|
17
18
|
program
|
|
18
19
|
.command("migrate")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-register-maintenance.d.ts","sourceRoot":"","sources":["../src/cli-register-maintenance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"cli-register-maintenance.d.ts","sourceRoot":"","sources":["../src/cli-register-maintenance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgMlE"}
|
|
@@ -68,6 +68,11 @@ export function registerMaintenanceCommands(program) {
|
|
|
68
68
|
.option("--format <format>", "Output format: json|table", "table")
|
|
69
69
|
.option("--limit <n>", "Limit rendered table rows", "50")
|
|
70
70
|
.action(withExitCode(async (options) => (await import("./commands/usage-remediation.js")).usageRemediationCommand(options)));
|
|
71
|
+
program
|
|
72
|
+
.command("telemetry [action]")
|
|
73
|
+
.description("Show, enable or disable anonymous usage telemetry (status|enable|disable)")
|
|
74
|
+
.option("--format <format>", "Output format: json|text", "text")
|
|
75
|
+
.action(withExitCode(async (action, options) => (await import("./commands/telemetry.js")).telemetryCommand(action, options)));
|
|
71
76
|
program
|
|
72
77
|
.command("merge-driver")
|
|
73
78
|
.description("Git merge driver: three-way merge .kb/symbols.yaml or a relationship shard by record id")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-register-reporting.d.ts","sourceRoot":"","sources":["../src/cli-register-reporting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYzC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"cli-register-reporting.d.ts","sourceRoot":"","sources":["../src/cli-register-reporting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYzC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4RhE"}
|
|
@@ -75,6 +75,7 @@ export function registerReportingCommands(program) {
|
|
|
75
75
|
.option("--migration-offset <n>", "Skip ready semantic-inventory migration batches", "0")
|
|
76
76
|
.option("--migration-predicate-limit <n>", "Maximum ranked predicate schemas per proposition", "5")
|
|
77
77
|
.option("--migration-predicate-min-score <score>", "Minimum predicate schema rank score", "0.35")
|
|
78
|
+
.option("--cases", "Print the edge cases derived from each requirement's typed claims, with their predicted outcome and covering scenarios", false)
|
|
78
79
|
.option("--format <format>", "Output format: json|table", "table")
|
|
79
80
|
.action(async (options, command) => {
|
|
80
81
|
if (options.input !== undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-validate.d.ts","sourceRoot":"","sources":["../src/cli-validate.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAGpE,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAGlE,MAAM,MAAM,mBAAmB,GAC3B;IACE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;CAC1C,GACD;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-validate.d.ts","sourceRoot":"","sources":["../src/cli-validate.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAGpE,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GACxB;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAGlE,MAAM,MAAM,mBAAmB,GAC3B;IACE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;CAC1C,GACD;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAsClE,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,GACb,mBAAmB,CA6BrB;AAGD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,GACb,gBAAgB,CAKlB"}
|
package/dist/cli-validate.js
CHANGED
|
@@ -2,6 +2,26 @@ import Ajv from "ajv";
|
|
|
2
2
|
function isObject(value) {
|
|
3
3
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4
4
|
}
|
|
5
|
+
// One validator per operation schema. Building an Ajv instance compiles the
|
|
6
|
+
// JSON Schema meta-schema, and a CLI call validates its input more than once.
|
|
7
|
+
const inputValidator = new Ajv({ allErrors: true, strict: false });
|
|
8
|
+
const compiledInputSchemas = new WeakMap();
|
|
9
|
+
function compileInputSchema(schema) {
|
|
10
|
+
let validator = compiledInputSchemas.get(schema);
|
|
11
|
+
if (validator === undefined) {
|
|
12
|
+
const exact = { ...schema, additionalProperties: false };
|
|
13
|
+
try {
|
|
14
|
+
validator = inputValidator.compile(exact);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// A schema whose $id the shared instance already holds for another
|
|
18
|
+
// schema object compiles on an instance of its own.
|
|
19
|
+
validator = new Ajv({ allErrors: true, strict: false }).compile(exact);
|
|
20
|
+
}
|
|
21
|
+
compiledInputSchemas.set(schema, validator);
|
|
22
|
+
}
|
|
23
|
+
return validator;
|
|
24
|
+
}
|
|
5
25
|
function formatValidationErrors(errors) {
|
|
6
26
|
return errors.map((error) => {
|
|
7
27
|
const location = error.instancePath.length > 0 ? error.instancePath : "/";
|
|
@@ -22,8 +42,7 @@ export function prepareOperationInput(input, schema) {
|
|
|
22
42
|
};
|
|
23
43
|
}
|
|
24
44
|
const businessInput = Object.fromEntries(Object.entries(input).filter(([key]) => key !== "_diagnostic_telemetry"));
|
|
25
|
-
const
|
|
26
|
-
const validator = new Ajv({ allErrors: true, strict: false }).compile(schemaWithExactTopLevel);
|
|
45
|
+
const validator = compileInputSchema(schema);
|
|
27
46
|
if (!validator(businessInput)) {
|
|
28
47
|
return {
|
|
29
48
|
valid: false,
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMtD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUrD;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,EAAE,MAAM,GAChB,OAAO,CAIT;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM7D;AAGD,wBAAgB,YAAY,IAAI,OAAO,CAiBtC;AAGD,wBAAsB,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAqC3C;AAED,wBAAsB,kBAAkB,CACtC,YAAY,UAAoD,EAChE,KAAK,cAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAGf"}
|
package/dist/cli.js
CHANGED
|
@@ -28,6 +28,7 @@ import { registerProofCommand } from "./cli-register-proof.js";
|
|
|
28
28
|
import { registerReportingCommands } from "./cli-register-reporting.js";
|
|
29
29
|
import { registerSkillsCommands } from "./cli-register-skills.js";
|
|
30
30
|
import { bootstrapKibiEnvironment } from "./env/bootstrap.js";
|
|
31
|
+
import { finishCliTelemetry, trackCommandPath } from "./usage-telemetry.js";
|
|
31
32
|
import { resolveWorkspaceCwd } from "./workspace-cwd.js";
|
|
32
33
|
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
33
34
|
export function packageVersion(value) {
|
|
@@ -70,14 +71,31 @@ export async function main() {
|
|
|
70
71
|
if (workspace.cwd !== process.cwd())
|
|
71
72
|
process.chdir(workspace.cwd);
|
|
72
73
|
bootstrapKibiEnvironment();
|
|
74
|
+
const startedAt = new Date();
|
|
75
|
+
const program = buildProgram();
|
|
76
|
+
const commandPath = trackCommandPath(program);
|
|
73
77
|
let exitCode = process.exitCode ?? 0;
|
|
78
|
+
let failure;
|
|
74
79
|
try {
|
|
75
|
-
await
|
|
80
|
+
await program.parseAsync(workspace.argv);
|
|
76
81
|
exitCode = process.exitCode ?? 0;
|
|
77
82
|
}
|
|
78
83
|
catch (error) {
|
|
84
|
+
failure = error;
|
|
79
85
|
exitCode = exitCodeFromCliFailure(error);
|
|
80
86
|
}
|
|
87
|
+
try {
|
|
88
|
+
await finishCliTelemetry({
|
|
89
|
+
commandPath: commandPath(),
|
|
90
|
+
packageVersion: packageVersion(packageJson),
|
|
91
|
+
startedAt,
|
|
92
|
+
exitCode: Number(exitCode),
|
|
93
|
+
error: failure,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Telemetry is best effort and never changes the exit code.
|
|
98
|
+
}
|
|
81
99
|
await Promise.all([process.stdout, process.stderr].map((stream) => stream.writableNeedDrain ? once(stream, "drain") : Promise.resolve()));
|
|
82
100
|
process.exit(exitCode);
|
|
83
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregated-checks.d.ts","sourceRoot":"","sources":["../../src/commands/aggregated-checks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"aggregated-checks.d.ts","sourceRoot":"","sources":["../../src/commands/aggregated-checks.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,cAAc,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAiB5C;;;;;GAKG;AAEH,wBAAgB,4BAA4B,CAC1C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAYR;AAsED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,EACpC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GACjC,OAAO,CAAC,SAAS,EAAE,CAAC,CAyEtB"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
1
3
|
import path from "node:path";
|
|
2
4
|
import { resolveKbPlPath } from "../prolog.js";
|
|
3
5
|
import { escapeAtom, toPrologAtom } from "../prolog/codec.js";
|
|
@@ -25,6 +27,68 @@ export function ontologyQualityOverridesGoal(env = process.env) {
|
|
|
25
27
|
; true
|
|
26
28
|
)`;
|
|
27
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* A private file the engine writes the violations JSON to. A large KB's
|
|
32
|
+
* report can exceed the engine's bounded output capacity, so the answer
|
|
33
|
+
* carries only a transport marker and the JSON travels through this file.
|
|
34
|
+
* A temp folder that cannot be written gives no file, and the engine answers
|
|
35
|
+
* the JSON instead.
|
|
36
|
+
*/
|
|
37
|
+
// implements REQ-003
|
|
38
|
+
function checkResultFile() {
|
|
39
|
+
let dir;
|
|
40
|
+
try {
|
|
41
|
+
dir = mkdtempSync(path.join(tmpdir(), "kibi-check-"));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return { path: undefined, dispose: () => { } };
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
path: path.join(dir, "violations.json"),
|
|
48
|
+
// rationale: the directory always exists when disposed, so `force` (which
|
|
49
|
+
// only ignores a missing path) never changes the outcome.
|
|
50
|
+
// Stryker disable next-line BooleanLiteral
|
|
51
|
+
dispose: () => rmSync(dir, { recursive: true, force: true }),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The aggregated checks goal. With a result file it prefers the transport
|
|
56
|
+
* predicate, which falls back to an answer when the engine cannot write the
|
|
57
|
+
* file, then the older file predicates; without one (or with an engine whose
|
|
58
|
+
* core predates both) it asks for the JSON as an answer.
|
|
59
|
+
*/
|
|
60
|
+
function aggregatedChecksQuery(checksPlPath, rulesAllowlist, resultPath) {
|
|
61
|
+
const target = resultPath === undefined ? "none" : toPrologAtom(resultPath);
|
|
62
|
+
const rules = rulesAllowlist
|
|
63
|
+
? `[${[...rulesAllowlist].map(toPrologAtom).join(",")}]`
|
|
64
|
+
: undefined;
|
|
65
|
+
const transport = rules
|
|
66
|
+
? `predicate_property(checks:check_selected_json_transport(_, _, _, _), _)
|
|
67
|
+
-> call(checks:check_selected_json_transport(${rules}, ${target}, Transport, JsonString))`
|
|
68
|
+
: `predicate_property(checks:check_all_json_transport(_, _, _, _), _)
|
|
69
|
+
-> call(checks:check_all_json_transport(${target}, false, Transport, JsonString))`;
|
|
70
|
+
const fileOnly = resultPath === undefined
|
|
71
|
+
? ""
|
|
72
|
+
: rules
|
|
73
|
+
? `predicate_property(checks:check_selected_json_file(_, _), _)
|
|
74
|
+
-> call(checks:check_selected_json_file(${rules}, ${target})), Transport = file
|
|
75
|
+
; `
|
|
76
|
+
: `predicate_property(checks:check_all_json_file(_, _), _)
|
|
77
|
+
-> call(checks:check_all_json_file(${target}, false)), Transport = file
|
|
78
|
+
; `;
|
|
79
|
+
const allAnswer = `predicate_property(checks:check_all_json_with_options(_, _), _)
|
|
80
|
+
-> call(checks:check_all_json_with_options(JsonString, false)), Transport = answer
|
|
81
|
+
; call(checks:check_all_json(JsonString)), Transport = answer`;
|
|
82
|
+
const answer = rules
|
|
83
|
+
? `predicate_property(checks:check_selected_json(_, _), _)
|
|
84
|
+
-> call(checks:check_selected_json(${rules}, JsonString)), Transport = answer
|
|
85
|
+
; ${allAnswer}`
|
|
86
|
+
: allAnswer;
|
|
87
|
+
const goal = `( ${transport}
|
|
88
|
+
; ${fileOnly}${answer}
|
|
89
|
+
)`;
|
|
90
|
+
return `(use_module('${escapeAtom(checksPlPath)}'), ${ontologyQualityOverridesGoal()}, ${goal})`;
|
|
91
|
+
}
|
|
28
92
|
/**
|
|
29
93
|
* Run all checks using the aggregated Prolog predicates.
|
|
30
94
|
* This makes a single Prolog call and parses JSON output, significantly
|
|
@@ -36,27 +100,36 @@ export async function runAggregatedChecks(prolog, rulesAllowlist) {
|
|
|
36
100
|
// implements REQ-003
|
|
37
101
|
const violations = [];
|
|
38
102
|
const checksPlPath = path.join(path.dirname(resolveKbPlPath()), "checks.pl");
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
103
|
+
const resultFile = checkResultFile();
|
|
104
|
+
let result;
|
|
105
|
+
let jsonString;
|
|
106
|
+
try {
|
|
107
|
+
result = await prolog.query(aggregatedChecksQuery(checksPlPath, rulesAllowlist, resultFile.path));
|
|
108
|
+
// rationale: the engine answers Transport "file" only after a successful
|
|
109
|
+
// query that was given a path, so neither guard changes which answers
|
|
110
|
+
// are read; they only narrow the path for the read.
|
|
111
|
+
// Stryker disable next-line ConditionalExpression,LogicalOperator
|
|
112
|
+
const mayRead = result.success && resultFile.path !== undefined;
|
|
113
|
+
if (mayRead && result.bindings.Transport === "file") {
|
|
114
|
+
try {
|
|
115
|
+
jsonString = readFileSync(resultFile.path, "utf8");
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// The engine wrote a file this process cannot read (an engine with
|
|
119
|
+
// another view of the temp folder): ask for the JSON as an answer.
|
|
120
|
+
result = await prolog.query(aggregatedChecksQuery(checksPlPath, rulesAllowlist, undefined));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
resultFile.dispose();
|
|
126
|
+
}
|
|
54
127
|
if (!result.success) {
|
|
55
128
|
throw new Error(`Aggregated checks query failed: ${result.error || "Unknown error"}`);
|
|
56
129
|
}
|
|
57
130
|
let violationsDict;
|
|
58
131
|
try {
|
|
59
|
-
|
|
132
|
+
jsonString ??= result.bindings.JsonString;
|
|
60
133
|
if (!jsonString) {
|
|
61
134
|
throw new Error("No JSON string in binding");
|
|
62
135
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/commands/coverage.ts"],"names":[],"mappings":"AAMA,UAAU,eAAe;IACvB,EAAE,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/commands/coverage.ts"],"names":[],"mappings":"AAMA,UAAU,eAAe;IACvB,EAAE,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAGD,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuC7E"}
|
|
@@ -26,5 +26,45 @@ export async function coverageCommand(options) {
|
|
|
26
26
|
migrationPredicateLimit: Number.parseInt(options.migrationPredicateLimit || "5", 10),
|
|
27
27
|
migrationPredicateMinScore: Number.parseFloat(options.migrationPredicateMinScore || "0.35"),
|
|
28
28
|
});
|
|
29
|
+
if (options.cases === true) {
|
|
30
|
+
printCaseTable(options.format, result.structuredContent);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
29
33
|
printDiscoveryResult(options.format, result.structuredContent, result.content[0]?.text ?? "Coverage summary unavailable.");
|
|
30
34
|
}
|
|
35
|
+
// implements REQ-kibi-case-coverage
|
|
36
|
+
// The edge cases of each returned requirement: one line per case with its
|
|
37
|
+
// predicted outcome and coverage, and the assumption an uncovered rejection
|
|
38
|
+
// case needs. JSON keeps the requirement id with its cases stage.
|
|
39
|
+
function printCaseTable(format, structured) {
|
|
40
|
+
const rows = Array.isArray(structured?.rows)
|
|
41
|
+
? structured.rows
|
|
42
|
+
: [];
|
|
43
|
+
const withCases = rows.flatMap((row) => {
|
|
44
|
+
const stages = row.proofStages;
|
|
45
|
+
const stage = stages?.cases;
|
|
46
|
+
return stage?.cases?.length ? [{ id: String(row.id), stage }] : [];
|
|
47
|
+
});
|
|
48
|
+
if (format === "json") {
|
|
49
|
+
console.log(JSON.stringify({ rows: withCases.map(({ id, stage }) => ({ id, cases: stage })) }, null, 2));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (withCases.length === 0) {
|
|
53
|
+
console.log("No requirement in this page has derived edge cases.");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const lines = [];
|
|
57
|
+
for (const { id, stage } of withCases) {
|
|
58
|
+
const summary = stage.summary ?? {};
|
|
59
|
+
lines.push(`${id}: ${stage.status} (${summary.covered ?? 0} covered, ${summary.uncovered ?? 0} uncovered, ${summary.unspecified ?? 0} unspecified, ${summary.waived ?? 0} waived)`);
|
|
60
|
+
for (const row of stage.cases ?? []) {
|
|
61
|
+
const where = row.coverage === "covered"
|
|
62
|
+
? ` by ${(row.scenarios ?? []).join(", ")}`
|
|
63
|
+
: "";
|
|
64
|
+
lines.push(` ${row.caseId} ${row.factId} ${row.constraint} -> ${row.predicted}: ${row.coverage}${where}`);
|
|
65
|
+
if (row.coverage === "uncovered" && row.predicted === "rejection")
|
|
66
|
+
lines.push(` assumes ${JSON.stringify(row.assumption ?? {})}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
console.log(lines.join("\n"));
|
|
70
|
+
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
export interface DoctorOptions {
|
|
2
2
|
format?: "json" | "table";
|
|
3
3
|
}
|
|
4
|
+
/** `doctor:capability_plugins+git_hooks` for the checks that failed. */
|
|
5
|
+
export declare function doctorFailureCategory(results: readonly {
|
|
6
|
+
name: string;
|
|
7
|
+
passed: boolean;
|
|
8
|
+
}[]): string | undefined;
|
|
4
9
|
export declare function doctorCommand(options?: DoctorOptions): Promise<{
|
|
5
10
|
exitCode: number;
|
|
6
11
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAiHA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAGD,wEAAwE;AACxE,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,GACpD,MAAM,GAAG,SAAS,CAUpB;AAGD,wBAAsB,aAAa,CACjC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAyH/B;AAED,wBAAsB,4BAA4B,CAChD,IAAI,GAAE,MAAM,OAAO,CAAC;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,CACT,GACxC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;;;;;;;;;;;;;MAkE3C;AAkGD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGzE;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAepB"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -25,6 +25,7 @@ import { kibiPackageVersions } from "../package-versions.js";
|
|
|
25
25
|
import { describeConfiguredCapabilityPlugins, readProjectKibiConfig, } from "../plugins/project-config.js";
|
|
26
26
|
import { SwiplResolutionError, inspectSwiplBundle, probeRequiredLibraries, resolveSwipl, } from "../prolog/swipl-resolver.js";
|
|
27
27
|
import { buildMigrationPlan, migrationAction, } from "../public/operations/migration-plan.js";
|
|
28
|
+
import { noteCliErrorCategory } from "../usage-telemetry.js";
|
|
28
29
|
import { resolveBranchAttachment, resolveReadBranchAttachment, } from "../utils/branch-resolver.js";
|
|
29
30
|
import { branchStoreCompilation, inspectBranchStore, storeLockTakeoverReason, uncompiledBranchStoreReason, } from "../utils/branch-store.js";
|
|
30
31
|
import { LEGACY_KB_MIGRATION_COMMAND, LEGACY_KB_MIGRATION_NOTE, } from "../utils/config.js";
|
|
@@ -32,6 +33,7 @@ import { resolveGitRepository, } from "../utils/git-repository-context.js";
|
|
|
32
33
|
import { readKbManifestStatus } from "../utils/kb-manifest.js";
|
|
33
34
|
import { manifestMergeDriverGaps, mergeDriverSetup, } from "../utils/merge-driver-setup.js";
|
|
34
35
|
import { LATEST_KB_SCHEMA_VERSION } from "../utils/schema-version.js";
|
|
36
|
+
import { detectHookManager, hookManagerCommands, missingKibiHookCommands, } from "./hook-managers.js";
|
|
35
37
|
import { KIBI_HOOK_BEGIN, hasManagedHooks, outdatedManagedHooks, } from "./init-helpers.js";
|
|
36
38
|
import { planLegacyStorageMigration } from "./legacy-storage-migration.js";
|
|
37
39
|
/**
|
|
@@ -45,6 +47,17 @@ const FIRST_PARTY_PLUGIN_SECRETS = {
|
|
|
45
47
|
/** Static Jev defaults — must stay aligned with kibi-plugin-jev (no import). */
|
|
46
48
|
const JEV_DEFAULT_MODEL = "jev-latest";
|
|
47
49
|
const JEV_MAX_TIMEOUT_MS = 120_000;
|
|
50
|
+
// implements REQ-kibi-anonymous-usage-telemetry
|
|
51
|
+
/** `doctor:capability_plugins+git_hooks` for the checks that failed. */
|
|
52
|
+
export function doctorFailureCategory(results) {
|
|
53
|
+
const failed = results
|
|
54
|
+
.filter((result) => !result.passed)
|
|
55
|
+
.map((result) => result.name
|
|
56
|
+
.toLowerCase()
|
|
57
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
58
|
+
.replace(/^_|_$/g, ""));
|
|
59
|
+
return failed.length === 0 ? undefined : `doctor:${failed.join("+")}`;
|
|
60
|
+
}
|
|
48
61
|
// implements REQ-003
|
|
49
62
|
export async function doctorCommand(options = {}) {
|
|
50
63
|
// The repository context is per-diagnostic-run state: clearing here keeps
|
|
@@ -110,6 +123,8 @@ export async function doctorCommand(options = {}) {
|
|
|
110
123
|
results.push({ name, ...(await check()) });
|
|
111
124
|
}
|
|
112
125
|
const allPassed = results.every((result) => result.passed);
|
|
126
|
+
// Usage telemetry names the failing checks by their fixed names.
|
|
127
|
+
noteCliErrorCategory(doctorFailureCategory(results));
|
|
113
128
|
const warnings = results.filter((result) => result.passed && result.warning === true).length;
|
|
114
129
|
const runtime = await runtimeProvenance();
|
|
115
130
|
const packageActions = await packageMigrationActions(runtime);
|
|
@@ -837,6 +852,47 @@ function hooksPathSuffix() {
|
|
|
837
852
|
: "";
|
|
838
853
|
return ` (core.hooksPath=${context.hooksPathConfig}${origin})`;
|
|
839
854
|
}
|
|
855
|
+
/**
|
|
856
|
+
* The hook manager (lefthook, husky, pre-commit) that owns this repository's
|
|
857
|
+
* hooks. Its hook files are generated runners, so the commands they run are
|
|
858
|
+
* read from the manager's configuration instead of the files Git executes.
|
|
859
|
+
*/
|
|
860
|
+
// implements REQ-git-hook-manager-integration
|
|
861
|
+
function doctorHookManager() {
|
|
862
|
+
const context = doctorRepositoryContext();
|
|
863
|
+
if (!context)
|
|
864
|
+
return null;
|
|
865
|
+
return detectHookManager(context.worktreeRoot, context.effectiveHooksDir, context.hooksPathConfig);
|
|
866
|
+
}
|
|
867
|
+
// implements REQ-git-hook-manager-integration
|
|
868
|
+
function checkHookManagerDelegation(manager, hooks, consequence) {
|
|
869
|
+
const worktreeRoot = doctorRepositoryContext()?.worktreeRoot ?? process.cwd();
|
|
870
|
+
const owner = `Managed by ${manager.name} (${manager.configPath})`;
|
|
871
|
+
const coverage = hooks.map((hook) => ({
|
|
872
|
+
hook,
|
|
873
|
+
missing: missingKibiHookCommands(hook, hookManagerCommands(manager.name, worktreeRoot, hook) ?? []),
|
|
874
|
+
}));
|
|
875
|
+
const gaps = coverage.filter((entry) => entry.missing.length > 0);
|
|
876
|
+
if (gaps.length === 0) {
|
|
877
|
+
const runs = coverage
|
|
878
|
+
.map(({ hook }) => `${hook} runs ${missingKibiHookCommands(hook, [])
|
|
879
|
+
.map((label) => `'${label}'`)
|
|
880
|
+
.join(" and ")}`)
|
|
881
|
+
.join("; ");
|
|
882
|
+
return { passed: true, message: `${owner}; ${runs}` };
|
|
883
|
+
}
|
|
884
|
+
// The manager may reach Kibi through a task runner or script that is not
|
|
885
|
+
// part of its configuration, so an invisible command is a warning only.
|
|
886
|
+
const described = gaps
|
|
887
|
+
.map(({ hook, missing }) => `${hook} does not visibly run ${missing.map((label) => `'${label}'`).join(" and ")}`)
|
|
888
|
+
.join("; ");
|
|
889
|
+
return {
|
|
890
|
+
passed: true,
|
|
891
|
+
warning: true,
|
|
892
|
+
message: `${owner}; ${described}. Kibi reads only the ${manager.name} configuration, not the task runners or scripts it calls; unless they run these commands, ${consequence}`,
|
|
893
|
+
remediation: `Add Kibi's commands to ${manager.configPath}. Print them with: kibi init --print-hook ${gaps.length === 1 ? (gaps[0]?.hook ?? "all") : "all"} --format ${manager.name}`,
|
|
894
|
+
};
|
|
895
|
+
}
|
|
840
896
|
/**
|
|
841
897
|
* Kibi-managed hook sections must match what this CLI installs. A section
|
|
842
898
|
* written by an older CLI keeps running while silently lacking newer gates
|
|
@@ -870,6 +926,10 @@ function checkManagedHookSections() {
|
|
|
870
926
|
return { passed: true, message: "Current for this Kibi CLI" };
|
|
871
927
|
}
|
|
872
928
|
function checkGitHooks() {
|
|
929
|
+
const manager = doctorHookManager();
|
|
930
|
+
if (manager) {
|
|
931
|
+
return checkHookManagerDelegation(manager, ["post-checkout", "post-merge"], "a new branch is not compiled on checkout or after a merge");
|
|
932
|
+
}
|
|
873
933
|
const postCheckoutPath = path.join(effectiveHooksDir(), "post-checkout");
|
|
874
934
|
const postMergePath = path.join(effectiveHooksDir(), "post-merge");
|
|
875
935
|
const preCommitPath = path.join(effectiveHooksDir(), "pre-commit");
|
|
@@ -919,42 +979,9 @@ function checkGitHooks() {
|
|
|
919
979
|
remediation: "Run: kibi init",
|
|
920
980
|
};
|
|
921
981
|
}
|
|
922
|
-
/**
|
|
923
|
-
* Individual shell commands of a hook script, ignoring comments. Lines are
|
|
924
|
-
* split on command separators so `a && b` counts as two commands.
|
|
925
|
-
*/
|
|
926
|
-
// implements REQ-git-hook-effective-install
|
|
927
|
-
function hookCommands(content) {
|
|
928
|
-
return content
|
|
929
|
-
.split("\n")
|
|
930
|
-
.filter((line) => !line.trimStart().startsWith("#"))
|
|
931
|
-
.flatMap((line) => line.split(/&&|\|\||;|\|/))
|
|
932
|
-
.map((command) => command.trim())
|
|
933
|
-
.filter((command) => command.length > 0);
|
|
934
|
-
}
|
|
935
|
-
// Matches `kibi <sub>`, `npx kibi <sub>`, `node_modules/.bin/kibi <sub>` and
|
|
936
|
-
// the template's `"$KIBI_BIN" <sub>`.
|
|
937
|
-
// implements REQ-git-hook-effective-install
|
|
938
|
-
function invokesKibi(command, subcommand) {
|
|
939
|
-
return new RegExp(`(?:\\bkibi|\\bKIBI_BIN)["'}]*\\s+${subcommand}(?=\\s|$)`).test(command);
|
|
940
|
-
}
|
|
941
|
-
/** The pre-commit gate the managed template runs, as a custom hook must. */
|
|
942
|
-
const PRE_COMMIT_DELEGATIONS = [
|
|
943
|
-
{
|
|
944
|
-
label: "kibi check-generated --staged --changed-only",
|
|
945
|
-
matches: (command) => invokesKibi(command, "check-generated") &&
|
|
946
|
-
/\s--staged(?=\s|$)/.test(command) &&
|
|
947
|
-
/\s--changed-only(?=\s|$)/.test(command),
|
|
948
|
-
},
|
|
949
|
-
{
|
|
950
|
-
label: "kibi check --staged",
|
|
951
|
-
matches: (command) => invokesKibi(command, "check") && /\s--staged(?=\s|$)/.test(command),
|
|
952
|
-
},
|
|
953
|
-
];
|
|
954
982
|
// implements REQ-git-hook-effective-install
|
|
955
983
|
function checkCustomPreCommitHook(content, executable) {
|
|
956
|
-
const
|
|
957
|
-
const missing = PRE_COMMIT_DELEGATIONS.filter((delegation) => !commands.some(delegation.matches)).map((delegation) => `'${delegation.label}'`);
|
|
984
|
+
const missing = missingKibiHookCommands("pre-commit", [content]).map((label) => `'${label}'`);
|
|
958
985
|
if (missing.length > 0) {
|
|
959
986
|
// An unmarked file that still carries the old template header is a Kibi
|
|
960
987
|
// hook from before managed sections; removing it lets init reinstall it.
|
|
@@ -980,6 +1007,10 @@ function checkCustomPreCommitHook(content, executable) {
|
|
|
980
1007
|
};
|
|
981
1008
|
}
|
|
982
1009
|
function checkPreCommitHook() {
|
|
1010
|
+
const manager = doctorHookManager();
|
|
1011
|
+
if (manager) {
|
|
1012
|
+
return checkHookManagerDelegation(manager, ["pre-commit"], "commits skip Kibi enforcement");
|
|
1013
|
+
}
|
|
983
1014
|
const postCheckoutPath = path.join(effectiveHooksDir(), "post-checkout");
|
|
984
1015
|
const postMergePath = path.join(effectiveHooksDir(), "post-merge");
|
|
985
1016
|
const preCommitPath = path.join(effectiveHooksDir(), "pre-commit");
|
|
@@ -1063,6 +1094,10 @@ function checkPreCommitHook() {
|
|
|
1063
1094
|
}
|
|
1064
1095
|
}
|
|
1065
1096
|
function checkPostRewriteHook() {
|
|
1097
|
+
const manager = doctorHookManager();
|
|
1098
|
+
if (manager) {
|
|
1099
|
+
return checkHookManagerDelegation(manager, ["post-rewrite"], "a rebased branch keeps a stale KB until the next 'kibi sync'");
|
|
1100
|
+
}
|
|
1066
1101
|
const postCheckoutPath = path.join(effectiveHooksDir(), "post-checkout");
|
|
1067
1102
|
const postMergePath = path.join(effectiveHooksDir(), "post-merge");
|
|
1068
1103
|
const postRewritePath = path.join(effectiveHooksDir(), "post-rewrite");
|
|
@@ -1091,7 +1126,7 @@ function checkPostRewriteHook() {
|
|
|
1091
1126
|
// A custom hook (no kibi-managed section) is never edited by init.
|
|
1092
1127
|
// implements REQ-git-hook-effective-install
|
|
1093
1128
|
if (!content.includes(KIBI_HOOK_BEGIN)) {
|
|
1094
|
-
if (
|
|
1129
|
+
if (missingKibiHookCommands("post-rewrite", [content]).length > 0) {
|
|
1095
1130
|
return {
|
|
1096
1131
|
passed: false,
|
|
1097
1132
|
message: `Custom post-rewrite hook (no kibi-managed section) does not run 'kibi sync'${hooksPathSuffix()}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-init.d.ts","sourceRoot":"","sources":["../../src/commands/github-init.ts"],"names":[],"mappings":"AAgCA,eAAO,MAAM,8BAA8B,sCACN,CAAC;AACtC,eAAO,MAAM,6BAA6B,qCAAqC,CAAC;AAChF,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AACpD,eAAO,MAAM,cAAc,4BAA4B,CAAC;AACxD,eAAO,MAAM,oBAAoB,qFACmD,CAAC;AACrF,eAAO,MAAM,iBAAiB,UAAU,CAAC;AACzC,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAM7C,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,CAAC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEpD,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;AACvE,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,WAAW,GACX,SAAS,GACT,sBAAsB,CAAC;AAC3B,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,WAAW,CAAC;AAE3D,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;IAC3C,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,oBAAoB,CAAC;IAChC,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;CAC9B,CAAC,CAAC;AAGH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,kBAAkB,GACvB,MAAM,CAER;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAS3E;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CA+BrE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"github-init.d.ts","sourceRoot":"","sources":["../../src/commands/github-init.ts"],"names":[],"mappings":"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"}
|
|
@@ -74,9 +74,11 @@ export function parseGitHubRemote(url) {
|
|
|
74
74
|
return undefined;
|
|
75
75
|
}
|
|
76
76
|
export function githubPagesUrls(repo) {
|
|
77
|
+
// The *.github.io host is case-insensitive, but the project-site path is
|
|
78
|
+
// case-sensitive, so the repository segment keeps its exact case.
|
|
77
79
|
const owner = repo.owner.toLowerCase();
|
|
78
|
-
const name = repo.repo
|
|
79
|
-
const isUserSite = name === `${owner}.github.io`;
|
|
80
|
+
const name = repo.repo;
|
|
81
|
+
const isUserSite = name.toLowerCase() === `${owner}.github.io`;
|
|
80
82
|
const origin = isUserSite
|
|
81
83
|
? `https://${owner}.github.io/`
|
|
82
84
|
: `https://${owner}.github.io/${name}/`;
|