Commit Graph
23 Commits
Author SHA1 Message Date
Yichen Jiang 01dea07922 Merge origin/master into codex/fix-stdio-readline-terminal 2026-06-23 16:27:49 +08:00
imccyu 6731793859 revert: use rewriteRelativeImportExtensions for NextNode .d.ts resolve 2026-06-22 09:02:58 +08:00
Tianyi Cui 07f4047ff0 Use explicit ts specifiers for declarations
Restore explicit .ts relative specifiers in source and enable rewriteRelativeImportExtensions so emitted JS uses .js while declarations keep explicit .ts specifiers. Add a NodeNext declaration-consumer gate to prevent extensionless declaration regressions.
2026-06-22 06:11:00 +08:00
imccyu 88b75181ad fix: apply ts-build-config adjustment to new packages 2026-06-22 01:38:39 +08:00
imccyu 74cdd9a2e5 Merge remote-tracking branch 'origin/master' into feat/adr0016-type-build-check 2026-06-22 00:35:51 +08:00
Tianyi Cui b0422f2a50 fix review findings: bump session format version + restore late turn-end warn
Codex review of the trace-event fold found two merge-blockers.

Blocker #1 — format version. Folding usage onto assistant/message and removing
the standalone usage/error events changed the persisted SessionEventMap shape,
which per the AGENTS.md "bump the version and reject — don't migrate" policy
requires a backend to reject any non-current log. Centralize the version in an
exported SESSION_FORMAT_VERSION constant (dsh-session), read by both write sites
(Session constructor default, SessionStore.prepare header) and the coordinator's
load-time assertVersion check. The constant is pinned at 0: while unreleased the
on-disk format is unstable/pre-release, so breaking shape churn is absorbed at v0
(no monotonic bump until the first tagged release) and any non-0 log is rejected
on load — no migration. Update every test/fixture/doc that stamps a
currently-written header to the constant, bump the ACP snapshot fixture + golden
headers to v0, and keep the version-rejection test meaningful by switching its
bad value to a clearly non-current 99. AGENTS.md documents both the monotonic
(SQLite SCHEMA_VERSION) and pinned-0 (session log) pre-release stances.

Blocker #2 — restore the late turn-end warn. failTurn now sets the error reason
only while the turn is still open; once turn/end is appended (a throwing
agent/turn-end listener after closeTurn) the reason can no longer reach the
durable log, so the late throw is logged via ctx.logger.warn instead of
vanishing into a futile post-close assignment. A regression test asserts the
warn fires.

Also guard the normal-step assistant/message append with the same
content-or-usage condition as the max-tokens branch (a content-less, usage-less
step records no trace-only row), with a covering test.
2026-06-21 11:08:10 +08:00
Tianyi Cui d6a2ab30c8 feat(types): brand bash ids + stop brand erosion; extract Branded to dsh-brand
Type-only change (brands are zero-cost casts; no runtime/wire impact). Closes
the two gaps in the "brand ids that cross package boundaries" policy and fixes
the dependency direction so a capability package never pulls in an unrelated one.

- Extract the `Branded<B>` primitive into a new standalone type-only package
  `@deepseek-ai/dsh-brand` (packages/util/brand) with no harness-package deps.
  dsh-llm keeps its owned CallId but imports Branded from dsh-brand; dsh-session,
  dsh-agent, and dsh-bash all import Branded from there. dsh-bash depends on
  dsh-brand ALONE — never on dsh-llm or dsh-session (the architectural fix: a
  generic execution backend must not couple to the LLM or session vocabulary).
- Mint BashTaskId + OwnerToken in dsh-bash and thread them through BashTask.id,
  the get/ownerOf/list/readOutput/kill seam, the bash-local generation site, and
  the dsh-tool-bash validate/access surface. OwnerToken is a DISTINCT brand from
  SessionId so the seam stays decoupled; dsh-tool-bash is the single boundary
  that casts SessionId -> OwnerToken.
- Brand at the SOURCE, not via mid-pipeline casts: agent-loop's Config types
  agents[].id as AgentId and resumeSessionId as SessionId, so the brand enters
  at the config boundary and the inner create()/resume casts disappear (only the
  genuinely-new per-run session-id string is cast).
- Stop brand erosion: propagate CallId/SessionId/AgentId to the registry/store
  Map keys and public params/exports (SessionStore, AgentRegistry + factory
  options, the ACP session-id surface + ToolPresenter CallId map, the
  persistence coordinator, invariants pendingCalls, the pi-ai tool-call maps).
- Docs: document BashTaskId/OwnerToken in bash.md (type-equiv re-pasted), point
  the Branded type-equiv at dsh-brand, fix stale param types in the session/
  agent/bash READMEs, regenerate the cordis catalog + module graph.

Implements docs/rfc/proposed/architecture/2026-06-20-branded-ids.md
2026-06-21 07:19:59 +08:00
Tianyi Cui 24168aee70 revert bash get()/list() removal — keep persistence-only prune
The original prune removed BashExecutor.get()/.list() too, but each is a
one-line accessor over the executor's already-tracked tasks map, and removing
them forced dsh-tool-bash's tests onto a ~35-line onTaskDone completion-tracking
harness just to replace the one-line ctx.bash.get(id) lookup. Per the AGENTS.md
"RFCs are proposals, not golden truth" principle, that disproportionate
migration cost is evidence the methods earn their keep — a test harness IS a
consumer programming against the seam.

