linkedparticles-core 1.192.2__tar.gz → 1.192.10__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.
Files changed (223) hide show
  1. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/PKG-INFO +8 -8
  2. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/constraints.txt +8 -8
  3. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/config.py +18 -3
  4. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/contradiction_disclosure.py +1 -2
  5. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/held_release.py +3 -3
  6. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/agent.py +51 -9
  7. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/general.py +2 -2
  8. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/mcp_memory.py +2 -2
  9. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/subject_scope.py +2 -2
  10. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/render/markdown.py +2 -2
  11. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/pyproject.toml +47 -16
  12. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_extraction_agent.py +41 -0
  13. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/LICENSE +0 -0
  14. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/NOTICE +0 -0
  15. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/README.md +0 -0
  16. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/conformance/README.md +0 -0
  17. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/conformance/profile.yaml +0 -0
  18. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/conformance/similarity_vectors.json +0 -0
  19. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/schemas/context.jsonld +0 -0
  20. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/schemas/interchange.schema.json +0 -0
  21. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/schemas/particle.schema.json +0 -0
  22. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/schemas/shacl/CorpusSnapshotShape.ttl +0 -0
  23. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/schemas/shacl/ParticleShape.ttl +0 -0
  24. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/schemas/shacl/ProvenanceChainShape.ttl +0 -0
  25. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/schemas/shacl/SubjectShape.ttl +0 -0
  26. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/schemas/shacl/TrustStatementShape.ttl +0 -0
  27. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/artifacts/schemas/trust_lens.schema.json +0 -0
  28. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/__init__.py +0 -0
  29. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/conformance/__init__.py +0 -0
  30. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/conformance/_resources.py +0 -0
  31. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/conformance/contract.py +0 -0
  32. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/conformance/fixtures.py +0 -0
  33. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/conformance/jsonschema.py +0 -0
  34. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/conformance/profile.py +0 -0
  35. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/conformance/runner.py +0 -0
  36. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/conformance/shacl.py +0 -0
  37. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/conformance/types.py +0 -0
  38. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/conformance/validator.py +0 -0
  39. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/__init__.py +0 -0
  40. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/_resources.py +0 -0
  41. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/cascade_gate.py +0 -0
  42. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/claims.py +0 -0
  43. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/closure_measure.py +0 -0
  44. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/conflict_resolution.py +0 -0
  45. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/conflict_review.py +0 -0
  46. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/consolidation_cadence.py +0 -0
  47. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/duplicate_key.py +0 -0
  48. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/equivalence.py +0 -0
  49. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/fingerprint.py +0 -0
  50. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/generics.py +0 -0
  51. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/granularity.py +0 -0
  52. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/jsonld_context.py +0 -0
  53. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/ladders.py +0 -0
  54. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/modality.py +0 -0
  55. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/observer_scope.py +0 -0
  56. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/past_value.py +0 -0
  57. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/predicate_profile.py +0 -0
  58. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/probe_verdict.py +0 -0
  59. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/progress.py +0 -0
  60. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/provenance.py +0 -0
  61. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/reanchor.py +0 -0
  62. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/rung_ladder.py +0 -0
  63. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/schema.py +0 -0
  64. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/scoring/__init__.py +0 -0
  65. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/scoring/confidence.py +0 -0
  66. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/scoring/decay.py +0 -0
  67. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/scoring/relevance.py +0 -0
  68. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/scoring/utility.py +0 -0
  69. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/spend_budget.py +0 -0
  70. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/stance.py +0 -0
  71. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/status.py +0 -0
  72. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/validity.py +0 -0
  73. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/vocabulary.py +0 -0
  74. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/vocabulary_jsonld.py +0 -0
  75. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/core/vocabulary_report.py +0 -0
  76. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/egress.py +0 -0
  77. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/embeddings.py +0 -0
  78. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/__init__.py +0 -0
  79. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/append_delta.py +0 -0
  80. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/calibration.py +0 -0
  81. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/components.py +0 -0
  82. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/docstrings.py +0 -0
  83. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/github/__init__.py +0 -0
  84. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/github/_shared.py +0 -0
  85. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/github/gist.py +0 -0
  86. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/github/pages.py +0 -0
  87. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/github/repo.py +0 -0
  88. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/hackernews.py +0 -0
  89. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/incremental.py +0 -0
  90. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/journal.py +0 -0
  91. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/mastodon.py +0 -0
  92. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/migration_preview.py +0 -0
  93. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/modality.py +0 -0
  94. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/nomisma.py +0 -0
  95. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/numista/__init__.py +0 -0
  96. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/numista/_shared.py +0 -0
  97. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/numista/coin.py +0 -0
  98. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/numista/issuer.py +0 -0
  99. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/numista/listing.py +0 -0
  100. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/polarity.py +0 -0
  101. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/property_keys.py +0 -0
  102. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/rdf.py +0 -0
  103. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/reddit.py +0 -0
  104. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/registry.py +0 -0
  105. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/scope.py +0 -0
  106. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/session_state.py +0 -0
  107. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/structure.py +0 -0
  108. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/subject_gate.py +0 -0
  109. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/taxonomy.py +0 -0
  110. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/tool_turns.py +0 -0
  111. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/trust_lens.py +0 -0
  112. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/vocabulary.py +0 -0
  113. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/extraction/wikidata.py +0 -0
  114. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/http.py +0 -0
  115. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/interchange/__init__.py +0 -0
  116. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/interchange/codec.py +0 -0
  117. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/interchange/jsonl.py +0 -0
  118. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/interchange/yaml_ld.py +0 -0
  119. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/__init__.py +0 -0
  120. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/adapters/__init__.py +0 -0
  121. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/adapters/anthropic.py +0 -0
  122. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/adapters/local.py +0 -0
  123. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/adapters/openai_compat.py +0 -0
  124. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/batch_budget.py +0 -0
  125. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/breaker.py +0 -0
  126. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/client.py +0 -0
  127. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/errors.py +0 -0
  128. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/fencing.py +0 -0
  129. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/logprobs.py +0 -0
  130. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/pool.py +0 -0
  131. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/registry.py +0 -0
  132. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/replay.py +0 -0
  133. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/spend_budget.py +0 -0
  134. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/llm/usage.py +0 -0
  135. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/py.typed +0 -0
  136. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/render/__init__.py +0 -0
  137. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/secrets.py +0 -0
  138. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/url_canonical.py +0 -0
  139. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/particles/url_safety.py +0 -0
  140. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/__init__.py +0 -0
  141. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/_client_fixtures.py +0 -0
  142. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/_upstream.py +0 -0
  143. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/MANIFEST.yaml +0 -0
  144. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/hackernews-thread-001/content.bin +0 -0
  145. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/hackernews-thread-001/manifest.yaml +0 -0
  146. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/hackernews-thread-001/snapshot.json +0 -0
  147. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/journal-entry-001/content.bin +0 -0
  148. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/journal-entry-001/manifest.yaml +0 -0
  149. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/journal-entry-001/snapshot.json +0 -0
  150. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/mastodon-thread-001/content.bin +0 -0
  151. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/mastodon-thread-001/manifest.yaml +0 -0
  152. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/mastodon-thread-001/snapshot.json +0 -0
  153. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/mcp-memory-export-001/content.bin +0 -0
  154. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/mcp-memory-export-001/manifest.yaml +0 -0
  155. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/mcp-memory-export-001/snapshot.json +0 -0
  156. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/nomisma-concept-001/content.bin +0 -0
  157. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/nomisma-concept-001/manifest.yaml +0 -0
  158. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/nomisma-concept-001/snapshot.json +0 -0
  159. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/numista-coin-001/content.bin +0 -0
  160. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/numista-coin-001/manifest.yaml +0 -0
  161. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/numista-coin-001/snapshot.json +0 -0
  162. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/numista-issuer-001/content.bin +0 -0
  163. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/numista-issuer-001/manifest.yaml +0 -0
  164. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/numista-issuer-001/snapshot.json +0 -0
  165. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/numista-listing-001/content.bin +0 -0
  166. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/numista-listing-001/manifest.yaml +0 -0
  167. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/numista-listing-001/snapshot.json +0 -0
  168. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/rdf-graph-001/content.bin +0 -0
  169. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/rdf-graph-001/manifest.yaml +0 -0
  170. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/rdf-graph-001/snapshot.json +0 -0
  171. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/reddit-thread-001/content.bin +0 -0
  172. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/reddit-thread-001/manifest.yaml +0 -0
  173. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/reddit-thread-001/snapshot.json +0 -0
  174. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/taxonomy-coins-001/content.bin +0 -0
  175. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/taxonomy-coins-001/manifest.yaml +0 -0
  176. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/taxonomy-coins-001/snapshot.json +0 -0
  177. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/trust-lens-001/content.bin +0 -0
  178. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/trust-lens-001/manifest.yaml +0 -0
  179. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/trust-lens-001/snapshot.json +0 -0
  180. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-article-001/content.bin +0 -0
  181. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-article-001/manifest.yaml +0 -0
  182. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-article-001/snapshot.json +0 -0
  183. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-article-002/content.bin +0 -0
  184. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-article-002/manifest.yaml +0 -0
  185. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-article-002/snapshot.json +0 -0
  186. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-essay-001/content.bin +0 -0
  187. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-essay-001/manifest.yaml +0 -0
  188. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-essay-001/snapshot.json +0 -0
  189. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-interview-001/content.bin +0 -0
  190. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-interview-001/manifest.yaml +0 -0
  191. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/web-interview-001/snapshot.json +0 -0
  192. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/wikidata-entity-001/content.bin +0 -0
  193. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/wikidata-entity-001/manifest.yaml +0 -0
  194. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conformance/fixtures/wikidata-entity-001/snapshot.json +0 -0
  195. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/conftest.py +0 -0
  196. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/fixtures/scope/normative-rule-file.md +0 -0
  197. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/fixtures/scope/normative-rule-file.recorded.json +0 -0
  198. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/fixtures/scope/rule-file-agents-md.md +0 -0
  199. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/fixtures/scope/rule-file-agents-md.recorded.json +0 -0
  200. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_calibration_isotonic.py +0 -0
  201. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_confidence.py +0 -0
  202. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_config_client_sections.py +0 -0
  203. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_config_sample.py +0 -0
  204. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_conformance_fixture_gen.py +0 -0
  205. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_conformance_similarity_vectors.py +0 -0
  206. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_conformance_validator.py +0 -0
  207. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_core_contradiction_disclosure.py +0 -0
  208. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_core_held_release.py +0 -0
  209. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_core_observer_scope.py +0 -0
  210. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_core_provenance.py +0 -0
  211. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_core_vocabulary.py +0 -0
  212. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_egress_policy.py +0 -0
  213. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_embeddings.py +0 -0
  214. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_extraction_vision.py +0 -0
  215. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_interchange_schema.py +0 -0
  216. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_llm_batch_budget.py +0 -0
  217. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_llm_logprobs.py +0 -0
  218. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_llm_pool.py +0 -0
  219. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_llm_replay.py +0 -0
  220. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_llm_usage.py +0 -0
  221. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_schema.py +0 -0
  222. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/tests/test_secrets.py +0 -0
  223. {linkedparticles_core-1.192.2 → linkedparticles_core-1.192.10}/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.2
