create-principles-disciple 1.80.0 → 1.82.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/core/dist/runtime-v2/__tests__/admission-gate.test.js +6 -6
- package/core/dist/runtime-v2/__tests__/admission-gate.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +39 -0
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/artificer-runner-vslice.test.js +52 -0
- package/core/dist/runtime-v2/__tests__/artificer-runner-vslice.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice.test.js +245 -1
- package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.js +131 -1
- package/core/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/scribe-runner-vslice.test.js +425 -2
- package/core/dist/runtime-v2/__tests__/scribe-runner-vslice.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/telemetry-event.test.d.ts +2 -0
- package/core/dist/runtime-v2/__tests__/telemetry-event.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/telemetry-event.test.js +69 -0
- package/core/dist/runtime-v2/__tests__/telemetry-event.test.js.map +1 -0
- package/core/dist/runtime-v2/admission-gate.d.ts.map +1 -1
- package/core/dist/runtime-v2/admission-gate.js +0 -8
- package/core/dist/runtime-v2/admission-gate.js.map +1 -1
- package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.d.ts +15 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.js +685 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.js.map +1 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-redaction-deep.test.d.ts +13 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-redaction-deep.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-redaction-deep.test.js +447 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-redaction-deep.test.js.map +1 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-validation-edge-cases.test.d.ts +12 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-validation-edge-cases.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-validation-edge-cases.test.js +433 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-validation-edge-cases.test.js.map +1 -0
- package/core/dist/runtime-v2/config/index.d.ts +14 -0
- package/core/dist/runtime-v2/config/index.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/index.js +16 -0
- package/core/dist/runtime-v2/config/index.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-defaults.d.ts +14 -0
- package/core/dist/runtime-v2/config/pd-config-defaults.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-defaults.js +74 -0
- package/core/dist/runtime-v2/config/pd-config-defaults.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-effective.d.ts +14 -0
- package/core/dist/runtime-v2/config/pd-config-effective.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-effective.js +118 -0
- package/core/dist/runtime-v2/config/pd-config-effective.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-feature-flags.d.ts +35 -0
- package/core/dist/runtime-v2/config/pd-config-feature-flags.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-feature-flags.js +99 -0
- package/core/dist/runtime-v2/config/pd-config-feature-flags.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-redaction.d.ts +22 -0
- package/core/dist/runtime-v2/config/pd-config-redaction.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-redaction.js +179 -0
- package/core/dist/runtime-v2/config/pd-config-redaction.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-types.d.ts +124 -0
- package/core/dist/runtime-v2/config/pd-config-types.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-types.js +35 -0
- package/core/dist/runtime-v2/config/pd-config-types.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-validate.d.ts +16 -0
- package/core/dist/runtime-v2/config/pd-config-validate.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-validate.js +443 -0
- package/core/dist/runtime-v2/config/pd-config-validate.js.map +1 -0
- package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js +10 -10
- package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js.map +1 -1
- package/core/dist/runtime-v2/feedback/index.d.ts +1 -1
- package/core/dist/runtime-v2/feedback/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/feedback/index.js +1 -1
- package/core/dist/runtime-v2/feedback/index.js.map +1 -1
- package/core/dist/runtime-v2/feedback/redact-sensitive.d.ts +2 -0
- package/core/dist/runtime-v2/feedback/redact-sensitive.d.ts.map +1 -1
- package/core/dist/runtime-v2/feedback/redact-sensitive.js +32 -3
- package/core/dist/runtime-v2/feedback/redact-sensitive.js.map +1 -1
- package/core/dist/runtime-v2/index.d.ts +5 -1
- package/core/dist/runtime-v2/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/index.js +9 -1
- package/core/dist/runtime-v2/index.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.d.ts +2 -0
- package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.js +398 -0
- package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.js.map +1 -0
- package/core/dist/runtime-v2/internalization/artificer-output.d.ts +3 -2
- package/core/dist/runtime-v2/internalization/artificer-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-output.js +40 -31
- package/core/dist/runtime-v2/internalization/artificer-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.d.ts +59 -38
- package/core/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/artificer-runner.js +121 -395
- package/core/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/dreamer-output.d.ts +4 -3
- package/core/dist/runtime-v2/internalization/dreamer-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/dreamer-output.js +11 -9
- package/core/dist/runtime-v2/internalization/dreamer-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/dreamer-runner.d.ts +31 -92
- package/core/dist/runtime-v2/internalization/dreamer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/dreamer-runner.js +79 -495
- package/core/dist/runtime-v2/internalization/dreamer-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-output.d.ts +2 -2
- package/core/dist/runtime-v2/internalization/evaluator-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-output.js +29 -23
- package/core/dist/runtime-v2/internalization/evaluator-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts +74 -48
- package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/evaluator-runner.js +164 -444
- package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/philosopher-output.d.ts +8 -2
- package/core/dist/runtime-v2/internalization/philosopher-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/philosopher-output.js +16 -11
- package/core/dist/runtime-v2/internalization/philosopher-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/philosopher-runner.d.ts +36 -55
- package/core/dist/runtime-v2/internalization/philosopher-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/philosopher-runner.js +117 -401
- package/core/dist/runtime-v2/internalization/philosopher-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-output.d.ts +8 -2
- package/core/dist/runtime-v2/internalization/scribe-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-output.js +33 -17
- package/core/dist/runtime-v2/internalization/scribe-output.js.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-runner.d.ts +56 -49
- package/core/dist/runtime-v2/internalization/scribe-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-runner.js +116 -398
- package/core/dist/runtime-v2/internalization/scribe-runner.js.map +1 -1
- package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.d.ts +2 -0
- package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.js +379 -0
- package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.js.map +1 -0
- package/core/dist/runtime-v2/runner/base-peer-runner.d.ts +122 -0
- package/core/dist/runtime-v2/runner/base-peer-runner.d.ts.map +1 -0
- package/core/dist/runtime-v2/runner/base-peer-runner.js +528 -0
- package/core/dist/runtime-v2/runner/base-peer-runner.js.map +1 -0
- package/core/dist/runtime-v2/runner/peer-runner-types.d.ts +107 -0
- package/core/dist/runtime-v2/runner/peer-runner-types.d.ts.map +1 -0
- package/core/dist/runtime-v2/runner/peer-runner-types.js +13 -0
- package/core/dist/runtime-v2/runner/peer-runner-types.js.map +1 -0
- package/core/dist/telemetry-event.d.ts +2 -2
- package/core/dist/telemetry-event.d.ts.map +1 -1
- package/core/dist/telemetry-event.js +89 -0
- package/core/dist/telemetry-event.js.map +1 -1
- package/dist/installer.d.ts +1 -1
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +24 -10
- package/dist/installer.js.map +1 -1
- package/dist/mvp-config.d.ts +33 -0
- package/dist/mvp-config.d.ts.map +1 -1
- package/dist/mvp-config.js +174 -0
- package/dist/mvp-config.js.map +1 -1
- package/package.json +1 -1
- package/pd-cli/dist/commands/config-doctor.d.ts +17 -0
- package/pd-cli/dist/commands/config-doctor.d.ts.map +1 -0
- package/pd-cli/dist/commands/config-doctor.js +143 -0
- package/pd-cli/dist/commands/config-doctor.js.map +1 -0
- package/pd-cli/dist/commands/console.d.ts +18 -0
- package/pd-cli/dist/commands/console.d.ts.map +1 -1
- package/pd-cli/dist/commands/console.js +439 -0
- package/pd-cli/dist/commands/console.js.map +1 -1
- package/pd-cli/dist/commands/runtime-features.d.ts +23 -8
- package/pd-cli/dist/commands/runtime-features.d.ts.map +1 -1
- package/pd-cli/dist/commands/runtime-features.js +72 -31
- package/pd-cli/dist/commands/runtime-features.js.map +1 -1
- package/pd-cli/dist/index.d.ts +1 -1
- package/pd-cli/dist/index.js +83 -31
- package/pd-cli/dist/index.js.map +1 -1
- package/pd-cli/dist/services/config-doctor.d.ts +102 -0
- package/pd-cli/dist/services/config-doctor.d.ts.map +1 -0
- package/pd-cli/dist/services/config-doctor.js +426 -0
- package/pd-cli/dist/services/config-doctor.js.map +1 -0
- package/pd-cli/dist/services/console-launcher.d.ts +110 -0
- package/pd-cli/dist/services/console-launcher.d.ts.map +1 -0
- package/pd-cli/dist/services/console-launcher.js +282 -0
- package/pd-cli/dist/services/console-launcher.js.map +1 -0
- package/pd-cli/dist/services/pd-config-loader.d.ts +64 -0
- package/pd-cli/dist/services/pd-config-loader.d.ts.map +1 -0
- package/pd-cli/dist/services/pd-config-loader.js +156 -0
- package/pd-cli/dist/services/pd-config-loader.js.map +1 -0
- package/pd-cli/package.json +3 -1
- package/plugin/dist/core/event-log.d.ts +10 -0
- package/plugin/dist/core/event-log.js +85 -1
- package/plugin/dist/core/pd-config-loader.d.ts +96 -0
- package/plugin/dist/core/pd-config-loader.js +307 -0
- package/plugin/dist/core/runtime-v2-prompt-activation-reader.d.ts +4 -0
- package/plugin/dist/core/runtime-v2-prompt-activation-reader.js +12 -56
- package/plugin/dist/core/surface-guard.d.ts +12 -8
- package/plugin/dist/core/surface-guard.js +51 -2
- package/plugin/dist/hooks/gate.js +3 -0
- package/plugin/dist/index.d.ts +4 -0
- package/plugin/dist/index.js +8 -52
- package/plugin/dist/service/correction-observer-service.d.ts +8 -0
- package/plugin/dist/service/correction-observer-service.js +48 -29
|
@@ -1,4 +1,42 @@
|
|
|
1
1
|
import { PLUGIN_SURFACE_REGISTRY, validateSurfaceRegistry, getSurfacesByCategory, } from '@principles/core/runtime-v2';
|
|
2
|
+
// Surface-level once-only log state (PRI-298).
|
|
3
|
+
// The first time a quiet/non-core surface guard actually fires in this
|
|
4
|
+
// process, the disabled reason is emitted once. Subsequent fires for the
|
|
5
|
+
// same surfaceId are still observable (the no-op handler preserves
|
|
6
|
+
// behaviour) but no longer flood the log. Fresh processes start with an
|
|
7
|
+
// empty set, so each plugin load gets one observable skip per surface.
|
|
8
|
+
//
|
|
9
|
+
// The Set is only updated when the log was actually emitted, so passing
|
|
10
|
+
// `undefined` for the logger on a quiet first fire does NOT consume the
|
|
11
|
+
// one-shot slot — a later registration that supplies a logger still gets
|
|
12
|
+
// the first-fire reason (PRI-298 / ERR-002).
|
|
13
|
+
const loggedSkipSurfaces = new Set();
|
|
14
|
+
/**
|
|
15
|
+
* Emit the disabled-reason log line for `surfaceId` at most once per
|
|
16
|
+
* process. Returns true if the log was emitted, false if it was suppressed
|
|
17
|
+
* (already logged, or no logger available). Only marks the surface as
|
|
18
|
+
* logged when the log was actually written, so a missing logger on first
|
|
19
|
+
* call does not consume the one-shot slot.
|
|
20
|
+
*/
|
|
21
|
+
function logSkipOnce(surfaceId, logger, message) {
|
|
22
|
+
if (loggedSkipSurfaces.has(surfaceId)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
if (!logger?.info) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
loggedSkipSurfaces.add(surfaceId);
|
|
29
|
+
logger.info(message);
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Reset the per-process surface-guard skip log bookkeeping. Intended for tests
|
|
34
|
+
* that need to assert on the first-fire log without cross-test pollution.
|
|
35
|
+
* Not part of the production API surface; do not call from runtime code.
|
|
36
|
+
*/
|
|
37
|
+
export function __resetSurfaceGuardSkipLogStateForTests() {
|
|
38
|
+
loggedSkipSurfaces.clear();
|
|
39
|
+
}
|
|
2
40
|
export function checkSurfaceGuard() {
|
|
3
41
|
const validation = validateSurfaceRegistry(PLUGIN_SURFACE_REGISTRY);
|
|
4
42
|
const violations = [];
|
|
@@ -65,8 +103,15 @@ export function guardHook(surfaceId, logger, handler) {
|
|
|
65
103
|
return handler;
|
|
66
104
|
}
|
|
67
105
|
const reason = check.reason ?? 'surface not enabled';
|
|
106
|
+
// Log on the first ACTUAL no-op invocation, not at construction time
|
|
107
|
+
// (PRI-298). Construction-time logging would emit a `SKIP` line at
|
|
108
|
+
// plugin startup for every registered quiet hook, regardless of
|
|
109
|
+
// whether the hook ever fires — which is exactly the startup log
|
|
110
|
+
// noise this change is meant to prevent. The one-shot is consumed only
|
|
111
|
+
// when the log was actually written, so `undefined` logger on first
|
|
112
|
+
// call does not eat the slot.
|
|
68
113
|
return (_event, _ctx) => {
|
|
69
|
-
logger
|
|
114
|
+
logSkipOnce(surfaceId, logger, `[PD:surface-guard] SKIP ${surfaceId}: ${reason}`);
|
|
70
115
|
return undefined;
|
|
71
116
|
};
|
|
72
117
|
}
|
|
@@ -76,7 +121,11 @@ export function guardService(surfaceId, service, logger) {
|
|
|
76
121
|
return service;
|
|
77
122
|
}
|
|
78
123
|
const reason = check.reason ?? 'surface not enabled';
|
|
79
|
-
|
|
124
|
+
// guardService is called once per service during plugin registration,
|
|
125
|
+
// so the once-only check fires on the registration call itself. The
|
|
126
|
+
// shared helper makes the consumption rule identical to guardHook:
|
|
127
|
+
// a missing logger on first call does not consume the one-shot.
|
|
128
|
+
logSkipOnce(surfaceId, logger, `[PD:surface-guard] SKIP service ${surfaceId}: ${reason}`);
|
|
80
129
|
return null;
|
|
81
130
|
}
|
|
82
131
|
export { PLUGIN_SURFACE_REGISTRY, validateSurfaceRegistry, getSurfacesByCategory };
|
|
@@ -316,6 +316,9 @@ export function handleBeforeToolCall(event, ctx) {
|
|
|
316
316
|
// ---------------------------------------------------------------------------
|
|
317
317
|
function _extractParamsSummary(params) {
|
|
318
318
|
const summary = {};
|
|
319
|
+
// NOTE: Do NOT redact here — this feeds into RuleHost.evaluate() which
|
|
320
|
+
// may match against paramsSummary.command. Redaction happens at
|
|
321
|
+
// EventLog.record() before persistence.
|
|
319
322
|
if (params.file_path)
|
|
320
323
|
summary.file_path = params.file_path;
|
|
321
324
|
if (params.path)
|
package/plugin/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { OpenClawPluginApi } from './openclaw-sdk.js';
|
|
2
2
|
declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
3
|
+
/**
|
|
4
|
+
* PRI-305/PRI-307: Load feature flag from .pd/config.yaml instead of .pd/feature-flags.yaml.
|
|
5
|
+
* Delegates to the shared plugin config loader for consistency.
|
|
6
|
+
*/
|
|
3
7
|
declare function loadFeatureFlagFromWorkspace(workspaceDir: string, flagId: string, logger?: {
|
|
4
8
|
warn?: (msg: string) => void;
|
|
5
9
|
info?: (msg: string) => void;
|
package/plugin/dist/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
|
-
import
|
|
3
|
-
import * as yaml from 'js-yaml';
|
|
4
|
-
import { computeEffectiveFlags, DEFAULT_FEATURE_FLAGS } from '@principles/core/runtime-v2';
|
|
2
|
+
import { loadFeatureFlagFromConfig } from './core/pd-config-loader.js';
|
|
5
3
|
import { classifyTask } from './core/local-worker-routing.js';
|
|
6
4
|
import { completeShadowObservation, recordShadowRouting } from './core/shadow-observation-registry.js';
|
|
7
5
|
import { getCommandDescription } from './i18n/commands.js';
|
|
@@ -52,57 +50,15 @@ const pendingShadowObservations = new Map();
|
|
|
52
50
|
// ── Feature Flag Loader (plugin I/O boundary) ─────────────────────────────
|
|
53
51
|
// Reads workspace feature-flags.yaml and checks a specific flag.
|
|
54
52
|
// Returns the flag definition with effective enabled state.
|
|
55
|
-
const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
56
53
|
function isRecord(value) {
|
|
57
54
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
58
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* PRI-305/PRI-307: Load feature flag from .pd/config.yaml instead of .pd/feature-flags.yaml.
|
|
58
|
+
* Delegates to the shared plugin config loader for consistency.
|
|
59
|
+
*/
|
|
59
60
|
function loadFeatureFlagFromWorkspace(workspaceDir, flagId, logger) {
|
|
60
|
-
|
|
61
|
-
if (!fs.existsSync(configPath)) {
|
|
62
|
-
const flags = computeEffectiveFlags({}, DEFAULT_FEATURE_FLAGS, configPath);
|
|
63
|
-
const flag = flags.flags[flagId];
|
|
64
|
-
return { enabled: flag?.enabled ?? false, source: 'defaults' };
|
|
65
|
-
}
|
|
66
|
-
let raw;
|
|
67
|
-
try {
|
|
68
|
-
raw = fs.readFileSync(configPath, 'utf8');
|
|
69
|
-
}
|
|
70
|
-
catch (e) {
|
|
71
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
72
|
-
logger?.warn?.(`[PD:FeatureFlags] Feature flags unreadable: ${msg} — using defaults`);
|
|
73
|
-
const flags = computeEffectiveFlags({}, DEFAULT_FEATURE_FLAGS, configPath);
|
|
74
|
-
const flag = flags.flags[flagId];
|
|
75
|
-
return { enabled: flag?.enabled ?? false, source: 'defaults' };
|
|
76
|
-
}
|
|
77
|
-
let parsed;
|
|
78
|
-
try {
|
|
79
|
-
parsed = yaml.load(raw, { schema: yaml.JSON_SCHEMA });
|
|
80
|
-
}
|
|
81
|
-
catch (e) {
|
|
82
|
-
const parseMsg = e instanceof Error ? e.message : String(e);
|
|
83
|
-
logger?.warn?.(`[PD:FeatureFlags] Feature flags YAML parse error: ${parseMsg} — using defaults`);
|
|
84
|
-
const flags = computeEffectiveFlags({}, DEFAULT_FEATURE_FLAGS, configPath);
|
|
85
|
-
const flag = flags.flags[flagId];
|
|
86
|
-
return { enabled: flag?.enabled ?? false, source: 'defaults' };
|
|
87
|
-
}
|
|
88
|
-
if (!isRecord(parsed)) {
|
|
89
|
-
logger?.warn?.(`[PD:FeatureFlags] Feature flags not a mapping — using defaults`);
|
|
90
|
-
const flags = computeEffectiveFlags({}, DEFAULT_FEATURE_FLAGS, configPath);
|
|
91
|
-
const flag = flags.flags[flagId];
|
|
92
|
-
return { enabled: flag?.enabled ?? false, source: 'defaults' };
|
|
93
|
-
}
|
|
94
|
-
// parsed is now narrowed to Record<string, unknown> by isRecord guard
|
|
95
|
-
const parsedRecord = Object.create(null);
|
|
96
|
-
for (const key of Object.keys(parsed)) {
|
|
97
|
-
if (DANGEROUS_KEYS.has(key))
|
|
98
|
-
continue;
|
|
99
|
-
if (Object.hasOwn(parsed, key)) {
|
|
100
|
-
parsedRecord[key] = parsed[key];
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
const flags = computeEffectiveFlags(parsedRecord, DEFAULT_FEATURE_FLAGS, configPath);
|
|
104
|
-
const flag = flags.flags[flagId];
|
|
105
|
-
return { enabled: flag?.enabled ?? false, source: flags.source };
|
|
61
|
+
return loadFeatureFlagFromConfig(workspaceDir, flagId, logger);
|
|
106
62
|
}
|
|
107
63
|
export function shouldStartEvolutionWorker(workspaceDir, logger) {
|
|
108
64
|
const flag = loadFeatureFlagFromWorkspace(workspaceDir, 'evolution_worker', logger);
|
|
@@ -111,7 +67,7 @@ export function shouldStartEvolutionWorker(workspaceDir, logger) {
|
|
|
111
67
|
}
|
|
112
68
|
const disabledInfo = JSON.stringify({
|
|
113
69
|
reason: 'mvp_quiet_per_adr0014',
|
|
114
|
-
nextAction: 'set evolution_worker.enabled=true in .pd/
|
|
70
|
+
nextAction: 'set features.evolution_worker.enabled=true in .pd/config.yaml to enable',
|
|
115
71
|
featureFlag: 'evolution_worker',
|
|
116
72
|
boundedContext: 'legacy_evolution_worker',
|
|
117
73
|
flagSource: flag.source,
|
|
@@ -125,7 +81,7 @@ export function shouldStartCorrectionObserver(workspaceDir, logger) {
|
|
|
125
81
|
}
|
|
126
82
|
const disabledInfo = JSON.stringify({
|
|
127
83
|
reason: 'correction_observer_disabled',
|
|
128
|
-
nextAction: 'set correction_observer.enabled=true in .pd/
|
|
84
|
+
nextAction: 'set features.correction_observer.enabled=true in .pd/config.yaml to enable',
|
|
129
85
|
featureFlag: 'correction_observer',
|
|
130
86
|
boundedContext: 'correction_observer_service',
|
|
131
87
|
flagSource: flag.source,
|
|
@@ -6,6 +6,14 @@ export interface CorrectionObserverServiceShape {
|
|
|
6
6
|
start: (ctx: OpenClawPluginServiceContext) => void;
|
|
7
7
|
stop?: (ctx: OpenClawPluginServiceContext) => void;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* PRI-307: Resolve CorrectionObserver from .pd/config.yaml.
|
|
11
|
+
*
|
|
12
|
+
* States:
|
|
13
|
+
* - disabled: feature flag off → return null, no noisy logs
|
|
14
|
+
* - needs_setup: enabled but missing API key or profile → return null with structured reason
|
|
15
|
+
* - ready/not_ready: enabled and configured → return observer instance
|
|
16
|
+
*/
|
|
9
17
|
export declare function resolveCorrectionObserver(wctx: WorkspaceContext, logger?: Pick<PluginLogger, 'info' | 'warn' | 'error' | 'debug'>): CorrectionObserver | null;
|
|
10
18
|
export declare function runCorrectionObserverCycle(wctx: WorkspaceContext, logger: PluginLogger): Promise<void>;
|
|
11
19
|
export declare const CorrectionObserverService: CorrectionObserverServiceShape;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
2
2
|
import { TrajectoryRegistry } from '../core/trajectory.js';
|
|
3
3
|
import { CorrectionCueLearner } from '../core/correction-cue-learner.js';
|
|
4
|
-
import {
|
|
4
|
+
import { PiAiRuntimeAdapter, CorrectionObserver, AgentScheduler, } from '@principles/core/runtime-v2';
|
|
5
5
|
import { KeywordOptimizationService } from './keyword-optimization-service.js';
|
|
6
6
|
import { SystemLogger } from '../core/system-logger.js';
|
|
7
|
+
import { resolveObserverConfig } from '../core/pd-config-loader.js';
|
|
7
8
|
let correctionObserverTimeoutId = null;
|
|
8
9
|
let correctionObserverStopped = false;
|
|
9
10
|
const startedWorkspaces = new Set();
|
|
@@ -11,40 +12,45 @@ const CORRECTION_OBSERVER_INTERVAL_MS = 15 * 60 * 1000;
|
|
|
11
12
|
const CORRECTION_OBSERVER_INITIAL_DELAY_MS = 10_000;
|
|
12
13
|
const CORRECTION_OBSERVER_MAX_RECENT_SESSIONS = 20;
|
|
13
14
|
const CORRECTION_OBSERVER_MAX_PAYLOAD_SESSIONS = 5;
|
|
15
|
+
/**
|
|
16
|
+
* PRI-307: Resolve CorrectionObserver from .pd/config.yaml.
|
|
17
|
+
*
|
|
18
|
+
* States:
|
|
19
|
+
* - disabled: feature flag off → return null, no noisy logs
|
|
20
|
+
* - needs_setup: enabled but missing API key or profile → return null with structured reason
|
|
21
|
+
* - ready/not_ready: enabled and configured → return observer instance
|
|
22
|
+
*/
|
|
14
23
|
export function resolveCorrectionObserver(wctx, logger) {
|
|
15
24
|
try {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
logger?.debug?.('[PD:CorrectionObserver] workflows.yaml pd-correction-observer policy not found. Falling back to environment variables.');
|
|
21
|
-
const provider = process.env.PD_CORRECTION_PROVIDER || 'anthropic';
|
|
22
|
-
const model = process.env.PD_CORRECTION_MODEL || 'anthropic/claude-3-5-sonnet';
|
|
23
|
-
const apiKeyEnv = process.env.PD_CORRECTION_API_KEY_ENV || 'ANTHROPIC_API_KEY';
|
|
24
|
-
const baseUrl = process.env.PD_CORRECTION_BASE_URL;
|
|
25
|
-
if (!process.env[apiKeyEnv]) {
|
|
26
|
-
logger?.debug?.(`[PD:CorrectionObserver] API key env ${apiKeyEnv} is not set. Periodic optimization disabled.`);
|
|
27
|
-
return null;
|
|
25
|
+
const observerConfig = resolveObserverConfig(wctx.workspaceDir, 'correction_observer', 'correctionObserver', logger);
|
|
26
|
+
if (!observerConfig.enabled) {
|
|
27
|
+
if (observerConfig.readiness === 'config_malformed') {
|
|
28
|
+
logger?.warn?.(`[PD:CorrectionObserver] Config malformed: ${observerConfig.reason}. ${observerConfig.nextAction}`);
|
|
28
29
|
}
|
|
30
|
+
else {
|
|
31
|
+
logger?.debug?.(`[PD:CorrectionObserver] ${observerConfig.reason}`);
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
if (observerConfig.readiness === 'needs_setup') {
|
|
36
|
+
logger?.info?.(`[PD:CorrectionObserver] ${observerConfig.reason}. ${observerConfig.nextAction}`);
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
// ready or not_ready — create the observer
|
|
40
|
+
if (observerConfig.runtimeProfileType === 'pi-ai') {
|
|
29
41
|
const adapter = new PiAiRuntimeAdapter({
|
|
30
|
-
provider,
|
|
31
|
-
model,
|
|
32
|
-
apiKeyEnv,
|
|
33
|
-
|
|
42
|
+
provider: observerConfig.provider ?? 'anthropic',
|
|
43
|
+
model: observerConfig.model ?? 'anthropic/claude-3-5-sonnet',
|
|
44
|
+
apiKeyEnv: observerConfig.apiKeyEnv ?? 'ANTHROPIC_API_KEY',
|
|
45
|
+
timeoutMs: observerConfig.timeoutMs ?? undefined,
|
|
46
|
+
baseUrl: observerConfig.baseUrl ?? undefined,
|
|
34
47
|
workspace: wctx.workspaceDir,
|
|
35
48
|
});
|
|
36
|
-
return new CorrectionObserver({ runtimeAdapter: adapter });
|
|
49
|
+
return new CorrectionObserver({ runtimeAdapter: adapter }, { timeoutMs: observerConfig.timeoutMs ?? undefined });
|
|
37
50
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
apiKeyEnv: String(policy.apiKeyEnv),
|
|
42
|
-
maxRetries: policy.maxRetries,
|
|
43
|
-
timeoutMs: policy.timeoutMs ?? 30_000,
|
|
44
|
-
baseUrl: policy.baseUrl,
|
|
45
|
-
workspace: wctx.workspaceDir,
|
|
46
|
-
});
|
|
47
|
-
return new CorrectionObserver({ runtimeAdapter: adapter }, { timeoutMs: policy.timeoutMs });
|
|
51
|
+
// OpenClaw profile — not yet supported for observer runtime
|
|
52
|
+
logger?.info?.(`[PD:CorrectionObserver] OpenClaw runtime profile not yet supported for correction observer. Skipping.`);
|
|
53
|
+
return null;
|
|
48
54
|
}
|
|
49
55
|
catch (err) {
|
|
50
56
|
logger?.warn?.(`[PD:CorrectionObserver] Failed to resolve CorrectionObserver: ${String(err)}`);
|
|
@@ -55,7 +61,8 @@ export async function runCorrectionObserverCycle(wctx, logger) {
|
|
|
55
61
|
try {
|
|
56
62
|
const observer = resolveCorrectionObserver(wctx, logger);
|
|
57
63
|
if (!observer) {
|
|
58
|
-
|
|
64
|
+
// PRI-307: No noisy "no API key" cycling. Only log at debug level.
|
|
65
|
+
logger?.debug?.(`[PD:CorrectionObserver] Observer not resolved. Skipping cycle.`);
|
|
59
66
|
return;
|
|
60
67
|
}
|
|
61
68
|
logger?.info?.('[PD:CorrectionObserver] Observer resolved. Initiating periodic optimization...');
|
|
@@ -135,6 +142,18 @@ export const CorrectionObserverService = {
|
|
|
135
142
|
logger.info(`[PD:CorrectionObserver] Already started for workspace: ${workspaceDir}. Skipping duplicate start.`);
|
|
136
143
|
return;
|
|
137
144
|
}
|
|
145
|
+
// PRI-307: Check observer config before starting
|
|
146
|
+
const observerConfig = resolveObserverConfig(workspaceDir, 'correction_observer', 'correctionObserver', logger);
|
|
147
|
+
if (!observerConfig.enabled) {
|
|
148
|
+
// Disabled → no start, no noisy cycling. Single structured log.
|
|
149
|
+
logger?.info?.(`[PD:CorrectionObserver] ${observerConfig.reason}. ${observerConfig.nextAction}`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (observerConfig.readiness === 'needs_setup') {
|
|
153
|
+
// Enabled but missing setup → structured needs_setup, no noisy cycling
|
|
154
|
+
logger?.info?.(`[PD:CorrectionObserver] ${observerConfig.reason}. ${observerConfig.nextAction}`);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
138
157
|
startedWorkspaces.add(workspaceDir);
|
|
139
158
|
correctionObserverStopped = false;
|
|
140
159
|
const wctx = WorkspaceContext.fromHookContext({ workspaceDir, ...ctx.config });
|