Commit Graph
423 Commits
Author SHA1 Message Date
ZacharyZhang-NY a1dd361f51 fix(thread): make wait-state side effects atomic 2026-04-23 19:08:06 -04:00
ZacharyZhang-NY f8a90f4402 fix(checkpoint): fail closed on pause queries 2026-04-23 18:58:06 -04:00
ZacharyZhang-NY a99bcb97c6 fix(worker): fail runs on message persistence errors 2026-04-23 18:55:08 -04:00
ZacharyZhang-NY 17e416d609 update 2026-04-23 15:26:30 -04:00
ZacharyZhang-NY cbef47f1ad Clear repository lint warnings 2026-04-22 20:47:01 -04:00
ZacharyZhang-NY 26c933fad7 Reduce runtime thread system noise 2026-04-22 20:34:16 -04:00
ZacharyZhang-NY a4af4a866a Prevent self-directed agent messages 2026-04-22 20:28:49 -04:00
ZacharyZhang-NY 1a7eb8f1b3 Enable lock-free parallel agent runs 2026-04-22 20:23:44 -04:00
ZacharyZhang-NY d13c9d83e8 Resolve filesystem work product targets by existing file 2026-04-22 20:06:01 -04:00
ZacharyZhang-NY 6da0a58769 refactor(db): group database domain modules 2026-04-22 19:24:25 -04:00
ZacharyZhang-NY e43a89096d refactor(main): audit warning suppression rules 2026-04-22 19:16:22 -04:00
ZacharyZhang-NY a7934d2111 refactor(ipc): split company operation handlers 2026-04-22 19:11:45 -04:00
ZacharyZhang-NY 9d38ec20f1 fix(ipc): expose classified handler codes 2026-04-22 19:07:08 -04:00
ZacharyZhang-NY 1883d9d9d3 fix(errors): warn on raw stringify fallback 2026-04-22 19:04:53 -04:00
ZacharyZhang-NY 7793f2da35 fix(connectors): guard pi provider resolution 2026-04-22 18:58:30 -04:00
ZacharyZhang-NY 0d9f4f15eb refactor(automation): register workflow actions 2026-04-22 18:54:31 -04:00
ZacharyZhang-NY 8148877b4a fix(runtime): preserve inbound correlations for active runs 2026-04-22 18:43:05 -04:00
ZacharyZhang-NY dca148a125 fix(prompt): render skills without pi shape casts 2026-04-22 18:39:56 -04:00
ZacharyZhang-NY 9f35dc7446 fix(runtime): erase pi tool array type safely 2026-04-22 18:37:03 -04:00
ZacharyZhang-NY fa006524c2 refactor(runtime): centralize lifecycle constants 2026-04-22 16:58:36 -04:00
ZacharyZhang-NY e540cbb2a6 refactor(service-graph): replace late bindings with event hub 2026-04-22 16:55:20 -04:00
ZacharyZhang-NY 612a760152 fix(runtime): move team building policy into tools 2026-04-22 16:38:59 -04:00
ZacharyZhang-NY 473486aa61 refactor(runtime): unify run attempt policy 2026-04-22 16:33:41 -04:00
ZacharyZhang-NY 775598ef4c fix(db): make task row state authoritative 2026-04-22 16:24:57 -04:00
ZacharyZhang-NY ebcc15c68d fix(runtime): derive unattributed cost from usage status 2026-04-22 16:18:03 -04:00
ZacharyZhang-NY f107415f4f fix(browser): execute social actions through cdp 2026-04-22 16:14:09 -04:00
ZacharyZhang-NY fb6d2a0d77 fix(runtime): tokenize context compaction budget 2026-04-22 16:00:12 -04:00
ZacharyZhang-NY 3aaa64ddfd refactor(runtime): enforce source file size boundaries 2026-04-22 15:56:09 -04:00
ZacharyZhang-NY 212e03219d fix(artifacts): classify projection filesystem errors 2026-04-22 15:48:00 -04:00
ZacharyZhang-NY eefb515aa2 fix(runtime): classify run usage status 2026-04-22 15:41:19 -04:00
ZacharyZhang-NY f90fb037f9 docs(runtime): separate pi dependency boundary 2026-04-22 14:39:19 -04:00
ZacharyZhang-NY feffd72b98 fix(runtime): run pi tools sequentially 2026-04-22 14:37:35 -04:00
ZacharyZhang-NY 64842a9185 fix(runtime): guard pi stream setup failures 2026-04-22 14:36:16 -04:00
ZacharyZhang-NY 5155136937 fix(api): require api server callbacks 2026-04-22 14:27:49 -04:00
ZacharyZhang-NY 529bb109db fix(runtime): preserve tool result facts in compaction 2026-04-22 14:22:28 -04:00
ZacharyZhang-NY 6dfa1a851d fix(runtime): compact context inside worker 2026-04-22 14:19:46 -04:00
ZacharyZhang-NY 33c6ede381 fix(runtime): fail runs on context input errors 2026-04-22 14:13:59 -04:00
ZacharyZhang-NY 43583ef30b fix(runtime): gate cofounder checkpoints 2026-04-22 14:05:26 -04:00
ZacharyZhang-NY 7a1dd647aa fix(api): make task updates transactional 2026-04-22 14:00:24 -04:00
ZacharyZhang-NY 19f8494d09 fix(db): make filesystem lock intent explicit 2026-04-22 13:51:41 -04:00
ZacharyZhang-NY 0785c9ba47 fix(db): make task checkout atomic 2026-04-22 13:38:54 -04:00
ZacharyZhang-NY dffeccf3e2 update 2026-04-22 13:19:43 -04:00
ZacharyZhang-NY 9fba8dd6c3 fix(projector): stop writing null workspace_id on work_products
Two sites in upsertFilesystemArtifact leaked null workspace_ids
into the work_products table and produced the orphan rows the read
path now has to heal:

