Skip to content

Releases: rbinar/cli-dispatch

v4.27.0 — worktree runners mirror every node_modules dir from the repo top

Choose a tag to compare

@rbinar rbinar released this 18 Aug 21:10
a22dd24

Fixed

  • Worktree runners now mirror every node_modules dir of the source checkout, resolved
    from the repo top
    (issue #158). Each *-worktree-run.sh used to create one link,
    $REPO/node_modules → $WT/node_modules, with $REPO being whatever --cwd was. On an npm
    workspaces monorepo with --cwd <repo>/packages/core, git worktree add still checks out the
    whole repo, so the worktree ROOT received the package-local node_modules and the hoisted
    root install (node_modules/.bin/vitest) was never linked — the worker finished fine and
    --verify 'cd packages/core && npx vitest run …' died with sh: vitest: command not found
    (exit 127). The runners now list the source's ignored node_modules/ directories from
    git rev-parse --show-toplevel (git ls-files --others --ignored --exclude-standard --directory, ~17 ms on a six-package monorepo) and symlink each into the worktree at the same
    relative path — root and per-package alike — skipping anything that already exists there.
    Cleanup removes all such links (find "$WT" -name node_modules -type l -delete; the printed
    manual-cleanup hint says the same); git worktree remove --force was verified not to follow
    the links into the source install. Regression test: worktree-node-modules.test.mjs (all
    five runners; --cwd at a package, at the root, and with no node_modules at all).

v4.26.0 — flag trivial delegations at the end of a run

Choose a tag to compare

@rbinar rbinar released this 17 Aug 22:53
83db08d

Added

  • Deterministic runs now surface trivial delegation decisions immediately. verdict.json
    carries a top-level advisory trivial boolean derived from the same shared diffstat rule as
    cli-dispatch-gain: a run is trivial only when insertions plus deletions are greater than zero
    and fewer than 50. Empty and missing diffstats remain non-trivial, and the signal never changes
    the runner's exit code or judges the work itself. When true, both Bash and PowerShell runners
    print one short inline-or-batch suggestion after the terminal summary and before the worktree
    note. The gain report's existing text and counts remain unchanged.

v4.25.0 — stop claimedButMissing from flagging dotted prose

Choose a tag to compare

@rbinar rbinar released this 17 Aug 22:53
83db08d

Fixed

  • Worker-report cross-checks no longer mistake dotted prose for missing files. Claimed-file
    extraction now requires either a slash-containing path or a bare filename with a known source,
    asset, or config extension — which is also what keeps bare domains such as www.java.com out,
    since no TLD is a source extension. Extension matching consumes the complete token, preventing
    long symbol names such as TasksServiceImpl.createTask from being truncated into invented file
    claims like TasksServiceImpl.createTa. Measured against the 68 verdicts on one machine that
    carried a usable worker report, claimedButMissing fired on 47% of runs before the change and
    19% after (71 → 29 tokens); every dropped token was a symbol, module name, or domain, and no
    file-shaped token was lost. Measured-file suffix matching and the conservative "nothing
    contradicted" meaning of an empty result remain unchanged.

v4.24.0 — scope the [CD] statusline badge to this session

Choose a tag to compare

@rbinar rbinar released this 17 Aug 20:07
dfd3776

Changed

  • The [CD] statusline now shows only workers spawned by the current Claude Code session.
    When stdin contains Claude Code's snake_case session_id, the fragment requires a matching
    meta.json parentSessionId in addition to the existing running state and 90-second
    status.json freshness check. It groups live workers in fixed ds, ag, cx, oc, cp
    order (for example, [CD](ds:1,ag:2,cx:1)), accepts both long and short backend spellings,
    and excludes workers from other parent sessions plus legacy workers without parent metadata.
    The group uses the existing yellow counter color; [CD] remains cyan. Stdin is still drained
    fully, and callers without a non-empty session_id retain the global ▶N behavior unchanged.
    The hot path reads only status.json and meta.json, never transcripts.

v4.23.0 — show the spawning Claude Code session on worker rows

Choose a tag to compare

@rbinar rbinar released this 17 Aug 20:07
dfd3776

Added

  • Worker rows now identify the Claude Code session that spawned them. Every backend parser
    records Claude Code's inherited session id in meta.json, preserving the original non-empty
    value across resumes. The dashboard shows the parent project and short session id before the
    worker cwd, while legacy workers without the field retain their previous metadata line.

  • Parent-project resolution stays cheap on the SSE-refreshed worker list. The list route maps
    session ids to dash-encoded ~/.claude/projects directories using cached directory listings
    only; it never reads transcript contents. The existing transcript-based parent index remains
    confined to the worker detail route.

v4.22.0 — ship the verify caveat with its remedy attached

Choose a tag to compare

@rbinar rbinar released this 16 Aug 23:36
f998d71

Changed

  • The injected policy now states the remedy in the same breath as the verify caveat.
    Measured across two sessions that received the policy and never once used the runner
    (5,799 and 2,361 Bash calls, 732 and 220 of them gate-able test/build/lint commands), the
    runner was considered exactly once and rejected like this: "--verify only says the tests
    pass, not that behavior was preserved — so I won't delegate the verification." That inverts
    the rule. The caveat exists because verification stays with the orchestrator, which is a
    reason to re-measure after delegating, not a reason to keep the work inline. Quoted
    half, the caveat became a veto. The policy paragraph now carries the remedy attached, and a
    test pins the pairing so it cannot be dropped silently. The wording change is bounded by the
    existing 160-word ceiling test, which was not modified (148 words with everything enabled).

v4.21.0 — stop counting the injected policy as runner adoption

Choose a tag to compare

@rbinar rbinar released this 16 Aug 23:22
fd4d01d

Fixed

  • /cli-dispatch:drift no longer counts its own policy text as runner adoption.
    countRunnerBashToolUses searched the whole span between two "type":"tool_use" markers
    for cli-dispatch-run / /cli-dispatch:run. That span can run to ~90KB and swallow the
    injected policy paragraph, user messages and tool_result payloads — and since the policy
    quotes the runner's command line verbatim, every ordinary Bash call in a policy-carrying
    session was scored as a runner invocation. The counter now reads only the Bash tool_use's
    own input.command, bounded to its JSONL record line, and applies the same rule to the
    no-marker fallback path.

  • A command that merely names the runner is no longer counted as running it.
    Waiting on it (pgrep -f cli-dispatch-run), reading its source (grep/sed on the
    script), probing it (command -v), and writing a commit message or PR body that quotes the
    documented command line were all scored as delegations. A runner invocation now requires
    the needle in shell command position — the first word of the command or of a ;/&&/||/
    pipe/newline-separated segment, after any leading VAR=value assignments — with heredoc
    bodies excluded. The bare, cd-prefixed, env-prefixed, absolute-path, multi-line and
    /cli-dispatch:run slash forms all still count.

    Measured on a frozen 646-file transcript snapshot, reported invocations fell from 228 to 18
    (about 15 real launches plus three --help probes) while agentSpawns, inlineEdits and
    policyInjectedSessions stayed byte-identical. The drift ratio the report had been printing
    was therefore understating drift by roughly an order of magnitude: 5.5 became 69.8 on the
    same data. Transcript scanning stays a text scan with no per-line JSON.parse; the report
    runs in the same ~2.5s over that snapshot as before.

v4.20.0 — measure delegation drift

Choose a tag to compare

@rbinar rbinar released this 15 Aug 17:52
677d37d

Added

  • /cli-dispatch:drift reports delegation drift between injected policy and actual runner use.
    The new read-only report counts recent deterministic runner sessions, raw worker sessions,
    policy-injected Claude Code transcripts, Anthropic Agent spawns, inline Edit/Write
    tool use, and Bash invocations of cli-dispatch-run or /cli-dispatch:run. It keeps
    transcript scanning cheap by filtering JSONL files by mtime before reading them and by
    counting with text scans rather than JSON parsing, making the "policy arrived but behaviour
    did not change" failure mode visible without dumping transcript contents.

v4.19.0 — stop inventing a missing wrapper, align the injected policy

Choose a tag to compare

@rbinar rbinar released this 15 Aug 17:52

Fixed

  • The SessionStart stale-wrapper notice no longer invents missing commands.
    policy-inject.mjs still compares ~/.config/cli-dispatch/.installed-version against the
    newest cached plugin version, but it now probes PATH for the backend-agnostic wrapper
    binaries before saying anything is missing. If all core wrappers are present, the notice
    says the installed wrappers are stale and recommends /cli-dispatch:setup without naming
    cli-dispatch-run as absent. If any core wrapper is truly absent, the notice lists the
    missing binary names explicitly and says they are missing from PATH. Backend-specific
    wrappers (ds-agent/cx-agent/ag-agent/oc-agent/cp-agent) are deliberately not probed,
    because a user may have installed only one backend.

  • The injected delegation policy now matches the global CLAUDE.md routing rule.
    The first policy sentence no longer narrows runner use to "mechanical work"; it names
    auditability as the binding constraint and allows exploratory work when there is a
    machine-checkable verify command and behavior-changing decisions remain in the
    orchestrator's brief. The /cli-dispatch:run ... --verify guidance, zero-babysitter-token
    emphasis, trivial-inline exception, escalation paragraph, and issue reminder behavior are
    unchanged.

v4.18.0 — keep the runner reachable after a plugin upgrade

Choose a tag to compare

@rbinar rbinar released this 08 Aug 23:10
61ed22f

Fixed

  • A plugin upgrade no longer silently disables the deterministic runner (issue #150).
    Upgrading refreshes the versioned plugin cache dir and nothing else — it never re-runs
    install.sh — so ~/.local/bin keeps whatever the last /cli-dispatch:setup installed.
    Any binary introduced by a newer version is therefore simply absent from PATH. That is how
    cli-dispatch-run, cli-dispatch-wait and cli-dispatch-gain came to be missing on a box
    running plugin 4.16.0 while the file sat right there in the cache, and /cli-dispatch:run
    died with command not found for a reason nothing on screen explained. Three changes:

    • The SessionStart hook now compares ~/.config/cli-dispatch/.installed-version against the
      newest version in the plugin cache and injects a one-paragraph notice when the install is
      behind. It is deliberately not gated on policy.json: a stale install is a broken
      install, not a preference, and someone who never wrote a policy file is the likeliest
      person to hit it. cli-dispatch-status.sh and version-check.sh already detected this,
      but only for people who ran a command that happened to check.
    • /cli-dispatch:run falls back to the plugin's own scripts/cli-dispatch-run when the
      wrapper is missing from PATH, so the documented zero-token flow still runs. Both the
      fallback and the hard-failure path now name the cause (an upgrade does not reinstall
      wrappers) alongside the fix, instead of only suggesting the per-backend commands.
    • /cli-dispatch:setup resolves the plugin root at runtime through the new
      resolve-plugin-root.sh (+ .ps1 twin) rather than invoking
      ${CLAUDE_PLUGIN_ROOT}/scripts/install.sh directly. CLAUDE_PLUGIN_ROOT is whichever
      version the running session loaded, which an upgrade does not change — so the old form
      could run an installer several versions old, and printed a stale version number while
      doing it. The reporter saw 3.30.1 in that step with 4.16.0 active and concluded that
      3.30.1 was what they had. The resolver picks the newest of (session root, newest cache dir
      carrying an installer) and keeps the session root on ties, on unparseable versions, and
      when the session root has no manifest — so a local dev checkout is never swapped out.

    The runner itself was never broken by any of this; it was only made unreachable, which is
    worse, because the fallback is the LLM-babysitter path this plugin exists to avoid.