Restore get()/list() (seam + LocalBashExecutor impl + the bash tests that used
them, dropping the doneFor/trackCompletions scaffolding). The persistence
has()/delete()/deleteStored removal stands — it had only contract-test callers
and no test-ergonomics cost. The RFC is retitled persistence-only with an
implementation note recording the bash revert.
2026-06-21 06:17:11 +08:00
Tianyi Cui 6ca8c3b99a fix review findings: stale get/list in proposed RFCs + doneFor double-await
Second Codex pass caught two proposed RFCs that describe the bash seam as it
WAS (with get/list) and would read stale once this prune lands, plus a latent
test-helper edge:
- docs/rfc/proposed/architecture/2026-06-20-branded-ids.md and
  2026-06-20-generic-long-running-tool-runtime.md: drop get/list from the
  BashExecutor seam description (surviving: resolve/run/start/ownerOf/
  readOutput/kill/onTaskDone). branded-ids will be further updated when it is
  implemented; this keeps it accurate in the meantime.
- trackCompletions now records every completion to `done` unconditionally (and
  also wakes a parked waiter), so a second doneFor(id) after completion resolves
  instead of hanging.
2026-06-21 03:00:07 +08:00
Tianyi Cui 5f9d10c587 fix review findings: stale seam docs + race-free doneFor test helper
Codex review of the PR2 diff caught doc/comment sites doc-sync does not gate
(core-data-structures prose) and a latent test-helper race:
- docs/core-data-structures/persistence.md + bash.md, sqlite README, and two
  source comments (coordinator.ts, jsonl.spec.ts) still listed the removed
  has/delete/get/list methods — updated to the surviving four-method
  persistence surface and the get/list-free bash seam.
- doneFor(ctx, id) attached its onTaskDone listener lazily, after the task
  could already have closed (e.g. `true`), so it could miss the completion and
  hang. Replaced with trackCompletions(ctx): one eagerly-installed listener
  (mounted in setup() before any task starts) records every completion, and
  doneFor resolves immediately for an already-finished task or on completion
  otherwise. Race-free, and there is no get-by-id seam left to poll instead.
2026-06-21 02:45:21 +08:00
Tianyi Cui 7792347c4f simplify(seams): prune dead methods from the persistence and bash seams
Two capability seams carried abstract methods no production consumer calls.
A method no consumer programs against is not a seam — it is speculative
surface every implementation must still provide and test.

- SessionPersistence: remove has() and delete(), the coordinator's
  has/delete/deleteCore, and the PersistenceBackend.deleteStored hook (with its
  jsonl + sqlite + in-spec memory-stub impls). Surviving service surface:
  create/append/load/list. Production uses only load() (resume) and list()
  (ACP session/list).
- BashExecutor: remove get(id) and list(), the abstract decls and the
  LocalBashExecutor impls. The internal tasks map survives (it backs
  ownerOf/readOutput/kill); get/list were pure public accessors over it with no
  shipping caller and no bash_list tool.
- Migrate tests that reached through ctx.bash.get(id) to the public completion
  seam: a doneFor(id) helper over onTaskDone awaits a task by id, and the
  HMR-reload ownership test now proves task survival through A's own bash_output
  ([status: running]) plus ownerOf + B-rejection — a stronger through-the-tool
  assertion than the removed lookup peek.
- Update seam READMEs (six -> four service methods, drop the deleteStored hook
  and the get/list row) and the two implemented persistence RFCs in place.

Implements docs/rfc/implemented/simplification/2026-06-20-prune-dead-seam-methods.md
2026-06-21 02:17:27 +08:00
Tianyi Cui 5024cd5757 Document the package hierarchy and finalize the RFC
Add a README to each group dir (core/llm/bash/session-persistence/ui/
support) stating its role and product-vs-support classification, and
rewrite packages/README.md around the hierarchy (group table, grouped
"what goes where", removed the package-hierarchy FIXME).

Move the package-hierarchy RFC to implemented/architecture/ and rewrite
it to describe what shipped (placement rationale, the paths-wildcard and
publint dedup, the two new guardrail gates). Fold the remaining
tsconfig.build.json references dedup into the discover-package-inventory
proposal and fix its cross-link.

Update AGENTS.md: regrouped repo-layout map, depth-2 globs, the new
verify-package-paths gate in the doc-sync listing, and a note that we
lean toward stricter lint in the agentic-coding era (machine-caught
errors and a consistent foundation outweigh the one-time cost).
2026-06-20 23:25:33 +08:00
Tianyi Cui ca2207e26c Fix doc cross-links for the hierarchy; add package-path + shape gates
Merge brought in the RFC-classification reorg and two new doc gates;
rewrite every drifted packages/<name> cross-link (Markdown link targets,
moved-README relative depths, and .ts comment paths) to the grouped paths.

