Commit Graph
59 Commits
Author SHA1 Message Date
ZacharyZhang-NYandClaude Opus 5.5 075dea725a Q143: earlier messages come from the database, page by page, back to the first one
Review limit (5) reached; the last finding (exhaustion latched) is fixed
by taking it from each latest hasMore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:52:22 -04:00
ZacharyZhang-NYandClaude Opus 5.5 87c297dd45 Q141: reply to a specific message in its thread, and see what each reply answers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:01:57 -04:00
ZacharyZhang-NYandClaude Opus 5.5 6e210301db Q136: remove rollback records that marked restores nothing performed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:53:26 -04:00
ZacharyZhang-NYandClaude Opus 5.5 f8f852c326 Q135: remove the thread replay that only digested events and reconstructed nothing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:47:48 -04:00
ZacharyZhang-NYandClaude Opus 5.5 3849b96192 Q133: remove chaos drills that never injected a fault, and the signals they wrote
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:39:36 -04:00
ZacharyZhang-NYandClaude Opus 5.5 e562444487 Q132: remove PR bot gates that no task completion or goal close consulted
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:36:07 -04:00
ZacharyZhang-NYandClaude Opus 5.5 fe45cd4d46 Q131: remove review agents and eval suites whose pass only counted configuration rows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:33:03 -04:00
ZacharyZhang-NYandClaude Opus 5.5 6afd7bef2a Q128: every model call of a run is recorded with its purpose and listed in the run
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 20:55:18 -04:00
ZacharyZhang-NYandClaude Opus 5.5 abfcbf4824 Q114: goal audits use the org's own auditor model and see pointers, not the executor's account
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:35:39 -04:00
ZacharyZhang-NYandClaude Opus 5.5 5aab82b7c3 Q110: an approval pins the content it approved, and later changes show against it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:01:15 -04:00
ZacharyZhang-NYandClaude Opus 5.5 170b977bf8 Q105: the Connectors page grants and revokes connector access
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 17:12:59 -04:00
ZacharyZhang-NYandClaude Opus 5.5 7eef3d459f Q88: a sign-in is saved only if a run can use and renew it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:02:12 -04:00
ZacharyZhang-NYandClaude Opus 5.5 665bf3cae1 Q83: a model passes an agent check before it does agent work
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 14:19:48 -04:00
ZacharyZhang-NYandClaude Opus 5.5 168572dd76 Q63: model calls are priced and agent and department budgets limit real spend
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 11:08:38 -04:00
ZacharyZhang-NYandClaude Opus 5.5 9e1f8da11c Q55: the operator can stop in-flight runs; pause stops them too
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 09:59:03 -04:00
ZacharyZhang-NYandClaude Opus 5.5 ec2698575d Q53: stalled goal reviews leave a visible state and a resume path
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 09:25:46 -04:00
ZacharyZhang-NYandClaude Opus 5.5 5c8233d258 Q31: a Library page to read and manage documents and knowledge
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 06:26:15 -04:00
ZacharyZhang-NYandClaude Opus 5.5 56b0594f91 Move Composio, logo.dev and Antigravity keys into Settings
The three third-party keys were hardcoded or read from the environment.
Operators now enter them in Settings > Integrations; they are stored
encrypted in the app-wide integration_keys table (migration 058).
An agent holding connector grants fails loudly when no Composio key is
saved. The goal-review test no longer depends on absolute dates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 01:34:14 -04:00
ZacharyZhang-NY cb71afa6b7 Avatar photo uploads and a global handbrake for the agent engine
Two operator asks, one review gate:

Avatar portraits (migration 052): the avatar editor gains "Upload
photo" - the renderer downscales the chosen picture to a ~96px cover
crop and stores it as a small data URL (PNG keeps transparency, the
rest compresses to JPEG), so the snapshot stays light and the CSP needs
nothing new. The portrait wins over emoji and initials everywhere the
shared Avatar renders (chat, org chart, office card, sidebar), and
"Remove photo" falls back cleanly. The main process validates scheme
and size (base64 image data URL, <=300k chars) so a rogue caller cannot
re-bloat the snapshot. e2e uploads a real PNG through the profile
dialog and sees the portrait land in the sidebar.

