create-principles-disciple 1.147.8 → 1.147.9

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.
Files changed (58) hide show
  1. package/_release/product-identity.json +2 -2
  2. package/core/dist/runtime-v2/activation/adaptive-delivery-record.d.ts +37 -0
  3. package/core/dist/runtime-v2/activation/adaptive-delivery-record.d.ts.map +1 -0
  4. package/core/dist/runtime-v2/activation/adaptive-delivery-record.js +126 -0
  5. package/core/dist/runtime-v2/activation/adaptive-delivery-record.js.map +1 -0
  6. package/core/dist/runtime-v2/activation/adaptive-principle-intervention.d.ts +46 -0
  7. package/core/dist/runtime-v2/activation/adaptive-principle-intervention.d.ts.map +1 -0
  8. package/core/dist/runtime-v2/activation/adaptive-principle-intervention.js +91 -0
  9. package/core/dist/runtime-v2/activation/adaptive-principle-intervention.js.map +1 -0
  10. package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.d.ts +2 -0
  11. package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.d.ts.map +1 -1
  12. package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.js +2 -0
  13. package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.js.map +1 -1
  14. package/core/dist/runtime-v2/index.d.ts +3 -0
  15. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  16. package/core/dist/runtime-v2/index.js +2 -0
  17. package/core/dist/runtime-v2/index.js.map +1 -1
  18. package/core/dist/runtime-v2/store/sqlite-connection.js +1 -1
  19. package/core/dist/runtime-v2/store/sqlite-connection.js.map +1 -1
  20. package/core/dist/runtime-v2/types/event-types.d.ts +6 -3
  21. package/core/dist/runtime-v2/types/event-types.d.ts.map +1 -1
  22. package/core/dist/runtime-v2/types/event-types.js +2 -0
  23. package/core/dist/runtime-v2/types/event-types.js.map +1 -1
  24. package/core/package.json +5 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +9 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/install-summary.d.ts +3 -0
  29. package/dist/install-summary.d.ts.map +1 -1
  30. package/dist/install-summary.js +17 -9
  31. package/dist/install-summary.js.map +1 -1
  32. package/dist/installers/workbuddy-host-installer.d.ts +20 -1
  33. package/dist/installers/workbuddy-host-installer.d.ts.map +1 -1
  34. package/dist/installers/workbuddy-host-installer.js +75 -14
  35. package/dist/installers/workbuddy-host-installer.js.map +1 -1
  36. package/host-runtime/dist/active-principle-prompt.d.ts +28 -0
  37. package/host-runtime/dist/active-principle-prompt.js +163 -50
  38. package/host-runtime/dist/adaptive-principle-revalidation.d.ts +8 -0
  39. package/host-runtime/dist/adaptive-principle-revalidation.js +52 -0
  40. package/host-runtime/dist/index.d.ts +16 -0
  41. package/host-runtime/dist/index.js +34 -0
  42. package/host-runtime/dist/prompt-activation-authority.d.ts +7 -0
  43. package/host-runtime/dist/prompt-activation-authority.js +16 -0
  44. package/package.json +2 -2
  45. package/pd-cli/package.json +1 -1
  46. package/plugin/dist/bundle.js +446 -446
  47. package/plugin/dist/core/event-log.d.ts +3 -0
  48. package/plugin/dist/governance-audit.js +3 -3
  49. package/plugin/dist/hooks/adaptive-activation-config.d.ts +8 -0
  50. package/plugin/dist/hooks/prompt-helpers.d.ts +5 -0
  51. package/plugin/dist/hooks/prompt-types.d.ts +1 -0
  52. package/plugin/dist/hooks/prompt.d.ts +8 -1
  53. package/plugin/dist/host-runtime/openclaw-host-runtime.d.ts +13 -0
  54. package/plugin/dist/openclaw-sdk.d.ts +4 -0
  55. package/plugin/dist/openclaw.plugin.json +33 -1
  56. package/plugin/openclaw.plugin.json +32 -0
  57. package/release-manager/dist/installers/workbuddy-host-installer.js +75 -14
  58. package/release-manager/package.json +1 -1
@@ -3,6 +3,8 @@ import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
  import { escapeXml } from '@principles/core/prompt-builder';
