pulseed 0.4.0 → 0.4.1
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/dist/base/state/state-manager-goal-write.d.ts +22 -0
- package/dist/base/state/state-manager-goal-write.d.ts.map +1 -0
- package/dist/base/state/state-manager-goal-write.js +74 -0
- package/dist/base/state/state-manager-goal-write.js.map +1 -0
- package/dist/base/state/state-manager-wal.d.ts +11 -0
- package/dist/base/state/state-manager-wal.d.ts.map +1 -0
- package/dist/base/state/state-manager-wal.js +89 -0
- package/dist/base/state/state-manager-wal.js.map +1 -0
- package/dist/base/state/state-manager.d.ts +1 -4
- package/dist/base/state/state-manager.d.ts.map +1 -1
- package/dist/base/state/state-manager.js +18 -127
- package/dist/base/state/state-manager.js.map +1 -1
- package/dist/interface/chat/chat-runner.d.ts +1 -1
- package/dist/interface/chat/event-subscriber.d.ts +4 -0
- package/dist/interface/chat/event-subscriber.d.ts.map +1 -1
- package/dist/interface/chat/event-subscriber.js +49 -2
- package/dist/interface/chat/event-subscriber.js.map +1 -1
- package/dist/interface/chat/tend-command.d.ts +1 -1
- package/dist/interface/cli/cli-command-registry.js +1 -1
- package/dist/interface/cli/cli-command-registry.js.map +1 -1
- package/dist/interface/cli/commands/chat.js +2 -2
- package/dist/interface/cli/commands/daemon.d.ts.map +1 -1
- package/dist/interface/cli/commands/daemon.js +87 -44
- package/dist/interface/cli/commands/daemon.js.map +1 -1
- package/dist/interface/cli/commands/schedule.js +2 -2
- package/dist/interface/cli/commands/setup/steps-runtime.js +1 -1
- package/dist/interface/cli/ensure-api-key.d.ts +4 -1
- package/dist/interface/cli/ensure-api-key.d.ts.map +1 -1
- package/dist/interface/cli/ensure-api-key.js +52 -15
- package/dist/interface/cli/ensure-api-key.js.map +1 -1
- package/dist/interface/tui/app.d.ts +1 -1
- package/dist/interface/tui/chat/scroll.d.ts +14 -0
- package/dist/interface/tui/chat/scroll.d.ts.map +1 -0
- package/dist/interface/tui/chat/scroll.js +46 -0
- package/dist/interface/tui/chat/scroll.js.map +1 -0
- package/dist/interface/tui/chat/suggestions.d.ts +8 -0
- package/dist/interface/tui/chat/suggestions.d.ts.map +1 -0
- package/dist/interface/tui/chat/suggestions.js +112 -0
- package/dist/interface/tui/chat/suggestions.js.map +1 -0
- package/dist/interface/tui/chat/types.d.ts +31 -0
- package/dist/interface/tui/chat/types.d.ts.map +1 -0
- package/dist/interface/tui/chat/types.js +2 -0
- package/dist/interface/tui/chat/types.js.map +1 -0
- package/dist/interface/tui/chat/viewport.d.ts +3 -0
- package/dist/interface/tui/chat/viewport.d.ts.map +1 -0
- package/dist/interface/tui/chat/viewport.js +78 -0
- package/dist/interface/tui/chat/viewport.js.map +1 -0
- package/dist/interface/tui/chat.d.ts +5 -49
- package/dist/interface/tui/chat.d.ts.map +1 -1
- package/dist/interface/tui/chat.js +7 -236
- package/dist/interface/tui/chat.js.map +1 -1
- package/dist/interface/tui/entry.js +3 -3
- package/dist/interface/tui/use-loop.d.ts +1 -1
- package/dist/orchestrator/execution/task/task-lifecycle.d.ts +3 -0
- package/dist/orchestrator/execution/task/task-lifecycle.d.ts.map +1 -1
- package/dist/orchestrator/execution/task/task-lifecycle.js +3 -0
- package/dist/orchestrator/execution/task/task-lifecycle.js.map +1 -1
- package/dist/orchestrator/execution/task/task-verifier-rules.d.ts.map +1 -1
- package/dist/orchestrator/execution/task/task-verifier-rules.js +34 -2
- package/dist/orchestrator/execution/task/task-verifier-rules.js.map +1 -1
- package/dist/orchestrator/execution/task/task-verifier-types.d.ts +2 -0
- package/dist/orchestrator/execution/task/task-verifier-types.d.ts.map +1 -1
- package/dist/orchestrator/loop/checkpoint-manager-loop.d.ts +1 -1
- package/dist/orchestrator/loop/checkpoint-manager-loop.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop/capability.d.ts +22 -0
- package/dist/orchestrator/loop/core-loop/capability.d.ts.map +1 -0
- package/dist/orchestrator/loop/core-loop/capability.js +151 -0
- package/dist/orchestrator/loop/core-loop/capability.js.map +1 -0
- package/dist/orchestrator/loop/core-loop/contracts.d.ts +245 -0
- package/dist/orchestrator/loop/core-loop/contracts.d.ts.map +1 -0
- package/dist/orchestrator/loop/core-loop/contracts.js +40 -0
- package/dist/orchestrator/loop/core-loop/contracts.js.map +1 -0
- package/dist/orchestrator/loop/core-loop/control.d.ts +27 -0
- package/dist/orchestrator/loop/core-loop/control.d.ts.map +1 -0
- package/dist/orchestrator/loop/core-loop/control.js +72 -0
- package/dist/orchestrator/loop/core-loop/control.js.map +1 -0
- package/dist/orchestrator/loop/core-loop/learning.d.ts +31 -0
- package/dist/orchestrator/loop/core-loop/learning.d.ts.map +1 -0
- package/dist/orchestrator/loop/core-loop/learning.js +92 -0
- package/dist/orchestrator/loop/core-loop/learning.js.map +1 -0
- package/dist/orchestrator/loop/core-loop/preparation.d.ts +63 -0
- package/dist/orchestrator/loop/core-loop/preparation.d.ts.map +1 -0
- package/dist/orchestrator/loop/core-loop/preparation.js +362 -0
- package/dist/orchestrator/loop/core-loop/preparation.js.map +1 -0
- package/dist/orchestrator/loop/core-loop/task-cycle.d.ts +29 -0
- package/dist/orchestrator/loop/core-loop/task-cycle.d.ts.map +1 -0
- package/dist/orchestrator/loop/core-loop/task-cycle.js +674 -0
- package/dist/orchestrator/loop/core-loop/task-cycle.js.map +1 -0
- package/dist/orchestrator/loop/core-loop-capability.d.ts +1 -24
- package/dist/orchestrator/loop/core-loop-capability.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop-capability.js +1 -153
- package/dist/orchestrator/loop/core-loop-capability.js.map +1 -1
- package/dist/orchestrator/loop/core-loop-learning.d.ts +1 -34
- package/dist/orchestrator/loop/core-loop-learning.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop-learning.js +1 -95
- package/dist/orchestrator/loop/core-loop-learning.js.map +1 -1
- package/dist/orchestrator/loop/core-loop-phases-b.d.ts +1 -31
- package/dist/orchestrator/loop/core-loop-phases-b.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop-phases-b.js +1 -669
- package/dist/orchestrator/loop/core-loop-phases-b.js.map +1 -1
- package/dist/orchestrator/loop/core-loop-phases-c.d.ts +1 -26
- package/dist/orchestrator/loop/core-loop-phases-c.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop-phases-c.js +1 -71
- package/dist/orchestrator/loop/core-loop-phases-c.js.map +1 -1
- package/dist/orchestrator/loop/core-loop-phases.d.ts +1 -68
- package/dist/orchestrator/loop/core-loop-phases.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop-phases.js +1 -367
- package/dist/orchestrator/loop/core-loop-phases.js.map +1 -1
- package/dist/orchestrator/loop/core-loop-types.d.ts +1 -244
- package/dist/orchestrator/loop/core-loop-types.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop-types.js +1 -39
- package/dist/orchestrator/loop/core-loop-types.js.map +1 -1
- package/dist/orchestrator/loop/core-loop.d.ts +3 -3
- package/dist/orchestrator/loop/core-loop.d.ts.map +1 -1
- package/dist/orchestrator/loop/core-loop.js +6 -6
- package/dist/orchestrator/loop/core-loop.js.map +1 -1
- package/dist/orchestrator/loop/loop-report-helper.d.ts +1 -1
- package/dist/orchestrator/loop/loop-report-helper.d.ts.map +1 -1
- package/dist/orchestrator/loop/parallel-dispatch.d.ts +2 -2
- package/dist/orchestrator/loop/parallel-dispatch.d.ts.map +1 -1
- package/dist/orchestrator/loop/post-loop-hooks.d.ts +1 -1
- package/dist/orchestrator/loop/post-loop-hooks.d.ts.map +1 -1
- package/dist/orchestrator/loop/tree-loop-runner.d.ts +1 -1
- package/dist/orchestrator/loop/tree-loop-runner.d.ts.map +1 -1
- package/dist/orchestrator/loop/tree-loop-runner.js +1 -1
- package/dist/orchestrator/loop/tree-loop-runner.js.map +1 -1
- package/dist/platform/dream/dream-schedule-suggestions.d.ts +1 -1
- package/dist/platform/drive/drive-system.d.ts +8 -0
- package/dist/platform/drive/drive-system.d.ts.map +1 -1
- package/dist/platform/drive/drive-system.js +39 -22
- package/dist/platform/drive/drive-system.js.map +1 -1
- package/dist/platform/observation/engine/observe-context.d.ts +4 -0
- package/dist/platform/observation/engine/observe-context.d.ts.map +1 -0
- package/dist/platform/observation/engine/observe-context.js +26 -0
- package/dist/platform/observation/engine/observe-context.js.map +1 -0
- package/dist/platform/observation/engine/observe-datasource-stage.d.ts +33 -0
- package/dist/platform/observation/engine/observe-datasource-stage.d.ts.map +1 -0
- package/dist/platform/observation/engine/observe-datasource-stage.js +66 -0
- package/dist/platform/observation/engine/observe-datasource-stage.js.map +1 -0
- package/dist/platform/observation/engine/observe-llm-stage.d.ts +25 -0
- package/dist/platform/observation/engine/observe-llm-stage.d.ts.map +1 -0
- package/dist/platform/observation/engine/observe-llm-stage.js +79 -0
- package/dist/platform/observation/engine/observe-llm-stage.js.map +1 -0
- package/dist/platform/observation/engine/observe-precheck.d.ts +21 -0
- package/dist/platform/observation/engine/observe-precheck.d.ts.map +1 -0
- package/dist/platform/observation/engine/observe-precheck.js +51 -0
- package/dist/platform/observation/engine/observe-precheck.js.map +1 -0
- package/dist/platform/observation/engine/observe-self-report.d.ts +18 -0
- package/dist/platform/observation/engine/observe-self-report.d.ts.map +1 -0
- package/dist/platform/observation/engine/observe-self-report.js +26 -0
- package/dist/platform/observation/engine/observe-self-report.js.map +1 -0
- package/dist/platform/observation/engine/observe-tool-stage.d.ts +21 -0
- package/dist/platform/observation/engine/observe-tool-stage.d.ts.map +1 -0
- package/dist/platform/observation/engine/observe-tool-stage.js +49 -0
- package/dist/platform/observation/engine/observe-tool-stage.js.map +1 -0
- package/dist/platform/observation/observation-engine.d.ts.map +1 -1
- package/dist/platform/observation/observation-engine.js +67 -246
- package/dist/platform/observation/observation-engine.js.map +1 -1
- package/dist/prompt/context-assembler.d.ts +61 -13
- package/dist/prompt/context-assembler.d.ts.map +1 -1
- package/dist/prompt/context-assembler.js +18 -3
- package/dist/prompt/context-assembler.js.map +1 -1
- package/dist/runtime/approval-broker.d.ts.map +1 -1
- package/dist/runtime/approval-broker.js +1 -0
- package/dist/runtime/approval-broker.js.map +1 -1
- package/dist/runtime/command-dispatcher.d.ts +35 -0
- package/dist/runtime/command-dispatcher.d.ts.map +1 -0
- package/dist/runtime/command-dispatcher.js +145 -0
- package/dist/runtime/command-dispatcher.js.map +1 -0
- package/dist/runtime/daemon/client.d.ts +67 -0
- package/dist/runtime/daemon/client.d.ts.map +1 -0
- package/dist/runtime/daemon/client.js +330 -0
- package/dist/runtime/daemon/client.js.map +1 -0
- package/dist/runtime/daemon/health.d.ts +31 -0
- package/dist/runtime/daemon/health.d.ts.map +1 -0
- package/dist/runtime/daemon/health.js +113 -0
- package/dist/runtime/daemon/health.js.map +1 -0
- package/dist/runtime/daemon/index.d.ts +9 -0
- package/dist/runtime/daemon/index.d.ts.map +1 -0
- package/dist/runtime/daemon/index.js +8 -0
- package/dist/runtime/daemon/index.js.map +1 -0
- package/dist/runtime/daemon/maintenance.d.ts +47 -0
- package/dist/runtime/daemon/maintenance.d.ts.map +1 -0
- package/dist/runtime/daemon/maintenance.js +230 -0
- package/dist/runtime/daemon/maintenance.js.map +1 -0
- package/dist/runtime/daemon/persistence.d.ts +20 -0
- package/dist/runtime/daemon/persistence.d.ts.map +1 -0
- package/dist/runtime/daemon/persistence.js +112 -0
- package/dist/runtime/daemon/persistence.js.map +1 -0
- package/dist/runtime/daemon/runner-lifecycle.d.ts +29 -0
- package/dist/runtime/daemon/runner-lifecycle.d.ts.map +1 -0
- package/dist/runtime/daemon/runner-lifecycle.js +56 -0
- package/dist/runtime/daemon/runner-lifecycle.js.map +1 -0
- package/dist/runtime/daemon/runner.d.ts +229 -0
- package/dist/runtime/daemon/runner.d.ts.map +1 -0
- package/dist/runtime/daemon/runner.js +875 -0
- package/dist/runtime/daemon/runner.js.map +1 -0
- package/dist/runtime/daemon/runtime-ownership.d.ts +30 -0
- package/dist/runtime/daemon/runtime-ownership.d.ts.map +1 -0
- package/dist/runtime/daemon/runtime-ownership.js +132 -0
- package/dist/runtime/daemon/runtime-ownership.js.map +1 -0
- package/dist/runtime/daemon/signals.d.ts +17 -0
- package/dist/runtime/daemon/signals.d.ts.map +1 -0
- package/dist/runtime/daemon/signals.js +31 -0
- package/dist/runtime/daemon/signals.js.map +1 -0
- package/dist/runtime/daemon/types.d.ts +8 -0
- package/dist/runtime/daemon/types.d.ts.map +1 -0
- package/dist/runtime/daemon/types.js +2 -0
- package/dist/runtime/daemon/types.js.map +1 -0
- package/dist/runtime/daemon-client.d.ts +1 -55
- package/dist/runtime/daemon-client.d.ts.map +1 -1
- package/dist/runtime/daemon-client.js +1 -297
- package/dist/runtime/daemon-client.js.map +1 -1
- package/dist/runtime/daemon-health.d.ts +1 -30
- package/dist/runtime/daemon-health.d.ts.map +1 -1
- package/dist/runtime/daemon-health.js +1 -112
- package/dist/runtime/daemon-health.js.map +1 -1
- package/dist/runtime/daemon-runner-lifecycle.d.ts +2 -0
- package/dist/runtime/daemon-runner-lifecycle.d.ts.map +1 -0
- package/dist/runtime/daemon-runner-lifecycle.js +2 -0
- package/dist/runtime/daemon-runner-lifecycle.js.map +1 -0
- package/dist/runtime/daemon-runner.d.ts +1 -231
- package/dist/runtime/daemon-runner.d.ts.map +1 -1
- package/dist/runtime/daemon-runner.js +1 -1042
- package/dist/runtime/daemon-runner.js.map +1 -1
- package/dist/runtime/daemon-runtime-ownership.d.ts +2 -0
- package/dist/runtime/daemon-runtime-ownership.d.ts.map +1 -0
- package/dist/runtime/daemon-runtime-ownership.js +2 -0
- package/dist/runtime/daemon-runtime-ownership.js.map +1 -0
- package/dist/runtime/daemon-signals.d.ts +1 -16
- package/dist/runtime/daemon-signals.d.ts.map +1 -1
- package/dist/runtime/daemon-signals.js +1 -30
- package/dist/runtime/daemon-signals.js.map +1 -1
- package/dist/runtime/event/dispatcher.d.ts +34 -0
- package/dist/runtime/event/dispatcher.d.ts.map +1 -0
- package/dist/runtime/event/dispatcher.js +124 -0
- package/dist/runtime/event/dispatcher.js.map +1 -0
- package/dist/runtime/event/index.d.ts +5 -0
- package/dist/runtime/event/index.d.ts.map +1 -0
- package/dist/runtime/event/index.js +5 -0
- package/dist/runtime/event/index.js.map +1 -0
- package/dist/runtime/event/server-snapshot-reader.d.ts +31 -0
- package/dist/runtime/event/server-snapshot-reader.d.ts.map +1 -0
- package/dist/runtime/event/server-snapshot-reader.js +94 -0
- package/dist/runtime/event/server-snapshot-reader.js.map +1 -0
- package/dist/runtime/event/server-sse.d.ts +25 -0
- package/dist/runtime/event/server-sse.d.ts.map +1 -0
- package/dist/runtime/event/server-sse.js +149 -0
- package/dist/runtime/event/server-sse.js.map +1 -0
- package/dist/runtime/event/server.d.ts +114 -0
- package/dist/runtime/event/server.d.ts.map +1 -0
- package/dist/runtime/event/server.js +651 -0
- package/dist/runtime/event/server.js.map +1 -0
- package/dist/runtime/event-dispatcher.d.ts +2 -0
- package/dist/runtime/event-dispatcher.d.ts.map +1 -0
- package/dist/runtime/event-dispatcher.js +2 -0
- package/dist/runtime/event-dispatcher.js.map +1 -0
- package/dist/runtime/event-server-snapshot-reader.d.ts +2 -0
- package/dist/runtime/event-server-snapshot-reader.d.ts.map +1 -0
- package/dist/runtime/event-server-snapshot-reader.js +2 -0
- package/dist/runtime/event-server-snapshot-reader.js.map +1 -0
- package/dist/runtime/event-server-sse.d.ts +2 -0
- package/dist/runtime/event-server-sse.d.ts.map +1 -0
- package/dist/runtime/event-server-sse.js +2 -0
- package/dist/runtime/event-server-sse.js.map +1 -0
- package/dist/runtime/event-server.d.ts +1 -91
- package/dist/runtime/event-server.d.ts.map +1 -1
- package/dist/runtime/event-server.js +1 -698
- package/dist/runtime/event-server.js.map +1 -1
- package/dist/runtime/executor/loop-supervisor.d.ts +9 -5
- package/dist/runtime/executor/loop-supervisor.d.ts.map +1 -1
- package/dist/runtime/executor/loop-supervisor.js +59 -76
- package/dist/runtime/executor/loop-supervisor.js.map +1 -1
- package/dist/runtime/gateway/http-channel-adapter.d.ts +1 -1
- package/dist/runtime/plugin-loader.d.ts +1 -1
- package/dist/runtime/queue/index.d.ts +0 -4
- package/dist/runtime/queue/index.d.ts.map +1 -1
- package/dist/runtime/queue/index.js +0 -2
- package/dist/runtime/queue/index.js.map +1 -1
- package/dist/runtime/queue/journal-backed-queue.d.ts.map +1 -1
- package/dist/runtime/queue/journal-backed-queue.js +2 -0
- package/dist/runtime/queue/journal-backed-queue.js.map +1 -1
- package/dist/runtime/schedule/engine-layers.d.ts +44 -0
- package/dist/runtime/schedule/engine-layers.d.ts.map +1 -0
- package/dist/runtime/schedule/engine-layers.js +433 -0
- package/dist/runtime/schedule/engine-layers.js.map +1 -0
- package/dist/runtime/schedule/engine.d.ts +82 -0
- package/dist/runtime/schedule/engine.d.ts.map +1 -0
- package/dist/runtime/schedule/engine.js +480 -0
- package/dist/runtime/schedule/engine.js.map +1 -0
- package/dist/runtime/schedule/index.d.ts +5 -0
- package/dist/runtime/schedule/index.d.ts.map +1 -0
- package/dist/runtime/schedule/index.js +5 -0
- package/dist/runtime/schedule/index.js.map +1 -0
- package/dist/runtime/schedule/presets.d.ts +536 -0
- package/dist/runtime/schedule/presets.d.ts.map +1 -0
- package/dist/runtime/schedule/presets.js +166 -0
- package/dist/runtime/schedule/presets.js.map +1 -0
- package/dist/runtime/schedule/source.d.ts +65 -0
- package/dist/runtime/schedule/source.d.ts.map +1 -0
- package/dist/runtime/schedule/source.js +16 -0
- package/dist/runtime/schedule/source.js.map +1 -0
- package/dist/runtime/schedule-engine-layers.d.ts +1 -43
- package/dist/runtime/schedule-engine-layers.d.ts.map +1 -1
- package/dist/runtime/schedule-engine-layers.js +1 -432
- package/dist/runtime/schedule-engine-layers.js.map +1 -1
- package/dist/runtime/schedule-engine.d.ts +1 -81
- package/dist/runtime/schedule-engine.d.ts.map +1 -1
- package/dist/runtime/schedule-engine.js +1 -479
- package/dist/runtime/schedule-engine.js.map +1 -1
- package/dist/runtime/schedule-presets.d.ts +1 -535
- package/dist/runtime/schedule-presets.d.ts.map +1 -1
- package/dist/runtime/schedule-presets.js +1 -165
- package/dist/runtime/schedule-presets.js.map +1 -1
- package/dist/runtime/schedule-source.d.ts +1 -64
- package/dist/runtime/schedule-source.d.ts.map +1 -1
- package/dist/runtime/schedule-source.js +1 -15
- package/dist/runtime/schedule-source.js.map +1 -1
- package/dist/runtime/types/daemon.d.ts.map +1 -1
- package/dist/runtime/types/daemon.js +2 -1
- package/dist/runtime/types/daemon.js.map +1 -1
- package/dist/runtime/watchdog.d.ts +44 -0
- package/dist/runtime/watchdog.d.ts.map +1 -0
- package/dist/runtime/watchdog.js +185 -0
- package/dist/runtime/watchdog.js.map +1 -0
- package/dist/tools/builtin/index.d.ts +1 -1
- package/dist/tools/schedule/CreateScheduleTool/CreateScheduleTool.d.ts +1 -1
- package/dist/tools/schedule/CreateScheduleTool/CreateScheduleTool.js +1 -1
- package/dist/tools/schedule/GetScheduleTool/GetScheduleTool.d.ts +1 -1
- package/dist/tools/schedule/ListSchedulesTool/ListSchedulesTool.d.ts +1 -1
- package/dist/tools/schedule/PauseScheduleTool/PauseScheduleTool.d.ts +1 -1
- package/dist/tools/schedule/RemoveScheduleTool/RemoveScheduleTool.d.ts +1 -1
- package/dist/tools/schedule/ResumeScheduleTool/ResumeScheduleTool.d.ts +1 -1
- package/dist/tools/schedule/UpdateScheduleTool/UpdateScheduleTool.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Completion checks, stall handling, and task execution for a CoreLoop iteration.
|
|
3
|
+
*/
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
import { KnowledgeGraph } from "../../../platform/knowledge/knowledge-graph.js";
|
|
7
|
+
import { loadDreamActivationState, mergeUniqueKnowledgeEntries } from "../../../platform/dream/dream-activation.js";
|
|
8
|
+
import { buildDriveContext, } from "./contracts.js";
|
|
9
|
+
import { getMilestones, evaluatePace, } from "../../goal/milestone-evaluator.js";
|
|
10
|
+
import { gatherStallEvidence } from "../stall-evidence.js";
|
|
11
|
+
import { verifyWithTools } from "../verification-layer1.js";
|
|
12
|
+
import { buildLoopToolContext } from "./preparation.js";
|
|
13
|
+
import { expandKnowledgeEntriesWithGraph, mergeWorkingMemorySelections, } from "../../execution/context/context-builder.js";
|
|
14
|
+
// ─── Phase 5 ───
|
|
15
|
+
/** Completion check + milestone deadline check.
|
|
16
|
+
* Sets result.error on fatal failure, sets result.completionJudgment. */
|
|
17
|
+
export async function checkCompletionAndMilestones(ctx, goalId, goal, result, startTime) {
|
|
18
|
+
// R1-1: record pre-task judgment (do NOT early-return here)
|
|
19
|
+
try {
|
|
20
|
+
const judgment = goal.children_ids.length > 0
|
|
21
|
+
? await ctx.deps.satisficingJudge.judgeTreeCompletion(goalId)
|
|
22
|
+
: ctx.deps.satisficingJudge.isGoalComplete(goal);
|
|
23
|
+
result.completionJudgment = judgment;
|
|
24
|
+
// Wire satisficing callback to MemoryLifecycleManager
|
|
25
|
+
// SatisficingJudge fires (goalId, satisfiedDimensions[]) but MLM expects per-dimension calls
|
|
26
|
+
if (ctx.deps.memoryLifecycleManager) {
|
|
27
|
+
const blockingSet = new Set(judgment.blocking_dimensions);
|
|
28
|
+
for (const dim of goal.dimensions) {
|
|
29
|
+
const isSatisfied = !blockingSet.has(dim.name);
|
|
30
|
+
ctx.deps.memoryLifecycleManager.onSatisficingJudgment(goalId, dim.name, isSatisfied);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
result.error = `Completion check failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
36
|
+
ctx.logger?.error(`CoreLoop: ${result.error}`, { goalId });
|
|
37
|
+
result.elapsedMs = Date.now() - startTime;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Milestone deadline check
|
|
41
|
+
try {
|
|
42
|
+
const allGoals = [goal];
|
|
43
|
+
for (const childId of goal.children_ids) {
|
|
44
|
+
const child = await ctx.deps.stateManager.loadGoal(childId);
|
|
45
|
+
if (child)
|
|
46
|
+
allGoals.push(child);
|
|
47
|
+
}
|
|
48
|
+
const milestones = getMilestones(allGoals);
|
|
49
|
+
if (milestones.length > 0) {
|
|
50
|
+
const milestoneAlerts = [];
|
|
51
|
+
for (const milestone of milestones) {
|
|
52
|
+
const currentAchievement = milestone.pace_snapshot?.achievement_ratio ??
|
|
53
|
+
(typeof milestone.dimensions[0]?.current_value === "number"
|
|
54
|
+
? Math.min(milestone.dimensions[0].current_value / 100, 1)
|
|
55
|
+
: 0);
|
|
56
|
+
const snapshot = evaluatePace(milestone, currentAchievement);
|
|
57
|
+
await ctx.deps.stateManager.savePaceSnapshot(milestone.id, snapshot);
|
|
58
|
+
if (snapshot.status === "at_risk" || snapshot.status === "behind") {
|
|
59
|
+
milestoneAlerts.push({
|
|
60
|
+
goalId: milestone.id,
|
|
61
|
+
status: snapshot.status,
|
|
62
|
+
pace_ratio: snapshot.pace_ratio,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
if (ctx.deps.learningPipeline) {
|
|
67
|
+
try {
|
|
68
|
+
await ctx.deps.learningPipeline.onMilestoneReached(goalId, `Milestone ${milestone.title}: pace ${snapshot.status}`);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// non-fatal
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (milestoneAlerts.length > 0) {
|
|
77
|
+
result.milestoneAlerts = milestoneAlerts;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Milestone check failure is non-fatal
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// ─── Phase 6 ───
|
|
86
|
+
/** Stall detection per-dimension and globally, plus portfolio rebalance. */
|
|
87
|
+
export async function detectStallsAndRebalance(ctx, goalId, goal, result) {
|
|
88
|
+
try {
|
|
89
|
+
const gapHistory = await ctx.deps.stateManager.loadGapHistory(goalId);
|
|
90
|
+
const gapHistoryByDimension = indexGapHistoryByDimension(goal, gapHistory);
|
|
91
|
+
// Gather tool-based workspace evidence for stall detection (Phase 6)
|
|
92
|
+
if (ctx.toolExecutor) {
|
|
93
|
+
try {
|
|
94
|
+
const toolContext = {
|
|
95
|
+
cwd: process.cwd(),
|
|
96
|
+
goalId,
|
|
97
|
+
trustBalance: 0,
|
|
98
|
+
preApproved: true,
|
|
99
|
+
approvalFn: async () => false,
|
|
100
|
+
};
|
|
101
|
+
const evidence = await gatherStallEvidence(ctx.toolExecutor, toolContext);
|
|
102
|
+
result.toolStallEvidence = evidence;
|
|
103
|
+
if (!evidence.hasWorkspaceChanges) {
|
|
104
|
+
ctx.logger?.info("CoreLoop: stall evidence — no workspace changes detected", { goalId, toolErrors: evidence.toolErrors });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Non-fatal: evidence gathering failure does not block stall detection
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Gap 3: isSuppressed wiring — suppression is per-dimension only.
|
|
112
|
+
// Collect suppressed dimensions from all active WaitStrategies; skip those dims in stall loop.
|
|
113
|
+
const suppressedDimensions = new Set();
|
|
114
|
+
if (ctx.deps.portfolioManager) {
|
|
115
|
+
try {
|
|
116
|
+
const portfolio = await ctx.deps.strategyManager.getPortfolio(goalId);
|
|
117
|
+
if (portfolio) {
|
|
118
|
+
for (const s of portfolio.strategies) {
|
|
119
|
+
if (s.state !== "active" || !ctx.deps.portfolioManager.isWaitStrategy(s))
|
|
120
|
+
continue;
|
|
121
|
+
const ws = s;
|
|
122
|
+
const waitUntil = typeof ws["wait_until"] === "string" ? ws["wait_until"] : null;
|
|
123
|
+
if (!ctx.deps.stallDetector.isSuppressed(waitUntil))
|
|
124
|
+
continue;
|
|
125
|
+
// Suppress only the primary_dimension of this WaitStrategy
|
|
126
|
+
const primaryDim = typeof ws["primary_dimension"] === "string" ? ws["primary_dimension"] : null;
|
|
127
|
+
if (primaryDim) {
|
|
128
|
+
suppressedDimensions.add(primaryDim);
|
|
129
|
+
ctx.logger?.info("CoreLoop: stall detection suppressed for dimension by active WaitStrategy", {
|
|
130
|
+
goalId,
|
|
131
|
+
dimension: primaryDim,
|
|
132
|
+
waitUntil,
|
|
133
|
+
});
|
|
134
|
+
result.waitSuppressed = true;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Non-fatal: suppression check failure does not block stall detection
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Per-dimension stall check (skip dimensions suppressed by active WaitStrategies)
|
|
144
|
+
for (const dim of goal.dimensions) {
|
|
145
|
+
if (suppressedDimensions.has(dim.name))
|
|
146
|
+
continue;
|
|
147
|
+
const dimGapHistory = gapHistoryByDimension.get(dim.name) ?? [];
|
|
148
|
+
const stallReport = ctx.deps.stallDetector.checkDimensionStall(goalId, dim.name, dimGapHistory);
|
|
149
|
+
if (stallReport) {
|
|
150
|
+
result.stallDetected = true;
|
|
151
|
+
result.stallReport = stallReport;
|
|
152
|
+
// Predicted stalls are advisory — log but don't pivot/escalate
|
|
153
|
+
if (stallReport.stall_type === "predicted_plateau" ||
|
|
154
|
+
stallReport.stall_type === "predicted_regression") {
|
|
155
|
+
ctx.logger?.info(`CoreLoop: early warning ${stallReport.stall_type} — monitoring, no pivot`, { goalId });
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const escalationLevel = await ctx.deps.stallDetector.getEscalationLevel(goalId, dim.name);
|
|
159
|
+
await applyStallAction(ctx, goalId, goal, dimGapHistory, stallReport, escalationLevel, dim.name, result, "");
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Global stall check
|
|
164
|
+
if (!result.stallDetected) {
|
|
165
|
+
await checkGlobalStall(ctx, goalId, goal, result, gapHistoryByDimension);
|
|
166
|
+
}
|
|
167
|
+
// Portfolio: check rebalance after stall detection
|
|
168
|
+
if (ctx.deps.portfolioManager) {
|
|
169
|
+
await rebalancePortfolio(ctx, goalId, goal, result);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
ctx.logger?.warn("CoreLoop: stall detection failed (non-fatal)", { error: err instanceof Error ? err.message : String(err) });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function indexGapHistoryByDimension(goal, gapHistory) {
|
|
177
|
+
const indexedHistory = new Map();
|
|
178
|
+
for (const dim of goal.dimensions) {
|
|
179
|
+
indexedHistory.set(dim.name, []);
|
|
180
|
+
}
|
|
181
|
+
for (const entry of gapHistory) {
|
|
182
|
+
const seenDimensions = new Set();
|
|
183
|
+
for (const gap of entry.gap_vector) {
|
|
184
|
+
if (seenDimensions.has(gap.dimension_name))
|
|
185
|
+
continue;
|
|
186
|
+
seenDimensions.add(gap.dimension_name);
|
|
187
|
+
const dimHistory = indexedHistory.get(gap.dimension_name);
|
|
188
|
+
if (!dimHistory) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
const normalizedGap = { normalized_gap: gap.normalized_weighted_gap ?? 1 };
|
|
192
|
+
dimHistory.push(normalizedGap);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return indexedHistory;
|
|
196
|
+
}
|
|
197
|
+
// ─── Shared stall-action helper ───
|
|
198
|
+
/** Apply REFINE/PIVOT/ESCALATE logic for a detected stall (per-dimension or global).
|
|
199
|
+
* @param dimHistory Gap history slice used for analysis (single-dim or first-dim for global).
|
|
200
|
+
* @param stallReport The detected StallReport.
|
|
201
|
+
* @param escalationLevel Current escalation level for the stall dimension.
|
|
202
|
+
* @param incrementDimName Dimension name passed to incrementEscalation after handling.
|
|
203
|
+
* @param logPrefix Short prefix for log messages, e.g. "" or "global ".
|
|
204
|
+
*/
|
|
205
|
+
async function applyStallAction(ctx, goalId, goal, dimHistory, stallReport, escalationLevel, incrementDimName, result, logPrefix) {
|
|
206
|
+
if (ctx.deps.learningPipeline) {
|
|
207
|
+
try {
|
|
208
|
+
await ctx.deps.learningPipeline.onStallDetected(goalId, stallReport);
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// non-fatal
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const activeStrategyForRecord = await Promise.resolve(ctx.deps.strategyManager.getActiveStrategy(goalId)).catch(() => null);
|
|
215
|
+
const strategyIdForRecord = activeStrategyForRecord?.id ?? "unknown";
|
|
216
|
+
// M14-S2: analyze stall cause to determine REFINE/PIVOT/ESCALATE
|
|
217
|
+
// Falls back to PIVOT behavior when analyzeStallCause is unavailable
|
|
218
|
+
const analysis = ctx.deps.stallDetector.analyzeStallCause?.(dimHistory);
|
|
219
|
+
result.stallAnalysis = analysis;
|
|
220
|
+
if (analysis?.recommended_action === "refine") {
|
|
221
|
+
// REFINE: keep current strategy, just log and continue
|
|
222
|
+
ctx.logger?.info(`CoreLoop: ${logPrefix}stall REFINE — parameter_issue detected, keeping strategy`, {
|
|
223
|
+
goalId,
|
|
224
|
+
evidence: analysis.evidence,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
else if (stallReport.suggested_cause === "information_deficit" && ctx.deps.goalRefiner) {
|
|
228
|
+
// Observation-failure stall: re-refine the leaf to get better dimensions
|
|
229
|
+
ctx.logger?.info(`CoreLoop: ${logPrefix}observation-failure stall — calling reRefineLeaf`, { goalId });
|
|
230
|
+
try {
|
|
231
|
+
await ctx.deps.goalRefiner.reRefineLeaf(goalId, stallReport.suggested_cause);
|
|
232
|
+
}
|
|
233
|
+
catch (reRefineErr) {
|
|
234
|
+
ctx.logger?.warn(`CoreLoop: ${logPrefix}reRefineLeaf failed (non-fatal)`, {
|
|
235
|
+
goalId,
|
|
236
|
+
err: reRefineErr instanceof Error ? reRefineErr.message : String(reRefineErr),
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else if (analysis?.recommended_action === "escalate") {
|
|
241
|
+
// ESCALATE: set escalation level to max to trigger loop exit
|
|
242
|
+
ctx.logger?.warn(`CoreLoop: ${logPrefix}stall ESCALATE — goal_unreachable detected`, {
|
|
243
|
+
goalId,
|
|
244
|
+
evidence: analysis.evidence,
|
|
245
|
+
});
|
|
246
|
+
await ctx.deps.strategyManager.onStallDetected(goalId, 3, goal.origin ?? "general");
|
|
247
|
+
result.pivotOccurred = true;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
// PIVOT: switch strategy, but check pivot count limit first
|
|
251
|
+
const portfolio = await ctx.deps.strategyManager.getPortfolio(goalId);
|
|
252
|
+
const activeStrategy = portfolio?.strategies.find((s) => s.state === "active");
|
|
253
|
+
const pivotCount = activeStrategy?.pivot_count ?? 0;
|
|
254
|
+
const maxPivotCount = activeStrategy?.max_pivot_count ?? 2;
|
|
255
|
+
if (pivotCount >= maxPivotCount) {
|
|
256
|
+
// Auto-escalate when pivot limit reached
|
|
257
|
+
ctx.logger?.warn(`CoreLoop: ${logPrefix}stall auto-ESCALATE — pivot_count limit reached`, {
|
|
258
|
+
goalId,
|
|
259
|
+
pivotCount,
|
|
260
|
+
maxPivotCount,
|
|
261
|
+
});
|
|
262
|
+
await ctx.deps.strategyManager.onStallDetected(goalId, 3, goal.origin ?? "general");
|
|
263
|
+
result.pivotOccurred = true;
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
const newStrategy = await ctx.deps.strategyManager.onStallDetected(goalId, escalationLevel + 1, goal.origin ?? "general");
|
|
267
|
+
if (newStrategy) {
|
|
268
|
+
result.pivotOccurred = true;
|
|
269
|
+
if (activeStrategy?.id) {
|
|
270
|
+
try {
|
|
271
|
+
await ctx.deps.strategyManager.incrementPivotCount(goalId, activeStrategy.id);
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
// non-fatal
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// M14-S3: Record decision (non-fatal)
|
|
281
|
+
if (ctx.deps.knowledgeManager) {
|
|
282
|
+
try {
|
|
283
|
+
const latestGap = dimHistory[dimHistory.length - 1]?.normalized_gap ?? 1;
|
|
284
|
+
await ctx.deps.knowledgeManager.recordDecision({
|
|
285
|
+
id: randomUUID(),
|
|
286
|
+
goal_id: goalId,
|
|
287
|
+
goal_type: goal.origin ?? "general",
|
|
288
|
+
strategy_id: strategyIdForRecord,
|
|
289
|
+
hypothesis: activeStrategyForRecord?.hypothesis,
|
|
290
|
+
decision: analysis?.recommended_action ?? "pivot",
|
|
291
|
+
context: {
|
|
292
|
+
gap_value: latestGap,
|
|
293
|
+
stall_count: stallReport.escalation_level,
|
|
294
|
+
cycle_count: dimHistory.length,
|
|
295
|
+
trust_score: 0,
|
|
296
|
+
},
|
|
297
|
+
outcome: "pending",
|
|
298
|
+
timestamp: new Date().toISOString(),
|
|
299
|
+
what_worked: [],
|
|
300
|
+
what_failed: [],
|
|
301
|
+
suggested_next: [],
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
// non-fatal: never block the loop for decision recording
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (incrementDimName) {
|
|
309
|
+
await ctx.deps.stallDetector.incrementEscalation(goalId, incrementDimName);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/** Global stall detection: check all dimensions together, handle REFINE/PIVOT/ESCALATE. */
|
|
313
|
+
async function checkGlobalStall(ctx, goalId, goal, result, gapHistoryByDimension) {
|
|
314
|
+
const globalStall = ctx.deps.stallDetector.checkGlobalStall(goalId, gapHistoryByDimension);
|
|
315
|
+
if (!globalStall)
|
|
316
|
+
return;
|
|
317
|
+
result.stallDetected = true;
|
|
318
|
+
result.stallReport = globalStall;
|
|
319
|
+
const firstDimHistory = gapHistoryByDimension.get(goal.dimensions[0]?.name ?? "") ?? [];
|
|
320
|
+
const firstDimName = goal.dimensions[0]?.name ?? "";
|
|
321
|
+
// Pass escalationLevel=1 so that escalationLevel+1=2, preserving the original global PIVOT level
|
|
322
|
+
await applyStallAction(ctx, goalId, goal, firstDimHistory, globalStall, 1, firstDimName, result, "global ");
|
|
323
|
+
}
|
|
324
|
+
/** Portfolio rebalance: check for rebalance triggers and handle wait strategy expiry. */
|
|
325
|
+
async function rebalancePortfolio(ctx, goalId, goal, result) {
|
|
326
|
+
if (!ctx.deps.portfolioManager)
|
|
327
|
+
return;
|
|
328
|
+
try {
|
|
329
|
+
const rebalanceTrigger = await ctx.deps.portfolioManager.shouldRebalance(goalId);
|
|
330
|
+
if (rebalanceTrigger) {
|
|
331
|
+
const rebalanceResult = await ctx.deps.portfolioManager.rebalance(goalId, rebalanceTrigger);
|
|
332
|
+
if (rebalanceResult.new_generation_needed) {
|
|
333
|
+
await ctx.deps.strategyManager.onStallDetected(goalId, 3, goal.origin ?? "general");
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
// Portfolio rebalance errors are non-fatal
|
|
339
|
+
}
|
|
340
|
+
try {
|
|
341
|
+
const portfolio = await ctx.deps.strategyManager.getPortfolio(goalId);
|
|
342
|
+
if (portfolio) {
|
|
343
|
+
for (const strategy of portfolio.strategies) {
|
|
344
|
+
if (ctx.deps.portfolioManager.isWaitStrategy(strategy)) {
|
|
345
|
+
// Gap 1: canAffordWait gate — if TimeHorizonEngine is available, check whether
|
|
346
|
+
// the goal can afford the wait before processing WaitStrategy expiry.
|
|
347
|
+
if (ctx.timeHorizonEngine) {
|
|
348
|
+
try {
|
|
349
|
+
const ws = strategy;
|
|
350
|
+
const waitUntil = typeof ws["wait_until"] === "string" ? ws["wait_until"] : null;
|
|
351
|
+
const startedAt = typeof ws["started_at"] === "string" ? ws["started_at"] : (goal.created_at ?? new Date().toISOString());
|
|
352
|
+
// Remaining wait time (not total): use now as reference so nearly-expired waits pass
|
|
353
|
+
const waitHours = waitUntil
|
|
354
|
+
? Math.max(0, (new Date(waitUntil).getTime() - Date.now()) / 3_600_000)
|
|
355
|
+
: 0;
|
|
356
|
+
const currentGap = result?.gapAggregate ?? 1;
|
|
357
|
+
const initialGap = typeof ws["gap_snapshot_at_start"] === "number" ? ws["gap_snapshot_at_start"] : currentGap;
|
|
358
|
+
// Compute an approximate velocity from gap progress and elapsed time.
|
|
359
|
+
// Fallback to a small positive value (0.01/h) when elapsed is too short to measure.
|
|
360
|
+
const elapsedHours = waitUntil
|
|
361
|
+
? Math.max(0, (Date.now() - new Date(startedAt).getTime()) / 3_600_000)
|
|
362
|
+
: 0;
|
|
363
|
+
const gapDelta = initialGap - currentGap;
|
|
364
|
+
const velocity = elapsedHours > 0.001 && gapDelta > 0
|
|
365
|
+
? gapDelta / elapsedHours
|
|
366
|
+
: 0.01; // conservative positive fallback; replace with real velocity when available
|
|
367
|
+
const budget = ctx.timeHorizonEngine.getTimeBudget(goal.deadline ?? null, startedAt, currentGap, initialGap, velocity);
|
|
368
|
+
if (!budget.canAffordWait(waitHours)) {
|
|
369
|
+
ctx.logger?.info("CoreLoop: canAffordWait=false, skipping WaitStrategy processing", {
|
|
370
|
+
goalId,
|
|
371
|
+
strategyId: strategy.id,
|
|
372
|
+
waitHours,
|
|
373
|
+
});
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
// Non-fatal: if canAffordWait check fails, proceed normally
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const waitTrigger = await ctx.deps.portfolioManager.handleWaitStrategyExpiry(goalId, strategy.id);
|
|
382
|
+
if (waitTrigger) {
|
|
383
|
+
await ctx.deps.portfolioManager.rebalance(goalId, waitTrigger);
|
|
384
|
+
if (result) {
|
|
385
|
+
result.waitExpired = true;
|
|
386
|
+
result.waitStrategyId = strategy.id;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
catch {
|
|
394
|
+
// WaitStrategy expiry errors are non-fatal
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
// ─── Phase 6b ───
|
|
398
|
+
/** Check dependency graph block.
|
|
399
|
+
* Returns true if goal is blocked (result.error set, caller should return). */
|
|
400
|
+
export function checkDependencyBlock(ctx, goalId, result) {
|
|
401
|
+
if (ctx.deps.goalDependencyGraph) {
|
|
402
|
+
try {
|
|
403
|
+
if (ctx.deps.goalDependencyGraph.isBlocked(goalId)) {
|
|
404
|
+
const blockingGoals = ctx.deps.goalDependencyGraph.getBlockingGoals(goalId);
|
|
405
|
+
result.error = `Goal ${goalId} is blocked by prerequisites: ${blockingGoals.join(", ")}`;
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
catch {
|
|
410
|
+
// Dependency graph errors are non-fatal
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
/** Collect context, run task cycle, handle capability acquisition,
|
|
416
|
+
* transfer detection, and post-task completion re-check.
|
|
417
|
+
* Returns true on success, false if the caller should return result early.
|
|
418
|
+
* `transferCheckCounter` is incremented via the callback to keep mutable state on CoreLoop. */
|
|
419
|
+
export async function runTaskCycleWithContext(ctx, goalId, goal, gapVector, driveScores, highDissatisfactionDimensions, loopIndex, result, startTime, callbacks) {
|
|
420
|
+
const { handleCapabilityAcquisition, incrementTransferCounter, tryGenerateReport } = callbacks;
|
|
421
|
+
try {
|
|
422
|
+
const taskStartTime = Date.now();
|
|
423
|
+
const driveContext = buildDriveContext(goal);
|
|
424
|
+
const adapter = ctx.deps.adapterRegistry.getAdapter(ctx.config.adapterType);
|
|
425
|
+
const baseDir = typeof ctx.deps.stateManager.getBaseDir === "function"
|
|
426
|
+
? ctx.deps.stateManager.getBaseDir()
|
|
427
|
+
: null;
|
|
428
|
+
const dreamActivation = baseDir
|
|
429
|
+
? await loadDreamActivationState(baseDir).catch(() => null)
|
|
430
|
+
: null;
|
|
431
|
+
const activationFlags = dreamActivation?.flags;
|
|
432
|
+
// Portfolio: select strategy for next task
|
|
433
|
+
if (ctx.deps.portfolioManager) {
|
|
434
|
+
try {
|
|
435
|
+
const selectionResult = await ctx.deps.portfolioManager.selectNextStrategyForTask(goalId);
|
|
436
|
+
if (selectionResult) {
|
|
437
|
+
ctx.deps.taskLifecycle.setOnTaskComplete((strategyId) => {
|
|
438
|
+
ctx.deps.portfolioManager?.recordTaskCompletion(strategyId);
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
catch {
|
|
443
|
+
// Portfolio strategy selection is non-fatal
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
// Collect knowledge context
|
|
447
|
+
let knowledgeContext;
|
|
448
|
+
if (ctx.deps.knowledgeManager) {
|
|
449
|
+
try {
|
|
450
|
+
const topDimension = driveScores[0]?.dimension_name ?? goal.dimensions[0]?.name;
|
|
451
|
+
if (topDimension) {
|
|
452
|
+
let entries = await ctx.deps.knowledgeManager.getRelevantKnowledge(goalId, topDimension);
|
|
453
|
+
if (activationFlags?.semanticContext) {
|
|
454
|
+
const semanticEntries = await ctx.deps.knowledgeManager.searchKnowledge(`${goal.title} ${goal.description} ${topDimension}`, 5).catch(() => []);
|
|
455
|
+
entries = mergeUniqueKnowledgeEntries(entries, semanticEntries, 8);
|
|
456
|
+
}
|
|
457
|
+
let contradictionWarnings = [];
|
|
458
|
+
if (activationFlags?.graphTraversal && entries.length > 0) {
|
|
459
|
+
const graph = baseDir
|
|
460
|
+
? await KnowledgeGraph.create(path.join(baseDir, "knowledge", "graph.json")).catch(() => null)
|
|
461
|
+
: null;
|
|
462
|
+
if (graph) {
|
|
463
|
+
const allEntries = await ctx.deps.knowledgeManager.loadKnowledge(goalId).catch(() => []);
|
|
464
|
+
const expanded = expandKnowledgeEntriesWithGraph(entries, allEntries, graph);
|
|
465
|
+
entries = mergeUniqueKnowledgeEntries(entries, expanded.relatedEntries, 10);
|
|
466
|
+
contradictionWarnings = expanded.contradictionWarnings;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
if (entries.length > 0) {
|
|
470
|
+
knowledgeContext = entries
|
|
471
|
+
.map((e) => `Q: ${e.question}\nA: ${e.answer}`)
|
|
472
|
+
.join("\n\n");
|
|
473
|
+
if (contradictionWarnings.length > 0) {
|
|
474
|
+
knowledgeContext += `\n\nContradiction warnings:\n${contradictionWarnings
|
|
475
|
+
.map((warning) => `- ${warning}`)
|
|
476
|
+
.join("\n")}`;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
catch {
|
|
482
|
+
// Knowledge retrieval failure is non-fatal
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
if (activationFlags?.crossGoalLessons && ctx.deps.memoryLifecycleManager) {
|
|
486
|
+
try {
|
|
487
|
+
const topDimension = driveScores[0]?.dimension_name ?? goal.dimensions[0]?.name ?? "";
|
|
488
|
+
const lessons = await ctx.deps.memoryLifecycleManager.searchCrossGoalLessons(`${goal.title} ${goal.description} ${topDimension}`, 3);
|
|
489
|
+
if (lessons.length > 0) {
|
|
490
|
+
const lessonsBlock = [
|
|
491
|
+
"Cross-goal lessons:",
|
|
492
|
+
...lessons.map((lesson, index) => `${index + 1}. ${lesson.lesson}`),
|
|
493
|
+
].join("\n");
|
|
494
|
+
knowledgeContext = knowledgeContext ? `${knowledgeContext}\n\n${lessonsBlock}` : lessonsBlock;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
catch {
|
|
498
|
+
// Non-fatal: proceed without cross-goal lessons.
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
// Tier-aware memory selection: use highDissatisfactionDimensions and dynamic budget
|
|
502
|
+
if (ctx.deps.memoryLifecycleManager) {
|
|
503
|
+
try {
|
|
504
|
+
const dimensions = goal.dimensions.map((d) => d.name);
|
|
505
|
+
const maxDissatisfaction = driveScores.length > 0
|
|
506
|
+
? Math.max(...driveScores.map((s) => s.dissatisfaction))
|
|
507
|
+
: 0;
|
|
508
|
+
const satisfiedDimensions = goal.dimensions
|
|
509
|
+
.filter((d) => !result.completionJudgment?.blocking_dimensions.includes(d.name))
|
|
510
|
+
.map((d) => d.name);
|
|
511
|
+
const tierAwareMemory = await ctx.deps.memoryLifecycleManager.selectForWorkingMemoryTierAware(goalId, dimensions, [], 10, [goalId], [], satisfiedDimensions, highDissatisfactionDimensions, maxDissatisfaction);
|
|
512
|
+
if (activationFlags?.semanticWorkingMemory) {
|
|
513
|
+
const topDimension = driveScores[0]?.dimension_name ?? goal.dimensions[0]?.name ?? "";
|
|
514
|
+
const semanticMemory = await ctx.deps.memoryLifecycleManager.selectForWorkingMemorySemantic(goalId, `${goal.title} ${goal.description} ${topDimension}`, dimensions, [], 5, driveScores.map((score) => ({
|
|
515
|
+
dimension: score.dimension_name,
|
|
516
|
+
dissatisfaction: score.dissatisfaction,
|
|
517
|
+
deadline: score.deadline,
|
|
518
|
+
})));
|
|
519
|
+
const mergedEntries = mergeWorkingMemorySelections(tierAwareMemory.shortTerm, semanticMemory.shortTerm, 5);
|
|
520
|
+
if (mergedEntries.length > 0) {
|
|
521
|
+
const memoryBlock = [
|
|
522
|
+
"Working memory:",
|
|
523
|
+
...mergedEntries.map((entry, index) => `${index + 1}. [${entry.data_type}] ${JSON.stringify(entry.data)}`),
|
|
524
|
+
].join("\n");
|
|
525
|
+
knowledgeContext = knowledgeContext ? `${knowledgeContext}\n\n${memoryBlock}` : memoryBlock;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
catch {
|
|
530
|
+
// Memory selection failure is non-fatal
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
// Fetch existing tasks for dedup context
|
|
534
|
+
let existingTasks;
|
|
535
|
+
if (adapter.listExistingTasks) {
|
|
536
|
+
try {
|
|
537
|
+
existingTasks = await adapter.listExistingTasks();
|
|
538
|
+
}
|
|
539
|
+
catch {
|
|
540
|
+
// Non-fatal: proceed without existing tasks context
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
// Collect workspace context
|
|
544
|
+
let workspaceContext;
|
|
545
|
+
if (ctx.deps.contextProvider) {
|
|
546
|
+
try {
|
|
547
|
+
const topDimension = driveScores[0]?.dimension_name ?? goal.dimensions[0]?.name ?? "";
|
|
548
|
+
workspaceContext = await ctx.deps.contextProvider(goalId, topDimension);
|
|
549
|
+
}
|
|
550
|
+
catch {
|
|
551
|
+
// Non-fatal: proceed without workspace context
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
ctx.logger?.debug("CoreLoop: running task cycle", { adapter: adapter.adapterType, goalId });
|
|
555
|
+
ctx.deps.onProgress?.({
|
|
556
|
+
iteration: loopIndex + 1,
|
|
557
|
+
maxIterations: ctx.config.maxIterations,
|
|
558
|
+
phase: "Executing task...",
|
|
559
|
+
gap: result.gapAggregate,
|
|
560
|
+
});
|
|
561
|
+
const taskResult = await ctx.deps.taskLifecycle.runTaskCycle(goalId, gapVector, driveContext, adapter, knowledgeContext, existingTasks, workspaceContext);
|
|
562
|
+
ctx.logger?.info("CoreLoop: task cycle result", { action: taskResult.action, taskId: taskResult.task.id });
|
|
563
|
+
result.taskResult = taskResult;
|
|
564
|
+
result.tokensUsed = (result.tokensUsed ?? 0) + (taskResult.tokensUsed ?? 0);
|
|
565
|
+
ctx.deps.onProgress?.({
|
|
566
|
+
iteration: loopIndex + 1,
|
|
567
|
+
maxIterations: ctx.config.maxIterations,
|
|
568
|
+
phase: "Verifying result...",
|
|
569
|
+
gap: result.gapAggregate,
|
|
570
|
+
taskDescription: taskResult.task.work_description
|
|
571
|
+
? taskResult.task.work_description.split("\n")[0]?.slice(0, 80)
|
|
572
|
+
: undefined,
|
|
573
|
+
});
|
|
574
|
+
// Handle capability_acquiring
|
|
575
|
+
if (taskResult.action === "capability_acquiring" && taskResult.acquisition_task) {
|
|
576
|
+
const acquisitionOutcome = await handleCapabilityAcquisition(taskResult.acquisition_task, goalId, adapter);
|
|
577
|
+
if (acquisitionOutcome?.replanRequired) {
|
|
578
|
+
ctx.logger?.info("CoreLoop: capability acquisition requested replanning", {
|
|
579
|
+
capabilityName: acquisitionOutcome.capabilityName,
|
|
580
|
+
replanRequired: acquisitionOutcome.replanRequired,
|
|
581
|
+
recommendationSource: acquisitionOutcome.recommendationSource,
|
|
582
|
+
recommendedPlugin: acquisitionOutcome.recommendedPlugin,
|
|
583
|
+
});
|
|
584
|
+
ctx.deps.onProgress?.({
|
|
585
|
+
iteration: loopIndex + 1,
|
|
586
|
+
maxIterations: ctx.config.maxIterations,
|
|
587
|
+
phase: "Generating task...",
|
|
588
|
+
gap: result.gapAggregate,
|
|
589
|
+
taskDescription: `Replanning after capability acquisition: ${acquisitionOutcome.capabilityName}`,
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
// Portfolio: record task completion
|
|
594
|
+
if (ctx.deps.portfolioManager && taskResult.action === "completed" && taskResult.task.strategy_id) {
|
|
595
|
+
try {
|
|
596
|
+
ctx.deps.portfolioManager.recordTaskCompletion(taskResult.task.strategy_id);
|
|
597
|
+
}
|
|
598
|
+
catch {
|
|
599
|
+
// Non-fatal
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
// Phase 7: tool-based verification (Layer 1)
|
|
603
|
+
if (ctx.toolExecutor && taskResult.task.success_criteria.length > 0) {
|
|
604
|
+
try {
|
|
605
|
+
const toolCtx = await buildLoopToolContext(ctx, goalId);
|
|
606
|
+
const verificationResult = await verifyWithTools(taskResult.task.success_criteria, ctx.toolExecutor, toolCtx);
|
|
607
|
+
if (!verificationResult.mechanicalPassed) {
|
|
608
|
+
taskResult.verificationResult = { ...taskResult.verificationResult, verdict: "fail" };
|
|
609
|
+
ctx.logger?.info("CoreLoop Phase 7: tool verification failed", {
|
|
610
|
+
taskId: taskResult.task.id,
|
|
611
|
+
details: verificationResult.details,
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
result.toolVerification = verificationResult;
|
|
615
|
+
// Feed execution results back to strategy for scoring
|
|
616
|
+
if (typeof ctx.deps.strategyManager.recordExecutionFeedback === 'function') {
|
|
617
|
+
const activeStrat = await ctx.deps.strategyManager.getActiveStrategy(goalId);
|
|
618
|
+
if (activeStrat) {
|
|
619
|
+
ctx.deps.strategyManager.recordExecutionFeedback({
|
|
620
|
+
strategyId: activeStrat.hypothesis,
|
|
621
|
+
taskId: taskResult.task?.id ?? 'unknown',
|
|
622
|
+
success: taskResult.action === 'completed',
|
|
623
|
+
verificationPassed: verificationResult.mechanicalPassed,
|
|
624
|
+
duration_ms: Date.now() - taskStartTime,
|
|
625
|
+
timestamp: Date.now(),
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
catch (err) {
|
|
631
|
+
ctx.logger?.warn("CoreLoop Phase 7: tool verification threw (non-fatal)", {
|
|
632
|
+
error: err instanceof Error ? err.message : String(err),
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
// Re-check completion after task execution
|
|
637
|
+
const updatedGoal = await ctx.deps.stateManager.loadGoal(goalId);
|
|
638
|
+
if (updatedGoal) {
|
|
639
|
+
const postTaskJudgment = updatedGoal.children_ids.length > 0
|
|
640
|
+
? await ctx.deps.satisficingJudge.judgeTreeCompletion(updatedGoal.id)
|
|
641
|
+
: ctx.deps.satisficingJudge.isGoalComplete(updatedGoal);
|
|
642
|
+
result.completionJudgment = postTaskJudgment;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
catch (err) {
|
|
646
|
+
result.error = `Task cycle failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
647
|
+
ctx.logger?.error(`CoreLoop: ${result.error}`, { goalId });
|
|
648
|
+
result.elapsedMs = Date.now() - startTime;
|
|
649
|
+
tryGenerateReport(goalId, loopIndex, result, goal);
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
652
|
+
// Track curiosity goal loop count
|
|
653
|
+
if (ctx.deps.curiosityEngine) {
|
|
654
|
+
const currentGoal = await ctx.deps.stateManager.loadGoal(goalId);
|
|
655
|
+
if (currentGoal?.origin === "curiosity") {
|
|
656
|
+
ctx.deps.curiosityEngine.incrementLoopCount(goalId);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
// Transfer Detection (every 5 iterations, suggestion-only)
|
|
660
|
+
const transferCount = incrementTransferCounter();
|
|
661
|
+
if (ctx.deps.knowledgeTransfer && transferCount % 5 === 0) {
|
|
662
|
+
try {
|
|
663
|
+
const candidates = await ctx.deps.knowledgeTransfer.detectTransferOpportunities(goalId);
|
|
664
|
+
if (candidates.length > 0) {
|
|
665
|
+
result.transfer_candidates = candidates;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
catch {
|
|
669
|
+
// non-fatal
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return true;
|
|
673
|
+
}
|
|
674
|
+
//# sourceMappingURL=task-cycle.js.map
|