Skip to content

Commit dad6816

Browse files
committed
Merge remote-tracking branch 'origin/main' into cl-7048-overhaul-typescript-skill
# Conflicts: # tests/unit/corbits-skills-catalog.test.ts
2 parents 07b4e54 + dabb74d commit dad6816

144 files changed

Lines changed: 3474 additions & 1927 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ matching `## [X.Y.Z]` section (plus install instructions). Do not maintain
1111
parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
1212
`## [Unreleased]` to `## [X.Y.Z] - YYYY-MM-DD`, then run the release script.
1313

14+
## [Unreleased]
15+
16+
### Fixed
17+
18+
- One-shot confirmation flashes (copy, mouse toggle, attach results, reasoning effort, stall recovery) now clear themselves after a short TTL. Rate-limit waits no longer park on the bottom notice row; the durable error stays in the transcript. Live stall notice and landing hold still omit a TTL so they stay until replaced.
19+
- A TTL flash no longer paints chrome after the TUI renderer is destroyed, which crashed parallel TUI tests with `TextBuffer is destroyed`.
20+
1421
## [0.3.1] - 2026-08-24
1522

1623
### Fixed

docs/ARCHITECTURE.md

Lines changed: 34 additions & 33 deletions
Large diffs are not rendered by default.

docs/IMPLEMENTATION.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,14 @@ Sixteen packages under `src/agent/directors/<id>/` register in `DIRECTOR_REGISTR
157157
2. `packageToProfile` maps envelope (`tools.allow`/`deny`) to `AgentProfile.capabilities` and `spawn.maySpawn``orchestrator`. System prompts are prefixed with a stable identity block (`formatDirectorSystemPrompt`: agent id, model role, optional skills).
158158
3. Nested spawn: packages with `spawn.allowlist` forward that list into nested `task` (`spawnAllowlist` on nestedDispatch). Off-list `agent` is refused. `task(agent=skywalker)` is refused (primary is not a spawned worker). Primary omits the list so plugin profiles stay reachable.
159159
4. `directorProfiles()` is the spawn catalog (`default-agents.ts`) — closed set minus skywalker; plugin agent profiles still load and can override by id.
160-
5. Primary chat role is Skywalker: `buildChatRole()``createSkywalkerSystemPrompt()`. Product mutation tools (`write_file` / `edit_file` / `delete_file`) live in CORE (and `SKYWALKER_TOOLS`) so they are advertised on the primary without a `tool_search` round-trip. DIY tiny/bounded edits on the parent; spawn build/docs directors for substantial work — a prompt judgment call, not a toolset strip. `PRIMARY_DENIED_PRODUCT_TOOLS` is gone. Shell file-writes stay denied; MCP tools are not re-filtered by a product-write deny list. There is no static per-profile write-path lock (CL-6952).
160+
5. Primary chat role is Skywalker: `buildChatRole()``createSkywalkerSystemPrompt()`. Product mutation tools (`write_file` / `edit_file` / `delete_file`) live in CORE (and `SKYWALKER_TOOLS`) so they are advertised on the primary without a `tool_search` round-trip. DIY tiny/bounded edits on the parent; spawn builder/docs directors for substantial work — a prompt judgment call, not a toolset strip. `PRIMARY_DENIED_PRODUCT_TOOLS` is gone. Shell file-writes stay denied; MCP tools are not re-filtered by a product-write deny list. There is no static per-profile write-path lock (CL-6952).
161161

162162
**Codex tool proxies.** When the active provider is Codex (`isCodexProviderName`), `createAgentToolset` and `runSubAgent` mount `apply_patch`, `shell`, and `update_plan` stringTools from `createCodexToolProxies`, all forwarding through the same posix `ToolRunner` seam (`runTool`) so permission plugins still apply. `apply_patch` parses the Codex envelope and forwards each op (`write_file` / `delete_file` / `read_file`). `shell` — the native Codex name is `shell`, not `exec_command`, per the pinned base-instructions text quoted in `codex-responses-adapter.ts`'s bridge message — normalizes Codex's `command` (string or `["bash","-lc",script]`-style argv array), `workdir`, and `timeout_ms` onto `run_shell`'s `{command, cwd?, timeout?}` and is gated by `allowShellFromCapabilities` (mirrors `allowDeleteFromCapabilities` against `run_shell`). `update_plan` maps Codex's `plan: [{step, status}]` onto `manage_tasks(action: "create")`; `pending`/`in_progress`/`completed` map to `todo`/`doing`/`done` — `manage_tasks`'s `cancelled` status has no Codex equivalent and is never produced by this proxy. Primary strips `apply_patch` after mount (Corbits DIY stays on `write_file` / `edit_file` / `delete_file`); `shell` and `update_plan` stay on primary (same classification as `run_shell` / `manage_tasks`). Build and docs leaf allowlists (`BUILD_TOOLS` / `DOCS_TOOLS`) include `apply_patch` so Codex workers keep the proxy after the capability filter. `CORE_TOOL_NAMES` does not list it.
163163

164164
6. There is no static write-path declaration on packages or profiles (CL-6952 removed it — no shipped director ever set one). Instead, `task-tool.ts` tracks each running dispatch by cwd; a new dispatch that lands on the same cwd as a still-running lane records a `concurrent-lane-overlap` entry in `intervention-log.ts` (class `conflict`). This is advisory only — it never blocks the spawn, since cwd overlap does not prove the two lanes touch the same files.
165165
7. Spawn effort: pin > package `modelRole` default (`defaultEffortForDirector`; intern=low; plan/review/orchestrator=high; implement/explore/docs/test=medium) > orchestrator/worker binary > parent inheritance. Optional skills are listed in the identity header for awareness; workers do not mount `use_skill` (guidance is baked into package system prompts). Primary mounts `use_skill` for its own skill list.
166166

167-
Intent defaults: `intent=implement` → director `build`; explore/plansame-named director; review → critique; general → error. Spawn: skywalker full fleet; greybeard intern/explore/critique only; all other directors no `task`. Live `<env>` injects cwd, platform, arch, runtime, date, and git status on every chat and worker prompt.
167+
Intent defaults: `intent=implement` → director `builder`; `explore``explorer`; `plan``counsel`; `review``critic`; general → error. Spawn: skywalker full fleet; greybeard intern/explorer/critic only; all other directors no `task`. Live `<env>` injects cwd, platform, arch, runtime, date, and git status on every chat and worker prompt.
168168

169169
### Auto Mode
170170

docs/PLUGINS.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,14 @@ shape.
309309
become slashes (marketplace backward compatibility). Frontmatter
310310
`argument-hint` is preserved so the TUI can show greyed arg guidance (e.g.
311311
`/create-issue``[description] [--from-doc]`). This is an additional
312-
surface: `discoverSkills` is unchanged, so the model can still auto-invoke any
313-
skill via `use_skill` — including first-party recipes that are not operator
314-
slashes (`dispatch`, `git-rebase`, `linear-issue-workflow`, `style`,
315-
`philosophy`, `typescript`, `opsh`). The slash command is a direct user entry
312+
surface: `discoverSkills` skips skills with `disable-model-invocation: true`
313+
from the lazy listing (those stay loadable via explicit `use_skill` /
314+
`resolveSkillBody`), so the model does not auto-suggest background libraries.
315+
First-party recipes that are not operator slashes remain listed for
316+
`use_skill` when they only set `user-invocable: false` (`dispatch`,
317+
`git-rebase`, `linear-issue-workflow`, `style`, `philosophy`, `typescript`,
318+
`opsh`). Background libs such as `git-worktrees` set both flags. The slash
319+
command is a direct user entry
316320
point on top.
317321
- **First-party catalog.** `plugins/corbits-skills/` (id `corbits-skills`,
318322
kind `command`, `defaultEnabled: true`) is the bundled skill catalog. Origin

docs/PRODUCT.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ is the direct, explicit resume path.
9898

9999
The TUI has an extensible slash-command framework. Built-ins include `/help` (shortcut + command overlay), `/model` (models-only picker for connected accounts; **Alt+A** adds a provider), `/settings`, `/permissions`, `/plugins`, `/clear`, `/new`, `/mcp`, and `/yolo` (persists as the user-global skip-permissions default; `--dangerously-skip-permissions` still forces this process; secret-guard and authz still apply; `/yolo [on|off|toggle]`, bare `/yolo` toggles), plus a `/<name>` command per available workflow. When a session starts with the persisted default already on, the TUI shows a startup notice ("Permission prompts are disabled by your saved default…") so the silent machine-wide default is never invisible; `corbits exec` prints the equivalent warning to stderr. Plugins can register additional commands.
100100

101-
**Default skills** exist out of the gate as first-party slash **actions**, not director names: `/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`. Each one is a Skywalker recipe — the slash sends the skill body to the primary, which then `task(agent="<director>")`. `/scribe` → shakespeare; `/implement` spawns build / greybeard / critique as the recipe specifies; `/plan` → plan director (eng change plan: files, AC, non-goals, risks, ordered steps; does not implement); `/review` is a code-review action. `/create-issue` remains the tracker command: Linear MCP when available; otherwise it `ask_operator`s for the platform (GitHub etc.) and persists `Preferred issue tracker` in `.corbits/MEMORY.md` (GitHub via `gh issue create`). Dispatch is not a default slash — it stays `use_skill` only, along with git-rebase, linear-issue-workflow, style, philosophy, typescript, and opsh (`user-invocable: false`). Draper and emil are not slashes; they remain closed directors via `task(agent=…)`. There is no catch-all worker. Slash names are also available to the model via `use_skill`. Disable the catalog in `/plugins` (`corbits-skills`) if you want them gone.
101+
**Default skills** exist out of the gate as first-party slash **actions**, not director names: `/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`. Each one is a Skywalker recipe — the slash sends the skill body to the primary, which then `task(agent="<director>")`. `/scribe` → shakespeare; `/implement` spawns builder / greybeard / critic as the recipe specifies; `/plan` → counsel director (eng change plan: files, AC, non-goals, risks, ordered steps; does not implement); `/review` is a code-review action. `/create-issue` remains the tracker command: Linear MCP when available; otherwise it `ask_operator`s for the platform (GitHub etc.) and persists `Preferred issue tracker` in `.corbits/MEMORY.md` (GitHub via `gh issue create`). Dispatch is not a default slash — it stays `use_skill` only, along with git-rebase, linear-issue-workflow, style, philosophy, typescript, and opsh (`user-invocable: false`). Draper and emil are not slashes; they remain closed directors via `task(agent=…)`. There is no catch-all worker. Slash names are also available to the model via `use_skill`. Disable the catalog in `/plugins` (`corbits-skills`) if you want them gone.
102102

103103
Providers are **models-first**: there is no standalone `/login` command. `/model` opens a **models-only list** (Recent, Favorites, then connected provider/model rows) — type-to-filter owns printable keys, so Connect is never a bare letter. **Alt+A** opens a dedicated add-provider selector over every first-class kind (OpenAI dual-path ChatGPT OAuth or API key, xAI, OpenCode Zen, Anthropic, Google, OpenCode Go, Z.AI Coding Plan, Custom), each annotated with its live account count and never filtered out for “already connected.” **Alt+F** toggles favorite on the highlighted model. **Alt+D** persists the highlighted pair as the default without switching the live session. Advanced provider drill-down (edit/delete/tiers) stays on the advanced surface, not a bare printable key while the model list is filtering. OAuth providers open their existing browser login with a named account step so multiple accounts per kind coexist (`codex/work`, …). API-key providers use the same named-instance step before the key (auth-only form: instance name + key + fixed catalog base URL), so personal and team keys land as distinct catalog rows (`openai/default`, `anthropic/work`, …); reusing a name re-keys that instance after confirm. Custom remains a free-form single endpoint (full manual form). Successful connect refreshes the catalog and reopens the model list focused on the new account’s default model. OpenCode Go routes each model by its protocol metadata (chat completions, OpenAI responses, or Anthropic messages) and can show subscription usage in the status bar when active (rolling 5h / weekly / monthly windows when the usage API responds; omitted on auth or network failure). When Go returns a quota or rate-limit error — including some HTTP 400 responses that carry limit payloads — Corbits classifies them so quota aborts cleanly and short provider rate limits remain retryable. On a free-tier or subscription quota hit, wait for the window to reset or use OpenCode Zen free models.
104104

@@ -144,14 +144,14 @@ Capabilities beyond the core toolset are opt-in plugins, enabled per workspace t
144144

145145
The primary session is always **orchestrator** (single-agent mode is gone). Its identity is **Skywalker** (product name remains Corbits Code; when asked its name, answer Skywalker): classify work, DIY tiny/single-file/one-route product edits, dispatch a **closed fleet of 16 directors** for substantial work, track the fleet, and synthesize. Product mutation tools (`write_file` / `edit_file` / `delete_file`) are mounted on the primary (CORE / `SKYWALKER_TOOLS`) — path tools are the DIY surface; spawn remains the default for substantial, multi-file, parallel, or specialist work. Shell file-writes stay denied. MCP tools are not re-filtered by a product-write deny list (that list is gone). There is no static per-package write-path declaration (CL-6952 removed it — no shipped director ever set one). A concurrent dispatch landing on the same working directory as another still-running lane is recorded as a `conflict` intervention, not blocked. Operator slash recipes (`/implement`, `/plan`, `/refactor`, `/review`, `/pull-request-review`, `/create-issue`, `/scribe`, `/interview`, `/ast-grep`) tell Skywalker which directors to spawn for substantial work; tiny/bounded edits may run on the primary.
146146

147-
| Lane | Directors |
148-
| --------- | ---------------------------------------------------------------------------------- |
149-
| Primary | skywalker |
150-
| Eng | build, explore, plan, intern, critique, greybeard, neckbeard, bruckheimer, gaasbot |
151-
| Design | draper, emil, brand-reviewer |
152-
| Docs / QA | shakespeare, testsmith, tester |
147+
| Lane | Directors |
148+
| --------- | -------------------------------------------------------------------------------------- |
149+
| Primary | skywalker |
150+
| Eng | builder, explorer, counsel, intern, critic, greybeard, neckbeard, bruckheimer, gaasbot |
151+
| Design | draper, emil, rand |
152+
| Docs / QA | shakespeare, testsmith, tester |
153153

154-
There is **no catch-all worker**. `task` requires `agent=…` or a non-general `intent` (implement/explore/plan/review→critique); bare dispatch and `intent=general` are refused. Named `task(agent=…)` selects a director package without requiring a plugin profile, except `skywalker` which is the primary session identity and is refused as a spawned worker. Nested spawn is runtime-enforced: only skywalker (full fleet allowlist) and greybeard (intern/explore/critique) may spawn; other workers have no `task`. Primary omits an allowlist so plugin profiles remain reachable from the main session.
154+
There is **no catch-all worker**. `task` requires `agent=…` or a non-general `intent` (implement/explore/plan/review→critic); bare dispatch and `intent=general` are refused. Named `task(agent=…)` selects a director package without requiring a plugin profile, except `skywalker` which is the primary session identity and is refused as a spawned worker. Nested spawn is runtime-enforced: only skywalker (full fleet allowlist) and greybeard (intern/explorer/critic) may spawn; other workers have no `task`. Primary omits an allowlist so plugin profiles remain reachable from the main session.
155155

156156
Corbits Code fans work out to short-lived **sub-agents** — child agents with their own loop, tools, and checklist — while the primary session stays focused.
157157

docs/TUI.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,10 @@ Color is a small, deliberate palette, not decoration
161161
(`src/tui/theme.ts`). Dimmed text is a dimmed cream, never a neutral
162162
gray, so every emphasis level keeps the same warm hue. Orange
163163
(`UI.action`) is spent once per screen: it marks the session identity,
164-
a leading `/command` or `@mention` in the prompt, and whatever is currently
165-
awaiting a human decision (an approval subject, an active choice) — nothing
166-
else competes with it. Standing caution (`mcp !`, `plugin !`, the context
167-
meter's 61–80 band) uses `UI.warning`; the meter turns `UI.error` at 81–100.
164+
a leading `/command` or `@mention` in the prompt, and the dithered subject
165+
of a decision surface (permission or operator ask) — nothing else competes
166+
with it. Standing caution (`mcp !`, `plugin !`, the context
167+
meter's 61–80 band, consequence impact under a list) uses `UI.warning`; the meter turns `UI.error` at 81–100.
168168
Ongoing, non-decision status uses the bronze/sand/ember chrome ramp and green
169169
(`UI.done`) for completion.
170170
The one deliberate exception is diff removals, where orange is content (the
@@ -292,9 +292,12 @@ approval.
292292
The decision surfaces (permission approval, operator question) are the one
293293
framed content in the shell, and they are shaped rather than merely listed
294294
(`src/tui/overlay-body.ts`): a dithered header (`░▒▓`) carries the
295-
subject in the action color, a blank row separates it from context, and each
296-
choice gets one row with the active choice marked by a solid block (``)
297-
rather than a background fill.
295+
subject in the action color — the only Breakthrough Orange on the card.
296+
The overlay host border and title use calm dim chrome (`UI.textDim`);
297+
consequence impact in the description zone paints `UI.warning` (sand), not
298+
orange. A blank row separates the subject from context, and each choice gets
299+
one row with the active choice marked by a solid block (``) rather than a
300+
background fill (cream text, not orange).
298301

299302
## How selectors should work
300303

@@ -546,7 +549,9 @@ running its own selection. Two chords cover remaining copy needs:
546549
(`CliRenderEvents.SELECTION``copyFinishedSelection` in
547550
`selection-copy.ts`). On mouse-up, non-empty selected text is written
548551
through the system clipboard port and the highlight clears with a status
549-
flash. Empty clicks do not copy.
552+
flash. Empty clicks do not copy. Confirmation flashes pass
553+
`ttlMs: RUNTIME_FLASH_MS` so they clear themselves; omit TTL only for
554+
live conditions that stay true until replaced (stall notice, landing hold).
550555
- **Alt+M** toggles DEC mouse reporting off and back on
551556
(`toggleMouseCapture`, `shell.ts`). Off, the terminal's own drag-select
552557
and copy work exactly as in any other terminal program; the status flash

0 commit comments

Comments
 (0)