Commit Graph
179 Commits
Author SHA1 Message Date
Yichen Jiang 3ad561862f Merge remote-tracking branch 'origin/master' into codex/rfc-subagent-background-tasks
Adopts #201 (session-prefix composition before pre-step + the pressure
gate). Only the generated RFC index conflicted; regenerated.
2026-07-09 23:17:16 +08:00
Yichen Jiang bd59fddacd refactor(tasks): declare-then-execute — ctx.tasks.start() replaces register()
start({ kind, label, owner, run }) preflights everything that can fail
(the attachSurface fence, validation, the owner-cleanup attach) BEFORE
invoking the producer's run() starter, then commits atomically —
'work started but never got a collectable id' is now structurally
impossible instead of a producer try/catch rollback obligation (the
P1 review fix, rebuilt on #185's declare/execute split). Producers
lose their catch-wraps; the leak tests now pin the stronger property
that a failed preflight never spawns anything. TaskRegistration splits
into TaskStart (identity + run) and TaskHooks (cancel/done/readOutput);
docs, type-equiv manifest, catalogs, and both RFCs move with it.
2026-07-09 21:55:07 +08:00
Yichen Jiang beaace5eb3 Merge remote-tracking branch 'origin/master' into codex/rfc-subagent-background-tasks
Adopts #185 (dsh-timeout: clampTimeout/deadline/timeoutOf drive bash
run() timeout classification; runBash loses its own timer) and #108
(ask_user_question) across the task-runtime rework: bash-local keeps
the BashProcess handle shape with master's deadline mechanics, tool
catalogs/expectations carry both the task_* and ask-user tools, and
generated docs are regenerated on the union.
2026-07-09 21:32:07 +08:00
Yichen Jiang 184e164091 feat(tasks): background task runtime, generic task_* control tools, bash/subagent producers
One shared ctx.tasks registry (branded <kind>-N ids, owner-fenced
read/kill/wait/list, attachSurface misconfiguration fence, reported-flag
notice dedup, atomic register) + dsh-tool-tasks (task_output/task_list/
task_kill, completion-notice injection, background prompt habit).
Producers opt in via their own enableRunInBackground config: bash
(stream kind; seam slimmed to resolve/run/start returning a BashProcess
handle, bash_output/bash_kill deleted) and subagent (final-output kind;
done settles after run.dispose()). Owner disposal drains tasks through
the new awaited ctx.agents.onCleanup seam in the loop's disposal chain.
Both RFCs moved to implemented/; docs, catalogs, snapshots re-pinned.
2026-07-09 21:22:54 +08:00
Yichen Jiang 0df497133c Merge branch 'master' into agent-request-messages 2026-07-09 21:12:31 +08:00
Yichen Jiang 1e06fdbb86 refactor: colocate user interaction with ui packages 2026-07-09 17:59:02 +08:00
Yichen Jiang bdab8c6a61 Merge remote-tracking branch 'origin/master' into codex/ask-user-question
# Conflicts:
#	docs/config-catalog.md
2026-07-09 13:34:13 +08:00
Yichen Jiang e4331ca5e7 Merge branch 'master' into agent-request-messages 2026-07-09 13:30:11 +08:00
Yichen Jiang fd1071392c docs(compact): sync the compactIfNeeded prose signature with the sessionPrefix parameter
The seam gained sessionPrefix between fullSystemPrompt and signal in
18d478bc, but the compact README member table and the compaction
core-data-structures page still showed the 3-arg form and listed only
agent/system/signal as what pre-step supplies. The generated service
catalog was already correct; only these two prose homes drifted.
2026-07-08 22:40:38 +08:00
Yichen Jiang b31399bdc4 Merge remote-tracking branch 'origin/master' into codex/ask-user-question
# Conflicts:
#	docs/module-graph.md
2026-07-08 22:22:25 +08:00
Yichen Jiang b04cfe3a41 Merge remote-tracking branch 'origin/master' into agent-request-messages 2026-07-08 15:54:36 +08:00
Yichen Jiang ea4c10d753 refactor(agent): replace the per-step advice seam with agent/session-prefix
Review discussion converged on the industry shape (Claude Code caches
user context per conversation; Codex separates initial context from
diffs; Kimi appends at continuation boundaries to protect prompt
caching): stable openers belong in a compose-once prefix, mid-session
changes belong in append-only history — not in a per-request slot.

