Skip to content

refactor(cue): cue-polish merge and cleanup#588

Merged
reachraza merged 286 commits intorcfrom
cue-polish
Mar 18, 2026
Merged

refactor(cue): cue-polish merge and cleanup#588
reachraza merged 286 commits intorcfrom
cue-polish

Conversation

@reachraza
Copy link
Collaborator

@reachraza reachraza commented Mar 18, 2026

Summary

  • Fix Cue pipeline ENOENT spawn error — Cue executor was using the bare command name (e.g., claude) instead of the resolved binary path, causing spawn claude ENOENT failures. Now resolves the full path via agentDetector.getAgent() before spawning, matching the normal process flow.
  • Remove unused catch (e) binding in web-server-factory.ts (eslint no-unused-vars fix)
  • Fix duplicate fontSizeReset shortcut entry in shortcuts.ts
  • Sync package.json version

This branch was rebased on top of rc after the cue-engine decomposition and review fixes were merged via PR #578. No new cue logic changes — all decomposition modules (cue-activity-log, cue-heartbeat, cue-subscription-setup, cue-fan-in-tracker, cue-run-manager) and bug fixes (concurrency slot leak, stale nextTriggers, fan-in guard, reconciler dispatch routing) are already in rc.

Test plan

  • npm run lint and npm run lint:eslint clean (0 errors/warnings)
  • Full test suite passing (23,491+ tests)
  • Cue tests: 477 passing, 0 regressions

New trigger that polls markdown files for unchecked tasks (- [ ]) and
fires events per file when content changes and pending tasks exist.
Includes content hashing to avoid re-triggering, picomatch glob matching,
6 new template variables, YAML validation, and full renderer support.
The tool execution display in TerminalOutput had a growing chain of
per-tool field extractors (command, pattern, file_path, query, etc.)
that required manual additions for every new tool type.

Replaced with a single generic summarizeToolInput function that walks
all input object entries and displays strings, string arrays, array
counts, and boolean/number key=value pairs automatically. TodoWrite
todos array retains its special progress summary formatting.

Removed dead helpers: safeStr, truncateStr. Updated tests to verify
generic behavior for arbitrary tool inputs.
- Resize wizard modal from max-w-5xl (1024px) to 1200px wide / 85vh tall,
  matching Director's Notes dimensions
- Add runAllDocuments toggle to PhaseReviewScreen (Step 5), visible when
  there are 2+ generated documents
- When enabled, all documents with tasks are included in the batch config
  instead of only the first
- Extract reusable ToggleSwitch component to ui/ and refactor
  SettingCheckbox to use it
- Add test for run-all-documents batch behavior

Closes #490
- Add explicit type="button" to ToggleSwitch to prevent unintended form
  submissions
- Pass ariaLabel={title} in SettingCheckbox for screen reader accessibility
- Remove duplicate sessionsRef declaration in App.tsx (store-based ref
  at L470 already provides live .current via getter, making the useRef
  added by deep-links redundant)
- Fix undefined sessionId in useSummarizeAndContinue.ts (use session.id)
- Add "Create Worktree" action to QuickActionsModal (Cmd+K) for git repo sessions
- Resolve to parent session when invoked from a worktree child
- Auto-focus newly created worktree sessions after creation
Format symphony-registry.json to fix CI prettier check failure.
Add fontSizeIncrease/Decrease/Reset to FIXED_SHORTCUTS registry
per CodeRabbit review feedback.
Applies provider-specific read-only args from centralized agent
definitions (e.g. --permission-mode plan for Claude Code,
--sandbox read-only for Codex) without duplicating logic.
Adds a robot face icon button to the right side of the left sidebar
bottom panel that toggles "Unread Agent Only" mode, hiding all agents
without unread indicators. Reassigns toggleTabUnread to Alt+Shift+U.
- Install @types/picomatch and @types/js-yaml for Cue module type safety
- Pass safeSend dependency to registerHistoryHandlers() (directors-notes-stream added the dep)
- Type SymphonyHandlerDependencies.settingsStore as Store<MaestroSettings>
  to fix ElectronStore iterator type mismatch
Adds a "Copy Deep Link" button to the tab context menu that copies
a maestro://session/{id}/tab/{tabId} URL to the clipboard. Reuses
the existing buildSessionDeepLink shared utility.
In dev mode, setAsDefaultProtocolClient without extra args registers
the stock Electron binary, causing the Electron splash screen to open
instead of Maestro. Pass process.execPath and the resolved app entry
point so macOS launches the correct application.
…ures tab

Stats collection, time range, database management, and WakaTime settings
now live under their respective Encore Feature toggle instead of General.
…layout

