Commit Graph
18490 Commits
Author SHA1 Message Date
Tianyi Cui fdff56c293 fix(cli): drop retired link-mode override after master integration
The release branch still passed resolutionMode: link from the source CLI
and documented a separate link/runtime selector. The integrated master
has removed that selector and its materializer in favor of one runtime
resolver that also supports source launches. The spread kept compiling
because excess-property checking did not reject it, but the property was
ignored by runProfile and the retained prose contradicted the runtime.

Remove the dead option/comment and its obsolete bilingual paragraph.
The CLI entry and the architecture note now match the integrated master;
keep source-module identity verified through its real source-launch and
tool-execution tests. This retires an old integration workaround, without
changing Session V4 or restoring a second profile resolution backend.
2026-09-19 18:03:33 +08:00
Tianyi Cui 5da1515286 test(cli): inspect flat V4 results in source launch smoke
The new master source-tool smoke reads isError and content from a V3
nested tool-result block. After integration with the V4 release, that
block no longer exists: the durable message itself has role tool,
toolCallId, isError and result content. The old assertions fail to
compile and cannot verify the current writer's output.

Read the existing V4 fields while retaining the real source-profile
launch, single Tools instance, call identity, sandbox error and shell
output checks. Do not impose the old single-wrapper cardinality on the
flat content array. This adapts the incoming regression test without
changing the V4 format, migration implementation or stored recordings.
2026-09-19 18:01:49 +08:00
Tianyi Cui 8b0b2dc1d8 Merge master b86916de into release/session-log-v4
Integrate the master tip observed for the final V4 landing preparation on
top of the already merged migration stack. Preserve the V4 writer, flat
message migration, extension policy, catalog validation and historical
recordings while bringing in upstream profile resolution and desktop/UI
changes.

Resolve four generated translation-pairing records from the combined
English/Chinese text. Keep this master checkpoint separate from any
integration fixes and retain all reviewed parent history. Follow-up
validation covers the affected launch/UI paths and migration replay.
2026-09-19 18:00:36 +08:00
Tianyi Cui 2e061ec93f Merge pull request #4583 from deepseek-harness/worktree/v4-lossless-tool-results-20260919
fix(session): preserve extensions while flattening V3 tool results
2026-09-19 17:51:02 +08:00
Tianyi Cui 56f8c7f51b docs(session): keep migration mappings specific to each edge
The cookbook previously promoted plugin prefixes and owner separation into a general requirement. That overstates the migration policy: direct source kinds and ordinary metadata need no new namespace solely because they are extensible.

Require each edge to document only the mappings its target needs and why, preserve nested opaque data, and permit alpha refusal of unexpected source fields that would otherwise acquire new target meaning. Exact V3 source and ToolSchema choices remain in the V3-to-V4 README; no runtime, schema, or provider behavior changes.
2026-09-19 17:27:14 +08:00
imccyu b3961e06a0 Merge pull request #4608 from deepseek-harness/worktree-removelink-rename
refactor(boot): rename the profile resolution generation to the runtime resolution
2026-09-19 17:25:04 +08:00
Tianyi Cui bb81d312ae docs(session): scope extension prefixes to declared mappings
The convention identifies how an edge preserves the identifiers and extension fields that it explicitly maps; it does not require every extension-owned field in every source slot to be renamed.

Keep the cookbook general enough for preserved stream-start extras while retaining the exact field-owner mappings documented by each migration edge. This changes policy wording only, not the current V4 schema or conversion implementation.
2026-09-19 17:20:53 +08:00
Tianyi Cui 7528528007 test(session): name the wrapper pass-through assertion precisely
This case calls only liftToolResult; the native validator has separate coverage. Name the behavior actually asserted so the test title does not claim both paths are covered by one assertion. Assertions and production behavior are unchanged.
2026-09-19 17:20:53 +08:00
Tianyi Cui 3e31760bc7 docs(session): explain historical result field ownership
The flat result conversion prefixes every extension-owned field, not just names currently colliding with core fields. Correct the cookbook wording to match that complete mapping.

