Skip to content

Retire Chronicle target profiles - #206

Open
juaristi22 wants to merge 1 commit into
mainfrom
retire-target-profiles-172
Open

Retire Chronicle target profiles#206
juaristi22 wants to merge 1 commit into
mainfrom
retire-target-profiles-172

Conversation

@juaristi22

Copy link
Copy Markdown
Collaborator

Summary

  • remove Chronicle-owned target profiles and target-resolution APIs now that Microcosm owns selection contracts
  • limit consumer artifacts to fact rows and manifest hashes
  • retire the target-profile agent lane and update the surrounding documentation and tests

Testing

  • uv run --locked --extra dev ruff check .
  • uv run --locked pytest -q --ignore=tests/test_chronicle_bundle.py --ignore=tests/test_chronicle_source_package.py (548 passed, 1 skipped)
  • uv run --locked pytest -q tests/test_chronicle_source_package.py plus the focused consumer, contract, governance, and import tests (167 passed)
  • uv run --locked pytest -q tests/test_chronicle_bundle.py -k 'not test_build_bundle_writes_merged_consumer_contract' (8 passed, 1 deselected)
  • wheel build and import smoke test
  • end-to-end build-consumer-artifact CLI smoke test

The 171,855-row full-bundle golden test was started locally but interrupted after eight minutes while computing the build ID. CI runs the complete test suite.

Fixes #172

@juaristi22
juaristi22 marked this pull request as ready for review August 28, 2026 22:56
@vahid-ahmadi

Copy link
Copy Markdown

Automated review pass (Claude Code, high effort, diff only — no execution). Deletion-dominant, so I pointed the review at what the retirement takes away rather than at new-code defects. Three findings, all of the same shape: a guarantee Chronicle used to enforce is now nobody's job, and its absence is silent.

1. policyengine_chronicle/consumer.py:~1640 — the schema version does not move with the contract

CONSUMER_ARTIFACT_SCHEMA_VERSION stays policyengine_ledger.consumer_artifact.v1 while the artifact's content contract changes incompatibly: the manifest no longer carries profiles, and artifacts that do are now hard-rejected.

The if "profiles" in manifest: raise guard protects readers of old artifacts, which is the easy direction. The unprotected direction is a downstream that pins schema_version == ...v1 and consumes a new artifact: it validates, finds no profiles, and resolves zero targets — compiling to nothing rather than refusing. Given microcosm compiles its target surface from this layer, an empty result there is a calibration that silently loses a family, not an error someone sees. Bumping the version is what makes the incompatibility loud on the consumer side.

2. chronicle/core.py:82 and the deleted resolve_profile_targets — the assertion policy is removed but the ambiguity it resolved is not

ASSERTION_POLICIES and DEFAULT_ASSERTION_POLICY = "observed_only" are deleted along with the resolver that enforced them, the per-series observation-vs-projection tie-break, and the ambiguous_assertion_at_period warning.

But ALLOWED_ASSERTIONS is unchanged, and the published feed still carries both observation and source_projection rows for the same series at the same period. So a consumer reading consumer_facts.jsonl directly now sums both — a double count that Chronicle refused by default until this PR. The ADR reassigns the responsibility to consumers, which is a legitimate architectural call, but nothing in the +271 added lines gives a consumer the tie-break the resolver implemented, and no fact-level marker makes the ambiguity visible at read time. A consumer that does not know to look will not fail; it will get roughly double.

This is the finding I would most want a ruling on, because it is a real semantic change shipping under a retirement label. If the intent is that consumers pin assertion explicitly, the feed refusing an unpinned read — or at minimum a documented, machine-readable statement of which series carry both — would keep the guarantee somewhere.

3. Deleted PeriodContractError / PeriodAlignmentDeclaration — the period-alignment guard has no substitute

The contract that hard-failed on consuming a fact at a period other than its reference period is deleted, with nothing Chronicle-side replacing it. Facts-only artifacts still carry period, but nothing enforces alignment, so the regression that guard was written for — microcosm#212, per its own docstring — is reachable again from the consumer's side.

Checked, not a finding

I checked pyproject.toml for stale packaging references to the fully-deleted policyengine_chronicle/target_profiles/: packages = ["chronicle", "db", "packages", "policyengine_chronicle"] is directory-level with no per-file globs, so nothing dangles.


The common thread is worth stating plainly: each of these three moves a check from "Chronicle refuses" to "the consumer should know", and in each case the consumer that does not know gets a plausible wrong answer rather than an error. If the retirement is the right call — and consolidating on facts-only artifacts may well be — then the replacement guarantees seem worth landing in the same PR, so there is no window where the old enforcement is gone and the new expectation is undocumented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Retire the target-profile surface: Chronicle is facts-only (#166 ruling)

2 participants