linkedparticles-core 1.192.28__tar.gz → 1.210.2__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_core-1.192.28 → linkedparticles_core-1.210.2}/PKG-INFO +1 -1
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/schemas/interchange.schema.json +1 -1
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/schemas/particle.schema.json +1 -1
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/schemas/shacl/CorpusSnapshotShape.ttl +2 -2
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/constraints.txt +9 -8
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/config.py +256 -84
- linkedparticles_core-1.210.2/particles/conformance/jsonschema.py +363 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/conformance/shacl.py +43 -3
- linkedparticles_core-1.210.2/particles/core/artifact_fold.py +242 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/conflict_review.py +56 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/duplicate_key.py +49 -6
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/held_release.py +59 -5
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/ladders.py +41 -2
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/observer_scope.py +45 -18
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/probe_verdict.py +11 -1
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/reanchor.py +5 -1
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/schema.py +109 -34
- linkedparticles_core-1.210.2/particles/core/schema_version.py +137 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/scoring/utility.py +245 -1
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/egress.py +9 -5
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/general.py +158 -11
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/journal.py +10 -3
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/registry.py +0 -7
- linkedparticles_core-1.210.2/particles/extraction/session_artifacts.py +142 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/subject_gate.py +9 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/interchange/codec.py +179 -7
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/__init__.py +18 -1
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/adapters/anthropic.py +139 -17
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/adapters/openai_compat.py +24 -3
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/errors.py +87 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/pool.py +17 -9
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/registry.py +28 -5
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/replay.py +24 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/usage.py +196 -2
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/render/markdown.py +11 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/pyproject.toml +1 -1
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_calibration_isotonic.py +1 -1
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_conformance_validator.py +0 -4
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_core_held_release.py +76 -1
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_core_observer_scope.py +46 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_egress_policy.py +23 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_interchange_schema.py +13 -0
- linkedparticles_core-1.210.2/tests/test_llm_errors.py +123 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_llm_pool.py +36 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_llm_usage.py +201 -1
- linkedparticles_core-1.210.2/tests/test_schema_openness.py +115 -0
- linkedparticles_core-1.192.28/particles/conformance/jsonschema.py +0 -72
- linkedparticles_core-1.192.28/particles/extraction/agent.py +0 -499
- linkedparticles_core-1.192.28/tests/test_extraction_agent.py +0 -287
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/LICENSE +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/NOTICE +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/README.md +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/conformance/README.md +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/conformance/profile.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/conformance/similarity_vectors.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/schemas/context.jsonld +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/schemas/shacl/ParticleShape.ttl +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/schemas/shacl/ProvenanceChainShape.ttl +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/schemas/shacl/SubjectShape.ttl +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/schemas/shacl/TrustStatementShape.ttl +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/artifacts/schemas/trust_lens.schema.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/conformance/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/conformance/_resources.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/conformance/contract.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/conformance/fixtures.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/conformance/profile.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/conformance/runner.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/conformance/types.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/conformance/validator.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/_resources.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/cascade_gate.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/claims.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/closure_measure.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/conflict_resolution.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/consolidation_cadence.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/contradiction_disclosure.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/equivalence.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/fingerprint.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/generics.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/granularity.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/jsonld_context.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/modality.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/past_value.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/predicate_profile.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/progress.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/provenance.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/rung_ladder.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/scoring/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/scoring/confidence.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/scoring/decay.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/scoring/relevance.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/spend_budget.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/stance.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/status.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/validity.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/vocabulary.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/vocabulary_jsonld.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/core/vocabulary_report.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/embeddings.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/append_delta.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/calibration.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/components.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/docstrings.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/github/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/github/_shared.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/github/gist.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/github/pages.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/github/repo.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/hackernews.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/incremental.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/mastodon.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/mcp_memory.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/migration_preview.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/modality.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/nomisma.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/numista/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/numista/_shared.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/numista/coin.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/numista/issuer.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/numista/listing.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/polarity.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/property_keys.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/rdf.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/reddit.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/scope.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/session_state.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/structure.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/subject_scope.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/taxonomy.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/tool_turns.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/trust_lens.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/vocabulary.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/extraction/wikidata.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/http.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/interchange/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/interchange/jsonl.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/interchange/yaml_ld.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/adapters/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/adapters/local.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/batch_budget.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/breaker.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/client.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/fencing.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/logprobs.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/llm/spend_budget.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/py.typed +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/render/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/secrets.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/url_canonical.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/particles/url_safety.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/__init__.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/_client_fixtures.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/_upstream.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/MANIFEST.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/hackernews-thread-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/hackernews-thread-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/hackernews-thread-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/journal-entry-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/journal-entry-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/journal-entry-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/mastodon-thread-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/mastodon-thread-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/mastodon-thread-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/mcp-memory-export-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/mcp-memory-export-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/mcp-memory-export-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/nomisma-concept-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/nomisma-concept-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/nomisma-concept-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/numista-coin-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/numista-coin-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/numista-coin-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/numista-issuer-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/numista-issuer-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/numista-issuer-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/numista-listing-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/numista-listing-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/numista-listing-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/rdf-graph-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/rdf-graph-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/rdf-graph-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/reddit-thread-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/reddit-thread-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/reddit-thread-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/taxonomy-coins-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/taxonomy-coins-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/taxonomy-coins-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/trust-lens-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/trust-lens-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/trust-lens-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-article-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-article-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-article-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-article-002/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-article-002/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-article-002/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-essay-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-essay-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-essay-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-interview-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-interview-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/web-interview-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/wikidata-entity-001/content.bin +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/wikidata-entity-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conformance/fixtures/wikidata-entity-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/conftest.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/fixtures/scope/normative-rule-file.md +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/fixtures/scope/normative-rule-file.recorded.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/fixtures/scope/rule-file-agents-md.md +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/fixtures/scope/rule-file-agents-md.recorded.json +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_confidence.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_config_client_sections.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_config_sample.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_conformance_fixture_gen.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_conformance_similarity_vectors.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_core_contradiction_disclosure.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_core_provenance.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_core_vocabulary.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_embeddings.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_extraction_vision.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_llm_batch_budget.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_llm_logprobs.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_llm_replay.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_schema.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_secrets.py +0 -0
- {linkedparticles_core-1.192.28 → linkedparticles_core-1.210.2}/tests/test_url_canonical.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: linkedparticles-core
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.210.2
|
|
4
4
|
Summary: Store-free client library for Particles: define, validate, serialize, and extract provenance-tracked belief particles
|
|
5
5
|
Project-URL: Homepage, https://linkedparticles.org
|
|
6
6
|
Project-URL: Documentation, https://docs.linkedparticles.org
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"schemaVersion": {
|
|
41
41
|
"type": "string",
|
|
42
|
-
"description": "Core particle schema version
|
|
42
|
+
"description": "Core particle schema version the unit's record satisfies: the lower of the record's and the encoder's, compared on MAJOR.MINOR. A validator holding an older minor of the same major removes the keys it does not declare before validating, and reports them (technical specification 10.1)."
|
|
43
43
|
},
|
|
44
44
|
"sourceParticleId": {
|
|
45
45
|
"type": "string",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"schema_version": {
|
|
78
78
|
"type": "string",
|
|
79
79
|
"pattern": "^\\d+\\.\\d+\\.\\d+$",
|
|
80
|
-
"description": "Particles schema version under which this particle was created"
|
|
80
|
+
"description": "Particles schema version under which this particle was created: MAJOR.MINOR.PATCH, compatible with another when the majors match (technical specification 6.1)"
|
|
81
81
|
},
|
|
82
82
|
"particle_type": {
|
|
83
83
|
"type": "string",
|
|
@@ -33,8 +33,8 @@ particles:CorpusSnapshotShape
|
|
|
33
33
|
sh:path particles:warcRecordType ;
|
|
34
34
|
sh:minCount 1 ; sh:maxCount 1 ;
|
|
35
35
|
sh:datatype xsd:string ;
|
|
36
|
-
sh:in ( "RESPONSE" "REVISIT" ) ;
|
|
37
|
-
sh:message "warc_record_type must be RESPONSE or
|
|
36
|
+
sh:in ( "RESPONSE" "REVISIT" "ABSENT" ) ;
|
|
37
|
+
sh:message "warc_record_type must be RESPONSE, REVISIT or ABSENT." ;
|
|
38
38
|
] ;
|
|
39
39
|
|
|
40
40
|
sh:property [
|
|
@@ -10,7 +10,7 @@ annotated-doc==0.0.5
|
|
|
10
10
|
# typer
|
|
11
11
|
annotated-types==0.8.0
|
|
12
12
|
# via pydantic
|
|
13
|
-
anthropic==1.
|
|
13
|
+
anthropic==1.17.0
|
|
14
14
|
# via linkedparticles
|
|
15
15
|
anyio==4.14.2 ; python_full_version < '3.15'
|
|
16
16
|
# via
|
|
@@ -67,9 +67,9 @@ distro==1.9.0
|
|
|
67
67
|
# via langsmith
|
|
68
68
|
docstring-parser==0.18.0
|
|
69
69
|
# via anthropic
|
|
70
|
-
fastapi==0.
|
|
70
|
+
fastapi==0.156.3
|
|
71
71
|
# via linkedparticles
|
|
72
|
-
filelock==4.
|
|
72
|
+
filelock==4.2.4
|
|
73
73
|
# via
|
|
74
74
|
# huggingface-hub
|
|
75
75
|
# linkedparticles
|
|
@@ -148,11 +148,11 @@ jsonschema==4.26.0
|
|
|
148
148
|
# mcp
|
|
149
149
|
jsonschema-specifications==2025.9.1
|
|
150
150
|
# via jsonschema
|
|
151
|
-
langchain-core==1.6.
|
|
151
|
+
langchain-core==1.6.12
|
|
152
152
|
# via linkedparticles
|
|
153
153
|
langchain-protocol==0.0.19
|
|
154
154
|
# via langchain-core
|
|
155
|
-
langsmith==0.14.
|
|
155
|
+
langsmith==0.14.12
|
|
156
156
|
# via langchain-core
|
|
157
157
|
lxml==6.1.3
|
|
158
158
|
# via pyld
|
|
@@ -185,6 +185,7 @@ numpy==2.4.6
|
|
|
185
185
|
# transformers
|
|
186
186
|
opentelemetry-api==1.45.1
|
|
187
187
|
# via
|
|
188
|
+
# anthropic
|
|
188
189
|
# fastapi
|
|
189
190
|
# linkedparticles
|
|
190
191
|
# opentelemetry-exporter-http-transport
|
|
@@ -287,7 +288,7 @@ pyld==3.3.0
|
|
|
287
288
|
# via linkedparticles
|
|
288
289
|
pyparsing==3.3.3
|
|
289
290
|
# via rdflib
|
|
290
|
-
pypdf==6.
|
|
291
|
+
pypdf==6.21.2
|
|
291
292
|
# via linkedparticles
|
|
292
293
|
pypdfium2==5.14.0
|
|
293
294
|
# via linkedparticles
|
|
@@ -346,7 +347,7 @@ scipy==1.17.1
|
|
|
346
347
|
# sentence-transformers
|
|
347
348
|
sentence-transformers==5.7.0
|
|
348
349
|
# via linkedparticles
|
|
349
|
-
setuptools==84.
|
|
350
|
+
setuptools==84.1.0
|
|
350
351
|
# via torch
|
|
351
352
|
shellingham==1.5.4
|
|
352
353
|
# via typer
|
|
@@ -356,7 +357,7 @@ sniffio==1.3.1
|
|
|
356
357
|
# via
|
|
357
358
|
# anthropic
|
|
358
359
|
# langsmith
|
|
359
|
-
sqlalchemy==2.1.
|
|
360
|
+
sqlalchemy==2.1.5
|
|
360
361
|
# via
|
|
361
362
|
# alembic
|
|
362
363
|
# linkedparticles
|
|
@@ -584,11 +584,19 @@ _LIST_PRICES_PER_MTOK: dict[str, tuple[float, float]] = {
|
|
|
584
584
|
# 2026-10 provider survey's 18 calls against claude-sonnet-5's 111,950 on the same
|
|
585
585
|
# calls (0.534). The extraction figure is the memory benchmark's 6,700 scaled the
|
|
586
586
|
# same way. The claude-sonnet-4-6 entries come from paired run
|
|
587
|
-
# (docs/benchmarks/default-model-adr0317-2026-10-13.md).
|
|
588
|
-
|
|
587
|
+
# (docs/benchmarks/default-model-adr0317-2026-10-13.md). The claude-haiku-5-5
|
|
588
|
+
# entries come from gate (2026-10-22): on 40 byte-identical
|
|
589
|
+
# extraction prompts it billed the same input tokens as claude-sonnet-5-5
|
|
590
|
+
# (124k each), so the same tokenizer factor, and wrote 1.63 times its output
|
|
591
|
+
# (196k against 120k), so 0.534 × 1.63.
|
|
592
|
+
_SHIPPED_CHARS_PER_TOKEN: dict[str, float] = {
|
|
593
|
+
"claude-sonnet-5-5": 2.98,
|
|
594
|
+
"claude-haiku-5-5": 2.98,
|
|
595
|
+
}
|
|
589
596
|
_SHIPPED_OUTPUT_SCALE: dict[str, float] = {
|
|
590
597
|
"claude-sonnet-5-5": 0.534,
|
|
591
598
|
"claude-sonnet-4-6": 0.800,
|
|
599
|
+
"claude-haiku-5-5": 0.87,
|
|
592
600
|
}
|
|
593
601
|
_SHIPPED_EXTRACTION_OUTPUT_TOKENS: dict[str, int] = {
|
|
594
602
|
"claude-sonnet-5-5": 3_578,
|
|
@@ -918,6 +926,47 @@ class RetiredValueQuarantineConfig(BaseModel):
|
|
|
918
926
|
enabled: bool = True
|
|
919
927
|
|
|
920
928
|
|
|
929
|
+
class RestatementConfig(BaseModel):
|
|
930
|
+
"""The restatement match of a re-extracted ``MUTABLE`` source.
|
|
931
|
+
|
|
932
|
+
Before the generation cascade retires an earlier claim, each new candidate
|
|
933
|
+
is paired with the nearest earlier-generation claim of the same entry, and
|
|
934
|
+
the duplicate ladder asks whether the two are one claim: the §6.10 key
|
|
935
|
+
first, then the judge. A ``SAME`` keeps the earlier claim and
|
|
936
|
+
records the new snapshot on it instead of minting a copy. A pair the judge
|
|
937
|
+
reads ``DIFFERENT`` whose two update readings say ``CHANGES`` is retired by
|
|
938
|
+
update, with the new claim's ``supersedes`` naming it.
|
|
939
|
+
"""
|
|
940
|
+
|
|
941
|
+
#: The whole match; ``false`` restores the behaviour before the match existed.
|
|
942
|
+
enabled: bool = True
|
|
943
|
+
#: Content cosine (the normalised scale) below which a pair is not
|
|
944
|
+
#: asked. Starts at the ``paraphrase_floor``; the replay fixture
|
|
945
|
+
#: tunes it.
|
|
946
|
+
floor: float = Field(default=0.70, ge=0.0, le=1.0)
|
|
947
|
+
#: Pairs per pass that reach the model judge, highest cosine first. The
|
|
948
|
+
#: rest keep the old behaviour and are disclosed as unasked.
|
|
949
|
+
max_judged: int = Field(default=64, ge=0)
|
|
950
|
+
#: Pairs per judge call.
|
|
951
|
+
judge_batch: int = Field(default=25, ge=1)
|
|
952
|
+
#: Whether a model-judged ``SAME`` carries the earlier claim. ``false``
|
|
953
|
+
#: holds the judge in its admission period: verdicts are recorded and the
|
|
954
|
+
#: would-be carries counted, and the pass writes as if it had said
|
|
955
|
+
#: ``DIFFERENT``. The owner sets it once the judge meets bar.
|
|
956
|
+
#: The §6.10 key rung carries regardless.
|
|
957
|
+
judge_admitted: bool = False
|
|
958
|
+
#: The ``DIFFERENT``-pair lineage write (an update retirement naming the
|
|
959
|
+
#: new claim). The update readings are asked either way: a ``SAME`` needs
|
|
960
|
+
#: them as its guard.
|
|
961
|
+
lineage: bool = True
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
class GenerationConfig(BaseModel):
|
|
965
|
+
"""How a new generation of a ``MUTABLE`` source replaces the old."""
|
|
966
|
+
|
|
967
|
+
restatement: RestatementConfig = Field(default_factory=RestatementConfig)
|
|
968
|
+
|
|
969
|
+
|
|
921
970
|
class ExtractionConfig(BaseModel):
|
|
922
971
|
# Total output allowance per extraction call. The reply itself runs to 2 to
|
|
923
972
|
# 3.5 tokens per source character (measured 2026-09-25 on claude-sonnet-5),
|
|
@@ -946,6 +995,18 @@ class ExtractionConfig(BaseModel):
|
|
|
946
995
|
# of 3.5 answer tokens a character plus thinking, and is the output limit
|
|
947
996
|
# of claude-haiku-4-5, the smallest of the Claude models routed here.
|
|
948
997
|
retry_max_tokens: int = Field(default=64000, ge=0)
|
|
998
|
+
# An extraction call answered with HTTP 429 (rate limited) is sent again
|
|
999
|
+
# after a wait, up to this many times, before it counts as a failed call
|
|
1000
|
+
# and leaves its snapshot PENDING. A 429 says nothing about the
|
|
1001
|
+
# source, and a run that sends several calls at once
|
|
1002
|
+
# (``audit.extraction_concurrency``) meets one sooner. The wait is the
|
|
1003
|
+
# reply's ``retry-after`` when it carries one, else
|
|
1004
|
+
# ``rate_limit_backoff_seconds`` doubled per attempt, and never more than
|
|
1005
|
+
# ``rate_limit_max_wait_seconds``. The provider SDK's own short retries run
|
|
1006
|
+
# first, inside each attempt. 0 restores the old single attempt.
|
|
1007
|
+
rate_limit_retries: int = Field(default=4, ge=0)
|
|
1008
|
+
rate_limit_backoff_seconds: float = Field(default=10.0, ge=0.0)
|
|
1009
|
+
rate_limit_max_wait_seconds: float = Field(default=120.0, ge=0.0)
|
|
949
1010
|
similarity_threshold: float = 0.80
|
|
950
1011
|
pdf_page_overlap_lines: int = 5
|
|
951
1012
|
# PDF hardening (security): a malicious PDF can carry an enormous page
|
|
@@ -983,6 +1044,14 @@ class ExtractionConfig(BaseModel):
|
|
|
983
1044
|
# max_llm_calls_per_source=8) but short enough that operator
|
|
984
1045
|
# recovery is quick.
|
|
985
1046
|
stale_in_progress_minutes: float = 30.0
|
|
1047
|
+
# a source whose every extraction call the model refused is
|
|
1048
|
+
# recorded, and ``extract --all-pending``, the consolidation catch-up and
|
|
1049
|
+
# the audit skip it until the extraction model or the content changes, or
|
|
1050
|
+
# this many days pass since the last refusal (a provider's classifier can
|
|
1051
|
+
# change behind an unchanged model id). Naming the entry, or
|
|
1052
|
+
# ``--retry-refused``, sends it at once. 0 turns the hold off. A chosen
|
|
1053
|
+
# figure: it cuts a held note to one call a month against one a night.
|
|
1054
|
+
refusal_retry_days: float = Field(default=30.0, ge=0.0)
|
|
986
1055
|
# Cost-estimate assumption, not a runtime knob: the general extractor's
|
|
987
1056
|
# fixed system prompt (rules + modality / polarity / stance / structure /
|
|
988
1057
|
# validity addenda, ~8k chars) is re-sent on every call, so an estimate
|
|
@@ -1018,12 +1087,6 @@ class ExtractionConfig(BaseModel):
|
|
|
1018
1087
|
# The largest delta chunk sent in one call. Each chunk after the first
|
|
1019
1088
|
# takes the end of the chunk before it as its context.
|
|
1020
1089
|
append_chunk_chars: int = Field(default=7500, ge=1000)
|
|
1021
|
-
# the agent extractor's prompt (the Stop hook's ask and its API
|
|
1022
|
-
# proxy) tells the model how many claims text of its size usually yields,
|
|
1023
|
-
# as a thoroughness guide, never a quota. 1.9 is the median claims per
|
|
1024
|
-
# 1000 characters of the general extractor's transcript deltas in the
|
|
1025
|
-
# maintainers' store (262 reads, measured 2026-10-16).
|
|
1026
|
-
agent_expected_claims_per_kchar: float = Field(default=1.9, gt=0.0)
|
|
1027
1090
|
# a pair the §6.6 contradiction probe confirms is read a second
|
|
1028
1091
|
# time, before the write loop, with each claim's source kind, name, time
|
|
1029
1092
|
# and passage (on ``llm.verification``). A pair the reading does not
|
|
@@ -1047,8 +1110,20 @@ class ExtractionConfig(BaseModel):
|
|
|
1047
1110
|
# Source types whose extracted claims are screened for an agent session's
|
|
1048
1111
|
# momentary working state (current worktree, cwd, branch), which is true
|
|
1049
1112
|
# for minutes and never a durable belief. CONVERSATION only: a coding-agent
|
|
1050
|
-
# transcript is where that narration appears.
|
|
1113
|
+
# transcript is where that narration appears. The same types get the
|
|
1114
|
+
# session-artifact rewrite: a described pull request is named
|
|
1115
|
+
# by its URL and a bare description is never a Subject. Empty disables both.
|
|
1051
1116
|
session_state_source_types: list[str] = Field(default_factory=lambda: ["CONVERSATION"])
|
|
1117
|
+
# `extract --all-pending` asks before it spends when its
|
|
1118
|
+
# estimate exceeds this many calls (the audit's threshold, for the same
|
|
1119
|
+
# question). A run without a terminal stops there unless given --yes or
|
|
1120
|
+
# --budget-usd. 0 asks before any call.
|
|
1121
|
+
confirm_call_threshold: int = Field(default=50, ge=0)
|
|
1122
|
+
# the model the estimate prices beside the configured one,
|
|
1123
|
+
# as "provider:model", offered through `extract --extraction-model`. It
|
|
1124
|
+
# passed extraction and subject-resolution bars against
|
|
1125
|
+
# claude-sonnet-5-5 on 2026-10-22. None prints the configured model only.
|
|
1126
|
+
alternative_model: str | None = "anthropic:claude-haiku-5-5"
|
|
1052
1127
|
|
|
1053
1128
|
|
|
1054
1129
|
class ExtractionScopeConfig(BaseModel):
|
|
@@ -1370,6 +1445,30 @@ class ImportProjectConfig(BaseModel):
|
|
|
1370
1445
|
)
|
|
1371
1446
|
|
|
1372
1447
|
|
|
1448
|
+
class ImportVaultConfig(BaseModel):
|
|
1449
|
+
"""The guards on the absences ``import vault`` records (§7).
|
|
1450
|
+
|
|
1451
|
+
A completed vault walk that no longer finds a previously imported note
|
|
1452
|
+
records an absence, which retires the note's claims at the next
|
|
1453
|
+
extraction. An unmounted volume, a sync client that has not finished, or a
|
|
1454
|
+
root typed one level too deep look exactly like deleting every note, so two
|
|
1455
|
+
rules decide whether a walk may record what it found; when either refuses,
|
|
1456
|
+
the walk records none and exits 1, and ``--confirm-absent`` records them.
|
|
1457
|
+
|
|
1458
|
+
Both numbers are a judgement, not a measurement: no imported vault had been
|
|
1459
|
+
observed when they were chosen. Every import that records absences logs the
|
|
1460
|
+
count and the fraction, so they can be tuned from evidence.
|
|
1461
|
+
"""
|
|
1462
|
+
|
|
1463
|
+
confirm_absent: Literal["first", "always"] = "first"
|
|
1464
|
+
"""``first`` asks for ``--confirm-absent`` before the first absence ever
|
|
1465
|
+
recorded under a root; ``always`` asks whenever a walk finds absences."""
|
|
1466
|
+
max_absent_fraction: float = Field(default=0.25, ge=0.0, le=1.0)
|
|
1467
|
+
"""After that, refuse to record absence for more than this fraction of the
|
|
1468
|
+
notes previously imported under the walked root (and for at least five
|
|
1469
|
+
notes, a fixed floor) unless ``--confirm-absent`` is passed."""
|
|
1470
|
+
|
|
1471
|
+
|
|
1373
1472
|
class MigrationConfig(BaseModel):
|
|
1374
1473
|
"""Inbound migration from another memory store.
|
|
1375
1474
|
|
|
@@ -1706,6 +1805,47 @@ class UtilityMiningConfig(BaseModel):
|
|
|
1706
1805
|
estimate_chars_per_token: float = Field(default=2.1, gt=0.0)
|
|
1707
1806
|
|
|
1708
1807
|
|
|
1808
|
+
class UtilityMonitorConfig(BaseModel):
|
|
1809
|
+
"""The nightly rank-lift monitor: is the configured ``λ`` still doing its job?
|
|
1810
|
+
|
|
1811
|
+
A read-only consolidation pass checks, in every view a session renders, that
|
|
1812
|
+
the head holds the beliefs the agent keeps applying *outside* it, and that it
|
|
1813
|
+
keeps room for beliefs that have not earned use yet. It reports; it never
|
|
1814
|
+
changes ``λ``.
|
|
1815
|
+
|
|
1816
|
+
The **cohort** is the view's ACTIVE beliefs applied in at least
|
|
1817
|
+
``min_sessions`` distinct sessions within the utility half-life whose
|
|
1818
|
+
recorded session-start context did not include the belief. Credit
|
|
1819
|
+
earned through the head only says the head kept what it showed, so it does
|
|
1820
|
+
not count. The head passes the floor when it holds at least ``capture`` of
|
|
1821
|
+
the cohort, and the ceiling when at least ``entry_share`` of its slots hold
|
|
1822
|
+
beliefs with no use yet (the exposure loop: a belief earns use only
|
|
1823
|
+
by being shown). A view whose cohort is smaller than ``min_cohort`` reports
|
|
1824
|
+
``cold`` and gets no verdict.
|
|
1825
|
+
|
|
1826
|
+
The defaults were chosen on one store (findings 5 and 6), where
|
|
1827
|
+
every variant tried gave the same verdict; they are thresholds on a report,
|
|
1828
|
+
never on a rank.
|
|
1829
|
+
|
|
1830
|
+
``head_sizes`` empty means the sizes the install declares: the projection
|
|
1831
|
+
manifest's default ``top_k`` (60), ``agent_memory.projection.max_lines`` and
|
|
1832
|
+
``mcp.recall.digest_max_beliefs``. List them when a manifest uses others.
|
|
1833
|
+
``max_views`` caps the views one run evaluates (store-wide plus project
|
|
1834
|
+
keys, largest first); the rest rotate into later runs. ``targets`` are belief
|
|
1835
|
+
ids whose rank is reported and whose entering or leaving a head is disclosed,
|
|
1836
|
+
never judged.
|
|
1837
|
+
"""
|
|
1838
|
+
|
|
1839
|
+
enabled: bool = True
|
|
1840
|
+
min_sessions: int = Field(default=2, ge=1)
|
|
1841
|
+
capture: float = Field(default=0.75, gt=0.0, le=1.0)
|
|
1842
|
+
min_cohort: int = Field(default=3, ge=1)
|
|
1843
|
+
entry_share: float = Field(default=0.25, ge=0.0, lt=1.0)
|
|
1844
|
+
max_views: int = Field(default=4, ge=1)
|
|
1845
|
+
head_sizes: list[int] = Field(default_factory=list)
|
|
1846
|
+
targets: list[str] = Field(default_factory=list)
|
|
1847
|
+
|
|
1848
|
+
|
|
1709
1849
|
class UtilityConfig(BaseModel):
|
|
1710
1850
|
"""Usefulness (outcome-learning) lens config (composition).
|
|
1711
1851
|
|
|
@@ -1735,6 +1875,7 @@ class UtilityConfig(BaseModel):
|
|
|
1735
1875
|
default: UtilityRuleConfig = Field(default_factory=UtilityRuleConfig)
|
|
1736
1876
|
mining: UtilityMiningConfig = Field(default_factory=UtilityMiningConfig)
|
|
1737
1877
|
explicit_weight: float = Field(default=25.0, ge=0)
|
|
1878
|
+
monitor: UtilityMonitorConfig = Field(default_factory=UtilityMonitorConfig)
|
|
1738
1879
|
|
|
1739
1880
|
|
|
1740
1881
|
class OwnerLensConfig(BaseModel):
|
|
@@ -1756,7 +1897,8 @@ class OwnerLensConfig(BaseModel):
|
|
|
1756
1897
|
seam, valid up to multi-tenant line.
|
|
1757
1898
|
|
|
1758
1899
|
A **list**, not a scalar, because a viewer's Subject fragments in practice
|
|
1759
|
-
("Jeff" / "Jeff Gage") until
|
|
1900
|
+
("Jeff" / "Jeff Gage") until an operator folds the fragments together with
|
|
1901
|
+
``particles subjects merge``. Entries are
|
|
1760
1902
|
canonical names or Subject ids and resolve **locally only** — never a live
|
|
1761
1903
|
authority lookup, since the digest is a zero-LLM, zero-network surface.
|
|
1762
1904
|
Resolve-or-inert: if nothing resolves the
|
|
@@ -2598,6 +2740,26 @@ class AutoMergeConfig(BaseModel):
|
|
|
2598
2740
|
max_per_run: int = 500
|
|
2599
2741
|
|
|
2600
2742
|
|
|
2743
|
+
class RereadMergeConfig(BaseModel):
|
|
2744
|
+
"""The judged merge of one append-only entry's re-read duplicates.
|
|
2745
|
+
|
|
2746
|
+
``links dedup --reread``: a census, a paid ``--judge`` step that writes
|
|
2747
|
+
probe-ledger verdicts only, and an ``--apply`` that merges from the ledger.
|
|
2748
|
+
``--apply`` also needs ``auto_merge.enabled``.
|
|
2749
|
+
"""
|
|
2750
|
+
|
|
2751
|
+
# which cosine strata the judge is admitted on. `none` until
|
|
2752
|
+
# the owner's labels give a 95 % Wilson lower bound of at least 0.95 on the
|
|
2753
|
+
# judge's SAME verdicts in a stratum; `high` admits pairs at 0.97 and
|
|
2754
|
+
# above, `all` admits every pair.
|
|
2755
|
+
admitted: Literal["none", "high", "all"] = "none"
|
|
2756
|
+
# questions one `--judge` run may put to the duplicate judge.
|
|
2757
|
+
# A capped run says how many remain; re-run to continue.
|
|
2758
|
+
max_judged: int = Field(default=2000, ge=0)
|
|
2759
|
+
# Pairs per duplicate-judge call.
|
|
2760
|
+
judge_batch: int = Field(default=25, ge=1)
|
|
2761
|
+
|
|
2762
|
+
|
|
2601
2763
|
class LinksSuggestConfig(BaseModel):
|
|
2602
2764
|
# cosine-similarity threshold for proposing CO_EVIDENTIAL link
|
|
2603
2765
|
# candidates between same-Subject particles via `particles links suggest`.
|
|
@@ -2618,6 +2780,9 @@ class LinksSuggestConfig(BaseModel):
|
|
|
2618
2780
|
apply_confirm_threshold: int = 10
|
|
2619
2781
|
# exact-duplicate auto-merge. Default OFF.
|
|
2620
2782
|
auto_merge: AutoMergeConfig = Field(default_factory=AutoMergeConfig)
|
|
2783
|
+
# the judged merge of re-read duplicates. Admitted on no stratum
|
|
2784
|
+
# by default.
|
|
2785
|
+
reread: RereadMergeConfig = Field(default_factory=RereadMergeConfig)
|
|
2621
2786
|
|
|
2622
2787
|
|
|
2623
2788
|
class VocabularyConfig(BaseModel):
|
|
@@ -2873,66 +3038,6 @@ class ClaudeCodeHarvestConfig(BaseModel):
|
|
|
2873
3038
|
catchup_limit: int = Field(default=5, ge=0)
|
|
2874
3039
|
|
|
2875
3040
|
|
|
2876
|
-
class AgentExtractionConfig(BaseModel):
|
|
2877
|
-
"""Agent-side extraction at a Stop hook.
|
|
2878
|
-
|
|
2879
|
-
The in-session agent extracts a span of its own deposited transcript, so a
|
|
2880
|
-
Claude Code user needs no API key for extraction. The ask defaults below
|
|
2881
|
-
come from the 2026-10-09 offline replay and store query
|
|
2882
|
-
(``docs/benchmarks/agent-extraction-defaults-2026-10-09.md``); the
|
|
2883
|
-
agent-dependent ones are confirmed by a shadow week before ``on`` becomes
|
|
2884
|
-
the keyless default.
|
|
2885
|
-
"""
|
|
2886
|
-
|
|
2887
|
-
# off: nothing asks. shadow: ask and verify, write and mark nothing, log
|
|
2888
|
-
# what would have happened. on: ask, verify, and write.
|
|
2889
|
-
mode: Literal["off", "shadow", "on"] = "off"
|
|
2890
|
-
# Ask only when the distilled transcript has grown this much past what was
|
|
2891
|
-
# extracted. Replay: 8000 gives about 1.7 asks per active hour.
|
|
2892
|
-
min_new_chars: int = Field(default=8000, ge=1)
|
|
2893
|
-
# Seconds between asks in one session.
|
|
2894
|
-
min_interval_seconds: int = Field(default=600, ge=0)
|
|
2895
|
-
# Waive the interval while more than one span is owed (catch-up asks), and
|
|
2896
|
-
# only after an answer that moved the ask's start.
|
|
2897
|
-
# Replay: recovers a quarter to two fifths of the backlog.
|
|
2898
|
-
catch_up: bool = True
|
|
2899
|
-
# Cap on asks per session, applied only where a background extractor can
|
|
2900
|
-
# take the rest. A keyless install is never capped: a cap there leaves
|
|
2901
|
-
# everything after the last ask unextracted (replay: 35 to 51 % uncovered).
|
|
2902
|
-
max_asks_per_session: int | None = Field(default=6, ge=1)
|
|
2903
|
-
# Largest span one ask carries, in bytes of distilled text. The span's text
|
|
2904
|
-
# rides in the ask, so this bounds the context one ask costs.
|
|
2905
|
-
max_span_chars: int = Field(default=40_000, ge=1000)
|
|
2906
|
-
# An ask unanswered after this many seconds is expired.
|
|
2907
|
-
ask_ttl_seconds: int = Field(default=900, ge=60)
|
|
2908
|
-
# A submission covers its span only with at least this many accepted claims
|
|
2909
|
-
# per 1000 characters. 1.27 is the 10th percentile of the general
|
|
2910
|
-
# extractor's own transcript deltas in the maintainers' store (262 delta
|
|
2911
|
-
# reads, measured 2026-10-16; it was 2.7 on 2026-10-09, before the
|
|
2912
|
-
# session-state and tool-turn filters thinned transcript extraction).
|
|
2913
|
-
min_claims_per_kchar: float = Field(default=1.27, ge=0.0)
|
|
2914
|
-
# ...and with no more than this share of candidates dropped for evidence
|
|
2915
|
-
# not found in the span. Placeholder until the shadow week measures it.
|
|
2916
|
-
max_evidence_drop_ratio: float = Field(default=0.5, ge=0.0, le=1.0)
|
|
2917
|
-
# In shadow mode, keep each submission's accepted candidates (claim text,
|
|
2918
|
-
# stated confidence, evidence) in a local JSONL file, so a later labelling
|
|
2919
|
-
# pass can fit a calibration map on real session claims. The
|
|
2920
|
-
# operator event log keeps counts only. Off writes nothing.
|
|
2921
|
-
keep_shadow_candidates: bool = True
|
|
2922
|
-
# None ⇒ ``<claude_code.state_dir>/agent-extraction-shadow.jsonl``.
|
|
2923
|
-
shadow_candidates_path: str | None = None
|
|
2924
|
-
|
|
2925
|
-
@field_validator("mode", mode="before")
|
|
2926
|
-
@classmethod
|
|
2927
|
-
def _yaml_booleans(cls, value: object) -> object:
|
|
2928
|
-
"""Read YAML's unquoted ``on`` / ``off``, which parse as booleans, as the modes."""
|
|
2929
|
-
if value is True:
|
|
2930
|
-
return "on"
|
|
2931
|
-
if value is False:
|
|
2932
|
-
return "off"
|
|
2933
|
-
return value
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
3041
|
class ClaudeCodeConfig(BaseModel):
|
|
2937
3042
|
"""Claude Code hook integration.
|
|
2938
3043
|
|
|
@@ -2960,13 +3065,13 @@ class ClaudeCodeConfig(BaseModel):
|
|
|
2960
3065
|
# timeout. On expiry the hook logs and exits 0 with no output — a memory
|
|
2961
3066
|
# outage must cost an empty digest, never a hung session start.
|
|
2962
3067
|
hook_deadline_seconds: float = Field(default=10.0, gt=0.0)
|
|
2963
|
-
# What a session's digest and MEMORY.md region see. ``
|
|
2964
|
-
# the
|
|
2965
|
-
#
|
|
2966
|
-
# Engages only once ``particles memory
|
|
2967
|
-
|
|
3068
|
+
# What a session's digest and MEMORY.md region see. ``project``
|
|
3069
|
+
# (the default since) reads through the session's project
|
|
3070
|
+
# observer: global beliefs plus those observed in this project. ``store``
|
|
3071
|
+
# is the whole store, as before. Engages only once ``particles memory
|
|
3072
|
+
# rescope`` has run on the store.
|
|
3073
|
+
observer_scope: Literal["store", "project"] = "project"
|
|
2968
3074
|
harvest: ClaudeCodeHarvestConfig = Field(default_factory=ClaudeCodeHarvestConfig)
|
|
2969
|
-
agent_extraction: AgentExtractionConfig = Field(default_factory=AgentExtractionConfig)
|
|
2970
3075
|
|
|
2971
3076
|
|
|
2972
3077
|
class AgentMemoryProjectionGitConfig(BaseModel):
|
|
@@ -3009,6 +3114,12 @@ class AgentMemoryProjectionConfig(BaseModel):
|
|
|
3009
3114
|
here are **init-time defaults** baked into the ``memory.yaml`` that
|
|
3010
3115
|
``particles init claude-code`` writes; editing the manifest afterwards is
|
|
3011
3116
|
the supported tuning path.
|
|
3117
|
+
|
|
3118
|
+
``exclude_source_tags`` is the exception, deliberately: it is
|
|
3119
|
+
read at **render time**, so it reaches existing installs without a manifest
|
|
3120
|
+
edit. The convention it sets: a knob limiting what any install's region may
|
|
3121
|
+
contain lives here, in config; a knob shaping one install's sections lives
|
|
3122
|
+
in the manifest.
|
|
3012
3123
|
"""
|
|
3013
3124
|
|
|
3014
3125
|
# Master switch: render + splice the memory-index region during the
|
|
@@ -3024,12 +3135,28 @@ class AgentMemoryProjectionConfig(BaseModel):
|
|
|
3024
3135
|
# generated memory.yaml, not read at render time (the manifest wins).
|
|
3025
3136
|
max_lines: int = Field(default=120, ge=1)
|
|
3026
3137
|
min_confidence: float = Field(default=0.30, ge=0.0, le=1.0)
|
|
3027
|
-
# Fold-and-archive (default-on):
|
|
3028
|
-
#
|
|
3029
|
-
#
|
|
3030
|
-
#
|
|
3031
|
-
#
|
|
3138
|
+
# Fold-and-archive (as amended, default-on): a
|
|
3139
|
+
# memory-index pointer outside the projected region is *moved*, never
|
|
3140
|
+
# destroyed, to the project's `MEMORY.archive.md` while the region just
|
|
3141
|
+
# rendered shows a belief its file's current, extracted snapshot states,
|
|
3142
|
+
# and is brought back once it does not. Other lines are never moved.
|
|
3143
|
+
# False turns both halves off; the projected region is still rendered.
|
|
3032
3144
|
fold_authored_lines: bool = True
|
|
3145
|
+
# Memory types whose pointers never fold (option d): a pointer
|
|
3146
|
+
# whose target file's frontmatter `metadata.type` is in this list stays in
|
|
3147
|
+
# MEMORY.md whatever the region shows, and one already archived comes
|
|
3148
|
+
# back. The region ranks by confidence, which does not keep a standing
|
|
3149
|
+
# rule in view. A target with no type follows the rule above. Compared
|
|
3150
|
+
# case-insensitively; [] restores the plain fold rule above.
|
|
3151
|
+
never_fold_types: list[str] = Field(default_factory=lambda: ["feedback", "user"])
|
|
3152
|
+
# Source tags the region never selects from: a belief whose
|
|
3153
|
+
# current sources all carry one of these is dropped before the cut (one no
|
|
3154
|
+
# source states any more is judged by the sources that ever did; one with
|
|
3155
|
+
# no source at all is kept). The default keeps the rule files
|
|
3156
|
+
# (AGENTS.md / CLAUDE.md, tagged `rule-file`) out: operating documentation
|
|
3157
|
+
# the harness serves from the files themselves. Read at render time, not
|
|
3158
|
+
# baked into memory.yaml. [] restores the unfiltered region.
|
|
3159
|
+
exclude_source_tags: list[str] = Field(default_factory=lambda: ["rule-file"])
|
|
3033
3160
|
# Optional git-versioned history of the projected view (opt-in).
|
|
3034
3161
|
git: AgentMemoryProjectionGitConfig = Field(default_factory=AgentMemoryProjectionGitConfig)
|
|
3035
3162
|
|
|
@@ -3203,6 +3330,16 @@ class AuditConfig(BaseModel):
|
|
|
3203
3330
|
# 0 probes nothing (disclosed the same way). `particles lint` is not
|
|
3204
3331
|
# affected: cost gating is the audit's concern, lint stays exhaustive.
|
|
3205
3332
|
max_contradiction_probes: int = Field(default=50, ge=0)
|
|
3333
|
+
# How many harvested snapshots' extraction calls run at once.
|
|
3334
|
+
# The calls are independent, and at one at a time they were the whole of
|
|
3335
|
+
# the 2026-09-25 first run's 66 minutes (96 memory files, ~39 s a call).
|
|
3336
|
+
# Only the model calls overlap: each snapshot's reconcile-and-write pass
|
|
3337
|
+
# still runs alone, in harvest order, after the passes before it, so the
|
|
3338
|
+
# store has one writer and a result does not depend on the setting. An
|
|
3339
|
+
# account's rate limit bounds the gain (a 429 backs off and retries, see
|
|
3340
|
+
# ``extraction.rate_limit_retries``). 1 is the serial loop; an in-memory
|
|
3341
|
+
# store always runs serially.
|
|
3342
|
+
extraction_concurrency: int = Field(default=4, ge=1)
|
|
3206
3343
|
# (the ruling, order, do not drop): under a probe
|
|
3207
3344
|
# cap the census probes the pairs some single reader sees first (the
|
|
3208
3345
|
# observer precondition reconciles or reviews them) and
|
|
@@ -3306,8 +3443,10 @@ class AuditConfig(BaseModel):
|
|
|
3306
3443
|
# output. Raise this if a run's usage line shows probes averaging more.
|
|
3307
3444
|
estimate_probe_input_tokens: int = Field(default=350, ge=0)
|
|
3308
3445
|
estimate_probe_output_tokens: int = Field(default=250, ge=0)
|
|
3309
|
-
# Wall time, for the time the estimate prints.
|
|
3310
|
-
#
|
|
3446
|
+
# Wall time, for the time the estimate prints. It is timed as if the calls
|
|
3447
|
+
# ran one at a time, as they did when these rates were measured, so it is an
|
|
3448
|
+
# upper bound under extraction_concurrency above. An
|
|
3449
|
+
# extraction call's time is mostly the output it writes, so extraction
|
|
3311
3450
|
# is timed by output tokens rather than per call or per file. 125 tokens a
|
|
3312
3451
|
# second plus 1.5 s per probe (short haiku replies) reproduces the
|
|
3313
3452
|
# 2026-09-25 run's 96 minutes and the 22 minutes one 49k-character ADR took
|
|
@@ -4198,6 +4337,7 @@ class ParticlesConfig(BaseModel):
|
|
|
4198
4337
|
agent_memory: AgentMemoryConfig = Field(default_factory=AgentMemoryConfig)
|
|
4199
4338
|
llm: LLMConfig = Field(default_factory=LLMConfig)
|
|
4200
4339
|
extraction: ExtractionConfig = Field(default_factory=ExtractionConfig)
|
|
4340
|
+
generation: GenerationConfig = Field(default_factory=GenerationConfig)
|
|
4201
4341
|
extraction_scope: ExtractionScopeConfig = Field(default_factory=ExtractionScopeConfig)
|
|
4202
4342
|
extraction_modality: ExtractionModalityConfig = Field(default_factory=ExtractionModalityConfig)
|
|
4203
4343
|
modality_regeneration: ModalityRegenerationConfig = Field(
|
|
@@ -4216,6 +4356,7 @@ class ParticlesConfig(BaseModel):
|
|
|
4216
4356
|
document_precedence: DocumentPrecedenceConfig = Field(default_factory=DocumentPrecedenceConfig)
|
|
4217
4357
|
journal_extractor: JournalExtractorConfig = Field(default_factory=JournalExtractorConfig)
|
|
4218
4358
|
import_project: ImportProjectConfig = Field(default_factory=ImportProjectConfig)
|
|
4359
|
+
import_vault: ImportVaultConfig = Field(default_factory=ImportVaultConfig)
|
|
4219
4360
|
web_clipper: WebClipperConfig = Field(default_factory=WebClipperConfig)
|
|
4220
4361
|
migration: MigrationConfig = Field(default_factory=MigrationConfig)
|
|
4221
4362
|
trust: TrustConfig = Field(default_factory=TrustConfig)
|
|
@@ -4597,7 +4738,7 @@ def validate_config() -> tuple[Path | None, ParticlesConfig]:
|
|
|
4597
4738
|
def _migrate_legacy_keys(raw: dict[str, Any]) -> None:
|
|
4598
4739
|
"""Migrate deprecated config keys in-place, logging a one-time warning.
|
|
4599
4740
|
|
|
4600
|
-
|
|
4741
|
+
Six migrations are active:
|
|
4601
4742
|
|
|
4602
4743
|
* ``lint.co_evidential_candidate_threshold`` was renamed to
|
|
4603
4744
|
``links_suggest.candidate_threshold``.
|
|
@@ -4619,6 +4760,11 @@ def _migrate_legacy_keys(raw: dict[str, Any]) -> None:
|
|
|
4619
4760
|
``audit.estimate_output_tokens_per_source_char``); see
|
|
4620
4761
|
:func:`_migrate_audit_output_keys`.
|
|
4621
4762
|
|
|
4763
|
+
* ``claude_code.agent_extraction`` and
|
|
4764
|
+
``extraction.agent_expected_claims_per_kchar`` configured agent-side
|
|
4765
|
+
extraction, which was removed (deprecated); they are dropped
|
|
4766
|
+
with a warning by :func:`_drop_retired_agent_extraction_keys`.
|
|
4767
|
+
|
|
4622
4768
|
Each old key is honoured only when its new home is unset, so an operator
|
|
4623
4769
|
who has already moved to the new key wins. The shims may be removed once
|
|
4624
4770
|
their deprecation cycle ends.
|
|
@@ -4628,6 +4774,32 @@ def _migrate_legacy_keys(raw: dict[str, Any]) -> None:
|
|
|
4628
4774
|
_migrate_query_answer_max_tokens(raw)
|
|
4629
4775
|
_migrate_shared_estimate_keys(raw)
|
|
4630
4776
|
_migrate_audit_output_keys(raw)
|
|
4777
|
+
_drop_retired_agent_extraction_keys(raw)
|
|
4778
|
+
|
|
4779
|
+
|
|
4780
|
+
def _drop_retired_agent_extraction_keys(raw: dict[str, Any]) -> None:
|
|
4781
|
+
"""Drop the keys of agent-side extraction, removed with deprecation.
|
|
4782
|
+
|
|
4783
|
+
``claude_code.agent_extraction`` and ``extraction.agent_expected_claims_per_kchar``
|
|
4784
|
+
configured a feature that no longer exists. They would be ignored anyway,
|
|
4785
|
+
so this only says so once, letting an operator delete them on purpose.
|
|
4786
|
+
"""
|
|
4787
|
+
dropped: list[str] = []
|
|
4788
|
+
claude_code = raw.get("claude_code")
|
|
4789
|
+
if isinstance(claude_code, dict) and claude_code.pop("agent_extraction", None) is not None:
|
|
4790
|
+
dropped.append("claude_code.agent_extraction")
|
|
4791
|
+
extraction = raw.get("extraction")
|
|
4792
|
+
if (
|
|
4793
|
+
isinstance(extraction, dict)
|
|
4794
|
+
and extraction.pop("agent_expected_claims_per_kchar", None) is not None
|
|
4795
|
+
):
|
|
4796
|
+
dropped.append("extraction.agent_expected_claims_per_kchar")
|
|
4797
|
+
if dropped:
|
|
4798
|
+
log.warning(
|
|
4799
|
+
"config: %s configured agent-side extraction, which was removed; "
|
|
4800
|
+
"the setting has no effect and can be deleted.",
|
|
4801
|
+
" and ".join(f"'{k}'" for k in dropped),
|
|
4802
|
+
)
|
|
4631
4803
|
|
|
4632
4804
|
|
|
4633
4805
|
def _migrate_co_evidential_threshold(raw: dict[str, Any]) -> None:
|