3
+ Version: 1.192.10
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.28
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,>=2.0
41
- Requires-Dist: pypdf>=6.15.0
42
- Requires-Dist: pyshacl<0.32,>=0.26
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>=2.7
47
- Requires-Dist: sqlalchemy[asyncio]<2.2,>=2.0
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>=4.30; extra == 'vision'
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.11.0
13
+ anthropic==1.13.0
14
14
  # via linkedparticles
15
15
  anyio==4.14.2 ; python_full_version < '3.15'
16
16
  # via
@@ -67,9 +67,9 @@ distro==1.9.0
67
67
  # via langsmith
68
68
  docstring-parser==0.18.0
69
69
  # via anthropic
70
- fastapi==0.142.2
70
+ fastapi==0.143.0
71
71
  # via linkedparticles
72
- filelock==4.0.12
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.7
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.13.5
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.46.5
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.19.0
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.3
359
+ sqlalchemy==2.1.4
360
360
  # via
361
361
  # alembic
362
362
  # linkedparticles
@@ -956,6 +956,12 @@ class ExtractionConfig(BaseModel):
956
956
  # The largest delta chunk sent in one call. Each chunk after the first
957
957
  # takes the end of the chunk before it as its context.
958
958
  append_chunk_chars: int = Field(default=7500, ge=1000)
