Skip to content

Commit 0750a21

Browse files
committed
Merge origin/main
# Conflicts: # docs/IMPLEMENTATION.md # src/agent/directors/registry.test.ts # src/agent/directors/tool-sets.ts # src/agent/tool-search.test.ts # src/agent/tool-search.ts # src/agent/tools.ts # tests/unit/tui/agent-tools.test.ts
2 parents 44d98c6 + bebe563 commit 0750a21

201 files changed

Lines changed: 6564 additions & 695 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.

.github/workflows/ci.yml

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,70 @@ on:
66
pull_request:
77
workflow_dispatch:
88

9+
concurrency:
10+
group: ci-${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }}
11+
cancel-in-progress: ${{ github.event_name != 'push' }}
12+
913
jobs:
10-
check:
14+
lint:
15+
runs-on: ubuntu-latest
16+
# TODO(CL-6802 stage 2): flip blocking after the mechanical fix batch
17+
continue-on-error: true
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v4
21+
22+
- name: Setup Bun
23+
uses: oven-sh/setup-bun@v2
24+
with:
25+
bun-version: "1.3.14"
26+
27+
- name: Cache dependencies
28+
uses: actions/cache@v4
29+
with:
30+
path: node_modules
31+
key: bun-${{ hashFiles('bun.lock') }}
32+
33+
- name: Install dependencies
34+
run: bun install --frozen-lockfile
35+
36+
- name: Cache lint
37+
uses: actions/cache@v4
38+
with:
39+
path: |
40+
.eslintcache
41+
node_modules/.cache/prettier
42+
key: lint-${{ github.sha }}
43+
restore-keys: |
44+
lint-
45+
46+
- name: Lint
47+
run: bun run lint
48+
49+
typecheck:
50+
runs-on: ubuntu-latest
51+
steps:
52+
- name: Checkout
53+
uses: actions/checkout@v4
54+
55+
- name: Setup Bun
56+
uses: oven-sh/setup-bun@v2
57+
with:
58+
bun-version: "1.3.14"
59+
60+
- name: Cache dependencies
61+
uses: actions/cache@v4
62+
with:
63+
path: node_modules
64+
key: bun-${{ hashFiles('bun.lock') }}
65+
66+
- name: Install dependencies
67+
run: bun install --frozen-lockfile
68+
69+
- name: Typecheck
70+
run: bun run typecheck
71+
72+
build-and-test:
1173
runs-on: ubuntu-latest
1274
steps:
1375
- name: Checkout
@@ -23,6 +85,12 @@ jobs:
2385
with:
2486
bun-version: "1.3.14"
2587

88+
- name: Cache dependencies
89+
uses: actions/cache@v4
90+
with:
91+
path: node_modules
92+
key: bun-${{ hashFiles('bun.lock') }}
93+
2694
# The runner image has no ripgrep, so the grep plugin silently exercised
2795
# its fallback walker and left the ripgrep path untested.
2896
- name: Install ripgrep
@@ -31,9 +99,6 @@ jobs:
3199
- name: Install dependencies
32100
run: bun install --frozen-lockfile
33101

34-
- name: Typecheck
35-
run: bun run typecheck
36-
37102
- name: Build
38103
run: bun run build
39104

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ dist/
88
.corbits/MEMORY.md
99
.interchange/
1010
.cache/
11+
.eslintcache
1112
.pi
1213
.claude/settings.local.json
1314
.claude/worktrees

.prettierignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
dist/
2+
vendor/
3+
.worktrees/
4+
scratch/
5+
node_modules/
6+
CHANGELOG.md

.prettierrc.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"semi": true,
3+
"trailingComma": "all",
4+
"printWidth": 100
5+
}

AGENTS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ When refactoring replaces an old path, delete the old one. No back-compat shims,
3838
## Build & Validation
3939

4040
```bash
41-
bun run typecheck
42-
bun run build
43-
bun run test
41+
bun run check
4442
```
4543

44+
`bun run check` is the single pre-PR gate: it runs `lint`, `typecheck`, `build`, and `test`, in that order, matching CI.
45+
4646
Run the full suite before declaring any task complete. Do not substitute individual targets. If a failure is pre-existing and unrelated to your change, say so explicitly.
4747

4848
`bun run test` runs `bun test ./src ./tests ./evals`. A bare `bun test` also

