Commit Graph
3650 Commits
Author SHA1 Message Date
_Kerman 9676696a31 fix(agent-loop): suppress cancel-requested for a no-op keepInbox cancel
cancel() emitted agent/cancel-requested whenever queued or steering work
existed, even under keepInbox with no active turn — a call the contract
documents as a no-op. Consumers could misread that notification as a real
cancellation. Emit only when the call actually aborts the active turn or
discards pending work, matching the "effective call" contract.
2026-07-27 01:22:19 +08:00
Tianyi Cui 43d81b67ce fix(subprocess): consumers with one mixed env map split DSH_* onto the managed channel
Codex review of the acp-only fix found lsp-local carries the identical
defect: its server config's unrestricted env merges into the connection's
ordinary spawn channel, so a configured DSH_* fact crashed the spawn with
the reserved-namespace rejection. The partition now lives on the seam as
splitEnvChannels() beside the scrub it complements; the ACP run and the
LSP connection both use it, and each proves child delivery end-to-end
(MOCK_ECHO_ENV / LSP_FAKE_ECHO_ENV fixture knobs). Seam + consumer README
rows updated (en+zh, re-recorded). bash-local is already two-channel;
mcp/pty/sdk bypass the seam and only share the scrub.
2026-07-27 01:21:32 +08:00
Tianyi Cui fced51d4eb fix(subagent): route explicit DSH_* config entries onto the managed env channel
The acp run passed config.env wholesale into the spawn spec's ordinary
channel, which rejects the reserved DSH_* namespace — a deployment fact
like DSH_PERMISSION_MODE (the acp-agent example's own knob, used by the
with-key e2e) crashed the spawn. The run now splits DSH_* entries onto
dshEnv, where the scrubbed base expects current facts to arrive. New
layering test drives the split through the real seam via a MOCK_ECHO_ENV
knob on the mock server; README env prose updated (en+zh, re-recorded).
2026-07-27 01:04:37 +08:00
Tianyi Cui 51bf3ca96e Merge remote-tracking branch 'origin/master' into worktree/archive-agent-notes-20260726
# Conflicts:
#	.agents/notes/archived/process/2026-07-23-browser-demo-gif-recording.i18n.yaml
2026-07-27 00:53:07 +08:00
Tianyi Cui 420e0b5fb7 Merge remote-tracking branch 'origin/master' into worktree/fix-pty-sigint-flake 2026-07-27 00:35:06 +08:00
Tianyi Cui 72fa31b745 Merge remote-tracking branch 'origin/master' into worktree/packed-chunks-default-rfc 2026-07-27 00:29:58 +08:00
Tianyi Cui 1fc289c8bb Merge branch 'worktree-subprocess-consumers' into worktree-process-service-seam 2026-07-27 00:22:29 +08:00
Tianyi Cui ea58a5660b Merge remote-tracking branch 'origin/master' into worktree-process-service-seam 2026-07-27 00:22:15 +08:00
Tianyi Cui 45a5175e44 feat(tool-web): replace the regex HTML-to-markdown converter with turndown
Implements the turndown Agent Note from the NIH dependency audit (full
variant, not the minimal entities-only fallback): dsh-tool-web's fetch
rendering now converts HTML through turndown + @joplin/turndown-plugin-gfm
(atx headings, fenced code, dash bullets, GFM tables/strikethrough) over
the real domino DOM, with script/style/noscript removed wholesale. The
hand-rolled ~86-line regex converter html.ts and its entity tables are
deleted; renderBody wraps the conversion in try/catch falling back to
the raw HTML body, because turndown's recursive DOM walk overflows with
a RangeError on pathological nesting (measured: 4k levels on the main
thread, 8k in a worker) where the regex version could never throw.

Closure weight, measured: tool-web IS in the single-exe runtime closure,
and the exe asset globs would pack ~7.9 MB of the three new packages —
but ~6 MB of that is domino's test corpus, with runtime lib/ at ~550 KB
against a ~174 MB artifact (<0.5% either way), so the swap wins.

Per testing policy the previously-missing keyless web_fetch snapshot
ships in the same change: the acp-agent `web-fetch` scenario boots a new
web.cordis.yml overlay (web seam + real dsh-web-fetch-local provider +
tool-web fetch-only + a loopback HTTP fixture server on a fixed port
serving deterministic HTML with entities, a GFM table, and nesting), so
recording and keyless replay both drive the real HTTP fetch and real
conversion end to end; the scenario pins the new `web` header class.

