Commit Graph
8 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 911d88457f fix(agent): preserve background fleet progress lifecycle
Problem:
- Background fleet group IDs were namespaced twice and child progress could stop after the job-ID handoff.

Root cause:
- The group merger emitted through a nested sub-sink and Execute closed it even after handing lifecycle ownership to the background job.

Fix:
- Emit already-namespaced group and child progress through the raw call sink.
- Transfer merger close ownership only for background jobs while preserving foreground cleanup.
- Add deterministic background lifecycle and stable-ID coverage.

Verification:
- go test ./...
- go test -race ./internal/agent ./internal/event ./internal/cli -count=1
- go test ./... (desktop)
- pnpm test:typecheck && pnpm test && pnpm build (desktop/frontend)
- ./scripts/cache-guard.sh
- Remote zero-diff gate
2026-08-05 11:58:46 +08:00
SivanCola c17a09c671 fix: explicit group lifecycle terminals for parallel_tasks/fleet
The backend now emits an explicit lifecycle for group cards: running when
children start and exactly one terminal (completed/cancelled/failed,
including validation failures and zero-child cancellation) after the group
settles, keyed by the group call ID. Frontends no longer infer group
completion from the children observed so far — a background group's children
dispatch asynchronously, so a job-id result arriving first or a fast first
child finishing before later children dispatch could previously settle the
group permanently while children were still running. The reducer now settles
group cards only from their own terminal event; the child-inference helpers
are removed. Adds reverse-order, zero-child cancellation, group failure, and
group lifecycle integration tests.
2026-08-05 11:10:03 +08:00
SivanCola 9ef543ee05 agent: add bounded subagent progress forwarding
Forward each sub-agent run's Reasoning/Text/Notice/Retrying as reserved
ToolProgress channel events (reasonix.subagent.status/reasoning/text/notice)
so local frontends can show live per-child progress without the child's
bodies entering the parent transcript or provider context. A shared merger
per parent task group paces previews: one pending slot per (child, channel),
a 250ms merge window, a 32 event/sec group budget round-robined across
children, and an 8 KiB per-child pending buffer with UTF-8-safe tails.
RunProfileSpec emits exactly one terminal status (completed/cancelled/failed)
after synchronously flushing pending previews; late events are ignored.
Background runs emit queued at registration and running on slot acquisition;
parallel_tasks and fleet share one merger per call via context. Real
sub-agent tool progress is namespaced and forwarded like ToolDispatch.
2026-08-05 09:31:12 +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 cf9ee2823f fix(rewind): close transaction recovery gaps
Problem:
Local rewind could leave split state around crash and compensation windows, expose unsafe legacy file restores, and lose undo metadata in Desktop paths.

Root cause:
Checkpoint persistence and compensation did not model every intermediate state, queued writers were registered too late, and UI capability propagation trusted incomplete ownership metadata.

Fix:
Make checkpoint expiration and truncation failure-aware, verify blob identities, recover rename intermediates, retain pending failed compensation, normalize paths, require final ownership fingerprints, reserve queued background writers, and preserve Desktop transaction IDs for undo.

Verification:
go test ./...
go test -race ./internal/checkpoint ./internal/control ./internal/agent
cd desktop && go test focused rewind/workspace suites
cd desktop/frontend && pnpm build
./scripts/cache-guard.sh
go vet and golangci-lint for root and desktop modules
2026-08-04 03:17:52 +08:00
SivanCola d25f7833c3 fix: make local rewind recovery atomic
Problem: Combined rewind recovery could leave conversation and files split after a crash, background writers could cross the preview/commit window, and ancestor symlinks could redirect checkpoint I/O outside the workspace.

Root cause: Startup recovery had no conversation applier, writer registration was not coupled to the mutation barrier, compatibility rewind bypassed the transaction engine, and filesystem operations relied on lexical containment checks.

Fix: Defer combined recovery until resume, restore conversation and checkpoints before file compensation, route legacy rewind through transactions, hold writer barriers across direct and fleet background agents, and use no-follow workspace-relative filesystem operations.

Verification: go test ./...; go test -race ./internal/checkpoint ./internal/control ./internal/agent; desktop go test ./...; Windows checkpoint cross-compile; frontend rewind contract test; cache guard; go vet focused packages.
2026-08-04 01:43:25 +08:00
SivanCola 2335d0df9e Add profile-aware parallel subagent fleets / 新增可配置并行子智能体 Fleet (#6636)
* feat(subagents): add profile-aware parallel fleets

Problem:
Custom subagent profiles could only be run serially through skill execution, making multi-document workloads unnecessarily slow and leaving concurrent writers without one session-wide safety boundary.

Root cause:
Task execution had no runtime profile selector or shared fleet scheduler, and write coordination was split across entry points without atomic parent reservations or enforceable path claims.

Fix:
- add profile-aware task and fleet execution with session-wide total/writer concurrency limits
- normalize and enforce write path claims, including sandboxed Bash roots and parent write reservations
- make background tasks queue asynchronously and keep parallel_tasks on the shared scheduler
- expose concurrency and read-only profile controls in Desktop and document the contracts

Verification:
- go test ./...
- cd desktop && go test ./...
- go test -race ./internal/agent ./internal/boot ./internal/config ./internal/skill
- cd desktop/frontend && pnpm typecheck && pnpm test:typecheck && pnpm test
- ./scripts/cache-guard.sh

* Tighten subagent write and tool boundaries

Problem:
Path-bound Bash retained sandbox cache and temporary-directory write lanes, wildcard tool allowlists could reject valid narrowed calls, and stale scheduler code blocked lint.

Root cause:
Bash root rebinding did not enable minimal-write confinement, tool lists were intersected before live-registry pattern expansion, and obsolete control flow remained after scheduler unification.

Fix:
Restrict rebound Bash to claim roots, expand both allowlists before intersection, remove stale scheduler parameters and helpers, and add focused execution regressions.

Verification:
- golangci-lint v2.12.2: 0 issues
- go test ./...
- go test -race ./internal/agent ./internal/tool/builtin ./internal/boot ./internal/config ./internal/skill
- cd desktop && go test ./...
- ./scripts/cache-guard.sh

* Preserve fleet cancellation results

Problem:
Cancelled fleet writers could be reported as skipped after they had started, and preflight conflicts could cite the wrong task numbers when read-only items were interleaved.

Root cause:
The cancellation path stopped draining terminal worker results after waiting, while write claims were compacted into a writer-only slice before indexed validation.

Fix:
Drain every started worker result after cancellation, reserve skipped for tasks that never started, and retain one claim slot per original fleet item. Add deterministic cancellation and mixed-task indexing regressions.

Verification:
- go test -race ./internal/agent -run '^TestFleet' -count=1
- go test ./internal/agent
- go test ./...
- golangci-lint v2.12.2: 0 issues
- ./scripts/cache-guard.sh
- git diff --check
2026-07-18 22:18:44 +08:00