feat(terminals): durcit le portail d'écriture de délégation

Fiabilise la livraison des délégations inter-agents dans le terminal :
écriture par chunks UTF-8 bornés (512 o, délai 8 ms) pour éviter les
comportements de paste/drop des TUI sur agents froids, et réconciliation
de l'attachement front (frontAttachedAgentRef / reconcileFrontAttachment)
pour ne reporter « front attaché » qu'une fois les DelegationReady
réellement consommés. Tests vitest associés.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-20 08:56:26 +02:00
parent 287681c198
commit e462136df2
3 changed files with 149 additions and 26 deletions

View File

@ -120,6 +120,25 @@ describe("useWritePortal (§20)", () => {
]);
});
it("chunks long delegated text before submit and acks after the submit", async () => {
const { system, input, view } = setup();
const { handle, writes } = makeHandle();
act(() => view.result.current.portal.bindHandle(handle));
const text = `début ${"x".repeat(1200)} fin`;
await act(async () => {
system.emit(PROFILELESS("t1", text));
await vi.runAllTimersAsync();
});
expect(writes.length).toBeGreaterThan(2);
expect(writes[writes.length - 1]).toBe("\r");
expect(writes.slice(0, -1).join("")).toBe(text);
expect(input.delivered).toEqual([
{ projectId: "p1", agentId: "ag1", ticket: "t1" },
]);
});
it("K=2 race → exactly two \\x7f backspaces before the text (never Ctrl-U)", async () => {
const { system, view } = setup();
const { handle, writes } = makeHandle();
@ -255,6 +274,26 @@ describe("useWritePortal (§20)", () => {
expect(input.delivered.length).toBe(1);
});
it("reports front attachment only after the delegation subscription is ready", async () => {
const { input, view } = setup();
const { handle } = makeHandle();
act(() => view.result.current.portal.bindHandle(handle));
expect(input.frontAttached).toEqual([]);
await act(async () => {
await Promise.resolve();
});
expect(input.frontAttached).toEqual([{ agentId: "ag1", attached: true }]);
act(() => view.result.current.portal.unbindHandle());
expect(input.frontAttached).toEqual([
{ agentId: "ag1", attached: true },
{ agentId: "ag1", attached: false },
]);
});
it("is inert for a plain (agent-less) cell", async () => {
const { system, view } = setup(null);
const { handle, writes } = makeHandle();