Commit Graph
100 Commits
Author SHA1 Message Date
Chinesezjc bbdac8febe docs(time): state the module contract and the zone mapper as they are
- the constants name one bound each
- resolveLocalInstant reuses an instance a caller already holds instead of
  copying it per candidate date
- the README entry-point paragraph drops its duplicate sentence
- the note replaces an invalid reason for the zone mapper and a
  review-vantage sentence with the facts
2026-09-25 01:01:26 +08:00
Chinesezjc 7edd3efe85 refactor(time): give the four-digit bound one owner
- isFourDigitYearInstant is the shared predicate; Schedule's five
  representability guards delegate to it instead of re-deriving the range
- the reason for a field outside its calendar range is out_of_range in
  both strict parsers, so year 0 no longer reads as a wall-clock problem
- LocalCalendarTime.year states which entries reject year 0 and which
  accept it at the UTC edges
- the note counts the five removed expressions and records that the zone
  mapper is a silent catch-all; the Chinese side mirrors the English
  paragraph order
2026-09-25 00:53:09 +08:00
Chinesezjc 92ee4e98f0 docs(time): state each entry's return precisely
- the README no longer claims resolveLocalInstant answers a string
- the accepted-input table records the widened plain date-time input
- canonicalClientTimeZone is named as the wire-boundary form rather than
  left outside a blanket claim about discriminated results
- the non-canonical scheduledAt diagnostic has one source
2026-09-25 00:41:31 +08:00
Chinesezjc 51a7572852 refactor(time): answer the shared resolver from one place
- resolveLocalInstant accepts an already-built plain date-time, so the
  recurrence walkers drop their private copy of the disambiguation and
  round-trip decision
- decodeInstant narrows its field explicitly and drops the assertion
- the model-input exhaustiveness fallbacks throw a plain Error, matching
  the timing-change fallback, while durable decoding keeps
  ScheduleLogError
- the library module and README state which entries answer a
  discriminated result
2026-09-25 00:31:56 +08:00
Chinesezjc 2d28a1dee7 docs: narrow the zone ignore and correct the time-vocabulary note
- the guarded ignore covers only the uncovered branch point
- the note says two consumers copied the profile, counts copies rather
  than consumers, and scopes the platform cause to the unsupported
  rejection
- the note names the remaining instant-profile copy in session-format
2026-09-24 22:19:01 +08:00
Chinesezjc 9f6696c2d5 Merge remote-tracking branch 'origin/master' into refactor/unify-time-vocabulary
# Conflicts:
#	packages/util/time/package.json
2026-09-24 21:56:53 +08:00
Chinesezjc 22f8be30a1 refactor(time-context): consume the shared zone vocabulary
time-context kept a third copy of the IANA profile: its own regular
expression and its own Intl canonicalization in request-zone.ts. It now
reads a request's reported zone through canonicalizeTimeZone and keeps
its stricter policy — an alias whose canonical answer differs from the
reported value is still refused, with the same three diagnostics.

The shared rejection now carries the platform error it caught, so the
unsupported refusal keeps its cause in both time-context and Schedule.
2026-09-24 21:54:34 +08:00
Chinesezjc 0ca5865a5c Merge pull request #5153 from deepseek-harness/fix/preset-legacy-tool-expectation
test: expect the Host Schedule tools in the legacy preset patch case
2026-09-24 18:19:09 +08:00
Chinesezjc 1fa5ea3faa test: expect the Host Schedule tools in the legacy preset patch case
The shipped Web bundle gives every live root Agent the Host Schedule
tools, and every other scenario in this file that boots the shipped
base/web bundle with the minimal preset expects ['bash',
...SCHEDULE_TOOLS]. This case uses the same bootWeb composition and adds
only a settings patch, which does not change tool composition, so its
['bash'] expectation failed on every PR.
2026-09-24 18:00:23 +08:00
Chinesezjc 4611e32e64 Merge pull request #5123 from deepseek-harness/feat/automation-phase1
feat(schedule): ship Schedule in the default Web composition
2026-09-24 17:10:53 +08:00
Chinesezjc f31e51124b test(cli): pin the shipped Schedule rows by name, not loader id 2026-09-24 16:49:34 +08:00
Chinesezjc 015c187e67 test(cli): read the inspect answer through the spill policy
The shipped Web composition now puts four Schedule tools on every live root
Agent, which pushes a full-preset `cordis_inspect_query` answer past the
12,500-token inline budget, so the spill policy retains its head and tail with
a spill path instead of the complete JSON.
2026-09-24 16:41:20 +08:00
Chinesezjc 5c768e3c8a fix(schedule): point shared session references at the selected generation
Refreshed owners publish a v4 generation, so every scenario that names
another owner's Session fixture must name that owner's highest generation.
The shipped Web composition also puts the Host Schedule tools on every live
root Agent, so the minimal-preset tool-table assertions include them.
2026-09-24 16:37:05 +08:00
Chinesezjc fe6ce46248 docs(context): keep the group summary within its word budget 2026-09-24 16:28:51 +08:00
Chinesezjc e896737840 feat(schedule): ship Schedule in the default Web composition
The Web bundle now mounts `time-context` and `schedule` and leaves the
`ui-schedule` client row enabled, so the Automation tasks page, the Session
reminder catalog, and the `schedule_*` tools work without an overlay. Both
packages join the bundle's declared dependencies, and the example overlay is
deleted: re-inserting its rows would mount both Host plugins twice.

