@gajae-code/coding-agent 0.14.2 → 0.15.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/CHANGELOG.md +120 -1
- package/dist/types/async/job-manager.d.ts +4 -1
- package/dist/types/autoresearch/dashboard.d.ts +29 -4
- package/dist/types/autoresearch/data-context.d.ts +25 -0
- package/dist/types/autoresearch/git.d.ts +65 -7
- package/dist/types/autoresearch/harness.d.ts +58 -0
- package/dist/types/autoresearch/prompts.d.ts +51 -0
- package/dist/types/autoresearch/runs.d.ts +173 -0
- package/dist/types/autoresearch/types.d.ts +9 -139
- package/dist/types/capability/types.d.ts +20 -0
- package/dist/types/cli/accounts-cli.d.ts +1 -0
- package/dist/types/commands/{rlm.d.ts → autoresearch.d.ts} +2 -4
- package/dist/types/config/autorouting-contract.d.ts +146 -0
- package/dist/types/config/autorouting-generator.d.ts +40 -0
- package/dist/types/config/autorouting-tier-map.d.ts +16844 -0
- package/dist/types/config/autorouting.d.ts +35 -0
- package/dist/types/config/model-discovery-manager.d.ts +8 -1
- package/dist/types/config/model-registry.d.ts +30 -1
- package/dist/types/config/provider-selection-policy.d.ts +23 -0
- package/dist/types/config/settings-schema.d.ts +61 -3
- package/dist/types/config/settings.d.ts +3 -0
- package/dist/types/coordinator/contract.d.ts +1 -1
- package/dist/types/coordinator-mcp/durability.d.ts +29 -0
- package/dist/types/coordinator-mcp/event-webhook.d.ts +50 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +1 -1
- package/dist/types/coordinator-mcp/server.d.ts +14 -0
- package/dist/types/crash/index-store.d.ts +3 -0
- package/dist/types/crash/record-loader.d.ts +2 -0
- package/dist/types/crash/upstream/relay.d.ts +5 -3
- package/dist/types/cursor.d.ts +12 -0
- package/dist/types/defaults/gjc-defaults.d.ts +35 -1
- package/dist/types/defaults/gjc-skills.generated.d.ts +1 -1
- package/dist/types/discovery/helpers.d.ts +1 -1
- package/dist/types/edit/index.d.ts +2 -1
- package/dist/types/eval/py/executor.d.ts +2 -0
- package/dist/types/extensibility/extensions/loader.d.ts +32 -0
- package/dist/types/extensibility/gjc-plugins/types.d.ts +1 -1
- package/dist/types/extensibility/skills.d.ts +2 -0
- package/dist/types/gjc-runtime/autoresearch-runtime.d.ts +194 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
- package/dist/types/gjc-runtime/psmux-detect.d.ts +1 -1
- package/dist/types/gjc-runtime/python-transcript.d.ts +19 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +2 -8
- package/dist/types/gjc-runtime/session-layout.d.ts +6 -3
- package/dist/types/gjc-runtime/state-renderer.d.ts +0 -22
- package/dist/types/gjc-runtime/state-schema.d.ts +7 -7
- package/dist/types/gjc-runtime/tmux-common.d.ts +2 -2
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +38 -1
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +2 -24
- package/dist/types/gjc-runtime/ultragoal-validation-policy.d.ts +73 -0
- package/dist/types/gjc-runtime/workflow-recovery-projection.d.ts +100 -0
- package/dist/types/hooks/skill-keywords.d.ts +1 -1
- package/dist/types/main.d.ts +0 -10
- package/dist/types/modes/acp/acp-agent.d.ts +13 -6
- package/dist/types/modes/components/model-selector.d.ts +14 -0
- package/dist/types/modes/components/skill-hud/render.d.ts +6 -1
- package/dist/types/modes/components/smart-routing-panel.d.ts +82 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +14 -0
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/types.d.ts +9 -0
- package/dist/types/rlm/artifacts.d.ts +4 -4
- package/dist/types/runtime/optional-runtime-services.d.ts +2 -1
- package/dist/types/runtime/workspace-tree-service.d.ts +5 -1
- package/dist/types/runtime-mcp/config.d.ts +6 -0
- package/dist/types/runtime-mcp/manager.d.ts +10 -0
- package/dist/types/sdk/acp/adapter.d.ts +0 -4
- package/dist/types/sdk/broker/broker.d.ts +1 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +57 -2
- package/dist/types/sdk/broker/session-index.d.ts +15 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +6 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -0
- package/dist/types/sdk/bus/index.d.ts +8 -0
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +2 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -2
- package/dist/types/sdk/client/client.d.ts +39 -4
- package/dist/types/sdk/host/host.d.ts +1 -0
- package/dist/types/sdk/host/internal-autorouting-state.d.ts +3 -0
- package/dist/types/sdk/host/model-pin.d.ts +29 -0
- package/dist/types/sdk/host/session-runtime.d.ts +2 -1
- package/dist/types/sdk/lifecycle-session.d.ts +13 -0
- package/dist/types/sdk/router/session-router.d.ts +27 -1
- package/dist/types/sdk/session.d.ts +11 -1
- package/dist/types/session/agent-session.d.ts +36 -6
- package/dist/types/session/artifacts.d.ts +16 -1
- package/dist/types/session/internal/managed-session-storage.d.ts +7 -0
- package/dist/types/session/session-manager.d.ts +84 -2
- package/dist/types/session/session-staging-paths.d.ts +3 -0
- package/dist/types/skill-state/canonical-skills.d.ts +1 -1
- package/dist/types/skill-state/workflow-hud.d.ts +12 -21
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +1 -0
- package/dist/types/slash-commands/helpers/autorouting-status.d.ts +8 -0
- package/dist/types/system-prompt.d.ts +23 -0
- package/dist/types/task/executor.d.ts +35 -4
- package/dist/types/task/index.d.ts +17 -3
- package/dist/types/task/receipt.d.ts +3 -1
- package/dist/types/task/types.d.ts +144 -0
- package/dist/types/tools/atomic-file-write.d.ts +72 -0
- package/dist/types/tools/descriptors.d.ts +1 -0
- package/dist/types/tools/index.d.ts +36 -1
- package/dist/types/tools/move-session.d.ts +40 -0
- package/dist/types/tools/python.d.ts +12 -0
- package/dist/types/tools/resource-gc.d.ts +0 -3
- package/dist/types/tools/search.d.ts +8 -1
- package/dist/types/tools/skill.d.ts +9 -4
- package/dist/types/tools/subagent.d.ts +33 -3
- package/dist/types/utils/xml-escape.d.ts +2 -0
- package/dist/types/workflow/workflow-intent-diff.d.ts +2 -2
- package/dist/types/workflow/workflow-intent-report-consumer.d.ts +1 -1
- package/package.json +11 -12
- package/scripts/build-sdk-package-smoke.ts +7 -5
- package/scripts/check-autorouting-tier-map.ts +183 -0
- package/scripts/generate-sdk-operation-inventory.ts +12 -0
- package/scripts/generate-tool-catalog.ts +40 -5
- package/src/async/job-manager.ts +5 -2
- package/src/autoresearch/dashboard.ts +134 -314
- package/src/autoresearch/data-context.ts +35 -0
- package/src/autoresearch/git.ts +186 -26
- package/src/autoresearch/{helpers.ts → harness.ts} +65 -40
- package/src/autoresearch/{prompt-setup.md → prompts/prompt-setup.md} +7 -7
- package/src/autoresearch/prompts/prompt.md +103 -0
- package/src/autoresearch/prompts.ts +126 -0
- package/src/autoresearch/runs.ts +708 -0
- package/src/autoresearch/types.ts +9 -150
- package/src/capability/index.ts +4 -4
- package/src/capability/types.ts +20 -0
- package/src/cli/accounts-cli.ts +21 -5
- package/src/cli/config-cli.ts +25 -1
- package/src/cli/fast-help.ts +1 -2
- package/src/cli/list-models.ts +5 -8
- package/src/cli/setup-cli.ts +8 -0
- package/src/cli.ts +2 -21
- package/src/commands/autoresearch.ts +33 -0
- package/src/commands/coordinator.ts +15 -0
- package/src/commands/launch.ts +2 -4
- package/src/commands/quick-lane.ts +1 -1
- package/src/commands/sdk.ts +24 -0
- package/src/commands/state.ts +1 -1
- package/src/config/autorouting-contract.ts +474 -0
- package/src/config/autorouting-generator.ts +238 -0
- package/src/config/autorouting-tier-map.ts +6108 -0
- package/src/config/autorouting.ts +120 -0
- package/src/config/model-discovery-manager.ts +42 -11
- package/src/config/model-registry.ts +348 -68
- package/src/config/provider-selection-policy.ts +60 -9
- package/src/config/settings-schema.ts +195 -6
- package/src/config/settings.ts +62 -1
- package/src/config.ts +2 -3
- package/src/coordinator/contract.ts +0 -1
- package/src/coordinator-mcp/codex-handoff.ts +68 -42
- package/src/coordinator-mcp/durability.ts +200 -0
- package/src/coordinator-mcp/event-webhook.ts +278 -0
- package/src/coordinator-mcp/question-state.ts +109 -46
- package/src/coordinator-mcp/server.ts +932 -504
- package/src/crash/index-store.ts +126 -22
- package/src/crash/record-loader.ts +7 -0
- package/src/crash/upstream/relay.ts +82 -34
- package/src/cursor.ts +84 -1
- package/src/debug/index.ts +26 -0
- package/src/defaults/gjc/skills/autoresearch/SKILL.md +116 -0
- package/src/defaults/gjc/skills/autoresearch/auto-critic.md +46 -0
- package/src/defaults/gjc/skills/autoresearch/auto-iterate.md +42 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +17 -37
- package/src/defaults/gjc/skills/ralplan/SKILL.md +21 -18
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +6 -17
- package/src/defaults/gjc/skills/ultragoal/ai-slop-cleaner.md +2 -2
- package/src/defaults/gjc-defaults.ts +89 -2
- package/src/defaults/gjc-skills.generated.ts +24 -17
- package/src/discovery/builtin.ts +18 -5
- package/src/discovery/helpers.ts +6 -6
- package/src/edit/index.ts +5 -2
- package/src/eval/py/executor.ts +8 -0
- package/src/extensibility/extensions/loader.ts +135 -13
- package/src/extensibility/extensions/wrapper.ts +1 -2
- package/src/extensibility/gjc-plugins/schema.ts +1 -1
- package/src/extensibility/runtime-skill-discovery.ts +2 -2
- package/src/extensibility/skill-management.ts +2 -3
- package/src/extensibility/skills.ts +16 -8
- package/src/gjc-runtime/autoresearch-runtime.ts +1509 -0
- package/src/gjc-runtime/gc-render.ts +0 -1
- package/src/gjc-runtime/gc-runtime.ts +1 -11
- package/src/gjc-runtime/launch-tmux.ts +3 -3
- package/src/gjc-runtime/psmux-detect.ts +2 -2
- package/src/gjc-runtime/python-transcript.ts +58 -0
- package/src/gjc-runtime/ralplan-runtime.ts +6 -18
- package/src/gjc-runtime/session-layout.ts +18 -7
- package/src/gjc-runtime/session-state-sidecar.ts +58 -9
- package/src/gjc-runtime/state-renderer.ts +0 -38
- package/src/gjc-runtime/state-runtime.ts +43 -22
- package/src/gjc-runtime/state-schema.ts +1 -1
- package/src/gjc-runtime/tmux-common.ts +7 -7
- package/src/gjc-runtime/ultragoal-change-set.ts +232 -11
- package/src/gjc-runtime/ultragoal-runtime.ts +309 -114
- package/src/gjc-runtime/ultragoal-validation-policy.ts +247 -0
- package/src/gjc-runtime/workflow-command-ref.ts +15 -11
- package/src/gjc-runtime/workflow-manifest.generated.json +413 -532
- package/src/gjc-runtime/workflow-manifest.ts +43 -83
- package/src/gjc-runtime/workflow-recovery-projection.ts +616 -0
- package/src/hooks/skill-keywords.ts +3 -3
- package/src/hooks/skill-state.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +26 -24
- package/src/lsp/index.ts +25 -5
- package/src/main.ts +2 -27
- package/src/modes/acp/acp-agent.ts +200 -75
- package/src/modes/components/model-selector.ts +216 -13
- package/src/modes/components/oauth-selector.ts +5 -5
- package/src/modes/components/skill-hud/render.ts +173 -35
- package/src/modes/components/smart-routing-panel.ts +531 -0
- package/src/modes/components/tool-status-header.ts +6 -3
- package/src/modes/controllers/command-controller.ts +17 -7
- package/src/modes/controllers/input-controller.ts +44 -9
- package/src/modes/controllers/runtime-mcp-command-controller.ts +4 -0
- package/src/modes/controllers/selector-controller.ts +298 -65
- package/src/modes/interactive-mode.ts +8 -1
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +1 -1
- package/src/modes/types.ts +9 -1
- package/src/prompts/agents/planner.md +1 -1
- package/src/prompts/system/system-prompt.md +1 -1
- package/src/prompts/system/volatile-project-context.md +2 -1
- package/src/prompts/tools/move-session.md +15 -0
- package/src/prompts/tools/python.md +12 -0
- package/src/prompts/tools/skill-discovery.md +1 -1
- package/src/prompts/tools/skill.md +2 -2
- package/src/prompts/tools/task-summary.md +1 -0
- package/src/prompts/tools/task.md +6 -0
- package/src/rlm/artifacts.ts +12 -10
- package/src/runtime/optional-runtime-services.ts +3 -2
- package/src/runtime/workspace-tree-service.ts +11 -3
- package/src/runtime-mcp/config.ts +8 -1
- package/src/runtime-mcp/manager.ts +33 -0
- package/src/sdk/acp/adapter.ts +48 -1
- package/src/sdk/broker/broker.ts +30 -2
- package/src/sdk/broker/discovery.ts +217 -2
- package/src/sdk/broker/lifecycle.ts +385 -59
- package/src/sdk/broker/session-index.ts +243 -48
- package/src/sdk/broker/transport.ts +1 -0
- package/src/sdk/bus/chat-daemon-control.ts +8 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +5 -0
- package/src/sdk/bus/index.ts +208 -11
- package/src/sdk/bus/kind-aware-reconciliation.ts +16 -0
- package/src/sdk/bus/reconciliation-store.ts +27 -5
- package/src/sdk/bus/telegram-daemon-contract.ts +12 -2
- package/src/sdk/client/client.ts +204 -22
- package/src/sdk/host/host.ts +16 -0
- package/src/sdk/host/internal-autorouting-state.ts +13 -0
- package/src/sdk/host/model-pin.ts +101 -0
- package/src/sdk/host/reverse-leases.ts +2 -1
- package/src/sdk/host/session-runtime.test.ts +224 -1
- package/src/sdk/host/session-runtime.ts +125 -37
- package/src/sdk/lifecycle/service.ts +3 -1
- package/src/sdk/lifecycle-session.ts +42 -1
- package/src/sdk/protocol/operation-inventory.generated.json +66 -0
- package/src/sdk/router/session-router.ts +375 -36
- package/src/sdk/session.ts +547 -47
- package/src/session/account-inventory.ts +1 -1
- package/src/session/agent-session.ts +765 -189
- package/src/session/artifacts.ts +234 -4
- package/src/session/internal/managed-session-storage.ts +91 -4
- package/src/session/provider-safety-stop-hint.ts +3 -2
- package/src/session/session-manager.ts +775 -16
- package/src/session/session-staging-paths.ts +8 -0
- package/src/setup/hermes/templates/operator-instructions.v1.md +0 -1
- package/src/setup/host-plugin-setup.ts +2 -2
- package/src/skill-state/active-state.ts +2 -2
- package/src/skill-state/canonical-skills.ts +1 -1
- package/src/skill-state/initial-phase.ts +1 -1
- package/src/skill-state/workflow-hud.ts +41 -41
- package/src/skill-state/workflow-mutation-guard.ts +26 -7
- package/src/slash-commands/builtin-registry.ts +77 -0
- package/src/slash-commands/helpers/autorouting-status.ts +55 -0
- package/src/system-prompt.ts +102 -5
- package/src/task/discovery.ts +2 -3
- package/src/task/executor.ts +617 -43
- package/src/task/index.ts +262 -15
- package/src/task/receipt.ts +30 -0
- package/src/task/render.ts +11 -1
- package/src/task/types.ts +316 -0
- package/src/tools/atomic-file-write.ts +594 -0
- package/src/tools/bisect.ts +3 -2
- package/src/tools/descriptors.test.ts +3 -0
- package/src/tools/descriptors.ts +24 -0
- package/src/tools/image-gen.ts +5 -1
- package/src/tools/index.ts +62 -5
- package/src/tools/move-session.ts +107 -0
- package/src/tools/python.ts +205 -0
- package/src/tools/read.ts +88 -15
- package/src/tools/renderers.ts +2 -0
- package/src/tools/resource-gc.ts +8 -177
- package/src/tools/search.ts +30 -6
- package/src/tools/skill-discovery.ts +1 -0
- package/src/tools/skill.ts +37 -7
- package/src/tools/subagent-render.ts +119 -13
- package/src/tools/subagent.ts +91 -74
- package/src/tools/tool-catalog.generated.ts +64 -2
- package/src/tools/write.ts +16 -12
- package/src/utils/xml-escape.ts +14 -0
- package/src/web/search/providers/codex.ts +2 -2
- package/src/workflow/workflow-intent-diff.ts +13 -12
- package/src/workflow/workflow-intent-report-consumer.ts +6 -6
- package/dist/types/autoresearch/helpers.d.ts +0 -24
- package/dist/types/autoresearch/index.d.ts +0 -2
- package/dist/types/autoresearch/state.d.ts +0 -17
- package/dist/types/autoresearch/storage.d.ts +0 -142
- package/dist/types/autoresearch/tools/init-experiment.d.ts +0 -31
- package/dist/types/autoresearch/tools/log-experiment.d.ts +0 -23
- package/dist/types/autoresearch/tools/run-experiment.d.ts +0 -8
- package/dist/types/autoresearch/tools/update-notes.d.ts +0 -12
- package/dist/types/commands/team.d.ts +0 -24
- package/dist/types/gjc-runtime/team-gc.d.ts +0 -7
- package/dist/types/gjc-runtime/team-launch.d.ts +0 -61
- package/dist/types/gjc-runtime/team-notify.d.ts +0 -45
- package/dist/types/gjc-runtime/team-runtime.d.ts +0 -336
- package/dist/types/gjc-runtime/team-store.d.ts +0 -168
- package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +0 -43
- package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +0 -92
- package/dist/types/gjc-runtime/team-workers.d.ts +0 -83
- package/dist/types/rlm/index.d.ts +0 -47
- package/dist/types/rlm/preset.d.ts +0 -23
- package/dist/types/rlm/python-tool.d.ts +0 -16
- package/src/autoresearch/command-resume.md +0 -14
- package/src/autoresearch/index.ts +0 -536
- package/src/autoresearch/prompt.md +0 -103
- package/src/autoresearch/resume-message.md +0 -10
- package/src/autoresearch/state.ts +0 -273
- package/src/autoresearch/storage.ts +0 -699
- package/src/autoresearch/tools/init-experiment.ts +0 -272
- package/src/autoresearch/tools/log-experiment.ts +0 -524
- package/src/autoresearch/tools/run-experiment.ts +0 -475
- package/src/autoresearch/tools/update-notes.ts +0 -109
- package/src/commands/rlm.ts +0 -19
- package/src/commands/team.ts +0 -238
- package/src/defaults/gjc/skills/deep-interview/auto-research-greenfield.md +0 -42
- package/src/defaults/gjc/skills/team/SKILL.md +0 -467
- package/src/gjc-runtime/team-gc.ts +0 -49
- package/src/gjc-runtime/team-launch.ts +0 -404
- package/src/gjc-runtime/team-notify.ts +0 -326
- package/src/gjc-runtime/team-runtime.ts +0 -5923
- package/src/gjc-runtime/team-store.ts +0 -878
- package/src/gjc-runtime/team-worker-heartbeat.ts +0 -149
- package/src/gjc-runtime/team-worker-memory-guard.ts +0 -363
- package/src/gjc-runtime/team-workers.ts +0 -1123
- package/src/prompts/system/rlm-report-command.md +0 -1
- package/src/prompts/system/rlm-research.md +0 -23
- package/src/rlm/index.ts +0 -365
- package/src/rlm/preset.ts +0 -76
- package/src/rlm/python-tool.ts +0 -68
|
@@ -1,536 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import type { AutocompleteItem } from "@gajae-code/tui";
|
|
4
|
-
import { logger, prompt } from "@gajae-code/utils";
|
|
5
|
-
import type { ExtensionContext, ExtensionFactory } from "../extensibility/extensions";
|
|
6
|
-
import * as git from "../utils/git";
|
|
7
|
-
import commandResumeTemplate from "./command-resume.md" with { type: "text" };
|
|
8
|
-
import { createDashboardController } from "./dashboard";
|
|
9
|
-
import { ensureAutoresearchBranch } from "./git";
|
|
10
|
-
import { formatNum } from "./helpers";
|
|
11
|
-
import promptTemplate from "./prompt.md" with { type: "text" };
|
|
12
|
-
import setupPromptTemplate from "./prompt-setup.md" with { type: "text" };
|
|
13
|
-
import resumeMessageTemplate from "./resume-message.md" with { type: "text" };
|
|
14
|
-
import {
|
|
15
|
-
buildExperimentState,
|
|
16
|
-
createExperimentState,
|
|
17
|
-
createRuntimeStore,
|
|
18
|
-
currentResults,
|
|
19
|
-
findBaselineMetric,
|
|
20
|
-
findBaselineRunNumber,
|
|
21
|
-
findBestKeptMetric,
|
|
22
|
-
reconstructControlState,
|
|
23
|
-
} from "./state";
|
|
24
|
-
import { openAutoresearchStorage, openAutoresearchStorageIfExists, type RunRow, type SessionRow } from "./storage";
|
|
25
|
-
import { createInitExperimentTool } from "./tools/init-experiment";
|
|
26
|
-
import { createLogExperimentTool } from "./tools/log-experiment";
|
|
27
|
-
import { createRunExperimentTool } from "./tools/run-experiment";
|
|
28
|
-
import { createUpdateNotesTool } from "./tools/update-notes";
|
|
29
|
-
import type { AutoresearchRuntime, ExperimentResult, PendingRunSummary } from "./types";
|
|
30
|
-
|
|
31
|
-
const EXPERIMENT_TOOL_NAMES = ["init_experiment", "run_experiment", "log_experiment", "update_notes"];
|
|
32
|
-
|
|
33
|
-
export const createAutoresearchExtension: ExtensionFactory = api => {
|
|
34
|
-
const runtimeStore = createRuntimeStore();
|
|
35
|
-
const dashboard = createDashboardController();
|
|
36
|
-
|
|
37
|
-
const getSessionKey = (ctx: ExtensionContext): string => ctx.sessionManager.getSessionId();
|
|
38
|
-
const getRuntime = (ctx: ExtensionContext): AutoresearchRuntime => runtimeStore.ensure(getSessionKey(ctx));
|
|
39
|
-
|
|
40
|
-
const loadActiveSession = async (
|
|
41
|
-
ctx: ExtensionContext,
|
|
42
|
-
): Promise<{ session: SessionRow | null; currentBranch: string | null }> => {
|
|
43
|
-
const currentBranch = await tryReadBranch(ctx.cwd);
|
|
44
|
-
const storage = await openAutoresearchStorageIfExists(ctx.cwd);
|
|
45
|
-
if (!storage) return { session: null, currentBranch };
|
|
46
|
-
const session = storage.getActiveSessionForBranch(currentBranch);
|
|
47
|
-
return { session, currentBranch };
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const rehydrate = async (ctx: ExtensionContext): Promise<void> => {
|
|
51
|
-
const runtime = getRuntime(ctx);
|
|
52
|
-
const control = reconstructControlState(ctx.sessionManager.getBranch());
|
|
53
|
-
runtime.goal = control.goal;
|
|
54
|
-
runtime.autoResumeArmed = false;
|
|
55
|
-
runtime.lastAutoResumePendingRunNumber = null;
|
|
56
|
-
|
|
57
|
-
// Skip storage entirely if autoresearch was never activated in this conversation.
|
|
58
|
-
// This is the common case: every project gets a session_start event but most
|
|
59
|
-
// never touch autoresearch, so we must not create a SQLite file just to look.
|
|
60
|
-
const everActivated = control.lastMode !== null;
|
|
61
|
-
const { session, currentBranch } = everActivated
|
|
62
|
-
? await loadActiveSession(ctx)
|
|
63
|
-
: { session: null, currentBranch: null };
|
|
64
|
-
|
|
65
|
-
// Mode is effective only when the recorded session matches the current git
|
|
66
|
-
// branch. When the user switches off the autoresearch branch the widget hides
|
|
67
|
-
// and the experiment tools detach, but the session entries are preserved so
|
|
68
|
-
// switching back resumes seamlessly.
|
|
69
|
-
const onActiveBranch = session === null || session.branch === null || session.branch === currentBranch;
|
|
70
|
-
runtime.autoresearchMode = control.autoresearchMode && onActiveBranch;
|
|
71
|
-
|
|
72
|
-
if (session && onActiveBranch) {
|
|
73
|
-
const storage = await openAutoresearchStorageIfExists(ctx.cwd);
|
|
74
|
-
if (storage) {
|
|
75
|
-
const loggedRuns = storage.listLoggedRuns(session.id);
|
|
76
|
-
runtime.state = buildExperimentState(session, loggedRuns);
|
|
77
|
-
runtime.goal = runtime.goal ?? session.goal;
|
|
78
|
-
runtime.lastRunSummary = pendingRunSummaryFromRow(storage.getPendingRun(session.id));
|
|
79
|
-
} else {
|
|
80
|
-
runtime.state = createExperimentState();
|
|
81
|
-
runtime.lastRunSummary = null;
|
|
82
|
-
}
|
|
83
|
-
} else {
|
|
84
|
-
runtime.state = createExperimentState();
|
|
85
|
-
runtime.lastRunSummary = null;
|
|
86
|
-
}
|
|
87
|
-
runtime.lastRunDuration = runtime.lastRunSummary?.durationSeconds ?? null;
|
|
88
|
-
runtime.lastRunAsi = runtime.lastRunSummary?.parsedAsi ?? null;
|
|
89
|
-
runtime.lastRunArtifactDir = runtime.lastRunSummary?.runDirectory ?? null;
|
|
90
|
-
runtime.lastRunNumber = runtime.lastRunSummary?.runNumber ?? null;
|
|
91
|
-
runtime.runningExperiment = null;
|
|
92
|
-
dashboard.updateWidget(ctx, runtime);
|
|
93
|
-
|
|
94
|
-
const activeTools = api.getActiveTools();
|
|
95
|
-
const experimentTools = new Set(EXPERIMENT_TOOL_NAMES);
|
|
96
|
-
const nextActiveTools = runtime.autoresearchMode
|
|
97
|
-
? [...new Set([...activeTools, ...EXPERIMENT_TOOL_NAMES])]
|
|
98
|
-
: activeTools.filter(name => !experimentTools.has(name));
|
|
99
|
-
const toolsChanged =
|
|
100
|
-
nextActiveTools.length !== activeTools.length ||
|
|
101
|
-
nextActiveTools.some((name, index) => name !== activeTools[index]);
|
|
102
|
-
if (toolsChanged) {
|
|
103
|
-
await api.setActiveTools(nextActiveTools);
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const setMode = (
|
|
108
|
-
ctx: ExtensionContext,
|
|
109
|
-
enabled: boolean,
|
|
110
|
-
goal: string | null,
|
|
111
|
-
mode: "on" | "off" | "clear",
|
|
112
|
-
): void => {
|
|
113
|
-
const runtime = getRuntime(ctx);
|
|
114
|
-
runtime.autoresearchMode = enabled;
|
|
115
|
-
runtime.autoResumeArmed = false;
|
|
116
|
-
runtime.goal = goal;
|
|
117
|
-
runtime.lastAutoResumePendingRunNumber = null;
|
|
118
|
-
api.appendEntry("autoresearch-control", goal ? { mode, goal } : { mode });
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
api.registerTool(createInitExperimentTool({ dashboard, getRuntime, pi: api }));
|
|
122
|
-
api.registerTool(createRunExperimentTool({ dashboard, getRuntime, pi: api }));
|
|
123
|
-
api.registerTool(createLogExperimentTool({ dashboard, getRuntime, pi: api }));
|
|
124
|
-
api.registerTool(createUpdateNotesTool({ dashboard, getRuntime, pi: api }));
|
|
125
|
-
|
|
126
|
-
api.registerCommand("autoresearch", {
|
|
127
|
-
description: "Toggle builtin autoresearch mode, or pass off / clear, or a goal message.",
|
|
128
|
-
getArgumentCompletions(argumentPrefix: string): AutocompleteItem[] | null {
|
|
129
|
-
if (argumentPrefix.includes(" ")) return null;
|
|
130
|
-
const normalized = argumentPrefix.trim().toLowerCase();
|
|
131
|
-
if (normalized.length === 0) return null;
|
|
132
|
-
const completions: AutocompleteItem[] = [
|
|
133
|
-
{ label: "off", value: "off", description: "Leave autoresearch mode" },
|
|
134
|
-
{
|
|
135
|
-
label: "clear",
|
|
136
|
-
value: "clear",
|
|
137
|
-
description: "Reset worktree to baseline and close the active session",
|
|
138
|
-
},
|
|
139
|
-
];
|
|
140
|
-
const filtered = completions.filter(item => item.label.startsWith(normalized));
|
|
141
|
-
return filtered.length > 0 ? filtered : null;
|
|
142
|
-
},
|
|
143
|
-
async handler(args, ctx): Promise<void> {
|
|
144
|
-
const trimmed = args.trim();
|
|
145
|
-
const runtime = getRuntime(ctx);
|
|
146
|
-
|
|
147
|
-
if (trimmed === "" && runtime.autoresearchMode) {
|
|
148
|
-
setMode(ctx, false, runtime.goal, "off");
|
|
149
|
-
dashboard.updateWidget(ctx, runtime);
|
|
150
|
-
const experimentTools = new Set(EXPERIMENT_TOOL_NAMES);
|
|
151
|
-
await api.setActiveTools(api.getActiveTools().filter(name => !experimentTools.has(name)));
|
|
152
|
-
ctx.ui.notify("Autoresearch mode disabled", "info");
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (trimmed === "off") {
|
|
157
|
-
setMode(ctx, false, runtime.goal, "off");
|
|
158
|
-
dashboard.updateWidget(ctx, runtime);
|
|
159
|
-
const experimentTools = new Set(EXPERIMENT_TOOL_NAMES);
|
|
160
|
-
await api.setActiveTools(api.getActiveTools().filter(name => !experimentTools.has(name)));
|
|
161
|
-
ctx.ui.notify("Autoresearch mode disabled", "info");
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (trimmed === "clear" || trimmed.startsWith("clear ")) {
|
|
166
|
-
const flagPart = trimmed === "clear" ? "" : trimmed.slice("clear ".length).trim();
|
|
167
|
-
const keepTree = flagPart.includes("--keep-tree");
|
|
168
|
-
const resetTreeForce = flagPart.includes("--reset-tree");
|
|
169
|
-
await handleClear(ctx, runtime, { keepTree, resetTreeForce });
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const goalArg = trimmed.length > 0 ? trimmed : null;
|
|
174
|
-
const branchResult = await ensureAutoresearchBranch(api, ctx.cwd, goalArg ?? runtime.goal);
|
|
175
|
-
if (!branchResult.ok) {
|
|
176
|
-
ctx.ui.notify(branchResult.error, "error");
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
if (branchResult.warning) {
|
|
180
|
-
ctx.ui.notify(branchResult.warning, "warning");
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Look up an existing session for the branch we just landed on. A session
|
|
184
|
-
// recorded under a different autoresearch/* branch is intentionally ignored
|
|
185
|
-
// — `/autoresearch` on a fresh branch starts a fresh session. Only open the
|
|
186
|
-
// DB if it already exists; the empty-state path must not create one.
|
|
187
|
-
const existingStorage = await openAutoresearchStorageIfExists(ctx.cwd);
|
|
188
|
-
const existingSession = existingStorage?.getActiveSessionForBranch(branchResult.branchName) ?? null;
|
|
189
|
-
const resumeContext = trimmed;
|
|
190
|
-
const branchStatusLine = branchResult.branchName
|
|
191
|
-
? branchResult.created
|
|
192
|
-
? `Created and checked out dedicated git branch \`${branchResult.branchName}\` before resuming.`
|
|
193
|
-
: `Using dedicated git branch \`${branchResult.branchName}\`.`
|
|
194
|
-
: "Continuing on the current branch — no autoresearch branch was created.";
|
|
195
|
-
|
|
196
|
-
if (existingSession && existingStorage) {
|
|
197
|
-
if (goalArg) existingStorage.updateSession(existingSession.id, { goal: goalArg });
|
|
198
|
-
if (branchResult.branchName) {
|
|
199
|
-
existingStorage.updateSession(existingSession.id, { branch: branchResult.branchName });
|
|
200
|
-
}
|
|
201
|
-
const refreshed = existingStorage.getSessionById(existingSession.id) ?? existingSession;
|
|
202
|
-
runtime.state = buildExperimentState(refreshed, existingStorage.listLoggedRuns(refreshed.id));
|
|
203
|
-
runtime.goal = refreshed.goal ?? goalArg;
|
|
204
|
-
setMode(ctx, true, runtime.goal, "on");
|
|
205
|
-
dashboard.updateWidget(ctx, runtime);
|
|
206
|
-
await api.setActiveTools([...new Set([...api.getActiveTools(), ...EXPERIMENT_TOOL_NAMES])]);
|
|
207
|
-
api.sendUserMessage(
|
|
208
|
-
prompt.render(commandResumeTemplate, {
|
|
209
|
-
branch_status_line: branchStatusLine,
|
|
210
|
-
has_resume_context: resumeContext.length > 0,
|
|
211
|
-
resume_context: resumeContext,
|
|
212
|
-
}),
|
|
213
|
-
);
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
setMode(ctx, true, goalArg, "on");
|
|
218
|
-
dashboard.updateWidget(ctx, runtime);
|
|
219
|
-
await api.setActiveTools([...new Set([...api.getActiveTools(), ...EXPERIMENT_TOOL_NAMES])]);
|
|
220
|
-
if (goalArg !== null) {
|
|
221
|
-
api.sendUserMessage(goalArg);
|
|
222
|
-
} else {
|
|
223
|
-
ctx.ui.notify("Autoresearch enabled—describe what to optimize in your next message.", "info");
|
|
224
|
-
}
|
|
225
|
-
},
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
api.registerShortcut("ctrl+x", {
|
|
229
|
-
description: "Toggle autoresearch dashboard",
|
|
230
|
-
handler(ctx): void {
|
|
231
|
-
const runtime = getRuntime(ctx);
|
|
232
|
-
if (runtime.state.results.length === 0 && !runtime.runningExperiment) {
|
|
233
|
-
ctx.ui.notify("No autoresearch results yet", "info");
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
runtime.dashboardExpanded = !runtime.dashboardExpanded;
|
|
237
|
-
dashboard.updateWidget(ctx, runtime);
|
|
238
|
-
},
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
api.registerShortcut("ctrl+shift+x", {
|
|
242
|
-
description: "Show autoresearch dashboard overlay",
|
|
243
|
-
handler(ctx): Promise<void> {
|
|
244
|
-
return dashboard.showOverlay(ctx, getRuntime(ctx));
|
|
245
|
-
},
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
api.on("session_start", (_event, ctx) => rehydrate(ctx));
|
|
249
|
-
api.on("session_switch", (_event, ctx) => rehydrate(ctx));
|
|
250
|
-
api.on("session_branch", (_event, ctx) => rehydrate(ctx));
|
|
251
|
-
api.on("session_tree", (_event, ctx) => rehydrate(ctx));
|
|
252
|
-
api.on("session_shutdown", (_event, ctx) => {
|
|
253
|
-
dashboard.clear(ctx);
|
|
254
|
-
runtimeStore.clear(getSessionKey(ctx));
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
api.on("agent_end", async (_event, ctx) => {
|
|
258
|
-
const runtime = getRuntime(ctx);
|
|
259
|
-
runtime.runningExperiment = null;
|
|
260
|
-
dashboard.updateWidget(ctx, runtime);
|
|
261
|
-
dashboard.requestRender();
|
|
262
|
-
if (!runtime.autoresearchMode) return;
|
|
263
|
-
if (ctx.hasPendingMessages()) {
|
|
264
|
-
runtime.autoResumeArmed = false;
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
const { session } = await loadActiveSession(ctx);
|
|
268
|
-
const storage = session ? await openAutoresearchStorageIfExists(ctx.cwd) : null;
|
|
269
|
-
const pendingRow = session && storage ? storage.getPendingRun(session.id) : null;
|
|
270
|
-
const pendingRun = pendingRunSummaryFromRow(pendingRow);
|
|
271
|
-
runtime.lastRunSummary = pendingRun;
|
|
272
|
-
runtime.lastRunDuration = pendingRun?.durationSeconds ?? runtime.lastRunDuration;
|
|
273
|
-
runtime.lastRunAsi = pendingRun?.parsedAsi ?? runtime.lastRunAsi;
|
|
274
|
-
const shouldResumePendingRun =
|
|
275
|
-
pendingRun !== null && runtime.lastAutoResumePendingRunNumber !== pendingRun.runNumber;
|
|
276
|
-
if (!shouldResumePendingRun && !runtime.autoResumeArmed) {
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
runtime.autoResumeArmed = false;
|
|
280
|
-
runtime.lastAutoResumePendingRunNumber = pendingRun?.runNumber ?? null;
|
|
281
|
-
api.sendMessage(
|
|
282
|
-
{
|
|
283
|
-
customType: "autoresearch-resume",
|
|
284
|
-
content: prompt.render(resumeMessageTemplate, {
|
|
285
|
-
has_pending_run: Boolean(pendingRun),
|
|
286
|
-
}),
|
|
287
|
-
display: false,
|
|
288
|
-
attribution: "agent",
|
|
289
|
-
},
|
|
290
|
-
{ deliverAs: "nextTurn", triggerTurn: true },
|
|
291
|
-
);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
api.on("before_agent_start", async (event, ctx) => {
|
|
295
|
-
const runtime = getRuntime(ctx);
|
|
296
|
-
if (!runtime.autoresearchMode) return;
|
|
297
|
-
// Re-check git branch on every agent start. If the user manually switched
|
|
298
|
-
// off the autoresearch/* branch between turns, we silently drop autoresearch
|
|
299
|
-
// from this turn — the widget hides, the experiment tools detach, and we do
|
|
300
|
-
// not inject the autoresearch system prompt.
|
|
301
|
-
const { session, currentBranch } = await loadActiveSession(ctx);
|
|
302
|
-
const onActiveBranch = session === null || session.branch === null || session.branch === currentBranch;
|
|
303
|
-
if (!onActiveBranch) {
|
|
304
|
-
runtime.autoresearchMode = false;
|
|
305
|
-
runtime.state = createExperimentState();
|
|
306
|
-
runtime.lastRunSummary = null;
|
|
307
|
-
runtime.runningExperiment = null;
|
|
308
|
-
dashboard.updateWidget(ctx, runtime);
|
|
309
|
-
const experimentTools = new Set(EXPERIMENT_TOOL_NAMES);
|
|
310
|
-
await api.setActiveTools(api.getActiveTools().filter(name => !experimentTools.has(name)));
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
const storage = await openAutoresearchStorageIfExists(ctx.cwd);
|
|
314
|
-
if (session && storage) {
|
|
315
|
-
runtime.state = buildExperimentState(session, storage.listLoggedRuns(session.id));
|
|
316
|
-
}
|
|
317
|
-
const pendingRow = session && storage ? storage.getPendingRun(session.id) : null;
|
|
318
|
-
const pendingRun = pendingRunSummaryFromRow(pendingRow);
|
|
319
|
-
runtime.lastRunSummary = pendingRun;
|
|
320
|
-
runtime.lastRunDuration = pendingRun?.durationSeconds ?? runtime.lastRunDuration;
|
|
321
|
-
runtime.lastRunAsi = pendingRun?.parsedAsi ?? runtime.lastRunAsi;
|
|
322
|
-
const state = runtime.state;
|
|
323
|
-
const currentSegmentResults = currentResults(state.results, state.currentSegment);
|
|
324
|
-
const baselineMetric = findBaselineMetric(state.results, state.currentSegment);
|
|
325
|
-
const baselineRunNumber = findBaselineRunNumber(state.results, state.currentSegment);
|
|
326
|
-
const bestMetric = findBestKeptMetric(state.results, state.currentSegment, state.bestDirection);
|
|
327
|
-
const bestResult = bestKeptResult(state.results, state.currentSegment, state.bestDirection);
|
|
328
|
-
const goal = runtime.goal ?? state.goal ?? state.name ?? "";
|
|
329
|
-
const recentResults = currentSegmentResults.slice(-3).map(result => {
|
|
330
|
-
const asiSummary = summarizeExperimentAsi(result);
|
|
331
|
-
return {
|
|
332
|
-
asi_summary: asiSummary,
|
|
333
|
-
description: result.description,
|
|
334
|
-
has_asi_summary: Boolean(asiSummary),
|
|
335
|
-
metric_display: formatNum(result.metric, state.metricUnit),
|
|
336
|
-
run_number: result.runNumber ?? state.results.indexOf(result) + 1,
|
|
337
|
-
status: result.status,
|
|
338
|
-
has_deviations: result.scopeDeviations.length > 0,
|
|
339
|
-
deviations: result.scopeDeviations.join(", "),
|
|
340
|
-
justified: Boolean(result.justification),
|
|
341
|
-
flagged: result.flagged,
|
|
342
|
-
flagged_reason: result.flaggedReason ?? "",
|
|
343
|
-
};
|
|
344
|
-
});
|
|
345
|
-
const unjustifiedRuns = currentSegmentResults
|
|
346
|
-
.filter(r => r.status === "keep" && !r.flagged && r.scopeDeviations.length > 0 && !r.justification)
|
|
347
|
-
.slice(-3)
|
|
348
|
-
.map(r => ({
|
|
349
|
-
run_number: r.runNumber,
|
|
350
|
-
paths: r.scopeDeviations.join(", "),
|
|
351
|
-
}));
|
|
352
|
-
if (!session) {
|
|
353
|
-
const currentBranch = await tryReadBranch(ctx.cwd);
|
|
354
|
-
const onAutoresearchBranch = currentBranch?.startsWith("autoresearch/") ?? false;
|
|
355
|
-
const baselineWarning = onAutoresearchBranch
|
|
356
|
-
? null
|
|
357
|
-
: "Heads up: you are not on a dedicated `autoresearch/*` branch. `log_experiment discard` will only revert run-modified files, not reset to baseline — so harness files written before `init_experiment` may not survive a discard. Clean the worktree and re-run `/autoresearch` if you want full revert safety.";
|
|
358
|
-
return {
|
|
359
|
-
systemPrompt: [
|
|
360
|
-
prompt.render(setupPromptTemplate, {
|
|
361
|
-
base_system_prompt: event.systemPrompt.join("\n\n"),
|
|
362
|
-
has_goal: goal.trim().length > 0,
|
|
363
|
-
goal,
|
|
364
|
-
working_dir: ctx.cwd,
|
|
365
|
-
has_branch: Boolean(currentBranch),
|
|
366
|
-
branch: currentBranch ?? "",
|
|
367
|
-
has_baseline_warning: baselineWarning !== null,
|
|
368
|
-
baseline_warning: baselineWarning ?? "",
|
|
369
|
-
}),
|
|
370
|
-
],
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
return {
|
|
374
|
-
systemPrompt: [
|
|
375
|
-
prompt.render(promptTemplate, {
|
|
376
|
-
base_system_prompt: event.systemPrompt.join("\n\n"),
|
|
377
|
-
has_goal: goal.trim().length > 0,
|
|
378
|
-
goal,
|
|
379
|
-
working_dir: ctx.cwd,
|
|
380
|
-
default_metric_name: state.metricName,
|
|
381
|
-
metric_name: state.metricName,
|
|
382
|
-
has_branch: Boolean(state.branch),
|
|
383
|
-
branch: state.branch,
|
|
384
|
-
has_baseline_commit: Boolean(state.baselineCommit),
|
|
385
|
-
baseline_commit: state.baselineCommit ? state.baselineCommit.slice(0, 12) : "",
|
|
386
|
-
has_notes: state.notes.trim().length > 0,
|
|
387
|
-
notes: state.notes,
|
|
388
|
-
current_segment: state.currentSegment + 1,
|
|
389
|
-
current_segment_run_count: currentSegmentResults.length,
|
|
390
|
-
has_baseline_metric: baselineMetric !== null,
|
|
391
|
-
baseline_metric_display: formatNum(baselineMetric, state.metricUnit),
|
|
392
|
-
baseline_run_number: baselineRunNumber,
|
|
393
|
-
has_best_result: bestResult !== null && bestMetric !== null,
|
|
394
|
-
best_metric_display: bestMetric !== null ? formatNum(bestMetric, state.metricUnit) : "-",
|
|
395
|
-
best_run_number: bestResult ? (bestResult.runNumber ?? state.results.indexOf(bestResult) + 1) : null,
|
|
396
|
-
has_recent_results: recentResults.length > 0,
|
|
397
|
-
recent_results: recentResults,
|
|
398
|
-
has_unjustified_runs: unjustifiedRuns.length > 0,
|
|
399
|
-
unjustified_runs: unjustifiedRuns,
|
|
400
|
-
has_pending_run: Boolean(pendingRun),
|
|
401
|
-
pending_run_number: pendingRun?.runNumber,
|
|
402
|
-
pending_run_command: pendingRun?.command,
|
|
403
|
-
pending_run_passed: pendingRun?.passed ?? false,
|
|
404
|
-
has_pending_run_metric: pendingRun?.parsedPrimary !== null && pendingRun?.parsedPrimary !== undefined,
|
|
405
|
-
pending_run_metric_display:
|
|
406
|
-
pendingRun?.parsedPrimary !== null && pendingRun?.parsedPrimary !== undefined
|
|
407
|
-
? formatNum(pendingRun.parsedPrimary, state.metricUnit)
|
|
408
|
-
: null,
|
|
409
|
-
}),
|
|
410
|
-
],
|
|
411
|
-
};
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
async function handleClear(
|
|
415
|
-
ctx: ExtensionContext,
|
|
416
|
-
runtime: AutoresearchRuntime,
|
|
417
|
-
opts: { keepTree: boolean; resetTreeForce: boolean },
|
|
418
|
-
): Promise<void> {
|
|
419
|
-
const storage = await openAutoresearchStorage(ctx.cwd);
|
|
420
|
-
const session = storage.getActiveSession();
|
|
421
|
-
const branchName = await tryReadBranch(ctx.cwd);
|
|
422
|
-
const onAutoresearchBranch = branchName?.startsWith("autoresearch/") ?? false;
|
|
423
|
-
const shouldResetTree = !opts.keepTree && (onAutoresearchBranch || opts.resetTreeForce);
|
|
424
|
-
if (shouldResetTree && session?.baselineCommit) {
|
|
425
|
-
try {
|
|
426
|
-
await git.reset(ctx.cwd, { hard: true, target: session.baselineCommit });
|
|
427
|
-
await git.clean(ctx.cwd);
|
|
428
|
-
ctx.ui.notify(`Reset worktree to baseline ${session.baselineCommit.slice(0, 12)}.`, "info");
|
|
429
|
-
} catch (err) {
|
|
430
|
-
ctx.ui.notify(
|
|
431
|
-
`Failed to reset worktree to baseline: ${err instanceof Error ? err.message : String(err)}`,
|
|
432
|
-
"error",
|
|
433
|
-
);
|
|
434
|
-
}
|
|
435
|
-
} else if (shouldResetTree) {
|
|
436
|
-
ctx.ui.notify("No baseline commit recorded — skipped worktree reset.", "warning");
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
removeLegacyArtifacts(ctx.cwd);
|
|
440
|
-
|
|
441
|
-
if (session) {
|
|
442
|
-
storage.closeSession(session.id);
|
|
443
|
-
}
|
|
444
|
-
runtime.state = createExperimentState();
|
|
445
|
-
runtime.goal = null;
|
|
446
|
-
runtime.lastRunDuration = null;
|
|
447
|
-
runtime.lastRunAsi = null;
|
|
448
|
-
runtime.lastRunArtifactDir = null;
|
|
449
|
-
runtime.lastRunNumber = null;
|
|
450
|
-
runtime.lastRunSummary = null;
|
|
451
|
-
setMode(ctx, false, null, "clear");
|
|
452
|
-
dashboard.updateWidget(ctx, runtime);
|
|
453
|
-
const experimentTools = new Set(EXPERIMENT_TOOL_NAMES);
|
|
454
|
-
await api.setActiveTools(api.getActiveTools().filter(name => !experimentTools.has(name)));
|
|
455
|
-
ctx.ui.notify("Autoresearch session cleared.", "info");
|
|
456
|
-
}
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
const LEGACY_ARTIFACTS = [
|
|
460
|
-
"autoresearch.md",
|
|
461
|
-
"autoresearch.sh",
|
|
462
|
-
"autoresearch.checks.sh",
|
|
463
|
-
"autoresearch.program.md",
|
|
464
|
-
"autoresearch.ideas.md",
|
|
465
|
-
"autoresearch.jsonl",
|
|
466
|
-
"autoresearch.config.json",
|
|
467
|
-
".autoresearch",
|
|
468
|
-
];
|
|
469
|
-
|
|
470
|
-
function removeLegacyArtifacts(workDir: string): void {
|
|
471
|
-
for (const name of LEGACY_ARTIFACTS) {
|
|
472
|
-
const target = path.join(workDir, name);
|
|
473
|
-
try {
|
|
474
|
-
fs.rmSync(target, { recursive: true, force: true });
|
|
475
|
-
} catch (err) {
|
|
476
|
-
logger.warn("Failed to remove legacy autoresearch artifact", {
|
|
477
|
-
path: target,
|
|
478
|
-
error: err instanceof Error ? err.message : String(err),
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
function pendingRunSummaryFromRow(row: RunRow | null): PendingRunSummary | null {
|
|
485
|
-
if (!row) return null;
|
|
486
|
-
if (row.status !== null) return null;
|
|
487
|
-
if (row.completedAt === null) return null;
|
|
488
|
-
const passed = row.exitCode === 0 && !row.timedOut;
|
|
489
|
-
return {
|
|
490
|
-
command: row.command,
|
|
491
|
-
durationSeconds: row.durationMs !== null ? row.durationMs / 1000 : null,
|
|
492
|
-
parsedAsi: row.parsedAsi,
|
|
493
|
-
parsedMetrics: row.parsedMetrics,
|
|
494
|
-
parsedPrimary: row.parsedPrimary,
|
|
495
|
-
passed,
|
|
496
|
-
preRunDirtyPaths: row.preRunDirtyPaths,
|
|
497
|
-
runDirectory: path.dirname(row.logPath),
|
|
498
|
-
runNumber: row.id,
|
|
499
|
-
exitCode: row.exitCode,
|
|
500
|
-
timedOut: row.timedOut,
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
function summarizeExperimentAsi(result: ExperimentResult): string | null {
|
|
505
|
-
const hypothesis = typeof result.asi?.hypothesis === "string" ? result.asi.hypothesis.trim() : "";
|
|
506
|
-
const rollback = typeof result.asi?.rollback_reason === "string" ? result.asi.rollback_reason.trim() : "";
|
|
507
|
-
const next = typeof result.asi?.next_action_hint === "string" ? result.asi.next_action_hint.trim() : "";
|
|
508
|
-
const summary = [hypothesis, rollback, next].filter(part => part.length > 0).join(" | ");
|
|
509
|
-
return summary.length > 0 ? summary.slice(0, 220) : null;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
function bestKeptResult(
|
|
513
|
-
results: ExperimentResult[],
|
|
514
|
-
segment: number,
|
|
515
|
-
direction: "lower" | "higher",
|
|
516
|
-
): ExperimentResult | null {
|
|
517
|
-
let best: ExperimentResult | null = null;
|
|
518
|
-
for (const result of results) {
|
|
519
|
-
if (result.segment !== segment || result.status !== "keep" || result.flagged) continue;
|
|
520
|
-
if (!best) {
|
|
521
|
-
best = result;
|
|
522
|
-
continue;
|
|
523
|
-
}
|
|
524
|
-
const better = direction === "lower" ? result.metric < best.metric : result.metric > best.metric;
|
|
525
|
-
if (better) best = result;
|
|
526
|
-
}
|
|
527
|
-
return best;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
async function tryReadBranch(cwd: string): Promise<string | null> {
|
|
531
|
-
try {
|
|
532
|
-
return (await git.branch.current(cwd)) ?? null;
|
|
533
|
-
} catch {
|
|
534
|
-
return null;
|
|
535
|
-
}
|
|
536
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
{{base_system_prompt}}
|
|
2
|
-
|
|
3
|
-
## Autoresearch Mode
|
|
4
|
-
|
|
5
|
-
Autoresearch mode is active.
|
|
6
|
-
|
|
7
|
-
{{#if has_goal}}
|
|
8
|
-
Primary goal:
|
|
9
|
-
{{goal}}
|
|
10
|
-
{{else}}
|
|
11
|
-
There is no goal recorded for this session yet. Infer what to optimize from the latest user message and the conversation; capture the goal in your notes (`update_notes`) once it is clear.
|
|
12
|
-
{{/if}}
|
|
13
|
-
|
|
14
|
-
Session state and run artifacts are managed for you. The benchmark entrypoint is `bash autoresearch.sh` (committed during Phase 1). Do not edit `autoresearch.sh` mid-segment unless you intentionally bump segment via `init_experiment new_segment: true`. Do not create `autoresearch.md` or `.autoresearch/` in this repo.
|
|
15
|
-
|
|
16
|
-
Working directory: `{{working_dir}}`
|
|
17
|
-
{{#if has_branch}}Active branch: `{{branch}}`{{/if}}
|
|
18
|
-
{{#if has_baseline_commit}}Baseline commit: `{{baseline_commit}}`{{/if}}
|
|
19
|
-
|
|
20
|
-
You are running an autonomous experiment loop. Keep iterating until the user interrupts you or the configured maximum iteration count is reached.
|
|
21
|
-
|
|
22
|
-
### Available tools
|
|
23
|
-
- `init_experiment` — open or reconfigure the session. Pass `new_segment: true` to start a fresh baseline within the current session.
|
|
24
|
-
- `run_experiment` — run the benchmark (`bash autoresearch.sh`). Output is captured automatically and `METRIC name=value` / `ASI key=value` lines printed by the harness are parsed back to you. The command is fixed; if you need a different workload, edit `autoresearch.sh` and bump segment via `init_experiment new_segment: true`.
|
|
25
|
-
- `log_experiment` — record the result. On `keep`, changes are committed only on a dedicated `autoresearch/*` branch; otherwise the tool warns and leaves files in the worktree. On `discard`/`crash`/`checks_failed`, the worktree is reverted. Pass `flag_runs` to mark earlier runs as suspect; flagged runs are excluded from baseline and best-metric math.
|
|
26
|
-
- `update_notes` — replace the durable session playbook (`body`) or append to the ideas backlog (`append_idea`). The notes are injected into your system prompt every iteration.
|
|
27
|
-
|
|
28
|
-
### Operating protocol
|
|
29
|
-
1. Understand the target before touching code: read source, identify the bottleneck, verify prerequisites and benchmark inputs.
|
|
30
|
-
2. Update goal, scope, or constraints via another `init_experiment` call (no segment bump) or `update_notes`. Bump segment when you intentionally change `autoresearch.sh`.
|
|
31
|
-
3. Establish a baseline first.
|
|
32
|
-
4. Iterate: change code, run `run_experiment`, log honestly with `log_experiment`. One coherent experiment per iteration.
|
|
33
|
-
5. Keep the primary metric as the decision maker:
|
|
34
|
-
- `keep` when it improves;
|
|
35
|
-
- `discard` when it regresses or stays flat;
|
|
36
|
-
- `crash` when the run fails;
|
|
37
|
-
- `checks_failed` when validation fails (you decide what validation means; run it through the regular `bash` tool).
|
|
38
|
-
6. Use ASI freely — it is opaque, just stash useful learnings (`hypothesis`, `rollback_reason`, `next_action_hint`, anything else).
|
|
39
|
-
7. When confidence is low, re-run promising changes before keeping them. `log_experiment` reports a confidence score (multiples of the observed noise floor) on each kept run.
|
|
40
|
-
|
|
41
|
-
### Scope, off-limits, and accountability
|
|
42
|
-
- Edits are not blocked. You can change anything.
|
|
43
|
-
- `log_experiment` records the modified paths. Files outside `scope_paths` or inside `off_limits` are recorded as `scope_deviations` on the run.
|
|
44
|
-
- If you keep a run with deviations, pass `justification` explaining why. Without it, the run logs but is flagged in the next iteration's prompt as unjustified.
|
|
45
|
-
- If a previous run looks reward-hacked or otherwise wrong, pass `flag_runs: [{ run_id, reason }]` on the next `log_experiment` to exclude it from baseline and best-metric calculations.
|
|
46
|
-
|
|
47
|
-
{{#if has_notes}}
|
|
48
|
-
### Your notes (use `update_notes` to edit)
|
|
49
|
-
|
|
50
|
-
{{notes}}
|
|
51
|
-
|
|
52
|
-
{{/if}}
|
|
53
|
-
{{#if has_recent_results}}
|
|
54
|
-
### Current segment snapshot
|
|
55
|
-
- segment: `{{current_segment}}`
|
|
56
|
-
- runs in current segment: `{{current_segment_run_count}}`
|
|
57
|
-
{{#if has_baseline_metric}}
|
|
58
|
-
- baseline `{{metric_name}}`: `{{baseline_metric_display}}`
|
|
59
|
-
{{/if}}
|
|
60
|
-
{{#if has_best_result}}
|
|
61
|
-
- best kept `{{metric_name}}`: `{{best_metric_display}}`{{#if best_run_number}} from run `#{{best_run_number}}`{{/if}}
|
|
62
|
-
{{/if}}
|
|
63
|
-
|
|
64
|
-
Recent runs:
|
|
65
|
-
{{#each recent_results}}
|
|
66
|
-
- run `#{{run_number}}`: `{{status}}` `{{metric_display}}` — {{description}}
|
|
67
|
-
{{#if has_asi_summary}}
|
|
68
|
-
ASI: {{asi_summary}}
|
|
69
|
-
{{/if}}
|
|
70
|
-
{{#if has_deviations}}
|
|
71
|
-
Modified outside scope: {{deviations}}{{#unless justified}} (no justification){{/unless}}
|
|
72
|
-
{{/if}}
|
|
73
|
-
{{#if flagged}}
|
|
74
|
-
FLAGGED: {{flagged_reason}}
|
|
75
|
-
{{/if}}
|
|
76
|
-
{{/each}}
|
|
77
|
-
{{/if}}
|
|
78
|
-
{{#if has_unjustified_runs}}
|
|
79
|
-
|
|
80
|
-
### Unjustified deviations
|
|
81
|
-
{{#each unjustified_runs}}
|
|
82
|
-
- run `#{{run_number}}` modified `{{paths}}` outside scope without justification. Either accept it, justify it on the next log, or `flag_runs` it.
|
|
83
|
-
{{/each}}
|
|
84
|
-
{{/if}}
|
|
85
|
-
{{#if has_pending_run}}
|
|
86
|
-
|
|
87
|
-
### Pending run
|
|
88
|
-
An unlogged run is waiting:
|
|
89
|
-
- run: `#{{pending_run_number}}`
|
|
90
|
-
- command: `{{pending_run_command}}`
|
|
91
|
-
{{#if has_pending_run_metric}}
|
|
92
|
-
- parsed `{{metric_name}}`: `{{pending_run_metric_display}}`
|
|
93
|
-
{{/if}}
|
|
94
|
-
- result: {{#if pending_run_passed}}passed{{else}}failed{{/if}}
|
|
95
|
-
|
|
96
|
-
Finish the `log_experiment` step before starting another benchmark.
|
|
97
|
-
{{/if}}
|
|
98
|
-
|
|
99
|
-
### Guardrails
|
|
100
|
-
- Do not game the benchmark.
|
|
101
|
-
- Do not overfit to synthetic inputs if the real workload is broader.
|
|
102
|
-
- Preserve correctness.
|
|
103
|
-
- If the user sends another message while a run is in progress, finish the current run and logging cycle first, then address the new input in the next iteration.
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
Continue the autoresearch loop now.
|
|
2
|
-
|
|
3
|
-
- Re-read your notes and the recent-runs context above before deciding the next direction.
|
|
4
|
-
- Inspect recent git history for context.
|
|
5
|
-
{{#if has_pending_run}}
|
|
6
|
-
- A previous benchmark run completed but was never logged. Finish `log_experiment` before starting a new run.
|
|
7
|
-
{{/if}}
|
|
8
|
-
- Continue from the most promising unfinished direction.
|
|
9
|
-
- Keep iterating until interrupted or until the configured iteration cap is reached.
|
|
10
|
-
- Preserve correctness and do not game the benchmark.
|