959
+ # the agent extractor's prompt (the Stop hook's ask and its API
960
+ # proxy) tells the model how many claims text of its size usually yields,
961
+ # as a thoroughness guide, never a quota. 1.9 is the median claims per
962
+ # 1000 characters of the general extractor's transcript deltas in the
963
+ # maintainers' store (262 reads, measured 2026-10-16).
964
+ agent_expected_claims_per_kchar: float = Field(default=1.9, gt=0.0)
959
965
  # a pair the §6.6 contradiction probe confirms is read a second
960
966
  # time, before the write loop, with each claim's source kind, name, time
961
967
  # and passage (on ``llm.verification``). A pair the reading does not
@@ -2801,12 +2807,21 @@ class AgentExtractionConfig(BaseModel):
2801
2807
  # An ask unanswered after this many seconds is expired.
2802
2808
  ask_ttl_seconds: int = Field(default=900, ge=60)
2803
2809
  # A submission covers its span only with at least this many accepted claims
2804
- # per 1000 characters. 2.7 is the 10th percentile of the general
2805
- # extractor's own transcript deltas in the maintainers' store.
2806
- min_claims_per_kchar: float = Field(default=2.7, ge=0.0)
2810
+ # per 1000 characters. 1.27 is the 10th percentile of the general
2811
+ # extractor's own transcript deltas in the maintainers' store (262 delta
2812
+ # reads, measured 2026-10-16; it was 2.7 on 2026-10-09, before the
2813
+ # session-state and tool-turn filters thinned transcript extraction).
2814
+ min_claims_per_kchar: float = Field(default=1.27, ge=0.0)
2807
2815
  # ...and with no more than this share of candidates dropped for evidence
2808
2816
  # not found in the span. Placeholder until the shadow week measures it.
2809
2817
  max_evidence_drop_ratio: float = Field(default=0.5, ge=0.0, le=1.0)
2818
+ # In shadow mode, keep each submission's accepted candidates (claim text,
2819
+ # stated confidence, evidence) in a local JSONL file, so a later labelling
2820
+ # pass can fit a calibration map on real session claims. The
2821
+ # operator event log keeps counts only. Off writes nothing.
2822
+ keep_shadow_candidates: bool = True
2823
+ # None ⇒ ``<claude_code.state_dir>/agent-extraction-shadow.jsonl``.
2824
+ shadow_candidates_path: str | None = None
2810
2825
 
2811
2826
  @field_validator("mode", mode="before")
2812
2827
  @classmethod
@@ -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
@@ -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
- #:, the re-anchor pass, and the document sweep
36
- #:. A claim a person retired is not among them, and a record
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
  {
@@ -55,7 +55,7 @@ log = logging.getLogger(__name__)
55
55
  EXTRACTOR_ID = "claude-code-agent"
56
56
  #: The agent prompt's version. A calibration map applies only to the version
57
57
  #: it was fitted under, so bump this on any prompt change.
58
- EXTRACTOR_VERSION = "0.1.0"
58
+ EXTRACTOR_VERSION = "0.2.0"
59
59
 
60
60
  #: The MCP tool the agent submits through.
61
61
  SUBMIT_TOOL = "extraction_submit"
@@ -78,16 +78,54 @@ _JSON_ONLY = "Return ONLY a JSON array. No prose before or after. Each element:"
78
78
  _AGENT_SCHEMA_FIELD = ',\n "evidence": "<verbatim passage from the source text>"'
79
79
 
80
80
  _SUBMIT_INSTRUCTION = """\
81
- Particles memory: before you finish, extract this session's durable claims.
81
+ Particles memory: before you finish, extract the claims in the session text below.
82
82
 
83
- Read the session text below. It is the part of this conversation not yet
84
- recorded. Apply the rules, then call the `{tool}` tool exactly once with
85
- `ask_id` set to "{ask_id}" and `candidates` set to the JSON array described.
86
- If nothing in the text is worth recording, call it with an empty array.
87
- Do not summarise what you recorded afterwards; reply with one short line.
83
+ The text is the part of this conversation not yet recorded. When you have
84
+ extracted it, call the `{tool}` tool exactly once with `ask_id` set to
85
+ "{ask_id}" and `candidates` set to the JSON array described. If the text
86
+ holds no claim the rules admit, call it with an empty array. Do not summarise
87
+ what you recorded afterwards; reply with one short line.
88
+
89
+ {thoroughness}
88
90
 
89
91
  """
90
92
 
93
+ #: Shared by the ask and the API proxy, so the proxy's benchmark and
94
+ #: calibration measure the prompt the agent is given. The shadow week found the
95
+ #: 0.1.0 ask yielding about 0.4x the general extractor's claims on the same
96
+ #: transcripts: the agent read "durable claims ... worth recording" as an
97
+ #: invitation to curate ("keeping things modest"), took a whole span in one
98
+ #: pass where the general extractor reads 7,500-character chunks, and wrote
99
+ #: every schema field of every candidate, nulls included.
100
+ _THOROUGHNESS = """\
101
+ Extract exactly as a background extractor reading this text would: every
102
+ individual claim the rules admit, not a summary and not a selection of
103
+ highlights. Do not leave a claim out because it seems minor, obvious, or true
104
+ only for now; what is kept is decided later, not here. Work through the text
105
+ in order, a few paragraphs at a time, and finish each part before moving on.
106
+
107
+ The text is about {kchars} thousand characters long. Text like this usually
108
+ yields about {expected} claims. That is a guide to how thorough to be, never a
109
+ quota: do not invent, split, or repeat claims to reach it, and record fewer
110
+ when the text holds fewer.
111
+
112
+ Keep each candidate compact. Always give content, subjects, confidence_value
113
+ and evidence; leave out every other field whose value would be null or the
114
+ default (uncertainty_nature EPISTEMIC, scope WORLD, assertion_modality
115
+ FALSIFIABLE, polarity ASSERTED)."""
116
+
117
+
118
+ def expected_claims(span_chars: int) -> int:
119
+ """How many claims a span this size usually yields: the ask's thoroughness guide."""
120
+ rate = get_config().extraction.agent_expected_claims_per_kchar
121
+ return max(1, round(rate * span_chars / 1000))
122
+
123
+
124
+ def thoroughness(span_text: str) -> str:
125
+ """The completeness and compactness instructions for a span of this size."""
126
+ chars = len(span_text)
127
+ return _THOROUGHNESS.format(kchars=max(1, round(chars / 1000)), expected=expected_claims(chars))
128
+
91
129
 
92
130
  def agent_rules(reference_date: str) -> str:
93
131
  """The agent extractor's rules: the general extractor's, plus the evidence field.
@@ -115,7 +153,9 @@ def build_ask(ask_id: str, span_text: str, *, reference_date: str | None = None)
115
153
  date = reference_date or datetime.now(UTC).date().isoformat()
116
154
  rules = agent_rules(date).replace(_JSON_ONLY, "The `candidates` array. Each element:")
117
155
  return (
118
- _SUBMIT_INSTRUCTION.format(tool=SUBMIT_TOOL, ask_id=ask_id)
156
+ _SUBMIT_INSTRUCTION.format(
157
+ tool=SUBMIT_TOOL, ask_id=ask_id, thoroughness=thoroughness(span_text)
158
+ )
119
159
  + rules
120
160
  + "\n\n"
121
161
  + data_fence_instruction(nonce)
@@ -328,7 +368,9 @@ class AgentExtractor:
328
368
  text = content_to_text(content)
329
369
  nonce = make_nonce()
330
370
  date = datetime.now(UTC).date().isoformat()
331
- system = agent_rules(date) + "\n\n" + data_fence_instruction(nonce)
371
+ system = (
372
+ thoroughness(text) + "\n\n" + agent_rules(date) + "\n\n" + data_fence_instruction(nonce)
373
+ )
332
374
  try:
333
375
  raw, provider_model = await complete_with_provider_model(
334
376
  "extraction",
@@ -555,8 +555,8 @@ _EXTRACT_SCHEMA_TAIL = """
555
555
  }"""
556
556
 
557
557
 
558
- #: The rule a delta read carries when its prompt holds a context section
559
- #:. In the prompt proper, never inlined in the chunk text, so the
558
+ #: The rule a delta read carries when its prompt holds a context section.
559
+ #: In the prompt proper, never inlined in the chunk text, so the
560
560
  #: instruction is a trusted rule rather than words inside the fenced data.
561
561
  APPEND_CONTEXT_RULE = """