Hide CUE filter button from History panel and Director's Notes when the
Maestro Cue encore feature is disabled. In the History panel, move the
activity graph to its own row when all 3 filter types are visible (CUE
enabled) to prevent crowding; keep it inline when only 2 types show.
… Notes stats

agentCount was using sessionIds.length which counts all history files on
disk, including deleted agents and those with no entries in the selected
time range. Now tracks which agents actually contribute entries using a
Set, matching how the synopsis handler already does it.
Use -top-0.5 -right-0.5 positioning to match the Mail icon's
notification dot in TabBar, placing it slightly outside button bounds.
…bled

Show a CUE entry type description (with Zap icon and teal badge) in the
History Panel Guide modal, gated on the maestroCue encore feature flag.
Describes the trigger types: file changes, time intervals, agent
completions, GitHub activity, and pending tasks.
- maestro-cue.md: Overview, enabling, quick start, modal UI, shortcuts
- maestro-cue-configuration.md: Full YAML schema, settings, validation
- maestro-cue-events.md: All 6 event types with payloads and examples
- maestro-cue-advanced.md: Fan-in/out, filtering, chaining, templates
- Update encore-features.md and docs.json to wire into navigation
Previously the "View history" link in the auto-run status bar was only
visible on the autorun tab. Now it appears on all tabs except history.
- Reorder Encore Features tab: Usage & Stats → Symphony → Director's Notes
- Remove BETA badge from Usage Dashboard modal header
- Director's Notes retains BETA badge as it's still in beta
- Usage & Stats and Symphony are default-on stable features
…ndex

- Add standalone CueYamlEditor modal with lazy loading and modalStore integration
- Add "Configure Maestro Cue" to session context menu and Quick Actions
- Thread onConfigureCue through AppModals, SessionList, and QuickActionsModal
- Fix CueHelpModal z-index to use MODAL_PRIORITIES.CUE_HELP instead of hardcoded 50
- Change Maestro Cue shortcut from Cmd+Shift+Q (conflicts with macOS quit) to Opt+Q
reachraza and others added 25 commits March 13, 2026 15:19
Add outputTruncated boolean to both single-source and fan-in completion
event payloads so downstream consumers know when source output was clipped
at 5000 chars. Remove debug console.log from claude-output-parser that
was logging raw usage data to stdout in production.
Debate and autorun edge modes have no backend implementation yet.
Mark them as disabled with "(Soon)" label and tooltip to set correct
user expectations.
End-to-end tests verifying the full flow: pipelineToYamlSubscriptions
generates {{CUE_SOURCE_OUTPUT}} in chain prompts, and
substituteTemplateVariables resolves it to actual source output.
Covers normal, empty, and multi-content scenarios.
…e token stripping, timeout payload

- Remove pointerEvents: 'none' from coming-soon edge buttons so title
  tooltip still shows on hover (onClick guard already prevents action)
- Update NodeConfigPanel placeholder to check both hasIncomingAgentEdges
  AND includeUpstreamOutput before claiming output is auto-included
- Strip bare {{CUE_SOURCE_OUTPUT}} token (without trailing \n\n) in
  yamlToPipeline round-trip
- Add outputTruncated to fan-in timeout continue-mode payload for
  consistency with normal fan-in and single-source paths
…oduction readiness

Fix NaN bug in numeric filter comparisons where non-numeric payload
values silently passed through >=, <=, >, < filters. Route file watcher
errors through engine logger instead of console.error. Add validation
for duplicate/empty subscription names, HH:MM time ranges, interval
upper bounds, and label field parsing. 26 new tests (408 total).
The inputMode === 'ai' guard on the newTab shortcut prevented Cmd+T
(Ctrl+T on Windows) from working when a terminal tab was focused.
Removed the guard so the shortcut works regardless of active mode.
… in validation

Replace Number()+isNaN() with a toComparableNumber() helper that rejects
null, empty/whitespace strings, NaN, and Infinity via Number.isFinite().
Fixes edge case where Number('') and Number(null) silently coerce to 0
and pass numeric filters. Add Number.isFinite() guard to interval_minutes
validation. 7 new tests (415 total).
…n new tab

Trim-normalize subscription names before duplicate detection so names
with surrounding whitespace are correctly caught. Ensure Cmd+T sets
inputMode to 'ai' so creating a tab from terminal mode switches to AI
view. Add -Infinity/NaN edge case tests for filter coercion.
fix(cue): enable multi-agent pipeline output passing and polish editor UX
…mprehensive test coverage

