principles-disciple 1.78.0 → 1.79.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.
@@ -2,7 +2,7 @@
2
2
  "id": "principles-disciple",
3
3
  "name": "Principles Disciple",
4
4
  "description": "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
5
- "version": "1.78.0",
5
+ "version": "1.79.0",
6
6
  "activation": {
7
7
  "onCapabilities": [
8
8
  "hook"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "principles-disciple",
3
- "version": "1.78.0",
3
+ "version": "1.79.0",
4
4
  "description": "Native OpenClaw plugin for Principles Disciple",
5
5
  "type": "module",
6
6
  "main": "./dist/bundle.js",
@@ -1,23 +1,11 @@
1
1
  import * as path from 'path';
2
2
  import * as fs from 'fs';
3
3
  import * as yaml from 'js-yaml';
4
- import { SqliteConnection, SqliteActivationStateStore, computeEffectiveFlags, DEFAULT_FEATURE_FLAGS } from '@principles/core/runtime-v2';
5
- import type { ActivationStatusRecord, EffectiveFeatureFlags } from '@principles/core/runtime-v2';
4
+ import { SqliteConnection, SqliteActivationStateStore, computeEffectiveFlags, DEFAULT_FEATURE_FLAGS, filterPromptActivations, resolvePrincipleFromArtifact } from '@principles/core/runtime-v2';
5
+ import type { EffectiveFeatureFlags, ActivatedPrinciple, PromptActivationReaderResult } from '@principles/core/runtime-v2';
6
6
 
7
- export const RUNTIME_V2_PRINCIPLE_BUDGET = 2000;
8
-
9
- export interface ActivatedPrinciple {
10
- principleId: string;
11
- text: string;
12
- artifactId: string;
13
- activationId: string;
14
- }
15
-
16
- export interface PromptActivationReaderResult {
17
- principles: ActivatedPrinciple[];
18
- warnings: string[];
19
- source: 'runtime_v2';
20
- }
7
+ export { RUNTIME_V2_PRINCIPLE_BUDGET } from '@principles/core/runtime-v2';
8
+ export type { ActivatedPrinciple, PromptActivationReaderResult };
21
9
 
22
10
  export interface PromptActivationReaderDeps {
23
11
  logger?: { warn?: (msg: string) => void; info?: (msg: string) => void; error?: (msg: string) => void };
@@ -54,14 +42,29 @@ export class PromptActivationReader {
54
42
  sqliteConn = new SqliteConnection(this.workspaceDir);
55
43
  const store = new SqliteActivationStateStore(sqliteConn);
56
44
 
57
- const activations = await store.listPromptActivations();
45
+ const allActivations = await store.listPromptActivations();
46
+ const promptActivations = filterPromptActivations(allActivations);
47
+
48
+ for (const activation of promptActivations) {
49
+ let artifactRow: unknown | null;
50
+ try {
51
+ artifactRow = this.queryArtifactRow(sqliteConn, activation.artifactId);
52
+ } catch (e) {
53
+ const msg = e instanceof Error ? e.message : String(e);
54
+ const warning = `artifact_query_failed: artifactId=${activation.artifactId} reason=${msg}; nextAction=check_pi_artifacts_table`;
55
+ warnings.push(warning);
56
+ this.deps.logger?.warn?.(`[PD:RuntimeV2] ${warning}`);
57
+ continue;
58
+ }
58
59
 
59
- for (const activation of activations) {
60
- if (activation.channel !== 'prompt' || activation.action !== 'prompt_activate') {
60
+ if (artifactRow === null) {
61
+ const warning = `artifact_not_found: artifactId=${activation.artifactId}; nextAction=check_pi_artifacts_table`;
62
+ warnings.push(warning);
63
+ this.deps.logger?.warn?.(`[PD:RuntimeV2] ${warning}`);
61
64
  continue;
62
65
  }
63
66
 
64
- const result = this.resolvePrincipleFromActivation(sqliteConn, activation);
67
+ const result = resolvePrincipleFromArtifact(artifactRow, activation);
65
68
  if (result.ok) {
66
69
  principles.push(result.principle);
67
70
  } else {
@@ -85,6 +88,21 @@ export class PromptActivationReader {
85
88
  return { principles, warnings, source: 'runtime_v2' };
86
89
  }
87
90
 
91
+ private queryArtifactRow(sqliteConn: SqliteConnection, artifactId: string): unknown | null {
92
+ try {
93
+ const db = sqliteConn.getDb();
94
+ const row = db.prepare(`
95
+ SELECT artifact_id, artifact_kind, content_json, validation_status
96
+ FROM pi_artifacts
97
+ WHERE artifact_id = ?
98
+ `).get(artifactId);
99
+ return row ?? null;
100
+ } catch (e) {
101
+ const msg = e instanceof Error ? e.message : String(e);
102
+ throw new Error(`artifact_query_failed: artifactId=${artifactId} reason=${msg}; nextAction=check_pi_artifacts_table`);
103
+ }
104
+ }
105
+
88
106
  private loadFeatureFlags(): EffectiveFeatureFlags {
89
107
  const configPath = path.join(this.workspaceDir, '.pd', 'feature-flags.yaml');
90
108
 
@@ -141,91 +159,4 @@ export class PromptActivationReader {
141
159
  }
142
160
  return result;
143
161
  }
144
-
145
- private resolvePrincipleFromActivation(
146
- sqliteConn: SqliteConnection,
147
- activation: ActivationStatusRecord,
148
- ): { ok: true; principle: ActivatedPrinciple } | { ok: false; warning: string } {
149
- const db = sqliteConn.getDb();
150
-
151
- let contentJson: string;
152
-
153
- try {
154
- const row = db.prepare(`
155
- SELECT artifact_id, artifact_kind, content_json, validation_status
156
- FROM pi_artifacts
157
- WHERE artifact_id = ?
158
- `).get(activation.artifactId);
159
-
160
- if (!isRecord(row)) {
161
- return { ok: false, warning: `artifact_query_unexpected: artifactId=${activation.artifactId}; nextAction=check_pi_artifacts_table` };
162
- }
163
-
164
- const artifact_id = Object.hasOwn(row, 'artifact_id') && typeof row.artifact_id === 'string' && row.artifact_id.length > 0 ? row.artifact_id : null;
165
- const artifact_kind = Object.hasOwn(row, 'artifact_kind') && typeof row.artifact_kind === 'string' ? row.artifact_kind : null;
166
- const raw_content_json = Object.hasOwn(row, 'content_json') && typeof row.content_json === 'string' ? row.content_json : null;
167
- const validation_status = Object.hasOwn(row, 'validation_status') && typeof row.validation_status === 'string' ? row.validation_status : null;
168
-
169
- if (!artifact_id) {
170
- return { ok: false, warning: `artifact_not_found: artifactId=${activation.artifactId} activationId=${activation.activationId}; nextAction=verify_artifact_exists_or_remove_stale_activation` };
171
- }
172
-
173
- if (artifact_kind !== 'principle') {
174
- return { ok: false, warning: `artifact_not_principle: artifactId=${artifact_id} kind=${artifact_kind ?? 'missing'}; nextAction=skip_non_principle_activations` };
175
- }
176
-
177
- if (validation_status !== 'validated') {
178
- return { ok: false, warning: `artifact_not_validated: artifactId=${artifact_id} status=${validation_status ?? 'missing'}; nextAction=skip_unvalidated_artifacts` };
179
- }
180
-
181
- if (raw_content_json === null) {
182
- return { ok: false, warning: `artifact_missing_content_json: artifactId=${artifact_id}; nextAction=ensure_artifact_has_content_json` };
183
- }
184
-
185
- contentJson = raw_content_json;
186
- } catch (e) {
187
- const msg = e instanceof Error ? e.message : String(e);
188
- return { ok: false, warning: `artifact_query_failed: artifactId=${activation.artifactId} reason=${msg}; nextAction=check_pi_artifacts_table` };
189
- }
190
-
191
- let parsed: unknown;
192
- try {
193
- parsed = JSON.parse(contentJson);
194
- } catch (e) {
195
- const msg = e instanceof Error ? e.message : String(e);
196
- return { ok: false, warning: `artifact_content_json_parse_error: artifactId=${activation.artifactId} reason=${msg}; nextAction=fix_artifact_content_json` };
197
- }
198
-
199
- if (!isRecord(parsed)) {
200
- return { ok: false, warning: `artifact_content_malformed: artifactId=${activation.artifactId} reason=parsed_to_non_object; nextAction=fix_artifact_content_json` };
201
- }
202
-
203
- const principleId = Object.hasOwn(parsed, 'principleId') && typeof parsed.principleId === 'string' ? parsed.principleId : undefined;
204
- const text = Object.hasOwn(parsed, 'text') && typeof parsed.text === 'string' ? parsed.text : undefined;
205
-
206
- const draftObj = Object.hasOwn(parsed, 'principleDraft') && isRecord(parsed.principleDraft) ? parsed.principleDraft : null;
207
- const draftTitle = draftObj && Object.hasOwn(draftObj, 'title') && typeof draftObj.title === 'string' ? draftObj.title : undefined;
208
- const draftStatement = draftObj && Object.hasOwn(draftObj, 'statement') && typeof draftObj.statement === 'string' ? draftObj.statement : undefined;
209
-
210
- const resolvedPrincipleId = principleId && principleId.length > 0 ? principleId : draftTitle;
211
- const resolvedText = text && text.length > 0 ? text : draftStatement;
212
-
213
- if (!resolvedPrincipleId || resolvedPrincipleId.length === 0) {
214
- return { ok: false, warning: `artifact_missing_principle_id: artifactId=${activation.artifactId}; nextAction=ensure_artifact_has_principleId_or_principleDraft_title` };
215
- }
216
-
217
- if (!resolvedText || resolvedText.length === 0) {
218
- return { ok: false, warning: `artifact_missing_text: artifactId=${activation.artifactId} principleId=${resolvedPrincipleId}; nextAction=ensure_artifact_has_text_or_principleDraft_statement` };
219
- }
220
-
221
- return {
222
- ok: true,
223
- principle: {
224
- principleId: resolvedPrincipleId,
225
- text: resolvedText,
226
- artifactId: activation.artifactId,
227
- activationId: activation.activationId,
228
- },
229
- };
230
- }
231
162
  }
@@ -12,9 +12,9 @@ import { defaultContextConfig } from '../types.js';
12
12
  import { extractSummary, getHistoryVersions, parseWorkingMemorySection, workingMemoryToInjection, autoCompressFocus, safeReadCurrentFocus } from '../core/focus-history.js';
13
13
  import { PathResolver } from '../core/path-resolver.js';
14
14
  import { selectPrinciplesForInjection, DEFAULT_PRINCIPLE_BUDGET } from '../core/principle-injection.js';
15
- import { getCachedMaskedPrincipleSet, WorkflowFunnelLoader, PiAiRuntimeAdapter, EmpathyObserver, AgentScheduler } from '@principles/core/runtime-v2';
15
+ import { getCachedMaskedPrincipleSet, WorkflowFunnelLoader, PiAiRuntimeAdapter, EmpathyObserver, AgentScheduler, RUNTIME_V2_PRINCIPLE_BUDGET, trimToBudget, renderPrinciplesToDirectives } from '@principles/core/runtime-v2';
16
16
  import { truncateInjectionToBudget } from '@principles/core/prompt-builder';
17
- import { PromptActivationReader, RUNTIME_V2_PRINCIPLE_BUDGET } from '../core/runtime-v2-prompt-activation-reader.js';
17
+ import { PromptActivationReader } from '../core/runtime-v2-prompt-activation-reader.js';
18
18
  import {
19
19
  matchEmpathyKeywords,
20
20
  loadKeywordStore,
@@ -898,20 +898,12 @@ ${heartbeatChecklist}
898
898
  dedupedV2 = v2Result.principles.filter((p) => !legacyActiveIds.has(p.principleId));
899
899
 
900
900
  if (dedupedV2.length > 0) {
901
- let remaining = RUNTIME_V2_PRINCIPLE_BUDGET;
902
- const lines: string[] = [];
903
- lines.push('Runtime V2 activated principles (owner-approved):');
904
- remaining -= 'Runtime V2 activated principles (owner-approved):'.length;
905
-
906
- for (const p of dedupedV2) {
907
- const entry = `- [${escapeXml(p.principleId)}] ${escapeXml(p.text)}`;
908
- if (remaining < entry.length + 1) {
909
- logger?.info?.(`[PD:RuntimeV2] Principle budget reached (${RUNTIME_V2_PRINCIPLE_BUDGET}c) — truncating after ${lines.length - 1} principles`);
910
- break;
911
- }
912
- lines.push(entry);
913
- remaining -= entry.length + 1;
914
- runtimeV2PrincipleIds.add(p.principleId);
901
+ const { lines, injectedIds, truncated } = trimToBudget(dedupedV2, RUNTIME_V2_PRINCIPLE_BUDGET, escapeXml);
902
+ if (truncated) {
903
+ logger?.info?.(`[PD:RuntimeV2] Principle budget reached (${RUNTIME_V2_PRINCIPLE_BUDGET}c) — truncating after ${injectedIds.size} principles`);
904
+ }
905
+ for (const id of injectedIds) {
906
+ runtimeV2PrincipleIds.add(id);
915
907
  }
916
908
  runtimeV2PrinciplesContent = lines.join('\n');
917
909
  }
@@ -984,24 +976,8 @@ ${empathySilenceConstraint}
984
976
  // PLACED IN prependSystemContext (before gateway system prompt) for highest LLM attention.
985
977
  // These are owner-reviewed, validated behavior constraints — not background context.
986
978
  if (runtimeV2PrincipleIds.size > 0) {
987
- const directiveLines: string[] = [];
988
- directiveLines.push('');
989
- directiveLines.push('## 【OWNER-APPROVED BEHAVIOR DIRECTIVES】');
990
- directiveLines.push('');
991
- directiveLines.push('Owner-approved behavior directives are active operating constraints learned from prior owner corrections.');
992
- directiveLines.push('These directives are mandatory for this session unless they conflict with safety, security, or higher-priority system policy.');
993
- directiveLines.push('For ambiguous coding or file-changing tasks, follow these directives before using mutating tools.');
994
- directiveLines.push('');
995
- for (const p of dedupedV2) {
996
- if (!runtimeV2PrincipleIds.has(p.principleId)) continue;
997
- directiveLines.push(`<directive id="${escapeXml(p.principleId)}" source="runtime_v2_activation">`);
998
- directiveLines.push(`MANDATORY: ${escapeXml(p.text)}`);
999
- directiveLines.push('Apply this as an active behavior constraint. Do not treat this as background context.');
1000
- directiveLines.push('</directive>');
1001
- directiveLines.push('');
1002
- }
1003
- directiveLines.push('Note: These directives do not override safety, security, or core system policy.');
1004
- prependSystemContext += directiveLines.join('\n');
979
+ const directiveText = renderPrinciplesToDirectives(dedupedV2, runtimeV2PrincipleIds, escapeXml);
980
+ prependSystemContext += directiveText;
1005
981
  }
1006
982
 
1007
983
  // Routing guidance removed per PRI-291 (MVP diet).