Global pause (migration 053): when agents start talking in circles,
one topbar toggle - visible on every page - pulls the handbrake.
app_state.autorun_paused survives restarts; the queue worker checks it
each tick and neither enqueues nor claims while set (the run already in
flight finishes). Queued work simply waits and the paused state renders
as an amber "resume" pill. A unit test drives the real worker: paused
leaves a queued run untouched through many ticks, resuming claims it
within moments; e2e flips the toggle in the live shell.
2026-07-09 00:09:02 -04:00
ZacharyZhang-NY e55b8b85b0 Make every identity editable: agent and operator names plus avatars
- Migration 049: avatar_emoji/avatar_color on agents and employees
- updateAgent accepts a new name (mention-name validated) and avatar;
  new updateEmployeeProfile renames the operator and sets their avatar
- Avatars are emoji-on-color tiles (renderer CSP blocks remote images);
  an AvatarDirectoryContext built from the snapshot lets the shared
  Avatar component honor custom looks at every call site - chat rows,
  conversation list, org chart, office card, sidebar - without
  threading props through pages
- Team edit dialog gains Name + avatar editor (CEO included); the
  sidebar foot opens an Edit-profile dialog for the operator
- e2e: rename an agent to a new mention handle with an emoji avatar,
  edit the operator profile, both verified in the live shell
2026-07-08 21:33:23 -04:00
ZacharyZhang-NY 86aa6fdb29 Ship skills built-in: bundle the catalogue, assign per hire, force humanizer
Skills no longer come from the user's ~/.agents library - most users have
none, and the CEO branch that compiled the entire catalogue into its
prompt overflowed the model context (1.1MB) and failed every CEO run.

- Bundle "built-in skills/" with the app (extraResources) and stage it
  at startup into <profile>/builtin-skills as one dir-per-skill copy -
  both bundle shapes (SKILL.md dirs and flat category .md files)
  normalize into the same importable layout
- Import the staged catalogue per org at startup and inside onboarding,
  so the CEO's first run already carries it
- Forced house style: resolveRuntimeSnapshot unions the humanizer skill
  into every agent's runtime (CEO included) as a resolution rule - no
  binding row to forget, delete, or bypass; revoke_skill refuses it
- CEO staffs hires with skills: hire_agent accepts a skills array,
  grant_skill/revoke_skill adjust later, list_skills now shows
  descriptions from skill frontmatter
- Kill the c_suite compile-all branch; everyone resolves bindings-only,
  capped at 200k chars with omissions named in the prompt
- Remove the Skills settings page and its import/sync/test IPC surface;
  drop ~/.agents discovery and the AGENTCOMPANY_NEW_SKILLS_ROOT seam in
  favor of AGENTCOMPANY_NEW_BUILTIN_SKILLS_DIR
- Tests: staging/import/forced-resolution/cap units, real-bundle CI
  check, e2e asserts the tab is gone and the catalogue self-imports
2026-07-08 21:18:50 -04:00
ZacharyZhang-NY 3e4c7c81a2 Localize the renderer UI into Chinese behind the language setting 2026-07-07 13:22:19 -04:00
ZacharyZhang-NY d404e1e72a Pin the UI locale to the language setting and add theme + language selectors with a dark palette 2026-07-07 12:28:06 -04:00
ZacharyZhang-NY 38bd3588e7 Connected connectors can be deleted and reconnected; mirror sweeps stale rows and ops serialize per org 2026-07-07 12:09:31 -04:00
ZacharyZhang-NY defe8f12b1 Make the CEO the grant authority: implicit all-access, agent-tool grants, no manual assignment UI 2026-07-07 11:24:28 -04:00
ZacharyZhang-NY 00e05054ca Mirror the Composio project's auth configs as the connector catalog with logo.dev icons 2026-07-07 11:06:07 -04:00
ZacharyZhang-NY 2d43950123 Read skills from the global and workspace .agents/skills directories
- Discover skill directories under ~/.agents/skills and each
  workspace''s .agents/skills; a directory qualifies with a full
  skill.manifest.json or just a SKILL.md, whose manifest is derived
  (frontmatter name or the directory name). Paths resolve per platform
  on Windows, macOS, and Linux.
- Sync at startup for every organization and again when the Skills
  page opens; skills the org already carries are skipped, and one
  broken directory cannot block the rest.
- AGENTCOMPANY_NEW_SKILLS_ROOT points tests at a temporary library
  (overriding USERPROFILE crashes Electron on Windows).
2026-07-07 01:21:33 -04:00
ZacharyZhang-NY 256e0680c6 Ship Composio as a built-in integration and trim Settings
- Resolve the API key from cred.txt at the project root in development
  and the packaged resources directory in production; the file is the
  source of truth, so a rotated key replaces the stored one. Fixes the
  401 packaged builds hit when a stale database key won.
- Remove the user-facing Composio key editor; the key ships with the
  product and is not configurable.
- Remove the Migration console from Settings.
- Remove the Connectors and Home refresh buttons; connector statuses
  sync when the page opens.
2026-07-07 01:20:21 -04:00
ZacharyZhang-NY 07d0b4587d Promote AgentCompany-New to the repository root and retire the old app
The legacy application - its src, tests, landing site, promo assets, docs,
release tooling, CI workflows, and root configs - leaves the tree; it stays
reachable in history. Everything under AgentCompany-New moves up unchanged:
same package name, so the production userData/database path is untouched,
and e2e/build scripts already resolved paths relative to the project. The
developer cred.txt stays gitignored at its new location. Full verify:ci
passes from the new root.
2026-07-07 00:04:13 -04:00
ZacharyZhang-NY 227fd7faf2 refactor(ipc): validate write payloads in preload 2026-04-24 01:31:29 -04:00
ZacharyZhang-NY 710448a75f fix(preload): keep zod out of sandbox bundle 2026-04-22 18:31:24 -04:00
ZacharyZhang-NY 9e712f2746 refactor(ipc): generate preload forwarders from registry 2026-04-22 16:49:02 -04:00
ZacharyZhang-NY ff9a52324e Route work-product clicks through a resolver IPC
Filesystem work products store `external_id` as a workspace-relative
path so artifacts survive a workspace-root move, but the renderer was
handing that relative fragment straight to `shell.openPath`, which
needs an absolute managed path. Clicks flickered into a failed open.

Add a dedicated `openWorkProduct({ companyId, id })` IPC backed by
`resolveWorkProductTarget` on the DB layer. The resolver joins the
work-product row back to its originating task → workspace (or run →
workspace for taskless runs), composes an absolute path, and rejects
any relative fragment that would escape the workspace root. The
renderer now passes the work product's id — path resolution stays on
the main process where the managed-path policy already lives.
2026-04-19 15:05:21 -04:00
ZacharyZhang-NY 0a40c55b3c fix(thread-panel): wire the scoped reply composer to real participants
The thread-panel composer was pinned to `channel="direct"` with no
`directParticipantIds` and no `replyTo`. Clicking reply in a human
review thread sent a message with no recipient and the send button
stayed disabled — a silent dead-end for the entire Co-Founder
review UX.

The fix exposes the thread's participant list to the renderer:

  - `listThreadParticipantsSchema` and the matching IPC channel
    (`agent-company:list-thread-participants`) return the rows from
    `conversation_participants` for a given thread.
  - `threadIntegration.onTaskCreated` / `onApprovalCreated` already
    enrol the owning agent and the virtual user on thread creation,
    so the list is populated without any backfill.
  - `ThreadPanel` loads participants alongside events and forwards
    the agent ids to `MessageComposer.directParticipantIds`. The
    composer's existing `directRecipientId` memo picks the first
    non-board agent, so replies now target the correct agent — or
    surface the "no recipient" notice when the thread has none.

The Board/user member is deliberately excluded from the list the
composer consumes: the composer wants an agent to route to. All
other wiring (wait-state precision, threadId) stays untouched.
2026-04-19 01:19:23 -04:00
ZacharyZhang-NY 6abc1a823f refactor(inbox): derive from snapshot; delete getInbox IPC chain
Sibling refactor to the sidebar-badges cleanup. The inbox aggregates
five item categories (pending approvals, failed runs, budget warnings,
blocked/review tasks, unread company/incident/urgent messages) — every
row is already in `ProfileSnapshot`. The server-side `getInbox`
aggregation (180 lines of SQL + projection) was a redundant second
path.

New: `src/shared/inbox-items.ts::deriveInboxItems(snapshot, companyId)`
produces the same InboxItem[] shape with the same severity ordering
and 24h failed-run window. Pure function, no IPC, no state.

Deleted:
- database/company-crud.ts::getInbox (180-line aggregation)
- database-base.ts::getInbox pass-through
- ipc-core-read-handlers.ts: handler
- preload/index.ts: bridge binding
- shared/contracts/channels.ts: channel name
- shared/contracts/desktop-api/companies.ts: API signature
- state/slices/company.ts: `inboxItems` field, `setInboxItems` action
- useDataLoader.ts: both getInbox call sites (initial snapshot load
  and section-change effect)
- useCompanyController.ts: inbox reset on company switch

OperationsSections now computes `inboxItems` via `useMemo` off the
current snapshot + company id. The snapshot is already company-scoped
at the main/database/snapshot.ts layer when `currentCompanyId` is
non-null; the derivation re-filters defensively so the function works
correctly even for unscoped snapshots.

Tests: 603/603 green. No new tests added — the derivation is a pure
function whose shape is exercised end-to-end by the existing Inbox
component integration.
2026-04-18 21:42:58 -04:00
ZacharyZhang-NY 487f2456ff refactor(badges): derive from snapshot; delete getSidebarBadges IPC chain
Badges were fetched via a dedicated IPC that aggregated counts on the
server, while the same data lived in ProfileSnapshot on the client.
Two paths to the same answer drift whenever one side mutates between
refreshes — the visible symptom being "badge = 1 unread" with an empty
inbox after a message gets marked read in another screen.

Delete the whole server path. Sidebar badges are now derived on the
client from the snapshot via `deriveSidebarBadges(snapshot, companyId)`
in `src/shared/sidebar-badges.ts`. One source of truth; drift is
physically impossible.

Deletions:
- database/company-settings.ts::getSidebarBadges (120-line SQL aggregation)
- database-base.ts::getSidebarBadges pass-through
- ipc-core-read-handlers.ts: handler
- preload/index.ts: bridge binding
- shared/contracts/channels.ts: channel name
- shared/contracts/desktop-api/companies.ts: API signature
- shared/contracts/schemas-badges.ts::sidebarBadgesSchema Zod schema
- renderer/state/slices/company.ts: `badges` field, `setBadges`,
  `refreshBadges`
- useDataLoader: both getSidebarBadges call sites
- useCompanyController: badge reset on company switch
- useDesktopEvents: refreshBadges call on granular patches
- tests/unit/store.test.ts: refreshBadges test (deleted code)

The snapshot's agentMessages already carries board-reader read state
via boardReadReceiptMap (`snapshot.ts:39-47` has always LEFT JOIN'd
agent_message_reads with agent_id = BOARD_READER_ID). So derivation
needs no schema change — the infrastructure was in place, just unused.

fix(communication/MessageList): render orphaned-reply messages at the
top level

The thread-flattening used `filteredMessages.filter(m => !m.parentMessageId)`
to pick top-level messages. When an agent replies to a company/incident
post with a DM (the CEO prompt explicitly instructs this in
wake-reasons/en.ts:119), the DM lands in the direct channel with
parentMessageId pointing to a message that lives in another channel.
That parent is not in `filteredMessages` for the direct channel, so the
reply had no parent to nest under AND was excluded from top-level. The
channel rendered as a blank pane even though exactly one message
matched — the "clicked Dr. X ↔ Dr. Y, got empty" symptom.

Fix: a message is top-level when it either has no parent OR its parent
is outside the current filtered view. Replies with in-view parents
still nest normally.
2026-04-18 21:38:34 -04:00
ZacharyZhang-NY c71d033b0c refactor: prune dead IPC surface and orphaned modules
Drop code that nothing consumed. Verified by full renderer+shared grep:
every removed channel had zero callers via window.agentCompany.* and
zero references from desktop-api types. No backend internal use either —
the database/API-server layers keep their methods, only the IPC exposure
goes.

Removed IPC handlers (26 total):

  Thread CRUD surface (12) — writes happen inside the backend
    createThread, listThreads, addThreadEvent,
    setThreadWaitState, resolveThreadWaitState,
    addParticipant, removeParticipant, listParticipants,
    subscribeThread, unsubscribeThread,
    listSubscriptions, listSubscribedThreads
    (kept reads: getThread, listThreadEvents, listThreadWaitStates)

  Half-implemented features (13)
    saveSecret, listComments, getAgentMetrics, getApiPort,
    listWakeupRequests, listAgentMessages, autoAssignTask,
    listRunEvents, recoveryDismiss,
    getHeartbeatPolicy, setHeartbeatPolicy,
    getRuntimeState, setRuntimeState

  Whole vertical slice: openConnectorAuthTerminal
    IPC handler + channel + preload + DesktopApi type +
    connector-auth-service function + useConnectorCallbacks
    handleLoginConnector + OnboardingContext.onLoginConnector +
    OnboardingWizard wiring. Pi-mono has no CLI auth flow;
    the no-op that "returned false for legacy UI compatibility"
    had no legacy UI left.