1. Create path unconditionally forwarded ctx.workspaceId, which was
   null whenever a run was created without a workspace binding
   (historically cognitive runs, or runs that lost their link through
   the observationPath regression fixed in 1f2f977).

2. Update path passed {workspaceId: ctx.workspaceId} as part of the
   patch. updateWorkProduct treats any key present in patch as "write
   this value", so a run touching a previously-well-linked row with
   ctx.workspaceId=null would clobber the existing workspace_id back
   to null — actively destroying data.

Resolve both at the projector layer:

  - Add workspacesMod.findWorkspaceIdByLocalPath(companyId, localPath)
    as a reverse-lookup. workspacePath is the argument the projector
    is already walking; it came from some workspace row's local_path,
    so finding that row by path is deterministic.
  - Compute resolvedWorkspaceId = ctx.workspaceId ?? reverseLookup(...)
    once, and use it for both the identity lookup
    (findWorkProductByExternalId) and the subsequent write.
  - On the update path, only include workspaceId in the patch when
    resolvedWorkspaceId is non-null. Null now means "no info — leave
    the existing column alone" instead of "clobber to null".

Together with the read-path heal in cfb8ba5 this closes the loop:
new files never enter the table with a null workspace_id if we can
possibly resolve it, old files keep their links, and truly unlinkable
rows still fall back to the observation workspace on open.