The Agent Note moves proposed -> implemented and is rewritten per the
lifecycle contract (Decision/Consequences/Testing, closure verdict and
alternatives recorded); tool-web and acp-agent READMEs updated in both
languages and pairs re-recorded.
2026-07-27 00:22:13 +08:00
_Kerman 9ef55cda98 fix(tui): match reference discard listener on content, not the unassigned id
The reference-admission discard listener matched on followup()'s returned id,
but an agent/inbox/enqueue listener that synchronously cancels emits
agent/inbox/discard before followup() returns to assign that id. The match
then missed, leaking both the submit and discard listeners plus the attached
context per referenced prompt. Match on the content reference instead — the
same value send() carries onto the message, known before followup() runs, and
symmetric with the submit wrapper's content check.

The prior "ordinary allowed path" test passed only because the fake agent
returned a fixed 'stub' id that collided with the id the test constructed;
it now releases each wrapper through its own allowed admission, and a new
regression drives the synchronous-discard timing directly.
2026-07-27 00:21:00 +08:00
Tianyi Cui d3a4f4af1b fix(tests): lsp specs ride the seam scrub; acp e2e mounts the subprocess service
CI now exports DSH_GATE_CONCURRENCY into every job, and the lsp suites
spread the raw parent env into the spawn spec's ordinary channel — which
the seam rightly rejects for DSH_* names. The specs now build their child
env the way production does (scrubbedParentEnv() + explicit extras).
The acp with-key e2e never mounted dsh-subprocess-local, leaving the
provider's inject unsatisfied, so no 'acp' provider ever registered.
2026-07-27 00:18:03 +08:00
Tianyi Cui d2b15e71df Merge pull request #662 from deepseek-harness/code-mode-ui/shiki
feat(web): shiki syntax highlighting for code surfaces
2026-07-27 00:00:23 +08:00
Tianyi Cui 48400c436b Merge branch 'master' into code-mode-ui/dispatch-spill 2026-07-26 23:58:31 +08:00
Tianyi Cui e0e187a6a7 test(pty): avoid echoed readiness marker race 2026-07-26 23:52:12 +08:00
Tianyi Cui 3cabde323f fix(acp-snapshot): keep the malformed-record capture branch-free for per-file coverage
Store the captured validation error as unknown in a wrapper object and
rethrow it directly: the instanceof-Error normalization added an
un-inducible false branch that failed harness.ts's 100% branch gate.
2026-07-26 23:45:13 +08:00
Tianyi Cui 4ff496c65c feat(session): default JSONL writes to packed rows 2026-07-26 23:44:52 +08:00
_Kerman 6de88f427c Merge remote-tracking branch 'origin/master' into xtr/agent-loop-message-machine 2026-07-26 23:23:18 +08:00
Tianyi Cui 32ae16fa59 Merge origin/master into worktree/archive-agent-notes-20260726 2026-07-26 23:11:33 +08:00
Tianyi Cui a8a1ada183 docs: move execa Agent Note to implemented; update inbound links and README contracts
- proposed/testing -> implemented/testing with the lifecycle rewrite
  (Proposal->Decision in present tense, Acceptance criteria + Risks
  folded into Consequences); zh counterpart mirrored and both pairs
  re-recorded.
- the rejected NIH-audit roll-up pair now links the implemented/ path.
- loader-smoke README: captured output is bounded by execa's default
  100 MB maxBuffer, no longer unbounded.
- acp-snapshot README: harness.ts now also imports vitest (vi.waitFor),
  so the vitest-run-only constraint names both modules.
- jsonrpc keyless smoke: raise the invalid-env case's subprocess
  deadline to 25s (the 9s pick starved a cold tsx boot on slow NFS).
2026-07-26 23:10:38 +08:00
Tianyi Cui 98980900d0 Merge origin/master into worktree/archive-agent-notes-20260726
# Conflicts:
#	.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.i18n.yaml
#	.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.md
#	.agents/notes/implemented/testing/2026-07-24-web-gui-browser-e2e-lane.zh.md
2026-07-26 23:07:21 +08:00
Tianyi Cui 37140bf823 docs(notes): archive low-value decision records 2026-07-26 23:06:00 +08:00
_Kerman 0dc5d07ae7 fix: close five composition seams found in review round five
goal-session rides retry turns and survives admission failures. A
recovery policy closes a goal round's failed turn and reopens its
history under a retry trigger; the attempt now adopts that turn and
drops the failed turn's provisional reason, so the round settles from
the retry's own outcome instead of blocking an armed goal with
turn-error after a successful response. A downstream admission hook
that throws (rather than blocks) used to strand the queued reservation
forever; the listener now clears a still-turnless matching attempt on
the rejection path and reschedules the round.

