pr/0ff80446a fix whisper mode hiding rich final answe#253
Merged
plusplusoneplusplus merged 31 commits intoMay 31, 2026
Merged
Conversation
Owner
plusplusoneplusplus
commented
May 31, 2026
- Fix whisper mode hiding rich final answer split by hidden tool
- Write Ralph grilling goal file under notes/Plans, not the repo
- docs(classify-diff): add getter/setter classification heuristic
- fix(classification): eliminate cross-PR state bleed in useClassification (AC-01)
- feat(coc): AC-02 self-heal stale .pending markers in generic classification handler
- feat(coc): AC-03 per-invocation provider/model selection for classify-diff
- fix(spa): resolve TDZ bug in PullRequestDetail and fix test mocks
- fix(pr-popout-chat): use pullRequestChat context so backend emits PR framing
- feat: give commit review popout structural parity with PR review popout
- feat(coc): AC-05 give embedded CommitDetail classification/review-progress parity
- test(spa): fix 6 failing tests after commit-review parity refactor
- fix(coc): persist token usage for queue-dispatched chats and Ralph iterations
- feat(work-items): add workItems.aiAuthoring feature flag and AI draft endpoints
- feat(work-items): implement LLM generator for AI authoring draft endpoints
- feat(work-items): AI authoring composer UI and coc-client typed methods
- feat(ai-authoring): add Create with AI to hierarchy tree and admin toggle
- test(work-items): add hierarchy smoke tests and AC compliance checks for AI authoring
- refactor(admin): move Providers and Servers from Connections to Configure group
- fix(whisper): detect bash tool commits when whisper group is expanded
- fix: register workItems.aiAuthoring.enabled in ADMIN_CONFIG_FIELDS so it persists across restarts
- fix: normalize tool names to lowercase in commit/PR detection
- feat: capture token breakdown (system/tool/conversation) in data pipeline
- feat(coc-spa): segmented context-window bar with breakdown popover
- fix(coc): widen ChatDetail load-effect substring to 1200 chars
- feat(spa): always show ctx hover popover with total fallback
- feat(spa): redesign work items hierarchy UI to match mockup
- scripts: add coc.service.template for Linux systemd daemon setup
- fix(spa): allow CTX popover to escape ComposerMetaStrip overflow clip
In whisper mode, filterWhisperChunks kept only the single last content chunk as the final message. When a hidden suggest_follow_ups (or report_intent) tool call sat between the substantive answer and a trivial closing line, only the closing line survived and the rich answer was collapsed into the summary. Walk back from the last content chunk to absorb the whole final message, stepping over non-breaking trailing tools (suggest_follow_ups, report_intent, task_complete, ask_user) and stopping at the first substantive tool/tool-group. Add regression tests and update the dashboard-spa reference. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
During the Ralph grilling phase the goal spec file was landing in the repository working tree because the generic `grill-me` skill hardcoded a working-directory-relative `Plans/<area>/<feature>/goal.md` path. Move the goal-file save location into CoC and inject it via the user message (not the system message) so it lands under `~/.coc/repos/<workspaceId>/notes/Plans/<folder>/<name>.goal.md`, where the Notes/scratchpad UI can open and manually edit it (`isGoalFile` matches `*.goal.md`): - chat-base-executor: add `buildRalphGrillSuffix(autoFolderContext)` which appends an explicit `*.goal.md` save-location directive to the grilling user prompt; suppress the generic `.plan.md` auto-folder system block during grilling to avoid a contradictory save target. - grill-me skill: make it host-agnostic — defer to the host-provided save location and only fall back to a working-directory-relative `Plans/<area>/<feature>/` when none is supplied. Bump to 0.1.3. - Add regression test asserting the goal-file directive is injected into the user message (pointing at notes/Plans with `.goal.md`) and never into the system message. - Document the grilling-phase prompt injection in the coc-knowledge ralph reference. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Clarify that a direct field-passthrough getter/setter is mechanical/low, while one with validation, transform, lazy init, or side effects is logic. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ion (AC-01) - Add currentKeyRef to track the live classification key; every async response (initial GET, poll tick, POST) checks the ref before calling setState so stale responses from previous PRs are silently dropped. - Replace the mount-only cleanup useEffect with a key-scoped effect ([keyStr]) that clears the polling interval, resets state to idle, and updates currentKeyRef on every key change (also covers unmount). - Drop the pr?.headSha ?? pr?.sourceBranch fallback in PullRequestDetail: the classificationKey is undefined until a real commit SHA is present, preventing two PRs on the same branch from aliasing to one cache key. - Add 10 unit tests in useClassification.test.ts covering: key-change state reset, interval cancellation with fake timers, stale-GET/POST/poll guards, rapid A→B→A switching, and key-to-undefined transition. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…cation handler
On every GET and POST to /api/repos/:repoId/classify-diff, if a
.pending marker exists the handler now validates the marker's task ID
against the live queue via bridge.getTask(). A task with status
'queued' or 'running' is kept alive; any other status (failed,
cancelled, completed) or a missing task (server restarted, memory
lost) is treated as stale: the marker is cleared and the endpoint
reports { status: 'none' }, allowing the user to re-trigger. Any
exception from the queue lookup is treated as alive (fail-safe).
Changes:
- generic-classification-handler.ts: import clearPending; add
clearPendingGeneric helper; add isTaskAlive(processId, bridge)
helper; apply liveness check in both GET and POST handlers
- genericClassificationHandler.test.ts: expand coverage from 7 to 15
tests covering alive/queued/not-found/failed/cancelled/throws paths
on GET, and alive/stale paths on POST; fix POST mock to use
EventEmitter so readJsonBody's data+end events are emitted correctly
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…-diff - Add provider? to PrClassificationPayload in task-types.ts - Thread provider/model from POST body into enqueued task payload and config in generic-classification-handler.ts (guarded by VALID_CHAT_PROVIDERS) - Add lastClassificationPrefs to PerRepoPrefsClient for per-repo persistence - Extend useClassification hook: provider/model state + refs, setProvider/ setModel callbacks, preferences load on mount, POST body enrichment - Add provider/model dropdowns to ClassificationFilterBar (PrFilesPanel) and PopOutGitReviewShell classify toolbar using useAgentProviders + useModels - Pass workspaceId option to useClassification in PullRequestDetail - 11 new tests: hook POST body, setProvider/setModel, prefs persistence, prefs load on mount, invalid prefs ignored, no-workspaceId guard; handler provider/model threading (valid, invalid, omitted, model-only) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move headSha/classificationKey/classificationHook/classification block
to after the workspaceId declaration so workspaceId is in scope when
useClassification({ workspaceId }) is called.
Also update test mocks:
- Add getActiveProvider to config mocks in all affected PR test files
- Add vi.hoisted prefsMocks for preferencesApi in PullRequestDetail and
PullRequestsTab tests (with re-initialization after vi.resetAllMocks)
- Add agentProviders and preferences to cocClient mock in
PopOutGitReviewShell.prTitle test
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…framing The pop-out PR chat panel was sending `context.prChat` which the backend prompt-builder does not recognise, silently dropping PR framing from the AI prompt. Switch to the already-supported `context.pullRequestChat` shape so the prompt-builder prepends "I'm asking about pull request #N. PR title: T" to every message sent from the pop-out chat panel. - usePrChatBinding: accept repoId + prTitle options; send context.pullRequestChat instead of context.prChat (AC-01 approach a) - PrChatPanel: add repoId + prTitle props and forward to the hook - PopOutGitReviewShell/PrReviewContent: thread repoId + prTitle (already held by PrReviewContent) down into PrChatPanel - workspaceId stays in the payload so resolveRootPath resolves to the workspace rootPath as the agent CWD (AC-02) - Tests: update usePrChatBinding.test.ts to assert the new context shape, add assertions for repoId/prTitle options and workspaceId payload presence Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
AC-01/02/03/04: CommitReviewContent in PopOutGitReviewShell now mirrors
PrReviewContent layout exactly:
- Classification toolbar (provider selector, model selector, Classify
button, Chat toggle) — same position and controls as the PR toolbar
- Classification filter bar (logic/mechanical/test/generated) shown when
results are ready
- PopOutFilePanel receives full classification and review-progress props
(isFileDimmed, getFileBadge, prioritySort, reviewedFiles, visitedFiles,
prev/next priority navigation) — same as PR file panel
- FileDiffPanel receives isReviewed / onToggleReviewed / getHunkClassification
/ hunkActiveFilters — same as PR diff panel
- CommitChatPanel mounted in the same right-side slot (w-[340px] border-l)
as PrChatPanel, activated by the Chat button in the toolbar
- Review progress is session-local only (usePrReviewProgress called
without the persistence option), so no new server state is added
- Priority navigation (prev/next) computed via pickPriorityFile, same as PR
- 'No file selected' slot shows commit summary (subject, author, hash)
plus file count — structurally matches the PR empty state
- CommitDetail import removed from PopOutGitReviewShell (now unused there)
diffSource.ts: createCommitDiffSource now includes classificationKey
{ type: 'commit', repoId: workspaceId, identifier: hash } so useClassification
receives a valid key without extra props in CommitReviewContent.
Tests:
- diffSource.test.ts: two new cases covering classificationKey shape and
identifier value for commits
- commitPopoutReviewProgress.test.ts: 8 new cases verifying session-local
progress semantics (no server fetch, resets on hash change, markVisited/
markReviewed/toggleReviewed/unmarkReviewed, hydrated=true immediately)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…gress parity Add classification toolbar (provider/model selectors, Classify button, error display), category filter bar, session-local review progress (reviewed count, visited tracking), and next/prev priority-file navigation to the embedded CommitDetail component. This mirrors the same controls already present in the commit popout (CommitReviewContent) so both surfaces share structural parity. Hooks used (all existing): - useClassification — same classificationKey as popout (type:'commit') - usePrReviewProgress — session-local only (no persistence option) - useAgentProviders / useModels — provider/model selectors Priority navigation scrolls within the unified diff via viewerRef.current?.scrollToFile() rather than switching files, matching the monolithic-diff nature of the embedded view. New test: CommitDetail.classification.test.tsx Updated: CommitDetail.test.ts import assertion, four rendering test mocks to add parseDiffFileList + new hook stubs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- PopOutGitReviewShell.test.tsx: update source assertion from '<CommitDetail' to '<CommitReviewContent' (popout now uses the new CommitReviewContent wrapper instead of CommitDetail directly) - PopOutGitReviewShell.filePanel.test.tsx: update 'renders CommitDetail only for commit overview' test — CommitReviewContent now renders FileDiffPanel for selected files and a 'Select a file' placeholder otherwise (not CommitDetail); update assertions accordingly - PopOutGitReviewShell.render.test.tsx: add requestSpaApi mock, useAgentProviders/useModels/useClassification mocks so CommitReviewContent (which now uses these hooks) can mount; update testId from 'commit-detail' to 'popout-file-panel' to match new CommitReviewContent structure - DiffViewToggle.wiring.test.tsx: add requestSpaApi mock, parseDiffFileList to UnifiedDiffViewer mock, useAgentProviders/useModels/CommitChatPanel mocks so CommitDetail (which now uses these hooks) can mount Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…erations The queue executor path (process-lifecycle-runner.ts) discarded token usage data returned by the SDK, causing the dashboard to show no token chip for Ralph, autopilot, and run-workflow/run-script chat tasks, and excluding them from /api/stats/token-usage aggregates. Changes: - chat-base-executor.ts: add TokenUsage to ChatModeExecutionResult and include result.tokenUsage in executeByType() return object so the SDK usage propagates to the runner. - process-lifecycle-runner.ts (success turn): carry tokenUsage on the assistant turn, accumulate cumulativeTokenUsage from prior turns (mirrors follow-up-executor.ts semantics), persist tokenLimit / currentTokens on the process, and emit a 'token-usage' process event. Tests added: 7 new cases in process-lifecycle-runner.test.ts covering: - tokenUsage persisted on assistant turn - no tokenUsage field when SDK returns none - cumulativeTokenUsage accumulated on process - cumulativeTokenUsage accumulated across multiple iterations - token-usage event emitted - no event when tokenUsage absent - tokenLimit / currentTokens persisted on process Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… endpoints - Add `workItems.aiAuthoring.enabled` feature flag (default false) to: - CLIConfig / ResolvedCLIConfig in config.ts - Zod schema in config/schema.ts - Namespace registry in config/namespace-registry.ts - Runtime config handler (exposed as `workItemsAiAuthoringEnabled` feature flag) - SPA config utils (`isWorkItemsAiAuthoringEnabled()` helper) - coc-client RuntimeDashboardConfig contract type - Create `work-item-ai-routes.ts` with two workspace-scoped endpoints: - POST /api/workspaces/:id/work-items/ai-draft — draft for new work item - POST /api/workspaces/:id/work-items/:itemId/ai-draft — improvement draft - Both gated behind the feature flag (403 when disabled) - Both enforce MAX_CLARIFICATION_ROUNDS = 3 limit - Both route ephemeral drafts only — no data persisted until caller approves - AI generator functions injected (absent until LLM integration iteration) - Register AI draft routes before /:workItemId routes to prevent "ai-draft" from matching as a work item ID - Add 24 tests covering: feature flag gating, input validation, draft/ clarification responses, workspace scoping, generator error surfacing, clarification round limit enforcement - Update rest-api.md reference with the new AI authoring endpoints Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…oints
Add work-item-ai-generator.ts that implements the GenerateNewItemDraftFn and
GenerateImproveItemDraftFn contracts defined in work-item-ai-routes.ts:
- SYSTEM_PROMPT: structured JSON-only contract with both ClarificationResponse
and DraftResponse schemas, including the plan template
- buildNewItemPrompt / buildImproveItemPrompt: compose context-rich user prompts
including clarification answers, hierarchy guidance, and the force-draft
instruction when MAX_CLARIFICATION_ROUNDS is reached
- parseAiDraftResponse: robust JSON parser that strips markdown code fences,
validates required fields, filters invalid values (bad priority, non-string
tags/questions, childTask entries without title), and throws descriptive
errors on malformed responses
- createWorkItemAiGenerators(options): factory returning both generator fns
with an optional ISDKService override for testing; calls AI via lazy-imported
createCLIAIInvoker with systemMessage: { mode: 'replace', content: SYSTEM_PROMPT }
- Wire generators into registerAllRoutes in routes/index.ts so the AI-draft
endpoints now call the actual LLM instead of returning 503
Tests (36 new, all passing):
- parseAiDraftResponse: happy path, code fence stripping, field filtering,
default values, error cases
- buildNewItemPrompt / buildImproveItemPrompt: content assertions
- createWorkItemAiGenerators: draft, clarification, error, childTasks paths
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add WorkItemAiDraftFields, WorkItemAiGenerationResponse, and related types to coc-client contracts - Add WorkItemsClient.aiDraft() and aiImprove() typed SDK methods - Create WorkItemAiComposer modal with two-column layout: left = prompt + clarification Q&A; right = editable preview tabs - Wire "Create with AI" entry point into WorkItemsTab (feature-flagged) - Wire "Improve with AI" button into WorkItemDetail (feature-flagged) - Approval calls existing create/update/plan routes — no automatic execution - Hierarchy-disabled workspaces: child tasks become plan checklist - Tests cover all states, approval flows, feature flag gates, and API usage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ggle
- WorkItemHierarchyTree: add optional onCreateWithAi prop; render
hierarchy-create-with-ai-btn in header and hierarchy-empty-create-with-ai-btn
in empty state when the prop is provided
- WorkItemsTab: pass onCreateWithAi={aiAuthoringEnabled ? ... : undefined} to
WorkItemHierarchyTree so the ✨ button appears in hierarchy mode when the
feature flag is on (AC-01 item 5)
- AdminPanel: add workItemsAiAuthoringEnabled state, read from
resolved.workItems?.aiAuthoring?.enabled, include in dirty-check, save
payload, featuresSnapshot, and cancel handler; add Work Items AI Authoring
toggle (experimental badge) after the hierarchy board toggle (AC-05 item 6)
- Tests: extend WorkItemHierarchy.layout.test.ts with onCreateWithAi prop and
WorkItemsTab prop-passing coverage; add
AdminPanel-work-items-ai-authoring.test.tsx (5 tests: render, default-off,
reflect-config, save-payload, cancel-resets)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…for AI authoring Iteration 5 of the AI authoring Ralph session. New test files: - test/server/work-items/work-item-ai-hierarchy.test.ts (14 tests) - Hierarchy-enabled route: accepts epic/feature/pbi types - Passes hierarchyEnabled=true/false to generator context - Returns childTasks in draft response - Full approval round-trip: create parent PBI + child work items - Cross-workspace parentId rejected (AC-04 DoD 3) - Hierarchy-disabled checklist fallback (AC-04 DoD 2) - Approval flow does not trigger any /execute endpoints (AC-03 DoD 4) - test/spa/react/repos/WorkItemAiAcCompliance.test.ts (53 tests) - Source-level DoD evidence for every AC-01 through AC-05 bullet - AC-01: Create with AI entry points (list, hierarchy tree, empty state, detail) - AC-02: 3-round limit, generate-anyway bypass, review-before-save, error surfacing - AC-03: Approval via create/update/plan routes; no execution calls in handleApprove - AC-04: ALLOWED_CHILD_TYPES validation, checklist fold, workspace-scoped child creation - AC-05: Feature flag default false, no ~\/.coc disk writes, no SDK session caching All 241 AI-authoring tests pass; full suite pre-existing flaky test unrelated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…gure group The Providers admin tab and Servers tool tab now appear under the Configure sidebar group instead of a separate Connections group. The Connections group becomes container-only (Messaging and container Agents). Breadcrumb labels, tests, spec, and knowledge references updated accordingly. Co-authored-by: Cursor <cursoragent@cursor.com>
WhisperCollapsedGroup's inline commit-detection trigger was missing 'bash' from its shell-tool name check, so CommitStrip was never rendered for Bash tool calls in whisper mode (toolCompactness=3, the default). Non-whisper path in ConversationTurnBubble already included 'bash'; this aligns the expanded-group path to match. Add three regression tests: Bash commit shows strip on expand, PascalCase 'Bash' (normalised → 'bash') also shows strip, and read-only git log still produces no strip. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… it persists across restarts
The field was wired into AdminPanel's save payload and namespace-registry
but missing from the admin-config-fields registry. Because `_applyUpdate`
only iterates ADMIN_CONFIG_FIELDS, the toggle value was silently dropped
on every PUT /api/admin/config call — nothing was written to the config
file, so the setting reset to false on server restart.
Adds the `bool('workItems.aiAuthoring.enabled', ...)` entry alongside the
existing workItems.hierarchy.enabled entry, and extends the
admin-config-fields unit tests to cover the new field (ADMIN_EDITABLE_KEYS
membership, boolean validate(), nested apply(), runtime='live').
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Claude SDK stores tool names with capitalized first letter (e.g. "Bash", "Task") but SHELL_TOOL_NAMES and AGENT_TOOL_NAMES only contain lowercase entries. The set check silently failed for any tool call from Claude agents, so commits and pull requests made via the Bash tool were never detected in the whisper group summary. Fix: call .toLowerCase() on the raw tool name before the Set lookup in both commitDetection.ts and pullRequestDetection.ts. Add regression tests for toolName='Bash' in both test files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…line Add systemTokens, toolDefinitionsTokens, conversationTokens fields from session.usage_info breakdown to the full data pipeline: - coc-agent-sdk: extend TokenUsage, ISessionEvent.data, SessionTelemetry, and StreamingSession.handleUsageInfo to capture the three breakdown fields - forge: add sessionSystemTokens, sessionToolTokens, sessionConversationTokens to ProcessOutputEvent - coc server: thread breakdown through sse-handler token-usage event, process-lifecycle-runner, and follow-up-executor emitProcessEvent calls - dashboard SPA: useChatSSE reads and stores the three new breakdown fields; ChatDetail holds state; WorkItemExecutionSession wires no-op setters Tests: extend session-telemetry and streaming-session test suites with coverage for breakdown recording, propagation, and the absence-case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ContextWindowIndicator and ComposerMetaStrip now accept three optional breakdown props (system / tool-definitions / conversation tokens, emitted by the Copilot SDK via session.usage_info): systemTokens / sessionSystemTokens → purple segment toolDefinitionsTokens / sessionToolTokens → blue segment conversationTokens / sessionConversationTokens → green segment other (currentTokens minus above three) → gray segment When the breakdown is not available the components fall back to the original single-colour (green/yellow/red) fill bar — no regression. On hover (desktop) or tap (mobile) a small popover anchored to the indicator shows a table: Category | Tokens | % of limit, including a Total row. Prop-threading changes: - ChatHeader + buildOverflowItems: added sessionSystemTokens, sessionToolTokens, sessionConversationTokens (passed through to ContextWindowIndicator in the overflow item render). - FollowUpInputArea: same three props forwarded to ComposerMetaStrip. - ChatDetail: both ChatHeader and FollowUpInputArea call sites updated. Tests: 47 tests across ContextWindowIndicator and ComposerMetaStrip covering segmented bar colours, other-segment logic, popover show/hide/toggle, and category labels. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The token-breakdown implementation (iteration 1) added three setSession*Tokens(undefined) calls to the load useEffect, shifting SET_FOLLOW_UP_STREAMING past the previous 800-char window used by the test assertion. Increase to 1200 to accommodate the extra lines. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- ContextWindowIndicator: remove native title tooltip; always show custom popover on hover — full breakdown table when system/tool/ conversation token data is available, otherwise a simple Total row - ComposerMetaStrip: same change; additionally shows the model name at the bottom of the popover (previously only in the native title) - Tests: update 'does NOT show popover when breakdown absent' → shows simple popover; add model-name-in-popover tests (+2 tests total) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update the Work Items tab hierarchy view with the redesigned visual treatment: GitHub Primer-inspired type pills, breadcrumb navigation, two-line tree rows with guide lines, card-based description/plan sections, and filter chip controls. Co-authored-by: Cursor <cursoragent@cursor.com>
Adds a commented systemd unit file template for running coc-serve-loop.sh as a persistent daemon on Linux (e.g. Azure VM). Includes placeholders for user/path, instructions for generating the EnvironmentFile (needed for nvm-managed Node), and notes on SSH port forwarding for secure remote access. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The root div had overflow-hidden which clipped the absolutely-positioned popover (bottom-full, renders above the strip). Changed to overflow-visible so the popover can escape. The CWD chip already handles its own text truncation via shortenPath + truncate on the code element, so the root overflow constraint was not needed. Previously, the native browser title tooltip masked the issue; after the previous commit removed title in favour of a custom popover, hover/click on CTX showed nothing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ms.aiAuthoring.enabled The new workItems.aiAuthoring.enabled config field (registered in ADMIN_CONFIG_FIELDS) was missing from two tests in config.test.ts: 1. The comprehensive inline snapshot – added aiAuthoring under workItems in both 'resolved' and 'sources' sections. 2. The 'all CONFIG_SOURCE_KEYS should be file' test – added workItems.aiAuthoring.enabled to the YAML config written by that test so the key gets a 'file' source. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The 'RALPH_NEXT enqueue sets continuationOfSessionId' test resolved iter 2 with a RALPH_NEXT signal while maxIterations was 3, so the bridge spawned a third ralph iteration. That iteration kept writing into the ralph-sessions directory asynchronously after the synchronous executor.dispose() returned, racing with the afterEach rm(dataDir) and intermittently failing with ENOTEMPTY on rmdir. Fix: - Resolve iter 2 with a terminal response (no RALPH_NEXT/RALPH_COMPLETE) so no further iteration or final-check task is spawned. The assertion is captured at enqueue time and is unaffected. - Drain all in-flight work via executor.drainAndDispose(5000) before teardown so every ralph-session write settles before the data dir is removed. - Add a default terminal mockSendMessage response so stray backlog tasks resolve quickly during drain instead of hanging on an undefined mock. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The dashboard rendered AssistantStatsBadge eagerly (not just when expanded), calling .toLocaleString() on tokenUsage.totalTokens/input/ output. When a turn persists a partial tokenUsage (e.g. an SSE token-usage event carrying only context-window fields, or an SDK result without a full per-turn breakdown), those fields are undefined and the call threw, taking down the entire SPA via the root error boundary. Coerce each numeric field with ?? 0 and fall back totalTokens to input + output so a missing field can never crash the badge. Adds regression tests covering partial, fallback, and full tokenUsage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.