- Add circular chain detection (MAX_CHAIN_DEPTH=10) to prevent infinite A→B→A loops
- Clean event queue and scheduledFiredKeys on session teardown/refresh
- Generate separate runId for output prompt phase with independent DB tracking
- Add GitHub poller seed marker on first-poll failure to prevent event flooding
- Validate watch glob patterns via picomatch in YAML loader
- Warn at setup time when prompt_file references a missing file
- Add 42 new tests: multi-hop chains, session lifecycle, template variables,
  config hotloading, output prompt edge cases, filter/GitHub/concurrency stress
…elper

- Rewrite chain depth guard to propagate via AgentCompletionData.chainDepth
  across async hops instead of a synchronous instance counter that resets
  between microtasks; thread chainDepth through dispatchSubscription,
  executeCueRun, doExecuteCueRun, QueuedEvent, and drainQueue
- Extract validateGlobPattern helper in cue-yaml-loader to deduplicate
  the file.changed and task.pending glob validation blocks
- Remove duplicate empty-filter test, merge assertion into original
- Add missing CUE_GH_MERGED_AT to github template variable test
- Rename misleading test to 'preserves 5000-char sourceOutput without
  truncation'
- Make fan-in/fan-out test async with proper await before assertions
- Rewrite circular chain and self-referencing tests to rely on the
  MAX_CHAIN_DEPTH guard instead of manually stopping the engine
- Remove low-signal expect(container).toBeTruthy() and unnecessary
  async from CueModal edge case tests
…og message

- Remove unreachable manuallyStoppedRuns.has(outputRunId) check — outputRunId
  is never added to activeRuns so stopRun() can never populate it
- Fix misleading log: seed marker prevents silent event loss (items swallowed
  by seeding path), not event flooding
Store chainDepth in FanInSourceCompletion and pass the max across
completed sources to dispatchSubscription in both the all-complete
and timeout-continue branches, closing a gap where circular pipelines
routed through fan-in nodes would bypass the depth guard.
…ion collision

Keys now use format sessionId:subName:time instead of subName:time,
so teardown of one session cannot delete another session's fired
markers when both have identically-named subscriptions.
fix(cue): harden engine safety, fill test coverage gaps, and design group chat integration
…0+1)

- Delete CueGraphView.tsx (1,166 lines dead code, superseded by CuePipelineEditor)
- Add cue-test-helpers.ts: shared createMockSession/Config/Deps factory across 6 test files
- Deduplicate CueGraphSession: add to cue-pipeline-types.ts, remove local copies from CueModal and CuePipelineEditor

- cue-engine.ts decomposition (1,574 → 719 lines, −55%):
- cue-activity-log.ts: ring buffer (push/getAll/clear), ACTIVITY_LOG_MAX=500
- cue-heartbeat.ts: heartbeat writer + sleep/wake detection + reconciliation
- cue-subscription-setup.ts: 5 setup functions (heartbeat, scheduled, file, GitHub, task)
- cue-fan-in-tracker.ts: fan-in source tracking + completion dispatch
- cue-run-manager.ts: concurrency gating, queue management, run lifecycle

Key wiring decisions:
- onRunCompleted callback resolves circular dep between run-manager and engine
- onRunStopped callback ensures stopped runs appear in activity log
- scheduledFiredKeys Set owned by engine, passed by ref to subscription setup
- fanInTracker.reset() added to stop() to prevent timer leaks across restarts
- calculateNextScheduledTime re-exported from engine for backwards compat

Tests: 475 passing, 0 regressions; added stopRun→activityLog coverage
…r scheduled fire

- stopRun now eagerly decrements activeRunCount and drains the queue,
  so queued events dispatch immediately instead of waiting for the
  async finally block (which may never run if onCueRun hangs)
- finally block skips its decrement for manually stopped runs to
  prevent double-decrement race with newly drained runs
- setupScheduledSubscription now recalculates nextTriggers after each
  fire so the UI shows the next future time, not a stale past one
- stopAll uses snapshot of keys to avoid mutating Map during iteration
- Added regression tests for both fixes (477 total cue tests passing)
…n and types

- Heartbeat onDispatch now calls dispatchSubscription instead of
  runManager.execute directly, so fan-out works for reconciled events
- Added getActiveRunCount(sessionId) to CueRunManager, used by
  getStatus() instead of reaching into getActiveRunMap() internals
- Guard Math.max in fan-in-tracker against empty completions array
  to avoid -Infinity chainDepth propagation
- CueGraphSession.event typed as CueEventType instead of string
…riptions

