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,330 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
//
|
|
3
|
+
// Client-side rendering for the local console (`capsule console`). Vanilla
|
|
4
|
+
// JS, no build step, no external script -- matches gallery.html's own "no
|
|
5
|
+
// network calls" discipline (see server.py's docstring): every fetch() call
|
|
6
|
+
// below targets a same-origin, relative "/api/..." path, never an external
|
|
7
|
+
// URL.
|
|
8
|
+
//
|
|
9
|
+
// Verdict-chip glyphs/classes below are the presentation-layer mapping from
|
|
10
|
+
// components.css's own comment ("distinct from the data-layer
|
|
11
|
+
// disposition.decision / verdict_class tokens -- do not conflate"): sourced
|
|
12
|
+
// from real disposition.verdict_class / assurance.effect_mode values, never
|
|
13
|
+
// invented. "blocked" always renders the sage slashed-circle (never brick,
|
|
14
|
+
// never red) per the product law components.css documents at its verdict-
|
|
15
|
+
// chip section.
|
|
16
|
+
(function () {
|
|
17
|
+
"use strict";
|
|
18
|
+
|
|
19
|
+
var state = { selectedId: null };
|
|
20
|
+
|
|
21
|
+
function qs(id) { return document.getElementById(id); }
|
|
22
|
+
|
|
23
|
+
function fetchJSON(url) {
|
|
24
|
+
return fetch(url).then(function (res) { return res.json(); });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function currentFilters() {
|
|
28
|
+
var filters = {};
|
|
29
|
+
["agent", "verdict", "since", "until"].forEach(function (key) {
|
|
30
|
+
var value = qs("filter-" + key).value.trim();
|
|
31
|
+
if (value) filters[key] = value;
|
|
32
|
+
});
|
|
33
|
+
return filters;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function buildQuery(filters) {
|
|
37
|
+
var parts = [];
|
|
38
|
+
Object.keys(filters).forEach(function (key) {
|
|
39
|
+
parts.push(encodeURIComponent(key) + "=" + encodeURIComponent(filters[key]));
|
|
40
|
+
});
|
|
41
|
+
return parts.length ? "?" + parts.join("&") : "";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Presentation-layer verdict chip -- see this file's header comment.
|
|
45
|
+
function verdictPresentation(disposition, assurance) {
|
|
46
|
+
var verdictClass = (disposition && disposition.verdict_class) || null;
|
|
47
|
+
var effectMode = (assurance && assurance.effect_mode) || null;
|
|
48
|
+
|
|
49
|
+
if (verdictClass === "blocked") {
|
|
50
|
+
return { css: "blocked", glyph: "⊘", label: "blocked" };
|
|
51
|
+
}
|
|
52
|
+
if (verdictClass === "hitl_dispatched") {
|
|
53
|
+
return {
|
|
54
|
+
css: "needs-decision",
|
|
55
|
+
glyph: "?",
|
|
56
|
+
label: "needs decision",
|
|
57
|
+
subline: disposition.approver ? "waiting: " + disposition.approver : null,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (effectMode === "dispatched_unconfirmed") {
|
|
61
|
+
return { css: "dispatched", glyph: "→", label: "dispatched · unconfirmed" };
|
|
62
|
+
}
|
|
63
|
+
if (effectMode === "confirmed" || verdictClass === "executed" || verdictClass === "confirmed") {
|
|
64
|
+
return { css: "confirmed", glyph: "✓", label: "confirmed" };
|
|
65
|
+
}
|
|
66
|
+
// Honestly-unknown fallback: a runtime/system state this console does
|
|
67
|
+
// not recognize, never a guess dressed up as one of the above.
|
|
68
|
+
return { css: "errored", glyph: "!", label: verdictClass || "errored" };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function verdictChipHTML(disposition, assurance) {
|
|
72
|
+
var v = verdictPresentation(disposition, assurance);
|
|
73
|
+
var subline = v.subline ? '<span class="verdict-subline">' + escapeHTML(v.subline) + "</span>" : "";
|
|
74
|
+
return (
|
|
75
|
+
'<span class="verdict-chip verdict-chip--' + v.css + '">' +
|
|
76
|
+
'<span class="verdict-glyph">' + v.glyph + "</span>" + escapeHTML(v.label) +
|
|
77
|
+
"</span>" + subline
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function escapeHTML(text) {
|
|
82
|
+
var div = document.createElement("div");
|
|
83
|
+
div.textContent = String(text == null ? "" : text);
|
|
84
|
+
return div.innerHTML;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Convention-label rendering (design principle item 2): action_class is
|
|
88
|
+
// never a hardcoded string here -- it's whatever record.action_class /
|
|
89
|
+
// detail.action_class the server-side registry lookup (registry/conventions.py)
|
|
90
|
+
// already resolved. Unknown ids render as-is, marked unregistered -- honest,
|
|
91
|
+
// not an error, never omitted. Reuses the existing ".mono" utility
|
|
92
|
+
// (components.css) rather than inventing a new class.
|
|
93
|
+
function actionClassHTML(actionClass) {
|
|
94
|
+
if (!actionClass) return "";
|
|
95
|
+
var suffix = actionClass.registered ? "" : " (unregistered)";
|
|
96
|
+
return '<span class="mono">' + escapeHTML(actionClass.label) + escapeHTML(suffix) + "</span>";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Assurance-grade rendering (design principle item 3): self_attested
|
|
100
|
+
// renders plain text, a badged grade (assurance_grade.badged, currently
|
|
101
|
+
// only "anchored") wears the neutral .rung-chip pill.
|
|
102
|
+
function assuranceGradeHTML(assuranceGrade) {
|
|
103
|
+
if (!assuranceGrade) return "";
|
|
104
|
+
if (!assuranceGrade.badged) {
|
|
105
|
+
return '<span class="rung-plain mono">' + escapeHTML(assuranceGrade.grade) + "</span>";
|
|
106
|
+
}
|
|
107
|
+
return '<span class="rung-chip"><span class="rung-dot" style="width:8px;height:8px;background:var(--asg-sage)"></span>' +
|
|
108
|
+
escapeHTML(assuranceGrade.grade) + "</span>";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function renderCheckpoint(data) {
|
|
112
|
+
qs("checkpoint-line").textContent = data.line;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function renderCliEcho(text) {
|
|
116
|
+
qs("cli-echo-bar").textContent = text;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function renderRecords(data) {
|
|
120
|
+
var stream = qs("record-stream");
|
|
121
|
+
stream.innerHTML = "";
|
|
122
|
+
data.records.forEach(function (record) {
|
|
123
|
+
var row = document.createElement("div");
|
|
124
|
+
row.className = "record-row" + (record.capsule_id === state.selectedId ? " selected" : "");
|
|
125
|
+
row.dataset.capsuleId = record.capsule_id;
|
|
126
|
+
row.innerHTML =
|
|
127
|
+
'<span class="record-fp mono">' + escapeHTML(record.fingerprint) + "</span>" +
|
|
128
|
+
'<span class="record-main">' +
|
|
129
|
+
'<span class="record-action">' + escapeHTML(record.action) + " · " + escapeHTML(record.agent) +
|
|
130
|
+
(record.action_class ? " · " + actionClassHTML(record.action_class) : "") + "</span>" +
|
|
131
|
+
'<span class="record-meta">' + escapeHTML(record.timestamp) + "</span>" +
|
|
132
|
+
"</span>" +
|
|
133
|
+
verdictChipHTML(record.disposition, record.assurance);
|
|
134
|
+
row.addEventListener("click", function () { selectRecord(record.capsule_id); });
|
|
135
|
+
stream.appendChild(row);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
qs("console-stream-status").textContent =
|
|
139
|
+
data.shown + " of " + data.total + " records shown (filtered view — the ledger itself is never filtered) · " +
|
|
140
|
+
(data.gap_count ? data.gap_count + " chain gap(s) detected" : "sequence unbroken");
|
|
141
|
+
|
|
142
|
+
renderCliEcho(data.cli_echo);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function renderInspectorEmpty() {
|
|
146
|
+
qs("inspector").innerHTML = '<div class="inspector-empty">select a record to inspect it</div>';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function renderChainRow(entry) {
|
|
150
|
+
var row = document.createElement("button");
|
|
151
|
+
row.type = "button";
|
|
152
|
+
row.className = "inspector-chain-row mono";
|
|
153
|
+
row.textContent = entry.fingerprint + " · " + (entry.relation || "(no relation given)");
|
|
154
|
+
row.addEventListener("click", function () { selectRecord(entry.capsule_id); });
|
|
155
|
+
return row;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Payloads the capsule commits to by digest (disposition reason, check
|
|
159
|
+
// evidence). The record never carries the preimages, so each renders as
|
|
160
|
+
// withheld beside its digest, never as a blank field. Plain text, not a
|
|
161
|
+
// verify stage: a withheld payload is not a verification result.
|
|
162
|
+
function withheldPayloadsHTML(payloads) {
|
|
163
|
+
if (!payloads || !payloads.length) return "";
|
|
164
|
+
return payloads.map(function (p) {
|
|
165
|
+
var name = p.label + (p.check_id ? " · " + p.check_id : "");
|
|
166
|
+
return '<div class="rung-plain mono">' + escapeHTML(name) + " — " + escapeHTML(p.state) +
|
|
167
|
+
" · digest " + escapeHTML(p.digest) + "</div>";
|
|
168
|
+
}).join("");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function renderInspector(detail) {
|
|
172
|
+
var inspector = qs("inspector");
|
|
173
|
+
inspector.innerHTML = "";
|
|
174
|
+
|
|
175
|
+
var header = document.createElement("div");
|
|
176
|
+
header.className = "inspector-section";
|
|
177
|
+
header.innerHTML =
|
|
178
|
+
'<div class="inspector-section-title">Identity</div>' +
|
|
179
|
+
'<div class="envelope-line">capsule ' + escapeHTML(detail.fingerprint) + "</div>" +
|
|
180
|
+
verdictChipHTML(detail.disposition, (detail.sealed || {}).assurance) +
|
|
181
|
+
assuranceGradeHTML(detail.assurance_grade) +
|
|
182
|
+
(detail.action_class ? '<div class="rung-plain">' + actionClassHTML(detail.action_class) + "</div>" : "");
|
|
183
|
+
inspector.appendChild(header);
|
|
184
|
+
|
|
185
|
+
// Checks that ran -- policy constraints, presentation-layer reuse of
|
|
186
|
+
// the verdict-chip component (pass=confirmed, fail=blocked -- sage,
|
|
187
|
+
// never brick: a held check is not a verification failure). Brick is
|
|
188
|
+
// reserved for the real cryptographic verify() section below.
|
|
189
|
+
var checksSection = document.createElement("div");
|
|
190
|
+
checksSection.className = "inspector-section";
|
|
191
|
+
var checksHTML = '<div class="inspector-section-title">Checks that ran</div>';
|
|
192
|
+
if (!detail.checks.length) {
|
|
193
|
+
checksHTML += '<div class="inspector-chain-empty">no checks recorded on this capsule</div>';
|
|
194
|
+
} else {
|
|
195
|
+
checksHTML += '<div class="inspector-check-list">';
|
|
196
|
+
detail.checks.forEach(function (check) {
|
|
197
|
+
var chipClass = check.result === "pass" ? "confirmed" : check.result === "fail" ? "blocked" : "dispatched";
|
|
198
|
+
var glyph = check.result === "pass" ? "✓" : check.result === "fail" ? "⊘" : "–";
|
|
199
|
+
checksHTML +=
|
|
200
|
+
'<span class="verdict-chip verdict-chip--' + chipClass + '" title="' + escapeHTML(check.method || "") + '">' +
|
|
201
|
+
'<span class="verdict-glyph">' + glyph + "</span>" + escapeHTML(check.id || "check") +
|
|
202
|
+
"</span>";
|
|
203
|
+
});
|
|
204
|
+
checksHTML += "</div>";
|
|
205
|
+
}
|
|
206
|
+
checksSection.innerHTML = checksHTML;
|
|
207
|
+
inspector.appendChild(checksSection);
|
|
208
|
+
|
|
209
|
+
var payloadsHTML = withheldPayloadsHTML(detail.payloads);
|
|
210
|
+
if (payloadsHTML) {
|
|
211
|
+
var payloadsSection = document.createElement("div");
|
|
212
|
+
payloadsSection.className = "inspector-section";
|
|
213
|
+
payloadsSection.innerHTML = '<div class="inspector-section-title">Payloads</div>' + payloadsHTML;
|
|
214
|
+
inspector.appendChild(payloadsSection);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Real cryptographic verification -- the one legitimate brick use in
|
|
218
|
+
// this panel, reusing the verify-ritual component verbatim.
|
|
219
|
+
var verifySection = document.createElement("div");
|
|
220
|
+
verifySection.className = "inspector-section";
|
|
221
|
+
var verifyHTML = '<div class="inspector-section-title">Verify</div><div style="border:1px solid var(--asg-sand); border-radius:12px">';
|
|
222
|
+
if (detail.verify.ok) {
|
|
223
|
+
verifyHTML +=
|
|
224
|
+
'<div class="verify-stage verify-stage--pass"><span class="verify-stage-glyph">✓</span>' +
|
|
225
|
+
'<span class="verify-stage-name">verifies</span>' +
|
|
226
|
+
'<span class="verify-stage-detail">digest, chain, and signature all check out</span></div>';
|
|
227
|
+
} else if (detail.verify.findings.length) {
|
|
228
|
+
detail.verify.findings.forEach(function (finding) {
|
|
229
|
+
verifyHTML +=
|
|
230
|
+
'<div class="verify-stage verify-stage--fail"><span class="verify-stage-glyph">✕</span>' +
|
|
231
|
+
'<span class="verify-stage-name mono">' + escapeHTML(finding.code) + "</span>" +
|
|
232
|
+
'<span class="verify-stage-detail">' + escapeHTML(finding.detail) + "</span></div>";
|
|
233
|
+
});
|
|
234
|
+
} else {
|
|
235
|
+
verifyHTML +=
|
|
236
|
+
'<div class="verify-stage verify-stage--skip"><span class="verify-stage-glyph">–</span>' +
|
|
237
|
+
'<span class="verify-stage-name">verify</span>' +
|
|
238
|
+
'<span class="verify-stage-detail">no verification result available</span></div>';
|
|
239
|
+
}
|
|
240
|
+
verifyHTML += "</div>";
|
|
241
|
+
verifySection.innerHTML = verifyHTML;
|
|
242
|
+
inspector.appendChild(verifySection);
|
|
243
|
+
|
|
244
|
+
// Chain: what this record cites, and what cites it.
|
|
245
|
+
var chainSection = document.createElement("div");
|
|
246
|
+
chainSection.className = "inspector-section";
|
|
247
|
+
chainSection.innerHTML = '<div class="inspector-section-title">Chain</div>';
|
|
248
|
+
var citesWrap = document.createElement("div");
|
|
249
|
+
if (detail.chain.cites) {
|
|
250
|
+
var citeLabel = document.createElement("div");
|
|
251
|
+
citeLabel.className = "inspector-chain-empty";
|
|
252
|
+
citeLabel.textContent = detail.chain.cites.found ? "cites:" : "cites (not found in this ledger — a chain gap):";
|
|
253
|
+
citesWrap.appendChild(citeLabel);
|
|
254
|
+
if (detail.chain.cites.found) citesWrap.appendChild(renderChainRow(detail.chain.cites));
|
|
255
|
+
} else {
|
|
256
|
+
var noCites = document.createElement("div");
|
|
257
|
+
noCites.className = "inspector-chain-empty";
|
|
258
|
+
noCites.textContent = "cites: (none)";
|
|
259
|
+
citesWrap.appendChild(noCites);
|
|
260
|
+
}
|
|
261
|
+
chainSection.appendChild(citesWrap);
|
|
262
|
+
|
|
263
|
+
var citedByLabel = document.createElement("div");
|
|
264
|
+
citedByLabel.className = "inspector-chain-empty";
|
|
265
|
+
citedByLabel.style.marginTop = "8px";
|
|
266
|
+
citedByLabel.textContent = detail.chain.cited_by.length ? "cited by:" : "cited by: (nothing yet)";
|
|
267
|
+
chainSection.appendChild(citedByLabel);
|
|
268
|
+
detail.chain.cited_by.forEach(function (entry) { chainSection.appendChild(renderChainRow(entry)); });
|
|
269
|
+
inspector.appendChild(chainSection);
|
|
270
|
+
|
|
271
|
+
// Fold strip: live fold values for this record's agent, in the exact
|
|
272
|
+
// deterministic-mark + envelope-line pattern gallery.html's own
|
|
273
|
+
// deterministic-class example uses.
|
|
274
|
+
var foldSection = document.createElement("div");
|
|
275
|
+
foldSection.className = "inspector-section";
|
|
276
|
+
var foldHTML = '<div class="inspector-section-title">Fold strip</div>';
|
|
277
|
+
if (!detail.fold_strip.length) {
|
|
278
|
+
foldHTML += '<div class="inspector-chain-empty">no folds configured</div>';
|
|
279
|
+
} else {
|
|
280
|
+
detail.fold_strip.forEach(function (fold) {
|
|
281
|
+
foldHTML +=
|
|
282
|
+
'<div class="inspector-fold-row">' +
|
|
283
|
+
'<div style="display:flex; align-items:baseline; gap:8px">' +
|
|
284
|
+
'<span class="mono" style="color:var(--asg-sage); font-weight:600; font-size:13px">✓</span>' +
|
|
285
|
+
'<span class="inspector-fold-value">' + escapeHTML(fold.fold_id) + ": " +
|
|
286
|
+
'<strong class="mono" style="font-weight:500">' + escapeHTML(JSON.stringify(fold.result)) + "</strong></span>" +
|
|
287
|
+
"</div>" +
|
|
288
|
+
'<div class="envelope-line">' + escapeHTML(fold.envelope_line) + "</div>" +
|
|
289
|
+
"</div>";
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
foldSection.innerHTML = foldHTML;
|
|
293
|
+
inspector.appendChild(foldSection);
|
|
294
|
+
|
|
295
|
+
// Sealed fields -- the raw capsule, exactly as sealed.
|
|
296
|
+
var sealedSection = document.createElement("div");
|
|
297
|
+
sealedSection.className = "inspector-section";
|
|
298
|
+
sealedSection.innerHTML =
|
|
299
|
+
'<div class="inspector-section-title">Sealed fields</div>' +
|
|
300
|
+
'<div class="inspector-sealed">' + escapeHTML(JSON.stringify(detail.sealed, null, 2)) + "</div>";
|
|
301
|
+
inspector.appendChild(sealedSection);
|
|
302
|
+
|
|
303
|
+
var echoSection = document.createElement("div");
|
|
304
|
+
echoSection.className = "inspector-section inspector-cli-echo";
|
|
305
|
+
echoSection.innerHTML = '<div class="cli-echo">' + escapeHTML(detail.cli_echo) + "</div>";
|
|
306
|
+
inspector.appendChild(echoSection);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function selectRecord(capsuleId) {
|
|
310
|
+
state.selectedId = capsuleId;
|
|
311
|
+
Array.prototype.forEach.call(document.querySelectorAll(".record-row"), function (row) {
|
|
312
|
+
row.classList.toggle("selected", row.dataset.capsuleId === capsuleId);
|
|
313
|
+
});
|
|
314
|
+
fetchJSON("/api/records/" + encodeURIComponent(capsuleId)).then(function (detail) {
|
|
315
|
+
if (detail.error) return;
|
|
316
|
+
renderInspector(detail);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function refresh() {
|
|
321
|
+
fetchJSON("/api/checkpoint").then(renderCheckpoint);
|
|
322
|
+
fetchJSON("/api/records" + buildQuery(currentFilters())).then(renderRecords);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
326
|
+
qs("filter-apply").addEventListener("click", refresh);
|
|
327
|
+
renderInspectorEmpty();
|
|
328
|
+
refresh();
|
|
329
|
+
});
|
|
330
|
+
})();
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>capsule-ledger console — component gallery</title>
|
|
7
|
+
<!--
|
|
8
|
+
No Google Fonts <link>: this page (like capsule_ledger/report/render.py's
|
|
9
|
+
verify surface) makes no outbound network calls. The same font-family
|
|
10
|
+
declarations are kept so a browser with Playfair Display / DM Sans /
|
|
11
|
+
DM Mono installed locally still renders them, with a close system-font
|
|
12
|
+
fallback otherwise.
|
|
13
|
+
-->
|
|
14
|
+
<link rel="stylesheet" href="tokens.css">
|
|
15
|
+
<link rel="stylesheet" href="components.css">
|
|
16
|
+
<style>
|
|
17
|
+
.gallery-wrap { max-width: 1180px; margin: 0 auto; padding: 56px 48px 100px; }
|
|
18
|
+
.gallery-header { border-bottom: 1px solid var(--asg-sand); padding-bottom: 24px; margin-bottom: 44px; }
|
|
19
|
+
.gallery-title { font-family: var(--asg-font-display); font-size: 34px; font-weight: 700; letter-spacing: -1px; color: var(--asg-bark); margin: 10px 0 8px; }
|
|
20
|
+
.gallery-sub { font-size: 14.5px; font-weight: 300; color: var(--asg-text-muted); max-width: 640px; margin: 0; }
|
|
21
|
+
section.gallery-section { margin-bottom: 56px; }
|
|
22
|
+
.section-title { font-family: var(--asg-font-display); font-size: 24px; font-weight: 700; color: var(--asg-bark); margin: 0 0 6px; }
|
|
23
|
+
.section-note { font-size: 13px; font-weight: 300; color: var(--asg-text-muted); max-width: 720px; margin: 0 0 20px; }
|
|
24
|
+
.state-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px; }
|
|
25
|
+
.state-grid--2 { grid-template-columns: 1fr 1fr; }
|
|
26
|
+
.state-label { font-family: var(--asg-font-mono); font-size: 10px; letter-spacing: 1px; text-transform: uppercase; color: var(--asg-text-muted); margin-bottom: 8px; }
|
|
27
|
+
.state-slot { display: flex; flex-direction: column; gap: 6px; }
|
|
28
|
+
.row-stack { display: flex; flex-direction: column; gap: 10px; }
|
|
29
|
+
.chip-stack { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
|
|
30
|
+
</style>
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
<div class="gallery-wrap">
|
|
34
|
+
|
|
35
|
+
<header class="gallery-header">
|
|
36
|
+
<div class="eyebrow">capsule-ledger console</div>
|
|
37
|
+
<h1 class="gallery-title">Component gallery</h1>
|
|
38
|
+
<p class="gallery-sub">Every token and component in the visual language, rendered in every listed
|
|
39
|
+
state, for review against <span class="mono">Visual Language Spec.dc.html</span>. Static assets --
|
|
40
|
+
no build step, no network calls; open this file directly in a browser.</p>
|
|
41
|
+
</header>
|
|
42
|
+
|
|
43
|
+
<!-- ══════ 1 · EVALUATION-CLASS MARKS ══════ -->
|
|
44
|
+
<section class="gallery-section" id="evaluation-classes">
|
|
45
|
+
<div class="eyebrow">Rule 2 · never confusable</div>
|
|
46
|
+
<h2 class="section-title">Three evaluation classes</h2>
|
|
47
|
+
<p class="section-note">Deterministic, model-assisted, and manual each own a mark, a color, and a
|
|
48
|
+
frame the others may not borrow. A model-assisted claim never renders a check mark.</p>
|
|
49
|
+
|
|
50
|
+
<div class="state-grid">
|
|
51
|
+
<div class="eval-card">
|
|
52
|
+
<div class="eval-card-head">
|
|
53
|
+
<span class="eval-mark eval-mark--deterministic">✓</span>
|
|
54
|
+
<div><div class="eval-card-title">Deterministic</div><div class="eval-card-kind">computed · replayable</div></div>
|
|
55
|
+
</div>
|
|
56
|
+
<p class="eval-card-body">A fold or query result. Rendered as <strong>fact</strong>, always with
|
|
57
|
+
its verification envelope. Mark: solid sage check. Anyone can replay it.</p>
|
|
58
|
+
<div class="eval-example--deterministic">
|
|
59
|
+
<div style="display:flex; align-items:baseline; gap:8px">
|
|
60
|
+
<span class="eval-mark--deterministic-inline mono" style="color:var(--asg-sage); font-weight:600; font-size:13px">✓</span>
|
|
61
|
+
<span style="font-size:14px; color:var(--asg-text-body)">Spend this week: <strong class="mono" style="font-weight:500">€4,120.00</strong></span>
|
|
62
|
+
</div>
|
|
63
|
+
<div class="envelope-line" style="margin-top:8px">fold spend_weekly_eur · records 0–212<br>checkpoint #216 · as of 14s ago</div>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div class="eval-card">
|
|
68
|
+
<div class="eval-card-head">
|
|
69
|
+
<span class="eval-mark eval-mark--model">≈</span>
|
|
70
|
+
<div><div class="eval-card-title">Model-assisted</div><div class="eval-card-kind">interpretation · awaiting human</div></div>
|
|
71
|
+
</div>
|
|
72
|
+
<p class="eval-card-body">An AI reading of the evidence. Rendered as an <strong>attributed
|
|
73
|
+
claim</strong> — model id, evidence range, confidence. Mark: dashed amber tilde. Never a check.</p>
|
|
74
|
+
<div class="eval-example--model">
|
|
75
|
+
<div style="display:flex; align-items:baseline; gap:8px">
|
|
76
|
+
<span class="mono" style="color:var(--asg-amber); font-weight:600; font-size:14px">≈</span>
|
|
77
|
+
<span class="eval-claim" style="font-size:14px; line-height:1.8">"This looks like a retry storm —
|
|
78
|
+
<span class="eval-cited-chip"><span class="eval-mark--deterministic-inline">✓</span>11 near-identical calls / 90s · shape fold · 118–129</span>
|
|
79
|
+
— worth a look."</span>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="envelope-line envelope-line--amber" style="margin-top:8px">claude-sonnet-4-6 · reads records 118–129 · every number in the claim is a cited fold chip, never the model's own<br>confidence: moderate · <span style="border-bottom:1px dotted var(--asg-amber)">confirm</span> / <span style="border-bottom:1px dotted var(--asg-amber)">override</span></div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div class="eval-card">
|
|
86
|
+
<div class="eval-card-head">
|
|
87
|
+
<span class="eval-mark eval-mark--manual">EO</span>
|
|
88
|
+
<div><div class="eval-card-title">Manual</div><div class="eval-card-kind">human attestation · signed</div></div>
|
|
89
|
+
</div>
|
|
90
|
+
<p class="eval-card-body">A person put their name on it. Rendered as a <strong>signature</strong> —
|
|
91
|
+
who, their role, when, recorded as its own capsule. Mark: bark seal with initials.</p>
|
|
92
|
+
<div class="eval-example--manual">
|
|
93
|
+
<div class="eval-signature-name">E. Okafor</div>
|
|
94
|
+
<div style="font-size:12.5px; color:var(--asg-text-muted); margin-top:2px">General Counsel — authorized this action</div>
|
|
95
|
+
<div class="envelope-line envelope-line--muted" style="margin-top:8px">signed 2026-08-04 09:12 UTC · recorded as 94c877c7…</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</section>
|
|
100
|
+
|
|
101
|
+
<!-- ══════ 2 · ENVELOPE LINE ══════ -->
|
|
102
|
+
<section class="gallery-section" id="envelope-line">
|
|
103
|
+
<div class="eyebrow">DM Mono · literal text</div>
|
|
104
|
+
<h2 class="section-title">Envelope line</h2>
|
|
105
|
+
<p class="section-note">Verbatim format pinned in <span class="mono">capsule_ledger/cli/format.py</span>:
|
|
106
|
+
<span class="mono">fold <id> · records N–M · checkpoint #X · as of <staleness></span>.
|
|
107
|
+
Always accompanies a deterministic mark.</p>
|
|
108
|
+
<div class="row-stack">
|
|
109
|
+
<div class="envelope-line">fold spend_weekly_eur · records 0–212 · checkpoint #216 · as of 14s ago</div>
|
|
110
|
+
<div class="envelope-line">fold refusal_count · records 0–212 · checkpoint #216 · as of just now</div>
|
|
111
|
+
<div class="envelope-line envelope-line--muted">fold guard_dry_run@216 · records 118–129 · checkpoint #216 · as of 2m ago</div>
|
|
112
|
+
</div>
|
|
113
|
+
</section>
|
|
114
|
+
|
|
115
|
+
<!-- ══════ 3 · RUNG CHIP ══════ -->
|
|
116
|
+
<section class="gallery-section" id="rung-chip">
|
|
117
|
+
<div class="eyebrow">Rule 3 · degradation shown, not hidden</div>
|
|
118
|
+
<h2 class="section-title">Assurance rungs</h2>
|
|
119
|
+
<p class="section-note">Classes and rungs are orthogonal. Climbing is normal life (animate once,
|
|
120
|
+
settle); a downgrade shows the rung it <em>holds</em>, never the one it hoped for.</p>
|
|
121
|
+
|
|
122
|
+
<div class="row-stack" style="margin-bottom:24px">
|
|
123
|
+
<div class="rung-row" style="border-radius:12px 12px 0 0">
|
|
124
|
+
<div class="rung-dot-wrap"><span class="rung-dot" style="width:10px; height:10px; background:transparent; border:2px solid var(--asg-sand-dark)"></span></div>
|
|
125
|
+
<div><div class="rung-name">Standalone</div><div class="rung-mode">ledger_mode: standalone</div></div>
|
|
126
|
+
<div class="rung-plain">The record is signed and complete on its own. A stranger must trust the operator that it was never replaced.</div>
|
|
127
|
+
<div></div>
|
|
128
|
+
</div>
|
|
129
|
+
<div class="rung-row" style="border-top:none">
|
|
130
|
+
<div class="rung-dot-wrap"><span class="rung-dot" style="width:10px; height:10px; background:var(--asg-sand-dark)"></span></div>
|
|
131
|
+
<div><div class="rung-name">Countersigned</div><div class="rung-mode">attestation: counterparty</div></div>
|
|
132
|
+
<div class="rung-plain">The other side of the action signed it too. Neither party can now tell a different story.</div>
|
|
133
|
+
<div></div>
|
|
134
|
+
</div>
|
|
135
|
+
<div class="rung-row" style="border-top:none">
|
|
136
|
+
<div class="rung-dot-wrap"><span class="rung-dot" style="width:11px; height:11px; background:var(--asg-amber)"></span></div>
|
|
137
|
+
<div><div class="rung-name">Locally receipted</div><div class="rung-mode">ledger_mode: chained</div></div>
|
|
138
|
+
<div class="rung-plain">The record holds its place in an unbroken sequence. Removing or editing it would visibly break the chain.</div>
|
|
139
|
+
<div></div>
|
|
140
|
+
</div>
|
|
141
|
+
<div class="rung-row" style="border-top:none">
|
|
142
|
+
<div class="rung-dot-wrap"><span class="rung-dot" style="width:12px; height:12px; background:var(--asg-amber)"></span></div>
|
|
143
|
+
<div><div class="rung-name">Counterparty-visible</div><div class="rung-mode">shared checkpoint</div></div>
|
|
144
|
+
<div class="rung-plain">The sequence summary is held by the counterparty as well — history can't be rewritten without the other side noticing.</div>
|
|
145
|
+
<div></div>
|
|
146
|
+
</div>
|
|
147
|
+
<div class="rung-row" style="border-top:none; border-radius:0 0 12px 12px; background:rgba(122,140,110,0.06)">
|
|
148
|
+
<div class="rung-dot-wrap"><span class="rung-dot" style="width:13px; height:13px; background:var(--asg-sage)"></span></div>
|
|
149
|
+
<div><div class="rung-name">Externally registered</div><div class="rung-mode">ledger_mode: anchored · 3 external witnesses</div></div>
|
|
150
|
+
<div class="rung-plain">A summary was lodged with independent public logs — this history cannot be quietly rewritten afterwards.</div>
|
|
151
|
+
<div></div>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<div class="chip-stack">
|
|
156
|
+
<div class="state-slot"><span class="state-label">normal</span><span class="rung-chip"><span class="rung-dot" style="width:8px; height:8px; background:var(--asg-sage)"></span>locally receipted</span></div>
|
|
157
|
+
<div class="state-slot"><span class="state-label">rung held (downgrade)</span><span class="rung-chip rung-chip--held"><span class="rung-dot" style="width:8px; height:8px"></span>registered with 1 of 3 logs · retrying</span></div>
|
|
158
|
+
</div>
|
|
159
|
+
</section>
|
|
160
|
+
|
|
161
|
+
<!-- ══════ 4 · STALENESS CHIP ══════ -->
|
|
162
|
+
<section class="gallery-section" id="staleness-chip">
|
|
163
|
+
<div class="eyebrow">Rule 3 · staleness on every aggregate</div>
|
|
164
|
+
<h2 class="section-title">Staleness chip</h2>
|
|
165
|
+
<p class="section-note">There is no global real-time truth; the chip says so honestly. Past its
|
|
166
|
+
policy bound, an aggregate's freshness claim can no longer be trusted (see components.css §4).</p>
|
|
167
|
+
<div class="chip-stack">
|
|
168
|
+
<div class="state-slot"><span class="state-label">fresh</span><span class="staleness-chip staleness-chip--fresh mono">as of 14s ago</span></div>
|
|
169
|
+
<div class="state-slot"><span class="state-label">refreshing</span><span class="staleness-chip staleness-chip--refreshing mono">as of 2m ago · refreshing</span></div>
|
|
170
|
+
<div class="state-slot"><span class="state-label">stale beyond policy bound</span><span class="staleness-chip staleness-chip--stale-beyond-bound mono">stale · older than policy bound (5m)</span></div>
|
|
171
|
+
</div>
|
|
172
|
+
</section>
|
|
173
|
+
|
|
174
|
+
<!-- ══════ 5 · VERDICT CHIPS ══════ -->
|
|
175
|
+
<section class="gallery-section" id="verdict-chips">
|
|
176
|
+
<div class="eyebrow">Local Console · presentational categories</div>
|
|
177
|
+
<h2 class="section-title">Verdict chips</h2>
|
|
178
|
+
<p class="section-note">Presentation-layer labels — distinct from the data-layer
|
|
179
|
+
<span class="mono">disposition.decision</span> / <span class="mono">verdict_class</span> tokens.
|
|
180
|
+
Blocked wears sage, never red: proof the guard ran, not a failure.</p>
|
|
181
|
+
<div class="state-grid">
|
|
182
|
+
<div class="state-slot">
|
|
183
|
+
<span class="state-label">confirmed</span>
|
|
184
|
+
<span class="verdict-chip verdict-chip--confirmed"><span class="verdict-glyph">✓</span>confirmed</span>
|
|
185
|
+
</div>
|
|
186
|
+
<div class="state-slot">
|
|
187
|
+
<span class="state-label">dispatched · unconfirmed</span>
|
|
188
|
+
<span class="verdict-chip verdict-chip--dispatched"><span class="verdict-glyph">→</span>dispatched · unconfirmed</span>
|
|
189
|
+
</div>
|
|
190
|
+
<div class="state-slot">
|
|
191
|
+
<span class="state-label">blocked (sage, never red)</span>
|
|
192
|
+
<span class="verdict-chip verdict-chip--blocked"><span class="verdict-glyph">⊘</span>blocked</span>
|
|
193
|
+
</div>
|
|
194
|
+
<div class="state-slot">
|
|
195
|
+
<span class="state-label">needs decision</span>
|
|
196
|
+
<span>
|
|
197
|
+
<span class="verdict-chip verdict-chip--needs-decision"><span class="verdict-glyph">?</span>needs decision</span>
|
|
198
|
+
<span class="verdict-subline">waiting: treasury-approver</span>
|
|
199
|
+
</span>
|
|
200
|
+
</div>
|
|
201
|
+
<div class="state-slot">
|
|
202
|
+
<span class="state-label">errored</span>
|
|
203
|
+
<span class="verdict-chip verdict-chip--errored"><span class="verdict-glyph">!</span>errored</span>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</section>
|
|
207
|
+
|
|
208
|
+
<!-- ══════ 6 · CLI-ECHO BAR ══════ -->
|
|
209
|
+
<section class="gallery-section" id="cli-echo">
|
|
210
|
+
<div class="eyebrow">Standing rule</div>
|
|
211
|
+
<h2 class="section-title">The CLI echo</h2>
|
|
212
|
+
<p class="section-note">Every GUI filter or action shows its CLI/API equivalent, live.</p>
|
|
213
|
+
<div class="cli-echo">≡ capsule log --agent hermes --verdict blocked --since 19:00</div>
|
|
214
|
+
</section>
|
|
215
|
+
|
|
216
|
+
<!-- ══════ 7 · BRICK-FAILURE TREATMENT ══════ -->
|
|
217
|
+
<section class="gallery-section" id="brick-failure">
|
|
218
|
+
<div class="eyebrow">Rule 5 · precision, never a generic red X</div>
|
|
219
|
+
<h2 class="section-title">When verification fails</h2>
|
|
220
|
+
<p class="section-note">Failure red is <span class="mono" style="color:var(--asg-brick)">#A93F2B</span>
|
|
221
|
+
— reserved exclusively for verification failure. Nothing else on any surface may use it.
|
|
222
|
+
A failed record names the stage that failed.</p>
|
|
223
|
+
|
|
224
|
+
<div class="state-grid--2" style="display:grid; gap:20px; margin-bottom:24px">
|
|
225
|
+
<div class="fail-card">
|
|
226
|
+
<div class="fail-card-head"><span class="fail-icon">✕</span><span class="fail-stage mono">digest_mismatch</span></div>
|
|
227
|
+
<div class="fail-title">The contents changed</div>
|
|
228
|
+
<div class="fail-render">"This record does not match its fingerprint — it is not the record that was sealed." The mismatching field group is named; the rest of the bundle keeps its own verdicts.</div>
|
|
229
|
+
</div>
|
|
230
|
+
<div class="fail-card">
|
|
231
|
+
<div class="fail-card-head"><span class="fail-icon">✕</span><span class="fail-stage mono">signature_invalid</span></div>
|
|
232
|
+
<div class="fail-title">The signature doesn't hold</div>
|
|
233
|
+
<div class="fail-render">"The signature on this record was not made by the key it names." Renders who it claims to be from, and that the claim fails — never just a red icon.</div>
|
|
234
|
+
</div>
|
|
235
|
+
<div class="fail-card">
|
|
236
|
+
<div class="fail-card-head"><span class="fail-icon">✕</span><span class="fail-stage mono">chain_gap</span></div>
|
|
237
|
+
<div class="fail-title">A break in the sequence</div>
|
|
238
|
+
<div class="fail-render">"Records are missing between #47 (Tue 14:02) and #48 (Tue 14:19)." The gap window is the finding — located in time and position, browsable from either edge.</div>
|
|
239
|
+
</div>
|
|
240
|
+
<div class="fail-card">
|
|
241
|
+
<div class="fail-card-head"><span class="fail-icon">✕</span><span class="fail-stage mono">inclusion_unproven</span></div>
|
|
242
|
+
<div class="fail-title">The witness receipt doesn't check out</div>
|
|
243
|
+
<div class="fail-render">"This record claims external registration, but the log's receipt doesn't check out (or can't be reached — retry when online)." Distinguishes unreachable from disproven, always — and never claims more independence than the witnessing rung actually held (an operated default witness is not the same claim as the "Externally registered" rung above).</div>
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
|
|
247
|
+
<h3 style="font-family:var(--asg-font-display); font-size:18px; color:var(--asg-bark); margin:0 0 10px">The verify ritual</h3>
|
|
248
|
+
<p class="section-note">Four stage rows. Pass is sage, fail is brick (the only other permitted brick
|
|
249
|
+
use), skipped is a neutral outline — never a silent green dot, never a bare red X.</p>
|
|
250
|
+
<div class="state-grid--2" style="display:grid; gap:20px">
|
|
251
|
+
<div>
|
|
252
|
+
<div class="state-label">all pass, witness skipped offline</div>
|
|
253
|
+
<div style="border:1px solid var(--asg-sand); border-radius:12px">
|
|
254
|
+
<div class="verify-stage verify-stage--pass"><span class="verify-stage-glyph">✓</span><span class="verify-stage-name">Integrity</span><span class="verify-stage-detail">every record matches its fingerprint</span></div>
|
|
255
|
+
<div class="verify-stage verify-stage--pass"><span class="verify-stage-glyph">✓</span><span class="verify-stage-name">Sequence</span><span class="verify-stage-detail">nothing missing between the first and last record shown</span></div>
|
|
256
|
+
<div class="verify-stage verify-stage--pass"><span class="verify-stage-glyph">✓</span><span class="verify-stage-name">Authenticity</span><span class="verify-stage-detail">signed by acme-research</span></div>
|
|
257
|
+
<div class="verify-stage verify-stage--skip"><span class="verify-stage-glyph">–</span><span class="verify-stage-name">Witness</span><span class="verify-stage-detail">skipped (no connection) — everything else verified</span></div>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
<div>
|
|
261
|
+
<div class="state-label">integrity fails, rest continue</div>
|
|
262
|
+
<div style="border:1px solid var(--asg-sand); border-radius:12px">
|
|
263
|
+
<div class="verify-stage verify-stage--fail"><span class="verify-stage-glyph">✕</span><span class="verify-stage-name">Integrity</span><span class="verify-stage-detail">digest_mismatch — see failure card above</span></div>
|
|
264
|
+
<div class="verify-stage verify-stage--pass"><span class="verify-stage-glyph">✓</span><span class="verify-stage-name">Sequence</span><span class="verify-stage-detail">nothing missing between the first and last record shown</span></div>
|
|
265
|
+
<div class="verify-stage verify-stage--pass"><span class="verify-stage-glyph">✓</span><span class="verify-stage-name">Authenticity</span><span class="verify-stage-detail">signed by acme-research</span></div>
|
|
266
|
+
<div class="verify-stage verify-stage--pass"><span class="verify-stage-glyph">✓</span><span class="verify-stage-name">Witness</span><span class="verify-stage-detail">registered with 3 of 3 logs</span></div>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
</section>
|
|
271
|
+
|
|
272
|
+
</div>
|
|
273
|
+
</body>
|
|
274
|
+
</html>
|