5
5
  import { loadPdConfigForPlugin } from './pd-config.js';
6
+ import { readPromptActivationAuthority } from './prompt-activation-authority.js';
7
+ import { revalidateAdaptivePrinciple } from './adaptive-principle-revalidation.js';
6
8
  /** PRI-904 SPEC §10: bounded diagnostic id lists (mirrors the core selector's cap of 16). */
7
9
  export const MAX_SHARED_DIAGNOSTIC_IDS = 16;
8
10
  /**
@@ -34,7 +36,10 @@ export async function readPromptActivationCandidates(input) {
34
36
  return { principles, warnings, aborted: true, selfReportEnabled, abstractionLayerEnabled };
35
37
  }
36
38
  try {
37
- connection = new SqliteConnection({ workspaceDir: input.workspaceDir, readonly: true, bootstrapIfMissing: false });
39
+ connection = new SqliteConnection({ workspaceDir: input.workspaceDir, readonly: true, bootstrapIfMissing: false,
40
+ // Additional adaptive reads must not hold the host behind SQLite's synchronous busy wait.
41
+ ...(input.includeAuthority === true ? { busyTimeoutMs: 0 } : {}),
42
+ });
38
43
  const activations = filterPromptActivations(await new SqliteActivationStateStore(connection).listPromptActivations());
39
44
  const artifactStore = new SqlitePIArtifactStore(connection);
40
45
  for (const activation of activations) {
@@ -61,6 +66,19 @@ export async function readPromptActivationCandidates(input) {
61
66
  warnings.push(resolved.warning);
62
67
  continue;
63
68
  }
69
+ if (input.includeAuthority === true) {
70
+ try {
71
+ const authority = readPromptActivationAuthority(connection, artifact.artifactId, 'prompt');
72
+ if (authority.authority)
73
+ resolved.principle.authority = authority.authority;
74
+ if (authority.approvedBy)
75
+ resolved.principle.approvedBy = authority.approvedBy;
76
+ }
77
+ catch {
78
+ // Approval lookup failure is unknown, never inferred as owner or policy.
79
+ warnings.push(`prompt_activation_authority_unavailable: artifactId=${artifact.artifactId}`);
80
+ }
81
+ }
64
82
  principles.push(resolved.principle);
65
83
  }
66
84
  }
@@ -84,6 +102,11 @@ export async function buildActivePrinciplePromptContext(input) {
84
102
  additionalContext: '', principleIds: [], activationIds: [], artifactIds: [], warnings,
85
103
  budget: budgetChars, truncated: false,
86
104
  selectionPolicy: 'legacy_fifo_prefix_v1', eligibleCount: 0,
105
+ ...(input.adaptivePriority ? { adaptivePacking: {
106
+ status: 'unavailable', reason: 'reader_aborted',
107
+ targetActivationId: input.adaptivePriority.activationId, targetArtifactId: input.adaptivePriority.artifactId,
108
+ displacedActivationIds: [], ...(input.hookInvocationId ? { hookInvocationId: input.hookInvocationId } : {}),
109
+ } } : {}),
87
110
  budgetCapacitySource: promptBudget.capacitySource,
88
111
  budgetCapacityStatus: promptBudget.capacityStatus,
89
112
  budgetContextWindowTokens: promptBudget.contextWindowTokens,
@@ -92,9 +115,6 @@ export async function buildActivePrinciplePromptContext(input) {
92
115
  ...(promptBudget.fallbackDetail !== undefined ? { budgetFallbackDetail: promptBudget.fallbackDetail } : {}),
93
116
  };
94
117
  }
95
- const included = [];
96
- let additionalContext = '';
97
- let truncated = false;
98
118
  // PRI-904: same fair-rotation semantics as the plugin route's trimToBudget —
99
119
  // deterministic rotating start over the base (ASC) candidate order, circular
100
120
  // scan, continue-on-non-fit. Costs are measured with the REAL serializer
@@ -108,56 +128,149 @@ export async function buildActivePrinciplePromptContext(input) {
108
128
  const rotationStartIndex = selectionPolicy === 'fair_rotation_v1' && roundKey !== undefined
109
129
  ? ((roundKey % n) + n) % n
110
130
  : undefined;
111
- const droppedActivationIds = [];
112
- const oversizedActivationIds = [];
113
- const standaloneFits = (principle) => renderPrinciplesToDirectives([principle], new Set([principle.principleId]), { escapeFn: escapeXml, selfReportInstruction: selfReportEnabled }).length
114
- <= budgetChars;
115
- const scanOrder = rotationStartIndex === undefined
131
+ const nativeScanOrder = rotationStartIndex === undefined
116
132
  ? principles
117
133
  : principles.slice(rotationStartIndex).concat(principles.slice(0, rotationStartIndex));
118
- for (const principle of scanOrder) {
119
- const candidate = [...included, principle];
120
- const candidateContext = renderPrinciplesToDirectives(candidate, new Set(candidate.map((entry) => entry.principleId)), { escapeFn: escapeXml, selfReportInstruction: selfReportEnabled });
121
- if (candidateContext.length > budgetChars) {
122
- if (standaloneFits(principle)) {
123
- // Fits alone but not now — normal budget truncation.
124
- truncated = true;
125
- if (droppedActivationIds.length < MAX_SHARED_DIAGNOSTIC_IDS)
126
- droppedActivationIds.push(principle.activationId);
127
- }
128
- else if (oversizedActivationIds.length < MAX_SHARED_DIAGNOSTIC_IDS) {
129
- // Can never fit alone — oversize, not starvation (PRI-904 SPEC §6.6).
130
- oversizedActivationIds.push(principle.activationId);
134
+ const pack = (scanOrder) => {
135
+ const included = [];
136
+ let additionalContext = '';
137
+ let truncated = false;
138
+ const dropped = [];
139
+ const oversized = [];
140
+ const standaloneFits = (principle) => renderPrinciplesToDirectives([principle], new Set([principle.principleId]), { escapeFn: escapeXml, selfReportInstruction: selfReportEnabled }).length
141
+ <= budgetChars;
142
+ for (const principle of scanOrder) {
143
+ const candidate = [...included, principle];
144
+ const candidateContext = renderPrinciplesToDirectives(candidate, new Set(candidate.map((entry) => entry.principleId)), { escapeFn: escapeXml, selfReportInstruction: selfReportEnabled });
145
+ if (candidateContext.length > budgetChars) {
146
+ if (standaloneFits(principle)) {
147
+ truncated = true;
148
+ if (dropped.length < MAX_SHARED_DIAGNOSTIC_IDS)
149
+ dropped.push(principle.activationId);
150
+ }
151
+ else if (oversized.length < MAX_SHARED_DIAGNOSTIC_IDS) {
152
+ oversized.push(principle.activationId);
153
+ }
154
+ if (selectionPolicy === 'legacy_fifo_prefix_v1')
155
+ break;
156
+ continue;
131
157
  }
132
- if (selectionPolicy === 'legacy_fifo_prefix_v1')
133
- break;
134
- continue;
158
+ included.push(principle);
159
+ additionalContext = candidateContext;
135
160
  }
136
- included.push(principle);
137
- additionalContext = candidateContext;
161
+ return { included, additionalContext, truncated, dropped, oversized };
162
+ };
163
+ const makeResult = (packing, eligiblePrinciples, adaptivePacking) => {
164
+ const resultWarnings = [...warnings];
165
+ if (packing.truncated) {
166
+ resultWarnings.push('prompt_context_truncated: production_prompt_cap; nextAction=reduce_active_prompt_principles');
167
+ }
168
+ const injectedIds = new Set(packing.included.map((principle) => principle.principleId));
169
+ return {
170
+ additionalContext: packing.additionalContext,
171
+ principleIds: [...injectedIds],
172
+ activationIds: packing.included.map((principle) => principle.activationId),
173
+ artifactIds: packing.included.map((principle) => principle.artifactId),
174
+ warnings: resultWarnings,
175
+ budget: budgetChars,
176
+ truncated: packing.truncated,
177
+ selectionPolicy,
178
+ eligibleCount: eligiblePrinciples.length,
179
+ ...(rotationStartIndex !== undefined ? { rotationStartIndex } : {}),
180
+ ...(packing.dropped.length > 0 ? { droppedActivationIds: packing.dropped } : {}),
181
+ ...(packing.oversized.length > 0 ? { oversizedActivationIds: packing.oversized } : {}),
182
+ budgetCapacitySource: promptBudget.capacitySource,
183
+ budgetCapacityStatus: promptBudget.capacityStatus,
184
+ budgetContextWindowTokens: promptBudget.contextWindowTokens,
185
+ budgetPolicyVersion: promptBudget.policyVersion,
186
+ ...(promptBudget.fallbackReason !== undefined ? { budgetFallbackReason: promptBudget.fallbackReason } : {}),
187
+ ...(promptBudget.fallbackDetail !== undefined ? { budgetFallbackDetail: promptBudget.fallbackDetail } : {}),
188
+ ...(adaptivePacking ? { adaptivePacking } : {}),
189
+ };
190
+ };
191
+ const nativePacking = pack(nativeScanOrder);
192
+ const nativeResult = makeResult(nativePacking, principles);
193
+ const priority = input.adaptivePriority;
194
+ if (priority === undefined)
195
+ return nativeResult;
196
+ const report = (status, reason, displacedActivationIds = []) => ({
197
+ status,
198
+ ...(reason ? { reason } : {}),
199
+ targetActivationId: typeof priority.activationId === 'string' ? priority.activationId : '',
200
+ targetArtifactId: typeof priority.artifactId === 'string' ? priority.artifactId : '',
201
+ ...(input.hookInvocationId ? { hookInvocationId: input.hookInvocationId } : {}),
202
+ displacedActivationIds,
203
+ });
204
+ const nativeTargetMatches = principles.filter((principle) => principle.artifactId === priority.artifactId && principle.activationId === priority.activationId);
205
+ const [nativeTarget] = nativeTargetMatches;
206
+ const baselineHasTarget = nativePacking.included.some((principle) => principle.artifactId === priority.artifactId && principle.activationId === priority.activationId);
207
+ const withoutTarget = (reason) => {
208
+ if (nativeTargetMatches.length !== 1 || !nativeTarget)
209
+ return { ...nativeResult, adaptivePacking: report('unavailable', reason) };
210
+ const targetPrincipleId = nativeTarget.principleId;
211
+ const safePrinciples = principles.filter((principle) => principle.principleId !== targetPrincipleId);
212
+ const safeScanOrder = nativeScanOrder.filter((principle) => principle.principleId !== targetPrincipleId);
213
+ const safePacking = pack(safeScanOrder);
214
+ return makeResult(safePacking, safePrinciples, report('unavailable', reason, baselineHasTarget ? [nativeTarget.activationId] : []));
215
+ };
216
+ if (typeof priority.artifactId !== 'string' || !priority.artifactId.trim()
217
+ || typeof priority.activationId !== 'string' || !priority.activationId.trim()) {
218
+ return { ...nativeResult, adaptivePacking: report('unavailable', 'invalid_target') };
138
219
  }
139
- if (truncated) {
140
- warnings.push('prompt_context_truncated: production_prompt_cap; nextAction=reduce_active_prompt_principles');
220
+ if (nativeTargetMatches.length === 0)
221
+ return { ...nativeResult, adaptivePacking: report('unavailable', 'target_unavailable') };
222
+ if (nativeTargetMatches.length !== 1)
223
+ return { ...nativeResult, adaptivePacking: report('unavailable', 'target_ambiguous') };
224
+ if (!nativeTarget)
225
+ return { ...nativeResult, adaptivePacking: report('unavailable', 'target_unavailable') };
226
+ if (principles.filter((principle) => principle.principleId === nativeTarget.principleId).length !== 1) {
227
+ return { ...nativeResult, adaptivePacking: report('unavailable', 'target_ambiguous') };
141
228
  }
142
- const injectedIds = new Set(included.map((principle) => principle.principleId));
143
- return {
144
- additionalContext,
145
- principleIds: [...injectedIds],
146
- activationIds: included.map((principle) => principle.activationId),
147
- artifactIds: included.map((principle) => principle.artifactId),
148
- warnings,
149
- budget: budgetChars,
150
- truncated,
151
- selectionPolicy,
152
- eligibleCount: principles.length,
153
- ...(rotationStartIndex !== undefined ? { rotationStartIndex } : {}),
154
- ...(droppedActivationIds.length > 0 ? { droppedActivationIds } : {}),
155
- ...(oversizedActivationIds.length > 0 ? { oversizedActivationIds } : {}),
156
- budgetCapacitySource: promptBudget.capacitySource,
157
- budgetCapacityStatus: promptBudget.capacityStatus,
158
- budgetContextWindowTokens: promptBudget.contextWindowTokens,
159
- budgetPolicyVersion: promptBudget.policyVersion,
160
- ...(promptBudget.fallbackReason !== undefined ? { budgetFallbackReason: promptBudget.fallbackReason } : {}),
161
- ...(promptBudget.fallbackDetail !== undefined ? { budgetFallbackDetail: promptBudget.fallbackDetail } : {}),
162
- };
229
+ const authorityRead = await readPromptActivationCandidates({ workspaceDir: input.workspaceDir, includeAuthority: true });
230
+ const authorizedMatches = authorityRead.principles.filter((principle) => principle.artifactId === priority.artifactId && principle.activationId === priority.activationId);
231
+ const [authorizedTarget] = authorizedMatches;
232
+ if (authorityRead.aborted || authorityRead.warnings.length > 0 || authorizedMatches.length !== 1 || !authorizedTarget
233
+ || authorityRead.principles.filter((principle) => principle.principleId === authorizedTarget.principleId).length !== 1) {
234
+ return withoutTarget('authority_unavailable');
235
+ }
236
+ if (!authorizedTarget.authority
237
+ || authorizedTarget.principleId !== nativeTarget.principleId
238
+ || authorizedTarget.text !== nativeTarget.text
239
+ || authorizedTarget.artifactContentSha256 !== nativeTarget.artifactContentSha256) {
240
+ return withoutTarget('target_changed');
241
+ }
242
+ const signal = input.signal ?? new AbortController().signal;
243
+ const targetRendered = renderPrinciplesToDirectives([nativeTarget], new Set([nativeTarget.principleId]), { escapeFn: escapeXml });
244
+ const targetBody = targetRendered.slice(targetRendered.indexOf('<directive '), targetRendered.indexOf('</directive>') + '</directive>'.length);
245
+ const prepared = (status, displaced = []) => ({
246
+ ...report(status, undefined, displaced), targetSnapshot: authorizedTarget, targetBody,
247
+ nativeBaseline: nativeResult, ...(input.deadlineAt !== undefined ? { deadlineAt: input.deadlineAt } : {}),
248
+ });
249
+ if (baselineHasTarget) {
250
+ const stillValid = await revalidateAdaptivePrinciple(input.workspaceDir, authorizedTarget, signal);
251
+ if (!stillValid)
252
+ return withoutTarget('target_changed');
253
+ return { ...nativeResult, adaptivePacking: prepared('target_present') };
254
+ }
255
+ const targetIndex = nativeScanOrder.indexOf(nativeTarget);
256
+ const targetFirstScan = [nativeTarget, ...nativeScanOrder.filter((principle, index) => index !== targetIndex && principle.principleId !== nativeTarget.principleId)];
257
+ const prioritizedPacking = pack(targetFirstScan);
258
+ if (!prioritizedPacking.included.some((principle) => principle.principleId === nativeTarget.principleId)) {
259
+ return { ...nativeResult, adaptivePacking: report('unavailable', 'target_does_not_fit') };
260
+ }
261
+ const mandatoryIds = input.mandatoryPrincipleIds ?? [];
262
+ if (!Array.isArray(mandatoryIds) || mandatoryIds.some((id) => typeof id !== 'string')
263
+ || mandatoryIds.some((id) => !prioritizedPacking.included.some((principle) => principle.principleId === id))) {
264
+ return { ...nativeResult, adaptivePacking: report('unavailable', 'mandatory_constraint_displaced') };
265
+ }
266
+ const stillValid = await revalidateAdaptivePrinciple(input.workspaceDir, authorizedTarget, signal);
267
+ if (!stillValid)
268
+ return { ...nativeResult, adaptivePacking: report('unavailable', 'target_changed') };
269
+ const prioritizedActivationIds = new Set(prioritizedPacking.included.map((principle) => principle.activationId));
270
+ const displacedActivationIds = nativePacking.included
271
+ .filter((principle) => !prioritizedActivationIds.has(principle.activationId))
272
+ .map((principle) => principle.activationId);
273
+ const result = makeResult(prioritizedPacking, principles, prepared('prioritized', displacedActivationIds));
274
+ // Adaptive assembly is deliberately limited to the existing renderer's Native budget cap.
275
+ return result;
163
276
  }
@@ -0,0 +1,8 @@
1
+ import { type PromptActivationCandidates } from './active-principle-prompt.js';
2
+ import type { ActivatedPrinciple } from '@principles/core/runtime-v2';
3
+ export type AdaptivePrincipleReader = (input: {
4
+ workspaceDir: string;
5
+ }) => Promise<PromptActivationCandidates>;
6
+ /** Bind a test or host-specific reader while keeping the production call signature minimal. */
7
+ export declare function createAdaptivePrincipleRevalidator(reader: AdaptivePrincipleReader): (workspaceDir: string, expected: ActivatedPrinciple, signal: AbortSignal) => Promise<boolean>;
8
+ export declare function revalidateAdaptivePrinciple(workspaceDir: string, expected: ActivatedPrinciple, signal: AbortSignal): Promise<boolean>;
@@ -0,0 +1,52 @@
1
+ import { readPromptActivationCandidates, } from './active-principle-prompt.js';
2
+ /**
3
+ * Rechecks the rendered principle's identity, body, and authorization at the
4
+ * adaptive-intervention return boundary. A full artifact digest is required;
5
+ * legacy snapshots without it cannot certify a stable artifact revision.
6
+ */
7
+ async function revalidateWithReader(input, reader) {
8
+ const { workspaceDir, expected, signal } = input;
9
+ if (signal.aborted || !expected.artifactContentSha256 || !/^[a-f0-9]{64}$/.test(expected.artifactContentSha256))
10
+ return false;
11
+ let onAbort;
12
+ const aborted = new Promise((resolve) => {
13
+ onAbort = () => resolve(null);
14
+ signal.addEventListener('abort', onAbort, { once: true });
15
+ if (signal.aborted)
16
+ onAbort();
17
+ });
18
+ try {
19
+ const result = await Promise.race([reader({ workspaceDir }), aborted]);
20
+ if (!result || signal.aborted || result.aborted || result.warnings.length > 0)
21
+ return false;
22
+ const matches = result.principles.filter((candidate) => candidate.artifactId === expected.artifactId && candidate.activationId === expected.activationId);
23
+ if (matches.length !== 1)
24
+ return false;
25
+ const [current] = matches;
26
+ if (!current)
27
+ return false;
28
+ // Duplicate principle identity is ambiguous even if one activation pair matches.
29
+ if (result.principles.filter((candidate) => candidate.principleId === expected.principleId).length !== 1)
30
+ return false;
31
+ return current.principleId === expected.principleId
32
+ && current.artifactContentSha256 === expected.artifactContentSha256
33
+ && current.text === expected.text
34
+ && current.authority === expected.authority
35
+ && current.approvedBy === expected.approvedBy;
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ finally {
41
+ if (onAbort)
42
+ signal.removeEventListener('abort', onAbort);
43
+ }
44
+ }
45
+ /** Bind a test or host-specific reader while keeping the production call signature minimal. */
46
+ export function createAdaptivePrincipleRevalidator(reader) {
47
+ return (workspaceDir, expected, signal) => revalidateWithReader({ workspaceDir, expected, signal }, reader);
48
+ }
49
+ export function revalidateAdaptivePrinciple(workspaceDir, expected, signal) {
50
+ const readWithAuthority = ({ workspaceDir: currentWorkspaceDir }) => readPromptActivationCandidates({ workspaceDir: currentWorkspaceDir, includeAuthority: true });
51
+ return revalidateWithReader({ workspaceDir, expected, signal }, readWithAuthority);
52
+ }
@@ -5,6 +5,7 @@ import type { RuleImplementationRuntime } from './rule-implementation-runtime.js
5
5
  import { type PainDatabaseFactory, type PainEnrichmentProvider } from './production-pain-evidence.js';
6
6
  import type { GovernanceHostKind, ToolSemanticRegistry } from '@principles/core/runtime-v2';
7
7
  export * from './active-principle-prompt.js';
8
+ export * from './prompt-activation-authority.js';
8
9
  export * from './prompt-injection-projection.js';
9
10
  export * from './prompt-activation-deliverability.js';
10
11
  export * from './prompt-injection-status.js';
@@ -76,6 +77,20 @@ export declare function createProductionHostRuntime(options?: Partial<Pick<HostR
76
77
  projectDir?: string;
77
78
  /** PRI-634-F: host-declared tool semantics supplied by the constructing host adapter. */
78
79
  toolSemantics?: ToolSemanticRegistry;
80
+ /** Optional, already-scoped single prompt target from the host adapter. Errors fail closed to Native. */
81
+ adaptivePriorityProvider?: (event: HostEvent) => {
82
+ artifactId: string;
83
+ activationId: string;
84
+ hookInvocationId?: string;
85
+ signal?: AbortSignal;
86
+ deadlineAt?: number;
87
+ } | undefined | Promise<{
88
+ artifactId: string;
89
+ activationId: string;
90
+ hookInvocationId?: string;
91
+ signal?: AbortSignal;
92
+ deadlineAt?: number;
93
+ } | undefined>;
79
94
  /**
80
95
  * PRI-750: optional event emission port. When present, the shared-path
81
96
  * handlers record injection/tool events carrying the host's natural
@@ -96,3 +111,4 @@ export * from './explicit-owner-statement-prefix.js';
96
111
  export { listObservedDesignGateSessions } from './workspace-behavior-evidence.js';
97
112
  export { readDesignGateSpecSnapshot, describeCodexRuleContextFact } from './design-gate-facts.js';
98
113
  export { createCodexArtificerTrustedFactsPort } from './codex-artificer-trusted-facts.js';
114
+ export { revalidateAdaptivePrinciple, createAdaptivePrincipleRevalidator, type AdaptivePrincipleReader } from './adaptive-principle-revalidation.js';
@@ -6,6 +6,7 @@ import { buildActivePrinciplePromptContext } from './active-principle-prompt.js'
6
6
  import { createProductionRuleHostGate } from './production-rulehost-gate.js';
7
7
  import { createProductionPainEvidenceHandler } from './production-pain-evidence.js';
8
8
  export * from './active-principle-prompt.js';
9
+ export * from './prompt-activation-authority.js';
9
10
  export * from './prompt-injection-projection.js';
10
11
  // SPEC PD_PROMPT_CAPACITY_V1: route-aware single-artifact deliverability
11
12
  // precheck (B1 write gate + A candidate fit) and the per-live-activation
@@ -225,8 +226,35 @@ export function createProductionHostRuntime(options = {}) {
225
226
  const declaredWindow = promptBudgetHostKind === undefined
226
227
  ? undefined
227
228
  : operatorDeclaredContextWindow(loadPdConfigForPlugin(event.context.workspaceDir).effective.config.promptBudget, promptBudgetHostKind);
229
+ let adaptivePriority;
230
+ let skippedPriority;
231
+ if (options.adaptivePriorityProvider) {
232
+ try {
233
+ adaptivePriority = await options.adaptivePriorityProvider(event);
234
+ if (adaptivePriority && (typeof adaptivePriority.artifactId !== 'string' || !adaptivePriority.artifactId.trim()
235
+ || typeof adaptivePriority.activationId !== 'string' || !adaptivePriority.activationId.trim()
236
+ || (adaptivePriority.deadlineAt !== undefined && !Number.isFinite(adaptivePriority.deadlineAt)))) {
237
+ adaptivePriority = undefined;
238
+ }
239
+ if (adaptivePriority?.signal?.aborted
240
+ || (adaptivePriority?.deadlineAt !== undefined && Date.now() >= adaptivePriority.deadlineAt)) {
241
+ skippedPriority = adaptivePriority;
242
+ adaptivePriority = undefined;
243
+ }
244
+ }
245
+ catch {
246
+ // An optional adaptive provider can never alter the ordinary Native path on failure.
247
+ adaptivePriority = undefined;
248
+ }
249
+ }
228
250
  const prompt = await buildActivePrinciplePromptContext({
229
251
  workspaceDir: event.context.workspaceDir,
252
+ ...(adaptivePriority ? {
253
+ adaptivePriority: { artifactId: adaptivePriority.artifactId, activationId: adaptivePriority.activationId },
254
+ ...(adaptivePriority.signal ? { signal: adaptivePriority.signal } : {}),
255
+ ...(adaptivePriority.deadlineAt !== undefined ? { deadlineAt: adaptivePriority.deadlineAt } : {}),
256
+ ...(adaptivePriority.hookInvocationId ? { hookInvocationId: adaptivePriority.hookInvocationId } : {}),
257
+ } : {}),
230
258
  promptBudget: resolvePromptBudget({
231
259
  // SPEC-PD-MODEL-AWARE-PROMPT-BUDGET-001: resolve ONCE per request
232
260
  // from the host's own hook facts (OpenClaw effective window /
@@ -250,6 +278,11 @@ export function createProductionHostRuntime(options = {}) {
250
278
  catalog: getPromptModelCatalog(),
251
279
  }),
252
280
  });
281
+ if (skippedPriority?.hookInvocationId)
282
+ prompt.adaptivePacking = {
283
+ status: 'unavailable', reason: 'deadline', targetActivationId: skippedPriority.activationId,
284
+ targetArtifactId: skippedPriority.artifactId, hookInvocationId: skippedPriority.hookInvocationId, displacedActivationIds: [],
285
+ };
253
286
  // PRI-750: record the injection event on the shared path with the host
254
287
  // turn id (Codex turn_id → runId) so receipt events carry a turn-level
255
288
  // anchor in the same events_*.jsonl format as the OpenClaw path. The
@@ -326,3 +359,4 @@ export * from './explicit-owner-statement-prefix.js';
326
359
  export { listObservedDesignGateSessions } from './workspace-behavior-evidence.js';
327
360
  export { readDesignGateSpecSnapshot, describeCodexRuleContextFact } from './design-gate-facts.js';
328
361
  export { createCodexArtificerTrustedFactsPort } from './codex-artificer-trusted-facts.js';
362
+ export { revalidateAdaptivePrinciple, createAdaptivePrincipleRevalidator } from './adaptive-principle-revalidation.js';
@@ -0,0 +1,7 @@
1
+ import type { SqliteConnection } from '@principles/core/runtime-v2';
2
+ export interface PromptActivationAuthority {
3
+ authority?: 'owner' | 'system_policy';
4
+ approvedBy?: string;
5
+ }
6
+ /** Read the existing approval row without changing how activation is granted. */
7
+ export declare function readPromptActivationAuthority(sqliteConn: Pick<SqliteConnection, 'getDb'>, artifactId: string, channel: string): PromptActivationAuthority;
@@ -0,0 +1,16 @@
1
+ /** Read the existing approval row without changing how activation is granted. */
2
+ export function readPromptActivationAuthority(sqliteConn, artifactId, channel) {
3
+ const row = sqliteConn.getDb().prepare(`
4
+ SELECT decided_by FROM approvals
5
+ WHERE artifact_id = ? AND channel = ? AND status = 'approved'
6
+ ORDER BY decided_at DESC LIMIT 1
7
+ `).get(artifactId, channel);
8
+ if (row !== null && typeof row === 'object' && Object.hasOwn(row, 'decided_by')) {
9
+ const decidedBy = row.decided_by;
10
+ return {
11
+ authority: 'owner',
12
+ approvedBy: typeof decidedBy === 'string' && decidedBy.length > 0 ? decidedBy : undefined,
13
+ };
14
+ }
15
+ return { authority: 'system_policy' };
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-principles-disciple",
3
- "version": "1.147.8",
3
+ "version": "1.147.9",
4
4
  "description": "Interactive CLI installer for Principles Disciple OpenClaw plugin",
5
5
  "type": "module",
6
6
  "bin": {
@@ -101,5 +101,5 @@
101
101
  "pd": {
102
102
  "bundledPluginVersion": "2.6.1"
103
103
  },
104
- "gitHead": "d9bbe994104eac08a8a41fa1c9374f28dc629aec"
104
+ "gitHead": "75c6765405cfb763e52c2b558e80a76deb96e3f6"
105
105
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@principles/pd-cli",
3
- "version": "1.164.0",
3
+ "version": "1.165.0",
4
4
  "description": "PD CLI — Pain recording, sample management, and governance tasks for Principles Disciple",
5
5
  "type": "module",
6
6
  "bin": {