CHANGELOG.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,189 @@ 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+
## [0.2.103] - 2026-08-23
15+
16+
### TUI
17+
18+
- **In-flight tool rows show elapsed time.** Ordinary pending calls (MCP,
19+
search, shell) tick a live clock the same way Task rows already do, so a
20+
slow-but-alive call is distinguishable from a hung turn.
21+
22+
- **The stall notice comes down the moment activity resumes.** It is a live
23+
diagnosis, not a sticky banner: a tool finishing or the turn settling
24+
clears it on that paint, even if the monitor tick has already been
25+
cancelled.
26+
27+
### Tools
28+
29+
- **MCP tool calls arm their own watchdog.** Default 5 minutes
30+
(`settings.mcp.timeoutMs`), still capped by `tools.maxTimeoutMs` when set.
31+
Expiry returns a model-reactable tool error; the turn is not aborted.
32+
`task` and `run_shell` behavior is unchanged.
33+
34+
### Sub-agents
35+
36+
- **Successful leaf `task` completions re-arm the primary backstop.** A
37+
productive fleet no longer hard-pauses solely from turns-since-operator
38+
volume. Failed or salvaged leaf reports get no credit, so true tool-only
39+
no-progress still nudges then pauses.
40+
41+
- **Leaf no-progress repeat limit raised from 2 to 5.** Legitimate polling
42+
/ retry streaks survive longer before salvage.
43+
44+
### Auth / evals
45+
46+
- **Exec refreshes Codex instructions before first Codex inference**, same
47+
shared path as the TUI, with best-effort fallback to cache/bundled copy.
48+
Capability eval cells also stamp instructions hash, built-in tools, and
49+
requested reasoning effort for triage.
50+
51+
- **New capability eval cases:** misleading-symptom, flaky-diagnosis,
52+
broken-toolchain, hidden-contract-inventory (held-out tests), and
53+
impossible-spec (reward-hacking bait).
54+
55+
### CI
56+
57+
- **Codex instructions unit mock restores `node:fs` in `afterAll`.** The
58+
leaked in-memory fake had been poisoning later suites under
59+
`bun test ./src ./tests ./evals` since the mock landed.
60+
61+
## [0.2.102] - 2026-08-22
62+
63+
### Permissions
64+
65+
- **Workspace containment returns canonical real paths.** Writers receive the
66+
realpath from the containment allow, closing the symlink-retarget window
67+
between check and write; the write-path allowlist compares both sides in
68+
canonical space so symlinked cwds don't false-deny.
69+
70+
- **Dangling or looping symlink components fail closed.** A path component
71+
that exists but cannot resolve (dangling link, symlink loop) is denied by
72+
containment and the write-path allowlist instead of being treated as a
73+
missing tail; genuinely-new file paths still resolve via the nearest real
74+
ancestor.
75+
76+
### Trust
77+
78+
- **Project-trust stores are keyed by realpath.** The same repo reached via
79+
symlink twins (e.g. `/tmp` vs `/private/tmp`) now finds the same grants;
80+
the saved `repo` field and validity compare canonicalize consistently.
81+
82+
### TUI
83+
84+
- **Typeahead popups no longer leak queued permission gates.** Both the
85+
@-mention popup and the slash-command palette refresh their suggestion
86+
lists in place instead of close+reopen, so a queued gate can't open (and
87+
swallow keys) mid-filter. Zero matches shows "(no matches)" without
88+
releasing the popup; Enter there preserves the typed text.
89+
90+
## [0.2.101] - 2026-08-22
91+
92+
### Permissions
93+
94+
- **`/yolo` persists as the user-global skip-permissions default.** Exec
95+
inherits it; `--dangerously-skip-permissions` still forces the current
96+
process. Secret-guard and authz still apply. The TUI shows a startup notice
97+
(and exec a stderr warning) when prompts are disabled by the saved default.
98+
99+
- **Always-allow for `git worktree *` now covers later worktree commands.**
100+
Contained and permitted-sibling worktree add/remove segments no longer hit
101+
the restricted-path guard before grant matching, so a standing grant
102+
applies instead of re-prompting on every dispatch. Force flags, chained
103+
commands, and genuinely-outside destinations still prompt.
104+
105+
- **Empty workspace roots can no longer disable path containment.** An empty
106+
string in the roots list used to make every absolute path count as
107+
contained; it is now rejected before the prefix compare.
108+
109+
### TUI
110+
111+
- **The stall watchdog no longer aborts healthy waits for the model.** A run
112+
that is merely awaiting the model's next token (after submit or after a
113+
tool batch resolves) surfaces a persistent stall notice but is never
114+
auto-aborted; auto-abort is reserved for a stream that started emitting
115+
and then died mid-flight. Live sub-agents and open permission gates keep
116+
their existing exemptions.
117+
118+
### Sub-agents
119+
120+
- **Thinking-token loops now trip the repetition detector.** Thinking deltas
121+
feed the same cycle buffer and abort path as visible text, with a
122+
short-period digit-folded check that catches monotonic counters (`0/1 1/2
123+
2/3 …`) without flagging healthy templated enumeration; the looped window
124+
is flushed to `partial.jsonl` for diagnosis.
125+
126+
### Trust & plugins
127+
128+
- **Project-trust stores are atomic, serialized, and cwd-correct.** Saves go
129+
through temp-file + rename behind a per-store mutation queue; a store
130+
missing its `repo` field is invalid (empty grants); plugin trust paths
131+
resolve against the project cwd, never the process cwd, and relative
132+
entries are dropped on load.
133+
134+
- **Repo plugins with `defaultEnabled` load agent profiles**, matching how
135+
skills already gate; tool plugins remain consent-gated. A later same-id
136+
install can no longer silently turn a bundled default off.
137+
138+
### CI
139+
140+
- **ESLint + Prettier land with a split concurrent CI** (lint / typecheck /
141+
build-and-test) with dependency and lint caches; `bun run check` is the
142+
single pre-PR gate. The lint job is non-blocking until the repo-wide
143+
mechanical fix batch lands.
144+
145+
## [0.2.100] - 2026-08-22
146+
147+
### Plugins
148+
149+
- **Requested `run_shell` timeouts are no longer capped at 10 minutes.** The 15s
150+
default when timeout is omitted is unchanged. `shell.maxTimeoutMs` still
151+
clamps the command when set.
152+
153+
- Capability evals accept `--concurrency <n>` (env `CORBITS_EVAL_CONCURRENCY`,
154+
default 1); overlapping `httpFixture` cells isolate `EVAL_HTTP_URL` so
155+
parallel web-bait runs do not share a process.env origin.
156+
157+
### TUI
158+
159+
- **Tool `run()` no longer has an implicit 11-minute wall-clock abort.** The
160+
outer watchdog arms only when Settings set `tools.timeoutMs` /
161+
`tools.maxTimeoutMs`, or when `run_shell` passes a positive `timeout`
162+
(requested plus slack, so this layer cannot beat shell-guard). Unset
163+
settings leave `task` and other tools unbounded; parent cancel, maxTurns,
164+
and eval `--agent-timeout-ms` still bound the run. `tools.maxTimeoutMs`
165+
still clamps non-shell tools when set and does not cap a longer requested
166+
`run_shell`.
167+
168+
- **`task` (sub-agent dispatch) is always exempt from the generic tool-execution
169+
watchdog**, even when Settings arm it. Workers past 11 minutes with healthy
170+
activity complete and return their own report instead of surfacing as
171+
operator cancels; maxTurns, no-progress, thrash, and the opt-in `deadlineMs`
172+
remain the operative bounds.
173+
174+
### Directors
175+
176+
- **Skywalker spawn-target for product code is `build`.** Prompt and
177+
skill copy that still said `spawn implement` / `task(agent="implement")`
178+
now dispatch `build`. Intent graph `explore → implement → critique`
179+
and slash `/implement` are unchanged.
180+
181+
- **Skywalker may DIY tiny product writes (CL-6629).** Path tools
182+
(`write_file` / `edit_file` / `delete_file`) remount on the primary
183+
session. Tiny/single-file/one-route bounded edits are the exception;
184+
spawn remains default for substantial/multi-file/parallel/specialist
185+
work (hard cap 4 workers). Docs/design still spawn shakespeare /
186+
bruckheimer / brand-reviewer except one-line fixes. Greybeard stays
187+
write-free. Shell file-writes stay denied. Spawn is a judgment call,
188+
not a tool ban.
189+
190+
- **Exec and capability evals can run as a chosen primary director.**
191+
`corbits exec --director <id>` (and eval `--director`) overlays that
192+
package's system prompt and initially-advertised tool set on the product exec path.
193+
Omit / skywalker keep the default Skywalker session. Directors that
194+
cannot spawn (for example build) do not mount `task`. This is an
195+
exec/eval/CI override, not a TUI or single-agent mode.
196+
14197
## [0.2.99] - 2026-08-21
15198

