renderplan 0.1.1__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/events/events.jsonl +7 -0
  2. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/releases/v0.1.1/release.md +4 -4
  3. renderplan-0.1.2/.ledger/releaseledger/data/ledgers/main/releases/v0.1.2/audit/commit-audit.yaml +44 -0
  4. renderplan-0.1.2/.ledger/releaseledger/data/ledgers/main/releases/v0.1.2/entries/entry-0001.md +31 -0
  5. renderplan-0.1.2/.ledger/releaseledger/data/ledgers/main/releases/v0.1.2/release.md +27 -0
  6. renderplan-0.1.2/.ledger/releaseledger/work/v0.1.2/audit-decisions.yaml +20 -0
  7. renderplan-0.1.2/.ledger/releaseledger/work/v0.1.2/audit.yaml +33 -0
  8. renderplan-0.1.2/.ledger/releaseledger/work/v0.1.2/entries.yaml +28 -0
  9. renderplan-0.1.2/.ledger/releaseledger/work/v0.1.2/evidence/f88173e.patch +123 -0
  10. renderplan-0.1.2/.ledger/releaseledger/work/v0.1.2/evidence/manifest.json +29 -0
  11. renderplan-0.1.2/.ledger/releaseledger/work/v0.1.2/range.json +13 -0
  12. {renderplan-0.1.1 → renderplan-0.1.2}/PKG-INFO +1 -1
  13. {renderplan-0.1.1 → renderplan-0.1.2}/docs/changelog.md +9 -1
  14. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/_version.py +3 -3
  15. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/collection.py +1 -1
  16. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/validation.py +8 -4
  17. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan.egg-info/PKG-INFO +1 -1
  18. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan.egg-info/SOURCES.txt +9 -0
  19. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan.egg-info/scm_file_list.json +9 -0
  20. renderplan-0.1.2/renderplan.egg-info/scm_version.json +8 -0
  21. {renderplan-0.1.1 → renderplan-0.1.2}/tests/test_collection.py +37 -0
  22. {renderplan-0.1.1 → renderplan-0.1.2}/tests/test_contracts.py +7 -0
  23. {renderplan-0.1.1 → renderplan-0.1.2}/tests/test_renderplan_set.py +2 -0
  24. renderplan-0.1.1/renderplan.egg-info/scm_version.json +0 -8
  25. {renderplan-0.1.1 → renderplan-0.1.2}/.codecrate.toml +0 -0
  26. {renderplan-0.1.1 → renderplan-0.1.2}/.github/workflows/codecov.yml +0 -0
  27. {renderplan-0.1.1 → renderplan-0.1.2}/.github/workflows/pre-commit.yml +0 -0
  28. {renderplan-0.1.1 → renderplan-0.1.2}/.github/workflows/python-publish.yml +0 -0
  29. {renderplan-0.1.1 → renderplan-0.1.2}/.github/workflows/tests.yml +0 -0
  30. {renderplan-0.1.1 → renderplan-0.1.2}/.gitignore +0 -0
  31. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/ledger.toml +0 -0
  32. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/.ledger-project.toml +0 -0
  33. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/config.toml +0 -0
  34. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/.ledger-project.toml +0 -0
  35. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/releases/v0.1.0/audit/commit-audit.yaml +0 -0
  36. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/releases/v0.1.0/entries/entry-0001.md +0 -0
  37. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/releases/v0.1.0/entries/entry-0002.md +0 -0
  38. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/releases/v0.1.0/entries/entry-0003.md +0 -0
  39. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/releases/v0.1.0/entries/entry-0004.md +0 -0
  40. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/releases/v0.1.0/release.md +0 -0
  41. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/releases/v0.1.1/audit/commit-audit.yaml +0 -0
  42. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/releases/v0.1.1/entries/entry-0001.md +0 -0
  43. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/data/ledgers/main/releases/v0.1.1/entries/entry-0002.md +0 -0
  44. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/work/v0.1.1/audit-decisions.yaml +0 -0
  45. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/work/v0.1.1/audit.yaml +0 -0
  46. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/work/v0.1.1/entries.yaml +0 -0
  47. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/work/v0.1.1/evidence/0e39bcd.patch +0 -0
  48. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/work/v0.1.1/evidence/f27def9.patch +0 -0
  49. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/work/v0.1.1/evidence/manifest.json +0 -0
  50. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/work/v0.1.1/range.json +0 -0
  51. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/releaseledger/write.lock +0 -0
  52. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/taskledger/.ledger-project.toml +0 -0
  53. {renderplan-0.1.1 → renderplan-0.1.2}/.ledger/taskledger/config.toml +0 -0
  54. {renderplan-0.1.1 → renderplan-0.1.2}/.pre-commit-config.yaml +0 -0
  55. {renderplan-0.1.1 → renderplan-0.1.2}/LICENSE +0 -0
  56. {renderplan-0.1.1 → renderplan-0.1.2}/README.md +0 -0
  57. {renderplan-0.1.1 → renderplan-0.1.2}/docs/Makefile +0 -0
  58. {renderplan-0.1.1 → renderplan-0.1.2}/docs/conf.py +0 -0
  59. {renderplan-0.1.1 → renderplan-0.1.2}/docs/make.bat +0 -0
  60. {renderplan-0.1.1 → renderplan-0.1.2}/docs/make.py +0 -0
  61. {renderplan-0.1.1 → renderplan-0.1.2}/docs/requirements.txt +0 -0
  62. {renderplan-0.1.1 → renderplan-0.1.2}/examples/af_heart.renderprofile.toml +0 -0
  63. {renderplan-0.1.1 → renderplan-0.1.2}/examples/chapter.preflight.toml +0 -0
  64. {renderplan-0.1.1 → renderplan-0.1.2}/examples/chapter.render-manifest.toml +0 -0
  65. {renderplan-0.1.1 → renderplan-0.1.2}/examples/chapter.renderplan.toml +0 -0
  66. {renderplan-0.1.1 → renderplan-0.1.2}/examples/chapter.replan.preflight.toml +0 -0
  67. {renderplan-0.1.1 → renderplan-0.1.2}/pyproject.toml +0 -0
  68. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/__init__.py +0 -0
  69. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/__main__.py +0 -0
  70. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/_toml.py +0 -0
  71. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/cli.py +0 -0
  72. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/codec.py +0 -0
  73. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/contracts.py +0 -0
  74. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/errors.py +0 -0
  75. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/identity.py +0 -0
  76. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/model.py +0 -0
  77. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/paths.py +0 -0
  78. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/py.typed +0 -0
  79. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/set.py +0 -0
  80. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan/version.py +0 -0
  81. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan.egg-info/dependency_links.txt +0 -0
  82. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan.egg-info/entry_points.txt +0 -0
  83. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan.egg-info/requires.txt +0 -0
  84. {renderplan-0.1.1 → renderplan-0.1.2}/renderplan.egg-info/top_level.txt +0 -0
  85. {renderplan-0.1.1 → renderplan-0.1.2}/setup.cfg +0 -0
  86. {renderplan-0.1.1 → renderplan-0.1.2}/tests/test_identity.py +0 -0
