@principles/host-runtime 0.12.2 → 0.13.1
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/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { isHostEvent, isHostEventResult, } from '@principles/core/host';
|
|
3
|
-
import { getPromptModelCatalog, resolvePromptBudget } from '@principles/core/runtime-v2';
|
|
3
|
+
import { getPromptModelCatalog, operatorDeclaredContextWindow, resolvePromptBudget } from '@principles/core/runtime-v2';
|
|
4
|
+
import { loadPdConfigForPlugin } from './pd-config.js';
|
|
4
5
|
import { buildActivePrinciplePromptContext } from './active-principle-prompt.js';
|
|
5
6
|
import { createProductionRuleHostGate } from './production-rulehost-gate.js';
|
|
6
7
|
import { createProductionPainEvidenceHandler } from './production-pain-evidence.js';
|
|
@@ -212,6 +213,19 @@ export function createProductionHostRuntime(options = {}) {
|
|
|
212
213
|
// reports `legacy_fifo_prefix_v1` honestly. The selector's fair-rotation
|
|
213
214
|
// capability is retained and stays reachable for callers that DO hold a
|
|
214
215
|
// legitimate advancing round authority.
|
|
216
|
+
// PRI-1020: the Owner's declared window (.pd/config.yaml promptBudget)
|
|
217
|
+
// is tier 0 of the budget chain — resolved per host and fed into the
|
|
218
|
+
// SAME single resolver below. One extra sync config read per prompt
|
|
219
|
+
// build (the candidates reader loads it independently): deliberate, so
|
|
220
|
+
// a config flip applies on the next turn with no cache to invalidate.
|
|
221
|
+
// Malformed config degrades to defaults (no declaration) and is already
|
|
222
|
+
// surfaced as config_invalid warnings by readPromptActivationCandidates.
|
|
223
|
+
const promptBudgetHostKind = options.hostKind === 'openclaw' || options.hostKind === 'codex' || options.hostKind === 'workbuddy'
|
|
224
|
+
? options.hostKind
|
|
225
|
+
: undefined;
|
|
226
|
+
const declaredWindow = promptBudgetHostKind === undefined
|
|
227
|
+
? undefined
|
|
228
|
+
: operatorDeclaredContextWindow(loadPdConfigForPlugin(event.context.workspaceDir).effective.config.promptBudget, promptBudgetHostKind);
|
|
215
229
|
const prompt = await buildActivePrinciplePromptContext({
|
|
216
230
|
workspaceDir: event.context.workspaceDir,
|
|
217
231
|
excludePrincipleIds: options.promptExcludePrincipleIds?.(event),
|
|
@@ -221,6 +235,8 @@ export function createProductionHostRuntime(options = {}) {
|
|
|
221
235
|
// Codex+WorkBuddy model id) against the installed local Pi AI
|
|
222
236
|
// catalog — no network, no LLM call. Missing/untrusted facts
|
|
223
237
|
// resolve to the legacy fixed budget with an observable reason.
|
|
238
|
+
// PRI-1020: an Owner declaration outranks all of these (tier 0).
|
|
239
|
+
...(declaredWindow !== undefined ? { operatorDeclared: { contextWindowTokens: declaredWindow } } : {}),
|
|
224
240
|
hostCapacity: event.context.modelContext === undefined
|
|
225
241
|
? undefined
|
|
226
242
|
: {
|
|
@@ -701,6 +701,10 @@ export async function runInternalizationConsumerCycle(workspaceDir, ports) {
|
|
|
701
701
|
// identity on the live production chain. listForCandidate reads
|
|
702
702
|
// the ledger from disk per call — no cross-cycle staleness.
|
|
703
703
|
ledgerIdentity: {
|
|
704
|
+
resolveForCandidate: async (candidateId) => {
|
|
705
|
+
const candidate = await stateManager.getCandidate(candidateId);
|
|
706
|
+
return new PrincipleTreeLedgerAdapter({ stateDir: `${workspaceDir}/.state` }).resolveCandidatePrincipleIdentity(candidateId, candidate?.rawRecommendationKind);
|
|
707
|
+
},
|
|
704
708
|
// PRI-915: availability first — an unreadable ledger must not
|
|
705
709
|
// read as an unresolved chain.
|
|
706
710
|
isAvailable: () => new PrincipleTreeLedgerAdapter({ stateDir: `${workspaceDir}/.state` }).isAvailable(),
|
|
@@ -711,6 +715,10 @@ export async function runInternalizationConsumerCycle(workspaceDir, ports) {
|
|
|
711
715
|
case 'artificer':
|
|
712
716
|
runner = new ArtificerRunner({
|
|
713
717
|
stateManager, runtimeAdapter: adapter, eventEmitter: storeEmitter, artifactStore: stateManager.piArtifactStore, validator: new DefaultArtificerValidator(),
|
|
718
|
+
ledgerIdentity: { resolveForCandidate: async (candidateId) => {
|
|
719
|
+
const candidate = await stateManager.getCandidate(candidateId);
|
|
720
|
+
return new PrincipleTreeLedgerAdapter({ stateDir: `${workspaceDir}/.state` }).resolveCandidatePrincipleIdentity(candidateId, candidate?.rawRecommendationKind);
|
|
721
|
+
} },
|
|
714
722
|
// PRI-982 (SPEC-PD-IAER-001 FR-02): the preflight-assembled Owner
|
|
715
723
|
// evidence pack — present only when the authoritative channel is
|
|
716
724
|
// code_tool_hook AND the readiness gate returned ready (same
|
|
@@ -753,6 +761,10 @@ export async function runInternalizationConsumerCycle(workspaceDir, ports) {
|
|
|
753
761
|
// PRI-915: availability first — an unreadable ledger must surface
|
|
754
762
|
// as identity_source_unavailable, not as invalid_identity drift.
|
|
755
763
|
ledgerIdentity: {
|
|
764
|
+
resolveForCandidate: async (candidateId) => {
|
|
765
|
+
const candidate = await stateManager.getCandidate(candidateId);
|
|
766
|
+
return new PrincipleTreeLedgerAdapter({ stateDir: `${workspaceDir}/.state` }).resolveCandidatePrincipleIdentity(candidateId, candidate?.rawRecommendationKind);
|
|
767
|
+
},
|
|
756
768
|
isAvailable: () => new PrincipleTreeLedgerAdapter({ stateDir: `${workspaceDir}/.state` }).isAvailable(),
|
|
757
769
|
hasPrinciple: (principleId) => new PrincipleTreeLedgerAdapter({ stateDir: `${workspaceDir}/.state` }).hasPrinciple(principleId),
|
|
758
770
|
},
|
|
@@ -70,6 +70,10 @@ export async function dispatchRolloutActivation(workspaceDir, input, options = {
|
|
|
70
70
|
// used to mint the principle UUID); candidate lineage reuses the artifact
|
|
71
71
|
// read model plus raw diagnostic_json reads.
|
|
72
72
|
const ledgerIdentity = {
|
|
73
|
+
getCandidateKind: (candidateId) => {
|
|
74
|
+
const row = connection.getDb().prepare('SELECT recommendation_kind FROM principle_candidates WHERE candidate_id = ?').get(candidateId);
|
|
75
|
+
return row !== null && typeof row === 'object' && Object.hasOwn(row, 'recommendation_kind') ? Reflect.get(row, 'recommendation_kind') : undefined;
|
|
76
|
+
},
|
|
73
77
|
ledger: new PrincipleTreeLedgerAdapter({ stateDir: `${workspaceDir}/.state` }),
|
|
74
78
|
getArtifactById: artifactReadModel.getArtifactById,
|
|
75
79
|
getTaskDiagnosticJson: (taskId) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PROMPT_BUDGET_POLICY_VERSION, type PromptBudgetCapacitySource, type PromptBudgetCapacityStatus, type PromptBudgetFallbackReason, type PromptBudgetResolution } from '@principles/core/runtime-v2';
|
|
1
|
+
import { PROMPT_BUDGET_POLICY_VERSION, type PromptBudgetCapacitySource, type PromptBudgetCapacityStatus, type PromptBudgetFallbackReason, type PromptBudgetResolution, type PromptBudgetConfig } from '@principles/core/runtime-v2';
|
|
2
2
|
import { type PromptInjectionTargetHost } from './prompt-injection-projection.js';
|
|
3
3
|
/**
|
|
4
4
|
* PRI-1017: runtime budget OBSERVATION read model over the EXISTING
|
|
@@ -174,3 +174,12 @@ export declare function selectConsoleRuntimeBudgetFacts(input: {
|
|
|
174
174
|
* rides events or console payloads.
|
|
175
175
|
*/
|
|
176
176
|
export declare function runtimeBudgetObservationToResolution(observation: RuntimePromptBudgetObservation): PromptBudgetResolution;
|
|
177
|
+
/**
|
|
178
|
+
* PRI-1020: the Owner's declared window as a budget resolution, for console
|
|
179
|
+
* surfaces with NO fresh runtime observation. Goes through the same single
|
|
180
|
+
* resolver (tier 0) so an injected forecast and the console fallback can
|
|
181
|
+
* never disagree about what a declaration means. Undefined when the
|
|
182
|
+
* workspace declares nothing — the caller then keeps the historical fixed
|
|
183
|
+
* fallback.
|
|
184
|
+
*/
|
|
185
|
+
export declare function operatorDeclaredBudgetResolution(promptBudget: PromptBudgetConfig | undefined, hostKind: PromptInjectionTargetHost): PromptBudgetResolution | undefined;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { PROMPT_BUDGET_POLICY_VERSION, RUNTIME_V2_PRINCIPLE_BUDGET, isValidContextWindowTokens, promptBudgetCharsForContextWindow, } from '@principles/core/runtime-v2';
|
|
3
|
+
import { PROMPT_BUDGET_POLICY_VERSION, RUNTIME_V2_PRINCIPLE_BUDGET, isValidContextWindowTokens, promptBudgetCharsForContextWindow, resolvePromptBudget, operatorDeclaredContextWindow, } from '@principles/core/runtime-v2';
|
|
4
4
|
import { isPromptInjectionTargetHost, } from './prompt-injection-projection.js';
|
|
5
5
|
/**
|
|
6
6
|
* PRI-1017: runtime budget OBSERVATION read model over the EXISTING
|
|
@@ -104,6 +104,7 @@ function parseObservedAt(value) {
|
|
|
104
104
|
return Number.isFinite(parsed) ? parsed : null;
|
|
105
105
|
}
|
|
106
106
|
const BUDGET_CAPACITY_SOURCES = new Set([
|
|
107
|
+
'operator_declared',
|
|
107
108
|
'host_effective_window',
|
|
108
109
|
'pi_catalog_exact',
|
|
109
110
|
'legacy_fallback',
|
|
@@ -177,7 +178,11 @@ function narrowObservation(parsed, workspaceDir, nowMs) {
|
|
|
177
178
|
// formula derives from it; the legacy fallback needs the legacy budget, no
|
|
178
179
|
// window, and a bounded reason. Anything else is not a trustworthy fact.
|
|
179
180
|
if (rawStatus === 'confirmed') {
|
|
180
|
-
|
|
181
|
+
// PRI-1020: operator_declared joins the confirmed set — a declared window
|
|
182
|
+
// is a real window (the Owner's explicit cap), so its observations carry
|
|
183
|
+
// the window and the exact formula budget like the other confirmed
|
|
184
|
+
// sources.
|
|
185
|
+
if (rawSource !== 'operator_declared' && rawSource !== 'host_effective_window' && rawSource !== 'pi_catalog_exact')
|
|
181
186
|
return null;
|
|
182
187
|
if (!isValidContextWindowTokens(rawWindow))
|
|
183
188
|
return null;
|
|
@@ -447,3 +452,17 @@ export function runtimeBudgetObservationToResolution(observation) {
|
|
|
447
452
|
...(observation.fallbackReason !== null ? { fallbackReason: observation.fallbackReason } : {}),
|
|
448
453
|
};
|
|
449
454
|
}
|
|
455
|
+
/**
|
|
456
|
+
* PRI-1020: the Owner's declared window as a budget resolution, for console
|
|
457
|
+
* surfaces with NO fresh runtime observation. Goes through the same single
|
|
458
|
+
* resolver (tier 0) so an injected forecast and the console fallback can
|
|
459
|
+
* never disagree about what a declaration means. Undefined when the
|
|
460
|
+
* workspace declares nothing — the caller then keeps the historical fixed
|
|
461
|
+
* fallback.
|
|
462
|
+
*/
|
|
463
|
+
export function operatorDeclaredBudgetResolution(promptBudget, hostKind) {
|
|
464
|
+
const declaredWindow = operatorDeclaredContextWindow(promptBudget, hostKind);
|
|
465
|
+
if (declaredWindow === undefined)
|
|
466
|
+
return undefined;
|
|
467
|
+
return resolvePromptBudget({ operatorDeclared: { contextWindowTokens: declaredWindow } });
|
|
468
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@principles/host-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.1",
|
|
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.296.2",
|
|
35
35
|
"@principles/install-layout": "^0.4.0",
|
|
36
36
|
"better-sqlite3": "^13.0.3",
|
|
37
37
|
"js-yaml": "^5.4.3"
|