Spike S1: resume/fork/liveness — GO; flood: pause/resume — GO
Demonstrated on CLI 2.1.173: resuming a live session interleaves both
TUIs into one transcript (no lock, no warning) — liveness detection via
registry pid+procStart is mandatory; --fork-session is safe on live
sessions; --resume must run in the session's original cwd ("No
conversation found" otherwise); registry files are cleaned on graceful
exit AND SIGTERM, may be GC'd later after SIGKILL — never reason on
file presence. ANSI-stripped TUI text loses spaces (cursor-positioned
painting) — confirms @xterm/headless for screen parsing.
Flood: 21 MB through node-pty with 10s pause => 0 bytes leaked, no
loss, 4.7 ms echo after flood.
This commit is contained in:
67
spikes/s3-tui/flood.mjs
Normal file
67
spikes/s3-tui/flood.mjs
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env node
|
||||
// Spike S3 (volet flood) — pause()/resume() node-pty sous 20 Mo de débit, sans claude (zéro quota).
|
||||
// Critères : aucune perte (marqueur final reçu, volume >= attendu), 0 octet pendant pause,
|
||||
// process bash survit à 10 s de pause, écho < 100 ms après le flood.
|
||||
import ptyMod from '@homebridge/node-pty-prebuilt-multiarch';
|
||||
import { execSync } from 'node:child_process';
|
||||
import { writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const CAPTURES = new URL('./captures/', import.meta.url).pathname;
|
||||
mkdirSync(CAPTURES, { recursive: true });
|
||||
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
|
||||
// 20 Mo de base64 (lignes de 76 chars) — la conversion LF→CRLF du TTY est prise en compte
|
||||
execSync('head -c 15728640 /dev/urandom | base64 > /tmp/spike-flood.txt && wc -c < /tmp/spike-flood.txt');
|
||||
const fileBytes = parseInt(execSync('wc -c < /tmp/spike-flood.txt').toString().trim(), 10);
|
||||
const fileLines = parseInt(execSync('wc -l < /tmp/spike-flood.txt').toString().trim(), 10);
|
||||
const expectedMin = fileBytes; // reçu = fileBytes + fileLines (CR ajoutés) ; on vérifie >= fileBytes
|
||||
|
||||
const p = ptyMod.spawn('bash', ['--norc'], { name: 'xterm-256color', cols: 120, rows: 32, cwd: '/tmp', env: process.env });
|
||||
let received = 0;
|
||||
let buf = '';
|
||||
let pausedBytes = 0;
|
||||
let paused = false;
|
||||
p.onData((d) => {
|
||||
received += Buffer.byteLength(d);
|
||||
if (paused) pausedBytes += Buffer.byteLength(d);
|
||||
buf = (buf + d).slice(-4000);
|
||||
});
|
||||
|
||||
const results = {};
|
||||
const t0 = Date.now();
|
||||
await sleep(500);
|
||||
p.write('cat /tmp/spike-flood.txt; echo FLOOD-DONE-MARKER\r');
|
||||
|
||||
// Après ~2 Mo reçus : pause 10 s
|
||||
while (received < 2 * 1024 * 1024 && Date.now() - t0 < 60000) await sleep(50);
|
||||
const beforePause = received;
|
||||
p.pause(); paused = true;
|
||||
await sleep(10000);
|
||||
p.resume(); paused = false;
|
||||
results.pause = { beforePause, bytesDuringPause: pausedBytes, pauseHeld: pausedBytes < 65536 };
|
||||
|
||||
// Attendre la fin du flood
|
||||
const tFlood = Date.now();
|
||||
while (!buf.includes('FLOOD-DONE-MARKER') && Date.now() - tFlood < 120000) await sleep(100);
|
||||
results.flood = {
|
||||
fileBytes, fileLines, received, receivedAtLeastFile: received >= expectedMin,
|
||||
markerReceived: buf.includes('FLOOD-DONE-MARKER'),
|
||||
totalMs: Date.now() - t0,
|
||||
};
|
||||
|
||||
// Écho après flood : write d'un marqueur, mesure du round-trip
|
||||
await sleep(500);
|
||||
const echoT0 = process.hrtime.bigint();
|
||||
p.write('echo ECHO-RT-TEST');
|
||||
let echoMs = null;
|
||||
const tEcho = Date.now();
|
||||
while (Date.now() - tEcho < 5000) {
|
||||
if (buf.includes('ECHO-RT-TEST')) { echoMs = Number(process.hrtime.bigint() - echoT0) / 1e6; break; }
|
||||
await sleep(5);
|
||||
}
|
||||
results.echo = { echoMs, under100ms: echoMs !== null && echoMs < 100 };
|
||||
|
||||
p.kill();
|
||||
writeFileSync(join(CAPTURES, 'flood-results.json'), JSON.stringify(results, null, 1));
|
||||
console.log(JSON.stringify(results, null, 1));
|
||||
Reference in New Issue
Block a user