Add two doc-sync/hygiene gates so the manual checks this restructure
needed become automated:
- verify-package-paths.ts: flags a packages/<path> reference (in Markdown
  or a .ts comment/string) that does not resolve AND names a real package
  in a segment — i.e. a stale path to a MOVED package. A path naming a
  non-existent package (a forward-looking proposal) is left alone, so it
  applies uniformly across proposed/implemented/rejected.
- check-workspace-constraints: assert the packages/<group>/<pkg> depth-2
  shape (group dirs carry no package.json; no flat or over-nested
  packages). Group names stay open; only the shape is fixed.
2026-06-20 23:12:14 +08:00
Tianyi Cui d02e9f1bd6 Reorganize packages into a modular hierarchy
Move the 18 flat packages/<name> packages into role-grouped dirs:
core/, llm/, bash/, session-persistence/, ui/, support/. Group dirs are
pure containers; each package keeps its @deepseek-ai/dsh-* name.

Collapse the per-package tsconfig paths maps (base + typecheck) into one
@deepseek-ai/dsh-* wildcard with a candidate per group, and derive the
publint list from the hierarchy. Update all depth-coupled globs/configs
(workspace, tsdown, vitest, eslint, knip, tsconfig includes/refs,
per-package tsconfigs, generators, doc-script scopes, type-equiv manifest)
and the cross-package/script relative imports in tests.

Fix doc-typecheck's workspacePaths() to parse tsconfig JSONC via the
TypeScript API instead of a regex comment-strip, which corrupted the
new wildcard `/*/` path candidates.

WIP: doc cross-links and package/RFC docs still to update.
2026-06-20 22:55:20 +08:00
Tianyi Cui d1b7c3bf95 feat(bash): add an opaque owner token to the executor seam
Background-task ownership needs a stable home that survives a consumer HMR
reload. Add an optional `owner?: string` to `BashExecRequest` and a
required-but-nullable `owner: string | undefined` to the resolved
`BashExecSpec` (mirroring how `workdir`/`timeoutMs` are required on the spec —
a forgotten owner is a visible `undefined`, never a silently-absent property
that yields an unowned, cross-session-readable task). `resolve()` carries it
through.

Expose the stored token via a new `BashExecutor.ownerOf(id): string |
undefined` seam (ONE read path — not also on the public `BashTask`). The
executor stores and returns the token verbatim and NEVER interprets it: the
access POLICY lives in the consumer (`dsh-tool-bash`). `bash-local` stores
`owner` on its `TrackedTask` and implements `ownerOf`; unknown-id and
known-but-ownerless both read as `undefined`. Because ownership lives on the
task in the executor (disposed with the `dsh-bash` fiber), it survives a
`tool-bash` HMR reload.

Updates the StubExecutor seam test and the bash/bash-local READMEs.
2026-06-20 08:12:49 +08:00
Tianyi Cui 7f131dd4d8 refactor: rename build typings dir to types 2026-06-20 00:26:02 +08:00
Tianyi Cui ed94daed9e fix: address build config review findings 2026-06-20 00:21:57 +08:00
imccyu 6b15b606d7 refactor: packages/tsconfig.json in packages use lib/typings/ as output subfolder 2026-06-19 23:35:16 +08:00
imccyu 6f6e0517d4 refactor: ts in packages use extensionless import 2026-06-19 23:35:15 +08:00
Tianyi Cui 49bb6a88eb fix(tool-bash): handle unavailable spill paths 2026-06-19 01:54:57 +08:00
Tianyi Cui 513e16f9dc fix(dev): make hooks and bash seams safer 2026-06-17 21:26:44 +08:00
Tianyi Cui 066f94c7e0 docs: unwrap hard-wrapped Markdown to one line per paragraph
Hard line breaks mid-paragraph make docs harder to edit and diff — a
one-word change reflows and re-diffs the whole paragraph. Reflow all
tracked non-vendor Markdown (plus vendor/AGENTS.md) so each prose
paragraph is a single line; soft-wrapping is the editor's job. Fenced
code, tables, and list structure are preserved (wrapped list items fold
to one line per bullet). Documents the convention in AGENTS.md.
2026-06-13 20:27:04 +08:00
Tianyi Cui 8b5a3ef730 Add bash execution: dsh-bash seam, dsh-bash-local impl, dsh-tool-bash tools
Three packages following the new capability-seam pattern (interface /
implementation / consumer, now documented in docs/architecture.md):

- dsh-bash: abstract BashExecutor service (ctx.bash) + vocabulary types.
- dsh-bash-local: local subprocesses — bash -c per call in a detached
  process group, SIGTERM→SIGKILL group kills, tail-keep truncation with
  full-stream spill files, model-friendly env, background task registry.
- dsh-tool-bash: the bash / bash_output / bash_kill tool schemas with
  runtime arg validation and background completion notices via
  agent.inject(). Non-zero exits are reported, not errored.

Design surveyed against the bash tools of Claude Code, OpenCode, Codex,
and pi (notes in the package READMEs). Permissions/sandbox stay TODO on
the tools/execute waterfall seam; stateful-shell alternatives recorded
in run.ts.
2026-06-13 18:28:10 +08:00