@principles/host-runtime 0.12.2 → 0.13.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/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
  : {
@@ -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
- if (rawSource !== 'host_effective_window' && rawSource !== 'pi_catalog_exact')
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.12.2",
3
+ "version": "0.13.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.295.3",
34
+ "@principles/core": "^1.296.0",
35
35
  "@principles/install-layout": "^0.4.0",
36
36
  "better-sqlite3": "^13.0.3",
37
37
  "js-yaml": "^5.4.3"