tasks, webui: field table check, line length and bidi escapes (#1596)

Row 102, the row 88 follow-up. Built by a Haiku subagent under
Researcher (decision 129), packet agents/researcher/work/queue-102/,
row102.patch in candidate manifest
8dedcec601ee79a08b4421842af694c0acdae6af3da31b26505c581d3dbc5558.
Filbert approved on #1596, comment 28251. Mos gave the go for the one
public/ line, bus.js's UNSEEN pattern (decision 123, sage-0140).

Sage's gate rerun on 3a1e11b83 with rows 85, 102 and 103 applied,
Docker up: node suites bus 128, business 67, cli 165, control-board
124, conversation 182, discord 178, harness 73, ledger 78, mosaic 69,
queue 155, runs 43, seat 113, tasks 92, webui 108; scripts auth 15,
conductor 17, config 24, discord 66, extension-package 18,
foundation 44, queue 28, release 14, task 98. All pass, 0 fail.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-13 16:34:47 -05:00
co-authored by Claude Opus 5.5
parent 305a012b13
commit 2a9b77b56b
6 changed files with 10 additions and 6 deletions
+1 -1
View File
@@ -10,7 +10,7 @@
const esc = v => String(v ?? '').replace(/[&<>"']/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
// The CHAT-02 rules: C0 controls show as control pictures, C1 and bidi controls as
// [U+XXXX]. Newlines and tabs stay. Markdown stays as its source.
const CONTROL = /[\u0000-\u0008\u000b-\u001f\u007f]/g, UNSEEN = /[\u0080-\u009f؜‎‏‪-‮⁦-⁩]/g;
const CONTROL = /[\u0000-\u0008\u000b-\u001f\u007f]/g, UNSEEN = /[\u0080-\u009f\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/g;
const inert = v => String(v ?? '').replace(CONTROL, c => c === '\u007f' ? '␡' : String.fromCharCode(0x2400 + c.charCodeAt(0))).replace(UNSEEN, c => `[U+${c.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}]`);
const txt = v => esc(inert(v)); // every agent-, tracker- or bus-authored string goes through this
const announce = text => { $('announce').textContent = text; };
+1 -1
View File
@@ -108,7 +108,7 @@ test('S5 pages in a browser: real broker rows, inert text, Copy, routes, failure
assert.equal(await b.evaluate('!!window.injected'), false, where);
assert.equal(await b.evaluate('document.querySelectorAll("#bus-view script, #bus-view img, #bus-view iframe, #bus-view object, #bus-view embed, #bus-view svg, #bus-view style, #bus-view link").length'), 0, where);
const shown = await text('#bus-view');
assert.doesNotMatch(shown, /[\u0000-\u0008\u000b-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/, where);
assert.doesNotMatch(shown, /[\u0000-\u0008\u000b-\u001f\u007f-\u009f\u200e\u200f\u202a-\u202e\u2066-\u2069]/, where);
};
const noOverflow = async where => {
for (const width of [320, 1440]) {
+1 -1
View File
@@ -17,7 +17,7 @@ import { startServer } from '../src/serve.mjs';
import { BusReadError, busReader, humanCall } from '../src/bus.mjs';
import { close } from './fixture.mjs';
const HOSTILE = '<img src=x onerror="window.injected=true"> ‮evil';
const HOSTILE = '<img src=x onerror="window.injected=true"> \u202eevil';
const at = '2026-10-08T12:00:00.000Z';
const businesses = {
demo: {