All notable changes to Corbits Code are documented here.
Format loosely follows Keep a Changelog. Versions
are package.json / vX.Y.Z git tags cut by scripts/release.sh.
This file is the only release-notes source. /changelog and the shipped
binary read it; scripts/release.sh builds the GitHub release body from the
matching ## [X.Y.Z] section (plus install instructions). Do not maintain
parallel copies under docs/ or scripts/notes/. At cut time: rename
## [Unreleased] to ## [X.Y.Z] - YYYY-MM-DD, then run the release script.
-
Taller live chain-of-thought preview. Parent reasoning still paints through the existing thinking row (one fold per turn, settle-to-opener + expand) — no separate mid-turn stream lane. The hard-capped live wrap rises from 3 to 10 inset lines (
LIVE_THINKING_MAX_LINES) so mid-turn CoT is glanceable; reveal rate stays 28 chars/sec. Sub-agent Task-row thinking is unchanged. Assistant mid-turn text continues to grow the open streaming assistant row frominference.text.delta. -
Live agents sit in a chrome strip above the prompt. Running and finished workers no longer compete with the transcript for vertical space; the strip stays parked over the input, finished rows linger briefly, then it clears when idle. Transcript task-row rewrites pause while the strip owns live status.
-
edit_filefiller args no longer count as a second mode. Models pad the unused mode withstart_line: 0/end_line: 0/old_string: "". Those now count as absent, so substring vs line-range is chosen from the real fields. Mixed-mode calls still reject, and the error names exactly which fields to drop so a retry can differ. -
taskrejections name only the missing field. A typed brief that omittedpromptused to be told bothdescriptionandpromptwere required, so the model retried the identical call. The error now names the actual gap and echoes the valid field back. -
Truncation no longer promises a retrievable remainder. Tool results cut at 80,000 chars now say the discarded tail is gone and re-running yields the same cut, instead of pointing at a
tool-output:///blob that only held the truncated text.
-
Parents and the TUI see why a child stopped. Forced stops (repetition, stall, deadline, turn-budget, no-progress, operator cancel, thrash) carry a machine-readable
Stopped:line on the report and a reason on the child's session. Fleet rows announce<lane> stopped — <reason>instead of a silent done/cancelled. -
Repetition detection covers short-phrase, counter, emoji, and zero-width floods. The periodic window floor drops to 8 chars (with a higher repeat bar so healthy lists stay quiet). A digit-folded pass catches incrementing counters and fence/emoji floods; a contentless-growth check flags streams of invisibles that used to normalize to healthy text.
-
Cross-provider replay no longer 400s the rest of the session. Switching model/provider mid-session used to replay foreign thinking signatures and output-only blocks the new adapter cannot encode. Every adapter now sanitizes persisted history before
buildRequest: drop unmappable blocks, strip foreign signatures, and synthesize danglingtool_results. -
Grok and OpenAI Responses set
prompt_cache_keyper session. Codex already did; xAI and Go Responses did not, so Grok threads cached at ~66–72% versus Codex's 92%+. Parent and each sub-agent thread get a stable, distinct key. -
TUI first inference waits for Codex instructions refresh. The TUI used to fire the refresh un-awaited, so turn 2's request prefix could change under a live cache key and force a full miss. Delivery now waits for that promise (non-Codex profiles skip it; a failed refresh still falls back to cached/bundled copy).
-
Codex Responses no longer sends
reasoning.summary: "auto". ChatGPT Codex rejects that value for gpt-5.6-terra / gpt-5.3-codex family models (HTTP 400 at turn 0). The adapter now sends{ effort }only, matching Codex CLI catalogdefault_reasoning_summary=none. -
Codex native tools proxy onto Corbits tools.
apply_patch,exec_command, andupdate_planfrom Codex-family models land on the real file, shell, andmanage_taskshandlers instead of being rejected as unknown names.
- Required checks are
prettier,eslint,typecheck, andbuild-and-test. The old combinedlintjob (cached, continue-on-error) never reported the status contexts the main ruleset required, so every PR sat blocked. Lint result caches are gone in CI; localbun run lintstill uses--cache.
-
In-flight tool rows show elapsed time. Ordinary pending calls (MCP, search, shell) tick a live clock the same way Task rows already do, so a slow-but-alive call is distinguishable from a hung turn.
-
The stall notice comes down the moment activity resumes. It is a live diagnosis, not a sticky banner: a tool finishing or the turn settling clears it on that paint, even if the monitor tick has already been cancelled.
- MCP tool calls arm their own watchdog. Default 5 minutes
(
settings.mcp.timeoutMs), still capped bytools.maxTimeoutMswhen set. Expiry returns a model-reactable tool error; the turn is not aborted.taskandrun_shellbehavior is unchanged.
-
Successful leaf
taskcompletions re-arm the primary backstop. A productive fleet no longer hard-pauses solely from turns-since-operator volume. Failed or salvaged leaf reports get no credit, so true tool-only no-progress still nudges then pauses. -
Leaf no-progress repeat limit raised from 2 to 5. Legitimate polling / retry streaks survive longer before salvage.
-
Exec refreshes Codex instructions before first Codex inference, same shared path as the TUI, with best-effort fallback to cache/bundled copy. Capability eval cells also stamp instructions hash, built-in tools, and requested reasoning effort for triage.
-
New capability eval cases: misleading-symptom, flaky-diagnosis, broken-toolchain, hidden-contract-inventory (held-out tests), and impossible-spec (reward-hacking bait).
- Codex instructions unit mock restores
node:fsinafterAll. The leaked in-memory fake had been poisoning later suites underbun test ./src ./tests ./evalssince the mock landed.
-
Workspace containment returns canonical real paths. Writers receive the realpath from the containment allow, closing the symlink-retarget window between check and write; the write-path allowlist compares both sides in canonical space so symlinked cwds don't false-deny.
-
Dangling or looping symlink components fail closed. A path component that exists but cannot resolve (dangling link, symlink loop) is denied by containment and the write-path allowlist instead of being treated as a missing tail; genuinely-new file paths still resolve via the nearest real ancestor.
- Project-trust stores are keyed by realpath. The same repo reached via
symlink twins (e.g.
/tmpvs/private/tmp) now finds the same grants; the savedrepofield and validity compare canonicalize consistently.
- Typeahead popups no longer leak queued permission gates. Both the @-mention popup and the slash-command palette refresh their suggestion lists in place instead of close+reopen, so a queued gate can't open (and swallow keys) mid-filter. Zero matches shows "(no matches)" without releasing the popup; Enter there preserves the typed text.
-
/yolopersists as the user-global skip-permissions default. Exec inherits it;--dangerously-skip-permissionsstill forces the current process. Secret-guard and authz still apply. The TUI shows a startup notice (and exec a stderr warning) when prompts are disabled by the saved default. -
Always-allow for
git worktree *now covers later worktree commands. Contained and permitted-sibling worktree add/remove segments no longer hit the restricted-path guard before grant matching, so a standing grant applies instead of re-prompting on every dispatch. Force flags, chained commands, and genuinely-outside destinations still prompt. -
Empty workspace roots can no longer disable path containment. An empty string in the roots list used to make every absolute path count as contained; it is now rejected before the prefix compare.
- The stall watchdog no longer aborts healthy waits for the model. A run that is merely awaiting the model's next token (after submit or after a tool batch resolves) surfaces a persistent stall notice but is never auto-aborted; auto-abort is reserved for a stream that started emitting and then died mid-flight. Live sub-agents and open permission gates keep their existing exemptions.
- Thinking-token loops now trip the repetition detector. Thinking deltas
feed the same cycle buffer and abort path as visible text, with a
short-period digit-folded check that catches monotonic counters (
0/1 1/2 2/3 …) without flagging healthy templated enumeration; the looped window is flushed topartial.jsonlfor diagnosis.
-
Project-trust stores are atomic, serialized, and cwd-correct. Saves go through temp-file + rename behind a per-store mutation queue; a store missing its
repofield is invalid (empty grants); plugin trust paths resolve against the project cwd, never the process cwd, and relative entries are dropped on load. -
Repo plugins with
defaultEnabledload agent profiles, matching how skills already gate; tool plugins remain consent-gated. A later same-id install can no longer silently turn a bundled default off.
- ESLint + Prettier land with a split concurrent CI (lint / typecheck /
build-and-test) with dependency and lint caches;
bun run checkis the single pre-PR gate. The lint job is non-blocking until the repo-wide mechanical fix batch lands.
-
Requested
run_shelltimeouts are no longer capped at 10 minutes. The 15s default when timeout is omitted is unchanged.shell.maxTimeoutMsstill clamps the command when set. -
Capability evals accept
--concurrency <n>(envCORBITS_EVAL_CONCURRENCY, default 1); overlappinghttpFixturecells isolateEVAL_HTTP_URLso parallel web-bait runs do not share a process.env origin.
-
Tool
run()no longer has an implicit 11-minute wall-clock abort. The outer watchdog arms only when Settings settools.timeoutMs/tools.maxTimeoutMs, or whenrun_shellpasses a positivetimeout(requested plus slack, so this layer cannot beat shell-guard). Unset settings leavetaskand other tools unbounded; parent cancel, maxTurns, and eval--agent-timeout-msstill bound the run.tools.maxTimeoutMsstill clamps non-shell tools when set and does not cap a longer requestedrun_shell. -
task(sub-agent dispatch) is always exempt from the generic tool-execution watchdog, even when Settings arm it. Workers past 11 minutes with healthy activity complete and return their own report instead of surfacing as operator cancels; maxTurns, no-progress, thrash, and the opt-indeadlineMsremain the operative bounds.
-
Skywalker spawn-target for product code is
build. Prompt and skill copy that still saidspawn implement/task(agent="implement")now dispatchbuild. Intent graphexplore → implement → critiqueand slash/implementare unchanged. -
Skywalker may DIY tiny product writes (CL-6629). Path tools (
write_file/edit_file/delete_file) remount on the primary session. Tiny/single-file/one-route bounded edits are the exception; spawn remains default for substantial/multi-file/parallel/specialist work (hard cap 4 workers). Docs/design still spawn shakespeare / bruckheimer / brand-reviewer except one-line fixes. Greybeard stays write-free. Shell file-writes stay denied. Spawn is a judgment call, not a tool ban. -
Exec and capability evals can run as a chosen primary director.
corbits exec --director <id>(and eval--director) overlays that package's system prompt and initially-advertised tool set on the product exec path. Omit / skywalker keep the default Skywalker session. Directors that cannot spawn (for example build) do not mounttask. This is an exec/eval/CI override, not a TUI or single-agent mode.
Skywalker is the primary orchestrator over a closed director fleet: product write tools stay off the primary, and you cannot spawn Skywalker as a task leaf. Workers are not done until they return the four-heading report. First-party action skills ship as slashes; eval runners require an explicit provider/model pair; the style skill no longer refuses non-git folders.
- Late-connected MCP tools are callable the same turn they appear in
tool_search.@intx/agentsnapshots dispatch names atcreateAgent, and the post-connect reload that used to rebuild that snapshot waited for every server — including one stuck on OAuth. Catalogedmcp__*tools then returnedunknown tool. Construction now dispatches misses through the live runner, so Linear/Exa (and any other server that finished) work even while another server still needs auth.
-
Model picker rows are model-first. Each leaf is
model * [provider];(current)still marks the live session model. Alt+D persists the focused pair as the default (globaldefaultProvider+ providerdefaultModel+ project-local selection) without switching the live session or closing the picker. -
Settled permission and operator prompts no longer recap into the chat. The overlay is the question; answering it used to leave a grey
permission/operatorcard restating the same command and the chosen option. After a decision those recap rows are gone — the tool row that follows is the outcome. Expanding a collapsed payload while the overlay is still open still writes the full payload into the transcript, because that text would otherwise be unreachable before approval.
- Shipped directors have no writePaths lock. Docs/design leaves
(shakespeare, brand-reviewer, bruckheimer) still mount write tools, but
package
writePathsis omitted. Lane routing (P/A/I, DESIGN.md, product discovery) is spawn policy, not a file lock. OptionalwritePathsremains and the permission gate still enforces it when a profile sets it. - Skywalker is not a task leaf.
task(agent=skywalker)is refused. The spawn catalog (directorProfiles()) lists the other 15 closed directors; the primary session is still Skywalker.
- Tool-less mid-run narration is not a finished report. A worker that stops tooling with Summary-only (or other incomplete) prose is not complete. The director injects one wrap-up nudge asking for the four headings (Summary / Findings / Blockers / Paths), then salvages as incomplete-report if the next tool-less turn is still missing the envelope.
- First-party skills catalog is on out of the gate.
corbits-skillsships action slashes/implement,/plan,/refactor,/review(was/code-review),/pull-request-review,/create-issue(was/linear-create),/scribe,/interview,/ast-grep. Dispatch, git-rebase, linear-issue-workflow, style, philosophy, typescript, and opsh stayuse_skillonly (user-invocable: false). Draper and emil are not skills or slashes — closed directors viatask(agent=…)only./planis the eng change-plan recipe (task(agent="plan"); does not implement or file tracker issues)./create-issueremains the tracker command: Linear MCP when available; otherwiseask_operatorfor the platform and persistsPreferred issue trackerin.corbits/MEMORY.md(GitHub viagh issue create). Each recipe tells Skywalker to spawn closed directors — the operator types the slash; the primary does not do the work. Turn the catalog off in/pluginsif you want those commands gone. - Style skill no longer refuses non-git folders. Edits, tests, and
reports are allowed without a repository. Do not
git initunless asked. Commits, amends, rebases, and isolated worktree dispatch still require an existing repo.
- Capability eval workdirs are git repos. After copying the fixture
and seeding skill stubs, the runner initializes the tmp workdir (
git init,git add -A, one unsigned hermeticeval fixturecommit) so isolated workers have HEAD and git-aware skills have a baseline. - Eval runners require an explicit model pair.
eval:capabilityandeval:public-swe-onetake--provider/--model(capability also accepts--matrixwith complete cells) so local.corbits/settings.jsonis not the implicit target. - Capability eval records
tasktool calls.taskToolCallCountis derived from the turn stream (informational). Older result files without the field default fromtoolCallsByName.taskso the frozen baseline still parses. - Capability eval smoke cases for dispatch and recall.
complex-dispatch-spawnrequires at least onetask()plus a working GET /readyz.complex-recall-after-bulk-readplants a token, asks the agent to read the fixture, then write it back. Informational only — not in the frozen baseline-0286 gate until a deliberate refreeze. Neither case proves compaction fired or that the primary skipped implementing the route.
- Resume is keyed to this checkout's git toplevel. Linked worktrees no
longer share (or list) each other's sessions —
--git-common-dirmade every worktree show every other worktree's history. Sessions previously created from a worktree remain under the main checkout key; resume from the main path to recover them.
Corrupt resume state no longer kills sessions, Codex quota errors name the reset window, and provider/model selection is more reliable across restarts and mid-session switches.
- Poisoned resumes recover. Resume loads no longer die on null-padded
turns.jsonldata after a stale compaction window. Usable turns are recovered, valid metadata is preserved, and pending gates re-arm instead of leaving the session wedged.
- Quota errors explain the reset. Codex
usage_limit_reachedresponses are parsed as quota exhaustion, show the plan/profile when available, include the reset ETA, and point/modelat another subscription instead of looping on a doomed retry.
- Workers follow a mid-session model switch. Sub-agents spawned after you switched models kept running against the provider the session started on, so switching away from an exhausted or disconnected account left every new worker failing until a restart. Provider, model catalog, and settings are now read live at spawn time, so tier settings written mid-session are visible too.
- Single-agent session mode is gone. The primary session is always
orchestrator-capable (
task/search_agentsalways available). The first-run mode picker and Settings → Session rows are removed. LegacysessionModein settings files still loads without error and is ignored (CL-5814). - Dual-column fleet rail removed. TUI geometry is stack-only forever
(
layoutMode: "stack",railWidth: 0).DUAL_MIN_COLUMNS/RAIL_WIDTH_*constants and dual absolute-positioning of the agents box are gone. Live fleet status remains● Tasktranscript rows; the agents chrome zone stays empty.
- Parent live reasoning no longer sideways-scrolls. Streaming thinking used a one-line marquee onto the newest tokens. It now paints a short wrapped preview (up to three inset lines of the newest revealed prose); expand still opens the full block. Sub-agent Task-row thinking is unchanged.
- Skywalker dig fleets cascading into stalled Task floods. "Why stalled / why no thinking / spawn looks broken" asks were reclassified as orchestration and fanned into parallel explore waves; Grok leaves then sat quiet mid-think or looped, which looked like spawn failure and invited another dig wave. Skywalker now hard-caps concurrent leaves at 4, classifies digs/screenshots/ why-how as COMMUNICATION (answer or one explore leaf), and forbids re-fan-out diagnostic waves when leaves stall or salvage.
- Grok sub-agent stall false positives. Live fleets on grok-4.6 show routine
60–180s gaps between tool cycles while the model thinks. UI stall paint and
Grok's salvage kill were far shorter, so healthy thinking looked hung and got
nudged/stopped mid-inference.
DEFAULT_STALL_MSand parentSTALL_NOTICE_MSare both 300s (aligned with the 5-minutesubAgentStallTimeoutMs). The grok-responses path asks forreasoning.summary: "detailed"so summary deltas keep the activity clock moving (auto summaries were tiny vs billed thinking tokens). - Live fleet status is
● Tasktranscript rows again. The FLEET board / dual-rail agents chrome restated the same workers above chat and made progress hard to read.taskcalls paint live rows (clock + current tool) viasyncAgentProgress;formatChromeZoneskeeps the agents zone empty and suppresses the manage_tasks checklist while any lane is running. web_fetch/web_searchalways advertised. They were registered but only discoverable viatool_search, so strict providers (and thrashy models) never saw them on the wire despite Skywalker saying they were mounted. Both are now inCATALOG_TOOL_NAMES. Capabilityweb-baithard-requireswebFetchToolCallCount >= 1viarequireBehaviors.
-
Public SWE-bench one-shot smoke.
bun run eval:public-swe-oneruns Corbits product exec on a single SWE-bench Lite instance (defaultpsf__requests-3362), taking--providerand--modelon the CLI, and writespreds.jsonlunderevals/public/results/. Official Docker resolved/not-resolved grading stays optional/manual. -
Capability eval:
complex-stock-gate. Multi-file stock-gatedPOST /orders(404/409/201 + stock decrement) on the demo-comparison fixture; sync API grader. -
Capability eval:
complex-idempotent-orders. Header-driven Idempotency-Key on POST /orders (201/200/409) with multi-file order store; sync API grader. -
Capability eval:
complex-bugfix. SWE-bench-style issue→patch→tests on the newtests/fixtures/buggy-servicefixture (intentional post GET bug; users green). -
Capability eval:
complex-pagination. Querylimit/offseton GET /products (demo-comparison); sync Response grader + slice semantics. -
Capability eval:
complex-rename-user. Cross-file rename of username→displayNameon multi-file-service; runtime + source checks. -
Fixture:
tests/fixtures/buggy-service. multi-file-service clone with a deliberate post-route defect for bugfix capability evals. -
Director API-contract loop (launch tuning iter1). Implement preserves sync public surfaces; critique ranks sync→async signature drift as blocking; Skywalker puts stated signatures into success_criteria, skips explore/critique on tiny green ships, re-dispatches implement on blocking critique findings, and routes URL reads through mounted
web_fetch(no shell thrash). complex-jwt case prompt states the sync Response contract. -
Closed director fleet (CL-5818 Level 6 wiring). Sixteen director packages under
src/agent/directors/<id>/(prompts, tool envelopes, spawn rights, nudge budgets, report contract) register inDIRECTOR_REGISTRY.task(agent=…)resolves directors without requiring plugin profiles;task(intent=…)maps implement/explore/plan/review→critique (generalis refused). Default agent profiles are the closed fleet viadirectorProfiles(). -
Primary is Skywalker by name. System role answers "Skywalker"; agent id
skywalker. Product mutation tools are not mounted on the primary session (structural never-implement), not only prompt policy. -
Director identity at spawn. Every package system prompt is prefixed with agent id, model role, and optional skills; profiles include
agent id:in description so search_agents / re-spawn are unambiguous. -
modelRole drives leaf effort. Spawn effort cascade is pin → package modelRole default (intern=low) → orchestrator/leaf → parent. Env block adds arch + runtime alongside platform/date/git.
-
No general leaf at the wire. Bare
task(noagent, nointent) andintent=generalfail closed; nested directors enforcespawn.allowlist(greybeard → intern/explore/critique). -
Director write-path locks. Docs/design packages may write only under package
writePaths(shakespeare: PRODUCT/ARCHITECTURE/IMPLEMENTATION; brand-reviewer: DESIGN.md; bruckheimer: PRODUCT.md + docs/*), enforced in the permission gate. -
PRODUCT / ARCHITECTURE / IMPLEMENTATION document the closed director fleet, spawn matrix, intent map, and tool envelopes.
- Named API-key instances. First-class API-key providers (OpenAI key,
Anthropic, Google, OpenCode Zen/Go, Z.AI, ...) ask for an instance name before
the key, so personal and team keys can coexist (
openai/default,anthropic/work, ...). Reusing an existing name replaces that instance after an explicit confirm. Custom endpoints stay free-form and single-entry. - API-key connect keeps the project selection. Connecting an API-key or Custom provider now writes the same project-local provider/model selection OAuth already wrote, so a restart in that repo resolves to the account just connected. Secrets stay in global credential storage only.
- Grok 4.6 is selectable. xAI OAuth accounts now list
grok-4.6alongside Grok 4.5 and Composer 2.5 Fast.
- Custom from Alt+A. The add-provider selector now includes Custom alongside first-class kinds, so free-form OpenAI-compatible endpoints are reachable from the model picker without dropping into onboarding. Custom still uses the full manual form (name, base URL, key, model).
- MCP auth is
mcp !on the prompt box. A server waiting on authorization no longer takes a notice-row sentence (mcp granola needs auth (/mcp)). The top rule carries a compactmcp !immediately left of the model label;/mcpstill names the servers.
- Contribution rules are codified. The pull request template and agent docs now spell out the expected commit, review, and Linear-linking discipline.
- Models-only connect prose. PRODUCT, IMPLEMENTATION, and operator-facing
error strings document
/modelas models-only with Alt+A to add a provider. Stale bare-c/ Ctrl+A / in-list "connect ->" instructions are gone.
Codex connect works again: streaming responses no longer die on a missing header, multiple ChatGPT accounts can be connected by name, and providers are added from the model picker with Alt+A.
- Codex streaming repaired. Some Codex models (the gpt-5.6 family) stream valid responses with no Content-Type header, which failed every turn with "Cannot detect response kind". The response protocol is now recovered from what the request asked for, so those models work; genuinely malformed responses still fail loudly.
- Named accounts with re-auth. Browser sign-in asks for an account name
first, so any number of ChatGPT or Grok accounts can be connected side by
side (
codex/work,codex/personal, …). Reusing an existing name re-authorizes that account after an explicit confirmation — the recovery path for expired sign-ins. Second sign-ins can no longer silently overwrite an existing account's credentials.
- Alt+A adds providers. The model picker lists only connected accounts and their models; Alt+A opens an add-provider selector that always shows every provider with its connected-account count, so adding a second account is never blocked. After connecting, the picker reopens focused on the new account.
- Connect works mid-session. Adding a provider from a running session no longer crashes with a renderer conflict; the sign-in surface shares the session's screen and hands control back when done.
- Pickers stay on screen. Overlays opened after using one on the launch screen no longer render below the prompt box.
Drag-select auto-copy, a flat type-to-filter model picker, install-aware upgrade notices, quieter long-session compaction, and layout breathing room.
- Drag-select auto-copy. With mouse capture on (the default), finishing a
drag selection in the transcript writes the selected text to the system
clipboard on mouse-up. Highlight clears immediately; the status flash waits
for the clipboard write (
Copied …on success,Copy failedon error). Alt+C structured copy uses the same honesty. Alt+M still hands the mouse back for native terminal selection. - Flat model picker. Choosing a model is one type-to-filter list of
provider / modelrows — no nested provider drill-down. Type to narrow, Enter selects; Alt+F still toggles favorites when wired. - Install-aware upgrade notice. When a newer GitHub release exists, a non-blocking startup notice names the running and latest versions and the right upgrade step for Homebrew, source/Bun, deb, release binary, or unknown. Network and detection failures skip quietly.
- Bottom breathing room. The prompt box sits one blank row above the terminal's last line on tall enough terminals, so the layout no longer feels flush against the frame edge.
- User-message breathing room. Your turns in the transcript keep a blank bar row above and below the message text, so prompts are easier to spot while scrolling.
- Landing survives MCP connect failure. An MCP status failure still shows as a system notice and no longer wipes the mountain landing screen.
- Quieter re-reads under compaction. When the same file is read more than
once in a long session, older successful
read_fileresults become a short stub and the newest stays whole, so context is not filled with duplicate file bodies. Chunked reads of different ranges stay distinct. Errors stay verbatim. - Changelog watermark honesty. Upgrade notes are no longer marked as “already shown” when nothing was actually displayed.
Tool-only auto-pause that no longer stops healthy work, resume the last session
in a folder, and /feedback that just sends.
- Hard pause requires a repeating tool-call cycle, not a bare tool-only turn count. Period detection catches identical repeats, A/B alternation, and longer fixed rotations; a short identical poll (re-run a flaky test, check a build) no longer false-positives.
- Soft wrap-up nudge at 25 tool-only turns for every model family — a check-in, never a stop. Grok drops its miscalibrated 6/10 pair and shares the default; its shorter sub-agent stall timeout and finish-bias residual stay.
- Raw-count backstop for cycles above the period ceiling or phase-broken patterns: first a progress-summary nudge, then a hard pause only if another full interval passes with no genuine operator message. Synthetic system sends (compaction continuations and the like) no longer reset the counter.
- Shared period-detection helper lifts the character-stream repetition search so tool fingerprints reuse the same shape; a local forensics script re-derives thresholds against real session traces.
corbits resume/corbits continuereopen the latest session for the current project folder, a specific session id, or the interactive picker.- Invalid ids error instead of silently falling through to “last”; id and
--pickcannot be combined. Legacy session trees still migrate on resume by id.
/feedbacksends free-text product feedback when you choose to. Bare/feedbackwaits for the next line; text on the same line sends immediately; empty Enter cancels. Other slash commands clear a pending arm.- The reply is a short system notice (Thanks — feedback sent.), not a model turn — no busy state, no queue.
- Settings describe optional ambient analytics clearly, and say when an environment setting has disabled them so the toggle cannot re-enable.
- Generation properties use PostHog cost names:
$ai_cache_read_input_tokens,$ai_cache_creation_input_tokens,$ai_reasoning_tokens. - Broader auth and slash product events.
- Markdown settle waits for body paint so heading-only frames no longer flake CI.
--helpexits 0 cleanly.
Orchestrator-first release: a truthful fleet board, thrash salvage that stops false completes, steering that keeps your input, and one TUI root. Goal mode is gone. Coupled Interchange packages are vendored at head.
- One fleet board replaces the agents strip and task panel — identity, elapsed time, and what each leaf is doing, clamped to the rows it was granted.
- Lane tools show a subject, not just a tool name: a bounded, secret-scrubbed preview of path / command / pattern on the board and dispatch trailer.
- Task dispatch collapses to a sentence (description, else prompt) instead of dumping raw argument JSON; expanded detail uses real line breaks.
- Fleet progress reports without a prompt; bursts settle to one row per agent; a mid-rebuild drop surfaces a not-delivered notice.
/newand/clearwipe the painted transcript and cancel live sub-agents so orphans do not keep burning tokens under the old session.
intent=implementthat never edits is not a successful complete. Tool-using leaves that never write salvage as never-edited and hard-block identical re-dispatch (same path as never-acted and thrash).- Soft mid-run re-read nudge before the hard thrash stop: implement leaves are asked to edit or wrap up; explore leaves are asked to expand findings or change approach — never forced into edit.
- Format characters no longer break loop detection. Zero-width spaces, BOM, bidi marks, soft hyphens, and word joiners are stripped before period detection.
- Queue and steer are one mid-run gesture; stop-and-reinject cuts the current turn and puts a new instruction in its place.
- Queued operator input survives Ctrl+C instead of being discarded.
--dangerously-skip-permissionsreaches pre-gate sandboxes (path-escape, delete, list_dir, shell cwd). Secret-guard path denies and authz hard blocks are unchanged.- Contained git worktree ops auto-allow in auto mode, through the same workspace-containment authority as shell path restrictions.
manage_tasksno longer asks for approval.- Queued approval timers arm only when the gate is shown.
The goal subsystem is gone end to end — runtime, TUI chrome, slash commands, and docs. Continuous work is the orchestrator plus task dispatch.
- OpenTUI shell flattened into
src/tui/— one product root (path rewrite only). - Landing snow paints; mountain and hero survive startup load notices.
- Slash popup shows
/nameonly; Ctrl+O palette and bare?are removed. - Semantic activity ticker; skill and agent names highlight in the prompt; duplicate pasted images are rejected by content hash.
- MCP auth banner clears after mid-session re-auth succeeds.
- Active-run liveness is one write; crashed sessions no longer list as running forever; a rotated session stays crash-coverable.
- SIGINT / SIGTERM / SIGHUP terminate the process; a detached throw restores the terminal before exit.
- In-session provider connect actually connects; onboarding validates a credential before reporting a provider as configured.
- Model picker no longer overwrites the persisted default when you only inspect models.
- OAuth success footer links the product site and GitHub.
@intx/types,@intx/storage-isogit, and@intx/inferencevendored at Interchange head (local inference patches reapplied); licenses recorded and re-sync documented.- Process-wide session id on every capture; PostHog AI events in privacy mode; expanded anonymous product event catalog.
- Grep results go through the secret scrub.
- Shared helpers for grep truncation, MCP tool identifiers, pricing tree walks, and grant scoping; nightly random-seed CI job dropped.
Running several sub-agents at once was close to unusable. The watchdog meant to catch a hung run was killing healthy ones, approvals piled up one at a time and printed twice, and the panel showing what each agent was doing had collapsed to a line of counts. This release fixes that path end to end.
- The stall watchdog aborted healthy parallel fan-outs. Any silence counted as a hang, and in a fan-out the first sub-agent to finish flipped the run back to awaiting-a-response while the rest still worked. Since the parent emits nothing while children run, the whole run read as silent: a no-response notice at ninety seconds, then an abort of everything in flight at fifteen minutes. The watchdog now consults the outstanding tool calls it was already tracking.
- The clock also ran while you read an approval. Blocked-on-the-operator is now part of the turn state rather than something only the painter derived, so the watchdog and the phase line read one source. Gates still queued behind another are covered, not only the one on screen.
- A grant no longer has to be given once per agent. Minting one now settles every queued request it already covers. The reconciliation lives in the permission layer behind a single idempotent settle, so it holds for any surface and cannot double-resolve or strand a request. Session teardown denies whatever is still queued instead of abandoning it.
- Every approval wrote two transcript rows. A screen of approvals read as twice as many requests as had happened. There is now exactly one row per decision — including denials, timeouts, and aborts, which previously wrote nothing, so a refused permission was indistinguishable from a hang.
- Project-scoped grants never matched a sub-agent. A grant was stamped with the session root while a sub-agent asks from its own git worktree, and the two were compared as plain strings — so the agents generating the approvals could never benefit from an earlier answer. Both sides now resolve through the worktree registry that already governs path containment, by exact match rather than prefix.
- The live agents panel is back above the prompt — one row per running sub-agent with elapsed time, current tool, and whether it has gone quiet. Rows hold position instead of reordering on each event, the zone shrinks a row at a time under a short terminal rather than disappearing, and when a fan-out exceeds the space the quietest agent stays visible. Rows are measured in terminal columns, so a wide-character description cannot overflow the zone.
- Goal mode stuck at "working" indefinitely. Two events registered the same tool call under different identities — one by id, one by name — so a call was counted twice and cleared once, and the turn waited forever on work that had finished. Goal mode was worst affected because it continues on its own and never emits the fallback that settles a stalled turn.
run.jsonrecords its turn count at every turn boundary rather than only at session start and end, so a resumed session reports what it actually did.
A second sweep over the OpenTUI cutover, plus a rebuilt model surface. Two of these faults could end a session outright, and several were behaviour that had been fixed once already and lost when the renderer was replaced.
The picker lists providers first and descends into models on select, with Escape returning to the provider level. Recents and favourites stay flat at the top, and each account appears as its own row.
- Model tiers are gone.
settings.tiers,profile.tier, and thetask(tier=)argument no longer exist, and/fast,/standard, and/cleverare retired rather than remapped — a tier was a per-name fallback chain, which neither a favourite nor a pinned model expresses. Per-agent selection continues throughprofile.inference. A settings file containingtiersstill loads; the key is dropped on save. - The context meter was wrong by nearly four times for any provider with a custom name. An account-qualified identity did not match the registry, so a 500k window read as the 128k default. Resolution now tries the identity as given, the bare model id, and the canonical provider/model form, and marks a figure as estimated only when it genuinely falls back.
- The current model is read from the live session rather than inferred from the most recent pick, which mislabelled any session that never opened the picker.
- Switching models poisoned the conversation permanently. A reasoning signature issued by one provider was replayed to another that could not decrypt it, and every subsequent turn failed with HTTP 400. Signatures now carry the provider that issued them, so two backends sharing a model name cannot replay each other's. Switching accounts on the same provider still preserves reasoning continuity.
- A model that fell into a loop ran unbounded. Repetition is detected by character period within a streaming cycle, and by comparing cycle fingerprints across tool calls, so a loop that emits a tool call each pass is still caught. Ordinary narration repeated before successive tool calls is not.
- Plugin diagnostics wrote raw to stderr and corrupted the frame. They now go through the log sink, and the warnings that used to vanish with them are surfaced where the operator can see them.
- The provider setup screen garbled its own text on short terminals — rows were compressed into one another instead of clipping.
- The command palette matches the prompt box width, drops its marker column, kind column, and title rule, and marks the selected row by colour rather than a grey band.
- An open overlay reserves its own border, title, and content rows before any other chrome is allowed to starve it.
/resumewas offering sessions that did not exist. Demo fixture data was shipping in the production bundle and rendering whenever a dependency was missing. A missing dependency now produces an honest empty state.- Dialog choices read as plain English rather than internal names.
- Compaction stopped hollowing out the turns it had just decided to keep. A file edit inside the recent window keeps its content.
run.jsonis finalized when the process crashes, without reading from disk on the crash path.- An
@-mentioned file outside the workspace is inlined once rather than blocked, gated by the sensitive-path list and a total byte cap. That list now covers shell histories, system credential files, keychains, browser cookie and login stores, and cloud credentials.
- An agent could rewrite your global git configuration to push, altering every repository on the machine. That now requires operator approval, and a scoped push path applies credentials per invocation with nothing written to any config file.
present,manage_goal,manage_tasks, andlspare advertised only when they apply.- Live progress appears on a dispatched sub-agent's transcript row.
- The most recently queued message can be cancelled.
- The test suite only passed in one order. Bun mutates the namespace object
returned by
await import()when a module is later mocked, so the usual capture-then-restore idiom silently reinstalled the mock process-wide. Under randomized order the suite produced over a hundred failures; it now passes across every seed tried, and CI runs a fixed seed on each change plus a rotating seed nightly. docs/TUI.mdstates how the terminal UI is meant to look and behave — overlays, selectors, the palette, the prompt box, scrolling, and key macros. Nine documents describing the finished migration are retired.
A bug-fix release on the OpenTUI cutover. Most of these faults had no visible symptom: sessions that hung with no way out, memory that grew without bound, and session state that quietly corrupted itself.
One behaviour reverses from 0.2.90. That release gave the mouse to your terminal so drag-select and copy worked normally. Scrolling then landed in the prompt instead of the chat, because a terminal with mouse reporting off translates a wheel tick into arrow-key bytes indistinguishable from a real keypress — and arrows drive prompt history. The main session shell now takes the mouse: the wheel scrolls the transcript, arrows still cycle prompt history, and click-to-expand on tool rows and drag-to-scroll work without pressing Alt+M first. The cost is native drag-select in the transcript; Alt+M hands the mouse back when you want to select text, and Alt+C copies a message, tool output or diff without the mouse at all. The onboarding and session pickers keep native selection either way.
Sessions could hang with no way out.
- Pressing Esc on a permission or operator prompt abandoned the request the agent was waiting on. The session hung permanently and Ctrl+C did not recover it — the interrupt path never reached that promise. Dismissing now resolves it as a denial.
- Goal-mode auto-deny and the tool-watchdog abort were both inert. The producer sent a timeout and an abort signal; a locally redeclared event type in the renderer silently dropped both, so an unattended run could park on a permission prompt forever.
- A permission or operator prompt raised before any transcript row existed rendered its title and footer but clipped its choices, because the layout asked for room for exactly one option regardless of how many there were.
- Messages typed while the agent was working were queued and never sent. The drain waited on a signal that fires once at shutdown rather than at each turn boundary.
- A detached throw left the process alive with the event loop held open. Real
uncaughtExceptionandunhandledRejectionhandlers now write a crash report and exit non-zero.
Memory and state grew or drifted without bound.
- Transcript rows were retained for the life of the process; a 600-row cap was lost during the cutover and never restored.
- History past 500 rows could not be reached by scrolling, and every appended row rebuilt the whole painted window.
- Concurrent writes to a session's
run.jsonare serialized per session, so a late progress snapshot can no longer resurrect a finished run asrunning. - Resuming a session reset
turnsUsedto zero and dropped its connected MCP servers. - Quitting during an @-mention lookup or a clipboard read could write into freed renderer memory.
The context meter lied, and compaction could not act.
- The meter read only provider-reported usage with no fallback, so a provider that omitted usage left it frozen while real occupancy climbed. It now falls back to a local estimate and marks the number as approximate.
- The meter and the compaction governor computed context size from different fields, so they could disagree by the full size of the prompt cache.
- The system prompt and tool schemas are counted, having previously been omitted from the estimate entirely.
- Compaction armed at a turn count where the compactor was guaranteed to do nothing, then re-armed, spinning without progress. Both now derive their floor from one definition.
Input and rendering.
- Pasting several lines into a terminal that does not negotiate bracketed paste sent each line as a separate message.
- Markdown headings no longer flicker while the text below them streams.
- Parallel
taskdispatches paired results to calls by tool name, so three concurrent sub-agents could resolve the wrong rows and append orphans. They are keyed by call id. - The onboarding and session pickers no longer turn on mouse reporting, so drag-select works there.
- The sub-agent concurrency cap is removed. Sub-agents run unbounded, and the
maxConcurrentSubAgentssetting no longer exists — an existing settings file containing it still loads. Setting it to0previously disabled sub-agents entirely; that capability is gone with it.
The interactive TUI is now OpenTUI. The Ink renderer is deleted, not feature-flagged, so rollback is the prior tag rather than a setting.
What moved under your hands. Ctrl+Enter (or Ctrl+J) inserts a newline; Shift+Enter only works on terminals that report the modifier. The mouse belongs to your terminal by default, so drag-select and copy behave normally — Alt+M takes the mouse when you want click-to-expand or drag-scroll. Quitting is unchanged: Ctrl+C interrupts, twice exits.
- OpenTUI renderer — zone-based geometry resolver with per-zone minimums and an explicit collapse order, replacing React reconciliation.
- Multi-line composer that wraps and grows to 40vh before it scrolls.
- Copy mode (Alt+C) writes to the system clipboard on macOS, Windows, and Linux, with an OSC 52 fallback for content selection cannot reach.
- Free-text answers to operator questions — type a reply instead of picking from a list, which the tool had always promised and the interface never had.
- Live status for hooks, subagent progress, MCP connections and grants, which were emitted but had nothing listening.
- Standalone binary could not start.
build:binexcluded its own native module, so a distributed binary had nonode_modulesto resolve it from. - Terminal-owned selection. Mouse reporting is off by default; while it is on, the terminal forwards drags to the app and cannot select text.
- Copy wrote nowhere. Alt+C had always written to an in-memory array.
- A crash left the terminal wedged. An uncaught throw kept the alternate screen, mouse reporting and raw mode, and the process survived.
- Bidirectional overrides reached the approval overlay, so text could read as one thing and run as another at the moment of approval. Model output is sanitized too, including sequences split across streaming deltas.
- Search output ignored its byte cap on a breach, and had no cap at all on hosts without ripgrep.
- Repeated tool calls dropped every result after the first.
- A retried turn painted itself twice.
- Approval text wrapped by code units, not columns, so wide characters overflowed the subject being approved.
- Native buffers leaked on every transcript repaint, landing clear and shell dispose.
- Onboarding truncated a pasted API key at 1000 characters without saying so.
- A question could arrive with no way to answer it when another overlay already held the screen.
- Resumed sessions dropped
view,planandtasksblocks silently. - Ctrl+D quit mid-edit. The host claims no key of its own now.
- Authorization moved out of the transcript and into
/mcp. A server needing OAuth used to dump a raw authorization URL as a transcript row at session start — unactionable, uncopyable, and gone once it scrolled away. The notice row now names the servers waiting (mcp granola needs auth (/mcp)) and clears when they connect; nothing blocks usage, an unauthorized server simply has no tools. /mcpis a real surface listing every configured server and its live state — connected with tool count, needs auth, or failed with the reason. Enter on an unauthorized row opens its authorization page in the browser and copies the link, so the flow also works over SSH.- The OAuth callback page carries the brand. One page now serves MCP servers and inference providers alike, on the terminal's own palette, with the mark animating through the same dithered draw/fill timeline as the landing. It names what happened — "Linear connected successfully", "Granola failed to connect" — and humanizes server names and error codes on the way in. Entirely inline: a local authorization callback makes no network call.
- Shell-block messaging cites host safety and OOM risk, and names the
bounded
grep/search_filestools as the alternative, rather than reading as a tool-routing preference. Open-endedfind/rg/grep -rstill hard-deny. - Pure directory listing outside the workspace auto-allows again —
ls, andtreebounded by-L/--max-depthto depth 10. Content readers still ask. Unbounded recursive listing (ls -R, bare or over-deeptree) asks even inside the workspace. tree -ono longer auto-allows — a listing command that writes a file is not a listing command, and it had been bypassingwrite_filereview. Long--recursivespellings onls, down to every unambiguous abbreviation, are caught too.
- Shift+Enter does not insert a newline on terminals that do not report the modifier. Ctrl+Enter and Ctrl+J do.
- Markdown flickers mildly while streaming. The deterministic cause is fixed; a residue remains from the async highlighter.
- Transcript history past 500 rows cannot be scrolled to, and rows are retained for the life of the process.
- A detached throw or a signal can leave a session marked running.
Patch: models-first /model picker and OpenCode Go subscription billing pin.
- Models-first
/model— open on a Recent / Favorites / all-models list; Alt+A / Alt+F for favorites; connect is auth-only for Tier A first-class providers. - Tier A connect catalog — OpenAI dual-path (ChatGPT login vs API key), Anthropic, xAI, Z.AI, OpenCode Zen, OpenCode Go; no OpenRouter/Copilot in the first-run list.
- OpenCode Go billed as Zen PAYG — central
isOpenCodeGoProvider/isOpenCodeGoProviderIdidentity; force subscriptionOPENCODE_GO_BASE_URLat catalog load,buildProviderEntry,resolveProvider, and inference source build so a wrong diskbaseURLcannot mis-bill. - Go model on Zen path —
isGoModelOnZenPathwarning when a known Go model sits on a credits-billed Zen provider. - Recent/favorite model prefs serialize writes so concurrent toggles cannot clobber each other.
- Empty success toasts and double-recording of recent models on apply.
Hotfix: Homebrew standalone binary failed on first TUI launch.
- Standalone release binaries no longer externalize
react-devtools-core, which broke first TUI launch after Homebrew install (Cannot find package 'react-devtools-core').
- Homebrew formula is
corbits-code(brew install corbitsdev/tap/corbits-code). The CLI binary remainscorbits.
Patch release: always-on PerfTrace measurement stack, session state under ~/.corbits/projects, post-upgrade release notes in the interactive banner, and related Codex/TUI polish.
- Always-on PerfTrace — in-process span API, ring buffer, and privacy-strict tag allowlist (
src/perf/). One span model for turns, inference (TTFT/stream), tools, permission waits, and subagents. No settings required for local measurement. - Offline dump + rollup —
dumpSpansand pure rollups by phase/turn/session; TTFT vs stream shares. - Attribution report — exclusive wall-time shares (inference / tools / permission / subagent / other), open-turn stall dumps, CLI
bun scripts/perf-report.ts, operator guide indocs/perftrace-attribution-guide.md. - Opt-in OTEL export — settings/env surface (
OTEL_EXPORTER_OTLP_*,~/.corbits/settings.jsonotelblock) plus OTLP HTTP JSON sink. Fail-closed config; dump-safe header redaction. Targets Phoenix, PostHog OTEL, or any OTLP collector — separate from PostHog product analytics. - Latency eval harness — assert phase presence and relative magnitudes in tests (
assert-spans, multi-tool fixture). - Reasoning effort by agent role — orchestrator vs task-leaf defaults so high-effort leaves stop multiplying wall time.
- Session state under
~/.corbits/projects— project key from git toplevel (worktrees share); dual-read migrate from in-repo.agent-state; path-restriction exception for the global state root. - Post-upgrade release notes — on a fresh interactive start after upgrade, show bounded Keep-a-Changelog sections in the session banner; stamp
lastChangelogVersionin global settings; first install is quiet;/changelogand/changelog fullfor on-demand history. ShipsCHANGELOG.mdnext to release binaries. - Streaming stall / loop detection — trailing-window repetition detection; preserve partial streamed output in exec and TUI; partial-capture lifecycle owned by the cycle recorder.
- Nested UI polish — quieter chrome, context meter, task/shell rows, observe-leave behavior.
- Approval queue re-eval — when a grant widens, re-check the pending queue; stored approvals evaluated through
@intx/authz. - Task re-dispatch cap — parents stop re-dispatching identical thrashing / budget-exhausted briefs.
- Hard-deny shell authz through
env -S/ split-string payloads (including empty payload and end-of-options forms). - Streaming markdown tables stay on one column-width set (no mid-stream realign / raw-pipe degradation).
- Shell approval modal scroll, expand, and agent-label display; shared scroll-window math.
- Worktree preserve: do not drop stash when unknown or detached HEAD advanced; count gitignored-but-present files as content worth keeping. (related main commits)
- Judge shell auto-allow and restriction against the process cwd; queued-grant coverage uses the session path restriction.
- Package rename: root package is
@corbits/code(wascorbits). - Homebrew release tap points at
corbitsdev/homebrew-tap. - TUI root and event log split into focused modules (assembly vs presentation).
- Sub-agent tool description no longer claims an incorrect working-tree isolation model.
docs/PERFTRACE.md— local sink, OTEL config, collector examples, relationship to product telemetry.- Codex request parity checklist (spike, no production behavior change).
- Codex SSE golden fixture pack + parse tests.
Patch release: agents use the core tools. Every behavior change validated by a before/after eval matrix on grok-4.5 — pass rate 19/21 → 21/21, total turns 312 → 106, input tokens 2.8M → 1.1M, zero sub-agent churn on the stall fixture.
- Built-in
web_fetch(native fetch, markdown output, SSRF guards) andweb_search(keyless hosted providers) replace the plugin-only web tools (). - Per-project
settings.envsupplies shell environment as configuration instead of commands. - Model-family policy drives the directors: main sessions get a wrap-up nudge and a loud auto-pause on runaway tool-only loops; silent sub-agents get a continuation nudge then a clean stop; grok thresholds tightened ().
- A shared prompt discipline block steers every model to dedicated tools, single-purpose commands, and finishing behavior ().
- The capability eval is now a behavior gate: bait cases, behavior metrics, repeat runs, provider pinning with loud mismatch failure, and honest baseline comparison ().
- Command substitution inside double quotes stays visible to grant replay ().
- Persisted grants no longer key on model-authored comment lines ().
- Chains of five or more segments are approved once only; env assignments (including
env -Ssmuggling, scanned deny-first) and upload-shaped network commands now ask ().
- Sub-agents receive the web tools and project env the prompt promises them; the family policy reaches interactive sessions; approval and error copy states thresholds and next steps.
Patch release: shell permission hardening, sub-agent dispatch controls, and a live TUI test suite.
- Command substitution (
`...`,$(...)) no longer auto-allows, and substituted paths stay visible to the restricted-target check. - Authz-hard-blocked commands deny at the gate instead of showing an Accept button.
- Restricted targets are re-checked when replaying a stored grant.
- Glob metacharacters are escaped in persisted exact-command grants.
- Relative
pluginPathsentries are dropped at trust migration instead of resolving against the launch directory.
- Task tiers resolve OAuth providers from the live catalog.
- Typed task spawn contract: intent, success criteria, do-not list, report focus, with intent-driven soft defaults for tools, tier, and turn budget.
- Sub-agent thrash detection with re-read caps and a one-shot wrap-up nudge near the turn budget; Grok leaf agents get a finish-bias prompt residual.
- A stale approval-prompt resume no longer unfreezes a newer tool-budget pause.
- The TUI test suite runs again (1105 tests were dark from a Bun isolate regression).
Patch release: permission-approval hardening and plugin trust fixes.
- Tool timeout freezes while a permission prompt is open; toggle via Settings → Tools.
- Path-added plugin trust is global, revocable from
/plugins, and survives directory changes. - Install docs and package metadata point at corbits-code and the
dist/corbitsbinary.
- Chained shell commands prompt once for the whole chain; multi-segment grants are exact-match only and the modal strips spoofing characters.
Patch release: reverts the inline transcript renderer.
- Alternate-screen transcript restored — the inline renderer emitted committed history into the terminal's native scrollback, so a running session could be scrolled out of, and a live tail shorter than the viewport left a large blank region between the transcript and the prompt. Reverts the differential-inline cutover, bringing back the full-screen alternate buffer, mouse-wheel scrolling, and the app-owned viewport.
Patch release: safety, subagent performance, TUI polish, persistence correctness, and first-class release packaging. Everything merged after 0.2.81 through 3084b44.
corbits exec+ local capability eval harness — non-interactive product path and fixture-based capability suite for regression gates.- FIFO operator approval queue — plan, permission, and operator modals no longer race; one gate at a time.
- Release packaging —
scripts/release.shbuilds macOS/Linux binaries, checksums, debs, GitHub release assets, and Homebrew tap formula. - Diff polish — background washes on edit hunks and
+N/-Mstats on collapsed rows. - Theme-routed chat chrome — input and slash menu colors go through the theme.
- Scrub and truncate MCP tool results; strip terminal control sequences from tool output.
- Secret denylist covers cloud and keychain credential shapes.
- Fail-closed shell pre-approval: no multi-segment grants.
- Auto-mode shell asks when the command targets paths outside the workspace.
- Shell guard allows piped search without unblocking open-ended tree walks.
- Reject
tool-output://URIs before they reach ripgrep or the filesystem. - Constrain
@-mention file resolution to the workspace root. - Allow sibling worktree paths past pre-realpath path confinement.
edit_fileline-range edits always run post-write verification.- Reject conflicting
edit_filemodes (substring vs line-range exclusive). - Partial
grepresults on ripgrep size cap or timeout. - Cap long error output and show a pass/fail glyph on shell failures.
- Coalesce stray redirect fragments back into their owning shell command.
- Cache subagent session snapshots by revision instead of cloning on every notify.
- Dedup tool names on the
tool_call.startpath in the session store. - Skip retaining full turn history when no lifecycle hooks are configured.
- Gate stream drain intervals to streaming and flush on stop.
- Validate persistence boundaries with arktype and unify goal-status enums.
- Record real cache-write token counts instead of hardcoding zero.
- Fall back to 256-color values on non-truecolor terminals.
- Rename Intercode → Corbits Code with
corbitsCLI hard cutover. - Migrate legacy
.intercodesettings on first Corbits run. - Minimal anonymous PostHog telemetry with hard opt-out (see
docs/TELEMETRY.md).
- Inject full agent profile bodies into
search_agents. - Sub-agents can re-read parent
tool-output://blobs. - Cancel salvage and optional
tasktier override. - Claude marketplace plugin discovery when opted in.
- Never-acted salvage when a sub-agent uses no tools.