You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Spec proposal 0018 (chain-ambiguity category) landed in spec
v0.16.0 between PR-4 push and the spec agent's code review.
This commit adds the new error category and the required
routing swaps; PR-4 stays open as the carrier.
- Submodule pinned to v0.16.0; pyproject + __spec_version__ +
test_smoke pin assertions follow.
- New canonical error class CheckpointStateMigrationChainAmbiguous
(and the matching category string) added to checkpoint/errors.py,
re-exported from openarmature.checkpoint. Non-transient. Carries
optional from_version / to_version when known (always set for
the registration-time case; resume-time multi-shortest-path also
populates).
- MigrationRegistry.register raises
CheckpointStateMigrationChainAmbiguous directly at registration
time per spec §10.10 (proposal 0018), so the canonical category
surfaces at the registration boundary without wrapping. The
internal BFS keeps raising ValueError for multi-shortest-path
detection; CompiledGraph._migrate_record's except branch now
routes that to CheckpointStateMigrationChainAmbiguous at the
resume boundary.
- Routing precedence on resume per §10.10 (v0.16.0): chain-ambiguous
→ missing → failed → record-invalid. Code-comment in
_migrate_record documents the ordering so a future reader
doesn't swap it back.
- Code comments record two design-choice notes the spec agent
flagged: the load-bearing equal-depth-re-entry behavior in BFS
cycle protection (tightening to <= breaks multi-shortest-path
detection), and the registration-order ordering of describe()
output.
- Conformance harness gains the expected_chain_ambiguity_error
primitive. Accepts the canonical category at EITHER the case
top-level (registration-time detection: registration raises,
resume block unreachable) OR inside resume (load-time detection
during BFS). Spec §10.12.2's compile-time-SHOULD /
load-time-acceptable carve-out lands in the driver as a
single try/except wrap around both phases.
- Fixture 047 (state-migration-chain-ambiguous) covered; all 9
state-migration fixtures (039-047) pass.
- 3 new unit tests for the new category's class shape +
attribute carriage; existing duplicate-pair tests updated to
assert the canonical category instead of ValueError.
- docs/concepts/checkpointing.md updated for the third category +
the v0.16.0 routing precedence. CHANGELOG entry updated and
Pinned-version line bumped to 0.10.0 → 0.16.0.
OTel openarmature.checkpoint.migrate span emission deferred to
a follow-on; documented inline in _migrate_record. Spec §6
cross-ref is SHOULD-level, and the emission needs the
_InvocationContext that's currently created AFTER the migration
path runs. The follow-on can either restructure resume to build
the context first or use a side-channel observer dispatch.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). The
8
8
9
9
### Added
10
10
11
-
- **State migration for checkpointed graphs (proposal 0014, introduced in spec v0.15.0).** Saved checkpoints whose `schema_version` doesn't match the current state class now route through a registered migration chain instead of failing on resume. Surface: `State.schema_version: ClassVar[str] = ""` (declare a non-empty value to opt in), `GraphBuilder.with_state_migration(from_version, to_version, migrate)` and `with_state_migrations(*migrations)` for registration, `StateMigration` and `MigrationRegistry` types exported from `openarmature.checkpoint`. Chain resolution is BFS over the registered edges; the shortest path wins. Multi-shortest-path ambiguity (e.g., a diamond `v1→v2→v4` + `v1→v3→v4`) surfaces as `CheckpointStateMigrationMissing` per spec §10.12.2's load-time-detection allowance. Two new error categories: `CheckpointStateMigrationMissing` (no chain bridges the versions, or chain ambiguous) and `CheckpointStateMigrationFailed` (a migration function raised). Both non-transient. Post-migration deserialization failures still route to `CheckpointRecordInvalid` per §10.12.4. The same chain applies to each entry in `parent_states` in lockstep with the outer state per §10.12.2.
11
+
- **State migration for checkpointed graphs (proposal 0014, introduced in spec v0.15.0; refined by proposal 0018 in spec v0.16.0).** Saved checkpoints whose `schema_version` doesn't match the current state class now route through a registered migration chain instead of failing on resume. Surface: `State.schema_version: ClassVar[str] = ""` (declare a non-empty value to opt in), `GraphBuilder.with_state_migration(from_version, to_version, migrate)` and `with_state_migrations(*migrations)` for registration, `StateMigration` and `MigrationRegistry` types exported from `openarmature.checkpoint`. Chain resolution is BFS over the registered edges; the shortest path wins. Three new error categories: `CheckpointStateMigrationChainAmbiguous` (proposal 0018: duplicate `(from, to)` pair at registration time, or multiple distinct shortest paths between the saved and current versions at resume time), `CheckpointStateMigrationMissing` (no chain bridges the versions), and `CheckpointStateMigrationFailed` (a migration function raised). All non-transient. Post-migration deserialization failures still route to `CheckpointRecordInvalid` per §10.12.4. The same chain applies to each entry in `parent_states` in lockstep with the outer state per §10.12.2. Routing precedence per §10.10 (v0.16.0): chain-ambiguous → missing → failed → record-invalid.
12
12
-**`Checkpointer.supports_state_migration` Protocol attribute.** Marks whether a backend can expose the structural intermediate form (a plain dict, JSON tree) the migration registry consumes. `SQLiteCheckpointer(serialization="json")` opts in; `SQLiteCheckpointer(serialization="pickle")` and `InMemoryCheckpointer` opt out. On version mismatch against a non-migration-eligible backend the engine raises `CheckpointRecordInvalid` per spec §10.12.1.
13
13
-**Prompt-management capability (proposal 0017, introduced in spec v0.15.0).** New `openarmature.prompts` subpackage. `PromptManager` composes one or more `PromptBackend`s, exposes `fetch` / `render` / `get`, applies the §8 fallback semantics (`prompt_store_unavailable` continues to the next backend; `prompt_not_found` stops the chain), and renders templates with Jinja2's `StrictUndefined` per §7. `Prompt` / `PromptResult` / `PromptGroup` are Pydantic models matching spec §3 / §4 / §9. Three error categories (`PromptNotFound`, `PromptRenderError`, `PromptStoreUnavailable`) with `PROMPT_TRANSIENT_CATEGORIES` exported for retry-middleware classifiers. `FilesystemPromptBackend` is the minimum local-filesystem reference backend (layout: `<root>/<label>/<name>.j2`; `version` derived from the first 16 hex chars of `template_hash`). New runtime dependency: `jinja2>=3.1`.
14
14
-**`openarmature.prompts.context` — observability propagation per spec §11.**`with_active_prompt(result)` and `with_active_prompt_group(group)` context managers + `current_prompt_result()` / `current_prompt_group()` inspectors. When the OTel observer is active and an LLM call fires inside `with_active_prompt`, the `openarmature.llm.complete` span carries the normative `openarmature.prompt.*` attributes (`name`, `version`, `label`, `template_hash`, `rendered_hash`, `group_name`). Nesting is innermost-wins.
@@ -24,7 +24,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). The
24
24
25
25
### Changed
26
26
27
-
-**Pinned spec version: 0.10.0 → 0.15.0.** Adopts the skip-ahead governance principle: the submodule jumps across v0.11.0–v0.15.0 (proposals 0009, 0011, 0014, 0015, 0016, 0017) in one bump. Only the surface introduced by proposal 0016 is implemented in this changelog entry; fixtures from 0011 / 0014 / 0015 / 0017 are marked deferred-skip in the conformance suite and unmark as their respective PRs land.
27
+
-**Pinned spec version: 0.10.0 → 0.16.0.** Adopts the skip-ahead governance principle: the submodule jumps across v0.11.0–v0.16.0 (proposals 0009, 0011, 0014, 0015, 0016, 0017, 0018) in one bump. Only the surfaces introduced by proposals 0014–0017 are implemented in the batch's release; fixtures from 0011 are deferred-skip in the conformance suite and unmark with PR-5.
28
28
-**`CheckpointRecord.schema_version` semantic shift (proposal 0014).** Previously a backend-internal record-shape version (`CHECKPOINT_SCHEMA_VERSION = "1"` constant), now the user-facing state-schema version per spec §10.2. The framework reads `type(state).schema_version` at save time. Pre-PR-4 records carrying `"1"` are reinterpreted as user-facing v1 identifiers; users with such records either declare `schema_version="1"` on their state class or discard the pre-PR-4 records. `SQLiteCheckpointer` no longer rejects records with non-default `schema_version` at the backend boundary; version-mismatch routing is now an engine concern at resume time. The `CHECKPOINT_SCHEMA_VERSION` module constant is removed; future record-shape evolution can add backend-private metadata fields if needed.
0 commit comments