@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
package/src/autoresearch/git.ts
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Autoresearch branch isolation (ported from the deleted extension's `git.ts`).
|
|
3
|
+
*
|
|
4
|
+
* Every mission is meant to run on a dedicated `autoresearch/*` branch created
|
|
5
|
+
* from a slugified goal. On that branch `keep` auto-commits the iteration and
|
|
6
|
+
* `discard` resets the worktree to HEAD; off-branch (no repo, or a dirty tree
|
|
7
|
+
* that prevents branch creation) we degrade: `keep` skips auto-commits and
|
|
8
|
+
* `discard` reverts only run-modified paths instead of resetting to baseline.
|
|
9
|
+
*
|
|
10
|
+
* Dirty-worktree behavior is faithful to the extension contract: when the tree
|
|
11
|
+
* is dirty and we are NOT already on an autoresearch branch, we return a
|
|
12
|
+
* warning and continue on the current branch rather than failing.
|
|
13
|
+
*/
|
|
14
|
+
import * as fs from "node:fs";
|
|
15
|
+
import * as path from "node:path";
|
|
2
16
|
import * as git from "../utils/git";
|
|
3
|
-
import { normalizePathSpec } from "./
|
|
17
|
+
import { HARNESS_FILENAME, normalizePathSpec } from "./harness";
|
|
4
18
|
|
|
5
|
-
const AUTORESEARCH_BRANCH_PREFIX = "autoresearch/";
|
|
19
|
+
export const AUTORESEARCH_BRANCH_PREFIX = "autoresearch/";
|
|
6
20
|
const BRANCH_NAME_MAX_LENGTH = 48;
|
|
7
21
|
|
|
8
22
|
export interface EnsureAutoresearchBranchFailure {
|
|
@@ -19,21 +33,38 @@ export interface EnsureAutoresearchBranchSuccess {
|
|
|
19
33
|
|
|
20
34
|
export type EnsureAutoresearchBranchResult = EnsureAutoresearchBranchFailure | EnsureAutoresearchBranchSuccess;
|
|
21
35
|
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
36
|
+
export function getCurrentAutoresearchBranch(workDir: string): Promise<string | null> {
|
|
37
|
+
return git.branch.current(workDir).then(currentBranch => {
|
|
38
|
+
return currentBranch?.startsWith(AUTORESEARCH_BRANCH_PREFIX) ? currentBranch : null;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* True when `rawPath` is one of the mission's own research artifacts: the
|
|
44
|
+
* `autoresearch.sh` harness at the working-directory root. This is the complete
|
|
45
|
+
* agent-writable surface for an active mission — product code, manifests,
|
|
46
|
+
* dependencies, and every other path stay blocked by the research-only
|
|
47
|
+
* mutation guard regardless of branch name.
|
|
48
|
+
*
|
|
49
|
+
* Mission state under `.gjc/**` is intentionally NOT listed here: it is
|
|
50
|
+
* runtime-owned and only the sanctioned `gjc autoresearch` CLI writes it.
|
|
51
|
+
*/
|
|
52
|
+
export function isAutoresearchAuthorizedResearchPath(_cwd: string, rawPath: string): boolean {
|
|
53
|
+
const normalized = normalizePathSpec(rawPath);
|
|
54
|
+
if (normalized === ".") return false;
|
|
55
|
+
return normalized === HARNESS_FILENAME;
|
|
25
56
|
}
|
|
26
57
|
|
|
27
58
|
/**
|
|
28
59
|
* Ensure the working tree is on an `autoresearch/*` branch when possible.
|
|
29
60
|
*
|
|
30
|
-
*
|
|
31
|
-
* `{ ok: true, branchName: null, warning }` rather than failing
|
|
32
|
-
* warning and continues on the current branch — `keep`
|
|
33
|
-
* will revert only run-modified paths
|
|
61
|
+
* When the worktree is dirty and we are not already on an autoresearch branch,
|
|
62
|
+
* this returns `{ ok: true, branchName: null, warning }` rather than failing:
|
|
63
|
+
* the caller surfaces the warning and continues on the current branch — `keep`
|
|
64
|
+
* will skip auto-commits and `discard` will revert only run-modified paths
|
|
65
|
+
* instead of resetting to baseline.
|
|
34
66
|
*/
|
|
35
67
|
export async function ensureAutoresearchBranch(
|
|
36
|
-
api: ExtensionAPI,
|
|
37
68
|
workDir: string,
|
|
38
69
|
goal: string | null,
|
|
39
70
|
): Promise<EnsureAutoresearchBranchResult> {
|
|
@@ -58,21 +89,27 @@ export async function ensureAutoresearchBranch(
|
|
|
58
89
|
};
|
|
59
90
|
}
|
|
60
91
|
|
|
61
|
-
const workDirPrefix = await readGitWorkDirPrefix(
|
|
92
|
+
const workDirPrefix = await readGitWorkDirPrefix(workDir);
|
|
62
93
|
const dirtyPaths = collectRelativeDirtyPaths(dirtyPathsOutput, workDirPrefix);
|
|
63
|
-
const currentBranch = await getCurrentAutoresearchBranch(
|
|
94
|
+
const currentBranch = await getCurrentAutoresearchBranch(workDir);
|
|
64
95
|
if (currentBranch) {
|
|
65
96
|
return { ok: true, branchName: currentBranch, created: false };
|
|
66
97
|
}
|
|
67
98
|
if (dirtyPaths.length > 0) {
|
|
68
99
|
const preview = formatDirtyPaths(dirtyPaths);
|
|
69
100
|
return {
|
|
70
|
-
ok:
|
|
71
|
-
|
|
101
|
+
ok: true,
|
|
102
|
+
branchName: null,
|
|
103
|
+
created: false,
|
|
104
|
+
warning:
|
|
105
|
+
`Worktree is dirty (${preview}). Continuing autoresearch on the current branch without a dedicated ` +
|
|
106
|
+
"`autoresearch/*` branch: `keep` will skip auto-commits and `discard` will revert only run-modified " +
|
|
107
|
+
"files instead of resetting to baseline. Commit or stash these changes and re-run to get full branch " +
|
|
108
|
+
"isolation.",
|
|
72
109
|
};
|
|
73
110
|
}
|
|
74
111
|
|
|
75
|
-
const branchName = await allocateBranchName(
|
|
112
|
+
const branchName = await allocateBranchName(workDir, goal);
|
|
76
113
|
try {
|
|
77
114
|
await git.branch.checkoutNew(workDir, branchName);
|
|
78
115
|
} catch (err) {
|
|
@@ -109,8 +146,7 @@ export function relativizeGitPathToWorkDir(repoRelativePath: string, workDirPref
|
|
|
109
146
|
return normalizePathSpec(normalizedPath.slice(normalizedPrefix.length + 1));
|
|
110
147
|
}
|
|
111
148
|
|
|
112
|
-
async function readGitWorkDirPrefix(
|
|
113
|
-
void api;
|
|
149
|
+
async function readGitWorkDirPrefix(workDir: string): Promise<string> {
|
|
114
150
|
try {
|
|
115
151
|
return await git.show.prefix(workDir);
|
|
116
152
|
} catch {
|
|
@@ -170,23 +206,18 @@ export function normalizeStatusPath(rawPath: string): string {
|
|
|
170
206
|
return normalizePathSpec(normalized);
|
|
171
207
|
}
|
|
172
208
|
|
|
173
|
-
async function allocateBranchName(
|
|
209
|
+
async function allocateBranchName(workDir: string, goal: string | null): Promise<string> {
|
|
174
210
|
const baseName = `${AUTORESEARCH_BRANCH_PREFIX}${slugifyGoal(goal)}-${currentDateStamp()}`;
|
|
175
211
|
let candidate = baseName;
|
|
176
212
|
let suffix = 2;
|
|
177
|
-
while (await
|
|
213
|
+
while (await git.ref.exists(workDir, `refs/heads/${candidate}`)) {
|
|
178
214
|
candidate = `${baseName}-${suffix}`;
|
|
179
215
|
suffix += 1;
|
|
180
216
|
}
|
|
181
217
|
return candidate;
|
|
182
218
|
}
|
|
183
219
|
|
|
184
|
-
|
|
185
|
-
void api;
|
|
186
|
-
return git.ref.exists(workDir, `refs/heads/${branchName}`);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function slugifyGoal(goal: string | null): string {
|
|
220
|
+
export function slugifyGoal(goal: string | null): string {
|
|
190
221
|
const normalized = (goal ?? "")
|
|
191
222
|
.toLowerCase()
|
|
192
223
|
.replace(/[^a-z0-9]+/g, "-")
|
|
@@ -317,3 +348,132 @@ export function computeRunModifiedPaths(
|
|
|
317
348
|
}
|
|
318
349
|
return { tracked, untracked };
|
|
319
350
|
}
|
|
351
|
+
|
|
352
|
+
// ---------------------------------------------------------------------------
|
|
353
|
+
// keep / discard
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
|
|
356
|
+
export interface KeepAutoresearchRunInput {
|
|
357
|
+
cwd: string;
|
|
358
|
+
description: string;
|
|
359
|
+
status: string;
|
|
360
|
+
metric: number;
|
|
361
|
+
metrics: { [key: string]: number };
|
|
362
|
+
/** Paths modified by this run (workdir-relative). */
|
|
363
|
+
files: string[];
|
|
364
|
+
/** True when on a dedicated `autoresearch/*` branch. */
|
|
365
|
+
onAutoresearchBranch: boolean;
|
|
366
|
+
primaryMetric: string;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export interface KeepAutoresearchRunResult {
|
|
370
|
+
/** Error text when the commit failed; `ok` is false. */
|
|
371
|
+
error?: string;
|
|
372
|
+
/** Human note for the caller (e.g. "nothing to commit", "committed", "skipped"). */
|
|
373
|
+
note?: string;
|
|
374
|
+
/** Commit SHA after the keep (null when nothing was committed). */
|
|
375
|
+
commitHash?: string | null;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Keep an iteration: commit the modified files on a dedicated autoresearch
|
|
380
|
+
* branch. Off-branch (degraded mode) auto-commit is skipped and the files stay
|
|
381
|
+
* in the worktree, matching the extension contract.
|
|
382
|
+
*/
|
|
383
|
+
export async function keepAutoresearchRun(input: KeepAutoresearchRunInput): Promise<KeepAutoresearchRunResult> {
|
|
384
|
+
if (!input.onAutoresearchBranch) {
|
|
385
|
+
return {
|
|
386
|
+
note: "Auto-commit skipped: not on a dedicated autoresearch branch. Modified files remain in the worktree.",
|
|
387
|
+
commitHash: null,
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
if (input.files.length === 0) {
|
|
391
|
+
return { note: "nothing to commit", commitHash: null };
|
|
392
|
+
}
|
|
393
|
+
try {
|
|
394
|
+
await git.stage.files(input.cwd, input.files);
|
|
395
|
+
} catch (err) {
|
|
396
|
+
return { error: `git add failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
397
|
+
}
|
|
398
|
+
if (!(await git.diff.has(input.cwd, { cached: true, files: input.files }))) {
|
|
399
|
+
return { note: "nothing to commit", commitHash: null };
|
|
400
|
+
}
|
|
401
|
+
const payload: { [key: string]: string | number } = {
|
|
402
|
+
status: input.status,
|
|
403
|
+
[input.primaryMetric]: input.metric,
|
|
404
|
+
};
|
|
405
|
+
for (const [name, value] of Object.entries(input.metrics)) {
|
|
406
|
+
payload[name] = value;
|
|
407
|
+
}
|
|
408
|
+
const commitMessage = `${input.description}\n\nResult: ${JSON.stringify(payload)}`;
|
|
409
|
+
try {
|
|
410
|
+
await git.commit(input.cwd, commitMessage, { files: input.files });
|
|
411
|
+
const commitHash = await git.head.sha(input.cwd);
|
|
412
|
+
return { note: `committed at ${(commitHash ?? "").slice(0, 12)}`, commitHash };
|
|
413
|
+
} catch (err) {
|
|
414
|
+
return { error: `git commit failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export interface DiscardAutoresearchRunInput {
|
|
419
|
+
cwd: string;
|
|
420
|
+
/** Paths that were already dirty before the run started (workdir-relative). */
|
|
421
|
+
preRunDirtyPaths: string[];
|
|
422
|
+
/** True when on a dedicated `autoresearch/*` branch. */
|
|
423
|
+
onAutoresearchBranch: boolean;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export interface DiscardAutoresearchRunResult {
|
|
427
|
+
error?: string;
|
|
428
|
+
note?: string;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Discard a failed/crashed iteration. On a dedicated autoresearch branch the
|
|
433
|
+
* worktree resets to HEAD (never rewinding prior `keep` commits); off-branch
|
|
434
|
+
* only run-modified paths are reverted so pre-existing user dirt survives.
|
|
435
|
+
*/
|
|
436
|
+
export async function discardAutoresearchRun(
|
|
437
|
+
input: DiscardAutoresearchRunInput,
|
|
438
|
+
): Promise<DiscardAutoresearchRunResult> {
|
|
439
|
+
if (input.onAutoresearchBranch) {
|
|
440
|
+
try {
|
|
441
|
+
await git.reset(input.cwd, { hard: true, target: "HEAD" });
|
|
442
|
+
await git.clean(input.cwd);
|
|
443
|
+
return { note: "worktree reset to HEAD" };
|
|
444
|
+
} catch (err) {
|
|
445
|
+
return { error: `git reset/clean failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
let statusText: string;
|
|
450
|
+
try {
|
|
451
|
+
statusText = await git.status(input.cwd, { porcelainV1: true, untrackedFiles: "all", z: true });
|
|
452
|
+
} catch (err) {
|
|
453
|
+
return { error: `git status failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
454
|
+
}
|
|
455
|
+
let workDirPrefix: string;
|
|
456
|
+
try {
|
|
457
|
+
workDirPrefix = await git.show.prefix(input.cwd);
|
|
458
|
+
} catch {
|
|
459
|
+
workDirPrefix = "";
|
|
460
|
+
}
|
|
461
|
+
const { tracked, untracked } = computeRunModifiedPaths(input.preRunDirtyPaths, statusText, workDirPrefix);
|
|
462
|
+
const total = tracked.length + untracked.length;
|
|
463
|
+
if (total === 0) return { note: "nothing to revert" };
|
|
464
|
+
if (tracked.length > 0) {
|
|
465
|
+
try {
|
|
466
|
+
await git.restore(input.cwd, { files: tracked, source: "HEAD", staged: true, worktree: true });
|
|
467
|
+
} catch (err) {
|
|
468
|
+
return { error: `git restore failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
for (const filePath of untracked) {
|
|
472
|
+
try {
|
|
473
|
+
fs.rmSync(path.join(input.cwd, filePath), { force: true, recursive: true });
|
|
474
|
+
} catch {
|
|
475
|
+
// best effort
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return { note: `reverted ${total} file${total === 1 ? "" : "s"}` };
|
|
479
|
+
}
|
|
@@ -1,6 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Autoresearch harness contract: the `autoresearch.sh` entrypoint contract plus
|
|
3
|
+
* parsing of `METRIC <name>=<value>` and `ASI <key>=<value>` lines out of
|
|
4
|
+
* captured output.
|
|
5
|
+
*
|
|
6
|
+
* The contract (ported from the deleted extension's `helpers.ts`):
|
|
7
|
+
* - the harness is `./autoresearch.sh` at the working directory;
|
|
8
|
+
* - it exits 0 on success and non-zero on failure;
|
|
9
|
+
* - it prints the primary metric as `METRIC <name>=<value>` and any secondary
|
|
10
|
+
* metrics as additional `METRIC` lines;
|
|
11
|
+
* - it may print `ASI <key>=<value>` lines for opaque structured learnings.
|
|
12
|
+
*
|
|
13
|
+
* Parsing tolerates interleaved noise: only well-formed lines are recognized,
|
|
14
|
+
* malformed lines are ignored (never thrown), and prototype-polluting key
|
|
15
|
+
* names are dropped.
|
|
16
|
+
*/
|
|
2
17
|
import type { ASIData, ASIValue, MetricDirection, NumericMetricMap } from "./types";
|
|
3
18
|
|
|
19
|
+
export const HARNESS_FILENAME = "autoresearch.sh";
|
|
20
|
+
export const DEFAULT_HARNESS_COMMAND = `bash ${HARNESS_FILENAME}`;
|
|
21
|
+
|
|
4
22
|
export const METRIC_LINE_PREFIX = "METRIC";
|
|
5
23
|
export const ASI_LINE_PREFIX = "ASI";
|
|
6
24
|
export const EXPERIMENT_MAX_LINES = 10;
|
|
@@ -8,33 +26,36 @@ export const EXPERIMENT_MAX_BYTES = 4 * 1024;
|
|
|
8
26
|
|
|
9
27
|
const DENIED_KEY_NAMES = new Set(["__proto__", "constructor", "prototype"]);
|
|
10
28
|
|
|
29
|
+
const METRIC_LINE_RE = new RegExp(`^${METRIC_LINE_PREFIX}\\s+([\\w.µ-]+)=(\\S+)\\s*$`, "gm");
|
|
30
|
+
const ASI_LINE_RE = new RegExp(`^${ASI_LINE_PREFIX}\\s+([\\w.-]+)=(.+)\\s*$`, "gm");
|
|
31
|
+
|
|
32
|
+
/** All `METRIC name=value` lines found anywhere in the captured output. */
|
|
11
33
|
export function parseMetricLines(output: string): Map<string, number> {
|
|
12
34
|
const metrics = new Map<string, number>();
|
|
13
|
-
|
|
14
|
-
let match = regex.exec(output);
|
|
35
|
+
let match = METRIC_LINE_RE.exec(output);
|
|
15
36
|
while (match !== null) {
|
|
16
|
-
const name = match[1];
|
|
37
|
+
const name = match[1] ?? "";
|
|
17
38
|
if (!DENIED_KEY_NAMES.has(name)) {
|
|
18
39
|
const value = Number(match[2]);
|
|
19
40
|
if (Number.isFinite(value)) {
|
|
20
41
|
metrics.set(name, value);
|
|
21
42
|
}
|
|
22
43
|
}
|
|
23
|
-
match =
|
|
44
|
+
match = METRIC_LINE_RE.exec(output);
|
|
24
45
|
}
|
|
25
46
|
return metrics;
|
|
26
47
|
}
|
|
27
48
|
|
|
49
|
+
/** All `ASI key=value` lines found anywhere in the captured output, or null when none parse. */
|
|
28
50
|
export function parseAsiLines(output: string): ASIData | null {
|
|
29
51
|
const asi: ASIData = {};
|
|
30
|
-
|
|
31
|
-
let match = regex.exec(output);
|
|
52
|
+
let match = ASI_LINE_RE.exec(output);
|
|
32
53
|
while (match !== null) {
|
|
33
|
-
const key = match[1];
|
|
54
|
+
const key = match[1] ?? "";
|
|
34
55
|
if (!DENIED_KEY_NAMES.has(key)) {
|
|
35
|
-
asi[key] = parseAsiValue(match[2]);
|
|
56
|
+
asi[key] = parseAsiValue(match[2] ?? "");
|
|
36
57
|
}
|
|
37
|
-
match =
|
|
58
|
+
match = ASI_LINE_RE.exec(output);
|
|
38
59
|
}
|
|
39
60
|
return Object.keys(asi).length > 0 ? asi : null;
|
|
40
61
|
}
|
|
@@ -50,8 +71,7 @@ function parseAsiValue(raw: string): ASIValue {
|
|
|
50
71
|
}
|
|
51
72
|
if (value.startsWith("{") || value.startsWith("[") || value.startsWith('"')) {
|
|
52
73
|
try {
|
|
53
|
-
|
|
54
|
-
return parsed;
|
|
74
|
+
return JSON.parse(value) as ASIValue;
|
|
55
75
|
} catch {
|
|
56
76
|
return value;
|
|
57
77
|
}
|
|
@@ -59,6 +79,38 @@ function parseAsiValue(raw: string): ASIValue {
|
|
|
59
79
|
return value;
|
|
60
80
|
}
|
|
61
81
|
|
|
82
|
+
export interface ParsedHarnessOutput {
|
|
83
|
+
/** Every parsed metric, keyed by name. */
|
|
84
|
+
metrics: NumericMetricMap;
|
|
85
|
+
/**
|
|
86
|
+
* The surfaced primary metric: `metrics[primaryMetricName]` when a name is
|
|
87
|
+
* supplied, otherwise the value of the first `METRIC` line in the output.
|
|
88
|
+
*/
|
|
89
|
+
primary: number | null;
|
|
90
|
+
/** Parsed ASI learnings, or null when no ASI line parsed. */
|
|
91
|
+
asi: ASIData | null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Parse captured harness output into the primary metric, secondary values, and
|
|
96
|
+
* ASI learnings. Malformed or noisy lines are ignored, never thrown.
|
|
97
|
+
*/
|
|
98
|
+
export function parseHarnessOutput(output: string, primaryMetricName?: string): ParsedHarnessOutput {
|
|
99
|
+
const metricMap = parseMetricLines(output);
|
|
100
|
+
const metrics: NumericMetricMap = {};
|
|
101
|
+
for (const [name, value] of metricMap.entries()) {
|
|
102
|
+
metrics[name] = value;
|
|
103
|
+
}
|
|
104
|
+
let primary: number | null = null;
|
|
105
|
+
if (primaryMetricName !== undefined) {
|
|
106
|
+
primary = metricMap.get(primaryMetricName) ?? null;
|
|
107
|
+
} else {
|
|
108
|
+
const first = metricMap.entries().next();
|
|
109
|
+
primary = first.done ? null : first.value[1];
|
|
110
|
+
}
|
|
111
|
+
return { metrics, primary, asi: parseAsiLines(output) };
|
|
112
|
+
}
|
|
113
|
+
|
|
62
114
|
export function mergeAsi(base: ASIData | null, override: ASIData | undefined): ASIData | undefined {
|
|
63
115
|
if (!base && !override) return undefined;
|
|
64
116
|
return {
|
|
@@ -101,18 +153,7 @@ export function formatElapsed(milliseconds: number): string {
|
|
|
101
153
|
return `${seconds}s`;
|
|
102
154
|
}
|
|
103
155
|
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
process.kill(-pid, signal);
|
|
107
|
-
} catch {
|
|
108
|
-
try {
|
|
109
|
-
process.kill(pid, signal);
|
|
110
|
-
} catch {
|
|
111
|
-
// Process already exited.
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
156
|
+
/** True when `current` beats `best` under the given direction. */
|
|
116
157
|
export function isBetter(current: number, best: number, direction: MetricDirection): boolean {
|
|
117
158
|
return direction === "lower" ? current < best : current > best;
|
|
118
159
|
}
|
|
@@ -200,19 +241,3 @@ function sanitizeAsiValue(value: unknown): ASIValue | undefined {
|
|
|
200
241
|
}
|
|
201
242
|
return undefined;
|
|
202
243
|
}
|
|
203
|
-
|
|
204
|
-
export async function tryGitStatus(cwd: string): Promise<string> {
|
|
205
|
-
try {
|
|
206
|
-
return await git.status(cwd, { porcelainV1: true, untrackedFiles: "all", z: true });
|
|
207
|
-
} catch {
|
|
208
|
-
return "";
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export async function tryGitPrefix(cwd: string): Promise<string> {
|
|
213
|
-
try {
|
|
214
|
-
return await git.show.prefix(cwd);
|
|
215
|
-
} catch {
|
|
216
|
-
return "";
|
|
217
|
-
}
|
|
218
|
-
}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Autoresearch Mode — Phase 1: Harness Setup
|
|
4
4
|
|
|
5
|
-
Autoresearch mode is active and there is no
|
|
5
|
+
Autoresearch mode is active and there is no mission yet. Your job in this turn is to **build the benchmark harness**, not to optimise anything. Optimisation starts only after the mission is written.
|
|
6
6
|
|
|
7
7
|
{{#if has_goal}}
|
|
8
8
|
Primary goal (for context — implement the harness so it can measure this):
|
|
9
9
|
{{goal}}
|
|
10
10
|
{{else}}
|
|
11
|
-
There is no goal recorded yet. Infer what to optimise from the latest user message and design the harness to measure that. Capture the goal when you
|
|
11
|
+
There is no goal recorded yet. Infer what to optimise from the latest user message and design the harness to measure that. Capture the goal when you write the mission.
|
|
12
12
|
{{/if}}
|
|
13
13
|
|
|
14
14
|
Working directory: `{{working_dir}}`
|
|
@@ -27,17 +27,17 @@ Write `./autoresearch.sh` at the working directory. It is the canonical benchmar
|
|
|
27
27
|
- print any secondary metrics as additional `METRIC <name>=<value>` lines;
|
|
28
28
|
- run the same workload deterministically every time (no live network, no time-of-day dependencies, fixed seeds where applicable).
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Do not edit product source, manifests, or dependencies. The harness must use existing checked-in commands and fixtures, or report that the mission requires the normal approval-gated implementation path before benchmarking can proceed.
|
|
31
31
|
|
|
32
32
|
### Steps
|
|
33
33
|
|
|
34
34
|
1. Inspect the target. Read source, identify what to measure, decide on the workload.
|
|
35
|
-
2. Write `autoresearch.sh`
|
|
35
|
+
2. Write `autoresearch.sh` only when it is an explicitly approved research artifact; otherwise use an existing benchmark command.
|
|
36
36
|
3. Validate it: invoke `bash autoresearch.sh` through the regular `bash` tool. Confirm it exits 0 and emits at least one `METRIC` line. Iterate on the harness until it does.
|
|
37
|
-
4.
|
|
37
|
+
4. Start the mission with `gjc autoresearch` (cold intake: goal, constraints, deliverables, and an explicit mode) or `gjc autoresearch --spec <spec>` (handoff intake). Record the primary metric name and its direction (lower/higher is better) with the mission. The harness baseline is snapshotted at mission start and Phase 2 (the iteration loop) begins.
|
|
38
38
|
|
|
39
39
|
### Rules
|
|
40
40
|
|
|
41
|
-
- Do **not**
|
|
41
|
+
- Do **not** start the iteration loop yet. The experiment machinery is unavailable until a mission exists.
|
|
42
42
|
- Do **not** treat a compile-only check as a benchmark. The harness must actually execute the workload and emit `METRIC`.
|
|
43
|
-
- Do **not** create `autoresearch.md`, `autoresearch.checks.sh`, `autoresearch.program.md`, `autoresearch.ideas.md`, `autoresearch.jsonl`, `.autoresearch/`, or `autoresearch.config.json`.
|
|
43
|
+
- Do **not** create `autoresearch.md`, `autoresearch.checks.sh`, `autoresearch.program.md`, `autoresearch.ideas.md`, `autoresearch.jsonl`, `.autoresearch/`, or `autoresearch.config.json`. Mission and run state is tracked for you under `.gjc/_session-{id}/autoresearch/`.
|
|
@@ -0,0 +1,103 @@
|
|
|
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 mission yet. Infer what to optimize from the latest user message and the conversation; capture the goal in your notes once it is clear.
|
|
12
|
+
{{/if}}
|
|
13
|
+
|
|
14
|
+
Mission state and run artifacts are managed for you under `.gjc/_session-{id}/autoresearch/`. The benchmark entrypoint is `bash autoresearch.sh` (committed during Phase 1). Do not edit `autoresearch.sh` mid-segment unless you intentionally start a fresh baseline. 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 a research-only evidence loop. Do not modify product code, manifests, dependencies, or benchmark harnesses. Stop with a caveat when evidence requires an implementation change.
|
|
21
|
+
|
|
22
|
+
### Available tools
|
|
23
|
+
|
|
24
|
+
- `python` — a persistent session REPL. Variables, imports, and loaded data survive across calls.
|
|
25
|
+
- `bash` — run an existing benchmark command. Output is captured automatically; `METRIC name=value` and `ASI key=value` lines are parsed back to you, with any other output treated as noise.
|
|
26
|
+
- Run ledger — record each experiment result and flag suspect runs; flagged runs are excluded from baseline and best-metric math.
|
|
27
|
+
|
|
28
|
+
### Operating protocol
|
|
29
|
+
|
|
30
|
+
1. Understand the target without modifying it: read source, identify the bottleneck, verify prerequisites and benchmark inputs.
|
|
31
|
+
2. Record the goal, scope, and constraints with the mission.
|
|
32
|
+
3. Establish a baseline first.
|
|
33
|
+
4. Iterate: run the existing benchmark or data experiment, record honestly. One coherent experiment per iteration.
|
|
34
|
+
5. Keep the primary metric as the decision maker:
|
|
35
|
+
- `keep` when it improves;
|
|
36
|
+
- `discard` when it regresses or stays flat;
|
|
37
|
+
- `crash` when the run fails;
|
|
38
|
+
- `checks_failed` when validation fails (you decide what validation means; run it through the regular `bash` tool).
|
|
39
|
+
6. Use ASI freely — it is opaque, just stash useful learnings (`hypothesis`, `rollback_reason`, `next_action_hint`, anything else).
|
|
40
|
+
7. When confidence is low, re-run promising changes before keeping them. Each kept run reports a confidence score (multiples of the observed noise floor).
|
|
41
|
+
|
|
42
|
+
### Scope, off-limits, and accountability
|
|
43
|
+
|
|
44
|
+
- Product edits are prohibited. A benchmark or data experiment that needs changes is evidence for a separate approval-gated implementation request.
|
|
45
|
+
- If a previous run looks reward-hacked or otherwise wrong, flag it so it is excluded from baseline and best-metric calculations.
|
|
46
|
+
|
|
47
|
+
{{#if has_notes}}
|
|
48
|
+
### Your notes
|
|
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 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
|
+
Record the run in the ledger 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 recording cycle first, then address the new input in the next iteration.
|