mirror of
https://github.com/qwibitai/nanoclaw.git
synced 2026-07-09 18:57:08 +08:00
fix(setup): SSF-002 follow-up — step children: silence logger info, force clack colors
QA on the VM showed two leaks in the effect:step tee: the host logger's INFO lines (it always emits ANSI and defaults to info) landed on the wizard screen, and the child's clack card drew colorless because picocolors disables ANSI on a piped stdout, clashing with the wizard theme. hostExecStream now spawns steps with LOG_LEVEL=warn (operator-set level wins; warnings/errors still pass) and FORCE_COLOR=1 when the operator's terminal is a real TTY. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HB8rQxJN7itcFhNYVDntpm
This commit is contained in:
@@ -148,6 +148,20 @@ describe('thin skill driver', () => {
|
||||
expect(out.fields.PLATFORM_ID).toBe('telegram:42');
|
||||
});
|
||||
|
||||
it('hostExecStream children run with LOG_LEVEL=warn — host logger info noise stays off the wizard', async () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'driver-loglevel-'));
|
||||
const prev = process.env.LOG_LEVEL;
|
||||
delete process.env.LOG_LEVEL; // simulate an operator who didn't set one
|
||||
try {
|
||||
const out = await hostExecStream(root)(
|
||||
'echo "=== NANOCLAW SETUP: ENV ==="; echo "STATUS: success"; echo "LVL: $LOG_LEVEL"; echo "=== END ==="',
|
||||
);
|
||||
expect(out.fields.LVL).toBe('warn');
|
||||
} finally {
|
||||
if (prev !== undefined) process.env.LOG_LEVEL = prev;
|
||||
}
|
||||
});
|
||||
|
||||
function reuseScratch(): { root: string; skill: string } {
|
||||
const root = mkdtempSync(join(tmpdir(), 'reuse-'));
|
||||
const skill = mkdtempSync(join(tmpdir(), 'reuse-skill-'));
|
||||
|
||||
@@ -282,7 +282,20 @@ export function hostExecStream(projectRoot: string): (cmd: string) => Promise<St
|
||||
new Promise((resolve) => {
|
||||
const child = spawn('bash', ['-c', cmd], {
|
||||
cwd: projectRoot,
|
||||
env: { ...process.env, PATH: `${join(projectRoot, 'bin')}:${process.env.PATH ?? ''}` },
|
||||
env: {
|
||||
...process.env,
|
||||
PATH: `${join(projectRoot, 'bin')}:${process.env.PATH ?? ''}`,
|
||||
// A step renders curated operator UI (a code card, a QR) — the host
|
||||
// logger's info noise doesn't belong on the wizard screen, and it
|
||||
// always emits ANSI so it can't be filtered by stream. Warnings and
|
||||
// errors still pass. An operator-set LOG_LEVEL wins (debugging).
|
||||
LOG_LEVEL: process.env.LOG_LEVEL ?? 'warn',
|
||||
// The child's stdout is a pipe, so picocolors would strip its clack
|
||||
// rendering to bare box chars that clash with the wizard theme.
|
||||
// When the OPERATOR's terminal is a real TTY, the teed lines land
|
||||
// there — force color so the child's card matches the parent.
|
||||
...(process.stdout.isTTY ? { FORCE_COLOR: '1' } : {}),
|
||||
},
|
||||
stdio: ['inherit', 'pipe', 'pipe'],
|
||||
});
|
||||
const blocks: Array<{ fields: Record<string, string> }> = [];
|
||||
|
||||
Reference in New Issue
Block a user