Skip to content

feat(desktop): unify session experience and stabilize transcript / 统一会话体验并稳定 Transcript 滚动 - #9777

Open
SivanCola wants to merge 56 commits into
esengine:main-v2from
SivanCola:feature/session-experience-transcript-stability
Open

feat(desktop): unify session experience and stabilize transcript / 统一会话体验并稳定 Transcript 滚动#9777
SivanCola wants to merge 56 commits into
esengine:main-v2from
SivanCola:feature/session-experience-transcript-stability

Conversation

@SivanCola

@SivanCola SivanCola commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Replace the three overlapping work-process settings with one two-state Session experience preference: Standard or Deep.
  • Remove react-virtuoso and its restore, compensation, footer handoff, index-translation, and size-tree control paths.
  • Replace the Transcript scroll core with Reasonix-owned TimelineProjection, TranscriptKernel, and TranscriptViewportWriter.
  • Render up to 100 completed turns in full DOM; use @tanstack/react-virtual only as a range/measurement adapter above that threshold, with active and resident-tail turns kept in ordinary DOM.

User-visible behavior

  • Standard shows work while a task runs and collapses completed process details by default.
  • Deep keeps the complete process expanded.
  • Message-level overrides remain available and survive rerenders/window recycling for the current session.
  • Warnings, approvals, delivery cards, and user-action surfaces remain reachable in either mode.
  • Settings now expose one keyboard-accessible segmented control with aligned English, Simplified Chinese, and Traditional Chinese copy and search metadata.

Transcript architecture

The runtime path is now:

TranscriptStore / ControllerLiveStore
  -> TimelineProjection
  -> TranscriptKernel
  -> Full DOM / TanStack Window Adapter
  -> TranscriptViewportWriter
  -> native scroll container
  • Stable backend-derived turn/block identities replace virtual row indexes.
  • Native scrollTop, scrollHeight, and clientHeight are the geometry source of truth.
  • Generation fences invalidate stale session callbacks, measurements, timers, and commands.
  • Every scroll transaction reaches committed, cancelled, or expired.
  • User gestures and selection outrank jump/restore/prepend/display/composer transactions; tail-follow has the lowest priority.
  • All structural writes use behavior: "auto"; a static CI gate enforces the single writer.
  • Streaming turns remain outside cold virtual history. The latest two completed turns and active turn form the resident tail.
  • Repeated invalid geometry or missing visible blocks degrades the current generation to full DOM without reviving a second implementation stack.
  • Runtime diagnostics record numeric/enum ownership and outcomes only, never transcript content.

Compatibility and migration

  • New canonical field: [desktop] session_experience = "standard" | "deep".
  • Missing or invalid canonical values resolve to standard.
  • New UI/rendering code does not hydrate from legacy localStorage.
  • Deprecated config fields, setters, events, and localStorage mirrors remain for one release cycle.
  • Legacy expanded calls map to deep; other legacy combinations map to standard.
  • Canonical writes mirror standard -> display=standard, reasoning=auto and deep -> display=standard, reasoning=expanded for rollback compatibility.
  • Save success and failure both reload the authoritative Settings snapshot.

Review closure and acceptance (5da8657)

Three additive review slices, with no history rewrite:

  • 9cc1f4ef7: async source/navigation ownership, terminal transactions and deterministic races.
  • ff559421b: atomic covered window geometry, unified full/window/safety presentation, 40-completed-block budget, resident retirement and committed command lifetimes.
  • 5da865779: scope restoration and acceptance/architecture documentation.

Source paging survives a cancelled jump, but obsolete generation/request identities cannot position or mutate another session. All geometry uses cancellable Kernel frames and one health/correction entry. Before-paint safety retains keyed native hosts and trusted prefix coordinates, mounts only loaded pages, and locks after two faults until replacement. Stable commands no longer retain historical selection-row contexts.

Current local cumulative verification passed:

  • pnpm build with existing single-writer, TypeScript and bundle budgets
  • pnpm test:transcript
  • pnpm test:transcript-browser (selection, scroll/safety, composer)
  • pnpm test:transcript-reader-browser (Chromium + WebKit)
  • pnpm test:all
  • config go test ./internal/config and desktop go test .
  • go run ./tools/repolint and git diff --check

