kibi-cli 2.21.0 → 2.22.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-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 +1 -0
- package/dist/commands/check.d.ts +0 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +47 -111
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +107 -5
- package/dist/commands/init-helpers.d.ts +14 -1
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +49 -10
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +27 -4
- package/dist/commands/legacy-storage-migration.d.ts +46 -1
- package/dist/commands/legacy-storage-migration.d.ts.map +1 -1
- package/dist/commands/legacy-storage-migration.js +244 -9
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +150 -166
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +9 -0
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +4 -0
- package/dist/decision-firmness.d.ts +39 -0
- package/dist/decision-firmness.d.ts.map +1 -0
- package/dist/decision-firmness.js +115 -0
- package/dist/extractors/markdown.d.ts +2 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +14 -0
- package/dist/extractors/symbols-coordinator.js +1 -0
- package/dist/intent-search.d.ts.map +1 -1
- package/dist/intent-search.js +28 -6
- package/dist/operations/migration/inventory-rederive.d.ts +40 -1
- package/dist/operations/migration/inventory-rederive.d.ts.map +1 -1
- package/dist/operations/migration/inventory-rederive.js +99 -8
- package/dist/operations/migration/requirement-status.d.ts +25 -0
- package/dist/operations/migration/requirement-status.d.ts.map +1 -0
- package/dist/operations/migration/requirement-status.js +105 -0
- package/dist/operations/migration/schema6.d.ts +27 -0
- package/dist/operations/migration/schema6.d.ts.map +1 -1
- package/dist/operations/migration/schema6.js +308 -7
- package/dist/operations/migration/supersedes-reason.d.ts +26 -0
- package/dist/operations/migration/supersedes-reason.d.ts.map +1 -0
- package/dist/operations/migration/supersedes-reason.js +69 -0
- package/dist/operations/migration/symbol-legacy-links.d.ts +51 -0
- package/dist/operations/migration/symbol-legacy-links.d.ts.map +1 -0
- package/dist/operations/migration/symbol-legacy-links.js +319 -0
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +10 -2
- package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-loader.js +11 -0
- package/dist/operations/modeling/predicate-types.d.ts +32 -1
- package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.js +175 -35
- package/dist/operations/mutation/context-warning.d.ts +12 -2
- package/dist/operations/mutation/context-warning.d.ts.map +1 -1
- package/dist/operations/mutation/context-warning.js +6 -6
- package/dist/operations/mutation/delete.d.ts +5 -1
- package/dist/operations/mutation/delete.d.ts.map +1 -1
- package/dist/operations/mutation/delete.js +223 -17
- 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 +130 -35
- package/dist/operations/mutation/types.d.ts +39 -1
- package/dist/operations/mutation/types.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.d.ts +17 -2
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +82 -13
- package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
- package/dist/operations/mutation/validate-upsert.js +40 -8
- package/dist/operations/planning/apply-plan.d.ts +6 -1
- package/dist/operations/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +26 -5
- package/dist/public/impact/diagnostics.d.ts.map +1 -1
- package/dist/public/impact/diagnostics.js +24 -14
- package/dist/public/operations/catalog.d.ts +14 -5
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +6 -0
- package/dist/public/operations/contracts.d.ts.map +1 -1
- package/dist/public/operations/contracts.js +35 -2
- package/dist/public/operations/decision-firmness.d.ts +34 -0
- package/dist/public/operations/decision-firmness.d.ts.map +1 -0
- package/dist/public/operations/decision-firmness.js +216 -0
- package/dist/public/operations/discovery-executors.d.ts +2 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +25 -4
- package/dist/public/operations/migration-plan.d.ts +2 -0
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +101 -16
- package/dist/public/operations/result-envelope.d.ts.map +1 -1
- package/dist/public/operations/result-envelope.js +27 -1
- package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
- package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
- package/dist/public/operations/specs/check-rules.generated.js +6 -1
- package/dist/public/operations/specs/check.d.ts +1 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts +5 -0
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +5 -0
- package/dist/public/operations/specs/mutation.d.ts +6 -2
- package/dist/public/operations/specs/mutation.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation.js +6 -2
- package/dist/public/operations/specs/planning.d.ts +2 -2
- package/dist/public/operations/specs/planning.js +2 -2
- package/dist/public/operations/specs/upsert.d.ts +5 -0
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/symbol-granularity-check.d.ts +18 -0
- package/dist/public/operations/symbol-granularity-check.d.ts.map +1 -0
- package/dist/public/operations/symbol-granularity-check.js +175 -0
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +11 -0
- package/dist/public/skills/kibi-traceability/SKILL.md +6 -4
- package/dist/public/skills/kibi-usage/SKILL.md +50 -10
- package/dist/public/skills/kibi-usage/resources/source-authoring.md +4 -2
- package/dist/public/symbol-granularity.d.ts +17 -0
- package/dist/public/symbol-granularity.d.ts.map +1 -1
- package/dist/public/symbol-granularity.js +21 -0
- package/dist/relationships/shards.d.ts +10 -0
- package/dist/relationships/shards.d.ts.map +1 -1
- package/dist/relationships/shards.js +27 -11
- package/dist/schemas/entity.schema.json +28 -0
- package/dist/search-answer.d.ts +31 -2
- package/dist/search-answer.d.ts.map +1 -1
- package/dist/search-answer.js +115 -17
- package/dist/traceability/evidence-model.d.ts +7 -3
- package/dist/traceability/evidence-model.d.ts.map +1 -1
- package/dist/traceability/staged-symbols-manifest.js +6 -5
- package/dist/traceability/validate.d.ts +14 -1
- package/dist/traceability/validate.d.ts.map +1 -1
- package/dist/traceability/validate.js +41 -0
- package/dist/types/entities.d.ts +4 -0
- package/dist/types/entities.d.ts.map +1 -1
- package/dist/utils/kb-manifest.d.ts +6 -0
- package/dist/utils/kb-manifest.d.ts.map +1 -1
- package/dist/utils/kb-manifest.js +6 -0
- package/dist/utils/rule-registry.generated.d.ts +26 -0
- package/dist/utils/rule-registry.generated.d.ts.map +1 -1
- package/dist/utils/rule-registry.generated.js +31 -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 +3 -1
- package/package.json +3 -3
- package/schema/entities.pl +6 -0
- package/src/public/impact/diagnostics.ts +29 -17
- package/src/public/operations/check-executor.ts +13 -0
- package/src/public/operations/contracts.ts +39 -2
- package/src/public/operations/decision-firmness.ts +280 -0
- package/src/public/operations/discovery-executors.ts +29 -4
- package/src/public/operations/migration-plan.ts +100 -19
- package/src/public/operations/result-envelope.ts +34 -1
- package/src/public/operations/specs/check-rules.generated.ts +6 -1
- package/src/public/operations/specs/mutation-schemas.ts +6 -0
- package/src/public/operations/specs/mutation.ts +7 -2
- package/src/public/operations/specs/planning.ts +2 -2
- package/src/public/operations/symbol-granularity-check.ts +233 -0
- package/src/public/schemas/entity.ts +12 -0
- package/src/public/skills/kibi-traceability/SKILL.md +6 -4
- package/src/public/skills/kibi-usage/SKILL.md +50 -10
- package/src/public/skills/kibi-usage/resources/source-authoring.md +4 -2
- package/src/public/symbol-granularity.ts +37 -0
- package/src/schemas/entity.schema.json +28 -0
|
@@ -345,7 +345,12 @@ const BASE_DATA_SCHEMAS = {
|
|
|
345
345
|
sourceType: stringValue,
|
|
346
346
|
}),
|
|
347
347
|
kb_skills_read: objectData({ content: stringValue }, ["content"]),
|
|
348
|
-
kb_query: objectData({
|
|
348
|
+
kb_query: objectData({
|
|
349
|
+
entities: recordArray,
|
|
350
|
+
count: integerValue,
|
|
351
|
+
factQuery: recordValue,
|
|
352
|
+
branchStore: recordValue,
|
|
353
|
+
}, ["entities", "count"]),
|
|
349
354
|
kb_search: objectData({
|
|
350
355
|
results: valueArray,
|
|
351
356
|
count: integerValue,
|
|
@@ -464,6 +469,8 @@ const BASE_DATA_SCHEMAS = {
|
|
|
464
469
|
"record_ontology_gap",
|
|
465
470
|
"review_nonlogical",
|
|
466
471
|
"replace_grounding",
|
|
472
|
+
"extend_requirement",
|
|
473
|
+
"keep_existing_grounding",
|
|
467
474
|
],
|
|
468
475
|
},
|
|
469
476
|
recommendedPredicateSchema: { type: ["object", "null"] },
|
|
@@ -477,7 +484,14 @@ const BASE_DATA_SCHEMAS = {
|
|
|
477
484
|
type: ["string", "null"],
|
|
478
485
|
description: "The planned predicate fact id (FACT-PRED-...) that a requires_predicate link must target. Candidate ids (SUGGEST-...) are never relationship targets.",
|
|
479
486
|
},
|
|
480
|
-
existingGrounding:
|
|
487
|
+
existingGrounding: {
|
|
488
|
+
...recordArray,
|
|
489
|
+
description: "The grounding links requirementId already has for this claim: matched by claim_key (the same proposition text) or, for a predicate fact, by the recommended candidate's canonical_key (the same predicate tuple in other words; matchedBy says which).",
|
|
490
|
+
},
|
|
491
|
+
decisionConflicts: {
|
|
492
|
+
...recordArray,
|
|
493
|
+
description: "When no hash-bound plan ran the contradiction analysis: stored decision facts of current requirements that agree with the complete candidate on its key arguments and decide the opposite (requirementId, factId, effect, proposedEffect, canonicalKey). A warning repeats each one.",
|
|
494
|
+
},
|
|
481
495
|
replacementPlan: { type: ["object", "null"] },
|
|
482
496
|
bindingHints: {
|
|
483
497
|
...recordArray,
|
|
@@ -535,6 +549,10 @@ const BASE_DATA_SCHEMAS = {
|
|
|
535
549
|
relationships_created: integerValue,
|
|
536
550
|
warnings: valueArray,
|
|
537
551
|
semanticAdvisor: recordValue,
|
|
552
|
+
claimKey: {
|
|
553
|
+
...stringValue,
|
|
554
|
+
description: "For a fact with claim_text: the stored claim_key, derived from claim_text when the payload did not supply it.",
|
|
555
|
+
},
|
|
538
556
|
status: stringValue,
|
|
539
557
|
effectFailures: recordArray,
|
|
540
558
|
nextActions: recordArray,
|
|
@@ -569,6 +587,21 @@ const BASE_DATA_SCHEMAS = {
|
|
|
569
587
|
status: stringValue,
|
|
570
588
|
effectFailures: recordArray,
|
|
571
589
|
nextActions: recordArray,
|
|
590
|
+
outcome: {
|
|
591
|
+
type: "string",
|
|
592
|
+
enum: [
|
|
593
|
+
"plan_returned",
|
|
594
|
+
"supersession_required",
|
|
595
|
+
"plan_applied",
|
|
596
|
+
"dry_run",
|
|
597
|
+
],
|
|
598
|
+
description: "Absent on a direct delete. plan_returned: deletionPlan was returned and nothing was written; nextActions[0].input is the exact kb_apply_plan input. supersession_required: an authored requirement must be superseded with kb_upsert instead. plan_applied: approvedPlanHash matched and the plan was applied. dry_run: dryRun:true previewed the delete and nothing was written.",
|
|
599
|
+
},
|
|
600
|
+
dryRun: { const: true },
|
|
601
|
+
wouldDelete: recordValue,
|
|
602
|
+
planHash: stringValue,
|
|
603
|
+
sourcePaths: stringArray,
|
|
604
|
+
recoveryJournalId: stringValue,
|
|
572
605
|
}),
|
|
573
606
|
kb_check: {
|
|
574
607
|
description: "Synchronous check payload, or a kibi.job.v1 receipt when async:true detached the check into a background job (poll kb_job_status with the jobId).",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Violation } from "../../utils/rule-registry.js";
|
|
2
|
+
import { type AuthoredEntity } from "./entity-context.js";
|
|
3
|
+
/** A firm decision must cite the human words it rests on (blocking). */
|
|
4
|
+
export declare const DECISION_FIRM_UNREFERENCED_RULE = "decision-firm-unreferenced";
|
|
5
|
+
/** Only a firm decision may supersede a firm decision (blocking). */
|
|
6
|
+
export declare const DECISION_FIRM_SUPERSEDED_RULE = "decision-firm-superseded";
|
|
7
|
+
/** A supersede must say why under "Why this changed" (blocking). */
|
|
8
|
+
export declare const SUPERSEDES_REASON_MISSING_RULE = "supersedes-reason-missing";
|
|
9
|
+
/** How many legacy supersedes the schema 9 migration acknowledged (info). */
|
|
10
|
+
export declare const SUPERSEDES_REASON_ACKNOWLEDGED_RULE = "supersedes-reason-acknowledged";
|
|
11
|
+
export declare const DECISION_FIRMNESS_RULES: readonly ["decision-firm-unreferenced", "decision-firm-superseded", "supersedes-reason-missing", "supersedes-reason-acknowledged"];
|
|
12
|
+
/** Every authored requirement and ADR. */
|
|
13
|
+
export declare function listDecisionEntities(workspaceRoot: string): AuthoredEntity[];
|
|
14
|
+
/**
|
|
15
|
+
* Supersedes edges from requirements and ADRs, keyed by the superseding id,
|
|
16
|
+
* read from authored `links` and the relationship shards so the check and the
|
|
17
|
+
* migration agree before a sync. A shard edge whose source entity no longer
|
|
18
|
+
* exists is ignored: it must not make its target look replaced.
|
|
19
|
+
*/
|
|
20
|
+
export declare function authoredSupersedes(workspaceRoot: string, entities: readonly AuthoredEntity[]): Map<string, Set<string>>;
|
|
21
|
+
/**
|
|
22
|
+
* Superseding requirements and ADRs, whatever their status, without a "Why
|
|
23
|
+
* this changed" explanation. The schema 9 migration acknowledges their edges
|
|
24
|
+
* once, retired ones included, so one that becomes current again does not
|
|
25
|
+
* start blocking; read-only.
|
|
26
|
+
*/
|
|
27
|
+
export declare function unexplainedSupersedes(entities: readonly AuthoredEntity[], edges: ReadonlyMap<string, Set<string>>): AuthoredEntity[];
|
|
28
|
+
/** The supersede edges of an entity, as the manifest acknowledges them. */
|
|
29
|
+
export declare function supersedeAcknowledgements(id: string, edges: ReadonlyMap<string, Set<string>>): string[];
|
|
30
|
+
/** Evaluate the firmness rules over authored requirements and ADRs. */
|
|
31
|
+
export declare function evaluateDecisionFirmness(entities: readonly AuthoredEntity[], edges: ReadonlyMap<string, Set<string>>, rules?: ReadonlySet<string>, acknowledged?: ReadonlySet<string>): Violation[];
|
|
32
|
+
/** Read the authored decisions once and evaluate the selected rules. */
|
|
33
|
+
export declare function collectDecisionFirmnessViolations(rules: ReadonlySet<string>, workspaceRoot: string): Violation[];
|
|
34
|
+
//# sourceMappingURL=decision-firmness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-firmness.d.ts","sourceRoot":"","sources":["../../../src/public/operations/decision-firmness.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EACL,KAAK,cAAc,EAGpB,MAAM,qBAAqB,CAAC;AAE7B,wEAAwE;AAExE,eAAO,MAAM,+BAA+B,+BAA+B,CAAC;AAC5E,qEAAqE;AAErE,eAAO,MAAM,6BAA6B,6BAA6B,CAAC;AACxE,oEAAoE;AAEpE,eAAO,MAAM,8BAA8B,8BAA8B,CAAC;AAC1E,6EAA6E;AAE7E,eAAO,MAAM,mCAAmC,mCACd,CAAC;AAGnC,eAAO,MAAM,uBAAuB,oIAK1B,CAAC;AAIX,0CAA0C;AAE1C,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,EAAE,CAS5E;AAED;;;;;GAKG;AAEH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,SAAS,cAAc,EAAE,GAClC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CA+B1B;AASD;;;;;GAKG;AAEH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,SAAS,cAAc,EAAE,EACnC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GACtC,cAAc,EAAE,CAQlB;AAED,2EAA2E;AAE3E,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GACtC,MAAM,EAAE,CAIV;AAED,uEAAuE;AAEvE,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,SAAS,cAAc,EAAE,EACnC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EACvC,KAAK,GAAE,WAAW,CAAC,MAAM,CAAoC,EAC7D,YAAY,GAAE,WAAW,CAAC,MAAM,CAAa,GAC5C,SAAS,EAAE,CAiGb;AAED,wEAAwE;AAExE,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAC1B,aAAa,EAAE,MAAM,GACpB,SAAS,EAAE,CASb"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Kibi — repo-local, per-branch, queryable long-term memory for software projects
|
|
3
|
+
Copyright (C) 2026 Piotr Franczyk
|
|
4
|
+
|
|
5
|
+
This program is free software: you can redistribute it and/or modify
|
|
6
|
+
it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU Affero General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
18
|
+
import path from "node:path";
|
|
19
|
+
import { MIN_WHY_CHANGED_WORDS, WHY_THIS_CHANGED_HEADING, carriesFirmness, effectiveFirmness, firmnessRef, supersedeAcknowledgement, whyThisChangedWords, } from "../../decision-firmness.js";
|
|
20
|
+
import { listLaneMarkdownFiles, readText, } from "../../operations/migration/kb-sources.js";
|
|
21
|
+
import { readAllShards } from "../../relationships/shards.js";
|
|
22
|
+
import { readKbManifest } from "../../utils/kb-manifest.js";
|
|
23
|
+
import { isCurrentAuthoredEntity, readAuthoredEntity, } from "./entity-context.js";
|
|
24
|
+
/** A firm decision must cite the human words it rests on (blocking). */
|
|
25
|
+
// implements REQ-kb-decision-firmness
|
|
26
|
+
export const DECISION_FIRM_UNREFERENCED_RULE = "decision-firm-unreferenced";
|
|
27
|
+
/** Only a firm decision may supersede a firm decision (blocking). */
|
|
28
|
+
// implements REQ-kb-decision-firmness
|
|
29
|
+
export const DECISION_FIRM_SUPERSEDED_RULE = "decision-firm-superseded";
|
|
30
|
+
/** A supersede must say why under "Why this changed" (blocking). */
|
|
31
|
+
// implements REQ-kb-decision-firmness
|
|
32
|
+
export const SUPERSEDES_REASON_MISSING_RULE = "supersedes-reason-missing";
|
|
33
|
+
/** How many legacy supersedes the schema 9 migration acknowledged (info). */
|
|
34
|
+
// implements REQ-kb-decision-firmness
|
|
35
|
+
export const SUPERSEDES_REASON_ACKNOWLEDGED_RULE = "supersedes-reason-acknowledged";
|
|
36
|
+
// implements REQ-kb-decision-firmness
|
|
37
|
+
export const DECISION_FIRMNESS_RULES = [
|
|
38
|
+
DECISION_FIRM_UNREFERENCED_RULE,
|
|
39
|
+
DECISION_FIRM_SUPERSEDED_RULE,
|
|
40
|
+
SUPERSEDES_REASON_MISSING_RULE,
|
|
41
|
+
SUPERSEDES_REASON_ACKNOWLEDGED_RULE,
|
|
42
|
+
];
|
|
43
|
+
const DECISION_LANES = ["requirements", "adr"];
|
|
44
|
+
/** Every authored requirement and ADR. */
|
|
45
|
+
// implements REQ-kb-decision-firmness
|
|
46
|
+
export function listDecisionEntities(workspaceRoot) {
|
|
47
|
+
const entities = [];
|
|
48
|
+
for (const file of listLaneMarkdownFiles(workspaceRoot, DECISION_LANES)) {
|
|
49
|
+
const content = readText(file.absolutePath);
|
|
50
|
+
if (content === null)
|
|
51
|
+
continue;
|
|
52
|
+
const entity = readAuthoredEntity(content, file.relativePath);
|
|
53
|
+
if (entity !== null && carriesFirmness(entity.type))
|
|
54
|
+
entities.push(entity);
|
|
55
|
+
}
|
|
56
|
+
return entities;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Supersedes edges from requirements and ADRs, keyed by the superseding id,
|
|
60
|
+
* read from authored `links` and the relationship shards so the check and the
|
|
61
|
+
* migration agree before a sync. A shard edge whose source entity no longer
|
|
62
|
+
* exists is ignored: it must not make its target look replaced.
|
|
63
|
+
*/
|
|
64
|
+
// implements REQ-kb-decision-firmness
|
|
65
|
+
export function authoredSupersedes(workspaceRoot, entities) {
|
|
66
|
+
const edges = new Map();
|
|
67
|
+
const known = new Set(entities.map((entity) => entity.id));
|
|
68
|
+
const add = (from, to) => {
|
|
69
|
+
const targets = edges.get(from) ?? new Set();
|
|
70
|
+
targets.add(to);
|
|
71
|
+
edges.set(from, targets);
|
|
72
|
+
};
|
|
73
|
+
for (const entity of entities) {
|
|
74
|
+
const links = entity.data.links;
|
|
75
|
+
if (!Array.isArray(links))
|
|
76
|
+
continue;
|
|
77
|
+
for (const link of links) {
|
|
78
|
+
if (link !== null &&
|
|
79
|
+
typeof link === "object" &&
|
|
80
|
+
link.type === "supersedes" &&
|
|
81
|
+
typeof link.target === "string") {
|
|
82
|
+
add(entity.id, link.target);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
for (const relationship of readAllShards(path.join(workspaceRoot, ".kb"))) {
|
|
88
|
+
if (relationship.type === "supersedes" && known.has(relationship.from))
|
|
89
|
+
add(relationship.from, relationship.to);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// Malformed shards fail sync with their own diagnostic.
|
|
94
|
+
}
|
|
95
|
+
return edges;
|
|
96
|
+
}
|
|
97
|
+
function supersededIds(edges) {
|
|
98
|
+
const superseded = new Set();
|
|
99
|
+
for (const targets of edges.values())
|
|
100
|
+
for (const target of targets)
|
|
101
|
+
superseded.add(target);
|
|
102
|
+
return superseded;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Superseding requirements and ADRs, whatever their status, without a "Why
|
|
106
|
+
* this changed" explanation. The schema 9 migration acknowledges their edges
|
|
107
|
+
* once, retired ones included, so one that becomes current again does not
|
|
108
|
+
* start blocking; read-only.
|
|
109
|
+
*/
|
|
110
|
+
// implements REQ-kb-decision-firmness
|
|
111
|
+
export function unexplainedSupersedes(entities, edges) {
|
|
112
|
+
return entities
|
|
113
|
+
.filter((entity) => edges.has(entity.id) &&
|
|
114
|
+
whyThisChangedWords(entity.body) < MIN_WHY_CHANGED_WORDS)
|
|
115
|
+
.sort((left, right) => left.id.localeCompare(right.id));
|
|
116
|
+
}
|
|
117
|
+
/** The supersede edges of an entity, as the manifest acknowledges them. */
|
|
118
|
+
// implements REQ-kb-decision-firmness
|
|
119
|
+
export function supersedeAcknowledgements(id, edges) {
|
|
120
|
+
return [...(edges.get(id) ?? [])]
|
|
121
|
+
.sort()
|
|
122
|
+
.map((target) => supersedeAcknowledgement(id, target));
|
|
123
|
+
}
|
|
124
|
+
/** Evaluate the firmness rules over authored requirements and ADRs. */
|
|
125
|
+
// implements REQ-kb-decision-firmness
|
|
126
|
+
export function evaluateDecisionFirmness(entities, edges, rules = new Set(DECISION_FIRMNESS_RULES), acknowledged = new Set()) {
|
|
127
|
+
const findings = [];
|
|
128
|
+
const superseded = supersededIds(edges);
|
|
129
|
+
const byId = new Map(entities.map((entity) => [entity.id, entity]));
|
|
130
|
+
const current = entities
|
|
131
|
+
.filter((entity) => isCurrentAuthoredEntity(entity, superseded))
|
|
132
|
+
.sort((left, right) => left.id.localeCompare(right.id));
|
|
133
|
+
const firmnessOf = (entity) => effectiveFirmness(entity.type, entity.data.firmness);
|
|
134
|
+
if (rules.has(DECISION_FIRM_UNREFERENCED_RULE)) {
|
|
135
|
+
for (const entity of current) {
|
|
136
|
+
if (firmnessOf(entity) !== "firm")
|
|
137
|
+
continue;
|
|
138
|
+
if (firmnessRef({ type: entity.type, ...entity.data }) !== undefined)
|
|
139
|
+
continue;
|
|
140
|
+
findings.push({
|
|
141
|
+
rule: DECISION_FIRM_UNREFERENCED_RULE,
|
|
142
|
+
entityId: entity.id,
|
|
143
|
+
description: `${entity.id} is marked firmness: firm but names no human words it rests on (origin.ref${entity.type === "req" ? " or approval_ref" : ""} is missing)`,
|
|
144
|
+
suggestion: "Set origin.ref to the message, review or ticket where a human stated this rule; if no human stated it, use firmness: default (or exploratory for a guess)",
|
|
145
|
+
source: entity.path,
|
|
146
|
+
evidence: { type: entity.type, firmness: "firm" },
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Every superseder counts, retired ones too: replacing a non-firm
|
|
151
|
+
// superseder must not launder the overruled firm decision.
|
|
152
|
+
if (rules.has(DECISION_FIRM_SUPERSEDED_RULE)) {
|
|
153
|
+
for (const entity of [...entities].sort((left, right) => left.id.localeCompare(right.id))) {
|
|
154
|
+
if (firmnessOf(entity) === "firm")
|
|
155
|
+
continue;
|
|
156
|
+
const firmTargets = [...(edges.get(entity.id) ?? [])]
|
|
157
|
+
.filter((id) => {
|
|
158
|
+
const target = byId.get(id);
|
|
159
|
+
return (target !== undefined &&
|
|
160
|
+
effectiveFirmness(target.type, target.data.firmness) === "firm");
|
|
161
|
+
})
|
|
162
|
+
.sort();
|
|
163
|
+
if (firmTargets.length === 0)
|
|
164
|
+
continue;
|
|
165
|
+
findings.push({
|
|
166
|
+
rule: DECISION_FIRM_SUPERSEDED_RULE,
|
|
167
|
+
entityId: entity.id,
|
|
168
|
+
description: `${entity.id} (firmness: ${firmnessOf(entity)}) supersedes the firm decision${firmTargets.length === 1 ? "" : "s"} ${firmTargets.join(", ")}; only a human may change a firm decision`,
|
|
169
|
+
suggestion: "Ask the person who stated the firm decision; if they agree, mark the replacement firmness: firm with origin.ref to their words, otherwise remove the supersedes link and propose the change instead",
|
|
170
|
+
source: entity.path,
|
|
171
|
+
evidence: { firmness: firmnessOf(entity), firmTargets },
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const currentIds = new Set(current.map((entity) => entity.id));
|
|
176
|
+
const unexplained = unexplainedSupersedes(entities, edges).filter((entity) => currentIds.has(entity.id));
|
|
177
|
+
const isAcknowledged = (entity) => supersedeAcknowledgements(entity.id, edges).every((edge) => acknowledged.has(edge));
|
|
178
|
+
const exempt = unexplained.filter(isAcknowledged);
|
|
179
|
+
if (rules.has(SUPERSEDES_REASON_MISSING_RULE)) {
|
|
180
|
+
for (const entity of unexplained) {
|
|
181
|
+
if (isAcknowledged(entity))
|
|
182
|
+
continue;
|
|
183
|
+
const targets = [...(edges.get(entity.id) ?? [])].sort();
|
|
184
|
+
const unacknowledged = targets.filter((target) => !acknowledged.has(supersedeAcknowledgement(entity.id, target)));
|
|
185
|
+
findings.push({
|
|
186
|
+
rule: SUPERSEDES_REASON_MISSING_RULE,
|
|
187
|
+
entityId: entity.id,
|
|
188
|
+
description: `${entity.id} supersedes ${unacknowledged.join(", ")} without a '## ${WHY_THIS_CHANGED_HEADING}' section of at least ${MIN_WHY_CHANGED_WORDS} words`,
|
|
189
|
+
suggestion: `Add '## ${WHY_THIS_CHANGED_HEADING}' to the body: name the evidence (a failing test, a measured cost, a constraint the old decision missed, a new requirement) and answer the superseded decision's reasoning. A preference is not evidence; propose it instead of superseding.`,
|
|
190
|
+
source: entity.path,
|
|
191
|
+
evidence: { type: entity.type, supersedes: unacknowledged },
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (rules.has(SUPERSEDES_REASON_ACKNOWLEDGED_RULE) && exempt.length) {
|
|
196
|
+
findings.push({
|
|
197
|
+
rule: SUPERSEDES_REASON_ACKNOWLEDGED_RULE,
|
|
198
|
+
entityId: "workspace",
|
|
199
|
+
description: `${exempt.length} current superseding requirement${exempt.length === 1 ? " or ADR was" : "s and ADRs were"} recorded before schema 9 without a '${WHY_THIS_CHANGED_HEADING}' section`,
|
|
200
|
+
suggestion: "When you next touch one, add the reason if the history or a person states it; never invent one",
|
|
201
|
+
evidence: {
|
|
202
|
+
total: exempt.length,
|
|
203
|
+
ids: exempt.slice(0, 25).map((entity) => entity.id),
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return findings;
|
|
208
|
+
}
|
|
209
|
+
/** Read the authored decisions once and evaluate the selected rules. */
|
|
210
|
+
// implements REQ-kb-decision-firmness
|
|
211
|
+
export function collectDecisionFirmnessViolations(rules, workspaceRoot) {
|
|
212
|
+
if (!DECISION_FIRMNESS_RULES.some((rule) => rules.has(rule)))
|
|
213
|
+
return [];
|
|
214
|
+
const entities = listDecisionEntities(workspaceRoot);
|
|
215
|
+
return evaluateDecisionFirmness(entities, authoredSupersedes(workspaceRoot, entities), rules, new Set(readKbManifest(workspaceRoot)?.supersedesReasonAcknowledged ?? []));
|
|
216
|
+
}
|
|
@@ -51,6 +51,8 @@ export type QueryPayload = {
|
|
|
51
51
|
readonly entities: readonly Record<string, unknown>[];
|
|
52
52
|
readonly count: number;
|
|
53
53
|
readonly factQuery?: FactQueryPayload;
|
|
54
|
+
/** Present when an empty answer came from a store never compiled for this branch. */
|
|
55
|
+
readonly branchStore?: SearchBranchStoreNotice;
|
|
54
56
|
};
|
|
55
57
|
export declare const FACT_KINDS: readonly ["subject", "property_value", "predicate", "predicate_schema", "observation", "meta", "rule", "rule_schema"];
|
|
56
58
|
export type SearchInput = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery-executors.d.ts","sourceRoot":"","sources":["../../../src/public/operations/discovery-executors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"discovery-executors.d.ts","sourceRoot":"","sources":["../../../src/public/operations/discovery-executors.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { compilerFingerprintReason } from "../../commands/sync/cache.js";
|
|
3
|
+
import { effectiveFirmness } from "../../decision-firmness.js";
|
|
3
4
|
import { EngineClient } from "../../engine.js";
|
|
4
5
|
import { executeIntentSearch, validateIntentSearchInput, } from "../../intent-search.js";
|
|
5
6
|
import { classifyActivation } from "../../operations/bootstrap/activation.js";
|
|
@@ -288,7 +289,12 @@ function factRowSummary(row) {
|
|
|
288
289
|
const names = Array.isArray(row.argumentNames)
|
|
289
290
|
? row.argumentNames.map(String).join(", ")
|
|
290
291
|
: "";
|
|
291
|
-
|
|
292
|
+
// A built-in schema is no stored entity: its id is for kb_model's
|
|
293
|
+
// schemaId, not for a kb_query by id.
|
|
294
|
+
const builtin = row.builtin === true
|
|
295
|
+
? ` [builtin${id ? ` ${id}` : ""}, not a stored entity]`
|
|
296
|
+
: "";
|
|
297
|
+
return `${row.name}(${names})${builtin}`;
|
|
292
298
|
}
|
|
293
299
|
return `${id} (${String(row.title ?? "")})`;
|
|
294
300
|
}
|
|
@@ -433,9 +439,20 @@ export async function executeQuery(input, context) {
|
|
|
433
439
|
const indexedPage = prolog.queryEntities
|
|
434
440
|
? await prolog.queryEntities(pageInput, signal)
|
|
435
441
|
: await queryEntitiesViaQuery(prolog, pageInput, signal);
|
|
436
|
-
|
|
442
|
+
// A requirement or ADR without authored firmness reads as `default`;
|
|
443
|
+
// the row says so, so a reader never has to know the default.
|
|
444
|
+
// implements REQ-kb-decision-firmness
|
|
445
|
+
const paginated = indexedPage.entities.map((entity) => {
|
|
446
|
+
const firmness = effectiveFirmness(entity.type, entity.firmness);
|
|
447
|
+
return firmness === undefined || entity.firmness === firmness
|
|
448
|
+
? entity
|
|
449
|
+
: { ...entity, firmness };
|
|
450
|
+
});
|
|
451
|
+
// An empty page from a never-compiled store says nothing about the
|
|
452
|
+
// authored entities, so the answer names the store state.
|
|
453
|
+
const storeNotice = indexedPage.count === 0 ? uncompiledSearchNotice(context) : null;
|
|
437
454
|
const text = indexedPage.count === 0
|
|
438
|
-
? `No entities found${type ? ` of type '${type}'` : ""}.`
|
|
455
|
+
? `No entities found${type ? ` of type '${type}'` : ""}.${storeNotice ? ` Note: ${storeNotice.detail} Run kibi sync before relying on query results.` : ""}`
|
|
439
456
|
: `Found ${indexedPage.count} entities${type ? ` of type '${type}'` : ""}. Showing ${paginated.length} (offset ${offset}, limit ${limit}): ${paginated
|
|
440
457
|
.map((entity) => {
|
|
441
458
|
const entityId = String(entity.id ?? "").replace(/^file:\/\/.*\//, "");
|
|
@@ -444,7 +461,11 @@ export async function executeQuery(input, context) {
|
|
|
444
461
|
.join(", ")}`;
|
|
445
462
|
return {
|
|
446
463
|
content: [{ type: "text", text }],
|
|
447
|
-
structuredContent: {
|
|
464
|
+
structuredContent: {
|
|
465
|
+
entities: paginated,
|
|
466
|
+
count: indexedPage.count,
|
|
467
|
+
...(storeNotice ? { branchStore: storeNotice } : {}),
|
|
468
|
+
},
|
|
448
469
|
};
|
|
449
470
|
}
|
|
450
471
|
catch (error) {
|
|
@@ -77,6 +77,8 @@ export declare function withoutActionCodes(plan: MigrationPlan, codes: ReadonlyS
|
|
|
77
77
|
export declare function migrationAction(input: Partial<MigrationAction> & Pick<MigrationAction, "id" | "code">): MigrationAction;
|
|
78
78
|
/** Migration code for mechanical predicate namespace/alias repairs. */
|
|
79
79
|
export declare const PREDICATE_SCHEMA_ALIGNMENT_CODE = "predicate_schema_alignment";
|
|
80
|
+
/** Migration code of the grouped untracked-source parity findings. */
|
|
81
|
+
export declare const UNTRACKED_KNOWLEDGE_SOURCES_CODE = "untracked_knowledge_sources";
|
|
80
82
|
export declare function buildActionsFromCheck(input: {
|
|
81
83
|
violations?: readonly Readonly<Record<string, unknown>>[];
|
|
82
84
|
qualityDiagnostics?: readonly Readonly<Record<string, unknown>>[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-plan.d.ts","sourceRoot":"","sources":["../../../src/public/operations/migration-plan.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"migration-plan.d.ts","sourceRoot":"","sources":["../../../src/public/operations/migration-plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -261,14 +261,80 @@ function predicateSchemaAlignmentAction(diagnostic) {
|
|
|
261
261
|
}
|
|
262
262
|
/** Migration code for mechanical predicate namespace/alias repairs. */
|
|
263
263
|
export const PREDICATE_SCHEMA_ALIGNMENT_CODE = "predicate_schema_alignment";
|
|
264
|
+
/** Migration code of the grouped untracked-source parity findings. */
|
|
265
|
+
export const UNTRACKED_KNOWLEDGE_SOURCES_CODE = "untracked_knowledge_sources";
|
|
266
|
+
/**
|
|
267
|
+
* Every source-relationship-parity finding explained by untracked files
|
|
268
|
+
* (evidence `untrackedSources`) has one cause and one fix: the files Git
|
|
269
|
+
* does not track and no pending-source receipt covers. After a storage move
|
|
270
|
+
* that can be thousands of relationships, so they become one review action
|
|
271
|
+
* naming the files instead of one per relationship.
|
|
272
|
+
*/
|
|
273
|
+
// implements REQ-agent-guided-migration-orchestration, REQ-kibi-source-relationship-parity
|
|
274
|
+
function untrackedSourceActionFromViolations(violations) {
|
|
275
|
+
const consumed = new Set();
|
|
276
|
+
const files = new Set();
|
|
277
|
+
const entityIds = new Set();
|
|
278
|
+
const relationships = [];
|
|
279
|
+
for (const [index, violation] of violations.entries()) {
|
|
280
|
+
if (violation.rule !== "source-relationship-parity")
|
|
281
|
+
continue;
|
|
282
|
+
const evidence = isRecord(violation.evidence) ? violation.evidence : {};
|
|
283
|
+
const sources = Array.isArray(evidence.untrackedSources)
|
|
284
|
+
? evidence.untrackedSources.filter(isRecord)
|
|
285
|
+
: [];
|
|
286
|
+
if (sources.length === 0)
|
|
287
|
+
continue;
|
|
288
|
+
consumed.add(index);
|
|
289
|
+
for (const source of sources) {
|
|
290
|
+
if (typeof source.file === "string")
|
|
291
|
+
files.add(source.file);
|
|
292
|
+
if (typeof source.entityId === "string")
|
|
293
|
+
entityIds.add(source.entityId);
|
|
294
|
+
}
|
|
295
|
+
if (evidence.relationship !== undefined)
|
|
296
|
+
relationships.push(evidence.relationship);
|
|
297
|
+
}
|
|
298
|
+
if (consumed.size === 0)
|
|
299
|
+
return null;
|
|
300
|
+
const listed = [...files].sort();
|
|
301
|
+
return {
|
|
302
|
+
consumed,
|
|
303
|
+
action: migrationAction({
|
|
304
|
+
id: "untracked-knowledge-sources",
|
|
305
|
+
code: UNTRACKED_KNOWLEDGE_SOURCES_CODE,
|
|
306
|
+
category: "relationship",
|
|
307
|
+
safety: "review",
|
|
308
|
+
invocation: {
|
|
309
|
+
kind: "review",
|
|
310
|
+
instruction: `${consumed.size} authored relationship(s) are missing from the compiled KB because ${listed.length} file(s) declaring their endpoints are not tracked by Git and no pending-source receipt covers them: ${listed.join(", ")}. Stage them (git add; staging is enough, Kibi never stages files itself) or rewrite the entities with kb_upsert, then run kibi sync and rerun kibi migrate.`,
|
|
311
|
+
},
|
|
312
|
+
affectedEntityIds: [...entityIds],
|
|
313
|
+
affectedFiles: listed,
|
|
314
|
+
postconditions: [{ rule: "source-relationship-parity", findings: 0 }],
|
|
315
|
+
evidence: {
|
|
316
|
+
relationshipCount: consumed.size,
|
|
317
|
+
files: listed,
|
|
318
|
+
// A sample; the count above is the full number.
|
|
319
|
+
relationships: relationships.slice(0, 20),
|
|
320
|
+
},
|
|
321
|
+
dispositionRequired: true,
|
|
322
|
+
}),
|
|
323
|
+
};
|
|
324
|
+
}
|
|
264
325
|
// implements REQ-agent-guided-migration-orchestration, REQ-kibi-predicate-vocabulary-migration, REQ-cli-schema-migration
|
|
265
326
|
export function buildActionsFromCheck(input) {
|
|
266
327
|
const actions = [];
|
|
267
328
|
const lifecycle = lifecycleActionsFromViolations(input.violations ?? []);
|
|
268
329
|
actions.push(...lifecycle.actions.map(migrationAction));
|
|
330
|
+
const untracked = untrackedSourceActionFromViolations(input.violations ?? []);
|
|
331
|
+
if (untracked !== null)
|
|
332
|
+
actions.push(untracked.action);
|
|
269
333
|
for (const [index, violation] of (input.violations ?? []).entries()) {
|
|
270
334
|
if (lifecycle.consumed.has(index))
|
|
271
335
|
continue;
|
|
336
|
+
if (untracked?.consumed.has(index))
|
|
337
|
+
continue;
|
|
272
338
|
const rule = typeof violation.rule === "string" ? violation.rule : "check";
|
|
273
339
|
const entityId = typeof violation.entityId === "string" ? violation.entityId : "";
|
|
274
340
|
const suggestion = typeof violation.suggestion === "string"
|
|
@@ -442,6 +508,17 @@ function readLegacySchemaVersion(workspaceRoot) {
|
|
|
442
508
|
// implements REQ-agent-guided-migration-orchestration
|
|
443
509
|
/** Migration action code of the automatic recompile of changed sources. */
|
|
444
510
|
export const FRESHNESS_RESYNC = "freshness_resync";
|
|
511
|
+
// implements REQ-cli-status-pre-first-sync
|
|
512
|
+
/**
|
|
513
|
+
* Stale reasons one `kibi sync` clears: sources whose content changed since
|
|
514
|
+
* the last compilation, and a store compiled under another compiler contract
|
|
515
|
+
* (the sync discards that cache, re-imports every source and stamps the
|
|
516
|
+
* current contract).
|
|
517
|
+
*/
|
|
518
|
+
const RESYNC_REASON_CODES = new Set([
|
|
519
|
+
...MTIME_SOURCE_REASON_CODES,
|
|
520
|
+
"compiler_changed",
|
|
521
|
+
]);
|
|
445
522
|
export function buildActionsFromStatus(input) {
|
|
446
523
|
const actions = [];
|
|
447
524
|
const attachment = input.branchAttachment;
|
|
@@ -488,14 +565,19 @@ export function buildActionsFromStatus(input) {
|
|
|
488
565
|
}));
|
|
489
566
|
}
|
|
490
567
|
const storeState = typeof store?.state === "string" ? store.state : null;
|
|
491
|
-
|
|
568
|
+
// Legacy storage is evaluated whether or not the legacy config survives:
|
|
569
|
+
// legacy copies left beside a migrated .kb/ (moved, identical or stale)
|
|
570
|
+
// are the same finding 'kibi doctor' and 'kibi migrate' report.
|
|
571
|
+
// implements REQ-cli-schema-migration
|
|
572
|
+
const legacyStorage = planLegacyStorageMigration(input.workspaceRoot);
|
|
573
|
+
const legacyStorageMigrationRequired = legacyConfigExists(input.workspaceRoot) ||
|
|
574
|
+
legacyStorage.moves.length > 0 ||
|
|
575
|
+
legacyStorage.removals.length > 0 ||
|
|
576
|
+
legacyStorage.blockers.length > 0;
|
|
492
577
|
// A legacy cutover that cannot move its files (a destination already
|
|
493
578
|
// exists, a malformed config) is an operator decision, not an automatic
|
|
494
579
|
// step that fails when applied and takes the compile with it.
|
|
495
|
-
const
|
|
496
|
-
? planLegacyStorageMigration(input.workspaceRoot)
|
|
497
|
-
: null;
|
|
498
|
-
const legacyStorageBlocked = legacyStorage !== null && legacyStorage.blockers.length > 0;
|
|
580
|
+
const legacyStorageBlocked = legacyStorage.blockers.length > 0;
|
|
499
581
|
if (storeState === "missing") {
|
|
500
582
|
actions.push(migrationAction({
|
|
501
583
|
id: "branch-store-ensure",
|
|
@@ -542,26 +624,29 @@ export function buildActionsFromStatus(input) {
|
|
|
542
624
|
invocation: legacyStorageBlocked
|
|
543
625
|
? {
|
|
544
626
|
kind: "review",
|
|
545
|
-
instruction: `
|
|
627
|
+
instruction: `Legacy knowledge files outside .kb/ cannot be migrated automatically: ${legacyStorage.blockers.join(" ")} Then run 'kibi migrate --yes'.`,
|
|
546
628
|
}
|
|
547
629
|
: { kind: "cli", command_argv: ["kibi", "migrate", "--yes"] },
|
|
548
630
|
affectedFiles: [
|
|
549
631
|
".kb/manifest.json",
|
|
550
632
|
".kb/migrations",
|
|
551
633
|
".kb/config.json",
|
|
552
|
-
...
|
|
634
|
+
...legacyStorage.moves.map((move) => move.from),
|
|
635
|
+
...legacyStorage.removals.map((removal) => removal.path),
|
|
553
636
|
],
|
|
554
637
|
evidence: {
|
|
555
638
|
configStatus,
|
|
556
|
-
...(
|
|
557
|
-
? {
|
|
558
|
-
: {
|
|
639
|
+
...(legacyStorageMigrationRequired
|
|
640
|
+
? {
|
|
559
641
|
legacyStorage: {
|
|
560
642
|
moves: legacyStorage.moves,
|
|
643
|
+
removals: legacyStorage.removals,
|
|
644
|
+
conflicts: legacyStorage.conflicts,
|
|
561
645
|
blockers: legacyStorage.blockers,
|
|
562
646
|
legacyConfig: legacyStorage.legacyConfig,
|
|
563
647
|
},
|
|
564
|
-
}
|
|
648
|
+
}
|
|
649
|
+
: {}),
|
|
565
650
|
},
|
|
566
651
|
dependsOn: storeState === "missing" ? ["branch-store-ensure"] : [],
|
|
567
652
|
autoApplicable: !operatorOnly,
|
|
@@ -598,10 +683,10 @@ export function buildActionsFromStatus(input) {
|
|
|
598
683
|
// implements REQ-cli-status-pre-first-sync
|
|
599
684
|
// Sources whose content changed since the last compilation (kb_status has
|
|
600
685
|
// already dropped mtime-only reasons) are fixed by recompiling them: one
|
|
601
|
-
// automatic `kibi sync`, not a review per file.
|
|
602
|
-
//
|
|
603
|
-
|
|
604
|
-
|
|
686
|
+
// automatic `kibi sync`, not a review per file. A store compiled under
|
|
687
|
+
// another compiler contract is fixed by the same sync. An uncompiled store
|
|
688
|
+
// is compiled by the step above, which also covers these reasons.
|
|
689
|
+
const resyncReasons = (input.staleReasons ?? []).filter((reason) => typeof reason.code === "string" && RESYNC_REASON_CODES.has(reason.code));
|
|
605
690
|
if (resyncReasons.length > 0 && uncompiled === undefined) {
|
|
606
691
|
actions.push(migrationAction({
|
|
607
692
|
id: "freshness-resync",
|
|
@@ -626,7 +711,7 @@ export function buildActionsFromStatus(input) {
|
|
|
626
711
|
if (code === BRANCH_STORE_NOT_COMPILED)
|
|
627
712
|
continue;
|
|
628
713
|
// Planned above as one automatic resync (or covered by the compile).
|
|
629
|
-
if (
|
|
714
|
+
if (RESYNC_REASON_CODES.has(code))
|
|
630
715
|
continue;
|
|
631
716
|
const file = typeof reason.path === "string" ? reason.path : "";
|
|
632
717
|
actions.push(migrationAction({
|