Move calculateNextScheduledTime call above the filter gate so the
UI's "Next" column updates even when the filter suppresses the event.
Previously nextTriggers would go stale on filtered-out scheduled fires.
The immediate heartbeat dispatch was missing the state.lastTriggered
update that the interval branch already performs, leaving the Cue
modal's "Last Triggered" column empty until the first interval tick.
Loop bound was dayOffset < 7 (0..6), missing the 7th day offset.
When a single-day schedule's slot had already passed (e.g. Mon 09:00
checked at Mon 09:01), the function returned null because next Monday
was at offset 7. Changed to <= 7 so weekly schedules always resolve.
Resolved 16 merge conflicts from rc (CLI auto-run --agent flag,
agent-spawner customModel/readOnly, settingsStore persistentWebLink,
CI workflow branches, system prompt updates, and others).

Verified: cue-engine decomposition intact (5 extracted modules),
CueGraphView still deleted, CueGraphSession not re-duplicated,
477 cue tests and 23,491 total tests passing, lint clean.
Drop the unused `e` parameter from the catch block that persists
webAuthToken, fixing the eslint no-unused-vars warning.
@greptile-apps
Copy link

greptile-apps bot commented Mar 18, 2026

Greptile Summary

This is a small cleanup/polish PR that applies three targeted fixes with no functional logic changes: it removes an unused catch binding in web-server-factory.ts, de-duplicates the fontSizeReset shortcut entry in shortcuts.ts, and adds --ignore-unknown to the prettier lint-staged command in package.json.

  • web-server-factory.ts: catch (e)catch {} — valid TypeScript optional-catch-binding syntax (TS 4.0+), silences the ESLint no-unused-vars warning without altering error-handling behavior.
  • shortcuts.ts: The fontSizeReset shortcut (['Meta', 'Shift', '0']) was present twice in DEFAULT_SHORTCUTS; the duplicate occurrence (before openCue) is removed, leaving a single canonical entry after jumpToTerminal.
  • package.json: prettier --writeprettier --write --ignore-unknown in lint-staged prevents prettier from throwing on file types it cannot process (binary assets, uncommon extensions), which is a commonly recommended configuration for projects with mixed file types.

Confidence Score: 5/5

  • This PR is safe to merge — all three changes are minimal, well-scoped, and carry no risk.
  • All changes are purely cosmetic/lint fixes: an optional catch-binding removal, a duplicate shortcut entry de-duplication, and a safer prettier flag. No logic paths are altered, no new dependencies are introduced, and the stated test results (23 k+ tests, 477 cue tests, 0 regressions) align with the trivial scope of the diff.
  • No files require special attention.

Important Files Changed

Filename Overview
src/main/web-server/web-server-factory.ts Removes unused e binding from a catch block (catch (e)catch {}), a clean ESLint no-unused-vars fix; the error path is correctly handled via logger.warn.
src/renderer/constants/shortcuts.ts Removes the duplicate fontSizeReset entry (previously appeared twice in DEFAULT_SHORTCUTS); the remaining single entry is placed after jumpToTerminal with correct keys ['Meta', 'Shift', '0'].
package.json Adds --ignore-unknown to the prettier --write command in lint-staged, preventing prettier from erroring on file types it cannot format (e.g. images, binaries).

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[lint-staged triggered on commit] --> B{"File type known\nby prettier?"}
    B -- "Yes (--ignore-unknown)" --> C[prettier --write]
    B -- "No (--ignore-unknown)" --> D[Skip silently ✓]
    C --> E[eslint --fix\n*.js/.ts/.tsx etc.]
    D --> E
    E --> F[Commit proceeds]

    G[web-server-factory.ts\npersistentWebLink = true] --> H{Valid UUID\nin store?}
    H -- Yes --> I[Use stored token]
    H -- No --> J[Generate randomUUID]
    J --> K[try: persist token]
    K -- success --> L[Server starts\nwith persistent token]
    K -- "catch {}\nnon-fatal" --> M[logger.warn\nServer starts\nwith ephemeral token]

    N[DEFAULT_SHORTCUTS\nshortcuts.ts] --> O[...\ndirectorNotes\nopenCue\nfilterUnreadAgents\njumpToTerminal\nfontSizeReset ✓ single entry]
Loading

Last reviewed commit: "fix: remove unused c..."

Cue executor was using the bare command name (e.g., 'claude') from the
agent definition, causing ENOENT errors when Node.js spawn() couldn't
find the binary on PATH. The normal spawn flow resolves the full binary
path via agentDetector.getAgent(), but Cue skipped this step. Now uses
the agent detector to resolve the path before passing it to the executor.
@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a27a8173-6e3d-4390-8464-7490ad1fbf77

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cue-polish
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@reachraza reachraza merged commit 5200bb8 into rc Mar 18, 2026
4 checks passed
@pedramamini pedramamini deleted the cue-polish branch March 18, 2026 22:07
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.

4 participants