@principles/host-runtime 0.10.4 → 0.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/active-principle-prompt.d.ts +23 -1
- package/dist/active-principle-prompt.js +21 -5
- package/dist/index.js +33 -2
- package/dist/prompt-activation-deliverability.d.ts +36 -3
- package/dist/prompt-activation-deliverability.js +44 -26
- package/dist/prompt-injection-projection.d.ts +23 -1
- package/dist/prompt-injection-projection.js +25 -6
- package/dist/prompt-injection-status.d.ts +20 -5
- package/dist/prompt-injection-status.js +30 -7
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ActivatedPrinciple, type PromptSelectionPolicy } from '@principles/core/runtime-v2';
|
|
1
|
+
import { type ActivatedPrinciple, type PromptBudgetResolution, type PromptSelectionPolicy } from '@principles/core/runtime-v2';
|
|
2
2
|
/** PRI-904 SPEC §10: bounded diagnostic id lists (mirrors the core selector's cap of 16). */
|
|
3
3
|
export declare const MAX_SHARED_DIAGNOSTIC_IDS = 16;
|
|
4
4
|
export interface ActivePrinciplePromptResult {
|
|
@@ -23,6 +23,20 @@ export interface ActivePrinciplePromptResult {
|
|
|
23
23
|
droppedActivationIds?: string[];
|
|
24
24
|
/** PRI-904 (bounded, max 16): activation ids that cannot fit even in an empty payload. */
|
|
25
25
|
oversizedActivationIds?: string[];
|
|
26
|
+
/**
|
|
27
|
+
* SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001: provenance of the `budget` this
|
|
28
|
+
* selection ran under (capacity source/status + the resolved context
|
|
29
|
+
* window). Present on every result; `legacy_fallback` + `unknown` means
|
|
30
|
+
* no model capacity could be confirmed and the fixed budget was used.
|
|
31
|
+
*/
|
|
32
|
+
budgetCapacitySource?: PromptBudgetResolution['capacitySource'];
|
|
33
|
+
budgetCapacityStatus?: PromptBudgetResolution['capacityStatus'];
|
|
34
|
+
budgetContextWindowTokens?: number | null;
|
|
35
|
+
budgetPolicyVersion?: PromptBudgetResolution['policyVersion'];
|
|
36
|
+
/** SPEC §7 v0.2: bounded fallback reason code; present only on legacy_fallback. */
|
|
37
|
+
budgetFallbackReason?: PromptBudgetResolution['fallbackReason'];
|
|
38
|
+
/** Non-sensitive log context (provider/model ids); never emitted to events. */
|
|
39
|
+
budgetFallbackDetail?: string;
|
|
26
40
|
}
|
|
27
41
|
export interface PromptActivationCandidates {
|
|
28
42
|
principles: ActivatedPrinciple[];
|
|
@@ -52,4 +66,12 @@ export declare function buildActivePrinciplePromptContext(input: {
|
|
|
52
66
|
* characterization baseline).
|
|
53
67
|
*/
|
|
54
68
|
roundKey?: number;
|
|
69
|
+
/**
|
|
70
|
+
* SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001 §6.1: the budget resolution for
|
|
71
|
+
* THIS request, resolved once by the entry point that holds the model
|
|
72
|
+
* facts. Absent → the resolver's no-facts default (legacy fixed 2000,
|
|
73
|
+
* capacityStatus unknown) — the historical behavior, used by callers with
|
|
74
|
+
* no model context (console projections, WorkBuddy without model facts).
|
|
75
|
+
*/
|
|
76
|
+
promptBudget?: PromptBudgetResolution;
|
|
55
77
|
}): Promise<ActivePrinciplePromptResult>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SqliteActivationStateStore, SqliteConnection, SqlitePIArtifactStore, computeFeatureFlagsFromConfig, filterPromptActivations, renderPrinciplesToDirectives, resolvePrincipleFromArtifact, resolvePromptBudget, } from '@principles/core/runtime-v2';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { escapeXml } from '@principles/core/prompt-builder';
|
|
@@ -81,13 +81,23 @@ export async function readPromptActivationCandidates(input) {
|
|
|
81
81
|
return { principles, excludedPrincipleIds, warnings, aborted: false, selfReportEnabled, abstractionLayerEnabled };
|
|
82
82
|
}
|
|
83
83
|
export async function buildActivePrinciplePromptContext(input) {
|
|
84
|
+
// One resolution per request (SPEC §6.1): the caller's pre-resolved budget
|
|
85
|
+
// or the fixed-fallback default — never a per-line constant read.
|
|
86
|
+
const promptBudget = input.promptBudget ?? resolvePromptBudget();
|
|
87
|
+
const { budgetChars } = promptBudget;
|
|
84
88
|
const { principles, excludedPrincipleIds, warnings, aborted, selfReportEnabled } = await readPromptActivationCandidates(input);
|
|
85
89
|
if (aborted) {
|
|
86
90
|
return {
|
|
87
91
|
additionalContext: '', principleIds: [], activationIds: [], artifactIds: [], warnings,
|
|
88
|
-
budget:
|
|
92
|
+
budget: budgetChars, truncated: false, excludedPrincipleIds,
|
|
89
93
|
excludedCount: excludedPrincipleIds.length, allValidatedPrinciplesExcluded: false,
|
|
90
94
|
selectionPolicy: 'legacy_fifo_prefix_v1', eligibleCount: 0,
|
|
95
|
+
budgetCapacitySource: promptBudget.capacitySource,
|
|
96
|
+
budgetCapacityStatus: promptBudget.capacityStatus,
|
|
97
|
+
budgetContextWindowTokens: promptBudget.contextWindowTokens,
|
|
98
|
+
budgetPolicyVersion: promptBudget.policyVersion,
|
|
99
|
+
...(promptBudget.fallbackReason !== undefined ? { budgetFallbackReason: promptBudget.fallbackReason } : {}),
|
|
100
|
+
...(promptBudget.fallbackDetail !== undefined ? { budgetFallbackDetail: promptBudget.fallbackDetail } : {}),
|
|
91
101
|
};
|
|
92
102
|
}
|
|
93
103
|
const included = [];
|
|
@@ -109,14 +119,14 @@ export async function buildActivePrinciplePromptContext(input) {
|
|
|
109
119
|
const droppedActivationIds = [];
|
|
110
120
|
const oversizedActivationIds = [];
|
|
111
121
|
const standaloneFits = (principle) => renderPrinciplesToDirectives([principle], new Set([principle.principleId]), { escapeFn: escapeXml, selfReportInstruction: selfReportEnabled }).length
|
|
112
|
-
<=
|
|
122
|
+
<= budgetChars;
|
|
113
123
|
const scanOrder = rotationStartIndex === undefined
|
|
114
124
|
? principles
|
|
115
125
|
: principles.slice(rotationStartIndex).concat(principles.slice(0, rotationStartIndex));
|
|
116
126
|
for (const principle of scanOrder) {
|
|
117
127
|
const candidate = [...included, principle];
|
|
118
128
|
const candidateContext = renderPrinciplesToDirectives(candidate, new Set(candidate.map((entry) => entry.principleId)), { escapeFn: escapeXml, selfReportInstruction: selfReportEnabled });
|
|
119
|
-
if (candidateContext.length >
|
|
129
|
+
if (candidateContext.length > budgetChars) {
|
|
120
130
|
if (standaloneFits(principle)) {
|
|
121
131
|
// Fits alone but not now — normal budget truncation.
|
|
122
132
|
truncated = true;
|
|
@@ -144,7 +154,7 @@ export async function buildActivePrinciplePromptContext(input) {
|
|
|
144
154
|
activationIds: included.map((principle) => principle.activationId),
|
|
145
155
|
artifactIds: included.map((principle) => principle.artifactId),
|
|
146
156
|
warnings,
|
|
147
|
-
budget:
|
|
157
|
+
budget: budgetChars,
|
|
148
158
|
truncated,
|
|
149
159
|
excludedPrincipleIds,
|
|
150
160
|
excludedCount: excludedPrincipleIds.length,
|
|
@@ -155,5 +165,11 @@ export async function buildActivePrinciplePromptContext(input) {
|
|
|
155
165
|
...(rotationStartIndex !== undefined ? { rotationStartIndex } : {}),
|
|
156
166
|
...(droppedActivationIds.length > 0 ? { droppedActivationIds } : {}),
|
|
157
167
|
...(oversizedActivationIds.length > 0 ? { oversizedActivationIds } : {}),
|
|
168
|
+
budgetCapacitySource: promptBudget.capacitySource,
|
|
169
|
+
budgetCapacityStatus: promptBudget.capacityStatus,
|
|
170
|
+
budgetContextWindowTokens: promptBudget.contextWindowTokens,
|
|
171
|
+
budgetPolicyVersion: promptBudget.policyVersion,
|
|
172
|
+
...(promptBudget.fallbackReason !== undefined ? { budgetFallbackReason: promptBudget.fallbackReason } : {}),
|
|
173
|
+
...(promptBudget.fallbackDetail !== undefined ? { budgetFallbackDetail: promptBudget.fallbackDetail } : {}),
|
|
158
174
|
};
|
|
159
175
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { isHostEvent, isHostEventResult, } from '@principles/core/host';
|
|
3
|
-
import {
|
|
3
|
+
import { getPromptModelCatalog, resolvePromptBudget } from '@principles/core/runtime-v2';
|
|
4
4
|
import { buildActivePrinciplePromptContext } from './active-principle-prompt.js';
|
|
5
5
|
import { createProductionRuleHostGate } from './production-rulehost-gate.js';
|
|
6
6
|
import { createProductionPainEvidenceHandler } from './production-pain-evidence.js';
|
|
@@ -211,6 +211,26 @@ export function createProductionHostRuntime(options = {}) {
|
|
|
211
211
|
const prompt = await buildActivePrinciplePromptContext({
|
|
212
212
|
workspaceDir: event.context.workspaceDir,
|
|
213
213
|
excludePrincipleIds: options.promptExcludePrincipleIds?.(event),
|
|
214
|
+
promptBudget: resolvePromptBudget({
|
|
215
|
+
// SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001: resolve ONCE per request
|
|
216
|
+
// from the host's own hook facts (OpenClaw effective window /
|
|
217
|
+
// Codex+WorkBuddy model id) against the installed local Pi AI
|
|
218
|
+
// catalog — no network, no LLM call. Missing/untrusted facts
|
|
219
|
+
// resolve to the legacy fixed budget with an observable reason.
|
|
220
|
+
hostCapacity: event.context.modelContext === undefined
|
|
221
|
+
? undefined
|
|
222
|
+
: {
|
|
223
|
+
contextTokenBudget: event.context.modelContext.contextTokenBudget,
|
|
224
|
+
contextWindowSource: event.context.modelContext.contextWindowSource,
|
|
225
|
+
},
|
|
226
|
+
modelIdentity: event.context.modelContext === undefined
|
|
227
|
+
? undefined
|
|
228
|
+
: {
|
|
229
|
+
providerId: event.context.modelContext.modelProviderId,
|
|
230
|
+
modelId: event.context.modelContext.modelId,
|
|
231
|
+
},
|
|
232
|
+
catalog: getPromptModelCatalog(),
|
|
233
|
+
}),
|
|
214
234
|
});
|
|
215
235
|
// PRI-750: record the injection event on the shared path with the host
|
|
216
236
|
// turn id (Codex turn_id → runId) so receipt events carry a turn-level
|
|
@@ -231,11 +251,22 @@ export function createProductionHostRuntime(options = {}) {
|
|
|
231
251
|
injectedCount: prompt.principleIds.length,
|
|
232
252
|
skippedWarnings: prompt.warnings,
|
|
233
253
|
injectedCharCount: prompt.additionalContext.length,
|
|
234
|
-
budget:
|
|
254
|
+
budget: prompt.budget,
|
|
235
255
|
...(options.hostKind === 'openclaw' || options.hostKind === 'codex' || options.hostKind === 'workbuddy' ? { hostKind: options.hostKind } : {}),
|
|
236
256
|
eventId: randomUUID(),
|
|
237
257
|
...(prompt.truncated !== undefined ? { v2Truncated: prompt.truncated } : {}),
|
|
238
258
|
...(event.context.turnId !== undefined ? { runId: event.context.turnId } : {}),
|
|
259
|
+
// SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001: budget provenance — the
|
|
260
|
+
// recorded budget is the one THIS injection actually ran under
|
|
261
|
+
// (prompt.budget), never a constant restated after the fact.
|
|
262
|
+
...(prompt.budgetPolicyVersion !== undefined ? { budgetPolicyVersion: prompt.budgetPolicyVersion } : {}),
|
|
263
|
+
...(prompt.budgetCapacitySource !== undefined ? { budgetCapacitySource: prompt.budgetCapacitySource } : {}),
|
|
264
|
+
...(prompt.budgetCapacityStatus !== undefined ? { budgetCapacityStatus: prompt.budgetCapacityStatus } : {}),
|
|
265
|
+
...(prompt.budgetContextWindowTokens != null ? { budgetContextWindowTokens: prompt.budgetContextWindowTokens } : {}),
|
|
266
|
+
// SPEC §7 v0.2: the bounded fallback reason code rides the event so
|
|
267
|
+
// operators can tell model-identity absence from catalog ambiguity
|
|
268
|
+
// etc. without touching logs. Detail stays out of events.
|
|
269
|
+
...(prompt.budgetFallbackReason !== undefined ? { budgetFallbackReason: prompt.budgetFallbackReason } : {}),
|
|
239
270
|
// PRI-904: selection diagnostics (bounded, optional). On this route
|
|
240
271
|
// the policy is legacy_fifo_prefix_v1 and NO rotation provenance is
|
|
241
272
|
// emitted — a fair claim would be untrue here (see above).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ActivatedPrinciple } from '@principles/core/runtime-v2';
|
|
1
|
+
import { type ActivatedPrinciple, type PromptBudgetTierFit } from '@principles/core/runtime-v2';
|
|
2
2
|
import { PROMPT_INJECTION_UNIT, type PromptInjectionBudgetScope, type PromptInjectionRouteDecision, type PromptInjectionRouteName, type PromptInjectionTargetHost } from './prompt-injection-projection.js';
|
|
3
3
|
/**
|
|
4
4
|
* SPEC PD_PROMPT_CAPACITY_V1 R-B2: ONE route-aware single-artifact capacity
|
|
@@ -25,18 +25,46 @@ export type PromptArtifactDeliverability = {
|
|
|
25
25
|
route: PromptInjectionRouteName;
|
|
26
26
|
hostKind?: PromptInjectionTargetHost;
|
|
27
27
|
basis?: PromptInjectionRouteDecision['basis'];
|
|
28
|
+
/**
|
|
29
|
+
* The budget this judgment is binding against: the MINIMUM supported
|
|
30
|
+
* tier — a deliverable here fits under EVERY supported budget
|
|
31
|
+
* (SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001 §6.3), so the strictest tier is
|
|
32
|
+
* the honest evidence.
|
|
33
|
+
*/
|
|
28
34
|
budget: number;
|
|
35
|
+
budgetMinChars: number;
|
|
36
|
+
budgetMaxChars: number;
|
|
29
37
|
/** Single-item cost in UTF-16 code units under the bound route's serializer. */
|
|
30
38
|
costChars: number;
|
|
31
39
|
budgetScope: PromptInjectionBudgetScope;
|
|
32
40
|
unit: typeof PROMPT_INJECTION_UNIT;
|
|
41
|
+
} | {
|
|
42
|
+
/**
|
|
43
|
+
* SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001 §6.3: the artifact fits under
|
|
44
|
+
* SOME supported budgets but not all — whether it injects depends on the
|
|
45
|
+
* runtime model's context window. NOT a promise of injection and NOT a
|
|
46
|
+
* permanent refusal; approval flow proceeds unchanged.
|
|
47
|
+
*/
|
|
48
|
+
status: 'model_dependent';
|
|
49
|
+
route: PromptInjectionRouteName;
|
|
50
|
+
hostKind?: PromptInjectionTargetHost;
|
|
51
|
+
basis?: PromptInjectionRouteDecision['basis'];
|
|
52
|
+
budgetMinChars: number;
|
|
53
|
+
budgetMaxChars: number;
|
|
54
|
+
costChars: number;
|
|
55
|
+
budgetScope: PromptInjectionBudgetScope;
|
|
56
|
+
unit: typeof PROMPT_INJECTION_UNIT;
|
|
57
|
+
nextAction: string;
|
|
33
58
|
} | {
|
|
34
59
|
status: 'undeliverable';
|
|
35
60
|
reason: 'single_item_exceeds_budget';
|
|
36
61
|
route: PromptInjectionRouteName;
|
|
37
62
|
hostKind?: PromptInjectionTargetHost;
|
|
38
63
|
basis?: PromptInjectionRouteDecision['basis'];
|
|
64
|
+
/** The budget this judgment is binding against: the MAXIMUM supported tier. */
|
|
39
65
|
budget: number;
|
|
66
|
+
budgetMinChars: number;
|
|
67
|
+
budgetMaxChars: number;
|
|
40
68
|
costChars: number;
|
|
41
69
|
overByChars: number;
|
|
42
70
|
budgetScope: PromptInjectionBudgetScope;
|
|
@@ -47,10 +75,10 @@ export type PromptArtifactDeliverability = {
|
|
|
47
75
|
/** Stable machine-readable reason (route facts or artifact content unresolvable). */
|
|
48
76
|
reason: string;
|
|
49
77
|
nextAction: string;
|
|
50
|
-
/** Route-unconfirmed case: per-host single-item fit so the UI can show both. */
|
|
78
|
+
/** Route-unconfirmed case: per-host single-item tier fit so the UI can show both. */
|
|
51
79
|
perHost?: readonly {
|
|
52
80
|
hostKind: PromptInjectionTargetHost;
|
|
53
|
-
|
|
81
|
+
tierFit: PromptBudgetTierFit;
|
|
54
82
|
costChars: number;
|
|
55
83
|
}[];
|
|
56
84
|
};
|
|
@@ -72,11 +100,16 @@ export declare function resolvePromptCandidatePrinciple(artifact: PromptDelivera
|
|
|
72
100
|
* lines). For an entry that does NOT fit, trimToBudget returns only the
|
|
73
101
|
* header line, so the would-be cost is reconstructed from the header line it
|
|
74
102
|
* DID return plus the real entry line (same format authority, listEntryLine).
|
|
103
|
+
*
|
|
104
|
+
* The budget parameter defaults to the legacy fixed budget: approval-time
|
|
105
|
+
* callers hold no runtime model facts, and SPEC §6.3 requires the fixed
|
|
106
|
+
* fallback — never an invented capacity — when none can be confirmed.
|
|
75
107
|
*/
|
|
76
108
|
export declare function computePromptSingleItemFit(input: {
|
|
77
109
|
principle: ActivatedPrinciple;
|
|
78
110
|
route: PromptInjectionRouteName;
|
|
79
111
|
selfReportEnabled: boolean;
|
|
112
|
+
budget?: number;
|
|
80
113
|
}): {
|
|
81
114
|
fits: boolean;
|
|
82
115
|
costChars: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { PROMPT_BUDGET_FALLBACK_CHARS, PROMPT_BUDGET_MAX_CHARS, PROMPT_BUDGET_MIN_CHARS, SqliteConnection, SqlitePIArtifactStore, classifySingleItemBudgetTier, computeFeatureFlagsFromConfig, listEntryLine, renderPrinciplesToDirectives, resolvePrincipleFromArtifact, trimToBudget, } from '@principles/core/runtime-v2';
|
|
4
4
|
import { escapeXml } from '@principles/core/prompt-builder';
|
|
5
5
|
import { loadPdConfigForPlugin } from './pd-config.js';
|
|
6
6
|
import { PROMPT_INJECTION_TARGET_HOSTS, PROMPT_INJECTION_UNIT, promptRouteForHost, resolvePromptInjectionRouteDecision, } from './prompt-injection-projection.js';
|
|
@@ -38,13 +38,18 @@ function selfReportEnabledFor(workspaceDir) {
|
|
|
38
38
|
* lines). For an entry that does NOT fit, trimToBudget returns only the
|
|
39
39
|
* header line, so the would-be cost is reconstructed from the header line it
|
|
40
40
|
* DID return plus the real entry line (same format authority, listEntryLine).
|
|
41
|
+
*
|
|
42
|
+
* The budget parameter defaults to the legacy fixed budget: approval-time
|
|
43
|
+
* callers hold no runtime model facts, and SPEC §6.3 requires the fixed
|
|
44
|
+
* fallback — never an invented capacity — when none can be confirmed.
|
|
41
45
|
*/
|
|
42
46
|
export function computePromptSingleItemFit(input) {
|
|
47
|
+
const budget = input.budget ?? PROMPT_BUDGET_FALLBACK_CHARS;
|
|
43
48
|
if (input.route === 'shared_render') {
|
|
44
49
|
const render = renderPrinciplesToDirectives([input.principle], new Set([input.principle.principleId]), { escapeFn: escapeXml, selfReportInstruction: input.selfReportEnabled });
|
|
45
|
-
return { fits: render.length <=
|
|
50
|
+
return { fits: render.length <= budget, costChars: render.length };
|
|
46
51
|
}
|
|
47
|
-
const trimmed = trimToBudget([input.principle],
|
|
52
|
+
const trimmed = trimToBudget([input.principle], budget, escapeXml);
|
|
48
53
|
const fits = trimmed.injectedIds.has(input.principle.principleId);
|
|
49
54
|
const costChars = trimmed.lines.length > 1
|
|
50
55
|
? trimmed.lines.join('\n').length
|
|
@@ -52,6 +57,7 @@ export function computePromptSingleItemFit(input) {
|
|
|
52
57
|
return { fits, costChars };
|
|
53
58
|
}
|
|
54
59
|
const UNDELIVERABLE_NEXT_ACTION = 'shorten the principle statement and resubmit, or use the activations page "modify to injectable version" entry to create a replacement artifact (the approval facts are preserved)';
|
|
60
|
+
const MODEL_DEPENDENT_NEXT_ACTION = 'this principle fits the injection budget only on models with a larger context window; it may be excluded at runtime on smaller-context models — the approval itself is unaffected';
|
|
55
61
|
/**
|
|
56
62
|
* Precheck one artifact against the workspace's effective injection route.
|
|
57
63
|
* Pure read — no state mutation, safe to call before any governance write.
|
|
@@ -78,7 +84,7 @@ export async function checkPromptArtifactDeliverability(input) {
|
|
|
78
84
|
targetHost: input.targetHost,
|
|
79
85
|
});
|
|
80
86
|
if (decision.status === 'confirmed' && decision.route !== undefined) {
|
|
81
|
-
const {
|
|
87
|
+
const { costChars } = computePromptSingleItemFit({
|
|
82
88
|
principle: resolved.principle,
|
|
83
89
|
route: decision.route,
|
|
84
90
|
selfReportEnabled,
|
|
@@ -86,44 +92,56 @@ export async function checkPromptArtifactDeliverability(input) {
|
|
|
86
92
|
const budgetScope = decision.route === 'shared_render'
|
|
87
93
|
? 'full_directive_context'
|
|
88
94
|
: 'selected_lines';
|
|
89
|
-
|
|
95
|
+
const shared = {
|
|
96
|
+
route: decision.route,
|
|
97
|
+
...(decision.hostKind !== undefined ? { hostKind: decision.hostKind } : {}),
|
|
98
|
+
...(decision.basis !== undefined ? { basis: decision.basis } : {}),
|
|
99
|
+
budgetMinChars: PROMPT_BUDGET_MIN_CHARS,
|
|
100
|
+
budgetMaxChars: PROMPT_BUDGET_MAX_CHARS,
|
|
101
|
+
costChars,
|
|
102
|
+
budgetScope,
|
|
103
|
+
unit: PROMPT_INJECTION_UNIT,
|
|
104
|
+
};
|
|
105
|
+
// SPEC §6.3: approval time holds no runtime model identity — classify
|
|
106
|
+
// against the SUPPORTED budget range instead of pretending to know the
|
|
107
|
+
// executing model's window.
|
|
108
|
+
const tierFit = classifySingleItemBudgetTier(costChars);
|
|
109
|
+
if (tierFit === 'fits_all_tiers') {
|
|
90
110
|
return {
|
|
91
111
|
status: 'deliverable',
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
...shared,
|
|
113
|
+
budget: PROMPT_BUDGET_MIN_CHARS,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (tierFit === 'model_dependent') {
|
|
117
|
+
return {
|
|
118
|
+
status: 'model_dependent',
|
|
119
|
+
...shared,
|
|
120
|
+
nextAction: MODEL_DEPENDENT_NEXT_ACTION,
|
|
99
121
|
};
|
|
100
122
|
}
|
|
101
123
|
return {
|
|
102
124
|
status: 'undeliverable',
|
|
125
|
+
...shared,
|
|
103
126
|
reason: 'single_item_exceeds_budget',
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
...(decision.basis !== undefined ? { basis: decision.basis } : {}),
|
|
107
|
-
budget: RUNTIME_V2_PRINCIPLE_BUDGET,
|
|
108
|
-
costChars,
|
|
109
|
-
overByChars: costChars - RUNTIME_V2_PRINCIPLE_BUDGET,
|
|
110
|
-
budgetScope,
|
|
111
|
-
unit: PROMPT_INJECTION_UNIT,
|
|
127
|
+
budget: PROMPT_BUDGET_MAX_CHARS,
|
|
128
|
+
overByChars: costChars - PROMPT_BUDGET_MAX_CHARS,
|
|
112
129
|
nextAction: UNDELIVERABLE_NEXT_ACTION,
|
|
113
130
|
};
|
|
114
131
|
}
|
|
115
|
-
// Route unconfirmed: report per-host fit for every standard host
|
|
116
|
-
// guessing (R-A1) — the write gate refuses, the UI can show
|
|
117
|
-
// Roster derives from the single SSoT list (review P3-1: a
|
|
118
|
-
// two-host array dropped WorkBuddy from unconfirmed
|
|
132
|
+
// Route unconfirmed: report per-host tier fit for every standard host
|
|
133
|
+
// instead of guessing (R-A1) — the write gate refuses, the UI can show
|
|
134
|
+
// both facts. Roster derives from the single SSoT list (review P3-1: a
|
|
135
|
+
// hand-typed two-host array dropped WorkBuddy from unconfirmed
|
|
136
|
+
// deliverability reports).
|
|
119
137
|
const perHost = PROMPT_INJECTION_TARGET_HOSTS.map((hostKind) => {
|
|
120
138
|
const route = promptRouteForHost(hostKind, decision.flagEnabled);
|
|
121
|
-
const {
|
|
139
|
+
const { costChars } = computePromptSingleItemFit({
|
|
122
140
|
principle: resolved.principle,
|
|
123
141
|
route,
|
|
124
142
|
selfReportEnabled,
|
|
125
143
|
});
|
|
126
|
-
return { hostKind,
|
|
144
|
+
return { hostKind, tierFit: classifySingleItemBudgetTier(costChars), costChars };
|
|
127
145
|
});
|
|
128
146
|
return {
|
|
129
147
|
status: 'unconfirmed',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type PromptSelectionPolicy } from '@principles/core/runtime-v2';
|
|
1
|
+
import { type PromptBudgetResolution, type PromptSelectionPolicy } from '@principles/core/runtime-v2';
|
|
2
2
|
/** Hosts with a production prompt-injection path today (shared GovernanceHostKind boundary). */
|
|
3
3
|
export type PromptInjectionTargetHost = 'openclaw' | 'codex' | 'workbuddy';
|
|
4
4
|
/** Single host roster (review P2): every consumer derives from this list, so a
|
|
@@ -140,6 +140,20 @@ export interface PromptInjectionProjection {
|
|
|
140
140
|
* route (where `usedChars` already IS the full render).
|
|
141
141
|
*/
|
|
142
142
|
fullRenderChars?: number;
|
|
143
|
+
/**
|
|
144
|
+
* SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001 §6.1/§7: provenance of `budget` —
|
|
145
|
+
* the same policy/resolution the real injection runs, so consumers can
|
|
146
|
+
* tell "runtime capacity confirmed" apart from "fixed-budget fallback"
|
|
147
|
+
* instead of assuming the forecast matches every model.
|
|
148
|
+
*/
|
|
149
|
+
budgetCapacitySource?: PromptBudgetResolution['capacitySource'];
|
|
150
|
+
budgetCapacityStatus?: PromptBudgetResolution['capacityStatus'];
|
|
151
|
+
budgetContextWindowTokens?: number | null;
|
|
152
|
+
budgetPolicyVersion?: PromptBudgetResolution['policyVersion'];
|
|
153
|
+
/** SPEC §7 v0.2: bounded fallback reason code; present only on legacy_fallback. */
|
|
154
|
+
budgetFallbackReason?: PromptBudgetResolution['fallbackReason'];
|
|
155
|
+
/** Non-sensitive log context; never emitted to events. */
|
|
156
|
+
budgetFallbackDetail?: string;
|
|
143
157
|
}
|
|
144
158
|
/**
|
|
145
159
|
* PR #1844 follow-up: forecast the prompt-injection budget from the SAME
|
|
@@ -186,6 +200,14 @@ export declare function buildLivePromptInjectionProjection(input: {
|
|
|
186
200
|
roundKey?: number;
|
|
187
201
|
/** AC-01: explicit route binding — 'codex'/'workbuddy' always shared, 'openclaw' by flag. */
|
|
188
202
|
targetHost?: PromptInjectionTargetHost;
|
|
203
|
+
/**
|
|
204
|
+
* SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001 §6.1: budget resolution this
|
|
205
|
+
* projection must run under. Absent → the fixed-fallback default (the
|
|
206
|
+
* honest "no runtime capacity confirmed" policy), NOT a silent second
|
|
207
|
+
* policy. Callers holding live model facts (the plugin hook) pass the
|
|
208
|
+
* SAME resolution the injection uses.
|
|
209
|
+
*/
|
|
210
|
+
promptBudget?: PromptBudgetResolution;
|
|
189
211
|
}): Promise<PromptInjectionProjection>;
|
|
190
212
|
/**
|
|
191
213
|
* AC-01/R-A1: the host-aware entry every console/CLI consumer should use.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { computeFeatureFlagsFromConfig, renderPrinciplesToDirectives, resolvePromptBudget, trimToBudget, } from '@principles/core/runtime-v2';
|
|
2
2
|
import { escapeXml } from '@principles/core/prompt-builder';
|
|
3
3
|
import { loadPdConfigForPlugin } from './pd-config.js';
|
|
4
4
|
import { buildActivePrinciplePromptContext, readPromptActivationCandidates, MAX_SHARED_DIAGNOSTIC_IDS } from './active-principle-prompt.js';
|
|
@@ -223,6 +223,7 @@ function isDiagnosticCapHit(ids) {
|
|
|
223
223
|
* `selectionPolicy` on the result.
|
|
224
224
|
*/
|
|
225
225
|
export async function buildLivePromptInjectionProjection(input) {
|
|
226
|
+
const promptBudget = input.promptBudget ?? resolvePromptBudget();
|
|
226
227
|
const flagEnabled = computeFeatureFlagsFromConfig(loadPdConfigForPlugin(input.workspaceDir).effective).flags.abstraction_layer_v1?.enabled === true;
|
|
227
228
|
// Route face follows THE one route formula (review P2-2: a re-typed
|
|
228
229
|
// codex-only ternary forecast WorkBuddy as legacy_trim while its adapter
|
|
@@ -232,7 +233,7 @@ export async function buildLivePromptInjectionProjection(input) {
|
|
|
232
233
|
? flagEnabled
|
|
233
234
|
: promptRouteForHost(input.targetHost, flagEnabled) === 'shared_render';
|
|
234
235
|
if (sharedRoute) {
|
|
235
|
-
const context = await buildActivePrinciplePromptContext(input);
|
|
236
|
+
const context = await buildActivePrinciplePromptContext({ ...input, promptBudget });
|
|
236
237
|
const oversized = context.oversizedActivationIds ?? [];
|
|
237
238
|
const dropped = context.droppedActivationIds ?? [];
|
|
238
239
|
return {
|
|
@@ -256,6 +257,12 @@ export async function buildLivePromptInjectionProjection(input) {
|
|
|
256
257
|
droppedActivationIds: dropped,
|
|
257
258
|
oversizedDiagnosticTruncated: isDiagnosticCapHit(oversized),
|
|
258
259
|
droppedDiagnosticTruncated: isDiagnosticCapHit(dropped),
|
|
260
|
+
budgetCapacitySource: context.budgetCapacitySource,
|
|
261
|
+
budgetCapacityStatus: context.budgetCapacityStatus,
|
|
262
|
+
budgetContextWindowTokens: context.budgetContextWindowTokens,
|
|
263
|
+
budgetPolicyVersion: context.budgetPolicyVersion,
|
|
264
|
+
...(context.budgetFallbackReason !== undefined ? { budgetFallbackReason: context.budgetFallbackReason } : {}),
|
|
265
|
+
...(context.budgetFallbackDetail !== undefined ? { budgetFallbackDetail: context.budgetFallbackDetail } : {}),
|
|
259
266
|
};
|
|
260
267
|
}
|
|
261
268
|
const candidates = await readPromptActivationCandidates(input);
|
|
@@ -263,7 +270,7 @@ export async function buildLivePromptInjectionProjection(input) {
|
|
|
263
270
|
if (candidates.aborted || principles.length === 0) {
|
|
264
271
|
return {
|
|
265
272
|
route: 'legacy_trim',
|
|
266
|
-
budget:
|
|
273
|
+
budget: promptBudget.budgetChars,
|
|
267
274
|
usedChars: 0,
|
|
268
275
|
truncated: false,
|
|
269
276
|
injectedPrincipleIds: [],
|
|
@@ -279,11 +286,17 @@ export async function buildLivePromptInjectionProjection(input) {
|
|
|
279
286
|
droppedActivationIds: [],
|
|
280
287
|
oversizedDiagnosticTruncated: false,
|
|
281
288
|
droppedDiagnosticTruncated: false,
|
|
289
|
+
budgetCapacitySource: promptBudget.capacitySource,
|
|
290
|
+
budgetCapacityStatus: promptBudget.capacityStatus,
|
|
291
|
+
budgetContextWindowTokens: promptBudget.contextWindowTokens,
|
|
292
|
+
budgetPolicyVersion: promptBudget.policyVersion,
|
|
293
|
+
...(promptBudget.fallbackReason !== undefined ? { budgetFallbackReason: promptBudget.fallbackReason } : {}),
|
|
294
|
+
...(promptBudget.fallbackDetail !== undefined ? { budgetFallbackDetail: promptBudget.fallbackDetail } : {}),
|
|
282
295
|
};
|
|
283
296
|
}
|
|
284
297
|
// PR-1894: pass the caller's round key so the forecast runs the SAME
|
|
285
298
|
// packing policy production runs this turn.
|
|
286
|
-
const trimmed = trimToBudget(principles,
|
|
299
|
+
const trimmed = trimToBudget(principles, promptBudget.budgetChars, escapeXml, input.roundKey);
|
|
287
300
|
const injected = principles.filter((p) => trimmed.injectedIds.has(p.principleId));
|
|
288
301
|
// PR-1894: the legacy_trim route IS the OpenClaw plugin-local route, which
|
|
289
302
|
// rotates on every recorded user turn (PRI-904). Reachability is therefore
|
|
@@ -291,11 +304,11 @@ export async function buildLivePromptInjectionProjection(input) {
|
|
|
291
304
|
// round key — a console without a session key must still be able to tell
|
|
292
305
|
// "queued behind rotation" apart from "structurally starved", otherwise it
|
|
293
306
|
// keeps telling the Owner to deactivate healthy principles.
|
|
294
|
-
const eventuallyInjectedActivationIds = collectReachableActivationIds(principles,
|
|
307
|
+
const eventuallyInjectedActivationIds = collectReachableActivationIds(principles, promptBudget.budgetChars);
|
|
295
308
|
const fullRenderChars = renderPrinciplesToDirectives(injected, trimmed.injectedIds, { escapeFn: escapeXml, selfReportInstruction: candidates.selfReportEnabled }).length;
|
|
296
309
|
return {
|
|
297
310
|
route: 'legacy_trim',
|
|
298
|
-
budget:
|
|
311
|
+
budget: promptBudget.budgetChars,
|
|
299
312
|
usedChars: trimmed.lines.join('\n').length,
|
|
300
313
|
truncated: trimmed.truncated,
|
|
301
314
|
injectedPrincipleIds: [...trimmed.injectedIds],
|
|
@@ -312,6 +325,12 @@ export async function buildLivePromptInjectionProjection(input) {
|
|
|
312
325
|
oversizedDiagnosticTruncated: isDiagnosticCapHit(trimmed.oversizedActivationIds),
|
|
313
326
|
droppedDiagnosticTruncated: isDiagnosticCapHit(trimmed.droppedActivationIds),
|
|
314
327
|
...(injected.length > 0 ? { fullRenderChars } : {}),
|
|
328
|
+
budgetCapacitySource: promptBudget.capacitySource,
|
|
329
|
+
budgetCapacityStatus: promptBudget.capacityStatus,
|
|
330
|
+
budgetContextWindowTokens: promptBudget.contextWindowTokens,
|
|
331
|
+
budgetPolicyVersion: promptBudget.policyVersion,
|
|
332
|
+
...(promptBudget.fallbackReason !== undefined ? { budgetFallbackReason: promptBudget.fallbackReason } : {}),
|
|
333
|
+
...(promptBudget.fallbackDetail !== undefined ? { budgetFallbackDetail: promptBudget.fallbackDetail } : {}),
|
|
315
334
|
};
|
|
316
335
|
}
|
|
317
336
|
export async function resolveLivePromptInjectionProjection(input) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type PromptBudgetTierFit } from '@principles/core/runtime-v2';
|
|
1
2
|
import { type PromptInjectionBudgetScope, type PromptInjectionRouteDecision, type PromptInjectionRouteName, type PromptInjectionTargetHost } from './prompt-injection-projection.js';
|
|
2
3
|
/**
|
|
3
4
|
* SPEC PD_PROMPT_CAPACITY_V1 R-A3: per-live-activation injection status for
|
|
@@ -9,25 +10,39 @@ import { type PromptInjectionBudgetScope, type PromptInjectionRouteDecision, typ
|
|
|
9
10
|
* `route_unconfirmed` surfaces AC-01's honest unknown instead of a guess.
|
|
10
11
|
* No compliance/遵守 counts are produced here — absence of injection logs is
|
|
11
12
|
* NOT reported as "zero compliance" (AC-12 boundary).
|
|
13
|
+
*
|
|
14
|
+
* SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001: "oversized" now means the entry
|
|
15
|
+
* exceeds the MAXIMUM supported budget (never injectable on any supported
|
|
16
|
+
* model); a row that misses the CURRENT projection budget but fits within
|
|
17
|
+
* the supported [min, max] range is `model_dependent` — whether it injects
|
|
18
|
+
* depends on the runtime model's context window, which this surface cannot
|
|
19
|
+
* see. Budget figures come from the projection's resolution (legacy
|
|
20
|
+
* fallback when no runtime capacity is confirmed), never a bare constant.
|
|
12
21
|
*/
|
|
13
|
-
export type PromptActivationInjectionStatusKind = 'injectable' | 'oversized' | 'window_excluded' | 'resolution_failed' | 'route_unconfirmed';
|
|
22
|
+
export type PromptActivationInjectionStatusKind = 'injectable' | 'oversized' | 'model_dependent' | 'window_excluded' | 'resolution_failed' | 'route_unconfirmed';
|
|
14
23
|
export interface PromptActivationInjectionStatus {
|
|
15
24
|
activationId: string;
|
|
16
25
|
principleId?: string;
|
|
17
26
|
status: PromptActivationInjectionStatusKind;
|
|
18
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Present for injectable/window_excluded/oversized/model_dependent under a
|
|
29
|
+
* confirmed route. For model_dependent rows it keeps the POSITIVE window
|
|
30
|
+
* fact: true = the entry fits THIS surface's (usually fallback) projection
|
|
31
|
+
* window, but still exceeds the measured floor — a smaller-context runtime
|
|
32
|
+
* model would exclude it.
|
|
33
|
+
*/
|
|
19
34
|
inCurrentWindow?: boolean;
|
|
20
35
|
/** Present when the single-item cost was computable. */
|
|
21
36
|
costChars?: number;
|
|
22
37
|
budget?: number;
|
|
23
38
|
budgetScope?: PromptInjectionBudgetScope;
|
|
24
39
|
route?: PromptInjectionRouteName;
|
|
25
|
-
/** Present for resolution_failed / route_unconfirmed (structured reason). */
|
|
40
|
+
/** Present for resolution_failed / route_unconfirmed / model_dependent (structured reason). */
|
|
26
41
|
reason?: string;
|
|
27
|
-
/** Present for route_unconfirmed: per-host single-item fit facts. */
|
|
42
|
+
/** Present for route_unconfirmed: per-host single-item tier fit facts. */
|
|
28
43
|
perHostFits?: readonly {
|
|
29
44
|
hostKind: PromptInjectionTargetHost;
|
|
30
|
-
|
|
45
|
+
tierFit: PromptBudgetTierFit;
|
|
31
46
|
}[];
|
|
32
47
|
}
|
|
33
48
|
export interface PromptActivationInjectionStatusReport {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { PROMPT_BUDGET_MAX_CHARS, PROMPT_BUDGET_MIN_CHARS, SqliteActivationStateStore, SqliteConnection, SqlitePIArtifactStore, classifySingleItemBudgetTier, computeFeatureFlagsFromConfig, filterPromptActivations, resolvePrincipleFromArtifact, } from '@principles/core/runtime-v2';
|
|
4
4
|
import { loadPdConfigForPlugin } from './pd-config.js';
|
|
5
5
|
import { computePromptSingleItemFit } from './prompt-activation-deliverability.js';
|
|
6
6
|
import { PROMPT_INJECTION_TARGET_HOSTS, buildLivePromptInjectionProjection, promptRouteForHost, resolvePromptInjectionRouteDecision, } from './prompt-injection-projection.js';
|
|
@@ -86,12 +86,12 @@ export async function readPromptActivationInjectionStatuses(input) {
|
|
|
86
86
|
}
|
|
87
87
|
const perHostFits = PROMPT_INJECTION_TARGET_HOSTS.map((hostKind) => {
|
|
88
88
|
const hostRoute = promptRouteForHost(hostKind, route.flagEnabled);
|
|
89
|
-
const {
|
|
89
|
+
const { costChars } = computePromptSingleItemFit({
|
|
90
90
|
principle: { principleId: row.principleId, text: row.text, artifactId: '', activationId: row.activationId },
|
|
91
91
|
route: hostRoute,
|
|
92
92
|
selfReportEnabled,
|
|
93
93
|
});
|
|
94
|
-
return { hostKind,
|
|
94
|
+
return { hostKind, tierFit: classifySingleItemBudgetTier(costChars) };
|
|
95
95
|
});
|
|
96
96
|
return {
|
|
97
97
|
activationId: row.activationId,
|
|
@@ -116,20 +116,43 @@ export async function readPromptActivationInjectionStatuses(input) {
|
|
|
116
116
|
principle: { principleId: row.principleId, text: row.text, artifactId: '', activationId: row.activationId },
|
|
117
117
|
route: projection.route,
|
|
118
118
|
selfReportEnabled,
|
|
119
|
+
budget: projection.budget,
|
|
119
120
|
});
|
|
120
121
|
const inCurrentWindow = projection.injectedActivationIds.includes(row.activationId);
|
|
121
122
|
const budgetScope = projection.budgetScope;
|
|
122
|
-
|
|
123
|
+
const serialization = projection.route === 'shared_render' ? 'full directive render' : 'list entry';
|
|
124
|
+
// Tier verdict FIRST (SPEC §6.3): the projection budget on this surface
|
|
125
|
+
// is usually the fixed fallback (2000) — the console holds no runtime
|
|
126
|
+
// model facts. An entry in (MIN, fallback] fits THAT estimate and may
|
|
127
|
+
// even sit in the current window, but it exceeds the measured floor, so
|
|
128
|
+
// on a 32K/64K model (budget = floor) it would NOT inject. Reporting it
|
|
129
|
+
// as an unconditional `injectable` would contradict the approval-time
|
|
130
|
+
// `model_dependent` verdict for the very same artifact.
|
|
131
|
+
const tierFit = classifySingleItemBudgetTier(costChars);
|
|
132
|
+
if (tierFit === 'exceeds_max_tier') {
|
|
123
133
|
return {
|
|
124
134
|
activationId: row.activationId,
|
|
125
135
|
principleId: row.principleId,
|
|
126
136
|
status: 'oversized',
|
|
127
137
|
inCurrentWindow: false,
|
|
128
138
|
costChars,
|
|
129
|
-
budget:
|
|
139
|
+
budget: projection.budget,
|
|
130
140
|
budgetScope,
|
|
131
141
|
route: projection.route,
|
|
132
|
-
reason: `single_item_exceeds_budget: this principle's own entry is ${costChars} chars > ${
|
|
142
|
+
reason: `single_item_exceeds_budget: this principle's own entry is ${costChars} chars > the ${PROMPT_BUDGET_MAX_CHARS}-char maximum supported budget under the ${serialization} serialization`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (tierFit === 'model_dependent') {
|
|
146
|
+
return {
|
|
147
|
+
activationId: row.activationId,
|
|
148
|
+
principleId: row.principleId,
|
|
149
|
+
status: 'model_dependent',
|
|
150
|
+
inCurrentWindow,
|
|
151
|
+
costChars,
|
|
152
|
+
budget: projection.budget,
|
|
153
|
+
budgetScope,
|
|
154
|
+
route: projection.route,
|
|
155
|
+
reason: `model_dependent_capacity: this principle's own entry is ${costChars} chars — above the ${PROMPT_BUDGET_MIN_CHARS}-char measured floor, so smaller-context models exclude it${fits ? ' even though it fits this surface\'s fallback-budget estimate' : ''}; injection depends on the runtime model`,
|
|
133
156
|
};
|
|
134
157
|
}
|
|
135
158
|
return {
|
|
@@ -138,7 +161,7 @@ export async function readPromptActivationInjectionStatuses(input) {
|
|
|
138
161
|
status: inCurrentWindow ? 'injectable' : 'window_excluded',
|
|
139
162
|
inCurrentWindow,
|
|
140
163
|
costChars,
|
|
141
|
-
budget:
|
|
164
|
+
budget: projection.budget,
|
|
142
165
|
budgetScope,
|
|
143
166
|
route: projection.route,
|
|
144
167
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@principles/host-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Shared host-neutral orchestration for Principles Disciple MVP-Core hook paths.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"lint": "eslint \"src/**/*.ts\""
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@principles/core": "^1.
|
|
34
|
+
"@principles/core": "^1.295.0",
|
|
35
35
|
"@principles/install-layout": "^0.4.0",
|
|
36
36
|
"better-sqlite3": "^13.0.3",
|
|
37
37
|
"js-yaml": "^5.4.3"
|