562
562
  - The user message holds two fenced sections. The one labelled "context" is
@@ -113,8 +113,8 @@ OBSERVATION_TAG = "memory-compat:observation"
113
113
  RELATION_TAG = "memory-compat:relation"
114
114
  #: Marks a Subject as deleted through the façade.
115
115
  TOMBSTONE_TAG = "memory-compat:deleted"
116
- #: Marks a particle as arriving by migration rather than by an agent write
117
- #:. Distinct from ``CalibrationSource.IMPORTED`` on purpose: the
116
+ #: Marks a particle as arriving by migration rather than by an agent write.
117
+ #: Distinct from ``CalibrationSource.IMPORTED`` on purpose: the
118
118
  #: calibration source says *how the number was produced*, this says *which run
119
119
  #: put the record here*, so an operator can find or retract one import.
120
120
  IMPORT_TAG = "migration:mcp-memory"
@@ -40,8 +40,8 @@ from particles.core.schema import ParticleType
40
40
  from particles.extraction.polarity import is_non_asserted
41
41
  from particles.extraction.scope import is_excluded_document_meta
42
42
 
43
- #: Key on the ``properties`` dict carrying the subject-scope record. Prefixed
44
- #:; the ``extraction:`` namespace is registered in §5.
43
+ #: Key on the ``properties`` dict carrying the subject-scope record. Prefixed;
44
+ #: the ``extraction:`` namespace is registered in §5.
45
45
  SUBJECT_SCOPE_KEY = "extraction:subject_scope"