The latest 10,000-turn archived/lazy performance run measured projection 67.49ms and immutable prefix/range commit 0.83ms, with 40 completed blocks mounted. Safety replay uses 120 loaded of 1,000 total turns, not fully loaded synthetic bodies; it checks real native selection/focus, reader/tail ≤4px, zero held-gesture writes, full-mode generation locking and ≤1s interactivity. No budget is raised.

Remaining qualification: collected whole-App heap still grows during repeated session switching, including the no-fault control. Heap snapshots showed the fixed Transcript selection resolver count stays at 11 (previously +1,960); remaining retainers include App-shell callback contexts and compiled code. The main-v2 memory baseline is not established. This is explicitly documented, not labeled leak-free or hidden behind a byte threshold. Final-head native/Go/race/lint/CodeQL checks have now passed on this exact SHA; earlier heads were not used as evidence. Not a merge-ready signoff.

Full evidence and limits: Transcript acceptance.

Final-head CI evidence

Verified head: 5da8657791a8df68f209b0135313f9915fd82659. All applicable checks passed; the unrelated site job was conditionally skipped.

Qualification Final-head evidence
Linux WebKitGTK 4.0, frontend replays, desktop Go/race desktop job
Linux WebKitGTK 4.1 native recovery 4.1 job
Isolated macOS WKWebView sustained reading WKWebView job
Windows Chromium, real WebView2 scrolling/selection, Wails startup and Go Windows desktop job
Root Go tests/race/lint/coverage CI run
Go, TypeScript/JavaScript and Actions CodeQL CodeQL run

Native selection tests executed successfully. Their upload step is failure-only and was skipped on success; this is log/check evidence, not a claim that a successful-run attachment exists. PR checks do not replace the full main-v2 release sweep. Remaining App-shell heap attribution is still open, so green CI is not a merge-ready signoff.

Scope and related PRs

  • Restored the independent API-key await/disabled-input behavior introduced by 410876875 to current main-v2. No Provider production redesign; necessary merged model-capability fixture compatibility remains.
  • Stabilize transcript scrolling and Markdown surfaces / 稳定 transcript 滚动与 Markdown 展示 #9754: stable prepend/jump/native-scroll ownership goals are covered by the new Kernel, not its Virtuoso controllers or approximately 16px alignment. Shared empty-fence Markdown suppression already exists and remains independently useful.
  • fix(desktop): stabilize long transcript scrolling #9673: long-history/reader/tail goals are covered; its 1,000-row cutoff and Virtuoso branch are not adopted. The new threshold is 100 completed turns; natural-height pending Markdown remains a shared-pipeline behavior.
  • Neither related PR is closed, merged or otherwise modified.

Release and rollback

  • The new kernel is the only production Transcript path; there is no Virtuoso feature flag.
  • Rollback is a revert of this PR. Compatibility mirrors allow the previous release to read settings after rollback.
  • Removal of deprecated fields and setters is deferred until the next complete release cycle.

Documentation-impact: updated - session experience behavior and the Transcript kernel state machine, invariants, safety mode, and compatibility-removal condition are documented.
Cache-impact: low - standing desktop contributor instructions and config declarations changed, but provider-visible prompts, model-input bytes, memory serialization, tool payloads, and cache keys are unchanged.
Cache-guard: internal/config/session_experience_test.go plus scripts/check-cache-impact.sh; verified the change is limited to desktop presentation/config compatibility and does not alter provider request construction.
System-prompt-review: reviewed by the PR author - desktop/AGENTS.md documents engineering invariants only, and internal/config/config.go adds a desktop presentation preference without changing system prompts.

SivanCola and others added 2 commits June 1, 2026 23:35
Problem: The desktop exposed three overlapping work-process preferences, while switching disclosure state could invalidate transcript geometry and compete with user scrolling.

Root cause: Reasoning, process-fold, and transcript layout paths interpreted independent legacy state; display changes were not represented as one canonical preference transaction.

Fix: Add the standard/deep session experience contract with compatibility migration, unify reasoning/tool/process rendering, preserve manual row overrides, and route display changes through the transcript arbiter's anchor-aware single-writer path. Add deterministic preference, settings, compatibility, and bundle-budget coverage.

