Extension Playbooks
These playbooks are decision-complete checklists for common repository extensions.
Playbook A: Add a New Law Source Adapter
Goal
Add a new source adapter that can download/ingest data while preserving canonical identity contracts.
Required contracts
- Source identity key tuple must be stable and explicit:
sourceowner_alias_kindowner_alias_value- Source artifacts must be traceable to manifest rows and source refs.
- Runner-facing APIs should remain at store/pipeline boundaries, not direct SQL.
Files to edit
backend/src/law_graph/pipelines/<source>/...(new adapter pipeline)backend/src/law_graph/pipelines/__init__.pyand/or origin registrationbackend/src/law_graph/cli.py(new source command wiring)- Source-specific ingest projection adapter (if ingest shape differs)
- Tests:
backend/tests/unit/...for adapter behaviorbackend/tests/integration/pipelines/...for end-to-end flow
Storage touchpoints
- Download persistence should flow through download manifest store/repository.
- Ingest persistence should flow through
IngestManifestDbStoreintent APIs. - Identity resolution must use source alias keys consistently.
Runner registration points
- Origin pipeline registry (
get_origin_pipelineand related origin config) - CLI subcommands for download/ingest/backfill (if supported)
Do not edit
- Do not add SQL primitives in runner/pipeline modules.
- Do not bypass store APIs to call ingest/download repositories directly.
- Do not add fallback identity keys outside the canonical tuple.
Acceptance checklist
- New source commands run from CLI and Makefile workflow.
- Identity key tuple is used consistently end-to-end.
- Download and ingest manifests capture source rows correctly.
- Unit + integration tests cover happy path and key failures.
Playbook B: Add a New Ingest Persisted Field or Table
Goal
Add ingest persistence without violating SQLModel-first contracts.
Required flow
- Contract first: define/update SQLModel contract in
backend/src/law_graph/storage/contracts/ingest/.... - Repository primitive: add/update
IngestRepositorytable primitive. - Store intent API: expose policy-level method in
IngestManifestDbStore. - Runner path: call store method from ingest runner, not repository.
- Migration policy: schema/data migration in external scripts only.
- Roundtrip tests: write -> read -> validate contract behavior.
Files to edit
backend/src/law_graph/storage/contracts/ingest/...backend/src/law_graph/storage/repositories/ingest_repository.pybackend/src/law_graph/storage/ingest_manifest_db.pybackend/src/law_graph/pipelines/normattiva/ingest/__init__.py(call path)backend/scripts/migrations/...(if schema migration needed)backend/tests/...contract/store/runner tests
Do not edit
- Do not run migrations from runtime downloader/ingest code paths.
- Do not duplicate schema literals/enums across multiple modules.
- Do not add one-to-one pass-through store aliases with no policy value.
Acceptance checklist
- SQLModel contract is canonical and imported where needed.
- Repository change is table-oriented primitive only.
- Store API encapsulates orchestration/policy concerns.
- Runner uses store API, not repository directly.
- Migration script exists (when required) and runtime code stays migration-free.
- Roundtrip contract tests pass.
Playbook C: Add or Modify Ingestion Transformation Logic
Goal
Place new transformation logic at the correct layer (delta, etl, or store)
without leaking concerns.
Placement checklist
- Put logic in
delta/*when it changes canonical record semantics, reconstruction semantics, or timeline/event modeling. - Put logic in
etl/*(or source snapshot adapters) when it maps raw payloads into normalized snapshots/variant inputs. - Keep the steady-state ingest worker on the direct
RawAct -> DeltaProjection -> VariantEventpath; avoid rebuilding full schemaActtrees unless the workflow explicitly needs snapshots. - Put logic in
IngestManifestDbStoreonly when it is orchestration policy (batch dedupe, lock scope, transaction grouping).
Files to edit
backend/src/law_graph/delta/builder.pyand related delta modules (if canonical semantics change)- Source ingest/snapshot adapter modules under
backend/src/law_graph/pipelines/... backend/src/law_graph/pipelines/normattiva/ingest/__init__.py(pipeline wiring)- Tests adjacent to changed layer (
unit+integration)
Do not edit
- Do not encode transformation-specific business rules in repository SQL methods.
- Do not add downloader-specific behavior in delta resolver/builder modules.
- Do not mutate contracts as an incidental side effect of transformation changes.
Acceptance checklist
- Logic lives in the correct layer by ownership.
- Existing contracts and boundaries remain explicit.
- Tests cover transformation behavior and regression scenarios.
- Ingest output remains reconstructable via
resolve_state.