46
46
 
47
47
  #: The one value that marks a claim as author-scoped. Absence of the key means
@@ -568,8 +568,8 @@ def is_within_directory(directory: Path, path: Path) -> bool:
568
568
  return False
569
569
 
570
570
 
571
- #: Ownership ledger a one-file-per-subject exporter keeps at its export root
572
- #:: the root-relative paths of every ``.md`` file its last run wrote.
571
+ #: Ownership ledger a one-file-per-subject exporter keeps at its export root:
572
+ #: the root-relative paths of every ``.md`` file its last run wrote.
573
573
  EXPORT_MANIFEST_NAME = ".particles-export.json"
574
574
 
575
575
  #: Append-only journal of files a run has written that its prior manifest did
@@ -19,7 +19,7 @@
19
19
  # version and advance together.
20
20
  [project]
21
21
  name = "linkedparticles-core"
22
- version = "1.192.2"
22
+ version = "1.192.10"
23
23
  description = "Store-free client library for Particles: define, validate, serialize, and extract provenance-tracked belief particles"
24
24
  readme = "README.md"
25
25
  requires-python = ">=3.11"
@@ -63,14 +63,33 @@ classifiers = [
63
63
  # by a module in this distribution. It is a subset of the engine's, never a
64
64
  # superset: installing the engine installs this, so a package needed by both
65
65
  # is declared in both and resolved once.
66
+ #
67
+ # These ranges are the published compatibility claim, and they are allowed to
68
+ # be wider than the development upstream's own floors, which a dependency bot
69
+ # raises to each new release. Three rules bound them, and a test in the
70
+ # upstream checks all three against its own pyproject and lockfile:
71
+ #
72
+ # 1. Every range admits the version the upstream's suite runs against.
73
+ # 2. A next-breaking upper bound is the upstream's bound, moved when it is,
74
+ # and the floor beneath it sits on the release line just below it: the
75
+ # bound declares that line the only one vetted.
76
+ # 3. No floor reaches back into an older major than the upstream's floor,
77
+ # since the code is ported to and tested on that major alone.
78
+ #
79
+ # Where a published advisory affects a path this layer exercises, the floor
80
+ # is the first release that fixes it, and the advisory is named beside it.
66
81
  dependencies = [
67
82
  "pydantic>=2.7",
68
83
  "pyyaml>=6.0",
69
84
  "httpx>=0.27",
70
- "anthropic>=0.28",
85
+ # The 1.x SDK surface: the `omit` sentinel, and sampling parameters passed
86
+ # through `extra_body` since 1.0 dropped the typed keyword arguments.
87
+ "anthropic>=1.0",
71
88
  "numpy>=1.26",
72
89
  "scipy>=1.13",
73
- "sentence-transformers>=2.7",
90
+ # GHSA-jhr6-gm9c-rqjv (fixed in 5.6.0): the encoder model is loaded at
91
+ # runtime, so the fix is a floor here.
92
+ "sentence-transformers>=5.6.0",
74
93
  # Declared explicitly *only* so `[tool.uv.sources]` below can route it to
75
94
  # the CPU-only wheel index — uv sources apply to a project's direct
76
95
  # dependencies, and torch is otherwise transitive via
@@ -81,22 +100,25 @@ dependencies = [
81
100
  # async session; the import is executed at module load even though no
82
101
  # Client module opens a connection. Declared so a store-free install still
83
102
  # imports, and with `[asyncio]` because that import needs greenlet, which
84
- # SQLAlchemy stopped installing by default in 2.1. Bounded below the next
85
- # minor: 2.1 changed ORM and typing behaviour this code depends on.
86
- "sqlalchemy[asyncio]>=2.0,<2.2",
103
+ # SQLAlchemy stopped installing by default in 2.1. Floored at 2.1 and
104
+ # bounded below the next minor: 2.1 changed ORM and typing behaviour this
105
+ # code depends on.
106
+ "sqlalchemy[asyncio]>=2.1,<2.2",
87
107
  # JSON-LD / RDF / SHACL parsing stack — these handle attacker-influenced
88
108
  # input (interchange import, conformance validation), so they carry tested
89
109
  # next-breaking upper bounds in addition to the floor: a future breaking
90
110
  # major of any of them must be vetted before adoption rather than pulled in
91
111
  # silently by a downstream `pip install`.
92
- "pyld>=2.0,<4",
93
- "pyshacl>=0.26,<0.32",
112
+ "pyld>=3.0,<4",
113
+ "pyshacl>=0.40,<0.41",
94
114
  "rdflib>=7.0,<8",
95
115
  "jsonschema>=4.22",
96
116
  # Deposited PDFs are attacker-influenced input on the runtime path, so this
97
- # floor (CVE-2026-71852 / CVE-2026-71870, fixed in 6.15.0) is a direct
98
- # dependency floor rather than an environment constraint.
99
- "pypdf>=6.15.0",
117
+ # is a direct dependency floor rather than an environment constraint. 6.19.0
118
+ # is the first release with every published advisory fixed, the latest
119
+ # being GHSA-php9-fj8v-98fj, GHSA-v247-6f48-mgcj and GHSA-w23x-9jrw-r45c
120
+ # (CVE-2026-71852 / CVE-2026-71870 were fixed in 6.15.0).
121
+ "pypdf>=6.19.0",
100
122
  "html2text>=2024.2",
101
123
  "lxml-stubs>=0.5.1",
102
124
  # Observability API only: a small, pure-Python, no-op-by-default package.
@@ -113,7 +135,7 @@ dependencies = [
113
135
  # extractor imports it lazily and raises an actionable ImportError when vision
114
136
  # extraction is enabled without it, so the base install stays lean.
115
137
  vision = [
116
- "pypdfium2>=4.30",
138
+ "pypdfium2>=5.0",
117
139
  ]
118
140
 
119
141
  # PyPI renders these beside the description and maps the recognized names
@@ -221,11 +243,20 @@ explicit = true
221
243
  [tool.uv.sources]
222
244
  torch = [{ index = "pytorch-cpu", marker = "sys_platform != 'darwin'" }]
223
245
 
224
- # Security floors on packages that are not direct dependencies — they arrive
225
- # transitively, so a floor here raises the minimum without adding a spurious
226
- # direct dependency. Revisit each line once the parent's own floor moves past
227
- # the fixed version.
246
+ # `exclude-newer` is the seven-day supply-chain cooldown: a resolve here never
247
+ # picks a release published in the last week, which is the window in which a
248
+ # compromised upload is usually caught and yanked. It is a relative span, so the
249
+ # committed `uv.lock` (cut by the export from this file) records the span and
250
+ # not a timestamp, and `uv sync --locked` stays satisfied as the days pass. The
251
+ # lock and this line travel together: drop the line and `uv lock --check`
252
+ # reports the lock stale.
253
+ #
254
+ # The `constraint-dependencies` are security floors on packages that are not
255
+ # direct dependencies. They arrive transitively, so a floor here raises the
256
+ # minimum without adding a spurious direct dependency. Revisit each line once
257
+ # the parent's own floor moves past the fixed version.
228
258
  [tool.uv]
259
+ exclude-newer = "7 days"
229
260
  constraint-dependencies = [
230
261
  "idna>=3.15", # CVE-2026-45409, runtime hostname path
231
262
  "setuptools>=83.0.0", # PYSEC-2026-3447, build path (pulled in by torch)
@@ -94,6 +94,18 @@ class TestVerifySubmission:
94
94
  )
95
95
  assert verified.accepted[0].uncertainty_nature.value == "ALEATORY"
96
96
 
97
+ def test_a_compact_candidate_takes_the_defaults(self) -> None:
98
+ # The 0.2.0 ask tells the agent to leave out null and default fields.
99
+ compact = {
100
+ "content": "Staging runs Postgres 17.",
101
+ "subjects": ["staging database"],
102
+ "confidence_value": 0.9,
103
+ "evidence": "Postgres 17",
104
+ }
105
+ verified = agent.verify_submission([compact], SPAN)
106
+ assert len(verified.accepted) == 1 and not verified.malformed
107
+ assert verified.accepted[0].uncertainty_nature.value == "EPISTEMIC"
108
+
97
109
 
98
110
  class TestCoverage:
99
111
  cfg = AgentExtractionConfig(min_claims_per_kchar=2.0, max_evidence_drop_ratio=0.5)
@@ -203,6 +215,35 @@ class TestPrompt:
203
215
  assert '<session nonce="' in ask and "hello" in ask
204
216
  assert "{reference_date}" not in ask
205
217
 
218
+ def test_ask_asks_for_every_claim_and_names_the_expected_count(self) -> None:
219
+ span = "## User\n\n" + "x" * 9990
220
+ ask = agent.build_ask("ask-123", span, reference_date="2026-10-09")
221
+ assert "durable" not in ask.split("Rules:")[0]
222
+ assert "not a selection of" in ask
223
+ # 10,000 characters at the default 1.9 claims per 1000.
224
+ assert "about 10 thousand characters" in ask and "about 19 claims" in ask
225
+ assert "never a\nquota" in ask
226
+
227
+ def test_expected_count_follows_config(self, monkeypatch: pytest.MonkeyPatch) -> None:
228
+ cfg = agent.get_config().extraction
229
+ monkeypatch.setattr(cfg, "agent_expected_claims_per_kchar", 3.0)
230
+ assert agent.expected_claims(20_000) == 60
231
+ assert agent.expected_claims(10) == 1
232
+
233
+ async def test_the_proxy_is_given_the_same_guide(self, monkeypatch: pytest.MonkeyPatch) -> None:
234
+ seen: dict[str, str] = {}
235
+
236
+ async def fake(purpose: str, user: str, **kwargs: Any) -> tuple[str, str]:
237
+ seen["system"] = kwargs["system"]
238
+ return "[]", "anthropic:test"
239
+
240
+ monkeypatch.setattr("particles.llm.complete_with_provider_model", fake)
241
+ await agent.AgentExtractor().extract(
242
+ None, # type: ignore[arg-type]
243
+ SPAN.encode(),
244
+ )
245
+ assert agent.thoroughness(SPAN) in seen["system"]
246
+
206
247
  def test_rules_carry_the_general_extractor_rules(self) -> None:
207
248
  rules = agent.agent_rules("2026-10-09")
208
249
  assert "One particle = one falsifiable assertion" in rules