linkedparticles-core 1.187.2__tar.gz → 1.190.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/PKG-INFO +1 -1
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/context.jsonld +2 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/interchange.schema.json +2 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/particle.schema.json +10 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/shacl/ParticleShape.ttl +19 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/config.py +162 -7
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/contract.py +10 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/schema.py +171 -3
- linkedparticles_core-1.190.0/particles/core/validity.py +392 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/general.py +209 -4
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/interchange/codec.py +10 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/__init__.py +4 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/registry.py +35 -5
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/pyproject.toml +1 -1
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_validity_extraction.py +200 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/LICENSE +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/NOTICE +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/README.md +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/conformance/README.md +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/conformance/profile.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/conformance/similarity_vectors.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/shacl/CorpusSnapshotShape.ttl +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/shacl/ProvenanceChainShape.ttl +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/shacl/SubjectShape.ttl +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/shacl/TrustStatementShape.ttl +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/trust_lens.schema.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/constraints.txt +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/_resources.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/fixtures.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/jsonschema.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/profile.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/runner.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/shacl.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/types.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/validator.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/_resources.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/cascade_gate.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/claims.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/closure_measure.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/conflict_resolution.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/conflict_review.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/consolidation_cadence.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/contradiction_disclosure.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/duplicate_key.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/equivalence.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/fingerprint.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/generics.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/granularity.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/held_release.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/jsonld_context.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/modality.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/observer_scope.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/past_value.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/predicate_profile.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/probe_verdict.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/progress.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/provenance.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/reanchor.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/scoring/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/scoring/confidence.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/scoring/decay.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/scoring/relevance.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/scoring/utility.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/spend_budget.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/stance.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/status.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/vocabulary.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/vocabulary_jsonld.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/core/vocabulary_report.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/egress.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/embeddings.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/agent.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/append_delta.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/calibration.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/components.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/docstrings.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/github/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/github/_shared.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/github/gist.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/github/pages.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/github/repo.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/hackernews.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/incremental.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/journal.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/mastodon.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/mcp_memory.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/migration_preview.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/modality.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/nomisma.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/numista/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/numista/_shared.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/numista/coin.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/numista/issuer.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/numista/listing.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/polarity.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/property_keys.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/rdf.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/reddit.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/registry.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/scope.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/session_state.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/structure.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/subject_gate.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/subject_scope.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/taxonomy.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/tool_turns.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/trust_lens.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/vocabulary.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/extraction/wikidata.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/http.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/interchange/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/interchange/jsonl.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/interchange/yaml_ld.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/adapters/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/adapters/anthropic.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/adapters/local.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/adapters/openai_compat.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/batch_budget.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/breaker.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/client.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/errors.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/fencing.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/logprobs.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/pool.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/replay.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/spend_budget.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/llm/usage.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/py.typed +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/render/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/render/markdown.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/secrets.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/url_canonical.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/url_safety.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/__init__.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/_client_fixtures.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/_upstream.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/MANIFEST.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/hackernews-thread-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/hackernews-thread-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/hackernews-thread-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/journal-entry-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/journal-entry-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/journal-entry-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/mastodon-thread-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/mastodon-thread-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/mastodon-thread-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/mcp-memory-export-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/mcp-memory-export-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/mcp-memory-export-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/nomisma-concept-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/nomisma-concept-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/nomisma-concept-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/numista-coin-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/numista-coin-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/numista-coin-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/numista-issuer-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/numista-issuer-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/numista-issuer-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/numista-listing-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/numista-listing-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/numista-listing-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/rdf-graph-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/rdf-graph-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/rdf-graph-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/reddit-thread-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/reddit-thread-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/reddit-thread-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/taxonomy-coins-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/taxonomy-coins-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/taxonomy-coins-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/trust-lens-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/trust-lens-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/trust-lens-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-article-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-article-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-article-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-article-002/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-article-002/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-article-002/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-essay-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-essay-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-essay-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-interview-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-interview-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/web-interview-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/wikidata-entity-001/content.bin +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/wikidata-entity-001/manifest.yaml +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conformance/fixtures/wikidata-entity-001/snapshot.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/conftest.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/fixtures/scope/normative-rule-file.md +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/fixtures/scope/normative-rule-file.recorded.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/fixtures/scope/rule-file-agents-md.md +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/fixtures/scope/rule-file-agents-md.recorded.json +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_calibration_isotonic.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_confidence.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_config_client_sections.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_config_sample.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_conformance_fixture_gen.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_conformance_similarity_vectors.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_conformance_validator.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_core_contradiction_disclosure.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_core_held_release.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_core_observer_scope.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_core_provenance.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_core_vocabulary.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_egress_policy.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_embeddings.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_extraction_agent.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_extraction_vision.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_interchange_schema.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_llm_batch_budget.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_llm_logprobs.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_llm_pool.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_llm_replay.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_llm_usage.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_schema.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/tests/test_secrets.py +0 -0
- {linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/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.190.0
|
|
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
|
{linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/context.jsonld
RENAMED
|
@@ -63,6 +63,8 @@
|
|
|
63
63
|
"particleType": { "@id": "particles:particleType" },
|
|
64
64
|
"assertionModality": { "@id": "particles:assertionModality" },
|
|
65
65
|
"validUntil": { "@id": "psum:duration", "@type": "xsd:dateTime" },
|
|
66
|
+
"validFrom": { "@id": "particles:validFrom", "@type": "xsd:dateTime" },
|
|
67
|
+
"validKind": { "@id": "particles:validKind" },
|
|
66
68
|
"supersedes": { "@id": "particles:supersedes", "@type": "@id" },
|
|
67
69
|
"subjectIds": { "@id": "particles:subject", "@type": "@id", "@container": "@set" },
|
|
68
70
|
"subjects": { "@id": "particles:subjects", "@container": "@list" },
|
|
@@ -85,6 +85,8 @@
|
|
|
85
85
|
},
|
|
86
86
|
"uncertaintyKind": { "type": "string" },
|
|
87
87
|
"validUntil": { "type": "string", "format": "date-time" },
|
|
88
|
+
"validFrom": { "type": "string", "format": "date-time" },
|
|
89
|
+
"validKind": { "type": "string", "enum": ["EVENT", "STATE"] },
|
|
88
90
|
"supersedes": { "type": "string" },
|
|
89
91
|
"basis": {
|
|
90
92
|
"type": "object",
|
{linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/artifacts/schemas/particle.schema.json
RENAMED
|
@@ -100,6 +100,16 @@
|
|
|
100
100
|
"format": "date-time",
|
|
101
101
|
"description": "Core: expiry for time-bounded claims (lazy query-time filter, §9.3)"
|
|
102
102
|
},
|
|
103
|
+
"valid_from": {
|
|
104
|
+
"type": ["string", "null"],
|
|
105
|
+
"format": "date-time",
|
|
106
|
+
"description": "Core: when the claim begins to hold in the world, the counterpart of valid_until; read by the window route (§9.3), never by reconciliation"
|
|
107
|
+
},
|
|
108
|
+
"valid_kind": {
|
|
109
|
+
"type": ["string", "null"],
|
|
110
|
+
"enum": ["EVENT", "STATE", null],
|
|
111
|
+
"description": "Core: how the world-time pair is read; EVENT is a moment (the point [valid_from, valid_from], never with a valid_until), STATE a span"
|
|
112
|
+
},
|
|
103
113
|
"supersedes": {
|
|
104
114
|
"type": ["string", "null"],
|
|
105
115
|
"format": "uuid",
|
|
@@ -112,6 +112,25 @@ particles:ParticleShape
|
|
|
112
112
|
sh:message "assertion_modality, when present, must be FALSIFIABLE, EVALUATIVE, EXPERIENTIAL, or CONSTITUTIVE." ;
|
|
113
113
|
] ;
|
|
114
114
|
|
|
115
|
+
# validKind — optional reading of the world-time pair: EVENT is
|
|
116
|
+
# a moment, STATE a span. An EVENT never carries a validUntil — a
|
|
117
|
+
# cardinality across two properties the shape cannot express without a
|
|
118
|
+
# SPARQL constraint, so the Core model validator enforces it.
|
|
119
|
+
sh:property [
|
|
120
|
+
sh:path particles:validKind ;
|
|
121
|
+
sh:maxCount 1 ;
|
|
122
|
+
sh:datatype xsd:string ;
|
|
123
|
+
sh:in ( "EVENT" "STATE" ) ;
|
|
124
|
+
sh:message "valid_kind, when present, must be EVENT or STATE." ;
|
|
125
|
+
] ;
|
|
126
|
+
|
|
127
|
+
sh:property [
|
|
128
|
+
sh:path particles:validFrom ;
|
|
129
|
+
sh:maxCount 1 ;
|
|
130
|
+
sh:datatype xsd:dateTime ;
|
|
131
|
+
sh:message "valid_from, when present, must be a single xsd:dateTime." ;
|
|
132
|
+
] ;
|
|
133
|
+
|
|
115
134
|
# canonicalForm — optional marker of which of the prose/structured pair is
|
|
116
135
|
# the assertion; PROSE default. STRUCTURED additionally requires
|
|
117
136
|
# a structuredClaim to be present — a cardinality the shape cannot express
|
|
@@ -409,7 +409,9 @@ class ProviderSelection(BaseModel):
|
|
|
409
409
|
"""
|
|
410
410
|
|
|
411
411
|
provider: str = "anthropic"
|
|
412
|
-
|
|
412
|
+
# The compiled default since 1.189.0, when it moved from claude-sonnet-4-6
|
|
413
|
+
# behind measurements registered before the runs.
|
|
414
|
+
model: str = "claude-sonnet-5-5"
|
|
413
415
|
|
|
414
416
|
|
|
415
417
|
class OpenAICompatProviderConfig(BaseModel):
|
|
@@ -572,6 +574,27 @@ _LIST_PRICES_PER_MTOK: dict[str, tuple[float, float]] = {
|
|
|
572
574
|
}
|
|
573
575
|
|
|
574
576
|
|
|
577
|
+
# Measured estimate factors that ship for the compiled default and the model it
|
|
578
|
+
# replaced, keyed like ``llm.price_per_mtok``. Characters per input
|
|
579
|
+
# token follow the shipped convention: the old tokenizer's 4.0 rule of thumb
|
|
580
|
+
# divided by the measured token ratio against claude-sonnet-4-6 (1.3437 on one
|
|
581
|
+
# run's byte-identical extraction prompts, token-counting endpoint, 2026-10-13).
|
|
582
|
+
# The output scale is relative to claude-sonnet-5, which the audit's per-call
|
|
583
|
+
# figures were fitted on: claude-sonnet-5-5 wrote 59,760 output tokens on the
|
|
584
|
+
# 2026-10 provider survey's 18 calls against claude-sonnet-5's 111,950 on the same
|
|
585
|
+
# calls (0.534). The extraction figure is the memory benchmark's 6,700 scaled the
|
|
586
|
+
# same way. The claude-sonnet-4-6 entries come from paired run
|
|
587
|
+
# (docs/benchmarks/default-model-adr0317-2026-10-13.md).
|
|
588
|
+
_SHIPPED_CHARS_PER_TOKEN: dict[str, float] = {"claude-sonnet-5-5": 2.98}
|
|
589
|
+
_SHIPPED_OUTPUT_SCALE: dict[str, float] = {
|
|
590
|
+
"claude-sonnet-5-5": 0.534,
|
|
591
|
+
"claude-sonnet-4-6": 0.800,
|
|
592
|
+
}
|
|
593
|
+
_SHIPPED_EXTRACTION_OUTPUT_TOKENS: dict[str, int] = {
|
|
594
|
+
"claude-sonnet-5-5": 3_578,
|
|
595
|
+
"claude-sonnet-4-6": 5_363,
|
|
596
|
+
}
|
|
597
|
+
|
|
575
598
|
_T = TypeVar("_T")
|
|
576
599
|
|
|
577
600
|
|
|
@@ -591,6 +614,23 @@ def lookup_by_model(
|
|
|
591
614
|
return None, None
|
|
592
615
|
|
|
593
616
|
|
|
617
|
+
#: Every completion purpose, in the order the operator-facing lines print them.
|
|
618
|
+
#: A literal here because config cannot import ``particles.llm``;
|
|
619
|
+
#: tests/test_config.py pins it equal to ``particles.llm.LLMPurpose``.
|
|
620
|
+
LLM_PURPOSES: tuple[str, ...] = (
|
|
621
|
+
"extraction",
|
|
622
|
+
"semantic_lint",
|
|
623
|
+
"verification",
|
|
624
|
+
"subject_resolution",
|
|
625
|
+
"query_response",
|
|
626
|
+
"synthesis",
|
|
627
|
+
"abstraction",
|
|
628
|
+
"benchmark",
|
|
629
|
+
"benchmark_answer",
|
|
630
|
+
"use_judge",
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
|
|
594
634
|
def _default_prices() -> dict[str, TokenPrice]:
|
|
595
635
|
return {
|
|
596
636
|
model: TokenPrice(input=inp, output=out)
|
|
@@ -603,9 +643,11 @@ class LLMConfig(BaseModel):
|
|
|
603
643
|
|
|
604
644
|
``default`` is the fallback pairing; each purpose may override it. The
|
|
605
645
|
operator can thus route high-volume ``extraction`` to a cheap model while
|
|
606
|
-
keeping low-volume ``synthesis`` on a hosted one.
|
|
607
|
-
``claude-sonnet-
|
|
608
|
-
before
|
|
646
|
+
keeping low-volume ``synthesis`` on a hosted one. Every purpose falls back
|
|
647
|
+
to the compiled default, ``claude-sonnet-5-5`` since 1.189.0 (
|
|
648
|
+
``claude-sonnet-4-6`` before), except ``use_judge``, which carries its own
|
|
649
|
+
compiled selection. ``particles config validate`` names the
|
|
650
|
+
default in force and where it came from.
|
|
609
651
|
|
|
610
652
|
The legacy ``extraction.model`` / ``wiki.model`` keys are migrated into
|
|
611
653
|
this section by ``_migrate_legacy_keys`` (``extraction.model`` →
|
|
@@ -712,6 +754,30 @@ class LLMConfig(BaseModel):
|
|
|
712
754
|
override = getattr(self, purpose, None)
|
|
713
755
|
return override if isinstance(override, ProviderSelection) else self.default
|
|
714
756
|
|
|
757
|
+
def selection_source(self, purpose: str) -> str:
|
|
758
|
+
"""Where ``purpose``'s selection comes from, as an operator reads it.
|
|
759
|
+
|
|
760
|
+
``"llm.<purpose>"`` when the configuration sets that purpose,
|
|
761
|
+
``"compiled llm.<purpose>"`` for a purpose with its own compiled
|
|
762
|
+
selection that the configuration leaves alone (``use_judge``),
|
|
763
|
+
``"llm.default"`` when the purpose falls back to a configured default,
|
|
764
|
+
and ``"compiled default"`` when nothing set it. ``"default"`` itself
|
|
765
|
+
reads as either of the last two.
|
|
766
|
+
"""
|
|
767
|
+
if purpose != "default" and getattr(self, purpose, None) is not None:
|
|
768
|
+
if purpose in self.model_fields_set:
|
|
769
|
+
return f"llm.{purpose}"
|
|
770
|
+
return f"compiled llm.{purpose}"
|
|
771
|
+
return "llm.default" if "default" in self.model_fields_set else "compiled default"
|
|
772
|
+
|
|
773
|
+
def routed_elsewhere(self) -> dict[str, ProviderSelection]:
|
|
774
|
+
"""The purposes whose selection differs from ``default``, in purpose order."""
|
|
775
|
+
return {
|
|
776
|
+
purpose: sel
|
|
777
|
+
for purpose in LLM_PURPOSES
|
|
778
|
+
if (sel := self.for_purpose(purpose)) != self.default
|
|
779
|
+
}
|
|
780
|
+
|
|
715
781
|
@model_validator(mode="after")
|
|
716
782
|
def _validate_provider_wiring(self) -> LLMConfig:
|
|
717
783
|
"""Fail dangling provider names / adapter kinds at config load.
|
|
@@ -976,6 +1042,16 @@ class ModalityRegenerationConfig(BaseModel):
|
|
|
976
1042
|
commit_interval: int = Field(default=25, ge=1)
|
|
977
1043
|
|
|
978
1044
|
|
|
1045
|
+
class ValidityBackfillConfig(BaseModel):
|
|
1046
|
+
"""Defaults for ``particles validity``, the prose-date default for ``valid_from``.
|
|
1047
|
+
|
|
1048
|
+
The pass makes no model call, so it has no rate limit; ``commit_interval``
|
|
1049
|
+
is how often it commits, so an interrupt costs seconds of work.
|
|
1050
|
+
"""
|
|
1051
|
+
|
|
1052
|
+
commit_interval: int = Field(default=200, ge=1)
|
|
1053
|
+
|
|
1054
|
+
|
|
979
1055
|
class ExtractionPolarityConfig(BaseModel):
|
|
980
1056
|
"""LLM-semantic claim-polarity classification of candidates (cap. 1).
|
|
981
1057
|
|
|
@@ -1777,6 +1853,10 @@ class SubjectsConfig(BaseModel):
|
|
|
1777
1853
|
# claude-sonnet-4-6; on an ordinary-prose gold set, 0.898 to 0.918 against
|
|
1778
1854
|
# 0.735, 45 of 49 names judged at about US$0.20 per 100 names, no correct
|
|
1779
1855
|
# link lost on either (docs/benchmarks/subject-resolution-judge-2026-10-01.md).
|
|
1856
|
+
# Re-measured 2026-10-13 on claude-sonnet-5-5, the compiled default since
|
|
1857
|
+
# 1.189.0, at 7 hits: 1.000 on the suite and 0.939 on the ordinary-prose
|
|
1858
|
+
# set, no correct link lost, at about US$0.09 and US$0.20 per 100 names
|
|
1859
|
+
# (docs/benchmarks/default-model-adr0317-2026-10-13.md).
|
|
1780
1860
|
# With no LLM key, an open breaker, or an unusable reply it takes the top
|
|
1781
1861
|
# hit, so `top_hit` is also what an offline store gets. Set `top_hit` to
|
|
1782
1862
|
# resolve with no model call at all.
|
|
@@ -3061,7 +3141,12 @@ class AuditConfig(BaseModel):
|
|
|
3061
3141
|
# measured ~3,600 output tokens per memory-note call on claude-haiku-4-5
|
|
3062
3142
|
# against ~6,700 on claude-sonnet-5, so routing ``llm.extraction`` to haiku
|
|
3063
3143
|
# warrants an entry of about 0.55. A model with no entry is scaled by 1.
|
|
3064
|
-
|
|
3144
|
+
# Ships with measured entries for the compiled default and the model it
|
|
3145
|
+
# replaced (``_SHIPPED_OUTPUT_SCALE``); operator entries merge
|
|
3146
|
+
# over them key by key.
|
|
3147
|
+
estimate_output_scale_by_model: dict[str, float] = Field(
|
|
3148
|
+
default_factory=lambda: dict(_SHIPPED_OUTPUT_SCALE)
|
|
3149
|
+
)
|
|
3065
3150
|
# Each call's output is taken to fall anywhere within this fraction of its
|
|
3066
3151
|
# expected figure. The expected range runs from every call at (1 - spread)
|
|
3067
3152
|
# to every call at (1 + spread), and a call whose output would pass
|
|
@@ -3108,6 +3193,14 @@ class AuditConfig(BaseModel):
|
|
|
3108
3193
|
# Wall time per second reading: the measured runs read 22 flags in ~41 s.
|
|
3109
3194
|
estimate_seconds_per_verification: float = Field(default=2.0, ge=0.0)
|
|
3110
3195
|
|
|
3196
|
+
@field_validator("estimate_output_scale_by_model", mode="before")
|
|
3197
|
+
@classmethod
|
|
3198
|
+
def _merge_over_shipped_scales(cls, value: Any) -> Any:
|
|
3199
|
+
"""Operator entries replace the shipped ones key by key; the rest stay."""
|
|
3200
|
+
if isinstance(value, dict):
|
|
3201
|
+
return {**_SHIPPED_OUTPUT_SCALE, **value}
|
|
3202
|
+
return value
|
|
3203
|
+
|
|
3111
3204
|
@field_validator("estimate_output_scale_by_model")
|
|
3112
3205
|
@classmethod
|
|
3113
3206
|
def _non_negative_output_scale(cls, value: dict[str, float]) -> dict[str, float]:
|
|
@@ -3524,8 +3617,10 @@ class MemoryBenchmarkConfig(BaseModel):
|
|
|
3524
3617
|
# on claude-sonnet-5 but ~3.6k on claude-haiku-4-5 — so an arm routing
|
|
3525
3618
|
# ``llm.extraction`` elsewhere is mis-estimated ~2x on the write side
|
|
3526
3619
|
# without an entry here. The rendered estimate says which source it used.
|
|
3620
|
+
# Ships with measured entries for the compiled default and the model it
|
|
3621
|
+
# replaced; operator entries merge over them key by key.
|
|
3527
3622
|
estimate_output_tokens_per_extraction_call_by_model: dict[str, int] = Field(
|
|
3528
|
-
default_factory=dict
|
|
3623
|
+
default_factory=lambda: dict(_SHIPPED_EXTRACTION_OUTPUT_TOKENS)
|
|
3529
3624
|
)
|
|
3530
3625
|
# Characters per input token — the factor the estimate and the pre-flight
|
|
3531
3626
|
# context-window check divide prompt bytes by. The scalar is the classic
|
|
@@ -3536,8 +3631,30 @@ class MemoryBenchmarkConfig(BaseModel):
|
|
|
3536
3631
|
# lookup as ``llm.price_per_mtok`` — is what keeps their input projection and
|
|
3537
3632
|
# their window verdict honest. The write side is keyed on the extraction
|
|
3538
3633
|
# model, the answer side and the window check on the answer model.
|
|
3634
|
+
# The map ships one entry, for the compiled default, and the
|
|
3635
|
+
# scalar stays the old tokenizer's 4.0, so a model with no entry (a local
|
|
3636
|
+
# or OpenAI-compatible one included) keeps the factor it always had.
|
|
3637
|
+
# Operator entries merge over the shipped one key by key.
|
|
3539
3638
|
chars_per_token: float = Field(default=4.0, gt=0.0)
|
|
3540
|
-
chars_per_token_by_model: dict[str, float] = Field(
|
|
3639
|
+
chars_per_token_by_model: dict[str, float] = Field(
|
|
3640
|
+
default_factory=lambda: dict(_SHIPPED_CHARS_PER_TOKEN)
|
|
3641
|
+
)
|
|
3642
|
+
|
|
3643
|
+
@field_validator("estimate_output_tokens_per_extraction_call_by_model", mode="before")
|
|
3644
|
+
@classmethod
|
|
3645
|
+
def _merge_over_shipped_output_tokens(cls, value: Any) -> Any:
|
|
3646
|
+
"""Operator entries replace the shipped ones key by key; the rest stay."""
|
|
3647
|
+
if isinstance(value, dict):
|
|
3648
|
+
return {**_SHIPPED_EXTRACTION_OUTPUT_TOKENS, **value}
|
|
3649
|
+
return value
|
|
3650
|
+
|
|
3651
|
+
@field_validator("chars_per_token_by_model", mode="before")
|
|
3652
|
+
@classmethod
|
|
3653
|
+
def _merge_over_shipped_chars_per_token(cls, value: Any) -> Any:
|
|
3654
|
+
"""Operator entries replace the shipped ones key by key; the rest stay."""
|
|
3655
|
+
if isinstance(value, dict):
|
|
3656
|
+
return {**_SHIPPED_CHARS_PER_TOKEN, **value}
|
|
3657
|
+
return value
|
|
3541
3658
|
|
|
3542
3659
|
@field_validator("estimate_output_tokens_per_extraction_call_by_model")
|
|
3543
3660
|
@classmethod
|
|
@@ -3735,6 +3852,31 @@ class LeakageBenchmarkConfig(BaseModel):
|
|
|
3735
3852
|
confirm_call_threshold: int = Field(default=50, ge=0)
|
|
3736
3853
|
|
|
3737
3854
|
|
|
3855
|
+
class UpdateGateBenchmarkConfig(BaseModel):
|
|
3856
|
+
"""The trip-versus-move case and the update-gate pair sets.
|
|
3857
|
+
|
|
3858
|
+
Run counts and safety margins only. The pipeline under test runs the
|
|
3859
|
+
compiled defaults with every purpose pinned to the chosen model: nothing
|
|
3860
|
+
here re-tunes extraction, reconciliation or consolidation. There is no
|
|
3861
|
+
confirm threshold: every live run asks before its first call, because
|
|
3862
|
+
neither suite has a free live path.
|
|
3863
|
+
"""
|
|
3864
|
+
|
|
3865
|
+
# The record's protocol (item 5): the bar is stated only when a
|
|
3866
|
+
# run uses these counts.
|
|
3867
|
+
move_runs: int = Field(default=3, ge=0)
|
|
3868
|
+
trip_alone_runs: int = Field(default=2, ge=0)
|
|
3869
|
+
# Samples per pair in the update-gate replay; the sets were registered at 3.
|
|
3870
|
+
samples: int = Field(default=3, ge=1)
|
|
3871
|
+
# The per-run ceiling --max-usd defaults to, as a multiple of a measured
|
|
3872
|
+
# estimate (a profile or the 2026-10-12 record). An upper-bound estimate is
|
|
3873
|
+
# already a ceiling and is used as is.
|
|
3874
|
+
max_usd_multiplier: float = Field(default=4.0, ge=1.0)
|
|
3875
|
+
# How long one run's child may take before it is stopped and reported
|
|
3876
|
+
# incomplete. A live run took a few minutes on 2026-10-12.
|
|
3877
|
+
run_timeout_seconds: float = Field(default=1800.0, gt=0.0)
|
|
3878
|
+
|
|
3879
|
+
|
|
3738
3880
|
class BenchmarkConfig(BaseModel):
|
|
3739
3881
|
"""Benchmark-harness run persistence (family).
|
|
3740
3882
|
|
|
@@ -3903,6 +4045,7 @@ class ParticlesConfig(BaseModel):
|
|
|
3903
4045
|
extraction_stance: ExtractionStanceConfig = Field(default_factory=ExtractionStanceConfig)
|
|
3904
4046
|
extraction_polarity: ExtractionPolarityConfig = Field(default_factory=ExtractionPolarityConfig)
|
|
3905
4047
|
extraction_validity: ExtractionValidityConfig = Field(default_factory=ExtractionValidityConfig)
|
|
4048
|
+
validity_backfill: ValidityBackfillConfig = Field(default_factory=ValidityBackfillConfig)
|
|
3906
4049
|
extraction_vision: ExtractionVisionConfig = Field(default_factory=ExtractionVisionConfig)
|
|
3907
4050
|
structured_claim: StructuredClaimConfig = Field(default_factory=StructuredClaimConfig)
|
|
3908
4051
|
rdf: RdfConfig = Field(default_factory=RdfConfig)
|
|
@@ -3956,6 +4099,9 @@ class ParticlesConfig(BaseModel):
|
|
|
3956
4099
|
default_factory=RelevanceFloorBenchmarkConfig
|
|
3957
4100
|
)
|
|
3958
4101
|
benchmark_leakage: LeakageBenchmarkConfig = Field(default_factory=LeakageBenchmarkConfig)
|
|
4102
|
+
benchmark_update_gate: UpdateGateBenchmarkConfig = Field(
|
|
4103
|
+
default_factory=UpdateGateBenchmarkConfig
|
|
4104
|
+
)
|
|
3959
4105
|
benchmark: BenchmarkConfig = Field(default_factory=BenchmarkConfig)
|
|
3960
4106
|
refetch_floors: dict[str, int] = Field(default_factory=lambda: dict(_DEFAULT_REFETCH_FLOORS))
|
|
3961
4107
|
local_refresh: LocalRefreshConfig = Field(default_factory=LocalRefreshConfig)
|
|
@@ -4130,6 +4276,15 @@ _ENV_OVERRIDES: list[tuple[str, str, str]] = [
|
|
|
4130
4276
|
]
|
|
4131
4277
|
|
|
4132
4278
|
|
|
4279
|
+
def env_override_names() -> frozenset[str]:
|
|
4280
|
+
"""Every environment variable that overrides a config field.
|
|
4281
|
+
|
|
4282
|
+
A benchmark that runs the SDK in a child process with a private environment
|
|
4283
|
+
removes these, so no override of the operator's reaches the run.
|
|
4284
|
+
"""
|
|
4285
|
+
return frozenset(name for name, _section, _field in _ENV_OVERRIDES)
|
|
4286
|
+
|
|
4287
|
+
|
|
4133
4288
|
# ---------------------------------------------------------------------------
|
|
4134
4289
|
# Loader
|
|
4135
4290
|
# ---------------------------------------------------------------------------
|
{linkedparticles_core-1.187.2 → linkedparticles_core-1.190.0}/particles/conformance/contract.py
RENAMED
|
@@ -103,6 +103,16 @@ CONTRACT: list[FieldContract] = [
|
|
|
103
103
|
),
|
|
104
104
|
FieldContract("uncertainty_kind", FieldTier.OPTIONAL, "Extension A free-text label"),
|
|
105
105
|
FieldContract("valid_until", FieldTier.OPTIONAL, "Time-bounded claims only"),
|
|
106
|
+
FieldContract(
|
|
107
|
+
"valid_from",
|
|
108
|
+
FieldTier.OPTIONAL,
|
|
109
|
+
"Claims with a stated world-time start; the window route's input",
|
|
110
|
+
),
|
|
111
|
+
FieldContract(
|
|
112
|
+
"valid_kind",
|
|
113
|
+
FieldTier.OPTIONAL,
|
|
114
|
+
"EVENT (a moment) or STATE (a span); how valid_from and valid_until are read",
|
|
115
|
+
),
|
|
106
116
|
FieldContract("supersedes", FieldTier.OPTIONAL, "Set by reindex, not by extractors"),
|
|
107
117
|
FieldContract(
|
|
108
118
|
"tags",
|
|
@@ -112,6 +112,19 @@ class AssertionModality(StrEnum):
|
|
|
112
112
|
CONSTITUTIVE = "CONSTITUTIVE" # a rule a document establishes ("a Particle MUST …")
|
|
113
113
|
|
|
114
114
|
|
|
115
|
+
class ValidKind(StrEnum):
|
|
116
|
+
"""How a claim's world-time interval is read.
|
|
117
|
+
|
|
118
|
+
An ``EVENT`` is a moment: its interval is the point ``[valid_from,
|
|
119
|
+
valid_from]``, and it never carries a ``valid_until``. A ``STATE`` is a
|
|
120
|
+
span from ``valid_from`` until it closes (its own ``valid_until``, or for a
|
|
121
|
+
retired claim the close rule), either end open.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
EVENT = "EVENT"
|
|
125
|
+
STATE = "STATE"
|
|
126
|
+
|
|
127
|
+
|
|
115
128
|
class ParticleType(StrEnum):
|
|
116
129
|
CLAIM = "CLAIM"
|
|
117
130
|
REVIEW = "REVIEW" # human review annotation records
|
|
@@ -596,6 +609,14 @@ class Particle(BaseModel):
|
|
|
596
609
|
# (revision chain). Kept in declaration order for serialization
|
|
597
610
|
# stability.
|
|
598
611
|
valid_until: datetime | None = None
|
|
612
|
+
# Core (§6.2): the world-time axis beside the assertion-time
|
|
613
|
+
# one. ``valid_from`` is when the claim begins to hold; ``valid_kind``
|
|
614
|
+
# says whether it is a moment (EVENT) or a span (STATE). Read-time
|
|
615
|
+
# material for the window route and nothing else: never an input to
|
|
616
|
+
# reconciliation, ranking, or confidence. How a value was set rides on
|
|
617
|
+
# ``properties`` (``extraction:valid_from_basis`` and its siblings).
|
|
618
|
+
valid_from: datetime | None = None
|
|
619
|
+
valid_kind: ValidKind | None = None
|
|
599
620
|
supersedes: str | None = None
|
|
600
621
|
# Extension A field — stored but not processed by Core logic
|
|
601
622
|
basis: dict[str, Any] | None = None
|
|
@@ -667,6 +688,28 @@ class Particle(BaseModel):
|
|
|
667
688
|
raise ValueError("canonical_form=STRUCTURED requires a structured_claim")
|
|
668
689
|
return self
|
|
669
690
|
|
|
691
|
+
@model_validator(mode="after")
|
|
692
|
+
def _check_validity_interval(self) -> Particle:
|
|
693
|
+
"""The world-time interval is well-formed.
|
|
694
|
+
|
|
695
|
+
A start after the end is no interval, and a moment has one end, so an
|
|
696
|
+
EVENT never carries a ``valid_until``.
|
|
697
|
+
"""
|
|
698
|
+
if self.valid_from is not None and self.valid_until is not None:
|
|
699
|
+
start = (
|
|
700
|
+
self.valid_from if self.valid_from.tzinfo else self.valid_from.replace(tzinfo=UTC)
|
|
701
|
+
)
|
|
702
|
+
end = (
|
|
703
|
+
self.valid_until
|
|
704
|
+
if self.valid_until.tzinfo
|
|
705
|
+
else self.valid_until.replace(tzinfo=UTC)
|
|
706
|
+
)
|
|
707
|
+
if start > end:
|
|
708
|
+
raise ValueError("valid_from must not be after valid_until")
|
|
709
|
+
if self.valid_kind is ValidKind.EVENT and self.valid_until is not None:
|
|
710
|
+
raise ValueError("an EVENT is a moment and carries no valid_until")
|
|
711
|
+
return self
|
|
712
|
+
|
|
670
713
|
|
|
671
714
|
def is_truth_apt(particle: Particle) -> bool:
|
|
672
715
|
"""Whether the engine should apply truth-semantics to this particle.
|
|
@@ -831,8 +874,9 @@ class ExtractorCalibration(BaseModel):
|
|
|
831
874
|
pipeline applies the record only when the current extraction
|
|
832
875
|
provider/model matches; on mismatch the particle falls back to
|
|
833
876
|
``calibration_source=EXTRACTOR_DIRECT``. ``None`` is a legacy record
|
|
834
|
-
(fitted before this key existed); it is treated as
|
|
835
|
-
|
|
877
|
+
(fitted before this key existed); it is treated as
|
|
878
|
+
``anthropic:claude-sonnet-4-6``, the compiled default before 1.189.0
|
|
879
|
+
and the model those records were fitted on.
|
|
836
880
|
heldout_suite_id: Benchmark suite(s) whose recorded runs the fit was
|
|
837
881
|
scored on out of sample, ``+``-joined like
|
|
838
882
|
``benchmark_suite_id``. ``None`` on a record persisted before the
|
|
@@ -1178,6 +1222,37 @@ class StructuralGroupBy(StrEnum):
|
|
|
1178
1222
|
OBJECT = "object"
|
|
1179
1223
|
|
|
1180
1224
|
|
|
1225
|
+
class TimeWindow(BaseModel):
|
|
1226
|
+
"""An interval of world time a query asks about.
|
|
1227
|
+
|
|
1228
|
+
Either end may be open; a window with both ends equal is a point, the
|
|
1229
|
+
``--on`` form. Timezone-naive values are read as UTC, the store's
|
|
1230
|
+
convention.
|
|
1231
|
+
"""
|
|
1232
|
+
|
|
1233
|
+
start: datetime | None = None
|
|
1234
|
+
end: datetime | None = None
|
|
1235
|
+
|
|
1236
|
+
@model_validator(mode="after")
|
|
1237
|
+
def _check_bounds(self) -> TimeWindow:
|
|
1238
|
+
if self.start is None and self.end is None:
|
|
1239
|
+
raise ValueError("a time window needs a start or an end")
|
|
1240
|
+
# Naive values are read as UTC, the store's convention (the as_of
|
|
1241
|
+
# validator does the same), so the two ends and the claims compare.
|
|
1242
|
+
if self.start is not None and self.start.tzinfo is None:
|
|
1243
|
+
self.start = self.start.replace(tzinfo=UTC)
|
|
1244
|
+
if self.end is not None and self.end.tzinfo is None:
|
|
1245
|
+
self.end = self.end.replace(tzinfo=UTC)
|
|
1246
|
+
if self.start is not None and self.end is not None and self.start > self.end:
|
|
1247
|
+
raise ValueError("a time window's start must not be after its end")
|
|
1248
|
+
return self
|
|
1249
|
+
|
|
1250
|
+
@property
|
|
1251
|
+
def is_point(self) -> bool:
|
|
1252
|
+
"""True for the ``--on`` form: both ends set and equal."""
|
|
1253
|
+
return self.start is not None and self.end is not None and self.start == self.end
|
|
1254
|
+
|
|
1255
|
+
|
|
1181
1256
|
class QueryRequest(BaseModel):
|
|
1182
1257
|
# Bounded so an oversized question can't drive an arbitrarily large prompt
|
|
1183
1258
|
# into the paid query-response completion (security review F6). 8192 chars is
|
|
@@ -1234,6 +1309,14 @@ class QueryRequest(BaseModel):
|
|
|
1234
1309
|
# is rejected by the validator below (HTTP 422; CLI/MCP surface the
|
|
1235
1310
|
# message).
|
|
1236
1311
|
as_of: datetime | None = None
|
|
1312
|
+
# the world-time window — select the claims that began in,
|
|
1313
|
+
# or were in force during, this interval of world time. Unset (None) is
|
|
1314
|
+
# byte-for-byte today's read. With a question it prefilters the candidate
|
|
1315
|
+
# set before scoring and ``top_k``; without one it selects the
|
|
1316
|
+
# deterministic listing ordered by ``valid_from``. Composes with
|
|
1317
|
+
# ``as_of`` (world time, then believed-at-T visibility). A window read
|
|
1318
|
+
# admits retired claims for the period they held.
|
|
1319
|
+
window: TimeWindow | None = None
|
|
1237
1320
|
# read through a project observer — only beliefs that are global
|
|
1238
1321
|
# or were observed in this project are candidates. ``None`` (the default) is
|
|
1239
1322
|
# the store-wide view, for which the read is byte-identical to before. The
|
|
@@ -1310,6 +1393,18 @@ class QueryRequest(BaseModel):
|
|
|
1310
1393
|
or self.list_vocabulary
|
|
1311
1394
|
or self.is_aggregate
|
|
1312
1395
|
or (self.question is None and self.has_claim_filters)
|
|
1396
|
+
or self.is_window_listing
|
|
1397
|
+
)
|
|
1398
|
+
|
|
1399
|
+
@property
|
|
1400
|
+
def is_window_listing(self) -> bool:
|
|
1401
|
+
"""True for the window listing: a window, no question, no claim filter
|
|
1402
|
+
or aggregate. Ordered by ``valid_from``, no LLM call."""
|
|
1403
|
+
return (
|
|
1404
|
+
self.window is not None
|
|
1405
|
+
and self.question is None
|
|
1406
|
+
and not self.has_claim_filters
|
|
1407
|
+
and not self.is_aggregate
|
|
1313
1408
|
)
|
|
1314
1409
|
|
|
1315
1410
|
@model_validator(mode="after")
|
|
@@ -1318,7 +1413,13 @@ class QueryRequest(BaseModel):
|
|
|
1318
1413
|
raise ValueError(
|
|
1319
1414
|
"a query needs a question, a structural claim filter "
|
|
1320
1415
|
"(predicate / object_*), an aggregate (count / group_by), "
|
|
1321
|
-
"list_predicates, or list_vocabulary"
|
|
1416
|
+
"a time window, list_predicates, or list_vocabulary "
|
|
1417
|
+
""
|
|
1418
|
+
)
|
|
1419
|
+
if self.window is not None and (self.list_predicates or self.list_vocabulary):
|
|
1420
|
+
raise ValueError(
|
|
1421
|
+
"a time window selects claims; it does not combine with the "
|
|
1422
|
+
"predicate or vocabulary listings"
|
|
1322
1423
|
)
|
|
1323
1424
|
if self.is_aggregate and self.question is not None:
|
|
1324
1425
|
raise ValueError(
|
|
@@ -1537,6 +1638,63 @@ class AsOfNote(BaseModel):
|
|
|
1537
1638
|
successor: AsOfSuccessor | None = None
|
|
1538
1639
|
|
|
1539
1640
|
|
|
1641
|
+
class WindowReading(StrEnum):
|
|
1642
|
+
"""Why a claim is in a world-time window.
|
|
1643
|
+
|
|
1644
|
+
``BEGAN``: its ``valid_from`` lies in the window, whatever its kind; what
|
|
1645
|
+
"what happened in the week" asks. ``IN_FORCE``: a STATE that started
|
|
1646
|
+
before the window and had not closed. ``HELD_AT``: a STATE whose start is
|
|
1647
|
+
unknown but which is known to hold at its anchor (basis ``as-of``), read as
|
|
1648
|
+
in force from there. ``WITHIN``: a claim anchored to a coarse unit (an
|
|
1649
|
+
EVENT somewhere in a month or a year, or a STATE spanning one) whose unit
|
|
1650
|
+
intersects the window.
|
|
1651
|
+
"""
|
|
1652
|
+
|
|
1653
|
+
BEGAN = "BEGAN"
|
|
1654
|
+
IN_FORCE = "IN_FORCE"
|
|
1655
|
+
HELD_AT = "HELD_AT"
|
|
1656
|
+
WITHIN = "WITHIN"
|
|
1657
|
+
|
|
1658
|
+
|
|
1659
|
+
class WindowHit(BaseModel):
|
|
1660
|
+
"""How one hit sits in the requested world-time window (§4).
|
|
1661
|
+
|
|
1662
|
+
A **response model, not particle substrate**: computed at read time,
|
|
1663
|
+
never stored. ``closed_at`` and ``close_basis`` say when a STATE's
|
|
1664
|
+
interval ended and which rule said so (its own ``valid_until``, its
|
|
1665
|
+
successor's ``valid_from``, or its retirement instant); both None for an
|
|
1666
|
+
open interval and for an EVENT. ``retired`` carries the note for
|
|
1667
|
+
a retired claim admitted for the period it held. ``restates`` names the
|
|
1668
|
+
retired original this hit stood in for.
|
|
1669
|
+
"""
|
|
1670
|
+
|
|
1671
|
+
reading: WindowReading
|
|
1672
|
+
valid_from: datetime
|
|
1673
|
+
# None for an unkinded claim, admitted under the ``BEGAN`` reading only.
|
|
1674
|
+
valid_kind: ValidKind | None = None
|
|
1675
|
+
closed_at: datetime | None = None
|
|
1676
|
+
close_basis: Literal["valid_until", "successor", "retired_at"] | None = None
|
|
1677
|
+
retired: AsOfNote | None = None
|
|
1678
|
+
restates: str | None = None
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
class WindowCoverage(BaseModel):
|
|
1682
|
+
"""What a window read could and could not judge.
|
|
1683
|
+
|
|
1684
|
+
Disclosure only. ``undated`` are candidates with no ``valid_from``;
|
|
1685
|
+
``unkinded`` carry a date but no kind and so match the ``BEGAN`` reading
|
|
1686
|
+
only; ``retired_admitted`` is how many retired claims the window let in;
|
|
1687
|
+
``restated`` how many of those yielded to a successor in the set.
|
|
1688
|
+
"""
|
|
1689
|
+
|
|
1690
|
+
candidates: int
|
|
1691
|
+
admitted: int
|
|
1692
|
+
undated: int
|
|
1693
|
+
unkinded: int
|
|
1694
|
+
retired_admitted: int
|
|
1695
|
+
restated: int
|
|
1696
|
+
|
|
1697
|
+
|
|
1540
1698
|
class RelevanceNote(BaseModel):
|
|
1541
1699
|
"""The question-level relevance disclosure for a semantic query.
|
|
1542
1700
|
|
|
@@ -1873,6 +2031,16 @@ class QueryResponse(BaseModel):
|
|
|
1873
2031
|
# reconstructible (rung 4). Born-retired rows are never counted. Always 0
|
|
1874
2032
|
# on a normal query.
|
|
1875
2033
|
as_of_excluded_undatable: int = 0
|
|
2034
|
+
# echo of the request's world-time window; None on a read with
|
|
2035
|
+
# no window.
|
|
2036
|
+
window: TimeWindow | None = None
|
|
2037
|
+
# per-result window readings, query-time only. Parallel to
|
|
2038
|
+
# ``particles`` (``window_hits[i]`` annotates ``particles[i]``). Empty
|
|
2039
|
+
# unless the request set ``window``.
|
|
2040
|
+
window_hits: list[WindowHit | None] = Field(default_factory=list)
|
|
2041
|
+
# what the window could and could not judge. None on a read
|
|
2042
|
+
# with no window. Disclosure only.
|
|
2043
|
+
window_coverage: WindowCoverage | None = None
|
|
1876
2044
|
# set when the request named an ``observer_project``; None on a
|
|
1877
2045
|
# store-wide read. Disclosure only.
|
|
1878
2046
|
observer_scope: ObserverScopeNote | None = None
|