Skip to content

Commit e1df050

Browse files
committed
Merge remote-tracking branch 'origin/main' into cl-11727-restore-the-live-codex-model-catalog-fetch-for-chatgpt
The comment above CODEX_DEFAULT_MODELS conflicted with #1580; this keeps both: the live-catalog fallback role and the Plus-catalog provenance. The list is unchanged.
2 parents 75655fe + d5d6f42 commit e1df050

21 files changed

Lines changed: 862 additions & 78 deletions

‎.corbits-triage.yml‎

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Corbits Triage policy.
2+
rules:
3+
- check: max-files-changed
4+
text: Flag pull requests over 30 files changed.
5+
max: 30
6+
onFail: label
7+
reason: A large change is a risk signal, not a hold.
8+
evidence:
9+
- maintainer-stated
10+
- check: max-lines-changed
11+
text: Flag pull requests over 5,000 lines changed.
12+
max: 5000
13+
onFail: label
14+
reason: A large change is a risk signal, not a hold.
15+
evidence:
16+
- maintainer-stated
17+
- check: no-merge-conflicts
18+
text: Flag merge conflicts with the base branch.
19+
reason: A pull request with conflicts cannot be merged as it is.
20+
evidence:
21+
- maintainer-stated
22+
- check: ci-green
23+
text: CI must pass before merge.
24+
reason: A change is not ready until CI passes.
25+
evidence:
26+
- maintainer-stated
27+
- check: conventional-commits
28+
text: Titles and commits follow Conventional Commits.
29+
reason: Titles and commits use the conventional form.
30+
evidence:
31+
- maintainer-stated
32+
- check: hidden-content
33+
text: Flag text hidden in the pull request.
34+
reason: Hidden text can steer a review.
35+
evidence:
36+
- maintainer-stated
37+
- check: no-duplicate
38+
text: Flag a pull request whose diff or commits match another open one.
39+
reason: Two pull requests for the same change waste a review.
40+
evidence:
41+
- maintainer-stated
42+
- check: sensitive-paths
43+
text: Route schema, auth, CI and lockfile changes to a person.
44+
reason: Those changes reach beyond what the diff shows.
45+
evidence:
46+
- maintainer-stated
47+
- check: no-forbidden-paths
48+
text: Never accept changes to node_modules/**.
49+
paths:
50+
- node_modules/**
51+
reason: Dependencies are not edited by hand.
52+
evidence:
53+
- maintainer-stated
54+
- id: no-ai-attribution
55+
check: text
56+
text: Titles, descriptions and commits carry no AI attribution.
57+
fields: [title, description, commits]
58+
failWhen: contains
59+
phrases:
60+
- "Co-Authored-By:"
61+
- "Claude-Session:"
62+
- "claude.ai/code/session"
63+
- "noreply@anthropic.com"
64+
- "Generated with Claude"
65+
- "Generated with [Claude"
66+
onFail: label
67+
reason: No AI co-author lines, session trailers, or generated-with footers.
68+
evidence:
69+
- maintainer-stated
70+
- id: conventions
71+
check: code-patterns
72+
text: Added code follows the repository's conventions.
73+
presets:
74+
- convention
75+
onFail: label
76+
reason: No invented fallbacks, nested ternaries, immediately invoked functions, promise chains, empty catches, or suppression comments.
77+
evidence:
78+
- maintainer-stated
79+
- id: no-process-env-in-tests
80+
check: code-patterns
81+
text: Tests do not read process.env.
82+
onFail: label
83+
reason: A test must not depend on the environment.
84+
evidence:
85+
- maintainer-stated
86+
patterns:
87+
- id: no-process-env-in-tests
88+
language: typescript
89+
message: Reads process.env in a test.
90+
files:
91+
[
92+
"**/*.test.ts",
93+
"**/*.test.tsx",
94+
"**/*.test.js",
95+
"**/*.test.jsx",
96+
"**/*.test.mjs",
97+
"**/*.test.cjs",
98+
]
99+
rule:
100+
pattern: process.env
101+
- id: no-process-env-in-tests
102+
language: javascript
103+
message: Reads process.env in a test.
104+
files:
105+
[
106+
"**/*.test.ts",
107+
"**/*.test.tsx",
108+
"**/*.test.js",
109+
"**/*.test.jsx",
110+
"**/*.test.mjs",
111+
"**/*.test.cjs",
112+
]
113+
rule:
114+
pattern: process.env
115+
actions:
116+
pass:
117+
- do: approve
118+
when:
119+
author:
120+
- users:
121+
- thegreataxios
122+
- brianjfox
123+
- do: request-review
124+
target:
125+
to: users
126+
users:
127+
- thegreataxios
128+
when:
129+
author:
130+
- external
131+
fail:
132+
- do: request-changes
133+
unsure:
134+
- do: assign
135+
target:
136+
to: users
137+
users:
138+
- thegreataxios
139+
when:
140+
author:
141+
- maintainers

