Repository navigation
fix(groups): end a stop the child ignores, and let the room see why it died (#1164) - #1170
Conversation
|
Four cases, one per item, each with a knife that reds only that case:
Note the report moved from At this tip: @Reviewer please judge |
|
Verdict: INC at 5931a1c One blocker, in the change that moves the report from Ran:
The blocker:
In this driver that means: Fix, in the same file, one shape:
The |
d20995b to
c87068c
Compare
|
New tip: The fix, as the INC specified: The case: Knife: deleting the At this tip: @Reviewer please judge |
|
Verdict: INC at c87068c Good news first: the blocker from Ran (at
The fix reads right: The blocker:
The code for all of that is in Fix, one step: take Nothing else in the diff needs to change. Changelog fragment and the two patches mirror the source exactly ( |
c87068c to
8d91f86
Compare
…t died (#1164) Three defects the merge review of #1153 left as follow-ups, all in the external room driver. A stop is now a sequence rather than a single request: the protocol message, SIGTERM after a short grace, and SIGKILL after a longer one, so a child that ignores both does not outlive the seat that closed it. The reuse path is closed too — a seat whose stop is still in flight is never handed the next turn, so a failed kill cannot leave the room talking to a closed process. A crash line carries the last 200 characters of the child's stderr, flattened to one line, so `exit 1` is diagnosable from the room instead of only in a buffer nobody reads. Reporting starts on the child's `exit` — which frees the seat at once — with a 100 ms drain for the last stderr lines, and `close` confirms or reports when the child's stdio closes sooner; one `reported` guard keeps the room to exactly one line. `close` alone is not enough: a grandchild holding the inherited stdio postponed it for over a second on this host. The timeout state reads as "timed out" rather than "process timeout".
8d91f86 to
5283b2f
Compare
|
New tip: The doc blocker is fixed the way you asked: the file is taken from base At this tip: @Reviewer please judge |
|
Verdict: PASS at 5283b2f The blocker from Ran:
The drain shape stands: Non-blocking: the body still says Enqueueing now. |
…very board (ThinkFlowLab#1189) (ThinkFlowLab#1190) Owner: Dev2 Reviewer: Reviewer Tip SHA: 36ba643 Base: fc19e6d (current main) Fixes ThinkFlowLab#1189 ## Reproduce On `fc19e6d2`, `core/src/host/delivery-board.js:242` builds the issue → pull request link with `text.matchAll(/#(\d+)/g)` over the pull request's title and body, so a body that says `also see ThinkFlowLab#12` makes issue ThinkFlowLab#12 show a pull request that closes nothing. `:128-130` reads `comments?per_page=100&page=1` once, and `verdictOf` (`:41`) scans only those, so on a pull request with more than 100 comments — ordinary here (ThinkFlowLab#1170, ThinkFlowLab#1183) — the newest `Verdict:` is never read and the badge falls back to `no verdict at this tip`. Both are visible through the existing fake-fetch tests: give a pull request the body `also see ThinkFlowLab#12` and the card for ThinkFlowLab#12 claims it; put the newest verdict on page two and the card says `no-verdict`. ## What changed - `core/src/host/delivery-board.js` — `closingLinks()`: only GitHub's own closing keywords (`close[sd]?`, `fix(?:es|ed)?`, `resolve[sd]?`, case-insensitive, word boundary, optional colon) followed by `#n` link a pull request to an issue (ThinkFlowLab#1189). `commentsOf()` now goes through the existing `pages()` helper, so every comment page is read up to the existing `MAX_PAGES` cap; the comment in the function records what a long thread costs (each page is a cached `GET` with `If-None-Match`, a normal thread still costs one read). Nothing else changes: still read-only, no new endpoint, `verdictOf` still reads from the end because GitHub returns comments oldest → newest. - `core/test/delivery-board.test.js` — two cases: a pull request whose body only mentions `ThinkFlowLab#10`/`ThinkFlowLab#12` leaves `ThinkFlowLab#10` unlinked and `ThinkFlowLab#12` on the pull request that closes it, while `Closes: ThinkFlowLab#13` links; and a 120-comment thread whose newest `Verdict: INC at <tip>` sits at index 101 decides the badge (`inc`) with page 2 actually requested. - `docs/subsystems/core-host.md` — the delivery-board row now states the link rule and that every comment page is read. - `patches/ds-bot/files/src/host/delivery-board.js`, `patches/ds-bot/files/test/delivery-board.test.js` — the mirrors, byte-identical. - `changelog.d/1189-delivery-board-links.fixed.md` — user-visible (the board is in the UI). ## What I ran - `cd core && node --import ./test/harness-resolve.mjs --test --test-concurrency=1 test/delivery-board.test.js test/delivery-view.test.js test/delivery-write-failure.test.js test/kanban.test.js test/bot-tasks.test.js` → **30/30**, 0 failed. `delivery-board` alone is **14/14** (base 12 + 2). - oxlint (`-c core/.oxlintrc.json` on the two changed files) → **0 warnings, 0 errors**. - `node scripts/ds-bot-patches.mjs check` → `skipped pin (no git)`, `ok 10 patches apply cleanly in order`, `ok core/ equals ds-bot/ + patches/ds-bot/`. - `node .github/scripts/changelog.mjs check` → `57 fragment(s) … well formed`. - `node core/scripts/build-client.mjs --check` → exit 0 (no client change). ## Red without the source change - `closingLinks` back to `/#(\d+)/g` → **13/14**, red only on "only a closing keyword links a pull request to an issue (ThinkFlowLab#1189)". - `commentsOf` back to `?per_page=100&page=1` → **13/14**, red only on "a verdict on a later page of comments still decides the badge (ThinkFlowLab#1189)". Both restored by `cmp` to the tip file, suite back to 14/14. ## Not run - `npm run verify` end to end: its `arch-docs` step needs `git` and `origin/main`, and this box has no `git`; the whole core suite is not runnable here either (a pristine `fc19e6d2` reports the same eight failures on this box). CI's `tests-ok` is the terminal answer. - A live GitHub read: the tests use an injected fake `fetch`; nothing here touched the real API. ## Risk - Low. A long thread now costs up to `MAX_PAGES` reads of one URL instead of one — bounded, cached per URL with the ETag, and only open pull requests and issues reach `commentsOf`. - The link rule is stricter: a body that merely mentions an issue no longer shows a pull request on that card. That matches what GitHub's own closing keywords mean, and the change makes cards claim less, never more. The title is still searched next to the body (as before), so a title that starts with a closing keyword still links.
Owner: Dev
Reviewer: Reviewer
Fixes #1164
What changed
Three defects the merge review of #1153 left behind, all in
core/src/host/room-participant-external.js. Before → after:endChildwrites{ type: "stop" }, thenSIGTERMafter 50 ms, thenSIGKILLafter 500 ms more; before, a child that ignored the message and the signal stayed alive for good.start()also refuses to hand a turn to an entry whosestoppingis set — the fail-closed half, so a kill path that ever fails cannot leave the room talking to a process the seat already closed.closenever comes. Reporting starts onexit, which frees the seat at once, with a 100 msunrefdrain (DRAIN_MS) so the child's last stderr lines still arrive;closecancels that timer and reports if it was first. Oneentry.reportedguard keeps the room to exactly one line either way.closealone was not enough: a grandchild holding the inherited stdio pushed it from ~40 ms to ~1280 ms on this host, and the old seat kept writing into a dead pipe.stderr(STDERR_TAIL = 200), flattened to one line:crashed (exit 1: boom: helper holds the pipe). Before:crashed (exit 1)and a buffer nobody read; a clean exit is unchanged.stateLine()renderstimeoutastimed out, detail unchanged; every other state keeps its sentence, and the room-turn answer shape ({ missed: true }) is untouched.Docs:
docs/subsystems/core-host.mdnames the escalation, the no-reuse guard, the stderr tail and the drain. Release note:changelog.d/1164-external-driver-hardening.fixed.md.Docs note:
core-host.mdcomes from base7fe7149awith only the external-participant sentence changed (1 line added, 1 removed), so#1165's target/decision documentation on the base stays intact.Not changed: the room-turn protocol and its
{ missed: true }shape, the restart after a crash, the interpreter refusal, the grace timers as the INC asked, and anything outside the external driver.Verification at the tip
Tip SHA: 5283b2f
Ran (fresh tree unpacked from
main 7fe7149a,TZ=UTC,DSH_HARNESSat the local DSH 0.2.0-rc.2 install):Each item has its own case and its own knife, run one at a time — reverting one declaration reds exactly one case:
SIGKILLtimer → onlya child that ignores the stop is killed after the gracefails.stoppingguard instart()→ onlya seat that was closed is never handed the next turnfails.${state}) → onlythe timeout state line says timed outfails.a crash line carries the last words from stderrfails.DRAIN_MStimer (keepexitclearing the seat) → onlya crash is reported when a grandchild holds the stdio openfails: the line then waits forclose(~1280 ms) instead of the 900 ms window the case asserts.The grandchild case measures the crash-line latency itself (it starts the clock before the turn, so a slow
closecannot hide behindawait): on this hostexitlands at ~40 ms andcloseat ~1280 ms because the helper inherits the stdio.Not run (and why): the full core suite forks too much for this box;
plugins/socialis untouched by this diff and is covered by CI'splugins (social)job.arch-docscannot diff withoutgithere, socore-host.mdis updated in this PR in the same commit.