Commit Graph
27 Commits
Author SHA1 Message Date
Tianyi Cui f044d3fad2 fix(session): address v0 migration review 2026-09-03 01:52:25 +08:00
Tianyi Cui 17f49f6191 fix(session): keep cold listing body-free 2026-09-02 21:29:43 +08:00
Tianyi Cui cf9948b147 Merge master into session format migration
# Conflicts:
#	packages/session/session-projection-cache/tests/cache.spec.ts
2026-09-02 17:41:58 +08:00
imccyu c917fe6d46 Merge remote-tracking branch 'origin/master' into merge/projcache-v6-compat-into-master
# Conflicts:
#	packages/session/session-projection-cache/src/spec.ts
#	packages/storage/storage-json/src/per-record-unit.ts
#	packages/storage/storage-json/tests/json-backend.spec.ts
2026-09-02 16:55:00 +08:00
imccyu db2dd2f840 docs(session-projection-cache): land the read-compat note as implemented and state fixture provenance in place
Review follow-ups: the Agent Note triplet moves to implemented/ rewritten as
shipped state (Decision/Consequences/Testing, present tense), cross-linked
both ways with the 2026-07-28 storage recovery proposal whose projcache
reset/destroy path it supersedes (that proposal stays live for authoritative
and whole-medium damage). The fixtures spec header and the note state the
fixture provenance as recorded facts of the released builds instead of
citing local tooling, and the spec JSDoc points at the note's final home.
2026-09-02 15:25:07 +08:00
imccyu 49df707c86 fix(session-projection-cache): keep upgraded caches readable and boots safe across domain versions
The session_projcache domain declares compatibleVersions: [3, 4] and
invalidRecords: 'backup-and-skip'. The two lineage identity fields become
optional — records admitted from older versions predate them, and the single
reader (identityMatches) interprets absence as the unseeded lineage: exact
for unseeded sessions, while a seeded caller fails the match and refolds
cold, so the lineage binding keeps its protection. Upgraded homes therefore
boot and serve their cached listing titles immediately, including homes
whose new tree already holds current-stamped documents without lineage
fields, and a record failing validation anyway is backed up and skipped
instead of refusing the plugin tree.

