Skip to content

Commit 762b0cd

Browse files
committed
Harden Codex rewrite, echo force spelling, soften bake prose, drop link underline
Guard the Codex parallel_tool_calls rewrite with a non-JSON passthrough, echo the typed force spelling in grant-mismatch notices, soften bake-only telemetry prose to match use_skill reporting, and remove the markdown link underline the click-only transcript cannot back with hover.
1 parent 28d39de commit 762b0cd

6 files changed

Lines changed: 36 additions & 19 deletions

File tree

‎docs/PLUGINS.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,10 @@ shape.
326326
`skill_search` / `use_skill` when they only set `user-invocable: false`
327327
(`git-rebase`, `linear-issue-workflow`, `style`, `philosophy`,
328328
`native-integration`, `typescript`, `ponytail`, `opsh`). Background libs
329-
such as `git-worktrees` set both flags. Bake-only bodies such as
330-
`idiot-proof` and `native-runtime` also set both flags (baked into workers;
331-
not a slash and not listed for `use_skill`). The slash command is a direct
329+
such as `git-worktrees` set both flags. Bodies that stay out of discovery
330+
such as `idiot-proof` and `native-runtime` also set both flags (not a slash,
331+
and hidden from the skill listing — though an explicit `use_skill` load by
332+
name still resolves). The slash command is a direct
332333
user entry point on top.
333334
- **First-party catalog.** `plugins/corbits-skills/` (id `corbits-skills`,
334335
kind `command`, `defaultEnabled: true`) is the bundled skill catalog. Origin

‎docs/TELEMETRY.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ skill out of slash synthesis, not out of name reporting: eleven bundled
8686
skills carry the flag — eight stay listed and loadable (`git-rebase`,
8787
`linear-issue-workflow`, `opsh`, `philosophy`, `style`, `typescript`,
8888
`native-integration`, `ponytail`), `git-worktrees` resolves by explicit name
89-
only, and two stay hidden bake-only (`idiot-proof`, `native-runtime`). Of
89+
only, and two stay hidden from discovery (`idiot-proof`, `native-runtime`):
90+
still loadable by explicit name, but every load reports `custom`. Of
9091
the eleven, seven are reported by name and four stay `custom` (pinned;
9192
conservative under-reporting, never a leak). Unknown,
9293
project-local, and plugin-authored skill names are never transmitted —