16199
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.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ Corbits Code defaults to **auto mode** (`auto = true`). Workspace file writes/ed
101101

102102
Wrappers such as `bash -c '…'`, `sh`/`zsh -c`, `xargs`, and transparent prefixes (`env`, `nice`, `timeout`) are peeled so the same rules apply to the inner command. Unparseable wrappers fall through to ask rather than auto-allow.
103103

104-
Catastrophic patterns (`rm -rf /`, `sudo`, `curl | bash`, force-push, open-ended `find`/`rg`/`grep -r`, …) are always denied by authorization, independent of auto mode. `--dangerously-skip-permissions` (and mid-session `/yolo` in the TUI) is a separate escape hatch that bypasses the permission gate (not secret-guard path denies or authz hard blocks).
104+
Catastrophic patterns (`rm -rf /`, `sudo`, `curl | bash`, force-push, open-ended `find`/`rg`/`grep -r`, …) are always denied by authorization, independent of auto mode. `--dangerously-skip-permissions` still forces this process; `/yolo` persists as the user-global default. Both bypass the permission gate (not secret-guard path denies or authz hard blocks).
105105

106106
Details live in `docs/PRODUCT.md` (safety model) and `docs/ARCHITECTURE.md` (permission gate and auto-shell policy).
107107

0 commit comments

Comments
 (0)