The fixed-rate floor drops from 300 to 60 seconds across the Host decoder,
the create and update validation, the model-visible tool schema, and the
client's per-unit floors.

Web recorded sessions and header sidecars are refreshed for the readings
`time-context` now appends; `normalizeWebSessionVolatiles` tokenizes their
sampled instant, browser zone, and elapsed duration so replay stays stable.
2026-09-24 16:11:52 +08:00
Chinesezjc d40567afaf Merge remote-tracking branch 'origin/master' into refactor/unify-time-vocabulary 2026-09-24 13:53:58 +08:00
Chinesezjc b42cae0c8b fix(schedule): mark the unreachable zone-rejection branch
The shared parser never answers not_canonical_shape, so a switch over the
union left that case uncovered and failed the per-file coverage gate.
2026-09-24 13:25:05 +08:00
Chinesezjc 0a89067fde docs: regenerate the module graph for the schedule to util-time edge 2026-09-24 13:15:06 +08:00
Chinesezjc 6c9c7cb69e docs(time): state the throwing preconditions and exact contracts
- Instant entries that take already-validated values throw on violated
  preconditions; the module header said every entry answers a result.
- formatFourDigitYearInstant also refuses a non-integral epoch.
- Schedule's reason mappers switch over the closed unions with a never
  default, so a new library reason fails the build instead of falling
  through to a catch-all.
- The Agent Note claimed the schedule suites pin these diagnostics; they
  assert codes only, and the note now records the added message assertion.
2026-09-24 13:08:06 +08:00
Chinesezjc 882a18c57b docs: drop a nonexistent path reference from the time-vocabulary note 2026-09-24 13:02:11 +08:00
Chinesezjc 7ee7dfde55 fix(schedule): preserve both local-calendar diagnostics
A calendar date the month does not have keeps the at diagnostic; only an
out-of-range clock field keeps the local at one. The extraction had
collapsed both onto the local at wording.
2026-09-24 13:00:40 +08:00
Chinesezjc c96d48d491 refactor(schedule): extract time vocabulary into dsh-util-time
Move Schedule's strict RFC 3339 instant, local-calendar, and IANA zone
parsing into @deepseek-ai/dsh-util-time, and have Schedule consume it.

The shared entries answer discriminated results and own no failure
vocabulary; Schedule keeps its error codes, diagnostics, durable record
shapes, and all recurrence arithmetic.
2026-09-24 12:55:36 +08:00
Chinesezjc 7a362b263b Merge pull request #4335 from deepseek-harness/feat/schedule-storage-phase1
feat(schedule): persist tasks and resume due sessions
2026-09-23 23:33:33 +08:00
Chinesezjc 0810a4403a Merge pull request #4285 from deepseek-harness/fix/composer-draft-scroll-jump
fix(web): insert pasted composer text as line-break nodes
2026-09-15 20:03:25 +08:00
Chinesezjc 96da25c8f5 fix(web): insert pasted composer text as line-break nodes
The composer's paste path used RangeSelection.insertText, which keeps every
pasted newline inside one text node. In that document the browser reports the
collapsed caret's geometry as the whole block's, so deleting the draft's last
line moved the capped scrollport to the draft's head while the caret stayed at
its end.

RangeSelection.insertRawText splits the input into text and line-break nodes,
the document a typed draft already has.
2026-09-15 19:29:53 +08:00
Chinesezjc 64a8ba929d Merge pull request #4195 from deepseek-harness/fix/compaction-banner-offset
fix(web): hold a compaction summary's code banner below the pinned header
2026-09-15 00:13:26 +08:00
Chinesezjc b416ac99e4 fix(web): hold a compaction summary's code banner below the pinned header
A summary's fenced code block pins its banner at the scrollport top, where the
pinned compaction header already sits, so the header covers the banner's Copy
control and a click there collapses the summary. Stop the banner below the
header's band and square the pinned header's corners so its opaque fill masks
the scrolling prose at the edges.
2026-09-15 00:03:33 +08:00
Chinesezjc c75e3d4e81 Merge pull request #1170 from deepseek-harness/sticky-collapsible-headers
feat(web): pin Think and compaction headers sticky while scrolling
2026-09-14 23:34:53 +08:00
Chinesezjc 67271a921b feat(web): pin Think and compaction headers sticky while scrolling
Both blocks render their expanded body uncapped, so a long reasoning chain or
compaction summary carried the disclosure header off the viewport and buried
the toggle. Pin each header to the conversation scroll container while the
block is open, keeping the rule scoped to these two blocks so the capped tool
rows do not stack headers at the top of the viewport.