‎CHANGELOG.md‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ release that deserves narration. Passing `--notes <file>` overrides both for
2020
the GitHub body. Sections below this line predate generation and were written
2121
by hand.
2222

23+
## [0.3.48] - 2026-10-30
24+
25+
### What's Changed
26+
* fix(agent): match tool_search queries against tool parameters by @bwachman in https://github.com/corbitsdev/corbits-code/pull/1573
27+
* fix(agent): match tool names across a trailing plural s by @bwachman in https://github.com/corbitsdev/corbits-code/pull/1574
28+
* fix(reactor): keep rejected and timed-out approval results across a rebuild by @bwachman in https://github.com/corbitsdev/corbits-code/pull/1575
29+
* fix(session): settle a dropped approval on the rebuilt agent without a new turn by @bwachman in https://github.com/corbitsdev/corbits-code/pull/1576
30+
* chore(deps): bump @corbits/oauth-core to 0.3.3 (CL-11513) by @TheGreatAxios in https://github.com/corbitsdev/corbits-code/pull/1572
31+
* fix(mcp): keep padded optional arguments from filtering MCP reads by @bwachman in https://github.com/corbitsdev/corbits-code/pull/1578
32+
* feat(review): post one plain-language review by @TheGreatAxios in https://github.com/corbitsdev/corbits-code/pull/1582
33+
34+
35+
**Full Changelog**: https://github.com/corbitsdev/corbits-code/compare/v0.3.47...v0.3.48
36+
2337
## [0.3.47] - 2026-10-26
2438

2539
### What's Changed

