Constraint: Windows and Linux artifacts are built on native GitHub runners from a temporary snapshot branch
Rejected: Build Windows/Linux locally on Apple Silicon | docker/wine packaging is not stable on this host
Confidence: medium
Scope-risk: moderate
Directive: This snapshot branch is transport-only and should be deleted after the release completes
Tested: local verify/build stages before snapshot creation
Not-tested: remote packaging before workflow execution
Each of these catches already logged via an accessible `logger` or `log`.
The migration wraps the thrown value through `classifyUnknownError(raw,
fallback)` and emits the log line with the structured `[code]` prefix.
Observable behaviour — return values, fail strings, DB writes — is
unchanged; the only addition is a machine-readable `code` on every log
line so future telemetry can bucket by category.
Sites migrated (11 files, 20 catch sites):
src/main/browser-action-service.ts (2) approval lookup, payload JSON
src/main/ipc-credentials-handlers.ts (4) save, remove, test lookup, test resolve
src/main/hire-hook.ts (3) getAgent, connector def, outer exception
src/main/checkpoint-engine.ts (2) onTaskStarted, onDocumentDrafted
src/main/document-lifecycle.ts (1) getRun while deriving taskId
src/main/skills/runtime.ts (2) builtin statSync, builtin readdir
src/main/worker/handlers/run-status-handler.ts (1) run not found during status
src/main/worker/handlers/run-log-handler.ts (1) lease renewal lookup
src/main/notification-service.ts (1) notification.close during destroy
src/main/updater-service.ts (1) autoUpdater.checkForUpdates
src/main/ipc-support.ts (2) ipc handler throw, emitEvent send
Why only 20 tonight: 248 catches exist in src/main/. Rewriting them all
in one commit is high-diff-risk (collides with Linus's in-flight
database/backup/migration work on database/*, connector-definitions-*,
message-* and scripts/*) and low-value (pure-library catches with no
accessible logger produce dead `void classified` constructs). The
taxonomy module is committed separately so the remaining 228 sites can
land incrementally via the C6.2 proposal.
All 11 files selected sit outside Linus's working set. Verified:
- pnpm typecheck clean
- pnpm test:unit 498 passed
Land the B5 harness skeleton: fixture loader (strict JSONL contract with
meta header + ordered turn records + assertions tail), replay-client that
swaps in for pi-ai's streamSimple by replaying recorded assistant turns,
structural assertion judge (tool_called / no_tool_called /
message_contains_substring / tool_call_arg_matches / trace_max_turns), an
eval-runner that sums the token ledger and produces an EvalResult, a
vitest driver (tests/eval/harness.test.ts) that discovers *.jsonl
fixtures, and a record-fixture CLI that writes fixture meta headers.
Hard contracts:
- No fallback: replay-client and fixture-loader throw on exhaustion /
malformed input rather than synthesizing defaults.
- No mock: types reuse @mariozechner/pi-ai AgentMessage / ToolCall
verbatim; shadow types are forbidden.
- No fake fixture data: tests/eval/fixtures/ ships only README +
.gitkeep. Real traces are recorded by the user against live providers.
package.json adds test:eval (vitest --passWithNoTests so an empty
fixture dir is green) and eval:record (CLI entrypoint). electron-builder
already excludes tests/ via its files: glob — fixtures never enter the
shipped .asar.
Sessions are already agent-scoped post-v34, but the code kept routing
rotation / accumulation / handoff through the task indirection. Heartbeat
runs (no task) silently skipped all three, letting taskless transcripts
grow past the model's context window — the 7M-token explosion.
- DB adds getSessionById(sessionId) — direct lookup bypassing
tasks.active_session_id
- session-management-service: generateHandoff(session) is now agent-scoped,
walking recent runs across tasks + heartbeats; getHandoffForAgent(agentId)
is the canonical lookup, getHandoffContext(taskId) is a thin shim for
callers that still hold a task id
- turn-context.ts::resolveSession drops the `if (!task)` early return:
rotation evaluation runs on the agent session unconditionally
- run-finished-helpers.ts::accumulateAndRotateSession drops the `!task`
gate: tokens accumulate and rotation fires for every run, keyed on the
agent session, not the task
- Rotation evaluator contract: evaluatePreRunSessionRotation(agentId,
connectorId) → { rotated, handoff, sessionId }; old (taskId, connectorId)
signature removed
IPC contract tightening: ipc-support::emitEvent becomes a best-effort
sink. "Render frame was disposed" during renderer reload is a lifecycle
signal, not a logic error; silently drop it instead of letting it abort
downstream event emissions.
Artifact projection: pi's write/edit tool results now upsert a
`work_products` row via a new agent-runtime/artifact-projector.ts. No
more agents writing 54 files into the workspace that the UI never sees.
Migration v40 relaxes work_products.task_id to nullable so heartbeat
artifacts can register too.
File size: split agent-event-projection.ts out of runtime-bridge.ts to
keep the bridge under the 400-line cap after adding the projector hook.
Tests: 604 unit + integration green; generateHandoff callsites updated
for the single-argument signature; artifact-projector has pure-function
coverage via the projector module's own shape.
Removes the four workspace adapter packages (claude-local, codex-local,
gemini-local, adapter-utils) now that all runtime provider dispatch lives
in @mariozechner/pi-ai + pi-agent-core + pi-coding-agent. Refreshes the
lockfile, drops bundledMainDependencies from the Vite config, and adds
pi-coding-agent as a direct dependency for the worker's coding tools.
- Install @tailwindcss/typography required by styles.css @plugin directive
- All 9 automated verification checks pass: zero old variables, zero old border radius, zero data-theme, 70 OKLCH tokens, key tokens present, status-colors exports verified, no fontsource packages
- Zero renderer type errors, build succeeds
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Install recharts@3.8.1 as dependency
- Create chart-utils.ts with 4 exported pure functions: aggregateRunsByDay, aggregateCostsByDay, aggregateAgentWorkload, formatShortDate
- Create dashboard-charts.test.ts with 16 unit tests covering all aggregation behaviors
- All tests pass: 14-day bucketing with zero-fill, timed_out/interrupted as failed, null cost handling, top-8 + Others grouping, name truncation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Agents kept running after closing AgentCompany because worker processes
auto-recreated on exit, retry timers were never cleared, child CLI
processes weren't terminated, and orchestration had no quit guards.
Changes:
- Add isQuitting guards to all orchestration/automation entry points
- Track and clear all setTimeout/setInterval timers on quit
- Send cancel-run to all active CLI processes before killing worker
- Add destroyed flag to prevent worker recreation after intentional destroy
- Add quit confirmation dialog: Stop All & Quit / Minimize to Background / Cancel
- Bump version to 0.4.96
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Align Electron CSS with website design schema (Inter font, #FBFAF5/#191919
palette, #213448/#94B4C1 accent)
- Generate proper app icons from logo.svg via cairosvg (no more Pillow ladder)
- Square bg icons for Electron/tray (Apple HIG — OS applies squircle mask)
- Circle bg icons for website favicon only
- Add scrolling ASCII agent-activity animation to onboarding hero left panel
- Remove dock.setIcon() — let macOS use bundle .icns with system mask
- Fix goal title overflow with min-w-0 for flex truncation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace all orange/red icon assets with new brand colors:
- Circle background #191919, logo mark #FBFAF5
- Regenerated: icon.png, icon.ico, icon.icns, all tray icons
- Updated generate-icons.py with new palette and circle shape
- Added source logo.svg
- Bump version to 0.4.92
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tray was invisible on Windows/Linux (icon not bundled in asar) and
completely absent on macOS (early return guard). Generate dedicated
tray-sized icons, bundle them in the packaged app, and create tray
on all platforms with macOS Template image support.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add deliverable review gate: pause workflow when agents produce important
documents (PRDs, design docs, etc.) for human review before continuing
- Add company-level reviewDeliverables setting with onboarding card selector
- Block agent heartbeats when deliverable review is pending (agent + CEO)
- Trigger review at document creation time in API server for reliability
- Fix autoApproveHires vs reviewDeliverables conflict in approval-policy
- Fix app quit: force-exit on all platforms (macOS Dock, Windows tray, Linux)
- Add multi-platform CI/CD pipeline (macOS arm64/x64, Windows x64/arm64,
Linux x64/arm64 with deb/AppImage/rpm/snap) with code signing support
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create scripts/build-all-platforms.mjs that detects current platform, invokes electron-builder via build-desktop.mjs, verifies artifacts in build/release/, and reports remaining platforms
- Add "build:all" script entry to package.json for D-07 cross-platform build validation
- Install @tanstack/react-virtual for virtualized list rendering
- Create useRovingTabIndex hook in src/renderer/lib/keyboard.ts for arrow-key navigation
- Add virtualization to 6 lists: TaskQueue, ApprovalList, ActivityList, CostList, AgentRoster, MessageList
- MessageList uses measureElement for variable-height message items with auto-scroll
- All 6 lists have role="listbox" with role="option" on rows for accessibility
- All 6 lists support ArrowDown/ArrowUp/j/k/Home/End keyboard navigation
- Add 8 unit tests for useRovingTabIndex covering all key bindings and edge cases
- Install zustand 5.x and immer 11.x dependencies
- Create 6 Zustand slices: navigation, company, selection, ui, communication, social
- Create combined store with devtools + immer middleware
- Create IPC event batcher with 50ms debounce window (schedule/flush/dispose)
- Create typed selector hooks for narrow state subscriptions
- Add 14 unit tests covering store initialization, slice behaviors, and batcher timing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>