Skip to content

feat(goal): make Goal the sole long-task runtime / Goal 成为唯一长任务状态机 - #7959

Merged
SivanCola merged 20 commits into
esengine:main-v2from
SivanCola:feature/goal-sole-runtime
Aug 9, 2026
Merged

feat(goal): make Goal the sole long-task runtime / Goal 成为唯一长任务状态机#7959
SivanCola merged 20 commits into
esengine:main-v2from
SivanCola:feature/goal-sole-runtime

Conversation

@SivanCola

@SivanCola SivanCola commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Make Goal the only long-running task state machine. AutoResearch is reduced to a fail-closed, read-only compatibility reader for historical .reasonix/autoresearch/<task-id>/ archives. New runs no longer create archives, inject AutoResearch protocol, write findings, or expose AutoResearch through CLI help, Desktop APIs, or frontend state.

The default provider-visible tool schemas and order remain byte-stable with main-v2. Planner and child-agent isolation is enforced through host-side Goal recorders, not dynamic schema visibility.

Changes

  • Centralize Goal budget classification in internal/taskintent: simple 10 turns, write 20 turns, and research 40 turns.
  • Make Goal the sole owner of pause/resume, budget accounting, progress detection, Delivery readiness, tool receipts, update_goal, bounded evaluation, and completion/blocking gates.
  • Remove active AutoResearch runtime/evidence protocol handling, criterion readiness, lifecycle writes, and Desktop/Wails/frontend product surfaces.
  • Reduce internal/autoresearch to a read-only archive reader with task-ID validation, workspace confinement, symlink and traversal rejection, JSON schema validation, bounded JSONL records, and file-identity checks.
  • Recover explicit .reasonix/autoresearch/<task-id>/ inputs using the archived original objective, then run an ordinary research-budget Goal.
  • Decode legacy autoResearchTaskID sidecars, preserve Goal state, todos, Delivery checkpoints, and consumed budget, and fill missing objective text from task_spec.json when required.
  • Persist migrated and failed-recovery states as Goal-only sidecars that omit autoResearchTaskID; current writes set researchMode=Off as a downgrade fence.
  • Treat Finding.kind as an opaque string so verification and unknown future values remain readable and displayable.
  • Keep only a display sanitizer for historical <autoresearch-evidence> transcript blocks; current Goal semantics do not parse those blocks or write state from them.
  • Keep deprecated Goal budget flags parseable with a notice while removing them from help, completion, UI, and current documentation.

Compatibility

Field / format Current behavior Result
Legacy sidecar with Goal text and autoResearchTaskID Restores the Goal without requiring archive access, upgrades to research budget, and rewrites without the task ID Recoverable
Legacy sidecar without Goal text Reads and validates the named archive; missing, corrupt, unsafe, or unreadable archives produce a blocked Goal-only state Fail closed
Failed archive migration The persisted sidecar omits the task ID; an in-process Controller token may retry, while restart remains blocked unless an explicit archive path is supplied again No legacy runtime reactivation
budgetClass Missing or unknown values are normalized; current Goals persist simple/write/research budget state and consumed turns Authoritative budget
researchMode Read only for old sidecars and deprecated flags; current sidecars write Off Safe downgrade fence
Historical archive Opened read-only through a confined root and never created, updated, deleted, or migrated in place Archive contents and timestamps preserved
Finding.kind Preserved as an opaque string, including verification, unknown values, and empty legacy values Forward compatible
Provider tool contract Default schemas and ordering match main-v2; planner/child contexts only replace the Goal recorder Byte-stable

No replacement AutoResearch API is introduced. GoalRuntime is the only current long-task runtime surface.

Security and concurrency

  • Archive access rejects unsafe task IDs, path traversal, symlinked roots/tasks/files, oversized records, corrupt schemas, and file replacement detected across validation reads.
  • Archive reads do not mutate file contents or timestamps; tests compare archive hashes and mtimes before and after recovery.
  • Goal migrations and late turn updates are epoch-bound so stale work cannot replace a newer Goal lifecycle.
  • Legacy archive reads happen outside Goal locks, then apply only if the captured Goal epoch is still current.
  • The archive goal loader consumes one bound and validated LoadTask result, avoiding a second reopen that could observe a different filesystem generation.

Cache impact

Cache-impact: low.

  • The ordinary Goal prompt prefix remains stable.
  • Research Goals only remove the historical <autoresearch-runtime> block.
  • Default provider-visible tool schema bytes and ordering remain identical to main-v2.
  • Planner and child-agent Goal isolation does not change provider-visible schemas.

