Skip to content

Commit ada82bd

Browse files
committed
fix cli shorthand trailing backslash param parsing
1 parent 220380b commit ada82bd

3 files changed

Lines changed: 32 additions & 0 deletions

File tree

ANALYSIS.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,10 @@
182182
- Updated shorthand argv reconstruction in `index.ts` to include `--params` only when parsed params are present.
183183
- Added regression coverage in `test/parsing.test.ts` (`shorthand parser with empty parens omits params flag`).
184184
- Practical impact: no-arg shorthand exec now serializes cleanly as `params: []` in live CLI↔cerebro-link websocket calls.
185+
186+
## 2026-02-21 slot-11 follow-up (13:3x PT)
187+
- Rationale: shorthand parameter parsing dropped a terminal escape marker when params ended with a backslash (for example `Gon.ask(hello\\)`), which can corrupt path-like inputs and silently alter user intent.
188+
- Change scope:
189+
- Updated `parseParamsString(...)` in `index.ts` to retain a trailing literal backslash when an escape sequence is unfinished at end-of-input.
190+
- Added regression coverage in `test/parsing.test.ts` (`shorthand parser preserves trailing backslash in params`).
191+
- Practical impact: shorthand `cerebro.exec` calls now preserve terminal backslashes in parameter payloads instead of truncating them.

index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,11 @@ export function createCli<R extends AnyRouter>({
393393
}
394394
}
395395

396+
if (escape) {
397+
currentParam += '\\';
398+
sawParamToken = true;
399+
}
400+
396401
if (sawParamToken || currentParam.trim().length > 0 || paramsString.trimEnd().endsWith(',')) {
397402
pushCurrentParam();
398403
}

test/parsing.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,26 @@ test("shorthand parser accepts hyphenated agent and method names", async () => {
637637
);
638638
});
639639

640+
test("shorthand parser preserves trailing backslash in params", async () => {
641+
const router = t.router({
642+
"cerebro.exec": t.procedure
643+
.input(
644+
z.object({
645+
agent: z.string(),
646+
method: z.string(),
647+
params: z.array(z.string()),
648+
})
649+
)
650+
.query(({ input }) => JSON.stringify(input)),
651+
});
652+
653+
const result = await run(router, ["cerebro.exec", "Gon.ask(hello\\\\)"]);
654+
655+
expect(result).toMatchInlineSnapshot(
656+
`"{\"agent\":\"Gon\",\"method\":\"ask\",\"params\":[\"hello\\\\\"]}"`
657+
);
658+
});
659+
640660
test("boolean array input", async () => {
641661
const router = t.router({
642662
test: t.procedure

0 commit comments

Comments
 (0)