Record why retaining opaque message and wrapper owners does not invent a shared owner or a new core metadata field. The deliberate costs are retaining duplicate opaque values and requiring plugin consumers to use V4 names; the first-class tool-message decision and runtime implementation stay unchanged.
2026-09-19 17:20:53 +08:00
Tianyi Cui 4ab9101271 docs(session): state the flat result converter failure contract
The exported converter rejects malformed wrappers with SessionFormatError in addition to refusing unsupported nesting. Document both failure categories so callers can distinguish corruption from a converter support limit.

Remove the obsolete claim that recorded replay compares serialized field order: the native-writer parity assertion compares parsed objects. The emitted fields and their order remain unchanged.
2026-09-19 17:20:53 +08:00
Tianyi Cui 45ce6ef21d docs(session): clarify converter fixes leave existing successors intact
An incoming converter runs only when a historical generation is selected. Fixing a mapping after the target ships does not revisit already-produced target files, so allowing compatible converter fixes must not imply repairing those files automatically.

Keep the user-approved ability to extend or correct historical conversion without a target version bump. Require documentation of changed accepted mappings and continued support for existing outputs, and distinguish that work from changing target representation or interpretation incompatibly. Keep operational alpha guidance in the cookbook and the owning decision note focused on the runtime facts.
2026-09-19 17:20:53 +08:00
Tianyi Cui c7923096c7 test(session): bind tool-result parity to retained V3 replay
The parity assertion previously compared a fixed V3 log with whichever generation the ordinary scenario selected. A legitimate V4 re-recording could change call ids and make the assertion compare different model inputs.

Run an additional replay-only variant through the existing headless runner with both its replay file and migration expectation bound to the retained V3 recording. Keep the ordinary scenario on its highest generation, retain call ids in the comparison, and preserve every committed recording.

Validation: the ordinary replay, retained-V3 replay, and old-wrapper negative control pass. Changing only the latest V4 call ids makes the former assertion fail but leaves the corrected retained-V3 replay passing; both fixture and source bytes are restored after this control.
2026-09-19 17:20:53 +08:00
Tianyi Cui e90c55e0ab docs(session): distinguish converter support from target compatibility
The compatibility obligation belongs to the released target format.
An incoming converter can be fixed or support more historical inputs after
the target ships, as long as its output preserves that target's meaning.
Alpha releases may reject valid historical cases without an implemented,
evidenced mapping instead of expanding the format for speculative inputs.

Record the native-writer oracle, pre-normalization comparison, supported
flat V4 tool-result representation, uniform plugin naming, owner collision
rules, retained source files and read-only private corpus handling in the
migration cookbook. Align the existing architecture note with this rule;
keep native target changes and source conversion fixes distinct.

This updates contributor guidance only. It does not change finalization
checkpoint machinery, existing V4 schemas, or any released codec.
2026-09-19 17:20:53 +08:00
Tianyi Cui 1e7686b2c9 test(session): compare migration with raw native writer output
The ordinary snapshot comparator prepares both inputs through the current
format catalog. That can hide a writer still emitting an old tool-result
wrapper: both sides become the same normalized representation.

For the existing stock tool-call-turn replay, explicitly migrate its
retained V3 recording and compare result message fields with the freshly
harvested native log before format normalization. Check both generation
headers and remove only the generated message ID from this comparison.
Do not use the scenario's selected V4 successor as the migration input.

Add a negative control whose header claims the current writer while its
body keeps the V3 wrapper; the raw comparison must reject it. The same
shipped headless profile and stock bash tool provide the positive case.
Keep all recordings and their selected generations unchanged.
2026-09-19 17:20:53 +08:00
Tianyi Cui 0c8180c9b6 fix(session): preserve V3 result extensions in flat tool messages
The ordinary V3 writer records a user-role message containing one result
wrapper. V4 writes the same tool output directly in a tool-role message.
Keep that native V4 representation instead of introducing a nested message
content type for hypothetical historical shapes.

Preserve extra historical fields when removing the wrapper. Prefix outer
message fields with plugin:message: and result fields with plugin:result:
so equal names retain their original ownership and cannot overwrite the
interpreted call ID or error flag. Include the complete old name, even
when it is already prefixed, and preserve every JSON value and own key.
Only the validated wrapper supplies the interpreted result fields.

Leave unimplemented nested-result conversion as an explicit refusal that
preserves its source. Describe this as the converter's current limit, not
an impossibility or a reason to extend the established V4 format.