@@ -9,3 +9,10 @@
9
9
  {"data":{"row_count":2},"event":"audit.created","event_id":"event-0009","record_revisions":{"commit_audit_sheet":1},"release_version":"v0.1.1","schema_version":2}
10
10
  {"data":{"updated_rows":2},"event":"audit.updated","event_id":"event-0010","record_revisions":{"commit_audit_sheet":2},"release_version":"v0.1.1","schema_version":2}
11
11
  {"data":{"entry_ids":["entry-0001","entry-0002"],"synced_audit_rows":2},"event":"entry.batch_added","event_id":"event-0011","record_revisions":{"commit_audit_sheet":3,"entry:v0.1.1/entry-0001":1,"entry:v0.1.1/entry-0002":1,"release:v0.1.1":3},"release_version":"v0.1.1","schema_version":2}
12
+ {"data":{"status":"planned"},"event":"release.created","event_id":"event-0012","record_revisions":{"release:v0.1.2":1},"release_version":"v0.1.2","schema_version":2}
13
+ {"data":{"fields":["git_base_ref","git_base_sha","git_commit_count","git_head_ref","git_head_sha","git_range"]},"event":"release.updated","event_id":"event-0013","record_revisions":{"release:v0.1.2":2},"release_version":"v0.1.2","schema_version":2}
14
+ {"data":{"row_count":1},"event":"audit.created","event_id":"event-0014","record_revisions":{"commit_audit_sheet":1},"release_version":"v0.1.2","schema_version":2}
15
+ {"data":{"updated_rows":1},"event":"audit.updated","event_id":"event-0015","record_revisions":{"commit_audit_sheet":2},"release_version":"v0.1.2","schema_version":2}
16
+ {"data":{"entry_ids":["entry-0001"],"synced_audit_rows":1},"event":"entry.batch_added","event_id":"event-0016","record_revisions":{"commit_audit_sheet":3,"entry:v0.1.2/entry-0001":1,"release:v0.1.2":3},"release_version":"v0.1.2","schema_version":2}
17
+ {"data":{"released_at":"2026-10-13"},"event":"release.finalized","event_id":"event-0017","record_revisions":{"release:v0.1.1":4},"release_version":"v0.1.1","schema_version":2}
18
+ {"data":{"released_at":"2026-10-14"},"event":"release.finalized","event_id":"event-0018","record_revisions":{"release:v0.1.2":4},"release_version":"v0.1.2","schema_version":2}
@@ -3,16 +3,16 @@ schema_version: 2
3
3
  object_type: release