The compaction header also overrides its stacking rank above the summary's
code-block banner and keeps an opaque hover fill.
2026-09-14 19:52:04 +08:00
Chinesezjc 62dd508cb0 test(permission): pin the disposed guard on the invalidation tick
The late-listener case now carries a pending generation change, so its
assertions depend on the disposed guard, and the silent-generation cases assert
their tick counts.
2026-09-11 17:45:23 +08:00
Chinesezjc eb6373d711 fix(permission): tick only on a real generation change
A notification repeating the published generation no longer withdraws displayed
options, so the invalidation observable and the README describe the same rule.
The composer seat hides on a cleared catalog while the slash picker keeps its
failure and retry, and the disposed guard that both callers already provide is
gone from the tick.
2026-09-11 17:20:22 +08:00
Chinesezjc 38391bf6ba Merge remote-tracking branch 'origin/master' into auto-review-per-call 2026-09-11 17:03:09 +08:00
Chinesezjc 14bdce3644 docs(permission): describe dismissal as a catalog invalidation
The package README, its Chinese pair, and the catalog spec now state both
public observables and pin the generation-change tick that withdraws displayed
options.
2026-09-11 17:00:54 +08:00
Chinesezjc 4a935ed8fd fix(permission): drop the picker only on a catalog invalidation
Publishing the result of a read the picker waits for no longer closes that
picker, so a failed read keeps its error and retry state; a catalog
notification or generation change still withdraws stale options. Correct the
action-history rationale in the Auto review note and cover both paths with the
real popup controller.
2026-09-11 16:29:31 +08:00
Chinesezjc e995d71a0e fix(permission): keep the picker retryable after a failed catalog read
Availability now follows the Session projection alone, so a failed catalog
read surfaces through the picker's own retry instead of hiding the command.
Type-guard the persisted denial reason before trimming it, and record in the
Auto review note why the reviewer reads the complete action history.
2026-09-11 15:46:19 +08:00
Chinesezjc 1de37ddc2b test(web): follow the settled-loader startup audit
Loader settlement no longer rejects on a failed optional entry, so the Auto
rollback scenario reads the conflict from the startup audit. Refresh the Auto
denial golden for the merged composer chrome.
2026-09-11 15:41:46 +08:00
Chinesezjc 6b19923ad5 fix(auto-review): clear the master integration gates
Register the permission catalog default response so the web roster boot
matches every Remote call it makes, and carry the deprecation rule for the
session history read this reviewer needs with the deferred migration
recorded in the package README.
2026-09-11 15:08:48 +08:00
Chinesezjc 3afad043c6 Merge remote-tracking branch 'origin/auto-review-per-call' into auto-review-per-call 2026-09-11 14:29:11 +08:00
Chinesezjc 358d0bc49c Merge remote-tracking branch 'origin/master' into auto-review-per-call 2026-09-11 14:27:30 +08:00
Chinesezjc d8c54899b7 fix(experimental): align the Auto review package version with the release 2026-09-11 14:27:27 +08:00
Chinesezjc a605cf579d Merge branch 'master' into auto-review-per-call 2026-09-11 14:19:16 +08:00
Chinesezjc fed65b7cad Merge master into the Auto review branch
Resolve 36 conflicts across source, bilingual READMEs, and generated
documentation: keep master's command-identity and popup APIs, RemoteMock
test infrastructure, and regenerated catalogs; keep the Auto review
catalog, slot, dismissal, and snapshot content.
2026-09-11 14:15:32 +08:00
Chinesezjc 1050091d82 Merge pull request #3926 from deepseek-harness/ci/blacksmith-hosted-image-fixes
test/ci: remove the host-paced assumptions the hosted coverage lanes hit
2026-09-10 18:01:54 +08:00
Chinesezjc 0377049465 ci: give the Linux coverage lane the hosted image's teardown budget
The managed-scope disposal cases in subprocess-local and bash-sandbox run past
the 5000ms default when this lane's four partitions, six workers per gate, and
sibling gates share one host. The same commit stays inside the budget on the
in-house pool: the hosted image exceeded it (run 34449848541) and the lane is
green with 90000 (run 34457655892). The Windows coverage lane already grants
the same budget for the same class of teardown.

