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
|
@@ -0,0 +1,105 @@
|
|
|
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 { planInventoryRederivation, } from "./inventory-rederive.js";
|
|
20
|
+
import { listLaneMarkdownFiles, readText, readTopLevelField, sliceFrontmatter, withTopLevelField, writeFileAtomically, } from "./kb-sources.js";
|
|
21
|
+
/**
|
|
22
|
+
* Requirement statuses outside the current vocabulary (`req-status-vocabulary`).
|
|
23
|
+
*
|
|
24
|
+
* A requirement with ADR vocabulary such as `status: accepted` compiles, but
|
|
25
|
+
* it is not a current requirement: the proof ladder skips it and the
|
|
26
|
+
* ingestion boundary does not validate its semantic inventory, so inventory
|
|
27
|
+
* drift stays hidden until someone maps the status. Which current status a
|
|
28
|
+
* legacy one means is a semantic choice, so the mapping is only suggested;
|
|
29
|
+
* the latent drift is computed as if the suggestion were applied.
|
|
30
|
+
*/
|
|
31
|
+
/** Statuses `kibi check` accepts on a requirement (canonical and legacy). */
|
|
32
|
+
const REQUIREMENT_STATUSES = new Set([
|
|
33
|
+
"open",
|
|
34
|
+
"in_progress",
|
|
35
|
+
"closed",
|
|
36
|
+
"active",
|
|
37
|
+
"approved",
|
|
38
|
+
]);
|
|
39
|
+
/**
|
|
40
|
+
* Suggested current status for ADR or lifecycle vocabulary found on
|
|
41
|
+
* requirements: decided or still-proposed intent stays `open`; retired
|
|
42
|
+
* intent is `closed`.
|
|
43
|
+
*/
|
|
44
|
+
// implements REQ-cli-schema-migration
|
|
45
|
+
export const SUGGESTED_REQUIREMENT_STATUS = {
|
|
46
|
+
accepted: "open",
|
|
47
|
+
proposed: "open",
|
|
48
|
+
draft: "open",
|
|
49
|
+
deprecated: "closed",
|
|
50
|
+
superseded: "closed",
|
|
51
|
+
rejected: "closed",
|
|
52
|
+
};
|
|
53
|
+
function statusOf(content) {
|
|
54
|
+
const slice = sliceFrontmatter(content);
|
|
55
|
+
return slice === null ? undefined : readTopLevelField(slice.text, "status");
|
|
56
|
+
}
|
|
57
|
+
function idOf(content) {
|
|
58
|
+
const slice = sliceFrontmatter(content);
|
|
59
|
+
return slice === null ? undefined : readTopLevelField(slice.text, "id");
|
|
60
|
+
}
|
|
61
|
+
/** Every requirement whose authored status is outside the vocabulary. */
|
|
62
|
+
// implements REQ-cli-schema-migration
|
|
63
|
+
export function planRequirementStatusMappings(workspaceRoot) {
|
|
64
|
+
const findings = [];
|
|
65
|
+
for (const file of listLaneMarkdownFiles(workspaceRoot, ["requirements"])) {
|
|
66
|
+
const content = readText(file.absolutePath);
|
|
67
|
+
if (content === null)
|
|
68
|
+
continue;
|
|
69
|
+
const status = statusOf(content);
|
|
70
|
+
if (typeof status !== "string" || REQUIREMENT_STATUSES.has(status))
|
|
71
|
+
continue;
|
|
72
|
+
const id = idOf(content);
|
|
73
|
+
const requirementId = typeof id === "string" && id.length > 0
|
|
74
|
+
? id
|
|
75
|
+
: path.basename(file.relativePath, ".md");
|
|
76
|
+
const suggestedStatus = SUGGESTED_REQUIREMENT_STATUS[status] ?? null;
|
|
77
|
+
findings.push({
|
|
78
|
+
requirementId,
|
|
79
|
+
path: file.relativePath,
|
|
80
|
+
status,
|
|
81
|
+
suggestedStatus,
|
|
82
|
+
latentDrift: suggestedStatus === null
|
|
83
|
+
? null
|
|
84
|
+
: (planInventoryRederivation(workspaceRoot, requirementId, {
|
|
85
|
+
status: suggestedStatus,
|
|
86
|
+
}).find((plan) => plan.requirementId === requirementId) ?? null),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return findings.sort((left, right) => left.requirementId.localeCompare(right.requirementId));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Set the status of one requirement from `from` to `to`, replacing only its
|
|
93
|
+
* `status` line. Refuses when the authored status is no longer `from`.
|
|
94
|
+
*/
|
|
95
|
+
// implements REQ-cli-schema-migration
|
|
96
|
+
export function applyRequirementStatusMapping(workspaceRoot, relativePath, from, to) {
|
|
97
|
+
const absolute = path.join(workspaceRoot, relativePath);
|
|
98
|
+
const content = readText(absolute);
|
|
99
|
+
if (content === null || statusOf(content) !== from)
|
|
100
|
+
throw new Error(`${relativePath} no longer has status ${from}; rerun kibi migrate and approve the new plan.`);
|
|
101
|
+
const next = withTopLevelField(content, "status", to);
|
|
102
|
+
if (next === null)
|
|
103
|
+
throw new Error(`${relativePath}: status could not be set to ${to} without changing other frontmatter fields; set it by hand.`);
|
|
104
|
+
writeFileAtomically(absolute, next);
|
|
105
|
+
}
|
|
@@ -4,14 +4,31 @@ import { CLOSE_SUPERSEDED_REQUIREMENTS_CODE, MIGRATION_SYNC_ACTION_ID, MIGRATION
|
|
|
4
4
|
export declare const ORIGIN_SCHEMA_VERSION = 6;
|
|
5
5
|
/** The KB schema generation that requires body context on current entities. */
|
|
6
6
|
export declare const BODY_CONTEXT_SCHEMA_VERSION = 8;
|
|
7
|
+
/** The KB schema generation that adds decision firmness. */
|
|
8
|
+
export declare const DECISION_FIRMNESS_SCHEMA_VERSION = 9;
|
|
7
9
|
/** Automatic: re-derive a drifted inventory with the current advisor. */
|
|
8
10
|
export declare const SEMANTIC_INVENTORY_REDERIVE_CODE = "semantic_inventory_rederive";
|
|
9
11
|
/** Review: a drifted inventory Kibi cannot re-derive safely. */
|
|
10
12
|
export declare const SEMANTIC_INVENTORY_REVIEW_CODE = "semantic_inventory_review";
|
|
13
|
+
/**
|
|
14
|
+
* Review, applied only when approved by id: re-derive a drifted inventory and
|
|
15
|
+
* drop the grounding links that no longer ground a modeled claim.
|
|
16
|
+
*/
|
|
17
|
+
export declare const SEMANTIC_INVENTORY_REDERIVE_DROP_GROUNDING_CODE = "semantic_inventory_rederive_drop_grounding";
|
|
18
|
+
/** Review, applied only when approved by id: map a legacy requirement status. */
|
|
19
|
+
export declare const REQ_STATUS_VOCABULARY_MAP_CODE = "req_status_vocabulary_map";
|
|
11
20
|
/** Automatic: stamp `origin: {kind: migration}` on authored entities. */
|
|
12
21
|
export declare const ENTITY_ORIGIN_BACKFILL_CODE = "entity_origin_backfill";
|
|
13
22
|
export declare const ENTITY_ORIGIN_BACKFILL_ACTION_ID = "entity-origin-backfill";
|
|
14
23
|
export { CLOSE_SUPERSEDED_REQUIREMENTS_CODE, MIGRATION_SYNC_ACTION_ID, MIGRATION_SYNC_CODE, SOURCE_PATH_REWRITE_CODE, };
|
|
24
|
+
/**
|
|
25
|
+
* One action per requirement whose status is outside the vocabulary: a
|
|
26
|
+
* review (the target status is a semantic choice) carrying the suggested
|
|
27
|
+
* mapping and the inventory drift the requirement shows once mapped. With a
|
|
28
|
+
* suggestion it is executable when approved by id; the re-derivation of the
|
|
29
|
+
* latent drift depends on it.
|
|
30
|
+
*/
|
|
31
|
+
export declare function requirementStatusActions(workspaceRoot: string): MigrationAction[];
|
|
15
32
|
/**
|
|
16
33
|
* Exceptions without approved_by, read from authored sources so the list is
|
|
17
34
|
* available before the KB compiles.
|
|
@@ -49,6 +66,11 @@ export declare function buildLifecycleRepairActions(workspaceRoot: string): {
|
|
|
49
66
|
actions: MigrationAction[];
|
|
50
67
|
sourceRewriteActionIds: string[];
|
|
51
68
|
};
|
|
69
|
+
/**
|
|
70
|
+
* The automatic legacy-link pass over `.kb/symbols.yaml`, bound to the
|
|
71
|
+
* manifest bytes it was planned from; null when no link needs a mark.
|
|
72
|
+
*/
|
|
73
|
+
export declare function symbolLegacyLinkAction(workspaceRoot: string): MigrationAction | null;
|
|
52
74
|
/** The sync that recompiles sources rewritten by earlier actions. */
|
|
53
75
|
export declare function migrationSyncAction(dependsOn: readonly string[]): MigrationAction;
|
|
54
76
|
type ApplyContext = Readonly<{
|
|
@@ -57,5 +79,10 @@ type ApplyContext = Readonly<{
|
|
|
57
79
|
}>;
|
|
58
80
|
/** Execute one automatic action produced by this module. */
|
|
59
81
|
export declare function applySchema6MigrationAction(action: MigrationAction, context: ApplyContext): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Review actions Kibi can execute, but only when a person approves them by
|
|
84
|
+
* id (`--approved-action`): `--apply-safe` selects automatic actions alone.
|
|
85
|
+
*/
|
|
86
|
+
export declare const SCHEMA6_APPROVABLE_REVIEW_CODES: ReadonlySet<string>;
|
|
60
87
|
export declare const SCHEMA6_AUTOMATIC_CODES: ReadonlySet<string>;
|
|
61
88
|
//# sourceMappingURL=schema6.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema6.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/schema6.ts"],"names":[],"mappings":"AAuBA,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAEL,kCAAkC,EAClC,wBAAwB,EACxB,mBAAmB,EAEnB,wBAAwB,EAOzB,MAAM,kDAAkD,CAAC;
|
|
1
|
+
{"version":3,"file":"schema6.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/schema6.ts"],"names":[],"mappings":"AAuBA,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAEL,kCAAkC,EAClC,wBAAwB,EACxB,mBAAmB,EAEnB,wBAAwB,EAOzB,MAAM,kDAAkD,CAAC;AAoD1D,gEAAgE;AAEhE,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,+EAA+E;AAE/E,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,4DAA4D;AAE5D,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAElD,yEAAyE;AAEzE,eAAO,MAAM,gCAAgC,gCAAgC,CAAC;AAC9E,gEAAgE;AAEhE,eAAO,MAAM,8BAA8B,8BAA8B,CAAC;AAC1E;;;GAGG;AAEH,eAAO,MAAM,+CAA+C,+CACd,CAAC;AAC/C,iFAAiF;AAEjF,eAAO,MAAM,8BAA8B,8BAA8B,CAAC;AAC1E,yEAAyE;AAEzE,eAAO,MAAM,2BAA2B,2BAA2B,CAAC;AAEpE,eAAO,MAAM,gCAAgC,2BAA2B,CAAC;AACzE,OAAO,EACL,kCAAkC,EAClC,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,GACzB,CAAC;AAgLF;;;;;;GAMG;AAEH,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,GACpB,eAAe,EAAE,CAqEnB;AAyBD;;;GAGG;AAEH,wBAAgB,+BAA+B,CAC7C,aAAa,EAAE,MAAM,GACpB,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAsDnE;AAGD,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,uDAAuD;IACvD,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC,CAAC,CAAC;AAEH;;;;;;GAMG;AAEH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,GAAG,wBAAwB,CAgN3B;AAED;;;;;;GAMG;AAEH,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG;IAClE,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,sBAAsB,EAAE,MAAM,EAAE,CAAC;CAClC,CAoCA;AAED;;;GAGG;AAEH,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,GACpB,eAAe,GAAG,IAAI,CAqBxB;AAED,qEAAqE;AAErE,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,eAAe,CAEjB;AA0CD,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC,CAAC;AAEH,4DAA4D;AAE5D,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAgHf;AAED;;;GAGG;AAEH,eAAO,MAAM,+BAA+B,EAAE,WAAW,CAAC,MAAM,CAK9D,CAAC;AAGH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAWtD,CAAC"}
|
|
@@ -21,24 +21,39 @@ import { migrationAction, } from "../../public/operations/migration-plan.js";
|
|
|
21
21
|
import { CLOSE_SUPERSEDED_REQUIREMENTS_ACTION_ID, CLOSE_SUPERSEDED_REQUIREMENTS_CODE, MIGRATION_SYNC_ACTION_ID, MIGRATION_SYNC_CODE, SOURCE_PATH_REWRITE_ACTION_ID, SOURCE_PATH_REWRITE_CODE, closeSupersededRequirementsActionInput, exceptionUnapprovedActionInput, migrationSyncActionInput, sourcePathReviewActionInput, sourcePathRewriteActionInput, supersessionCycleReviewActionInput, } from "../../public/operations/schema6-check-actions.js";
|
|
22
22
|
import { readAllShards } from "../../relationships/shards.js";
|
|
23
23
|
import { CONTEXT_MISSING_TAG_CODE, SEMANTIC_TEXT_PIN_CODE, applyContextMissingTags, applySemanticTextPins, countByType, planContextMissingTags, planSemanticTextPins, } from "./entity-body-context.js";
|
|
24
|
-
import { applyInventoryRederivation, planInventoryRederivation, } from "./inventory-rederive.js";
|
|
24
|
+
import { applyInventoryRederivation, applyInventoryRederivationDroppingGrounding, planInventoryRederivation, } from "./inventory-rederive.js";
|
|
25
25
|
import { listLaneMarkdownFiles } from "./kb-sources.js";
|
|
26
26
|
import { applyOriginBackfill, planOriginBackfill } from "./origin-backfill.js";
|
|
27
27
|
import { POLARITY_VALUE_BACKFILL_CODE, applyPolarityValueBackfill, planPolarityValueBackfill, } from "./polarity-values.js";
|
|
28
|
+
import { applyRequirementStatusMapping, planRequirementStatusMappings, } from "./requirement-status.js";
|
|
28
29
|
import { applySourcePathRepairs, findSourceRepairs, plannedSourcePathRepairs, } from "./source-paths.js";
|
|
29
30
|
import { applySupersededClosures, planSupersededClosures, } from "./superseded-closure.js";
|
|
31
|
+
import { SUPERSEDES_REASON_ACKNOWLEDGE_CODE, applySupersedesReasonAcknowledgement, planSupersedesReasonAcknowledgement, } from "./supersedes-reason.js";
|
|
32
|
+
import { SYMBOL_LEGACY_LINK_MARK_ACTION_ID, SYMBOL_LEGACY_LINK_MARK_CODE, applySymbolLegacyLinks, planSymbolLegacyLinks, } from "./symbol-legacy-links.js";
|
|
30
33
|
/** The KB schema generation that introduced entity `origin`. */
|
|
31
34
|
// implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
|
|
32
35
|
export const ORIGIN_SCHEMA_VERSION = 6;
|
|
33
36
|
/** The KB schema generation that requires body context on current entities. */
|
|
34
37
|
// implements REQ-kb-entity-body-context, REQ-cli-schema-migration
|
|
35
38
|
export const BODY_CONTEXT_SCHEMA_VERSION = 8;
|
|
39
|
+
/** The KB schema generation that adds decision firmness. */
|
|
40
|
+
// implements REQ-kb-decision-firmness, REQ-cli-schema-migration
|
|
41
|
+
export const DECISION_FIRMNESS_SCHEMA_VERSION = 9;
|
|
36
42
|
/** Automatic: re-derive a drifted inventory with the current advisor. */
|
|
37
43
|
// implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
|
|
38
44
|
export const SEMANTIC_INVENTORY_REDERIVE_CODE = "semantic_inventory_rederive";
|
|
39
45
|
/** Review: a drifted inventory Kibi cannot re-derive safely. */
|
|
40
46
|
// implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
|
|
41
47
|
export const SEMANTIC_INVENTORY_REVIEW_CODE = "semantic_inventory_review";
|
|
48
|
+
/**
|
|
49
|
+
* Review, applied only when approved by id: re-derive a drifted inventory and
|
|
50
|
+
* drop the grounding links that no longer ground a modeled claim.
|
|
51
|
+
*/
|
|
52
|
+
// implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
|
|
53
|
+
export const SEMANTIC_INVENTORY_REDERIVE_DROP_GROUNDING_CODE = "semantic_inventory_rederive_drop_grounding";
|
|
54
|
+
/** Review, applied only when approved by id: map a legacy requirement status. */
|
|
55
|
+
// implements REQ-cli-schema-migration
|
|
56
|
+
export const REQ_STATUS_VOCABULARY_MAP_CODE = "req_status_vocabulary_map";
|
|
42
57
|
/** Automatic: stamp `origin: {kind: migration}` on authored entities. */
|
|
43
58
|
// implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
|
|
44
59
|
export const ENTITY_ORIGIN_BACKFILL_CODE = "entity_origin_backfill";
|
|
@@ -52,15 +67,33 @@ const CURRENT_REQUIREMENT_STATUSES = new Set([
|
|
|
52
67
|
"active",
|
|
53
68
|
"approved",
|
|
54
69
|
]);
|
|
55
|
-
function rederiveAction(plan) {
|
|
70
|
+
function rederiveAction(plan, after) {
|
|
56
71
|
const changed = plan.changes.filter((change) => change.change !== "kept");
|
|
72
|
+
const id = `semantic-inventory-rederive-${plan.requirementId}`;
|
|
57
73
|
return migrationAction({
|
|
58
|
-
id
|
|
74
|
+
id,
|
|
59
75
|
code: SEMANTIC_INVENTORY_REDERIVE_CODE,
|
|
60
76
|
category: "semantic",
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
77
|
+
...(after === undefined
|
|
78
|
+
? {
|
|
79
|
+
safety: "automatic",
|
|
80
|
+
autoApplicable: true,
|
|
81
|
+
invocation: {
|
|
82
|
+
kind: "cli",
|
|
83
|
+
command_argv: ["kibi", "migrate", "--yes"],
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
: {
|
|
87
|
+
safety: "review",
|
|
88
|
+
autoApplicable: false,
|
|
89
|
+
invocation: {
|
|
90
|
+
kind: "cli",
|
|
91
|
+
command_argv: approvalArgv([after.actionId, id]),
|
|
92
|
+
},
|
|
93
|
+
dependsOn: [after.actionId],
|
|
94
|
+
dispositionRequired: true,
|
|
95
|
+
allowedDispositions: ["fixed", "deferred"],
|
|
96
|
+
}),
|
|
64
97
|
affectedEntityIds: [plan.requirementId],
|
|
65
98
|
affectedFiles: [plan.path],
|
|
66
99
|
postconditions: [
|
|
@@ -77,9 +110,23 @@ function rederiveAction(plan) {
|
|
|
77
110
|
changes: changed,
|
|
78
111
|
contractHash: plan.contractHash,
|
|
79
112
|
rule: "Claims whose claim_key and claim_text still match keep their status and grounding; new or changed claims are unresolved, never modeled.",
|
|
113
|
+
...(after === undefined
|
|
114
|
+
? {}
|
|
115
|
+
: {
|
|
116
|
+
afterStatus: after.status,
|
|
117
|
+
note: `This drift shows once the requirement has status ${after.status}; approve it together with ${after.actionId}.`,
|
|
118
|
+
}),
|
|
80
119
|
},
|
|
81
120
|
});
|
|
82
121
|
}
|
|
122
|
+
function approvalArgv(ids) {
|
|
123
|
+
return [
|
|
124
|
+
"kibi",
|
|
125
|
+
"migrate",
|
|
126
|
+
"--apply-safe",
|
|
127
|
+
...ids.flatMap((id) => ["--approved-action", id]),
|
|
128
|
+
];
|
|
129
|
+
}
|
|
83
130
|
function reviewAction(plan) {
|
|
84
131
|
return migrationAction({
|
|
85
132
|
id: `semantic-inventory-review-${plan.requirementId}`,
|
|
@@ -88,7 +135,7 @@ function reviewAction(plan) {
|
|
|
88
135
|
safety: "review",
|
|
89
136
|
invocation: {
|
|
90
137
|
kind: "review",
|
|
91
|
-
instruction: `${plan.requirementId} (${plan.path}) no longer matches the current semantic advisor and cannot be re-derived automatically: ${plan.reasons.join("; ")}. Fix it
|
|
138
|
+
instruction: `${plan.requirementId} (${plan.path}) no longer matches the current semantic advisor and cannot be re-derived automatically: ${plan.reasons.join("; ")}. Fix it in ${plan.path} itself: kibi sync rejects this requirement, so store-backed tools (kb_upsert, kb_delete) cannot see it until it compiles. In its front matter, write the re-derived contract from this action's evidence.contract (semantic_inventory, logic_claims, semantic_source_hash and their version fields), then make modeled claims and requires_* links match one to one: re-ground or remove each listed grounding link, and keep a claim modeled only while a grounding fact with the same claim_key remains. Run kibi sync to confirm.${plan.rederivableByDroppingGrounding ? ` Or approve semantic-inventory-rederive-drop-grounding-${plan.requirementId}, which writes that contract and removes exactly the listed orphaned grounding links.` : ""} To see how the advisor reads the prose, run \`kibi model --input -\` with {"mode":"analyze","type":"req","id":"${plan.requirementId}","text":<the requirement's semantic_text, or its statement when it has none>}.`,
|
|
92
139
|
},
|
|
93
140
|
affectedEntityIds: [plan.requirementId],
|
|
94
141
|
affectedFiles: [plan.path],
|
|
@@ -99,9 +146,151 @@ function reviewAction(plan) {
|
|
|
99
146
|
reasons: plan.reasons,
|
|
100
147
|
summary: plan.summary,
|
|
101
148
|
changes: plan.changes.filter((change) => change.change !== "kept"),
|
|
149
|
+
contract: plan.contract,
|
|
150
|
+
contractHash: plan.contractHash,
|
|
102
151
|
},
|
|
103
152
|
});
|
|
104
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* The explicit alternative to a manual inventory fix: write the re-derived
|
|
156
|
+
* contract and remove the orphaned grounding links from the requirement's
|
|
157
|
+
* front matter. It drops modeled logic, so it is a review action that
|
|
158
|
+
* `--apply-safe` never selects on its own; approving its id runs it.
|
|
159
|
+
*/
|
|
160
|
+
function dropGroundingAction(plan, after) {
|
|
161
|
+
const id = `semantic-inventory-rederive-drop-grounding-${plan.requirementId}`;
|
|
162
|
+
const drops = plan.orphanedGrounding.map(({ type, target, claimKey }) => ({
|
|
163
|
+
type,
|
|
164
|
+
target,
|
|
165
|
+
claimKey,
|
|
166
|
+
}));
|
|
167
|
+
return migrationAction({
|
|
168
|
+
id,
|
|
169
|
+
code: SEMANTIC_INVENTORY_REDERIVE_DROP_GROUNDING_CODE,
|
|
170
|
+
category: "semantic",
|
|
171
|
+
safety: "review",
|
|
172
|
+
autoApplicable: false,
|
|
173
|
+
invocation: {
|
|
174
|
+
kind: "cli",
|
|
175
|
+
command_argv: approvalArgv(after === undefined ? [id] : [after.actionId, id]),
|
|
176
|
+
},
|
|
177
|
+
dependsOn: after === undefined ? [] : [after.actionId],
|
|
178
|
+
affectedEntityIds: [plan.requirementId],
|
|
179
|
+
affectedFiles: [plan.path],
|
|
180
|
+
postconditions: [
|
|
181
|
+
{
|
|
182
|
+
check: "proposition-complete-ingestion",
|
|
183
|
+
entityId: plan.requirementId,
|
|
184
|
+
errors: 0,
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
dispositionRequired: true,
|
|
188
|
+
allowedDispositions: ["fixed", "deferred"],
|
|
189
|
+
evidence: {
|
|
190
|
+
reason: `Re-derive the semantic inventory of ${plan.requirementId} and drop the ${drops.length} grounding link(s) that no longer ground a modeled claim, so kibi sync accepts it. The modeled logic those links carried is removed from the requirement (the facts themselves stay); re-ground the claims later with kibi model if they still matter.`,
|
|
191
|
+
approve: `kibi migrate --apply-safe --approved-plan-hash <this plan's planHash>${after === undefined ? "" : ` --approved-action ${after.actionId}`} --approved-action ${id}`,
|
|
192
|
+
...(after === undefined ? {} : { afterStatus: after.status }),
|
|
193
|
+
droppedGrounding: drops,
|
|
194
|
+
summary: plan.summary,
|
|
195
|
+
changes: plan.changes.filter((change) => change.change !== "kept"),
|
|
196
|
+
contract: plan.contract,
|
|
197
|
+
contractHash: plan.contractHash,
|
|
198
|
+
...(after === undefined
|
|
199
|
+
? { alternativeTo: `semantic-inventory-review-${plan.requirementId}` }
|
|
200
|
+
: {}),
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
/** The grounding links an approved drop-grounding action lists. */
|
|
205
|
+
function plannedDrops(action) {
|
|
206
|
+
return plannedRecords(action.evidence.droppedGrounding).flatMap(({ type, target }) => typeof type === "string" && typeof target === "string"
|
|
207
|
+
? [{ type, target }]
|
|
208
|
+
: []);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* One action per requirement whose status is outside the vocabulary: a
|
|
212
|
+
* review (the target status is a semantic choice) carrying the suggested
|
|
213
|
+
* mapping and the inventory drift the requirement shows once mapped. With a
|
|
214
|
+
* suggestion it is executable when approved by id; the re-derivation of the
|
|
215
|
+
* latent drift depends on it.
|
|
216
|
+
*/
|
|
217
|
+
// implements REQ-cli-schema-migration, REQ-kibi-proposition-complete-ingestion
|
|
218
|
+
export function requirementStatusActions(workspaceRoot) {
|
|
219
|
+
const actions = [];
|
|
220
|
+
for (const finding of planRequirementStatusMappings(workspaceRoot)) {
|
|
221
|
+
const id = `req-status-vocabulary-map-${finding.requirementId}`;
|
|
222
|
+
const drift = finding.latentDrift;
|
|
223
|
+
const target = finding.suggestedStatus;
|
|
224
|
+
actions.push(migrationAction({
|
|
225
|
+
id,
|
|
226
|
+
code: REQ_STATUS_VOCABULARY_MAP_CODE,
|
|
227
|
+
category: "schema",
|
|
228
|
+
safety: "review",
|
|
229
|
+
autoApplicable: false,
|
|
230
|
+
invocation: target === null
|
|
231
|
+
? {
|
|
232
|
+
kind: "review",
|
|
233
|
+
instruction: `${finding.requirementId} (${finding.path}) has status ${finding.status}, which is not a requirement status, so it is skipped by the proof ladder and its semantic inventory is never validated. Set status to open, in_progress or closed (legacy: active, approved) in the file, or use proof_exempt to park it, then rerun kibi migrate.`,
|
|
234
|
+
}
|
|
235
|
+
: { kind: "cli", command_argv: approvalArgv([id]) },
|
|
236
|
+
affectedEntityIds: [finding.requirementId],
|
|
237
|
+
affectedFiles: [finding.path],
|
|
238
|
+
postconditions: [{ rule: "req-status-vocabulary", findings: 0 }],
|
|
239
|
+
dispositionRequired: true,
|
|
240
|
+
allowedDispositions: ["fixed", "deferred"],
|
|
241
|
+
evidence: {
|
|
242
|
+
reason: `Status ${finding.status} is ADR or lifecycle vocabulary, not a requirement status: the requirement is skipped by the proof ladder and kibi sync never validates its semantic inventory.`,
|
|
243
|
+
status: finding.status,
|
|
244
|
+
suggestedStatus: target,
|
|
245
|
+
...(target === null
|
|
246
|
+
? {}
|
|
247
|
+
: {
|
|
248
|
+
mapping: `${finding.status} -> ${target}`,
|
|
249
|
+
approve: `kibi migrate --apply-safe --approved-plan-hash <this plan's planHash> --approved-action ${id}`,
|
|
250
|
+
choice: "The target status is a semantic choice; to pick another one, set it in the file by hand instead of approving this action.",
|
|
251
|
+
}),
|
|
252
|
+
latentDrift: drift === null
|
|
253
|
+
? null
|
|
254
|
+
: {
|
|
255
|
+
ingestionErrors: drift.errors,
|
|
256
|
+
safe: drift.safe,
|
|
257
|
+
reasons: drift.reasons,
|
|
258
|
+
summary: drift.summary,
|
|
259
|
+
contractHash: drift.contractHash,
|
|
260
|
+
orphanedGrounding: drift.orphanedGrounding,
|
|
261
|
+
...(drift.safe
|
|
262
|
+
? {
|
|
263
|
+
rederiveAction: `semantic-inventory-rederive-${finding.requirementId}`,
|
|
264
|
+
}
|
|
265
|
+
: drift.rederivableByDroppingGrounding
|
|
266
|
+
? {
|
|
267
|
+
rederiveAction: `semantic-inventory-rederive-drop-grounding-${finding.requirementId}`,
|
|
268
|
+
}
|
|
269
|
+
: {
|
|
270
|
+
note: "After the mapping, kibi sync rejects this requirement until its inventory is fixed by hand; rerun kibi migrate for the semantic_inventory_review action.",
|
|
271
|
+
}),
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
}));
|
|
275
|
+
if (target === null || drift === null)
|
|
276
|
+
continue;
|
|
277
|
+
const after = { actionId: id, status: target };
|
|
278
|
+
if (drift.safe)
|
|
279
|
+
actions.push(rederiveAction(drift, after));
|
|
280
|
+
else if (drift.rederivableByDroppingGrounding)
|
|
281
|
+
actions.push(dropGroundingAction(drift, after));
|
|
282
|
+
}
|
|
283
|
+
return actions;
|
|
284
|
+
}
|
|
285
|
+
/** The status mapping an approved req_status_vocabulary_map action lists. */
|
|
286
|
+
function plannedStatusMapping(action) {
|
|
287
|
+
const path = action.affectedFiles[0];
|
|
288
|
+
const from = action.evidence.status;
|
|
289
|
+
const to = action.evidence.suggestedStatus;
|
|
290
|
+
if (path === undefined || typeof from !== "string" || typeof to !== "string")
|
|
291
|
+
throw new Error("Requirement status mapping names no file or target status; set the status by hand.");
|
|
292
|
+
return { path, from, to };
|
|
293
|
+
}
|
|
105
294
|
/**
|
|
106
295
|
* Exceptions without approved_by, read from authored sources so the list is
|
|
107
296
|
* available before the KB compiles.
|
|
@@ -249,13 +438,50 @@ export function buildSchema6MigrationFragment(input) {
|
|
|
249
438
|
}));
|
|
250
439
|
}
|
|
251
440
|
}
|
|
441
|
+
// Schema 9: acknowledge supersedes recorded before they had to explain
|
|
442
|
+
// themselves. Manifest only; no source changes and no reason is written.
|
|
443
|
+
if (input.currentSchemaVersion === null ||
|
|
444
|
+
input.currentSchemaVersion < DECISION_FIRMNESS_SCHEMA_VERSION) {
|
|
445
|
+
const unexplained = planSupersedesReasonAcknowledgement(input.workspaceRoot);
|
|
446
|
+
if (unexplained.length > 0) {
|
|
447
|
+
const id = "supersedes-reason-acknowledge";
|
|
448
|
+
// Not a source rewrite, but the schema upgrade and the store sync
|
|
449
|
+
// must wait for it like one: the bumped schema blocks without it.
|
|
450
|
+
sourceRewriteActionIds.push(id);
|
|
451
|
+
actions.push(migrationAction({
|
|
452
|
+
id,
|
|
453
|
+
code: SUPERSEDES_REASON_ACKNOWLEDGE_CODE,
|
|
454
|
+
category: "schema",
|
|
455
|
+
safety: "automatic",
|
|
456
|
+
autoApplicable: true,
|
|
457
|
+
invocation: {
|
|
458
|
+
kind: "cli",
|
|
459
|
+
command_argv: ["kibi", "migrate", "--yes"],
|
|
460
|
+
},
|
|
461
|
+
affectedEntityIds: unexplained.map((row) => row.id),
|
|
462
|
+
affectedFiles: [".kb/manifest.json"],
|
|
463
|
+
postconditions: [{ rule: "supersedes-reason-missing", findings: 0 }],
|
|
464
|
+
evidence: {
|
|
465
|
+
reason: "Schema 9 blocks a current requirement or ADR that supersedes another without a 'Why this changed' section. Existing ones are acknowledged in the manifest (counted by supersedes-reason-acknowledged); no reason is invented.",
|
|
466
|
+
count: unexplained.length,
|
|
467
|
+
byType: countByType(unexplained),
|
|
468
|
+
preserves: "every authored source file",
|
|
469
|
+
},
|
|
470
|
+
}));
|
|
471
|
+
}
|
|
472
|
+
}
|
|
252
473
|
const drift = planInventoryRederivation(input.workspaceRoot);
|
|
253
474
|
for (const plan of drift) {
|
|
254
475
|
const action = plan.safe ? rederiveAction(plan) : reviewAction(plan);
|
|
255
476
|
actions.push(action);
|
|
256
477
|
if (plan.safe)
|
|
257
478
|
sourceRewriteActionIds.push(action.id);
|
|
479
|
+
if (!plan.safe && plan.rederivableByDroppingGrounding)
|
|
480
|
+
actions.push(dropGroundingAction(plan));
|
|
258
481
|
}
|
|
482
|
+
// Requirements with a status outside the vocabulary: mapping is a review,
|
|
483
|
+
// and their latent drift is re-derived only after an approved mapping.
|
|
484
|
+
actions.push(...requirementStatusActions(input.workspaceRoot));
|
|
259
485
|
if (drift.some((plan) => !plan.safe)) {
|
|
260
486
|
diagnostics.push(`${drift.filter((plan) => !plan.safe).length} requirement inventory(ies) need a manual fix before kibi sync succeeds; see the semantic_inventory_review actions.`);
|
|
261
487
|
}
|
|
@@ -308,6 +534,13 @@ export function buildSchema6MigrationFragment(input) {
|
|
|
308
534
|
const lifecycle = buildLifecycleRepairActions(input.workspaceRoot);
|
|
309
535
|
actions.push(...lifecycle.actions);
|
|
310
536
|
sourceRewriteActionIds.push(...lifecycle.sourceRewriteActionIds);
|
|
537
|
+
// Coarse symbol links the staged gate would block are marked at any schema
|
|
538
|
+
// version, by the gate's own rule.
|
|
539
|
+
const legacyLinks = symbolLegacyLinkAction(input.workspaceRoot);
|
|
540
|
+
if (legacyLinks !== null) {
|
|
541
|
+
actions.push(legacyLinks);
|
|
542
|
+
sourceRewriteActionIds.push(legacyLinks.id);
|
|
543
|
+
}
|
|
311
544
|
return { actions, sourceRewriteActionIds, diagnostics };
|
|
312
545
|
}
|
|
313
546
|
/**
|
|
@@ -348,6 +581,33 @@ export function buildLifecycleRepairActions(workspaceRoot) {
|
|
|
348
581
|
}
|
|
349
582
|
return { actions, sourceRewriteActionIds };
|
|
350
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* The automatic legacy-link pass over `.kb/symbols.yaml`, bound to the
|
|
586
|
+
* manifest bytes it was planned from; null when no link needs a mark.
|
|
587
|
+
*/
|
|
588
|
+
// implements REQ-cli-schema-migration, REQ-symbol-behavioral-anchors
|
|
589
|
+
export function symbolLegacyLinkAction(workspaceRoot) {
|
|
590
|
+
const plan = planSymbolLegacyLinks(workspaceRoot);
|
|
591
|
+
if (plan.targets.length === 0)
|
|
592
|
+
return null;
|
|
593
|
+
return migrationAction({
|
|
594
|
+
id: SYMBOL_LEGACY_LINK_MARK_ACTION_ID,
|
|
595
|
+
code: SYMBOL_LEGACY_LINK_MARK_CODE,
|
|
596
|
+
category: "symbol",
|
|
597
|
+
safety: "automatic",
|
|
598
|
+
autoApplicable: true,
|
|
599
|
+
invocation: { kind: "cli", command_argv: ["kibi", "migrate", "--yes"] },
|
|
600
|
+
affectedEntityIds: plan.targets.map((target) => target.id),
|
|
601
|
+
affectedFiles: [plan.manifestPath],
|
|
602
|
+
postconditions: [{ rule: "symbol_granularity_violation", findings: 0 }],
|
|
603
|
+
evidence: {
|
|
604
|
+
reason: "These symbols link a source file coarsely while it declares narrower behavioral symbols, so the staged check (kibi check --staged) blocks the next commit that touches them. Each gets granularity_reason: legacy-link (accepted legacy granularity); no link moves and no other field changes.",
|
|
605
|
+
count: plan.targets.length,
|
|
606
|
+
manifestHash: plan.manifestHash,
|
|
607
|
+
symbols: plan.targets,
|
|
608
|
+
},
|
|
609
|
+
});
|
|
610
|
+
}
|
|
351
611
|
/** The sync that recompiles sources rewritten by earlier actions. */
|
|
352
612
|
// implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
|
|
353
613
|
export function migrationSyncAction(dependsOn) {
|
|
@@ -397,6 +657,10 @@ export async function applySchema6MigrationAction(action, context) {
|
|
|
397
657
|
applyContextMissingTags(context.workspaceRoot);
|
|
398
658
|
return;
|
|
399
659
|
}
|
|
660
|
+
case SUPERSEDES_REASON_ACKNOWLEDGE_CODE: {
|
|
661
|
+
applySupersedesReasonAcknowledgement(context.workspaceRoot);
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
400
664
|
case SEMANTIC_INVENTORY_REDERIVE_CODE: {
|
|
401
665
|
const requirementId = action.affectedEntityIds[0];
|
|
402
666
|
if (requirementId === undefined)
|
|
@@ -407,9 +671,33 @@ export async function applySchema6MigrationAction(action, context) {
|
|
|
407
671
|
applyInventoryRederivation(context.workspaceRoot, requirementId, contractHash);
|
|
408
672
|
return;
|
|
409
673
|
}
|
|
674
|
+
case REQ_STATUS_VOCABULARY_MAP_CODE: {
|
|
675
|
+
const mapping = plannedStatusMapping(action);
|
|
676
|
+
applyRequirementStatusMapping(context.workspaceRoot, mapping.path, mapping.from, mapping.to);
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
case SEMANTIC_INVENTORY_REDERIVE_DROP_GROUNDING_CODE: {
|
|
680
|
+
const requirementId = action.affectedEntityIds[0];
|
|
681
|
+
const contractHash = action.evidence.contractHash;
|
|
682
|
+
if (requirementId === undefined || typeof contractHash !== "string")
|
|
683
|
+
throw new Error("Inventory re-derivation names no requirement or contract hash.");
|
|
684
|
+
applyInventoryRederivationDroppingGrounding(context.workspaceRoot, requirementId, contractHash, plannedDrops(action));
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
410
687
|
case ENTITY_ORIGIN_BACKFILL_CODE:
|
|
411
688
|
applyOriginBackfill(context.workspaceRoot, context.clock().toISOString());
|
|
412
689
|
return;
|
|
690
|
+
case SYMBOL_LEGACY_LINK_MARK_CODE: {
|
|
691
|
+
const result = applySymbolLegacyLinks(context.workspaceRoot, {
|
|
692
|
+
...(typeof action.evidence.manifestHash === "string"
|
|
693
|
+
? { expectedHash: action.evidence.manifestHash }
|
|
694
|
+
: {}),
|
|
695
|
+
expectedIds: action.affectedEntityIds,
|
|
696
|
+
});
|
|
697
|
+
if (result.unmarked.length > 0)
|
|
698
|
+
throw new Error(`Could not mark ${result.unmarked.join(", ")} as legacy-link in place; add granularity_reason: legacy-link to them by hand.`);
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
413
701
|
case CLOSE_SUPERSEDED_REQUIREMENTS_CODE: {
|
|
414
702
|
const result = applySupersededClosures(context.workspaceRoot, new Set(action.affectedEntityIds));
|
|
415
703
|
if (result.skipped.length > 0)
|
|
@@ -435,14 +723,27 @@ export async function applySchema6MigrationAction(action, context) {
|
|
|
435
723
|
throw new Error(`Migration action '${action.code}' has no schema 6 executor.`);
|
|
436
724
|
}
|
|
437
725
|
}
|
|
726
|
+
/**
|
|
727
|
+
* Review actions Kibi can execute, but only when a person approves them by
|
|
728
|
+
* id (`--approved-action`): `--apply-safe` selects automatic actions alone.
|
|
729
|
+
*/
|
|
730
|
+
// implements REQ-kibi-schema6-migration, REQ-cli-schema-migration, REQ-agent-guided-migration-orchestration
|
|
731
|
+
export const SCHEMA6_APPROVABLE_REVIEW_CODES = new Set([
|
|
732
|
+
SEMANTIC_INVENTORY_REDERIVE_DROP_GROUNDING_CODE,
|
|
733
|
+
REQ_STATUS_VOCABULARY_MAP_CODE,
|
|
734
|
+
// A re-derivation that waits on an approved status mapping.
|
|
735
|
+
SEMANTIC_INVENTORY_REDERIVE_CODE,
|
|
736
|
+
]);
|
|
438
737
|
// implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
|
|
439
738
|
export const SCHEMA6_AUTOMATIC_CODES = new Set([
|
|
440
739
|
POLARITY_VALUE_BACKFILL_CODE,
|
|
441
740
|
SEMANTIC_TEXT_PIN_CODE,
|
|
442
741
|
CONTEXT_MISSING_TAG_CODE,
|
|
742
|
+
SUPERSEDES_REASON_ACKNOWLEDGE_CODE,
|
|
443
743
|
SEMANTIC_INVENTORY_REDERIVE_CODE,
|
|
444
744
|
ENTITY_ORIGIN_BACKFILL_CODE,
|
|
445
745
|
CLOSE_SUPERSEDED_REQUIREMENTS_CODE,
|
|
446
746
|
SOURCE_PATH_REWRITE_CODE,
|
|
747
|
+
SYMBOL_LEGACY_LINK_MARK_CODE,
|
|
447
748
|
MIGRATION_SYNC_CODE,
|
|
448
749
|
]);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Migration action code for the schema 9 acknowledgement. */
|
|
2
|
+
export declare const SUPERSEDES_REASON_ACKNOWLEDGE_CODE = "supersedes_reason_acknowledge";
|
|
3
|
+
/** One superseding decision the migration acknowledges. */
|
|
4
|
+
export type SupersedesReasonTarget = Readonly<{
|
|
5
|
+
id: string;
|
|
6
|
+
type: string;
|
|
7
|
+
path: string;
|
|
8
|
+
/** The supersede edges to acknowledge, as the manifest records them. */
|
|
9
|
+
edges: readonly string[];
|
|
10
|
+
}>;
|
|
11
|
+
/**
|
|
12
|
+
* Superseding requirements and ADRs without a "Why this changed" section
|
|
13
|
+
* whose supersede edges the manifest does not acknowledge yet, retired ones
|
|
14
|
+
* included. Nothing in the sources changes: no reason is written, the
|
|
15
|
+
* manifest only records that these edges predate the rule. Read-only.
|
|
16
|
+
*/
|
|
17
|
+
export declare function planSupersedesReasonAcknowledgement(workspaceRoot: string): SupersedesReasonTarget[];
|
|
18
|
+
/** The manifest list with the targets' edges added, sorted and unique. */
|
|
19
|
+
export declare function mergeSupersedesAcknowledgements(existing: readonly string[] | undefined, targets: readonly SupersedesReasonTarget[]): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Record the acknowledged edges in the manifest; returns how many entities
|
|
22
|
+
* were acknowledged. Without a manifest there is no schema to upgrade from,
|
|
23
|
+
* so it refuses rather than report an acknowledgement it did not write.
|
|
24
|
+
*/
|
|
25
|
+
export declare function applySupersedesReasonAcknowledgement(workspaceRoot: string): number;
|
|
26
|
+
//# sourceMappingURL=supersedes-reason.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supersedes-reason.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/supersedes-reason.ts"],"names":[],"mappings":"AA0BA,8DAA8D;AAE9D,eAAO,MAAM,kCAAkC,kCACd,CAAC;AAElC,2DAA2D;AAE3D,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B,CAAC,CAAC;AAEH;;;;;GAKG;AAEH,wBAAgB,mCAAmC,CACjD,aAAa,EAAE,MAAM,GACpB,sBAAsB,EAAE,CAgB1B;AAED,0EAA0E;AAE1E,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACvC,OAAO,EAAE,SAAS,sBAAsB,EAAE,GACzC,MAAM,EAAE,CAIV;AAED;;;;GAIG;AAEH,wBAAgB,oCAAoC,CAClD,aAAa,EAAE,MAAM,GACpB,MAAM,CAiBR"}
|