kibi-cli 2.9.0 → 2.11.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/operations/bootstrap/candidates.d.ts +2 -1
- package/dist/operations/bootstrap/candidates.d.ts.map +1 -1
- package/dist/operations/bootstrap/candidates.js +2 -2
- package/dist/operations/bootstrap/generate.d.ts.map +1 -1
- package/dist/operations/bootstrap/generate.js +6 -2
- package/dist/operations/bootstrap/intent-claims.d.ts +2 -1
- package/dist/operations/bootstrap/intent-claims.d.ts.map +1 -1
- package/dist/operations/bootstrap/intent-claims.js +27 -5
- package/dist/operations/bootstrap/markdown-candidates.d.ts +8 -1
- package/dist/operations/bootstrap/markdown-candidates.d.ts.map +1 -1
- package/dist/operations/bootstrap/markdown-candidates.js +59 -5
- package/dist/operations/bootstrap/presentation.d.ts.map +1 -1
- package/dist/operations/bootstrap/presentation.js +6 -0
- package/dist/operations/bootstrap/requirement-claims.d.ts +61 -1
- package/dist/operations/bootstrap/requirement-claims.d.ts.map +1 -1
- package/dist/operations/bootstrap/requirement-claims.js +263 -0
- package/dist/operations/bootstrap/types.d.ts +6 -0
- package/dist/operations/bootstrap/types.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.d.ts +7 -0
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +39 -12
- package/dist/operations/modeling/predicate-binding-hints.d.ts +11 -0
- package/dist/operations/modeling/predicate-binding-hints.d.ts.map +1 -0
- package/dist/operations/modeling/predicate-binding-hints.js +91 -0
- package/dist/operations/modeling/predicate-bindings.d.ts +24 -1
- package/dist/operations/modeling/predicate-bindings.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-bindings.js +113 -3
- package/dist/operations/modeling/predicate-types.d.ts +19 -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 +117 -44
- package/dist/operations/planning/apply-plan.d.ts +8 -0
- package/dist/operations/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +69 -20
- package/dist/operations/semantic-advisor/observation-plan.d.ts +7 -0
- package/dist/operations/semantic-advisor/observation-plan.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/observation-plan.js +13 -14
- package/dist/public/operations/catalog.d.ts +15 -0
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/contracts.d.ts.map +1 -1
- package/dist/public/operations/contracts.js +5 -1
- package/dist/public/operations/specs/bootstrap.d.ts +15 -0
- package/dist/public/operations/specs/bootstrap.d.ts.map +1 -1
- package/dist/public/operations/specs/bootstrap.js +15 -0
- package/dist/public/operations/specs/planning.d.ts +1 -1
- package/dist/public/operations/specs/planning.d.ts.map +1 -1
- package/dist/public/operations/specs/planning.js +1 -1
- package/dist/public/skills/kibi-bootstrap/SKILL.md +5 -5
- package/dist/public/skills/kibi-usage/SKILL.md +20 -8
- package/dist/public/skills/kibi-usage/resources/workflows.md +2 -2
- package/package.json +1 -1
- package/src/public/operations/contracts.ts +6 -1
- package/src/public/operations/specs/bootstrap.ts +18 -0
- package/src/public/operations/specs/planning.ts +4 -1
- package/src/public/skills/kibi-bootstrap/SKILL.md +5 -5
- package/src/public/skills/kibi-usage/SKILL.md +20 -8
- package/src/public/skills/kibi-usage/resources/workflows.md +2 -2
|
@@ -92,12 +92,122 @@ export function isGenericPlaceholder(value) {
|
|
|
92
92
|
(normalized.endsWith("_policy") &&
|
|
93
93
|
["executable", "cwd", "environment", "stdio", "termination"].some((kind) => normalized.startsWith(kind))));
|
|
94
94
|
}
|
|
95
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Words that carry no domain meaning on their own: auxiliary and trivial
|
|
97
|
+
* verbs, articles, pronouns and filler. A binding made of one of them names
|
|
98
|
+
* no reviewed value, so it stays unbound.
|
|
99
|
+
*/
|
|
100
|
+
const STOP_WORD_BINDINGS = new Set([
|
|
101
|
+
"a",
|
|
102
|
+
"an",
|
|
103
|
+
"the",
|
|
104
|
+
"be",
|
|
105
|
+
"is",
|
|
106
|
+
"are",
|
|
107
|
+
"was",
|
|
108
|
+
"were",
|
|
109
|
+
"been",
|
|
110
|
+
"being",
|
|
111
|
+
"am",
|
|
112
|
+
"do",
|
|
113
|
+
"does",
|
|
114
|
+
"did",
|
|
115
|
+
"done",
|
|
116
|
+
"have",
|
|
117
|
+
"has",
|
|
118
|
+
"had",
|
|
119
|
+
"it",
|
|
120
|
+
"its",
|
|
121
|
+
"this",
|
|
122
|
+
"that",
|
|
123
|
+
"these",
|
|
124
|
+
"those",
|
|
125
|
+
"they",
|
|
126
|
+
"them",
|
|
127
|
+
"there",
|
|
128
|
+
"thing",
|
|
129
|
+
"something",
|
|
130
|
+
"anything",
|
|
131
|
+
"some",
|
|
132
|
+
"any",
|
|
133
|
+
"of",
|
|
134
|
+
"to",
|
|
135
|
+
"in",
|
|
136
|
+
"at",
|
|
137
|
+
"by",
|
|
138
|
+
"for",
|
|
139
|
+
"with",
|
|
140
|
+
"and",
|
|
141
|
+
"or",
|
|
142
|
+
"not",
|
|
143
|
+
"null",
|
|
144
|
+
"nil",
|
|
145
|
+
"n_a",
|
|
146
|
+
"na",
|
|
147
|
+
"tbd",
|
|
148
|
+
"todo",
|
|
149
|
+
"x",
|
|
150
|
+
"xxx",
|
|
151
|
+
"foo",
|
|
152
|
+
"bar",
|
|
153
|
+
"example",
|
|
154
|
+
"placeholder",
|
|
155
|
+
]);
|
|
156
|
+
/** A binding value in the snake_case form argument names use. */
|
|
157
|
+
export function bindingToken(value) {
|
|
158
|
+
return value
|
|
159
|
+
.trim()
|
|
160
|
+
.toLowerCase()
|
|
161
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
162
|
+
.replace(/^_+|_+$/g, "");
|
|
163
|
+
}
|
|
164
|
+
function claimNames(text, token) {
|
|
165
|
+
if (!text || !token)
|
|
166
|
+
return false;
|
|
167
|
+
const words = token.split("_").filter(Boolean);
|
|
168
|
+
if (words.length === 0)
|
|
169
|
+
return false;
|
|
170
|
+
return new RegExp(`\\b${words.join("[\\s_-]+")}\\b`, "i").test(text);
|
|
171
|
+
}
|
|
172
|
+
function matchesConstant(value, context) {
|
|
173
|
+
const token = bindingToken(value);
|
|
174
|
+
return (context.constants?.some((constant) => bindingToken(constant) === token) ??
|
|
175
|
+
false);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Why a value only stands in for a binding, or null when it can be a reviewed
|
|
179
|
+
* value: it repeats its own or another argument's name, or it is a bare stop
|
|
180
|
+
* word. Declared constants and the booleans `true`/`false` always pass.
|
|
181
|
+
*/
|
|
182
|
+
// implements REQ-model-predicates-binding-placeholders
|
|
183
|
+
export function nameOrStopWordReason(value, context = {}) {
|
|
184
|
+
const token = bindingToken(value);
|
|
185
|
+
if (token === "true" || token === "false")
|
|
186
|
+
return null;
|
|
187
|
+
if (matchesConstant(value, context))
|
|
188
|
+
return null;
|
|
189
|
+
if (STOP_WORD_BINDINGS.has(token))
|
|
190
|
+
return `"${token}" is a stop word`;
|
|
191
|
+
const own = context.argumentName ? bindingToken(context.argumentName) : "";
|
|
192
|
+
const repeatsName = (own !== "" && token === own) ||
|
|
193
|
+
(context.argumentNames ?? []).some((name) => bindingToken(name) === token);
|
|
194
|
+
if (repeatsName && !claimNames(context.text, token))
|
|
195
|
+
return `it repeats the argument name ${token} and the claim does not name it`;
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
// implements REQ-mcp-suggest-predicates, REQ-model-predicates-binding-placeholders
|
|
199
|
+
export function classifyBinding(value, text, explicit, canonical = false, context = {}) {
|
|
96
200
|
const normalized = value.trim();
|
|
97
|
-
|
|
201
|
+
// A value that only repeats an argument name or a stop word is unbound
|
|
202
|
+
// however it was supplied or extracted.
|
|
203
|
+
if (nameOrStopWordReason(normalized, { ...context, text }) !== null)
|
|
204
|
+
return "placeholder";
|
|
205
|
+
const constant = matchesConstant(normalized, context);
|
|
206
|
+
if (canonical && (constant || !isGenericPlaceholder(normalized)))
|
|
98
207
|
return "extracted";
|
|
99
208
|
if (explicit &&
|
|
100
|
-
(
|
|
209
|
+
(constant ||
|
|
210
|
+
!isGenericPlaceholder(normalized) ||
|
|
101
211
|
["true", "false"].includes(normalized.toLowerCase())))
|
|
102
212
|
return "explicit";
|
|
103
213
|
if (!normalized || isGenericPlaceholder(normalized))
|
|
@@ -86,6 +86,22 @@ export interface RecommendedPredicateSchema {
|
|
|
86
86
|
rationale: string;
|
|
87
87
|
reuse_scope: string;
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* What an agent needs to bind one unbound predicate argument: its type, the
|
|
91
|
+
* declared constants of a closed vocabulary, schema example values and why
|
|
92
|
+
* the current value was not accepted.
|
|
93
|
+
*/
|
|
94
|
+
export interface BindingHint {
|
|
95
|
+
argument: string;
|
|
96
|
+
position: number;
|
|
97
|
+
type: string;
|
|
98
|
+
description?: string;
|
|
99
|
+
allowedValues?: string[];
|
|
100
|
+
examples: string[];
|
|
101
|
+
currentValue: string;
|
|
102
|
+
provenance: BindingProvenance;
|
|
103
|
+
reason: string;
|
|
104
|
+
}
|
|
89
105
|
/** A logical grounding relationship an existing requirement has for a claim. */
|
|
90
106
|
export interface ExistingClaimGrounding {
|
|
91
107
|
relationship: {
|
|
@@ -110,7 +126,7 @@ export interface SuggestPredicatesResult {
|
|
|
110
126
|
requirementId: string | null;
|
|
111
127
|
subject: string;
|
|
112
128
|
candidates: PredicateSuggestion[];
|
|
113
|
-
recommendedAction: "apply_requires_predicate" | "provide_argument_bindings" | "resolve_schema_reference" | "record_ontology_gap" | "review_nonlogical" | "
|
|
129
|
+
recommendedAction: "apply_requires_predicate" | "provide_argument_bindings" | "resolve_schema_reference" | "record_ontology_gap" | "review_nonlogical" | "replace_grounding";
|
|
114
130
|
recommendedPredicateSchema: RecommendedPredicateSchema | null;
|
|
115
131
|
applyPlan: Array<Record<string, unknown>>;
|
|
116
132
|
relationshipPlan: Record<string, unknown> | null;
|
|
@@ -118,6 +134,8 @@ export interface SuggestPredicatesResult {
|
|
|
118
134
|
relationshipTarget?: string | null;
|
|
119
135
|
existingGrounding?: ExistingClaimGrounding[];
|
|
120
136
|
replacementPlan?: Record<string, unknown> | null;
|
|
137
|
+
/** On provide_argument_bindings: one hint per unbound argument of the recommended candidate. */
|
|
138
|
+
bindingHints?: BindingHint[];
|
|
121
139
|
warnings: string[];
|
|
122
140
|
};
|
|
123
141
|
applyPlan: Array<Record<string, unknown>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"predicate-types.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"predicate-types.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest-predicates.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/suggest-predicates.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"suggest-predicates.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/suggest-predicates.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACX,MAAM,0CAA0C,CAAC;AAyBlD,OAAO,KAAK,EAGV,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EACV,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AA6H9B,wBAAgB,sCAAsC,CACpD,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,qBAAqB,GAAG,gBAAgB,CAAC,EACzE,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,qBAAqB,GAAG,gBAAgB,CAAC,GACzE,MAAM,CAIR;AAED,wBAAgB,2CAA2C,CACzD,IAAI,EAAE,IAAI,CACR,mBAAmB,EACnB,qBAAqB,GAAG,OAAO,GAAG,gBAAgB,CACnD,EACD,KAAK,EAAE,IAAI,CACT,mBAAmB,EACnB,qBAAqB,GAAG,OAAO,GAAG,gBAAgB,CACnD,GACA,MAAM,CAKR;AA0FD,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,IAAI,EAAE,qBAAqB,EAC3B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,uBAAuB,CAAC,CAmQlC;AA8GD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,qBAAqB,EAC3B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,uBAAuB,CAAC,CAElC"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { escapeAtom } from "../../prolog/codec.js";
|
|
2
|
+
import { loadEntities } from "../../public/operations/discovery-entities.js";
|
|
2
3
|
import { parsePrologList } from "../mutation/serialization.js";
|
|
3
4
|
import { analyzeSemanticAdvisorInput } from "../semantic-advisor/analyze-prose.js";
|
|
4
5
|
import { semanticClaimKey } from "../semantic-advisor/clauses.js";
|
|
5
6
|
import { composeOntologyCatalogForOperation } from "../semantic-advisor/plugin-orchestration.js";
|
|
6
7
|
import { STRONG_APPLICABILITY_SCORE, WEAK_CANDIDATE_MARGIN, evaluateSemanticApplicability, } from "./predicate-applicability.js";
|
|
7
8
|
import { buildGapApplyPlan, buildPredicateApplyPlan, buildPredicateSchemaDraft, buildRelationshipPlan, buildSuggestion, } from "./predicate-applyplan.js";
|
|
9
|
+
import { buildBindingHints, describeBindingHints, } from "./predicate-binding-hints.js";
|
|
8
10
|
import { BUILT_IN_PREDICATE_SCHEMAS } from "./predicate-catalog.js";
|
|
9
11
|
import { inferSubject } from "./predicate-inference.js";
|
|
10
12
|
import { loadExistingPredicateSchemas } from "./predicate-loader.js";
|
|
@@ -159,7 +161,7 @@ function unquoted(value) {
|
|
|
159
161
|
* second link (for example requires_predicate beside a bootstrap
|
|
160
162
|
* requires_property) fails the proposition-complete rule.
|
|
161
163
|
*/
|
|
162
|
-
// implements REQ-model-predicates-grounding-aware
|
|
164
|
+
// implements REQ-model-predicates-grounding-aware-v2
|
|
163
165
|
async function existingClaimGrounding(prolog, requirementId, claimKey, warnings) {
|
|
164
166
|
if (prolog === null || !requirementId)
|
|
165
167
|
return [];
|
|
@@ -287,53 +289,69 @@ export async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
287
289
|
const completeCandidate = recommendedCandidate && recommendedCandidate.binding_status === "complete"
|
|
288
290
|
? recommendedCandidate
|
|
289
291
|
: undefined;
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
:
|
|
297
|
-
|
|
298
|
-
|
|
292
|
+
// The action names the predicate state; existingGrounding (non-empty) is
|
|
293
|
+
// the separate "already grounded" signal. A complete candidate for a claim
|
|
294
|
+
// that is already grounded becomes a replacement, never a second link.
|
|
295
|
+
const recommendedAction = !recommendedCandidate
|
|
296
|
+
? unavailableSchema
|
|
297
|
+
? "resolve_schema_reference"
|
|
298
|
+
: "record_ontology_gap"
|
|
299
|
+
: completeCandidate
|
|
300
|
+
? alreadyGrounded
|
|
301
|
+
? "replace_grounding"
|
|
302
|
+
: "apply_requires_predicate"
|
|
303
|
+
: "provide_argument_bindings";
|
|
299
304
|
const predicatePlan = completeCandidate
|
|
300
305
|
? buildPredicateApplyPlan(completeCandidate, args)
|
|
301
306
|
: [];
|
|
302
|
-
// An already grounded claim gets no write plan: a second
|
|
303
|
-
// would fail the proposition-complete rule
|
|
304
|
-
// swaps the grounding instead.
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
?
|
|
309
|
-
:
|
|
310
|
-
|
|
311
|
-
|
|
307
|
+
// An already grounded claim gets no predicate write plan: a second
|
|
308
|
+
// grounding link would fail the proposition-complete rule, so the
|
|
309
|
+
// replacement plan below swaps the grounding instead. The ontology-gap
|
|
310
|
+
// observation is not a grounding relationship, so it is planned either way.
|
|
311
|
+
const applyPlan = completeCandidate
|
|
312
|
+
? alreadyGrounded
|
|
313
|
+
? []
|
|
314
|
+
: predicatePlan
|
|
315
|
+
: !recommendedCandidate && !unavailableSchema
|
|
316
|
+
? buildGapApplyPlan(text, args)
|
|
317
|
+
: [];
|
|
312
318
|
const plannedFactId = typeof predicatePlan[0]?.id === "string" ? predicatePlan[0].id : null;
|
|
313
319
|
const relationshipPlan = completeCandidate && !alreadyGrounded
|
|
314
320
|
? buildRelationshipPlan(plannedFactId ?? "", args.requirementId, text, args.existingLogicClaims)
|
|
315
321
|
: null;
|
|
316
322
|
const replacementPlan = alreadyGrounded && plannedFactId !== null && args.requirementId
|
|
317
|
-
? buildGroundingReplacementPlan(args.requirementId, plannedFactId, predicatePlan, existingGrounding)
|
|
323
|
+
? buildGroundingReplacementPlan(args.requirementId, plannedFactId, predicatePlan, existingGrounding, await storedRequirementProperties(prolog, args.requirementId, warnings))
|
|
318
324
|
: null;
|
|
319
325
|
const relationshipTarget = relationshipPlan !== null || replacementPlan !== null
|
|
320
326
|
? plannedFactId
|
|
321
327
|
: null;
|
|
328
|
+
const groundingSummary = existingGrounding
|
|
329
|
+
.map((row) => `${row.relationship.type} -> ${row.factId}`)
|
|
330
|
+
.join(", ");
|
|
322
331
|
if (alreadyGrounded) {
|
|
323
|
-
warnings.push(`${args.requirementId} already grounds this claim (${claimKey}) through ${
|
|
332
|
+
warnings.push(`${args.requirementId} already grounds this claim (${claimKey}) through ${groundingSummary}. A modeled claim takes exactly one logical grounding relationship, so adding requires_predicate beside it fails the proposition-complete rule. ${replacementPlan ? "Keep the existing grounding, or follow replacementPlan to swap it for the predicate." : "Keep the existing grounding; no predicate replacement is available yet."}`);
|
|
324
333
|
}
|
|
325
|
-
const
|
|
334
|
+
const bindingHints = recommendedAction === "provide_argument_bindings" && recommendedCandidate
|
|
335
|
+
? buildBindingHints(recommendedCandidate, text)
|
|
336
|
+
: [];
|
|
337
|
+
const recommendedPredicateSchema = !recommendedCandidate && !unavailableSchema
|
|
326
338
|
? buildPredicateSchemaDraft(text, subject)
|
|
327
339
|
: null;
|
|
328
|
-
const
|
|
329
|
-
? `${args.requirementId} already grounds this claim through ${
|
|
330
|
-
:
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
340
|
+
const groundedPrefix = alreadyGrounded
|
|
341
|
+
? `${args.requirementId} already grounds this claim through ${groundingSummary}. `
|
|
342
|
+
: "";
|
|
343
|
+
const textSummary = groundedPrefix +
|
|
344
|
+
(replacementPlan
|
|
345
|
+
? `To use ${completeCandidate?.predicate_name} instead, follow replacementPlan and link requires_predicate to ${plannedFactId}; otherwise keep the existing grounding.`
|
|
346
|
+
: completeCandidate
|
|
347
|
+
? `Suggested ${candidates.length} predicate candidate(s). Top applicable match: ${completeCandidate.predicate_name}. Apply the predicate fact ${plannedFactId}, then link requires_predicate to that fact id (not a candidate id).`
|
|
348
|
+
: recommendedCandidate
|
|
349
|
+
? `Matched ${recommendedCandidate.predicate_name}, but exact reviewed values are still required for: ${recommendedCandidate.unbound_arguments.join(", ")}. Bind them from the claim text: ${describeBindingHints(bindingHints)}. A value that repeats an argument name or a stop word stays unbound. No apply plan was generated.`
|
|
350
|
+
: unavailableSchema
|
|
351
|
+
? `Requested predicate schema ${args.schemaId} is unavailable or semantically inapplicable. No apply plan was generated.`
|
|
352
|
+
: alreadyGrounded
|
|
353
|
+
? "No predicate candidate passed the semantic applicability gate; keep the existing grounding and record the ontology-gap observation in applyPlan so the missing schema stays visible."
|
|
354
|
+
: "No predicate candidate passed the semantic applicability gate; record an ontology gap and review the generated schema draft instead of silently writing prose.");
|
|
337
355
|
const logicClaims = Array.from(new Set([...(args.existingLogicClaims ?? []), claimKey]));
|
|
338
356
|
return {
|
|
339
357
|
content: [{ type: "text", text: textSummary }],
|
|
@@ -352,18 +370,72 @@ export async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
352
370
|
relationshipTarget,
|
|
353
371
|
existingGrounding,
|
|
354
372
|
replacementPlan,
|
|
373
|
+
bindingHints,
|
|
355
374
|
warnings,
|
|
356
375
|
},
|
|
357
376
|
applyPlan,
|
|
358
377
|
};
|
|
359
378
|
}
|
|
379
|
+
/** Stored requirement fields a relationship-only update must restate. */
|
|
380
|
+
const RESTATED_REQUIREMENT_FIELDS = [
|
|
381
|
+
"title",
|
|
382
|
+
"status",
|
|
383
|
+
"priority",
|
|
384
|
+
"owner",
|
|
385
|
+
"tags",
|
|
386
|
+
];
|
|
387
|
+
/**
|
|
388
|
+
* The requirement fields the replacement's requirement upsert restates, so
|
|
389
|
+
* the step is a complete kb_upsert payload (title and status are required)
|
|
390
|
+
* that keeps the stored metadata. The stored proposition ledger and text_ref
|
|
391
|
+
* are merged by kb_upsert itself.
|
|
392
|
+
*/
|
|
393
|
+
// implements REQ-model-predicates-plan-roundtrip
|
|
394
|
+
async function storedRequirementProperties(prolog, requirementId, warnings) {
|
|
395
|
+
if (prolog === null)
|
|
396
|
+
return null;
|
|
397
|
+
try {
|
|
398
|
+
const [stored] = await loadEntities(prolog, {
|
|
399
|
+
id: requirementId,
|
|
400
|
+
type: "req",
|
|
401
|
+
});
|
|
402
|
+
if (stored === undefined)
|
|
403
|
+
return null;
|
|
404
|
+
const restated = {};
|
|
405
|
+
for (const field of RESTATED_REQUIREMENT_FIELDS)
|
|
406
|
+
if (stored[field] !== undefined && stored[field] !== null)
|
|
407
|
+
restated[field] = stored[field];
|
|
408
|
+
return typeof restated.title === "string" &&
|
|
409
|
+
typeof restated.status === "string"
|
|
410
|
+
? restated
|
|
411
|
+
: null;
|
|
412
|
+
}
|
|
413
|
+
catch (error) {
|
|
414
|
+
warnings.push(`Requirement ${requirementId} could not be read (${error instanceof Error ? error.message : String(error)}); add its stored title and status to the last replacementPlan step before applying it.`);
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
360
418
|
/**
|
|
361
419
|
* Ordered steps that swap an existing grounding for the planned predicate
|
|
362
420
|
* fact while keeping one grounding relationship per modeled claim: write the
|
|
363
|
-
* fact, retract the old grounding link, then link requires_predicate.
|
|
421
|
+
* fact, retract the old grounding link, then link requires_predicate. The
|
|
422
|
+
* order is forced: kb_upsert merges a requirement's relationships, so linking
|
|
423
|
+
* first would give the claim two groundings and be rejected. Between the
|
|
424
|
+
* retraction and the link the claim is ungrounded (kb_check reports
|
|
425
|
+
* logic-coverage), so the steps run back to back and `rollback` restores the
|
|
426
|
+
* old link if the last step fails.
|
|
364
427
|
*/
|
|
365
|
-
// implements REQ-model-predicates-grounding-aware
|
|
366
|
-
function buildGroundingReplacementPlan(requirementId, factId, predicatePlan, existing) {
|
|
428
|
+
// implements REQ-model-predicates-grounding-aware-v2, REQ-model-predicates-plan-roundtrip
|
|
429
|
+
function buildGroundingReplacementPlan(requirementId, factId, predicatePlan, existing, stored) {
|
|
430
|
+
const requirementUpsert = (relationships) => ({
|
|
431
|
+
type: "req",
|
|
432
|
+
id: requirementId,
|
|
433
|
+
...(stored === null ? {} : { properties: stored }),
|
|
434
|
+
relationships,
|
|
435
|
+
});
|
|
436
|
+
const restate = stored === null
|
|
437
|
+
? `add the requirement's stored title and status as properties (they could not be read), keep this relationship only`
|
|
438
|
+
: "the properties restate the stored title, status and metadata; kb_upsert keeps the stored proposition ledger";
|
|
367
439
|
return {
|
|
368
440
|
relationshipTarget: factId,
|
|
369
441
|
steps: [
|
|
@@ -381,17 +453,18 @@ function buildGroundingReplacementPlan(requirementId, factId, predicatePlan, exi
|
|
|
381
453
|
},
|
|
382
454
|
{
|
|
383
455
|
operation: "kb_upsert",
|
|
384
|
-
input:
|
|
385
|
-
type: "
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
{ type: "requires_predicate", from: requirementId, to: factId },
|
|
389
|
-
],
|
|
390
|
-
},
|
|
391
|
-
reason: `Link requires_predicate to ${factId}; upsert the requirement with its stored title and status and this relationship only.`,
|
|
456
|
+
input: requirementUpsert([
|
|
457
|
+
{ type: "requires_predicate", from: requirementId, to: factId },
|
|
458
|
+
]),
|
|
459
|
+
reason: `Link requires_predicate to ${factId}; ${restate}.`,
|
|
392
460
|
},
|
|
393
461
|
],
|
|
394
|
-
|
|
462
|
+
rollback: {
|
|
463
|
+
operation: "kb_upsert",
|
|
464
|
+
input: requirementUpsert(existing.map((row) => row.relationship)),
|
|
465
|
+
reason: "Only if the last step fails: restore the retracted grounding link so the claim is grounded again.",
|
|
466
|
+
},
|
|
467
|
+
instructions: `Only replace the grounding when the predicate states the claim at least as precisely as ${existing.map((row) => row.factId).join(", ")}. Apply the steps unchanged, in order and back to back: linking requires_predicate before the retraction is rejected because the claim would have two groundings, and between the retraction and the link the claim is ungrounded, so kb_check reports logic-coverage for ${requirementId} until the last step lands. If the last step fails, apply rollback. Run kb_check after the last step.`,
|
|
395
468
|
};
|
|
396
469
|
}
|
|
397
470
|
export async function executeSuggestPredicates(args, context) {
|
|
@@ -9,6 +9,14 @@ export declare function assertBootstrapRecoveryDependencies(remaining: readonly
|
|
|
9
9
|
dependsOn?: readonly string[];
|
|
10
10
|
}[], applied: ReadonlySet<string>): void;
|
|
11
11
|
export declare function orderBootstrapActions(actions: readonly BootstrapAction[], completed?: Set<string>): BootstrapAction[];
|
|
12
|
+
/**
|
|
13
|
+
* Checks a plan-bearing kb_apply_plan call can start: the approved hash, the
|
|
14
|
+
* plan shape and canonical hash, and for a bootstrap plan its live snapshots.
|
|
15
|
+
* Writes nothing. An MCP async apply runs it before returning the job
|
|
16
|
+
* receipt, so input and stale-plan errors fail the call instead of the job.
|
|
17
|
+
* The apply itself repeats every check under the workspace lock.
|
|
18
|
+
*/
|
|
19
|
+
export declare function preflightApplyPlan(args: ApplyPlanArgs, context: OperationContext): Promise<void>;
|
|
12
20
|
export declare function executeApplyPlan(args: ApplyPlanArgs, context: OperationContext): Promise<{
|
|
13
21
|
content: Array<{
|
|
14
22
|
type: "text";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-plan.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/apply-plan.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAEV,gBAAgB,EAGjB,MAAM,0CAA0C,CAAC;AAQlD,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,uBAAuB,CAAC;AA+D/B,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAGhB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAG/B,eAAO,MAAM,yBAAyB,EAAG,2BAAoC,CAAC;AA6G9E,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,IAAI,CAMN;AAED,wBAAgB,mCAAmC,CACjD,SAAS,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EAAE,EACnE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,GAC3B,IAAI,CAaN;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,SAAS,cAAoB,GAC5B,eAAe,EAAE,CA2CnB;
|
|
1
|
+
{"version":3,"file":"apply-plan.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/apply-plan.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAEV,gBAAgB,EAGjB,MAAM,0CAA0C,CAAC;AAQlD,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,uBAAuB,CAAC;AA+D/B,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAGhB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAG/B,eAAO,MAAM,yBAAyB,EAAG,2BAAoC,CAAC;AA6G9E,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,IAAI,CAMN;AAED,wBAAgB,mCAAmC,CACjD,SAAS,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EAAE,EACnE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,GAC3B,IAAI,CAaN;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,SAAS,cAAoB,GAC5B,eAAe,EAAE,CA2CnB;AA8zBD;;;;;;GAMG;AAEH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAiCf;AAyqDD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC;IACT,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,iBAAiB,EAAE,eAAe,CAAC;CACpC,CAAC,CAkDD"}
|
|
@@ -675,15 +675,12 @@ async function executeSourceRecovery(args, context, onCommitted = () => undefine
|
|
|
675
675
|
},
|
|
676
676
|
};
|
|
677
677
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
if (!prolog)
|
|
685
|
-
throw new Error("Bootstrap apply requires a Prolog runtime");
|
|
686
|
-
const operationContext = { ...context, prolog, sourceFirst: true };
|
|
678
|
+
/**
|
|
679
|
+
* The bootstrap plan's live-state checks: branch, KB snapshot, workspace
|
|
680
|
+
* snapshot and declared source hashes must still match the plan.
|
|
681
|
+
*/
|
|
682
|
+
// implements REQ-bootstrap-apply-long-running
|
|
683
|
+
async function assertBootstrapPlanCurrent(args, operationContext) {
|
|
687
684
|
const statusResult = await executeStatus({}, operationContext);
|
|
688
685
|
const status = statusResult.structuredContent;
|
|
689
686
|
if (!status)
|
|
@@ -698,18 +695,70 @@ async function executeBootstrapPlan(args, context, recovery = false, remainingAc
|
|
|
698
695
|
sourceHashes: args.plan.expected.sourceHashes,
|
|
699
696
|
})
|
|
700
697
|
: status.snapshotId;
|
|
701
|
-
if (
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
698
|
+
if (args.plan.expected.branch !== "unknown" &&
|
|
699
|
+
status.branch !== args.plan.expected.branch)
|
|
700
|
+
throw new Error("Bootstrap apply failed: branch changed since planning");
|
|
701
|
+
if (boundLiveKbSnapshot !== args.plan.expected.kbSnapshotId)
|
|
702
|
+
throw new Error("Bootstrap apply failed: KB snapshot changed since planning");
|
|
703
|
+
if (args.plan.expected.workspaceSnapshot !== "unknown" &&
|
|
704
|
+
(!workspace.available ||
|
|
705
|
+
workspace.snapshot.hash !== args.plan.expected.workspaceSnapshot))
|
|
706
|
+
throw new Error("Bootstrap apply failed: workspace snapshot changed since planning");
|
|
707
|
+
await validateSources(operationContext, args.plan.expected.sourceHashes);
|
|
708
|
+
return status;
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Checks a plan-bearing kb_apply_plan call can start: the approved hash, the
|
|
712
|
+
* plan shape and canonical hash, and for a bootstrap plan its live snapshots.
|
|
713
|
+
* Writes nothing. An MCP async apply runs it before returning the job
|
|
714
|
+
* receipt, so input and stale-plan errors fail the call instead of the job.
|
|
715
|
+
* The apply itself repeats every check under the workspace lock.
|
|
716
|
+
*/
|
|
717
|
+
// implements REQ-mcp-apply-plan-async-preflight
|
|
718
|
+
export async function preflightApplyPlan(args, context) {
|
|
719
|
+
if (!("plan" in args))
|
|
720
|
+
return;
|
|
721
|
+
if (!isRecord(args.plan))
|
|
722
|
+
throw new Error("Apply plan failed: plan must be an object");
|
|
723
|
+
if (typeof args.approvedPlanHash !== "string" ||
|
|
724
|
+
!/^[a-f0-9]{64}$/i.test(args.approvedPlanHash))
|
|
725
|
+
throw new Error("Apply plan failed: approvedPlanHash must be the SHA-256 planHash returned with the plan");
|
|
726
|
+
if (isBootstrapApplyArgs(args)) {
|
|
727
|
+
preflightBootstrapActions(validateBootstrapPlanShape(args), context);
|
|
728
|
+
const prolog = context.prolog ?? (await context.ensureProlog?.());
|
|
729
|
+
if (!prolog)
|
|
730
|
+
throw new Error("Bootstrap apply requires a Prolog runtime");
|
|
731
|
+
await assertBootstrapPlanCurrent(args, {
|
|
732
|
+
...context,
|
|
733
|
+
prolog,
|
|
734
|
+
sourceFirst: true,
|
|
735
|
+
});
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
if (isMigrationApplyArgs(args)) {
|
|
739
|
+
validateMigrationPlanShape(args);
|
|
740
|
+
return;
|
|
712
741
|
}
|
|
742
|
+
if (isEntityDeletionApplyArgs(args)) {
|
|
743
|
+
validateEntityDeletionPlan(args);
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
validateCompilePlanShape(args);
|
|
747
|
+
}
|
|
748
|
+
async function executeBootstrapPlan(args, context, recovery = false, remainingActions, priorResults = [], onCommitted = () => undefined, carry = {}) {
|
|
749
|
+
const actions = recovery
|
|
750
|
+
? [...(remainingActions ?? args.plan.actions)]
|
|
751
|
+
: validateBootstrapPlanShape(args);
|
|
752
|
+
preflightBootstrapActions(actions, context);
|
|
753
|
+
const prolog = context.prolog ?? (await context.ensureProlog?.());
|
|
754
|
+
if (!prolog)
|
|
755
|
+
throw new Error("Bootstrap apply requires a Prolog runtime");
|
|
756
|
+
const operationContext = { ...context, prolog, sourceFirst: true };
|
|
757
|
+
const status = recovery
|
|
758
|
+
? (await executeStatus({}, operationContext)).structuredContent
|
|
759
|
+
: await assertBootstrapPlanCurrent(args, operationContext);
|
|
760
|
+
if (!status)
|
|
761
|
+
throw new Error("Bootstrap apply failed: status returned no payload");
|
|
713
762
|
const journalId = `bootstrap-${args.plan.planHash.slice(0, 16)}`;
|
|
714
763
|
const journalPath = path.join(context.workspaceRoot, ".kb", "recovery", `${journalId}.json`);
|
|
715
764
|
if (!recovery && context.fs) {
|
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
import { type Payload } from "./shared.js";
|
|
2
|
+
/**
|
|
3
|
+
* A review observation the advisor suggests for unresolved prose. The review
|
|
4
|
+
* tags (`review:ambiguity`, `review:ontology-gap`, ...) stay in `tags`: a tag
|
|
5
|
+
* is not a KB entity, so the plan carries no relationship to it, and the
|
|
6
|
+
* step explains itself in `document.body` (an observation without body
|
|
7
|
+
* context fails entity-context-missing), so kb_upsert accepts it as returned.
|
|
8
|
+
*/
|
|
2
9
|
export declare function observationPlan(payload: Payload, title: string, tags: readonly string[]): readonly Readonly<Record<string, unknown>>[];
|
|
3
10
|
//# sourceMappingURL=observation-plan.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observation-plan.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/observation-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,
|
|
1
|
+
{"version":3,"file":"observation-plan.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/observation-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAKb,MAAM,aAAa,CAAC;AAGrB;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAoB9C"}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
// implements REQ-mcp-semantic-advisor-preflight
|
|
1
|
+
import { shortHash, sourceOf, statementOf, stringValue, } from "./shared.js";
|
|
2
|
+
// implements REQ-mcp-semantic-advisor-preflight, REQ-model-predicates-plan-roundtrip
|
|
3
|
+
/**
|
|
4
|
+
* A review observation the advisor suggests for unresolved prose. The review
|
|
5
|
+
* tags (`review:ambiguity`, `review:ontology-gap`, ...) stay in `tags`: a tag
|
|
6
|
+
* is not a KB entity, so the plan carries no relationship to it, and the
|
|
7
|
+
* step explains itself in `document.body` (an observation without body
|
|
8
|
+
* context fails entity-context-missing), so kb_upsert accepts it as returned.
|
|
9
|
+
*/
|
|
3
10
|
export function observationPlan(payload, title, tags) {
|
|
4
11
|
const factId = `FACT-OBS-${shortHash(`${stringValue(payload.id)}.${title}.${statementOf(payload)}`)}`;
|
|
5
|
-
const target = tags.includes("review:ambiguity")
|
|
6
|
-
? "review:ambiguous-claim"
|
|
7
|
-
: tags.includes("review:keyword-false-positive")
|
|
8
|
-
? "review:keyword-false-positive"
|
|
9
|
-
: tags.includes("review:ontology-gap")
|
|
10
|
-
? "review:ontology-gap"
|
|
11
|
-
: tags.includes("review:nonlogical")
|
|
12
|
-
? "review:nonlogical"
|
|
13
|
-
: undefined;
|
|
14
12
|
return [
|
|
15
13
|
{
|
|
16
14
|
type: "fact",
|
|
@@ -23,9 +21,10 @@ export function observationPlan(payload, title, tags) {
|
|
|
23
21
|
text_ref: statementOf(payload),
|
|
24
22
|
tags,
|
|
25
23
|
},
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
document: {
|
|
25
|
+
body: `${title}. The semantic advisor suggested this review observation because the prose below is not safely grounded by a typed fact; it stays open until a reviewer models, rewords or dismisses the claim.\n\n> ${statementOf(payload).trim().replace(/\n/g, "\n> ")}`,
|
|
26
|
+
},
|
|
27
|
+
relationships: [],
|
|
29
28
|
},
|
|
30
29
|
];
|
|
31
30
|
}
|