Cover owner/name collisions, opaque special keys, absent error flags,
unchanged sources and strict native reopening through plain and compressed
read/write persistence. No current message type or schema is added.
2026-09-19 17:20:53 +08:00
Tianyi Cui 869367d5d0 test(session): continue catalog backfill after unavailable evidence
Isolated complete/incomplete-child tests did not distinguish skipping one child
from prematurely stopping the entire candidate loop. A stop could therefore
silently omit a later child's fully supported catalog fact.

Pair a complete child with an older unavailable child so deterministic ordering
processes the unavailable evidence first. Cover missing, unsupported-version,
and multiple-descriptor evidence, requiring exactly the complete child's fact
with the correct sequence and timestamp.

A temporary continue-to-break mutation failed all three new cases. Restoring
the implementation passed the focused 19 cases and the complete selected owner
run: 428 passed, one compression-specific skip, with 100% coverage on facts.ts
and migration.ts. This commit changes tests only.
2026-09-19 17:17:29 +08:00
Tianyi Cui e838401a9b docs(session): state incomplete catalog evidence limits
The child-catalog README did not record the lasting missing-entry consequence
under Known Limitations, and its validation wording implied that duplicate or
unsupported descriptors had their discovery fields checked. The converter only
checks those fields when exactly one supported own descriptor is available.

Specify that distinction, retain creation-time checks for existing entries, and
state that current V4 reads do not rescan children to repair an omitted entry.
Document the first-descriptor composition reader and last-descriptor identity
projection accurately: multiple own records violate the establishing provider's
exactly-once rule, so the backfill policy does not choose between those consumer
policies. This corrects the rationale without changing migration admission.

Update the paired English/Chinese package docs and decision note together.
Validation: doc-sync 41/41, full lint, and owner tests passed; production source,
frozen generations, persistence schema, and recorded fixtures are unchanged.
2026-09-19 17:17:29 +08:00
Tianyi CuiandDudu-0223 ade7035fd8 fix(session): preserve parents with incomplete child catalog evidence
A readable V3 child may have no own descriptor, an unknown descriptor version,
or multiple descriptors. Those states do not provide a unique discovery fact,
but they do not make the parent or the retained child history unreadable.
Rejecting the entire parent prevented otherwise valid V3 Sessions from opening.

Append a missing parent catalog row only for exactly one supported own child
descriptor. Keep existing parent entries and every child record when no fact is
available. Retain rejection of mismatched creation times, unambiguous mode/label
conflicts, malformed known fields, unreadable membership and revision drift.

Cover raw and compressed read/write publication, preserved source bytes, late
descriptor availability, inherited descriptors and Preview packing. Document
that unavailable discovery evidence can leave a child absent from its parent
catalog and does not trigger automatic backfill after the V4 successor exists.

Extracts the child-evidence behavior from 7ba7e174dd1 and the Preview regression
from 9c85eb60bd25, preserving the original migration authors' work while keeping
message representation and extension interpretation outside this commit.

Co-authored-by: Dudu-0223 <[email protected]>
2026-09-19 17:17:29 +08:00
Tianyi Cui c6f6aa3293 fix(session): preserve V3 tool-schema metadata keys
The V3 writer on master declares and emits only name, description and
parameters. deferLoading is a first-class V4 persistence addition whose
provider behavior is not implemented yet. Prefixing every historical extra
ToolSchema key changes ordinary plugin metadata without a format need.

Preserve all ordinary tool-definition keys and JSON values unchanged,
including vendor metadata, own __proto__ properties, already-prefixed keys
and nested parameters. Remove the general key-renaming mapper. Reject only
an own top-level deferLoading field in V3 input: there is no established V3
meaning to translate, and the alpha converter may refuse unsupported source
forms rather than invent compatibility semantics. Leave native V4's
optional-true declaration, admission and provider refusal behavior intact.

