Skip to content

pr/0ff80446a fix whisper mode hiding rich final answe#253

Merged
plusplusoneplusplus merged 31 commits into
mainfrom
pr/0ff80446a-fix-whisper-mode-hiding-rich-final-answe
May 31, 2026
Merged

pr/0ff80446a fix whisper mode hiding rich final answe#253
plusplusoneplusplus merged 31 commits into
mainfrom
pr/0ff80446a-fix-whisper-mode-hiding-rich-final-answe

Conversation

@plusplusoneplusplus
Copy link
Copy Markdown
Owner

  • 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

plusplusoneplusplus and others added 28 commits May 31, 2026 15:23
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>
plusplusoneplusplus and others added 2 commits May 31, 2026 15:51
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>
@plusplusoneplusplus plusplusoneplusplus merged commit e103737 into main May 31, 2026
34 checks passed
@plusplusoneplusplus plusplusoneplusplus deleted the pr/0ff80446a-fix-whisper-mode-hiding-rich-final-answe branch May 31, 2026 23:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant