Files
deepseek-harness/packages/core
Hypatia May b341155652 feat(session): project the inherited-history boundary into the log
A plugin owning a standalone open/close bracket cannot tell a dead marker
from a live one: an unmatched `compact/start` reads identically whether the
previous writer died mid-compaction or a compaction is running now.
`Session.firstLiveSeq` already holds that answer exactly, but only in memory.

Append the log-only `session/inherited` event at that seq from the seeded
constructor — the single waist all six seeded-start paths pass through
(resume, configured startup on a persisted id, `sessions.fork()`, a subagent
fork child, `adopt()`'s live prefix, and a bare seeded `create`). Read it
through the new `isInheritedSeq(events, seq)`.

The constructor placement means persistence needs no changes: the marker is
already in `events` when a backend captures the creation seed, so it rides
the ordinary seed path with no load-time write. It also covers fork, where
the inherited bracket's owner may still be running — the case a
persistence-layer boundary could not reach.

Activity ordering excludes the boundary through `lastActivityTime()`, since
lazy resume makes browsing a pickup and the three call sites would otherwise
float every opened session to the top of a picker or list.
2026-07-30 11:39:26 +08:00
..
2026-07-26 05:06:39 +08:00

core/ — product API spine

English | 中文

The session log, system-prompt assembly, tool registry, agent vocabulary, and concrete loop that form the harness's default control spine. These are product packages — the stable surface plugins and consumers build against.

Package Role ctx key
scope/ Scoped-context registration primitive (scope tags, scope-filtered dispatch) (library — no ctx key)
session/ Event-sourced session log + in-memory store ctx.sessions
system-prompt/ Prompt-section + tool-schema assembly registry ctx.systemPrompt
tools/ Scoped tool registry + pre-policy, guards, around-dispatch, post-policy, and final-result observation ctx.tools
agent/ Agent interface, live registry, process-local initiator scope, agent/* event vocabulary ctx.agents
agent-loop/ Concrete plugin implementing the public Agent contract and owning the loop driver ctx.agentLoop

scope/ is the one non-service package here: a dependency-free library (createScope/scopeOf/scopeTarget) the registries and the loop build per-agent scoping on — it sits below session/ and system-prompt/ in the module graph precisely so they can consume it without a cycle.

agent-loop is the one concrete implementation of the agent seam and lives here because it is the harness's default product loop. It runs each driver inside ctx.agents.withInitiator(). Extension plugins depend on agent, including when they need the initiating Agent, and never on agent-loop directly, so the loop stays swappable.

The default composition that wires this spine into a runnable agent lives in examples/agent-spine-demo: one bundle plugin that loads the control spine plus selected default capabilities (timer + llm + sessions + fallback session titles + system-prompt + tools + agents + invariants + the local skill family + tool-bash + workspace-context + agent-loop) and forwards agent-loop's agents list as its own config. It sits in examples/ — ready-to-run demo/reference bundles — not in core/: core/ ships the swappable spine pieces, while a demo bundle picks one concrete composition of them and adds a front door.