Some checks failed
CI / Build & test (Node 24) (push) Has been cancelled
CI / Pack & boot smoke (Node 22) (push) Has been cancelled
CI / No em/en dashes (push) Has been cancelled
CI / Build & test (Node 22) (push) Has been cancelled
Deploy site (production) / build-and-deploy (push) Successful in 20s
Remplace les 547 tirets cadratins (U+2014) et demi-cadratins (U+2013) des fichiers versionnés par la ponctuation contextuelle adaptée (point médian, deux-points, virgule, parenthèses ; tiret simple pour les plages), sur 122 fichiers (appli, vitrine, doc, tests, workflows, scripts). Ajoute le job CI « lint-dashes » (git grep -P) qui échoue si un tiret cadratin/demi-cadratin réapparaît, hors logo binaire et captures brutes du terminal (fidélité des fixtures de détection de dialogue).
68 lines
2.8 KiB
JavaScript
68 lines
2.8 KiB
JavaScript
#!/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));
|