‎src/permission/gate.ts‎

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,22 @@ function segmentGuard(
151151
// notice can name the operative reason: a force flag, or a destination the
152152
// containment authority did not approve. Returns undefined for anything else.
153153
// Display-only refinement — the guard decision itself is unchanged.
154-
function worktreeMismatchKind(
155-
segment: string,
156-
): "force" | "destination" | "worktree" | undefined {
154+
type WorktreeMismatch =
155+
| { kind: "force"; flag: string }
156+
| { kind: "destination" }
157+
| { kind: "worktree" };
158+
159+
function worktreeMismatchKind(segment: string): WorktreeMismatch | undefined {
157160
const tokens = tokenize(segment);
158161
if (tokens[0] !== "git" || tokens[1] !== "worktree") return undefined;
159162
if (tokens[2] !== "add" && tokens[2] !== "remove") return undefined;
160-
if (tokens.slice(3).some(isWorktreeForceFlag)) return "force";
163+
const flag = tokens.slice(3).find(isWorktreeForceFlag);
164+
if (flag !== undefined) return { kind: "force", flag };
161165
// `add` takes a destination for the new worktree; `remove` names an
162166
// existing worktree, so only `add` gets the destination noun.
163-
return tokens[2] === "remove" ? "worktree" : "destination";
167+
return tokens[2] === "remove"
168+
? { kind: "worktree" }
169+
: { kind: "destination" };
164170
}
165171

166172
// Explains a grant mismatch: a standing grant covers the segment, but the
@@ -174,13 +180,13 @@ function grantMismatchNotice(
174180
return "A standing grant matches this command, but it references a sensitive path, so it still needs approval.";
175181
}
176182
const worktreeKind = worktreeMismatchKind(segment);
177-
if (worktreeKind === "force") {
178-
return "A standing grant matches this command, but it uses --force, so it still needs approval.";
183+
if (worktreeKind?.kind === "force") {
184+
return `A standing grant matches this command, but it uses ${worktreeKind.flag}, so it still needs approval.`;
179185
}
180-
if (worktreeKind === "destination") {
186+
if (worktreeKind?.kind === "destination") {
181187
return "A standing grant matches this command, but the worktree destination is outside the approved locations, so it still needs approval.";
182188
}
183-
if (worktreeKind === "worktree") {
189+
if (worktreeKind?.kind === "worktree") {
184190
return "A standing grant matches this command, but the worktree is outside the approved locations, so it still needs approval.";
185191
}
186192
return "A standing grant matches this command, but it targets a path outside the workspace, so it still needs approval.";

‎src/provider/codex-responses.ts‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,19 @@ function withHostReasoningEffort(adapter: ProviderAdapter): ProviderAdapter {
5555
// (HTTP 200 on POST /codex/responses, echoed true in response.created). The
5656
// packaged adapter still pins false, so the host rewrites the field on the
5757
// wire; the reactor already fans out a multi-call batch concurrently.
58-
function withParallelToolCalls(adapter: ProviderAdapter): ProviderAdapter {
58+
export function withParallelToolCalls(
59+
adapter: ProviderAdapter,
60+
): ProviderAdapter {
5961
return {
6062
...adapter,
6163
buildRequest: (messages, model, options) => {
6264
const request = adapter.buildRequest(messages, model, options);
63-
const body = JSON.parse(request.body) as Record<string, unknown>;
65+
let body: Record<string, unknown>;
66+
try {
67+
body = JSON.parse(request.body) as Record<string, unknown>;
68+
} catch {
69+
return request;
70+
}
6471
body["parallel_tool_calls"] = true;
6572
return { ...request, body: JSON.stringify(body) };
6673
},

‎src/telemetry/classify.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ const BUILT_IN_AGENT_NAMES: ReadonlySet<string> = new Set([
8080
// eleven bundled skills carry it — eight stay listed and loadable
8181
// (git-rebase, linear-issue-workflow, opsh, philosophy, style, typescript,
8282
// native-integration, ponytail), `git-worktrees` resolves by explicit name
83-
// only, and two stay hidden bake-only (idiot-proof, native-runtime), which
84-
// are baked into agent prompts rather than invoked as skills. Of the eleven,
83+
// only, and two stay hidden from listings (idiot-proof, native-runtime):
84+
// `disable-model-invocation` keeps them out of discovery, but an explicit
85+
// `use_skill` / `resolveSkillBody` load still resolves — and reports `custom`.
86+
// Of the eleven,
8587
// seven are reported by name and four stay `custom` (pinned; conservative
8688
// under-reporting, never a leak). Project- or plugin-authored skills are
8789
// never reported by name.

‎src/tui/stream.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -953,9 +953,9 @@ const MARKDOWN_STYLES = {
953953
"markup.raw": { fg: UI.inFlight },
954954
"markup.list": { fg: UI.inFlightBright },
955955
"markup.quote": { fg: UI.textDim, italic: true },
956-
"markup.link": { fg: UI.inFlightBright, underline: true },
956+
"markup.link": { fg: UI.inFlightBright },
957957
"markup.link.label": { fg: UI.inFlightBright },
958-
"markup.link.url": { fg: UI.inFlightBright, underline: true },
958+
"markup.link.url": { fg: UI.inFlightBright },
959959
keyword: { fg: UI.inFlightBright },
960960
string: { fg: UI.done },
961961
number: { fg: UI.done },

0 commit comments

Comments
 (0)