Verification: pnpm --dir desktop/frontend typecheck; pnpm --dir desktop/frontend test:typecheck; pnpm --dir desktop/frontend test:transcript; pnpm --dir desktop/frontend check:scroll-writer; pnpm --dir desktop/frontend build; go test ./internal/config; (cd desktop && go test ./...).
@SivanCola
SivanCola requested a review from esengine as a code owner September 4, 2026 06:02
@github-actions github-actions Bot added desktop Wails desktop app (desktop/**) config Configuration & setup (internal/config) v2 Go rewrite (1.x) — main-v2 branch, active development labels Sep 4, 2026
# Conflicts:
#	desktop/frontend/scripts/check-bundle-budget.mjs
Problem:

Sustained WKWebView and WebView2 scrolling could outrun the mounted window or outlive the wheel-only gesture timeout. The resulting delayed range commit allowed a reader restore to reverse native travel, while frame-count browser assertions observed transient geometry instead of the required logical state.

Root cause:

The viewport adapter exposed too little bounded runway for native scroll delivery, and gesture ownership was leased from wheel dispatch rather than renewed by the authoritative native scroll stream. Test setup and settlement were also tied to locator timing and fixed paint counts.

Fix:

Renew the native gesture lease through the final scroll event, provide a 12-block TanStack runway under the existing 40-block cap, and make native diagnostics measure writes around delivered wheel input. Browser fixtures now activate setup transitions atomically and await tail or logical-anchor convergence.

Verification:

Passed pnpm build, transcript unit/browser/reader suites, frontend test:all, Desktop Go test and race, go vet, golangci-lint, and repolint.
Problem: native WebViews can deliver a TanStack range or a measurement notification one paint behind the authoritative scroll position, leaving a blank frame or moving a reader anchor after native input.

Root cause: the window adapter painted every asynchronous candidate and gesture completion recaptured geometry even when no native scroll had occurred.

Fix: introduce a covered-range commit protocol that retains a valid painted range, reconstructs large native jumps from the prefix-size ledger, and lets only native scroll events update gesture anchors. Record the range source in content-free native diagnostics and document the invariant.

Verification: pnpm test:transcript; pnpm build; pnpm test:transcript-browser; pnpm test:transcript-reader-browser; pnpm test:all; go test ./...; go test -race ./...; make lint.
Problem: main-v2 advanced with model-picker interaction fixes while this PR already replaced the same legacy picker and settings paths with generation-fenced components.

Resolution: preserve the PR's AnchoredPopover and last-request-wins ModelPicker ownership, incorporate the upstream KeyField save transaction and flex rule, and remove the now-dead legacy ModelSelect path instead of reintroducing two picker implementations.

Verification: model-switcher-refresh, settings-refresh-snapshot, and provider-access-card tests; pnpm build; pnpm test:all; transcript browser and reader-browser replays.
Integrate current subagent outcome recovery and reasoning replay work while preserving the TranscriptKernel architecture and tightened bundle ratchets.

Normalize subagent terminal outcomes once at the tool-result boundary, lazy-load expanded subagent presentation and CSS, and keep asynchronous feature styling out of the transcript geometry path.

Verified with pnpm build, pnpm test:all, transcript browser and reader replays, go test ./..., go test -race ./..., and make lint.
Make the window adapter the sole owner of DOM-to-prefix-ledger measurement publication. Native input now holds geometry commits until its ownership lease ends; changed item sizes then enter one logical-anchor transaction and settle as a batch. This prevents asynchronous ResizeObserver updates from moving mounted blocks behind TranscriptKernel on WebKit and WebView2.\n\nDocument and test the measurement commit invariant without adding platform-specific compensation or relaxing existing gates.
Problem: WebKit and WebView2 could move or blank the reader viewport while a windowed transcript published several measured block sizes one at a time. Native gestures also depended on hook-owned global timers that were outside the kernel generation fence.

Root cause: each resizeItem call exposed an intermediate TanStack prefix tree, so browser-native scroll anchoring could react between item updates even though the application single-writer accepted no scroll command.

Fix: make Reasonix own an immutable block-keyed measurement ledger, invalidate TanStack once per complete batch, move gesture leases and paint callbacks behind the injectable kernel clock, and make safe mode count genuinely consecutive geometry anomalies.

Verification: pnpm test:transcript; pnpm test:transcript-browser; pnpm test:transcript-reader-browser; pnpm test:all; pnpm build; go test .; go test -race .; go run ./tools/repolint
Problem: native WKWebView could still reverse by 5849px after history prepend while the application writer accepted zero reader writes.

Root cause: the resident-tail boundary retired one in-flow block at a time without first recording its rendered height. TanStack replaced those blocks with estimates, so a sequence of resident-to-cold transfers changed the native scroll extent during sustained reading.

Fix: scan the contiguous eligible resident prefix, exclude anchor/focus/selection owners, publish every exact DOM height in one immutable ledger snapshot, then move the resident boundary once.

Verification: pnpm test:transcript; pnpm test:transcript-browser; pnpm test:transcript-reader-browser; pnpm build; go run ./tools/repolint
Problem: Native transcript readers could shift by hundreds of pixels when delayed block measurements were published around an unchanged scrollTop.

Root cause: The window adapter derived its publication boundary from DOM that might already include lazy-content growth, and expressed TanStack scrollMargin relative to an offset parent rather than the native scroller.

Fix: Resolve an anchor-safe boundary from the later of the kernel anchor and the committed prefix range, express scrollMargin in native coordinates, keep earlier measurements staged, and extend the deterministic reader replay diagnostics and contracts.

Verification: pnpm test:transcript; pnpm build; 12 repeated Chromium and WebKit reader transactions; pnpm test:transcript-browser; go run ./tools/repolint.
Problem: The native WKWebView smoke still observed a 197px reader displacement even though the writer accepted no scroll commands.

Root cause: A prefix-range anchor can precede the actually painted block when estimates are low, while a DOM-only anchor can move backward when lazy content grows into view. Neither source is independently authoritative.

Fix: Publish cold measurements only at or after the latest identity reported by the kernel, committed prefix range, and mounted DOM. Extend native diagnostics with virtual item indexes and document the three-source invariant.

Verification: pnpm test:transcript; pnpm build; 12 repeated Chromium and WebKit reader transactions; pnpm test:transcript-browser; go run ./tools/repolint.
Problem: Native WKWebView showed sequential visible-block reflow without any scroll writer command.

Root cause: Protecting only the first reader anchor still allowed size publication for later blocks already painted in the same viewport, moving their successors.

Fix: Require both committed prefix geometry and mounted DOM to identify a post-viewport overscan boundary; keep every before/visible measurement staged and add a deterministic whole-viewport regression.

Verification: pnpm test:transcript; pnpm build; 12 repeated Chromium/WebKit reader transactions; pnpm test:transcript-browser; go run ./tools/repolint.
Problem: Native WKWebView still reflowed visible blocks and exposed a blank frame even though measurement publication was restricted to post-viewport items.

Root cause: TanStack measure() cleared its keyed size cache and rebuilt the entire prefix, reapplying older off-screen deltas ahead of the reader.

Fix: Atomically publish the safe Reasonix suffix and transfer only those keyed sizes to TanStack in one browser task. Forbid global measurement invalidation and cover simultaneous painted/post-viewport churn.

Verification: pnpm test:transcript; pnpm lint:hooks; pnpm typecheck; pnpm build; 12 repeated Chromium/WebKit reader transactions; pnpm test:transcript-browser; go run ./tools/repolint.
Problem: Sustained WKWebView wheel input could move a previously safe overscan boundary into view before React committed its size publication.

Root cause: The measurement predicate used a tear-free snapshot, but that snapshot cannot predict compositor motion that continues during the same native gesture.

Fix: Give native gesture ownership absolute priority over cold measurement publication. Stage every size until ownership ends, then publish only the suffix beyond the final native viewport.

Verification: pnpm test:transcript; pnpm build; 12 repeated Chromium/WebKit reader transactions; go run ./tools/repolint.
Problem: With reader geometry frozen correctly, sustained WKWebView scrolling could still outrun the symmetric 30-block mounted range for one or two frames.

Root cause: Half of the bounded overscan budget sat behind the current motion, while the asynchronous native compositor needed more forward coverage before React's next range commit.

Fix: Introduce one directional range extractor shared by normal candidates and synchronous reconstruction. Preserve a four-block reversal cushion and spend the remaining fixed budget ahead without relaxing the 40-block gate.

Verification: pnpm test:transcript; pnpm build; 12 repeated Chromium/WebKit reader transactions; pnpm test:transcript-browser; go run ./tools/repolint.
Problem: Long coalesced wheel streams could exhaust the frozen estimated window and expose a blank viewport, while publishing measurements too close to the compositor caused visible reflow.

Root cause: Measurement publication was either frozen for the whole native lease or resumed at the painted viewport edge, with no owner-level model for bounded compositor travel.

Fix: Make the lazy transcript measurement ledger own a generation-reset publication frontier. Pixel wheel input retains the largest step plus one viewport; touch, selection, keyboard, thumb, and non-pixel input remain fully staged. Add sustained Chromium/WebKit coverage without increasing startup or bundle budgets.

Verification: pnpm test:transcript; pnpm test:transcript-browser; pnpm test:transcript-reader-browser; pnpm test:all; pnpm build; go run ./tools/repolint
…lity

Sync PR esengine#9777 with main-v2 at cfac404 after the host-notice i18n migration landed. The merge keeps the session-experience compatibility layer and Transcript kernel changes intact.

Verification: go test ./...; cd desktop && go test ./...; cd desktop && go test -race .; go run ./tools/repolint
Problem: the native Windows gate used a fixed wheel-pixel budget to decide when a streamed, platform-measured transcript should be at the tail. The final ledger can be taller than that budget even when every native event is accepted without blank or reverse frames.

Root cause: the host treated an implementation-dependent scroll delta sum as a semantic tail signal. This diverged from the native geometry contract and from the adaptive WKWebView gate.

Fix: keep the bounded sustained reader traversal, then drive bounded native wheel batches from explicit scrollHeight/scrollTop/clientHeight reports. Finish only after two stable <=4px tail-follow observations, while retaining a hard event ceiling so a real regression still fails.

Verification: pnpm test:all; pnpm test:transcript-reader-browser; GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go test -tags reasonix_transcript_smoke ./cmd/transcript-native-smoke; go run ./tools/repolint.
Problem: the hosted Linux WebKit reader gate discarded every kernel and viewport observation when its unchanged 5s anchor condition timed out, leaving only an opaque Playwright stack trace.

Fix: preserve the same deadline and <=4px requirement, but complete the bounded probe path and attach the last 40 content-free kernel diagnostics plus anchor/window geometry to the assertion failure. Successful paths clear both probe hooks.

Verification: pnpm test:transcript-reader-browser; node --check desktop/frontend/bench/transcript-reader-transaction.mjs; go run ./tools/repolint.
Problem: repeated reader-measurement iterations accumulated upward wheel travel until they crossed the history boundary. A correct history-prepend transaction could then replace the measurement anchor, so one test conflated two independent state machines.

Fix: establish every measurement iteration from the kernel-owned physical tail before transferring ownership with native wheel input. The measurement race remains reader-owned and bounded away from pagination; prepend keeps its dedicated integration coverage.

Verification: REASONIX_TRANSCRIPT_READER_ITERATIONS=30 pnpm test:transcript-reader-browser; go run ./tools/repolint.
Problem: Linux WebKit can deliver Playwright/native mouse gestures without the PointerEvent path, allowing staged transcript measurements to publish while the user still owns the viewport.\n\nRoot cause: kernel and immutable measurement-ledger ownership began only from pointerdown, while the host's mouse stream emitted mousedown/mouseup.\n\nFix: route pointer and compatibility mouse starts through the same deduplicated kernel state, mirror the unbounded measurement boundary, and terminate through one shared event set.\n\nVerification: transcript unit matrix, 30x Chromium/WebKit reader replay, pnpm test:all, pnpm build with the unchanged bundle budget, and repolint.
Problem: WebKitGTK could publish prefix measurements during a held mouse gesture, while WKWebView could move farther than the largest individual wheel delta before React committed the viewport frontier.

Root cause: the measurement ledger treated the React gesture snapshot as the owner of unbounded native input and modeled wheel runway as one maximum step instead of the unsettled compositor journey.

Fix: let native unbounded leases freeze publication immediately, accumulate pixel-wheel travel behind one viewport runway, and add an independent mouseup release for native input React does not claim.

Verification: focused ledger and viewport contracts, 30x Chromium and WebKit reader replays, pnpm test:all including 10,000-turn performance, pnpm build with unchanged bundle budgets, and repolint.
…lity

Integrate the latest model-level vision capability and agent-contract changes without rewriting the PR history.

Resolve the shared bundle and repolint ratchets against the smaller TranscriptKernel startup graph. Migrate the stale provider frontend fixtures from mutable VisionModels and FetchProviderModels to the authoritative read-only model capability catalog.

Verification: go test ./..., all 239 frontend suites, remote frontend suites, 10,000-turn performance, Chromium/WebKit transcript browser replays, production build budgets, and repolint.
Problem: Linux WebKit could move the held reader anchor even though native input had already claimed the measurement ledger and no programmatic scroll write was accepted.

Root cause: TranscriptWindow computed the publication runway during render. A native capture event could update the authoritative lease after that render, leaving the subsequent layout-effect commit with a stale safe boundary.

Fix: read the native lease and derive both prefix and DOM publication frontiers inside the layout effect immediately before staged measurements can enter TanStack. Keep failure diagnostics tied to the same held-anchor snapshot.

Verification: focused viewport contracts, 30x Chromium and WebKit reader transactions, production build with unchanged budgets, single-writer gate, and repolint.
The durable steer reconciliation test observed TurnDone but left the Controller autosave goroutine alive. On Linux, t.TempDir cleanup could race a final autosave and fail with directory not empty. Close the owning Controller and join its autosave group before temporary-directory cleanup.
WebKit can deliver one wheel delta across several compositor frames. Establish the reader transaction baseline only after native viewport geometry is stable so the remaining user-owned wheel movement cannot be mistaken for a product-induced anchor drift. The boundary is rAF-driven and does not depend on sleeps.
@github-actions github-actions Bot added the agent Core agent loop (internal/agent, internal/control) label Sep 4, 2026
Keep the sustained native-wheel workload as the stress phase, then probe the shared Transcript tail contract between bounded native-input batches. WebKitGTK now finishes only after two stable native tail observations or an explicit bounded exhaustion, matching the geometry-driven macOS and Windows hosts. Delayed probe and finish sources are owned by host cleanup.
…lity

# Conflicts:
#	desktop/frontend/src/__tests__/provider-editor-model-picker.test.tsx
#	desktop/frontend/src/__tests__/settings-refresh-snapshot.test.tsx
Problem: unloaded navigation could outlive its surface or a user's native gesture, and old history cleanup could release a replacement request.

Root cause: paging, pending UI, and viewport transactions had independent lifetimes.

Fix: separate source-page ownership from generation-and-interaction-bound navigation; retain ownership through the Kernel terminal outcome and use cancellable geometry observers and an injectable test clock.

Verification: deterministic question and Kernel races, real Transcript navigation integration, Transcript suite, and frontend test:all passed in the cumulative working tree. Native and final-head CI verification remains pending.
…ecycle

Problem: resident growth could exceed the completed-block budget, uncovered ranges could paint blank, and fallback could replace selected or focused hosts.

Root cause: range, prefix size views, presentation branches, asynchronous geometry, and render-captured command ownership were published independently.

Fix: commit a concrete immutable prefix/range snapshot, trim optional overscan after resident retirement, share full/window/safety keyed hosts, and coalesce generation-bound geometry. Bind commands to current committed state instead of retaining historical render closures. Keep source paging independent of lazy navigation.

Verification: deterministic Transcript suite, 100/101/135 and 1k/10k growth, source-navigation races, stale surface callbacks, Chromium/WebKit reader replay, paged full safety with native selection/focus, production build budgets and repolint pass locally. All-test and final native CI qualification remain separately tracked; heap profiling exposed remaining App-shell context retention outside this renderer fix.
Problem: the integration PR mixed an independent API-key save change with Transcript work and lacked attributable safety/performance evidence.

Root cause: prior merge/review fixes blurred scope and platform qualification, while render and navigation memory costs had not been measured independently.

Fix: restore API-key behavior to current main-v2, retain necessary capability fixture compatibility, document the shared ownership/geometry/presentation contracts and the one-release settings boundary. Record related PR overlap and measured paging, mount, latency and heap data without claiming unverified whole-app stability.

Verification: production bundle and repository budgets remain unchanged; focused Transcript and config/desktop Go tests plus browser replays passed. Final-head CI and residual App-shell retention qualification are explicitly required before merge-ready signoff.
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/**) 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