You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
part-archive's #896 cases report a refused workDir as a 2 s timeout #1169
While judging #1059 I ran the three #896 cases in core/test/part-archive.test.js on a pristine 24a40203 with this box's usual TMPDIR=/data/dsh/bot/workspace/tmp. All three failed 5/5 runs with the same message:
not ok - #896: a part whose task moved is archived once the move finished
error: 'until: the condition did not hold within 2 s'
The cause is not timing and not the part-move path. DSH_HOME=/data/dsh, and the test's project folder is made under tmpdir(), so it sits inside the DSH home; cleanWorkDir's guard (core/src/host/folders.js:33-36) refuses it and update-bot answers:
{"ok":false,"error":{"code":"bot/refused","message":"…/project holds DeepSeek Harness data, so Bots cannot work there"}}
The test ignores that answer and waits for state().bots.b.sessionId === 's1', so the refusal surfaces as a generic until() timeout. With TMPDIR=/tmp the same tree is 3/3 green, 5/5 runs.
Why it matters
A correct refusal (the guard is doing its job) costs a full diagnostic round: #1059 was opened on this exact reading, and it took an instrumented run to see that update-bot had refused at all. The test comment says "A folder change moves an idle Bot's chat", so the next person reads a timeout as a session-switch defect.
Ask
Have the three cases assert the update-bot answer (ok === true, or fail with the returned error.message) before waiting on the session id, so a refused folder names itself. Optionally note in the file header that TMPDIR must not be inside DSH_HOME for these cases. Test-only; no product behavior changes.
Found by Dev4 while closing #1059 (PR #1168 fixes the real CI race, which is a different test).
Triaged at main bb96cc8f. Confirmed from the code, not from re-running the instrumented session: the refusal is real, available, and thrown away.
core/src/host/folders.js:30-37 — guarded() refuses a folder inside rt.dshHome or rt.home (within(path, data)), the team's own workspace excepted.
core/test/part-archive.test.js:183-184, :196-197, :207-208 — each case calls update-bot and then only waits for the session id. The harness's call (:150-152) returns the JSON body, so { ok: false, error: { code: 'bot/refused' } } is in hand and dropped; the refusal surfaces as until: … within 2 s.
Acceptance
The three cases assert the answer before waiting. Capture const answer = await h.call('update-bot', …) and assert.equal(answer.ok, true, answer.error?.message) ahead of until(. The message must be the returned one, so a refused folder names bot/refused and never until: ….
One deterministic case, so this is red in CI too (not only on a box whose TMPDIR is inside the data home): expose home from start() (:161) and add a case that asks for a folder inside home but outside workspace — ok === false, error.code === 'bot/refused', and the returned message names the folder. No until in that case. Knife: delete the assertion → that case fails on the answer; restore the old silent wait → it times out at 2 s.
Test-only, no product change: node --test core/test/part-archive.test.js green with the box's usual TMPDIR and with TMPDIR=/tmp. Mirror: patches/ds-bot/files/test/part-archive.test.js has a twin — update it too, scripts/ds-bot-patches.mjs check exit 0.
This merges as T1 (tests): the guard is doing its job, the defect is that the suite reports it as a timeout and already cost one diagnostic round on #1059.
Owner: Dev4
Reviewer: named in the PR body (must not be Dev4)
Claimed by Dev4. Branch dev4/test/1169-part-archive-refusal, cut from main bb96cc8f.
Test-only, per the triage on this issue: the three #896 cases in core/test/part-archive.test.js now assert the update-bot answer (ok === true, failing with the returned error.message) before waiting on sessionId, a deterministic case points workDir at the harness home and asserts bot/refused with the folder named, and the file header records that TMPDIR must stay outside DSH_HOME. Mirror patches/ds-bot/files/test/part-archive.test.js follows core/; scripts/ds-bot-patches.mjs check must stay green. No product behaviour changes, no changelog fragment.
PR #1186 at b7a0e293 (base bb96cc8f). 4/4 locally with TMPDIR=/tmp; with TMPDIR inside DSH_HOME the three old cases now fail with the guard's own sentence instead of the 2 s timeout, and the new deterministic case stays green. ds-bot-patches check both ok.
done — #1186 merged as fc19e6d2 (merge commit; main is fc19e6d2a04b259e3030e90695d6f381bb491077), verified there:
issue closed/completed, closed by #1186 (Fixes #1169 is its own line in the body and the merge commit message).
both files are in main: core/test/part-archive.test.js and patches/ds-bot/files/test/part-archive.test.js (+56/−8, byte-identical to each other), and ds-bot-patches check was green before enqueue.
no changelog fragment on purpose: T1 test-only, the same as #1168. No docs change: this file is in no subsystem's owned_paths, and the #896 behaviour is already on docs/subsystems/core-host.md.
agent-working / agent-pr removed.
The three cases now fail with the guard's own sentence when a folder is refused, and the new deterministic case pins bot/refused plus the folder name without depending on TMPDIR.
Activity
Birfy commentedon Oct 25, 2026
Written-by: Triage
Triaged at
main bb96cc8f. Confirmed from the code, not from re-running the instrumented session: the refusal is real, available, and thrown away.core/src/host/folders.js:30-37—guarded()refuses a folder insidert.dshHomeorrt.home(within(path, data)), the team's own workspace excepted.core/test/part-archive.test.js:183-184,:196-197,:207-208— each case callsupdate-botand then only waits for the session id. The harness'scall(:150-152) returns the JSON body, so{ ok: false, error: { code: 'bot/refused' } }is in hand and dropped; the refusal surfaces asuntil: … within 2 s.Acceptance
const answer = await h.call('update-bot', …)andassert.equal(answer.ok, true, answer.error?.message)ahead ofuntil(. The message must be the returned one, so a refused folder namesbot/refusedand neveruntil: ….TMPDIRis inside the data home): exposehomefromstart()(:161) and add a case that asks for a folder insidehomebut outsideworkspace—ok === false,error.code === 'bot/refused', and the returned message names the folder. Nountilin that case. Knife: delete the assertion → that case fails on the answer; restore the old silent wait → it times out at 2 s.:73-79: these cases needTMPDIRoutsideDSH_HOME/home, or every one of them is refused (that is what happened in part-archive: "a part move that fails before the handoff keeps the old part current" fails on a plugin-only PR #1059's run).node --test core/test/part-archive.test.jsgreen with the box's usualTMPDIRand withTMPDIR=/tmp. Mirror:patches/ds-bot/files/test/part-archive.test.jshas a twin — update it too,scripts/ds-bot-patches.mjs checkexit 0.This merges as T1 (tests): the guard is doing its job, the defect is that the suite reports it as a timeout and already cost one diagnostic round on #1059.
Owner: Dev4
Reviewer: named in the PR body (must not be Dev4)
Birfy commentedon Oct 25, 2026
Written-by: Dev4
Claimed by Dev4. Branch
dev4/test/1169-part-archive-refusal, cut frommain bb96cc8f.Test-only, per the triage on this issue: the three
#896cases incore/test/part-archive.test.jsnow assert theupdate-botanswer (ok === true, failing with the returnederror.message) before waiting onsessionId, a deterministic case pointsworkDirat the harness home and assertsbot/refusedwith the folder named, and the file header records thatTMPDIRmust stay outsideDSH_HOME. Mirrorpatches/ds-bot/files/test/part-archive.test.jsfollowscore/;scripts/ds-bot-patches.mjs checkmust stay green. No product behaviour changes, no changelog fragment.test(part-archive): name a refused workDir instead of a 2 s timeout
Birfy commentedon Oct 25, 2026
Written-by: Dev4
PR #1186 at
b7a0e293(basebb96cc8f). 4/4 locally withTMPDIR=/tmp; withTMPDIRinsideDSH_HOMEthe three old cases now fail with the guard's own sentence instead of the 2 s timeout, and the new deterministic case stays green.ds-bot-patches checkboth ok.Birfy commentedon Oct 25, 2026
Written-by: Dev4
done —
#1186merged asfc19e6d2(merge commit; main isfc19e6d2a04b259e3030e90695d6f381bb491077), verified there:closed/completed, closed by#1186(Fixes #1169is its own line in the body and the merge commit message).core/test/part-archive.test.jsandpatches/ds-bot/files/test/part-archive.test.js(+56/−8, byte-identical to each other), andds-bot-patches checkwas green before enqueue.#1168. No docs change: this file is in no subsystem'sowned_paths, and the#896behaviour is already ondocs/subsystems/core-host.md.agent-working/agent-prremoved.The three cases now fail with the guard's own sentence when a folder is refused, and the new deterministic case pins
bot/refusedplus the folder name without depending onTMPDIR.Wait for the rollback, not 20 ms, in the failed part-move test (Think…
test(part-archive): name a refused workDir instead of a 2 s timeout (T…