Commit Graph
6272 Commits
Author SHA1 Message Date
Tianyi Cui be23e5b2ac Merge latest master into subagent policy inheritance 2026-07-29 00:40:25 +08:00
Tianyi Cui 739647afc0 fix(subagent): publish inherited policy facts to telemetry
Inherited sandbox and approval events were part of the constructor seed. Session.firstLiveSeq classifies every constructor event as replayed history, so telemetry adoption skipped these child-only creation facts even though no parent or prior process had exported them.

Capture the parent overrides at the same synchronous delegation boundary, but append the events during the child factory setup while the session is still unpublished. They remain ordered after fork history, persist with the first child batch, and retain last-event-wins behavior while landing on the live side of the telemetry boundary. This uses the existing setup and session append contracts instead of adding another seed category or telemetry special case.

Add regression coverage for exporting an unpublished suffix without re-exporting constructor history, assert the spawn and fork firstLiveSeq boundaries, and restore the public seed documentation to replay/fork history only.
2026-07-29 00:39:56 +08:00
Tianyi Cui d533e225ad Merge pull request #852 from deepseek-harness/worktree-fe-docs
Client test runtime: outward service interfaces + single-slot DOM snapshots
2026-07-29 00:29:50 +08:00
imccyu 9d9cdd640e style(test-runtime): drop a trailing space 2026-07-29 00:09:40 +08:00
Tianyi Cui 48518ea850 Merge branch 'master' into worktree-fe-docs 2026-07-29 00:00:38 +08:00
Tianyi Cui ce63309515 Merge pull request #854 from deepseek-harness/worktree-devfast
feat(cli): launch source with native TypeScript
2026-07-29 00:00:30 +08:00
imccyu 3e6a7fea43 test(ui-sidebar): pin the shell chrome with local DOM snapshots
First consumer of the runtime's single-slot mounting: the real apply mounts
on its own fiber, renderSlot('sidebar', ...) captures exactly the sidebar
slot's output, and update() re-renders the collapsed rail in place. The
.snap files carry semantic class names and svg fingerprints only.
2026-07-28 23:54:14 +08:00
imccyu a3f9a4d3ee test(client): migrate the ui-conversation and web benches onto SlotTestRuntime
The five ui-conversation machinery specs (apply-inject, chat-apply,
chat-toolview-slot, service-orchestration, selection-survival — now .tsx)
and the web app/app-shell specs assemble through the runtime instead of
hand-built Context + SlotsService + fake-session scaffolding per suite.
Session behavior mocks are typed against ISession, so incomplete fakes
fail at compile time.
2026-07-28 23:54:14 +08:00
imccyu 3f7a8c6f8e feat(client): add the dsh-client-test-runtime package
A jsdom slot test runtime for feature specs: a real Cordis Context, the
production SlotsService and web-react renderer, and typed session/workspace
doubles (TestSessions implements ISessions with FixtureSession sessions;
TestWorkspaces implements IWorkspaces), so the compiler flags fixture drift
when a production face changes. Fixtures feed plain data: list rows,
conversation snapshots, and ISession-typed behavior stubs; provide-bundle
materialization runs the shared SessionProvideChannel.

