Summary
Version the persisted task metadata (session.metadata.kagan) and migrate older payloads
on read, so evolving the metadata shape never silently drops task state.
Problem
All task state lives in session.metadata.kagan and is parsed through task.ts's
MetadataSchema. The schema tolerates drift only with per-field .catch(undefined)
(e.g. task.ts:313, task.ts:318). That means when a field is renamed or moved, an older
payload does not fail loudly — it silently parses to undefined and the task loses that
state, with no migration path. As the schema grows this gets riskier: a board that has
existed across several releases can carry a mix of old and new shapes.
Proposal
- Add an explicit
schemaVersion integer to the Kagan metadata.
- Add a migrate-on-read step in the parse path: before validation, upgrade a payload from
its recorded version to the current version through a chain of pure version-to-version
transforms.
- Transforms report whether they changed anything, so a caller can decide to persist the
upgraded shape back via patchKagan (write-back is optional; migrate-on-read alone keeps
behavior correct).
Design notes
- Migrate before validate, so an old shape never trips the current schema.
- Keep each transform a pure
payload -> payload function with a direct unit test; a bump
from vN-1 to vN adds one transform and one test.
- Retiring a field is an explicit step in the transform (drop it), not an implicit
.catch(undefined).
- Leave the per-field
.catch(undefined) as a last-resort guard against genuinely corrupt
data, not as the migration mechanism.
Acceptance criteria
- A metadata payload written at
vN-1 loads into a fully populated current parsed view
(no field silently lost to a rename/move).
- Every version bump ships its transform plus a unit test exercising an old payload.
- Loading a current-version payload is a no-op (idempotent).
Summary
Version the persisted task metadata (
session.metadata.kagan) and migrate older payloadson read, so evolving the metadata shape never silently drops task state.
Problem
All task state lives in
session.metadata.kaganand is parsed throughtask.ts'sMetadataSchema. The schema tolerates drift only with per-field.catch(undefined)(e.g.
task.ts:313,task.ts:318). That means when a field is renamed or moved, an olderpayload does not fail loudly — it silently parses to
undefinedand the task loses thatstate, with no migration path. As the schema grows this gets riskier: a board that has
existed across several releases can carry a mix of old and new shapes.
Proposal
schemaVersioninteger to the Kagan metadata.its recorded version to the current version through a chain of pure version-to-version
transforms.
upgraded shape back via
patchKagan(write-back is optional; migrate-on-read alone keepsbehavior correct).
Design notes
payload -> payloadfunction with a direct unit test; a bumpfrom
vN-1tovNadds one transform and one test..catch(undefined)..catch(undefined)as a last-resort guard against genuinely corruptdata, not as the migration mechanism.
Acceptance criteria
vN-1loads into a fully populated current parsed view(no field silently lost to a rename/move).