diff --git a/AGENTS.md b/AGENTS.md
index 9e572e7..bab1fb4 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -115,327 +115,30 @@ cleanup backlog notes that future agents rely on.
4. Update docs or plan notes when the validation strategy or migration boundary
changes.
-## Linear Issue Writing Spec
-
-Linear is the shared work ledger for cross-agent work. Issues should be
-specific, searchable, dependency-aware, and tied to an observable outcome.
-Treat an issue as a short engineering spec, not as a note or a chat summary.
-
-### When to create or update an issue
-
-- Create a Linear issue when work must survive beyond the current chat, spans
- more than one file or module, introduces a blocker, or needs durable tracking.
-- Update an existing issue instead of creating a duplicate when the scope is
- the same.
-- Split a ticket when it contains more than one independent reviewable outcome.
- Use an umbrella issue for the broad objective and child issues for delivery
- slices.
-- Do not mirror every trivial local task into Linear. Use Linear for durable
- planning, blockers, coordination, and user-visible work.
-
-### Title and naming
-
-- Use outcome-first titles of the form `: `.
-- Keep titles short, concrete, and searchable.
-- Put the domain noun in the title, not just the implementation verb.
-- If the work concerns temporal semantics, PIT APIs, dataset contracts,
- compatibility shims, or public-web source families, name that domain
- explicitly in the title.
-- Avoid vague titles such as `Cleanup`, `Refactor`, or `Improve module`
- unless paired with the exact target.
-- Good examples:
- - `Public web: extract shared source finalization helpers`
- - `Registry APIs: add base class for entity-driven public sources`
- - `Archive loaders: unify historical-batch URL selection`
-
-### Issue body shape
-
-Use a compact spec structure:
-
-- Objective: what should exist when the issue is done.
-- Why now: why this matters now.
-- Scope: the exact modules, files, or docs in scope.
-- Non-goals: what is explicitly out of scope.
-- Dependencies: hard blockers with issue IDs.
-- Acceptance criteria: observable conditions that define success.
-- Validation: tests, lint, docs, or review gates.
-- Follow-on work: separate issues for future slices, if needed.
-
-### Dependency rules
-
-- Use parent/child relationships for umbrella work and implementation slices.
-- Use `blockedBy` and `blocks` only for hard prerequisites.
-- Use `relatedTo` for adjacent work that does not prevent completion.
-- Keep blocker chains shallow.
-- If the blocker does not yet exist, create it first or state the missing
- prerequisite explicitly.
-- Do not block on anticipated future reuse alone; keep that as a scoped note
- unless the dependency is already real.
-
-### Priority rules
-
-- Priority 1 / Urgent: broken build, release blocker, or active outage.
-- Priority 2 / High: foundational platform work or an item that unlocks
- multiple other tickets.
-- Priority 3 / Normal: planned implementation slices and most feature work.
-- Priority 4 / Low: docs-only work, cleanup, exploratory refactors.
-- Default to Priority 3 unless there is a concrete reason to raise it.
-
-### Blocker handling
-
-- If a task is blocked, say so explicitly in the issue and when communicating
- with the user.
-- State the blocking issue ID(s), the missing prerequisite, and the next
- unblock step.
-- Never present a blocked issue as complete.
-- If the user asks to complete work but a Linear blocker remains, surface the
- blocker before claiming success.
-
-### Done criteria
-
-- Mark an issue Done only when the implementation slice is landed, validation
- passes, and acceptance criteria are satisfied.
-- If behavior, APIs, or supported-source coverage changed, update the relevant
- docs:
- - `docs/api/` for API and reference behavior
- - `docs/getting-started/` for onboarding or examples
- - `docs/guides/` for workflows and conceptual docs
- - `doc/plan/` for mirrored ticket tables and implementation plans
-- Close the issue with a short note summarizing the result, validation, docs
- changes, and any follow-on issue IDs.
-- If useful work remains, split it into follow-on issues instead of leaving the
- original issue ambiguous.
-
-### Umbrella closeout
-
-- Treat an umbrella issue as a maintenance checkpoint, not just a delivery
- milestone.
-- Before closing an umbrella, do the cleanup pass, documentation maintenance,
- and mirrored-plan updates that the completed slices imply.
-- If an umbrella is intentionally doc-free, record that explicitly in the
- closeout note and explain why no docs changed.
-
-### Engineering plan quality
-
-- Every implementation issue should include a concrete plan with small phases.
-- Prefer stable scaffolds plus surgical deltas over whole-module rewrites.
-- If the plan cannot be explained as a few reviewable phases, the issue is too
- large and should be split.
-
-## Ticket Implementation Workflow
-
-All coding agents working from Linear must follow this workflow for every
-implementation ticket unless the user explicitly overrides it.
-
-### Required execution order
-
-1. Review upstream context before coding.
-2. Announce the current ticket number and its plain-English goal on screen.
-3. Implement the current ticket with test-driven development.
-4. Update the relevant docs after the implementation and tests pass.
-5. Leave a handoff note in Linear describing what changed and any caveats.
-6. Mark the ticket `Done`, then update the mirrored ticket table in the
- relevant plan doc.
-
-### Step 1: Review upstream context
-
-Before writing code, the implementer must:
-
-- read the current ticket body in full
-- read all hard-blocking upstream tickets and their completion notes
-- read recent comments on the parent issue when the parent is an active
- umbrella ticket
-- inspect the referenced plan docs and the current code paths in scope
-- identify the exact files, tests, and docs that are likely to change
-
-If an upstream ticket is not done, do not start implementation unless the user
-explicitly approves working around the blocker.
-
-### Step 2: Announce the current ticket on screen
-
-Before coding, print the ticket number and a short plain-English explanation
-of what the ticket aims to do in the current terminal/chat session.
-
-Minimum expectation:
-
-- include the Linear ticket id, for example `ALP-123`
-- explain the ticket goal in one or two plain-English sentences
-- do this after reading upstream tickets and before writing code
-
-### Step 3: Implement with TDD
-
-For code-changing tickets:
-
-- start by adding or updating the tests that define the target behavior
-- run the tests and confirm they fail for the expected reason
-- implement the smallest coherent code change that makes the tests pass
-- rerun the targeted tests, then rerun the broader validation required by the
- ticket or module owner rules
-
-Minimum expectation:
-
-- targeted tests for the changed behavior
-- broader regression coverage for the touched subsystem when practical
-
-For documentation-only or planning-only tickets, state explicitly in the ticket
-that TDD does not apply.
-
-### Step 4: Update docs after tests pass
-
-When behavior, APIs, runtime flow, source coverage, governance, validation, or
-developer workflow changes, update the relevant docs after the implementation is
-stable:
-
-- `docs/api/` for API and source reference behavior
-- `docs/getting-started/` for quickstart and setup
-- `docs/guides/` for workflows and design guidance
-- `doc/plan/` for mirrored ticket tables and implementation plans
-
-Doc updates are part of completing the ticket, not optional follow-up work,
-unless the ticket is explicitly scoped as doc-free.
-
-### Step 5: Leave a Linear handoff note
-
-Before marking the ticket done, add a Linear comment with:
-
-- what was implemented
-- which tests were added or updated
-- which test commands were run and whether they passed
-- which docs were updated
-- any caveats, deferred work, follow-on risks, or compatibility notes
-
-If the ticket is blocked or only partially complete, leave the same note but do
-not mark it done.
-
-### Step 6: Mark done and update the mirrored plan table
-
-Linear is the source of truth for ticket state. The plan tables in `doc/plan/`
-are the repo-local mirror for subsequent coding agents.
-
-Mark the ticket `Done` only when:
-
-- the code is landed
-- the agreed validation passed
-- the relevant docs are updated or the ticket explicitly records why no docs
- changed
-- the Linear handoff note is written
-
-After the ticket is moved to `Done` in Linear:
-
-- update the corresponding plan-table row in the relevant plan doc
-- keep the table sorted in implementation order
-- skip tickets already marked `Done` when selecting the next ticket
-- do not mark the plan-table row `Done` before the Linear ticket is actually
- closed
-
-### Recommended Linear closeout template
-
-Use this structure for the final implementation note:
-
-- Implemented:
-- Tests:
-- Docs:
-- Caveats:
-- Follow-ons:
-
-## Code Review Workflow
-
-When the task is a code review rather than a feature implementation, use the
-repo-wide review program under `doc/plan/` when one exists and the linked
-Linear review workstream for ticket state. If Alphaforge does not yet have a
-dedicated review program doc or review-ticket queue, treat the user-directed
-scope or the current branch diff as the review slice and follow the same
-dossier, severity, and closeout standards.
-
-### Review ticket selection
-
-- Linear is the source of truth for review-ticket state when review tickets
- exist.
-- Use the mirrored queue in `doc/plan/` when a dedicated review-program doc is
- present.
-- Pick the earliest review ticket in the ordered queue whose status is not
- `Done`, unless the user explicitly redirects to a different slice.
-- If no dedicated review queue exists yet, review the current branch diff or the
- user-directed scope instead of inventing tickets.
-- Tickets in the same wave may run in parallel only when their write scopes do
- not conflict.
-
-### Review scope and posture
-
-- Treat review tickets as review-and-fix slices, not as read-only audits.
-- Review code and tests together.
-- Check local, regional, and global behavior:
- - Local: single function, class, or module behavior.
- - Regional: bounded interactions across modules, adapters, registries,
- transforms, or docs.
- - Global: user-visible or workflow-visible behavior across major layers.
-- For important behavior, missing regional or global interaction coverage is a
- review finding, not a note for later.
-- Keep compatibility-only coverage isolated from the ordinary API-surface
- suites.
-- Use the available test strata explicitly during review and remediation:
- - targeted source or module tests for local behavior
- - adapter, contract, or regression tests for bounded interactions
- - broader workflow or docs validation when the slice affects user-visible
- behavior
-
-### Required review workflow
-
-1. Read the review ticket or selected scope, the mirrored plan section if one
- exists, and any upstream blockers.
-2. Build a review dossier:
- - files in scope
- - tests in scope
- - contracts being defended
- - inbound and outbound module interactions
- - current local / regional / global coverage map
- - relevant docs, plan notes, and compatibility or migration notes
-3. Announce the ticket number or review slice and the plain-English review goal
- before editing.
-4. Perform the static review of code and tests.
-5. Run the targeted tests for the slice and the broader regression required by
- the ticket when practical.
-6. Land low-risk in-scope fixes, test additions, doc updates, or plan updates
- inside the same ticket when the user asked for review-and-fix work.
-7. Split larger remediations into follow-on Linear issues instead of letting
- the review ticket sprawl.
-
-### Findings and severity
-
-- Findings are the primary output of a review ticket.
-- Use this severity rubric:
- - `P0`: wrong result, silent corruption, or broken governance on a critical
- path
- - `P1`: high-confidence correctness, runtime, or contract bug
- - `P2`: meaningful maintainability, test, or observability gap with real risk
- - `P3`: lower-risk cleanup or consistency gap
-
-### Review closeout requirements
-
-Before marking a review ticket `Done`:
-
-- leave a Linear handoff note with:
- - Reviewed:
- - Findings:
- - Tests checked:
- - Coverage assessment:
- - Docs / plan mismatches:
- - Compatibility or shim removal candidates:
- - Follow-on tickets:
- - Disposition:
-- update the mirrored ticket row in the review-program doc when one exists
-- do not mark the ticket `Done` if a hard blocker remains unresolved
-
-### Code review deliverables
-
-Every completed review ticket should leave behind:
-
-- prioritized findings with file references
-- a local / regional / global coverage assessment
-- missing-test and misleading-test notes
-- docs and plan mismatches
-- compatibility or shim-removal notes where relevant
-- follow-on issues for out-of-scope or larger remediations
+## Repo Tracking Configuration
+
+This repo inherits the shared Linear, planning, implementation, and review
+workflow from [/Users/steveyang/Projects/steveya/AGENTS.md](/Users/steveyang/Projects/steveya/AGENTS.md).
+If `alphaforge` is opened directly instead of from the workspace root, read the
+workspace file before starting Linear-tracked work.
+
+- Linear project: `alphaforge`
+- Linear team: `alphaforge`
+- Ticket prefix: `ALP`
+- Queue-driving plan docs should live in `doc/plan/` and use the shared
+ `draft__`, `active__`, or `done__` filename prefixes.
+- Supporting notes that are not themselves the active queue may keep
+ descriptive names, for example `migration_note.md`.
+- Official docs roots:
+ - `docs/api/`
+ - `docs/getting-started/`
+ - `docs/guides/`
+- Review program path: use `doc/plan/active__code-review-program.md` when one
+ exists; otherwise treat the user-directed scope or current diff as the review
+ slice.
+- Repo-specific naming should keep the temporal or PIT domain explicit when the
+ work touches temporal semantics, PIT APIs, dataset contracts, compatibility
+ shims, or public-web source families.
## Anti-Hallucination Rules
diff --git a/doc/plan/post_migration_plan.md b/doc/plan/active__post-migration-plan.md
similarity index 100%
rename from doc/plan/post_migration_plan.md
rename to doc/plan/active__post-migration-plan.md
diff --git a/doc/plan/done__cftc-commodity-cot-loader.md b/doc/plan/done__cftc-commodity-cot-loader.md
new file mode 100644
index 0000000..9b015de
--- /dev/null
+++ b/doc/plan/done__cftc-commodity-cot-loader.md
@@ -0,0 +1,148 @@
+# CFTC Commodity CoT Loader Completion Plan
+
+## Objective
+
+Audit and complete Alphaforge's public-web surface for CFTC commodity
+Commitments of Traders data.
+
+This plan is intentionally framed as a completion plan rather than a greenfield
+loader build. The repo already ships `CFTCDisaggregatedCoTSource` on
+`cftc.cot.disagg`, so the first job is to confirm whether that existing surface
+already satisfies the intended commodity CoT requirement or whether the real
+gap is narrower.
+
+Status mirror last synced: `2026-04-12`
+
+Current status:
+
+- the umbrella workstream exists in Linear as
+ [ALP-39](https://linear.app/quant-macro/issue/ALP-39/public-web-cftc-commodity-cot-loader-completion)
+- `cftc.cot.disagg` already exists in code, tests, and docs, so the current
+ risk is scope drift or contract ambiguity rather than a missing file
+- the audit has already identified one concrete mismatch: the public quickstart
+ example was using adapter-style `value` / bare-entity semantics against the
+ raw public-web loader contract
+- `ALP-40` is done: the audit confirmed there was no missing loader
+- `ALP-41` is canceled: no code-hardening slice remained after the audit
+- `ALP-42` is done: docs and validation now match the shipped raw-loader
+ contract
+- the workstream is complete and should move to `done__` status in the plan
+ mirror
+
+## Why This Plan Exists
+
+The current request is phrased as if Alphaforge still needs a commodity CoT
+loader. The repo state does not match that framing:
+
+- `alphaforge/data/public_web/cftc_cot.py` already defines
+ `CFTCDisaggregatedCoTSource`
+- `alphaforge/data/sources/cftc.py` already exposes `cot.disagg`
+- `tests/public_web/test_cftc_cot.py` already covers disaggregated commodity
+ fixtures, entity ids, and archive URL selection
+- public docs already mention `cftc.cot.disagg`
+
+That means the correct planning move is to audit the intended commodity scope
+first, then either:
+
+- confirm the current loader is already the right implementation and close the
+ request with docs and validation evidence, or
+- land the smallest reviewable hardening slices needed to close a real contract
+ gap
+
+## Repo-Grounded Current State
+
+### Implemented surfaces
+
+- Public-web loader:
+ `alphaforge/data/public_web/cftc_cot.py`
+- Adapter routing:
+ `alphaforge/data/sources/cftc.py`
+- Targeted public-web coverage:
+ `tests/public_web/test_cftc_cot.py`
+- Adapter and PIT coverage:
+ `tests/test_cftc_dtcc_adapter.py`
+- Public docs:
+ `docs/api/public-web.md`
+ `docs/getting-started/quickstart-public-web.md`
+ `docs/guides/public-web-source-authoring.md`
+
+### Known ambiguity this plan resolves
+
+The existing commodity surface is the disaggregated futures report. The user
+request may instead mean:
+
+- validate that `cftc.cot.disagg` is the intended commodity CoT variant
+- add missing metrics, entity mapping, or archive behavior to that existing
+ loader
+- align docs and examples so downstream users know which commodity CoT variant
+ Alphaforge actually supports
+
+This plan does not assume the answer in advance. `ALP-40` is responsible for
+making that explicit from the current code and tests.
+
+## Scope
+
+- `alphaforge/data/public_web/cftc_cot.py`
+- `alphaforge/data/sources/cftc.py`
+- `tests/public_web/test_cftc_cot.py`
+- `tests/test_cftc_dtcc_adapter.py` when adapter parity moves
+- `docs/api/public-web.md`
+- `docs/getting-started/quickstart-public-web.md`
+- `docs/guides/public-web-source-authoring.md`
+
+## Non-goals
+
+- adding unrelated CFTC datasets such as swaps, supplemental, or index-trader
+ reports
+- redesigning the shared archive-loader stack unless a concrete commodity CoT
+ bug demands a narrow fix
+- changing PIT transform semantics unless the audit proves the commodity CoT
+ contract currently depends on the wrong transform boundary
+
+## Ordered Ticket Mirror
+
+Rules for coding agents:
+
+- Linear is the source of truth for ticket scope and status.
+- This plan is the repo-local queue mirror for subsequent agents.
+- Always start with `ALP-40`.
+- If `ALP-40` concludes that the current implementation already satisfies the
+ intended commodity scope, rewrite or close `ALP-41` before writing
+ unnecessary code.
+- Do not mark any row `Done` here before the corresponding Linear issue is
+ actually closed.
+
+### Ordered Queue
+
+| Ticket | Slice | Status |
+| --- | --- | --- |
+| [ALP-40](https://linear.app/quant-macro/issue/ALP-40/public-web-audit-existing-cftc-commodity-cot-loader-contract) | Audit the existing `cftc.cot.disagg` contract and state the real remaining gap | Done |
+| [ALP-41](https://linear.app/quant-macro/issue/ALP-41/public-web-harden-cftc-commodity-cot-loader-gaps) | Land the smallest code changes needed after the audit | Canceled |
+| [ALP-42](https://linear.app/quant-macro/issue/ALP-42/public-web-document-and-validate-cftc-commodity-cot-surface) | Align docs, validation, and closeout with the final supported surface | Done |
+
+## Validation
+
+Minimum expected validation by slice:
+
+- `ALP-40`
+ - static audit of loader, adapter, tests, and docs
+- `ALP-41`
+ - targeted `tests/public_web/test_cftc_cot.py`
+ - targeted adapter slices if dataset routing, source naming, or series-key
+ behavior changes
+- `ALP-42`
+ - rerun relevant targeted tests after the final code state
+ - run docs validation if doc content changes materially
+
+## Closeout Criteria
+
+This plan is complete only when:
+
+- the intended commodity CoT variant is explicitly identified
+- the existing loader is either confirmed sufficient or hardened through a
+ narrow implementation slice
+- docs and examples reflect the actual supported commodity CoT surface
+- the Linear handoff notes record the validation and any residual caveats
+
+Those conditions are now met. Keep this file as the historical mirror under
+`done__cftc-commodity-cot-loader.md`.
diff --git a/doc/plan/public_web_refactor_plan.md b/doc/plan/done__public-web-refactor-plan.md
similarity index 100%
rename from doc/plan/public_web_refactor_plan.md
rename to doc/plan/done__public-web-refactor-plan.md
diff --git a/doc/plan/core_platform_roadmap.md b/doc/plan/draft__core-platform-roadmap.md
similarity index 99%
rename from doc/plan/core_platform_roadmap.md
rename to doc/plan/draft__core-platform-roadmap.md
index 6c9a9e9..6ddf0d3 100644
--- a/doc/plan/core_platform_roadmap.md
+++ b/doc/plan/draft__core-platform-roadmap.md
@@ -680,7 +680,7 @@ Status mirror last synced: `2026-04-05`
These tickets should not be picked up until their migration trigger conditions
are satisfied. The detailed cleanup backlog lives in
-`doc/plan/post_migration_plan.md`.
+`doc/plan/active__post-migration-plan.md`.
| Ticket | Status |
| --- | --- |
diff --git a/doc/plan/migration_note.md b/doc/plan/migration_note.md
index 10618f1..f26d863 100644
--- a/doc/plan/migration_note.md
+++ b/doc/plan/migration_note.md
@@ -17,12 +17,12 @@ focus on:
- temporary shims and planned removals
This note complements the roadmap in
-`doc/plan/core_platform_roadmap.md`. The roadmap explains what the program is
+`doc/plan/draft__core-platform-roadmap.md`. The roadmap explains what the program is
trying to build; this file records what changed and what downstream users need
to know.
Post-migration cleanup items that should only happen after downstream repos are
-fully moved live in `doc/plan/post_migration_plan.md`.
+fully moved live in `doc/plan/active__post-migration-plan.md`.
## Downstream Repos To Watch
@@ -124,7 +124,7 @@ not be treated as equal long-term public directions:
- defaulting to `DataSource` as the primary public loading abstraction
Removal and cleanup of these bridges is tracked in
-`doc/plan/post_migration_plan.md` under `ALP-23` through `ALP-27`.
+`doc/plan/active__post-migration-plan.md` under `ALP-23` through `ALP-27`.
## Repo-By-Repo Migration Checklist
@@ -259,7 +259,7 @@ Promoted release-rule and missingness semantics into the core
- `ALP-20` can now rely on the shared release-aware health vocabulary instead
of inventing separate operational timing rules.
- Shim removal after downstream migration is explicitly tracked in `ALP-23`
- and mirrored in `doc/plan/post_migration_plan.md`.
+ and mirrored in `doc/plan/active__post-migration-plan.md`.
### 2026-04-04
@@ -348,7 +348,7 @@ instead of asking downstream code to reach into legacy-style accessor helpers.
**Follow-up notes:**
- Post-migration cleanup for the legacy helper names is tracked in `ALP-27`
- and mirrored in `doc/plan/post_migration_plan.md`.
+ and mirrored in `doc/plan/active__post-migration-plan.md`.
- `ALP-14` can build batch ref-period panel helpers on top of these typed query
semantics instead of inventing another batch-only contract.
@@ -495,7 +495,7 @@ instead of looping one query at a time.
- `ALP-16` should narrow the documented `DataSource` role even further now
that the canonical fetch route is explicit and batch-capable.
- Final removal of the legacy context access path remains tracked in `ALP-25`
- and mirrored in `doc/plan/post_migration_plan.md`.
+ and mirrored in `doc/plan/active__post-migration-plan.md`.
### 2026-04-04
@@ -830,7 +830,7 @@ repo-local roadmap and migration logs synchronized through the end of the epic.
- No new compatibility shim or temporary bridge was introduced in this ticket.
- Existing migration bridges remain tracked in
- `doc/plan/post_migration_plan.md`.
+ `doc/plan/active__post-migration-plan.md`.
**Follow-up notes:**
diff --git a/docs/api/public-web.md b/docs/api/public-web.md
index 26bf9ea..774996e 100644
--- a/docs/api/public-web.md
+++ b/docs/api/public-web.md
@@ -58,6 +58,13 @@ Archive-backed CFTC loaders now raise an explicit failure when a requested
archive cannot be downloaded or parsed, rather than silently skipping the bad
year and returning partial history.
+For the raw public-web CoT loaders, entity filtering uses the raw loader
+`entity_id` contract, not adapter `series_key` values. The disaggregated
+commodity loader `cftc.cot.disagg` uses entity ids of the form
+`futures.{contract_code}.{trader_category}.cftc` and exposes metric columns
+such as `long_positions`, `short_positions`, `spread_positions`,
+`open_interest`, `change_long`, and `change_short`.
+
### Outliers and provider-specific loaders
| Source name | Class | Table(s) |
diff --git a/docs/getting-started/quickstart-public-web.md b/docs/getting-started/quickstart-public-web.md
index cfd2420..5bf8bea 100644
--- a/docs/getting-started/quickstart-public-web.md
+++ b/docs/getting-started/quickstart-public-web.md
@@ -48,13 +48,19 @@ dtcc_daily = dtcc.fetch(
cot_frame = cot.fetch(
Query(
table="cftc.cot.disagg",
- columns=["value"],
- entities=["wheat_srw"],
+ columns=["long_positions", "short_positions", "trader_category"],
+ entities=["futures.wheat_srw.m_money.cftc"],
start=pd.Timestamp("2025-01-01", tz="UTC"),
)
)
```
+For raw public-web CoT loaders, `entities` uses the loader's raw `entity_id`
+contract rather than adapter `series_key` values. For
+`cftc.cot.disagg`, the canonical pattern is
+`futures.{contract_code}.{trader_category}.cftc`, for example
+`futures.wheat_srw.m_money.cftc`.
+
If you instantiate a source directly instead of using
`default_public_web_sources()`, keep constructor-specific requirements explicit.
For example, `EurexRefdataContractsSource` requires an `api_url`.
diff --git a/docs/guides/contracts-and-benchmarks.md b/docs/guides/contracts-and-benchmarks.md
index 3fea2c1..320ae8a 100644
--- a/docs/guides/contracts-and-benchmarks.md
+++ b/docs/guides/contracts-and-benchmarks.md
@@ -85,7 +85,7 @@ Before removing a compatibility surface or tightening a public contract:
2. run `python -m pytest tests/contracts`
3. rerun `python -m benchmarks.pit` if the change touches PIT retrieval paths
4. update `doc/plan/migration_note.md` with the downstream impact
-5. update `doc/plan/post_migration_plan.md` if a temporary bridge was added
+5. update `doc/plan/active__post-migration-plan.md` if a temporary bridge was added
That discipline keeps migration work anchored to explicit checks instead of
repo-local assumptions.
diff --git a/docs/guides/core-platform-architecture.md b/docs/guides/core-platform-architecture.md
index 34e5b7a..d84a2b7 100644
--- a/docs/guides/core-platform-architecture.md
+++ b/docs/guides/core-platform-architecture.md
@@ -95,4 +95,4 @@ Use the canonical side for new work:
| PIT ingestion strictness | `"error"`, `"warn"`, `"coerce"` | boolean `strict=True/False` |
Those compatibility surfaces remain only to support downstream migration.
-Their removal backlog is tracked in `doc/plan/post_migration_plan.md`.
+Their removal backlog is tracked in `doc/plan/active__post-migration-plan.md`.
diff --git a/docs/guides/core-platform-migration.md b/docs/guides/core-platform-migration.md
index 71444fd..51ac1a0 100644
--- a/docs/guides/core-platform-migration.md
+++ b/docs/guides/core-platform-migration.md
@@ -73,7 +73,7 @@ Also rerun the targeted subsystem tests for the touched layer and update the
repo-local migration notes:
- `doc/plan/migration_note.md`
-- `doc/plan/post_migration_plan.md` when a temporary bridge is added or retired
+- `doc/plan/active__post-migration-plan.md` when a temporary bridge is added or retired
## Documentation expectations
@@ -82,7 +82,7 @@ When a migration-sensitive ticket lands:
- update the canonical docs first
- leave legacy paths documented only as temporary compatibility notes
- record the downstream impact in `doc/plan/migration_note.md`
-- keep the roadmap mirror in `doc/plan/core_platform_roadmap.md` aligned with
+- keep the roadmap mirror in `doc/plan/draft__core-platform-roadmap.md` aligned with
Linear state
That keeps downstream migrations tied to one canonical direction at a time.