(cherry picked from commit bf3468adf0947a51f09d4a1aaae2865f3e50a2f2)
2026-09-10 17:47:27 +08:00
Chinesezjc 114e8c9b09 test: drop two host-paced assumptions the hosted image exposes
The ACP plugin-config case drove a real dispose with 150ms graces. On the hosted
image the SIGKILL escalation landed while the managed scope could not take the
signal — systemctl failed the kill ("Failed to send signal SIGKILL to auxiliary
processes: Invalid argument") — so the run reported a teardown failure the
configuration never asked for. The case asserts that config graces reach the
real run, so the values only need to clear the host's scope handling. Its mock
refuses stdin EOF and SIGTERM by design, so the case waits out both graces and
carries its own budget for that fixed cost.

Both illegal-UTF-8 residual cases relied on a plain sched_yield leaving each
write as its own read chunk. A starved reader coalesces hundreds of bytes into
one chunk, which inflates the measured peak for correct accounting too: the
hosted image measured 2563 against the 2048 bound. Pace with a real sleep so
each byte is its own chunk everywhere, and keep each payload above the bound
(3200 bytes; 1100 CESU-8 sequences) so a raw-byte undercount still flushes past
it instead of only at EOF.

(cherry picked from commit 30e0c3ff0415befe3652a55611df8a18d82c18bb)
2026-09-10 17:47:27 +08:00
Chinesezjc c4c2d16308 test(subprocess): align the teardown race with the settlement contract
`disposal contains a spawn-failure rejection that races teardown` asserted one
winner of the race. A bootstrap that publishes its pre-exec failure rejects with
that failure, and a teardown that stops the bootstrap first settles as the
requested termination — the recorded failure only outranks the stop when it was
published before the stop landed. Assert the contract instead: a rejection
carries the failure, a stop carries SIGTERM, which only the Linux scope records
because the win32 job owner and the fallback launcher both reject the start.

The two terminal cases that drive a mocked PTY exit state why they pin
`internals.platform`: under the host's native scope the mocked exit races the
scope bootstrap and fails as `terminal scope exited before its bootstrap
consumed the launch request`.

(cherry picked from commit fee113eb9a5632555304858d2bf6355588a3aaf0)
2026-09-10 17:47:27 +08:00
Chinesezjc 87f32dc8ca docs(notes): record the hosted-image assumptions the coverage suite names
The failover leg runs this suite on pools this repository does not own, and the
coverage lanes failed there on host properties their cases never named: the
containment a mocked PTY exit raced, the grace a managed scope needs before it
can take a SIGKILL, reader coalescing in the illegal-UTF-8 residual cases, and
a Windows image that refuses the folder dialog class. Record what each case
pins now, what was rejected, and the runs that measured it, so the next pool
change starts from those host dependencies instead of re-diagnosing them.
2026-09-10 17:36:16 +08:00
Chinesezjc 45c10ed2ce ci: give the Linux coverage lane the hosted image's teardown budget
The managed-scope disposal cases in subprocess-local and bash-sandbox run past
the 5000ms default when this lane's four partitions, six workers per gate, and
sibling gates share one host. The same commit stays inside the budget on the
in-house pool: the hosted image exceeded it (run 34449848541) and the lane is
green with 90000 (run 34457655892). The Windows coverage lane already grants
the same budget for the same class of teardown.
2026-09-10 17:36:16 +08:00
Chinesezjc f45ca2d9ac test: drop two host-paced assumptions the hosted image exposes
The ACP plugin-config case drove a real dispose with 150ms graces. On the hosted
image the SIGKILL escalation landed while the managed scope could not take the
signal — systemctl failed the kill ("Failed to send signal SIGKILL to auxiliary
processes: Invalid argument") — so the run reported a teardown failure the
configuration never asked for. The case asserts that config graces reach the
real run, so the values only need to clear the host's scope handling. Its mock
refuses stdin EOF and SIGTERM by design, so the case waits out both graces and
carries its own budget for that fixed cost.

Both illegal-UTF-8 residual cases relied on a plain sched_yield leaving each
write as its own read chunk. A starved reader coalesces hundreds of bytes into
one chunk, which inflates the measured peak for correct accounting too: the
hosted image measured 2563 against the 2048 bound. Pace with a real sleep so
each byte is its own chunk everywhere, and keep each payload above the bound
(3200 bytes; 1100 CESU-8 sequences) so a raw-byte undercount still flushes past
it instead of only at EOF.
2026-09-10 17:36:15 +08:00
Chinesezjc df709f442c test(subprocess): align the teardown race with the settlement contract
`disposal contains a spawn-failure rejection that races teardown` asserted one
winner of the race. A bootstrap that publishes its pre-exec failure rejects with
that failure, and a teardown that stops the bootstrap first settles as the
requested termination — the recorded failure only outranks the stop when it was
published before the stop landed. Assert the contract instead: a rejection
carries the failure, a stop carries SIGTERM, which only the Linux scope records
because the win32 job owner and the fallback launcher both reject the start.

The two terminal cases that drive a mocked PTY exit state why they pin
`internals.platform`: under the host's native scope the mocked exit races the
scope bootstrap and fails as `terminal scope exited before its bootstrap
consumed the launch request`.
2026-09-10 17:36:14 +08:00
Chinesezjc ac5f851095 test(directory-picker): probe the folder dialog class instead of the platform
A Windows Server image can answer CoCreateInstance(CLSID_FileOpenDialog)
with CLASS_E_CLASSNOTAVAILABLE, so the win32 COM smoke has no dialog to
open and the POSIX rejection expectation is the only proof that image can
produce. Gate the pair on a PowerShell activation probe taken outside the
code under test, so a GUID or vtable regression in src still fails the
smoke instead of skipping it.
2026-09-10 17:36:13 +08:00
Chinesezjc 40606d1558 Merge pull request #3873 from deepseek-harness/ci/failover-canary-leg
ci: opt-in canary runner leg for the CI pool failover switches
2026-09-10 13:59:53 +08:00
Chinesezjc 360354e38b Merge remote-tracking branch 'origin/master' into ci/failover-canary-leg 2026-09-09 20:04:23 +08:00
Chinesezjc acc8535390 docs(ci): record the canary failover value and the glob fix across internal notes
The failover runbook, the node-compatibility note, the native-Windows note,
and the serial-reference note record the third variable value's scope and
exclusions (bilingual, pairing re-recorded); a new implemented process note
owns the value's participating set, the dormant-by-default canary posture,
and the walker-fix rationale. .github/AGENTS.md points at both notes.
2026-09-09 19:20:29 +08:00
Chinesezjc d79294f23a fix(scripts): enumerate repo files with a dirent walker instead of node fs.glob
Node's internal fs.glob, from some 24.x releases, lstat-probes
<matched>/<next segment> while expanding a ** pattern over a symlinked
file and throws ENOTDIR instead of skipping (observed on node 24.13.0
scanning snapshots/acp/image-compaction's symlinked
system-prompt.expected.md, which failed verify-md-wrap inside
check:ci:static). uniqueRepoFiles now walks with dirent types, never
probing a path under a file, and mirrors fs.glob's dot:false and
follow:false semantics: the four repo-files gate pattern sets enumerate
identically. Broken or cyclic symlinks fail loudly in the caller's
realpathSync, and pattern forms the walker does not model (metacharacters,
a trailing **, empty segments) are rejected up front. repo-files.spec.ts
pins the symlink, broken-link, and rejection behavior.
2026-09-09 19:20:29 +08:00
Chinesezjc 9bae613128 ci: add an opt-in canary value to the CI pool failover switches
The per-platform failover repository variables (DSH_CI_FAILOVER_LINUX and
DSH_CI_FAILOVER_WINDOWS) accept a third value alongside the existing
selfhosted routing. Set by a repository writer, the value retargets the
always-on pull-request and master lanes onto the matching hosted-runner
labels (16-core pools map to the 16-vCPU tier, standard legs to 4-vCPU);
unset or any other value keeps today's runners, so the leg is dormant until
a writer opts in - a canary path for capacity fallback, never the default.

Participating jobs: the three enterprise Linux workers, the node-compat
legs, the four Windows lanes, and the all-checks-passed verdict in ci.yml;
expected-filenames; the sandbox bwrap leg; and the two manual benchmark
matrices (4-32 vCPU tiers map to equivalents; 64/96-core rows keep the
fleet labels). Everything pinned to its own runner by spec, credential, or
host capability keeps it under every value, and the release-shaped chains
stay entirely hosted. request-review.yml was retired on master while this
work was in flight and the branch takes the deletion.

Specs pin the new branches: ci-workflow.spec.ts asserts the labels appear
in the extended selectors, and ci-compatible-selfhosted.spec.ts evaluates
the routing mode.
2026-09-09 19:02:10 +08:00
ChinesezjcandTianyi Cui 02a029e679 Feedback is recorded in the session log and delivered through DeepSeek
Co-authored-by: Tianyi Cui <[email protected]>
2026-09-05 23:21:22 +08:00
Chinesezjc a33b9081b6 Merge remote-tracking branch 'origin/master' into fix/ci-node-compile-cache-data-disk 2026-09-04 17:13:09 +08:00
Chinesezjc 4dfd3b5948 fix(note): restore blank line before Alternatives heading after merge conflict resolution 2026-09-04 16:50:44 +08:00
Chinesezjc cff9a004a6 Merge remote-tracking branch 'origin/master' into fix/ci-node-compile-cache-data-disk 2026-09-04 16:22:44 +08:00
Chinesezjc f7f4bab746 Merge origin/master into fix/ci-node-compile-cache-data-disk 2026-09-04 16:17:32 +08:00
Chinesezjc bee0c13f28 Merge pull request #3513 from deepseek-harness/fix/test-tmp-teardown-self-clean
test: remove dsh-* temp dirs created by unit tests at teardown
2026-09-04 12:11:53 +08:00
Chinesezjc 1f0a87eb06 Merge remote-tracking branch 'origin/master' into fix/test-tmp-teardown-self-clean
# Conflicts:
#	packages/subprocess/subprocess-local/tests/spawn.spec.ts
2026-09-04 11:58:16 +08:00
Chinesezjc d8a995e00e docs: align the changed-spec count with the merged-base diff (36) 2026-09-04 11:56:31 +08:00
Chinesezjc 3f07443702 Merge branch 'master' into fix/test-tmp-teardown-self-clean 2026-09-04 11:15:31 +08:00
Chinesezjc dde27f5163 Merge remote-tracking branch 'origin/master' into fix/test-tmp-teardown-self-clean 2026-09-03 19:04:31 +08:00
Chinesezjc cf4cfd9e4a docs: correct the changed-spec count in the Agent Note verification section 2026-09-03 18:17:09 +08:00
Chinesezjc c8fc38541f test: own the default spill dir in subprocess specs; correct retention wording
Second review round (ds-review-bot v4p/v5/v6): the exit cleanup claim that
collectors unlink their spill files on dispose was wrong — completed spill
files are retained (seal() only closes, discardSpill() is the only unlink),
so the exit removal only ever applies to directories that never spilled.
Reword the JSDoc, README, and Agent Note accordingly, drop the redundant
readdirSync precheck (rmdirSync ENOTEMPTY is caught anyway), and recount the
v8-ignore window. The spawn.spec default-spill test now records the default
per-process directory it created and removes it in afterAll, so a completed
spill file is never left behind by the unit suite.
2026-09-03 17:29:21 +08:00
Chinesezjc 1bc330ce01 docs: cross-link the spill retention decision from the teardown note
The Agent Note now links the 2026-07-17 local-spill-startup-cleanup note it
builds on, and the privateSpillDir JSDoc documents the empty-dir exit
removal alongside the directory's creation contract.
2026-09-03 17:07:43 +08:00
Chinesezjc 29e6669e3c test: narrow process-exit spill cleanup to empty dirs; drop spill-store deletion
Review (ds-review-bot) found the exit-time deletion of per-process spill
roots conflicts with the documented retention decision: spill artifacts are
model-visible locators that resumed or forked sessions may still reference
(2026-07-17-local-spill-startup-cleanup), and an exception thrown from an
'exit' listener can change the process exit code.

- dsh-spill-local: revert the exit handler entirely; its default root is
  already owned by the package's 30-day startup sweep.
- dsh-subprocess-local/spawn: remove the per-process spill dir at a
  JavaScript-observable exit only while it is EMPTY (collectors unlink
  their spill files on dispose), best-effort with a named swallow so a
  Windows-held handle never changes the exit code; dirs holding spill
  files keep them for external cleanup.
- Document the empty-dir exit removal in the package README and the Agent
  Note, and re-record both bilingual pairs.
2026-09-03 17:06:48 +08:00
Chinesezjc 6d9776a3b0 test: exempt process-exit spill cleanup from the per-file coverage gate
The exit listener runs after the coverage dump, so its body can never be
measured by the unit coverage lane; mark it v8-ignore with the reason, as
with other process-exit-only code paths.
2026-09-03 16:35:45 +08:00
Chinesezjc 1107ff5fe1 test: remove remaining dsh-* spill/temp dirs in shell and fs specs
Full-template residue histogram on the CI host surfaced four more normal-exit
leaks below the earlier cutoff: tool-bash/tool-pwsh tools.spec (module spill
dir / per-test homes), bash-sandbox sandbox.spec (module spill dir and the
read-only denial root), and fs-sandbox fs-sandbox.spec (inline tmp dir). All
four now remove what they create at the same teardown points as their
neighbors.
2026-09-03 16:26:22 +08:00
Chinesezjc 0364343a7e test: remove dsh-* temp dirs created by unit tests at teardown
Spec files that create /tmp/dsh-* directories via mkdtemp now track and
delete them in afterEach/afterAll; module-scope fixture dirs (executor
spill dirs) are removed in afterAll. The file list came from the
observed-residue inventory on the self-hosted CI host: only specs whose
dirs actually accumulated were leak sources (issue #3134), superseding
the kept-but-unmerged CI sweep branch per the #3233 review decision.

Product per-process spill roots (dsh-subprocess-local spawn,
dsh-spill-local store) register a process-exit handler that removes the
memoized dir, so processes that used the spawn/spill path clean up on
normal exit. A SIGKILLed process cannot run in-process teardown; the
machine-side timer remains the backstop for that path.

Agent Note: .agents/notes/implemented/process/2026-08-28-test-temp-dir-self-cleanup.md
2026-09-03 16:19:18 +08:00
Chinesezjc 100fcb286f Merge pull request #3432 from deepseek-harness/fix/pwsh-loader-composition-timeout
test(pwsh): restore product-default deadline in loader composition
2026-09-03 15:59:41 +08:00
Chinesezjc 91f7e08136 Merge branch 'master' into fix/pwsh-loader-composition-timeout 2026-09-03 15:05:54 +08:00
Chinesezjc ecd75e6dd6 test(pwsh): clarify deadline comment and keep case budget independent
Review feedback: the dsh-terminal-bash product default is 30s, not 300s;
the raised value bounds one send plus the complete startup sequence, so it
must cover the same cold start the tool deadline does. The vitest case
budget stays at its pre-existing 120s: the case-level timeout overrides
the lane --testTimeout, so syncing it to the plugin deadline would make a
stalled partition wait 300s instead of 120s.
2026-09-03 13:05:22 +08:00
Chinesezjc a631115597 Merge pull request #2828 from deepseek-harness/feat/toolcard-image-result
feat(ui-tool): render read_image results as the image
2026-09-02 12:45:39 +08:00
Chinesezjc 3648331b11 Merge remote-tracking branch 'origin/master' into feat/toolcard-image-result
# Conflicts:
#	packages/client/ui-chat/src/client/chat/ChatNodeSeat.tsx
#	packages/client/ui-chat/src/client/chat/ChatView.tsx
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
2026-09-02 12:02:25 +08:00
Chinesezjc e4c822544c test(pwsh): restore product-default deadline in loader composition
The first call pays the full pwsh cold-start latency (spawn + .NET +
PSReadLine + Defender) inside the tool deadline. A 60s bound on the fully
loaded self-hosted Windows pool is exceeded often enough to reset the
session mid-test: two master CI runs (2026-09-01, runs 33524764567 and
33534262413) each failed at ~62s with the second call observing a fresh
session (cwd back at root, env empty). 300s matches the product default
so cold start no longer races the budget.
2026-09-02 11:50:18 +08:00
Chinesezjc d2954806de fix(snapshots): project read-image-attachment-path fixture into canonical packed layout 2026-09-01 15:19:37 +08:00
Chinesezjc a23c3dd64e Merge branch 'origin/master' into feat/toolcard-image-result 2026-09-01 14:45:24 +08:00
Chinesezjc d13d0a4b86 ci: re-trigger workflow after dropped push event 2026-09-01 11:53:19 +08:00
Chinesezjc 9d15938073 Merge pull request #1148 from deepseek-harness/feat/code-runtime-python-backend
feat(code-runtime-python): add the CPython subprocess backend
2026-09-01 11:44:16 +08:00
Chinesezjc 6e5ed52aed fix(ui-tool): address review wording and JSDoc accuracy on the image card 2026-09-01 11:43:26 +08:00
Chinesezjc 666bd48eae fix(ui-tool): scope the image-card path fallback to nested calls; repair merge-broken docs and snapshot fixtures 2026-09-01 11:40:21 +08:00
Chinesezjc a0c0b55c8a Merge remote-tracking branch 'origin/master' into feat/code-runtime-python-backend
# Conflicts:
#	packages/experimental/code-runtime-python/package.json
2026-09-01 11:29:10 +08:00
Chinesezjc 6ce131c4f4 Merge remote-tracking branch 'origin/master' into feat/code-runtime-python-backend 2026-08-31 21:41:18 +08:00
Chinesezjc a8d8b8cddd docs(code-runtime-python): sync hostFrameParseCeiling example numbers to the 16x multiple
The hostFrameParseCeiling JSDoc and one load-gate test comment still quoted
the pre-16x derivation (~29 MiB for a ~300 MiB heap, ~14 MiB for a 128 MiB
old space). With HOST_PARSE_WORST_CASE_MULTIPLE = 16 the same hosts derive
~14 MiB and ~7 MiB (floor((176-64)/16)); protocol.spec.ts pins the 304 MiB
case at 15 MiB. Comment-only correction, no behavior change.
2026-08-31 18:57:34 +08:00
Chinesezjc 56ca8af0ee feat(ui-tool): render the image card for nested read_image calls 2026-08-31 18:14:08 +08:00
Chinesezjc 974fca9f5a fix(code-runtime-python): restore oxlint suppressions lost in the #3289 merge-forward and re-pack the ptc-python fixture
The #3289 merge-forward dropped four typescript/no-unnecessary-condition
suppressions from index.ts (boot-write-failure fake child stdin, the
admit()-closure logsTruncated recheck, and both settled rechecks whose
guards flip mid-wait), turning the lint:contracts-ready gate red. Re-add
them with their reasons. The merge also carried a ptc-python-turn session
fixture that was not in canonical packed layout; migrate-packed-session-fixtures
re-writes it so session-fixture-layout passes.
2026-08-31 17:52:25 +08:00
Chinesezjc 5bb2c46453 Merge branch 'master' into feat/toolcard-image-result 2026-08-31 17:11:15 +08:00
Chinesezjc 8fb9bc29e9 Merge branch 'master' into turtle/pr-open-start-date 2026-08-31 16:27:41 +08:00
Chinesezjc c5a94f11df Merge pull request #3354 from deepseek-harness/fix/windows-coverage-flaky-test-budgets
test: stabilize the Windows coverage lane against timing flakes
2026-08-31 16:11:55 +08:00
Chinesezjc 8ace43a8b1 Merge pull request #3364 from deepseek-harness/fix/notices-serial-windows-timeout
fix(ci): serial-windows notices timeout and generator store-scan cost
2026-08-31 16:10:47 +08:00
Chinesezjc 4f877cdab1 Merge branch 'master' into fix/notices-serial-windows-timeout 2026-08-31 15:55:59 +08:00
Chinesezjc a00c9a062c Merge branch 'master' into fix/windows-coverage-flaky-test-budgets 2026-08-31 15:45:19 +08:00
Chinesezjc a074e6131f fix(ci): serial-windows notices timeout and generator store-scan cost
render() loaded the workspace manifests once per external dependency
name through workspaceLinkedManifest, an O(names x manifests) file
read on the cold path; on the loaded self-hosted Windows host with
coverage instrumentation the freshness spec crossed Vitest's default
5000ms budget and failed the serial-windows standby gate four times in
a week. Load the manifests once in render() and thread the map through
the collectors instead.

The serial-windows lane also ran the coverage inventory at the strictest
budget of any lane: add DSH_COVERAGE_TEST_TIMEOUT_MS=90000 to match the
pull-request windows-coverage lane, pinned by ci-workflow.spec.ts.
2026-08-31 15:33:16 +08:00
Chinesezjc 8e9d5467b0 fix(code-runtime-python): bound reply and call backlogs, snapshot binding metadata, and compact the reply queue
Review findings on the CPython backend: a child that never reads fd 3 leaves
the reply pipe full forever, so the drain loop waits on 'drain' while every
call frame it keeps sending resolves a binding and queues another reply —
the backlog (and the binding results it pins) would grow until the wall
clock. sendReply now caps the pending backlog at MAX_PENDING_REPLIES and
settles the run as worker-exit past it, mirroring the frame cap; a child
flooding calls against a binding that never settles would otherwise bypass
that cap (pendingReplies grows only after the await), so the dispatcher
counts in-flight binding calls before dispatch and releases the slot in the
async body's finally, capping outstanding closures at the same bound. The
drain also compacts its consumed prefix (replyQueue.splice(0, head)) once
head reaches the bound, so a drain that stays alive without emptying cannot
grow the backing store linearly with cumulative throughput.

The completion-value meter counted lone surrogates with
_SURROGATE.findall(folded), materializing one single-character string per
surrogate: a surrogate-dense value near the budget (millions of surrogates,
each serializing to six bytes) allocated millions of objects before the meter
returned, defeating the meter's counting-without-building contract. The count
is now the length difference between folded and the without string the meter
already computes; a standalone equivalence check confirms it matches findall
across lone-high, lone-low, paired, astral, and mixed cases.

validateBindings read namespace.global/errorClass.name/memberNameProperty
several times and retained the original errorClass object for the boot
frame, whose JSON.stringify re-read it after validation: a stateful getter
could throw or change between the two stages, turning the seam-misuse
rejection into a worker-exit or injecting an unvalidated name. Each field is
now read once into a plain value and the bindings map stores a plain
{ name, memberNameProperty } copy, so validation and the boot frame see
identical values.

Regression tests: a hostile child floods 5000 sequential valid calls without
reading fd 3 and the run settles worker-exit with the reply-queue message
before maxWallMs; a 3,000,000-surrogate completion succeeds at an
18,000,002-byte budget and reports output-limit one byte under; a 5000-call
flood against a never-settling binding settles worker-exit with the
call-backlog message; getter-backed namespace metadata that throws or
changes on a second read boots and runs with each field read exactly once; a
two-wave flood whose replies exceed the writable high-water mark drives the
drain past the compaction bound mid-delivery and verifies all 1524 replies
arrive. README Known Limitations gains the reply-backlog and call-backlog
bounds (en/zh, pairing re-recorded); a new Agent Note registers the findings.
2026-08-31 15:25:26 +08:00
Chinesezjc b75eec0967 docs(doc-graphs): list the experimental Python backend as a codeRuntime implementation
The capability-seams graph derives its implementation lists from
SERVICE_ROLES in scripts/gen-doc-graphs.ts, which still listed only the
worker-thread backend. Add experimental-code-runtime-python so the
generated graph and table match the registered ctx.codeRuntime
implementations; regenerate docs/capability-seams.md, sync the zh pair,
and re-record the i18n pairing.
2026-08-31 15:25:26 +08:00
Chinesezjc 2df28fd249 fix(code-runtime-python): validate explicit pythonBin at load, snapshot bindings, and settle the reply drain
Review findings on the CPython backend: an explicit pythonBin path bypassed
the load-time checks (missing/non-executable/directory paths surfaced only
as a run-time worker-exit); a throwing binding member accessor escaped the
fd-3 data callback and terminated the host; the reply drain waited on
'drain' alone, so a pipe destroyed under the wait hung forever; and two
staging-leak assertions diffed a global tmpdir that parallel workers can
perturb.

resolvePythonBin now applies the same accessSync(X_OK) + isFile check to
explicit paths (resolved against the host CWD), and the load error message
distinguishes 'is not an executable regular file' from 'does not resolve on
PATH'. validateBindings snapshots callables into a plain record during run()'s
synchronous validation, turning an accessor throw into the seam-misuse
rejection and fixing the key set the boot frame and dispatch share. The reply
drain waits on drain/close/error together and short-circuits on
proto.destroyed. The staging-leak assertions check the exact paths this test
file staged (recorded by the mocked mkdtempSync) instead of a tmpdir diff.

docs(code-runtime-python): add the alternatives section to the hardening note

docs(config-catalog): refresh the code-runtime-python Config source line

test(code-runtime-python): cover the async spawn-error worker-exit path
2026-08-31 15:25:26 +08:00