Repository navigation
release: v1.0.0-alpha.6 - #244
Merged
Merged
Conversation
…en batch
mutateSubagentSteps rebuilt the steps[subIdx] slot object inside produce
({...subStep} spread) on every 80ms subagent delta flush. AgentProcessBlock's
stepById returns objects by identity, so StepCard's props.step changed
reference per batch, re-running every style/classList render effect and
cancelling+replaying the running animations (stepCardPulse, icon spin) —
the visible per-token "twitch" on subagent cards.
Solid-store produce mutates in place: assigning the property directly
(subStep.subagentSteps = mutate(...)) keeps the slot object's reference
stable across the whole stream. Only readers of subagentSteps itself
(live progress line, subagent conversation view) still update — fine-grained
semantics preserved.
Also: StepCard's icon classList referenced 'is-spinning', which has no CSS
definition anywhere (orphan class) — the running step icon never animated.
Switch to the already-defined-but-unused theme utility
'animate-agent-process-spin' (--animate-agent-process-spin +
agentProcessIconSpin keyframes, 2.4s linear infinite).
check:frontend green (87 tests, tsc, eslint 0 warnings, prettier, gates).
…asking, CLIXML stderr AIO self-iteration round 2 left an 8-item report (.temp/harness- report-round2.md, preserved in the tracking issue); the three P0s are all 'pwsh object output x pipe capture' pits. All claims re-verified by independent probe before implementation, and the fixes by a live pwsh behavioral matrix in the exact production spawn shape (CREATE_NO_WINDOW + pipes). - P0-1: PowerShell's default formatter commits LAZILY at runspace close; a script-level exit skips the flush, so 'run git once, then print a table' dropped the table 100% of the time (2-byte stdout, three false conclusions in the report's session). The body now runs in a scriptblock piped through Out-Default (eager render), with \True captured INSIDE the block (the pipe resets it outside). - P0-2: the old tail (\ -ne \0) exits 0 the moment any native command succeeded, masking every later cmdlet error from tool_ok and the failure-signature detectors. The new tail only propagates a NONZERO native exit code, falling through to the captured \True otherwise. - P0-3: redirected stderr made pwsh serialize error records as CLIXML (unreadable _x001B_ escapes, signature detection dead). Adds -OutputFormat Text (honored by pwsh 7, silently ignored by 5.1) plus a mechanical CLIXML decoder in decode_console_output (record boundaries to lines, tag strip, _xHHHH_ unescape, ANSI strip) for the 5.1 residual. - P1-1 (\/backtick blanket block): relaxation DECLINED - \ is a command-substitution vector regardless of intent and the scan runs before any trust decision; the rejection messages now teach the equivalent rewrites (-ExpandProperty, '+' concat, temp .ps1 via pwsh -File) instead. - P2-3: the finish_reason=length continuation instruction now carries the truncated reply's last ~200 chars as an anchor (multi-section output no longer loses the thread on resume). - P2-5: the report itself is filed as an issue (the sanctioned home for one-off artifacts per docs-style.md). - P1-2 / P2-1 / P2-2 / P2-4: declined with rationale in the PR description (environment facts and design tradeoffs). Tests: shell_tools 33 (+3: CLIXML decode, tail structure, live pwsh matrix - all three cases fail under the old tail); round_artifacts +1 (anchor, four branches); full suite 464 green; clippy -D warnings clean.
fix(chat): stop subagent step-card animation restart per streamed token batch
Harness round 2's additions (CLIXML decoder + behavioral tests) pushed shell_tools.rs to 2951 lines, over the 2770 file-size ratchet (the gate failure CI caught on this PR; the ratchet itself is untouched). Mechanical move, zero behavior change: the self-contained encode/decode pair around agent shell commands now lives in utils/shell_codec.rs - - decode: decode_console_output (+ ANSI code page + CLIXML unwrap) - encode: START_PROCESS_HIDDEN_SHIM, pwsh_script, rewrite_cmd_start_hidden, cmd_utf8_prelude, pwsh_encoded shell_tools re-exports the historical names (rewrite_cmd_start_hidden test-only, hence cfg(all(windows, test))); all tests stay in shell_tools untouched. Full verify green: clippy -D warnings, 464 Rust tests, check:frontend (incl. the file-size gate) 87 FE tests.
fix(harness): pwsh object-output P0s - formatter loss on exit, rc-0 masking, CLIXML stderr
…rip + real effort ladder
Real-world report: DeepSeek V4.1 Flash spends tens of minutes thinking,
re-reads dozens of files, never acts - the thinking:action ratio explodes.
Diagnosis: model trait (thinking ON at HIGH effort by default, documented)
AMPLIFIED by two genuine harness defects, both fixed here.
Defect 1 (the amplifier): reasoning_content was never round-tripped -
violating DeepSeek's documented tool-call contract. In tool-carrying
conversations the field is the model's CROSS-ROUND WORKING MEMORY
('let the model continue its previous thinking'); AIO dropped it on both
paths (in-turn append_assistant_message built role/content/tool_calls
only; history finish_message_for_api never inserted it though the DB
stores it). Every round started thinking from scratch and re-read files
to re-establish understanding - the re-read loop behind the report.
- New deepseek provider plugin (claims api.deepseek.com; URL/auth/models
delegate to the fallback), with trait additions:
- roundtrip_reasoning_content (default false - OpenAI's strict schema
rejects the unknown field, so the contract must stay provider-scoped)
- adjust_chat_body (default no-op), applied unconditionally in
stream_one_round after generic body assembly
- In-turn: append_assistant_message attaches the round's reasoning as
reasoning_content when flagged (empty stays absent); main loop computes
the flag once per turn, subagent loops wired identically
- History: finish_message_for_api inserts it (assistant role, non-empty,
gated by the same flag); the FE now passes message.reasoning through
buildApiMessages; chat-mode (no tools) stays unflagged per the contract
(server ignores the field without tools)
Defect 2: the reasoning slider was a no-op for DeepSeek. Thinking is ON
at HIGH effort by default and the only documented off-switch is
{'thinking':{'type':'disabled'}} - which AIO never sent. The deepseek
adjust_chat_body override now: Off -> thinking disabled (the slider's
'off' is finally real; BEHAVIOR CHANGE: DeepSeek users at Off no longer
get chain-of-thought output - move the slider to Low+ when thinking is
wanted); Medium -> Low (DeepSeek's real ladder is low/high/max and
upstream collapses medium to high - Low keeps three settings
distinguishable); Low/High pass through. Subagent rounds (which never
inherit the slider) default to thinking disabled - executor role.
Tests: provider +4 (host claim/guards, effort ladder mapping, URL
delegation), round_artifacts +1 (round-trip three branches), messages +1
(history round-trip role/flag/empty gating); full suite 469 green;
npm run verify fully green (87 FE tests, gates rgba=173 any=77 held).
…trip fix(provider): DeepSeek thinking/action imbalance - reasoning round-trip + real effort ladder
…d step reveal + O(1) step lookup
Report: switching to the topic where AIO worked on AIO itself (9 rounds /
18 messages) loads visibly slower than other topics, and expanding its
hundreds of intermediate steps collapses the frame rate. Measured the real
DB: that topic carries 16.53MB of agent_steps_json / ~1674 step cards (the
worst single message: 588 steps, 381 tool calls, 8.01MB). Three stacked
costs, all fixed:
1. Collapsed historical rounds still mounted their cards (the main switch
cost). max-height:0 hides without unmounting, so a topic switch built up
to 100 cards per past round (~469 cards across this topic's five big
rounds), each with its own effects, signals and 920ms entrance timer,
plus one linear stepById scan per card. Now the body is gated by
<Show when={isExpanded()}>: a collapsed round mounts ZERO cards (Solid's
false branch builds no DOM/components/effects) and the id-sync effect
short-circuits while collapsed, resolving lazily on expand.
2. 'Show earlier' mounted every remaining card in one frame. Replaced the
showAllSteps boolean with paged reveal: each click adds another
STEP_WINDOW (100) page and the button label counts down the remainder.
3. stepById ran timelineSteps().find(...) per card, and timelineSteps()
sliced the whole array on every call - ~345k element copies for a full
reveal. Now a memoized timeline + id->step Map make it O(n) once and
O(1) per card.
Supporting: content-visibility:auto + contain-intrinsic-size on the step
card (offscreen cards skip layout/paint, the MessageBubble pattern);
paged-in historical steps are pre-marked as animated (same contract as
ChatInterface's load-earlier) so expanding does not fire a hundred
simultaneous entrance animations.
Window arithmetic extracted to utils/stepWindow.ts with 6 unit tests
(active pass-through, tail-window bounds, page increments, short/empty
lists, negative reveal, countdown). Untouched: the active round's streaming
queue/auto-follow, DiffView (measured: 1 changed file - not a bottleneck),
and the legacy no-agentSteps ToolCallBubble fallback.
Verified: npm run verify green (93 FE tests incl. 6 new, gates, lint, tsc,
build; Rust suite green). Real-device frame timing still needs the installed
build - the mount arithmetic here is 469 -> 0 cards on switch and 588 -> 100
per reveal click.
perf(chat): long-process topic switch/expand jank - lazy mount + paged step reveal + O(1) lookup
Promotes the four post-alpha.5 sections into the v1.0.0-alpha.6 release block (chronological: subagent step-card twitch #239, pwsh object-output P0s #241, DeepSeek reasoning round-trip #242, long-process step-window jank #243) and merges the duplicate '## Unreleased' heading the self-iteration commit introduced at the file top into the single bracketed section that carries the historical round content. Verification: docs link check + prettier clean; version bumped in package.json / tauri.conf.json / Cargo.toml / Cargo.lock.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release branch for v1.0.0-alpha.6 — the "field-report-driven root fixes" release.
Four real-usage reports, each traced to its root cause with measured evidence:
producerebuilt the step slot object per 80 ms stream batch, soStepCard'sprops.stepidentity changed and every render effect (including the animation shorthand) re-ran — replayed pulse/spin per token. Fixed with in-place property assignment; the orphanis-spinningclass replaced by the theme's realanimate-agent-process-spinutility.exitskipped PowerShell's lazy format flush (table output lost whenever a native command had run — 3 false conclusions in the reporting session);$LASTEXITCODE=0masked later cmdlet errors as success; redirected stderr arrived as CLIXML. Fixed with theOut-Defaultscriptblock tail, non-zero-only exit propagation,-OutputFormat Text+ a mechanical CLIXML decoder — verified by a live pwsh behavioural matrix in the production spawn shape.reasoning_contentwas never round-tripped (violating DeepSeek's documented tool-call contract — the model's cross-round working memory), forcing every round to re-think and re-read files; and the reasoning slider was a no-op because thinking defaults ON at high effort. Newdeepseekprovider plugin: round-trip both paths + a real effort ladder (off→thinking: disabled,medium→low).agent_steps_json/ ~1674 step cards (worst message: 588 steps / 381 tool calls / 8.01 MB). Collapsed historical rounds were mounting up to 100 cards each (max-height: 0hides but does not unmount), "show earlier" mounted all 588 in one frame, and the step lookup was O(n²). Now: lazy mount gate (collapsed rounds mount 0 cards), paged reveal (100 per click), memoized O(1) lookup,content-visibilityon cards, and paged-in history pre-marked as animated.Changes in this PR
1.0.0-alpha.6v1.0.0-alpha.6block (chronological order), and the duplicate## Unreleasedheading that the self-iteration commit introduced at the file top merged back into the single bracketed sectionVerification
npm run verifygreen (#239: 87 FE tests;#241: 460 Rust + gates;#242: 469 Rust + full verify;#243: 93 FE tests + full verify)