Cache-guard: scripts/cache-guard.sh covers ordinary dialogue, long dialogue, tool loops, and boot extension composition; Goal prompt construction paths are included in scripts/check-cache-impact.sh.

System-prompt-review: completed. The expected prompt change is limited to removing the AutoResearch runtime protocol from research Goals.

Documentation impact

Documentation-impact: updated - English and Chinese Guide/SPEC/Goal Enforcement/collaboration/site documentation now describe Goal-only automatic budgets and read-only legacy archive compatibility. Historical AutoResearch design and audit documents are marked superseded.

Verification

  • go test ./... -count=1
  • go test -race ./internal/control ./internal/agent ./internal/jobs ./internal/tool ./internal/tool/builtin ./internal/memory ./internal/autoresearch -count=1
  • go vet ./...
  • golangci-lint run --timeout=5m
  • cd desktop && go test ./... -count=1
  • cd desktop/frontend && pnpm typecheck && pnpm test:all && pnpm build
  • go run ./tools/repolint
  • scripts/cache-guard.sh
  • scripts/check-cache-impact.sh
  • git diff --check

Focused regression coverage includes budget classification, Goal continuation/pause/resume/completion, old-sidecar and explicit-path recovery, fail-closed archive errors, archive immutability, opaque finding kinds, protocol removal, static provider tool contracts, and removal of Desktop AutoResearch surfaces.

Integration notes

Problem:
AutoResearch still had active write paths, protocol injection, and desktop
surfaces after Goal already owned long-task lifecycle, which left dual
completion gates and upgrade ambiguity.

Root cause:
The previous host-managed AutoResearch runtime remained wired into store
writes, Compose, turn orchestration, evaluator evidence, and Wails/TS APIs
instead of being reduced to read-only archive recovery.

Fix:
- Keep Goal as the only state machine for budgets, pause/resume, receipts,
  update_goal, Delivery readiness, and completion.
- Shrink internal/autoresearch to a fail-closed read-only archive reader.
- Restore explicit legacy task paths and old sidecars as ordinary research
  Goals without mutating archive contents or persisting autoResearchTaskID.
- Remove AutoResearch runtime/evidence protocol and desktop API surfaces.
- Treat Finding.kind as an opaque string; stop enum rejection on write.
- Centralize simple/write/research budget selection in taskintent.
- Update docs/site and cache-impact coverage for Goal prompt construction.

Verification:
- go test ./internal/control ./internal/autoresearch ./internal/taskintent ./internal/goaleval ./internal/agent
- go test -race ./internal/control ./internal/agent
- cd desktop && go test ./...
- cd desktop/frontend && pnpm typecheck && pnpm test:all && pnpm build
- go run ./tools/repolint
- scripts/cache-guard.sh
- scripts/check-cache-impact.sh

Cache-impact: low - ordinary Goal prefixes stay stable; research Goals only
drop the old AutoResearch protocol block; provider-visible tool schema and
default tool order remain byte-stable.
@SivanCola
SivanCola requested a review from esengine as a code owner August 8, 2026 09:29
@github-actions github-actions Bot added desktop Wails desktop app (desktop/**) agent Core agent loop (internal/agent, internal/control) v2 Go rewrite (1.x) — main-v2 branch, active development labels Aug 8, 2026
Problem: models could repeatedly call Goal, planning-only, or background-job tools outside the workflow phase that owns them, leaving no visible answer or operating inherited state.\n\nRoot cause: provider schemas were static and the run-loop repair path recognized only update_goal.\n\nFix: add contextual provider visibility, phase-safe Planner filtering, Goal and Jobs context shadowing, and one bounded generic recovery nudge with focused regression coverage.\n\nVerification: go test ./...; go test -race ./internal/agent ./internal/jobs ./internal/tool ./internal/tool/builtin ./internal/control; go vet ./...; scripts/cache-guard.sh.
@github-actions github-actions Bot added skills Skill system (internal/skill, internal/tool) config Configuration & setup (internal/config) labels Aug 8, 2026
Problem: the contextual-tool fix intentionally grows several already-baselined owner and test files, so repo standards rejects the PR.\n\nRoot cause: repolint budgets remained at the pre-fix line and function counts.\n\nFix: raise only the nine affected file/function budgets and add the new complete_step test-file allowance, without rewriting unrelated baseline entries.\n\nVerification: go run ./tools/repolint; git diff --check.
Problem: the latest main-v2 governor merge adds three baselined function and file lines after the Goal PR sync.\n\nRoot cause: the governor commit did not update repository standards budgets before becoming the PR base.\n\nFix: record only the exact e2ebench and agent.go growth reported by repolint.\n\nVerification: go run ./tools/repolint; git diff --check.
Problem:
Workflow-only tools could remain model-visible outside their executable context, mixed batches did not repair every unavailable call, and legacy AutoResearch recovery could lose retry state or reactivate after downgrade.

Root cause:
Tool schemas and child metadata were assembled from static registries, parent runtime services leaked through inherited contexts, and legacy task IDs were cleared before migration persistence was known to succeed.

Fix:
Filter schemas through ContextualTool, bound mixed-batch repair, isolate child Goal/Jobs/memory state, compute contextual metadata, and make legacy sidecar migration retryable, fail-closed, and downgrade-safe with budgetClass as the authority.

Verification:
go test ./... -count=1
go test -race ./internal/control ./internal/agent ./internal/jobs ./internal/tool ./internal/tool/builtin ./internal/memory ./internal/autoresearch -count=1
go vet ./...
golangci-lint run --timeout=5m
cd desktop && go test ./... -count=1
pnpm typecheck; pnpm test:all; pnpm build
scripts/cache-guard.sh
go run ./tools/repolint
git diff --check
Problem: the Goal-only runtime still had provider-context schema filtering assumptions, and an explicit legacy archive could lose its recovery token after a Controller restart.\n\nRoot cause: execution isolation was coupled to provider-visible tool removal, while explicit archive identity lived only in memory and was not distinguished from a sidecar Goal text.\n\nFix: keep stable Registry schemas and enforce Goal, Jobs, and memory boundaries at execution time; add epoch-fenced read-only archive recovery with explicit-path restart handling; preserve unknown Finding kinds and add focused regression coverage.\n\nVerification: go test ./...; go test -race ./internal/control ./internal/agent; cd desktop/frontend && pnpm typecheck && pnpm test:all && pnpm build; scripts/cache-guard.sh; scripts/check-cache-impact.sh; go run ./tools/repolint; git diff --check.
@github-actions github-actions Bot added the tui Terminal UI / CLI (internal/cli, internal/control) label Aug 8, 2026
Problem:
The explicit legacy archive fail-closed test passed on Unix but failed on Windows because chmod zero does not make a file unreadable there.

Root cause:
The fixture relied on Unix permission semantics instead of creating a platform-independent archive read failure.

Fix:
Replace task_spec.json with a directory so archive decoding fails deterministically on every supported platform.

Verification:
go test ./internal/control -count=1
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go test -c ./internal/control
Problem
The PR branch received a concurrent sibling fix while the local branch also integrated the latest main-v2 and completed the Goal-only runtime hardening.

Root cause
The sibling implementation reintroduced context-dependent provider tool schemas and a pending legacy task field, conflicting with the PR's cache-stability and Goal-state ownership requirements.

Fix
Merge the remote branch without force-push, retain static provider schemas with execution-time isolation, keep epoch-fenced legacy restoration outside the active Goal machine, and document the reconciled behavior.

Verification
- go test ./... -count=1
- go test -race ./internal/control ./internal/agent -count=1
- cd desktop && go test ./... -count=1
- desktop/frontend pnpm typecheck, test:all, build
- scripts/cache-guard.sh
- scripts/check-cache-impact.sh
- go run ./tools/repolint
- git diff --check
Problem:
A concurrent branch reconciliation kept static provider schemas and moved legacy recovery state outside the Goal machine, diverging from the approved esengine#7959 behavior after the latest-base merge.

Root cause:
The merge resolved overlapping Goal, Jobs, child-context, and tool-registry owner files in favor of an alternative execution-only isolation design.

Fix:
Restore ContextualTool provider visibility, bounded mixed-call repair, transactional retryable legacy migration, downgrade fencing, contextual metadata, and child Goal/Jobs/memory isolation on top of the merged base. Keep the portable Windows archive-read fixture.

Verification:
go test ./... -count=1
go test -race ./internal/control ./internal/agent ./internal/jobs ./internal/tool ./internal/tool/builtin ./internal/memory ./internal/autoresearch -count=1
go vet ./...
golangci-lint run --timeout=5m
cd desktop && go test ./... -count=1
scripts/cache-guard.sh
scripts/check-cache-impact.sh
go run ./tools/repolint
git diff --check
Problem:
The PR head had fallen behind main-v2 and GitHub reported a merge conflict after the Skills settings consistency work landed.

Root cause:
Both branches updated the repository lint baseline while the latest base also changed desktop settings, config loading, and runtime rebuild paths.

Fix:
Merge main-v2 without rewriting history and regenerate the repolint baseline from the semantically combined tree.

Verification:
- go test ./... -count=1
- go test -race ./internal/control ./internal/agent -count=1
- go vet ./...
- golangci-lint run --timeout=5m
- cd desktop && go test ./... -count=1
- cd desktop/frontend && pnpm test:all
- cd desktop/frontend && pnpm build
- scripts/cache-guard.sh
- scripts/check-cache-impact.sh
- go run ./tools/repolint
- git diff --check
Problem
Legacy archive retry identity lived inside the active Goal machine, and the removed AutoResearch readiness reader still carried a second completion contract.

Root cause
Archive failures depended on a Goal-owned task token that was written back into new sidecars and could be mistaken for an active AutoResearch runtime.

Fix
Keep archive identity only in the Controller-owned read-only recovery boundary, fence ordinary Goal resume for legacy failures, omit deprecated sidecar fields, and fold finding compatibility checks into the read-only summary path.

Verification
Focused legacy restore, finding compatibility, control, agent, boot, and autoresearch tests pass; git diff --check passes.
…runtime-fix

# Conflicts:
#	desktop/frontend/src/__tests__/stream-delta-batch.test.ts
#	tools/repolint/baseline.json
Problem: The Goal/runtime fixes added lines and complexity to several files already at their repolint debt ceilings, causing the repository gate to fail after merging the latest baseline.

Root cause: Contextual tool visibility, legacy durability helpers, and their tests were implemented inline in large owner files instead of dedicated modules.

Fix: Extract workflow context, planner registry, subagent identity, Goal durability, Jobs context, CLI Goal handling, and focused tests into scoped files. Keep provider behavior unchanged and add the new schema-bearing files to cache-impact coverage.

Verification: go test ./internal/agent ./internal/boot ./internal/control ./internal/jobs ./internal/tool/builtin -count=1; go run ./tools/repolint; git diff --check
Problem: The PR made provider-visible schemas conditional on Goal, Plan, and Jobs context, removing update_goal from ordinary and economy requests and violating the required byte-stable tool contract.

Root cause: A broad contextual-tool mechanism was added while hardening Goal recorder isolation, coupling an execution boundary to provider schema selection.

Fix: Restore static Schemas() requests and the main-v2 tool order, remove contextual schema APIs and phase-specific visibility, and keep only execution-time Goal recorder isolation for planners and child agents. Correct the changelog and cache-impact coverage.

Verification: go test ./internal/agent ./internal/boot ./internal/control ./internal/tool ./internal/tool/builtin -count=1; go run ./tools/repolint; git diff --exit-code origin/main-v2 -- internal/agent/extensions.go internal/agent/run_loop.go internal/agent/sampling_request.go internal/tool/tool.go internal/tool/builtin/bgjobs.go internal/tool/builtin/completestep.go internal/tool/builtin/updategoal.go internal/jobs/jobs.go internal/memory/queue.go; git diff --check
Problem
The Goal-only migration still exposed a stale Desktop AutoResearch mock, retained a removed variadic setup shape, and reopened a legacy archive after it had already been validated.

Root cause
Compatibility cleanup stopped short of the final source-level boundary, and the archive goal loader performed redundant validation after LoadTask had bound and verified the archive snapshot.

Fix
Remove the stale Desktop mock and variadic argument, document the evidence sanitizer as display-only, and use the single validated LoadTask result for legacy goal recovery.

Verification
- go test ./internal/control ./internal/autoresearch ./internal/agent ./internal/taskintent ./internal/boot ./internal/tool -count=1
- go test -race ./internal/control ./internal/agent ./internal/jobs ./internal/tool ./internal/tool/builtin ./internal/memory ./internal/autoresearch -count=1
- go test ./... -count=1
- cd desktop && go test ./... -count=1
- cd desktop/frontend && pnpm typecheck && pnpm test:all && pnpm build
- go vet ./...
- golangci-lint run --timeout=5m
- scripts/cache-guard.sh
- go run ./tools/repolint
- git diff --check
@SivanCola
SivanCola merged commit 677ca8d into esengine:main-v2 Aug 9, 2026
28 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config) desktop Wails desktop app (desktop/**) skills Skill system (internal/skill, internal/tool) tui Terminal UI / CLI (internal/cli, internal/control) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant