principles-disciple 1.72.0 → 1.74.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/INSTALL.md +1 -3
- package/openclaw.plugin.json +10 -5
- package/package.json +17 -19
- package/scripts/acceptance-test.mjs +16 -73
- package/scripts/sync-plugin.mjs +382 -77
- package/src/commands/archive-impl.ts +2 -1
- package/src/commands/capabilities.ts +2 -2
- package/src/commands/context.ts +2 -2
- package/src/commands/disable-impl.ts +2 -1
- package/src/commands/evolution-status.ts +16 -16
- package/src/commands/export.ts +12 -67
- package/src/commands/pain.ts +91 -1
- package/src/commands/principle-rollback.ts +2 -1
- package/src/commands/promote-impl.ts +7 -43
- package/src/commands/rollback-impl.ts +2 -1
- package/src/commands/rollback.ts +2 -1
- package/src/commands/samples.ts +2 -1
- package/src/commands/thinking-os.ts +2 -1
- package/src/config/errors.ts +18 -2
- package/src/constants/diagnostician.ts +2 -2
- package/src/constants/tools.ts +2 -1
- package/src/core/__tests__/focus-history.test.ts +210 -0
- package/src/core/config.ts +1 -1
- package/src/core/correction-cue-learner.ts +2 -136
- package/src/core/correction-types.ts +16 -88
- package/src/core/dictionary.ts +19 -20
- package/src/core/empathy-keyword-matcher.ts +17 -289
- package/src/core/empathy-types.ts +18 -229
- package/src/core/event-log.ts +29 -132
- package/src/core/evolution-reducer.ts +21 -2
- package/src/core/evolution-types.ts +76 -464
- package/src/core/file-store.ts +80 -0
- package/src/core/focus-history.ts +228 -955
- package/src/core/local-worker-routing.ts +34 -314
- package/src/core/merge-gate-audit.ts +0 -195
- package/src/core/migration.ts +0 -1
- package/src/core/pain-diagnostic-gate.ts +154 -0
- package/src/core/pain-signal.ts +21 -138
- package/src/core/pain.ts +15 -88
- package/src/core/path-resolver.ts +0 -1
- package/src/core/paths.ts +0 -1
- package/src/core/pd-task-reconciler.ts +26 -115
- package/src/core/pd-task-service.ts +9 -9
- package/src/core/pd-task-types.ts +23 -127
- package/src/core/principle-compiler/__tests__/compiler-replay-gate.test.ts +174 -0
- package/src/core/principle-compiler/code-validator.ts +15 -42
- package/src/core/principle-compiler/compiler.ts +100 -15
- package/src/core/principle-compiler/index.ts +5 -2
- package/src/core/principle-compiler/template-generator.ts +4 -104
- package/src/core/principle-injection.ts +10 -202
- package/src/core/principle-internalization/filesystem-lifecycle-datasource.ts +42 -0
- package/src/core/principle-internalization/lifecycle-read-model.ts +39 -242
- package/src/core/principle-internalization/principle-lifecycle-service.ts +12 -10
- package/src/core/principle-tree-ledger-adapter.ts +145 -0
- package/src/core/principle-tree-ledger.ts +8 -6
- package/src/core/reflection/reflection-context.ts +14 -109
- package/src/core/replay-engine.ts +8 -500
- package/src/core/rule-host-helpers.ts +5 -35
- package/src/core/rule-host-types.ts +10 -82
- package/src/core/rule-host.ts +6 -63
- package/src/core/runtime-v2-prompt-activation-reader.ts +231 -0
- package/src/core/session-tracker.ts +87 -101
- package/src/core/shadow-observation-registry.ts +19 -48
- package/src/core/trajectory.ts +3 -1
- package/src/core/workflow-funnel-loader.ts +62 -68
- package/src/core/workspace-context.ts +46 -0
- package/src/core/workspace-dir-service.ts +1 -1
- package/src/core/workspace-dir-validation.ts +18 -9
- package/src/hooks/AGENTS.md +1 -1
- package/src/hooks/gate-block-helper.ts +71 -64
- package/src/hooks/gate.ts +183 -31
- package/src/hooks/lifecycle.ts +30 -32
- package/src/hooks/llm.ts +60 -32
- package/src/hooks/pain.ts +297 -103
- package/src/hooks/prompt.ts +400 -440
- package/src/hooks/subagent.ts +2 -29
- package/src/i18n/commands.ts +2 -10
- package/src/index.ts +95 -85
- package/src/openclaw-sdk.ts +311 -0
- package/src/service/central-database.ts +8 -4
- package/src/service/evolution-queue-migration.ts +2 -1
- package/src/service/evolution-worker.ts +163 -1786
- package/src/service/internalization-trigger-adapter.ts +302 -0
- package/src/service/keyword-optimization-service.ts +4 -4
- package/src/service/monitoring-query-service.ts +1 -215
- package/src/service/queue-io.ts +60 -331
- package/src/service/runtime-summary-service.ts +59 -16
- package/src/service/subagent-workflow/index.ts +0 -41
- package/src/service/subagent-workflow/types.ts +9 -120
- package/src/service/subagent-workflow/workflow-store.ts +2 -119
- package/src/service/workflow-watchdog.ts +0 -43
- package/src/types/event-payload.ts +16 -74
- package/src/types/event-types.ts +38 -547
- package/src/types/hygiene-types.ts +7 -30
- package/src/types/principle-tree-schema.ts +20 -222
- package/src/types/queue.ts +15 -70
- package/src/types/runtime-summary.ts +5 -49
- package/src/utils/io.ts +8 -20
- package/src/utils/retry.ts +1 -1
- package/src/utils/shadow-fingerprint.ts +2 -2
- package/src/utils/workspace-resolver.ts +50 -0
- package/templates/langs/en/core/AGENTS.md +7 -7
- package/templates/langs/en/core/BOOT.md +1 -1
- package/templates/langs/en/core/HEARTBEAT.md +2 -2
- package/templates/langs/en/principles/THINKING_OS.md +3 -2
- package/templates/langs/en/skills/ai-sprint-orchestration/references/agent-registry.json +1 -72
- package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +6 -6
- package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +6 -6
- package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +2 -12
- package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +2 -12
- package/templates/langs/en/skills/ai-sprint-orchestration/scripts/run.mjs +51 -15
- package/templates/langs/en/skills/evolve-task/SKILL.md +3 -3
- package/templates/langs/en/skills/pd-cli-operator/SKILL.md +67 -0
- package/templates/langs/en/skills/pd-diagnostician/SKILL.md +1 -1
- package/templates/langs/en/skills/pd-mentor/SKILL.md +2 -3
- package/templates/langs/en/skills/pd-pain-signal/SKILL.md +17 -39
- package/templates/langs/en/skills/pd-runtime-v2/SKILL.md +61 -0
- package/templates/langs/zh/core/AGENTS.md +7 -7
- package/templates/langs/zh/core/BOOT.md +1 -1
- package/templates/langs/zh/core/HEARTBEAT.md +2 -2
- package/templates/langs/zh/principles/THINKING_OS.md +3 -2
- package/templates/langs/zh/skills/ai-sprint-orchestration/references/agent-registry.json +1 -72
- package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +6 -6
- package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +6 -6
- package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/nocturnal-trinity-quality-enhancement.json +8 -8
- package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +2 -12
- package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +2 -12
- package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +51 -15
- package/templates/langs/zh/skills/ai-sprint-orchestration/test/run.test.mjs +21 -5
- package/templates/langs/zh/skills/evolve-task/SKILL.md +4 -4
- package/templates/langs/zh/skills/pd-cli-operator/SKILL.md +67 -0
- package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +1 -1
- package/templates/langs/zh/skills/pd-mentor/SKILL.md +2 -3
- package/templates/langs/zh/skills/pd-pain-signal/SKILL.md +17 -38
- package/templates/langs/zh/skills/pd-runtime-v2/SKILL.md +61 -0
- package/tests/build-artifacts.test.ts +1 -3
- package/tests/commands/evolution-status.test.ts +0 -118
- package/tests/core/bootstrap-rules.test.ts +1 -1
- package/tests/core/config.test.ts +1 -1
- package/tests/core/event-log.test.ts +35 -0
- package/tests/core/evolution-engine.test.ts +610 -0
- package/tests/core/file-store.test.ts +102 -0
- package/tests/core/focus-history.test.ts +203 -11
- package/tests/core/merge-gate-audit.test.ts +2 -169
- package/tests/core/migration.test.ts +7 -7
- package/tests/core/model-deployment-registry.test.ts +7 -1
- package/tests/core/model-training-registry.test.ts +19 -0
- package/tests/core/observability.test.ts +0 -1
- package/tests/core/pain-diagnostic-gate.test.ts +498 -0
- package/tests/core/pain.test.ts +0 -1
- package/tests/core/path-resolver.test.ts +1 -1
- package/tests/core/paths-refactor.test.ts +0 -22
- package/tests/core/principle-internalization/deprecated-readiness.test.ts +2 -2
- package/tests/core/principle-internalization/lifecycle-metrics.test.ts +2 -2
- package/tests/core/principle-internalization/{internalization-routing-policy.test.ts → lifecycle-routing-policy.test.ts} +6 -6
- package/tests/core/principle-internalization/lineage-source-retired.test.ts +56 -0
- package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +1 -23
- package/tests/core/principle-tree-ledger-adapter.test.ts +253 -0
- package/tests/core/reflection-context.test.ts +0 -14
- package/tests/core/replay-engine.test.ts +127 -215
- package/tests/core/rule-host-helpers.test.ts +2 -2
- package/tests/core/rule-implementation-runtime.test.ts +0 -27
- package/tests/core/workflow-funnel-loader.test.ts +162 -0
- package/tests/core/workspace-context.test.ts +2 -2
- package/tests/core/workspace-dir-validation.test.ts +8 -1
- package/tests/core-anti-growth.test.ts +191 -0
- package/tests/hook-workspace-nextaction-contract.test.ts +42 -0
- package/tests/hooks/confirm-first-removal.test.ts +188 -0
- package/tests/hooks/gate-auto-correct-shadow.test.ts +310 -0
- package/tests/hooks/gate-auto-correct.test.ts +665 -0
- package/tests/hooks/gate-no-path-write-tool.test.ts +172 -0
- package/tests/hooks/gate-rule-host-pipeline.test.ts +2 -1
- package/tests/hooks/pain.test.ts +269 -12
- package/tests/hooks/prompt-characterization.test.ts +500 -0
- package/tests/hooks/prompt-size-guard.test.ts +32 -17
- package/tests/hooks/runtime-v2-prompt-activation.test.ts +869 -0
- package/tests/index.test.ts +94 -1
- package/tests/integration/auto-entry-gate.test.ts +248 -0
- package/tests/integration/internalization-trigger-guard.test.ts +69 -0
- package/tests/integration/m8-legacy-paths.test.ts +63 -0
- package/tests/integration/runtime-v2-pain-guard.test.ts +125 -0
- package/tests/plugin-config-resolution-cutover.test.ts +359 -0
- package/tests/runtime-v2-discovery-guard.test.ts +154 -0
- package/tests/service/central-database.test.ts +457 -0
- package/tests/service/evolution-worker.correction-observer.test.ts +173 -0
- package/tests/service/evolution-worker.timeout.test.ts +11 -129
- package/tests/service/internalization-trigger-adapter.test.ts +251 -0
- package/tests/service/monitoring-query-service.test.ts +1 -47
- package/tests/service/queue-io.test.ts +1 -62
- package/tests/service/runtime-summary-service.test.ts +3 -1
- package/tests/service/workflow-watchdog.test.ts +0 -91
- package/tests/utils/file-lock.test.ts +5 -3
- package/tests/utils/session-key.test.ts +52 -0
- package/tests/utils/subagent-probe.test.ts +48 -1
- package/vitest.config.ts +4 -11
- package/.planning/codebase/ARCHITECTURE.md +0 -157
- package/.planning/codebase/CONCERNS.md +0 -145
- package/.planning/codebase/CONVENTIONS.md +0 -148
- package/.planning/codebase/INTEGRATIONS.md +0 -81
- package/.planning/codebase/STACK.md +0 -87
- package/.planning/codebase/STRUCTURE.md +0 -193
- package/.planning/codebase/TESTING.md +0 -243
- package/.planning/phases/01-basic-visualization/01-GAP-CLOSURE-VERIFICATION.md +0 -113
- package/docs/COMMAND_REFERENCE.md +0 -76
- package/docs/COMMAND_REFERENCE_EN.md +0 -79
- package/scripts/build-web.mjs +0 -46
- package/scripts/diagnose-nocturnal.mjs +0 -537
- package/scripts/seed-nocturnal-scenarios.mjs +0 -384
- package/src/commands/nocturnal-review.ts +0 -322
- package/src/commands/nocturnal-rollout.ts +0 -790
- package/src/commands/nocturnal-train.ts +0 -986
- package/src/commands/pd-reflect.ts +0 -88
- package/src/core/adaptive-thresholds.ts +0 -478
- package/src/core/diagnostician-task-store.ts +0 -192
- package/src/core/nocturnal-arbiter.ts +0 -715
- package/src/core/nocturnal-artifact-lineage.ts +0 -116
- package/src/core/nocturnal-artificer.ts +0 -257
- package/src/core/nocturnal-candidate-scoring.ts +0 -530
- package/src/core/nocturnal-compliance.ts +0 -1146
- package/src/core/nocturnal-dataset.ts +0 -763
- package/src/core/nocturnal-executability.ts +0 -428
- package/src/core/nocturnal-export.ts +0 -499
- package/src/core/nocturnal-paths.ts +0 -240
- package/src/core/nocturnal-reasoning-deriver.ts +0 -343
- package/src/core/nocturnal-rule-implementation-validator.ts +0 -246
- package/src/core/nocturnal-snapshot-contract.ts +0 -99
- package/src/core/nocturnal-trajectory-extractor.ts +0 -512
- package/src/core/nocturnal-trinity-types.ts +0 -218
- package/src/core/nocturnal-trinity.ts +0 -2680
- package/src/core/principle-internalization/deprecated-readiness.ts +0 -93
- package/src/core/principle-internalization/internalization-routing-policy.ts +0 -208
- package/src/core/principle-internalization/lifecycle-metrics.ts +0 -152
- package/src/http/principles-console-route.ts +0 -709
- package/src/service/central-health-service.ts +0 -49
- package/src/service/central-overview-service.ts +0 -138
- package/src/service/control-ui-query-service.ts +0 -900
- package/src/service/cooldown-strategy.ts +0 -97
- package/src/service/evolution-pain-context.ts +0 -79
- package/src/service/evolution-query-service.ts +0 -407
- package/src/service/health-query-service.ts +0 -1038
- package/src/service/nocturnal-config.ts +0 -214
- package/src/service/nocturnal-runtime.ts +0 -734
- package/src/service/nocturnal-service.ts +0 -1605
- package/src/service/nocturnal-target-selector.ts +0 -545
- package/src/service/sleep-cycle.ts +0 -157
- package/src/service/startup-reconciler.ts +0 -112
- package/src/service/subagent-workflow/correction-observer-types.ts +0 -82
- package/src/service/subagent-workflow/correction-observer-workflow-manager.ts +0 -250
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +0 -1
- package/src/service/subagent-workflow/dynamic-timeout.ts +0 -30
- package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +0 -268
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +0 -795
- package/src/service/subagent-workflow/runtime-direct-driver.ts +0 -268
- package/src/service/subagent-workflow/workflow-manager-base.ts +0 -580
- package/src/tools/write-pain-flag.ts +0 -215
- package/templates/langs/en/skills/plan-script/SKILL.md +0 -32
- package/templates/langs/zh/skills/plan-script/SKILL.md +0 -32
- package/tests/commands/nocturnal-review.test.ts +0 -448
- package/tests/commands/nocturnal-train.test.ts +0 -97
- package/tests/commands/pd-reflect.test.ts +0 -49
- package/tests/core/adaptive-thresholds.test.ts +0 -261
- package/tests/core/nocturnal-arbiter.test.ts +0 -559
- package/tests/core/nocturnal-artifact-lineage.test.ts +0 -53
- package/tests/core/nocturnal-artificer.test.ts +0 -241
- package/tests/core/nocturnal-candidate-scoring.test.ts +0 -532
- package/tests/core/nocturnal-compliance-p-principles.test.ts +0 -133
- package/tests/core/nocturnal-compliance.test.ts +0 -646
- package/tests/core/nocturnal-dataset.test.ts +0 -892
- package/tests/core/nocturnal-e2e.test.ts +0 -234
- package/tests/core/nocturnal-executability.test.ts +0 -357
- package/tests/core/nocturnal-export.test.ts +0 -517
- package/tests/core/nocturnal-reasoning-deriver.test.ts +0 -372
- package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +0 -428
- package/tests/core/nocturnal-rule-implementation-validator.test.ts +0 -127
- package/tests/core/nocturnal-snapshot-contract.test.ts +0 -121
- package/tests/core/nocturnal-trajectory-extractor.test.ts +0 -634
- package/tests/core/nocturnal-trinity.test.ts +0 -2053
- package/tests/core/pain-auto-repair.test.ts +0 -96
- package/tests/core/pain-integration.test.ts +0 -510
- package/tests/fixtures/nocturnal-reviewed-subset.json +0 -183
- package/tests/http/principles-console-route.test.ts +0 -162
- package/tests/integration/chaos-resilience.test.ts +0 -348
- package/tests/integration/empathy-workflow-integration.test.ts +0 -626
- package/tests/integration/pain-diagnostician-loop.e2e.test.ts +0 -380
- package/tests/service/control-ui-query-service.test.ts +0 -121
- package/tests/service/cooldown-strategy.test.ts +0 -164
- package/tests/service/data-endpoints-regression.test.ts +0 -834
- package/tests/service/empathy-observer-workflow-manager.test.ts +0 -175
- package/tests/service/evolution-worker.nocturnal.test.ts +0 -601
- package/tests/service/nocturnal-runtime-hardening.test.ts +0 -118
- package/tests/service/nocturnal-runtime.test.ts +0 -473
- package/tests/service/nocturnal-service-code-candidate.test.ts +0 -330
- package/tests/service/nocturnal-target-selector.test.ts +0 -615
- package/tests/service/startup-reconciler.test.ts +0 -148
- package/tests/tools/write-pain-flag.test.ts +0 -358
- package/ui/src/App.tsx +0 -45
- package/ui/src/api.ts +0 -220
- package/ui/src/charts.tsx +0 -955
- package/ui/src/components/ErrorState.tsx +0 -6
- package/ui/src/components/Loading.tsx +0 -13
- package/ui/src/components/ProtectedRoute.tsx +0 -12
- package/ui/src/components/Shell.tsx +0 -91
- package/ui/src/components/WorkspaceConfig.tsx +0 -178
- package/ui/src/components/index.ts +0 -5
- package/ui/src/context/auth.tsx +0 -80
- package/ui/src/context/theme.tsx +0 -66
- package/ui/src/hooks/useAutoRefresh.ts +0 -39
- package/ui/src/i18n/ui.ts +0 -473
- package/ui/src/main.tsx +0 -16
- package/ui/src/pages/EvolutionPage.tsx +0 -333
- package/ui/src/pages/FeedbackPage.tsx +0 -138
- package/ui/src/pages/GateMonitorPage.tsx +0 -136
- package/ui/src/pages/LoginPage.tsx +0 -89
- package/ui/src/pages/OverviewPage.tsx +0 -599
- package/ui/src/pages/SamplesPage.tsx +0 -174
- package/ui/src/pages/ThinkingModelsPage.tsx +0 -702
- package/ui/src/styles.css +0 -2020
- package/ui/src/types.ts +0 -384
- package/ui/src/utils/format.ts +0 -15
package/src/service/queue-io.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Full persistence layer encapsulating queue file locking, atomic writes,
|
|
5
5
|
* queue format, and enqueue orchestration. Depends on file-lock.ts, io.ts,
|
|
6
|
-
* queue-migration.ts,
|
|
6
|
+
* queue-migration.ts, and pain.ts.
|
|
7
7
|
* Zero imports from evolution-worker.ts.
|
|
8
8
|
*/
|
|
9
9
|
|
|
@@ -16,364 +16,93 @@ import { migrateQueueToV2 } from './queue-migration.js';
|
|
|
16
16
|
import type { EvolutionQueueItem } from '../core/evolution-types.js';
|
|
17
17
|
import type { RawQueueItem } from './queue-migration.js';
|
|
18
18
|
import type { PluginLogger } from '../openclaw-sdk.js';
|
|
19
|
-
import type { WorkspaceContext } from '../core/workspace-context.js';
|
|
20
|
-
import { CorrectionCueLearner } from '../core/correction-cue-learner.js';
|
|
21
|
-
import { readPainFlagContract } from '../core/pain.js';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Extended EvolutionQueueItem that includes the recentPainContext field.
|
|
25
|
-
* This field is added inline in evolution-worker.ts but needs to be available
|
|
26
|
-
* in queue-io.ts for the enqueue functions.
|
|
27
|
-
*/
|
|
28
|
-
interface EvolutionQueueItemWithPain extends EvolutionQueueItem {
|
|
29
|
-
recentPainContext?: RecentPainContext;
|
|
30
|
-
}
|
|
31
19
|
|
|
32
20
|
export const EVOLUTION_QUEUE_LOCK_SUFFIX = '.lock';
|
|
33
21
|
export const LOCK_MAX_RETRIES = 50;
|
|
34
22
|
export const LOCK_RETRY_DELAY_MS = 50;
|
|
35
23
|
export const LOCK_STALE_MS = 30_000;
|
|
36
24
|
|
|
37
|
-
export const SLEEP_REFLECTION_DEDUP_WINDOW_MS = 4 * 60 * 60 * 1000; // 4 hours
|
|
38
|
-
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
// requireQueueLock — thin wrapper that adds LockUnavailableError
|
|
41
|
-
// ---------------------------------------------------------------------------
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Acquire a queue lock, throwing LockUnavailableError on failure.
|
|
45
|
-
* This is the standard lock used across all queue operations.
|
|
46
|
-
*/
|
|
47
25
|
export async function requireQueueLock(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
26
|
+
resourcePath: string,
|
|
27
|
+
logger: PluginLogger | { warn?: (message: string) => void; info?: (message: string) => void } | undefined,
|
|
28
|
+
scope: string,
|
|
29
|
+
lockSuffix: string = EVOLUTION_QUEUE_LOCK_SUFFIX,
|
|
52
30
|
): Promise<() => void> {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
31
|
+
try {
|
|
32
|
+
return await acquireQueueLock(resourcePath, logger, lockSuffix);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
throw new LockUnavailableError(resourcePath, scope, { cause: err });
|
|
35
|
+
}
|
|
58
36
|
}
|
|
59
37
|
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
// RecentPainContext
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
|
-
|
|
64
|
-
export interface RecentPainContext {
|
|
65
|
-
mostRecent: {
|
|
66
|
-
score: number;
|
|
67
|
-
source: string;
|
|
68
|
-
reason: string;
|
|
69
|
-
timestamp: string;
|
|
70
|
-
sessionId: string;
|
|
71
|
-
/** Trajectory pain_events row ID — set when pain flag includes pain_event_id */
|
|
72
|
-
painEventId?: number;
|
|
73
|
-
} | null;
|
|
74
|
-
recentPainCount: number;
|
|
75
|
-
recentMaxPainScore: number;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// ---------------------------------------------------------------------------
|
|
79
|
-
// Task ID creation
|
|
80
|
-
// ---------------------------------------------------------------------------
|
|
81
|
-
|
|
82
38
|
export function createEvolutionTaskId(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
39
|
+
source: string,
|
|
40
|
+
score: number,
|
|
41
|
+
preview: string,
|
|
42
|
+
reason: string,
|
|
43
|
+
now: number,
|
|
88
44
|
): string {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
45
|
+
return createHash('md5')
|
|
46
|
+
.update(`${source}:${score}:${preview}:${reason}:${now}`)
|
|
47
|
+
.digest('hex')
|
|
48
|
+
.substring(0, 8);
|
|
93
49
|
}
|
|
94
50
|
|
|
95
|
-
// ---------------------------------------------------------------------------
|
|
96
|
-
// Queue helpers
|
|
97
|
-
// ---------------------------------------------------------------------------
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Check whether a specific task kind has a pending or in-progress entry.
|
|
101
|
-
*/
|
|
102
51
|
export function hasPendingTask(queue: EvolutionQueueItem[], taskKind: string): boolean {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Build a dedup key from pain context.
|
|
110
|
-
* Returns null when no pain context is available (bypasses dedup).
|
|
111
|
-
*/
|
|
112
|
-
function buildPainSourceKey(
|
|
113
|
-
painCtx: ReturnType<typeof readRecentPainContext>,
|
|
114
|
-
): string | null {
|
|
115
|
-
if (!painCtx.mostRecent) return null;
|
|
116
|
-
return `${painCtx.mostRecent.source}::${painCtx.mostRecent.reason?.slice(0, 50) ?? ''}`;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Check whether a similar sleep_reflection task completed recently.
|
|
121
|
-
*/
|
|
122
|
-
function hasRecentSimilarReflection(
|
|
123
|
-
queue: EvolutionQueueItemWithPain[],
|
|
124
|
-
painSourceKey: string,
|
|
125
|
-
now: number,
|
|
126
|
-
): EvolutionQueueItem | null {
|
|
127
|
-
return queue.find((t) => {
|
|
128
|
-
if (t.taskKind !== 'sleep_reflection') return false;
|
|
129
|
-
if (t.status !== 'completed') return false;
|
|
130
|
-
if (!t.completed_at) return false;
|
|
131
|
-
const age = now - new Date(t.completed_at).getTime();
|
|
132
|
-
if (age > SLEEP_REFLECTION_DEDUP_WINDOW_MS) return false;
|
|
133
|
-
const taskPainKey = buildPainSourceKey(t.recentPainContext ?? { mostRecent: null, recentPainCount: 0, recentMaxPainScore: 0 });
|
|
134
|
-
if (!taskPainKey) return false;
|
|
135
|
-
return taskPainKey === painSourceKey;
|
|
136
|
-
}) ?? null;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// ---------------------------------------------------------------------------
|
|
140
|
-
// Pain context
|
|
141
|
-
// ---------------------------------------------------------------------------
|
|
142
|
-
|
|
143
|
-
export function readRecentPainContext(wctx: WorkspaceContext): RecentPainContext {
|
|
144
|
-
const contract = readPainFlagContract(wctx.workspaceDir);
|
|
145
|
-
if (contract.status !== 'valid') {
|
|
146
|
-
return { mostRecent: null, recentPainCount: 0, recentMaxPainScore: 0 };
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
const score = parseInt(contract.data.score ?? '0', 10) || 0;
|
|
151
|
-
const source = contract.data.source ?? '';
|
|
152
|
-
const reason = contract.data.reason ?? '';
|
|
153
|
-
const timestamp = contract.data.time ?? '';
|
|
154
|
-
const sessionId = contract.data.session_id ?? '';
|
|
155
|
-
const painEventIdRaw = contract.data.pain_event_id;
|
|
156
|
-
const painEventId = painEventIdRaw ? parseInt(painEventIdRaw, 10) : undefined;
|
|
157
|
-
|
|
158
|
-
if (score > 0) {
|
|
159
|
-
return {
|
|
160
|
-
mostRecent: { score, source, reason, timestamp, sessionId, painEventId },
|
|
161
|
-
recentPainCount: 1,
|
|
162
|
-
recentMaxPainScore: score,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
} catch (err) {
|
|
166
|
-
// Best effort — non-fatal, but surface unexpected errors
|
|
167
|
-
|
|
168
|
-
console.warn(`[queue-io] Failed to read pain context (non-fatal): ${String(err)}`);
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return { mostRecent: null, recentPainCount: 0, recentMaxPainScore: 0 };
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Decide whether to skip enqueuing due to a recent similar reflection.
|
|
177
|
-
*/
|
|
178
|
-
export function shouldSkipForDedup(
|
|
179
|
-
queue: EvolutionQueueItemWithPain[],
|
|
180
|
-
wctx: WorkspaceContext,
|
|
181
|
-
logger: PluginLogger | undefined,
|
|
182
|
-
): boolean {
|
|
183
|
-
const recentPainContext = readRecentPainContext(wctx);
|
|
184
|
-
const painSourceKey = buildPainSourceKey(recentPainContext);
|
|
185
|
-
|
|
186
|
-
if (!painSourceKey) return false;
|
|
187
|
-
|
|
188
|
-
const now = Date.now();
|
|
189
|
-
const recentSimilarReflection = hasRecentSimilarReflection(queue, painSourceKey, now);
|
|
190
|
-
|
|
191
|
-
if (recentSimilarReflection) {
|
|
192
|
-
const completedTime = new Date(recentSimilarReflection.completed_at!).getTime();
|
|
193
|
-
logger?.debug?.(`[PD:EvolutionWorker] Skipping sleep_reflection — similar reflection completed ${Math.round((now - completedTime) / 60000)}min ago (same pain pattern: ${painSourceKey})`);
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// ---------------------------------------------------------------------------
|
|
200
|
-
// Enqueue functions
|
|
201
|
-
// ---------------------------------------------------------------------------
|
|
202
|
-
|
|
203
|
-
function enqueueNewSleepReflectionTask(
|
|
204
|
-
queue: EvolutionQueueItemWithPain[],
|
|
205
|
-
recentPainContext: ReturnType<typeof readRecentPainContext>,
|
|
206
|
-
queuePath: string,
|
|
207
|
-
logger: PluginLogger | undefined,
|
|
208
|
-
): void {
|
|
209
|
-
const taskId = createEvolutionTaskId('nocturnal', 50, 'idle workspace', 'Sleep-mode reflection', Date.now());
|
|
210
|
-
const nowIso = new Date().toISOString();
|
|
211
|
-
|
|
212
|
-
queue.push({
|
|
213
|
-
id: taskId,
|
|
214
|
-
taskKind: 'sleep_reflection',
|
|
215
|
-
priority: 'medium',
|
|
216
|
-
score: 50,
|
|
217
|
-
source: 'nocturnal',
|
|
218
|
-
reason: 'Sleep-mode reflection triggered by idle workspace',
|
|
219
|
-
trigger_text_preview: 'Idle workspace detected',
|
|
220
|
-
timestamp: nowIso,
|
|
221
|
-
enqueued_at: nowIso,
|
|
222
|
-
status: 'pending',
|
|
223
|
-
traceId: taskId,
|
|
224
|
-
retryCount: 0,
|
|
225
|
-
maxRetries: 1,
|
|
226
|
-
recentPainContext,
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// Cast to EvolutionQueueItem[] because saveEvolutionQueue expects the base type
|
|
230
|
-
// but the queue may contain extended fields (recentPainContext) that are
|
|
231
|
-
// serialized as part of the JSON - this is safe at runtime.
|
|
232
|
-
saveEvolutionQueue(queuePath, queue as unknown as EvolutionQueueItem[]);
|
|
233
|
-
logger?.info?.(`[PD:EvolutionWorker] Enqueued sleep_reflection task ${taskId}`);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Enqueue a sleep_reflection task if one is not already pending.
|
|
238
|
-
*/
|
|
239
|
-
export async function enqueueSleepReflectionTask(
|
|
240
|
-
wctx: WorkspaceContext,
|
|
241
|
-
logger: PluginLogger | undefined,
|
|
242
|
-
): Promise<void> {
|
|
243
|
-
const queuePath = wctx.resolve('EVOLUTION_QUEUE');
|
|
244
|
-
const releaseLock = await requireQueueLock(queuePath, logger, 'enqueueSleepReflection', EVOLUTION_QUEUE_LOCK_SUFFIX);
|
|
245
|
-
|
|
246
|
-
try {
|
|
247
|
-
const queue = loadEvolutionQueue(queuePath);
|
|
248
|
-
|
|
249
|
-
if (hasPendingTask(queue, 'sleep_reflection')) {
|
|
250
|
-
logger?.debug?.('[PD:EvolutionWorker] sleep_reflection task already pending/in-progress, skipping');
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (shouldSkipForDedup(queue, wctx, logger)) {
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const recentPainContext = readRecentPainContext(wctx);
|
|
259
|
-
enqueueNewSleepReflectionTask(queue, recentPainContext, queuePath, logger);
|
|
260
|
-
} finally {
|
|
261
|
-
releaseLock();
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Enqueue a keyword_optimization task if one is not already pending/in-progress.
|
|
267
|
-
*/
|
|
268
|
-
export async function enqueueKeywordOptimizationTask(
|
|
269
|
-
wctx: WorkspaceContext,
|
|
270
|
-
logger: PluginLogger | undefined,
|
|
271
|
-
): Promise<void> {
|
|
272
|
-
const queuePath = wctx.resolve('EVOLUTION_QUEUE');
|
|
273
|
-
const releaseLock = await requireQueueLock(queuePath, logger, 'enqueueKeywordOpt', EVOLUTION_QUEUE_LOCK_SUFFIX);
|
|
274
|
-
|
|
275
|
-
try {
|
|
276
|
-
const queue = loadEvolutionQueue(queuePath);
|
|
277
|
-
|
|
278
|
-
if (hasPendingTask(queue, 'keyword_optimization')) {
|
|
279
|
-
logger?.debug?.('[PD:EvolutionWorker] keyword_optimization task already pending/in-progress, skipping');
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const learner = CorrectionCueLearner.get(wctx.stateDir);
|
|
284
|
-
if (!learner.canRunKeywordOptimization()) {
|
|
285
|
-
logger?.debug?.('[PD:EvolutionWorker] keyword_optimization throttle exhausted, skipping');
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const taskId = createEvolutionTaskId('keyword_optimization', 50, 'keyword optimization', 'Keyword optimization via LLM', Date.now());
|
|
290
|
-
const nowIso = new Date().toISOString();
|
|
291
|
-
|
|
292
|
-
queue.push({
|
|
293
|
-
id: taskId,
|
|
294
|
-
taskKind: 'keyword_optimization',
|
|
295
|
-
priority: 'medium',
|
|
296
|
-
score: 50,
|
|
297
|
-
source: 'correction',
|
|
298
|
-
reason: 'Keyword optimization triggered by heartbeat',
|
|
299
|
-
trigger_text_preview: 'Keyword optimization via LLM',
|
|
300
|
-
timestamp: nowIso,
|
|
301
|
-
enqueued_at: nowIso,
|
|
302
|
-
status: 'pending',
|
|
303
|
-
traceId: taskId,
|
|
304
|
-
retryCount: 0,
|
|
305
|
-
maxRetries: 1,
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
saveEvolutionQueue(queuePath, queue);
|
|
309
|
-
logger?.info?.(`[PD:EvolutionWorker] Enqueued keyword_optimization task ${taskId}`);
|
|
310
|
-
} finally {
|
|
311
|
-
releaseLock();
|
|
312
|
-
}
|
|
52
|
+
return queue.some(
|
|
53
|
+
(t) => t.taskKind === taskKind && (t.status === 'pending' || t.status === 'in_progress'),
|
|
54
|
+
);
|
|
313
55
|
}
|
|
314
56
|
|
|
315
57
|
export async function acquireQueueLock(
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
58
|
+
resourcePath: string,
|
|
59
|
+
logger: PluginLogger | { warn?: (message: string) => void; info?: (message: string) => void } | undefined,
|
|
60
|
+
lockSuffix: string = EVOLUTION_QUEUE_LOCK_SUFFIX,
|
|
319
61
|
): Promise<() => void> {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
62
|
+
try {
|
|
63
|
+
const ctx: LockContext = await acquireLockAsync(resourcePath, {
|
|
64
|
+
lockSuffix,
|
|
65
|
+
maxRetries: LOCK_MAX_RETRIES,
|
|
66
|
+
baseRetryDelayMs: LOCK_RETRY_DELAY_MS,
|
|
67
|
+
lockStaleMs: LOCK_STALE_MS,
|
|
68
|
+
});
|
|
69
|
+
return () => releaseImportedLock(ctx);
|
|
70
|
+
} catch (error: unknown) {
|
|
71
|
+
const warn = logger?.warn;
|
|
72
|
+
warn?.(`[PD:EvolutionWorker] Failed to acquire lock for ${resourcePath}: ${String(error)}`);
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
333
75
|
}
|
|
334
76
|
|
|
335
|
-
/**
|
|
336
|
-
* RAII-style lock guard — always releases the lock on exceptions.
|
|
337
|
-
*/
|
|
338
77
|
export async function withQueueLock<T>(
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
78
|
+
resourcePath: string,
|
|
79
|
+
logger: PluginLogger | { warn?: (message: string) => void; info?: (message: string) => void } | undefined,
|
|
80
|
+
scope: string,
|
|
81
|
+
fn: () => Promise<T>,
|
|
343
82
|
): Promise<T> {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
83
|
+
const releaseLock = await acquireQueueLock(resourcePath, logger, EVOLUTION_QUEUE_LOCK_SUFFIX);
|
|
84
|
+
try {
|
|
85
|
+
return await fn();
|
|
86
|
+
} finally {
|
|
87
|
+
releaseLock();
|
|
88
|
+
}
|
|
350
89
|
}
|
|
351
90
|
|
|
352
|
-
/**
|
|
353
|
-
* Load and migrate the evolution queue. Returns empty array if file doesn't exist.
|
|
354
|
-
*/
|
|
355
91
|
export function loadEvolutionQueue(queuePath: string): EvolutionQueueItem[] {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
console.warn(`[queue-io] Failed to load evolution queue (recovering with empty): ${String(err)}`);
|
|
367
|
-
|
|
368
|
-
rawQueue = [];
|
|
369
|
-
}
|
|
92
|
+
let rawQueue: RawQueueItem[] = [];
|
|
93
|
+
try {
|
|
94
|
+
rawQueue = JSON.parse(fs.readFileSync(queuePath, 'utf8'));
|
|
95
|
+
} catch (err) {
|
|
96
|
+
if ((err as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
97
|
+
rawQueue = [];
|
|
98
|
+
} else {
|
|
99
|
+
console.warn(`[queue-io] Failed to load evolution queue (recovering with empty): ${String(err)}`);
|
|
100
|
+
rawQueue = [];
|
|
370
101
|
}
|
|
371
|
-
|
|
102
|
+
}
|
|
103
|
+
return migrateQueueToV2(rawQueue) as unknown as EvolutionQueueItem[];
|
|
372
104
|
}
|
|
373
105
|
|
|
374
|
-
/**
|
|
375
|
-
* Atomically write the queue to disk.
|
|
376
|
-
*/
|
|
377
106
|
export function saveEvolutionQueue(queuePath: string, queue: EvolutionQueueItem[]): void {
|
|
378
|
-
|
|
107
|
+
atomicWriteFileSync(queuePath, JSON.stringify(queue, null, 2));
|
|
379
108
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
|
+
import Database from 'better-sqlite3';
|
|
2
3
|
import * as path from 'path';
|
|
3
4
|
import { readPainFlagData } from '../core/pain.js';
|
|
4
5
|
import { listSessions } from '../core/session-tracker.js';
|
|
5
6
|
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
6
7
|
import { evaluatePhase3Inputs } from './phase3-input-filter.js';
|
|
7
8
|
import { TrajectoryRegistry } from '../core/trajectory.js';
|
|
8
|
-
import { getPendingDiagnosticianTasks } from '../core/diagnostician-task-store.js';
|
|
9
9
|
import type { WorkflowStage } from '../core/workflow-funnel-loader.js';
|
|
10
10
|
import type { RuntimeTruth, AnalyticsTruth } from '../types/runtime-summary.js';
|
|
11
|
+
import { buildGfiWorkspaceSnapshot } from '@principles/core/runtime-v2';
|
|
12
|
+
import type { GfiWorkspaceSnapshot } from '@principles/core/runtime-v2';
|
|
11
13
|
|
|
12
14
|
export type RuntimeDataQuality = 'authoritative' | 'partial';
|
|
13
15
|
export type RuntimeRewardPolicy =
|
|
@@ -47,6 +49,7 @@ export interface RuntimeSummary {
|
|
|
47
49
|
peak: number | null;
|
|
48
50
|
sources: RuntimeSummarySource[];
|
|
49
51
|
dataQuality: RuntimeDataQuality;
|
|
52
|
+
workspaceSnapshot?: GfiWorkspaceSnapshot;
|
|
50
53
|
};
|
|
51
54
|
evolution: {
|
|
52
55
|
queue: {
|
|
@@ -62,8 +65,8 @@ export interface RuntimeSummary {
|
|
|
62
65
|
};
|
|
63
66
|
dataQuality: RuntimeDataQuality;
|
|
64
67
|
};
|
|
65
|
-
// D:
|
|
66
|
-
|
|
68
|
+
// D: Runtime Diagnostician chain (M8) — replaced legacy heartbeat path
|
|
69
|
+
runtimeDiagnosis: {
|
|
67
70
|
/** Tasks pending in diagnostician_tasks.json (not yet processed by heartbeat) */
|
|
68
71
|
pendingTasks: number;
|
|
69
72
|
/** Total diagnosis tasks written by evolution worker (today from event log) */
|
|
@@ -123,6 +126,10 @@ export interface RuntimeSummary {
|
|
|
123
126
|
interface PersistedSessionState {
|
|
124
127
|
sessionId: string;
|
|
125
128
|
currentGfi?: number;
|
|
129
|
+
gfiBySource?: Record<string, number>;
|
|
130
|
+
lastErrorSource?: string;
|
|
131
|
+
consecutiveErrors?: number;
|
|
132
|
+
lastGfiDecayAt?: number;
|
|
126
133
|
dailyGfiPeak?: number;
|
|
127
134
|
lastActivityAt?: number;
|
|
128
135
|
lastControlActivityAt?: number;
|
|
@@ -311,6 +318,23 @@ export class RuntimeSummaryService {
|
|
|
311
318
|
const gfiPeak =
|
|
312
319
|
sessionPeak ?? (Number.isFinite(dailyGfiPeak) ? Number(dailyGfiPeak) : null);
|
|
313
320
|
|
|
321
|
+
// PRI-78/PRI-82: Build authoritative GFI workspace snapshot (active vs stale)
|
|
322
|
+
// Uses real persisted GFI fields: gfiBySource, consecutiveErrors, lastErrorSource,
|
|
323
|
+
// lastGfiDecayAt, dailyGfiPeak from session-tracker persistence.
|
|
324
|
+
const gfiWorkspaceSnapshot: GfiWorkspaceSnapshot = buildGfiWorkspaceSnapshot({
|
|
325
|
+
sessions: sessions.map((s) => ({
|
|
326
|
+
sessionId: s.sessionId,
|
|
327
|
+
currentGfi: s.currentGfi ?? 0,
|
|
328
|
+
gfiBySource: s.gfiBySource ?? {},
|
|
329
|
+
consecutiveErrors: s.consecutiveErrors ?? 0,
|
|
330
|
+
lastErrorSource: s.lastErrorSource,
|
|
331
|
+
lastGfiDecayAt: s.lastGfiDecayAt,
|
|
332
|
+
dailyGfiPeak: s.dailyGfiPeak,
|
|
333
|
+
lastActivityAt: s.lastControlActivityAt ?? s.lastActivityAt ?? 0,
|
|
334
|
+
})),
|
|
335
|
+
nowMs: Date.now(),
|
|
336
|
+
});
|
|
337
|
+
|
|
314
338
|
pushWarning(warnings, GFI_PARTIAL_WARNING);
|
|
315
339
|
if (sessionPeak === null && Number.isFinite(dailyGfiPeak)) {
|
|
316
340
|
pushWarning(warnings, DAILY_GFI_WARNING);
|
|
@@ -343,13 +367,25 @@ export class RuntimeSummaryService {
|
|
|
343
367
|
const gfiSources = this.buildGfiSources(events, selectedSessionId);
|
|
344
368
|
const gateStats = this.buildGateStats(events, selectedSessionId, warnings);
|
|
345
369
|
|
|
346
|
-
// D:
|
|
347
|
-
// Read pending tasks from the diagnostician task store
|
|
348
|
-
const pendingDiagTasks = getPendingDiagnosticianTasks(wctx.stateDir);
|
|
370
|
+
// D: Runtime Diagnostician chain (M8) — queries runtime-v2 SQLite task store
|
|
349
371
|
// Read heartbeat diagnosis stats from daily event log
|
|
350
372
|
const diagDailyStats = dailyStats?.[todayStr]?.evolution;
|
|
351
|
-
|
|
352
|
-
|
|
373
|
+
let pendingRuntimeDiagTasks = 0;
|
|
374
|
+
try {
|
|
375
|
+
const taskStoreDbPath = path.join(wctx.stateDir, '.principles', 'db', 'task-store.db');
|
|
376
|
+
if (fs.existsSync(taskStoreDbPath)) {
|
|
377
|
+
const db = new Database(taskStoreDbPath, { readonly: true });
|
|
378
|
+
const row = db.prepare(`
|
|
379
|
+
SELECT COUNT(*) as count FROM tasks
|
|
380
|
+
WHERE task_kind = 'diagnostician' AND status = 'pending'
|
|
381
|
+
`).get() as { count: number };
|
|
382
|
+
pendingRuntimeDiagTasks = row?.count ?? 0;
|
|
383
|
+
db.close();
|
|
384
|
+
}
|
|
385
|
+
} catch { /* task store not yet initialized — 0 pending */ }
|
|
386
|
+
// TODO(PRI-XXX): distinguish "not initialized" from permission/corruption/query errors
|
|
387
|
+
const runtimeDiagnosis = {
|
|
388
|
+
pendingTasks: pendingRuntimeDiagTasks,
|
|
353
389
|
tasksWrittenToday: diagDailyStats?.diagnosisTasksWritten ?? 0,
|
|
354
390
|
reportsWrittenToday: diagDailyStats?.diagnosticianReportsWritten ?? 0,
|
|
355
391
|
reportsMissingJsonToday: diagDailyStats?.reportsMissingJson ?? 0,
|
|
@@ -361,15 +397,15 @@ export class RuntimeSummaryService {
|
|
|
361
397
|
// D: Stall detection — high-signal warning when the diagnostician loop appears broken.
|
|
362
398
|
// Conditions: tasks are being injected (heartbeats > 0) but no reports are being written.
|
|
363
399
|
if (
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
400
|
+
runtimeDiagnosis.heartbeatsInjectedToday > 0 &&
|
|
401
|
+
runtimeDiagnosis.reportsWrittenToday === 0 &&
|
|
402
|
+
runtimeDiagnosis.pendingTasks > 0
|
|
367
403
|
) {
|
|
368
404
|
pushWarning(
|
|
369
405
|
warnings,
|
|
370
406
|
'Diagnostician appears stalled: heartbeats are injecting tasks ' +
|
|
371
|
-
`(${
|
|
372
|
-
`${
|
|
407
|
+
`(${runtimeDiagnosis.heartbeatsInjectedToday}) but no reports are being written. ` +
|
|
408
|
+
`${runtimeDiagnosis.pendingTasks} task(s) remain pending. ` +
|
|
373
409
|
'Check prompt injection size limits and diagnostician task processing.'
|
|
374
410
|
);
|
|
375
411
|
}
|
|
@@ -422,6 +458,7 @@ export class RuntimeSummaryService {
|
|
|
422
458
|
peak: gfiPeak,
|
|
423
459
|
sources: gfiSources,
|
|
424
460
|
dataQuality: 'partial',
|
|
461
|
+
workspaceSnapshot: gfiWorkspaceSnapshot,
|
|
425
462
|
},
|
|
426
463
|
evolution: {
|
|
427
464
|
queue: queueStats,
|
|
@@ -451,8 +488,8 @@ export class RuntimeSummaryService {
|
|
|
451
488
|
lastSignal: lastPainSignal,
|
|
452
489
|
},
|
|
453
490
|
gate: gateStats,
|
|
454
|
-
// D: Heartbeat Diagnostician chain
|
|
455
|
-
|
|
491
|
+
// D: Heartbeat Diagnostician chain
|
|
492
|
+
runtimeDiagnosis,
|
|
456
493
|
...(workflowFunnelsOutput && { workflowFunnels: workflowFunnelsOutput }),
|
|
457
494
|
metadata: {
|
|
458
495
|
generatedAt,
|
|
@@ -524,6 +561,12 @@ export class RuntimeSummaryService {
|
|
|
524
561
|
sessionId: live.sessionId,
|
|
525
562
|
currentGfi:
|
|
526
563
|
Number.isFinite(live.currentGfi) ? Number(live.currentGfi) : persisted?.currentGfi,
|
|
564
|
+
gfiBySource:
|
|
565
|
+
live.gfiBySource ? { ...live.gfiBySource } : persisted?.gfiBySource,
|
|
566
|
+
lastErrorSource: live.lastErrorSource || persisted?.lastErrorSource,
|
|
567
|
+
consecutiveErrors:
|
|
568
|
+
Number.isFinite(live.consecutiveErrors) ? Number(live.consecutiveErrors) : persisted?.consecutiveErrors,
|
|
569
|
+
lastGfiDecayAt: live.lastGfiDecayAt || persisted?.lastGfiDecayAt,
|
|
527
570
|
dailyGfiPeak:
|
|
528
571
|
Number.isFinite(live.dailyGfiPeak) ? Number(live.dailyGfiPeak) : persisted?.dailyGfiPeak,
|
|
529
572
|
lastActivityAt:
|
|
@@ -711,7 +754,7 @@ export class RuntimeSummaryService {
|
|
|
711
754
|
|
|
712
755
|
return {
|
|
713
756
|
source: `tool_failure:${String(entry.data?.toolName ?? 'unknown')}`,
|
|
714
|
-
score: this.asFiniteNumber(entry.data?.gfi),
|
|
757
|
+
score: this.asFiniteNumber(entry.data?.gfiAfter ?? entry.data?.gfi),
|
|
715
758
|
ts: entry.ts,
|
|
716
759
|
};
|
|
717
760
|
});
|
|
@@ -1,33 +1,7 @@
|
|
|
1
|
-
export {
|
|
2
|
-
RuntimeDirectDriver,
|
|
3
|
-
type TransportDriver,
|
|
4
|
-
type RunParams,
|
|
5
|
-
type RunResult,
|
|
6
|
-
type WaitParams,
|
|
7
|
-
type WaitResult,
|
|
8
|
-
type GetResultParams,
|
|
9
|
-
type GetResultResult,
|
|
10
|
-
type CleanupParams,
|
|
11
|
-
} from './runtime-direct-driver.js';
|
|
12
|
-
|
|
13
1
|
export { isExpectedSubagentError } from './subagent-error-utils.js';
|
|
14
2
|
|
|
15
3
|
export { WorkflowStore, type WorkflowStoreOptions } from './workflow-store.js';
|
|
16
4
|
|
|
17
|
-
export {
|
|
18
|
-
EmpathyObserverWorkflowManager,
|
|
19
|
-
createEmpathyObserverWorkflowManager,
|
|
20
|
-
empathyObserverWorkflowSpec,
|
|
21
|
-
type EmpathyObserverWorkflowOptions,
|
|
22
|
-
} from './empathy-observer-workflow-manager.js';
|
|
23
|
-
|
|
24
|
-
export {
|
|
25
|
-
NocturnalWorkflowManager,
|
|
26
|
-
nocturnalWorkflowSpec,
|
|
27
|
-
type NocturnalWorkflowOptions,
|
|
28
|
-
type NocturnalResult,
|
|
29
|
-
} from './nocturnal-workflow-manager.js';
|
|
30
|
-
|
|
31
5
|
export type {
|
|
32
6
|
WorkflowState,
|
|
33
7
|
WorkflowTransport,
|
|
@@ -36,23 +10,8 @@ export type {
|
|
|
36
10
|
WorkflowPersistContext,
|
|
37
11
|
WorkflowHandle,
|
|
38
12
|
SubagentWorkflowSpec,
|
|
39
|
-
EmpathyObserverWorkflowSpec,
|
|
40
|
-
EmpathyObserverPayload,
|
|
41
|
-
EmpathyResult,
|
|
42
13
|
WorkflowRow,
|
|
43
14
|
WorkflowEventRow,
|
|
44
15
|
WorkflowDebugSummary,
|
|
45
16
|
} from './types.js';
|
|
46
17
|
|
|
47
|
-
export {
|
|
48
|
-
CorrectionObserverWorkflowManager,
|
|
49
|
-
createCorrectionObserverWorkflowManager,
|
|
50
|
-
correctionObserverWorkflowSpec,
|
|
51
|
-
type CorrectionObserverWorkflowOptions,
|
|
52
|
-
} from './correction-observer-workflow-manager.js';
|
|
53
|
-
|
|
54
|
-
export type {
|
|
55
|
-
CorrectionObserverPayload,
|
|
56
|
-
CorrectionObserverResult,
|
|
57
|
-
CorrectionObserverWorkflowSpec,
|
|
58
|
-
} from './correction-observer-types.js';
|