4
4
  versioning:
5
5
  schema_version: 1
6
- revision: 3
6
+ revision: 4
7
7
  version: v0.1.1
8
- status: planned
8
+ status: released
9
9
  history_state: curated
10
10
  title: null
11
- released_at: null
11
+ released_at: "2026-10-13"
12
12
  previous_version: v0.1.0
13
13
  cancel_reason: null
14
14
  superseded_by: null
15
- changelog_file: null
15
+ changelog_file: docs/changelog.md
16
16
  boundary_ref: null
17
17
  source_refs: []
18
18
  source_count: null
@@ -0,0 +1,44 @@
1
+ schema_version: 1
2
+ object_type: commit_audit_sheet
3
+ versioning:
4
+ schema_version: 1
5
+ revision: 3
6
+ release_version: v0.1.2
7
+ git_base_ref: v0.1.1
8
+ git_base_sha: 2aab3cc46e452bb6b7fad46999d05d47d6e466a3
9
+ git_head_ref: HEAD
10
+ git_head_sha: f88173e8514ac2f095efc9793f35bddd7d0b5937
11
+ git_range: 2aab3cc46e452bb6b7fad46999d05d47d6e466a3..f88173e8514ac2f095efc9793f35bddd7d0b5937
12
+ commit_count: 1
13
+ rows:
14
+ - sha: f88173e8514ac2f095efc9793f35bddd7d0b5937
15
+ source_ref: git:f88173e8514ac2f095efc9793f35bddd7d0b5937
16
+ short_sha: f88173e
17
+ changed_paths:
18
+ - renderplan/collection.py
19
+ - renderplan/validation.py
20
+ - tests/test_collection.py
21
+ - tests/test_contracts.py
22
+ - tests/test_renderplan_set.py
23
+ stats:
24
+ files_changed: 5
25
+ insertions: 52
26
+ deletions: 6
27
+ inspected: true
28
+ inspected_paths:
29
+ - renderplan/collection.py
30
+ - renderplan/validation.py
31
+ - tests/test_collection.py
32
+ - tests/test_contracts.py
33
+ - tests/test_renderplan_set.py
34
+ observed_behavior:
35
+ RenderPlan-set validation now matches chapters by ID and full
36
+ identity, requires persisted plan identities, and exposes the collection contract
37
+ from the package root; RenderPlanSetError also remains compatible with ValueError
38
+ callers.
39
+ public_impact: public
40
+ decision: accepted
41
+ stale: false
42
+ evidence_subject: "feat: small improvements"
43
+ target_entry_id: entry-0001
44
+ notes: Reviewed the implementation changes and their focused regression tests.
@@ -0,0 +1,31 @@
1
+ ---
2
+ schema_version: 2
3
+ object_type: release_entry
4
+ versioning:
5
+ schema_version: 1
6
+ revision: 1
7
+ entry_id: entry-0001
8
+ release_version: v0.1.2
9
+ kind: changed
10
+ summary: Changed RenderPlan-set identity validation and exported the collection contract
11
+ status: accepted
12
+ audience: null
13
+ scopes: []
14
+ source_refs:
15
+ - git:f88173e8514ac2f095efc9793f35bddd7d0b5937
16
+ paths:
17
+ - renderplan/collection.py
18
+ - renderplan/validation.py
19
+ - tests/test_collection.py
20
+ - tests/test_contracts.py
21
+ - tests/test_renderplan_set.py
22
+ issues: []
23
+ prs: []
24
+ sources:
25
+ - git:f88173e8514ac2f095efc9793f35bddd7d0b5937
26
+ contributors:
27
+ - "@holgern"
28
+ breaking: false
29
+ internal: false
30
+ order: 1
31
+ ---
@@ -0,0 +1,27 @@
1
+ ---
2
+ schema_version: 2
3
+ object_type: release
4
+ versioning:
5
+ schema_version: 1
6
+ revision: 4
7
+ version: v0.1.2
8
+ status: released
9
+ history_state: curated
10
+ title: null
11
+ released_at: "2026-10-14"
12
+ previous_version: v0.1.1
13
+ cancel_reason: null
14
+ superseded_by: null
15
+ changelog_file: docs/changelog.md
16
+ boundary_ref: null
17
+ source_refs: []
18
+ source_count: null
19
+ entry_count: 1
20
+ artifact_count: 0
21
+ git_base_ref: v0.1.1
22
+ git_base_sha: 2aab3cc46e452bb6b7fad46999d05d47d6e466a3
23
+ git_head_ref: HEAD
24
+ git_head_sha: f88173e8514ac2f095efc9793f35bddd7d0b5937
25
+ git_range: 2aab3cc46e452bb6b7fad46999d05d47d6e466a3..f88173e8514ac2f095efc9793f35bddd7d0b5937
26
+ git_commit_count: 1
27
+ ---
@@ -0,0 +1,20 @@
1
+ rows:
2
+ - sha: f88173e8514ac2f095efc9793f35bddd7d0b5937
3
+ inspected: true
4
+ inspected_paths:
5
+ - renderplan/collection.py
6
+ - renderplan/validation.py
7
+ - tests/test_collection.py
8
+ - tests/test_contracts.py
9
+ - tests/test_renderplan_set.py
10
+ observed_behavior: >-
11
+ RenderPlan-set validation now matches chapters by ID and full identity,
12
+ requires persisted plan identities, and exposes the collection contract
13
+ from the package root; RenderPlanSetError also remains compatible with
14
+ ValueError callers.
15
+ public_impact: public
16
+ decision: accepted
17
+ target_entry_key: null
18
+ target_entry_id: null
19
+ notes: Reviewed the implementation changes and their focused regression tests.
20
+ stale: false
@@ -0,0 +1,33 @@
1
+ schema_version: 1
2
+ object_type: commit_audit_sheet
3
+ versioning:
4
+ schema_version: 1
5
+ revision: 1
6
+ release_version: v0.1.2
7
+ git_base_ref: v0.1.1
8
+ git_base_sha: 2aab3cc46e452bb6b7fad46999d05d47d6e466a3
9
+ git_head_ref: HEAD
10
+ git_head_sha: f88173e8514ac2f095efc9793f35bddd7d0b5937
11
+ git_range: 2aab3cc46e452bb6b7fad46999d05d47d6e466a3..f88173e8514ac2f095efc9793f35bddd7d0b5937
12
+ commit_count: 1
13
+ rows:
14
+ - sha: f88173e8514ac2f095efc9793f35bddd7d0b5937
15
+ source_ref: git:f88173e8514ac2f095efc9793f35bddd7d0b5937
16
+ short_sha: f88173e
17
+ changed_paths:
18
+ - renderplan/collection.py
19
+ - renderplan/validation.py
20
+ - tests/test_collection.py
21
+ - tests/test_contracts.py
22
+ - tests/test_renderplan_set.py
23
+ stats:
24
+ files_changed: 5
25
+ insertions: 52
26
+ deletions: 6
27
+ inspected: false
28
+ inspected_paths: []
29
+ observed_behavior: ""
30
+ public_impact: unknown
31
+ decision: needs_review
32
+ stale: false
33
+ evidence_subject: "feat: small improvements"
@@ -0,0 +1,28 @@
1
+ schema: releaseledger.entry-batch.v1
2
+ operation: create
3
+ schema_version: 1
4
+ object_type: release_entry_batch
5
+ release_version: v0.1.2
6
+ git_base_ref: 2aab3cc46e452bb6b7fad46999d05d47d6e466a3
7
+ git_base_sha: 2aab3cc46e452bb6b7fad46999d05d47d6e466a3
8
+ git_head_ref: f88173e8514ac2f095efc9793f35bddd7d0b5937
9
+ git_head_sha: f88173e8514ac2f095efc9793f35bddd7d0b5937
10
+ include_merges: nontrivial
11
+ entries:
12
+ - kind: changed
13
+ summary: Changed RenderPlan-set identity validation and exported the collection contract
14
+ status: accepted
15
+ source_refs:
16
+ - git:f88173e8514ac2f095efc9793f35bddd7d0b5937
17
+ paths:
18
+ - renderplan/collection.py
19
+ - renderplan/validation.py
20
+ - tests/test_collection.py
21
+ - tests/test_contracts.py
22
+ - tests/test_renderplan_set.py
23
+ sources:
24
+ - git:f88173e8514ac2f095efc9793f35bddd7d0b5937
25
+ prs: []
26
+ issues: []
27
+ contributors:
28
+ - "@holgern"
@@ -0,0 +1,123 @@
1
+ renderplan/collection.py | 2 +-
2
+ renderplan/validation.py | 11 ++++++-----
3
+ tests/test_collection.py | 37 +++++++++++++++++++++++++++++++++++++
4
+ tests/test_contracts.py | 7 +++++++
5
+ tests/test_renderplan_set.py | 1 +
6
+ 5 files changed, 52 insertions(+), 6 deletions(-)
7
+
8
+ diff --git a/renderplan/collection.py b/renderplan/collection.py
9
+ index 5c0c795..0514799 100644
10
+ --- a/renderplan/collection.py
11
+ +++ b/renderplan/collection.py
12
+ @@ -26,7 +26,7 @@ _PROFILE_ID_RE = re.compile(r"^sha256:[0-9a-f]{64}$")
13
+ _FINGERPRINT_RE = re.compile(r"^[0-9a-f]{12}$")
14
+
15
+
16
+ -class RenderPlanSetError(RenderPlanError):
17
+ +class RenderPlanSetError(RenderPlanError, ValueError):
18
+ """Invalid, unreadable, or unwritable RenderPlan-set metadata."""
19
+
20
+ def __init__(self, message: str, *, code: str = "index.invalid") -> None:
21
+ diff --git a/renderplan/validation.py b/renderplan/validation.py
22
+ index e60e791..2336436 100644
23
+ --- a/renderplan/validation.py
24
+ +++ b/renderplan/validation.py
25
+ @@ -37,17 +37,18 @@ def validate_set_chapter_plan(
26
+ ) -> None:
27
+ """Validate a chapter's plan and profile identities against its containing set."""
28
+ validate_renderplan_set(renderplan_set)
29
+ - if chapter not in renderplan_set.chapters:
30
+ - raise ValidationError("chapter is not a member of the RenderPlan set")
31
+ - actual_plan_id = plan.plan_id or plan.computed_id()
32
+ - if chapter.render_plan_id != actual_plan_id:
33
+ + member = next(
34
+ + (candidate for candidate in renderplan_set.chapters if candidate.id == chapter.id), None
35
+ + )
36
+ + if member is None or member != chapter:
37
+ + raise ValidationError("chapter is not a member of the RenderPlan set by ID and identity")
38
+ + if chapter.render_plan_id != plan.plan_id:
39
+ raise ValidationError("chapter render_plan_id does not match the RenderPlan")
40
+ if chapter.source_plan_id != plan.source_plan_id:
41
+ raise ValidationError("chapter source_plan_id does not match the RenderPlan")
42
+ if plan.render_profile_id != renderplan_set.profile_id:
43
+ raise ValidationError("RenderPlan render_profile_id does not match the RenderPlan set")
44
+
45
+ -
46
+ __all__ = [
47
+ "validate_manifest_handoff",
48
+ "validate_plan_profile",
49
+ diff --git a/tests/test_collection.py b/tests/test_collection.py
50
+ index 2b428b8..13c3123 100644
51
+ --- a/tests/test_collection.py
52
+ +++ b/tests/test_collection.py
53
+ @@ -28,6 +28,43 @@ SOURCE_PLAN_ID = "sha256:" + "b" * 64
54
+ RENDER_PLAN_ID = "sha256:" + "c" * 64
55
+
56
+
57
+ +
58
+ +def test_renderplan_set_contract_is_exported_from_package_root() -> None:
59
+ + from renderplan import (
60
+ + RENDERPLAN_SET_FORMAT,
61
+ + RENDERPLAN_SET_VERSION,
62
+ + RenderPlanSet,
63
+ + RenderPlanSetChapter,
64
+ + RenderPlanSetError,
65
+ + load_renderplan_set,
66
+ + renderplan_set_from_dict,
67
+ + renderplan_set_to_dict,
68
+ + renderplan_set_to_toml,
69
+ + save_renderplan_set,
70
+ + validate_renderplan_set,
71
+ + validate_renderplan_set_profile,
72
+ + validate_set_chapter_plan,
73
+ + )
74
+ +
75
+ + assert RENDERPLAN_SET_FORMAT == "renderplan-set"
76
+ + assert RENDERPLAN_SET_VERSION == 1
77
+ + assert all(
78
+ + callable(symbol)
79
+ + for symbol in (
80
+ + RenderPlanSet,
81
+ + RenderPlanSetChapter,
82
+ + RenderPlanSetError,
83
+ + load_renderplan_set,
84
+ + renderplan_set_from_dict,
85
+ + renderplan_set_to_dict,
86
+ + renderplan_set_to_toml,
87
+ + save_renderplan_set,
88
+ + validate_renderplan_set,
89
+ + validate_renderplan_set_profile,
90
+ + validate_set_chapter_plan,
91
+ + )
92
+ + )
93
+ +
94
+ def _profile(binding: str = "fixture") -> RenderProfile:
95
+ return RenderProfile(
96
+ roles={"narrator": RoleProfile(language="en-US", binding={"engine": binding})},
97
+ diff --git a/tests/test_contracts.py b/tests/test_contracts.py
98
+ index 47ded93..3119425 100644
99
+ --- a/tests/test_contracts.py
100
+ +++ b/tests/test_contracts.py
101
+ @@ -742,3 +742,10 @@ def test_validate_set_chapter_plan_checks_all_identity_edges() -> None:
102
+ )
103
+ with pytest.raises(ValidationError, match="render_profile_id"):
104
+ validate_set_chapter_plan(wrong_profile_set, chapter, render_plan)
105
+ + forged_chapter = replace(chapter, renderplan="other.renderplan.toml")
106
+ + with pytest.raises(ValidationError, match="not a member"):
107
+ + validate_set_chapter_plan(renderplan_set, forged_chapter, render_plan)
108
+ +
109
+ + unpersisted_plan = replace(render_plan, plan_id=None)
110
+ + with pytest.raises(ValidationError, match="render_plan_id"):
111
+ + validate_set_chapter_plan(renderplan_set, chapter, unpersisted_plan)
112
+ diff --git a/tests/test_renderplan_set.py b/tests/test_renderplan_set.py
113
+ index f15f174..8bfaca1 100644
114
+ --- a/tests/test_renderplan_set.py
115
+ +++ b/tests/test_renderplan_set.py
116
+ @@ -132,6 +132,7 @@ def test_renderplan_set_error_is_a_renderplan_error() -> None:
117
+ with pytest.raises(RenderPlanError):
118
+ replace(_set(), profile_fingerprint="bad")
119
+
120
+ + assert issubclass(RenderPlanSetError, ValueError)
121
+
122
+ def test_renderplan_set_profile_validation_distinguishes_identity_failures(
123
+ tmp_path: Path,
@@ -0,0 +1,29 @@
1
+ {
2
+ "candidate_count": 1,
3
+ "candidates": [
4
+ {
5
+ "additions": 52,
6
+ "deletions": 6,
7
+ "patch_file": "f88173e.patch",
8
+ "patch_sha256": "1d80d2bc3ed754a0c39fbab6b64f5a0e5f6f36944c6eace903ef0a48d1e8a85c",
9
+ "paths": [
10
+ "renderplan/collection.py",
11
+ "renderplan/validation.py",
12
+ "tests/test_collection.py",
13
+ "tests/test_contracts.py",
14
+ "tests/test_renderplan_set.py"
15
+ ],
16
+ "sha": "f88173e8514ac2f095efc9793f35bddd7d0b5937",
17
+ "short_sha": "f88173e",
18
+ "source_ref": "git:f88173e8514ac2f095efc9793f35bddd7d0b5937"
19
+ }
20
+ ],
21
+ "git_base_ref": "2aab3cc46e452bb6b7fad46999d05d47d6e466a3",
22
+ "git_base_sha": "2aab3cc46e452bb6b7fad46999d05d47d6e466a3",
23
+ "git_head_ref": "f88173e8514ac2f095efc9793f35bddd7d0b5937",
24
+ "git_head_sha": "f88173e8514ac2f095efc9793f35bddd7d0b5937",
25
+ "include_merges": "nontrivial",
26
+ "object_type": "git_evidence_manifest",
27
+ "release_version": "v0.1.2",
28
+ "schema_version": 1
29
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "base_ref": "2aab3cc46e452bb6b7fad46999d05d47d6e466a3",
3
+ "base_sha": "2aab3cc46e452bb6b7fad46999d05d47d6e466a3",
4
+ "candidate_count": 1,
5
+ "commit_count": 1,
6
+ "head_ref": "f88173e8514ac2f095efc9793f35bddd7d0b5937",
7
+ "head_sha": "f88173e8514ac2f095efc9793f35bddd7d0b5937",
8
+ "include_merges": "nontrivial",
9
+ "kind": "git_range_summary",
10
+ "merge_commit_count": 0,
11
+ "merge_commits_skipped": 0,
12
+ "range": "2aab3cc46e452bb6b7fad46999d05d47d6e466a3..f88173e8514ac2f095efc9793f35bddd7d0b5937"
13
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: renderplan
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Engine-neutral render profile, plan, preflight, manifest, and collection contracts for speech pipelines.
5
5
  Classifier: Development Status :: 3 - Alpha
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,6 +1,14 @@
1
1
  # Changelog
2
2
 
3
- ## [v0.1.1] - Unreleased
3
+ ## [v0.1.2] - 2026-10-14
4
+
5
+ ### Changed
6
+
7
+ - Changed RenderPlan-set identity validation and exported the collection contract
8
+
9
+ <!-- generated by releaseledger -->
10
+
11
+ ## [v0.1.1] - 2026-10-13
4
12
 
5
13
  ### Added
6
14
 
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.1.1'
22
- __version_tuple__ = version_tuple = (0, 1, 1)
21
+ __version__ = version = '0.1.2'
22
+ __version_tuple__ = version_tuple = (0, 1, 2)
23
23
 
24
- __commit_id__ = commit_id = 'g2aab3cc46'
24
+ __commit_id__ = commit_id = 'gc2981a645'
@@ -26,7 +26,7 @@ _PROFILE_ID_RE = re.compile(r"^sha256:[0-9a-f]{64}$")
26
26
  _FINGERPRINT_RE = re.compile(r"^[0-9a-f]{12}$")
27
27
 
28
28
 
29
- class RenderPlanSetError(RenderPlanError):
29
+ class RenderPlanSetError(RenderPlanError, ValueError):
30
30
  """Invalid, unreadable, or unwritable RenderPlan-set metadata."""
31
31
 
32
32
  def __init__(self, message: str, *, code: str = "index.invalid") -> None:
@@ -37,10 +37,14 @@ def validate_set_chapter_plan(
37
37
  ) -> None:
38
38
  """Validate a chapter's plan and profile identities against its containing set."""
39
39
  validate_renderplan_set(renderplan_set)
40
- if chapter not in renderplan_set.chapters:
41
- raise ValidationError("chapter is not a member of the RenderPlan set")
42
- actual_plan_id = plan.plan_id or plan.computed_id()
43
- if chapter.render_plan_id != actual_plan_id:
40
+ member = next(
41
+ (candidate for candidate in renderplan_set.chapters if candidate.id == chapter.id), None
42
+ )
43
+ if member is None or member != chapter:
44
+ raise ValidationError(
45
+ "chapter is not a member of the RenderPlan set by ID and identity"
46
+ )
47
+ if chapter.render_plan_id != plan.plan_id:
44
48
  raise ValidationError("chapter render_plan_id does not match the RenderPlan")
45
49
  if chapter.source_plan_id != plan.source_plan_id:
46
50
  raise ValidationError("chapter source_plan_id does not match the RenderPlan")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: renderplan
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Engine-neutral render profile, plan, preflight, manifest, and collection contracts for speech pipelines.
5
5
  Classifier: Development Status :: 3 - Alpha
6
6
  Classifier: Programming Language :: Python :: 3
@@ -24,6 +24,9 @@ pyproject.toml
24
24
  .ledger/releaseledger/data/ledgers/main/releases/v0.1.1/audit/commit-audit.yaml
25
25
  .ledger/releaseledger/data/ledgers/main/releases/v0.1.1/entries/entry-0001.md
26
26
  .ledger/releaseledger/data/ledgers/main/releases/v0.1.1/entries/entry-0002.md
27
+ .ledger/releaseledger/data/ledgers/main/releases/v0.1.2/release.md
28
+ .ledger/releaseledger/data/ledgers/main/releases/v0.1.2/audit/commit-audit.yaml
29
+ .ledger/releaseledger/data/ledgers/main/releases/v0.1.2/entries/entry-0001.md
27
30
  .ledger/releaseledger/work/v0.1.1/audit-decisions.yaml
28
31
  .ledger/releaseledger/work/v0.1.1/audit.yaml
29
32
  .ledger/releaseledger/work/v0.1.1/entries.yaml
@@ -31,6 +34,12 @@ pyproject.toml
31
34
  .ledger/releaseledger/work/v0.1.1/evidence/0e39bcd.patch
32
35
  .ledger/releaseledger/work/v0.1.1/evidence/f27def9.patch
33
36
  .ledger/releaseledger/work/v0.1.1/evidence/manifest.json
37
+ .ledger/releaseledger/work/v0.1.2/audit-decisions.yaml
38
+ .ledger/releaseledger/work/v0.1.2/audit.yaml
39
+ .ledger/releaseledger/work/v0.1.2/entries.yaml
40
+ .ledger/releaseledger/work/v0.1.2/range.json
41
+ .ledger/releaseledger/work/v0.1.2/evidence/f88173e.patch
42
+ .ledger/releaseledger/work/v0.1.2/evidence/manifest.json
34
43
  .ledger/taskledger/.ledger-project.toml
35
44
  .ledger/taskledger/config.toml
36
45
  docs/Makefile
@@ -21,6 +21,9 @@
21
21
  ".ledger/releaseledger/data/ledgers/main/releases/v0.1.1/entries/entry-0001.md",
22
22
  ".ledger/releaseledger/data/ledgers/main/releases/v0.1.1/entries/entry-0002.md",
23
23
  ".ledger/releaseledger/data/ledgers/main/releases/v0.1.1/release.md",
24
+ ".ledger/releaseledger/data/ledgers/main/releases/v0.1.2/audit/commit-audit.yaml",
25
+ ".ledger/releaseledger/data/ledgers/main/releases/v0.1.2/entries/entry-0001.md",
26
+ ".ledger/releaseledger/data/ledgers/main/releases/v0.1.2/release.md",
24
27
  ".ledger/releaseledger/work/v0.1.1/audit-decisions.yaml",
25
28
  ".ledger/releaseledger/work/v0.1.1/audit.yaml",
26
29
  ".ledger/releaseledger/work/v0.1.1/entries.yaml",
@@ -28,6 +31,12 @@
28
31
  ".ledger/releaseledger/work/v0.1.1/evidence/f27def9.patch",
29
32
  ".ledger/releaseledger/work/v0.1.1/evidence/manifest.json",
30
33
  ".ledger/releaseledger/work/v0.1.1/range.json",
34
+ ".ledger/releaseledger/work/v0.1.2/audit-decisions.yaml",
35
+ ".ledger/releaseledger/work/v0.1.2/audit.yaml",
36
+ ".ledger/releaseledger/work/v0.1.2/entries.yaml",
37
+ ".ledger/releaseledger/work/v0.1.2/evidence/f88173e.patch",
38
+ ".ledger/releaseledger/work/v0.1.2/evidence/manifest.json",
39
+ ".ledger/releaseledger/work/v0.1.2/range.json",
31
40
  ".ledger/releaseledger/write.lock",
32
41
  ".ledger/taskledger/.ledger-project.toml",
33
42
  ".ledger/taskledger/config.toml",
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.1.2",
3
+ "distance": 0,
4
+ "node": "gc2981a645889c974f2f7dc8b93ee8c3828655d9d",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-10-14"
8
+ }
@@ -28,6 +28,43 @@ SOURCE_PLAN_ID = "sha256:" + "b" * 64
28
28
  RENDER_PLAN_ID = "sha256:" + "c" * 64
29
29
 
30
30
 
31
+ def test_renderplan_set_contract_is_exported_from_package_root() -> None:
32
+ from renderplan import (
33
+ RENDERPLAN_SET_FORMAT,
34
+ RENDERPLAN_SET_VERSION,
35
+ RenderPlanSet,
36
+ RenderPlanSetChapter,
37
+ RenderPlanSetError,
38
+ load_renderplan_set,
39
+ renderplan_set_from_dict,
40
+ renderplan_set_to_dict,
41
+ renderplan_set_to_toml,
42
+ save_renderplan_set,
43
+ validate_renderplan_set,
44
+ validate_renderplan_set_profile,
45
+ validate_set_chapter_plan,
46
+ )
47
+
48
+ assert RENDERPLAN_SET_FORMAT == "renderplan-set"
49
+ assert RENDERPLAN_SET_VERSION == 1
50
+ assert all(
51
+ callable(symbol)
52
+ for symbol in (
53
+ RenderPlanSet,
54
+ RenderPlanSetChapter,
55
+ RenderPlanSetError,
56
+ load_renderplan_set,
57
+ renderplan_set_from_dict,
58
+ renderplan_set_to_dict,
59
+ renderplan_set_to_toml,
60
+ save_renderplan_set,
61
+ validate_renderplan_set,
62
+ validate_renderplan_set_profile,
63
+ validate_set_chapter_plan,
64
+ )
65
+ )
66
+
67
+
31
68
  def _profile(binding: str = "fixture") -> RenderProfile:
32
69
  return RenderProfile(
33
70
  roles={"narrator": RoleProfile(language="en-US", binding={"engine": binding})},
@@ -742,3 +742,10 @@ def test_validate_set_chapter_plan_checks_all_identity_edges() -> None:
742
742
  )
743
743
  with pytest.raises(ValidationError, match="render_profile_id"):
744
744
  validate_set_chapter_plan(wrong_profile_set, chapter, render_plan)
745
+ forged_chapter = replace(chapter, renderplan="other.renderplan.toml")
746
+ with pytest.raises(ValidationError, match="not a member"):
747
+ validate_set_chapter_plan(renderplan_set, forged_chapter, render_plan)
748
+
749
+ unpersisted_plan = replace(render_plan, plan_id=None)
750
+ with pytest.raises(ValidationError, match="render_plan_id"):
751
+ validate_set_chapter_plan(renderplan_set, chapter, unpersisted_plan)
@@ -132,6 +132,8 @@ def test_renderplan_set_error_is_a_renderplan_error() -> None:
132
132
  with pytest.raises(RenderPlanError):
133
133
  replace(_set(), profile_fingerprint="bad")
134
134
 
135
+ assert issubclass(RenderPlanSetError, ValueError)
136
+
135
137
 
136
138
  def test_renderplan_set_profile_validation_distinguishes_identity_failures(
137
139
  tmp_path: Path,
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.1.1",
3
- "distance": 0,
4
- "node": "g2aab3cc46e452bb6b7fad46999d05d47d6e466a3",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-10-13"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes