Commit Graph
19 Commits
Author SHA1 Message Date
YHH 4fbbca6a99 refactor(go): adopt modern stdlib idioms and gate them (#7831)
* refactor(go): adopt modern stdlib idioms across kernel and desktop

Mechanical sweep with golangci-lint's modernize/intrange/copyloopvar/
usestdlibvars fixers plus hand-fixes for what they could not rewrite:
slices.Contains, min/max, slices.Backward, WaitGroup.Go, reflect.TypeFor,
maps.Copy, strings.Cut/CutPrefix/SplitSeq, strings.Builder, range-over-int.
Net -549 lines with no behavior change.

Three loops in session.go stay index-based: slices.Backward yields element
copies, so the fixer's rewrite silently dropped writes to DecisionReceipts
and ToolCalls (caught by TestDelivery* and TestDependentSameBatch*). All 49
slices.Backward sites were audited for that shape; only these three write
through the index, and they carry a nolint with the reason.

CaptureAfter's scan loop had an empty body and never ran any logic, so the
fixer could not express it. Drop it and the accessor it was the only caller
of. omitzero is deliberately untouched: turning omitempty into omitzero
changes the JSON written for nested structs, which is a wire-format change
to session files and the extension protocol.

* build(lint): gate the modern-idiom linters

Nothing stopped the codebase from drifting back to pre-1.22 idioms. Both
modules are now clean for modernize, intrange, copyloopvar, and
usestdlibvars, so enable them rather than leaving the sweep as a one-off.

omitzero stays disabled with the reason inline; usetesting, perfsprint, and
errorlint still have residue and land separately.
2026-08-07 15:30:33 +08:00
SivanCola 2c54501b5e fix(agent): preserve parallel subagent results (#7375)
Problem: Long parallel_tasks and fleet answers could exceed the single-tool output limit, combining and truncating independent child reports.

Root cause: Both aggregators concatenated every full child answer before the global output guard applied head/tail truncation.

Fix: Persist each child transcript, return bounded fair previews with stable references, and add a conversation-scoped read_subagent_result pager with lineage and workspace checks.

Verification: go test ./... -count=1; go test -race ./internal/agent -count=1; ./scripts/cache-guard.sh; git diff --check.
2026-08-05 02:43:45 +08:00
SivanCola 6a2a84e039 feat(rewind): make local rollback transactional and conflict-safe
Problem:
Local rewind could partially restore files, silently fall back to legacy behavior, or apply a stale conflict decision.

Root cause:
Checkpoint payloads lacked a durable transaction protocol, mutation writers were not fenced consistently, and preview tokens were not revalidated at commit time.

Fix:
Add compatible v2 checkpoints, blob-backed atomic transactions with crash recovery, writer observation and barriers, controller prepare/commit/undo APIs, and immediate Desktop rewind with explicit conflict handling.

Verification:
Run root and Desktop Go suites, race tests, cache guard, Windows checkpoint cross-compile, frontend production build and targeted rewind/workspace contracts.
2026-08-04 00:43:48 +08:00
SivanCola 1ed116a978 fix(runtime): make guarded execution predictable
Problem:
Permission modes, Auto Guard recovery, late steer handling, and desktop submission paths could disagree about whether work should run, prompt, or stop. Concurrent session display writes and unbounded parallel task batches also exposed reliability gaps.

Root cause:
The affected paths used separate fallback assumptions, lost explicit rule provenance, accepted empty provider input behind visible display text, replayed stale guidance, and lacked serialization or admission bounds at key state boundaries.

Fix:
Unify permission precedence and matched-rule explanations, fail closed for headless Ask, require exact approval for dynamic Bash, preserve legacy PowerShell rules, cancel dismissed Ask turns, reject empty provider input while preserving skill-only turns, classify safe verification commands, recover stale edits automatically, persist late steer as local-only, serialize display sidecar updates, and cap parallel task batches.

Compatibility:
Existing session and wire formats remain readable; legacy Set-Content, Add-Content, and Out-File rules migrate transparently; unrelated Verb-Noun tool rules retain their meaning; provider prompt prefixes and tool schemas are unchanged.

Verification:
- go test -p 1 ./...
- cd desktop && go test ./...
- cd desktop/frontend && pnpm test
- cd desktop/frontend && pnpm typecheck
- git diff --check
2026-07-31 08:16:16 +08:00
SivanCola 5480019c4f feat(agent): evolve Auto mode with Auto Guard / 以 Auto Guard 强化自动模式 (#6732)
* feat(agent): add Auto-mode failure recovery checkpoint / 为自动模式增加失败恢复检查点

Problem:
In Auto mode, after a tool or verification failure the agent could silently
change strategy, expand write scope, or raise risk without a user decision.

Root cause:
There was only the Ask/Auto/YOLO permission axis and plan confirmation. No
host-side checkpoint blocked unconfirmed recovery mutations after failures.

Fix:
- Add a shared per-task recovery state machine (idle/diagnosing/awaiting/
  approved_once) consulted before permission and write-lock acquisition.
- Deterministic rules auto-continue same-strategy verification retries and
  force confirm for high-risk, scope, strategy, or consecutive failures.
- Independent recovery reviewer with isolated policy/session; fail closed.
- Fresh recovery approval cards (continue/revise/stop); never session-drain.
- Config/session defaults: new sessions on, pre-upgrade sessions off.
- Desktop composer toggle + settings default; Bot structured recovery UX;
  content-free recovery metrics; reviewer/gate sidecars for cold restart.
- Docs: English + Chinese tool-approval modes.

Verification:
- go test ./internal/recovery/ ./internal/control/ ./internal/bot/ -run
  'TestRecovery|TestCache|Approval' -count=1
- Cache-shape test: success-path system/tools hashes unchanged with gate on
- desktop package compiles (go test -c)

Cache-impact: low — success path keeps stable system prompt and tool schemas
byte-stable; only failure-path dynamic user-tail and an isolated reviewer
session add tokens.
Cache-guard: internal/recovery TestRecoveryWiringPreservesSuccessPathCacheShape
System-prompt-review: N/A for main agent (reviewer uses a separate fixed policy)

* fix(agent): harden auto recovery checkpoints

Problem:
Auto recovery could start a concurrent Agent.Run, wait forever in headless mode, duplicate revise feedback, and persist incomplete or orphaned recovery state.

Root cause:
Failure guidance was routed through Controller.Steer, headless detection relied on approval timeout, reviewer transcripts were treated as session sidecars, and recovery state lacked ordered atomic persistence and task-scoped replay semantics.

Fix:
Deliver guidance to the exact Agent.Run, use explicit headless mode, isolate root and subagent recovery identities, make recovery state atomic and session-owned, support cold-start decisions, and complete the Wails/mock bridge contract.

Verification:
go test ./...; go test -race ./...; root and desktop vet/lint; desktop tests; frontend typecheck/tests/build; real-browser Continue/Revise/Stop checks.

* style: format recovery checkpoint fields

Problem:
CI stopped before compilation because four recovery-related Go files from the original PR were not gofmt-clean.

Root cause:
Aligned struct fields were added without running the repository-wide formatter gate.

Fix:
Apply gofmt to the affected root and desktop files without changing behavior.

Verification:
The exact root and desktop gofmt checks from CI now produce no output.

* test(recovery): respect Windows file modes

Problem:
The Windows CI leg failed even though the recovery snapshot was written atomically and remained valid JSON.

Root cause:
The test expected POSIX 0600 permission bits from FileMode.Perm on Windows, where NTFS permissions are represented by inherited ACLs and Go reports synthetic 0666 bits.

Fix:
Keep the atomic persistence assertions on every platform and limit the numeric 0600 assertion to platforms where POSIX mode bits are meaningful.

Verification:
Focused recovery tests pass, the Windows test package cross-compiles, and the exact root gofmt gate is clean.

* fix: harden recovery checkpoint session isolation

Problem:
Recovery state could cross session boundaries, delayed snapshots could target a new session, destructive delete tools could bypass human confirmation, synchronous approval replies could be lost, and legacy sessions could resume enabled.

Root cause:
The gate resolved persistence paths asynchronously, session rotations did not consistently replace gate state, approval IDs were bound after event emission, delete tools were absent from deterministic risk rules, and resume ignored branch metadata.

Fix:
Capture and drain persistence per session, reset or carry recovery state explicitly across every rotation, bind approval IDs before emission, classify delete tools as high risk, and restore the persisted per-session preference with a legacy-off default.

Verification:
go test ./...
(cd desktop && go test ./...)
go test -race ./internal/recovery ./internal/control -run 'Recovery|FreshSessionRotations|SetSessionPath'
go vet ./...
./scripts/cache-guard.sh

* fix(recovery): preserve defaults across session resets

Problem:
Recovery settings were omitted from rendered configuration, and fresh sessions could inherit a resumed session preference instead of the configured default.

Root cause:
The serializers did not emit the new fields, while the controller kept one mutable recovery flag for both current-session state and future-session defaults. Desktop metadata snapshots also did not consistently mirror the effective preference.

Fix:
Render and round-trip the recovery settings, separate current and default controller state, route known-new paths through an explicit fresh-session binding, and synchronize Desktop tabs and branch metadata after rotation.

Verification:
go test ./...
(cd desktop && go test .)
go test -race ./internal/control -run recovery rotation cases
(cd desktop && go test -race . -run recovery session cases)

* feat(agent): evolve recovery checkpoint into Auto Guard

Problem:
Auto only applied the recovery checkpoint after failures, duplicated UI and config controls, and escalated every uncertain recovery directly to a human.

Root cause:
High-risk classification was scoped to active failure state, while persisted one-shot grants and recovery-specific Stop and replay branches made the flow stateful and fragmented.

Fix:
Add a deterministic pre-action Auto Guard, return reviewer denials to agents before three-strike human escalation, remove stale grant replay and recovery Stop, consolidate config and UI, and preserve legacy wire and config decoding.

Verification:
- go test ./...
- go test -race ./internal/recovery
- (cd desktop && go test ./...)
- (cd desktop/frontend && pnpm test:typecheck && pnpm test && pnpm build)

* test(recovery): synchronize prompt resolution

Problem:
Linux CI could schedule prompt-resolution goroutines before the gate re-keyed its provisional waiter, leaving two new tests blocked until the package timeout.

Root cause:
The tests resolved real approval IDs without first binding them, so they depended on scheduler timing even though production prompt emitters use BindApprovalID.

Fix:
Bind each approval ID synchronously inside the prompt callback before resolving the decision.

Verification:
- go test ./internal/recovery -run TestHighRiskMutationPromptsBeforeAnyFailure\|TestReviewerBlockReturnsReasonThenEscalates -count=100
- go test -race ./internal/recovery -run TestHighRiskMutationPromptsBeforeAnyFailure\|TestReviewerBlockReturnsReasonThenEscalates -count=100

* ci: restart stuck Windows runner

Problem:
The Windows test job stayed in progress well past its configured 10-minute step timeout and ignored both normal and force-cancel requests.

Root cause:
The hosted runner stopped reporting progress after entering the test step, preventing the workflow from reaching a rerunnable conclusion.

Fix:
Advance the PR head without file changes so the workflow concurrency policy replaces the stuck run with a fresh runner.

Verification:
The same head already passed Ubuntu, macOS, race, lint, coverage, CodeQL, cache-impact, and desktop Linux checks.

* fix(desktop): keep Yolo visible in composer

Problem:
The Auto Guard refinement hid Yolo from the composer unless it was already active, which made a supported approval mode less discoverable and left the three-column control partially empty.

Root cause:
The composer rendered the Yolo button conditionally and narrowed the approval control for a two-option default surface.

Fix:
Always render Ask, Auto, and Yolo, restore the three-option width, and align English/Chinese documentation and regression coverage with the direct selection flow.

Verification:
- pnpm exec tsx src/__tests__/composer-run-strip.test.tsx
- pnpm test:typecheck
- pnpm check:css
- pnpm test
- pnpm build
- Browser DOM/click verification for all three visible options

* fix(recovery): close Auto Guard evidence gaps

Problem:
Auto Guard could miss dependency/config deletes, moves, and common install or publish commands, while the recovery reviewer never received the read-only evidence gathered after a failure.

Root cause:
High-risk classification covered only a subset of file mutation tools and broad command names, and successful diagnostic observations were discarded before populating the task-local diagnosis state.

Fix:
Classify every built-in file mutation path and risky package-manager subcommand, keep ordinary verification commands on the fast path, and persist bounded, deduplicated, task-local diagnostic excerpts for the isolated reviewer. Mark dynamic reviewer evidence as untrusted.

Verification:
- go test -race ./internal/recovery -count=1
- env -u DEEPSEEK_API_KEY go test ./... -count=1
- go vet ./...
- cd desktop && go test ./... -count=1
- go test ./internal/recovery -run TestRecoveryWiringPreservesSuccessPathCacheShape -count=1
- ./scripts/cache-guard.sh

* fix(recovery): remove obsolete path helper

Problem:
The PR lint job rejected an unused pathFromArgs helper left behind after high-risk classification moved to multi-path extraction.

Root cause:
The compatibility wrapper had no remaining callers, while go vet does not report unused package-level functions.

Fix:
Remove the obsolete wrapper and retain pathsFromArgs as the single path extraction implementation.

Verification:
- go test ./internal/recovery -count=1
- go test -race ./internal/recovery -count=1
- go run github.com/golangci/golangci-lint/v2/cmd/[email protected].2 run --timeout=5m

* test(recovery): freeze Auto Guard behavior matrix

Problem:
Auto Guard routing is embedded in the Gate coordinator, so later
refactors risk changing product semantics without a focused oracle.

Fix:
Add a pure Decision engine skeleton and table-driven golden coverage for
the product matrix: ordinary Auto paths never call the reviewer, high
risk and scope/strategy/second-failure ask immediately, ambiguous
recovery reviews once, reject budget escalates on the third block, and
reviewer errors fail closed without burning reject credits.

Verification:
go test ./internal/recovery/

* refactor(recovery): pure decision core, collapsed state, provider reviewer

Problem:
Auto Guard mixed classification, routing, agent-based review, and multi-source
runtime state in one Gate, making later product simplification risky.

Root cause:
Phase/ConsecutiveFails/SafeRetryLeft/Pending lived as parallel truth, and the
reviewer spun a full agent.Agent with tools and compaction.

Fix:
- Route through a pure Decide engine (Classifier facts → allow/review/ask).
- Keep one taskRuntime + activeFailure; derive Phase and wire compatibility
  fields on Snapshot; Restore still drops Pending/ApprovalID grants.
- Replace the agent reviewer with a bounded provider.Stream call
  (temp 0, max 256 tokens, 8 KiB total, 4 KiB output cap, recovery-reviewer
  usage source).

Verification:
go test ./internal/recovery/ ./internal/control/ -run 'Recovery|AutoGuard|recovery'

* refactor(desktop): one-click Auto recovery and remove Guard toggles

Problem:
Recovery cards still used select-then-confirm, and unreleased per-tab /
Settings Auto Guard toggles competed with Ask/Auto/YOLO as a fourth control.

Fix:
- Recovery card is one click: Continue this step / Try another approach,
  optional guidance, details collapsed, localized reason by change_kind.
- Empty revise feedback is accepted; host injects a fixed agent guidance.
- Remove desktop Settings and Wails per-tab Auto Guard toggles; kill switch
  remains [agent].auto_recovery_checkpoint only.
- Stop persisting RecoveryCheckpointEnabled on BranchMeta.
- Document guarded Auto semantics in EN/ZH mode docs.

Verification:
go test ./internal/recovery ./internal/control -run Recovery
desktop go test focused recovery/session cases
pnpm exec tsx src/__tests__/decision-surface.test.tsx

* fix(desktop): keep legacy Auto Guard Wails no-ops

Problem:
Removing the Wails methods broke frontend typecheck against generated
bindings that still list the old surfaces.

Fix:
Restore thin no-op / config-read Wails methods so older frontends and
generated bindings keep compiling, without reviving per-tab or Settings
Auto Guard toggles as product controls.

Verification:
pnpm typecheck
go test . -run AutoRecovery|RecoveryCheckpoint|NewSessionUsesFresh (desktop)

* fix(recovery): unblock legacy Approve, honor project kill switch, keep evidence JSON valid

Problem:
1. Pre-action high-risk recovery cards parked a live waiter without taskRuntime,
   so Approve looked them up via Snapshot and never called ResolveRecovery —
   old clients could hang until context cancel.
2. Desktop re-applied Auto Guard from user-only config after boot, ignoring
   project [agent].auto_recovery_checkpoint = "off".
3. Reviewer evidence over 6 KiB was clipped mid-JSON, producing invalid payload.

Root cause:
Live waiter state was inferred from a persistence-shaped snapshot; desktop
overwrote the controller kill switch; field budgeting happened after marshal.

Fix:
- Gate.HasApproval(id) inspects the live waiter table; Approve routes through it.
- Remove desktop secondary SetRecoveryCheckpointEnabled / DefaultEnabled overrides.
- Budget optional evidence fields, then marshal; assert json.Valid and size.
- UTF-8-safe feedback clip at the 4 KiB host cap.

Verification:
go test -race ./internal/recovery ./internal/control
go test . -run AutoRecovery|NewSessionUsesFresh (desktop)

* fix(ci): clear Auto Guard lint failures and freeze project kill switch

Problem:
CI golangci-lint v2.12.2 failed on three issues introduced by the Auto Guard
refactor: an empty if (SA9003), a redundant explicit type (ST1023), and an
unused desktop helper (U1000).

Fix:
- Assert the real recovery approval id is cleared after legacy Approve.
- Use r := reviewer in the decision matrix helper.
- Remove unused currentTabRecoveryCheckpointEnabled.
- Add boot regression: global on + project off disables Auto Guard at Build
  and after SetFreshSessionPath.

Verification:
go test ./internal/recovery ./internal/control ./internal/boot -run LegacyApprove|BehaviorMatrix|BuildHonorsProject|HasApproval
staticcheck -checks SA9003,ST1023,U1000 on touched packages

* test(desktop): freeze project Auto Guard kill switch

Problem:
The existing regression only exercised boot.Build and did not pass through the desktop runtime wiring that previously reapplied the user-global Auto Guard setting.

Root cause:
The test used a legacy-compatible config path and treated a same-controller session rotation as proof of desktop rebuild behavior, so the secondary desktop overrides were outside its coverage.

Fix:
Use the primary user config path and add a desktop integration regression that builds a project tab with global on/project off, then verifies initial configuration and a fresh-session rotation both remain disabled.

Verification:
go test ./...
go test -race ./internal/recovery ./internal/control ./internal/boot
(cd desktop && go test ./...)
golangci-lint v2.12.2 in root and desktop
./scripts/cache-guard.sh

* refactor(recovery): make Auto Guard intrinsic to Auto

Problem:
The short-lived auto_recovery_checkpoint kill switch duplicated Auto mode state across config, recovery decisions, controller sessions, and desktop tabs, increasing user and maintenance cost.

Root cause:
Auto Guard was introduced as an optional feature even though its decision matrix is part of Auto mode's product contract.

Fix:
Remove the config key and the full runtime enablement chain. Ignore retired TOML and session metadata fields, clean them on the next save, and retain only no-op Wails compatibility methods for older generated frontends. Update docs and regressions, and format files that blocked the prior CI run.

Verification:
- go test -race ./internal/recovery ./internal/control
- go test ./internal/agent ./internal/config ./internal/boot
- cd desktop && go test ./...
- cd desktop/frontend && pnpm typecheck && pnpm test:typecheck
- decision-surface and composer-run-strip tests
- ./scripts/cache-guard.sh

* test(boot): isolate Windows config directories

Problem:
The Windows root-module CI repeatedly loaded a test provider from an earlier case, retried example.invalid for 92 seconds, and then timed out.

Root cause:
isolateConfigHome redirected HOME and XDG_CONFIG_HOME but not the AppData and LocalAppData directories used by os.UserConfigDir and os.UserCacheDir on Windows.

Fix:
Redirect USERPROFILE, AppData, and LocalAppData into the same per-test temporary directory.

Verification:
- go test ./internal/boot
- repeated the affected Boot tests three times
- confirmed the Go standard library reads AppData and LocalAppData on Windows

* fix(desktop): prevent approval control overlap

Problem:
The three-option approval bar overlapped the adjacent model selector at compact composer widths.

Root cause:
The 760px container rule shrank the approval wrapper to 164-178px while its child mode bar retained a fixed 200-232px width.

Fix:
Allow the approval mode bar to shrink with its compact parent and add a CSS contract regression for the responsive geometry.

Verification:
- pnpm test
- pnpm build
- pnpm typecheck
- pnpm test:typecheck
- pnpm check:css
- ./scripts/cache-guard.sh
- in-app browser geometry at 1280px and 1182px viewport widths

* fix(recovery): close Auto Guard review gaps

Problem:
Auto Guard missed wrapped dependency and configuration mutations, while desktop telemetry replayed cumulative recovery counters on every completed turn.

Root cause:
The high-risk classifier recognized only narrow command and path shapes, and the desktop sampled controller totals rather than per-turn deltas.

Fix:
Harden wrapper and configuration mutation classification, add atomic recovery metric draining, and cover both regressions with focused tests.

Verification:
- go test ./...
- go test -race ./internal/recovery ./internal/control
- cd desktop && go test ./...
- go vet ./...
- ./scripts/cache-guard.sh

* refactor(recovery): make Auto interruption-light

Problem:
Auto asked users to understand recovery internals and interrupted reversible workspace work, while Plan required select-then-confirm.

Root cause:
The recovery classifier treated config and dependency edits, strategy changes, and the second failure as human boundaries, and the desktop surface exposed internal guard concepts.

Fix:
- reserve human prompts for deterministic hard boundaries or three failed attempts
- keep low-risk recovery moving when optional review is unavailable
- simplify Plan and recovery decisions to two direct, accessible buttons
- align desktop, bot, docs, and localized copy

Verification:
- go test ./...
- pnpm --dir desktop/frontend test:all
- pnpm --dir desktop/frontend build
- browser verification for Auto, Plan + Auto, Goal + Auto, Plan confirmation, and recovery confirmation

* fix(recovery): align Auto boundaries and reviewer

Problem:
Auto could silently allow destructive or external commands, while the isolated reviewer still rejected bounded project-local dependency, config, strategy, and scope changes after failures.

Root cause:
The deterministic shell classifier omitted destructive Git variants, global package-manager forms, and external mutation CLIs. The fixed reviewer contract only allowed same_strategy verdicts after Auto policy moved bounded workspace recovery to the automatic path.

Fix:
- Classify destructive Git state changes, global package operations, HTTP/GitHub API mutations, and remote command families as hard boundaries while preserving proven read-only fast paths.
- Allow reviewer continue verdicts for bounded, task-aligned strategy and scope changes while keeping risk and uncertainty fail closed.
- Align the three-failure rationale and add policy and classifier regression coverage.

Verification:
- go test ./... -count=1
- go test -race ./internal/recovery ./internal/control ./internal/agent -count=1
- go vet ./...
- golangci-lint v2.12.2 ./internal/recovery/... (0 issues)
- ./scripts/cache-guard.sh

* fix(auto): scope reusable recovery approvals safely

Problem:
Auto Guard repeatedly interrupted bounded external operations, while several unlisted shell, PowerShell, Git checkout, and attached GitHub CLI flag forms could bypass the intended hard boundary.

Root cause:
Recovery confirmations were one-shot only and the shell classifier relied on an incomplete deny list without a host-owned semantic authorization scope.

Fix:
Add task-scoped semantic grants for explicitly bounded operations, expose opt-in actions across Desktop, CLI, and Bot, fail closed for unknown mutations, and cover destructive sibling forms and lifecycle boundaries.

Verification:
go test ./...
go test -race ./internal/recovery ./internal/control ./internal/agent
pnpm test:typecheck && pnpm test
pnpm run build
./scripts/cache-guard.sh

* refactor(auto): simplify recovery confirmation UI

Problem:
- Auto Guard confirmations exposed recovery diagnostics at equal visual priority, making simple decisions noisy.

Root cause:
- Raw recovery fields reused warning cards and appeared before the user's actual choices.

Fix:
- Show one concise action summary, recommend the safer alternative first, move optional task grants after the decisions, and flatten technical diagnostics behind disclosure.

Verification:
- pnpm test
- pnpm typecheck
- pnpm check:css
- In-app browser checks for default, expanded, and 620px layouts with no console errors.

* feat(auto): add optional recovery guidance

Problem: Auto Guard offered only a generic retry or one-shot continue, so users could not steer a safer alternative without adding another heavyweight decision.

Root cause: the simplified recovery surface removed free-text feedback entirely instead of keeping it behind progressive disclosure.

Fix: add a quiet guidance entry that expands an inline editor, routes text only through revise, clears unrelated task grants, restores keyboard focus, and localizes the flow.

Verification: pnpm test; pnpm typecheck; pnpm check:css; interactive in-app browser review of collapsed and expanded states.

* fix(auto): bind task grants to exact targets

Problem:
Task-scoped recovery grants for git pushes matched every ref on the same remote, stale grants remained attached to reused task IDs, and Desktop described a checked task grant as a one-shot continue.

Root cause:
The semantic grant key omitted the destination ref, runtime state did not retire grants when the host task scope changed, and recovery approval events exposed only a boolean instead of the host-classified scope.

Fix:
Scope reusable pushes to an explicit remote and destination, reject ambiguous or behavior-changing variants, retire grants on task-scope changes, expose a transient display scope to every frontend, and group explicit consent with the Continue action.

Verification:
go test ./...
go vet ./...
go test -race ./internal/recovery ./internal/eventwire ./internal/control ./internal/agent -count=1
pnpm test:all && pnpm build
(cd desktop && go test ./... -count=1)
./scripts/cache-guard.sh

* test(auto): cover legacy task-grant events

Problem:
Older backends do not send the optional task_grant_scope field.

Root cause:
The new exact-scope rendering tests only exercised events produced by the updated backend.

Fix:
Keep one grantable recovery fixture on the legacy wire shape and assert that Desktop renders the generic bounded-scope explanation.

Verification:
pnpm test:typecheck
pnpm exec tsx src/__tests__/decision-surface.test.tsx

* fix(auto): drain recovery writes before new session

Problem:
The macOS PR job intermittently failed while TempDir removed a session directory because /new could return with an old-session recovery snapshot still writing asynchronously.

Root cause:
ClearSession drained path-bound recovery persistence before deleting artifacts, but NewSession rotated the session path without the equivalent lifecycle barrier.

Fix:
Drain pending recovery writes for the old path before the final session snapshot and path rotation. Add a deterministic blocking persistence regression test that proves NewSession waits for the drain.

Verification:
- go test ./... -count=1
- go test -race ./internal/control -run '^(TestFreshSessionRotationsClearRecoveryState|TestNewSessionWaitsForPendingRecoveryPersistence)$' -count=10
- go test ./internal/control -run '^(TestFreshSessionRotationsClearRecoveryState|TestNewSessionWaitsForPendingRecoveryPersistence)$' -count=50
- go vet ./internal/control ./internal/recovery
- (cd desktop && go test ./... -count=1)
- ./scripts/cache-guard.sh
2026-07-22 02:52:24 +08:00
SivanColaandttmouse 03b39a6554 fix(delivery): recover readiness and isolate concurrent writers
Co-authored-by: ttmouse <[email protected]>
2026-07-16 03:51:42 +08:00
SivanCola 851c153e3f Merge remote-tracking branch 'fork/feature/mcp-settings-simplification' into codex/pr6498-readonly-boundary
# Conflicts:
#	internal/agent/agent.go
2026-07-15 14:10:03 +08:00
SivanCola d4ebb154da fix: unify strict read-only subagent execution 2026-07-15 11:26:01 +08:00
88be1a23ce fix(plan): separate workflow from permissions
Align Plan, Standard, and Goal with the shared Permissions and Sandbox path while preserving explicit phase opt-outs, fresh MCP reviews, and cache-stable provider surfaces.

Co-authored-by: HaoyueQin <[email protected]>

Co-authored-by: myipanta <[email protected]>
2026-07-15 11:18:45 +08:00
SivanCola f3029e35ed fix(delivery): align desktop marker test with exact-cut rule; trusted task text for parallel_tasks
Second review round:

- The desktop topic-title regression test built its message from a
  paraphrased delivery-runtime marker, which the byte-exact suffix cut
  correctly refuses to strip — the desktop CI job failed on it. The marker
  constant is now exported (agent.DeliveryRuntimeMarker) as the single
  source of truth; the test builds from it, and the exact-match contract
  stays intact. Its text is byte-identical since introduction, so the exact
  cut is safe for all persisted sessions.
- parallel_tasks children now pass the pristine task through
  Options.ClassifierTaskText before workspace wrapping, matching
  runSubSession. Without it the wrapped text hit the IsTask length fallback
  and a conversational child exhausted final-answer readiness instead of
  answering; regression test added (fails on the previous code).
2026-07-13 03:45:18 +08:00
Sivan e7e5bc2c0d feat: add runtime profiles and delivery capability routing
Add Economy/Balanced/Delivery runtime profiles with host-enforced delivery
gates, hybrid capability routing, a Delivery-only use_capability MCP proxy,
risk-adaptive structured review, skill requires/profiles metadata, and
capability metrics for e2ebench.
2026-07-11 16:56:03 +08:00
SivanColaandClaude Fable 5 5d88745a30 fix(agent): share the child step-budget rule with parallel_tasks and keep read_skill at the depth cap
Two sub-agent boundary inconsistencies:

1. parallel_tasks children hardcoded max_steps=20 while task and
   read_only_task children default to half the parent's budget (min 5).
   Extract TaskTool.childMaxSteps() as the single rule shared by all
   three paths, and document the default in the parallel_tasks schema,
   which previously said nothing.
2. subagentRecursiveTools listed read_skill, so a depth-capped
   sub-agent lost the ability to even read playbook text. read_skill
   renders inline skills and cannot recurse; stop stripping it at the
   depth cap. The guardian and planner surfaces keep excluding it via
   SubagentMetaTools so their provider-visible tool sets stay
   byte-identical.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-08 15:24:57 +00:00
SivanColaandClaude Fable 5 a605843642 fix(agent): unify sub-agent Options construction to stop config drift
Five hand-rolled agent.Options literals for sub-agent runs had drifted:

- boot.go skillRunner (writer-capable skill sub-agents) dropped the four
  compaction settings, silently ignoring user-configured compact ratios.
- Both skill runners dropped ResponseLanguage, so skill sub-agents did
  not follow the configured response-language preference.
- parallel_tasks children dropped both ResponseLanguage and
  ReasoningLanguage.

Remove the structural root cause instead of patching each literal:

- internal/agent/task.go: add TaskTool.subagentOptions() as the single
  construction point shared by task, read_only_task, and parallel_tasks.
- internal/boot/boot.go: add the subagentSkillOptions closure shared by
  the read-only and writer-capable skill runners.
- Pin language inheritance with
  TestParallelTasksInheritLanguagePreferencesFromContext, and document
  the deliberate loud-failure contract for a missing transcript store
  (pinned by #3586) so it is not "aligned" away again.

Cache note: only sub-agent session construction changes; parent-session
prefix bytes and tool schemas are untouched. Language blocks enter child
user turns via the existing per-run injection.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-08 14:13:09 +00:00
SivanCola c880b7ad73 Fix workspace routing for subagents and bot sessions 2026-07-04 03:36:15 +08:00
SivanCola 157809c4d7 fix(agent): harden bash sandbox and parallel tasks 2026-07-03 21:49:49 +08:00
lifu963 9d3be13f83 Fix parallel subagent cancellation aggregation
Return a cancellation-aware aggregate for parallel_tasks so completed children remain visible while unfinished work is marked cancelled or skipped instead of reported as fully completed.
2026-06-24 22:56:01 +08:00
SivanCola 2bed4482c8 fix: keep parallel orchestration cache conservative
Avoid changing the default parallel_tasks schema, built-in explore/research tool lists, and default plan approval prompt while retaining explicit orchestration runtime support.

Co-authored-by: SivanCola <[email protected]>
2026-06-19 02:40:50 +08:00
SivanCola 264f600345 fix: stabilize goal orchestration changes
Fix parallel_tasks foreground worker shutdown, reject dependency cycles, preserve /goal research flags, and persist goal state next to the session.

Co-authored-by: SivanCola <[email protected]>
2026-06-19 02:29:58 +08:00
SivanCola 951588bf29 fix: address goal enforcement review findings 2026-06-19 01:18:37 +08:00