Typecheck and build:verify clean.
2026-04-21 14:52:38 -04:00
ZacharyZhang-NY cfb8ba5dc1 fix(docs): heal orphan work_products by falling back to observation workspace
Work-product rows written before the artifact projector tracked
workspace_id end-to-end can lose the link through all three joins:
workspace_id is NULL, task_id is NULL, and the row's run exists but
its runs.workspace_id is also NULL. Those orphans were readable in
the DocumentCenter (the listing doesn't need a workspace root) but
could not be opened — resolveWorkProductTarget returned null and the
toast now reports workspace_unresolved.

Add a fourth resolution tier in resolveWorkProductTarget: if the
three-step chain yields nothing, look up the company's observation
workspace (primary first, then oldest) and check whether the
external_id resolves to a real file inside that root. If it does,
return that absolute path and the row opens. If the file isn't
there, the error falls through with an extended detail line naming
the observation root that was tried, so the operator sees exactly
why the heal also failed.

This is deterministic — exactly one fallback workspace — and
side-effect-free on the read path: the row itself is left alone,
no stealth write-back. A follow-up commit will stop the projector
from writing NULL workspace_id in the first place.

Typecheck and build:verify clean.
2026-04-21 14:51:06 -04:00
ZacharyZhang-NY 390f76fa76 fix(docs): split work-product open errors into actionable reasons
The previous handler folded every null target into one error code
("WORK_PRODUCT_NOT_FOUND: Work product not found or its workspace
is unresolved"). When a user couldn't open a file we had no way to
tell whether the row was archived, the provider/external_id was
empty, the workspace had no local_path, or the external_id escaped
the root.

Widen resolveWorkProductTarget's return from (target | null) to
(target | error) where error carries one of five reasons:

  not_found             row missing for id+company
  archived              status == "archived" tombstone
  no_target             provider != filesystem and no url
  workspace_unresolved  all three workspace_id / task_id / run_id
                         lookups returned no local_path
  path_escape           external_id is absolute or steps outside root

Each reason includes the concrete detail (ids checked, paths tried)
so the toast on the renderer side tells the user exactly which slot
is null without having to open the DB.

The IPC handler maps each reason to its own failure code and passes
the detail through, so WorkProductRow's toast now reads e.g.
"workspace_id=null task_id=null run_id=null — none led to a
workspace with a local_path" instead of a generic unresolved.

Typecheck and build:verify clean.
2026-04-21 14:45:59 -04:00
ZacharyZhang-NY 95c4b0ae48 refactor(design): migrate hardcoded colors to kami tokens
Purge remaining hardcoded color values from the component layer and main
process so every surface flows through the kami token system.

src/main/desktop-shell-window.ts
  - BrowserWindow.backgroundColor no longer paints pure white before the
    renderer mounts. It now picks kami parchment (#F5F4ED) or deep-dark
    (#141413) based on nativeTheme.shouldUseDarkColors so the startup
    flash respects the user's OS theme preference.

src/shared/constants.ts
  - DEPARTMENT_COLORS collapses 12 unrelated hex brand colors (violet,
    red, green, cyan, pink, ...) into six kami tokens: var(--primary),
    var(--kami-ink), var(--kami-dark-warm), var(--kami-charcoal),
    var(--kami-olive), var(--kami-stone). Departments are distinguished
    by warm-neutral ramp + ink-blue, never by second chromatic hue.

src/renderer/components/communication/{MessageItem,SearchResults}.tsx
  - Replace the string-concat tint pattern `${color}18` with
    color-mix(in oklab, ${color}, transparent 91%). The old pattern
    produced invalid CSS (e.g. `var(--primary)18`) whenever `color`
    was a CSS custom property, silently falling back to no background.
    color-mix works for both hex and var() inputs, eliminating the
    latent bug at the source.

src/renderer/components/ui/ActionButton.tsx
  - Replace hand-rolled rgba(74,93,122,0.35) and rgba(220,53,69,0.3)
    drop shadows with kami ring shadows routed through color-mix over
    var(--primary) and var(--destructive).

src/renderer/views/CommandPaletteView.tsx
  - Replace rgba(15,23,42,0.08) cold-slate shadow with a kami whisper
    shadow driven by color-mix over var(--foreground).

src/renderer/components/skills/SkillAgentToggles.tsx
src/renderer/components/execution/ModelManagementShared.tsx
  - Toggle thumbs switch from bg-white to bg-background so they
    inherit parchment in light mode and deep-dark in dark mode,
    removing the last pure-white surfaces from the renderer.

Third-party brand hex values in src/renderer/components/social/
social-config.ts are retained: they represent external brand identity
(Twitter blue, YouTube red, ...), not kami chrome, and collapsing them
to one hue would destroy recognition.

Typecheck clean. No business-logic signatures changed.
2026-04-21 13:38:06 -04:00
ZacharyZhang-NY 97033dfabd update 2026-04-21 12:44:33 -04:00
ZacharyZhang-NY 3353e46067 Backfill existing workspace files into work_products on first boot after observationPath fix
The 1f2f977 hotfix repairs the projector for new runs, but files that
already exist on disk before the fix lands stay invisible to the
DocumentCenter — a baseline+diff projector reports "changed" only
when a file's mtime advances past the run-start baseline, and a
quiescent file written before the fix never advances.

This commit adds a bootstrap-time one-shot rescan:

- New module `bootstrap/backfill-workspace-artifacts.ts` walks the
  primary/oldest workspace of every company exactly once (gated by
  `artifact_rescan_v1_done` in the settings table), applies the same
  registrability filter as `artifact-projector.ts` (skip .git/,
  node_modules/, .DS_Store, .lock/.log/.map; ignore package-lock.json
  / pnpm-lock.yaml / yarn.lock; cap at 5 000 files per workspace),
  and upserts a `work_products` row via `findWorkProductByExternalId`
  → `createWorkProduct` for any file the projector never registered.
- bootstrap-application.ts wires the call after recoverScheduledPosts
  (DB ready, services running, before the first heartbeat tick), so
  the rescan completes in the same boot tick that the user opens
  the DocumentCenter.

Idempotency: subsequent boots short-circuit on the settings flag.
The post-fix projector handles all future file activity inside
each run, so the backfill never needs to run twice. Per-workspace
file cap prevents a pathological tree from locking the bootstrap
path; overflow files are still picked up by the next run that
touches them. No fallback, no mock — files that fail stat are
silently skipped (same policy as the projector).

typecheck green, 543/543 unit tests, 10/10 eval. The user's 19
existing markdown deliverables under ~/Documents/Github/test/
should appear in the DocumentCenter on the next `pnpm dev`.
2026-04-20 16:25:48 -04:00
ZacharyZhang-NY 1f2f9770a6 Hotfix: separate workspace observation from lock claim — restore artifact projector for cognitive runs
Production regression of T1 (7829acc..15e3863). User reports "明明生成
了很多文件,但只有一个" — the filesystem shows 19 markdown deliverables
in ~/Documents/Github/test/{business-plan,operations,ceo-coordination}/
but the DocumentCenter surfaces only one row.

Root cause is structural, predicted in spirit by Karpathy's Round 1
take ("把'认知'和'执行'两件事一起锁是数据结构错"). The T1 rewrite
collapsed two concerns into one nullable field on the run context:

  workspacePath = workspace?.localPath ?? null
                  ^^^^^^^^^                ^^^^
                  lock target              observation root

For lockMode='none' (every cognitive C-suite agent post-T1) the
resolver returns workspace=null, so workspacePath was null, so
artifact-projector.ts:242 short-circuited every projection with
`{ kind: "skipped", reason: "no_workspace" }`. The agents kept
writing files via bash (cwd falls back to the company default
workspace at worker/runtime/index.ts:142), but nothing observed
them — the DocumentCenter only saw the one file that was projected
back when the agent still held an exclusive workspace.

Fix: split the two concerns. WorkspaceResolution gains a non-lock
`observationPath` field; the resolver populates it from the company
primary workspace (new `getCompanyObservationWorkspace` query —
primary first, oldest second, null only when company has zero
workspace rows) for lockMode='none' runs, and from `workspace.localPath`
itself for lockMode='exclusive' runs. RunDispatchParams threads the
field through; turn-context's `workspacePath` reads it first.
artifact-projector.ts is unchanged — it just sees a non-null path
again and resumes baselining, diffing, and upserting work_products
rows the way it did pre-T1.

Three new unit tests pin the regression: cognitive role with
workspace ⇒ observationPath set; cognitive role with no workspace ⇒
observationPath null; exclusive ⇒ observationPath equals
workspace.localPath. typecheck green, 543/543 unit tests, 10/10
eval. No fallback, no mock, no silent degradation.
2026-04-20 16:22:40 -04:00
ZacharyZhang-NY e15bf67c9f Workspace concurrency review iteration: Jobs's 3 taste asks
Closes the three specific_asks from Jobs's T1 review of the workspace
architecture fix (7829acc..15e3863):

1. docs/architecture/workspace-concurrency.md: decision table
   upgraded from a code block to a real Markdown table so it reads
   consistently with the failure-modes table lower in the file.

2. docs/architecture/workspace-concurrency.md + resolve-workspace.ts:
   added "Sunset coding-role inference" section and a TODO marker on
   CODING_ROLE_PATTERN tying the regex to the v52 transition window
   (target 2026-05-20). Both documents now name the end-state
   explicitly so a future engineer knows why the regex exists and
   when it dies.

3. resolve-workspace.ts: enriched the WorkspaceConfigurationError
   message to include taskId / agentId / projectId alongside the
   existing companyId, so a misconfigured setup points operators at
   the offending row instead of just the company.

No behaviour change, no fallback, no mock. typecheck green, 540 unit
tests green, 10 eval tests green.
2026-04-20 15:40:46 -04:00