create-principles-disciple 1.76.0 → 1.78.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/console/dist/server/config/feature-flags.d.ts +25 -0
- package/console/dist/server/config/feature-flags.js +101 -0
- package/console/dist/server/index.js +16 -0
- package/console/dist/server/models/FeedbackReportConsoleModel.d.ts +49 -0
- package/console/dist/server/models/FeedbackReportConsoleModel.js +242 -0
- package/console/dist/server/routes/feedback-reports.d.ts +18 -0
- package/console/dist/server/routes/feedback-reports.js +165 -0
- package/console/dist/ui/App.js +2 -1
- package/console/dist/ui/api.d.ts +26 -2
- package/console/dist/ui/api.js +18 -1
- package/console/dist/ui/components/app-sidebar.js +2 -1
- package/console/dist/ui/components/error-boundary.js +9 -2
- package/console/dist/ui/i18n/en.json +67 -1
- package/console/dist/ui/i18n/zh-CN.json +67 -1
- package/console/dist/ui/pages/ReportProblemPage.d.ts +1 -0
- package/console/dist/ui/pages/ReportProblemPage.js +186 -0
- package/console/dist/ui/pages/ReportProblemValidators.d.ts +51 -0
- package/console/dist/ui/pages/ReportProblemValidators.js +114 -0
- package/console/dist/web/assets/app.css +18 -0
- package/console/dist/web/assets/app.js +1047 -125
- package/console/package.json +1 -0
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +24 -1
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/feedback/create-report.test.d.ts +2 -0
- package/core/dist/runtime-v2/__tests__/feedback/create-report.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/feedback/create-report.test.js +402 -0
- package/core/dist/runtime-v2/__tests__/feedback/create-report.test.js.map +1 -0
- package/core/dist/runtime-v2/__tests__/feedback/privacy-preview.test.d.ts +2 -0
- package/core/dist/runtime-v2/__tests__/feedback/privacy-preview.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/feedback/privacy-preview.test.js +128 -0
- package/core/dist/runtime-v2/__tests__/feedback/privacy-preview.test.js.map +1 -0
- package/core/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.d.ts +2 -0
- package/core/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.js +231 -0
- package/core/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.js.map +1 -0
- package/core/dist/runtime-v2/__tests__/feedback/render-github-url.test.d.ts +2 -0
- package/core/dist/runtime-v2/__tests__/feedback/render-github-url.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/feedback/render-github-url.test.js +102 -0
- package/core/dist/runtime-v2/__tests__/feedback/render-github-url.test.js.map +1 -0
- package/core/dist/runtime-v2/__tests__/feedback/render-markdown.test.d.ts +2 -0
- package/core/dist/runtime-v2/__tests__/feedback/render-markdown.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/feedback/render-markdown.test.js +130 -0
- package/core/dist/runtime-v2/__tests__/feedback/render-markdown.test.js.map +1 -0
- package/core/dist/runtime-v2/__tests__/workspace-guidance-migration.test.d.ts +2 -0
- package/core/dist/runtime-v2/__tests__/workspace-guidance-migration.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/workspace-guidance-migration.test.js +328 -0
- package/core/dist/runtime-v2/__tests__/workspace-guidance-migration.test.js.map +1 -0
- package/core/dist/runtime-v2/activation/__tests__/prompt-activation-reader-contract.test.d.ts +2 -0
- package/core/dist/runtime-v2/activation/__tests__/prompt-activation-reader-contract.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/activation/__tests__/prompt-activation-reader-contract.test.js +343 -0
- package/core/dist/runtime-v2/activation/__tests__/prompt-activation-reader-contract.test.js.map +1 -0
- package/core/dist/runtime-v2/activation/index.d.ts +2 -0
- package/core/dist/runtime-v2/activation/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/index.js +1 -0
- package/core/dist/runtime-v2/activation/index.js.map +1 -1
- package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.d.ts +34 -0
- package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.d.ts.map +1 -0
- package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.js +109 -0
- package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.js.map +1 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +13 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
- package/core/dist/runtime-v2/feature-flags/__tests__/plugin-surface-registry.test.d.ts +2 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/plugin-surface-registry.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/plugin-surface-registry.test.js +141 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/plugin-surface-registry.test.js.map +1 -0
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +4 -1
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
- package/core/dist/runtime-v2/feature-flags/index.d.ts +2 -0
- package/core/dist/runtime-v2/feature-flags/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/feature-flags/index.js +1 -0
- package/core/dist/runtime-v2/feature-flags/index.js.map +1 -1
- package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.d.ts +25 -0
- package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.d.ts.map +1 -0
- package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js +233 -0
- package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js.map +1 -0
- package/core/dist/runtime-v2/feedback/create-report.d.ts +14 -0
- package/core/dist/runtime-v2/feedback/create-report.d.ts.map +1 -0
- package/core/dist/runtime-v2/feedback/create-report.js +257 -0
- package/core/dist/runtime-v2/feedback/create-report.js.map +1 -0
- package/core/dist/runtime-v2/feedback/feedback-types.d.ts +120 -0
- package/core/dist/runtime-v2/feedback/feedback-types.d.ts.map +1 -0
- package/core/dist/runtime-v2/feedback/feedback-types.js +243 -0
- package/core/dist/runtime-v2/feedback/feedback-types.js.map +1 -0
- package/core/dist/runtime-v2/feedback/index.d.ts +9 -0
- package/core/dist/runtime-v2/feedback/index.d.ts.map +1 -0
- package/core/dist/runtime-v2/feedback/index.js +11 -0
- package/core/dist/runtime-v2/feedback/index.js.map +1 -0
- package/core/dist/runtime-v2/feedback/internal-guards.d.ts +2 -0
- package/core/dist/runtime-v2/feedback/internal-guards.d.ts.map +1 -0
- package/core/dist/runtime-v2/feedback/internal-guards.js +6 -0
- package/core/dist/runtime-v2/feedback/internal-guards.js.map +1 -0
- package/core/dist/runtime-v2/feedback/privacy-preview.d.ts +14 -0
- package/core/dist/runtime-v2/feedback/privacy-preview.d.ts.map +1 -0
- package/core/dist/runtime-v2/feedback/privacy-preview.js +128 -0
- package/core/dist/runtime-v2/feedback/privacy-preview.js.map +1 -0
- package/core/dist/runtime-v2/feedback/redact-sensitive.d.ts +37 -0
- package/core/dist/runtime-v2/feedback/redact-sensitive.d.ts.map +1 -0
- package/core/dist/runtime-v2/feedback/redact-sensitive.js +272 -0
- package/core/dist/runtime-v2/feedback/redact-sensitive.js.map +1 -0
- package/core/dist/runtime-v2/feedback/render-github-url.d.ts +21 -0
- package/core/dist/runtime-v2/feedback/render-github-url.d.ts.map +1 -0
- package/core/dist/runtime-v2/feedback/render-github-url.js +57 -0
- package/core/dist/runtime-v2/feedback/render-github-url.js.map +1 -0
- package/core/dist/runtime-v2/feedback/render-markdown.d.ts +12 -0
- package/core/dist/runtime-v2/feedback/render-markdown.d.ts.map +1 -0
- package/core/dist/runtime-v2/feedback/render-markdown.js +166 -0
- package/core/dist/runtime-v2/feedback/render-markdown.js.map +1 -0
- package/core/dist/runtime-v2/feedback/safe-stringify.d.ts +6 -0
- package/core/dist/runtime-v2/feedback/safe-stringify.d.ts.map +1 -0
- package/core/dist/runtime-v2/feedback/safe-stringify.js +115 -0
- package/core/dist/runtime-v2/feedback/safe-stringify.js.map +1 -0
- package/core/dist/runtime-v2/index.d.ts +8 -1
- package/core/dist/runtime-v2/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/index.js +12 -1
- package/core/dist/runtime-v2/index.js.map +1 -1
- package/core/dist/runtime-v2/workspace-guidance-migration.d.ts +12 -0
- package/core/dist/runtime-v2/workspace-guidance-migration.d.ts.map +1 -0
- package/core/dist/runtime-v2/workspace-guidance-migration.js +193 -0
- package/core/dist/runtime-v2/workspace-guidance-migration.js.map +1 -0
- package/core/package.json +4 -0
- package/package.json +1 -1
- package/plugin/dist/commands/context.js +5 -5
- package/plugin/dist/commands/strategy.d.ts +0 -1
- package/plugin/dist/commands/strategy.js +0 -14
- package/plugin/dist/core/runtime-v2-prompt-activation-reader.d.ts +4 -13
- package/plugin/dist/core/runtime-v2-prompt-activation-reader.js +36 -74
- package/plugin/dist/core/surface-guard.d.ts +27 -0
- package/plugin/dist/core/surface-guard.js +82 -0
- package/plugin/dist/core/workspace-guidance-migrator.d.ts +12 -0
- package/plugin/dist/core/workspace-guidance-migrator.js +141 -0
- package/plugin/dist/hooks/prompt.js +20 -143
- package/plugin/dist/i18n/commands.js +2 -14
- package/plugin/dist/index.d.ts +27 -0
- package/plugin/dist/index.js +180 -65
- package/plugin/dist/service/correction-observer-service.d.ts +11 -0
- package/plugin/dist/service/correction-observer-service.js +172 -0
- package/plugin/dist/service/evolution-worker.js +1 -110
- package/plugin/dist/types.d.ts +2 -2
- package/plugin/dist/types.js +3 -3
- package/plugin/templates/langs/en/core/BOOTSTRAP.md +5 -19
- package/plugin/templates/langs/en/principles/THINKING_OS.md +1 -1
- package/plugin/templates/langs/en/skills/admin/SKILL.md +2 -2
- package/plugin/templates/langs/en/skills/bootstrap-tools/SKILL.md +1 -1
- package/plugin/templates/langs/en/skills/init-strategy/SKILL.md +1 -1
- package/plugin/templates/langs/en/skills/pd-mentor/SKILL.md +8 -23
- package/plugin/templates/langs/en/skills/reflection/SKILL.md +2 -2
- package/plugin/templates/langs/en/skills/report/SKILL.md +1 -1
- package/plugin/templates/langs/zh/core/BOOTSTRAP.md +3 -16
- package/plugin/templates/langs/zh/principles/THINKING_OS.md +1 -1
- package/plugin/templates/langs/zh/skills/admin/SKILL.md +2 -2
- package/plugin/templates/langs/zh/skills/bootstrap-tools/SKILL.md +1 -1
- package/plugin/templates/langs/zh/skills/init-strategy/SKILL.md +1 -1
- package/plugin/templates/langs/zh/skills/pd-mentor/SKILL.md +7 -22
- package/plugin/templates/langs/zh/skills/reflection/SKILL.md +2 -2
- package/plugin/templates/langs/zh/skills/report/SKILL.md +1 -1
- package/plugin/templates/workspace/.principles/THINKING_OS.md +1 -1
- package/templates/langs/en/core/BOOTSTRAP.md +1 -1
- package/templates/langs/en/principles/THINKING_OS.md +1 -1
- package/templates/langs/en/skills/admin/SKILL.md +2 -2
- package/templates/langs/en/skills/pd-grooming/SKILL.md +1 -1
- package/templates/langs/en/skills/reflection/SKILL.md +2 -2
- package/templates/langs/en/skills/report/SKILL.md +1 -1
- package/templates/langs/zh/core/BOOTSTRAP.md +1 -1
- package/templates/langs/zh/principles/THINKING_OS.md +1 -1
- package/templates/langs/zh/skills/admin/SKILL.md +2 -2
- package/templates/langs/zh/skills/pd-grooming/SKILL.md +1 -1
- package/templates/langs/zh/skills/reflection/SKILL.md +2 -2
- package/templates/langs/zh/skills/report/SKILL.md +1 -1
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/EXAMPLES.md +0 -63
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/REFERENCE.md +0 -136
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/SKILL.md +0 -67
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/references/agent-registry.json +0 -143
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +0 -107
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +0 -107
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +0 -95
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +0 -98
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +0 -58
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +0 -190
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +0 -310
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +0 -683
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +0 -604
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +0 -32
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +0 -707
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/scripts/run.mjs +0 -3455
- package/plugin/templates/langs/en/skills/evolve-system/SKILL.md +0 -46
- package/plugin/templates/langs/en/skills/manage-okr/SKILL.md +0 -96
- package/plugin/templates/langs/en/skills/pd-daily/SKILL.md +0 -199
- package/plugin/templates/langs/en/skills/pd-grooming/SKILL.md +0 -46
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/EXAMPLES.md +0 -63
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/REFERENCE.md +0 -136
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/SKILL.md +0 -67
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/references/agent-registry.json +0 -143
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +0 -107
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +0 -107
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/nocturnal-trinity-quality-enhancement.json +0 -111
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +0 -95
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +0 -98
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +0 -58
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +0 -190
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/runtime/.gitignore +0 -2
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +0 -310
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +0 -683
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +0 -604
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +0 -32
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +0 -707
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +0 -3455
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/test/archive.test.mjs +0 -230
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/test/contract-enforcement.test.mjs +0 -672
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/test/decision.test.mjs +0 -1321
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/test/run.test.mjs +0 -1435
- package/plugin/templates/langs/zh/skills/evolve-system/SKILL.md +0 -46
- package/plugin/templates/langs/zh/skills/manage-okr/SKILL.md +0 -109
- package/plugin/templates/langs/zh/skills/pd-daily/SKILL.md +0 -283
- package/plugin/templates/langs/zh/skills/pd-grooming/SKILL.md +0 -46
- package/plugin/templates/workspace/PLAN.md +0 -2
- package/templates/workspace/PLAN.md +0 -2
package/plugin/dist/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as yaml from 'js-yaml';
|
|
4
|
+
import { computeEffectiveFlags, DEFAULT_FEATURE_FLAGS } from '@principles/core/runtime-v2';
|
|
2
5
|
import { classifyTask } from './core/local-worker-routing.js';
|
|
3
6
|
import { completeShadowObservation, recordShadowRouting } from './core/shadow-observation-registry.js';
|
|
4
7
|
import { getCommandDescription } from './i18n/commands.js';
|
|
@@ -10,7 +13,7 @@ import { handleBeforeReset, handleBeforeCompaction, handleAfterCompaction } from
|
|
|
10
13
|
import { handleLlmOutput } from './hooks/llm.js';
|
|
11
14
|
import { handleSubagentEnded } from './hooks/subagent.js';
|
|
12
15
|
import * as TrajectoryCollector from './hooks/trajectory-collector.js';
|
|
13
|
-
import { handleInitStrategy
|
|
16
|
+
import { handleInitStrategy } from './commands/strategy.js';
|
|
14
17
|
import { handleBootstrapTools, handleResearchTools } from './commands/capabilities.js';
|
|
15
18
|
import { handleThinkingOs } from './commands/thinking-os.js';
|
|
16
19
|
import { handlePainCommand, handlePainReportCommand } from './commands/pain.js';
|
|
@@ -27,26 +30,110 @@ import { handleExportCommand } from './commands/export.js';
|
|
|
27
30
|
import { handleSamplesCommand } from './commands/samples.js';
|
|
28
31
|
import { handleWorkflowDebugCommand } from './commands/workflow-debug.js';
|
|
29
32
|
import { EvolutionWorkerService } from './service/evolution-worker.js';
|
|
33
|
+
import { CorrectionObserverService } from './service/correction-observer-service.js';
|
|
30
34
|
import { TrajectoryService } from './service/trajectory-service.js';
|
|
31
35
|
import { PDTaskService } from './core/pd-task-service.js';
|
|
32
36
|
import { CentralSyncService } from './service/central-sync-service.js';
|
|
33
37
|
import { ensureWorkspaceTemplates } from './core/init.js';
|
|
34
38
|
import { migrateDirectoryStructure } from './core/migration.js';
|
|
39
|
+
import { migrateStaleWorkspaceGuidance } from './core/workspace-guidance-migrator.js';
|
|
35
40
|
import { SystemLogger } from './core/system-logger.js';
|
|
36
41
|
import { PathResolver } from './core/path-resolver.js';
|
|
37
42
|
import { resolveCommandWorkspaceDir, resolveToolHookWorkspaceDirSafe } from './utils/workspace-resolver.js';
|
|
38
43
|
import { computeRuntimeShadowTaskFingerprint, PD_LOCAL_PROFILES } from './utils/shadow-fingerprint.js';
|
|
39
44
|
import { validateWorkspaceDir } from './core/workspace-dir-validation.js';
|
|
40
45
|
import { resolveWorkspaceDirFromApi } from './core/path-resolver.js';
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// Track started evolution workers — one per workspace
|
|
46
|
+
import { checkSurfaceGuard, guardHook, guardService } from './core/surface-guard.js';
|
|
47
|
+
// Track started workspaces — one-time init + evolution worker per workspace
|
|
44
48
|
const startedWorkspaces = new Set();
|
|
45
49
|
const HOOK_WORKSPACE_RESOLUTION_NEXT_ACTION = 'verify gateway plugin activation and hook workspace binding; ' +
|
|
46
50
|
'migrate live hook workspace resolution to PD-owned canonical configuration before relying on config-based recovery';
|
|
47
51
|
// Map from childSessionKey → shadowObservationId
|
|
48
52
|
// Used to complete shadow observations when subagent ends
|
|
49
53
|
const pendingShadowObservations = new Map();
|
|
54
|
+
// ── Feature Flag Loader (plugin I/O boundary) ─────────────────────────────
|
|
55
|
+
// Reads workspace feature-flags.yaml and checks a specific flag.
|
|
56
|
+
// Returns the flag definition with effective enabled state.
|
|
57
|
+
const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
58
|
+
function isRecord(value) {
|
|
59
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
60
|
+
}
|
|
61
|
+
function loadFeatureFlagFromWorkspace(workspaceDir, flagId, logger) {
|
|
62
|
+
const configPath = path.join(workspaceDir, '.pd', 'feature-flags.yaml');
|
|
63
|
+
if (!fs.existsSync(configPath)) {
|
|
64
|
+
const flags = computeEffectiveFlags({}, DEFAULT_FEATURE_FLAGS, configPath);
|
|
65
|
+
const flag = flags.flags[flagId];
|
|
66
|
+
return { enabled: flag?.enabled ?? false, source: 'defaults' };
|
|
67
|
+
}
|
|
68
|
+
let raw;
|
|
69
|
+
try {
|
|
70
|
+
raw = fs.readFileSync(configPath, 'utf8');
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
74
|
+
logger?.warn?.(`[PD:FeatureFlags] Feature flags unreadable: ${msg} — using defaults`);
|
|
75
|
+
const flags = computeEffectiveFlags({}, DEFAULT_FEATURE_FLAGS, configPath);
|
|
76
|
+
const flag = flags.flags[flagId];
|
|
77
|
+
return { enabled: flag?.enabled ?? false, source: 'defaults' };
|
|
78
|
+
}
|
|
79
|
+
let parsed;
|
|
80
|
+
try {
|
|
81
|
+
parsed = yaml.load(raw, { schema: yaml.JSON_SCHEMA });
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
const parseMsg = e instanceof Error ? e.message : String(e);
|
|
85
|
+
logger?.warn?.(`[PD:FeatureFlags] Feature flags YAML parse error: ${parseMsg} — using defaults`);
|
|
86
|
+
const flags = computeEffectiveFlags({}, DEFAULT_FEATURE_FLAGS, configPath);
|
|
87
|
+
const flag = flags.flags[flagId];
|
|
88
|
+
return { enabled: flag?.enabled ?? false, source: 'defaults' };
|
|
89
|
+
}
|
|
90
|
+
if (!isRecord(parsed)) {
|
|
91
|
+
logger?.warn?.(`[PD:FeatureFlags] Feature flags not a mapping — using defaults`);
|
|
92
|
+
const flags = computeEffectiveFlags({}, DEFAULT_FEATURE_FLAGS, configPath);
|
|
93
|
+
const flag = flags.flags[flagId];
|
|
94
|
+
return { enabled: flag?.enabled ?? false, source: 'defaults' };
|
|
95
|
+
}
|
|
96
|
+
// parsed is now narrowed to Record<string, unknown> by isRecord guard
|
|
97
|
+
const parsedRecord = Object.create(null);
|
|
98
|
+
for (const key of Object.keys(parsed)) {
|
|
99
|
+
if (DANGEROUS_KEYS.has(key))
|
|
100
|
+
continue;
|
|
101
|
+
if (Object.hasOwn(parsed, key)) {
|
|
102
|
+
parsedRecord[key] = parsed[key];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const flags = computeEffectiveFlags(parsedRecord, DEFAULT_FEATURE_FLAGS, configPath);
|
|
106
|
+
const flag = flags.flags[flagId];
|
|
107
|
+
return { enabled: flag?.enabled ?? false, source: flags.source };
|
|
108
|
+
}
|
|
109
|
+
export function shouldStartEvolutionWorker(workspaceDir, logger) {
|
|
110
|
+
const flag = loadFeatureFlagFromWorkspace(workspaceDir, 'evolution_worker', logger);
|
|
111
|
+
if (flag.enabled) {
|
|
112
|
+
return { shouldStart: true, flagSource: flag.source, disabledInfo: null };
|
|
113
|
+
}
|
|
114
|
+
const disabledInfo = JSON.stringify({
|
|
115
|
+
reason: 'mvp_quiet_per_adr0014',
|
|
116
|
+
nextAction: 'set evolution_worker.enabled=true in .pd/feature-flags.yaml to enable',
|
|
117
|
+
featureFlag: 'evolution_worker',
|
|
118
|
+
boundedContext: 'legacy_evolution_worker',
|
|
119
|
+
flagSource: flag.source,
|
|
120
|
+
});
|
|
121
|
+
return { shouldStart: false, flagSource: flag.source, disabledInfo };
|
|
122
|
+
}
|
|
123
|
+
export function shouldStartCorrectionObserver(workspaceDir, logger) {
|
|
124
|
+
const flag = loadFeatureFlagFromWorkspace(workspaceDir, 'correction_observer', logger);
|
|
125
|
+
if (flag.enabled) {
|
|
126
|
+
return { shouldStart: true, flagSource: flag.source, disabledInfo: null };
|
|
127
|
+
}
|
|
128
|
+
const disabledInfo = JSON.stringify({
|
|
129
|
+
reason: 'correction_observer_disabled',
|
|
130
|
+
nextAction: 'set correction_observer.enabled=true in .pd/feature-flags.yaml to enable',
|
|
131
|
+
featureFlag: 'correction_observer',
|
|
132
|
+
boundedContext: 'correction_observer_service',
|
|
133
|
+
flagSource: flag.source,
|
|
134
|
+
});
|
|
135
|
+
return { shouldStart: false, flagSource: flag.source, disabledInfo };
|
|
136
|
+
}
|
|
50
137
|
const plugin = {
|
|
51
138
|
name: "Principles Disciple",
|
|
52
139
|
description: "Evolutionary programming agent framework with strategic guardrails and reflection loops.",
|
|
@@ -68,9 +155,21 @@ const plugin = {
|
|
|
68
155
|
}
|
|
69
156
|
}, 1000);
|
|
70
157
|
healthCheckTimer.unref(); // Don't keep process alive for health check
|
|
158
|
+
// ── MVP Surface Guard (PRI-289): Verify surface classification ──
|
|
159
|
+
const surfaceGuard = checkSurfaceGuard();
|
|
160
|
+
if (!surfaceGuard.passed) {
|
|
161
|
+
for (const violation of surfaceGuard.violations) {
|
|
162
|
+
api.logger.error(`[PD:surface-guard] VIOLATION: ${violation}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
api.logger.info(`[PD:surface-guard] Core surfaces: ${surfaceGuard.enabledCoreSurfaces.join(', ')}`);
|
|
166
|
+
api.logger.info(`[PD:surface-guard] Disabled non-core surfaces: ${surfaceGuard.disabledNonCoreSurfaces.length}`);
|
|
167
|
+
for (const warning of surfaceGuard.warnings) {
|
|
168
|
+
api.logger.warn(`[PD:surface-guard] ${warning}`);
|
|
169
|
+
}
|
|
71
170
|
const language = api.pluginConfig?.language || 'en';
|
|
72
171
|
// ── Hook: Prompt Building ──
|
|
73
|
-
api.on('before_prompt_build', async (event, ctx) => {
|
|
172
|
+
api.on('before_prompt_build', guardHook('hook:before_prompt_build', api.logger, async (event, ctx) => {
|
|
74
173
|
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'before_prompt_build');
|
|
75
174
|
if (!workspaceDir) {
|
|
76
175
|
api.logger.error(`[PD:before_prompt_build] workspaceDir resolution failed. ` +
|
|
@@ -81,26 +180,46 @@ const plugin = {
|
|
|
81
180
|
return;
|
|
82
181
|
}
|
|
83
182
|
try {
|
|
84
|
-
if (!
|
|
183
|
+
if (!startedWorkspaces.has(workspaceDir)) {
|
|
184
|
+
startedWorkspaces.add(workspaceDir);
|
|
85
185
|
migrateDirectoryStructure(api, workspaceDir);
|
|
186
|
+
migrateStaleWorkspaceGuidance(api, workspaceDir);
|
|
86
187
|
ensureWorkspaceTemplates(api, workspaceDir, language);
|
|
87
188
|
SystemLogger.log(workspaceDir, 'SYSTEM_BOOT', `Principles Disciple online. Language: ${language}`);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
workspaceDir
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
189
|
+
// ── Start EvolutionWorker for THIS workspace ──
|
|
190
|
+
// Gated behind evolution_worker feature flag (MVP-Quiet, default OFF per ADR-0014).
|
|
191
|
+
const gate = shouldStartEvolutionWorker(workspaceDir, api.logger);
|
|
192
|
+
if (gate.shouldStart) {
|
|
193
|
+
EvolutionWorkerService.api = api;
|
|
194
|
+
EvolutionWorkerService.start({
|
|
195
|
+
config: api.config,
|
|
196
|
+
workspaceDir,
|
|
197
|
+
stateDir: path.join(workspaceDir, '.state'),
|
|
198
|
+
logger: api.logger,
|
|
199
|
+
});
|
|
200
|
+
api.logger.info(`[PD] EvolutionWorker started for workspace: ${workspaceDir} (flag source: ${gate.flagSource})`);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
// Structured observability per ERR-002: no silent skip
|
|
204
|
+
api.logger.info(`[PD] EvolutionWorker NOT started for workspace: ${workspaceDir}. ${gate.disabledInfo}`);
|
|
205
|
+
SystemLogger.log(workspaceDir, 'EVOLUTION_WORKER_DISABLED', gate.disabledInfo ?? '');
|
|
206
|
+
}
|
|
207
|
+
// ── Start CorrectionObserver for THIS workspace ──
|
|
208
|
+
// MVP-Core per ADR-0014 amendment, independently owned (PRI-293).
|
|
209
|
+
const corrGate = shouldStartCorrectionObserver(workspaceDir, api.logger);
|
|
210
|
+
if (corrGate.shouldStart) {
|
|
211
|
+
CorrectionObserverService.start({
|
|
212
|
+
config: api.config,
|
|
213
|
+
workspaceDir,
|
|
214
|
+
stateDir: path.join(workspaceDir, '.state'),
|
|
215
|
+
logger: api.logger,
|
|
216
|
+
});
|
|
217
|
+
api.logger.info(`[PD] CorrectionObserver started for workspace: ${workspaceDir} (flag source: ${corrGate.flagSource})`);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
api.logger.info(`[PD] CorrectionObserver NOT started for workspace: ${workspaceDir}. ${corrGate.disabledInfo}`);
|
|
221
|
+
SystemLogger.log(workspaceDir, 'CORRECTION_OBSERVER_DISABLED', corrGate.disabledInfo ?? '');
|
|
222
|
+
}
|
|
104
223
|
}
|
|
105
224
|
const result = await handleBeforePromptBuild(event, { ...ctx, api: api, workspaceDir });
|
|
106
225
|
// Record success
|
|
@@ -118,9 +237,9 @@ const plugin = {
|
|
|
118
237
|
});
|
|
119
238
|
api.logger.error(`[PD] Error in before_prompt_build: ${String(err)}`);
|
|
120
239
|
}
|
|
121
|
-
});
|
|
240
|
+
}));
|
|
122
241
|
// ── Hook: Security Gate ──
|
|
123
|
-
api.on('before_tool_call', (event, ctx) => {
|
|
242
|
+
api.on('before_tool_call', guardHook('hook:before_tool_call', api.logger, (event, ctx) => {
|
|
124
243
|
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'before_tool_call');
|
|
125
244
|
if (!workspaceDir) {
|
|
126
245
|
api.logger.error(`[PD:before_tool_call] workspaceDir resolution failed. ` +
|
|
@@ -146,9 +265,9 @@ const plugin = {
|
|
|
146
265
|
}, { flushImmediately: true });
|
|
147
266
|
api.logger.error(`[PD] Error in before_tool_call: ${String(err)}`);
|
|
148
267
|
}
|
|
149
|
-
});
|
|
268
|
+
}));
|
|
150
269
|
// ── Hook: Pain & Trust ──
|
|
151
|
-
api.on('after_tool_call', (event, ctx) => {
|
|
270
|
+
api.on('after_tool_call', guardHook('hook:after_tool_call', api.logger, (event, ctx) => {
|
|
152
271
|
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'after_tool_call');
|
|
153
272
|
if (!workspaceDir) {
|
|
154
273
|
api.logger.error(`[PD:after_tool_call] workspaceDir resolution failed. ` +
|
|
@@ -173,9 +292,9 @@ const plugin = {
|
|
|
173
292
|
}, { flushImmediately: true });
|
|
174
293
|
api.logger.error(`[PD:EmpathyObserver] Error in after_tool_call: ${String(err)}`);
|
|
175
294
|
}
|
|
176
|
-
});
|
|
295
|
+
}));
|
|
177
296
|
// ── Hook: LLM Analysis ──
|
|
178
|
-
api.on('llm_output', (event, ctx) => {
|
|
297
|
+
api.on('llm_output', guardHook('hook:llm_output', api.logger, (event, ctx) => {
|
|
179
298
|
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'llm_output');
|
|
180
299
|
if (!workspaceDir) {
|
|
181
300
|
api.logger.error(`[PD:llm_output] workspaceDir resolution failed. ` +
|
|
@@ -200,10 +319,10 @@ const plugin = {
|
|
|
200
319
|
});
|
|
201
320
|
api.logger.error(`[PD] Error in llm_output: ${String(err)}`);
|
|
202
321
|
}
|
|
203
|
-
});
|
|
322
|
+
}));
|
|
204
323
|
// ── Hook: Trajectory Collection (Behavior Evolution Phase 0) ──
|
|
205
324
|
// Note: after_tool_call and llm_output are safe to collect
|
|
206
|
-
api.on('after_tool_call', (event, ctx) => {
|
|
325
|
+
api.on('after_tool_call', guardHook('hook:after_tool_call.trajectory', api.logger, (event, ctx) => {
|
|
207
326
|
try {
|
|
208
327
|
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'trajectory.after_tool_call');
|
|
209
328
|
if (!workspaceDir)
|
|
@@ -214,8 +333,8 @@ const plugin = {
|
|
|
214
333
|
catch (_err) {
|
|
215
334
|
// Non-critical: don't log, just skip
|
|
216
335
|
}
|
|
217
|
-
});
|
|
218
|
-
api.on('llm_output', (event, ctx) => {
|
|
336
|
+
}));
|
|
337
|
+
api.on('llm_output', guardHook('hook:llm_output.trajectory', api.logger, (event, ctx) => {
|
|
219
338
|
try {
|
|
220
339
|
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'trajectory.llm_output');
|
|
221
340
|
if (!workspaceDir)
|
|
@@ -226,9 +345,9 @@ const plugin = {
|
|
|
226
345
|
catch (_err) {
|
|
227
346
|
// Non-critical: don't log, just skip
|
|
228
347
|
}
|
|
229
|
-
});
|
|
348
|
+
}));
|
|
230
349
|
// ── Hook: Subagent Loop Closure ──
|
|
231
|
-
api.on('subagent_spawning', (event, _ctx) => {
|
|
350
|
+
api.on('subagent_spawning', guardHook('hook:subagent_spawning', api.logger, (event, _ctx) => {
|
|
232
351
|
try {
|
|
233
352
|
// FIX (B): Never fall back to '.' — fail-fast with ERROR log if workspaceDir cannot be resolved.
|
|
234
353
|
// For subagent hooks, we use event.agentId as the target agent for workspace resolution.
|
|
@@ -266,8 +385,8 @@ const plugin = {
|
|
|
266
385
|
api.logger.error(`[PD] Error in subagent_spawning shadow routing: ${String(err)}`);
|
|
267
386
|
return { status: 'ok' }; // Don't block spawn on shadow observation errors
|
|
268
387
|
}
|
|
269
|
-
});
|
|
270
|
-
api.on('subagent_ended', (event, ctx) => {
|
|
388
|
+
}));
|
|
389
|
+
api.on('subagent_ended', guardHook('hook:subagent_ended', api.logger, (event, ctx) => {
|
|
271
390
|
try {
|
|
272
391
|
// FIX (B): Never fall back to '.' — fail-fast with ERROR log if workspaceDir cannot be resolved.
|
|
273
392
|
const workspaceDir = resolveWorkspaceDirFromApi(api, undefined);
|
|
@@ -301,9 +420,9 @@ const plugin = {
|
|
|
301
420
|
catch (err) {
|
|
302
421
|
api.logger.error(`[PD] Error in subagent_ended: ${String(err)}`);
|
|
303
422
|
}
|
|
304
|
-
});
|
|
423
|
+
}));
|
|
305
424
|
// ── Hook: Lifecycle ──
|
|
306
|
-
api.on('before_reset', (event, ctx) => {
|
|
425
|
+
api.on('before_reset', guardHook('hook:before_reset', api.logger, (event, ctx) => {
|
|
307
426
|
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'before_reset');
|
|
308
427
|
if (!workspaceDir) {
|
|
309
428
|
api.logger.error(`[PD:before_reset] workspaceDir resolution failed. ` +
|
|
@@ -312,8 +431,8 @@ const plugin = {
|
|
|
312
431
|
return;
|
|
313
432
|
}
|
|
314
433
|
return handleBeforeReset(event, { ...ctx, workspaceDir });
|
|
315
|
-
});
|
|
316
|
-
api.on('before_compaction', (event, ctx) => {
|
|
434
|
+
}));
|
|
435
|
+
api.on('before_compaction', guardHook('hook:before_compaction', api.logger, (event, ctx) => {
|
|
317
436
|
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'before_compaction');
|
|
318
437
|
if (!workspaceDir) {
|
|
319
438
|
api.logger.error(`[PD:before_compaction] workspaceDir resolution failed. ` +
|
|
@@ -322,8 +441,8 @@ const plugin = {
|
|
|
322
441
|
return;
|
|
323
442
|
}
|
|
324
443
|
return handleBeforeCompaction(event, { ...ctx, workspaceDir });
|
|
325
|
-
});
|
|
326
|
-
api.on('after_compaction', (event, ctx) => {
|
|
444
|
+
}));
|
|
445
|
+
api.on('after_compaction', guardHook('hook:after_compaction', api.logger, (event, ctx) => {
|
|
327
446
|
const workspaceDir = resolveToolHookWorkspaceDirSafe(ctx, api, 'after_compaction');
|
|
328
447
|
if (!workspaceDir) {
|
|
329
448
|
api.logger.error(`[PD:after_compaction] workspaceDir resolution failed. ` +
|
|
@@ -332,17 +451,28 @@ const plugin = {
|
|
|
332
451
|
return;
|
|
333
452
|
}
|
|
334
453
|
return handleAfterCompaction(event, { ...ctx, workspaceDir });
|
|
335
|
-
});
|
|
454
|
+
}));
|
|
336
455
|
// ── Service: Background Evolution Worker ──
|
|
337
456
|
try {
|
|
338
457
|
EvolutionWorkerService.api = api;
|
|
339
|
-
api.
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
api.
|
|
458
|
+
const guardedEvolutionWorker = guardService('service:evolution-worker', EvolutionWorkerService, api.logger);
|
|
459
|
+
if (guardedEvolutionWorker)
|
|
460
|
+
api.registerService(guardedEvolutionWorker);
|
|
461
|
+
const guardedCorrectionObserver = guardService('service:correction-observer', CorrectionObserverService, api.logger);
|
|
462
|
+
if (guardedCorrectionObserver)
|
|
463
|
+
api.registerService(guardedCorrectionObserver);
|
|
464
|
+
const guardedTrajectory = guardService('service:trajectory', TrajectoryService, api.logger);
|
|
465
|
+
if (guardedTrajectory)
|
|
466
|
+
api.registerService(guardedTrajectory);
|
|
467
|
+
const guardedPdTask = guardService('service:pd-task', PDTaskService, api.logger);
|
|
468
|
+
if (guardedPdTask)
|
|
469
|
+
api.registerService(guardedPdTask);
|
|
470
|
+
const guardedCentralSync = guardService('service:central-sync', CentralSyncService, api.logger);
|
|
471
|
+
if (guardedCentralSync)
|
|
472
|
+
api.registerService(guardedCentralSync);
|
|
343
473
|
}
|
|
344
474
|
catch (err) {
|
|
345
|
-
api.logger.error(`[PD] Failed to register
|
|
475
|
+
api.logger.error(`[PD] Failed to register services: ${String(err)}`);
|
|
346
476
|
}
|
|
347
477
|
// ── Slash Commands ──
|
|
348
478
|
// Register command with optional short alias
|
|
@@ -363,20 +493,9 @@ const plugin = {
|
|
|
363
493
|
}
|
|
364
494
|
};
|
|
365
495
|
registerCommandWithAlias('pd-init', 'pdi', getCommandDescription('pd-init', language), (ctx) => handleInitStrategy(ctx));
|
|
366
|
-
registerCommandWithAlias('pd-okr', 'pdk', getCommandDescription('pd-okr', language), (ctx) => handleManageOkr(ctx));
|
|
367
496
|
registerCommandWithAlias('pd-bootstrap', 'pdb', getCommandDescription('pd-bootstrap', language), (ctx) => handleBootstrapTools(ctx));
|
|
368
497
|
registerCommandWithAlias('pd-research', 'pdr', getCommandDescription('pd-research', language), (ctx) => handleResearchTools(ctx));
|
|
369
498
|
registerCommandWithAlias('pd-thinking', 'pdt', getCommandDescription('pd-thinking', language), (ctx) => handleThinkingOs(ctx), { acceptsArgs: true });
|
|
370
|
-
registerCommandWithAlias('pd-daily', 'pdd', getCommandDescription('pd-daily', language), () => ({
|
|
371
|
-
text: language === 'zh'
|
|
372
|
-
? "请执行 pd-daily 技能来配置并发送进化日报。系统将引导你完成配置流程,包括发送时间、渠道和报告风格偏好。"
|
|
373
|
-
: "Please execute the pd-daily skill to configure and send your daily evolution report. The system will guide you through the configuration process."
|
|
374
|
-
}));
|
|
375
|
-
registerCommandWithAlias('pd-grooming', 'pdg', getCommandDescription('pd-grooming', language), () => ({
|
|
376
|
-
text: language === 'zh'
|
|
377
|
-
? "请执行 pd-grooming 技能来执行大扫除。例如输入: '执行 pd-grooming 技能'"
|
|
378
|
-
: "Please execute the pd-grooming skill to clean up. For example: 'Execute pd-grooming skill'"
|
|
379
|
-
}));
|
|
380
499
|
registerCommandWithAlias('pd-help', 'pdh', getCommandDescription('pd-help', language), () => {
|
|
381
500
|
if (language === 'zh') {
|
|
382
501
|
return { text: `
|
|
@@ -392,10 +511,7 @@ const plugin = {
|
|
|
392
511
|
## 状态查询
|
|
393
512
|
| 短命令 | 长命令 | 用途 |
|
|
394
513
|
|--------|--------|------|
|
|
395
|
-
| \`/pdk\` | \`/pd-okr\` | OKR 目标管理 |
|
|
396
514
|
| \`/pdt\` | \`/pd-thinking\` | 思维模型管理 |
|
|
397
|
-
| \`/pdd\` | \`/pd-daily\` | 进化日报 |
|
|
398
|
-
| \`/pdg\` | \`/pd-grooming\` | 工作区清理 |
|
|
399
515
|
|
|
400
516
|
## 其他命令
|
|
401
517
|
| 命令 | 用途 |
|
|
@@ -424,10 +540,7 @@ const plugin = {
|
|
|
424
540
|
## Status
|
|
425
541
|
| Short | Full | Purpose |
|
|
426
542
|
|-------|------|---------|
|
|
427
|
-
| \`/pdk\` | \`/pd-okr\` | OKR goal management |
|
|
428
543
|
| \`/pdt\` | \`/pd-thinking\` | Mental model management |
|
|
429
|
-
| \`/pdd\` | \`/pd-daily\` | Evolution report |
|
|
430
|
-
| \`/pdg\` | \`/pd-grooming\` | Workspace cleanup |
|
|
431
544
|
|
|
432
545
|
## Other Commands
|
|
433
546
|
| Command | Purpose |
|
|
@@ -689,4 +802,6 @@ const plugin = {
|
|
|
689
802
|
}
|
|
690
803
|
};
|
|
691
804
|
export { PrincipleTreeLedgerAdapter } from './core/principle-tree-ledger-adapter.js';
|
|
805
|
+
/* istanbul ignore next — test exports for evolution worker gate */
|
|
806
|
+
export { loadFeatureFlagFromWorkspace, isRecord };
|
|
692
807
|
export default plugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { OpenClawPluginServiceContext, PluginLogger } from '../openclaw-sdk.js';
|
|
2
|
+
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
3
|
+
import { CorrectionObserver } from '@principles/core/runtime-v2';
|
|
4
|
+
export interface CorrectionObserverServiceShape {
|
|
5
|
+
id: string;
|
|
6
|
+
start: (ctx: OpenClawPluginServiceContext) => void;
|
|
7
|
+
stop?: (ctx: OpenClawPluginServiceContext) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveCorrectionObserver(wctx: WorkspaceContext, logger?: Pick<PluginLogger, 'info' | 'warn' | 'error' | 'debug'>): CorrectionObserver | null;
|
|
10
|
+
export declare function runCorrectionObserverCycle(wctx: WorkspaceContext, logger: PluginLogger): Promise<void>;
|
|
11
|
+
export declare const CorrectionObserverService: CorrectionObserverServiceShape;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
2
|
+
import { TrajectoryRegistry } from '../core/trajectory.js';
|
|
3
|
+
import { CorrectionCueLearner } from '../core/correction-cue-learner.js';
|
|
4
|
+
import { WorkflowFunnelLoader, PiAiRuntimeAdapter, CorrectionObserver, AgentScheduler, } from '@principles/core/runtime-v2';
|
|
5
|
+
import { KeywordOptimizationService } from './keyword-optimization-service.js';
|
|
6
|
+
import { SystemLogger } from '../core/system-logger.js';
|
|
7
|
+
let correctionObserverTimeoutId = null;
|
|
8
|
+
let correctionObserverStopped = false;
|
|
9
|
+
const startedWorkspaces = new Set();
|
|
10
|
+
const CORRECTION_OBSERVER_INTERVAL_MS = 15 * 60 * 1000;
|
|
11
|
+
const CORRECTION_OBSERVER_INITIAL_DELAY_MS = 10_000;
|
|
12
|
+
const CORRECTION_OBSERVER_MAX_RECENT_SESSIONS = 20;
|
|
13
|
+
const CORRECTION_OBSERVER_MAX_PAYLOAD_SESSIONS = 5;
|
|
14
|
+
export function resolveCorrectionObserver(wctx, logger) {
|
|
15
|
+
try {
|
|
16
|
+
const loader = new WorkflowFunnelLoader(wctx.stateDir);
|
|
17
|
+
const funnel = loader.getFunnel('pd-correction-observer');
|
|
18
|
+
const policy = funnel?.policy;
|
|
19
|
+
if (!policy || policy.runtimeKind !== 'pi-ai') {
|
|
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;
|
|
28
|
+
}
|
|
29
|
+
const adapter = new PiAiRuntimeAdapter({
|
|
30
|
+
provider,
|
|
31
|
+
model,
|
|
32
|
+
apiKeyEnv,
|
|
33
|
+
baseUrl,
|
|
34
|
+
workspace: wctx.workspaceDir,
|
|
35
|
+
});
|
|
36
|
+
return new CorrectionObserver({ runtimeAdapter: adapter });
|
|
37
|
+
}
|
|
38
|
+
const adapter = new PiAiRuntimeAdapter({
|
|
39
|
+
provider: String(policy.provider),
|
|
40
|
+
model: String(policy.model),
|
|
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 });
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
logger?.warn?.(`[PD:CorrectionObserver] Failed to resolve CorrectionObserver: ${String(err)}`);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export async function runCorrectionObserverCycle(wctx, logger) {
|
|
55
|
+
try {
|
|
56
|
+
const observer = resolveCorrectionObserver(wctx, logger);
|
|
57
|
+
if (!observer) {
|
|
58
|
+
logger?.info?.('[PD:CorrectionObserver] Observer not resolved (no API key or config). Skipping cycle.');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
logger?.info?.('[PD:CorrectionObserver] Observer resolved. Initiating periodic optimization...');
|
|
62
|
+
const db = TrajectoryRegistry.get(wctx.workspaceDir);
|
|
63
|
+
const recentSessions = db.listRecentSessions({ limit: CORRECTION_OBSERVER_MAX_RECENT_SESSIONS });
|
|
64
|
+
const recentSessionIds = recentSessions.map(s => s.sessionId);
|
|
65
|
+
if (recentSessionIds.length === 0) {
|
|
66
|
+
logger?.info?.('[PD:CorrectionObserver] No recent sessions found. Skipping correction optimization.');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const recentMessages = [];
|
|
70
|
+
for (const sId of recentSessionIds.slice(0, CORRECTION_OBSERVER_MAX_PAYLOAD_SESSIONS)) {
|
|
71
|
+
try {
|
|
72
|
+
const turns = db.listUserTurnsForSession(sId);
|
|
73
|
+
for (const t of turns) {
|
|
74
|
+
if (t.rawExcerpt) {
|
|
75
|
+
recentMessages.push(t.rawExcerpt);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (turnErr) {
|
|
80
|
+
logger?.warn?.(`[PD:CorrectionObserver] Failed to load user turns for session ${sId}: ${String(turnErr)}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const learner = CorrectionCueLearner.get(wctx.stateDir);
|
|
84
|
+
const keywords = learner.getStore().keywords;
|
|
85
|
+
const keywordStoreSummary = {
|
|
86
|
+
totalKeywords: keywords.length,
|
|
87
|
+
terms: keywords.map(k => ({
|
|
88
|
+
term: k.term,
|
|
89
|
+
weight: k.weight,
|
|
90
|
+
hitCount: k.hitCount ?? 0,
|
|
91
|
+
truePositiveCount: k.truePositiveCount ?? 0,
|
|
92
|
+
falsePositiveCount: k.falsePositiveCount ?? 0,
|
|
93
|
+
})),
|
|
94
|
+
};
|
|
95
|
+
const optimizationService = KeywordOptimizationService.get(wctx.stateDir, wctx.workspaceDir, logger);
|
|
96
|
+
const trajectoryHistory = await optimizationService.buildTrajectoryHistory(recentSessionIds);
|
|
97
|
+
const payload = {
|
|
98
|
+
parentSessionId: 'correction-observer-service',
|
|
99
|
+
workspaceDir: wctx.workspaceDir,
|
|
100
|
+
keywordStoreSummary,
|
|
101
|
+
recentMessages,
|
|
102
|
+
trajectoryHistory,
|
|
103
|
+
};
|
|
104
|
+
const scheduler = new AgentScheduler();
|
|
105
|
+
scheduler.register({
|
|
106
|
+
agentId: 'correction-observer',
|
|
107
|
+
mode: 'realtime',
|
|
108
|
+
runner: observer,
|
|
109
|
+
});
|
|
110
|
+
logger?.info?.(`[PD:CorrectionObserver] Dispatching with ${trajectoryHistory.length} trajectory events, ${recentMessages.length} recent messages.`);
|
|
111
|
+
const result = await scheduler.dispatch('correction-observer', payload);
|
|
112
|
+
logger?.info?.(`[PD:CorrectionObserver] Completed: updated=${result.updated}, summary="${result.summary}"`);
|
|
113
|
+
if (result.updated) {
|
|
114
|
+
optimizationService.applyResult(result);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
const errMsg = `Correction observer cycle failed: ${String(err)}`;
|
|
119
|
+
logger?.warn?.(`[PD:CorrectionObserver] ${errMsg}`);
|
|
120
|
+
SystemLogger.log(wctx.workspaceDir, 'CORRECTION_OBSERVER_CYCLE_FAILED', errMsg);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export const CorrectionObserverService = {
|
|
124
|
+
id: 'principles-correction-observer',
|
|
125
|
+
start(ctx) {
|
|
126
|
+
const workspaceDir = ctx?.workspaceDir;
|
|
127
|
+
const logger = ctx?.logger || console;
|
|
128
|
+
if (!workspaceDir) {
|
|
129
|
+
if (logger)
|
|
130
|
+
logger.warn('[PD:CorrectionObserver] workspaceDir not found in service config. Correction observer disabled.');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (startedWorkspaces.has(workspaceDir)) {
|
|
134
|
+
if (logger)
|
|
135
|
+
logger.info(`[PD:CorrectionObserver] Already started for workspace: ${workspaceDir}. Skipping duplicate start.`);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
startedWorkspaces.add(workspaceDir);
|
|
139
|
+
correctionObserverStopped = false;
|
|
140
|
+
const wctx = WorkspaceContext.fromHookContext({ workspaceDir, ...ctx.config });
|
|
141
|
+
if (logger)
|
|
142
|
+
logger.info(`[PD:CorrectionObserver] Starting with workspaceDir=${wctx.workspaceDir}, stateDir=${wctx.stateDir}`);
|
|
143
|
+
const interval = CORRECTION_OBSERVER_INTERVAL_MS;
|
|
144
|
+
async function runCycle() {
|
|
145
|
+
if (correctionObserverStopped)
|
|
146
|
+
return;
|
|
147
|
+
await runCorrectionObserverCycle(wctx, logger);
|
|
148
|
+
if (correctionObserverStopped)
|
|
149
|
+
return;
|
|
150
|
+
correctionObserverTimeoutId = setTimeout(runCycle, interval);
|
|
151
|
+
correctionObserverTimeoutId.unref();
|
|
152
|
+
}
|
|
153
|
+
correctionObserverTimeoutId = setTimeout(() => {
|
|
154
|
+
void runCycle().catch((err) => {
|
|
155
|
+
if (logger)
|
|
156
|
+
logger.error(`[PD:CorrectionObserver] Startup cycle failed: ${String(err)}`);
|
|
157
|
+
if (correctionObserverStopped)
|
|
158
|
+
return;
|
|
159
|
+
correctionObserverTimeoutId = setTimeout(runCycle, interval);
|
|
160
|
+
correctionObserverTimeoutId.unref();
|
|
161
|
+
});
|
|
162
|
+
}, CORRECTION_OBSERVER_INITIAL_DELAY_MS);
|
|
163
|
+
correctionObserverTimeoutId.unref();
|
|
164
|
+
},
|
|
165
|
+
stop(_ctx) {
|
|
166
|
+
correctionObserverStopped = true;
|
|
167
|
+
startedWorkspaces.clear();
|
|
168
|
+
if (correctionObserverTimeoutId)
|
|
169
|
+
clearTimeout(correctionObserverTimeoutId);
|
|
170
|
+
correctionObserverTimeoutId = null;
|
|
171
|
+
},
|
|
172
|
+
};
|