Files
ruflo/scripts/regen-statusline-artifact.mjs
ruvnet 9810d8d9c1 fix(statusline): real model name from stdin + worktree version resolution
Fixes #2733, #2742.

#2733 — hooks.ts's getUserInfo() hardcoded
`const modelName = 'Opus 4.6 (1M context)'`, ignoring the actual active
model Claude Code passes on stdin entirely. Cosmetically masked in the
default render path (the generated .claude/helpers/statusline.cjs
already parses stdin correctly and overrides this), but real for
direct/manual `hooks statusline` CLI use or any stdin-parse failure in
the wrapper. Fixed by mirroring statusline.cjs's own getModelFromStdin()
approach inside hooks.ts, so the CLI subcommand is correct standalone.

#2742 — getPkgVersion() in the generated statusline.cjs only probed
CWD-relative paths (CWD/node_modules/..., CWD/v3/@claude-flow/cli/...).
A linked git worktree has no node_modules of its own (worktrees don't
get their own `npm install`), so every probe missed and the version
silently fell back to the baked-in default from whenever the helper was
last generated. Fixed with a pure-fs worktree-root resolver: a linked
worktree's `.git` is a plain FILE containing `gitdir: <main>/.git/
worktrees/<name>`; walk up from CWD, parse the pointer, strip the
trailing segment to recover the main repo root, and probe its
node_modules/v3 paths too. No `git rev-parse` spawn (statusline renders
are latency-sensitive). Caught and fixed a real bug in this same
resolver during testing: git writes the gitdir pointer with forward
slashes even on native Windows, so a path.sep-based (backslash) marker
search silently never matched — normalize to forward slashes before
searching.

`v3/@claude-flow/cli/.claude/helpers/statusline.cjs` is the source of
truth per the #2679 redesign (generateStatuslineScript() reads it and
substitutes two tokens); regenerated the propagated root-level copy via
scripts/regen-statusline-artifact.mjs, which also needed a small
cross-platform fix (dynamic import() of a raw Windows path isn't a
valid ESM specifier — wrap with pathToFileURL()).

Also corrected a stale/misleading comment in message-transport.ts
claiming a fresh install "shows the in-code fallback pool until the
first refresh lands" — there has never been an in-code fallback pool
since ADR-311 ("zero local promo content"); a fresh install's promo
row is genuinely empty until the first background refresh lands.
Found while investigating a "promo doesn't show on new installs"
report; the underlying fail-closed design and SessionStart-triggered
refresh mechanism were confirmed working as intended (this machine's
own ~/.ruflo state shows a healthy, recently-rotated promo history) —
only the comment was wrong, not the behavior.

Left alone (separate, unreferenced, ~500-line legacy implementation
predating the #2195 delegation rewrite, no source references in its
own package): v3/@claude-flow/mcp/.claude/helpers/statusline.cjs.

Verified: 21/21 new + existing statusline tests pass, 122/122 funnel
tests pass, 10/10 hooks tests pass, clean tsc --noEmit. Manually
confirmed #2733 (real stdin model name renders; malformed/empty stdin
falls back to "Claude Code", never the old hardcoded string) and #2742
(a real `git worktree add` scenario resolves the main repo's version
instead of falling back) end-to-end.
2026-07-20 15:58:21 -04:00

34 lines
1.5 KiB
JavaScript

#!/usr/bin/env node
/**
* Regenerate .claude/helpers/statusline.cjs from the compiled generator.
* Run after any edit to v3/@claude-flow/cli/src/init/statusline-generator.ts
* so the committed root artifact matches the source of truth. The drift-guard
* test in v3/@claude-flow/cli/__tests__/statusline-cost-display.test.ts pins
* that these stay in lockstep.
*/
import { readFileSync, writeFileSync } from 'node:fs';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { dirname, resolve } from 'node:path';
const here = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(here, '..');
const generatorPath = resolve(repoRoot, 'v3/@claude-flow/cli/dist/src/init/statusline-generator.js');
// A raw absolute path (e.g. Windows `C:\...`) isn't a valid ESM specifier —
// dynamic import() requires a real URL scheme. pathToFileURL() is the
// documented cross-platform fix (works unchanged on POSIX too).
const { generateStatuslineScript } = await import(pathToFileURL(generatorPath).href);
const script = generateStatuslineScript({
statusline: { enabled: true, style: 'compact' },
runtime: { maxAgents: 15 },
});
const rootTarget = resolve(repoRoot, '.claude/helpers/statusline.cjs');
const pkgTarget = resolve(repoRoot, 'v3/@claude-flow/cli/.claude/helpers/statusline.cjs');
writeFileSync(rootTarget, script, 'utf-8');
writeFileSync(pkgTarget, script, 'utf-8');
console.log(`regenerated ${script.length} bytes`);
console.log(` → ${rootTarget}`);
console.log(` → ${pkgTarget}`);