agent/session-prefix fires ONCE per loop instance, lazily on its first
request-building step: the composed Message[] is deep-frozen, cached on
the transmission bookkeeping, recorded as EpochHeader.messagePrefix on
the anchoring 'initial'/'resume' snapshot, and reused verbatim for
every request the instance sends — prefix stability is structural, not
a producer discipline, and a resume recomposes with attributable drift.
The request is messagePrefix + boundary snapshot.

The per-step RequestAdvice/RequestAdviceContext surface and the
messageSuffix header field are dropped: the tail slot had no consumer,
and every current update pattern (new AGENTS.md discovered, memory
update, skills change) routes through the existing append-only history
channels — inject(), tools/post-execute additionalContext,
prompt-submit additionalContext — each paid once and prefix-cached
thereafter. The messagePrefix delta arm stays for codec totality; the
loop never produces one in practice.
2026-07-08 15:44:30 +08:00
Dudu-0223 ef2a150293 Merge remote-tracking branch 'origin/master' into timeout-design 2026-07-08 15:40:56 +08:00
Dudu-0223 395a0b8336 docs(timeout): update RFC + generated catalogs for the declaration split
The RFC's deployment-policy decision is unchanged; state the current
mechanism in place — the per-tool budget is declared on ToolDefinition
(timeoutMs, set by the owning tool plugin from its config) and the
enforcer is zero-config, so a mistyped tool name is impossible.
Regenerate config-catalog (timeout-policy -> no-config; tool-web gains
fetch/searchTimeoutMs), the event graph (tools/change loses its
timeout-policy consumer), the ToolDefinition type-equiv block, and a
source-line drift in the cordis services catalog.
2026-07-08 15:06:02 +08:00
Yichen Jiang d3f86996f7 Merge remote-tracking branch 'origin/master' into codex/ask-user-question
# Conflicts:
#	docs/config-catalog.md
#	examples/acp-agent/tests/snapshots/text-turn/session.jsonl
#	pnpm-lock.yaml
2026-07-08 11:09:20 +08:00
Yichen Jiang 2cbdeb0872 Merge remote-tracking branch 'origin/master' into agent-request-messages
docs/core-data-structures/core.md: combined master's canonical tool-order
wording (#196) with this branch's request-advice envelope + wire-order
paragraphs.
2026-07-08 10:24:35 +08:00
Yichen Jiang e97fffeab7 refactor(agent): rename agent/request-messages to agent/request-advice
tianyicui's review: the seam name did not say what the event or its
types do. 'advice' reads both ways — advisory content for the model,
and AOP before/after advice woven around a join point (here the
derived history) without modifying it — so RequestAdvice.before/after
are self-describing. Types follow: RequestAdvice / RequestAdviceContext;
the logged EpochHeader fields keep their positional names
(messagePrefix/messageSuffix).

Also sharpens the core.md wording the review flagged as ambiguous:
before-advice sits in front of the ENTIRE derived history, directly
after the system slot (the conventional home for session-stable openers
— an AGENTS.md digest, a skills catalog), after-advice follows the
history's last message. Catalogs and doc graphs regenerated.
2026-07-08 10:05:34 +08:00
Tianyi Cui 15a3431913 docs: catalog the code-runtime seam vocabulary (Codex review finding)
Adds the missing core-data-structures coverage the catalog policy
requires for non-spine seam vocabulary: the code-runtime.md sub-page
with drift-checked type-equiv blocks for all six seam types, the core.md
sub-page row, the type-equiv manifest entries, and LINK_MAP entries so
the generated service signature links CodeRunRequest/CodeRunResult;
cordis/config catalogs regenerated.
2026-07-08 02:38:47 +08:00
Tianyi Cui cd55c1d0f5 Merge branch 'master' into structured-output-subagent-seam 2026-07-07 23:50:12 +08:00
Tianyi Cui 0172e3b67d Merge remote-tracking branch 'origin/master' into structured-output-subagent-seam 2026-07-07 22:59:35 +08:00
imccyu 85308526c8 Merge branch 'master' into worktree-node-22-18-compat 2026-07-07 22:46:02 +08:00
Tianyi Cui a1c01cda52 Merge remote-tracking branch 'origin/master' into structured-output-subagent-seam
# Conflicts:
#	docs/config-catalog.md
2026-07-07 21:40:07 +08:00
Tianyi Cui d1b52a063b fix review findings: own-property and plain-JSON discipline in the schema subset
Three Codex findings on json-schema.ts, one discipline:

- required-declared and every value check now use Object.hasOwn — 'in' let
  inherited names (toString) satisfy required, dodge additionalProperties:
  false, and validate a declared property against the value's prototype
  member instead of a carried one
- isObjectLike now means PLAIN JSON object (proto chain of at most one link,
  realm-agnostic): a Date annotation or a Map-as-properties no longer passes
  structurally and serializes lossily — they fail loud as subset violations
- startInProcessRun asserts BEFORE the defensive structuredClone, so a
  hostile schema fails as OutputSchemaError, never a raw DataCloneError

Also the type-equiv catalog gap: tools.md gains the structured-output subset
vocabulary (4 blocks) with matching manifest entries. The driver index also
drops the runtime internals from its public re-export (runs acquire it
internally; no external consumer remains — see the following commit).
2026-07-07 21:07:54 +08:00
Yichen Jiang 17bd71e530 feat(agent): add the agent/request-messages request-only message seam
A new waterfall near request construction lets plugins contribute
request-ONLY messages framing the derived history: RequestMessages
{ before, after } with a frozen empty seed, fired inside the open step
after the agent/request config waterfall, so the step/start boundary
snapshot and its same-sync-frame invariant are untouched. The request
becomes messagePrefix + boundary snapshot + messageSuffix.

Contributions never enter session history — deriveMessages() is
unchanged — so the request header is their durable record:
EpochHeader gains messagePrefix/messageSuffix (canonical absence for
empty arrays), request/header-delta replaces either array whole with
an empty array encoding the transition back to absence, and the
dev-mode reconstruction cross-check now expects the folded header's
framing around the boundary derivation.

This is the seam for per-request advisory context that must be
model-visible now without becoming durable history (a skills catalog,
an environment reminder), keeping the base system prompt
workspace-independent and provider prefix caches stable. The docs
carry the channel cost model: session-frozen content belongs in
before, low-frequency change notices belong in durable history via
inject() (paid once, prefix-cached thereafter), and after is reserved
for small frequently-refreshed state snapshots re-paid on every
request they ride. No shipped producer yet, so ACP snapshot fixtures
are byte-identical.
2026-07-07 19:42:30 +08:00
Yichen Jiang 7065b32e0b Merge branch 'master' into codex/ask-user-question 2026-07-07 19:42:25 +08:00
imccyu 92b5eccc96 build: upgrade to 22.19 for deps 2026-07-07 17:39:04 +08:00
imccyu f33e14ff19 build: lower the Node engines floor to 22.18 2026-07-07 17:15:41 +08:00
Tianyi Cui e930dd328a Merge branch 'master' into worktree-llm-tool-order 2026-07-07 17:01:32 +08:00
Yichen Jiang b8327bc0e8 Merge remote-tracking branch 'origin/master' into codex/ask-user-question
# Conflicts:
#	examples/acp-agent/tests/snapshots/cancel/session.jsonl
#	examples/acp-agent/tests/snapshots/error-finish/session.jsonl
#	examples/acp-agent/tests/snapshots/fs-edit/session.jsonl
#	examples/acp-agent/tests/snapshots/fs-policy-reject/session.jsonl
#	examples/acp-agent/tests/snapshots/fs-read-window/session.jsonl
#	examples/acp-agent/tests/snapshots/fs-read/session.jsonl
#	examples/acp-agent/tests/snapshots/fs-terminal-card/session.jsonl
#	examples/acp-agent/tests/snapshots/fs-write-overwrite/session.jsonl
#	examples/acp-agent/tests/snapshots/fs-write/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-cc-posttool-block/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-cc-posttool-context/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-cc-pretool-deny/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-cc-promptsubmit-context/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-cc-stop-continue/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-codex-posttool-block/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-codex-posttool-context/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-codex-pretool-block/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-codex-promptsubmit-context/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-codex-stop-continue/session.jsonl
#	examples/acp-agent/tests/snapshots/multi-turn/session.jsonl
#	examples/acp-agent/tests/snapshots/subagent-fork/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-fork/session.jsonl
#	examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-mixed/session.jsonl
#	examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-multi/session.jsonl
#	examples/acp-agent/tests/snapshots/subagent-spawn/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-spawn/session.jsonl
#	examples/acp-agent/tests/snapshots/todo-plan/session.jsonl
#	examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl
#	examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl
2026-07-07 15:22:07 +08:00
Yichen Jiang cebf781d69 fix review findings: polish ask-user question 2026-07-07 14:57:06 +08:00
imccyu 42e7a2f691 fix: add tools reorder to system prompt 2026-07-07 11:03:11 +08:00
Tianyi Cui 08ff3e404f Merge remote-tracking branch 'origin/master' into structured-output-subagent-seam
# Conflicts:
#	packages/hooks/hooks-claude/tests/bridge.spec.ts
2026-07-07 09:41:14 +08:00
Hypatia May 4f55c15cf8 Merge remote-tracking branch 'origin/master' into session-fork 2026-07-07 09:06:00 +08:00
Hypatia May c7fba41ba9 Inline session fork parameters 2026-07-07 09:04:49 +08:00
Tianyi Cui 74502fa8c2 Structured output on the subagent seam: schema subset, capture runtime, spawn/fork support
Carved out of #170 per review feedback — the foundation the workflow tool
builds on, now standing alone on master:

- dsh-tools: the structured-output JSON Schema subset (StructuredOutputSchema,
  assertSupportedOutputSchema, validateStructuredValue) — rejects loud outside
  the enforced subset, listing every violation
- dsh-subagent: SubagentStartRequest.outputSchema / SubagentResult.structured
  become a real capability; the service rejects a schema'd request whose
  provider lacks it
- dsh-subagent-inprocess: the shared structured runtime — one global
  structured_output capture tool, a prepend final-assembly listener that
  strips the placeholder for plain agents and swaps in the run's own schema
  (plus the calling instruction as a trailing section) for structured
  children, an agent/turn-continuation veto once captured, and the
  capture/nudge loop in the run driver (structuredNudgeRetries, cancellation
  honored mid-nudge); lifetime refcounted by backends and live runs
- subagent-spawn / subagent-fork flip outputSchema: true

One deliberate divergence from the #170 revision: the backends do NOT add
'tools' to their plugin inject. Doing so deferred their apply past the todo
plugin, and the delegation tool mirrors provider lifecycle — so the
model-visible tool order of every existing prompt changed, invalidating every
recorded snapshot fixture. The runtime now gates its capture-tool registration
on tools availability itself (sync when live, a scoped inject fiber when the
Loader starts the backend first), keeping this PR byte-invisible to existing
transcripts: all 35 snapshot scenarios pass against master's fixtures
unchanged.
2026-07-06 23:29:08 +08:00
Tianyi Cui 116e2c45a8 docs: flatten single-file catalog dirs to docs/tool-catalog.md and docs/persistence-catalog.md
A directory holding exactly one file adds a path level for nothing;
cordis-catalog/ keeps its folder because it holds two sibling pages
(events.md + services.md), matching config-catalog.md which was born flat.

docs/tool-catalog/tools.md -> docs/tool-catalog.md and
docs/persistence-catalog/log-events.md -> docs/persistence-catalog.md; their
generators' OUT paths and in-page relative links drop one directory level,
and every citation repo-wide (docs, RFCs, package READMEs, generator
headers) is updated. graph-atlas.md, config-catalog.md, and the doc graphs
regenerate with the new paths.
2026-07-06 22:26:06 +08:00
Hypatia May aed594813b Merge remote-tracking branch 'origin/master' into session-fork
# Conflicts:
#	docs/architecture.md
#	docs/cordis-catalog/services.md
2026-07-06 14:30:36 +08:00
Yichen Jiang 929e6f21e9 Merge branch 'master' into codex/ask-user-question 2026-07-06 14:22:53 +08:00
Hypatia May 71f71816b9 fix: keep fork boundary check simple 2026-07-06 14:17:31 +08:00
Hypatia May 37aac7f313 fix: collapse session fork to one api 2026-07-06 13:57:59 +08:00
Hypatia May 0bf8749128 fix: fold session fork into session store 2026-07-06 12:35:34 +08:00
Hypatia May cf036299f3 Merge remote-tracking branch 'origin/master' into session-fork
# Conflicts:
#	docs/architecture.md
#	docs/cordis-catalog/events-and-services.md
#	docs/core-data-structures/core.md
#	docs/module-graph.md
#	docs/rfc/README.md
#	packages/README.md
#	tsconfig.base.json
2026-07-06 12:20:00 +08:00
Yichen Jiang 7d7c4a3c16 Merge remote-tracking branch 'origin/master' into codex/ask-user-question
# Conflicts:
#	docs/rfc/README.md
#	packages/ui/acp-agent/src/index.ts
2026-07-06 10:08:58 +08:00
Tianyi Cui c0808d5126 docs: the governing principle — every LLM request is reconstructable from the session log
The reconstructability RFC is the principle's home: model-visible ⟺
logged in both forms, the mechanism (boundary derivation + header
fold), the enforcement (write-time round-trip guard, the dev
invariant), the corollaries ranked (prefix-cache stability first), the
MiniCode lineage with the provenance arrow inverted, and the
alternatives it beat — including the stateful transmission client
whose three-design archaeology lives in PR #162.

Placements per the one-home-per-fact taxonomy: a standing-order line in
root AGENTS.md (with displacement trims to stay inside the 1,575-word
ceiling), the principle statement in architecture.md § Session Log and
its Turn Flow lines (condensed to the ratcheted 1,630 ceiling), the
request-envelope section in core-data-structures/core.md with the
LlmCallConfig paste, both review-requested FIXMEs
(FIXME(call-config-shape) beside the type, FIXME(catalog-verbs) at the
catalog's drift-gate note), cookbook rows redirected off agent/request
(tool filtering → system-prompt/assemble, plan-mode prompt → sections/
inject()), and the llm/stream JSDoc stating the frozen-request
contract. RFC index and all generated catalogs regenerated.
2026-07-06 03:49:35 +08:00
Tianyi Cui 7539231eca compact: the summary's provenance records its call envelope
compact/summary gains { model, maxTokens? } — the envelope the
summarize call actually used, reported by the backend that made the
call: summarize() now returns { summary, model, maxTokens? } instead of
bare blocks, so an overriding backend (template or remote summarizer)
reports its own envelope honestly and compactRegion logs it. 'Which
model wrote this summary' becomes answerable from the log alone, and
the one-shot summarize request — outside the loop's header-event fold
by design — is reconstructable from log + code (the reconstructability
RFC's scope statement).
2026-07-06 03:21:29 +08:00
Tianyi Cui a4f7e757fa session: cache the derived history — one projection per node, frozen and shared
deriveMessages() no longer re-derives and re-clones the whole surface
per call: each node is projected exactly once, when first seen (O(new
nodes) per access), through the now-public deriveEventMessage — the
per-node pure function external reconstructors and the dev invariant
fold over a log prefix, so no two paths can disagree about a request's
messages. A surface rewrite (replace, invalidate) rebuilds, signalled
by SurfaceManager.replaceGeneration — monotonic, bumped by every folded
replace and by invalidate(), never reset. Callers get a fresh array
snapshot per call over SHARED deep-frozen messages: isolation of the
append-only log moves from per-call cloning to unrepresentability
(mutation throws), which the two isolation tests now pin directly.
2026-07-06 02:51:20 +08:00
Tianyi Cui a7b569850b session: the request header becomes logged state — request/header events + fold/diff/apply
Every conversation request's non-content half (system prompt, tool
schemas, call config — the EpochHeader) is now recorded in the session
log: a 'request/header' full snapshot (reason 'initial' | 'resume' |
'fallback') anchors the fold at conversation birth and process
boundaries, and 'request/header-delta' events (system line-trim,
name-keyed tools delta, whole config) encode mid-run changes. The pure
trio — foldRequestHeader / diffHeader / applyHeaderDelta — reconstructs
the header any request was built under from the log alone; the writer
contract round-trip-verifies every delta with a 'fallback' snapshot
when the encoding cannot express a change (pure tool reordering), so a
well-formed log always folds cleanly. Canonical absence: empty system
and empty tools normalize to absent fields, matching request builds.

Persistence and cordis catalogs regenerated; SessionEventMap paste and
EpochHeader added to the core-data-structures session page.
2026-07-06 02:42:51 +08:00
Tianyi Cui 8510986909 compact: summarize is a direct one-shot llm/stream call, not a loop step
The summarization request no longer dispatches agent/request — that seam
shapes the loop's conversation requests; a hand-built one-shot's
interception surface is llm/stream, like every other direct call. The
model comes from summarizationModel falling back to the agent's own. The
turn/step parameters existed on the compact seam only to feed the
agent/request dispatch and leave compactIfNeeded/compactRegion.

Groundwork for making every conversation request a pure function of the
session log (reconstructability RFC, this branch): the seam split keeps
the loop's request path as the single thing the log must explain.

Ported from worktree-prompt-prefix-stability (PR #162) where it was
review-converged; catalog and producer/consumer graphs regenerated.
2026-07-06 02:16:11 +08:00
Tianyi Cui 3f83a4ee96 review: the persona becomes the system-prompt plugin's deployment config
Review round 2 (tianyicui inline comments):

- dsh-system-prompt itself registers the harness:identity (-100) and
  deployment:persona (0) sections — they must survive a swapped loop
  plugin, so they leave dsh-agent-loop; the persona text is the plugin's
  own validated 'persona' config. The model/cwd variables STAY on the
  loop: runtime facts of the agents it drives.
- AgentOptions.systemPrompt is deleted with all its forwarding plumbing:
  the app configs' systemPrompt keys become 'persona' routed through
  dsh-agent-core (schema = z.intersect of the owners'), the ACP bridge
  and tool-subagent stop carrying persona configuration, and subagent
  children now render the deployment persona like every other agent.
- Example personas drop transport/interface trivia (ACP, CLI) — facts
  irrelevant to the model.
- Root CONTEXT.md removed (not idiomatic); its persona definition was
  wrong under the new ownership anyway.
- Docs, READMEs, the prompt-variables RFC, and generated catalogs
  updated; new loop test pins the assemble-waterfall escape valve
  (an emptied assembly sends NO system field).
2026-07-05 23:23:46 +08:00
Tianyi Cui 2304f7a245 Merge origin/master: adopt the DeepSeek Harness SDK product name
Reconciliations beyond textual conflicts:
- product rename (DeepSeek Code -> DeepSeek Harness SDK) applied to the
  PR-added assertion in system-prompt.spec.ts that master's rename
  commit could not reach
- architecture.md: master's rewrite kept; this PR's prompt-assembly
  semantics re-added in the new doc's voice (Turn Flow footnote +
  service-spine row), within the 1630-word ceiling
- cordis catalog regenerated into master's split events.md/services.md
  (events-and-services.md deleted); module graph and doc graphs
  regenerated to pick up this PR's new events and dependency edges
2026-07-05 20:54:48 +08:00