‎bun.lock‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎e2e/mcp-late-dispatch.test.ts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ describe("integration — late MCP dispatch", () => {
371371
);
372372

373373
test.serial(
374-
"padded optional MCP arguments reach the server minus the values its schema rejects",
374+
"padded optional arguments to a read MCP tool reach the server without rejected placeholders or null",
375375
async () => {
376376
const received: Record<string, unknown>[] = [];
377377
await withSession(async (session) => {
@@ -428,7 +428,6 @@ describe("integration — late MCP dispatch", () => {
428428
team: "",
429429
fields: [],
430430
priority: 0,
431-
assignee: null,
432431
release: "v0345-ef53e73667fa",
433432
},
434433
]);

‎package.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@corbits/code",
3-
"version": "0.3.47",
3+
"version": "0.3.48",
44
"description": "Single-process coding agent CLI built on the Interchange runtime (Bun + TypeScript)",
55
"private": true,
66
"license": "SEE LICENSE IN LICENSE.md",
@@ -90,7 +90,7 @@
9090
"@anthropic-ai/sandbox-runtime": "0.0.79",
9191
"@corbits/codex-provider": "0.1.3",
9292
"@corbits/meta-provider": "0.1.1",
93-
"@corbits/oauth-core": "0.3.2",
93+
"@corbits/oauth-core": "0.3.3",
9494
"@corbits/openai-responses": "0.2.2",
9595
"@corbits/xai-provider": "0.1.4",
9696
"@intx/agent": "workspace:*",

‎plugins/corbits-skills/skills/review/SKILL.md‎

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,29 +52,36 @@ Deeper work (file-by-file behavior, architecture, coherence) can go to sub-agent
5252

5353
Raise what helps the author. Flag real defects and architecture that would constrain future work. Skip hypothetical problems in cases the code need not handle, stylistic nits, and vague remarks like "could be cleaner".
5454

55-
- Every finding has a `path:line` and a concrete failure mode. Severity is the review action, not adjectives.
55+
- Every finding is one of **blocking** (breaks the contract or the behavior), **should-fix** (a real defect that should change in this diff), or **informational** (true, but not something this diff has to change; the same rank as file-for-later). Severity is the review action, not an adjective.
56+
- Cite a line range, `path:start-end`, not a single line unless the failure is one line. A range is the lines a reader opens to see the failure.
5657
- Describe the branch as it stands now, in present tense, from `git diff <base>...HEAD`, not the journey or the PR description.
57-
- Write to a colleague: propose rather than command, say why, describe consequences instead of "wrong" or "broken", and suggest the one-liner when the fix is small.
58+
- Write the description for a person: what goes wrong, and the consequence. No finder jargon, no pass names.
5859
- **Cite the check.** Every affirmative claim ("tests pass", "no regressions") names the command or file range that proved it. Otherwise run the check, strike the claim, or narrow it to what you examined ("read `lock.go:42-68`, no acquire-while-holding cycle there").
5960

6061
## 6. Report and post
6162

62-
Summarize with the findings. When the target has an open GitHub PR, post the finished review on it; a review that only lives in chat is not done. Post when the operator asked for a PR review, when `/implement`'s whole-branch gate runs on a branch with an open PR, or when a record on the PR is the purpose. Do not post a private local read, and do not reopen the analysis while writing the body.
63+
Summarize with the findings. When the target has an open GitHub PR, post the finished review on it; a review that only lives in chat is not done. Post when the operator asked for a PR review, when `/implement`'s whole-branch gate runs on a branch with an open PR, or when a record on the PR is the purpose. Do not post a private local read. Do not implement fixes. Do not reopen the analysis while writing the body.
64+
65+
Wait until every pass Dispatch started has reported. Passes do not post to GitHub and do not approve, comment, or request changes.
66+
67+
Then post exactly one review with `gh pr review`. One verdict for the whole diff. Use one of `--approve`, `--comment`, or `--request-changes`, and swap that flag to match the verdict:
6368

6469
```bash
6570
gh pr review <number-or-url> --comment --body-file <file>
6671
```
6772

68-
Use `--approve` or `--request-changes` for the verdict. Shape:
69-
70-
```markdown
71-
## Review · <Approve | Comment | Request changes>
73+
The body is one short paragraph of what the branch does now, then a bullet list. Nothing else. Do not name the passes. Do not use finder jargon.
7274

73-
<one line: what the branch does>
75+
Each bullet is the severity, then the description, then the line range:
7476

75-
### Findings
77+
```markdown
78+
<what the branch does now, in plain language>
7679

77-
- `path/to/file.ts:12` — concrete problem and why it matters
80+
- **blocking** — <what goes wrong> `path/to/file.ts:12-18`
81+
- **should-fix** — <what goes wrong> `path/to/file.ts:40-44`
82+
- **informational** — <what is true, and why this diff need not change it> `path/to/file.ts:7`
7883
```
7984

80-
A clean review says "No findings." after the one line. No throat-clearing, praise to soften a finding, emoji, or "nit:" taste. When more than one lens produced a distinct judgment (reviewer, planner waiver, warden), each posts its own labelled review, and only the lens that owns the merge verdict may approve. Paste the review URL back to the operator. Posting does not change Linear state. Remove the PR worktree afterward.
85+
Request changes when any bullet is blocking or should-fix. Comment when every bullet is informational. Approve when there are no bullets, and say "No findings." after the paragraph. No throat-clearing, praise, emoji, or "nit:".
86+
87+
The note back to the operator is that same body plus the review URL. Do not write a second, more technical summary in chat. Posting does not change Linear state. Remove the PR worktree afterward.

‎src/agent/tool-schema-normalize.test.ts‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,78 @@ describe("normalizeToolDefinitionsForProvider", () => {
163163
}
164164
});
165165

166+
describe("optional MCP properties", () => {
167+
const listIssues: ToolDefinition = {
168+
name: "mcp__linear__list_issues",
169+
description: "[linear] list issues",
170+
inputSchema: {
171+
type: "object",
172+
properties: {
173+
release: { type: "string" },
174+
priority: { type: "number" },
175+
},
176+
required: ["release"],
177+
},
178+
};
179+
const builtin: ToolDefinition = {
180+
...listIssues,
181+
name: "list_issues",
182+
};
183+
184+
test.each([
185+
{ providerName: "codex/plus", model: "gpt-5.6-terra" },
186+
{ providerName: "opencode-go", model: "gpt-5.1" },
187+
{ providerName: "codex", model: "codex-mini-latest" },
188+
])("$providerName $model advertises null on MCP tools only", (ctx) => {
189+
const [mcp, own] = normalizeToolDefinitionsForProvider(
190+
[listIssues, builtin],
191+
ctx,
192+
);
193+
expect(mcp?.inputSchema).toEqual({
194+
type: "object",
195+
properties: {
196+
release: { type: "string" },
197+
priority: { type: ["number", "null"] },
198+
},
199+
required: ["release"],
200+
});
201+
expect(own).toBe(builtin);
202+
});
203+
204+
test.each([
205+
{ providerName: "anthropic", model: "claude-sonnet-5-5" },
206+
{ providerName: "moonshot", model: "kimi-k2" },
207+
])("$providerName leaves MCP tools as they are", (ctx) => {
208+
const defs = [listIssues];
209+
expect(normalizeToolDefinitionsForProvider(defs, ctx)).toBe(defs);
210+
});
211+
212+
test("grok sanitizes MCP tools without advertising null", () => {
213+
const [out] = normalizeToolDefinitionsForProvider([listIssues], {
214+
providerName: "xai/default-2",
215+
model: "grok-4.6",
216+
});
217+
expect(out?.inputSchema).toEqual(listIssues.inputSchema);
218+
});
219+
220+
test("returns the same array when no MCP property changes", () => {
221+
const nullable: ToolDefinition = {
222+
...listIssues,
223+
inputSchema: {
224+
type: "object",
225+
properties: { assignee: { type: ["string", "null"] } },
226+
},
227+
};
228+
const defs = [nullable, builtin];
229+
expect(
230+
normalizeToolDefinitionsForProvider(defs, {
231+
providerName: "openai",
232+
model: "gpt-5.6",
233+
}),
234+
).toBe(defs);
235+
});
236+
});
237+
166238
test("grok sanitizes untyped properties and strips $schema", () => {
167239
const untyped: ToolDefinition = {
168240
name: "submit_result",

0 commit comments

Comments
 (0)