Commit Graph

345 Commits

Author SHA1 Message Date
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
2be60b9a22 simplify(session): fold trace-only usage/error events into load-bearing events
The session event vocabulary carried two standalone trace-only events that
were not load-bearing as separate records. Fold their facts into nearby
load-bearing events and delete the standalone variants.

- Token usage now rides on `assistant/message` as an optional `usage` field —
  the assembled model output and its accounting travel together. The loop folds
  `assembler.usage` onto the append instead of emitting a separate `usage`
  event.
- The max-tokens path is the no-data-loss host: a step cut off with usage but
  EMPTY content (e.g. only a dropped tool call) previously emitted a standalone
  `usage`; it now records an empty-content `assistant/message { content: [],
  usage }`. `deriveMessages()` skips empty-content assistant messages, so the
  usage host never injects a spurious content-less assistant turn into the
  provider transcript. A step with neither content nor usage appends nothing.
- An operational error's step number now rides on `turn/end.reason` for
  `kind: 'error'` (`{ kind: 'error', step, message, code? }`) — the durable
  turn outcome ACP and resume already consume. `failTurn` sets the reason
  directly (no separate session `error` event). `agent/error` + logging are
  unchanged for live diagnostics.
- No format-version bump: pre-release, no persisted data, so per the format
  policy there is nothing to migrate or reject (the RFC's "refresh the format
  version" criterion over-reached). `version` stays 1.
- ACP fixtures + goldens re-recorded (keyless replay): dropped standalone
  usage/error lines, usage folded onto assistant/message, error step on
  turn/end.reason.

RFC moved proposed -> implemented with an implementation note recording the two
scope refinements.
2026-06-21 10:00:06 +08:00
Tianyi Cui
c6ed980d6f fix review findings: stale abort() docs + move RFC to implemented
Codex's no-ship was a completeness/docs-sync gap, not loop behavior:

- docs/architecture.md: drop the public abort() handle row; the teardown
  signal is now cancel() then await whenIdle().
- cancel.spec.ts: the module doc and the turn-start comment contrasted
  cancel() against a public abort() verb that no longer exists — reword to
  name the loop's private step AbortController.
- packages/ui/acp/src/index.ts: the post-resume-leak comment cited abort();
  cancel() is the surviving stop verb that likewise does not unregister.
- Move the RFC proposed -> implemented/simplification with amended text:
  Status flips, the both-removal proposal is narrowed to abort-only, and an
  implementation note records why whenIdle() is retained (load-bearing
  quiescence primitive with live ACP consumers). Update docs/rfc/README.md.
- AGENTS.md "RFCs are proposals, not golden truth": add the concrete
  abort/whenIdle worked example now that the implemented RFC exists to link.
- Regenerate the cordis catalog (line-number drift from the rebase).
2026-06-21 09:10:56 +08:00
Tianyi Cui
f6bd1468f2 simplify(agent): drop the unused public Agent.abort(), keep whenIdle()
The public Agent handle exposed abort() (step-only) and cancel() (queue-aware).
No production caller used abort() — ACP maps session/cancel to cancel(), and
lifecycle owners tear down via AgentHandle.dispose(); the loop's own stop paths
abort their per-step AbortController directly. So abort() is latent generality
that keeps a private loop mechanic public.

RFC-premise correction: the public-agent-stop-surface RFC proposed removing
whenIdle() too. Implementation found whenIdle() load-bearing — a real
quiescence primitive with a deliberate loop contract (settle-without-transition,
the replacement-turn race) and ACP test consumers; its proposed replacement
("observe the running->idle transition") is exactly the async-state race
AGENTS.md warns against. So only abort() is removed; whenIdle() stays. The RFC
is amended on the way to implemented/ to record the narrowed scope, and the new
AGENTS.md "RFCs are proposals, not golden truth" principle (PR1) gets its
worked example.

- Remove Agent.abort() from the interface + the ReactLoopAgent impl; the no-arg
  'aborted' default goes with it (cancel() keeps its 'cancelled' default).
- Migrate tests: empty-queue abort() -> cancel(reason); the two review-fixes
  tests whose subject is the in-flight step's AbortController drive that
  controller directly via the private currentAbort field (cancel() would clear
  the inbox and destroy the queued steering one of them proves survives a step
  abort). The no-arg-default test is dropped (cancel()'s default is already
  covered in cancel.spec.ts).
- Resulting public stop surface: cancel() + whenIdle(). Update agent/agent-loop
  READMEs, architecture.md, core.md type-equiv, the extension cookbook, the
  lifecycle RFC (short note), and the proposed ACP RFC.

Implements docs/rfc/implemented/simplification/2026-06-20-public-agent-stop-surface.md
2026-06-21 09:05:21 +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
584349f881 fix review findings: stale service prose + catalog cleanup
Codex review of the PR1 diff surfaced docs/cleanup drift:
- LlmService class JSDoc still advertised "streaming / non-streaming call
  surfaces, both interceptable via waterfall events" — corrected to the single
  streaming surface; regenerated the cordis catalog so its mirror updates.
- Removed GenerateResult from gen-cordis-catalog.ts LINK_MAP (the type is gone).
- The adapter-change RFC's acceptance criterion named the retired
  verify-event-taxonomy gate; updated to verify-cordis-catalog.
- Dropped the now-tautological "streaming and one-shot assembly agree" property
  test (the streaming/one-shot distinction lived in the removed flush API;
  usage/finish remain covered by assembler.spec.ts and the finish property).
2026-06-21 01:41:02 +08:00
Tianyi Cui
30cd67b8a1 simplify(llm): drop unconsumed adapter-change event and assembled call surfaces
The LLM service exposed three call surfaces (stream/streamBlocks/generate) but
the only production consumer — the agent loop — uses stream() exclusively,
feeding raw chunks through its own BlockAssembler for replay fidelity. Drop the
speculative convenience surfaces and the registry-change event that no listener
consumed, leaving stream() as the single model-call contract for both
production and tests.

- Remove LlmService.streamBlocks() and generate(), the llm/generate waterfall,
  and GenerateResult.
- Remove the llm/adapter-change event (declaration + emits) and the
  listener-throw rollback ordering that existed only to protect it; keep the
  HMR rollback disposer.
- Remove BlockAssembler.flushReady()/flushRemaining()/result() and the flushed
  cursor — the streaming-flush slice existed only for streamBlocks().
- Adapter tests drive a stream()+BlockAssembler helper (tests/assemble.ts)
  instead of generate(), exercising the same path production uses.
- Land the AGENTS.md "RFCs are proposals, not golden truth" principle and move
  both RFCs proposed -> implemented.

Implements:
- docs/rfc/implemented/simplification/2026-06-20-drop-unconsumed-llm-adapter-change-event.md
- docs/rfc/implemented/simplification/2026-06-20-drop-unconsumed-llm-assembled-surfaces.md
2026-06-21 01:27:41 +08:00
Tianyi Cui
18f1c010ca Merge pull request #79 from deepseek-ai/worktree-package-hierarchy
Reorganize packages into a modular hierarchy
2026-06-21 00:12:07 +08:00
Tianyi Cui
e42493b7a7 Fix package-path drift in master's new RFCs after merge
The merge brought in two new proposed/architecture RFCs that reference
the old flat packages/<name> paths and the package-hierarchy RFC's old
proposed/ location. Rewrite their package paths to the grouped layout and
repoint the cross-link to implemented/architecture/ — the verify-package-paths
and verify-md-links gates caught both.
2026-06-21 00:08:45 +08:00
Tianyi Cui
d1eb0877ab Merge remote-tracking branch 'origin/master' into worktree-package-hierarchy
# Conflicts:
#	docs/rfc/README.md
2026-06-21 00:02:36 +08:00
Tianyi Cui
184066e745 Tighten implemented RFC after self-review
Self-audited every factual claim against the shipped branch (hierarchy
tree, no group manifests, the dsh-* paths wildcard in both tsconfigs,
publint glob, explicit build references, the two new gates). Phrase the
paths-wildcard bullet as current state, and record the doc-typecheck
JSONC-parse subtlety the wildcard introduced so a future editor does not
reintroduce the regex comment-strip bug.
2026-06-21 00:00:38 +08:00
Tianyi Cui
eb16025d59 Merge pull request #78 from deepseek-ai/worktree-rfc-extract-example-app-packages
docs(rfc): propose extracting example apps into packages
2026-06-20 23:43:53 +08:00
Tianyi Cui
94a762658f docs(rfc): reject the superseded providerless-example-base RFC
git mv it from proposed/ to rejected/architecture/ (preserving history)
and fold the supersede note into a one-line rejected Status. The
extract-example-app-packages RFC subsumes it: once the spine moves into
dsh-agent-core and the base*.yml files are deleted, there is no shared
base YAML left to rename. Move its README row to Rejected -> Architecture
and repoint the supersede cross-link to the new path.
2026-06-20 23:37:41 +08:00
Tianyi Cui
21a28079d0 Merge remote-tracking branch 'origin/master' into worktree-rfc-extract-example-app-packages
# Conflicts:
#	docs/rfc/README.md
2026-06-20 23:28:58 +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
d9c9c5d403 docs(rfc): sharpen agent-loop, timer, and leaf-config accuracy
Self-review against the actual source surfaced three imprecisions:

- agent-loop placement: the core bundle forwards agent-loop's `agents`
  list as its own config (default []), matching AgentLoop.Config, rather
  than hardcoding []. This is what lets a shared core coexist with stdio
  pre-creating `main` and acp pre-creating none — and it directly rebuts
  the reason base-core.yml gives today for keeping the loop out of core.
- timer is universal and stdout-safe, so it lives in the shared spine,
  not the per-app front-door cluster (only logger + hmr are app-specific).
- model/systemPrompt land in different places per app (stdio onto the
  pre-created agent, acp onto the bridge plugin), routed by the app
  package's own Config — not a single uniform bundle entry.
2026-06-20 23:25:11 +08:00
Tianyi Cui
cf8007c070 Merge pull request #77 from deepseek-ai/worktree-branded-ids-rfc
docs(rfc): propose branded IDs everywhere they belong
2026-06-20 23:16:57 +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
bf3cfe84c3 docs(rfc): fix Codex review findings on branded-IDs RFC
- Correct the SessionStore signature: `get(id: string)` is non-optional,
  not `get(id?: string)` (only create/prepare take an optional id).
- Broaden the ACP brand-erosion description and the acceptance criterion
  beyond `Map<string>`: the session-id surface also includes the
  `bySession` WeakMap, the `loadingIds` Set, and the exported
  `streamSessionEventUpdate(sessionId)` signature.
- Use bare inline code spans for code paths instead of markdown links,
  matching the house style of the other architecture RFCs and removing the
  link/bare-span inconsistency within this file (doc-to-doc cross-links
  stay markdown links per docs/AGENTS.md).
2026-06-20 23:11:02 +08:00
Tianyi Cui
034779d761 docs(rfc): propose extracting example apps into packages
Add a proposed architecture RFC to make the examples folder thin: each
example becomes mostly an invocation of an app package. A shared
dsh-agent-core bundle owns the providerless spine; dsh-stdio-agent and
dsh-acp-agent app packages bake in their coupled front-door cluster
(UI + logger/hmr policy + agent pre-creation), turning the ACP
stdout-purity footgun into a property of the artifact. Leaf cordis.yml
shrinks to backends + config; start.ts is dropped in favor of a package
bin.

Supersedes the providerless-example-base RFC (cross-linked) and indexes
the new RFC under Proposed -> Architecture.
2026-06-20 23:05:31 +08:00
Tianyi Cui
08f6f17cc1 Merge remote-tracking branch 'origin/master' into worktree-package-hierarchy 2026-06-20 22:55:38 +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
ae5a908a21 docs(rfc): propose branded IDs everywhere they belong
Extend the existing Branded<B> machinery (CallId/SessionId/AgentId) to the
unbranded cross-boundary IDs that meet the brand.ts policy bar — chiefly the
model-facing bash task id (BashTask.id, the `bash-N` counter that shares
SessionId's `name-N` shape) and a distinct OwnerToken brand for the bash
owner token — and fix the brand erosion where existing brands decay back to
`string` at Map keys and method params.

Scoped focused per the "not every string needs a brand" policy: ModelId,
ToolName, numeric ordinals, and validated construction are listed as
deferred extensions, not in-scope work. Filed under proposed/architecture.
2026-06-20 22:46:59 +08:00
Tianyi Cui
b2d4e0a81c Merge pull request #76 from deepseek-ai/rfc-classification
Classify RFCs by kind via path-encoded subdirectories
2026-06-20 22:43:14 +08:00
Tianyi Cui
8c16524b90 chore(knip): drop dead entry pattern and fail on config hints
examples/acp-agent has no src/ directory — its plugins come from real
packages wired via cordis.yml, and its only local entry (start.ts) is
already auto-discovered. The examples/acp-agent/src/*.ts entry pattern
matched nothing, which knip surfaced as a config hint that exited 0 and
so went unnoticed.

Remove the dead pattern, and pass --treat-config-hints-as-errors so a
future stale entry (a renamed/removed path) fails the hygiene gate
instead of degrading to a silent hint.
2026-06-20 22:33:27 +08:00
Tianyi Cui
605587e79c docs(rfc): classify RFCs by kind via path-encoded subdirectories
Add a second axis to every RFC — its class (feature, bug-fix,
simplification, architecture, process, testing) — encoded in the path
as docs/rfc/{lifecycle}/{class}/file.md. The folder is the label, so
the closed set is enforced by structure rather than a parsed field.

Two new doc-sync gates back it:
- verify-rfc-classification: every RFC sits in a valid class folder and
  the README index lists it under the matching lifecycle→class heading.
- verify-doc-refs: every docs/*.md path cited in a packages|examples TS
  comment resolves — closes a drift class verify-md-links can't see, and
  catches the four comment refs this reorg moved.

The README gains a Classification section explaining the taxonomy and
per-class index sub-sections. A self-referential process RFC records why
the scheme is path-encoded and gated.
2026-06-20 22:29:45 +08:00
Tianyi Cui
906705e353 Merge pull request #72 from deepseek-ai/codex/rfc-simplify-candidates
docs: propose simplification RFCs
2026-06-20 21:45:52 +08:00
Tianyi Cui
f593f33dea Merge remote-tracking branch 'origin/master' into codex/rfc-simplify-candidates 2026-06-20 21:42:01 +08:00
Tianyi Cui
f995d147c4 Merge pull request #75 from deepseek-ai/cordis-catalog
docs: generated cordis events + services catalog
2026-06-20 21:40:17 +08:00
Tianyi Cui
c079b74c78 docs: clarify package hierarchy example 2026-06-20 21:36:49 +08:00
Tianyi Cui
d614f3aabf docs(rfc): record the core-data-structures catalog + type-equiv decision
PR #71 shipped the core-data-structures catalog and the verify-type-equiv
drift gate without an RFC (judged small at the time). Add the retroactive
implemented RFC so the sibling pair is documented symmetrically: the
spine-vs-seam scoping rule (discovered by testing candidate definitions against
borderline types like BashExecRequest and ToolDefinition), the
verbatim-match-over-assignability choice for the gate, and the process —
including the Codex-caught scan-gap bug fixed in 6da7a0f. Cross-link the two
catalog RFCs to each other and index the new one.
2026-06-20 21:34:04 +08:00
Tianyi Cui
800e08e930 docs: refine package hierarchy RFC 2026-06-20 21:28:02 +08:00
Tianyi Cui
7f2769c529 docs: address latest simplification review 2026-06-20 21:07:25 +08:00
Tianyi Cui
80179a5ed0 docs: address simplification review feedback 2026-06-20 20:34:56 +08:00
Tianyi Cui
99a203f445 docs: add simplification discovery skill 2026-06-20 20:09:26 +08:00
Tianyi Cui
d324b06e74 docs: fix Codex review findings on the cordis catalog
- Exclude protected methods from the generated service interface: a protected
  member (e.g. BashExecutor.notifyTaskDone) is a subclass hook, not part of the
  public ctx.<key> surface a plugin author calls. The method filter now drops
  private, protected, and static.
- Add BashTaskRead to the type cross-link map so readOutput()'s return type
  links to its core-data-structures page.
- Reword the generator module comment and the AGENTS.md @mode rule to state the
  current capability without narrating the retired event-taxonomy verifier
  (that history lives in the RFC).
2026-06-20 20:04:39 +08:00
Tianyi Cui
4e5c08ef82 docs: generated cordis events + services catalog
Add scripts/gen-cordis-catalog.ts: a fully-generated docs/cordis-catalog/
events-and-services.md cataloging every cordis event (exact signature + @mode)
and ctx.<key> service (exact interface), modeled on gen-module-graph's
--write/--check freshness gate. The harness tier renders in full from the
interface Events / interface Context declarations and their JSDoc; the inherited
cordis-core/loader/hmr/timer surface renders tersely from a curated table.

The generator hard-errors on a missing @mode tag and on a tag that contradicts
a conclusive signature shape (a trailing next param is structurally a
waterfall). Signature blocks use a ts cordis-catalog fence that doc-typecheck
skips. Type tokens cross-link to the core-data-structures catalog.

This supersedes the hand-maintained event-taxonomy table: verify-event-taxonomy
is deleted and verify-cordis-catalog joins doc-sync. architecture.md keeps the
Event taxonomy heading (TOC anchor) but points at the catalog; the Service-map
role table stays. RFC, AGENTS.md @mode authoring rule, and dependent doc/skill
references updated. Negative gate tests cover the missing-tag and
tag/shape-contradiction paths.
2026-06-20 19:47:09 +08:00
Tianyi Cui
552612622c docs: fold useful simplification RFCs from pr 74 2026-06-20 19:23:05 +08:00
Tianyi Cui
ee494969af docs: add @mode tags + enrich JSDoc on harness event declarations
Annotate all 24 harness events across the 5 event-declaring packages with
an explicit `@mode emit|waterfall|parallel` tag and self-contained JSDoc, so
the generated cordis catalog can render each entry's mode and prose from
source alone.
2026-06-20 19:21:42 +08:00
Tianyi Cui
9949f4f2ea Merge pull request #73 from deepseek-ai/worktree-acp-feature-checklist
docs: ACP feature support checklist
2026-06-20 18:14:08 +08:00
Tianyi Cui
0e73a45dc9 Merge remote-tracking branch 'origin/master' into worktree-acp-feature-checklist
# Conflicts:
#	AGENTS.md
2026-06-20 18:12:55 +08:00
Tianyi Cui
f5e61417ee docs: move ACP checklist into packages/acp
Co-locate the ACP feature support checklist with the bridge package
(packages/acp/acp-feature-support.md) and rewrite its relative links for
the new depth. Broaden the doc-sync globs (doc-typecheck, verify-md-wrap,
verify-md-links) from packages/*/README.md to packages/*/*.md so a
package-level doc beyond the README stays under the drift gates, and
update the AGENTS.md prose describing that scope.
2026-06-20 18:08:17 +08:00
Tianyi Cui
bcf255fc57 docs: fix review findings in ACP checklist
- session/close: ⚠️ (no handler; SDK dispatch returns method_not_found —
  disconnect/disposal teardown is not the per-session method)
- Codex plan: ⚠️ (CodexEventHandler.updatePlan emits the stable `plan`
  update; the plan-as-text note was stale)
- Codex elicitation: ⚠️ (maps onto session/request_permission; does not
  call elicitation/create|complete)
- Overview: qualify the "both adapters ship" clause — neither drives the
  client terminal/* family and only Claude uses fs/*
- Remove a stray </content> sentinel that rendered literally at EOF
2026-06-20 17:50:58 +08:00
Tianyi Cui
2d6bb4c8ce Merge pull request #71 from deepseek-ai/worktree-core-data-structures-doc
docs: core data structures catalog + verify-type-equiv gate
2026-06-20 17:36:20 +08:00
Tianyi Cui
5a6243900d fix(doc-sync): close verify-type-equiv scan gap; correct persistence prose
Review found verify-type-equiv only scanned docs the manifest already named, so
a type-equiv block in an unmanifested doc was silently skipped — defeating the
1:1 guarantee. Scan all docs in the markdown glob scope instead, so an orphan
block in any doc is caught. Also parse `abstract class` in blockSymbol (matches
sourceDeclaration's class support).

persistence.md listed the SessionPersistence surface as create/append/load/list;
the abstract service also exposes has/delete. AGENTS.md's doc-sync command
summary omitted verify-md-links and verify-type-equiv.
2026-06-20 17:29:42 +08:00
Tianyi Cui
ea3f138ae9 docs: address simplification RFC review 2026-06-20 17:26:23 +08:00