linkedparticles-core 1.192.2__tar.gz → 1.192.28__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.2 → linkedparticles_core-1.192.28}/PKG-INFO +8 -8
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/constraints.txt +9 -9
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/config.py +147 -3
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/closure_measure.py +59 -2
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/conflict_review.py +36 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/contradiction_disclosure.py +2 -3
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/held_release.py +3 -3
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/observer_scope.py +44 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/status.py +5 -2
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/embeddings.py +26 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/agent.py +51 -9
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/general.py +17 -2
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/mcp_memory.py +2 -2
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/reddit.py +164 -37
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/subject_scope.py +2 -2
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/usage.py +3 -2
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/render/markdown.py +2 -2
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/pyproject.toml +47 -16
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_core_observer_scope.py +53 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_embeddings.py +30 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_extraction_agent.py +41 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_llm_usage.py +11 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/LICENSE +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/NOTICE +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/README.md +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/conformance/README.md +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/conformance/profile.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/conformance/similarity_vectors.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/schemas/context.jsonld +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/schemas/interchange.schema.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/schemas/particle.schema.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/schemas/shacl/CorpusSnapshotShape.ttl +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/schemas/shacl/ParticleShape.ttl +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/schemas/shacl/ProvenanceChainShape.ttl +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/schemas/shacl/SubjectShape.ttl +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/schemas/shacl/TrustStatementShape.ttl +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/artifacts/schemas/trust_lens.schema.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/conformance/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/conformance/_resources.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/conformance/contract.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/conformance/fixtures.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/conformance/jsonschema.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/conformance/profile.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/conformance/runner.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/conformance/shacl.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/conformance/types.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/conformance/validator.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/_resources.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/cascade_gate.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/claims.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/conflict_resolution.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/consolidation_cadence.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/duplicate_key.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/equivalence.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/fingerprint.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/generics.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/granularity.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/jsonld_context.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/ladders.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/modality.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/past_value.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/predicate_profile.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/probe_verdict.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/progress.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/provenance.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/reanchor.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/rung_ladder.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/schema.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/scoring/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/scoring/confidence.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/scoring/decay.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/scoring/relevance.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/scoring/utility.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/spend_budget.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/stance.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/validity.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/vocabulary.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/vocabulary_jsonld.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/vocabulary_report.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/egress.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/append_delta.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/calibration.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/components.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/docstrings.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/github/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/github/_shared.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/github/gist.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/github/pages.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/github/repo.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/hackernews.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/incremental.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/journal.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/mastodon.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/migration_preview.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/modality.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/nomisma.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/numista/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/numista/_shared.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/numista/coin.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/numista/issuer.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/numista/listing.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/polarity.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/property_keys.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/rdf.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/registry.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/scope.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/session_state.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/structure.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/subject_gate.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/taxonomy.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/tool_turns.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/trust_lens.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/vocabulary.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/extraction/wikidata.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/http.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/interchange/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/interchange/codec.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/interchange/jsonl.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/interchange/yaml_ld.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/adapters/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/adapters/anthropic.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/adapters/local.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/adapters/openai_compat.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/batch_budget.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/breaker.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/client.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/errors.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/fencing.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/logprobs.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/pool.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/registry.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/replay.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/llm/spend_budget.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/py.typed +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/render/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/secrets.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/url_canonical.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/url_safety.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/__init__.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/_client_fixtures.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/_upstream.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/MANIFEST.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/hackernews-thread-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/hackernews-thread-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/hackernews-thread-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/journal-entry-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/journal-entry-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/journal-entry-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/mastodon-thread-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/mastodon-thread-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/mastodon-thread-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/mcp-memory-export-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/mcp-memory-export-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/mcp-memory-export-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/nomisma-concept-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/nomisma-concept-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/nomisma-concept-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/numista-coin-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/numista-coin-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/numista-coin-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/numista-issuer-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/numista-issuer-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/numista-issuer-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/numista-listing-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/numista-listing-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/numista-listing-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/rdf-graph-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/rdf-graph-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/rdf-graph-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/reddit-thread-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/reddit-thread-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/reddit-thread-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/taxonomy-coins-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/taxonomy-coins-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/taxonomy-coins-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/trust-lens-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/trust-lens-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/trust-lens-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-article-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-article-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-article-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-article-002/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-article-002/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-article-002/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-essay-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-essay-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-essay-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-interview-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-interview-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/web-interview-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/wikidata-entity-001/content.bin +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/wikidata-entity-001/manifest.yaml +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conformance/fixtures/wikidata-entity-001/snapshot.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/conftest.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/fixtures/scope/normative-rule-file.md +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/fixtures/scope/normative-rule-file.recorded.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/fixtures/scope/rule-file-agents-md.md +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/fixtures/scope/rule-file-agents-md.recorded.json +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_calibration_isotonic.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_confidence.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_config_client_sections.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_config_sample.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_conformance_fixture_gen.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_conformance_similarity_vectors.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_conformance_validator.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_core_contradiction_disclosure.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_core_held_release.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_core_provenance.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_core_vocabulary.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_egress_policy.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_extraction_vision.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_interchange_schema.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_llm_batch_budget.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_llm_logprobs.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_llm_pool.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_llm_replay.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_schema.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/tests/test_secrets.py +0 -0
- {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/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.192.
|
|
3
|
+
Version: 1.192.28
|
|
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
|
|
@@ -29,7 +29,7 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
29
29
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
30
30
|
Classifier: Typing :: Typed
|
|
31
31
|
Requires-Python: >=3.11
|
|
32
|
-
Requires-Dist: anthropic>=0
|
|
32
|
+
Requires-Dist: anthropic>=1.0
|
|
33
33
|
Requires-Dist: html2text>=2024.2
|
|
34
34
|
Requires-Dist: httpx>=0.27
|
|
35
35
|
Requires-Dist: jsonschema>=4.22
|
|
@@ -37,17 +37,17 @@ Requires-Dist: lxml-stubs>=0.5.1
|
|
|
37
37
|
Requires-Dist: numpy>=1.26
|
|
38
38
|
Requires-Dist: opentelemetry-api>=1.27
|
|
39
39
|
Requires-Dist: pydantic>=2.7
|
|
40
|
-
Requires-Dist: pyld<4,>=
|
|
41
|
-
Requires-Dist: pypdf>=6.
|
|
42
|
-
Requires-Dist: pyshacl<0.
|
|
40
|
+
Requires-Dist: pyld<4,>=3.0
|
|
41
|
+
Requires-Dist: pypdf>=6.19.0
|
|
42
|
+
Requires-Dist: pyshacl<0.41,>=0.40
|
|
43
43
|
Requires-Dist: pyyaml>=6.0
|
|
44
44
|
Requires-Dist: rdflib<8,>=7.0
|
|
45
45
|
Requires-Dist: scipy>=1.13
|
|
46
|
-
Requires-Dist: sentence-transformers>=
|
|
47
|
-
Requires-Dist: sqlalchemy[asyncio]<2.2,>=2.
|
|
46
|
+
Requires-Dist: sentence-transformers>=5.6.0
|
|
47
|
+
Requires-Dist: sqlalchemy[asyncio]<2.2,>=2.1
|
|
48
48
|
Requires-Dist: torch
|
|
49
49
|
Provides-Extra: vision
|
|
50
|
-
Requires-Dist: pypdfium2>=
|
|
50
|
+
Requires-Dist: pypdfium2>=5.0; extra == 'vision'
|
|
51
51
|
Description-Content-Type: text/markdown
|
|
52
52
|
|
|
53
53
|
# linkedparticles-core
|
|
@@ -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.13.0
|
|
14
14
|
# via linkedparticles
|
|
15
15
|
anyio==4.14.2 ; python_full_version < '3.15'
|
|
16
16
|
# via
|
|
@@ -42,7 +42,7 @@ attrs==26.1.0
|
|
|
42
42
|
# referencing
|
|
43
43
|
cachetools==7.2.0
|
|
44
44
|
# via pyld
|
|
45
|
-
certifi==2026.
|
|
45
|
+
certifi==2026.10.19
|
|
46
46
|
# via
|
|
47
47
|
# httpcore
|
|
48
48
|
# httpx
|
|
@@ -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.143.0
|
|
71
71
|
# via linkedparticles
|
|
72
|
-
filelock==4.
|
|
72
|
+
filelock==4.1.1
|
|
73
73
|
# via
|
|
74
74
|
# huggingface-hub
|
|
75
75
|
# linkedparticles
|
|
@@ -148,7 +148,7 @@ 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.10
|
|
152
152
|
# via linkedparticles
|
|
153
153
|
langchain-protocol==0.0.19
|
|
154
154
|
# via langchain-core
|
|
@@ -266,7 +266,7 @@ protobuf==7.36.2
|
|
|
266
266
|
# opentelemetry-proto
|
|
267
267
|
pycparser==3.0 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy'
|
|
268
268
|
# via cffi
|
|
269
|
-
pydantic==2.
|
|
269
|
+
pydantic==2.14.1
|
|
270
270
|
# via
|
|
271
271
|
# anthropic
|
|
272
272
|
# fastapi
|
|
@@ -275,7 +275,7 @@ pydantic==2.13.5
|
|
|
275
275
|
# linkedparticles
|
|
276
276
|
# mcp
|
|
277
277
|
# pydantic-settings
|
|
278
|
-
pydantic-core==2.
|
|
278
|
+
pydantic-core==2.50.1
|
|
279
279
|
# via pydantic
|
|
280
280
|
pydantic-settings==2.15.0
|
|
281
281
|
# via mcp
|
|
@@ -287,7 +287,7 @@ pyld==3.3.0
|
|
|
287
287
|
# via linkedparticles
|
|
288
288
|
pyparsing==3.3.3
|
|
289
289
|
# via rdflib
|
|
290
|
-
pypdf==6.
|
|
290
|
+
pypdf==6.20.1
|
|
291
291
|
# via linkedparticles
|
|
292
292
|
pypdfium2==5.14.0
|
|
293
293
|
# via linkedparticles
|
|
@@ -356,7 +356,7 @@ sniffio==1.3.1
|
|
|
356
356
|
# via
|
|
357
357
|
# anthropic
|
|
358
358
|
# langsmith
|
|
359
|
-
sqlalchemy==2.1.
|
|
359
|
+
sqlalchemy==2.1.4
|
|
360
360
|
# via
|
|
361
361
|
# alembic
|
|
362
362
|
# linkedparticles
|
|
@@ -595,6 +595,27 @@ _SHIPPED_EXTRACTION_OUTPUT_TOKENS: dict[str, int] = {
|
|
|
595
595
|
"claude-sonnet-4-6": 5_363,
|
|
596
596
|
}
|
|
597
597
|
|
|
598
|
+
# Cache-read multipliers that differ from ``llm.cache_read_price_multiplier``'s
|
|
599
|
+
# standard 0.1x, from the pricing page's footnotes (read 2026-10-18): cache hits
|
|
600
|
+
# on claude-opus-5-5 and claude-sonnet-5-5 bill at 0.05x base input, and on
|
|
601
|
+
# claude-fable-5-1 at 0.025x. Every other model uses the standard multiplier.
|
|
602
|
+
_SHIPPED_CACHE_READ_MULTIPLIER: dict[str, float] = {
|
|
603
|
+
"claude-fable-5-1": 0.025,
|
|
604
|
+
"claude-opus-5-5": 0.05,
|
|
605
|
+
"claude-sonnet-5-5": 0.05,
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
# How much less output a source type's extraction calls write per character
|
|
609
|
+
# than the documents ``audit.estimate_output_tokens_per_source_char`` was
|
|
610
|
+
# fitted on (memory notes and design records, about 5 claims per 1,000
|
|
611
|
+
# characters). A Claude Code transcript states about 1.9 per 1,000 (the
|
|
612
|
+
# general extractor's transcript deltas), so 0.4. Checked against
|
|
613
|
+
# the five metered consolidation nights of 2026-10-12 to 10-16 on the owner's
|
|
614
|
+
# store (claude-sonnet-5-5, mostly CONVERSATION snapshots): the expected
|
|
615
|
+
# output came out 1.1 to 1.9 times what the provider reported, before the
|
|
616
|
+
# estimate's high end adds its spread.
|
|
617
|
+
_SHIPPED_OUTPUT_SCALE_BY_SOURCE_TYPE: dict[str, float] = {"CONVERSATION": 0.4}
|
|
618
|
+
|
|
598
619
|
_T = TypeVar("_T")
|
|
599
620
|
|
|
600
621
|
|
|
@@ -731,6 +752,39 @@ class LLMConfig(BaseModel):
|
|
|
731
752
|
# at 1.25x input and a cache read at 0.1x.
|
|
732
753
|
cache_write_price_multiplier: float = Field(default=1.25, ge=0.0)
|
|
733
754
|
cache_read_price_multiplier: float = Field(default=0.1, ge=0.0)
|
|
755
|
+
# Per-model cache-read multipliers, keyed like ``price_per_mtok``, for the
|
|
756
|
+
# models the pricing page bills below the standard 0.1x
|
|
757
|
+
# (``_SHIPPED_CACHE_READ_MULTIPLIER``). Entries set here merge over the
|
|
758
|
+
# shipped ones; a model with no entry uses ``cache_read_price_multiplier``.
|
|
759
|
+
cache_read_price_multiplier_by_model: dict[str, float] = Field(
|
|
760
|
+
default_factory=lambda: dict(_SHIPPED_CACHE_READ_MULTIPLIER)
|
|
761
|
+
)
|
|
762
|
+
|
|
763
|
+
@field_validator("cache_read_price_multiplier_by_model", mode="before")
|
|
764
|
+
@classmethod
|
|
765
|
+
def _merge_over_shipped_cache_reads(cls, value: Any) -> Any:
|
|
766
|
+
"""Operator entries replace the shipped ones key by key; the rest stay."""
|
|
767
|
+
if isinstance(value, dict):
|
|
768
|
+
return {**_SHIPPED_CACHE_READ_MULTIPLIER, **value}
|
|
769
|
+
return value
|
|
770
|
+
|
|
771
|
+
@field_validator("cache_read_price_multiplier_by_model")
|
|
772
|
+
@classmethod
|
|
773
|
+
def _non_negative_cache_reads(cls, value: dict[str, float]) -> dict[str, float]:
|
|
774
|
+
"""A cache-read multiplier is a price ratio: zero or more."""
|
|
775
|
+
for key, factor in value.items():
|
|
776
|
+
if factor < 0:
|
|
777
|
+
raise ValueError(
|
|
778
|
+
f"llm.cache_read_price_multiplier_by_model[{key!r}] must be >= 0, got {factor}"
|
|
779
|
+
)
|
|
780
|
+
return value
|
|
781
|
+
|
|
782
|
+
def cache_read_multiplier_for(self, selection: ProviderSelection) -> float:
|
|
783
|
+
"""The cache-read price as a multiple of ``selection``'s input price."""
|
|
784
|
+
factor, _ = lookup_by_model(
|
|
785
|
+
self.cache_read_price_multiplier_by_model, selection.provider, selection.model
|
|
786
|
+
)
|
|
787
|
+
return self.cache_read_price_multiplier if factor is None else factor
|
|
734
788
|
|
|
735
789
|
@field_validator("price_per_mtok", mode="before")
|
|
736
790
|
@classmethod
|
|
@@ -936,6 +990,14 @@ class ExtractionConfig(BaseModel):
|
|
|
936
990
|
# alone. On a short source it rivals the source itself. Read by the audit
|
|
937
991
|
# estimate and the memory-rot benchmark.
|
|
938
992
|
estimate_prompt_overhead_tokens: int = Field(default=2500, ge=0)
|
|
993
|
+
# The part of that system prompt sent as a prompt-cache prefix,
|
|
994
|
+
# which a batch of extraction calls writes once and then reads at the
|
|
995
|
+
# model's cache-read price (``llm.cache_read_price_multiplier_by_model``).
|
|
996
|
+
# The consolidation estimate adds it per call on top of the overhead above;
|
|
997
|
+
# with ``llm.prompt_cache.enabled`` off it is priced as plain input.
|
|
998
|
+
# Measured: claude-sonnet-5-5 wrote a 2,868-token prefix on each of the
|
|
999
|
+
# metered nights of 2026-10-12 to 10-16.
|
|
1000
|
+
estimate_cached_prefix_tokens: int = Field(default=2900, ge=0)
|
|
939
1001
|
# The bulk extraction paths skip an unextracted snapshot of a MUTABLE
|
|
940
1002
|
# entry once a newer extractable snapshot of the same entry exists: the
|
|
941
1003
|
# generation cascade would retire the older generation's beliefs anyway,
|
|
@@ -956,6 +1018,12 @@ class ExtractionConfig(BaseModel):
|
|
|
956
1018
|
# The largest delta chunk sent in one call. Each chunk after the first
|
|
957
1019
|
# takes the end of the chunk before it as its context.
|
|
958
1020
|
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)
|
|
959
1027
|
# a pair the §6.6 contradiction probe confirms is read a second
|
|
960
1028
|
# time, before the write loop, with each claim's source kind, name, time
|
|
961
1029
|
# and passage (on ``llm.verification``). A pair the reading does not
|
|
@@ -1627,6 +1695,15 @@ class UtilityMiningConfig(BaseModel):
|
|
|
1627
1695
|
behavioural_matching: bool = True
|
|
1628
1696
|
max_behavioural_calls: int = Field(default=150, ge=0)
|
|
1629
1697
|
behavioural_candidate_limit: int = Field(default=200, ge=0)
|
|
1698
|
+
# Characters per input token the consolidation estimate prices a judge
|
|
1699
|
+
# prompt at. The prompt is mostly tool-call lines (paths, ids, shell
|
|
1700
|
+
# commands), which tokenize denser than prose: on the metered nights of
|
|
1701
|
+
# 2026-10-12 to 10-16, claude-sonnet-5-5 billed 3,560 to 4,240 input
|
|
1702
|
+
# tokens a call for prompts of about 9,100 characters (the action
|
|
1703
|
+
# evidence is capped, so the size holds night to night), 2.1 to 2.6
|
|
1704
|
+
# characters a token. The lower figure keeps the estimate above the bill.
|
|
1705
|
+
# The estimate uses the smaller of this and the model's own factor.
|
|
1706
|
+
estimate_chars_per_token: float = Field(default=2.1, gt=0.0)
|
|
1630
1707
|
|
|
1631
1708
|
|
|
1632
1709
|
class UtilityConfig(BaseModel):
|
|
@@ -2085,6 +2162,21 @@ class RedditConfig(BaseModel):
|
|
|
2085
2162
|
top_comment_count: int = 200
|
|
2086
2163
|
# Raised 500→1000 for parity with the gist comment body limit.
|
|
2087
2164
|
comment_body_limit: int = 1000
|
|
2165
|
+
# Where the importer fetches a thread's post and comment tree from. Reddit
|
|
2166
|
+
# bot-walls its own ``.json`` endpoint for unauthenticated clients (403), so
|
|
2167
|
+
# the default reads the Arctic Shift archive, a free third-party mirror that
|
|
2168
|
+
# serves Reddit's own field names. ``reddit`` keeps the direct curl fetch for
|
|
2169
|
+
# an operator whose network can still reach it. The share-link redirect is
|
|
2170
|
+
# always resolved through reddit.com, whichever backend is chosen.
|
|
2171
|
+
fetch_backend: Literal["arctic_shift", "reddit"] = "arctic_shift"
|
|
2172
|
+
# Base URL of the Arctic Shift API host (no trailing path).
|
|
2173
|
+
arctic_shift_base_url: str = "https://arctic-shift.photon-reddit.com"
|
|
2174
|
+
# ``limit`` passed to the archive's comment-tree endpoint: the most comments
|
|
2175
|
+
# one deposit pulls. The extractor still sends only ``top_comment_count``.
|
|
2176
|
+
arctic_shift_comment_limit: int = Field(default=25000, ge=1)
|
|
2177
|
+
# Longest wait honoured on an HTTP 429 before the one retry. A reset further
|
|
2178
|
+
# away than this fails the deposit at once instead of stalling it.
|
|
2179
|
+
arctic_shift_max_wait_seconds: float = Field(default=30.0, ge=0.0)
|
|
2088
2180
|
|
|
2089
2181
|
|
|
2090
2182
|
class HackerNewsConfig(BaseModel):
|
|
@@ -2216,6 +2308,19 @@ class QueryConfig(BaseModel):
|
|
|
2216
2308
|
# default follows the leakage measurement recorded in
|
|
2217
2309
|
# docs/benchmarks/leakage.md.
|
|
2218
2310
|
grounded_answers: bool = False
|
|
2311
|
+
# Keep each store's ACTIVE candidates decoded in memory between reads,
|
|
2312
|
+
# re-reading only the rows the store's change journal names as changed
|
|
2313
|
+
# (particles/store/candidate_cache.py). Semantic query, extraction, the
|
|
2314
|
+
# write-time reconciliation seam and the maintenance passes read through
|
|
2315
|
+
# it. Results are identical either way; off reads and decodes every
|
|
2316
|
+
# candidate on every read. The cache holds one decoded row per ACTIVE
|
|
2317
|
+
# belief for the life of the process.
|
|
2318
|
+
candidate_cache: bool = True
|
|
2319
|
+
# After a full build of a cache this many rows or larger, exempt the
|
|
2320
|
+
# process's live objects from Python's cyclic garbage collector
|
|
2321
|
+
# (gc.freeze), which otherwise walks the whole cache on most queries
|
|
2322
|
+
# (about 0.3 s at 56k rows). Process-wide; 0 never freezes.
|
|
2323
|
+
candidate_cache_freeze_rows: int = Field(default=10_000, ge=0)
|
|
2219
2324
|
|
|
2220
2325
|
|
|
2221
2326
|
class ContestednessConfig(BaseModel):
|
|
@@ -2801,12 +2906,21 @@ class AgentExtractionConfig(BaseModel):
|
|
|
2801
2906
|
# An ask unanswered after this many seconds is expired.
|
|
2802
2907
|
ask_ttl_seconds: int = Field(default=900, ge=60)
|
|
2803
2908
|
# A submission covers its span only with at least this many accepted claims
|
|
2804
|
-
# per 1000 characters.
|
|
2805
|
-
# extractor's own transcript deltas in the maintainers' store
|
|
2806
|
-
|
|
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)
|
|
2807
2914
|
# ...and with no more than this share of candidates dropped for evidence
|
|
2808
2915
|
# not found in the span. Placeholder until the shadow week measures it.
|
|
2809
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
|
|
2810
2924
|
|
|
2811
2925
|
@field_validator("mode", mode="before")
|
|
2812
2926
|
@classmethod
|
|
@@ -3210,6 +3324,36 @@ class AuditConfig(BaseModel):
|
|
|
3210
3324
|
# Wall time per second reading: the measured runs read 22 flags in ~41 s.
|
|
3211
3325
|
estimate_seconds_per_verification: float = Field(default=2.0, ge=0.0)
|
|
3212
3326
|
|
|
3327
|
+
# Multiplies the per-character output rate above for a source type that
|
|
3328
|
+
# states fewer (or more) claims per character than the documents it was
|
|
3329
|
+
# fitted on, keyed by corpus-entry source type (``CONVERSATION``). The
|
|
3330
|
+
# per-call base is unchanged. Read by the consolidation estimate, which
|
|
3331
|
+
# knows each snapshot's source type. Ships with a measured entry for
|
|
3332
|
+
# transcripts (``_SHIPPED_OUTPUT_SCALE_BY_SOURCE_TYPE``); operator entries
|
|
3333
|
+
# merge over it key by key, and a type with no entry is scaled by 1.
|
|
3334
|
+
estimate_output_scale_by_source_type: dict[str, float] = Field(
|
|
3335
|
+
default_factory=lambda: dict(_SHIPPED_OUTPUT_SCALE_BY_SOURCE_TYPE)
|
|
3336
|
+
)
|
|
3337
|
+
|
|
3338
|
+
@field_validator("estimate_output_scale_by_source_type", mode="before")
|
|
3339
|
+
@classmethod
|
|
3340
|
+
def _merge_over_shipped_type_scales(cls, value: Any) -> Any:
|
|
3341
|
+
"""Operator entries replace the shipped ones key by key; the rest stay."""
|
|
3342
|
+
if isinstance(value, dict):
|
|
3343
|
+
return {**_SHIPPED_OUTPUT_SCALE_BY_SOURCE_TYPE, **value}
|
|
3344
|
+
return value
|
|
3345
|
+
|
|
3346
|
+
@field_validator("estimate_output_scale_by_source_type")
|
|
3347
|
+
@classmethod
|
|
3348
|
+
def _non_negative_type_scale(cls, value: dict[str, float]) -> dict[str, float]:
|
|
3349
|
+
"""Every per-type output scale is a multiplier: zero or more."""
|
|
3350
|
+
for key, scale in value.items():
|
|
3351
|
+
if scale < 0:
|
|
3352
|
+
raise ValueError(
|
|
3353
|
+
f"audit.estimate_output_scale_by_source_type[{key!r}] must be >= 0, got {scale}"
|
|
3354
|
+
)
|
|
3355
|
+
return value
|
|
3356
|
+
|
|
3213
3357
|
@field_validator("estimate_output_scale_by_model", mode="before")
|
|
3214
3358
|
@classmethod
|
|
3215
3359
|
def _merge_over_shipped_scales(cls, value: Any) -> Any:
|
{linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/closure_measure.py
RENAMED
|
@@ -24,13 +24,20 @@ A transition is one of three kinds:
|
|
|
24
24
|
and *autonomous* otherwise: the trust ladder, update supersession,
|
|
25
25
|
duplicate merge, re-anchor, staleness, abstraction revalidation.
|
|
26
26
|
- ``contradiction_closed``: an INCONSISTENCY record closed, by a review
|
|
27
|
-
(gesture) or by
|
|
27
|
+
(gesture) or by a nightly pass (autonomous): the disclosure pass
|
|
28
|
+
or the held-claim release.
|
|
28
29
|
- ``promotion``: an abstraction asserted, by the accept gesture or
|
|
29
30
|
by the pass itself in ``auto`` mode.
|
|
30
31
|
|
|
31
32
|
A gesture is an explicit write verb, whether an operator or an agent ran it;
|
|
32
33
|
``gesture_by_actor`` keeps the two apart for a reader who needs them apart.
|
|
33
34
|
|
|
35
|
+
An autonomous closure is also tallied by its cause, and by whether it
|
|
36
|
+
returned a held claim to the store (:func:`tally_closures`). Most causes
|
|
37
|
+
release nothing: a lapsed or regrouped census record held no claim. A
|
|
38
|
+
withdrawn extraction record and a partner-retired one each restore the
|
|
39
|
+
claim the record held, and that release is the one no person approved.
|
|
40
|
+
|
|
34
41
|
Pure: the Engine gathers plain values and this module decides the tally.
|
|
35
42
|
Nothing here is stored on a particle; the result rides the
|
|
36
43
|
``CONSOLIDATION_RUN`` event.
|
|
@@ -39,8 +46,9 @@ Nothing here is stored on a particle; the result rides the
|
|
|
39
46
|
from __future__ import annotations
|
|
40
47
|
|
|
41
48
|
from collections import Counter
|
|
42
|
-
from collections.abc import Sequence
|
|
49
|
+
from collections.abc import Mapping, Sequence
|
|
43
50
|
from dataclasses import dataclass, field
|
|
51
|
+
from typing import Any
|
|
44
52
|
|
|
45
53
|
#: Event types whose PARTICLE refs name the beliefs an explicit write retired.
|
|
46
54
|
GESTURE_RETIREMENT_EVENTS: frozenset[str] = frozenset(
|
|
@@ -55,6 +63,10 @@ TRANSITION_KINDS: tuple[str, ...] = ("retirement", "contradiction_closed", "prom
|
|
|
55
63
|
#: The reason key for a retired row that carries no ``status_reason``.
|
|
56
64
|
UNSPECIFIED_REASON = "UNSPECIFIED"
|
|
57
65
|
|
|
66
|
+
#: The ``INCONSISTENCY_CLOSED`` payload keys that name the claim a close
|
|
67
|
+
#: returned to the store: a minted successor, or the ACTIVE twin it folded into.
|
|
68
|
+
RELEASE_KEYS: tuple[str, ...] = ("successor", "folded_into")
|
|
69
|
+
|
|
58
70
|
|
|
59
71
|
@dataclass(frozen=True)
|
|
60
72
|
class Retirement:
|
|
@@ -73,6 +85,51 @@ class GestureEvent:
|
|
|
73
85
|
particle_ids: tuple[str, ...] = ()
|
|
74
86
|
|
|
75
87
|
|
|
88
|
+
@dataclass(frozen=True)
|
|
89
|
+
class Closure:
|
|
90
|
+
"""One autonomous ``INCONSISTENCY_CLOSED`` event, reduced to what the tally reads."""
|
|
91
|
+
|
|
92
|
+
cause: str
|
|
93
|
+
#: Whether the close returned a held claim to the store.
|
|
94
|
+
released: bool = False
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def closure_from_payload(payload: Mapping[str, Any] | None) -> Closure:
|
|
98
|
+
"""Read one close event's cause and whether it released a held claim."""
|
|
99
|
+
data = payload or {}
|
|
100
|
+
cause = data.get("cause")
|
|
101
|
+
return Closure(
|
|
102
|
+
cause=cause if isinstance(cause, str) and cause else UNSPECIFIED_REASON,
|
|
103
|
+
released=any(data.get(key) for key in RELEASE_KEYS),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@dataclass(frozen=True)
|
|
108
|
+
class ClosureTally:
|
|
109
|
+
"""Autonomous closures by cause, and the held-claim releases among them."""
|
|
110
|
+
|
|
111
|
+
closed_by_cause: dict[str, int] = field(default_factory=dict)
|
|
112
|
+
released_by_cause: dict[str, int] = field(default_factory=dict)
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def closed(self) -> int:
|
|
116
|
+
return sum(self.closed_by_cause.values())
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def released(self) -> int:
|
|
120
|
+
return sum(self.released_by_cause.values())
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def tally_closures(closures: Sequence[Closure]) -> ClosureTally:
|
|
124
|
+
"""Count closures and held-claim releases per cause, causes sorted."""
|
|
125
|
+
closed = Counter(c.cause for c in closures)
|
|
126
|
+
released = Counter(c.cause for c in closures if c.released)
|
|
127
|
+
return ClosureTally(
|
|
128
|
+
closed_by_cause=dict(sorted(closed.items())),
|
|
129
|
+
released_by_cause=dict(sorted(released.items())),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
76
133
|
@dataclass(frozen=True)
|
|
77
134
|
class TransitionTally:
|
|
78
135
|
"""Lifecycle transitions in one window, split autonomous versus gesture."""
|
{linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/conflict_review.py
RENAMED
|
@@ -31,6 +31,42 @@ from particles.core.status import Status, StatusReason
|
|
|
31
31
|
|
|
32
32
|
_TERMINAL = (Status.RETRACTED, Status.SUPERSEDED)
|
|
33
33
|
|
|
34
|
+
CLOSED_RECORD: tuple[Status, StatusReason] = (Status.RETRACTED, StatusReason.CONFLICT_RESOLVED)
|
|
35
|
+
"""The state every non-DEFER resolution leaves an INCONSISTENCY record in.
|
|
36
|
+
|
|
37
|
+
The §6.6 wrapper-terminal rule: review, the trust cascade, the held-claim
|
|
38
|
+
release and the disclosure sweep all close a record this way. A record the
|
|
39
|
+
cascade closed before 1.192.15 was left ``PROVENANCE_STALE`` /
|
|
40
|
+
``CONFLICT_RESOLVED`` instead; migration 053 moves those here."""
|
|
41
|
+
|
|
42
|
+
CASCADE_ACTOR = "trust-cascade"
|
|
43
|
+
"""``asserted_by`` on the REVIEW particle the trust cascade writes per record."""
|
|
44
|
+
|
|
45
|
+
_CASCADE_REVIEW_PREFIX = "CASCADE REVIEW: auto-resolved INCONSISTENCY "
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def cascade_review_content(
|
|
49
|
+
inconsistency_id: str, winner_id: str, loser_id: str, statement_id: str
|
|
50
|
+
) -> str:
|
|
51
|
+
"""The content of the REVIEW particle the trust cascade writes for one record."""
|
|
52
|
+
return (
|
|
53
|
+
f"{_CASCADE_REVIEW_PREFIX}{inconsistency_id}. "
|
|
54
|
+
f"Winner: {winner_id}. Loser: {loser_id}. "
|
|
55
|
+
f"Triggered by trust statement {statement_id}."
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def cascade_reviewed_record_id(content: str) -> str | None:
|
|
60
|
+
"""The record a cascade REVIEW particle's content names, or None for other content.
|
|
61
|
+
|
|
62
|
+
The cascade writes no operator event, so its REVIEW particle is the one
|
|
63
|
+
trace that says which closed records it closed.
|
|
64
|
+
"""
|
|
65
|
+
if not content.startswith(_CASCADE_REVIEW_PREFIX):
|
|
66
|
+
return None
|
|
67
|
+
record_id, sep, _rest = content[len(_CASCADE_REVIEW_PREFIX) :].partition(". ")
|
|
68
|
+
return record_id if sep and record_id else None
|
|
69
|
+
|
|
34
70
|
|
|
35
71
|
class Demotion(Enum):
|
|
36
72
|
"""What demoting a conflict's losing claim takes, given its current status."""
|
|
@@ -76,8 +76,7 @@ DISCLOSURE_ACTOR = "memory-consolidate"
|
|
|
76
76
|
READING_STANDING = "standing/1"
|
|
77
77
|
#: The instruction for a pair with a claim from a time-stamped record (a
|
|
78
78
|
#: session transcript, another append-only log): a value observed at a later
|
|
79
|
-
#: time may be a change, and only the same moment or a fixed fact confirms
|
|
80
|
-
#:.
|
|
79
|
+
#: time may be a change, and only the same moment or a fixed fact confirms.
|
|
81
80
|
READING_OBSERVED = "observed/1"
|
|
82
81
|
|
|
83
82
|
_EXCERPT_CHARS = 120
|
|
@@ -420,7 +419,7 @@ class CloseCause(StrEnum):
|
|
|
420
419
|
REVIEW = "review"
|
|
421
420
|
"""A review action: a ``REVIEW_RESOLVED`` event names the record."""
|
|
422
421
|
CASCADE = "cascade"
|
|
423
|
-
"""The trust cascade:
|
|
422
|
+
"""The trust cascade: no event; its REVIEW particle names the record."""
|
|
424
423
|
LAPSED = "lapsed"
|
|
425
424
|
"""The lapse sweep: a side has no member left."""
|
|
426
425
|
REGROUPED = "regrouped"
|
{linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/held_release.py
RENAMED
|
@@ -31,9 +31,9 @@ from particles.core.observer_scope import PairPrecondition
|
|
|
31
31
|
from particles.core.schema import Particle
|
|
32
32
|
from particles.core.status import Status, StatusReason
|
|
33
33
|
|
|
34
|
-
#: The retirements an autonomous pass writes: rung 2.5 and its sweep
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
#: The retirements an autonomous pass writes: rung 2.5 and its sweep,
|
|
35
|
+
#: the re-anchor pass, and the document sweep.
|
|
36
|
+
#: A claim a person retired is not among them, and a record
|
|
37
37
|
#: behind one stays with review.
|
|
38
38
|
AUTONOMOUS_RETIREMENTS: frozenset[StatusReason] = frozenset(
|
|
39
39
|
{
|
{linkedparticles_core-1.192.2 → linkedparticles_core-1.192.28}/particles/core/observer_scope.py
RENAMED
|
@@ -158,6 +158,26 @@ def meet(premises: Iterable[BeliefScope]) -> BeliefScope:
|
|
|
158
158
|
return BeliefScope(keys=keys, lapsed=lapsed and not keys)
|
|
159
159
|
|
|
160
160
|
|
|
161
|
+
def join(members: Iterable[BeliefScope]) -> BeliefScope:
|
|
162
|
+
"""The scope a ``CO_EVIDENTIAL`` merge gives every sourced member: their union.
|
|
163
|
+
|
|
164
|
+
The join pools the group's attesting entries, so the merged
|
|
165
|
+
scope is global as soon as one member is, and otherwise the union of their
|
|
166
|
+
keys. A union with no keys is in view for no project; it is reported as
|
|
167
|
+
lapsed when some member was lapsed, which is a reading for display only,
|
|
168
|
+
since the pooled entries decide between lapsed and unattributed. Applies to
|
|
169
|
+
sourced beliefs: a derived belief keeps the meet of its premises.
|
|
170
|
+
"""
|
|
171
|
+
keys: set[str] = set()
|
|
172
|
+
lapsed = False
|
|
173
|
+
for member in members:
|
|
174
|
+
if member.is_global:
|
|
175
|
+
return GLOBAL_SCOPE
|
|
176
|
+
keys |= member.keys
|
|
177
|
+
lapsed = lapsed or member.lapsed
|
|
178
|
+
return BeliefScope(keys=frozenset(keys), lapsed=lapsed and not keys)
|
|
179
|
+
|
|
180
|
+
|
|
161
181
|
def visible(scope: BeliefScope, observer_project: str | None, *, widened: bool = False) -> bool:
|
|
162
182
|
"""The predicate: is a belief with ``scope`` in view for this observer?
|
|
163
183
|
|
|
@@ -187,6 +207,30 @@ def share_an_observer(a: BeliefScope, b: BeliefScope) -> bool:
|
|
|
187
207
|
return bool(a.keys & b.keys)
|
|
188
208
|
|
|
189
209
|
|
|
210
|
+
def same_scope(a: BeliefScope, b: BeliefScope) -> bool:
|
|
211
|
+
"""Whether two beliefs have exactly the same observers: the agent link test.
|
|
212
|
+
|
|
213
|
+
A ``CO_EVIDENTIAL`` edge unions the two groups' sources, so it leaves both
|
|
214
|
+
scopes unchanged only when they are already equal. Visibility is not
|
|
215
|
+
enough: a project's belief linked to a global one becomes global. Lapsed
|
|
216
|
+
and unattributed are distinct readings and only equal themselves.
|
|
217
|
+
"""
|
|
218
|
+
if a.is_global or b.is_global:
|
|
219
|
+
return a.is_global and b.is_global
|
|
220
|
+
if a.keys or b.keys:
|
|
221
|
+
return a.keys == b.keys
|
|
222
|
+
return a.lapsed == b.lapsed
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def describe_scope(scope: BeliefScope) -> str:
|
|
226
|
+
"""A short operator-facing reading of a scope, for refusals and reports."""
|
|
227
|
+
if scope.is_global:
|
|
228
|
+
return "global"
|
|
229
|
+
if scope.keys:
|
|
230
|
+
return "project " + ", ".join(sorted(scope.keys))
|
|
231
|
+
return "lapsed" if scope.lapsed else "unattributed"
|
|
232
|
+
|
|
233
|
+
|
|
190
234
|
class PairPrecondition(StrEnum):
|
|
191
235
|
"""Whether a (candidate, existing) pair may be reconciled."""
|
|
192
236
|
|
|
@@ -81,8 +81,11 @@ _ALLOWED: frozenset[tuple[Status | None, Status]] = frozenset(
|
|
|
81
81
|
(Status.ACTIVE, Status.SUPERSEDED),
|
|
82
82
|
(Status.ACTIVE, Status.RETRACTED),
|
|
83
83
|
(Status.ACTIVE, Status.PROVENANCE_STALE),
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
# Every non-DEFER resolution retracts the record (§6.6 wrapper-terminal
|
|
85
|
+
# rule): review, the trust cascade, the held-claim release and the
|
|
86
|
+
# disclosure sweep. There is no INCONSISTENCY → PROVENANCE_STALE edge;
|
|
87
|
+
# the cascade wrote one until 1.192.15 (migration 053).
|
|
88
|
+
(Status.INCONSISTENCY, Status.RETRACTED),
|
|
86
89
|
(Status.INCONSISTENCY, Status.INCONSISTENCY), # DEFER: re-set same status
|
|
87
90
|
(Status.PROVENANCE_STALE, Status.SUPERSEDED), # Reindex supersession of stale particle
|
|
88
91
|
(Status.PROVENANCE_STALE, Status.RETRACTED), # Explicit operator cleanup
|
|
@@ -26,6 +26,7 @@ from __future__ import annotations
|
|
|
26
26
|
import contextlib
|
|
27
27
|
import logging
|
|
28
28
|
import threading
|
|
29
|
+
from collections.abc import Sequence
|
|
29
30
|
from dataclasses import dataclass
|
|
30
31
|
from typing import Any
|
|
31
32
|
|
|
@@ -134,6 +135,31 @@ def cosine_similarity(
|
|
|
134
135
|
return max(0.0, min(1.0, raw))
|
|
135
136
|
|
|
136
137
|
|
|
138
|
+
def cosine_similarities(
|
|
139
|
+
query: np.ndarray[Any, np.dtype[np.floating[Any]]],
|
|
140
|
+
vectors: Sequence[np.ndarray[Any, np.dtype[np.floating[Any]]]],
|
|
141
|
+
) -> list[float]:
|
|
142
|
+
""":func:`cosine_similarity` of ``query`` against each vector, in one pass.
|
|
143
|
+
|
|
144
|
+
The same formula, the same ``1e-10`` epsilon and the same ``[0, 1]`` clamp,
|
|
145
|
+
computed over a stacked matrix instead of once per pair: on the
|
|
146
|
+
query-latency baseline the per-pair loop cost 81 ms at 56k candidates and
|
|
147
|
+
the matrix form 6 ms. A value can differ from the per-pair one in its last
|
|
148
|
+
bit, because the dot products are summed in another order. Each row is
|
|
149
|
+
reduced by the same loop wherever it sits in the matrix (``einsum``, not a
|
|
150
|
+
BLAS kernel that blocks rows by position), so two identical vectors always
|
|
151
|
+
get identical scores and keep their tie.
|
|
152
|
+
"""
|
|
153
|
+
if not vectors:
|
|
154
|
+
return []
|
|
155
|
+
matrix = np.stack(vectors)
|
|
156
|
+
dots = np.einsum("ij,j->i", matrix, query)
|
|
157
|
+
norms = np.sqrt(np.einsum("ij,ij->i", matrix, matrix))
|
|
158
|
+
raw = dots / (norms * np.linalg.norm(query) + 1e-10)
|
|
159
|
+
clamped: list[float] = np.clip(raw, 0.0, 1.0).tolist()
|
|
160
|
+
return clamped
|
|
161
|
+
|
|
162
|
+
|
|
137
163
|
class EmbeddingModel:
|
|
138
164
|
"""Protocol-compatible wrapper around sentence-transformers SentenceTransformer."""
|
|
139
165
|
|