A be/jab invocation is a VERB plus N params; the dispatcher should split into (verb, params[]), require the verb code, and pass the params as JS values, leaving any URI parse to the verb. Today core/loop.js cli() instead routes every positional through resolve.seed→classifyArg (new URI(arg)) BEFORE the verb sees it — a uniform pre-classification that silently drops a colon-bearing POST commit message (TICKET: log: … re-parses to a {kind:"path"} row scoping the post to a nonexistent target → no-op rc=0; the #msg sigil is the only escape). Fix: retire the central classify; the CLI packs each shell-token as a string (differentiating only the SAFE scalars — number/true/false/null), while the pager : address line (keyboard) runs the JS dogenizer + a shape-gated eval so {}/[]/scalars become real JS values. Scope: be/ (beagle-ext) dispatch + pager; reuses the existing tok/eval bindings, no beagle/js change. See Issues.
core/loop.js cli() splits flags/positionals, picks verb=args[0] via the _isVerb file probe, then resolve.seed(verb,args) runs classifyArg=new URI(arg) per positional → branch-free queue rows; raw args only tag along on ctx.args.jab post 'AAA: bbb ccc' commits, but jab post 'AAA: bbb: ccc' is a silent no-op rc=0 — the second colon-token makes classifyArg return a {kind:"path"} row that scopes the commit to a nonexistent path.: line (views/bro/pager.js _runSpell→driveSpell) is one un-split string we tokenize ourselves, so a space-separated verb arg arg spell never splits there today.eval (verified: typeof eval==="function", eval("2+3")→5, object needs paren-wrap eval("({a:1})")); the dogenizer is a lexer only — it validates tokens, not that a token is data vs code.(verb, params[]) and passes params as JS values to the required verb; the verb parses a URI itself if it wants one (no central classifyArg).: line): dogenizer for token boundaries + leading-token TYPE; eval ONLY shape-whitelisted literals — string/number/true/false/null → value, [/{ → eval("("+t+")") (paren-wrap, depth cap); anything identifier-led (feat, NaN, undefined, a call) → string verbatim, never eval; try/catch→string backstop.JSON.parse, exact true/false/null); NO eval, NO dogenizer, NO objects/arrays (keyboard-only) — so no code-exec surface and no NaN/undefined/Infinity trap.post foo bar) is arity, not grammar — a verb declares its last param GREEDY/rest, else quoting; solved by the verb, not the value parser.be/ submodule (beagle-ext) ONLY: core/loop.js, core/resolve.js, views/bro/pager.js+bro.js; REUSE the tok/eval/uri bindings — do NOT touch beagle/js (per user).+p); never assume the type is already narrowed. Post-change the CLI↔keyboard type divergence is only {}/[] (pager-only).TICKET: log: … message must commit, message intact) before the fix; do not regress the parity suites.io.spawn(...)/x=1/undefined too, so lexing is not a safety gate; the whitelist is.be/test/post/colon-msg/run.sh pins BOTH the single-colon control and the double-colon message committing with the exact message stored. Landed with JAB-004 11e4dddc.classifyArg/seed retired (core/resolve.js 208→27 lines); tokens packed as strings + safe scalars — via JAB-004; the params[] shape superseded by plain JS args.: line feeds shared/argline.js (bare / shell-split / verb(-eval) — via JAB-004 phase 1; per-token shape-gated eval superseded by the explicit verb( call-syntax gate.post msg… multiword arity (plus #msg/-m), owned by verbs/post/post.js — via JAB-004 phase 4.11e4dddc, Fri03 "plain js calling convention for the verbs"): central classifyArg retired, one tokenizer shared/argline.js, POST colon-drop fixed + pinned by test/post/colon-msg.(verb, params[]) shape (JAB-004 uses plain JS args) and per-token shape-gated eval (eval only on the explicit verb( call syntax).be/.