kibi-cli 2.25.0 → 2.26.2
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-errors.d.ts +14 -0
- package/dist/cli-errors.d.ts.map +1 -1
- package/dist/cli-errors.js +31 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +28 -0
- package/dist/commands/migrate.d.ts +2 -0
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +125 -6
- package/dist/commands/sync/cache.d.ts +30 -0
- package/dist/commands/sync/cache.d.ts.map +1 -1
- package/dist/commands/sync/cache.js +61 -0
- package/dist/commands/sync/extraction.d.ts +6 -0
- package/dist/commands/sync/extraction.d.ts.map +1 -1
- package/dist/commands/sync/extraction.js +4 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +27 -1
- package/dist/intent-search.d.ts.map +1 -1
- package/dist/intent-search.js +14 -3
- package/dist/operations/bootstrap/claim-restatement.d.ts +37 -0
- package/dist/operations/bootstrap/claim-restatement.d.ts.map +1 -0
- package/dist/operations/bootstrap/claim-restatement.js +83 -0
- package/dist/operations/bootstrap/generate.d.ts.map +1 -1
- package/dist/operations/bootstrap/generate.js +23 -12
- package/dist/operations/bootstrap/intent-claims.d.ts +5 -2
- package/dist/operations/bootstrap/intent-claims.d.ts.map +1 -1
- package/dist/operations/bootstrap/intent-claims.js +44 -4
- package/dist/operations/migration/requirement-status.d.ts +41 -2
- package/dist/operations/migration/requirement-status.d.ts.map +1 -1
- package/dist/operations/migration/requirement-status.js +75 -7
- package/dist/operations/migration/schema6.d.ts +9 -5
- package/dist/operations/migration/schema6.d.ts.map +1 -1
- package/dist/operations/migration/schema6.js +82 -13
- package/dist/operations/migration/symbol-coordinates-refresh.d.ts +36 -0
- package/dist/operations/migration/symbol-coordinates-refresh.d.ts.map +1 -0
- package/dist/operations/migration/symbol-coordinates-refresh.js +99 -0
- package/dist/operations/mutation/source-authoring.d.ts +9 -0
- package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
- package/dist/operations/mutation/source-authoring.js +50 -2
- package/dist/operations/mutation/stored-entity.d.ts +5 -0
- package/dist/operations/mutation/stored-entity.d.ts.map +1 -1
- package/dist/operations/mutation/types.d.ts +1 -1
- package/dist/operations/mutation/types.d.ts.map +1 -1
- package/dist/operations/mutation/uncompiled-source.d.ts +43 -0
- package/dist/operations/mutation/uncompiled-source.d.ts.map +1 -0
- package/dist/operations/mutation/uncompiled-source.js +115 -0
- package/dist/operations/mutation/upsert.d.ts +6 -0
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +32 -5
- package/dist/operations/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +4 -2
- package/dist/public/impact/analyzer.d.ts.map +1 -1
- package/dist/public/impact/analyzer.js +13 -3
- package/dist/public/impact/diagnostics.js +1 -1
- package/dist/public/impact/unowned-files.d.ts +31 -0
- package/dist/public/impact/unowned-files.d.ts.map +1 -0
- package/dist/public/impact/unowned-files.js +171 -0
- package/dist/public/operations/catalog.d.ts +2 -2
- package/dist/public/operations/discovery-entities.d.ts +11 -0
- package/dist/public/operations/discovery-entities.d.ts.map +1 -1
- package/dist/public/operations/discovery-entities.js +28 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +13 -1
- package/dist/public/operations/migration-plan.d.ts +25 -0
- package/dist/public/operations/migration-plan.d.ts.map +1 -1
- package/dist/public/operations/migration-plan.js +40 -0
- package/dist/public/operations/result-envelope.d.ts +2 -0
- package/dist/public/operations/result-envelope.d.ts.map +1 -1
- package/dist/public/operations/result-envelope.js +1 -0
- package/dist/public/operations/source-relationship-parity.d.ts.map +1 -1
- package/dist/public/operations/source-relationship-parity.js +22 -7
- package/dist/public/operations/specs/check.d.ts +1 -1
- package/dist/public/operations/specs/check.js +1 -1
- package/dist/public/operations/specs/upsert.d.ts +1 -1
- package/dist/public/operations/specs/upsert.js +1 -1
- package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
- package/dist/public/skills/kibi-usage/SKILL.md +11 -5
- package/dist/search-answer.d.ts +9 -0
- package/dist/search-answer.d.ts.map +1 -1
- package/dist/search-answer.js +66 -3
- package/dist/traceability/git-change-snapshot.d.ts.map +1 -1
- package/dist/traceability/git-change-snapshot.js +44 -3
- package/dist/traceability/staged-diagnostics.d.ts +1 -1
- package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
- package/dist/traceability/staged-migration.d.ts +13 -0
- package/dist/traceability/staged-migration.d.ts.map +1 -0
- package/dist/traceability/staged-migration.js +59 -0
- package/dist/traceability/staged-symbols-manifest.d.ts +11 -0
- package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
- package/dist/traceability/staged-symbols-manifest.js +50 -16
- package/package.json +2 -2
- package/src/public/impact/analyzer.ts +21 -7
- package/src/public/impact/diagnostics.ts +1 -1
- package/src/public/impact/unowned-files.ts +229 -0
- package/src/public/operations/discovery-entities.ts +36 -0
- package/src/public/operations/discovery-executors.ts +17 -1
- package/src/public/operations/migration-plan.ts +72 -0
- package/src/public/operations/result-envelope.ts +3 -0
- package/src/public/operations/source-relationship-parity.ts +22 -7
- package/src/public/operations/specs/check.ts +1 -1
- package/src/public/operations/specs/upsert.ts +1 -1
- package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
- package/src/public/skills/kibi-usage/SKILL.md +11 -5
package/dist/commands/sync.js
CHANGED
|
@@ -644,6 +644,27 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
644
644
|
changedManifestFiles.length === manifestFiles.length;
|
|
645
645
|
const extraction = await processExtractions(changedMarkdownFiles, changedManifestFiles, validateOnly, workspaceRoot);
|
|
646
646
|
const { failedCacheKeys, errors } = extraction;
|
|
647
|
+
// implements REQ-kibi-uncompiled-source-visibility
|
|
648
|
+
// Sources sync could not extract stay out of the store; record them so
|
|
649
|
+
// kb_status can say so. A source that failed in the store's first
|
|
650
|
+
// compilation (and in every sync since) is legacy content that missed the
|
|
651
|
+
// semantic baseline, so it keeps the baseline treatment once it compiles.
|
|
652
|
+
const previousExtractionFailures = syncCache.extractionFailures ?? {};
|
|
653
|
+
const nextExtractionFailures = {};
|
|
654
|
+
for (const failure of extraction.failures) {
|
|
655
|
+
const key = toCacheKey(workspaceRoot, failure.file);
|
|
656
|
+
const hash = nextHashes[key];
|
|
657
|
+
if (hash === undefined)
|
|
658
|
+
continue;
|
|
659
|
+
nextExtractionFailures[key] = {
|
|
660
|
+
hash,
|
|
661
|
+
message: failure.message,
|
|
662
|
+
...(initialSemanticBaseline ||
|
|
663
|
+
previousExtractionFailures[key]?.baseline === true
|
|
664
|
+
? { baseline: true }
|
|
665
|
+
: {}),
|
|
666
|
+
};
|
|
667
|
+
}
|
|
647
668
|
const extractedResults = normalizeExtractionSources(extraction.results, workspaceRoot);
|
|
648
669
|
const nextEntityHashes = {
|
|
649
670
|
...(syncCache.entityHashes ?? {}),
|
|
@@ -739,7 +760,9 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
739
760
|
const advertisedContract = result.entity.semantic_inventory_version !== undefined ||
|
|
740
761
|
result.entity.semantic_source_hash !== undefined ||
|
|
741
762
|
result.entity.semantic_inventory !== undefined;
|
|
742
|
-
const enforceBoundary = (!initialSemanticBaseline &&
|
|
763
|
+
const enforceBoundary = (!initialSemanticBaseline &&
|
|
764
|
+
syncCache.hashes[key] === undefined &&
|
|
765
|
+
previousExtractionFailures[key]?.baseline !== true) ||
|
|
743
766
|
syncCache.semanticContracts[key] === true ||
|
|
744
767
|
(previousSemanticHash !== undefined &&
|
|
745
768
|
previousSemanticHash !== boundary.sourceHash) ||
|
|
@@ -841,6 +864,7 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
841
864
|
semanticHashes: evictedSemanticHashes,
|
|
842
865
|
semanticContracts: evictedSemanticContracts,
|
|
843
866
|
compilerFingerprint: SYNC_COMPILER_FINGERPRINT,
|
|
867
|
+
extractionFailures: nextExtractionFailures,
|
|
844
868
|
});
|
|
845
869
|
info("✓ Imported 0 entities, 0 relationships (no changes)");
|
|
846
870
|
return withOptionalCommit({
|
|
@@ -990,6 +1014,7 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
990
1014
|
semanticHashes: evictedSemanticHashes,
|
|
991
1015
|
semanticContracts: evictedSemanticContracts,
|
|
992
1016
|
compilerFingerprint: SYNC_COMPILER_FINGERPRINT,
|
|
1017
|
+
extractionFailures: nextExtractionFailures,
|
|
993
1018
|
});
|
|
994
1019
|
published = true;
|
|
995
1020
|
if (performedFullReindex &&
|
|
@@ -1180,6 +1205,7 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
1180
1205
|
semanticHashes: evictedSemanticHashes,
|
|
1181
1206
|
semanticContracts: evictedSemanticContracts,
|
|
1182
1207
|
compilerFingerprint: SYNC_COMPILER_FINGERPRINT,
|
|
1208
|
+
extractionFailures: nextExtractionFailures,
|
|
1183
1209
|
});
|
|
1184
1210
|
published = true;
|
|
1185
1211
|
maybePushDocsNotIndexedDiagnostic(diagnostics, performedFullReindex, markdownFiles.length, entityCount);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent-search.d.ts","sourceRoot":"","sources":["../src/intent-search.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,kBAAkB,EAIxB,MAAM,2CAA2C,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,MAAM,MAAM,qBAAqB,GAC7B,QAAQ,GACR,SAAS,GACT,SAAS,GACT,aAAa,GACb,SAAS,CAAC;AAGd,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CACvC,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAC1D,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAGH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IACpD,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACpC,eAAe,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC,CAAC;AAGH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC,CAAC;AAGH,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC,CAAC;AAGH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,aAAa,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC5C,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IACvC,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC,CAAC;AAGH,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG;IAC5C,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;CACzC,CAAC;AAGF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;;;OAKG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC,CAAC;AAGH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACtC,QAAQ,EAAE,oBAAoB,CAAC;CAChC,CAAC,CAAC;AAEH,KAAK,SAAS,GAAG,QAAQ,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC,CAAC;AA6IH,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAQrD;
|
|
1
|
+
{"version":3,"file":"intent-search.d.ts","sourceRoot":"","sources":["../src/intent-search.ts"],"names":[],"mappings":"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"}
|
package/dist/intent-search.js
CHANGED
|
@@ -154,6 +154,13 @@ function topicText(query, locations = []) {
|
|
|
154
154
|
}
|
|
155
155
|
return topic.replace(CAMEL_IDENTIFIER, splitIdentifier);
|
|
156
156
|
}
|
|
157
|
+
const CODE_SPAN = /`([^`\n]+)`/g;
|
|
158
|
+
const CODE_SPAN_WEIGHT = 2;
|
|
159
|
+
/** Tokens of the question's backticked code spans (`canExport(user)`). */
|
|
160
|
+
// implements REQ-kibi-intent-aware-source-discovery
|
|
161
|
+
function codeSpanTokens(topic) {
|
|
162
|
+
return new Set([...topic.matchAll(CODE_SPAN)].flatMap((match) => tokens(match[1] ?? "")));
|
|
163
|
+
}
|
|
157
164
|
function normalize(value) {
|
|
158
165
|
return expandIdentifiers(value)
|
|
159
166
|
.trim()
|
|
@@ -338,7 +345,7 @@ function entityTokens(entity, body) {
|
|
|
338
345
|
ENTITY_TOKENS.set(entity, computed);
|
|
339
346
|
return computed;
|
|
340
347
|
}
|
|
341
|
-
function scoreEntity(entity, queryTokens, facets, sourceEvidence, graphEvidence, documentFrequency, documentCount, body, superseded = false, provenanceStub = false) {
|
|
348
|
+
function scoreEntity(entity, queryTokens, facets, sourceEvidence, graphEvidence, documentFrequency, documentCount, body, superseded = false, provenanceStub = false, emphasis = new Set()) {
|
|
342
349
|
const { title: titleTokens, metadata: metadataTokens, bodyTokens, } = entityTokens(entity, body);
|
|
343
350
|
const allSignalTokens = Array.from(new Set(queryTokens));
|
|
344
351
|
// BM25-style inverse document frequency over title, metadata and body:
|
|
@@ -355,7 +362,10 @@ function scoreEntity(entity, queryTokens, facets, sourceEvidence, graphEvidence,
|
|
|
355
362
|
let total = 0;
|
|
356
363
|
for (const token of allSignalTokens) {
|
|
357
364
|
const frequency = documentFrequency.get(token) ?? 0;
|
|
358
|
-
|
|
365
|
+
// A word the question writes as code (`canExport(user)`) names what it
|
|
366
|
+
// is about, so it weighs twice as much as the words around it.
|
|
367
|
+
const idf = Math.log(1 + (documentCount - frequency + 0.5) / (frequency + 0.5)) *
|
|
368
|
+
(emphasis.has(token) ? CODE_SPAN_WEIGHT : 1);
|
|
359
369
|
const fieldWeight = titleTokens.has(token)
|
|
360
370
|
? 1
|
|
361
371
|
: metadataTokens.has(token)
|
|
@@ -452,6 +462,7 @@ export async function rankIntentEntities(entities, options, workspaceRoot, graph
|
|
|
452
462
|
// Each clause of a compound question is also scored on its own, so the
|
|
453
463
|
// words of one clause do not dilute a match on another.
|
|
454
464
|
const clauseTokenSets = queryClauses(query).map((clause) => Array.from(new Set([...clause, ...facetTokens])));
|
|
465
|
+
const emphasis = codeSpanTokens(query);
|
|
455
466
|
const bodies = await readBodies(entities, workspaceRoot, bodyCache);
|
|
456
467
|
const documentFrequency = buildDocumentFrequency(entities, bodies);
|
|
457
468
|
const supersededIds = new Set(graphEdges
|
|
@@ -486,7 +497,7 @@ export async function rankIntentEntities(entities, options, workspaceRoot, graph
|
|
|
486
497
|
const body = bodies.get(entity) ?? null;
|
|
487
498
|
let scored;
|
|
488
499
|
for (const signalTokens of [allTokens, ...clauseTokenSets]) {
|
|
489
|
-
const candidate = scoreEntity(entity, signalTokens, facets, sourceEvidence, graphEvidence, documentFrequency, entities.length, body, supersededIds.has(entityId), isProvenanceStub(entity));
|
|
500
|
+
const candidate = scoreEntity(entity, signalTokens, facets, sourceEvidence, graphEvidence, documentFrequency, entities.length, body, supersededIds.has(entityId), isProvenanceStub(entity), emphasis);
|
|
490
501
|
if (scored === undefined || candidate.score > scored.score)
|
|
491
502
|
scored = candidate;
|
|
492
503
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** A current requirement a declared intent claim may restate. */
|
|
2
|
+
export type ExistingRequirement = {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly title: string;
|
|
5
|
+
readonly semanticText: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Token-set Jaccard at or above which a claim that is not an exact
|
|
9
|
+
* restatement is still flagged for review: the same threshold the
|
|
10
|
+
* entity-context check uses to call a context section a restatement of the
|
|
11
|
+
* title. Below it a claim is planned with no signal.
|
|
12
|
+
*/
|
|
13
|
+
export declare const NEAR_RESTATEMENT_JACCARD = 0.8;
|
|
14
|
+
export type RestatementMatch = {
|
|
15
|
+
/** exact: the normalized texts are equal; near: overlap at the threshold. */
|
|
16
|
+
readonly kind: "exact" | "near";
|
|
17
|
+
readonly requirementId: string;
|
|
18
|
+
/** The requirement field the claim matched. */
|
|
19
|
+
readonly field: "title" | "semantic_text";
|
|
20
|
+
/** Token-set Jaccard of the closest pair, rounded to two decimals. */
|
|
21
|
+
readonly score: number;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Case, whitespace and punctuation do not change what a sentence says, so
|
|
25
|
+
* they do not count when a claim is compared with a requirement.
|
|
26
|
+
*/
|
|
27
|
+
export declare function normalizeRestatementText(text: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* The current requirement a claim restates, if any. A claim restates a
|
|
30
|
+
* requirement exactly when its statement or excerpt, normalized, equals the
|
|
31
|
+
* requirement's title, its semantic text or one sentence of it; only that
|
|
32
|
+
* counts as already in the KB. A pair at or above NEAR_RESTATEMENT_JACCARD is
|
|
33
|
+
* a near restatement: a review signal, never a reason to drop the claim.
|
|
34
|
+
* Requirements are compared in id order, so the answer is deterministic.
|
|
35
|
+
*/
|
|
36
|
+
export declare function findRestatement(claimTexts: readonly (string | undefined)[], requirements: readonly ExistingRequirement[]): RestatementMatch | null;
|
|
37
|
+
//# sourceMappingURL=claim-restatement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-restatement.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/claim-restatement.ts"],"names":[],"mappings":"AAKA,iEAAiE;AAEjE,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF;;;;;GAKG;AAEH,eAAO,MAAM,wBAAwB,MAAsB,CAAC;AAG5D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAAC;IAC1C,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;GAGG;AAEH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM7D;AAwBD;;;;;;;GAOG;AAEH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,EAC3C,YAAY,EAAE,SAAS,mBAAmB,EAAE,GAC3C,gBAAgB,GAAG,IAAI,CAoCzB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { RESTATEMENT_JACCARD, tokenSetJaccard, } from "../../entity-body-context.js";
|
|
2
|
+
/**
|
|
3
|
+
* Token-set Jaccard at or above which a claim that is not an exact
|
|
4
|
+
* restatement is still flagged for review: the same threshold the
|
|
5
|
+
* entity-context check uses to call a context section a restatement of the
|
|
6
|
+
* title. Below it a claim is planned with no signal.
|
|
7
|
+
*/
|
|
8
|
+
// implements REQ-bootstrap-claim-restatement
|
|
9
|
+
export const NEAR_RESTATEMENT_JACCARD = RESTATEMENT_JACCARD;
|
|
10
|
+
/**
|
|
11
|
+
* Case, whitespace and punctuation do not change what a sentence says, so
|
|
12
|
+
* they do not count when a claim is compared with a requirement.
|
|
13
|
+
*/
|
|
14
|
+
// implements REQ-bootstrap-claim-restatement
|
|
15
|
+
export function normalizeRestatementText(text) {
|
|
16
|
+
return text
|
|
17
|
+
.toLowerCase()
|
|
18
|
+
.split(/[^\p{L}\p{N}]+/u)
|
|
19
|
+
.filter((token) => token !== "")
|
|
20
|
+
.join(" ");
|
|
21
|
+
}
|
|
22
|
+
/** The whole prose and each of its sentences. */
|
|
23
|
+
function proseUnits(text) {
|
|
24
|
+
const sentences = text
|
|
25
|
+
.split(/(?<=[.!?])\s+|\n+/)
|
|
26
|
+
.map((sentence) => sentence.trim())
|
|
27
|
+
.filter((sentence) => sentence !== "");
|
|
28
|
+
return [text, ...sentences];
|
|
29
|
+
}
|
|
30
|
+
function references(requirement) {
|
|
31
|
+
return [
|
|
32
|
+
{ field: "title", text: requirement.title },
|
|
33
|
+
...proseUnits(requirement.semanticText).map((text) => ({
|
|
34
|
+
field: "semantic_text",
|
|
35
|
+
text,
|
|
36
|
+
})),
|
|
37
|
+
].filter((reference) => normalizeRestatementText(reference.text) !== "");
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The current requirement a claim restates, if any. A claim restates a
|
|
41
|
+
* requirement exactly when its statement or excerpt, normalized, equals the
|
|
42
|
+
* requirement's title, its semantic text or one sentence of it; only that
|
|
43
|
+
* counts as already in the KB. A pair at or above NEAR_RESTATEMENT_JACCARD is
|
|
44
|
+
* a near restatement: a review signal, never a reason to drop the claim.
|
|
45
|
+
* Requirements are compared in id order, so the answer is deterministic.
|
|
46
|
+
*/
|
|
47
|
+
// implements REQ-bootstrap-claim-restatement
|
|
48
|
+
export function findRestatement(claimTexts, requirements) {
|
|
49
|
+
const texts = claimTexts
|
|
50
|
+
.filter((text) => typeof text === "string")
|
|
51
|
+
.map((text) => ({ text, normalized: normalizeRestatementText(text) }))
|
|
52
|
+
.filter((text) => text.normalized !== "");
|
|
53
|
+
if (texts.length === 0)
|
|
54
|
+
return null;
|
|
55
|
+
const ordered = [...requirements].sort((left, right) => left.id < right.id ? -1 : left.id > right.id ? 1 : 0);
|
|
56
|
+
let near = null;
|
|
57
|
+
let nearScore = 0;
|
|
58
|
+
for (const requirement of ordered) {
|
|
59
|
+
for (const reference of references(requirement)) {
|
|
60
|
+
const normalized = normalizeRestatementText(reference.text);
|
|
61
|
+
for (const claim of texts) {
|
|
62
|
+
if (claim.normalized === normalized)
|
|
63
|
+
return {
|
|
64
|
+
kind: "exact",
|
|
65
|
+
requirementId: requirement.id,
|
|
66
|
+
field: reference.field,
|
|
67
|
+
score: 1,
|
|
68
|
+
};
|
|
69
|
+
const score = tokenSetJaccard(claim.text, reference.text);
|
|
70
|
+
if (score >= NEAR_RESTATEMENT_JACCARD && score > nearScore) {
|
|
71
|
+
nearScore = score;
|
|
72
|
+
near = {
|
|
73
|
+
kind: "near",
|
|
74
|
+
requirementId: requirement.id,
|
|
75
|
+
field: reference.field,
|
|
76
|
+
score: Math.round(score * 100) / 100,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return near;
|
|
83
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/generate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/generate.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAgBjF,OAAO,KAAK,EAGV,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAGpB,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GACzC,SAAS,gBAAgB,EAAE,CAI7B;AA+BD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,EAChC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAC1C,OAAO,EAAE,MAAM,GACd;IACD,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAClE,QAAQ,CAAC,iBAAiB,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,CAwJA;AAmND,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAwI9B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { loadEntityIds } from "../../public/operations/discovery-entities.js";
|
|
3
|
+
import { loadCurrentRequirementTexts, loadEntityIds, } from "../../public/operations/discovery-entities.js";
|
|
4
4
|
import { executeStatus } from "../../public/operations/discovery-executors.js";
|
|
5
5
|
import { readWorkspaceSnapshot } from "../../public/operations/workspace-snapshot.js";
|
|
6
6
|
import { stagedLogicalGroundingError, } from "../semantic-advisor/ingestion-boundary.js";
|
|
@@ -238,21 +238,31 @@ function activationSuppressedClaims(declared, activation) {
|
|
|
238
238
|
activationMode: activation.activationMode,
|
|
239
239
|
}));
|
|
240
240
|
}
|
|
241
|
+
const NO_EXISTING_KNOWLEDGE = {
|
|
242
|
+
ids: new Set(),
|
|
243
|
+
requirements: [],
|
|
244
|
+
};
|
|
241
245
|
/**
|
|
242
246
|
* IDs already in the KB, so declared claims and discovered candidates that
|
|
243
|
-
* exist are counted under entity_exists instead of being planned again
|
|
244
|
-
*
|
|
245
|
-
*
|
|
247
|
+
* exist are counted under entity_exists instead of being planned again, and,
|
|
248
|
+
* when intent claims are declared, the current requirements those claims may
|
|
249
|
+
* restate. An attached root starts the lazy engine when the host supplied
|
|
250
|
+
* none (the CLI does so for status anyway); an unattached root never starts
|
|
251
|
+
* one.
|
|
246
252
|
*/
|
|
247
|
-
// implements REQ-bootstrap-intent-claim-accounting
|
|
248
|
-
async function
|
|
253
|
+
// implements REQ-bootstrap-intent-claim-accounting, REQ-bootstrap-claim-restatement
|
|
254
|
+
async function existingKnowledge(context, attached, withRequirements) {
|
|
249
255
|
try {
|
|
250
256
|
const prolog = context.prolog ?? (attached ? await context.ensureProlog?.() : undefined);
|
|
251
257
|
if (!prolog)
|
|
252
|
-
return
|
|
258
|
+
return NO_EXISTING_KNOWLEDGE;
|
|
253
259
|
// Ids only: materializing every entity (receipt histories included)
|
|
254
260
|
// just to build this set exceeds the bounded engine output.
|
|
255
|
-
|
|
261
|
+
const ids = new Set((await loadEntityIds(prolog)).filter(Boolean));
|
|
262
|
+
const requirements = withRequirements
|
|
263
|
+
? await loadCurrentRequirementTexts(prolog)
|
|
264
|
+
: [];
|
|
265
|
+
return { ids, requirements };
|
|
256
266
|
}
|
|
257
267
|
catch (error) {
|
|
258
268
|
throw new Error(`Bootstrap binding could not read existing entity IDs: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -346,11 +356,12 @@ export async function executePlanBootstrap(args, context) {
|
|
|
346
356
|
const maxCandidates = clamp(Math.trunc(args.maxCandidates ?? 50), 1, 200);
|
|
347
357
|
const entityBindingDiagnostics = [];
|
|
348
358
|
const discovery = await discoverBootstrap(context);
|
|
349
|
-
const
|
|
350
|
-
discovery.activation.activationState === "root_active_seeded").catch((error) => {
|
|
359
|
+
const existing = await existingKnowledge(context, discovery.activation.activationState === "root_active_thin" ||
|
|
360
|
+
discovery.activation.activationState === "root_active_seeded", (declared.intentClaims?.length ?? 0) > 0).catch((error) => {
|
|
351
361
|
entityBindingDiagnostics.push(error.message);
|
|
352
|
-
return
|
|
362
|
+
return NO_EXISTING_KNOWLEDGE;
|
|
353
363
|
});
|
|
364
|
+
const existingIds = existing.ids;
|
|
354
365
|
// Discovery runs before planning so its evidence paths can be bound into
|
|
355
366
|
// the exact plan rather than leaving the reviewer to reconstruct them.
|
|
356
367
|
const bound = await expectedSnapshots(context, discovery.evidence
|
|
@@ -374,7 +385,7 @@ export async function executePlanBootstrap(args, context) {
|
|
|
374
385
|
const allowDeclaredClaims = discovery.activation.allowDeclaredClaims ??
|
|
375
386
|
discovery.activation.allowCandidateGeneration;
|
|
376
387
|
const claimed = allowDeclaredClaims
|
|
377
|
-
? buildIntentClaimCandidates(declared, existingIds, minConfidence, subjectKeys)
|
|
388
|
+
? buildIntentClaimCandidates(declared, existingIds, minConfidence, subjectKeys, existing.requirements)
|
|
378
389
|
: {
|
|
379
390
|
candidates: [],
|
|
380
391
|
sourceOnlySignals: [],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ExistingRequirement } from "./claim-restatement.js";
|
|
1
2
|
import { type SubjectKeyRegistry } from "./requirement-claims.js";
|
|
2
3
|
import type { BootstrapDeclaredContext, Candidate, SourceOnlySignal } from "./types.js";
|
|
3
4
|
export type IntentClaimBuildResult = {
|
|
@@ -12,7 +13,9 @@ export type IntentClaimBuildResult = {
|
|
|
12
13
|
* what the agent read, binds it into the plan hash through the declared
|
|
13
14
|
* context, and keeps the citation on every candidate it produces. A claim the
|
|
14
15
|
* strict modeler cannot ground stays an explicit authoring follow-up instead
|
|
15
|
-
* of becoming unverifiable knowledge.
|
|
16
|
+
* of becoming unverifiable knowledge. An intent claim whose statement or
|
|
17
|
+
* excerpt restates a current requirement is already in the KB and is counted
|
|
18
|
+
* as such instead of being planned again under a new id.
|
|
16
19
|
*/
|
|
17
|
-
export declare function buildIntentClaimCandidates(declared: BootstrapDeclaredContext, existingIds: ReadonlySet<string>, minConfidence: number, subjectKeys?: SubjectKeyRegistry): IntentClaimBuildResult;
|
|
20
|
+
export declare function buildIntentClaimCandidates(declared: BootstrapDeclaredContext, existingIds: ReadonlySet<string>, minConfidence: number, subjectKeys?: SubjectKeyRegistry, existingRequirements?: readonly ExistingRequirement[]): IntentClaimBuildResult;
|
|
18
21
|
//# sourceMappingURL=intent-claims.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intent-claims.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/intent-claims.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EACV,wBAAwB,EAGxB,SAAS,EACT,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAQpB,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,iBAAiB,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACxD,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAClE,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,CAAC;
|
|
1
|
+
{"version":3,"file":"intent-claims.d.ts","sourceRoot":"","sources":["../../../src/operations/bootstrap/intent-claims.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,mBAAmB,EAGzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EACV,wBAAwB,EAGxB,SAAS,EACT,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAQpB,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,iBAAiB,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACxD,QAAQ,CAAC,UAAU,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAClE,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,CAAC;AAuPF;;;;;;;;;GASG;AAEH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,wBAAwB,EAClC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,EAChC,aAAa,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,kBAAkB,EAChC,oBAAoB,GAAE,SAAS,mBAAmB,EAAO,GACxD,sBAAsB,CA+MxB"}
|
|
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { renderRequirementBody } from "../../entity-body-context.js";
|
|
3
3
|
import { buildStrictWriteSet } from "../../utils/strict-modeling.js";
|
|
4
4
|
import { asImportedRule, confidenceBand, strictPlan, upsert, } from "./candidate-helpers.js";
|
|
5
|
+
import { findRestatement, } from "./claim-restatement.js";
|
|
5
6
|
import { claimFor, planSubjectKey, } from "./requirement-claims.js";
|
|
6
7
|
/** How much a claim is trusted follows the authority the human assigned. */
|
|
7
8
|
const AUTHORITY_CONFIDENCE = {
|
|
@@ -190,16 +191,27 @@ function conflictCandidates(declared, sources, existingIds, minConfidence) {
|
|
|
190
191
|
}
|
|
191
192
|
return { candidates, sourceOnlySignals: [], suppressed, diagnostics };
|
|
192
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* The review signal a planned claim carries when it closely restates a
|
|
196
|
+
* current requirement: kept, but named so the reviewer can drop it or link
|
|
197
|
+
* the two with restates or supersedes.
|
|
198
|
+
*/
|
|
199
|
+
// implements REQ-bootstrap-claim-restatement
|
|
200
|
+
function nearRestatementDiagnostic(source, claim, match) {
|
|
201
|
+
return `Intent claim at ${source.id}:${claim.reference} closely restates current requirement ${match.requirementId} (token overlap ${match.score} with its ${match.field === "title" ? "title" : "semantic text"}, not an exact match); it is still planned. Review it before apply: drop the claim if it states the same rule, or keep it and link the two with restates or supersedes.`;
|
|
202
|
+
}
|
|
193
203
|
/**
|
|
194
204
|
* Turn intent the agent harvested from declared knowledge sources into cited
|
|
195
205
|
* bootstrap candidates. Kibi never contacts those sources: it only records
|
|
196
206
|
* what the agent read, binds it into the plan hash through the declared
|
|
197
207
|
* context, and keeps the citation on every candidate it produces. A claim the
|
|
198
208
|
* strict modeler cannot ground stays an explicit authoring follow-up instead
|
|
199
|
-
* of becoming unverifiable knowledge.
|
|
209
|
+
* of becoming unverifiable knowledge. An intent claim whose statement or
|
|
210
|
+
* excerpt restates a current requirement is already in the KB and is counted
|
|
211
|
+
* as such instead of being planned again under a new id.
|
|
200
212
|
*/
|
|
201
|
-
// implements REQ-kibi-bootstrap-knowledge-sources, REQ-bootstrap-claim-kinds-and-conflicts
|
|
202
|
-
export function buildIntentClaimCandidates(declared, existingIds, minConfidence, subjectKeys) {
|
|
213
|
+
// implements REQ-kibi-bootstrap-knowledge-sources, REQ-bootstrap-claim-kinds-and-conflicts, REQ-bootstrap-claim-restatement
|
|
214
|
+
export function buildIntentClaimCandidates(declared, existingIds, minConfidence, subjectKeys, existingRequirements = []) {
|
|
203
215
|
const sources = new Map((declared.knowledgeSources ?? []).map((source) => [source.id, source]));
|
|
204
216
|
const candidates = [];
|
|
205
217
|
const sourceOnlySignals = [];
|
|
@@ -255,7 +267,31 @@ export function buildIntentClaimCandidates(declared, existingIds, minConfidence,
|
|
|
255
267
|
candidates.push(review);
|
|
256
268
|
continue;
|
|
257
269
|
}
|
|
258
|
-
|
|
270
|
+
// A claim that restates a current requirement word for word (case,
|
|
271
|
+
// whitespace and punctuation aside) is that requirement: count it as
|
|
272
|
+
// already in the KB under the requirement's id, and do not model it.
|
|
273
|
+
const restatement = findRestatement([claim.statement, claim.excerpt], existingRequirements);
|
|
274
|
+
if (restatement?.kind === "exact") {
|
|
275
|
+
suppressed.push({
|
|
276
|
+
candidateId: "",
|
|
277
|
+
reason: "entity_exists",
|
|
278
|
+
sourcePath: claim.reference,
|
|
279
|
+
entityType: "req",
|
|
280
|
+
statement: claim.statement,
|
|
281
|
+
sourceId: source.id,
|
|
282
|
+
matchedId: restatement.requirementId,
|
|
283
|
+
matchedBy: "restatement",
|
|
284
|
+
matchedField: restatement.field,
|
|
285
|
+
});
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const nearRestatement = restatement?.kind === "near" ? restatement : null;
|
|
289
|
+
const evidence = [
|
|
290
|
+
...citation(source, claim),
|
|
291
|
+
...(nearRestatement
|
|
292
|
+
? [`possible_restatement:${nearRestatement.requirementId}`]
|
|
293
|
+
: []),
|
|
294
|
+
];
|
|
259
295
|
const provenance = `${source.id}:${claim.reference}`;
|
|
260
296
|
let writeSet = null;
|
|
261
297
|
try {
|
|
@@ -301,6 +337,8 @@ export function buildIntentClaimCandidates(declared, existingIds, minConfidence,
|
|
|
301
337
|
? withClaimBody(asImportedRule(withRationale(step, claim.rationale), provenance), claimBody(source, claim))
|
|
302
338
|
: step),
|
|
303
339
|
});
|
|
340
|
+
if (nearRestatement)
|
|
341
|
+
diagnostics.push(nearRestatementDiagnostic(source, claim, nearRestatement));
|
|
304
342
|
continue;
|
|
305
343
|
}
|
|
306
344
|
if (writeSet?.isStrict && confidence < minConfidence)
|
|
@@ -326,6 +364,8 @@ export function buildIntentClaimCandidates(declared, existingIds, minConfidence,
|
|
|
326
364
|
confidence,
|
|
327
365
|
evidence,
|
|
328
366
|
});
|
|
367
|
+
if (nearRestatement)
|
|
368
|
+
diagnostics.push(nearRestatementDiagnostic(source, claim, nearRestatement));
|
|
329
369
|
}
|
|
330
370
|
const declaredConflicts = conflictCandidates(declared, sources, existingIds, minConfidence);
|
|
331
371
|
return {
|
|
@@ -5,6 +5,17 @@ import { type InventoryRederivation } from "./inventory-rederive.js";
|
|
|
5
5
|
* intent is `closed`.
|
|
6
6
|
*/
|
|
7
7
|
export declare const SUGGESTED_REQUIREMENT_STATUS: Readonly<Record<string, string>>;
|
|
8
|
+
/** The tag that keeps a delivered legacy requirement's meaning once closed. */
|
|
9
|
+
export declare const DELIVERED_REQUIREMENT_TAG = "implemented";
|
|
10
|
+
/**
|
|
11
|
+
* Legacy delivery statuses and their one lossless current reading: `closed`
|
|
12
|
+
* with the tag `implemented`, which kb.pl reads as a delivered requirement
|
|
13
|
+
* that still owes coverage. `kibi migrate` applies these without review.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DELIVERED_REQUIREMENT_STATUS: Readonly<Record<string, Readonly<{
|
|
16
|
+
status: string;
|
|
17
|
+
tag: string;
|
|
18
|
+
}>>>;
|
|
8
19
|
/** One requirement whose status is outside the vocabulary. */
|
|
9
20
|
export type RequirementStatusFinding = Readonly<{
|
|
10
21
|
requirementId: string;
|
|
@@ -12,6 +23,19 @@ export type RequirementStatusFinding = Readonly<{
|
|
|
12
23
|
status: string;
|
|
13
24
|
/** The suggested current status; null when Kibi has no suggestion. */
|
|
14
25
|
suggestedStatus: string | null;
|
|
26
|
+
/**
|
|
27
|
+
* The lossless mapping `kibi migrate` applies without review (delivery
|
|
28
|
+
* vocabulary); null when the target status is a person's choice.
|
|
29
|
+
*/
|
|
30
|
+
automatic: Readonly<{
|
|
31
|
+
status: string;
|
|
32
|
+
tag: string;
|
|
33
|
+
}> | null;
|
|
34
|
+
/**
|
|
35
|
+
* Why `kibi sync` cannot compile the requirement as authored (for example
|
|
36
|
+
* a status outside the entity schema); null when it compiles.
|
|
37
|
+
*/
|
|
38
|
+
extractionError: string | null;
|
|
15
39
|
/** Inventory drift the requirement shows once it has the suggested status. */
|
|
16
40
|
latentDrift: InventoryRederivation | null;
|
|
17
41
|
}>;
|
|
@@ -19,7 +43,22 @@ export type RequirementStatusFinding = Readonly<{
|
|
|
19
43
|
export declare function planRequirementStatusMappings(workspaceRoot: string): RequirementStatusFinding[];
|
|
20
44
|
/**
|
|
21
45
|
* Set the status of one requirement from `from` to `to`, replacing only its
|
|
22
|
-
* `status` line
|
|
46
|
+
* `status` line, and add `tag` when given and missing. Refuses when the
|
|
47
|
+
* authored status is no longer `from`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function applyRequirementStatusMapping(workspaceRoot: string, relativePath: string, from: string, to: string, tag?: string): void;
|
|
50
|
+
/** What mapping the delivery statuses changed, and what it could not edit. */
|
|
51
|
+
export type DeliveredStatusMappingResult = Readonly<{
|
|
52
|
+
mapped: readonly RequirementStatusFinding[];
|
|
53
|
+
skipped: readonly Readonly<{
|
|
54
|
+
path: string;
|
|
55
|
+
reason: string;
|
|
56
|
+
}>[];
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Map every requirement whose status is delivery vocabulary to `closed` with
|
|
60
|
+
* the tag `implemented`, front matter only. With `only`, maps just those
|
|
61
|
+
* requirement ids (a plan action applies what it planned). Idempotent.
|
|
23
62
|
*/
|
|
24
|
-
export declare function
|
|
63
|
+
export declare function applyDeliveredStatusMappings(workspaceRoot: string, only?: ReadonlySet<string>): DeliveredStatusMappingResult;
|
|
25
64
|
//# sourceMappingURL=requirement-status.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirement-status.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/requirement-status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"requirement-status.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/requirement-status.ts"],"names":[],"mappings":"AAqBA,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,yBAAyB,CAAC;AAkCjC;;;;GAIG;AAEH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOzE,CAAC;AAEF,+EAA+E;AAE/E,eAAO,MAAM,yBAAyB,gBAAgB,CAAC;AAEvD;;;;GAIG;AAEH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CACjD,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAK1D,CAAC;AAEF,8DAA8D;AAE9D,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;OAGG;IACH,SAAS,EAAE,QAAQ,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;IAC5D;;;OAGG;IACH,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,8EAA8E;IAC9E,WAAW,EAAE,qBAAqB,GAAG,IAAI,CAAC;CAC3C,CAAC,CAAC;AAqBH,yEAAyE;AAEzE,wBAAgB,6BAA6B,CAC3C,aAAa,EAAE,MAAM,GACpB,wBAAwB,EAAE,CAkC5B;AASD;;;;GAIG;AAEH,wBAAgB,6BAA6B,CAC3C,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,GAAG,CAAC,EAAE,MAAM,GACX,IAAI,CAiBN;AAED,8EAA8E;AAE9E,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,MAAM,EAAE,SAAS,wBAAwB,EAAE,CAAC;IAC5C,OAAO,EAAE,SAAS,QAAQ,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;CAChE,CAAC,CAAC;AAEH;;;;GAIG;AAEH,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GACzB,4BAA4B,CAuB9B"}
|