kibi-cli 2.18.0 → 2.20.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 +2 -2
- package/dist/cli-operation-metadata.js +2 -2
- package/dist/cli-register-maintenance.js +1 -1
- package/dist/commands/doctor.js +11 -5
- package/dist/commands/engine.d.ts +2 -1
- package/dist/commands/engine.d.ts.map +1 -1
- package/dist/commands/engine.js +6 -1
- package/dist/commands/sync/manifest.d.ts +10 -0
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +27 -0
- package/dist/commands/sync/untracked-targets.d.ts +17 -0
- package/dist/commands/sync/untracked-targets.d.ts.map +1 -1
- package/dist/commands/sync/untracked-targets.js +43 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +51 -2
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +33 -22
- package/dist/intent-search.d.ts +7 -0
- package/dist/intent-search.d.ts.map +1 -1
- package/dist/intent-search.js +66 -4
- package/dist/operations/modeling/predicate-applicability.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applicability.js +10 -4
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +16 -5
- package/dist/operations/modeling/predicate-catalog-4.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-catalog-4.js +3 -0
- package/dist/operations/modeling/predicate-inference-1.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-inference-1.js +34 -7
- package/dist/operations/modeling/predicate-score-3.js +1 -1
- package/dist/operations/modeling/predicate-types.d.ts +6 -0
- 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 +111 -0
- package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
- package/dist/operations/mutation/source-authoring.js +5 -12
- package/dist/operations/mutation/types.d.ts +26 -0
- package/dist/operations/mutation/types.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +8 -2
- package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
- package/dist/operations/mutation/validate-upsert.js +116 -4
- package/dist/operations/mutation/warnings.d.ts +10 -0
- package/dist/operations/mutation/warnings.d.ts.map +1 -1
- package/dist/operations/mutation/warnings.js +26 -0
- package/dist/operations/mutation/what-if.d.ts +25 -0
- package/dist/operations/mutation/what-if.d.ts.map +1 -0
- package/dist/operations/mutation/what-if.js +59 -0
- package/dist/operations/planning/compile-intent.d.ts +15 -20
- package/dist/operations/planning/compile-intent.d.ts.map +1 -1
- package/dist/operations/planning/compile-intent.js +64 -53
- package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/clauses.js +8 -7
- package/dist/prolog/janitor.d.ts +26 -2
- package/dist/prolog/janitor.d.ts.map +1 -1
- package/dist/prolog/janitor.js +55 -3
- package/dist/prolog/store-lock.d.ts +47 -3
- package/dist/prolog/store-lock.d.ts.map +1 -1
- package/dist/prolog/store-lock.js +148 -11
- package/dist/proof/inspect.d.ts +1 -1
- package/dist/proof/inspect.d.ts.map +1 -1
- package/dist/proof/inspect.js +9 -2
- package/dist/public/operations/catalog.d.ts +97 -4
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts +2 -2
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +35 -0
- package/dist/public/operations/check-format-shared.d.ts +16 -0
- package/dist/public/operations/check-format-shared.d.ts.map +1 -1
- package/dist/public/operations/check-format-shared.js +19 -0
- package/dist/public/operations/contracts.d.ts.map +1 -1
- package/dist/public/operations/contracts.js +11 -4
- package/dist/public/operations/discovery-executors.d.ts +39 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +368 -3
- package/dist/public/operations/specs/composite.d.ts +1 -1
- package/dist/public/operations/specs/composite.js +1 -1
- package/dist/public/operations/specs/discovery.d.ts +52 -3
- package/dist/public/operations/specs/discovery.d.ts.map +1 -1
- package/dist/public/operations/specs/discovery.js +58 -3
- package/dist/public/operations/specs/upsert.d.ts +44 -0
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/specs/upsert.js +14 -0
- package/dist/public/skills/kibi-usage/SKILL.md +44 -1
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +4 -2
- package/dist/runtime/cli-runtime.d.ts.map +1 -1
- package/dist/runtime/cli-runtime.js +7 -2
- package/dist/search-answer.d.ts +25 -3
- package/dist/search-answer.d.ts.map +1 -1
- package/dist/search-answer.js +96 -8
- package/dist/utils/branch-store.d.ts.map +1 -1
- package/dist/utils/branch-store.js +4 -2
- package/dist/utils/content-freshness.d.ts.map +1 -1
- package/dist/utils/content-freshness.js +12 -2
- package/dist/utils/symbol-manifest-layout.d.ts +9 -0
- package/dist/utils/symbol-manifest-layout.d.ts.map +1 -0
- package/dist/utils/symbol-manifest-layout.js +18 -0
- package/package.json +3 -3
- package/src/public/operations/check-executor.ts +44 -1
- package/src/public/operations/check-format-shared.ts +35 -1
- package/src/public/operations/contracts.ts +15 -4
- package/src/public/operations/discovery-executors.ts +484 -2
- package/src/public/operations/specs/composite.ts +1 -1
- package/src/public/operations/specs/discovery.ts +70 -3
- package/src/public/operations/specs/upsert.ts +15 -0
- package/src/public/skills/kibi-usage/SKILL.md +44 -1
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +4 -2
|
@@ -26,7 +26,7 @@ import { acquireSymbolCompilerLock, releaseSymbolCompilerLock, } from "./symbol-
|
|
|
26
26
|
import { validateSymbolGranularity } from "./symbol-granularity.js";
|
|
27
27
|
import { refreshSymbolCoordinatesForManifest } from "./symbol-refresh.js";
|
|
28
28
|
import { validateUpsertInput } from "./validation.js";
|
|
29
|
-
import { scenarioCoverageWarnings } from "./warnings.js";
|
|
29
|
+
import { scenarioCoverageWarnings, symbolCoverageWarnings, } from "./warnings.js";
|
|
30
30
|
import { acquireWorkspaceMutationLock, releaseWorkspaceMutationLock, } from "./workspace-mutation-lock.js";
|
|
31
31
|
function requireProlog(context) {
|
|
32
32
|
if (context.prolog === undefined) {
|
|
@@ -250,6 +250,9 @@ async function dryRunUpsert(input, context) {
|
|
|
250
250
|
export async function executeUpsert(input, context, options = {}) {
|
|
251
251
|
if (input.dryRun === true)
|
|
252
252
|
return dryRunUpsert(input, context);
|
|
253
|
+
// implements REQ-model-what-if-planned-facts
|
|
254
|
+
if (input.plannedFacts !== undefined)
|
|
255
|
+
throw new Error(`Upsert of ${input.id} rejected: plannedFacts is a dryRun-only input. Write the planned facts first (kb_upsert each, or kb_apply_plan with the kb_model plan), then upsert ${input.id} without plannedFacts.`);
|
|
253
256
|
const branchAttachment = context.branchAttachment ?? resolveBranchAttachment(context.workspaceRoot);
|
|
254
257
|
if ("error" in branchAttachment) {
|
|
255
258
|
throw new Error(`Unable to resolve KB branch: ${branchAttachment.error}`);
|
|
@@ -481,7 +484,10 @@ export async function executeUpsert(input, context, options = {}) {
|
|
|
481
484
|
if (changeKind === null) {
|
|
482
485
|
throw new Error(`Upsert commit completed without a created/updated result for ${input.id}`);
|
|
483
486
|
}
|
|
484
|
-
const coverage =
|
|
487
|
+
const coverage = [
|
|
488
|
+
...(await scenarioCoverageWarnings(prolog, validated.relationships, input.type, input.id)),
|
|
489
|
+
...(await symbolCoverageWarnings(prolog, validated.relationships, input.type, input.id)),
|
|
490
|
+
];
|
|
485
491
|
const created = changeKind === "created" ? 1 : 0;
|
|
486
492
|
const idStyleWarnings = created === 1
|
|
487
493
|
? entityIdStyleWarnings({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/validate-upsert.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAEjB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"validate-upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/validate-upsert.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAEjB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAYxE,OAAO,KAAK,EAIV,WAAW,EACX,qBAAqB,EACtB,MAAM,YAAY,CAAC;AA2MpB;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAAC,CAgHjD"}
|
|
@@ -4,11 +4,13 @@ import { entityIdStyleWarnings } from "../../utils/entity-id-style.js";
|
|
|
4
4
|
import { analyzeSemanticAdvisorInput } from "../semantic-advisor/analyze-prose.js";
|
|
5
5
|
import { assertSemanticInventoryBoundary } from "../semantic-advisor/ingestion-boundary.js";
|
|
6
6
|
import { entityContextWarnings } from "./context-warning.js";
|
|
7
|
-
import { buildUpsertContradictionPreviewGoal, formatUpsertError, } from "./contradictions.js";
|
|
7
|
+
import { buildUpsertContradictionPreviewGoal, buildWhatIfAnalysisGoal, formatUpsertError, } from "./contradictions.js";
|
|
8
8
|
import { validateRelationshipSources } from "./relationships.js";
|
|
9
9
|
import { validateSymbolGranularity } from "./symbol-granularity.js";
|
|
10
10
|
import { validateAppendOnlyProofReceipts, validateUpsertForCommit, } from "./upsert.js";
|
|
11
11
|
import { validateUpsertInput } from "./validation.js";
|
|
12
|
+
import { symbolCoverageWarnings } from "./warnings.js";
|
|
13
|
+
import { isBlockingWitness, parseWhatIfAnalysis } from "./what-if.js";
|
|
12
14
|
// implements REQ-kibi-entity-id-style
|
|
13
15
|
async function entityExists(prolog, id) {
|
|
14
16
|
const result = await prolog.query(`once(kb_entity('${escapeAtom(id)}', _Type, _Props))`);
|
|
@@ -33,6 +35,92 @@ async function previewContradictions(prolog, input, entity, relationships) {
|
|
|
33
35
|
throw new Error(formatUpsertError(input.id, preview.error, preview.errorRecord));
|
|
34
36
|
}
|
|
35
37
|
}
|
|
38
|
+
// implements REQ-model-what-if-planned-facts
|
|
39
|
+
/**
|
|
40
|
+
* Validate the planned facts in order, each against the live store plus the
|
|
41
|
+
* facts before it, exactly as kb_apply_plan validates a plan's steps. The
|
|
42
|
+
* result is the staged state the payload's own validation reads: a planned
|
|
43
|
+
* fact counts as a live relationship target and its claim_key is read from
|
|
44
|
+
* the plan, so a requirement can be previewed before its facts are written.
|
|
45
|
+
*/
|
|
46
|
+
async function stagePlannedFacts(input, context) {
|
|
47
|
+
const planned = input.plannedFacts;
|
|
48
|
+
if (planned === undefined)
|
|
49
|
+
return null;
|
|
50
|
+
if (!Array.isArray(planned))
|
|
51
|
+
throw new Error("plannedFacts must be an array of fact upsert payloads");
|
|
52
|
+
const entities = new Map();
|
|
53
|
+
const relationships = [];
|
|
54
|
+
const steps = [];
|
|
55
|
+
for (const [index, fact] of planned.entries()) {
|
|
56
|
+
const id = typeof fact?.id === "string" ? fact.id : `#${index + 1}`;
|
|
57
|
+
if (fact?.type !== "fact")
|
|
58
|
+
throw new Error(`planned fact ${id} is invalid: plannedFacts stages fact entities only (got type '${String(fact?.type)}')`);
|
|
59
|
+
if (fact.id === input.id)
|
|
60
|
+
throw new Error(`planned fact ${id} is invalid: it has the same id as the payload`);
|
|
61
|
+
try {
|
|
62
|
+
const { validated } = await validateUpsertForCommit(plannedFactUpsert(fact), context, { staged: { entities, relationships: [...relationships] } });
|
|
63
|
+
entities.set(fact.id, validated.entity);
|
|
64
|
+
relationships.push(...validated.relationships);
|
|
65
|
+
steps.push({
|
|
66
|
+
entity: validated.entity,
|
|
67
|
+
relationships: validated.relationships,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
throw new Error(`planned fact ${id} is invalid: ${error instanceof Error ? error.message : String(error)}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return { staged: { entities, relationships }, steps };
|
|
75
|
+
}
|
|
76
|
+
function plannedFactUpsert(fact) {
|
|
77
|
+
return {
|
|
78
|
+
type: fact.type,
|
|
79
|
+
id: fact.id,
|
|
80
|
+
properties: fact.properties,
|
|
81
|
+
...(fact.relationships !== undefined
|
|
82
|
+
? { relationships: fact.relationships }
|
|
83
|
+
: {}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// implements REQ-model-what-if-planned-facts, REQ-kibi-truthful-consistency
|
|
87
|
+
/**
|
|
88
|
+
* The contradiction preview for a payload with planned facts: the facts and
|
|
89
|
+
* the payload are staged together in a rolled-back transaction and the
|
|
90
|
+
* witnesses the KB would then hold are compared with the current KB's. A
|
|
91
|
+
* blocking witness the batch introduces refuses the dry run the way the
|
|
92
|
+
* commit would refuse the last write of the batch; the full split is
|
|
93
|
+
* returned so an agent sees the conflict before any fact exists.
|
|
94
|
+
*/
|
|
95
|
+
async function previewStagedContradictions(prolog, input, entity, relationships, facts) {
|
|
96
|
+
const result = await prolog.query(buildWhatIfAnalysisGoal([
|
|
97
|
+
...facts.steps.map((step) => ({
|
|
98
|
+
entity: step.entity,
|
|
99
|
+
relationships: step.relationships,
|
|
100
|
+
skipContradictionCheck: true,
|
|
101
|
+
})),
|
|
102
|
+
{ entity, relationships, skipContradictionCheck: true },
|
|
103
|
+
]));
|
|
104
|
+
if (!result.success)
|
|
105
|
+
throw new Error(formatUpsertError(input.id, result.error, result.errorRecord));
|
|
106
|
+
const analysis = parseWhatIfAnalysis(result.bindings.JsonString);
|
|
107
|
+
if (analysis === null)
|
|
108
|
+
throw new Error(`Failed to preview ${input.id} with planned facts: the staged contradiction analysis could not be read`);
|
|
109
|
+
const skip = input.type !== "req" || input._skipContradictionCheck === true;
|
|
110
|
+
const blocking = skip ? [] : analysis.introduced.filter(isBlockingWitness);
|
|
111
|
+
if (blocking.length > 0) {
|
|
112
|
+
const conflicts = blocking.map((witness) => {
|
|
113
|
+
const others = witness.requirements.filter((id) => id !== input.id);
|
|
114
|
+
return ` - Conflicts with ${others.join(", ") || witness.requirements.join(", ")}: ${witness.reason}`;
|
|
115
|
+
});
|
|
116
|
+
throw new Error(`Contradiction detected for requirement ${input.id} once its planned facts are written:\n${conflicts.join("\n")}\n\nTo resolve:\n 1. Add a supersedes relationship from the new requirement to the conflicting one, OR\n 2. Deprecate the conflicting requirement before creating the new one. (stage=contradiction_check, plannedFacts staged)`);
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
introduced: analysis.introduced,
|
|
120
|
+
removed: analysis.removed,
|
|
121
|
+
unchanged: analysis.unchanged,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
36
124
|
/**
|
|
37
125
|
* The validation chain for a runtime without a store: everything that does
|
|
38
126
|
* not need to read the KB.
|
|
@@ -58,12 +146,25 @@ async function validateWithoutStore(input, context) {
|
|
|
58
146
|
*/
|
|
59
147
|
export async function executeValidateUpsert(input, context) {
|
|
60
148
|
try {
|
|
149
|
+
if (input.plannedFacts !== undefined && context.prolog === undefined)
|
|
150
|
+
throw new Error("plannedFacts needs a KB store: the planned facts are staged against the current KB");
|
|
151
|
+
let whatIf;
|
|
152
|
+
let stagedFacts;
|
|
153
|
+
let relationships = input.relationships ?? [];
|
|
61
154
|
const { entity, semantic } = context.prolog !== undefined
|
|
62
|
-
? await
|
|
155
|
+
? await stagePlannedFacts(input, context).then(async (facts) => {
|
|
156
|
+
const result = await validateUpsertForCommit(input, context, facts === null ? {} : { staged: facts.staged });
|
|
63
157
|
// The commit goal checks requirement contradictions after the
|
|
64
158
|
// validations above; a dry run previews that stage as well, so
|
|
65
159
|
// "valid" means the commit would not refuse the write.
|
|
66
|
-
|
|
160
|
+
if (facts === null) {
|
|
161
|
+
await previewContradictions(context.prolog, input, result.validated.entity, result.validated.relationships);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
stagedFacts = [...facts.staged.entities.keys()];
|
|
165
|
+
whatIf = await previewStagedContradictions(context.prolog, input, result.validated.entity, result.validated.relationships, facts);
|
|
166
|
+
}
|
|
167
|
+
relationships = result.validated.relationships;
|
|
67
168
|
return {
|
|
68
169
|
entity: result.validated.entity,
|
|
69
170
|
semantic: result.semantic,
|
|
@@ -81,22 +182,33 @@ export async function executeValidateUpsert(input, context) {
|
|
|
81
182
|
!(await entityExists(context.prolog, input.id))
|
|
82
183
|
? candidateIdStyleWarnings
|
|
83
184
|
: [];
|
|
185
|
+
// The same symbol-coverage warning the write returns, so the dry run
|
|
186
|
+
// tells the agent before the write that kb_check will flag it.
|
|
187
|
+
const coverageWarnings = context.prolog
|
|
188
|
+
? await symbolCoverageWarnings(context.prolog, relationships, input.type, input.id)
|
|
189
|
+
: [];
|
|
84
190
|
const payload = {
|
|
85
191
|
valid: true,
|
|
86
192
|
errors: [],
|
|
87
193
|
warnings: [
|
|
88
194
|
...semantic.warnings,
|
|
195
|
+
...coverageWarnings,
|
|
89
196
|
...idStyleWarnings,
|
|
90
197
|
...entityContextWarnings(input, entity, context.workspaceRoot),
|
|
91
198
|
],
|
|
92
199
|
semanticAdvisor: semantic.receipt,
|
|
93
200
|
normalizedPreview: entity,
|
|
201
|
+
...(stagedFacts !== undefined ? { stagedFacts } : {}),
|
|
202
|
+
...(whatIf !== undefined ? { whatIf } : {}),
|
|
94
203
|
};
|
|
204
|
+
const stagedNote = stagedFacts === undefined
|
|
205
|
+
? ""
|
|
206
|
+
: ` ${stagedFacts.length} planned fact(s) were staged ahead of it (${stagedFacts.join(", ")}); the batch introduces ${whatIf?.introduced.length ?? 0} witness(es).`;
|
|
95
207
|
return {
|
|
96
208
|
content: [
|
|
97
209
|
{
|
|
98
210
|
type: "text",
|
|
99
|
-
text:
|
|
211
|
+
text: `kb_validate_upsert: payload is valid for kb_upsert preflight checks. No mutation was performed.${stagedNote}`,
|
|
100
212
|
},
|
|
101
213
|
],
|
|
102
214
|
structuredContent: payload,
|
|
@@ -2,4 +2,14 @@ import type { PrologPort } from "../../public/operations/runtime-types.js";
|
|
|
2
2
|
import type { RelationshipInput } from "./types.js";
|
|
3
3
|
export declare function scenarioCoverageWarning(entityId: string): readonly string[];
|
|
4
4
|
export declare function scenarioCoverageWarnings(prolog: PrologPort, relationships: readonly RelationshipInput[], entityType: string, entityId: string): Promise<readonly string[]>;
|
|
5
|
+
export declare function symbolCoverageWarning(entityId: string): readonly string[];
|
|
6
|
+
/**
|
|
7
|
+
* A production symbol (one that implements a requirement) needs a covered_by
|
|
8
|
+
* edge to a test that covers that requirement, or kb_check reports
|
|
9
|
+
* symbol-coverage once it is written. Warn before and after the write so the
|
|
10
|
+
* agent learns it from the upsert, not from the next check. An executable
|
|
11
|
+
* test symbol (executable_for) is not production code, and a symbol that
|
|
12
|
+
* already has a stored covered_by edge is left for kb_check to judge.
|
|
13
|
+
*/
|
|
14
|
+
export declare function symbolCoverageWarnings(prolog: PrologPort, relationships: readonly RelationshipInput[], entityType: string, entityId: string): Promise<readonly string[]>;
|
|
5
15
|
//# sourceMappingURL=warnings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warnings.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/warnings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAI3E;AAGD,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,UAAU,EAClB,aAAa,EAAE,SAAS,iBAAiB,EAAE,EAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAU5B"}
|
|
1
|
+
{"version":3,"file":"warnings.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/warnings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAI3E;AAGD,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,UAAU,EAClB,aAAa,EAAE,SAAS,iBAAiB,EAAE,EAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAU5B;AAGD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAIzE;AAGD;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,UAAU,EAClB,aAAa,EAAE,SAAS,iBAAiB,EAAE,EAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAe5B"}
|
|
@@ -17,3 +17,29 @@ export async function scenarioCoverageWarnings(prolog, relationships, entityType
|
|
|
17
17
|
}
|
|
18
18
|
return [];
|
|
19
19
|
}
|
|
20
|
+
// implements REQ-kibi-operation-interface-parity
|
|
21
|
+
export function symbolCoverageWarning(entityId) {
|
|
22
|
+
return [
|
|
23
|
+
`Production symbol ${entityId} has implements but no covered_by: kb_check will report symbol-coverage. Add covered_by: TEST-<area>-<behavior> to a test that validates the requirement's scenario (or verified_by(req,test) when the requirement has no scenario).`,
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
// implements REQ-kibi-operation-interface-parity
|
|
27
|
+
/**
|
|
28
|
+
* A production symbol (one that implements a requirement) needs a covered_by
|
|
29
|
+
* edge to a test that covers that requirement, or kb_check reports
|
|
30
|
+
* symbol-coverage once it is written. Warn before and after the write so the
|
|
31
|
+
* agent learns it from the upsert, not from the next check. An executable
|
|
32
|
+
* test symbol (executable_for) is not production code, and a symbol that
|
|
33
|
+
* already has a stored covered_by edge is left for kb_check to judge.
|
|
34
|
+
*/
|
|
35
|
+
export async function symbolCoverageWarnings(prolog, relationships, entityType, entityId) {
|
|
36
|
+
if (entityType !== "symbol")
|
|
37
|
+
return [];
|
|
38
|
+
const own = relationships.filter((relationship) => relationship.from === undefined || relationship.from === entityId);
|
|
39
|
+
const has = (type) => own.some((relationship) => relationship.type === type);
|
|
40
|
+
if (!has("implements") || has("covered_by") || has("executable_for"))
|
|
41
|
+
return [];
|
|
42
|
+
const id = escapeAtom(entityId);
|
|
43
|
+
const stored = await prolog.query(`once((kb_relationship(covered_by, '${id}', _) ; kb_relationship(executable_for, '${id}', _)))`);
|
|
44
|
+
return stored.success ? [] : symbolCoverageWarning(entityId);
|
|
45
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** A contradiction or scenario-infeasibility witness the checker reports. */
|
|
2
|
+
export type ContradictionWitness = Readonly<{
|
|
3
|
+
requirements: readonly string[];
|
|
4
|
+
reason: string;
|
|
5
|
+
status?: string;
|
|
6
|
+
/** property | predicate | rule | scenario_feasibility */
|
|
7
|
+
kind?: string;
|
|
8
|
+
} & Record<string, unknown>>;
|
|
9
|
+
export type WhatIfAnalysis = Readonly<{
|
|
10
|
+
after: readonly ContradictionWitness[];
|
|
11
|
+
introduced: readonly ContradictionWitness[];
|
|
12
|
+
removed: readonly ContradictionWitness[];
|
|
13
|
+
unchanged: readonly ContradictionWitness[];
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Parse checks:what_if_analysis_json/2 output. The binding is a quoted Prolog
|
|
17
|
+
* string, so the JSON may arrive encoded once more as a JSON string. A bare
|
|
18
|
+
* witness array (the what_if_contradiction_witnesses_json/2 shape) carries no
|
|
19
|
+
* current-KB baseline, so every witness in it is treated as introduced.
|
|
20
|
+
* Returns null when the output cannot be read.
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseWhatIfAnalysis(raw: unknown): WhatIfAnalysis | null;
|
|
23
|
+
/** Blocking: a proven contradiction or an infeasible success scenario. */
|
|
24
|
+
export declare function isBlockingWitness(witness: ContradictionWitness): boolean;
|
|
25
|
+
//# sourceMappingURL=what-if.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"what-if.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/what-if.ts"],"names":[],"mappings":"AAGA,6EAA6E;AAC7E,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CACzC;IACE,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAC5B,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,KAAK,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACvC,UAAU,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC5C,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACzC,SAAS,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAC5C,CAAC,CAAC;AA6BH;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAoBvE;AAGD,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAExE"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { normalizeEntityId } from "../../prolog/codec.js";
|
|
2
|
+
function text(value) {
|
|
3
|
+
return typeof value === "string" ? value.trim() : "";
|
|
4
|
+
}
|
|
5
|
+
function isRecord(value) {
|
|
6
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function whatIfWitness(witness) {
|
|
9
|
+
return {
|
|
10
|
+
...witness,
|
|
11
|
+
requirements: Array.isArray(witness.requirements)
|
|
12
|
+
? witness.requirements.map((id) => normalizeEntityId(String(id)))
|
|
13
|
+
: [],
|
|
14
|
+
reason: text(witness.reason),
|
|
15
|
+
status: text(witness.status) || "contradiction",
|
|
16
|
+
...(typeof witness.kind === "string" ? { kind: witness.kind } : {}),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function whatIfWitnesses(value) {
|
|
20
|
+
return (Array.isArray(value) ? value.filter(isRecord) : []).map(whatIfWitness);
|
|
21
|
+
}
|
|
22
|
+
// implements REQ-kibi-truthful-consistency
|
|
23
|
+
/**
|
|
24
|
+
* Parse checks:what_if_analysis_json/2 output. The binding is a quoted Prolog
|
|
25
|
+
* string, so the JSON may arrive encoded once more as a JSON string. A bare
|
|
26
|
+
* witness array (the what_if_contradiction_witnesses_json/2 shape) carries no
|
|
27
|
+
* current-KB baseline, so every witness in it is treated as introduced.
|
|
28
|
+
* Returns null when the output cannot be read.
|
|
29
|
+
*/
|
|
30
|
+
export function parseWhatIfAnalysis(raw) {
|
|
31
|
+
if (typeof raw !== "string")
|
|
32
|
+
return null;
|
|
33
|
+
let parsed;
|
|
34
|
+
try {
|
|
35
|
+
parsed = JSON.parse(raw);
|
|
36
|
+
if (typeof parsed === "string")
|
|
37
|
+
parsed = JSON.parse(parsed);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
if (Array.isArray(parsed)) {
|
|
43
|
+
const after = whatIfWitnesses(parsed);
|
|
44
|
+
return { after, introduced: after, removed: [], unchanged: [] };
|
|
45
|
+
}
|
|
46
|
+
if (!isRecord(parsed))
|
|
47
|
+
return null;
|
|
48
|
+
return {
|
|
49
|
+
after: whatIfWitnesses(parsed.after),
|
|
50
|
+
introduced: whatIfWitnesses(parsed.introduced),
|
|
51
|
+
removed: whatIfWitnesses(parsed.removed),
|
|
52
|
+
unchanged: whatIfWitnesses(parsed.unchanged),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// implements REQ-kibi-truthful-consistency
|
|
56
|
+
/** Blocking: a proven contradiction or an infeasible success scenario. */
|
|
57
|
+
export function isBlockingWitness(witness) {
|
|
58
|
+
return witness.status === "contradiction" || witness.status === "infeasible";
|
|
59
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type IntentSearchFacets, type IntentSearchMatch, type SourceLocation } from "../../intent-search.js";
|
|
2
2
|
import type { OperationContext } from "../../public/operations/runtime-types.js";
|
|
3
|
+
import { type ContradictionWitness } from "../mutation/what-if.js";
|
|
3
4
|
import type { SemanticInterpretationInput } from "../semantic-advisor/types.js";
|
|
4
5
|
export declare const COMPILE_PLAN_VERSION: "kibi.compile-plan.v1";
|
|
5
6
|
export type CompileIntentArgs = Readonly<{
|
|
@@ -47,13 +48,8 @@ export type ProposalDecision = Readonly<{
|
|
|
47
48
|
* (sides, facts, scenario, comparison) is kept alongside these normalized
|
|
48
49
|
* fields so callers can act on more than requirement ids.
|
|
49
50
|
*/
|
|
50
|
-
export type ContradictionWitness
|
|
51
|
-
|
|
52
|
-
reason: string;
|
|
53
|
-
status?: string;
|
|
54
|
-
/** property | predicate | rule | scenario_feasibility */
|
|
55
|
-
kind?: string;
|
|
56
|
-
} & Record<string, unknown>>;
|
|
51
|
+
export type { ContradictionWitness, WhatIfAnalysis, } from "../mutation/what-if.js";
|
|
52
|
+
export { isBlockingWitness, parseWhatIfAnalysis } from "../mutation/what-if.js";
|
|
57
53
|
export type TraceabilityProposal = Readonly<{
|
|
58
54
|
proposalId: string;
|
|
59
55
|
candidateId: string;
|
|
@@ -173,22 +169,21 @@ export type SourceWritePlan = Readonly<{
|
|
|
173
169
|
}>;
|
|
174
170
|
/** Rolled-back staging goal for a plan's steps (see what_if_analysis/2). */
|
|
175
171
|
export declare function planWhatIfGoal(steps: readonly PlanStep[], now: Date): string;
|
|
176
|
-
export type
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
172
|
+
export type GroundingPlanInput = Readonly<{
|
|
173
|
+
requirementId: string;
|
|
174
|
+
claimKey: string;
|
|
175
|
+
text: string;
|
|
176
|
+
/** The fact write(s), then the requirement upsert that links them. */
|
|
177
|
+
steps: readonly PlanStep[];
|
|
181
178
|
}>;
|
|
182
179
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* current
|
|
187
|
-
*
|
|
180
|
+
* A hash-bound compile plan for a grounding kb_model planned: the predicate
|
|
181
|
+
* fact and the requirement upsert that links it, validated and applied
|
|
182
|
+
* together by kb_apply_plan. Its contradiction analysis is the what-if over
|
|
183
|
+
* the current KB plus these steps, so a decision conflict with a fact that is
|
|
184
|
+
* already stored is reported here, before any write, and blocks the plan.
|
|
188
185
|
*/
|
|
189
|
-
export declare function
|
|
190
|
-
/** Blocking: a proven contradiction or an infeasible success scenario. */
|
|
191
|
-
export declare function isBlockingWitness(witness: ContradictionWitness): boolean;
|
|
186
|
+
export declare function compileGroundingPlan(context: OperationContext, prolog: NonNullable<OperationContext["prolog"]>, input: GroundingPlanInput): Promise<CompilePlanV1>;
|
|
192
187
|
export declare function executeCompileIntent(args: CompileIntentArgs, context: OperationContext): Promise<{
|
|
193
188
|
content: Array<{
|
|
194
189
|
type: "text";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile-intent.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/compile-intent.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEpB,MAAM,wBAAwB,CAAC;AAMhC,OAAO,KAAK,EACV,gBAAgB,EAEjB,MAAM,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"compile-intent.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/compile-intent.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,17 +3,18 @@ import path from "node:path";
|
|
|
3
3
|
import { renderRequirementBody, reviseRequirementBody, } from "../../entity-body-context.js";
|
|
4
4
|
import { executeIntentSearch, } from "../../intent-search.js";
|
|
5
5
|
import { publicCapabilityStamp } from "../../plugins/compose-semantic-classifier.js";
|
|
6
|
-
import { normalizeEntityId } from "../../prolog/codec.js";
|
|
7
6
|
import { loadEntities } from "../../public/operations/discovery-entities.js";
|
|
8
7
|
import { executeStatus } from "../../public/operations/discovery-executors.js";
|
|
9
8
|
import { readAuthoredEntity } from "../../public/operations/entity-context.js";
|
|
10
9
|
import { buildWhatIfAnalysisGoal } from "../mutation/contradictions.js";
|
|
11
10
|
import { canonicalSourcePath } from "../mutation/source-authoring.js";
|
|
12
11
|
import { validateUpsertInput } from "../mutation/validation.js";
|
|
12
|
+
import { isBlockingWitness, parseWhatIfAnalysis, } from "../mutation/what-if.js";
|
|
13
13
|
import { analyzeSemanticAdvisorInputWithPlugins } from "../semantic-advisor/plugin-orchestration.js";
|
|
14
14
|
import { canonicalize } from "../semantic-advisor/shared.js";
|
|
15
15
|
// implements REQ-kibi-change-to-proof-plan-compiler-v2
|
|
16
16
|
export const COMPILE_PLAN_VERSION = "kibi.compile-plan.v1";
|
|
17
|
+
export { isBlockingWitness, parseWhatIfAnalysis } from "../mutation/what-if.js";
|
|
17
18
|
// implements REQ-kibi-change-to-proof-plan-compiler-v2
|
|
18
19
|
export function compilePlanHash(plan) {
|
|
19
20
|
const { planHash: _ignored, ...body } = plan;
|
|
@@ -342,58 +343,6 @@ export function planWhatIfGoal(steps, now) {
|
|
|
342
343
|
};
|
|
343
344
|
}));
|
|
344
345
|
}
|
|
345
|
-
function whatIfWitness(witness) {
|
|
346
|
-
return {
|
|
347
|
-
...witness,
|
|
348
|
-
requirements: Array.isArray(witness.requirements)
|
|
349
|
-
? witness.requirements.map((id) => normalizeEntityId(String(id)))
|
|
350
|
-
: [],
|
|
351
|
-
reason: text(witness.reason),
|
|
352
|
-
status: text(witness.status) || "contradiction",
|
|
353
|
-
...(typeof witness.kind === "string" ? { kind: witness.kind } : {}),
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
function whatIfWitnesses(value) {
|
|
357
|
-
return (Array.isArray(value) ? value.filter(isRecord) : []).map(whatIfWitness);
|
|
358
|
-
}
|
|
359
|
-
// implements REQ-kibi-truthful-consistency
|
|
360
|
-
/**
|
|
361
|
-
* Parse checks:what_if_analysis_json/2 output. The binding is a quoted Prolog
|
|
362
|
-
* string, so the JSON may arrive encoded once more as a JSON string. A bare
|
|
363
|
-
* witness array (the what_if_contradiction_witnesses_json/2 shape) carries no
|
|
364
|
-
* current-KB baseline, so every witness in it is treated as introduced.
|
|
365
|
-
* Returns null when the output cannot be read.
|
|
366
|
-
*/
|
|
367
|
-
export function parseWhatIfAnalysis(raw) {
|
|
368
|
-
if (typeof raw !== "string")
|
|
369
|
-
return null;
|
|
370
|
-
let parsed;
|
|
371
|
-
try {
|
|
372
|
-
parsed = JSON.parse(raw);
|
|
373
|
-
if (typeof parsed === "string")
|
|
374
|
-
parsed = JSON.parse(parsed);
|
|
375
|
-
}
|
|
376
|
-
catch {
|
|
377
|
-
return null;
|
|
378
|
-
}
|
|
379
|
-
if (Array.isArray(parsed)) {
|
|
380
|
-
const after = whatIfWitnesses(parsed);
|
|
381
|
-
return { after, introduced: after, removed: [], unchanged: [] };
|
|
382
|
-
}
|
|
383
|
-
if (!isRecord(parsed))
|
|
384
|
-
return null;
|
|
385
|
-
return {
|
|
386
|
-
after: whatIfWitnesses(parsed.after),
|
|
387
|
-
introduced: whatIfWitnesses(parsed.introduced),
|
|
388
|
-
removed: whatIfWitnesses(parsed.removed),
|
|
389
|
-
unchanged: whatIfWitnesses(parsed.unchanged),
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
// implements REQ-kibi-truthful-consistency
|
|
393
|
-
/** Blocking: a proven contradiction or an infeasible success scenario. */
|
|
394
|
-
export function isBlockingWitness(witness) {
|
|
395
|
-
return witness.status === "contradiction" || witness.status === "infeasible";
|
|
396
|
-
}
|
|
397
346
|
// implements REQ-kibi-truthful-consistency
|
|
398
347
|
// Check the KB as it would be after this plan, not the KB as it is: stage every
|
|
399
348
|
// planned step in a rolled-back transaction and compare its contradiction and
|
|
@@ -608,6 +557,68 @@ function draftSteps(requirementId, scenarios, tests) {
|
|
|
608
557
|
}
|
|
609
558
|
return { steps, diagnostics };
|
|
610
559
|
}
|
|
560
|
+
// implements REQ-model-what-if-planned-facts
|
|
561
|
+
/**
|
|
562
|
+
* A hash-bound compile plan for a grounding kb_model planned: the predicate
|
|
563
|
+
* fact and the requirement upsert that links it, validated and applied
|
|
564
|
+
* together by kb_apply_plan. Its contradiction analysis is the what-if over
|
|
565
|
+
* the current KB plus these steps, so a decision conflict with a fact that is
|
|
566
|
+
* already stored is reported here, before any write, and blocks the plan.
|
|
567
|
+
*/
|
|
568
|
+
export async function compileGroundingPlan(context, prolog, input) {
|
|
569
|
+
const now = context.clock();
|
|
570
|
+
const statusResult = await executeStatus({}, context);
|
|
571
|
+
const status = statusResult.structuredContent;
|
|
572
|
+
if (!status)
|
|
573
|
+
throw new Error("Grounding plan failed: status query returned no payload");
|
|
574
|
+
const contradictions = await contradictionAnalysis(prolog, input.requirementId, input.steps, now);
|
|
575
|
+
const diagnostics = [];
|
|
576
|
+
let statusValue = contradictions.outcome === "conflict" ? "blocked" : "ready";
|
|
577
|
+
let planSteps = [...input.steps];
|
|
578
|
+
if (statusValue === "ready") {
|
|
579
|
+
try {
|
|
580
|
+
planSteps = await withDocumentTargets(context, prolog, input.steps, { id: input.requirementId }, now);
|
|
581
|
+
}
|
|
582
|
+
catch (error) {
|
|
583
|
+
statusValue = "needs_resolution";
|
|
584
|
+
diagnostics.push(`A plan step cannot be applied as written: ${error instanceof Error ? error.message : String(error)}`);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
// The hash binds the plan as it travels: a step field left undefined
|
|
588
|
+
// (kb_model's optional source) is absent on the wire, so it is absent here.
|
|
589
|
+
const planBody = JSON.parse(JSON.stringify({
|
|
590
|
+
version: COMPILE_PLAN_VERSION,
|
|
591
|
+
status: statusValue,
|
|
592
|
+
expected: {
|
|
593
|
+
branch: status.branch,
|
|
594
|
+
kbSnapshotId: status.snapshotId,
|
|
595
|
+
workspaceSnapshot: status.proofSnapshot ?? "unknown",
|
|
596
|
+
sourceHashes: {},
|
|
597
|
+
},
|
|
598
|
+
target: {
|
|
599
|
+
mode: "update",
|
|
600
|
+
requirementId: input.requirementId,
|
|
601
|
+
selectionReason: `kb_model mode predicates grounds claim ${input.claimKey} of the supplied requirementId.`,
|
|
602
|
+
},
|
|
603
|
+
discovery: { candidates: [], abstained: true },
|
|
604
|
+
propositions: [
|
|
605
|
+
{
|
|
606
|
+
claimKey: input.claimKey,
|
|
607
|
+
text: input.text,
|
|
608
|
+
span: { start: 0, end: Buffer.byteLength(input.text, "utf8") },
|
|
609
|
+
disposition: "predicate",
|
|
610
|
+
status: "modeled",
|
|
611
|
+
origin: "deterministic",
|
|
612
|
+
},
|
|
613
|
+
],
|
|
614
|
+
contradictionAnalysis: contradictions,
|
|
615
|
+
proposals: [],
|
|
616
|
+
steps: planSteps,
|
|
617
|
+
sourceWrites: [],
|
|
618
|
+
diagnostics,
|
|
619
|
+
}));
|
|
620
|
+
return { ...planBody, planHash: compilePlanHash(planBody) };
|
|
621
|
+
}
|
|
611
622
|
// implements REQ-kibi-change-to-proof-plan-compiler-v2
|
|
612
623
|
export async function executeCompileIntent(args, context) {
|
|
613
624
|
const intent = requiredIntent(args);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clauses.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/clauses.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"clauses.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/clauses.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC,CAAC,CAAC;AAmBH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAQD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB,WAAW,GAAG,aAAa,CAG7B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAW7D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AA4BD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAClC,SAAS,cAAc,EAAE,CA4B3B"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
// An explicit grant ("are allowed to", "is permitted to"
|
|
3
|
-
// permission just as "denied"/"forbidden"
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// unmodeled normative
|
|
8
|
-
|
|
2
|
+
// An explicit grant ("are allowed to", "is permitted to", "have permission
|
|
3
|
+
// to", "are entitled to") asserts a permission just as "denied"/"forbidden"
|
|
4
|
+
// assert a prohibition. Bare "can", "may" and "are able to" are accepted by
|
|
5
|
+
// the predicate applicability gate but not here: stored clause roles are
|
|
6
|
+
// derived from this pattern, and "it can be restricted to …" style capability
|
|
7
|
+
// prose would turn existing descriptive inventories into unmodeled normative
|
|
8
|
+
// clauses ("must be able to" is already normative through "must").
|
|
9
|
+
const NORMATIVE_ASSERTION_PATTERN = /\b(?:must|shall|should|required|requires?|may\s+only|(?:is|are)\s+(?:not\s+)?(?:allowed|permitted|entitled)\s+to|ha(?:s|ve)\s+(?:no\s+)?permission\s+to|permitted|may\s+(?:not\s+)?(?:be\s+)?\w+\s+only\b|may\s+(?:have\s+)?(?:at\s+most|at\s+least|exactly|no\s+more\s+than|up\s+to)|only\s+.+?\s+(?:may|can)|must\s+not|shall\s+not|cannot|can't|denied|forbidden|prohibited|(?:is|are|be|become|becomes|remain|remains)\s+(?:invalid|rejected|prohibited|forbidden)|(?:reject|rejects|rejected|rejection)\s+(?:invalid|unresolved|ambiguous)|fail(?:s|ed)?\s+(?:clearly|explicitly|with)|expires?\s+(?:after|within|in)|failure\s+(?:behavior|policy|outcome)|error\s+(?:handling|behavior|policy|outcome)|required\s+outcome|defaults?\s+to)\b/i;
|
|
9
10
|
// Conditional/temporal cues help discover clauses but do not by themselves
|
|
10
11
|
// turn explanatory or subjective context into an asserted obligation.
|
|
11
12
|
const NORMATIVE_PATTERN = new RegExp(`${NORMATIVE_ASSERTION_PATTERN.source}|\\b(?:before|unless|when|if)\\b`, "i");
|