Orphaned modules (zero importers in repo):
  src/main/runtime-env.ts
  src/main/database-stale-recovery.ts

Dead schema files (only referenced by their own barrel re-export):
  schemas-participants, schemas-subscriptions, schemas-heartbeat,
  schemas-run-events, schemas-runtime-state, schemas-wakeup

Renderer leftovers:
  .activity-row-enter CSS + its two unreferenced keyframes
  5 orphan i18n keys (app.console, app.refresh, app.expand,
  activity.timeline, auto.trigger) left over from earlier feature
  deletions

Also update two unit tests that mocked openConnectorAuthTerminal in
the RegisterCoreHandlersDependencies pick.
2026-04-17 22:38:10 -04:00
ZacharyZhang-NY f012f8e880 refactor(skills): drop company_skills.markdown column, read from disk via IPC
`company_skills.markdown` stored the full SKILL.md body. The on-disk
file under `profile/skills/{companyId}/{slug}/SKILL.md` is what pi-
coding-agent actually reads via `loadSkills` at runtime. The DB column
was a duplicate — import wrote to both, renderer read from DB. Any
discrepancy between disk and DB was invisible until the agent behaved
differently from what the user saw in SkillDetail.

Disk becomes the single source of truth. DB keeps name / description /
metadata / source info / file inventory — the cheap lookup row. UI reads
SKILL.md content live via a new IPC channel.

## Migration v37 (rebuild company_skills without markdown)

Table-rebuild pattern matching v35/v36: `fn:` form, PRAGMA walk for
drift columns, row-count assertion before DROP, `defer_foreign_keys`
for the `agent_skill_assignments(skill_id)` reference. Indexes
recreated. Idempotent via `schema_migrations` ledger.

Existing DB rows' markdown content is discarded — but the on-disk
SKILL.md files are the authoritative copy, so no user-visible data
loss. Any agent using those skills keeps working; the UI just starts
reading from disk instead of the DB cache.

## Code changes

- `src/main/database/skills.ts`: drop `markdown` from read mapping,
  upsert input type, INSERT column/bind list, ON CONFLICT DO UPDATE.
- `src/shared/types/records-core.ts`: `SkillRecord.markdown` removed.
- `src/main/skills/import.ts` + `import-github.ts`: drop `markdown:`
  from 4 `saveCompanySkill` call sites. Disk-write via
  `materializeSkillFiles` unchanged (it's what the file agent reads).
- `src/main/skills/index.ts`: expose `skillFilesDir` for the new IPC
  handler to resolve `${profile}/skills/${companyId}/${slug}/SKILL.md`.
- `src/shared/contracts/channels.ts` + `schemas-execution.ts` +
  `desktop-api/skills.ts`: new `getSkillMarkdown` channel
  `{ companyId, slug } → DesktopResult<string>`.
- `src/preload/index.ts`: expose `getSkillMarkdown(companyId, slug)`.
- `src/main/ipc-skill-handlers.ts`: handler validates schema, ensures
  company, resolves path, `readFile`, returns content. Fails closed
  with `SKILL_NOT_FOUND` on ENOENT, `SKILL_READ_FAILED` on other
  read errors.
- `src/renderer/components/skills/SkillDetail.tsx`: `useEffect` fetches
  markdown via IPC when the skill detail loads; shows "Loading…" until
  resolved, surfaces read errors. Preserves `stripFrontmatter`.
- Tests: drop `markdown:` from 2 fixture sites
  (`skill-types.test.ts`, `skill-aware-assignment.spec.ts`).

## Verification

- typecheck / lint / 578 tests green
- `grep 'skill\.markdown' src/` → 0 DB-record reads
- `grep '\.markdown\b' src/main/database/skills.ts` → 0
- Remaining `.markdown` references are all `ghSkill.markdown` (GitHub
  fetcher's intermediate struct feeding `materializeSkillFiles` to
  disk) and parameter names in `stripFrontmatter(markdown: string)` /
  fs-writer helpers — none read from a DB row.
2026-04-17 16:22:31 -04:00
ZacharyZhang-NY 5547c29491 update 2026-04-17 14:03:56 -04:00
ZacharyZhang-NY 893a0ddec1 chore(preload): drop stale @planned notes on delete{Task,Goal,Project,Workspace}
Handlers for deleteTask/deleteGoal/deleteProject live in
ipc-core-task-graph-handlers.ts:166-168 (backed by
database/tasks-crud.ts and database/entity-crud.ts), and
deleteWorkspace lives at line 169 (backed by database/workspaces.ts).
The four @planned comments were misleading.
2026-04-16 21:36:55 -04:00
ZacharyZhang-NY 9145572422 update 2026-04-05 20:14:48 -04:00
ZacharyZhang-NY 67c757f481 update 2026-04-04 12:03:50 -04:00
ZacharyZhang-NYandClaude Sonnet 4.6 66158e222e update
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 22:02:28 -04:00
ZacharyZhang-NY 6f1de8047e update 2026-03-30 00:15:21 -04:00
ZacharyZhang-NY 65e85135c1 large update 2026-03-29 14:08:15 -04:00
ZacharyZhang-NY 039c1d117f Merge branch 'worktree-agent-a2f30682'
# Conflicts:
#	.planning/STATE.md
#	src/main/ipc-core-read-handlers.ts
#	src/shared/contracts.ts
2026-03-27 19:40:29 -04:00
ZacharyZhang-NYandClaude Opus 4.6 920a764856 feat(09-01): define granular event types, IPC channels, entity getters, and Zustand patch methods
- Add 5 granular event interfaces (TaskUpdated, RunUpdated, ApprovalUpdated, AgentUpdated, BudgetChanged) to DesktopEvent union
- Add 4 entity getter IPC channels (getTask, getAgent, getRun, getApproval) with Zod validation and company ownership checks
- Add getRun method to AppDatabase following existing getTask pattern
- Add 4 preload bridge methods for entity getters
- Add 8 patch/remove methods and refreshBadges to CompanySlice
- Add selective-ipc.test.ts with exhaustive union type tests
- Extend store.test.ts with 14 patch method tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 19:33:33 -04:00
ZacharyZhang-NY feea5c1fe9 feat(05-02): IPC handlers, preload bridge, and ServiceGraph wiring for budget enforcement
- Create ipc-budget-handlers.ts with 6 budget channel handlers (save/delete/list policies, list/resolve incidents, get status)
- Add budgetService to RegisterDomainHandlersDependencies interface
- Register budget handlers in ipc-domain-handlers.ts composition
- Add BudgetEnforcementService lazy slot in service-graph.ts with getOrCreateBudgetEnforcementService
- Pass budgetService to domain handler registration in main-runtime-support.ts
- Fix preload bridge to pass {companyId} object for listBudgetPolicies and getBudgetStatus
- D-06: checkAutoResolve called on saveBudgetPolicy to auto-resolve incidents on limit increase
2026-03-26 20:57:52 -04:00
ZacharyZhang-NYandClaude Opus 4.6 3a68cfa707 feat(05-01): budget enforcement types, schemas, IPC channels, and database CRUD
- Add BudgetPolicyRecord, BudgetIncidentRecord, BudgetStatusSummary types
- Add 6 IPC channels for budget operations in contracts.ts
- Add Zod schemas for all budget payloads
- Add DesktopApi entries for budget methods
- Add database CRUD: saveBudgetPolicy, deleteBudgetPolicy, listBudgetPolicies,
  getBudgetPolicy, getActivePoliciesForRun, getSpentInWindow (cents aggregation),
  upsertBudgetIncident (D-08 dedup), resolveIncidentsForPolicy,
  resolveWarnIncidentsForPolicy, autoCloseExpiredIncidents
- Update recordRunCompletion to include project_id in cost_entries INSERT
- Add migration 18: convert agent budgetMonthlyUsd to budget_policies rows
- Add preload bridge stubs for budget IPC channels

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:47:20 -04:00
ZacharyZhang-NY 930273ce87 feat(04-02): worker lock release, wake promotion, IPC wakeup channel, and preload bridge
- Add releaseTaskLock to worker crash recovery after finishRun (EXEC-02)
- Track affected agent company IDs for targeted wake promotion
- Replace listWakeupRequests+loop with promoteWakeupRequests+wakeAgentIfPossible in run completion
- Track hadDeferredWakes flag for circuit breaker self-wake decision
- Add listWakeupRequests IPC channel to IPC_CHANNELS
- Add wakeupQuerySchema with Zod validation and WakeupRequestRecord interface
- Add listWakeupRequests to DesktopApi type
- Add listWakeupRequests preload bridge method
- Add registerHandle for listWakeupRequests IPC handler with company validation
2026-03-26 19:16:17 -04:00