The regression tests fail on the old mapper for metadata preservation and
unsupported-field refusal. Physical plain/zstd read/write tests verify source
bytes and identity remain unchanged and no V4 successor appears on refusal;
controls preserve nested parameters.deferLoading and native V4 true values.
No Session format/schema change, frozen codec edit, or historical recording
version bump is needed.
2026-09-19 17:15:38 +08:00
Tianyi Cui d5a109c60f fix(session): preserve direct V3 source kinds during wrapper conversion
Convert an unknown legacy plugin wrapper such as
{kind: 'plugin', plugin: 'acme'} into {kind: 'plugin:acme'}, retaining the
complete plugin name after one prefix. Keep the existing explicit
first-party producer renames and preserve all non-identity metadata.

A direct source already records its producer in kind. Reclassifying
unknown direct kinds into plugin:source:<name> needlessly changes that
attribution and forces plugin consumers to adopt new identifiers even
though V4 accepts their existing representation. Return every valid
direct source unchanged, including already-prefixed names. Remove the
obsolete direct-kind table and two-category identity helper rather than
adding collision classification or another mapping layer.

Update the source conversion examples, codec/restore regressions, and
native fixture producers together. Refresh only the owning Python
advanced scenario's unshipped V4 outputs; preserve historical V0-V3
recordings and their generation selection. Event names, content tags,
and ToolSchema migration remain separate concerns.