tests/fixtures/ archives the real on-disk media of every shipped generation
(v3 whole-unit file, v4 and v5 per-record documents, and the lineage-less
current-stamped shape); fixtures.spec.ts proves each recovers through the
real storage stack, rewrites to the current format on the next live write,
and that a hopeless record is salvaged without costing the boot.
2026-09-02 15:25:07 +08:00
Magolor d921d4b357 fix(storage-json): reject cross-version legacy bootstrap (#3431)
* fix(storage-json): reject cross-version legacy bootstrap

* test(webworker): sync projection cache fixture version

* docs(storage): record legacy bootstrap version ownership
2026-09-02 04:37:15 +00:00
Tianyi Cui d1521ea783 feat(session)!: add released format migration 2026-09-01 22:12:21 +08:00
Tianyi Cui 27bf1039db refactor(session)!: distinguish event seqs from log offsets 2026-09-01 20:36:00 +08:00
Turtle b8e3b32fcf Merge master into codex/omit-unneeded-invariants 2026-08-31 14:38:55 +08:00
imccyu 9135a13a8b refactor(consumers): remove cross-package runtime relays 2026-08-30 02:29:52 +08:00
Turtle 15f2997bcb cleanup: omit unneeded invariant companions 2026-08-28 13:12:52 +08:00
Magolor 0b5eba0c8d docs: rebuild the documentation skill and standards (#2983) 2026-08-25 23:47:20 +08:00
_Kerman 3c8b5a26a4 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2781
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/subsystems/session-projection.i18n.yaml
#	docs/subsystems/session-projection.md
#	docs/subsystems/session-projection.zh.md
#	packages/api/session-controller/src/history.ts
#	packages/api/session-controller/tests/session-cold.host.spec.ts
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/session/session-projection-cache/src/index.ts
#	packages/session/session-projection-cache/tests/cache.spec.ts
#	packages/session/session-projection/src/index.ts
#	scripts/run-gates.ts
2026-08-25 10:52:45 +08:00
imccyu 7fb2ca07e4 feat(session-query): add shared projected observations 2026-08-25 06:06:03 +08:00
_Kerman eb1f167fa4 refactor(session-projection-cache): restore the base method order
Keep the base class's relative method order (write before coldSnapshot) so
the diff against the base shows the cold-read methods as a pure insertion
instead of a reorder of existing methods.
2026-08-20 17:14:05 +08:00
_Kerman b67761a8a5 fix(session-projection-cache): checkpoint at session creation
A session that never talks — a forked child seeded with its ancestor's
title, say — previously got its first cache row only at detach; a crash,
or a fork held live in the store, left the seed-derived values (the
title) unreadable on the cold list. Session creation is now a third
mandatory write point: the creation checkpoint folds the seed and
persists immediately. Write-policy docs (README + catalogs) updated.
2026-08-20 16:37:41 +08:00
_Kerman 84db39cec4 feat(session-projection-cache): seed cold reads from the cache and write back
A detached history read still traverses the complete log, but each unit's
fold is now seeded from its cached checkpoint: the registry's restore
slices off the already-folded prefix (events at or below the row's seq)
and applies only the tail. The first cold read writes the refreshed
checkpoint back (fail-soft), so the cache row is created on first read
and kept current afterwards. The recipe lives on the cache
(cachedCheckpoint, coldSnapshot, writeBack); the api-proxy carrier only
supplies the stored header and the full log.
2026-08-20 16:25:39 +08:00
_Kerman 1201ecc828 fix(session-projection-cache): store checkpoints on a per-record storage domain
Restore the storage-domain medium the file-root design replaced: the cache
opens the session_projcache domain (per-record layout — one document per
session under the json backend root) and checkpoint writes land through
the domain's write chain. Reads and writes now share ONE coherent state:
cachedSnapshot reads synchronously from the domain's in-memory tables,
and every write is durability-first-then-memory, so a read can never go
around the write chain to the medium. The hand-rolled write chains,
in-flight tracking, per-session file paths, owner-only file modes, and
the sqlite no-path special case are gone; Config.root is removed and the
domain's version stamp makes a checkpointRecord bump discard stale
sessions per record instead of rejecting the whole medium. The async
ripple of the old file read is reverted: api-proxy's listing column and
subagent's cold identity read go back to synchronous cachedSnapshot.
2026-08-20 13:47:47 +08:00
_Kerman 89321489db refactor(session-projection-cache): own the cache tree under a config root
Store each session's projection_cache.json under the cache's own root tree
(<root>/<session-id>/projection_cache.json, wired to dshHomePath('projections')
in the base bundle) instead of beside the session log via
sessionPersistence.locate(). The cache owns its directory layout, keys
directories by the code-generated session id, and never consults the
persistence layer; the service now injects only sessionProjections and
sessions.

Drop the coldSnapshot method and its readFrom-tail fold ladder: every cold
consumer refolds from the log itself, so the cache only serves the listing
read (cachedSnapshot, one async file read per session) and the write side.
Fail-soft durability, per-path write serialization, in-flight drain, and
atomic 0600 writes are unchanged; the chain cleanup now observes its own
rejection so a failed write cannot surface as an unhandled error.

dsh-session-persistence leaves peer/dev dependencies and the tsconfig
reference; dsh-atomic-write moves to peerDependencies. Config gains a
required root.
2026-08-19 22:25:54 +08:00
_Kerman 3f4c5f0563 fix(session-projection-cache): address review — atomic-write reuse, sqlite no-path, ordering and drain
- Write through @deepseek-ai/dsh-atomic-write with { mode: 0o600,
  dirMode: 0o700 } instead of exporting a second atomic-write primitive
  from dsh-storage-json; the session tree stays owner-only like the jsonl
  backend's own directories.
- Serialize atomic replacements per cache path so an older cut can never
  overwrite a newer one; track in-flight writes and drain them on
  disposal so a late flush cannot land after teardown.
- Detect the absent per-session directory before the checkpoint cut and
  durability flush: sqlite-style backends no-op the write entirely.
- Cold-read write-back path and identity both come from the stored log
  header (tail.meta), so a stale caller header cannot mint an orphan
  cache file.
- Add no-path coverage (write no-op, cachedSnapshot undefined, cold
  fallback to the full-log rung) and a concurrent-write ordering test;
  the package now holds 100% statement/branch/function/line coverage.
- Sync README.md/zh (inject list, coldSnapshot signature, per-session
  file read wording), package description, the Agent Note alternatives,
  and the superseded proposed/implemented notes (EN/ZH); add the
  concurrent-checkpoint Known Limitation.
2026-08-19 21:40:12 +08:00
_Kerman cdb4cc3c68 feat(session-projection-cache): store one projection_cache.json per session
Replace the single global session_projcache domain with a per-session
cache file inside the session's own persistence directory, resolved
through sessionPersistence.locate(meta) — the persistence backend owns
the session-directory layout, the cache service keeps every checkpoint
and cold-read responsibility.

- cachedSnapshot(meta) becomes async (one file read per session);
  coldSnapshot takes the session header so it can locate the file, with
  the stored log header remaining the identity witness.
- Backends without a per-session directory (sqlite) disable the durable
  cache: writes no-op and cold reads fall to the full-log rung. An
  obsolete global cache is never read — derived data refolds on first
  cold read (no migration).
- writeAtomic is exported from dsh-storage-json as the shared atomic
  whole-file replace primitive; api-proxy listing and subagent cold
  reads await the now-async cachedSnapshot.
- READMEs and a new Agent Note document the per-session medium.
2026-08-19 21:03:20 +08:00
_Kerman 9127d7e8b7 fix(session-projection): keep host state off wire 2026-08-19 14:32:48 +08:00
_Kerman 4c421ec882 refactor(session-projection): separate state from client views 2026-08-19 13:11:05 +08:00
imccyu ec601ca13d build(vendor): rescope the vendored Cordis packages into @deepseek-ai
Machine-produced by `pnpm run rescope-vendor --apply` plus the regeneration it
prints: `pnpm install` for the lockfile, `pnpm run gen-third-party-notices`,
`verify-translation-pairing --write` for the touched bilingual pairs,
`gen-doc-graphs`, and one typert snapshot whose ids embed character offsets.
`pnpm run rescope-vendor --check` verifies the result.

Renames nine vendored packages (cordis, cosmokit, schemastery and the six
@cordisjs plugins) and every reference that resolves them: manifest names and
dependency keys, module specifiers including declare-module merges, cordis.yml
plugin names, tsconfig paths, every Markdown fence, and `docs/` prose.
Directory names, upstream versions, and dependency ranges are unchanged, so
vendor/README.md still reads as an upstream snapshot; its manifest table gains
an upstream-name column so THIRD_PARTY_NOTICES keeps MIT attribution pointed
at each fork's origin.

The tutorial tier follows the rename end to end: its yaml fences named plugins
the Loader can no longer resolve, its `ts ignore-check` fences disagreed with
the compiled fences beside them, and its prose quoted both. The contracts that
told readers to keep upstream names — the root convention and the vendoring
cookbook's tree comment and manifest invariant — now say to rescope instead.

Two rules read `@deepseek-ai/` as "another workspace plugin": the client bundle
purity gate now names the vendored libraries a browser bundle inlines, and the
files where a bare `cordis` is an agent-preset id keep that product data.
2026-08-10 22:04:13 +08:00
Tianyi Cui 25dcd7293c docs: purge chain-of-thought leakage from prose
Delete design-session citations (decision/audit/plan ordinals, stack
positions), change narration, review choreography, and reviewer-addressed
justification from comments, JSDoc, docs, READMEs, Agent Notes, tests, and
generator templates; restate every affected fact as current-state contract
prose. Fix generated docs at their sources and regenerate the catalogs and
cordis-surface regions; re-paste type-equiv blocks; update every bilingual
counterpart and re-record the pairs. Record the citation rule in the
committed-artifact-citations Agent Note.
2026-08-09 21:10:59 +08:00
Tianyi Cui 7e445c3a67 refactor(session): fold the session family into packages/session/
git mv the 12 packages from session-persistence/, session-projection/,
session-title/, and telemetry/ into one session/ group per the
regrouping RFC; merge the four group READMEs into one bilingual
triplet; rewrite the group segment in tsconfig references (intra-group
references shorten to ../<pkg>), tsconfig.base.json paths/globs,
knip.json keys, vitest include, gate scripts, and authored doc/note
citations; regenerate module graph, doc graphs, catalogs, and the
lockfile importer keys. No npm names change.

Full unit suite: 8779 passed; the 18 reported failures reproduce as
env flakes (ambient-proxy IPv6 tunneling, watched-dir inotify
timeouts under parallel load) — each passes in isolation with
NO_PROXY set, matching their known pre-existing behavior on master.
2026-08-09 01:21:11 +08:00