agent-loop contains a persistently rejecting step close in the catch
path the same way the finally contains the turn close, so the
post-finally tail always publishes the terminal status — previously a
double veto escaped run(), leaving status at running while whenIdle()
resolved. The whenIdle catch arm is annotated as the backstop it now
is: every driver rejection path is contained today.

workspace-context folds an already-appended baseline from the session
log when the plugin is hot-remounted over a live session, instead of
injecting a duplicate from its fresh mount-local guard.

The TUI's reference-admission discard listener installs before
followup(): admission runs synchronously inside it on the common path,
so a listener installed afterwards missed its own cleanup and leaked
one callback per referenced prompt.
2026-07-26 23:03:32 +08:00
Tianyi Cui d167af3fb7 Merge branch 'master' into worktree-tasks-service-seam 2026-07-26 22:57:38 +08:00
Tianyi Cui 0bcf4886ff Merge branch 'code-mode-ui/shiki' into code-mode-ui/trajectory-spans 2026-07-26 22:54:50 +08:00
Tianyi Cui d404609e19 docs(subprocess): bring the zh side of the consumer-migration pairs along
The parent branch's zh translations were recorded against its pre-reshape
en text; this PR's Node-ward en deltas get minimal zh updates across the
subprocess catalog and the subprocess/lsp-local/subagent READMEs (all
type-equiv blocks byte-identical), with pairing records re-recorded.
2026-07-26 22:54:44 +08:00
Tianyi Cui 46139d9816 Merge branch 'code-mode-ui/dispatch-spill' into code-mode-ui/shiki 2026-07-26 22:54:19 +08:00
Tianyi Cui 443e2bc509 refactor(tools): shapeDispatchLog off the public registry surface
Responding to review on #661: a public method on the generic ToolRegistry
service whose only caller is the run_code bridge was ad-hoc surface
widening. The bridge now receives it as a registry-private capability
closure in RunCodeBridgeOptions (the requireRuntime idiom, alongside the
cap), the method is private, and it leaves the generated service
catalog/API surfaces.

The pattern is now named as a code smell where reviewers look: the
packages/AGENTS.md capability-interface rule gains the inverse-smell
clause (ceiling 660→675 — the list is at capacity and the clause needs
one sentence), and dsh-code-review's capability-fit check tells reviewers
to flag single-consumer public service methods and require the closure
form.
2026-07-26 22:52:15 +08:00
Tianyi Cui c50b899015 refactor(llm-deepseek): replace hand-rolled SSE parser with eventsource-parser
Implements the approved simplification Agent Note: sse.ts now pipes the
response body through TextDecoderStream and EventSourceParserStream
(eventsource-parser/stream) and keeps only the DeepSeek protocol shim —
yield each event's data, terminate on [DONE], throw
LlmError('STREAM_CLOSED') on EOF without the sentinel. The SSE
spec-conformance tests are deleted; sse.spec.ts pins only the
[DONE]/STREAM_CLOSED/EOF contract, including the new spec-strict verdict
that an unterminated trailing event is truncation (the old parser
flushed it — a robustness nicety no real provider shape needs).

eventsource-parser@^3.1.0 becomes llm-deepseek's second runtime
dependency (already in the lockfile transitively via the MCP SDK).

