Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions KNOWN_ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,34 @@ Ein Fehlschlag mit anschließendem PASS beweist weder einen harmlosen Flake noch
Ursache, Fix oder Abschluss von KI-24. Weiter auf Windows messen, bevor Fristen
oder Wiederholungen geändert werden; kein Produktfix-Paket aus diesem Nachtrag.

### Offener CI-Befund: selftest-win-signal ohne Timeout-Schlusszeile (22.10.2026)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Move the win-signal incident to its own package

This V16-FU-2/R908-FU-1 change now also records an unrelated selftest-win-signal failure from PR #1835 and creates a separate follow-up assignment, even though the package report scopes the change to CLI drain coverage and claims that only the drain test changed. Keeping this independent CI investigation here bundles two packages and leaves the report, review classification, and evidence describing a different delta; move the incident record to its own package.

AGENTS.md reference: AGENTS.md:L13-L17

Useful? React with 👍 / 👎.


Weiter **offen**, Stufe niedrig, nur Prüfung: [Run 39834041335,
Linux-1-Job 120017507651](https://github.com/Cuarroc/ProjectA/actions/runs/39834041335/job/120017507651)
scheiterte in Queue #1847 für #1835 (`fc1d4662`) auf Basis `fa4f2d9a`,
Queue-Kopf `84f8d345421c338748a7261a68406f62b6d3e5f4`, am Gate
`selftest-win-signal` mit `never-finishing-run-times-out-with-3 (rc=3)`.
Jobfehler und Quellprädikat wurden von der Koordination unabhängig gelesen;
laut Roots Prüfung des Rohprotokolls stimmte der erwartete Exit-Code 3,
aber die exakte stdout-Zeile `conclusion=timeout` fehlte. Diese Rohbeobachtung
stammt von Root; `gh` verweigerte die Ausgabe wegen roher Terminal-Steuerzeichen.
`scripts/test-win-signal.sh` prüft beide Bedingungen und verwendet für diesen
Poll eine Sekunde Zeitlimit ohne Wartepause (`WIN_SIGNAL_SLEEP=0`). Ein
Timing-Wettlauf oder Flake ist eine Hypothese, keine bewiesene Ursache oder
Entwarnung; Timeout, Wiederholungen und Assertion bleiben unverändert.

Der erfolgreiche [main-Lauf 39832698357](https://github.com/Cuarroc/ProjectA/actions/runs/39832698357)
auf `fa4f2d9a` traf in `linux_1` nur die Auswahlentscheidung; die eigentlichen
Gates waren `SKIPPED`. Er belegt keinen erfolgreichen Lauf dieses Selbsttests.
Root reihte über Queue #1848 erneut ein; #1835 wurde am 22.10. um 19:07:35Z
als `5a07fc0895ff6bb813df265fa9d730d38d1b1ed9` gemergt. Der Merge allein
beweist weder einen PASS dieses Selbsttests noch Ursache oder Fix; hier wird
kein solcher PASS behauptet. Run-/Jobstatus, Auswahl und Merge wurden per
`gh run view` und `gh pr view` am 22.10. erneut gelesen (Exit 0).
Folgeauftrag `d2d1a8a8-0882-435e-902b-c3cad4e695fb` bleibt offen, niedrig,
nur Prüfung; kein Fix in TASK/ASSIGN. Dieser Eintrag dokumentiert den CI-Befund;
die bestehenden R908-Testzeitfenster sind damit nicht als neuer Fehler belegt.

## Behoben

Historische Befunde samt vollständigen Belegen stehen im
Expand Down
2 changes: 1 addition & 1 deletion docs/PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ Stand 15.10.: Testmodule der vier Nähte durch SLIM-M1/S1/A1/P1 ausgelagert (SLI
| V16-CHANGELOG-b | [Archiv: Historie][historie] | bestehender Owner | V16-CHANGELOG-a | Server | C | Erledigt #861 (merged 2026-10-09T15:02:01Z) | siehe Archiv | – |
| V16-RELEASE | Tag v1.6.0 (Beta-Regel x.y.0) | Nutzer | Z1 (bis DR-17), V16-KI30 (Fix-Abnahme), D5-GUARD, V16-UPD-CANCEL, V16-06, V16-CHANGELOG; #728 gemergt | PC | – | Erledigt: Tag v1.6.0 = d2582ceb (09.10. 23:22Z), release.yml 38004103979 grün, latest.json anonym 1.6.0, PC installiert; ersetzt: Freigabe: Nutzer 09.10. ~19:42Z an Root; Tag durch Root nach Merge dieses PRs (V16-RELEASE-PREP); ersetzt: Geplant: E2/E3 beantwortet; konkrete Freigabe dieses Releases weiterhin offen | jeder Release braucht Nutzerfreigabe; Environment release mit Required Reviewer Cuarroc am 09.10. per gh api bestätigt; danach Release-Pipeline grün | – |
| V16-FU | Nachläufer aus v1.6.0-Reviews und Release-Prüfung | Stabschef | v1.6.0 veröffentlicht (V16-RELEASE) | Server | B/C je Punkt | Erledigt 10.10.: SRV-2/SRV-5-Portschutz #931, SRV-3 #952, OWN-3 #930, NOT-1 und R912-FU-1 #941, NOT-2/NOT-3 #928, SRV-4 #927, REL-3 #926, REL-4 #929, R910-FU #937, R889-FU #899 (09.10.); Rest verschoben nach V16-FU-2; ursprünglich: Offen: R908-FU-1 (Wiring-Test stop→limitDrainForSignal), R908-FU-2 (Drain-Kommentar/Idempotenz); R912-FU-1 (existed-Flag statt stat, io-Seam); R910-FU, R896-FU, R899-FU K2, R889-FU; REL-3 (scripts/release.cmd veraltet), REL-4 (Rollback/releases-latest), NOT-1/2/3, SRV-2..5, OWN-3 | je Punkt eigenes Paket mit eigener Abnahme | – |
| V16-FU-2 | Rest aus V16-FU: SRV-5 gegenseitige Authentifizierung (laut #931 weiterhin geparkt), R908-FU-1 (Wiring-Test stop→limitDrainForSignal), R908-FU-2 (Drain-Kommentar/Idempotenz), R896-FU, R899-FU K2 | Stabschef | V16-FU | Server | B/C je Punkt | Geplant: nicht disponiert; ob schon anderswo erledigt: Unbekannt (zu prüfen) | je Punkt eigenes Paket mit eigener Abnahme | – |
| V16-FU-2 | Rest aus V16-FU: SRV-5 gegenseitige Authentifizierung (laut #931 weiterhin geparkt), R908-FU-1 (Wiring-Test stop→limitDrainForSignal), R908-FU-2 (Drain-Kommentar/Idempotenz), R896-FU, R899-FU K2 | Stabschef | V16-FU | Server | B/C je Punkt | In Arbeit: Teillieferung R908-FU-1 nach Merge von #1838: Wiring-Test am echten CLI-Einstieg für Linux-SIGTERM/SIGHUP und prozessseitig emittiertes SIGBREAK; kein nativer Windows-Signalnachweis. Neuer Kopf wartet auf erneute Root-Abnahme. SRV-5 gegenseitige Authentifizierung bleibt geparkt; R908-FU-2, R896-FU und R899-FU K2 bleiben offen | je Punkt eigenes Paket mit eigener Abnahme | – |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Describe only the post-merge PLAN state

The fresh replacement text still mixes mutually exclusive states: it describes R908-FU-1 as delivered “after merge of #1838” and then says the new head is awaiting Root acceptance. Once this commit is merged, that acceptance cannot still be pending, so the canonical row immediately becomes stale; retain the delivered scope and outstanding sibling work but remove the pre-merge approval status.

AGENTS.md reference: AGENTS.md:L139-L139

Useful? React with 👍 / 👎.

| V16-NACHBEOB | Zwei Wochenmessungen und 40 Queue-Läufe; Messgrößen-Leitfaden | Stabschef | v1.6.0 | Server | C | Verschoben; KI-30-Schluss (#874: 42 Queue-Läufe ab 09.10., 0 KI-30) liegt vor, sein Fenster weicht vom Originalkriterium (Fenster ab #518, 05.10.) ab — Abgleich: Unbekannt (zu prüfen); zwei Wochenmessungen ohne vollständigen Fensterbeleg | Wochenberichte BENCH-01/02 im Ticket | b8b16ec8 |

KI-30-Quellenkonflikt (Basis `03542ef`, geprüft 09.10.):
Expand Down
51 changes: 32 additions & 19 deletions tools/denkraum/server-entry-drain.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ async function freePort() {
const { port } = probe.address(); await new Promise(r => probe.close(r)); return port;
}
// freePort() can race with another binder; retry EADDRINUSE ("konnte nicht starten") on a fresh port, like server-stop/lifecycle.
async function startEntry(t, file, { webhook = false, args = [] } = {}) {
async function startEntry(t, file, { webhook = false, args = [], ipc = false } = {}) {
for (let attempt = 1; ; attempt++) {
const port = await freePort();
const env = { ...process.env, DECISION_DESK_STATE: file, DECISION_DESK_PORT: String(port), DECISION_DESK_ROOT_AGENT_ID: 'root-test',
DECISION_DESK_ROOT_RECEIPT_TOKEN: strongSecret(), DECISION_DESK_WEBHOOK_SECRET: strongSecret() };
delete env.DECISION_DESK_WEBHOOK_URL;
if (webhook) env.DECISION_DESK_WEBHOOK_URL = 'https://agentsroom.dev/api/triggers/t_abc123';
const child = spawn(process.execPath, [...args, entry], { env, stdio: ['ignore', 'pipe', 'pipe'] });
const child = spawn(process.execPath, [...args, entry], { env, stdio: ['ignore', 'pipe', 'pipe', ...(ipc ? ['ipc'] : [])] });
const out = { stdout: '', stderr: '' }, waiters = [];
const feed = (key, d) => { out[key] += d; for (const w of waiters) w(); };
child.stdout.on('data', d => feed('stdout', d)); child.stderr.on('data', d => feed('stderr', d));
Expand Down Expand Up @@ -95,20 +95,33 @@ test('DRSEC-G4b: SIGTERM lets an in-flight request finish within the budget and
assert.ok(await missing(`${file}.owner`));
});

test('DRSEC-G4b: SIGTERM with a notification send that never answers prints one short line and exits non-zero and keeps the owner record', { skip: posixOnly }, async t => {
const dir = await workdir(t), file = join(dir, 'ledger.json'), store = new DeskStore(file, { rootAgentId: 'root-test' });
await store.putQuestion(question('q1')); await store.migrate((await store.read()).revision);
await store.answer({ questionId: 'q1', questionRevision: 1, expectedAnswerId: null, requestId: 'req1', action: 'answer', selected: ['a'], note: 'x' });
await store.close();
// The webhook transport is the global fetch; this preload makes it announce itself and never settle.
const preload = join(dir, 'hang-fetch.mjs');
await writeFile(preload, "globalThis.fetch = () => { process.stdout.write('SEND-STARTED\\n'); return new Promise(() => {}); };\n");
const run = await startEntry(t, file, { webhook: true, args: ['--import', pathToFileURL(preload).href] });
assert.equal(await run.output(/SEND-STARTED/), true);
run.child.kill('SIGTERM');
const result = await within(run.done, 20000);
assert.equal(result.code, 1, result.stderr);
assert.equal(result.stderr.trim().split('\n').length, 1, result.stderr);
assert.match(result.stderr, /^Entscheidungsseite: Beenden fehlgeschlagen: DRAIN_TIMEOUT$/m);
assert.equal(await missing(`${file}.owner`), false, 'a stuck send keeps the owner record (intended)');
});
for (const signal of ['SIGTERM', 'SIGHUP', 'SIGBREAK']) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update the canonical PLAN row for this coverage

Because this commit completes the R908-FU-1 stop-to-drain wiring tests, docs/PLAN.md:444 would become stale: the V16-FU-2 row still says the package is not dispatched and whether it was completed elsewhere is unknown. Update that row in this change to record the delivered scope and leave only the genuinely outstanding sibling work; repository policy requires the Plan-ID row to describe the post-merge state before review-ok.

AGENTS.md reference: AGENTS.md:L139-L139

Useful? React with 👍 / 👎.

test(`DRSEC-G4b: ${signal} with a notification send that never answers prints one short line and exits non-zero and keeps the owner record`, { skip: posixOnly }, async t => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Obtain the required C+ outside review

On Windows, expanding the former single SIGTERM test into this loop introduces two additional tests, for SIGHUP and SIGBREAK, that are skipped via posixOnly. The report nevertheless classifies the package as Tier C and says gates suffice; repository policy explicitly makes tests that add skips C+, so this candidate needs one outside review before review-ok rather than the recorded gates-only disposition.

AGENTS.md reference: AGENTS.md:L33-L37

Useful? React with 👍 / 👎.

const dir = await workdir(t), file = join(dir, 'ledger.json'), store = new DeskStore(file, { rootAgentId: 'root-test' });
await store.putQuestion(question('q1')); await store.migrate((await store.read()).revision);
await store.answer({ questionId: 'q1', questionRevision: 1, expectedAnswerId: null, requestId: 'req1', action: 'answer', selected: ['a'], note: 'x' });
await store.close();
// The webhook transport is the global fetch; this preload makes it announce itself and never settle.
const preload = join(dir, 'hang-fetch.mjs');
// POSIX cannot deliver SIGBREAK. Bridge only that OS event through Node's public process emitter;
// this exercises the real CLI listener and stop closure, without claiming Windows delivery coverage.
await writeFile(preload, "globalThis.fetch = () => { process.stdout.write('SEND-STARTED\\n'); return new Promise(() => {}); };\n"
+ "process.on('message', signal => { if (signal === 'SIGBREAK') process.emit('SIGBREAK', 'SIGBREAK'); });\n");
const run = await startEntry(t, file, { webhook: true, args: ['--import', pathToFileURL(preload).href], ipc: signal === 'SIGBREAK' });
assert.equal(await run.output(/SEND-STARTED/), true);
const started = performance.now();
if (signal === 'SIGBREAK') run.child.send(signal);
else assert.equal(run.child.kill(signal), true);
const result = await within(run.done, 20000);
const elapsed = performance.now() - started;
t.diagnostic(`${signal} drain: ${elapsed.toFixed(0)} ms`);
assert.equal(result.code, 1, result.stderr);
assert.equal(result.stderr.trim().split('\n').length, 1, result.stderr);
assert.match(result.stderr, /^Entscheidungsseite: Beenden fehlgeschlagen: DRAIN_TIMEOUT$/m);
assert.equal(await missing(`${file}.owner`), false, 'a stuck send keeps the owner record (intended)');
// The specified totals are 6 s for SIGTERM and 4 s for console-close signals. A 500 ms lower
// tolerance and a 1.5 s upper margin distinguish those budgets without increasing either one.
const [min, max] = signal === 'SIGTERM' ? [5500, 7500] : [3500, 5500];
assert.ok(elapsed >= min && elapsed < max, `${signal} drain must take ${min}–${max} ms, got ${elapsed} ms`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Rebind the evidence to the actual candidate

The report embedded in commit 5adc89a3 says all commands ran against candidate 1f4ee7a2 and explicitly binds review-ok to that older SHA, even though 5adc89a3 is now the proposed commit. Thus the timing assertions added here have no gate or acceptance evidence bound to the actual candidate; re-run or explicitly revalidate the required evidence and review disposition against 5adc89a3 before marking it ready.

AGENTS.md reference: AGENTS.md:L119-L125

Useful? React with 👍 / 👎.

});
}
Loading