Refs #2692
2026-09-19 17:11:45 +08:00
imccyu cf3505b88e docs: call the package table the runtime resolution everywhere it is named
The generation note keeps generation for succession only and names the table, the interception, and the routes with the code's words; the CLI reference, Desktop, plugin-package-inventory, and loader-smoke READMEs, the bundled-runtime, agent-teams, plugin-bundles, and source-launch notes, and the client AGENTS guide follow. Pairing records re-recorded.
2026-09-19 17:06:35 +08:00
imccyu f7f22a6b48 refactor(boot): finish the interception vocabulary in code comments and the app-boot README
The Consumer-owned strictness bullet names the Loader subtree that agent presets own instead of the runtime resolution; the service field, its file comment, the dispose JSDoc, and the route JSDoc use interception; the native-after-interception route documents both anchors it can carry; stale module-fallback comments name the runtime resolution; importFromResolution matches its parameter.
2026-09-19 17:06:35 +08:00
imccyu b605d114bd docs(boot): finish the runtime resolution terminology in the generation and desktop notes 2026-09-19 17:06:35 +08:00
imccyu c0f34b4bcd docs(boot): name both installation anchor sources
The CLI derives the installation anchor from import.meta.url and the Desktop Host builds it from its runtime directory; neither is a symlink, so the installation root is kept as given. The note and the traversal comment say so instead of attributing every launcher to import.meta.url.
2026-09-19 17:06:35 +08:00
imccyu 06b0ff9560 docs(boot): describe the installation closure size without point-in-time counts 2026-09-19 17:06:35 +08:00
imccyu 058d1d779b docs(boot): keep the ancestor chain code block language neutral
The numbered chain lists directories only; the legend for ①-⑤ moves into prose so both language sides can read it while the code block stays byte-identical for the pairing gate.
2026-09-19 17:06:35 +08:00
imccyu 9848ac75f2 test(cli): explain the sandbox-unavailable acceptance in the source tool smoke 2026-09-19 17:06:35 +08:00
imccyu 048fc3e580 docs(boot): state that the installation anchor is already a real path
The lookup-order note records that the launcher derives the installation anchor from import.meta.url, so bundle discovery and dependency traversal start from the same real directory.
2026-09-19 17:06:35 +08:00
imccyu 15e07d2721 refactor(boot): rename the profile resolution generation to the runtime resolution
RuntimeResolution, RuntimeResolutionEntry, RuntimeResolutionOptions, and createRuntimeResolution replace the generation-named table types; installRuntimeInterception returns a RuntimeInterception; PluginPackages takes { resolution }; Worker environment data carries { resolution }; routes are native, interception, and native-after-interception. replace() keeps its successor-generation wording.
2026-09-19 17:06:34 +08:00
imccyu 5f48b2fff6 docs(boot): call the package table the runtime resolution
Notes and the app-boot README name the startup package table the runtime resolution and the installed hook the interception; generation remains the word for the additive successor semantics of replace().
2026-09-19 17:06:34 +08:00
imccyu bffd317c8c Merge pull request #4570 from deepseek-harness/worktree-removelink
fix(boot): keep runtime-only profile resolution and real package anchors
2026-09-19 17:04:22 +08:00
Yifffan a30f3a68c8 Merge pull request #4509 from deepseek-harness/feat/macos-sidebar-ui-and-drag-refine
feat(client): frame-owned macOS window chrome with single drag owner
2026-09-19 16:58:41 +08:00
imccyu 109efc7942 test(boot): cover the projection removal edge cases
A profile with the legacy directory but no node_modules, and a symlink whose target parent is gone, exercise the remaining branches of removeLinkProjections; the non-ENOENT realpath failure is a host filesystem fault and is excluded from coverage like its siblings.
2026-09-19 16:49:21 +08:00
Yif 9c48e74409 test(web): capture sidebar snapshots after the track-easing gate settles
The columnTransition probe raced data-animating's transitionend/600ms
settle: checkpoints recorded whichever side of the window the capture
landed on. Waiting for the attribute to drop pins the steady state —
no declared transition (computed 'all') — deterministically.
2026-09-19 16:39:47 +08:00
Yif 45d77b0e8e fix(ui-theme): match the scrollbar sheet exclusion against /-separated scan paths 2026-09-19 16:39:46 +08:00
imccyu 02fec3209e fix(boot): remove link-backend profile projections on profile load
removeLinkProjections unlinks the symlinks under a profile's node_modules whose target lies inside <profile>/.dsh-module-fallback/node_modules and then removes that directory; pnpm-installed packages and every other symlink stay. loadProfile and the Desktop applyRelease call it once per launch. Regression: with bundle A installed but deselected and bundle B selected, B's same-named plugin resolves instead of A's projected copy.
2026-09-19 16:34:07 +08:00
imccyu 0c342a81c4 docs(boot): record the one-time removal of link-backend profile projections
The lookup-order note, the cleanup-removal note, and the app-boot and Desktop READMEs state that profile load removes the .dsh-module-fallback projections the dsh 0.1.5 releases wrote into a profile, so a deselected bundle's projected plugin no longer shadows the same-named plugin the generation selects from another bundle.
2026-09-19 16:34:07 +08:00
Yif 9e95a7b183 fix(client): keep fullscreen sidebar strips draggable via fine-grained dockkit subtraction
Drop the fullscreen panel's whole-box no-drag: it swallowed the strips'
blank-run window drag and made no-drag the steady state, turning the
open/close app-region nudge into a computed-value no-op (electron#32341)
exactly when a hidden panel opens straight into fullscreen. The panel now
declares no steady-state app-region in either presentation, and ui-dockkit
subtracts the one box base.css never matches — the plain-div split divider —
alongside tabs, strip-end chrome, and pane bodies. New specs pin both
contracts against the stylesheets on disk.
2026-09-19 16:19:44 +08:00
Yif c6c1df6869 fix(ui-theme): normalize stylesheet-scan paths to forward slashes for Windows 2026-09-19 16:19:34 +08:00
Tianyi Cui ec2c4f2a42 test(session): isolate vocabulary fixture Git commands from caller paths
The new vocabulary fixture helper set cwd to a private repository but still
inherited GIT_DIR, GIT_WORK_TREE and GIT_INDEX_FILE. A negative control with
two disposable repositories demonstrated that git add/commit changed the
foreign repository's HEAD instead of the intended fixture repository.

Remove only those three location variables from the child environment.
Leave the caller's environment untouched and retain the existing identity,
hook and signing overrides. The regression checks the foreign HEAD and work
tree remain unchanged while the intended target commits its private file.
This is confined to the test helper; it adds no production Git abstraction
or Session-format behavior.
2026-09-19 15:43:10 +08:00
Tianyi Cui 696aa5f97c docs(session): describe retained source kinds by historical admission
The preserved direct-source set is the predecessor migration's accepted set
without the plugin wrapper. It includes older coordinator and subagent-report
identities even though those names have no current producer declaration.
Describe that historical admission fact instead of implying every retained
identity has a live V4 owner. No mapping or runtime behavior changes.
2026-09-19 15:43:10 +08:00
Tianyi Cui 4d9c4e7a12 fix(session): reject retired tool results in V4 Team checkpoints
Central V4 event admission already rejects tool-result content in Team
queue records, but projection checkpoints use the Team state schema directly.
After restoring the baseline Team parser during extraction, the production
SessionProjectionRegistry.restore() path accepted a decoded native V4
checkpoint containing the retired wrapper without reading an event.

Remove only that V4-incompatible schema arm. Keep the existing unknown-JSON
parser unchanged; its independent own-key preservation fix remains in the
standalone master PR, where recursive V3 tool results are still valid.

Exercise the real checkpoint restoration recipe with a valid text state and
an invalid retired-result state, plus queued-event projection. The new
checkpoint rejection failed before this change; central event admission and
the complete Team owner suite pass afterward with 100% projection coverage.
No Session schema, format version or projection state version is changed:
the rejected value is already outside the native V4 content vocabulary.
2026-09-19 15:43:10 +08:00
Tianyi Cui 88897a16c6 refactor(session): separate Team opaque JSON preservation from migration
Retaining own keys in the Team projection/checkpoint parser fixes a generic
JSON reconstruction defect. It is independent of V3-to-V4 identifier
conversion and can be reviewed directly against master, where recursive V3
tool-result content is still valid.

Restore the Team implementation, tests and paired README to this layer's
parent after the standalone owner captured the exact delta from 85737364be9.
The standalone port retains V3 validators and applies only the non-cloning
unknown-JSON repair. Migration content handling for team/message/queued and
all approved namespace, delivery and source-admission rules remain intact.

This removes an independent runtime/parser policy from the format stack;
it does not change any Session schema, codec, version or stored source file.
2026-09-19 15:43:10 +08:00
Tianyi Cui d5302e33f8 refactor(session): separate attachment carrier policy from V4 migration
The event-type allowlist and opaque-payload attachment policy change live
Session authorization/export behavior independently of a format upgrade.
They belong in a focused PR against master, where supported native V3 nested
tool-result content must also be handled deliberately.

Restore the session-controller and archive implementation, tests and README
pairs to this layer's parent. Remove the test-only session-format-catalog
dependency and its lock entry with the migration-specific attachment tests.
The original changes are captured from immutable commit 85737364be9 for the
standalone work; migration identifier conversion and reader checks are intact.

This extraction keeps the integration stack's existing attachment behavior
until the separate policy change is reviewed. It makes no Session-format,
schema or version change.
2026-09-19 15:43:10 +08:00
Tianyi Cui 11ef33b336 fix(session): reject unknown required V3 events before target interpretation
The physical V3 codec admits an unclassified event envelope without deciding
whether its type is required. The V3-to-V4 stage then used shared message
walkers and target vocabulary, so an invalid required developer/message could
acquire the V4 developer role although historical V3 restoration rejects it.
Generic required unknown events were also left to the wrong version's reader.

After preserving explicitly ignorable extensions, require every remaining
source type to belong to the fixed V3 vocabulary before interpreting payloads.
This is a fail-loud check for invalid or nonconforming source data, not new
compatibility handling for third-party events, which carry ignorable:true.
The approved plugin identifier conversion and native V4 readers are unchanged.

Exercise a complete developer-event sequence through direct migration,
historical/current catalogs, ignorable conversion and native V4 restoration;
add a generic unknown type. Both negative controls accepted the invalid source
before this guard. Plain/zstd read/write regressions verify refusal preserves
the source generation and never publishes a partial V4 successor.
2026-09-19 15:43:10 +08:00
Tianyi Cui fc74dbf4ea fix(session): limit delivery migration checks to the V4 target
A V3 delivery marker claiming generation 4 would become active when its
header advances to V4. The integration baseline already refused that case.
Renaming every higher-generation marker instead introduced a general
conversion policy for future formats that this V3-to-V4 edge does not own.

Restore the targeted generation 4 refusal. Keep other delivery event names,
payloads and coordinates unchanged, including generations 5 and 99, which
remain inactive in V4. Their future activation checks belong to a concrete
later format edge. Preserve the separate plugin-event identifier policy.

Cover read/write opens for both plain and zstd storage: target-generation
refusal preserves source bytes and publishes no successor, while later
markers survive V4 publication and native reopening unchanged. Update the
snapshot-normalizer cases and document the alpha converter coverage limit:
unsupported histories may fail without source mutation, and later converter
fixes may expand support without a new version when V4 output stays compatible.
2026-09-19 15:43:10 +08:00
Tianyi Cui 28b209867f fix(session): preserve historical stream-start extension field names
V3 and V4 declare the same block-start fields: type, index and blockType.
The migration's identifier policy can qualify an extension blockType, but
prefixing every additional field has no current V4 field collision to solve.
That rewrite changed captured keys to anticipate hypothetical future fields.

Retain every non-blockType field and value exactly, including already
prefixed names and own JSON keys. Keep the approved blockType identifier
prefix and the separate ToolSchema field policy unchanged. Update the local
conversion tests to verify both known and extension starts retain metadata
and to use the actual raw-record time field. Later field-specific conversion
belongs to a concrete source/target change instead of this edge.
2026-09-19 15:43:09 +08:00
Tianyi Cui 2833ff566e test(session): expect prefixed V3 opaque event identities on JSONL open
The JSONL retired-content admission matrix covers both historical V3 input
and native V4 input across read/write and plain/zstd storage. V3 migration
now prefixes unknown ignorable event identities with plugin:, while native
V4 reads retain their stored identity. The shared expectation still required
the unchanged V3 event tag and caused four deterministic CI failures.

Select the expected event type by input generation while retaining the full
payload, envelope, and immutable source-byte assertions. This corrects the
test for the intended migration without weakening native admission or
changing runtime behavior. The focused 20-case matrix now passes; restoring
the old expectation reproduces the same four failures locally.
2026-09-19 15:43:09 +08:00
Tianyi Cui bf29247fad fix(session): namespace historical V3 extensions with plugin prefixes
V3 permits external event, source and content identities and additional
request-tool fields. Copying those values into V4 can give an old plugin
named tool a core source identity, turn old tool-addition content into a
registry instruction, or activate formerly ignored deferLoading and delivery
metadata. Rejecting such collisions would instead refuse valid source logs.

Keep historical extensions in the existing extensible JSON representation.
Prefix unknown content and ignorable event tags with plugin:, preserving
all other content fields and opaque event payloads. Prefix external source
identities with plugin:plugin: or plugin:source: so wrapper and direct kinds
cannot collide even when original names already contain a category prefix.
Known first-party mappings remain explicit and unchanged.

Prefix extra request-tool field names and block-start field names with
plugin:, retaining exact values and existing-prefix doubling. Core schema
parameters, arguments, replay state and nested plugin data are not traversed.
Keep future-generation delivery records inactive after header promotion.
Pin the V3 event vocabulary independently of the current writer and provide
an offline verifier against an explicitly selected historical source commit.

Attachment authorization and export inspect declared event content only.
Team checkpoints preserve all own keys of unknown JSON blocks while still
rejecting malformed known content and retired core tool-result blocks.
Exercise physical read/write/reopen, prefix injectivity, own __proto__ keys,
provider opacity and retained source-identity snapshots.

No generic extension block, metadata wrapper or new schema-tooling type is
introduced. V4 type declarations, persistence schema, checkpoint and frozen
V0-V3 codecs remain unchanged. Canonical tool-result lifting and incomplete
child-catalog policy remain separate concerns.

Adapted from the extension-preservation work in 7ba7e174dd1 by Tianyi Cui.
Co-authored-by: Tianyi Cui <[email protected]>
2026-09-19 15:43:09 +08:00
Tianyi Cui cc970738d8 docs(session): scope checkpoint JSON preservation to domain reads
The cache reader preserves opaque JSON keys, but each projection still
parses the returned checkpoint through its own stateSchema before hydration.
State that ownership explicitly so documentation does not imply this reader
fix also changes projection-defined transformations or cloning behavior.

Distinguish the synthetic V7 StorageDomain regression fixture from released
cache archives. Describe its read, put and reopen path directly, and group
its JSON validation checks separately from archived-version recovery.
Translate the Chinese Agent Note headings and keep the paired docs aligned.
The note retains the borrowed-value tradeoff and links the independent
predecessor-format and lifecycle-identity decision.

Production expressions and all test assertions remain unchanged; only
contracts, fixture descriptions, test labels and grouping are clarified.
The fix does not add another persistence format or broaden migration scope.
2026-09-19 15:43:09 +08:00