mirror of
https://github.com/instructkr/claw-code.git
synced 2026-04-27 20:24:58 +08:00
roadmap: #279 filed
This commit is contained in:
12
ROADMAP.md
12
ROADMAP.md
@@ -17141,3 +17141,15 @@ Discovery-pattern continuation: extends the structural-gap-without-source-change
|
|||||||
Required fix shape: (a) add a typed `SessionError::SchemaVersionMismatch { found: u32, expected: u32, policy: VersionPolicy }` variant where `VersionPolicy` is `Strict | MigrationAvailable | ForwardCompatibleReadOnly`; (b) at the top of `from_json` and after the `session_meta` parse in `from_jsonl`, compare the parsed `version` against `SESSION_VERSION` and short-circuit when not equal under the configured policy; (c) introduce a small `migrate_session(version: u32, raw: &JsonValue) -> Result<Session, SessionError>` table even if the only entry today is `1 -> 1` identity, so future versions land with one well-known extension point; (d) when loading a future version under a `ForwardCompatibleReadOnly` policy, refuse to write back to the same path (preserve the original) and surface a one-time warning; (e) extend tests to cover `version: 0` (rejected/migrated), `version: 2` (rejected or read-only), `version: 999` (rejected), and a missing `version` field (rejected with a clear message rather than silently defaulting to `SESSION_VERSION`); (f) add a session-version provenance line to `claw status` and `claw doctor` output (closes the #273/#275 surface gap for this specific schema-of-record dimension) so operators can inspect on-disk schema age vs binary schema age without scraping JSONL. Acceptance: a session file with any version other than `SESSION_VERSION` produces a typed, surface-visible diagnostic before any in-memory state is mutated; the migration table is the single extension point for future bumps; `claw status` and `claw doctor` show `session_schema_version` as a first-class provenance field.
|
Required fix shape: (a) add a typed `SessionError::SchemaVersionMismatch { found: u32, expected: u32, policy: VersionPolicy }` variant where `VersionPolicy` is `Strict | MigrationAvailable | ForwardCompatibleReadOnly`; (b) at the top of `from_json` and after the `session_meta` parse in `from_jsonl`, compare the parsed `version` against `SESSION_VERSION` and short-circuit when not equal under the configured policy; (c) introduce a small `migrate_session(version: u32, raw: &JsonValue) -> Result<Session, SessionError>` table even if the only entry today is `1 -> 1` identity, so future versions land with one well-known extension point; (d) when loading a future version under a `ForwardCompatibleReadOnly` policy, refuse to write back to the same path (preserve the original) and surface a one-time warning; (e) extend tests to cover `version: 0` (rejected/migrated), `version: 2` (rejected or read-only), `version: 999` (rejected), and a missing `version` field (rejected with a clear message rather than silently defaulting to `SESSION_VERSION`); (f) add a session-version provenance line to `claw status` and `claw doctor` output (closes the #273/#275 surface gap for this specific schema-of-record dimension) so operators can inspect on-disk schema age vs binary schema age without scraping JSONL. Acceptance: a session file with any version other than `SESSION_VERSION` produces a typed, surface-visible diagnostic before any in-memory state is mutated; the migration table is the single extension point for future bumps; `claw status` and `claw doctor` show `session_schema_version` as a first-class provenance field.
|
||||||
|
|
||||||
**Status:** Open. No source code changed. Filed 2026-04-26 16:34 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `4e4edc8` before filing (post fast-forward onto gaebal-gajae's #277 channel-resolution preflight). Cluster delta: founds NEW `persisted-schema-version-policy` cluster (1 member) on the persistence-layer axis. Cross-axis bundle with silent-fallback cluster (input vs persisted state, structurally-absent-error-kind) and with provenance quartet #259+#271+#273+#275 (emission vs load-validation of state-of-record). Concrete delta this cycle: ROADMAP-only pinpoint appended after static audit of `Session::from_json`/`Session::from_jsonl` version-handling arms — three call sites for `SESSION_VERSION` (1 declaration + 2 assignments, 0 comparisons), zero migration/mismatch sites in the entire `runtime/src/session.rs` file. Concurrent-dogfood-rebase parity will be confirmed local==origin==fork at HEAD `4e4edc8+#278` after push.
|
**Status:** Open. No source code changed. Filed 2026-04-26 16:34 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `4e4edc8` before filing (post fast-forward onto gaebal-gajae's #277 channel-resolution preflight). Cluster delta: founds NEW `persisted-schema-version-policy` cluster (1 member) on the persistence-layer axis. Cross-axis bundle with silent-fallback cluster (input vs persisted state, structurally-absent-error-kind) and with provenance quartet #259+#271+#273+#275 (emission vs load-validation of state-of-record). Concrete delta this cycle: ROADMAP-only pinpoint appended after static audit of `Session::from_json`/`Session::from_jsonl` version-handling arms — three call sites for `SESSION_VERSION` (1 declaration + 2 assignments, 0 comparisons), zero migration/mismatch sites in the entire `runtime/src/session.rs` file. Concurrent-dogfood-rebase parity will be confirmed local==origin==fork at HEAD `4e4edc8+#278` after push.
|
||||||
|
|
||||||
|
## Pinpoint #279 — Session loader silently drops unknown fields inside known JSON/JSONL records with no extension policy or preservation map, so future schema data can be erased even if #278 adds version checks later
|
||||||
|
|
||||||
|
Dogfooded 2026-04-26 17:02 KST on `feat/jobdori-168c-emission-routing` at HEAD `6c154c9` (post-#278). Static audit of `rust/crates/runtime/src/session.rs` shows the loader rejects unknown top-level JSONL record `type` values (`unsupported JSONL record type` at lines 476-480), but for known records it cherry-picks recognized fields and drops all extras. `Session::from_json` reads `version`, `messages`, timestamps, `compaction`, `fork`, `workspace_root`, `prompt_history`, and `model`, then constructs `Session` with no `extensions` / `unknown_fields` preservation. `from_jsonl` does the same for `session_meta`, `message`, `compaction`, and `prompt_history`: any future field inside a known record (for example #268's `tool_catalog_revision`, #272's `ZeroTurnInvocation`, or #273's workspace provenance) is ignored on load and omitted on the next save/render.
|
||||||
|
|
||||||
|
Concrete failure mode: a future v2 session can add fields under known record types and be loaded by a v1 binary without an error, warning, or preservation. If the session is later saved/rotated/compacted, those fields disappear. #278 catches that the `version` tag itself is never compared, but even with a version comparison policy the field-level behavior needs a separate contract: should unknown fields in known records be rejected, preserved, quarantined, or ignored? Today the answer is implicit silent data loss.
|
||||||
|
|
||||||
|
Gap. The session persistence format lacks an extension/unknown-field policy. It is neither strict (fail on unknown fields in known records) nor forward-compatible (preserve unknown fields for round-trip) nor explicitly lossy (emit a warning/receipt when dropping them). This is distinct from #278, which targets the `version` field not being compared; #279 targets the per-record field preservation policy after a record type is accepted. It is also distinct from #259/#273 provenance emission gaps: this is load/save behavior for persisted state-of-record.
|
||||||
|
|
||||||
|
Required fix shape: (a) define a schema policy for unknown fields in known session records: strict reject for incompatible versions OR lossless preservation via `extensions: BTreeMap<String, JsonValue>`; (b) if rejecting, include record type, line number, and field names in a typed `SessionSchemaError::UnknownFields`; (c) if preserving, round-trip unknown fields through `to_json`, `render_jsonl_snapshot`, compaction, and rotation; (d) add `schema_extensions_dropped` warning telemetry if any field is intentionally ignored; (e) regression-test JSON and JSONL sessions containing a future `tool_catalog_revision` field inside `session_meta` and a future per-message field, proving they either fail typed or survive a load-save round-trip. Acceptance: a future schema field in a known record can never disappear silently.
|
||||||
|
|
||||||
|
**Status:** Open. No source code changed. Filed 2026-04-26 17:02 KST. Branch: feat/jobdori-168c-emission-routing. HEAD: `6c154c9` before filing. Cluster delta: persisted-schema-version-policy 1→2 (#278 version-comparison + #279 unknown-field policy); sibling to #278, distinct field-preservation layer. Concrete delta this cycle: ROADMAP-only pinpoint appended after static audit of `Session::from_json` / `from_jsonl` field selection.
|
||||||
|
|||||||
Reference in New Issue
Block a user