DOM snapshot support: declare()/renderSlot() mount a single slot inside a
data-slot wrapper for local .snap capture, and a snapshot serializer folds
CSS-module class hashes to their semantic locals and collapses svg internals
to a content fingerprint. The typed provide() constrains declared-service
fakes to Partial of the service's outward face.
2026-07-28 23:54:13 +08:00
Tianyi Cui 064205b54d Merge pull request #845 from deepseek-harness/worktree/pr623-policy-inheritance-simplify-20260728
subagent: simplify policy inheritance to seeded events
2026-07-28 23:44:01 +08:00
imccyu 0efc7f045e refactor(client): carve outward interfaces for the session, workspace, layout, slash, and conversation services
Feature packages now reach these domains through interface types only:
ISession/SessionFace (identity + prompt/cancel/loadOlder + the useSession
snapshot source), ISessions, IWorkspaces, ILayout, IConversation, and the
existing SlashServiceContract now actually mounted on Context.slash. The
concrete services implement their face; wire-pump and assembly entry
points stay on the classes. The provide-channel materialization and
current-projection logic moves into SessionProvideChannel so the
production service and the client test runtime share one implementation.
The workspaces service consumes sessions through the narrow SessionsPort.
2026-07-28 23:43:32 +08:00
imccyu 431c2180c1 fix(cli): harden native source resolution 2026-07-28 23:42:54 +08:00
imccyu b6b4a66da0 pkg: add build:lib script 2026-07-28 23:31:28 +08:00
imccyu e5218217c3 chore: raise lint heap limit 2026-07-28 23:20:18 +08:00
imccyu c804dfde3e docs: document native TypeScript source launch 2026-07-28 23:13:28 +08:00
imccyu db3b12a0f7 feat: launch dsh source with native TypeScript 2026-07-28 23:06:27 +08:00
imccyu 5ea161fa68 vendor: support native TypeScript source loading 2026-07-28 23:06:10 +08:00
Tianyi Cui eb38a365dc Merge pull request #791 from deepseek-harness/worktree-projcache
feat: persisted projection cache — durable checkpoints, tail reads, and cold listing columns
2026-07-28 22:55:30 +08:00
imccyu b4bc4f382e refactor(session-projection): compact checkpoint row fields to ver/seq/val
The persisted row (sessionId, key, stateVersion, observedSeq, state)
becomes (sessionId, key, ver, seq, val) — the cache medium repeats these
three names for every unit of every session, so the long forms dominated
the JSON payload. ProjectionCheckpointRow and the checkpointRow zod spec
rename together; the domain spec bumps to v3 (cache semantics: the old
medium is discarded, not migrated). The unit-facing declaration keeps
stateVersion — only the persisted/checkpoint row shape changes.
2026-07-28 22:45:35 +08:00
imccyu 931dd934e3 style: clear the lint lane — drop redundant assertions and non-thenable awaits
eslint --fix removed the no-unnecessary-type-assertion hits the review
knives introduced; the two await-thenable errors were vi.runAllTicks()
awaits in the cache spec, replaced with advanceTimersByTimeAsync(0) (the
fake-timer-safe microtask drain). Repo-wide eslint, dual-aggregate tsc,
and the focused 100% coverage set all green.
2026-07-28 22:26:12 +08:00
imccyu 019dd7d894 test,chore: clear the static and coverage lanes for the cache stack
Static: the cache package.json files array matches the workspace
constraint shape, the unused dsh-storage-json devDependency is dropped
(tests run on the memory backend), and docs/module-graph.md is
regenerated for the new package edge.