Docs: the Agent Note moves proposed/ → implemented/ and is rewritten per
the lifecycle contract; the rejected NIH roll-up note's inbound links
follow. The twin-adapters note, dsh-llm LlmAdapter JSDoc (and its
type-equiv fences), cookbook, group/package READMEs, root AGENTS.md
layout line, sdk-helper comments, and the regenerated config catalog
drop the "hand-rolled fetch + SSE" claim in both languages; all eight
touched pairs re-recorded.
2026-07-26 22:45:33 +08:00
Tianyi Cui e2882f486b fix(review): harden web replay verification
Validate replay sidecars and cross-copy failure facts, make browser console tripwires and macOS temp paths deterministic, and wait for asynchronous TUI resume details. Keep the owning docs, translations, and generated catalog aligned.
2026-07-26 22:38:33 +08:00
Tianyi Cui c4647a8609 test: adopt execa for hand-rolled subprocess plumbing, parseArgs for llm-mock-server CLI, vi.waitFor for poll loops
Implements the execa Agent Note's four sub-changes:
- execa (root devDep + loader-smoke dep) replaces the hand-rolled
  spawn-collect-timeout choreography in loader-smoke, apps/cli and
  cli-demo/acp-demo built-bin e2e, lsp-local and code-runtime-worker
  built-lib e2e, the tui pty-harness outer collector, the jsonrpc
  keyless smoke, and crash-recovery's child spawn. Genuinely custom
  parts stay custom: cli-demo's interrupt-on-marker, jsonrpc's
  line-predicate protocol driving, crash-recovery's SIGKILL-at-failpoint.
  The two loader-smoke /* v8 ignore */ OS-error branches are gone.
- llm-mock-server CLI tokenizes via node:util parseArgs; numeric
  coercion/bounds/cross-option constraints stay manual; pinned
  error-message tests updated to the parseArgs texts.
- both loadRootEnv copies in apps/web/tests are deleted: the owning
  vitest configs (web unconditionally, snapshot in record mode)
  already load the repo-root .env before these files run.
- the four poll loops (acp-snapshot harness waits + crash-recovery
  waitForFile) ride vi.waitFor with explicit {interval, timeout}.
2026-07-26 22:29:41 +08:00
_Kerman 344943e097 Merge remote-tracking branch 'origin/master' into xtr/agent-loop-message-machine
# Conflicts:
#	docs/cordis-catalog/services.md
#	examples/acp-agent/tests/snapshots/code-mode-workspace-context/session.jsonl
#	packages/core/tools/README.i18n.yaml
#	packages/core/tools/src/code-mode.ts
2026-07-26 22:17:47 +08:00
_Kerman 225552fb32 fix(tui,tool-tasks): finish removing dispose-ness from delivery
The TUI's referenced-prompt snapshot now rides the prompt's own
admission transaction instead of a pre-admission inject: while idle, a
one-shot prepended agent/prompt-submit wrapper appends the snapshot to
the allow decision's additionalContexts, so a blocking hook discards
the prompt and its attached context together instead of stranding the
snapshot in history for the next unrelated prompt. A prompt discarded
before admission releases the wrapper; steering keeps the inject path
since it bypasses admission and drains at the same boundary. The
session-reference snapshot adapter pinned the old context-before-prompt
order; the branch-wide order (prompt first, its contexts after) is now
asserted and the fixture re-recorded.

