Files
stack/agents/researcher/work/queue-102/row102.patch
T
jason.woltjeandClaude Sonnet 5.5 486c4aad34 research: row 102 build packet, row 88 follow-up N1-N4 (#1596)
Header sentence, line 13 wrap, bidi escapes in three files, inertCheck U+200E/U+200F. Patch and evidence only; the change is not applied to the tree.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 16:12:24 -05:00

83 lines
5.6 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
diff --git a/packages/conversation/tests/flows.test.mjs b/packages/conversation/tests/flows.test.mjs
index acd84aa35..e1bbce8fa 100644
--- a/packages/conversation/tests/flows.test.mjs
+++ b/packages/conversation/tests/flows.test.mjs
@@ -492,7 +492,7 @@ test("terminal: engine control characters are made visible; a lost connection re
const h = await started();
try {
const term = new Terminal({ client: h.client });
- h.engine.script([{ text: "\x1b]52;c;ZXZpbA==\x07 bell‮", stop: "stop" }]);
+ h.engine.script([{ text: "\x1b]52;c;ZXZpbA==\x07 bell\u202e", stop: "stop" }]);
await term.key("go\r");
await receiptState(h.client, term.lastReceipt.id, "finished");
await until(() => term.transcript.lines().some((l) => l.includes("bell")), 2000, "the reply");
diff --git a/packages/tasks/src/fields.mjs b/packages/tasks/src/fields.mjs
index 1c1d61fbc..e790430f0 100644
--- a/packages/tasks/src/fields.mjs
+++ b/packages/tasks/src/fields.mjs
@@ -2,7 +2,10 @@ import { readFileSync } from 'node:fs';
import { TASK_VERBS } from '../../bus/src/broker.mjs';
// Row 61 (#1550): the slice 1 field table as data, in ../fields.json. The Field table in
// docs/plans/2026-10-04_slice-1.md is the reviewed prose it must match, and tests/fields.test.mjs
-// checks that prose and this table against what the verbs do. Two layers, as lead decision 113 rules:
+// checks that prose and this table against what the verbs do. For the prose, it reads the rows of
+// the Field table and requires that every field name in a row is a label here and that the
+// task verbs a row names are exactly the verbs this table lists for that field.
+// Two layers, as lead decision 113 rules:
// - `verbs`: the writer verbs.mjs checks before anything else. `pm` is the pm definition
// (field-writer otherwise), `assigned` a role whose bot is an assignee (not-assigned
// otherwise), `any` no writer check.
diff --git a/packages/tasks/tests/fields.test.mjs b/packages/tasks/tests/fields.test.mjs
index ef81f3385..1c2e396d4 100644
--- a/packages/tasks/tests/fields.test.mjs
+++ b/packages/tasks/tests/fields.test.mjs
@@ -10,7 +10,8 @@ import { loadFields, checkFields, FieldTableError, FIELDS_FILE } from '../src/fi
import { TASK_VERBS } from '../../bus/src/broker.mjs';
import { loadRole } from '../../business/src/index.mjs';
// Row 61 (#1550): fields.json, and the Field table in docs/plans/2026-10-04_slice-1.md, against what
-// the verbs in src/verbs.mjs do, with the role files as given. The writer layer is read from the table; whether a write needs a decision, and who
+// the verbs in src/verbs.mjs do, with the role files as given. The writer layer is read from the
+// table; whether a write needs a decision, and who
// resolves it, from roles/*.json as the business loader reads them (lead decision 113). A version 1
// file, the researcher's, grants nothing. Neither expectation is written out here, so a change to
// the table, the prose, a role file or the verbs that leaves them disagreeing fails this file.
diff --git a/packages/webui/src/public/bus.js b/packages/webui/src/public/bus.js
index 108df3b98..0cc841bbc 100644
--- a/packages/webui/src/public/bus.js
+++ b/packages/webui/src/public/bus.js
@@ -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; };
diff --git a/packages/webui/tests/bus-browser.test.mjs b/packages/webui/tests/bus-browser.test.mjs
index 106a8dd26..bf09119f1 100644
--- a/packages/webui/tests/bus-browser.test.mjs
+++ b/packages/webui/tests/bus-browser.test.mjs
@@ -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]) {
diff --git a/packages/webui/tests/bus.test.mjs b/packages/webui/tests/bus.test.mjs
index 6fb74ccec..d1bb55e42 100644
--- a/packages/webui/tests/bus.test.mjs
+++ b/packages/webui/tests/bus.test.mjs
@@ -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: {