Coverage: two unreachable branches deleted rather than tested —
coldSnapshot's floor-0 tail reuse (a baseSeq-0 restore never throws and
an unrelated record still carries a usable watermark) and flushSoft's
non-mandatory clean-skip (throttle triggers only fire dirty). New tests
close the real gaps: write() on a never-dirty session and the non-JSON
unit-state rejection, plugin disposal clearing armed interval timers,
cachedSnapshot's all-version-mismatched and cwd-identity arms, the
zero-units empty-log cut, the coordinator seek-hook ladder (suffix /
not-found / plain failure / abort-reason relay), and the superseded-
retirement race proving forget()'s exact-entry guard.
2026-07-28 22:26:12 +08:00
imccyu ee79b7a73a docs: regenerate the cordis catalogs for the reshaped cache read faces
cachedSnapshot/coldSnapshot signature and JSDoc changes from the review
fixes flow into the generated service catalog and model-facing api-catalog.
2026-07-28 22:26:11 +08:00
imccyu c46419cf5c fix(apiproxy,client): the list projection column becomes a seedable watermarked block
Review finding (PR #791): the column carried bare values (no seq), so the
client could not seed its value store without risking a stale list block
outranking newer push frames — and nothing consumed the column at all,
leaving cold titles absent after a restart. SessionSummary.projections is
now the same SessionProjectionsBlock as the history tail (values +
asOfSeq; attached rows cut the live registry, cold rows serve the cache's
identity-checked cachedSnapshot whose asOfSeq is the lowest served-row
watermark). SessionManager.refreshList seeds each row's block into the
per-session projection store via per-key apply — partial-baseline
semantics: an absent key never clears, and higher-seq-wins keeps stale
list blocks beneath push frames and tail baselines — so cold titles
surface in the sidebar without opening a session.
2026-07-28 22:26:11 +08:00
imccyu 27198d3091 fix(session-projection-cache): bind records to the log lifecycle; flush before checkpoint
Review finding (PR #791): rows carried only version/watermark/state, so a
recreated session id, or a persistence store replaced under a surviving
cache, could pass every watermark check and seed state folded from an
unrelated log; a checkpoint racing ahead of an eager log flush could
likewise expose values no stored log contains. Records now store the
header identity (createdAt, cwd) they were folded from — reads validate it
against the live header (listing) or the tail's stored header (cold read)
and discard unrelated records whole (domain version 2 discards v1 media by
the pre-release stance). A live checkpoint additionally flushes the
session's buffered events durably before the cache row lands: the cache
can trail the log, never lead it. cachedValues is reshaped into
cachedSnapshot(meta): the identity witness plus the {asOfSeq, values} cut
the list carrier serves.
2026-07-28 22:26:10 +08:00
imccyu 1ef7c9473c fix(session-projection-cache): coldSnapshot honors not-found with zero registered units
Review finding (PR #791): with no projection definitions registered,
restoreFloor() is undefined and the fast path returned a successful empty
snapshot without touching persistence — a nonexistent session 'succeeded',
violating the documented not-found contract in that supported topology.
The no-unit branch now probes readFrom(id, 0): an absent log rejects with
the seam's not-found, a present one dates the empty cut at its stored end.
2026-07-28 22:26:10 +08:00
imccyu 54c893d7af docs: RFC — storage root placement and derived-medium recovery
The projection cache surfaced two substrate gaps, both properties of the
domain-KV stack it landed on. (1) The json backend's root is relative and
joined per-open against process.cwd(): sessions are patched global
(~/.dsh/sessions) but workspace.json/session_projcache.json land under
<launch dir>/.storages, splitting derived media from their source of
truth. Proposal: patch storage-json.root to ~/.dsh/storages beside the
session root (profile key storageRoot, mirroring persistenceRoot) and
resolve-once at backend construction, adopting the JSONL backend's
recorded rationale. (2) A damaged cache medium (truncated / version-bumped
/ schema-drifted) bricks fail-loud boot even though its content is fully
rebuildable from session logs. Proposal: DomainSpec grows
recovery: 'reject' | 'reset'; the facility, on exactly the damage-class
errors, destroys a declared-reset medium once and reopens empty —
workspace stays authoritative and loud. Bilingual pair recorded.
2026-07-28 22:26:10 +08:00
imccyu 9ae3e1a9ad docs: regenerate catalogs and graphs for the projection-cache seam; classify its types
gen-cordis-catalog/api, config and persistence catalogs, and doc graphs
regenerated over the new sessionProjectionCache service and the registry's
checkpoint faces. Classifications: ProjectionCheckpoint joins the type-link
exemptions (owned by the projection package source), Partial joins the
foundation names, the cache service gets its capability-seam role row, and
the package takes the one-sentence Model Experience contract (host-side
read-model accelerator, no model surface).
2026-07-28 22:26:09 +08:00
imccyu c0eec9d9e2 docs: bilingual counterparts for the projection-cache README and the touched pair records
The base's bilingual gate now covers this branch's new README: add the
Chinese counterpart of the session-projection-cache package README, the
cache row on the group README's Chinese side, and re-record the touched
pairs (group, cache, session-persistence — whose English side gained the
readFrom rows earlier on this branch). verify-translation-pairing: 541
pairs consistent.
2026-07-28 22:26:07 +08:00
imccyu a6e35c27d4 fix(session-projection): checkpoint hands out detached state clones, never live cell references
The watermark cache is the registry's authoritative mutable state; a
checkpoint consumer holding the live reference could corrupt every
subsequent snapshot and frame through it. structuredClone at the read face
(total, by the unit plain-JSON contract) pins the boundary; a mutation test
proves the cache is unreachable through handed-out rows. restore and
viewCheckpoint only touch caller-owned rows — no other leak path.
2026-07-28 22:25:29 +08:00
imccyu 003b22a157 feat(apiproxy): projection column on session.list — cold titles with zero log loads
SessionSummary grows an optional projections column (whole value per key,
same passthrough posture as the history-tail block): attached rows cut the
live registry watermark cache; cold rows view the persisted projection
cache's stored rows via the new registry viewCheckpoint face (version-
matching keys only, zero I/O) — the RFC's motivating scenario, every
session's title across a listing without loading one event log. The column
is fail-soft and absence-coded: no registry, no cache row, or a throwing
read serve the row without the column, never breaking the listing.
2026-07-28 22:25:29 +08:00
imccyu c330c1cd3e feat: dsh-session-projection-cache — durable projection checkpoints and the cold-read ladder
New package on the domain data form: one session_projcache record per
session (key → {stateVersion, observedSeq, state}), landing beside
workspace.json under the shipped json backend. Write policy: two mandatory
points (turn/end + session disposal) with count/interval throttling between
them (both Config fields required — flush cadence is a deployment choice);
every background write is fail-soft (log + stay stale, self-heal on the
next write or cold read). coldSnapshot(id) runs the read ladder — cached
rows + persistence readFrom from the registry's anchored restore floor +
registry restore + fail-soft write-back — detecting crash-repair-shrunk
logs via the one-below anchor and degrading to a single full re-read.
Mounted in apps/cli/cordis.yml (writeEveryEvents 200 / writeIntervalMs
5000).
2026-07-28 22:25:28 +08:00
imccyu fc4b573ff0 feat(session-projection): checkpoint/restore faces for the persisted projection cache
The registry grows the state-level read ladder the persisted cache builds
on: checkpoint(session) snapshots every unit's {stateVersion, observedSeq,
state} row from the watermark cache; restoreFloor(checkpoint) anchors the
tail read one event below the lowest usable watermark (so a shrunk log is
provable); restore(checkpoint, events, baseSeq) refolds each unit from its
usable row (or from init over a full read), rejects rows a tail read cannot
fix (version mismatch / overreach with baseSeq > 0 => re-read from 0), and
returns both the snapshot and the refreshed rows for durable write-back.
ProjectionCheckpointRow/ProjectionCheckpoint are the persisted-row types
minus the record keys.
2026-07-28 22:25:27 +08:00
imccyu a79de44c3b feat(session-persistence): readFrom(seq) primitive for watermark tail reads
SessionPersistence grows readFrom(id, fromSeq, signal?): the non-mutating
read-from-seq primitive for checkpoint consumers (the persisted projection
cache folds only the tail past its watermark). Coordinator owns validation,
per-id serialization, and the sequential fallback (loadStored + forward
skip); SQLite implements the optional seek-capable loadStoredFrom hook
(WHERE seq >= ?), JSONL stays sequential by contract. Contract suite covers
suffix exactness, empty-tail, non-mutation, and cancellation; seam README
(both languages) documents the method and the hook.
2026-07-28 22:25:25 +08:00
imccyu 29f76080a2 Merge pull request #846 from deepseek-harness/xtr/restore-pre-806-sessions
fix(persistence): restore pre-identity sessions
2026-07-28 22:23:19 +08:00
_Kerman b10dad0fcb fix(persistence): restore pre-identity sessions 2026-07-28 22:16:43 +08:00
Tianyi Cui cc6e5c7173 docs(session): catalog creation-time seed facts
The simplified inheritance path uses Session creation seeds for policy events, and the public CreateSessionOptions JSDoc now names that supported role. The type-equivalent persistence catalog still described seeds as replay/fork-only, so doc-sync correctly rejected the mismatch.

Align the explanatory paragraph and exact type-equivalent block in both languages, then re-record the bilingual pair. This keeps the public catalog from understating the constructor seam that makes the simplification possible.
2026-07-28 21:54:15 +08:00
Tianyi Cui 6d389d261e docs(policy): describe constructor-seeded inheritance
The implementation no longer stores inherited policy in SessionHeader or resolves a second baseline chain, but the feature, sandbox, and approval notes still described that machinery. Keeping those claims would make the smaller design look incomplete and invite reintroduction of the generic persistence surface.

Rewrite the owning feature note around the actual delegation snapshot: source-tagged policy events follow the optional fork prefix, ordinary last-event-wins folds establish precedence, and persistence captures the constructor seed with the first materialized batch. Condense the alternatives and consequences to the decisions and coverage that remain load-bearing.

Align the sandbox and approval notes plus the subagent-inprocess consumer README with that contract. Update the four Chinese counterparts minimally and re-record each pairing hash so both languages describe the same shipped mechanism.
2026-07-28 21:51:13 +08:00
Tianyi Cui db0b43bf86 persistence: advance schemas after removing policy columns
The simplification deletes sandbox_mode and approval_policy from the parent branch's SQLite layouts. Restoring master's older version numbers would violate the monotonic schema contract and could make a database created by the parent look current under a different layout.

Advance durable session persistence from schema 11 to 12 and the disposable session-query index from 6 to 7. The former rejects the incompatible parent layout; the latter resets its derived tables through the existing version-mismatch path.

JSONL shares SESSION_FORMAT_VERSION 0 during pre-release, so explicitly reject the retired sandboxMode and approvalPolicy header fields instead of silently dropping the only inherited policy facts from a parent-produced child log. New logs carry those facts as ordinary seeded events.

Focused JSONL, SQLite persistence, and SQLite query suites cover all affected source lines and branches.
2026-07-28 21:40:51 +08:00
Tianyi Cui 39ff4866ac Merge retargeted parent into policy inheritance simplification 2026-07-28 21:35:23 +08:00
Tianyi Cui 5d147735ac Merge latest master into subagent policy inheritance 2026-07-28 21:33:40 +08:00
Tianyi Cui a70f1a2b7a test(acp): remove vacuous policy inheritance scenario
The ACP fixture configured read-only as the deployment default for both parent and child. Its delegated write therefore remained denied even with inheritance disabled, so the scenario could not fail on the regression it claimed to protect.

Delete the overlay, scenario registration, sessions, prompt, and 473-line tool-schema sidecar. The Loader-booted headless snapshot remains the real composition guard: only its parent carries read-only while the deployment default is workspace-write, so removing inheritance makes the child write reach disk and fails the test.

Keeping one discriminating snapshot avoids 662 lines of duplicated fixture data and makes the review evidence correspond to the actual security boundary.
2026-07-28 21:32:10 +08:00
Tianyi Cui cfceb8452b subagent: seed inherited policy events at creation
The parent implementation introduced sandboxMode and approvalPolicy as generic SessionHeader fields, then propagated those fields through both persistence backends, session-query indexes, collision checks, policy-specific seed-boundary folds, catalogs, and a broad test matrix. That storage plane is unnecessary: Session already accepts a validated constructor seed, and persistence captures that seed when the session is announced before committing its first batch.

Capture each parent override synchronously at delegation, append source-tagged sandbox/mode and approval/policy records after the optional fork prefix, and create the child with that combined seed. Keeping header.seedLength at the original fork-prefix length preserves lineage while ordinary last-event-wins folds make the inherited records outrank stale parent history and remain subordinate to later child switches. Unswitched parents still stamp nothing, so children continue to follow deployment defaults.

Remove the generic header fields and every persistence/query/schema branch built around them. Collapse the inheritance suite from ten leaking scenarios to four owned-context cases covering real filesystem confinement, stale fork precedence, delegation-time capture, and the no-override path. The assembled headless snapshot now asserts the persisted inheritance event directly.

This keeps the security behavior while restoring policy ownership to the existing event log and deleting the speculative durability machinery that the original tests did not exercise.
2026-07-28 21:31:17 +08:00
Tianyi Cui 5335c03837 Merge pull request #824 from deepseek-harness/worktree/dedupe-snapshot-contracts
test(snapshot): share identical header sidecars
2026-07-28 21:13:01 +08:00
Tianyi Cui afa38c4b2f Merge latest master into subagent policy inheritance
Retarget the feature branch to the current master tip without rewriting its existing review history. Keeping this as a dedicated merge checkpoint makes the later simplification diff attributable to the stacked child rather than mixing base movement with design changes.

Resolve the identified-message API drift in the feature tests by constructing complete user messages, reading the nested tool-result message shape, and adapting the prompt-submit listener signature. Preserve both sides of the user-approval conflict: master’s createUserMessage wrapper and the feature’s inherited-policy attribution.

Regenerate the Cordis and persistence catalogs, re-record the session README pair, and refresh the affected ACP/headless fixtures so derived artifacts describe the merged source rather than either parent in isolation.

Validated with the focused policy/session/persistence/query suites (430 tests), focused ACP/headless snapshots (3 tests), build, doc-sync (25 gates), lint, hygiene, and git diff checks.
2026-07-28 21:11:20 +08:00
Tianyi Cui 0304ba1457 Merge branch 'master' into worktree/dedupe-snapshot-contracts 2026-07-28 21:08:38 +08:00
07akioni cad0615261 Merge pull request #829 from deepseek-harness/feat/close-todo
feat: implement todo plan clearance on turn start
2026-07-28 19:58:35 +08:00
07akioni a39890bba5 Merge branch 'master' into feat/close-todo 2026-07-28 19:45:36 +08:00
07akioni 2c65ebf6be test(connection): expect fixture todos projection null on empty log 2026-07-28 19:44:36 +08:00
07akioni 7bf36c6aa3 Merge origin/master into feat/close-todo
Keep master's session-projection carrier for todos, and fold turn/start
clearance into the tool-todo projection unit (plus TUI/fixture mirrors).
2026-07-28 19:43:56 +08:00
Tianyi Cui 466d13ed9c Merge pull request #806 from deepseek-harness/xtr/identified-immutable-messages 2026-07-28 19:39:56 +08:00