capsule-engine 0.1.0__py3-none-any.whl
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.
- capsule_engine/__init__.py +17 -0
- capsule_engine/bundle_viewer/__init__.py +21 -0
- capsule_engine/bundle_viewer/static/offline_shell.html +1509 -0
- capsule_engine/bundle_viewer/viewer.py +57 -0
- capsule_engine/cli/__init__.py +5 -0
- capsule_engine/cli/bundle_cmd.py +269 -0
- capsule_engine/cli/console_cmd.py +70 -0
- capsule_engine/cli/constraints_cmd.py +74 -0
- capsule_engine/cli/format.py +173 -0
- capsule_engine/cli/guard_cmds.py +361 -0
- capsule_engine/cli/init_cmds.py +169 -0
- capsule_engine/cli/main.py +120 -0
- capsule_engine/cli/packs_cmds.py +96 -0
- capsule_engine/cli/telemetry_cmd.py +80 -0
- capsule_engine/cli/tenant_cmds.py +199 -0
- capsule_engine/cli/verify_cmd.py +110 -0
- capsule_engine/compiler/__init__.py +13 -0
- capsule_engine/compiler/effect_model.py +79 -0
- capsule_engine/compiler/vocabulary.py +253 -0
- capsule_engine/console/__init__.py +10 -0
- capsule_engine/console/api.py +251 -0
- capsule_engine/console/components.css +406 -0
- capsule_engine/console/console.css +130 -0
- capsule_engine/console/console.html +51 -0
- capsule_engine/console/console.js +330 -0
- capsule_engine/console/gallery.html +274 -0
- capsule_engine/console/server.py +137 -0
- capsule_engine/console/tokens.css +68 -0
- capsule_engine/conversation/__init__.py +88 -0
- capsule_engine/conversation/capsules.py +268 -0
- capsule_engine/conversation/exchange.py +279 -0
- capsule_engine/conversation/merkle.py +80 -0
- capsule_engine/conversation/session.py +101 -0
- capsule_engine/envcompat.py +15 -0
- capsule_engine/events/__init__.py +14 -0
- capsule_engine/events/capsule.py +133 -0
- capsule_engine/examples/__init__.py +9 -0
- capsule_engine/examples/data/tau2_airline/LICENSE-tau2-bench +21 -0
- capsule_engine/examples/data/tau2_airline/PROVENANCE.json +70 -0
- capsule_engine/examples/data/tau2_airline/hand_labels.json +893 -0
- capsule_engine/examples/data/tau2_airline/pilot1_live_gemini-2-5-flash_airline_shift1.jsonl +190 -0
- capsule_engine/examples/data/tau2_airline/tau2_committed_claude-3-7-sonnet_airline_trial0.jsonl +556 -0
- capsule_engine/examples/data/tau2_airline/tau2_committed_gpt-4-1-mini_airline_trial0.jsonl +480 -0
- capsule_engine/examples/data/tau2_airline/tau2_committed_gpt-4-1_airline_trial0.jsonl +496 -0
- capsule_engine/examples/data/tau2_airline/tau2_committed_o4-mini_airline_trial0.jsonl +392 -0
- capsule_engine/examples/data/tau2_airline/tau2_conversations_claude-3-7-sonnet_airline_4trials.jsonl +200 -0
- capsule_engine/examples/tau2_airline_reference.py +460 -0
- capsule_engine/examples/tau2_conversation_exchange.py +92 -0
- capsule_engine/folds/__init__.py +104 -0
- capsule_engine/folds/account_core.py +89 -0
- capsule_engine/folds/approval_latency.py +86 -0
- capsule_engine/folds/catalog.py +79 -0
- capsule_engine/folds/catalog_defs/actions.count_by_developer.yaml +10 -0
- capsule_engine/folds/catalog_defs/actions.executed_count.yaml +16 -0
- capsule_engine/folds/catalog_defs/actions.last_decision.yaml +12 -0
- capsule_engine/folds/catalog_defs/counterparty.seen_before.v2.yaml +34 -0
- capsule_engine/folds/catalog_defs/counterparty.seen_before.v3.yaml +38 -0
- capsule_engine/folds/catalog_defs/counterparty.seen_before.yaml +28 -0
- capsule_engine/folds/catalog_defs/disclosure.class_seen.yaml +29 -0
- capsule_engine/folds/catalog_defs/disclosure.statement_seen.yaml +32 -0
- capsule_engine/folds/catalog_defs/hold.active_exposure.yaml +44 -0
- capsule_engine/folds/catalog_defs/spend.weekly.v2.yaml +38 -0
- capsule_engine/folds/catalog_defs/spend.weekly.v3.1.yaml +71 -0
- capsule_engine/folds/catalog_defs/spend.weekly.v3.yaml +76 -0
- capsule_engine/folds/catalog_defs/spend.weekly.yaml +33 -0
- capsule_engine/folds/counterparty_signals.py +179 -0
- capsule_engine/folds/definition.py +421 -0
- capsule_engine/folds/duration.py +16 -0
- capsule_engine/folds/engine.py +436 -0
- capsule_engine/folds/errors.py +44 -0
- capsule_engine/folds/loader.py +24 -0
- capsule_engine/folds/ordering.py +143 -0
- capsule_engine/folds/paths.py +25 -0
- capsule_engine/folds/record_type_coverage.py +58 -0
- capsule_engine/folds/reducers.py +75 -0
- capsule_engine/folds/retention_continuity.py +117 -0
- capsule_engine/folds/set_membership.py +59 -0
- capsule_engine/folds/taxonomy.py +231 -0
- capsule_engine/guards/__init__.py +59 -0
- capsule_engine/guards/action.py +446 -0
- capsule_engine/guards/action_taxonomy.json +27 -0
- capsule_engine/guards/action_taxonomy_v2.json +27 -0
- capsule_engine/guards/action_taxonomy_v3.json +27 -0
- capsule_engine/guards/action_taxonomy_v4.json +27 -0
- capsule_engine/guards/action_taxonomy_v5.json +27 -0
- capsule_engine/guards/capsule.py +377 -0
- capsule_engine/guards/checks/__init__.py +268 -0
- capsule_engine/guards/checks/action_class_gate.py +199 -0
- capsule_engine/guards/checks/base.py +33 -0
- capsule_engine/guards/checks/caps.py +517 -0
- capsule_engine/guards/checks/channel_change.py +64 -0
- capsule_engine/guards/checks/commitment.py +41 -0
- capsule_engine/guards/checks/counterparty_identity_change.py +95 -0
- capsule_engine/guards/checks/counterparty_list.py +176 -0
- capsule_engine/guards/checks/counterparty_seen_before.py +160 -0
- capsule_engine/guards/checks/credential_pattern.py +73 -0
- capsule_engine/guards/checks/dedupe.py +259 -0
- capsule_engine/guards/checks/destination_rail.py +120 -0
- capsule_engine/guards/checks/field_change_count.py +100 -0
- capsule_engine/guards/checks/offer_expiry.py +134 -0
- capsule_engine/guards/checks/plan_containment.py +180 -0
- capsule_engine/guards/checks/price_floor.py +211 -0
- capsule_engine/guards/checks/promise_never.py +236 -0
- capsule_engine/guards/checks/promise_requires_approval.py +214 -0
- capsule_engine/guards/checks/recipient_role.py +117 -0
- capsule_engine/guards/checks/recurring_charge.py +49 -0
- capsule_engine/guards/checks/refundability.py +46 -0
- capsule_engine/guards/checks/release_on_acceptance.py +286 -0
- capsule_engine/guards/checks/required_disclosure.py +233 -0
- capsule_engine/guards/checks/single_commitment.py +221 -0
- capsule_engine/guards/checks/task_authority.py +182 -0
- capsule_engine/guards/checks/upfront_amount.py +71 -0
- capsule_engine/guards/checks/verify_before_dispatch.py +75 -0
- capsule_engine/guards/classes.py +393 -0
- capsule_engine/guards/engine.py +926 -0
- capsule_engine/guards/history_state.py +127 -0
- capsule_engine/guards/plan.py +237 -0
- capsule_engine/guards/revocation.py +120 -0
- capsule_engine/guards/signing.py +60 -0
- capsule_engine/guards/statements.py +62 -0
- capsule_engine/guards/tool_call.py +83 -0
- capsule_engine/guards/wickets/__init__.py +23 -0
- capsule_engine/guards/wickets/catalog.py +75 -0
- capsule_engine/guards/wickets/catalog_defs/action_class_gate.v1.1.yaml +38 -0
- capsule_engine/guards/wickets/catalog_defs/action_class_gate.v1.2.yaml +52 -0
- capsule_engine/guards/wickets/catalog_defs/action_class_gate.yaml +34 -0
- capsule_engine/guards/wickets/catalog_defs/caps.v2.yaml +30 -0
- capsule_engine/guards/wickets/catalog_defs/caps.v3.yaml +49 -0
- capsule_engine/guards/wickets/catalog_defs/caps.v4.yaml +45 -0
- capsule_engine/guards/wickets/catalog_defs/caps.v5.1.yaml +53 -0
- capsule_engine/guards/wickets/catalog_defs/caps.v5.yaml +43 -0
- capsule_engine/guards/wickets/catalog_defs/caps.yaml +17 -0
- capsule_engine/guards/wickets/catalog_defs/caps_holds.yaml +18 -0
- capsule_engine/guards/wickets/catalog_defs/channel_change.v1.1.yaml +18 -0
- capsule_engine/guards/wickets/catalog_defs/channel_change.yaml +10 -0
- capsule_engine/guards/wickets/catalog_defs/counterparty_identity_change.yaml +9 -0
- capsule_engine/guards/wickets/catalog_defs/counterparty_list.yaml +20 -0
- capsule_engine/guards/wickets/catalog_defs/counterparty_seen_before.v2.yaml +15 -0
- capsule_engine/guards/wickets/catalog_defs/counterparty_seen_before.v3.yaml +23 -0
- capsule_engine/guards/wickets/catalog_defs/counterparty_seen_before.v4.yaml +26 -0
- capsule_engine/guards/wickets/catalog_defs/counterparty_seen_before.yaml +14 -0
- capsule_engine/guards/wickets/catalog_defs/credential_pattern.yaml +14 -0
- capsule_engine/guards/wickets/catalog_defs/dedupe.yaml +19 -0
- capsule_engine/guards/wickets/catalog_defs/destination_rail.seller.v1.1.yaml +32 -0
- capsule_engine/guards/wickets/catalog_defs/destination_rail.seller.yaml +10 -0
- capsule_engine/guards/wickets/catalog_defs/destination_rail.yaml +9 -0
- capsule_engine/guards/wickets/catalog_defs/hold_reconcile.yaml +14 -0
- capsule_engine/guards/wickets/catalog_defs/material_fields_changed.v1.1.yaml +22 -0
- capsule_engine/guards/wickets/catalog_defs/material_fields_changed.yaml +14 -0
- capsule_engine/guards/wickets/catalog_defs/offer_expiry.v1.1.yaml +31 -0
- capsule_engine/guards/wickets/catalog_defs/offer_expiry.yaml +24 -0
- capsule_engine/guards/wickets/catalog_defs/offer_fields_changed.v1.1.yaml +22 -0
- capsule_engine/guards/wickets/catalog_defs/offer_fields_changed.yaml +10 -0
- capsule_engine/guards/wickets/catalog_defs/price_floor.yaml +32 -0
- capsule_engine/guards/wickets/catalog_defs/promise_never.v1.1.yaml +64 -0
- capsule_engine/guards/wickets/catalog_defs/promise_never.yaml +16 -0
- capsule_engine/guards/wickets/catalog_defs/promise_requires_approval.v1.1.yaml +26 -0
- capsule_engine/guards/wickets/catalog_defs/promise_requires_approval.yaml +21 -0
- capsule_engine/guards/wickets/catalog_defs/recipient_role.seller.v1.1.yaml +23 -0
- capsule_engine/guards/wickets/catalog_defs/recipient_role.seller.v1.2.yaml +24 -0
- capsule_engine/guards/wickets/catalog_defs/recipient_role.seller.yaml +10 -0
- capsule_engine/guards/wickets/catalog_defs/recipient_role.v1.1.yaml +26 -0
- capsule_engine/guards/wickets/catalog_defs/recipient_role.yaml +11 -0
- capsule_engine/guards/wickets/catalog_defs/recipient_seen_before.yaml +16 -0
- capsule_engine/guards/wickets/catalog_defs/recurring_charge.yaml +9 -0
- capsule_engine/guards/wickets/catalog_defs/refundability.v1.1.yaml +15 -0
- capsule_engine/guards/wickets/catalog_defs/refundability.yaml +7 -0
- capsule_engine/guards/wickets/catalog_defs/release_on_acceptance.seller.v1.1.yaml +44 -0
- capsule_engine/guards/wickets/catalog_defs/release_on_acceptance.seller.v1.2.yaml +63 -0
- capsule_engine/guards/wickets/catalog_defs/release_on_acceptance.seller.yaml +36 -0
- capsule_engine/guards/wickets/catalog_defs/required_disclosure.v1.1.yaml +36 -0
- capsule_engine/guards/wickets/catalog_defs/required_disclosure.v1.2.yaml +42 -0
- capsule_engine/guards/wickets/catalog_defs/required_disclosure.yaml +25 -0
- capsule_engine/guards/wickets/catalog_defs/single_commitment.seller.yaml +14 -0
- capsule_engine/guards/wickets/catalog_defs/task_authority.v1.1.yaml +20 -0
- capsule_engine/guards/wickets/catalog_defs/task_authority.yaml +8 -0
- capsule_engine/guards/wickets/catalog_defs/upfront_amount.v1.1.yaml +19 -0
- capsule_engine/guards/wickets/catalog_defs/upfront_amount.yaml +11 -0
- capsule_engine/guards/wickets/catalog_defs/verify_before_dispatch.yaml +9 -0
- capsule_engine/guards/wickets/definition.py +164 -0
- capsule_engine/guards/wickets/errors.py +18 -0
- capsule_engine/guards/wickets/loader.py +26 -0
- capsule_engine/guards/wickets/retired.py +62 -0
- capsule_engine/holds/__init__.py +35 -0
- capsule_engine/holds/capsules.py +266 -0
- capsule_engine/holds/engine.py +476 -0
- capsule_engine/holds/errors.py +29 -0
- capsule_engine/holds/policy.py +62 -0
- capsule_engine/holds/scope.py +47 -0
- capsule_engine/mcp/__init__.py +16 -0
- capsule_engine/mcp/config.py +117 -0
- capsule_engine/mcp/server.py +338 -0
- capsule_engine/mcp/tools.py +424 -0
- capsule_engine/packaging.py +60 -0
- capsule_engine/packs/__init__.py +45 -0
- capsule_engine/packs/backfill_coverage.py +238 -0
- capsule_engine/packs/catalog/airline-engagement/AI-BOOTSTRAP.md +53 -0
- capsule_engine/packs/catalog/airline-engagement/folds/session_close.yaml +8 -0
- capsule_engine/packs/catalog/airline-engagement/pack.yaml +146 -0
- capsule_engine/packs/catalog/eu-ai-act/fixtures/trace/good_execution.json +36 -0
- capsule_engine/packs/catalog/eu-ai-act/fixtures/trace/oversight_declared.json +36 -0
- capsule_engine/packs/catalog/eu-ai-act/fixtures/trace/tampered_execution.json +36 -0
- capsule_engine/packs/catalog/eu-ai-act/fixtures/trace/trusted_issuer.jwk.json +5 -0
- capsule_engine/packs/catalog/eu-ai-act/obligations-pack-note.md +68 -0
- capsule_engine/packs/catalog/eu-ai-act/obligations-register.yaml +761 -0
- capsule_engine/packs/catalog/eu-ai-act/pack.yaml +88 -0
- capsule_engine/packs/catalog/eu-ai-act/register.yaml +96 -0
- capsule_engine/packs/catalog/eu-ai-act-deterministic/fixtures/synthetic_internal_assist_sample.jsonl +6 -0
- capsule_engine/packs/catalog/eu-ai-act-deterministic/pack.yaml +580 -0
- capsule_engine/packs/catalog/everyday/AI-BOOTSTRAP.md +194 -0
- capsule_engine/packs/catalog/everyday/fixtures/mini_ledger.jsonl +45 -0
- capsule_engine/packs/catalog/everyday/pack.yaml +480 -0
- capsule_engine/packs/catalog/payments-safety/AI-BOOTSTRAP.md +83 -0
- capsule_engine/packs/catalog/payments-safety/fixtures/mini_ledger.jsonl +8 -0
- capsule_engine/packs/catalog/payments-safety/folds/spend_weekly.yaml +29 -0
- capsule_engine/packs/catalog/payments-safety/pack.yaml +112 -0
- capsule_engine/packs/catalog/seller/fixtures/mini_ledger.jsonl +83 -0
- capsule_engine/packs/catalog/seller/pack.yaml +503 -0
- capsule_engine/packs/catalog/standard-vendor/AI-BOOTSTRAP.md +70 -0
- capsule_engine/packs/catalog/standard-vendor/folds/session_close.yaml +8 -0
- capsule_engine/packs/catalog/standard-vendor/pack.yaml +466 -0
- capsule_engine/packs/contract_diff.py +809 -0
- capsule_engine/packs/contract_validate.py +185 -0
- capsule_engine/packs/corpus_verify.py +126 -0
- capsule_engine/packs/enforce.py +81 -0
- capsule_engine/packs/errors.py +159 -0
- capsule_engine/packs/eu_ai_act_trace_field_map.py +46 -0
- capsule_engine/packs/install.py +266 -0
- capsule_engine/packs/loader.py +1462 -0
- capsule_engine/packs/measurability_report.py +280 -0
- capsule_engine/packs/obligation_results.py +72 -0
- capsule_engine/packs/pins.py +92 -0
- capsule_engine/packs/schema.py +1053 -0
- capsule_engine/packs/thresholds.py +146 -0
- capsule_engine/packs/trace_attainment.py +188 -0
- capsule_engine/packs/trace_reader.py +104 -0
- capsule_engine/policy/__init__.py +37 -0
- capsule_engine/policy/activation.py +87 -0
- capsule_engine/policy/catalog_defs/default.yaml +23 -0
- capsule_engine/policy/catalog_defs/holds.yaml +27 -0
- capsule_engine/policy/errors.py +46 -0
- capsule_engine/policy/limits.py +287 -0
- capsule_engine/policy/loader.py +26 -0
- capsule_engine/policy/manifest.py +289 -0
- capsule_engine/policy/profile.py +281 -0
- capsule_engine/policy/resolve.py +224 -0
- capsule_engine/register/__init__.py +39 -0
- capsule_engine/register/compiler.py +219 -0
- capsule_engine/register/errors.py +40 -0
- capsule_engine/register/loader.py +247 -0
- capsule_engine/register/schema.py +129 -0
- capsule_engine/registry/__init__.py +19 -0
- capsule_engine/registry/conventions.json +162 -0
- capsule_engine/registry/conventions.py +188 -0
- capsule_engine/registry/cpb_registry.json +78 -0
- capsule_engine/report/__init__.py +62 -0
- capsule_engine/report/build.py +267 -0
- capsule_engine/report/coverage.py +777 -0
- capsule_engine/report/errors.py +35 -0
- capsule_engine/report/live_check.py +126 -0
- capsule_engine/report/live_history.py +420 -0
- capsule_engine/report/model.py +95 -0
- capsule_engine/report/render.py +467 -0
- capsule_engine/report/replay.py +1677 -0
- capsule_engine/report/result.py +504 -0
- capsule_engine/report/result_from_folds.py +222 -0
- capsule_engine/report/result_from_layers.py +670 -0
- capsule_engine/report/sale_bundle.py +864 -0
- capsule_engine/report/static/verify.js +451 -0
- capsule_engine/schemas/evidence-contract-v0.json +383 -0
- capsule_engine/schemas/vendor/epistemic-types.json +21 -0
- capsule_engine/schemas/vendor/evidence-result-v0.json +463 -0
- capsule_engine/telemetry/__init__.py +9 -0
- capsule_engine/telemetry/consent.py +39 -0
- capsule_engine/telemetry/events.py +93 -0
- capsule_engine/telemetry/fixtures/synthetic_events.jsonl +45 -0
- capsule_engine/telemetry/funnel.py +147 -0
- capsule_engine/telemetry/record.py +106 -0
- capsule_engine/telemetry/sink.py +61 -0
- capsule_engine/telemetry/state.py +60 -0
- capsule_engine/tenants.py +327 -0
- capsule_engine-0.1.0.dist-info/METADATA +47 -0
- capsule_engine-0.1.0.dist-info/RECORD +288 -0
- capsule_engine-0.1.0.dist-info/WHEEL +5 -0
- capsule_engine-0.1.0.dist-info/entry_points.txt +2 -0
- capsule_engine-0.1.0.dist-info/licenses/LICENSE +202 -0
- capsule_engine-0.1.0.dist-info/licenses/capsule_engine/examples/data/tau2_airline/LICENSE-tau2-bench +21 -0
- capsule_engine-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Adapters: real deterministic-fold outputs -> Result v0 ``Claim``s.
|
|
3
|
+
|
|
4
|
+
Every adapter here reads ``tier``/``grade``/``evidence``/``proofs`` off REAL
|
|
5
|
+
objects the fold call already produced -- ``capsule_emit``'s own
|
|
6
|
+
``CheckpointRecord.grade()`` (the two-rung ladder position: ``self-attested``
|
|
7
|
+
until a real, non-stub, offline-verified witness stamp lands, then
|
|
8
|
+
``witnessed`` -- see that method's docstring) for ``grade``, and
|
|
9
|
+
``CheckpointRecord.digest()`` / ``WitnessRecord.entry_hash`` for
|
|
10
|
+
``evidence``/``proofs``. Nothing here asserts a grade or invents a digest;
|
|
11
|
+
that is the module's whole point -- "grade read from the bundle's
|
|
12
|
+
witness/countersign state, never asserted".
|
|
13
|
+
|
|
14
|
+
``tier`` is always ``"recomputed"`` in this module: every fold in
|
|
15
|
+
``capsule_engine/folds/`` is a deterministic recomputation over sealed
|
|
16
|
+
records (this repo's own report/build.py docstring: "nothing in this module
|
|
17
|
+
invents a number"), never a semantic judgment. A ``"judged"`` claim's source
|
|
18
|
+
is a ``capsule-judge`` verdict record -- a different subsystem this repo
|
|
19
|
+
does not import -- so no adapter in this module ever emits
|
|
20
|
+
``tier="judged"``; ``result.py``'s ``Claim`` supports it for a caller that
|
|
21
|
+
has one.
|
|
22
|
+
"""
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from dataclasses import dataclass
|
|
26
|
+
|
|
27
|
+
from agent_action_capsule import json_digest
|
|
28
|
+
from capsule_emit.chain_segment import ChainSegment
|
|
29
|
+
|
|
30
|
+
from ..folds.record_type_coverage import RecordTypeCoverageResult
|
|
31
|
+
from ..folds.retention_continuity import RetentionContinuityResult
|
|
32
|
+
from .result import Claim, DigestRef, DisclosureCarrier, ProofRef
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"GuardProjection",
|
|
36
|
+
"claim_from_guard_constraint",
|
|
37
|
+
"claim_from_retention_continuity",
|
|
38
|
+
"is_excluded_not_applicable",
|
|
39
|
+
"project_guard_constraint",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
# spec/evidence-result-v0.md section 1's rule, restated: sufficiency SATISFIED
|
|
43
|
+
# only when the fold actually reached a met/not_met judgment; INSUFFICIENT
|
|
44
|
+
# otherwise. "insufficient_evidence" is the fold's retired spelling of
|
|
45
|
+
# not_evaluable, still read as an alias for results written before the
|
|
46
|
+
# rename and always projected under the one canonical spelling.
|
|
47
|
+
# Accepted alias, never emitted: removing it breaks reading older results.
|
|
48
|
+
_RETENTION_VERDICT_MAP = {
|
|
49
|
+
"met": ("SATISFIED", "met", "SATISFIED"),
|
|
50
|
+
"not_met": ("SATISFIED", "not_met", "SATISFIED"),
|
|
51
|
+
"not_evaluable": ("INSUFFICIENT", "not_evaluable", "INSUFFICIENT"),
|
|
52
|
+
"insufficient_evidence": ("INSUFFICIENT", "not_evaluable", "INSUFFICIENT"),
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def claim_from_retention_continuity(
|
|
57
|
+
result: RetentionContinuityResult,
|
|
58
|
+
segment: ChainSegment,
|
|
59
|
+
*,
|
|
60
|
+
claim_id: str,
|
|
61
|
+
contract_ref: str,
|
|
62
|
+
requirement_ref: str,
|
|
63
|
+
) -> Claim:
|
|
64
|
+
"""Project one ``evaluate_retention_continuity`` call into a Result v0
|
|
65
|
+
claim. ``segment`` must be the SAME segment ``result`` was computed
|
|
66
|
+
over -- this function reads the segment's own last checkpoint for grade
|
|
67
|
+
and evidence/proof digests, it does not recompute the fold.
|
|
68
|
+
"""
|
|
69
|
+
if result.verdict not in _RETENTION_VERDICT_MAP:
|
|
70
|
+
raise ValueError(f"unrecognized retention-continuity verdict {result.verdict!r}")
|
|
71
|
+
sufficiency, verdict, disclosure_status = _RETENTION_VERDICT_MAP[result.verdict]
|
|
72
|
+
|
|
73
|
+
checkpoint = segment.checkpoint
|
|
74
|
+
grade = checkpoint.grade().value
|
|
75
|
+
evidence = (DigestRef(digest=checkpoint.digest()),)
|
|
76
|
+
proofs = tuple(
|
|
77
|
+
ProofRef(kind="receipt", digest=w.entry_hash) for w in checkpoint.witnesses
|
|
78
|
+
) or (ProofRef(kind="inclusion_proof", digest=checkpoint.digest()),)
|
|
79
|
+
|
|
80
|
+
return Claim(
|
|
81
|
+
id=claim_id,
|
|
82
|
+
contract_ref=contract_ref,
|
|
83
|
+
requirement_ref=requirement_ref,
|
|
84
|
+
tier="recomputed",
|
|
85
|
+
grade=grade,
|
|
86
|
+
sufficiency=sufficiency,
|
|
87
|
+
verdict=verdict,
|
|
88
|
+
evidence=evidence,
|
|
89
|
+
proofs=proofs,
|
|
90
|
+
presentation=DisclosureCarrier(status=disclosure_status, evidence=evidence),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def is_excluded_not_applicable(result: RecordTypeCoverageResult) -> bool:
|
|
95
|
+
"""spec section 3: a requirement excluded as NOT_APPLICABLE never
|
|
96
|
+
becomes a claim at all -- it only contributes to
|
|
97
|
+
``aggregate.coverage.excluded_not_applicable`` (``build_result``'s
|
|
98
|
+
``excluded_not_applicable`` count). This fold's own ``applicable`` flag
|
|
99
|
+
already carries that exclusion (an empty ``registered_kinds`` declaration,
|
|
100
|
+
per ``record_type_coverage.py``'s docstring: "nothing was declared to
|
|
101
|
+
check coverage against"), so this is a pure read, not a second judgment.
|
|
102
|
+
"""
|
|
103
|
+
return not result.applicable
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# A guard constraint record's result (pass | fail | n/a) projected onto the
|
|
107
|
+
# registered (EvidenceStatus, Sufficiency, Verdict) triple, beside the fold
|
|
108
|
+
# map above. pass/fail are settled; an n/a is read through the facts object
|
|
109
|
+
# guards/capsule.py's not_applicable_evidence() digests into evidence_digest.
|
|
110
|
+
_GUARD_SETTLED = {
|
|
111
|
+
"pass": ("SATISFIED", "SATISFIED", "met"),
|
|
112
|
+
"fail": ("SATISFIED", "SATISFIED", "not_met"),
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
_GRADE_BY_ATTESTATION_MODE = {"self_attested": "self-attested"}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dataclass(frozen=True)
|
|
120
|
+
class GuardProjection:
|
|
121
|
+
"""One guard constraint record, projected. ``excluded`` means the rule did
|
|
122
|
+
not apply: the record contributes to ``excluded_not_applicable`` and never
|
|
123
|
+
becomes a claim. ``recording_defect`` marks an n/a whose cause cannot be
|
|
124
|
+
read off the record (population b); it is counted on its own and kept out
|
|
125
|
+
of every rate."""
|
|
126
|
+
|
|
127
|
+
evidence_status: str
|
|
128
|
+
sufficiency: str | None
|
|
129
|
+
verdict: str | None
|
|
130
|
+
excluded: bool = False
|
|
131
|
+
recording_defect: bool = False
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# `record` is one raw constraint object of a sealed capsule's JSON, possibly
|
|
135
|
+
# from a producer other than this engine; it is decoded field by field here.
|
|
136
|
+
def project_guard_constraint(record: dict, *, candidate_fields: frozenset[str]) -> GuardProjection:
|
|
137
|
+
"""Project one sealed guard constraint record (``capsule["constraints"][i]``).
|
|
138
|
+
|
|
139
|
+
``candidate_fields`` are the normalized action fields an in-scope n/a may
|
|
140
|
+
name as missing; the record's ``evidence_digest`` is matched against the
|
|
141
|
+
facts object for each, so nothing beyond the sealed record is read.
|
|
142
|
+
|
|
143
|
+
| record | status | sufficiency | verdict |
|
|
144
|
+
|-----------------------------------------|----------------|-------------|---------------|
|
|
145
|
+
| pass / fail | SATISFIED | SATISFIED | met / not_met |
|
|
146
|
+
| n/a, in_scope false | NOT_APPLICABLE | (excluded, never a claim) |
|
|
147
|
+
| n/a, in_scope true, missing_field named | NOT_FOUND | GAP | not_evaluable |
|
|
148
|
+
| n/a with no readable cause | UNKNOWN | UNKNOWN | not_evaluable |
|
|
149
|
+
"""
|
|
150
|
+
result = record["result"]
|
|
151
|
+
if result in _GUARD_SETTLED:
|
|
152
|
+
status, sufficiency, verdict = _GUARD_SETTLED[result]
|
|
153
|
+
return GuardProjection(evidence_status=status, sufficiency=sufficiency, verdict=verdict)
|
|
154
|
+
if result != "n/a":
|
|
155
|
+
raise ValueError(f"unrecognized guard constraint result {result!r}")
|
|
156
|
+
|
|
157
|
+
constraint_id = record["id"]
|
|
158
|
+
digest = record.get("evidence_digest")
|
|
159
|
+
if digest == json_digest({"constraint_id": constraint_id, "in_scope": False, "missing_field": None}):
|
|
160
|
+
return GuardProjection(evidence_status="NOT_APPLICABLE", sufficiency=None, verdict=None, excluded=True)
|
|
161
|
+
for field_name in sorted(candidate_fields):
|
|
162
|
+
if digest == json_digest({"constraint_id": constraint_id, "in_scope": True, "missing_field": field_name}):
|
|
163
|
+
# LOCAL CHOICE, declared here rather than derived: NOT_FOUND -> GAP.
|
|
164
|
+
# The donated spec does not define NOT_FOUND's sufficiency.
|
|
165
|
+
# agent-action-capsule spec/evidence-result-v0.md section 2
|
|
166
|
+
# ("Disclosure policy", at origin/main 3dfc70b) collapses
|
|
167
|
+
# WITHHELD and NOT_COMMITTED into GAP and names NOT_FOUND only as
|
|
168
|
+
# the contrast case; it leaves NOT_FOUND's projection open. We
|
|
169
|
+
# chose GAP: the claim is inside the evaluated population, in the
|
|
170
|
+
# not_evaluable bucket, and NOT in unknown_count. Choosing UNKNOWN
|
|
171
|
+
# instead would put this case in the published unknown_count,
|
|
172
|
+
# which section 3 ("What the sponsor sees first") and section 7
|
|
173
|
+
# ("Aggregate") define as the count of claims resolved UNKNOWN.
|
|
174
|
+
return GuardProjection(evidence_status="NOT_FOUND", sufficiency="GAP", verdict="not_evaluable")
|
|
175
|
+
# No digest, or one that matches no facts object: the record does not say
|
|
176
|
+
# why the rule did not settle. This engine cannot emit one
|
|
177
|
+
# (ConstraintOutcome refuses an n/a without evidence), so this is a
|
|
178
|
+
# foreign or pre-fix record -- a recording defect, not a decline.
|
|
179
|
+
return GuardProjection(
|
|
180
|
+
evidence_status="UNKNOWN", sufficiency="UNKNOWN", verdict="not_evaluable", recording_defect=True
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
# `capsule` and `record` are raw sealed-capsule JSON, as for
|
|
185
|
+
# project_guard_constraint; only capsule_id, assurance and the record's own
|
|
186
|
+
# fields are read.
|
|
187
|
+
def claim_from_guard_constraint(
|
|
188
|
+
capsule: dict,
|
|
189
|
+
record: dict,
|
|
190
|
+
*,
|
|
191
|
+
claim_id: str,
|
|
192
|
+
contract_ref: str,
|
|
193
|
+
requirement_ref: str,
|
|
194
|
+
candidate_fields: frozenset[str],
|
|
195
|
+
) -> Claim | None:
|
|
196
|
+
"""A Result v0 claim for one constraint record of a sealed guard decision
|
|
197
|
+
capsule, or ``None`` when the rule did not apply (the caller counts it in
|
|
198
|
+
``build_result(excluded_not_applicable=...)``). Tier ``recomputed``: the
|
|
199
|
+
check is a deterministic predicate over the decision's recorded inputs.
|
|
200
|
+
Grade is read off the capsule's own ``assurance.attestation_mode``; only
|
|
201
|
+
``self_attested`` maps today, and anything else is refused rather than
|
|
202
|
+
guessed. Evidence is the constraint's own ``evidence_digest``
|
|
203
|
+
when it has one; the proof is the decision capsule's ``capsule_id``."""
|
|
204
|
+
projected = project_guard_constraint(record, candidate_fields=candidate_fields)
|
|
205
|
+
if projected.excluded:
|
|
206
|
+
return None
|
|
207
|
+
attestation_mode = (capsule.get("assurance") or {}).get("attestation_mode")
|
|
208
|
+
if attestation_mode not in _GRADE_BY_ATTESTATION_MODE:
|
|
209
|
+
raise ValueError(f"no Result grade is defined for attestation_mode {attestation_mode!r}")
|
|
210
|
+
evidence = (DigestRef(digest=record["evidence_digest"]),) if record.get("evidence_digest") else ()
|
|
211
|
+
return Claim(
|
|
212
|
+
id=claim_id,
|
|
213
|
+
contract_ref=contract_ref,
|
|
214
|
+
requirement_ref=requirement_ref,
|
|
215
|
+
tier="recomputed",
|
|
216
|
+
grade=_GRADE_BY_ATTESTATION_MODE[attestation_mode],
|
|
217
|
+
sufficiency=projected.sufficiency,
|
|
218
|
+
verdict=projected.verdict,
|
|
219
|
+
evidence=evidence,
|
|
220
|
+
proofs=(ProofRef(kind="inclusion_proof", digest=capsule["capsule_id"]),),
|
|
221
|
+
presentation=DisclosureCarrier(status=projected.evidence_status, evidence=evidence),
|
|
222
|
+
)
|