catabolic 0.1.0__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.
- catabolic-0.1.0/LICENSE +22 -0
- catabolic-0.1.0/MANIFEST.in +6 -0
- catabolic-0.1.0/PKG-INFO +470 -0
- catabolic-0.1.0/README.md +440 -0
- catabolic-0.1.0/docs/ARTIFACTS.md +324 -0
- catabolic-0.1.0/docs/AUDIT.md +155 -0
- catabolic-0.1.0/docs/AUTOMATION.md +186 -0
- catabolic-0.1.0/docs/CATALOG_REFRESH.md +119 -0
- catabolic-0.1.0/docs/COMPATIBILITY.md +250 -0
- catabolic-0.1.0/docs/COMPONENTS.md +264 -0
- catabolic-0.1.0/docs/CONSUMERS.md +421 -0
- catabolic-0.1.0/docs/CONSUMER_DESIGN.md +142 -0
- catabolic-0.1.0/docs/CONSUMER_VALIDATION.md +177 -0
- catabolic-0.1.0/docs/COPYRIGHT_AUDIT.md +179 -0
- catabolic-0.1.0/docs/DESIGN.md +340 -0
- catabolic-0.1.0/docs/DEVELOPMENT.md +180 -0
- catabolic-0.1.0/docs/ENRICHMENT.md +413 -0
- catabolic-0.1.0/docs/EXPERIENCE_ACCEPTANCE.md +229 -0
- catabolic-0.1.0/docs/FALLBACK.md +189 -0
- catabolic-0.1.0/docs/FAQ.md +150 -0
- catabolic-0.1.0/docs/GETTING_STARTED.md +156 -0
- catabolic-0.1.0/docs/GRAPHQL.md +175 -0
- catabolic-0.1.0/docs/HARDLINKS.md +160 -0
- catabolic-0.1.0/docs/HTTP.md +458 -0
- catabolic-0.1.0/docs/HTTP_BACKEND_M0.md +255 -0
- catabolic-0.1.0/docs/INBOX.md +210 -0
- catabolic-0.1.0/docs/INSTALLATION.md +147 -0
- catabolic-0.1.0/docs/MAINTENANCE.md +212 -0
- catabolic-0.1.0/docs/MANIFESTS.md +153 -0
- catabolic-0.1.0/docs/MEDIA_MODEL.md +196 -0
- catabolic-0.1.0/docs/MIGRATIONS.md +349 -0
- catabolic-0.1.0/docs/NATIVE_LAYOUT.md +114 -0
- catabolic-0.1.0/docs/OBSERVATIONS.md +314 -0
- catabolic-0.1.0/docs/OPEN_CATALOG.md +214 -0
- catabolic-0.1.0/docs/OPERATIONS.md +280 -0
- catabolic-0.1.0/docs/OUTPUT_LAYOUTS.md +221 -0
- catabolic-0.1.0/docs/PROCESSING_REVIEW.md +352 -0
- catabolic-0.1.0/docs/PROCESSORS.md +159 -0
- catabolic-0.1.0/docs/PROGRAMMABLE_CATALOG.md +346 -0
- catabolic-0.1.0/docs/PROGRAMMABLE_CATALOG_REVIEW.md +118 -0
- catabolic-0.1.0/docs/PROGRAMMABLE_CATALOG_VALIDATION.md +212 -0
- catabolic-0.1.0/docs/QUERYING.md +256 -0
- catabolic-0.1.0/docs/QUERY_FOLDERS.md +175 -0
- catabolic-0.1.0/docs/RELEASE_TESTING.md +217 -0
- catabolic-0.1.0/docs/RENDITION_WORKFLOWS.md +257 -0
- catabolic-0.1.0/docs/ROADMAP.md +324 -0
- catabolic-0.1.0/docs/RULES.md +204 -0
- catabolic-0.1.0/docs/SCALE_BENCHMARKS.md +170 -0
- catabolic-0.1.0/docs/SCHEMAS.md +135 -0
- catabolic-0.1.0/docs/TAGGING.md +220 -0
- catabolic-0.1.0/docs/TROUBLESHOOTING.md +167 -0
- catabolic-0.1.0/docs/TRUST_POLICIES.md +102 -0
- catabolic-0.1.0/docs/WATCHERS.md +165 -0
- catabolic-0.1.0/docs/WORKFLOW.md +141 -0
- catabolic-0.1.0/docs/WORKLOG.md +171 -0
- catabolic-0.1.0/docs/plans/UNIFIED_FALLBACK.md +226 -0
- catabolic-0.1.0/docs/plans/WATCHERS.md +176 -0
- catabolic-0.1.0/pyproject.toml +49 -0
- catabolic-0.1.0/setup.cfg +4 -0
- catabolic-0.1.0/src/catabolic/__init__.py +6 -0
- catabolic-0.1.0/src/catabolic/__main__.py +6 -0
- catabolic-0.1.0/src/catabolic/access/__init__.py +298 -0
- catabolic-0.1.0/src/catabolic/access/catalog.py +238 -0
- catabolic-0.1.0/src/catabolic/access/graphql.py +158 -0
- catabolic-0.1.0/src/catabolic/api_cli.py +245 -0
- catabolic-0.1.0/src/catabolic/api_events.py +79 -0
- catabolic-0.1.0/src/catabolic/app.py +533 -0
- catabolic-0.1.0/src/catabolic/artifact_cli.py +70 -0
- catabolic-0.1.0/src/catabolic/artifacts.py +792 -0
- catabolic-0.1.0/src/catabolic/catalog_refresh.py +203 -0
- catabolic-0.1.0/src/catabolic/catalog_refresh_cli.py +76 -0
- catabolic-0.1.0/src/catabolic/catalog_state.py +86 -0
- catabolic-0.1.0/src/catabolic/cli.py +1484 -0
- catabolic-0.1.0/src/catabolic/component_claims.py +121 -0
- catabolic-0.1.0/src/catabolic/component_cli.py +54 -0
- catabolic-0.1.0/src/catabolic/component_packages.py +497 -0
- catabolic-0.1.0/src/catabolic/component_packaging.py +596 -0
- catabolic-0.1.0/src/catabolic/component_sql.py +228 -0
- catabolic-0.1.0/src/catabolic/components.py +229 -0
- catabolic-0.1.0/src/catabolic/consumer_adapters.py +413 -0
- catabolic-0.1.0/src/catabolic/consumer_cli.py +358 -0
- catabolic-0.1.0/src/catabolic/consumer_setup.py +394 -0
- catabolic-0.1.0/src/catabolic/consumers.py +515 -0
- catabolic-0.1.0/src/catabolic/content_access.py +142 -0
- catabolic-0.1.0/src/catabolic/copy_selection.py +237 -0
- catabolic-0.1.0/src/catabolic/curation.py +549 -0
- catabolic-0.1.0/src/catabolic/database_io.py +84 -0
- catabolic-0.1.0/src/catabolic/document_text.py +130 -0
- catabolic-0.1.0/src/catabolic/documentation.py +372 -0
- catabolic-0.1.0/src/catabolic/domain.py +73 -0
- catabolic-0.1.0/src/catabolic/enrichment_cli.py +342 -0
- catabolic-0.1.0/src/catabolic/estimate_calibration.py +84 -0
- catabolic-0.1.0/src/catabolic/evaluation.py +105 -0
- catabolic-0.1.0/src/catabolic/execution_claims.py +132 -0
- catabolic-0.1.0/src/catabolic/exports.py +311 -0
- catabolic-0.1.0/src/catabolic/fallback_cli.py +119 -0
- catabolic-0.1.0/src/catabolic/fallback_models.py +97 -0
- catabolic-0.1.0/src/catabolic/fallback_policies.py +113 -0
- catabolic-0.1.0/src/catabolic/fallback_probe.py +135 -0
- catabolic-0.1.0/src/catabolic/fallback_projection.py +525 -0
- catabolic-0.1.0/src/catabolic/fallback_records.py +36 -0
- catabolic-0.1.0/src/catabolic/fallback_resolution.py +596 -0
- catabolic-0.1.0/src/catabolic/fallback_worker.py +110 -0
- catabolic-0.1.0/src/catabolic/filesystem.py +261 -0
- catabolic-0.1.0/src/catabolic/graphql_query.py +834 -0
- catabolic-0.1.0/src/catabolic/guides/ARTIFACTS.md +324 -0
- catabolic-0.1.0/src/catabolic/guides/AUTOMATION.md +186 -0
- catabolic-0.1.0/src/catabolic/guides/CATALOG_REFRESH.md +119 -0
- catabolic-0.1.0/src/catabolic/guides/COMPATIBILITY.md +250 -0
- catabolic-0.1.0/src/catabolic/guides/COMPONENTS.md +264 -0
- catabolic-0.1.0/src/catabolic/guides/CONSUMERS.md +421 -0
- catabolic-0.1.0/src/catabolic/guides/CONSUMER_DESIGN.md +142 -0
- catabolic-0.1.0/src/catabolic/guides/CONSUMER_VALIDATION.md +177 -0
- catabolic-0.1.0/src/catabolic/guides/DESIGN.md +340 -0
- catabolic-0.1.0/src/catabolic/guides/DEVELOPMENT.md +180 -0
- catabolic-0.1.0/src/catabolic/guides/ENRICHMENT.md +413 -0
- catabolic-0.1.0/src/catabolic/guides/EXPERIENCE_ACCEPTANCE.md +229 -0
- catabolic-0.1.0/src/catabolic/guides/FALLBACK.md +189 -0
- catabolic-0.1.0/src/catabolic/guides/FAQ.md +150 -0
- catabolic-0.1.0/src/catabolic/guides/GETTING_STARTED.md +156 -0
- catabolic-0.1.0/src/catabolic/guides/GRAPHQL.md +175 -0
- catabolic-0.1.0/src/catabolic/guides/HARDLINKS.md +160 -0
- catabolic-0.1.0/src/catabolic/guides/HTTP.md +458 -0
- catabolic-0.1.0/src/catabolic/guides/INBOX.md +210 -0
- catabolic-0.1.0/src/catabolic/guides/INSTALLATION.md +147 -0
- catabolic-0.1.0/src/catabolic/guides/MAINTENANCE.md +212 -0
- catabolic-0.1.0/src/catabolic/guides/MANIFESTS.md +153 -0
- catabolic-0.1.0/src/catabolic/guides/MEDIA_MODEL.md +196 -0
- catabolic-0.1.0/src/catabolic/guides/MIGRATIONS.md +349 -0
- catabolic-0.1.0/src/catabolic/guides/NATIVE_LAYOUT.md +114 -0
- catabolic-0.1.0/src/catabolic/guides/OBSERVATIONS.md +314 -0
- catabolic-0.1.0/src/catabolic/guides/OPEN_CATALOG.md +214 -0
- catabolic-0.1.0/src/catabolic/guides/OPERATIONS.md +280 -0
- catabolic-0.1.0/src/catabolic/guides/OUTPUT_LAYOUTS.md +221 -0
- catabolic-0.1.0/src/catabolic/guides/PROCESSING_REVIEW.md +352 -0
- catabolic-0.1.0/src/catabolic/guides/PROCESSORS.md +159 -0
- catabolic-0.1.0/src/catabolic/guides/PROGRAMMABLE_CATALOG.md +346 -0
- catabolic-0.1.0/src/catabolic/guides/PROGRAMMABLE_CATALOG_REVIEW.md +118 -0
- catabolic-0.1.0/src/catabolic/guides/PROGRAMMABLE_CATALOG_VALIDATION.md +212 -0
- catabolic-0.1.0/src/catabolic/guides/QUERYING.md +256 -0
- catabolic-0.1.0/src/catabolic/guides/QUERY_FOLDERS.md +175 -0
- catabolic-0.1.0/src/catabolic/guides/README.md +440 -0
- catabolic-0.1.0/src/catabolic/guides/RELEASE_TESTING.md +217 -0
- catabolic-0.1.0/src/catabolic/guides/RENDITION_WORKFLOWS.md +257 -0
- catabolic-0.1.0/src/catabolic/guides/RULES.md +204 -0
- catabolic-0.1.0/src/catabolic/guides/SCALE_BENCHMARKS.md +170 -0
- catabolic-0.1.0/src/catabolic/guides/SCHEMAS.md +135 -0
- catabolic-0.1.0/src/catabolic/guides/TAGGING.md +220 -0
- catabolic-0.1.0/src/catabolic/guides/TROUBLESHOOTING.md +167 -0
- catabolic-0.1.0/src/catabolic/guides/TRUST_POLICIES.md +102 -0
- catabolic-0.1.0/src/catabolic/guides/WATCHERS.md +165 -0
- catabolic-0.1.0/src/catabolic/guides/WORKFLOW.md +141 -0
- catabolic-0.1.0/src/catabolic/guides/WORKLOG.md +171 -0
- catabolic-0.1.0/src/catabolic/hardlinks.py +580 -0
- catabolic-0.1.0/src/catabolic/http/__init__.py +4 -0
- catabolic-0.1.0/src/catabolic/http/app.py +1022 -0
- catabolic-0.1.0/src/catabolic/http/contract.py +200 -0
- catabolic-0.1.0/src/catabolic/http/fallback.py +227 -0
- catabolic-0.1.0/src/catabolic/http/models.py +347 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.0.0/manifest.json +37 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.0.0/manifest.json.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.0.0/openapi.json +12407 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.0.0/openapi.json.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.0.0/schema.graphql +261 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.0.0/schema.graphql.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.1.0/manifest.json +40 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.1.0/manifest.json.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.1.0/openapi.json +13564 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.1.0/openapi.json.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.1.0/schema.graphql +287 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.1.0/schema.graphql.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.2.0/manifest.json +46 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.2.0/manifest.json.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.2.0/openapi.json +15408 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.2.0/openapi.json.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.2.0/schema.graphql +287 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.2.0/schema.graphql.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.3.0/manifest.json +46 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.3.0/manifest.json.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.3.0/openapi.json +15408 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.3.0/openapi.json.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.3.0/schema.graphql +335 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.3.0/schema.graphql.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.4.0/manifest.json +46 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.4.0/manifest.json.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.4.0/openapi.json +15452 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.4.0/openapi.json.license +2 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.4.0/schema.graphql +335 -0
- catabolic-0.1.0/src/catabolic/http/releases/1.4.0/schema.graphql.license +2 -0
- catabolic-0.1.0/src/catabolic/http/transport.py +98 -0
- catabolic-0.1.0/src/catabolic/http/watchers.py +161 -0
- catabolic-0.1.0/src/catabolic/http_worker.py +72 -0
- catabolic-0.1.0/src/catabolic/http_worker_local.py +109 -0
- catabolic-0.1.0/src/catabolic/importers.py +205 -0
- catabolic-0.1.0/src/catabolic/inbox_cli.py +106 -0
- catabolic-0.1.0/src/catabolic/interchange/__init__.py +4 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/index.json +8 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/index.json.license +2 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v1.md +179 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v1.md.license +2 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v1.schema.json +921 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v1.schema.json.license +2 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v2.md +232 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v2.md.license +2 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v2.schema.json +1190 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v2.schema.json.license +2 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v3.md +266 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v3.md.license +2 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v3.schema.json +1379 -0
- catabolic-0.1.0/src/catabolic/interchange/releases/manifest-v3.schema.json.license +2 -0
- catabolic-0.1.0/src/catabolic/interchange/specification.py +132 -0
- catabolic-0.1.0/src/catabolic/interchange/v1.py +257 -0
- catabolic-0.1.0/src/catabolic/interchange/v2.py +104 -0
- catabolic-0.1.0/src/catabolic/interchange/v3.py +85 -0
- catabolic-0.1.0/src/catabolic/interchange/validation.py +278 -0
- catabolic-0.1.0/src/catabolic/item_workflow.py +381 -0
- catabolic-0.1.0/src/catabolic/layouts.py +797 -0
- catabolic-0.1.0/src/catabolic/legacy_refresh_delivery.py +79 -0
- catabolic-0.1.0/src/catabolic/maintenance.py +634 -0
- catabolic-0.1.0/src/catabolic/manifest.py +567 -0
- catabolic-0.1.0/src/catabolic/media.py +124 -0
- catabolic-0.1.0/src/catabolic/media_catalog.py +218 -0
- catabolic-0.1.0/src/catabolic/migration.py +625 -0
- catabolic-0.1.0/src/catabolic/migrations/001_initial.sql +36 -0
- catabolic-0.1.0/src/catabolic/migrations/001_initial.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/002_migration_history.sql +7 -0
- catabolic-0.1.0/src/catabolic/migrations/002_migration_history.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/003_media_model.sql +35 -0
- catabolic-0.1.0/src/catabolic/migrations/003_media_model.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/004_tags.sql +40 -0
- catabolic-0.1.0/src/catabolic/migrations/004_tags.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/005_hardlinks.sql +20 -0
- catabolic-0.1.0/src/catabolic/migrations/005_hardlinks.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/006_enrichment.sql +66 -0
- catabolic-0.1.0/src/catabolic/migrations/006_enrichment.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/007_processing_attempts.sql +14 -0
- catabolic-0.1.0/src/catabolic/migrations/007_processing_attempts.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/008_processing_artifacts.sql +32 -0
- catabolic-0.1.0/src/catabolic/migrations/008_processing_artifacts.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/009_output_definitions.sql +30 -0
- catabolic-0.1.0/src/catabolic/migrations/009_output_definitions.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/010_item_workflow.sql +38 -0
- catabolic-0.1.0/src/catabolic/migrations/010_item_workflow.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/011_processing_rules.sql +24 -0
- catabolic-0.1.0/src/catabolic/migrations/011_processing_rules.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/012_rendition_publication.sql +47 -0
- catabolic-0.1.0/src/catabolic/migrations/012_rendition_publication.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/013_processor_workers.sql +31 -0
- catabolic-0.1.0/src/catabolic/migrations/013_processor_workers.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/014_catalog_refresh.sql +16 -0
- catabolic-0.1.0/src/catabolic/migrations/014_catalog_refresh.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/015_queries_projections.sql +37 -0
- catabolic-0.1.0/src/catabolic/migrations/015_queries_projections.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/016_operation_rules.sql +43 -0
- catabolic-0.1.0/src/catabolic/migrations/016_operation_rules.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/017_consumers.sql +87 -0
- catabolic-0.1.0/src/catabolic/migrations/017_consumers.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/018_volume_identity.sql +21 -0
- catabolic-0.1.0/src/catabolic/migrations/018_volume_identity.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/019_source_trust.sql +4 -0
- catabolic-0.1.0/src/catabolic/migrations/019_source_trust.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/020_trust_evidence.sql +10 -0
- catabolic-0.1.0/src/catabolic/migrations/020_trust_evidence.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/021_execution_claims.sql +16 -0
- catabolic-0.1.0/src/catabolic/migrations/021_execution_claims.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/022_http_access.sql +34 -0
- catabolic-0.1.0/src/catabolic/migrations/022_http_access.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/023_fallback_resolution.sql +324 -0
- catabolic-0.1.0/src/catabolic/migrations/023_fallback_resolution.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/024_watchers.sql +38 -0
- catabolic-0.1.0/src/catabolic/migrations/024_watchers.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/025_media_components.sql +45 -0
- catabolic-0.1.0/src/catabolic/migrations/025_media_components.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/026_observation_requests.sql +10 -0
- catabolic-0.1.0/src/catabolic/migrations/026_observation_requests.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/migrations/027_guarded_observations.sql +27 -0
- catabolic-0.1.0/src/catabolic/migrations/027_guarded_observations.sql.license +2 -0
- catabolic-0.1.0/src/catabolic/native_monitor.py +76 -0
- catabolic-0.1.0/src/catabolic/network_adapters.py +299 -0
- catabolic-0.1.0/src/catabolic/notification_worker.py +75 -0
- catabolic-0.1.0/src/catabolic/notifications.py +259 -0
- catabolic-0.1.0/src/catabolic/observations.py +893 -0
- catabolic-0.1.0/src/catabolic/operations.py +178 -0
- catabolic-0.1.0/src/catabolic/output_cli.py +109 -0
- catabolic-0.1.0/src/catabolic/outputs.py +315 -0
- catabolic-0.1.0/src/catabolic/plans.py +355 -0
- catabolic-0.1.0/src/catabolic/plex_import.py +407 -0
- catabolic-0.1.0/src/catabolic/plex_login.py +225 -0
- catabolic-0.1.0/src/catabolic/process_runner.py +113 -0
- catabolic-0.1.0/src/catabolic/processing.py +1070 -0
- catabolic-0.1.0/src/catabolic/processor_cli.py +115 -0
- catabolic-0.1.0/src/catabolic/processors.py +462 -0
- catabolic-0.1.0/src/catabolic/program_bundle.py +466 -0
- catabolic-0.1.0/src/catabolic/program_cli.py +221 -0
- catabolic-0.1.0/src/catabolic/program_contracts.py +108 -0
- catabolic-0.1.0/src/catabolic/projection_stats.py +251 -0
- catabolic-0.1.0/src/catabolic/projections.py +152 -0
- catabolic-0.1.0/src/catabolic/publication_lock.py +30 -0
- catabolic-0.1.0/src/catabolic/query.py +744 -0
- catabolic-0.1.0/src/catabolic/receipts.py +249 -0
- catabolic-0.1.0/src/catabolic/reconcile.py +856 -0
- catabolic-0.1.0/src/catabolic/remount.py +419 -0
- catabolic-0.1.0/src/catabolic/rendering.py +633 -0
- catabolic-0.1.0/src/catabolic/rendition_publication.py +348 -0
- catabolic-0.1.0/src/catabolic/rendition_requests.py +276 -0
- catabolic-0.1.0/src/catabolic/revision_evidence.py +19 -0
- catabolic-0.1.0/src/catabolic/rule_analysis.py +130 -0
- catabolic-0.1.0/src/catabolic/rule_cli.py +198 -0
- catabolic-0.1.0/src/catabolic/rule_estimates.py +185 -0
- catabolic-0.1.0/src/catabolic/rule_external.py +226 -0
- catabolic-0.1.0/src/catabolic/rules.py +893 -0
- catabolic-0.1.0/src/catabolic/saved_queries.py +351 -0
- catabolic-0.1.0/src/catabolic/scan_execution.py +541 -0
- catabolic-0.1.0/src/catabolic/scan_policy.py +111 -0
- catabolic-0.1.0/src/catabolic/scan_staging.py +55 -0
- catabolic-0.1.0/src/catabolic/scan_traversal.py +282 -0
- catabolic-0.1.0/src/catabolic/selection.py +427 -0
- catabolic-0.1.0/src/catabolic/source_access.py +77 -0
- catabolic-0.1.0/src/catabolic/source_events.py +31 -0
- catabolic-0.1.0/src/catabolic/source_trust.py +104 -0
- catabolic-0.1.0/src/catabolic/sql_query.py +721 -0
- catabolic-0.1.0/src/catabolic/store.py +158 -0
- catabolic-0.1.0/src/catabolic/supervisor.py +263 -0
- catabolic-0.1.0/src/catabolic/tagging.py +280 -0
- catabolic-0.1.0/src/catabolic/targets.py +353 -0
- catabolic-0.1.0/src/catabolic/volume_identity.py +60 -0
- catabolic-0.1.0/src/catabolic/watcher_cli.py +71 -0
- catabolic-0.1.0/src/catabolic/watcher_models.py +65 -0
- catabolic-0.1.0/src/catabolic/watcher_processing.py +91 -0
- catabolic-0.1.0/src/catabolic/watcher_schedule.py +68 -0
- catabolic-0.1.0/src/catabolic/watchers.py +439 -0
- catabolic-0.1.0/src/catabolic/watching.py +136 -0
- catabolic-0.1.0/src/catabolic/work_inbox.py +444 -0
- catabolic-0.1.0/src/catabolic/workflow_cli.py +116 -0
- catabolic-0.1.0/src/catabolic.egg-info/PKG-INFO +470 -0
- catabolic-0.1.0/src/catabolic.egg-info/SOURCES.txt +409 -0
- catabolic-0.1.0/src/catabolic.egg-info/dependency_links.txt +1 -0
- catabolic-0.1.0/src/catabolic.egg-info/entry_points.txt +2 -0
- catabolic-0.1.0/src/catabolic.egg-info/requires.txt +16 -0
- catabolic-0.1.0/src/catabolic.egg-info/top_level.txt +1 -0
- catabolic-0.1.0/tests/fixtures/experience/cases.json.license +2 -0
- catabolic-0.1.0/tests/fixtures/interchange/manifest-v1.json.license +2 -0
- catabolic-0.1.0/tests/test_application.py +778 -0
- catabolic-0.1.0/tests/test_artifacts.py +552 -0
- catabolic-0.1.0/tests/test_audit_fixes.py +364 -0
- catabolic-0.1.0/tests/test_catalog_refresh.py +290 -0
- catabolic-0.1.0/tests/test_component_lifecycle.py +264 -0
- catabolic-0.1.0/tests/test_component_media.py +496 -0
- catabolic-0.1.0/tests/test_component_migration.py +213 -0
- catabolic-0.1.0/tests/test_component_packages.py +315 -0
- catabolic-0.1.0/tests/test_components.py +263 -0
- catabolic-0.1.0/tests/test_consumer_publication.py +141 -0
- catabolic-0.1.0/tests/test_consumers.py +1021 -0
- catabolic-0.1.0/tests/test_distribution.py +97 -0
- catabolic-0.1.0/tests/test_document_text.py +266 -0
- catabolic-0.1.0/tests/test_documentation.py +86 -0
- catabolic-0.1.0/tests/test_enrichment.py +845 -0
- catabolic-0.1.0/tests/test_execution_claims.py +84 -0
- catabolic-0.1.0/tests/test_experience_acceptance.py +163 -0
- catabolic-0.1.0/tests/test_fallback_baseline.py +121 -0
- catabolic-0.1.0/tests/test_fallback_evidence.py +118 -0
- catabolic-0.1.0/tests/test_fallback_http.py +120 -0
- catabolic-0.1.0/tests/test_fallback_identity.py +187 -0
- catabolic-0.1.0/tests/test_fallback_lifecycle.py +158 -0
- catabolic-0.1.0/tests/test_fallback_processing.py +101 -0
- catabolic-0.1.0/tests/test_fallback_resolution.py +143 -0
- catabolic-0.1.0/tests/test_fallback_review.py +173 -0
- catabolic-0.1.0/tests/test_graphql_query.py +177 -0
- catabolic-0.1.0/tests/test_guarded_scans.py +598 -0
- catabolic-0.1.0/tests/test_hardlinks.py +513 -0
- catabolic-0.1.0/tests/test_http_backend.py +760 -0
- catabolic-0.1.0/tests/test_http_contract.py +262 -0
- catabolic-0.1.0/tests/test_http_renditions.py +327 -0
- catabolic-0.1.0/tests/test_http_review.py +293 -0
- catabolic-0.1.0/tests/test_interchange.py +268 -0
- catabolic-0.1.0/tests/test_item_workflow.py +296 -0
- catabolic-0.1.0/tests/test_layouts.py +451 -0
- catabolic-0.1.0/tests/test_maintenance.py +391 -0
- catabolic-0.1.0/tests/test_manifest.py +279 -0
- catabolic-0.1.0/tests/test_media_model.py +581 -0
- catabolic-0.1.0/tests/test_migrations.py +669 -0
- catabolic-0.1.0/tests/test_native_layout.py +175 -0
- catabolic-0.1.0/tests/test_native_processing.py +259 -0
- catabolic-0.1.0/tests/test_notifications.py +122 -0
- catabolic-0.1.0/tests/test_observation_service.py +562 -0
- catabolic-0.1.0/tests/test_outputs.py +317 -0
- catabolic-0.1.0/tests/test_plex_import.py +413 -0
- catabolic-0.1.0/tests/test_plex_login.py +264 -0
- catabolic-0.1.0/tests/test_processor_workers.py +223 -0
- catabolic-0.1.0/tests/test_program_bundle.py +307 -0
- catabolic-0.1.0/tests/test_programmable_catalog.py +561 -0
- catabolic-0.1.0/tests/test_programmable_migration.py +112 -0
- catabolic-0.1.0/tests/test_projection_stats.py +224 -0
- catabolic-0.1.0/tests/test_queries.py +434 -0
- catabolic-0.1.0/tests/test_query_layouts.py +399 -0
- catabolic-0.1.0/tests/test_release_safety.py +300 -0
- catabolic-0.1.0/tests/test_release_tooling.py +88 -0
- catabolic-0.1.0/tests/test_remount.py +375 -0
- catabolic-0.1.0/tests/test_rendition_workflows.py +407 -0
- catabolic-0.1.0/tests/test_rule_scale_calibration.py +162 -0
- catabolic-0.1.0/tests/test_rules.py +417 -0
- catabolic-0.1.0/tests/test_source_trust.py +261 -0
- catabolic-0.1.0/tests/test_sql_query.py +472 -0
- catabolic-0.1.0/tests/test_storage_acceptance.py +92 -0
- catabolic-0.1.0/tests/test_synthetic_library.py +54 -0
- catabolic-0.1.0/tests/test_tagging.py +416 -0
- catabolic-0.1.0/tests/test_targets.py +409 -0
- catabolic-0.1.0/tests/test_watcher_http.py +126 -0
- catabolic-0.1.0/tests/test_watcher_recovery.py +360 -0
- catabolic-0.1.0/tests/test_watchers.py +440 -0
- catabolic-0.1.0/tests/test_work_inbox.py +778 -0
catabolic-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jaga Tranvo
|
|
4
|
+
Copyright (c) 2026 The Catabolic Contributors
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
catabolic-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: catabolic
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Programmable media catalog with query-driven rules and safe output projections
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/Jagalite/catabolic
|
|
7
|
+
Project-URL: Documentation, https://github.com/Jagalite/catabolic/wiki
|
|
8
|
+
Project-URL: Repository, https://github.com/Jagalite/catabolic
|
|
9
|
+
Project-URL: Issues, https://github.com/Jagalite/catabolic/issues
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Operating System :: MacOS
|
|
12
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Requires-Python: >=3.11
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: graphql-core==3.2.12
|
|
18
|
+
Requires-Dist: pydantic==2.13.5
|
|
19
|
+
Provides-Extra: watch
|
|
20
|
+
Requires-Dist: watchdog==6.0.0; extra == "watch"
|
|
21
|
+
Provides-Extra: http
|
|
22
|
+
Requires-Dist: fastapi==0.141.1; extra == "http"
|
|
23
|
+
Requires-Dist: uvicorn==0.52.4; extra == "http"
|
|
24
|
+
Provides-Extra: notifications
|
|
25
|
+
Requires-Dist: apprise==1.13.1; extra == "notifications"
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: ruff==0.16.6; extra == "dev"
|
|
28
|
+
Requires-Dist: jsonschema==4.26.0; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# Catabolic
|
|
32
|
+
|
|
33
|
+
<!--
|
|
34
|
+
SPDX-FileCopyrightText: 2026 The Catabolic Contributors
|
|
35
|
+
SPDX-License-Identifier: MIT
|
|
36
|
+
-->
|
|
37
|
+
|
|
38
|
+
**A programmable media catalog.**
|
|
39
|
+
|
|
40
|
+
People and agents decide what belongs. Queries select catalog state. Rules
|
|
41
|
+
perform explicit processing and record results. Projections publish selected media
|
|
42
|
+
into maintained output structures. Consumer integrations connect those outputs
|
|
43
|
+
to applications; optional notifications tell people what happened.
|
|
44
|
+
|
|
45
|
+
Inventory media across drives and mounted storage, identify logical items, and
|
|
46
|
+
inspect their metadata, relationships, technical facts and processing evidence
|
|
47
|
+
with SQL or GraphQL. Save a reusable query, attach an operation rule or an output
|
|
48
|
+
projection, preview, execute a bounded batch, and verify the resulting state.
|
|
49
|
+
|
|
50
|
+
Completed processing becomes catalog evidence. A query for media missing a
|
|
51
|
+
rendition stops matching once that result is recorded. Different projections can
|
|
52
|
+
select different versions of the same item and maintain independent Plex,
|
|
53
|
+
Jellyfin, music or document layouts without changing original files. Durable jobs,
|
|
54
|
+
receipts and filesystem journals preserve recovery when work is interrupted.
|
|
55
|
+
|
|
56
|
+
Start with the [query → rule → projection guide](docs/PROGRAMMABLE_CATALOG.md),
|
|
57
|
+
including implemented operation types, compatibility and validation limits.
|
|
58
|
+
|
|
59
|
+
[Get started](https://github.com/Jagalite/catabolic/blob/main/docs/GETTING_STARTED.md) · [Documentation](https://github.com/Jagalite/catabolic/wiki) · [FAQ](https://github.com/Jagalite/catabolic/blob/main/docs/FAQ.md)
|
|
60
|
+
|
|
61
|
+
## What can you do with it?
|
|
62
|
+
|
|
63
|
+
- **Bring your collection together.** Catalog media across several drives and
|
|
64
|
+
mounted storage locations, and search the recorded catalog while they're offline.
|
|
65
|
+
- **Organize it your way.** Add titles, identities, tags, and relationships to
|
|
66
|
+
movies, TV, music, books, audiobooks, comics, photos, documents, and more.
|
|
67
|
+
- **Track your cataloging work.** Use the [work inbox](docs/INBOX.md) to find
|
|
68
|
+
unidentified files, pending reviews, and processing or projection failures.
|
|
69
|
+
Keep an entry worklog, defer unresolved items, and check required work before
|
|
70
|
+
marking an entry complete.
|
|
71
|
+
- **Make collections from searches.** Save a selection, such as favorite films or
|
|
72
|
+
books by an author, and refresh it into a symlink folder when you choose.
|
|
73
|
+
- **Build symlink libraries for your apps.** Generate popular folder formats or
|
|
74
|
+
custom layouts from the same catalog, with links back to your source files.
|
|
75
|
+
- **Keep useful metadata alongside your media.** Export catalog details,
|
|
76
|
+
playlists, and metadata files for other tools.
|
|
77
|
+
- **Keep track of custom versions.** Catalog your own remuxes and edits, or use
|
|
78
|
+
optional FFmpeg recipes to generate separate files with recorded source relationships.
|
|
79
|
+
- **Generate previews and smaller versions with rules.** Apply a recipe to a
|
|
80
|
+
saved selection, backfill existing media, and include new matches during
|
|
81
|
+
maintenance. Preview the estimated additional storage before queuing work.
|
|
82
|
+
- **Give each library the versions it needs.** Publish a separate transcode
|
|
83
|
+
library, keep originals in another, and register results from external processors.
|
|
84
|
+
[Automatic catalog updates](docs/CATALOG_REFRESH.md) can add links when new
|
|
85
|
+
versions become ready, with durable retries for offline destinations.
|
|
86
|
+
- **Keep projections useful during storage outages.** [Fallback policies](docs/FALLBACK.md)
|
|
87
|
+
try saved candidate queries in order: originals, backup occurrences, then existing
|
|
88
|
+
renditions. Logical membership survives outages, and an explicitly enabled worker
|
|
89
|
+
performs recoverable symlink switches with stable failback.
|
|
90
|
+
- **Select audio and subtitles consistently.** [Media components](docs/COMPONENTS.md)
|
|
91
|
+
make embedded streams and external files queryable together, with explicit
|
|
92
|
+
compatibility and separate extraction/mux operations.
|
|
93
|
+
- **Coordinate network processing.** Submit work through a versioned HTTP receipt
|
|
94
|
+
adapter, with durable jobs and worker leases. Estimates learn from successful
|
|
95
|
+
local renders, and paged rules can select up to 100,000 IDs. See
|
|
96
|
+
[processor workflows](docs/PROCESSORS.md).
|
|
97
|
+
|
|
98
|
+
For example, the same film can appear in your Plex library and a favorites folder
|
|
99
|
+
without storing another copy of the movie. Each symlink points to the existing
|
|
100
|
+
file while giving it a name and location suited to that library. You can preview
|
|
101
|
+
the changes before applying them.
|
|
102
|
+
|
|
103
|
+
## Build an application on the catalog
|
|
104
|
+
|
|
105
|
+
The optional [HTTP backend](docs/HTTP.md) exposes authorized GraphQL, operator SQL,
|
|
106
|
+
saved queries, metadata, revision-pinned content and durable rendition requests.
|
|
107
|
+
Scoped tokens can permit browser derivatives while denying originals. A separate
|
|
108
|
+
foreground worker prepares approved recipes; reusable short-lived tickets support
|
|
109
|
+
browser range requests. CLI and HTTP share jobs, artifacts and recovery.
|
|
110
|
+
|
|
111
|
+
Install the optional HTTP dependencies and configure grants/source exposure before
|
|
112
|
+
starting `catabolic --db catalog.db api serve`. The server defaults to loopback
|
|
113
|
+
and existing-content mode. Processing requires explicit enablement and a worker.
|
|
114
|
+
The [HTTP guide](docs/HTTP.md) records limits and current release qualification.
|
|
115
|
+
The [public developer contract](docs/HTTP.md#public-developer-contract) includes typed
|
|
116
|
+
responses, stable operation IDs, versioned OpenAPI/GraphQL artifacts and generated
|
|
117
|
+
TypeScript client acceptance tests.
|
|
118
|
+
|
|
119
|
+
## Works with your media apps
|
|
120
|
+
|
|
121
|
+
Folder presets cover **Plex, Jellyfin, Emby, Kodi, Infuse, Navidrome,
|
|
122
|
+
Audiobookshelf, Komga, Kavita**, and other applications. Custom naming rules let
|
|
123
|
+
you build a different structure. There are also explicit import options for
|
|
124
|
+
calibre, Calibre-Web, and Immich.
|
|
125
|
+
|
|
126
|
+
See [supported applications](https://github.com/Jagalite/catabolic/blob/main/docs/COMPATIBILITY.md) for the full list and each
|
|
127
|
+
integration's requirements. Folder presets and import options behave differently;
|
|
128
|
+
imports copy or upload selected media.
|
|
129
|
+
|
|
130
|
+
### Start from an existing Plex library
|
|
131
|
+
|
|
132
|
+
[Import Plex metadata](docs/CONSUMERS.md#import-an-existing-plex-library-into-catabolic)
|
|
133
|
+
to bootstrap file identification from your existing library. Connect your Plex
|
|
134
|
+
server, map its media paths to scanned Catabolic sources, then preview and apply
|
|
135
|
+
a bounded page. Imports preserve existing metadata, retain Plex identity and
|
|
136
|
+
provenance, and report ambiguous or unavailable files for review. They do not copy
|
|
137
|
+
media or change Plex. Movies, episode files, music tracks and photos are supported;
|
|
138
|
+
parent relationships, playlists and watched state are outside the import scope.
|
|
139
|
+
|
|
140
|
+
### Connect published outputs to Plex or Jellyfin
|
|
141
|
+
|
|
142
|
+
[Consumer bindings](docs/CONSUMERS.md) connect a projection or media subtree to an
|
|
143
|
+
exact server and library identity. Configure a binding once: verified publication
|
|
144
|
+
then records durable scan generations and can automatically request library scans.
|
|
145
|
+
Unchanged output creates no new scan. Offline servers leave retryable delivery
|
|
146
|
+
work without rerendering completed media or rewriting unchanged links.
|
|
147
|
+
|
|
148
|
+
Plex supports browser sign-in, server/library discovery, existing-library binding,
|
|
149
|
+
explicit library creation, normal section scans and bounded file-path indexing checks. Jellyfin supports
|
|
150
|
+
existing-library bindings and scans; legacy refresh commands remain available.
|
|
151
|
+
Folder naming presets for other apps do not imply an API integration.
|
|
152
|
+
|
|
153
|
+
Scan acceptance and verified indexing are separate outcomes. Plex must be able
|
|
154
|
+
to read both published symlinks and their resolved targets. Protocol and recovery
|
|
155
|
+
fixtures are tested; live Plex acceptance remains unverified. See the
|
|
156
|
+
[validation record](docs/CONSUMER_VALIDATION.md) for evidence and limitations.
|
|
157
|
+
|
|
158
|
+
## Install
|
|
159
|
+
|
|
160
|
+
Requires **Python 3.11+** on **macOS or Linux**.
|
|
161
|
+
|
|
162
|
+
```sh
|
|
163
|
+
python3 -m venv ~/.venvs/catabolic
|
|
164
|
+
. ~/.venvs/catabolic/bin/activate
|
|
165
|
+
python -m pip install catabolic
|
|
166
|
+
catabolic --help
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Prefer pipx or want to install a specific version? See the
|
|
170
|
+
[installation guide](https://github.com/Jagalite/catabolic/blob/main/docs/INSTALLATION.md).
|
|
171
|
+
|
|
172
|
+
## Try it without touching your library
|
|
173
|
+
|
|
174
|
+
The [getting started walkthrough](https://github.com/Jagalite/catabolic/blob/main/docs/GETTING_STARTED.md) creates a small sample
|
|
175
|
+
collection and walks through cataloging, tagging, and generating your first
|
|
176
|
+
folders. No media server, API key, or FFmpeg installation is needed.
|
|
177
|
+
|
|
178
|
+
Then add your own source locations, identify the files you want to organize,
|
|
179
|
+
choose an output format, and preview the result.
|
|
180
|
+
|
|
181
|
+
Catabolic is a command-line application and is currently **alpha**. Keep backups
|
|
182
|
+
and start with a small collection. Generated folders need access to their source
|
|
183
|
+
files; they are not independent backups.
|
|
184
|
+
|
|
185
|
+
## Agentic Operator guide
|
|
186
|
+
|
|
187
|
+
People and agents use the same five workflows:
|
|
188
|
+
|
|
189
|
+
- **Discover and identify:** bind sources → scan → inspect the inbox → propose
|
|
190
|
+
identities and associations → review and accept proposals.
|
|
191
|
+
- **Curate and complete:** inspect requirements → resolve reviews through their
|
|
192
|
+
owning services → check readiness → mark curation complete. Missing required
|
|
193
|
+
evidence can bring an item back into needs_attention. See [worklogs and
|
|
194
|
+
requirements](docs/WORKLOG.md).
|
|
195
|
+
- **Publish libraries:** save queries and output layouts → preview → publish →
|
|
196
|
+
verify. Curation readiness and projection health are separate. See the
|
|
197
|
+
[query → rule → projection guide](docs/PROGRAMMABLE_CATALOG.md).
|
|
198
|
+
- **Process media:** choose an approved operation → admit jobs → run workers →
|
|
199
|
+
inspect generated artifacts and lineage → recover failures. See
|
|
200
|
+
[processing rules](docs/RULES.md) and [artifacts](docs/ARTIFACTS.md).
|
|
201
|
+
- **Maintain continuously:** configure and enable watchers → run the supervisor →
|
|
202
|
+
inspect reports, history and the inbox → address outstanding work. See
|
|
203
|
+
[watchers](docs/WATCHERS.md).
|
|
204
|
+
|
|
205
|
+
The daily loop is **scan or supervise → inbox summary → inbox list → inbox show
|
|
206
|
+
→ existing operation → check again**. Start with the
|
|
207
|
+
[setup walkthrough](https://github.com/Jagalite/catabolic/wiki/Getting-Started)
|
|
208
|
+
to register sources and configure output catalogs and layouts. Then select your
|
|
209
|
+
database and profile for the commands below:
|
|
210
|
+
|
|
211
|
+
```sh
|
|
212
|
+
export CATABOLIC_DB=/absolute/path/catalog.sqlite3
|
|
213
|
+
export CATABOLIC_PROFILE=default
|
|
214
|
+
catabolic db status
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
If an upgrade is required, follow the
|
|
218
|
+
[migration guide](https://github.com/Jagalite/catabolic/wiki/Database-Migrations)
|
|
219
|
+
before continuing.
|
|
220
|
+
|
|
221
|
+
### 1. Refresh evidence: manually or with watchers
|
|
222
|
+
|
|
223
|
+
Choose either entry path using the database/profile selected above.
|
|
224
|
+
|
|
225
|
+
For a manual refresh:
|
|
226
|
+
|
|
227
|
+
```sh
|
|
228
|
+
catabolic scan
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Scans publish discoveries in guarded batches and report unfinished directories.
|
|
232
|
+
Use `scan --continue-request REQUEST_ID --extended` to continue outstanding work;
|
|
233
|
+
see [guarded observation policies and coverage](docs/OBSERVATIONS.md#guarded-discovery-and-continuation-schema-27).
|
|
234
|
+
|
|
235
|
+
For scheduled refreshes, [configure a watcher once](#configure-a-watcher-once),
|
|
236
|
+
then keep its supervisor running:
|
|
237
|
+
|
|
238
|
+
```sh
|
|
239
|
+
catabolic supervise
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
`supervise` runs continuously in the foreground; `supervise --once` handles one
|
|
243
|
+
pass. Watchers may refresh source observations when their plans require it.
|
|
244
|
+
Check scan or watcher results for incomplete evidence. Both paths lead to the
|
|
245
|
+
same inbox steps below; with a foreground supervisor, use another terminal with
|
|
246
|
+
the same database/profile.
|
|
247
|
+
|
|
248
|
+
### 2. Inspect the inbox
|
|
249
|
+
|
|
250
|
+
```sh
|
|
251
|
+
catabolic --json inbox summary
|
|
252
|
+
catabolic --json inbox list --limit 100
|
|
253
|
+
catabolic --json inbox show WORK_KEY
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Replace `WORK_KEY` with a key returned by `list`. Detail explains why the work
|
|
257
|
+
appears, which record owns it, and which existing operation addresses it. Follow
|
|
258
|
+
`next_cursor` with `inbox list --after CURSOR`; `--include-inactive` includes
|
|
259
|
+
waiting, deferred and historical entries. Reads use recorded evidence and do not
|
|
260
|
+
scan or complete work. An empty actionable inbox does not prove curation finished.
|
|
261
|
+
See the [inbox guide](docs/INBOX.md) for query examples and completion reporting.
|
|
262
|
+
|
|
263
|
+
### 3. Act through the owning service, then check again
|
|
264
|
+
|
|
265
|
+
Use the entry's suggested operation after reloading its owner and checking current
|
|
266
|
+
eligibility and preconditions. Suggestions describe work; they do not authorize it.
|
|
267
|
+
Review identities, associations and tags through the proposal workflow, resolve
|
|
268
|
+
explicit reviews through requirement operations, and record decisions in each
|
|
269
|
+
entry's worklog. The
|
|
270
|
+
[recommended workflow](https://github.com/Jagalite/catabolic/wiki/Recommended-Workflow)
|
|
271
|
+
covers curation, completion checks, and the first preview/apply/sync/verify cycle
|
|
272
|
+
for your symlink folders.
|
|
273
|
+
|
|
274
|
+
After acting, return to **step 2** to check recorded results. Return to **step 1**
|
|
275
|
+
when evidence needs refreshing. Keep checking even without new notifications:
|
|
276
|
+
previously outstanding work remains discoverable until its owner resolves it.
|
|
277
|
+
|
|
278
|
+
### Configure a watcher once
|
|
279
|
+
|
|
280
|
+
For scanning alone, use an [observation-only watcher](docs/OBSERVATIONS.md):
|
|
281
|
+
`{"plan":{"kind":"observation","sources":["media"]},"schedule":{"kind":"interval","seconds":3600}}`.
|
|
282
|
+
It schedules the same one-shot operation as `scan`, with no query or reaction.
|
|
283
|
+
`supervise --once` processes eligible watcher work; it does not mean “scan all sources once.”
|
|
284
|
+
|
|
285
|
+
For a query report as well as observation, use the configuration below.
|
|
286
|
+
|
|
287
|
+
Save an inbox query using the [inbox query examples](docs/INBOX.md#queries-and-watchers),
|
|
288
|
+
then put its immutable query revision ID in `inbox-watcher.json`:
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"version": 1,
|
|
293
|
+
"authority": "local_owner",
|
|
294
|
+
"plan": {"kind": "query", "query_id": "IMMUTABLE_QUERY_REVISION"},
|
|
295
|
+
"schedule": {"kind": "interval", "seconds": 3600},
|
|
296
|
+
"max_age_seconds": 300,
|
|
297
|
+
"reaction": "report"
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Using the database/profile selected above:
|
|
302
|
+
|
|
303
|
+
```sh
|
|
304
|
+
catabolic watcher put inbox-audit --file inbox-watcher.json
|
|
305
|
+
catabolic watcher preview inbox-audit
|
|
306
|
+
catabolic watcher enable inbox-audit
|
|
307
|
+
catabolic watcher run inbox-audit
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Continue with the supervisor entry path in **step 1**, then use the shared inbox
|
|
311
|
+
flow in **steps 2–3**. This report watcher does not perform suggested inbox actions
|
|
312
|
+
or launch an agent. To inspect watcher scheduling and failures:
|
|
313
|
+
|
|
314
|
+
```sh
|
|
315
|
+
catabolic watcher pending
|
|
316
|
+
catabolic watcher history inbox-audit
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
The [watcher guide](docs/WATCHERS.md) covers schedules,
|
|
320
|
+
events and recovery. For watcher-owned projections, use `watcher run` for repair
|
|
321
|
+
or inventory-only maintenance; legacy maintenance does not reconcile those outputs.
|
|
322
|
+
|
|
323
|
+
### Run routine maintenance
|
|
324
|
+
|
|
325
|
+
Once your output layouts are configured:
|
|
326
|
+
|
|
327
|
+
```sh
|
|
328
|
+
# Scan sources, refresh output links, verify them, and update metadata manifests.
|
|
329
|
+
catabolic maintenance --all-catalogs --manifest
|
|
330
|
+
|
|
331
|
+
# Or scan and report the backlog without updating output folders.
|
|
332
|
+
catabolic --json maintenance --inventory-only
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
The report includes new files, uncataloged files, entry statuses and unfinished
|
|
336
|
+
jobs. Maintenance defaults to zero output removals; it does not identify media
|
|
337
|
+
or mark entries complete. See the
|
|
338
|
+
[maintenance guide](https://github.com/Jagalite/catabolic/wiki/Maintenance)
|
|
339
|
+
for scan exclusions, budgets, optional analysis and handling incomplete cycles.
|
|
340
|
+
|
|
341
|
+
### Backfill previews or transcodes
|
|
342
|
+
|
|
343
|
+
Follow the [processing rules guide](https://github.com/Jagalite/catabolic/wiki/Processing-Rules)
|
|
344
|
+
to collect probe metadata and save a recipe, selection and generated destination.
|
|
345
|
+
Replace `RULE_ID` with the saved rule's ID, then review its full storage estimate:
|
|
346
|
+
|
|
347
|
+
```sh
|
|
348
|
+
catabolic rule preview RULE_ID
|
|
349
|
+
# Queue up to 10 outputs with a 10 GiB estimated planning budget.
|
|
350
|
+
catabolic rule apply RULE_ID --batch 10 --max-new-bytes 10737418240
|
|
351
|
+
catabolic rule run RULE_ID --batch 1
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Estimates show additional space, a likely range and any unknown sizes; they are
|
|
355
|
+
not guaranteed output sizes. Rendering requires an external FFmpeg installation
|
|
356
|
+
and creates separate files, preserving originals. After reviewing a rule, opt it
|
|
357
|
+
into future maintenance cycles:
|
|
358
|
+
|
|
359
|
+
```sh
|
|
360
|
+
catabolic rule enable RULE_ID
|
|
361
|
+
catabolic maintenance --all-catalogs --rules --rule-batch 10 --render-rules 1
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
`--rules` queues enabled rules; `--render-rules 1` also renders at most one job.
|
|
365
|
+
Ordinary maintenance does neither. For agents and scheduled runs, use global
|
|
366
|
+
`--json` and check exit codes; see [automation](https://github.com/Jagalite/catabolic/wiki/Automation).
|
|
367
|
+
|
|
368
|
+
### Set up delivery once
|
|
369
|
+
|
|
370
|
+
Start with a configured projection named `cinema` that publishes movie links
|
|
371
|
+
under `Movies`. Use the database/profile selected above. Sign in with Plex, open
|
|
372
|
+
the returned `authorization_url`, then complete the login with its `login_id`:
|
|
373
|
+
|
|
374
|
+
```sh
|
|
375
|
+
catabolic consumer plex-login
|
|
376
|
+
catabolic consumer plex-login-complete LOGIN_ID
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Completion returns a private `credential_file` path without printing the token.
|
|
380
|
+
Replace the example endpoint with your Plex server address and `CREDENTIAL_FILE`
|
|
381
|
+
with that path. Login does not discover the server address automatically.
|
|
382
|
+
|
|
383
|
+
```sh
|
|
384
|
+
catabolic consumer connection-put home --application plex \
|
|
385
|
+
--endpoint https://plex.example.test:32400 --credential-file CREDENTIAL_FILE --apply
|
|
386
|
+
catabolic consumer discover home --type movie
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
If discovery reports library `7` rooted at `/media/Movies`, preview and then save
|
|
390
|
+
the binding. The remote root is the path **as Plex sees it**, which may differ
|
|
391
|
+
from the host's output path. Plex also needs access to the symlinks' targets.
|
|
392
|
+
|
|
393
|
+
```sh
|
|
394
|
+
catabolic consumer bind cinema-plex --connection home --catalog cinema \
|
|
395
|
+
--subtree Movies --remote-root /media/Movies --library-id 7 --type movie \
|
|
396
|
+
--automatic --initial-scan
|
|
397
|
+
catabolic consumer bind cinema-plex --connection home --catalog cinema \
|
|
398
|
+
--subtree Movies --remote-root /media/Movies --library-id 7 --type movie \
|
|
399
|
+
--automatic --initial-scan --apply
|
|
400
|
+
catabolic projection execute cinema
|
|
401
|
+
catabolic consumer run --limit 10
|
|
402
|
+
catabolic consumer bindings
|
|
403
|
+
catabolic consumer verify-indexing cinema-plex --limit 100
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
`--initial-scan` schedules existing published files; `--automatic` enables delivery
|
|
407
|
+
after future publication. A saved binding alone does not start a worker. Scan
|
|
408
|
+
acceptance means Plex accepted the request; `verify-indexing` separately reports
|
|
409
|
+
whether expected paths were found and may be inconclusive while indexing or in a
|
|
410
|
+
large library. An output catalog without a saved projection can use `sync` and
|
|
411
|
+
`verify` instead; see the [consumer guide](docs/CONSUMERS.md).
|
|
412
|
+
|
|
413
|
+
For SSH, open the sign-in link on another device. Scheduled workers need access
|
|
414
|
+
to the same credential file. An existing token can instead be supplied through
|
|
415
|
+
protected configuration with `--credential-env PLEX_TOKEN`; see
|
|
416
|
+
[sign-in and credential setup](docs/CONSUMERS.md#sign-in-with-plex).
|
|
417
|
+
|
|
418
|
+
Publication performs a bounded delivery drain when automatic delivery is enabled.
|
|
419
|
+
Schedule `catabolic consumer run --limit 10` for delayed retries, or supervise
|
|
420
|
+
`catabolic consumer watch --interval 30`. The CLI does not start a background
|
|
421
|
+
service. Inspect `consumer attempts` and `consumer events` for separate outcomes.
|
|
422
|
+
|
|
423
|
+
The [consumer guide](docs/CONSUMERS.md) covers explicit library creation, path
|
|
424
|
+
mapping, repair and optional Apprise subscriptions. Apprise is installed separately
|
|
425
|
+
with the `notifications` extra; its per-destination retries are independent of
|
|
426
|
+
scan delivery. Preview and apply any required database upgrade before setup;
|
|
427
|
+
the current schema is 20. Upgrading does not enable automatic network actions.
|
|
428
|
+
|
|
429
|
+
## Publishing a release
|
|
430
|
+
|
|
431
|
+
Keep the version in `pyproject.toml` and `src/catabolic/__init__.py` identical,
|
|
432
|
+
then create and push a matching `vVERSION` tag on the release commit. Pushing a
|
|
433
|
+
version tag runs the release validation workflow; publication requires a separate
|
|
434
|
+
manual request after configuring PyPI Trusted Publishing.
|
|
435
|
+
|
|
436
|
+
For example, to publish version `0.1.0` from its matching tag:
|
|
437
|
+
|
|
438
|
+
```sh
|
|
439
|
+
gh workflow run release.yml --ref v0.1.0 -f publish=true
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
The workflow runs all CI checks before uploading the tested wheel and source
|
|
443
|
+
archive to PyPI. It uses the `pypi` GitHub environment and Trusted Publishing;
|
|
444
|
+
no stored API token is required. Configure the PyPI publisher for `Jagalite`,
|
|
445
|
+
repository `catabolic`, workflow `release.yml`, and environment `pypi`.
|
|
446
|
+
Any configured environment approval is still required. Ordinary branch pushes
|
|
447
|
+
never publish. See [release setup and validation](docs/RELEASE_TESTING.md#pypi-trusted-publishing)
|
|
448
|
+
for first-publication setup and recovery after an interrupted upload.
|
|
449
|
+
|
|
450
|
+
## Learn more
|
|
451
|
+
|
|
452
|
+
- [Wiki](https://github.com/Jagalite/catabolic/wiki) — walkthroughs and detailed guides.
|
|
453
|
+
- [Recommended workflow](https://github.com/Jagalite/catabolic/blob/main/docs/WORKFLOW.md) — the everyday cataloging cycle; also `catabolic docs workflow`.
|
|
454
|
+
- [Processing rules](https://github.com/Jagalite/catabolic/wiki/Processing-Rules) — recipes, retroactive storage estimates and maintenance; also `catabolic docs rules`.
|
|
455
|
+
- [Output consumers](docs/CONSUMERS.md) — Plex/Jellyfin setup, durable scan delivery and optional notifications; also `catabolic docs consumers`.
|
|
456
|
+
- [Rendition workflows](https://github.com/Jagalite/catabolic/wiki/Rendition-Workflows) — transcode libraries, external result receipts and completion requirements.
|
|
457
|
+
- [Using Catabolic with agents](https://github.com/Jagalite/catabolic/blob/main/docs/AUTOMATION.md) — automation and structured output.
|
|
458
|
+
- [SQL queries](https://github.com/Jagalite/catabolic/blob/main/docs/QUERYING.md) and [GraphQL](https://github.com/Jagalite/catabolic/blob/main/docs/GRAPHQL.md) — explore the catalog.
|
|
459
|
+
- [Troubleshooting](https://github.com/Jagalite/catabolic/blob/main/docs/TROUBLESHOOTING.md) — common questions and recovery steps.
|
|
460
|
+
- [Development](https://github.com/Jagalite/catabolic/blob/main/docs/DEVELOPMENT.md) — contribute, run tests, and maintain the docs.
|
|
461
|
+
|
|
462
|
+
Documentation is also available offline: run `catabolic docs` after installation.
|
|
463
|
+
|
|
464
|
+
## License
|
|
465
|
+
|
|
466
|
+
[MIT](https://github.com/Jagalite/catabolic/blob/main/LICENSE). Copyright 2026 Jaga Tranvo and The Catabolic Contributors.
|
|
467
|
+
|
|
468
|
+
Owner-controlled source identity settings and their evidence are described in [Trust policies](docs/TRUST_POLICIES.md), also available with `catabolic docs trust`.
|
|
469
|
+
|
|
470
|
+
Named query watchers share source observations while maintaining independent schedules and projection ownership. See [the watcher guide](docs/WATCHERS.md).
|