Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
252 commits
Select commit Hold shift + click to select a range
eb9bd2a
feat(dsh): register the dsh agent type, config, and model catalog
niiyeboah Sep 4, 2026
3ad34a2
feat(dsh): agent_stream_events table and StreamStore
niiyeboah Sep 4, 2026
af43f6c
feat(dsh): assistant and activity chat feed entries from stream rows
niiyeboah Sep 4, 2026
8b9b5ed
feat(dsh): per-agent profile overlay builder
niiyeboah Sep 4, 2026
92fbdc3
feat(dsh): ACP driver with one child process per agent
niiyeboah Sep 4, 2026
1ee3298
feat(dsh): fold ACP updates into stream rows and token usage
niiyeboah Sep 4, 2026
f9974f0
feat(dsh): supervisor starts, prompts, and stops dsh from the agent l…
niiyeboah Sep 4, 2026
69ddd84
feat(dsh): deliver prompts and messages to dsh over ACP instead of th…
niiyeboah Sep 4, 2026
8cb3dc5
feat(dsh): render assistant text and tool activity in the Chat tab
niiyeboah Sep 4, 2026
24cef19
fix(dsh): serialize stream event handling per agent
niiyeboah Sep 4, 2026
d849111
test(dsh): end-to-end against a fake ACP dsh shim
niiyeboah Sep 4, 2026
533a97f
feat(dsh): chat envelope tells stream-driven agents their replies are…
niiyeboah Sep 4, 2026
3d912d6
fix(dsh): harden the harness process path from review
niiyeboah Sep 4, 2026
e3409a6
fix(dsh): Chat tab rendering from UX review, plus three reviewer nits
niiyeboah Sep 4, 2026
caafb07
fix(dsh): keep the fade-in version stable while a stream row grows
niiyeboah Sep 4, 2026
ffe8559
Release v0.38.7-dsh.1
niiyeboah Sep 4, 2026
f47fbdd
fix(dsh): one header per tool run in the Chat feed
niiyeboah Sep 4, 2026
566612e
fix(dsh): restore after listen, launch prompt as first turn, key-awar…
niiyeboah Sep 4, 2026
93d2814
fix(dsh): model picker, Chat view, and icon for dsh agents
niiyeboah Sep 4, 2026
a81ee96
fix(dsh): no double reply, tool kinds from names, usage gap noted
niiyeboah Sep 4, 2026
d3f8531
fix(dsh): treat an explicit "other" tool kind as missing
niiyeboah Sep 4, 2026
a649336
docs: harness view spec, PromptKit's stream in Dispatch's tokens
niiyeboah Sep 5, 2026
abd096c
docs: implementation plan for the Harness view
niiyeboah Sep 5, 2026
a951820
feat(harness): turn rows in the stream with the parsed prompt source
niiyeboah Sep 5, 2026
08a0d7a
feat(harness): assemble HarnessTurn[] from stream rows
niiyeboah Sep 5, 2026
9fceb99
feat(harness): GET /api/v1/agents/:id/harness/turns
niiyeboah Sep 5, 2026
9d33d90
feat(harness): port PromptKit contracts, reducer and primitives onto …
niiyeboah Sep 5, 2026
dd6dcbb
feat(harness): Harness view for Dispatch Harness agents in the Agent …
niiyeboah Sep 5, 2026
d92e68f
test(harness): Harness view end to end; open Dispatch Harness agents …
niiyeboah Sep 5, 2026
b540397
test(release): expect no packaged-version tag for a prerelease root v…
niiyeboah Sep 5, 2026
77a441b
Release v0.38.7-dsh.2
niiyeboah Sep 5, 2026
1c0a8b9
fix(harness): refetch Harness turns on every path the Chat feed refet…
niiyeboah Sep 5, 2026
457c374
Release v0.38.7-dsh.3
niiyeboah Sep 5, 2026
9751eaf
feat(harness): tool input on steps, Harness-only pane, slash menu ove…
niiyeboah Sep 5, 2026
e40e048
Release v0.38.7-dsh.4
niiyeboah Sep 5, 2026
9e821c8
feat(harness): /model picker with reasoning effort, live model catalo…
niiyeboah Sep 5, 2026
06de18c
Release v0.38.7-dsh.5
niiyeboah Sep 5, 2026
c1c8137
fix(harness): carry dsh's empty-valued "provider default" effort thro…
niiyeboah Sep 5, 2026
95f7b7c
Release v0.38.7-dsh.6
niiyeboah Sep 5, 2026
18461ee
fix(harness): give a dsh agent its initial prompt as the first turn
niiyeboah Sep 5, 2026
5917d97
Release v0.38.7-dsh.7
niiyeboah Sep 5, 2026
b00640c
feat(harness): highlighted step details, Dispatch notices, grouped 5.…
niiyeboah Sep 5, 2026
de789ff
Release v0.38.7-dsh.8
niiyeboah Sep 5, 2026
6e9cb12
fix(harness): keep dsh's paging note out of read blocks; name the Ope…
niiyeboah Sep 5, 2026
8a7990f
Release v0.38.7-dsh.9
niiyeboah Sep 5, 2026
4293deb
fix(harness): no nested scrollbars in detail blocks
niiyeboah Sep 5, 2026
6cb3b55
Release v0.38.7-dsh.10
niiyeboah Sep 5, 2026
e5e0b4f
feat(harness): colour notice labels against their values
niiyeboah Sep 5, 2026
993210f
Release v0.38.7-dsh.11
niiyeboah Sep 5, 2026
f1c1636
fix(dsh): lifecycle edges from review #294
niiyeboah Sep 5, 2026
bfc2ca7
Release v0.38.7-dsh.12
niiyeboah Sep 5, 2026
d6e7abd
fix(dsh): job runs get the job MCP route, token and guidance
niiyeboah Sep 5, 2026
b4e0f88
Release v0.38.7-dsh.13
niiyeboah Sep 5, 2026
dcb62bb
feat(harness): starting state with the Dispatch bars; keep the sessio…
niiyeboah Sep 5, 2026
1924b0a
Release v0.38.7-dsh.14
niiyeboah Sep 5, 2026
218d1cd
feat(harness): pane-wide drops, media previews, and agent question cards
niiyeboah Sep 5, 2026
0941fb2
Release v0.38.7-dsh.15
niiyeboah Sep 5, 2026
af34a1c
feat(dsh): the Console pane shows the agent's command log above a shell
niiyeboah Sep 5, 2026
364f5e1
Release v0.38.7-dsh.16
niiyeboah Sep 5, 2026
cf9cea8
feat(harness): label settled turns with what happened
niiyeboah Sep 5, 2026
05ba2aa
Release v0.38.7-dsh.17
niiyeboah Sep 5, 2026
d7e6ab4
docs(harness): session handoff note with the queue and slash-menu tasks
niiyeboah Sep 5, 2026
eca9e00
feat(harness): show what waits behind a running turn, and open the sl…
niiyeboah Sep 5, 2026
9ab737c
Release v0.38.7-dsh.18
niiyeboah Sep 5, 2026
b690d2c
docs(harness): record that the queue and slash-menu tasks shipped in …
niiyeboah Sep 5, 2026
933416c
feat(harness): open subagents in place, pin the task list, show key u…
niiyeboah Sep 6, 2026
73e1f32
Release v0.38.7-dsh.19
niiyeboah Sep 6, 2026
e4b9f53
docs(harness): record dsh.19 in the handoff note
niiyeboah Sep 6, 2026
6e140e3
fix(harness): name the usage month in UTC and keep system reminders o…
niiyeboah Sep 6, 2026
e582672
Release v0.38.7-dsh.20
niiyeboah Sep 6, 2026
b3dc517
feat(settings): set usage budgets per provider in Settings, not env vars
niiyeboah Sep 6, 2026
3d35514
Release v0.38.7-dsh.21
niiyeboah Sep 6, 2026
21b75a1
fix(harness): keep the rail moving while the model thinks
niiyeboah Sep 6, 2026
9faefb6
Release v0.38.7-dsh.22
niiyeboah Sep 6, 2026
8668eb8
feat(harness): survive a restart, stop a turn, recall prompts with th…
niiyeboah Sep 6, 2026
d3244a9
Release v0.38.7-dsh.23
niiyeboah Sep 6, 2026
0b4452e
fix(harness): act on the five persona reviews of the dsh.18–dsh.23 work
niiyeboah Sep 6, 2026
70c5e84
feat(harness): show goal rounds as turns and a Goal strip; provider l…
niiyeboah Sep 6, 2026
81cdbca
Release v0.38.7-dsh.24
niiyeboah Sep 6, 2026
de32ef3
fix(harness): read the pre-restart status before start() overwrites i…
niiyeboah Sep 6, 2026
ed6b241
Release v0.38.7-dsh.25
niiyeboah Sep 6, 2026
241b88e
docs(harness): handoff note for dsh.25 and the goal-strip verification
niiyeboah Sep 6, 2026
52a6f16
chore: ignore bun build outputs
niiyeboah Sep 6, 2026
3430dbd
refactor(harness): drop the unused PromptKit reducer
niiyeboah Sep 6, 2026
2be8ca5
refactor(harness): put doc comments on the symbols they describe
niiyeboah Sep 6, 2026
6bfc58a
style(harness): American spelling and no em-dashes in this branch's c…
niiyeboah Sep 6, 2026
963fdab
fix(harness): review a Dispatch agent with a Dispatch reviewer by def…
niiyeboah Sep 6, 2026
743221a
feat(harness): say when a turn was interrupted instead of calling it …
niiyeboah Sep 6, 2026
f52a42f
Release v0.38.7-dsh.26
niiyeboah Sep 6, 2026
87eb661
docs(harness): record dsh.26 and the pull request in the handoff note
niiyeboah Sep 6, 2026
df4d260
docs(harness): a restart cuts a running Dispatch Harness turn; say so
niiyeboah Sep 6, 2026
5fef2a1
feat(harness): the agent type is dispatch, not dsh
niiyeboah Sep 6, 2026
f2f4fec
test(e2e): keep provider keys out of the E2E server
niiyeboah Sep 6, 2026
7473b1b
Improve agent turn recovery and question cards
niiyeboah Sep 7, 2026
ac441e0
Avoid automatic replay after agent restart
niiyeboah Sep 7, 2026
5066e9e
feat(harness): run the Dispatch Harness on a ChatGPT plan, not only a…
niiyeboah Sep 7, 2026
d384cd2
test(web): cover the ChatGPT plan row in the usage dialog
niiyeboah Sep 7, 2026
820bb64
Polish Markdown question card rendering
niiyeboah Sep 7, 2026
4bb7be1
feat(harness): "@" opens a path picker in the composer
niiyeboah Sep 7, 2026
0326e10
feat(harness): open a running step on its input until the result lands
niiyeboah Sep 7, 2026
464e3c5
Render option answer replies consistently
niiyeboah Sep 7, 2026
f3a931b
Preserve chat row memoization
niiyeboah Sep 7, 2026
57086a6
Match answer replies through question state
niiyeboah Sep 7, 2026
44fb638
fix(web): one token menu for "/" and "@", a picker that tracks the fi…
niiyeboah Sep 7, 2026
c08abd2
refactor(harness): one provider registry for auth, usage, and budgets
niiyeboah Sep 7, 2026
e63b003
fix(web): fold a settling step on the body it was open on
niiyeboah Sep 7, 2026
f1a103f
Release v0.38.7-dsh.27
niiyeboah Sep 7, 2026
9b6baff
fix(web): show which menu row the arrows are on, and paint @paths in …
niiyeboah Sep 7, 2026
6be1d54
Merge branch 'agt_6339c269c9db/agent-69c9db' into the Dispatch Harnes…
niiyeboah Sep 7, 2026
7a7e585
Release v0.38.12-dsh.28
niiyeboah Sep 7, 2026
ec49227
fix(harness): boot past the renumbered migrations, and a stream event…
niiyeboah Sep 7, 2026
ebddeae
fix(web): paint the field once, keep the menu's last rows visible, dr…
niiyeboah Sep 7, 2026
fb89c00
fix(server): keep the ACP dependency the fold dropped; mirror follows…
niiyeboah Sep 7, 2026
ce84e99
Release v0.38.12-dsh.29
niiyeboah Sep 7, 2026
4941af4
Merge remote-tracking branch 'origin/main' into dsh-harness-deploy
niiyeboah Sep 7, 2026
9053072
docs: design spec for the Dispatch Harness on four ACP engines
niiyeboah Sep 7, 2026
85da8c8
docs: implementation plan 1 (server) for the harness engines
niiyeboah Sep 8, 2026
6f044b5
docs: implementation plans 2 (web) and 3 (e2e, docs, release) for the…
niiyeboah Sep 8, 2026
bed808c
refactor(server): rename the dsh module and identifiers to harness
niiyeboah Sep 8, 2026
51493dd
chore: approve native builds for pnpm 11
niiyeboah Sep 8, 2026
9f5f459
feat(db): collapse the harness migrations to one guarded pair
niiyeboah Sep 8, 2026
7ee9945
docs: plan 1 corrections from the task 2 review and the shared-types …
niiyeboah Sep 8, 2026
b2b1a7e
feat(shared): harness engine registry, commands, plan and usage types
niiyeboah Sep 8, 2026
ef63f1f
feat(harness): engine table for claude, codex, gemini and opencode
niiyeboah Sep 8, 2026
9663d36
docs: plan 1 task 5 keeps advertised commands in a shared holder, lik…
niiyeboah Sep 8, 2026
54f8540
feat(harness): drive any engine spec over ACP
niiyeboah Sep 8, 2026
bb9c899
feat(harness): record plans, usage and nested tool calls
niiyeboah Sep 8, 2026
543c12b
feat(harness): nest subagent steps and carry plan and usage on turns
niiyeboah Sep 8, 2026
332621a
feat(harness): pick the engine from the model id and deliver the pers…
niiyeboah Sep 8, 2026
054e238
docs: plan 1 task 8 corrections from review
niiyeboah Sep 8, 2026
fbe5910
feat(harness): commands route and a usage report by engine
niiyeboah Sep 8, 2026
fdea8c9
docs: plan 1 task 9 carries the server.ts route wiring
niiyeboah Sep 8, 2026
f15b676
feat(server): engine binaries in config, engine-prefixed catalog, har…
niiyeboah Sep 8, 2026
91d94ae
refactor(harness): delete the dsh-only modules
niiyeboah Sep 8, 2026
729ffd7
docs: plan 3 task 3 owns the 0012 manifest parse error
niiyeboah Sep 8, 2026
0dd96c6
docs: plan 2 task 5 uses a neutral unknown-engine fixture
niiyeboah Sep 8, 2026
745276c
feat(web): carry plan, usage and nested steps into the harness turn m…
niiyeboah Sep 8, 2026
0db4b9f
feat(web): feed the tasks strip from the engine's plan
niiyeboah Sep 8, 2026
76e5440
feat(web): render a subagent's steps nested under its parent step
niiyeboah Sep 8, 2026
c96a397
feat(web): slash menu from the engine's advertised commands
niiyeboah Sep 8, 2026
bb5d3f3
Merge origin/main: pnpm 10+ hoist and build settings
niiyeboah Sep 8, 2026
293f6b6
feat(web): engine marks on the model chip, disabled with a reason whe…
niiyeboah Sep 8, 2026
cabaf45
fix(web): keep the model picker's selects disabled until the engine p…
niiyeboah Sep 8, 2026
6d0a616
feat(web): usage and budgets by engine
niiyeboah Sep 8, 2026
37294df
feat(web): login hint from the engine table, and the dsh-era shared t…
niiyeboah Sep 8, 2026
5e1c24b
feat(harness): say which engine is not logged in, and how to fix it
niiyeboah Sep 8, 2026
9de64c3
feat(web): a harness icon, the brand mark in a ring
niiyeboah Sep 8, 2026
d6c7763
feat(web): harness motion tokens, reduced-motion config, staggered rows
niiyeboah Sep 8, 2026
2f08ec9
feat(web): the turn fold, status word and queue move on the motion to…
niiyeboah Sep 8, 2026
bc3cffa
feat(web): tasks strip, chip label and starting screen on the motion …
niiyeboah Sep 8, 2026
fb2e967
fix(web): keep the composer mounted through the handoff, and key todo…
niiyeboah Sep 8, 2026
dfe5570
chore(web): sweep the last dsh-era words and em-dashes out of the har…
niiyeboah Sep 8, 2026
aca5365
test(e2e): one fake ACP agent that speaks all four engine dialects
niiyeboah Sep 8, 2026
0822947
test(e2e): drive the harness once per engine against the fake ACP agent
niiyeboah Sep 8, 2026
e39378e
docs: the Dispatch Harness engines for operators
niiyeboah Sep 8, 2026
33c2fb0
test(web): cover the /usage slash command opening the usage dialog
niiyeboah Sep 8, 2026
4e110cd
Release v0.38.13-harness.1
niiyeboah Sep 8, 2026
a3e1b7b
fix(db): forget the migration records earlier prereleases wrote
niiyeboah Sep 8, 2026
906d09f
fix(harness): give an agent with no model the default engine
niiyeboah Sep 8, 2026
524cf2f
perf(harness): coalesce the publish a streamed update drives
niiyeboah Sep 8, 2026
49f948e
perf(harness): keep the turn model and the edit diff off the render path
niiyeboah Sep 8, 2026
d6445fd
fix(harness): narrow the Claude logged-out reply to the start of a turn
niiyeboah Sep 8, 2026
8f9dd58
fix(harness): run the live harness spec, withhold provider keys, skip…
niiyeboah Sep 8, 2026
3794d61
chore(harness): cover a non-USD cost and drop a prop nothing passes
niiyeboah Sep 8, 2026
ea8454c
chore(harness): reword the env deny comment to keep the branch grep c…
niiyeboah Sep 8, 2026
56e2e11
test(e2e): re-enable the terminal type before each live terminal test
niiyeboah Sep 8, 2026
9e68eb4
fix(harness): keep restart cuts and queued chat honest
niiyeboah Sep 8, 2026
f273c74
fix(db): carry every old type value over, and tell rollback the truth
niiyeboah Sep 8, 2026
6d2bce1
test(harness): cover the login anchor with no tool call in the turn
niiyeboah Sep 8, 2026
7604e86
fix(dev): stop the dev servers through the process that owns the port
niiyeboah Sep 8, 2026
ae4e578
fix(dev): give the API server its full graceful shutdown before forci…
niiyeboah Sep 8, 2026
6ab8ea2
fix(dev): only stop a port owner that belongs to this stack, and expl…
niiyeboah Sep 8, 2026
01fdf61
fix(dev): match the stack by path prefix, and keep down going after a…
niiyeboah Sep 8, 2026
4adae28
Merge origin/main: feedback card action hook
niiyeboah Sep 8, 2026
9c05860
Release v0.38.13-harness.2
niiyeboah Sep 8, 2026
142735b
fix(boot): repair the kind check, promote early, kill every straggler
niiyeboah Sep 8, 2026
89e7cb8
fix(harness): close the server-side gaps the reviews found
niiyeboah Sep 8, 2026
5191cf0
fix(web): answer the frontend and product review of the harness views
niiyeboah Sep 8, 2026
d9b0510
fix(dev): identify a stack by its own marker, and wait for Vite's port
niiyeboah Sep 8, 2026
adddbce
docs(release): say what a rollback and a restart do to a harness agent
niiyeboah Sep 8, 2026
76f88f9
fix(dev): stop charging every up for the Vite owner check
niiyeboah Sep 8, 2026
c804987
fix(dev): keep --no-db usable when the API cannot bind
niiyeboah Sep 8, 2026
6f0945c
docs(release): name the real tmux session shape, and four review nits
niiyeboah Sep 8, 2026
01b7bba
Release v0.38.13-harness.3
niiyeboah Sep 8, 2026
192d17f
docs(spec): fold harness turns into the chat feed
niiyeboah Sep 9, 2026
f98b10f
docs(spec): record the one-feed decisions (Q1 keep Console, Q2 pinned…
niiyeboah Sep 9, 2026
35fc8aa
docs(plan): one feed, plan 1 of 4, the Dispatch Harness flag
niiyeboah Sep 9, 2026
e8c576e
feat(server): add the dispatch harness settings flag
niiyeboah Sep 9, 2026
a9b9748
refactor(server): trim wordy comments on the harness flag
niiyeboah Sep 9, 2026
3a39fc6
feat(server): keep dispatch out of the enabled agent types
niiyeboah Sep 9, 2026
7d1660a
refactor(server): trim restating comments on the enabled-types sanitizer
niiyeboah Sep 9, 2026
e207f21
feat(server): add getOfferedAgentTypes
niiyeboah Sep 9, 2026
582fe67
docs(plan): one feed, plan 2 of 4, turn entries in the chat feed
niiyeboah Sep 9, 2026
4227e8d
fix(server): gate agent creation on the offered types
niiyeboah Sep 9, 2026
1c062a8
fix(server): gate agent and persona launches on the offered types
niiyeboah Sep 9, 2026
e75ef14
docs(plan): one feed, plan 3 of 4, ChatPane is the dispatch agent's pane
niiyeboah Sep 9, 2026
a316b89
docs(plan): add the comment rule to plan 1's constraints
niiyeboah Sep 9, 2026
d2b8a8d
refactor(server): read the offered types in the last two gates
niiyeboah Sep 9, 2026
2d406c5
refactor(web): extract the server flag setting hook
niiyeboah Sep 9, 2026
2985319
test(server): make the harness exclusion in the update picker load-be…
niiyeboah Sep 9, 2026
06e25f0
feat(web): read the dispatch harness flag
niiyeboah Sep 9, 2026
3e258f8
docs(plan): fix the fold label in plan 2 and two dead assertions in p…
niiyeboah Sep 9, 2026
7e39562
docs(plan): one feed, plan 4 of 4, retire the parallel path
niiyeboah Sep 9, 2026
9ab72d2
feat(web): add the dispatch harness settings card
niiyeboah Sep 9, 2026
e1685a6
feat(web): offer the harness type from its flag
niiyeboah Sep 9, 2026
901fb66
docs(plan): apply the plan 4 review notes
niiyeboah Sep 9, 2026
37fad67
test(e2e): turn the harness on through its own endpoint
niiyeboah Sep 9, 2026
0da4ab2
refactor(server): move the feed's cursor primitives into feed-cursor.ts
niiyeboah Sep 9, 2026
aded5a9
docs(plan): drop the non-compiling turn case from plan 2 task 1
niiyeboah Sep 9, 2026
7df5e6f
feat(shared): add the turn feed entry and move the assembler into chat/
niiyeboah Sep 9, 2026
f35f201
feat(server): compose turn feed entries by anchor row
niiyeboah Sep 9, 2026
6e58b56
feat(server): serve harness turns in the chat feed
niiyeboah Sep 9, 2026
15aec8b
fix(server): answer the task 2 review's three important findings
niiyeboah Sep 9, 2026
c33ba48
feat(server): serve the harness queue on its own route
niiyeboah Sep 9, 2026
132b9a4
feat(server): publish the live turn as one chat.entry per flush
niiyeboah Sep 9, 2026
6e62047
refactor(web): move the turn components under chat/turn/
niiyeboah Sep 9, 2026
37a3ada
feat(web): render a harness turn as one feed entry
niiyeboah Sep 9, 2026
f3347a1
feat(web): dispatch turn entries in the chat feed
niiyeboah Sep 9, 2026
199b88d
feat(web): read the harness queue from its own cache
niiyeboah Sep 9, 2026
2157e06
refactor(shared): drop the flat assistant and activity feed entries
niiyeboah Sep 9, 2026
a5e626a
feat(web): derive the harness chrome from the chat feed
niiyeboah Sep 9, 2026
91b5394
feat(web): put the harness chrome in the chat composer region
niiyeboah Sep 9, 2026
06c984c
feat(web): give the chat composer the harness keys and menus
niiyeboah Sep 9, 2026
4a92605
fix(web): give a dispatch agent the same pane as every other type
niiyeboah Sep 9, 2026
a8549bd
refactor(web): delete the harness pane and its question card
niiyeboah Sep 9, 2026
4c9db5a
test(e2e): point the harness spec at the chat pane
niiyeboah Sep 9, 2026
2652f2b
test(e2e): cover a dispatch agent's one feed in the default suite
niiyeboah Sep 9, 2026
b3cb686
refactor(web): delete the harness turns query and its invalidations
niiyeboah Sep 10, 2026
d81b3dc
fix(web): drop a turn's prompt row from the cached feed
niiyeboah Sep 10, 2026
c274668
perf(web): stop refetching the chat feed per streamed chunk
niiyeboah Sep 10, 2026
381b345
refactor(server): delete the harness turns endpoint
niiyeboah Sep 10, 2026
09dc233
refactor(shared): delete the HarnessTurn wire types
niiyeboah Sep 10, 2026
22fa768
refactor(web): stop exporting ResultText
niiyeboah Sep 10, 2026
eeb14e5
docs(release): note the harness folding into the Chat feed
niiyeboah Sep 10, 2026
bdf3e94
refactor: answer four findings from the architecture review
niiyeboah Sep 10, 2026
784bb2a
fix(server): index the feed anti-join and serialize the turn publish
niiyeboah Sep 10, 2026
398bbbc
fix: follow a live turn, recall only your own prompt, gate every create
niiyeboah Sep 10, 2026
3166265
fix: make the feed's reinstated affordances true for a dispatch agent
niiyeboah Sep 10, 2026
9d1c70d
fix: clear the unread badge, and stop composing turns nobody reads
niiyeboah Sep 10, 2026
c084150
Improve harness provider and auth UX
niiyeboah Sep 11, 2026
837f47f
docs: drop stale harness implementation plans
niiyeboah Sep 11, 2026
dd5014e
chore(web): trim redundant PR comments
niiyeboah Sep 11, 2026
d4dc3c9
chore: remove redundant harness comments
niiyeboah Sep 11, 2026
0090f10
feat(harness): show provider and context usage
niiyeboah Sep 11, 2026
c47419a
chore: trim redundant harness comments
niiyeboah Sep 11, 2026
e2f5c08
fix(harness): hide stale context usage
niiyeboah Sep 11, 2026
71e929a
refactor(harness): scope usage to selected provider
niiyeboah Sep 11, 2026
9832281
refactor(harness): show active billing usage
niiyeboah Sep 11, 2026
9e52099
fix(web): apply server flag toggles immediately
niiyeboah Sep 11, 2026
3d5480e
test(e2e): wait for harness toggle state
niiyeboah Sep 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,13 @@ MEDIA_ROOT=~/.dispatch/media
# TLS (optional — both must be set to enable HTTPS)
# TLS_CERT=~/.dispatch/tls/cert.pem
# TLS_KEY=~/.dispatch/tls/key.pem

# Dispatch Harness engines (agent type "dispatch"). Each is a host install the
# service resolves with its own PATH, so use absolute paths. The engine is the
# first segment of the agent's model id: claude/…, codex/…, gemini/…, opencode/….
# DISPATCH_CLAUDE_HARNESS_BIN=~/.local/bin/claude-agent-acp
# DISPATCH_CODEX_HARNESS_BIN=~/.local/bin/codex-acp
# DISPATCH_GEMINI_BIN=~/.local/bin/gemini
# DISPATCH_OPENCODE_BIN=~/.local/bin/opencode
# The engines use the host CLIs' own logins (claude /login, codex login
# --device-auth, NO_BROWSER=true gemini, opencode auth login); no key here.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ opencode.json
.cursor/mcp.json
apps/server/src/generated/runtime-assets/
apps/server/src/generated/runtime-assets.js
*.bun-build
2 changes: 1 addition & 1 deletion apps/browser-extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dispatch/browser-extension",
"version": "0.38.13",
"version": "0.38.13-harness.3",
"private": true,
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion apps/browser-extension/public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "Dispatch Browser Feedback",
"description": "Select live page elements and send focused feedback to a Dispatch agent.",
"version": "0.38.13",
"version": "0.38.13-harness.3",
"minimum_chrome_version": "114",
"permissions": ["scripting", "storage", "sidePanel"],
"optional_host_permissions": ["<all_urls>"],
Expand Down
3 changes: 2 additions & 1 deletion apps/server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dispatch/server",
"version": "0.38.13",
"version": "0.38.13-harness.3",
"private": true,
"type": "module",
"scripts": {
Expand All @@ -15,6 +15,7 @@
"db:migrate": "bun run prepare:runtime-assets && bun src/db/migrate.ts"
},
"dependencies": {
"@agentclientprotocol/sdk": "1.4.0",
"@dispatch/shared": "workspace:*",
"@fastify/cookie": "^11.0.2",
"@fastify/multipart": "^9.4.0",
Expand Down
29 changes: 26 additions & 3 deletions apps/server/src/agent-type-settings.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import type { Pool } from "pg";

import { getSetting, setSetting } from "./db/settings.js";
import { isDispatchHarnessEnabled } from "./dispatch-harness-settings.js";
import {
AGENT_TYPES,
DEFAULT_ENABLED_AGENT_TYPES,
sanitizeEnabledAgentTypes,
type AgentType,
} from "./shared/agent-types.js";

export {
AGENT_TYPES,
CLI_AGENT_TYPES,
DEFAULT_ENABLED_AGENT_TYPES,
isCliAgentType,
sanitizeEnabledAgentTypes,
type AgentType,
Expand All @@ -21,13 +23,13 @@ const ENABLED_AGENT_TYPES_KEY = "enabled_agent_types";
export async function getEnabledAgentTypes(pool: Pool): Promise<AgentType[]> {
const raw = await getSetting(pool, ENABLED_AGENT_TYPES_KEY);
if (!raw) {
return [...AGENT_TYPES];
return [...DEFAULT_ENABLED_AGENT_TYPES];
}

try {
return sanitizeEnabledAgentTypes(JSON.parse(raw));
} catch {
return [...AGENT_TYPES];
return [...DEFAULT_ENABLED_AGENT_TYPES];
}
}

Expand All @@ -39,3 +41,24 @@ export async function setEnabledAgentTypes(
await setSetting(pool, ENABLED_AGENT_TYPES_KEY, JSON.stringify(sanitized));
return sanitized;
}

/**
* What the app may create right now: the persisted enabled types plus
* `dispatch` when and only when the Dispatch Harness flag is on.
*
* Every creation and discovery gate reads this, not `getEnabledAgentTypes`:
* the create route, the reviewer-type route, `dispatch_launch_agent`, persona
* launches, the plugin routes and the assisted-update driver picker. That is
* what makes the harness's one switch reach all of them at once.
*
* No duplicate is possible: `sanitizeEnabledAgentTypes` drops `dispatch` from
* the persisted list on every branch, so the append below is the only place
* it can enter.
*/
export async function getOfferedAgentTypes(pool: Pool): Promise<AgentType[]> {
const [enabled, harnessEnabled] = await Promise.all([
getEnabledAgentTypes(pool),
isDispatchHarnessEnabled(pool),
]);
return harnessEnabled ? [...enabled, "dispatch"] : enabled;
}
5 changes: 4 additions & 1 deletion apps/server/src/agents/activity-monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ export function createActivityMonitor(
FROM agents
WHERE deleted_at IS NULL
AND status = 'running'
AND tmux_session IS NOT NULL`
AND tmux_session IS NOT NULL
-- harness agents derive working/idle from their ACP stream; their
-- pane is a plain shell whose quiet would only demote them.
AND type <> 'dispatch'`
);

const runningIds = new Set<string>();
Expand Down
4 changes: 4 additions & 0 deletions apps/server/src/agents/archive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export type ArchiveDeps = {
getAgent: (id: string) => Promise<AgentRecord | null>;
getRequiredAgent: (id: string) => Promise<AgentRecord>;
harvestAgentTokens: (agent: AgentRecord) => Promise<void>;
/** Stop a protocol-driven harness that lives outside the tmux pane. */
stopHarness?: (agent: AgentRecord) => Promise<void>;
setAgentStatus: (
id: string,
status: AgentStatus,
Expand Down Expand Up @@ -261,6 +263,7 @@ export async function executeArchive(
"Stop hook failed during archive; continuing"
)
);
await deps.stopHarness?.(agent);
if (agent.tmuxSession && (await runtime.hasSession(agent.tmuxSession))) {
await runtime.stopSession(agent.tmuxSession, true);
}
Expand Down Expand Up @@ -423,6 +426,7 @@ export async function deleteAgentDirect(
"Stop hook failed during delete; continuing"
)
);
await deps.stopHarness?.(agent);
if (agent.tmuxSession && sessionExists) {
await runtime.stopSession(agent.tmuxSession, true);
}
Expand Down
117 changes: 117 additions & 0 deletions apps/server/src/agents/harness/agent-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { HARNESS_ENGINE_IDS, type HarnessEngineId } from "@dispatch/shared";

export type EngineBins = {
claudeHarnessBin: string;
codexHarnessBin: string;
geminiBin: string;
opencodeBin: string;
/** Absolute path to the host's `claude`, for `CLAUDE_CODE_EXECUTABLE`. */
claudeBin: string;
/** Absolute path to the host's `codex`, or null to run the adapter's bundled one. */
codexBin: string | null;
};

export type FullAccess =
/** Already in `args`. */
| { kind: "args" }
/** Already in `env`. */
| { kind: "env" }
/** `session/set_mode` to this mode id right after the session opens. */
| { kind: "set_mode"; modeId: string }
/** The agent asks per call; the driver's requestPermission handler allows. */
| { kind: "permission_request" };

export type EngineSpec = {
id: HarnessEngineId;
bin: string;
args: string[];
env: NodeJS.ProcessEnv;
/**
* `system_prompt`: `session/new` and `session/resume` carry
* `_meta.systemPrompt.append`. `first_prompt`: the persona is the leading
* block of a fresh session's first prompt.
*/
personaDelivery: "system_prompt" | "first_prompt";
fullAccess: FullAccess;
/** Declare `_meta["subagent-transcript"]` at initialize and nest by parentToolUseId. */
subagentTranscripts: boolean;
/** The model is a launch flag, so `/model` cannot switch it. */
modelFixedAtLaunch: boolean;
};

const ENGINE_IDS: readonly string[] = HARNESS_ENGINE_IDS;

export function splitModelId(model: string): {
engine: HarnessEngineId;
model: string;
} {
const slash = model.indexOf("/");
if (slash <= 0 || slash === model.length - 1) {
throw new Error(`harness model ids are engine/model; got "${model}"`);
}
const engine = model.slice(0, slash);
if (!ENGINE_IDS.includes(engine)) {
throw new Error(`unknown engine "${engine}" in model id "${model}"`);
}
return { engine: engine as HarnessEngineId, model: model.slice(slash + 1) };
}

export function engineSpecFor(
engine: HarnessEngineId,
model: string,
bins: EngineBins
): EngineSpec {
switch (engine) {
case "claude":
return {
id: engine,
bin: bins.claudeHarnessBin,
args: ["--dangerously-skip-permissions"],
env: { CLAUDE_CODE_EXECUTABLE: bins.claudeBin },
personaDelivery: "system_prompt",
fullAccess: { kind: "args" },
subagentTranscripts: true,
modelFixedAtLaunch: false,
};
case "codex":
return {
id: engine,
bin: bins.codexHarnessBin,
args: [],
env: {
INITIAL_AGENT_MODE: "agent-full-access",
NO_BROWSER: "1",
...(bins.codexBin ? { CODEX_PATH: bins.codexBin } : {}),
},
personaDelivery: "first_prompt",
fullAccess: { kind: "env" },
subagentTranscripts: false,
modelFixedAtLaunch: false,
};
case "gemini":
return {
id: engine,
bin: bins.geminiBin,
args: [
"--experimental-acp",
...(model !== "default" ? ["--model", model] : []),
],
env: {},
personaDelivery: "first_prompt",
fullAccess: { kind: "set_mode", modeId: "yolo" },
subagentTranscripts: false,
modelFixedAtLaunch: true,
};
case "opencode":
return {
id: engine,
bin: bins.opencodeBin,
args: ["acp"],
env: {},
personaDelivery: "first_prompt",
fullAccess: { kind: "permission_request" },
subagentTranscripts: false,
modelFixedAtLaunch: false,
};
}
}
Loading
Loading