tool-tasks drops the last consumer of the removed thrown-disposed
contract: completion notices now inject unconditionally, which is
well-defined during owner teardown — the loop treats disposal like any
cancel, so the notice appends as durable idle context (persisted for
resume while the session is attached, dropped with the detached log
after). README pair and the owner-disposal tests state the new
delivery contract.
2026-07-26 22:08:35 +08:00
Tianyi Cui 1b9d66eaac Merge branch 'worktree-process-service-seam' into worktree-subprocess-consumers
# Conflicts:
#	docs/core-data-structures/subprocess.md
#	packages/subagent/subagent-subprocess/README.md
#	packages/subprocess/README.md
#	packages/subprocess/subprocess-local/README.md
#	scripts/translation-pairing.manifest.json
2026-07-26 22:04:14 +08:00
Tianyi Cui a238c4b064 docs(subprocess): bring the zh side of the subprocess pairs along after the master merge
Master made bilingual pairing mandatory repo-wide; the subprocess family
docs get their zh counterparts: new pairs for the core-data subprocess
catalog and the three subprocess READMEs (switcher lines added on the en
side), and minimal zh updates for the packages/bash/bash-local README
deltas this PR made, with pairing records recorded.
2026-07-26 22:00:38 +08:00
Tianyi Cui 430f6441c8 Merge branch 'code-mode-ui/shiki' into code-mode-ui/trajectory-spans 2026-07-26 21:52:41 +08:00
Tianyi Cui b67ecc45fc Merge remote-tracking branch 'origin/master' into worktree/pr654-merge-20260726 2026-07-26 21:47:07 +08:00
Tianyi Cui 426da32217 Merge branch 'code-mode-ui/dispatch-spill' into code-mode-ui/shiki 2026-07-26 21:44:17 +08:00
Tianyi Cui a4644413e5 fix: restore master's branded-id casts in ui-workspace apply spec
A stale-lib eslint --fix pass during the merge stripped the 'as never'
casts the branded WorkspaceId/SessionId parameters require; typecheck
rejects the push. Take master's version verbatim.
2026-07-26 21:37:42 +08:00
Tianyi Cui d3dc2b9fab Merge branch 'code-mode-ui/live-parallel' into code-mode-ui/dispatch-spill
Conflict resolution: scripts/type-equiv.manifest.json takes master's new
paired-derivative format (one primary entry per pair) and re-adds this
stack's CodeDispatchLog entry in that format. zh README pairs brought
along for the dispatch-log arm (spill-policy behavior/limitations bullets,
tools limitation bullet now pointing at the shipped bounding).
2026-07-26 21:35:03 +08:00
Tianyi Cui 681af6de5e Merge remote-tracking branch 'origin/master' into worktree/fix-clean-symlink-boundary 2026-07-26 21:34:58 +08:00
Tianyi Cui 4bcb52ea12 Merge remote-tracking branch 'origin/master' into worktree/fix-clean-symlink-boundary
# Conflicts:
#	packages/support/llm-mock-server/tests/server.spec.ts
2026-07-26 21:33:44 +08:00
Tianyi Cui 709ac6b531 Merge branch 'master' into web-e2e-interactions 2026-07-26 21:29:34 +08:00
_Kerman 04f0435cc9 refactor(tools): let the terminal marker ride the nested result
The staged-promotion machinery (concludingParents keyed by parent token
plus a pendingParentConclusions staging map) spread one fact — this call
concluded the turn — across three registry-side collections with manual
cleanup. Align it with how additionalContexts already crosses the same
boundary: concludeTurn() marks only its own execution, the marker rides
that execution's successful result (ToolExecutionFailure types
concludesTurn as never, so a policy-converted failure sheds it with the
type), and the composite that owns the nested dispatch forwards it —
Code Mode's binding does so beside its existing context forwarding.

The registry loses both parent-keyed collections and the promotion
block; the propagation decision moves to the owning boundary; the
structured-output consumer's own two-phase commit is untouched.
2026-07-26 21:24:16 +08:00
Tianyi Cui 0ba1e8320e Merge branch 'master' into web-e2e-interactions 2026-07-26 21:23:10 +08:00
Tianyi Cui 76d95fdc4b docs: bring the zh README pairs along for the parallel-dispatch contract
master's bilingual README pairing (new since this branch forked) covers
packages/core/tools and packages/client/runtime, whose EN sides this PR
edits. Translate the scheduling-contract sentences (bridge pool, SDK
overlap line, loop cross-reference, codeDispatches lifecycle) into the zh
sides — including the verbatim shared model-facing block — and re-record
both pairing records.
2026-07-26 21:19:46 +08:00
_Kerman 39c09c9a49 Merge remote-tracking branch 'origin/master' into xtr/agent-loop-message-machine
# Conflicts:
#	docs/core-data-structures/tools.i18n.yaml
#	examples/acp-agent/tests/snapshots/code-mode-workspace-context/session.jsonl
#	packages/core/tools/README.i18n.yaml
2026-07-26 21:08:54 +08:00
Tianyi Cui 4d733c8cbb Merge branch 'worktree-tasks-service-seam' into worktree-process-service-seam 2026-07-26 21:05:15 +08:00
Tianyi Cui fc38f8c813 Merge branch 'master' into code-mode-ui/live-parallel 2026-07-26 21:04:03 +08:00
Tianyi Cui 1dfb38a0b2 Merge remote-tracking branch 'origin/master' into web-e2e-interactions 2026-07-26 20:59:25 +08:00
Tianyi Cui d0aebc9f92 docs(tasks): bring the zh side of the tasks pairs along after the master merge
Master made bilingual pairing mandatory repo-wide; this PR's seam-split
edits to the tasks docs get their zh counterparts: a new pair for the
dsh-tasks-local README and minimal updates to the tasks core-data doc,
agent-spine-demo README, and the tasks family READMEs, with pairing
records re-recorded.
2026-07-26 20:59:05 +08:00