linkedparticles 1.149.0__tar.gz → 1.151.18__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.
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/PKG-INFO +3 -3
- linkedparticles-1.151.18/alembic/versions/040_backfill_particle_tag_edges.py +88 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/openapi.json +2 -1
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/app.py +1 -1
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/audit.py +1 -1
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/benchmark.py +10 -10
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/corpus.py +52 -174
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/extractor.py +1 -1
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/init.py +1 -1
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/memory.py +3 -3
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/query.py +1 -1
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/observer/render.py +1 -1
- linkedparticles-1.151.18/particles/corpus/refresh_outcome.py +51 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/corpus/store.py +12 -1
- linkedparticles-1.151.18/particles/ingest/conflict_plan.py +348 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/narrative_merge.py +33 -17
- linkedparticles-1.151.18/particles/ingest/pair_selection.py +202 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/pending_collapse.py +24 -11
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/pipeline.py +599 -727
- linkedparticles-1.151.18/particles/ingest/routing.py +107 -0
- linkedparticles-1.151.18/particles/ingest/structure_edges.py +87 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/subject_resolver.py +28 -18
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/_quarantine.py +21 -6
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/abstraction.py +77 -17
- linkedparticles-1.151.18/particles/operations/candidate_pairs.py +137 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/cascade.py +30 -48
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/consolidation.py +21 -26
- linkedparticles-1.151.18/particles/operations/corpus_delete.py +278 -0
- linkedparticles-1.151.18/particles/operations/corpus_refresh.py +76 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/graph_view.py +130 -34
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/links_suggest.py +108 -84
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/contestedness.py +3 -35
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/contradictions.py +32 -75
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/observer_scope.py +2 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/as_of.py +4 -2
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/main.py +2 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/reconcile.py +2 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/reindex.py +139 -135
- linkedparticles-1.151.18/particles/operations/reindex_scope.py +124 -0
- linkedparticles-1.151.18/particles/operations/review.py +262 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/event_store.py +10 -4
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/particle_store.py +71 -44
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/subject_store.py +6 -4
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/taxonomy_store.py +12 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/utility_store.py +7 -11
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/pyproject.toml +7 -3
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/dogfood/__init__.py +3 -6
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_abstraction.py +308 -35
- linkedparticles-1.151.18/tests/test_candidate_pairs.py +224 -0
- linkedparticles-1.151.18/tests/test_conflict_plan.py +257 -0
- linkedparticles-1.151.18/tests/test_conflict_review.py +369 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_consolidation.py +3 -2
- linkedparticles-1.151.18/tests/test_corpus_delete_operation.py +385 -0
- linkedparticles-1.151.18/tests/test_decide_ladder.py +275 -0
- linkedparticles-1.151.18/tests/test_graph_layout.py +300 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_layer_boundary.py +49 -2
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_mcp_write.py +19 -0
- linkedparticles-1.151.18/tests/test_migration_040_tag_edges.py +82 -0
- linkedparticles-1.151.18/tests/test_narrative_merge.py +245 -0
- linkedparticles-1.151.18/tests/test_no_derived_columns.py +82 -0
- linkedparticles-1.151.18/tests/test_pair_selection.py +305 -0
- linkedparticles-1.151.18/tests/test_plan_collapse.py +78 -0
- linkedparticles-1.151.18/tests/test_plan_unmerge_group.py +183 -0
- linkedparticles-1.151.18/tests/test_provenance_append_only.py +339 -0
- linkedparticles-1.151.18/tests/test_refresh_outcome.py +40 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_reindex.py +57 -3
- linkedparticles-1.151.18/tests/test_reindex_scope.py +175 -0
- linkedparticles-1.151.18/tests/test_resolver_alias_attach.py +179 -0
- linkedparticles-1.151.18/tests/test_routing.py +188 -0
- linkedparticles-1.151.18/tests/test_structure_edges.py +177 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_taxonomy_store.py +15 -0
- linkedparticles-1.149.0/particles/operations/review.py +0 -372
- linkedparticles-1.149.0/tests/test_narrative_merge.py +0 -142
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/LICENSE +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/NOTICE +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/README.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/env.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/script.py.mako +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/001_initial.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/002_subjects.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/003_wikidata_label_cache.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/004_source_trust.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/005_structured_properties.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/006_extractor_records.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/007_domain_hint.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/008_content_published_at.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/009_provenance_chunk_hash.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/010_context_fingerprint.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/011_particle_relations.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/012_taxonomies.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/013_extractor_calibration.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/014_corpus_follow_edges.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/015_synthesis_cache.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/016_snapshot_extraction_started_at.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/017_operator_events.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/018_contributor_refs.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/019_embedding_model_id.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/020_trust_lenses.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/021_registered_at_string.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/022_assertion_modality.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/023_url_mentions.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/024_corpus_document_supersession.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/025_per_provider_calibration.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/026_conformance_trust_cap.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/027_lens_decay_rules.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/028_utility_lens.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/029_retired_at.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/030_utility_rank_lift.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/031_content_norm_hash.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/032_utility_event_source.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/033_structured_claim.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/034_extraction_provider_model.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/035_prefix_extraction_properties_keys.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/036_curation_snapshots.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/037_rekey_reviewer_trust_statements.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/038_snapshot_superseded_by.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic/versions/039_observer_scope_statements.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/alembic.ini +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/conformance/README.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/conformance/profile.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/conformance/similarity_vectors.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/graph/LICENSE.cytoscape.txt +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/graph/cytoscape.min.js +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/schemas/context.jsonld +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/schemas/interchange.schema.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/schemas/particle.schema.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/schemas/shacl/CorpusSnapshotShape.ttl +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/schemas/shacl/ParticleShape.ttl +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/schemas/shacl/ProvenanceChainShape.ttl +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/schemas/shacl/SubjectShape.ttl +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/schemas/shacl/TrustStatementShape.ttl +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/artifacts/schemas/trust_lens.schema.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/config.yaml.sample +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/constraints.txt +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/design/tokens.css +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/_orm_modules.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/_middleware.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/_rate_limit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/auth.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/_claude_code.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/_id_norm.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/_logging.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/_memory_projection.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/_output.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/_progress.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/_projection_git.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/_remote.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/_source_passage.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/config.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/conformance.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/curate.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/db.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/deposit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/engine.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/events.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/export.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/extract.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/hook.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/import_vault.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/inbox.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/interchange.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/links.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/lint.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/mcp.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/particle.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/project.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/quality.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/reconcile.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/reindex.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/review.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/rules.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/skills.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/structure.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/subjects.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/synthesis_cache.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/cli/trust.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/client/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/client/base.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/client/http.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/client/local.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/daemon.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/api/web_app.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/compare.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/equivalence.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/loader.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/memory/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/memory/comparators.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/memory/loader.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/memory/metrics.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/memory/rejudge.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/memory/runner.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/memory/schema.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/metrics.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/modality/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/modality/loader.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/modality/metrics.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/modality/runner.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/modality/schema.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/observer/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/observer/generator.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/observer/oracle.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/observer/runner.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/observer/schema.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/polarity/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/polarity/loader.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/polarity/metrics.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/polarity/runner.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/polarity/schema.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/relevance_floor/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/relevance_floor/harvest.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/relevance_floor/metrics.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/relevance_floor/render.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/relevance_floor/runner.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/relevance_floor/schema.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/rot/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/rot/generator.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/rot/oracle.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/rot/render.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/rot/rescore.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/rot/runner.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/rot/schema.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/rot/scoring.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/runner.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/schema.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/validity/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/validity/loader.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/validity/metrics.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/validity/runner.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/benchmark/validity/schema.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/corpus/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/corpus/blob_fsck.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/corpus/blob_health.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/corpus/deposit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/corpus/fetch.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/corpus/follow_edges.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/corpus/rule_sources.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/corpus/supersession.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/db.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/anki.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/article_synthesis/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/graph/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/graph/_assets.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/graph/exporter.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/graph/render.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/jsonl.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/logseq/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/logseq/exporter.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/logseq/format.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/logseq/narrative.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/logseq/synthesis.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/logseq/vault.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/markdown.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/notion.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/obsidian/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/obsidian/exporter.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/obsidian/format.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/obsidian/narrative.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/obsidian/synthesis.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/obsidian/vault.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/registry.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/summaries.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/exporters/wiki.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/authorities/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/authorities/_shared.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/authorities/registry.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/authorities/wikidata.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/candidate_dedup.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/duplicate_suppression.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/generation.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/importers/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/importers/github.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/importers/hackernews.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/importers/mastodon.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/importers/nomisma.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/importers/numista.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/importers/reddit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/importers/registry.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/importers/wikidata.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/observer_gate.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/ingest/update_supersession.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/integrations/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/integrations/_mapping.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/integrations/langchain.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/interchange/store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/memory_compat/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/memory_compat/graph.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/memory_compat/ops.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/memory_compat/server.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/observer.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/resources.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/server.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/corpus.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/diagnostics.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/events.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/graph.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/links_suggest.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/lint.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/particles.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/query.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/subjects.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/taxonomy.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/mcp/tools/write.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/observability/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/observability/setup.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/observability/spans.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/_llm.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/_scope.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/agent_write.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/audit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/curation/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/curation/cards.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/curation/collect.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/curation/leverage.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/curation/session.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/curation/snapshot.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/deposit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/deposit_suggest.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/digest.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/extract.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/inbox.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/assertion_quality.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/citation_signal.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/coverage.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/granularity.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/orchestrator.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/retirement.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/staleness.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/lint/wikidata_links.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/narrative.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/narrative_synthesis.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/projection/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/projection/manifest.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/projection/project.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/quality.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/contested.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/contestedness.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/decay_policy.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/effective_confidence.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/gaps.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/observer_scope.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/owner_policy.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/precedence.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/rank.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/respond.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/source_info.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/source_trust.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/stance.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/structural.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/query/utility_policy.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/retract.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/source_passage.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/structure.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/trust.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/utility_feedback.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/utility_mining.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/utility_sweep.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/operations/version_guard.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/render/article_synthesis/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/render/article_synthesis/cache.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/render/article_synthesis/layer_a.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/render/article_synthesis/layer_b.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/render/article_synthesis/orchestrate.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/render/article_synthesis/render.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/render/article_synthesis/topic.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/skills/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/skills/asking-the-store.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/skills/keeping-it-clean.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/skills/recording-a-belief.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/sql_safety.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/curation_snapshot_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/extractor_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/lens_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/observer_scope_join.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/observer_scope_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/relation_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/subject_cache.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/synthesis_cache_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/trust_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/url_mention_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/particles/store/wikidata_cache.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/__init__.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/_capped_http.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/_claude_projects.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/_client_fixtures.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/_observer_scope.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/_upstream.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/calibration/numismatic-calibration-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/calibration/prose-calibration-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/calibration/rdf-calibration-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/memory/fixtures/NOTICE +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/memory/fixtures/longmemeval_oracle_synthetic.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/modality/journal-modality-seed-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/polarity/adr-polarity-seed-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/suites/hackernews-seed-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/suites/numismatic-seed-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/suites/prose-article-seed-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/suites/rdf-seed-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/suites/reddit-seed-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/suites/wikidata-seed-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/benchmark/validity/durability-seed-001.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/MANIFEST.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/hackernews-thread-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/hackernews-thread-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/hackernews-thread-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/journal-entry-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/journal-entry-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/journal-entry-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/mastodon-thread-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/mastodon-thread-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/mastodon-thread-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/mcp-memory-export-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/mcp-memory-export-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/mcp-memory-export-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/nomisma-concept-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/nomisma-concept-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/nomisma-concept-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/numista-coin-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/numista-coin-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/numista-coin-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/numista-issuer-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/numista-issuer-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/numista-issuer-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/numista-listing-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/numista-listing-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/numista-listing-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/rdf-graph-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/rdf-graph-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/rdf-graph-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/reddit-thread-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/reddit-thread-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/reddit-thread-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/taxonomy-coins-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/taxonomy-coins-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/taxonomy-coins-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/trust-lens-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/trust-lens-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/trust-lens-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-article-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-article-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-article-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-article-002/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-article-002/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-article-002/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-essay-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-essay-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-essay-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-interview-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-interview-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/web-interview-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/wikidata-entity-001/content.bin +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/wikidata-entity-001/manifest.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conformance/fixtures/wikidata-entity-001/snapshot.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/conftest.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/dogfood/corpus.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/dogfood/llm_responses.yaml +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/dogfood/record.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/.obsidian/app.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/1933 Double Eagle.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/Coin Silver Standards.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/Flowing Hair Dollar.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/Grading and Condition.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/Home.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/Mint Records.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/Morgan Dollar.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/Most Expensive Coins.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/Philadelphia Mint.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/Seated Liberty Dollar.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/US Mint History.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/_GROUND_TRUTH.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/_templates/Coin Note Template.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/llm_wiki_vault/inventory.csv +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/memory_dir/MEMORY.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/memory_dir/deploy-pipeline.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/memory_dir/orion-api.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/scope/normative-rule-file.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/scope/normative-rule-file.recorded.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/scope/rule-file-agents-md.md +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/fixtures/scope/rule-file-agents-md.recorded.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/mcp/memory-tool-schema.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/mcp/resource-schema.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/mcp/tool-schema.json +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_account_level_failure.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_agent_write_operator.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_anki.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_api_client.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_api_middleware.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_api_rate_limit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_app.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_article_synthesis.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_as_of.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_audit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_auth.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_compare.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_memory.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_memory_comparators.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_modality.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_observer.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_polarity.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_relevance_floor.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_rot.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_runner.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_schema.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_benchmark_validity.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_blob_fsck.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_blob_health.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_calibration.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_calibration_integration.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_candidate_dedup.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cascade.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cascade_gate.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_claims.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_claude_code_hook.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_claude_code_init.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_claude_code_project.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_audit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_benchmark_memory.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_curate.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_extract.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_lint.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_logging.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_memory.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_memory_useful.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_output.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_particle_retract.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_particle_source.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_progress.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_query.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_structure.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_cli_suggested_commands.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_co_evidential_cli.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_co_evidential_merge.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_co_evidential_query_collapse.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_config.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_conflict_resolution.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_conformance.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_conformance_cli.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_conformance_profile.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_contested_badge.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_context_fingerprint.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_context_schema_sync.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_contributor_ref.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_corpus_cat.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_corpus_delete.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_corpus_fetch.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_corpus_fsck_cli.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_corpus_links_cli.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_corpus_retract.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_corpus_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_curation.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_curation_snapshot.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_daemon.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_db.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_decay.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_decay_policy.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_deposit_date.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_deposit_follow.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_deposit_project_keys.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_deposit_routing.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_deposit_suggest.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_deposit_versioned.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_docstrings.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_document_scope.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_dogfood_corpus.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_dogfood_record.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_duplicate_suppression.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_egress_chokepoint.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_embedding_model_marker.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_engine_cli.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_equivalence.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_exporter_quality_threshold.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_exporters_registry.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_extract.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_extraction_provider_model.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_extractor_ref.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_extractor_registry.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_fingerprint.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_generation_cascade.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_github_extractor.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_granularity.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_graph_exporter.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_hackernews_extractor.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_http.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_id_norm.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_inbox.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_incremental.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_integration_audit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_integration_journal_modality.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_integration_llm.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_integration_memory_benchmark.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_integration_polarity.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_integration_polarity_benchmark.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_integration_rot_benchmark.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_integration_validity_benchmark.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_integrations_langchain.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_interchange.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_journal.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_jsonl_exporter.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_jsonld_context.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_links_dedup.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_links_suggest.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_links_unmerge.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_lint.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_lint_callouts.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_lint_citation_signal.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_lint_contested.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_lint_contestedness.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_lint_granularity.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_llm.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_llm_batch.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_llm_circuit_breaker.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_llm_openai_compat.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_logseq_exporter.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_markdown.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_mastodon_extractor.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_mcp_links_suggest.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_mcp_memory.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_mcp_routing.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_mcp_server.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_memory_compat.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_memory_projection.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_memory_rescope_cli.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_migration_035_properties_keys.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_migration_037_reviewer_statement_key.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_migration_preview.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_narrative.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_narrative_cli.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_narrative_synthesis.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_nomisma.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_notion_exporter.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_numista.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_observability.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_observer_gate.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_observer_scope.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_observer_scope_surfaces.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_obsidian.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_openapi_snapshot.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_operations_scope.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_operator_events.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_operator_verb_routing.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_owner_policy.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_packaging.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_particle_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_pending_collapse.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_polarity.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_project_import.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_projection.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_projection_git.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_projection_manifest.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_property_keys.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_quality.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_query.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_query_contestedness.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_query_gaps.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_query_negative_retrieval.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_query_source_trust.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_query_stance.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_rdf.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_reconcile.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_reddit.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_relation_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_relevance.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_retired_value_quarantine.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_review.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_rule_sources.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_scope_exemption.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_skills.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_source_passage.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_sql_safety.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_stance.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_store_adjacent_paths.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_store_engine.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_structural_query.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_structured_claim.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_subject_authority.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_subject_scope.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_subjects.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_subjects_split.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_synthesis_cache_integration.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_synthesis_cache_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_synthesis_topic.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_taxonomy_extractor.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_taxonomy_schema.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_transitions.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_trust_lens.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_update_supersession.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_url_mention_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_url_safety.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_utility.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_utility_feedback.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_utility_mining.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_utility_policy.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_utility_store.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_vault_import.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_version_guard.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_web_app.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_web_clipper_import.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_wiki_exporter.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_wikidata_cache.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_wikidata_extractor.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_wikidata_importer.py +0 -0
- {linkedparticles-1.149.0 → linkedparticles-1.151.18}/tests/test_wikidata_link_confidence.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: linkedparticles
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.151.18
|
|
4
4
|
Summary: Auditable, provenance-tracked memory for AI agents — the Particles engine and its API, CLI, and MCP surfaces
|
|
5
5
|
Project-URL: Homepage, https://linkedparticles.org
|
|
6
6
|
Project-URL: Documentation, https://docs.linkedparticles.org
|
|
@@ -39,11 +39,11 @@ Requires-Dist: fastapi>=0.111
|
|
|
39
39
|
Requires-Dist: filelock>=3.13
|
|
40
40
|
Requires-Dist: greenlet>=3.5.0
|
|
41
41
|
Requires-Dist: jinja2>=3.1
|
|
42
|
-
Requires-Dist: linkedparticles-core==1.
|
|
42
|
+
Requires-Dist: linkedparticles-core==1.151.18
|
|
43
43
|
Requires-Dist: mcp<2,>=1.27.1
|
|
44
44
|
Requires-Dist: opentelemetry-api>=1.27
|
|
45
45
|
Requires-Dist: python-multipart>=0.0.9
|
|
46
|
-
Requires-Dist: sqlalchemy
|
|
46
|
+
Requires-Dist: sqlalchemy[asyncio]<2.2,>=2.0
|
|
47
47
|
Requires-Dist: typer>=0.12
|
|
48
48
|
Requires-Dist: uvicorn[standard]>=0.30
|
|
49
49
|
Requires-Dist: warcio>=1.7
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 The Particles authors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""Backfill ``particle_tag_edges`` from ``particles.tags_json``.
|
|
6
|
+
|
|
7
|
+
A particle's tags live in two places: ``particles.tags_json`` (the canonical
|
|
8
|
+
list, round-tripped to ``Particle.tags``) and ``particle_tag_edges`` (one row
|
|
9
|
+
per tag, the index every tag-filtered read joins on). Until this release
|
|
10
|
+
``insert_particle`` wrote only the JSON column; the edge rows came only from
|
|
11
|
+
``set_particle_tags`` / ``add_particle_tags``. A particle born with tags (an
|
|
12
|
+
agent assertion with ``tags``, a supersession or subject-assign successor
|
|
13
|
+
inheriting its predecessor's tags, a conversation deposit) was therefore
|
|
14
|
+
invisible to every tag-filtered query.
|
|
15
|
+
|
|
16
|
+
**The backfill.** For every particle with a non-empty ``tags_json``, insert the
|
|
17
|
+
edge rows it is missing. Rows already present are left alone, so the migration
|
|
18
|
+
is idempotent and safe on a store where some particles were retagged by hand.
|
|
19
|
+
Malformed JSON is skipped, not repaired: the column is read as-is by
|
|
20
|
+
``ParticleRow.to_model``, and this migration does not change what a particle
|
|
21
|
+
says about itself.
|
|
22
|
+
|
|
23
|
+
``downgrade()`` is a deliberate no-op. A backfilled edge cannot be told apart
|
|
24
|
+
from one ``set_particle_tags`` wrote, and each one agrees with the particle's
|
|
25
|
+
own tag list, so removing them would only reintroduce the defect.
|
|
26
|
+
|
|
27
|
+
Revision ID: 040
|
|
28
|
+
Revises: 039
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
import json
|
|
34
|
+
|
|
35
|
+
import sqlalchemy as sa
|
|
36
|
+
|
|
37
|
+
from alembic import op
|
|
38
|
+
|
|
39
|
+
revision = "040"
|
|
40
|
+
down_revision = "039"
|
|
41
|
+
branch_labels = None
|
|
42
|
+
depends_on = None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def backfill_tag_edges(bind: sa.engine.Connection) -> int:
|
|
46
|
+
"""Insert the edge rows each tagged particle is missing.
|
|
47
|
+
|
|
48
|
+
Takes the connection rather than calling ``op.get_bind()`` so the backfill
|
|
49
|
+
is exercisable outside an Alembic context, as in migration 037. See
|
|
50
|
+
``tests/test_migration_040_tag_edges.py``.
|
|
51
|
+
|
|
52
|
+
Returns the number of edge rows inserted.
|
|
53
|
+
"""
|
|
54
|
+
existing = {
|
|
55
|
+
(pid, tag)
|
|
56
|
+
for pid, tag in bind.execute(
|
|
57
|
+
sa.text("SELECT particle_id, tag FROM particle_tag_edges")
|
|
58
|
+
).fetchall()
|
|
59
|
+
}
|
|
60
|
+
rows = bind.execute(
|
|
61
|
+
sa.text("SELECT id, tags_json FROM particles WHERE tags_json IS NOT NULL")
|
|
62
|
+
).fetchall()
|
|
63
|
+
missing: list[dict[str, str]] = []
|
|
64
|
+
for pid, tags_json in rows:
|
|
65
|
+
try:
|
|
66
|
+
tags = json.loads(tags_json)
|
|
67
|
+
except (TypeError, ValueError):
|
|
68
|
+
continue
|
|
69
|
+
if not isinstance(tags, list):
|
|
70
|
+
continue
|
|
71
|
+
for tag in dict.fromkeys(t for t in tags if isinstance(t, str) and t):
|
|
72
|
+
if (pid, tag) not in existing:
|
|
73
|
+
existing.add((pid, tag))
|
|
74
|
+
missing.append({"pid": pid, "tag": tag})
|
|
75
|
+
if missing:
|
|
76
|
+
bind.execute(
|
|
77
|
+
sa.text("INSERT INTO particle_tag_edges (particle_id, tag) VALUES (:pid, :tag)"),
|
|
78
|
+
missing,
|
|
79
|
+
)
|
|
80
|
+
return len(missing)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def upgrade() -> None:
|
|
84
|
+
backfill_tag_edges(op.get_bind())
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def downgrade() -> None:
|
|
88
|
+
pass
|
|
@@ -2656,6 +2656,7 @@
|
|
|
2656
2656
|
"description": "The kind of operator action an event records.\n\nOne value per distinct *outcome*: opposite outcomes get distinct types\n(``PARTICLE_TAGGED`` vs ``PARTICLE_UNTAGGED``) so ``--type`` is a precise\nfilter; the *same* outcome reached two ways (``trust set`` /\n``trust statement-set`` both write a SourceTrustStatement) shares one type,\nwith ``actor`` recording which verb. Extensible for later verbs that meet\nthe inclusion criterion.",
|
|
2657
2657
|
"enum": [
|
|
2658
2658
|
"SOURCE_RETRACTED",
|
|
2659
|
+
"CORPUS_ENTRY_DELETED",
|
|
2659
2660
|
"CONFLICT_CANDIDATE_DROPPED",
|
|
2660
2661
|
"SUBJECTS_SPLIT",
|
|
2661
2662
|
"SUBJECTS_MERGED",
|
|
@@ -7849,7 +7850,7 @@
|
|
|
7849
7850
|
},
|
|
7850
7851
|
"/particles/{particle_id}/source": {
|
|
7851
7852
|
"get": {
|
|
7852
|
-
"description": "Return the source passage behind a particle, with how it was found.\n\n``match`` is ``EXACT`` (the hash-verified chunk the extractor saw),\n``LOCATED`` (best term-overlap paragraph
|
|
7853
|
+
"description": "Return the source passage behind a particle, with how it was found.\n\n``match`` is ``EXACT`` (the hash-verified chunk the extractor saw),\n``LOCATED`` (best term-overlap paragraph; a reading aid, not\nverification), ``WHOLE`` (the snapshot text), or ``UNAVAILABLE`` with a\n``note``. Display only: never a ranking input. 404 if the particle does\nnot exist.",
|
|
7853
7854
|
"operationId": "get_particle_source_particles__particle_id__source_get",
|
|
7854
7855
|
"parameters": [
|
|
7855
7856
|
{
|
|
@@ -1070,7 +1070,7 @@ async def get_particle_source(
|
|
|
1070
1070
|
"""Return the source passage behind a particle, with how it was found.
|
|
1071
1071
|
|
|
1072
1072
|
``match`` is ``EXACT`` (the hash-verified chunk the extractor saw),
|
|
1073
|
-
``LOCATED`` (best term-overlap paragraph
|
|
1073
|
+
``LOCATED`` (best term-overlap paragraph; a reading aid, not
|
|
1074
1074
|
verification), ``WHOLE`` (the snapshot text), or ``UNAVAILABLE`` with a
|
|
1075
1075
|
``note``. Display only: never a ranking input. 404 if the particle does
|
|
1076
1076
|
not exist."""
|
|
@@ -99,7 +99,7 @@ def audit_cmd(
|
|
|
99
99
|
),
|
|
100
100
|
),
|
|
101
101
|
output: Path | None = typer.Option(
|
|
102
|
-
None, "--output", help="
|
|
102
|
+
None, "--output", help="Write the Markdown report to FILE as well."
|
|
103
103
|
),
|
|
104
104
|
format_: str = typer.Option(
|
|
105
105
|
"markdown", "--format", help="Terminal format: markdown (default) or json."
|
|
@@ -695,13 +695,13 @@ def benchmark_observer_cmd(
|
|
|
695
695
|
"suppression); `chunked` sends two lines per chunk through carry-forward.",
|
|
696
696
|
),
|
|
697
697
|
) -> None:
|
|
698
|
-
"""The two-project observer fixture
|
|
698
|
+
"""The two-project observer fixture, with zero LLM calls.
|
|
699
699
|
|
|
700
700
|
Two repositories' memory files, sharing generic subjects, evolve over
|
|
701
701
|
`--days` and are harvested into one scratch store through the real
|
|
702
702
|
pipeline with scripted extraction and a scripted contradiction probe.
|
|
703
703
|
Each day, every line a project currently states is checked through that
|
|
704
|
-
project's observer: in view, or not
|
|
704
|
+
project's observer: in view, or not, and if not, which mechanism retired
|
|
705
705
|
it (cross-project supersession, the generation cascade, or a surviving
|
|
706
706
|
particle attested only by the other project) and whether the winner is in
|
|
707
707
|
view. Report-only; the only number the default flip is decided
|
|
@@ -765,7 +765,7 @@ def benchmark_rot_cmd( # noqa: PLR0913 — CLI option list is the API
|
|
|
765
765
|
"--arm",
|
|
766
766
|
help="Perception arm: oracle (scripted extraction + scripted §6.6 probe; "
|
|
767
767
|
"zero LLM calls, deterministic), probe (scripted extraction, live "
|
|
768
|
-
"contradiction probe), or live (the general extractor
|
|
768
|
+
"contradiction probe), or live (the general extractor, i.e. the product).",
|
|
769
769
|
),
|
|
770
770
|
seed: list[int] | None = typer.Option(
|
|
771
771
|
None,
|
|
@@ -792,7 +792,7 @@ def benchmark_rot_cmd( # noqa: PLR0913 — CLI option list is the API
|
|
|
792
792
|
False, "--yes", "-y", help="Skip the confirmation above the call threshold."
|
|
793
793
|
),
|
|
794
794
|
output: Path | None = typer.Option(
|
|
795
|
-
None, "--output", "-o", help="
|
|
795
|
+
None, "--output", "-o", help="Write the rendered report to this path as well."
|
|
796
796
|
),
|
|
797
797
|
output_format: _Format = typer.Option(
|
|
798
798
|
_Format.table, "--format", help="table (default) or json (the report of record)."
|
|
@@ -823,7 +823,7 @@ def benchmark_rot_cmd( # noqa: PLR0913 — CLI option list is the API
|
|
|
823
823
|
checkpoint, probes every attribute through the query op's selection half.
|
|
824
824
|
Reports currency (recall_current@k, current_first), supersession
|
|
825
825
|
(stale_over_current, stale_retained@k), and poison leakage across three
|
|
826
|
-
untrusted channels
|
|
826
|
+
untrusted channels, each reported separately, with no aggregate score.
|
|
827
827
|
"""
|
|
828
828
|
if ctx.invoked_subcommand is not None:
|
|
829
829
|
# ``benchmark rot rescore …`` owns the invocation.
|
|
@@ -941,7 +941,7 @@ def benchmark_rot_rescore_cmd(
|
|
|
941
941
|
) -> None:
|
|
942
942
|
"""Re-classify a saved rot report under the current scorer.
|
|
943
943
|
|
|
944
|
-
Free: retrieval is taken as recorded
|
|
944
|
+
Free: retrieval is taken as recorded, with no store, encoder, or LLM call. The
|
|
945
945
|
output is a complete report of record with ``selection.scorer_version`` set
|
|
946
946
|
to what ran and a first note naming the source and both versions.
|
|
947
947
|
"""
|
|
@@ -1028,8 +1028,8 @@ def benchmark_floor_harvest_cmd(
|
|
|
1028
1028
|
prompts: bool = typer.Option(
|
|
1029
1029
|
True,
|
|
1030
1030
|
"--prompts/--no-prompts",
|
|
1031
|
-
help="
|
|
1032
|
-
"
|
|
1031
|
+
help="Harvest question-shaped sentences the operator typed to the agent "
|
|
1032
|
+
"as well: a proxy source, reported apart. --no-prompts keeps explicit "
|
|
1033
1033
|
"memory queries only.",
|
|
1034
1034
|
),
|
|
1035
1035
|
allow_in_repo: bool = typer.Option(
|
|
@@ -1147,7 +1147,7 @@ def benchmark_floor_cmd( # noqa: PLR0913 — CLI option list is the API
|
|
|
1147
1147
|
judge: bool = typer.Option(
|
|
1148
1148
|
False,
|
|
1149
1149
|
"--judge",
|
|
1150
|
-
help="
|
|
1150
|
+
help="Run the LLM-priced stage too: answer every question with the gate "
|
|
1151
1151
|
"disabled, then judge the answer grounded-and-useful. Estimate-gated.",
|
|
1152
1152
|
),
|
|
1153
1153
|
estimate: bool = typer.Option(
|
|
@@ -1160,7 +1160,7 @@ def benchmark_floor_cmd( # noqa: PLR0913 — CLI option list is the API
|
|
|
1160
1160
|
False, "--yes", "-y", help="Skip the confirmation above the call threshold."
|
|
1161
1161
|
),
|
|
1162
1162
|
output: Path | None = typer.Option(
|
|
1163
|
-
None, "--output", "-o", help="
|
|
1163
|
+
None, "--output", "-o", help="Write the rendered report to this path as well."
|
|
1164
1164
|
),
|
|
1165
1165
|
output_format: _Format = typer.Option(
|
|
1166
1166
|
_Format.table,
|
|
@@ -355,99 +355,58 @@ def corpus_delete_cmd(
|
|
|
355
355
|
entry_id: str = typer.Argument(..., help="Entry ID (prefix OK)"),
|
|
356
356
|
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt"),
|
|
357
357
|
) -> None:
|
|
358
|
-
"""Delete a corpus entry, its snapshots, and
|
|
358
|
+
"""Delete a corpus entry, its snapshots, and the particles only it supports.
|
|
359
|
+
|
|
360
|
+
A particle that another entry also supports is kept, with this entry's
|
|
361
|
+
source refs removed. When the removed ref was its earliest source, the
|
|
362
|
+
next-earliest one becomes the age anchor. The delete is recorded as a
|
|
363
|
+
CORPUS_ENTRY_DELETED event that holds the entry id and counts, not the
|
|
364
|
+
deleted content.
|
|
365
|
+
"""
|
|
359
366
|
run(_corpus_delete(entry_id, yes))
|
|
360
367
|
|
|
361
368
|
|
|
362
369
|
async def _corpus_delete(entry_id_prefix: str, yes: bool) -> None:
|
|
363
|
-
from sqlalchemy import delete, select
|
|
364
|
-
|
|
365
370
|
from particles.api.cli._remote import ensure_local
|
|
366
|
-
from particles.corpus.store import
|
|
367
|
-
from particles.
|
|
368
|
-
from particles.store.subject_store import ParticleSubjectRow
|
|
371
|
+
from particles.corpus.store import get_entry
|
|
372
|
+
from particles.operations.corpus_delete import delete_entry, plan_entry_deletion
|
|
369
373
|
|
|
370
374
|
ensure_local("corpus delete")
|
|
371
375
|
|
|
372
376
|
async with session_scope() as session:
|
|
373
|
-
|
|
374
|
-
result = await session.execute(
|
|
375
|
-
select(CorpusEntryRow).where(
|
|
376
|
-
CorpusEntryRow.entry_id.like(
|
|
377
|
-
f"{escape_like_pattern(entry_id_prefix)}%", escape=LIKE_ESCAPE
|
|
378
|
-
)
|
|
379
|
-
)
|
|
380
|
-
)
|
|
381
|
-
row = result.scalar_one_or_none()
|
|
382
|
-
if row is None:
|
|
383
|
-
typer.echo(f"Entry {entry_id_prefix!r} not found.", err=True)
|
|
384
|
-
raise typer.Exit(1)
|
|
385
|
-
entry_id = row.entry_id
|
|
386
|
-
else:
|
|
387
|
-
entry_id = entry_id_prefix
|
|
388
|
-
|
|
377
|
+
entry_id = await _resolve_entry_id(session, entry_id_prefix)
|
|
389
378
|
entry = await get_entry(session, entry_id)
|
|
390
379
|
if entry is None:
|
|
391
380
|
typer.echo(f"Entry {entry_id_prefix!r} not found.", err=True)
|
|
392
381
|
raise typer.Exit(1)
|
|
393
382
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
)
|
|
399
|
-
)
|
|
400
|
-
particle_ids = list(particle_ids_result.scalars())
|
|
383
|
+
plan = await plan_entry_deletion(session, entry_id)
|
|
384
|
+
n_delete = len(plan.decision.to_delete)
|
|
385
|
+
n_strip = len(plan.decision.to_strip)
|
|
386
|
+
n_moved = sum(1 for s in plan.decision.to_strip if s.anchor_moved)
|
|
401
387
|
|
|
402
388
|
label = (entry.uri_r or entry_id).replace("file://", "")
|
|
403
389
|
typer.echo(f"Entry: {entry_id[:8]}… {label}")
|
|
404
|
-
typer.echo(f"Snapshots: {
|
|
405
|
-
typer.echo(f"Particles: {
|
|
390
|
+
typer.echo(f"Snapshots: {plan.snapshots}")
|
|
391
|
+
typer.echo(f"Particles: {n_delete} will be deleted (this entry is their only source)")
|
|
392
|
+
strip_line = f" {n_strip} kept, other sources remain; this entry's refs removed"
|
|
393
|
+
if n_moved:
|
|
394
|
+
strip_line += f" ({n_moved} with a new earliest source)"
|
|
395
|
+
typer.echo(strip_line)
|
|
406
396
|
|
|
407
397
|
if not yes:
|
|
408
398
|
typer.confirm("Delete this entry and all its data?", abort=True)
|
|
409
399
|
|
|
410
|
-
|
|
411
|
-
# the join rows, so afterwards we can re-check each for orphanhood.
|
|
412
|
-
candidate_subject_ids: set[str] = set()
|
|
413
|
-
if particle_ids:
|
|
414
|
-
candidate_subject_ids = set(
|
|
415
|
-
(
|
|
416
|
-
await session.execute(
|
|
417
|
-
select(ParticleSubjectRow.subject_id).where(
|
|
418
|
-
ParticleSubjectRow.particle_id.in_(particle_ids)
|
|
419
|
-
)
|
|
420
|
-
)
|
|
421
|
-
).scalars()
|
|
422
|
-
)
|
|
423
|
-
|
|
424
|
-
# Delete particles + every index row keyed on them. These tables carry
|
|
425
|
-
# no FK to ``particles`` (SQLite FK enforcement is off), so they would
|
|
426
|
-
# otherwise be left dangling.
|
|
427
|
-
if particle_ids:
|
|
428
|
-
await session.execute(delete(ParticleRow).where(ParticleRow.id.in_(particle_ids)))
|
|
429
|
-
await _purge_particle_index_rows(session, particle_ids)
|
|
430
|
-
|
|
431
|
-
# Subjects that lost their last link become orphans; drop them and any
|
|
432
|
-
# synthesis-cache rows keyed on them. A subject still linked to a
|
|
433
|
-
# surviving particle is left untouched.
|
|
434
|
-
subj_removed, synth_removed = await _purge_orphan_subjects(session, candidate_subject_ids)
|
|
435
|
-
|
|
436
|
-
# Delete provenance edges
|
|
437
|
-
await session.execute(
|
|
438
|
-
delete(ProvenanceEdgeRow).where(ProvenanceEdgeRow.corpus_entry_id == entry_id)
|
|
439
|
-
)
|
|
440
|
-
# Delete snapshots
|
|
441
|
-
await session.execute(delete(SnapshotRow).where(SnapshotRow.entry_id == entry_id))
|
|
442
|
-
# Delete entry
|
|
443
|
-
await session.execute(delete(CorpusEntryRow).where(CorpusEntryRow.entry_id == entry_id))
|
|
400
|
+
result = await delete_entry(session, entry_id)
|
|
444
401
|
await session.commit()
|
|
445
402
|
|
|
446
|
-
parts = [f"{
|
|
447
|
-
if
|
|
448
|
-
parts.append(f"{
|
|
449
|
-
if
|
|
450
|
-
parts.append(f"{
|
|
403
|
+
parts = [f"{result.particles_deleted} particles removed"]
|
|
404
|
+
if result.particles_stripped:
|
|
405
|
+
parts.append(f"{result.particles_stripped} kept with refs stripped")
|
|
406
|
+
if result.subjects_orphaned:
|
|
407
|
+
parts.append(f"{result.subjects_orphaned} orphaned subjects")
|
|
408
|
+
if result.synthesis_rows_deleted:
|
|
409
|
+
parts.append(f"{result.synthesis_rows_deleted} synthesis-cache rows")
|
|
451
410
|
typer.echo(f"Deleted entry {entry_id[:8]}… ({', '.join(parts)}).")
|
|
452
411
|
|
|
453
412
|
|
|
@@ -555,83 +514,6 @@ async def _corpus_retract(
|
|
|
555
514
|
)
|
|
556
515
|
|
|
557
516
|
|
|
558
|
-
# ---------------------------------------------------------------------------
|
|
559
|
-
# Orphan cleanup — shared by ``corpus delete`` and ``corpus prune-orphans``.
|
|
560
|
-
# None of the index tables (particle_subjects, particle_tag_edges,
|
|
561
|
-
# particle_relations, synthesis_cache) declare a foreign key, and SQLite FK
|
|
562
|
-
# enforcement is off, so deleting particles or subjects elsewhere leaves
|
|
563
|
-
# dangling rows unless they are swept explicitly here.
|
|
564
|
-
# ---------------------------------------------------------------------------
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
async def _purge_particle_index_rows(session: AsyncSession, particle_ids: list[str]) -> None:
|
|
568
|
-
"""Delete every index row keyed on one of ``particle_ids``.
|
|
569
|
-
|
|
570
|
-
Sweeps the ``particle_subjects`` join, ``particle_tag_edges``, and
|
|
571
|
-
``particle_relations`` (either endpoint). Caller deletes the
|
|
572
|
-
``ParticleRow`` rows themselves.
|
|
573
|
-
"""
|
|
574
|
-
from sqlalchemy import delete, or_
|
|
575
|
-
|
|
576
|
-
from particles.store.relation_store import ParticleRelationRow
|
|
577
|
-
from particles.store.subject_store import ParticleSubjectRow
|
|
578
|
-
from particles.store.taxonomy_store import ParticleTagEdgeRow
|
|
579
|
-
|
|
580
|
-
if not particle_ids:
|
|
581
|
-
return
|
|
582
|
-
await session.execute(
|
|
583
|
-
delete(ParticleSubjectRow).where(ParticleSubjectRow.particle_id.in_(particle_ids))
|
|
584
|
-
)
|
|
585
|
-
await session.execute(
|
|
586
|
-
delete(ParticleTagEdgeRow).where(ParticleTagEdgeRow.particle_id.in_(particle_ids))
|
|
587
|
-
)
|
|
588
|
-
await session.execute(
|
|
589
|
-
delete(ParticleRelationRow).where(
|
|
590
|
-
or_(
|
|
591
|
-
ParticleRelationRow.particle_a.in_(particle_ids),
|
|
592
|
-
ParticleRelationRow.particle_b.in_(particle_ids),
|
|
593
|
-
)
|
|
594
|
-
)
|
|
595
|
-
)
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
async def _purge_orphan_subjects(
|
|
599
|
-
session: AsyncSession, candidate_ids: set[str] | None
|
|
600
|
-
) -> tuple[int, int]:
|
|
601
|
-
"""Delete subjects with no remaining ``particle_subjects`` link.
|
|
602
|
-
|
|
603
|
-
Also drops any ``synthesis_cache`` rows keyed on the removed subjects.
|
|
604
|
-
Returns ``(subjects_removed, synthesis_rows_removed)``.
|
|
605
|
-
|
|
606
|
-
``candidate_ids`` restricts the orphan check to a known set — the subjects
|
|
607
|
-
that were linked to a just-deleted entry's particles — so a subject still
|
|
608
|
-
linked to surviving particles is never touched. Pass ``None`` to scan
|
|
609
|
-
every subject (the whole-DB ``prune-orphans`` sweep).
|
|
610
|
-
"""
|
|
611
|
-
from sqlalchemy import delete, select
|
|
612
|
-
from sqlalchemy.engine import CursorResult
|
|
613
|
-
|
|
614
|
-
from particles.store.subject_store import ParticleSubjectRow, SubjectRow
|
|
615
|
-
from particles.store.synthesis_cache_store import SynthesisCacheRow
|
|
616
|
-
|
|
617
|
-
if candidate_ids is not None and not candidate_ids:
|
|
618
|
-
return (0, 0)
|
|
619
|
-
|
|
620
|
-
linked = select(ParticleSubjectRow.subject_id).distinct()
|
|
621
|
-
stmt = select(SubjectRow.id).where(SubjectRow.id.not_in(linked))
|
|
622
|
-
if candidate_ids is not None:
|
|
623
|
-
stmt = stmt.where(SubjectRow.id.in_(candidate_ids))
|
|
624
|
-
orphan_ids = list((await session.execute(stmt)).scalars())
|
|
625
|
-
if not orphan_ids:
|
|
626
|
-
return (0, 0)
|
|
627
|
-
|
|
628
|
-
synth_result: CursorResult[None] = await session.execute( # type: ignore[assignment]
|
|
629
|
-
delete(SynthesisCacheRow).where(SynthesisCacheRow.subject_id.in_(orphan_ids))
|
|
630
|
-
)
|
|
631
|
-
await session.execute(delete(SubjectRow).where(SubjectRow.id.in_(orphan_ids)))
|
|
632
|
-
return (len(orphan_ids), synth_result.rowcount or 0)
|
|
633
|
-
|
|
634
|
-
|
|
635
517
|
@corpus_app.command("prune-orphans")
|
|
636
518
|
def corpus_prune_orphans_cmd(
|
|
637
519
|
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt"),
|
|
@@ -652,6 +534,7 @@ async def _corpus_prune_orphans(yes: bool) -> None:
|
|
|
652
534
|
from sqlalchemy.engine import CursorResult
|
|
653
535
|
|
|
654
536
|
from particles.api.cli._remote import ensure_local
|
|
537
|
+
from particles.operations.corpus_delete import purge_orphan_subjects
|
|
655
538
|
from particles.store.particle_store import ParticleRow
|
|
656
539
|
from particles.store.relation_store import ParticleRelationRow
|
|
657
540
|
from particles.store.subject_store import ParticleSubjectRow, SubjectRow
|
|
@@ -711,7 +594,7 @@ async def _corpus_prune_orphans(yes: bool) -> None:
|
|
|
711
594
|
await session.execute(delete(ParticleRelationRow).where(dangling_rel_q))
|
|
712
595
|
# Orphan-subject removal must run *after* the dangling join rows are
|
|
713
596
|
# gone, so a subject linked only via a now-deleted row is detected.
|
|
714
|
-
subj_removed, synth_from_subj = await
|
|
597
|
+
subj_removed, synth_from_subj = await purge_orphan_subjects(session, None)
|
|
715
598
|
synth_res: CursorResult[None] = await session.execute( # type: ignore[assignment]
|
|
716
599
|
delete(SynthesisCacheRow).where(dangling_synth_q)
|
|
717
600
|
)
|
|
@@ -820,13 +703,9 @@ async def _corpus_refresh(
|
|
|
820
703
|
entry_id: str | None, force: bool, backfill_cascade: bool, yes: bool
|
|
821
704
|
) -> None:
|
|
822
705
|
from particles.api.cli._remote import ensure_local
|
|
823
|
-
from particles.
|
|
824
|
-
from particles.corpus.
|
|
825
|
-
from particles.
|
|
826
|
-
list_refreshable_local_entries,
|
|
827
|
-
list_snapshots_for_entry,
|
|
828
|
-
resolve_entry_id,
|
|
829
|
-
)
|
|
706
|
+
from particles.corpus.refresh_outcome import RefreshOutcome
|
|
707
|
+
from particles.corpus.store import list_refreshable_local_entries, resolve_entry_id
|
|
708
|
+
from particles.operations.corpus_refresh import refresh_entries
|
|
830
709
|
|
|
831
710
|
if backfill_cascade:
|
|
832
711
|
await _corpus_refresh_backfill(yes)
|
|
@@ -853,24 +732,23 @@ async def _corpus_refresh(
|
|
|
853
732
|
return
|
|
854
733
|
|
|
855
734
|
changed = unchanged = missing = 0
|
|
856
|
-
for
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
await session.commit()
|
|
735
|
+
async for result in refresh_entries(
|
|
736
|
+
session, (target_id for target_id, _uri in targets), force=force
|
|
737
|
+
):
|
|
738
|
+
short = result.entry_id[:8]
|
|
739
|
+
match result.outcome:
|
|
740
|
+
case None:
|
|
741
|
+
typer.echo(f" {short} error: {result.error}", err=True)
|
|
742
|
+
case RefreshOutcome.MISSING:
|
|
743
|
+
missing += 1
|
|
744
|
+
typer.echo(f" {short} missing (source unavailable)")
|
|
745
|
+
case RefreshOutcome.UNCHANGED_MTIME | RefreshOutcome.UNCHANGED_HASH:
|
|
746
|
+
unchanged += 1
|
|
747
|
+
case RefreshOutcome.CHANGED:
|
|
748
|
+
changed += 1
|
|
749
|
+
typer.echo(
|
|
750
|
+
f" {short} changed → snapshot {(result.snapshot_id or '')[:8]} PENDING"
|
|
751
|
+
)
|
|
874
752
|
|
|
875
753
|
typer.echo(
|
|
876
754
|
f"\nChecked {len(targets)} local source(s): {changed} changed, "
|
|
@@ -886,7 +764,7 @@ def corpus_fsck_cmd(
|
|
|
886
764
|
[],
|
|
887
765
|
"--search",
|
|
888
766
|
help=(
|
|
889
|
-
"
|
|
767
|
+
"Look for strays under this blob root too, the directory holding the "
|
|
890
768
|
"two-character shards (repeatable). Nothing is inferred: the audit tells "
|
|
891
769
|
"you what is missing so you can point --search at where you think it went."
|
|
892
770
|
),
|
|
@@ -1229,7 +1229,7 @@ def extractor_benchmark_validity_cmd(
|
|
|
1229
1229
|
Reports the dangerous **wrong-expiry rate**: of the aligned claims whose
|
|
1230
1230
|
gold is durable (no boundary), the fraction the extractor wrongly assigned a
|
|
1231
1231
|
``valid_until`` and thereby set up for silent retirement by the §9.3
|
|
1232
|
-
staleness lint (the headline, the over-eager-expiry risk).
|
|
1232
|
+
staleness lint (the headline, the over-eager-expiry risk). It also reports existence
|
|
1233
1233
|
precision/recall of correct date-bounded extraction and date accuracy.
|
|
1234
1234
|
Discovers every validity suite under --suites-dir the extractor is the
|
|
1235
1235
|
production routing choice for (or runs only --suite). Report-only
|
|
@@ -115,7 +115,7 @@ def init_claude_code_cmd(
|
|
|
115
115
|
True,
|
|
116
116
|
"--skills/--no-skills",
|
|
117
117
|
help=(
|
|
118
|
-
"
|
|
118
|
+
"Install the shipped agent-onboarding skill files too, "
|
|
119
119
|
"into the harness's skills directory (a Particles-owned subdirectory; "
|
|
120
120
|
"--remove deletes exactly that). Default on: an agent that has the "
|
|
121
121
|
"tools but not the guidance is the gap these close."
|
|
@@ -229,7 +229,7 @@ def rescope_cmd(
|
|
|
229
229
|
A belief is *in view* for a project when one of its sources was harvested
|
|
230
230
|
there, which is read from the `project:` tag on the source's corpus entry.
|
|
231
231
|
Older versions stamped a per-worktree name, or nothing at all. This verb
|
|
232
|
-
adds the project's real key beside whatever an entry already carries
|
|
232
|
+
adds the project's real key beside whatever an entry already carries. It
|
|
233
233
|
never removes a tag, and running it twice changes nothing.
|
|
234
234
|
|
|
235
235
|
It reports the two things you need to see: harvested entries it could not
|
|
@@ -350,7 +350,7 @@ def widen_cmd(
|
|
|
350
350
|
judgement, so it is yours to record. The belief and its sources are not
|
|
351
351
|
touched: the widening is a standing statement the read lens consults, and
|
|
352
352
|
`--revoke` withdraws it. There is deliberately no agent-facing way to do
|
|
353
|
-
this
|
|
353
|
+
this: an agent that could widen its own belief could put it in front of
|
|
354
354
|
every future session.
|
|
355
355
|
"""
|
|
356
356
|
configure_output(verbose, debug, quiet, progress)
|
|
@@ -692,7 +692,7 @@ def consolidate_cmd(
|
|
|
692
692
|
),
|
|
693
693
|
),
|
|
694
694
|
output: Path | None = typer.Option(
|
|
695
|
-
None, "--output", help="
|
|
695
|
+
None, "--output", help="Write the run report as Markdown to FILE as well."
|
|
696
696
|
),
|
|
697
697
|
format_: str = typer.Option(
|
|
698
698
|
"markdown", "--format", help="Terminal format: markdown (default) or json."
|
|
@@ -68,7 +68,7 @@ def query_cmd(
|
|
|
68
68
|
include_ancestors: bool = typer.Option(
|
|
69
69
|
False,
|
|
70
70
|
"--include-ancestors",
|
|
71
|
-
help="
|
|
71
|
+
help="Match particles tagged with a broader ancestor of each --tag as well "
|
|
72
72
|
"(up-expansion over taxonomy parent links)",
|
|
73
73
|
),
|
|
74
74
|
show_particles: bool = typer.Option(
|
|
@@ -33,7 +33,7 @@ def _metrics_rows(m: ObserverMetrics) -> list[str]:
|
|
|
33
33
|
]
|
|
34
34
|
for kind in ("fact", "rule", "own"):
|
|
35
35
|
if kind in m.by_kind:
|
|
36
|
-
rows.append(f"| In view
|
|
36
|
+
rows.append(f"| In view, `{kind}` lines | {_rate(m.by_kind[kind])} |")
|
|
37
37
|
return rows
|
|
38
38
|
|
|
39
39
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 The Particles authors
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""Classify one :func:`~particles.corpus.fetch.maybe_refetch` result.
|
|
6
|
+
|
|
7
|
+
The decide half of a refresh, as a pure function over plain values (
|
|
8
|
+
D2). ``particles corpus refresh`` and consolidation pass 0.5 both derive their
|
|
9
|
+
counts from :func:`classify_refresh`. The outcomes are fine-grained, so a report
|
|
10
|
+
that wants one ``unchanged`` total sums the two unchanged outcomes.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from enum import StrEnum
|
|
16
|
+
|
|
17
|
+
from particles.core.schema import Snapshot, WarcRecordType
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class RefreshOutcome(StrEnum):
|
|
21
|
+
"""What one re-check of a corpus entry found."""
|
|
22
|
+
|
|
23
|
+
MISSING = "missing"
|
|
24
|
+
"""No snapshot came back: the source is unavailable, or the entry is not refetchable."""
|
|
25
|
+
UNCHANGED_MTIME = "unchanged_mtime"
|
|
26
|
+
"""The latest snapshot came back untouched: a tier-1 short-circuit, before any read."""
|
|
27
|
+
UNCHANGED_HASH = "unchanged_hash"
|
|
28
|
+
"""A REVISIT was written: the body was read and its hash matched."""
|
|
29
|
+
CHANGED = "changed"
|
|
30
|
+
"""A new RESPONSE snapshot landed PENDING."""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def classify_refresh(before_id: str | None, snap: Snapshot | None) -> RefreshOutcome:
|
|
34
|
+
"""Classify a refetch result against the entry's latest snapshot id before it.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
before_id: The entry's newest snapshot id before the refetch, or None
|
|
38
|
+
when it had none.
|
|
39
|
+
snap: What ``maybe_refetch`` returned.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
The outcome. A returned snapshot whose id equals ``before_id`` is
|
|
43
|
+
``UNCHANGED_MTIME`` whatever its record type, since no new row was written.
|
|
44
|
+
"""
|
|
45
|
+
if snap is None:
|
|
46
|
+
return RefreshOutcome.MISSING
|
|
47
|
+
if snap.snapshot_id == before_id:
|
|
48
|
+
return RefreshOutcome.UNCHANGED_MTIME
|
|
49
|
+
if snap.warc_record_type is WarcRecordType.REVISIT:
|
|
50
|
+
return RefreshOutcome.UNCHANGED_HASH
|
|
51
|
+
return RefreshOutcome.CHANGED
|