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.
Files changed (288) hide show
  1. capsule_engine/__init__.py +17 -0
  2. capsule_engine/bundle_viewer/__init__.py +21 -0
  3. capsule_engine/bundle_viewer/static/offline_shell.html +1509 -0
  4. capsule_engine/bundle_viewer/viewer.py +57 -0
  5. capsule_engine/cli/__init__.py +5 -0
  6. capsule_engine/cli/bundle_cmd.py +269 -0
  7. capsule_engine/cli/console_cmd.py +70 -0
  8. capsule_engine/cli/constraints_cmd.py +74 -0
  9. capsule_engine/cli/format.py +173 -0
  10. capsule_engine/cli/guard_cmds.py +361 -0
  11. capsule_engine/cli/init_cmds.py +169 -0
  12. capsule_engine/cli/main.py +120 -0
  13. capsule_engine/cli/packs_cmds.py +96 -0
  14. capsule_engine/cli/telemetry_cmd.py +80 -0
  15. capsule_engine/cli/tenant_cmds.py +199 -0
  16. capsule_engine/cli/verify_cmd.py +110 -0
  17. capsule_engine/compiler/__init__.py +13 -0
  18. capsule_engine/compiler/effect_model.py +79 -0
  19. capsule_engine/compiler/vocabulary.py +253 -0
  20. capsule_engine/console/__init__.py +10 -0
  21. capsule_engine/console/api.py +251 -0
  22. capsule_engine/console/components.css +406 -0
  23. capsule_engine/console/console.css +130 -0
  24. capsule_engine/console/console.html +51 -0
  25. capsule_engine/console/console.js +330 -0
  26. capsule_engine/console/gallery.html +274 -0
  27. capsule_engine/console/server.py +137 -0
  28. capsule_engine/console/tokens.css +68 -0
  29. capsule_engine/conversation/__init__.py +88 -0
  30. capsule_engine/conversation/capsules.py +268 -0
  31. capsule_engine/conversation/exchange.py +279 -0
  32. capsule_engine/conversation/merkle.py +80 -0
  33. capsule_engine/conversation/session.py +101 -0
  34. capsule_engine/envcompat.py +15 -0
  35. capsule_engine/events/__init__.py +14 -0
  36. capsule_engine/events/capsule.py +133 -0
  37. capsule_engine/examples/__init__.py +9 -0
  38. capsule_engine/examples/data/tau2_airline/LICENSE-tau2-bench +21 -0
  39. capsule_engine/examples/data/tau2_airline/PROVENANCE.json +70 -0
  40. capsule_engine/examples/data/tau2_airline/hand_labels.json +893 -0
  41. capsule_engine/examples/data/tau2_airline/pilot1_live_gemini-2-5-flash_airline_shift1.jsonl +190 -0
  42. capsule_engine/examples/data/tau2_airline/tau2_committed_claude-3-7-sonnet_airline_trial0.jsonl +556 -0
  43. capsule_engine/examples/data/tau2_airline/tau2_committed_gpt-4-1-mini_airline_trial0.jsonl +480 -0
  44. capsule_engine/examples/data/tau2_airline/tau2_committed_gpt-4-1_airline_trial0.jsonl +496 -0
  45. capsule_engine/examples/data/tau2_airline/tau2_committed_o4-mini_airline_trial0.jsonl +392 -0
  46. capsule_engine/examples/data/tau2_airline/tau2_conversations_claude-3-7-sonnet_airline_4trials.jsonl +200 -0
  47. capsule_engine/examples/tau2_airline_reference.py +460 -0
  48. capsule_engine/examples/tau2_conversation_exchange.py +92 -0
  49. capsule_engine/folds/__init__.py +104 -0
  50. capsule_engine/folds/account_core.py +89 -0
  51. capsule_engine/folds/approval_latency.py +86 -0
  52. capsule_engine/folds/catalog.py +79 -0
  53. capsule_engine/folds/catalog_defs/actions.count_by_developer.yaml +10 -0
  54. capsule_engine/folds/catalog_defs/actions.executed_count.yaml +16 -0
  55. capsule_engine/folds/catalog_defs/actions.last_decision.yaml +12 -0
  56. capsule_engine/folds/catalog_defs/counterparty.seen_before.v2.yaml +34 -0
  57. capsule_engine/folds/catalog_defs/counterparty.seen_before.v3.yaml +38 -0
  58. capsule_engine/folds/catalog_defs/counterparty.seen_before.yaml +28 -0
  59. capsule_engine/folds/catalog_defs/disclosure.class_seen.yaml +29 -0
  60. capsule_engine/folds/catalog_defs/disclosure.statement_seen.yaml +32 -0
  61. capsule_engine/folds/catalog_defs/hold.active_exposure.yaml +44 -0
  62. capsule_engine/folds/catalog_defs/spend.weekly.v2.yaml +38 -0
  63. capsule_engine/folds/catalog_defs/spend.weekly.v3.1.yaml +71 -0
  64. capsule_engine/folds/catalog_defs/spend.weekly.v3.yaml +76 -0
  65. capsule_engine/folds/catalog_defs/spend.weekly.yaml +33 -0
  66. capsule_engine/folds/counterparty_signals.py +179 -0
  67. capsule_engine/folds/definition.py +421 -0
  68. capsule_engine/folds/duration.py +16 -0
  69. capsule_engine/folds/engine.py +436 -0
  70. capsule_engine/folds/errors.py +44 -0
  71. capsule_engine/folds/loader.py +24 -0
  72. capsule_engine/folds/ordering.py +143 -0
  73. capsule_engine/folds/paths.py +25 -0
  74. capsule_engine/folds/record_type_coverage.py +58 -0
  75. capsule_engine/folds/reducers.py +75 -0
  76. capsule_engine/folds/retention_continuity.py +117 -0
  77. capsule_engine/folds/set_membership.py +59 -0
  78. capsule_engine/folds/taxonomy.py +231 -0
  79. capsule_engine/guards/__init__.py +59 -0
  80. capsule_engine/guards/action.py +446 -0
  81. capsule_engine/guards/action_taxonomy.json +27 -0
  82. capsule_engine/guards/action_taxonomy_v2.json +27 -0
  83. capsule_engine/guards/action_taxonomy_v3.json +27 -0
  84. capsule_engine/guards/action_taxonomy_v4.json +27 -0
  85. capsule_engine/guards/action_taxonomy_v5.json +27 -0
  86. capsule_engine/guards/capsule.py +377 -0
  87. capsule_engine/guards/checks/__init__.py +268 -0
  88. capsule_engine/guards/checks/action_class_gate.py +199 -0
  89. capsule_engine/guards/checks/base.py +33 -0
  90. capsule_engine/guards/checks/caps.py +517 -0
  91. capsule_engine/guards/checks/channel_change.py +64 -0
  92. capsule_engine/guards/checks/commitment.py +41 -0
  93. capsule_engine/guards/checks/counterparty_identity_change.py +95 -0
  94. capsule_engine/guards/checks/counterparty_list.py +176 -0
  95. capsule_engine/guards/checks/counterparty_seen_before.py +160 -0
  96. capsule_engine/guards/checks/credential_pattern.py +73 -0
  97. capsule_engine/guards/checks/dedupe.py +259 -0
  98. capsule_engine/guards/checks/destination_rail.py +120 -0
  99. capsule_engine/guards/checks/field_change_count.py +100 -0
  100. capsule_engine/guards/checks/offer_expiry.py +134 -0
  101. capsule_engine/guards/checks/plan_containment.py +180 -0
  102. capsule_engine/guards/checks/price_floor.py +211 -0
  103. capsule_engine/guards/checks/promise_never.py +236 -0
  104. capsule_engine/guards/checks/promise_requires_approval.py +214 -0
  105. capsule_engine/guards/checks/recipient_role.py +117 -0
  106. capsule_engine/guards/checks/recurring_charge.py +49 -0
  107. capsule_engine/guards/checks/refundability.py +46 -0
  108. capsule_engine/guards/checks/release_on_acceptance.py +286 -0
  109. capsule_engine/guards/checks/required_disclosure.py +233 -0
  110. capsule_engine/guards/checks/single_commitment.py +221 -0
  111. capsule_engine/guards/checks/task_authority.py +182 -0
  112. capsule_engine/guards/checks/upfront_amount.py +71 -0
  113. capsule_engine/guards/checks/verify_before_dispatch.py +75 -0
  114. capsule_engine/guards/classes.py +393 -0
  115. capsule_engine/guards/engine.py +926 -0
  116. capsule_engine/guards/history_state.py +127 -0
  117. capsule_engine/guards/plan.py +237 -0
  118. capsule_engine/guards/revocation.py +120 -0
  119. capsule_engine/guards/signing.py +60 -0
  120. capsule_engine/guards/statements.py +62 -0
  121. capsule_engine/guards/tool_call.py +83 -0
  122. capsule_engine/guards/wickets/__init__.py +23 -0
  123. capsule_engine/guards/wickets/catalog.py +75 -0
  124. capsule_engine/guards/wickets/catalog_defs/action_class_gate.v1.1.yaml +38 -0
  125. capsule_engine/guards/wickets/catalog_defs/action_class_gate.v1.2.yaml +52 -0
  126. capsule_engine/guards/wickets/catalog_defs/action_class_gate.yaml +34 -0
  127. capsule_engine/guards/wickets/catalog_defs/caps.v2.yaml +30 -0
  128. capsule_engine/guards/wickets/catalog_defs/caps.v3.yaml +49 -0
  129. capsule_engine/guards/wickets/catalog_defs/caps.v4.yaml +45 -0
  130. capsule_engine/guards/wickets/catalog_defs/caps.v5.1.yaml +53 -0
  131. capsule_engine/guards/wickets/catalog_defs/caps.v5.yaml +43 -0
  132. capsule_engine/guards/wickets/catalog_defs/caps.yaml +17 -0
  133. capsule_engine/guards/wickets/catalog_defs/caps_holds.yaml +18 -0
  134. capsule_engine/guards/wickets/catalog_defs/channel_change.v1.1.yaml +18 -0
  135. capsule_engine/guards/wickets/catalog_defs/channel_change.yaml +10 -0
  136. capsule_engine/guards/wickets/catalog_defs/counterparty_identity_change.yaml +9 -0
  137. capsule_engine/guards/wickets/catalog_defs/counterparty_list.yaml +20 -0
  138. capsule_engine/guards/wickets/catalog_defs/counterparty_seen_before.v2.yaml +15 -0
  139. capsule_engine/guards/wickets/catalog_defs/counterparty_seen_before.v3.yaml +23 -0
  140. capsule_engine/guards/wickets/catalog_defs/counterparty_seen_before.v4.yaml +26 -0
  141. capsule_engine/guards/wickets/catalog_defs/counterparty_seen_before.yaml +14 -0
  142. capsule_engine/guards/wickets/catalog_defs/credential_pattern.yaml +14 -0
  143. capsule_engine/guards/wickets/catalog_defs/dedupe.yaml +19 -0
  144. capsule_engine/guards/wickets/catalog_defs/destination_rail.seller.v1.1.yaml +32 -0
  145. capsule_engine/guards/wickets/catalog_defs/destination_rail.seller.yaml +10 -0
  146. capsule_engine/guards/wickets/catalog_defs/destination_rail.yaml +9 -0
  147. capsule_engine/guards/wickets/catalog_defs/hold_reconcile.yaml +14 -0
  148. capsule_engine/guards/wickets/catalog_defs/material_fields_changed.v1.1.yaml +22 -0
  149. capsule_engine/guards/wickets/catalog_defs/material_fields_changed.yaml +14 -0
  150. capsule_engine/guards/wickets/catalog_defs/offer_expiry.v1.1.yaml +31 -0
  151. capsule_engine/guards/wickets/catalog_defs/offer_expiry.yaml +24 -0
  152. capsule_engine/guards/wickets/catalog_defs/offer_fields_changed.v1.1.yaml +22 -0
  153. capsule_engine/guards/wickets/catalog_defs/offer_fields_changed.yaml +10 -0
  154. capsule_engine/guards/wickets/catalog_defs/price_floor.yaml +32 -0
  155. capsule_engine/guards/wickets/catalog_defs/promise_never.v1.1.yaml +64 -0
  156. capsule_engine/guards/wickets/catalog_defs/promise_never.yaml +16 -0
  157. capsule_engine/guards/wickets/catalog_defs/promise_requires_approval.v1.1.yaml +26 -0
  158. capsule_engine/guards/wickets/catalog_defs/promise_requires_approval.yaml +21 -0
  159. capsule_engine/guards/wickets/catalog_defs/recipient_role.seller.v1.1.yaml +23 -0
  160. capsule_engine/guards/wickets/catalog_defs/recipient_role.seller.v1.2.yaml +24 -0
  161. capsule_engine/guards/wickets/catalog_defs/recipient_role.seller.yaml +10 -0
  162. capsule_engine/guards/wickets/catalog_defs/recipient_role.v1.1.yaml +26 -0
  163. capsule_engine/guards/wickets/catalog_defs/recipient_role.yaml +11 -0
  164. capsule_engine/guards/wickets/catalog_defs/recipient_seen_before.yaml +16 -0
  165. capsule_engine/guards/wickets/catalog_defs/recurring_charge.yaml +9 -0
  166. capsule_engine/guards/wickets/catalog_defs/refundability.v1.1.yaml +15 -0
  167. capsule_engine/guards/wickets/catalog_defs/refundability.yaml +7 -0
  168. capsule_engine/guards/wickets/catalog_defs/release_on_acceptance.seller.v1.1.yaml +44 -0
  169. capsule_engine/guards/wickets/catalog_defs/release_on_acceptance.seller.v1.2.yaml +63 -0
  170. capsule_engine/guards/wickets/catalog_defs/release_on_acceptance.seller.yaml +36 -0
  171. capsule_engine/guards/wickets/catalog_defs/required_disclosure.v1.1.yaml +36 -0
  172. capsule_engine/guards/wickets/catalog_defs/required_disclosure.v1.2.yaml +42 -0
  173. capsule_engine/guards/wickets/catalog_defs/required_disclosure.yaml +25 -0
  174. capsule_engine/guards/wickets/catalog_defs/single_commitment.seller.yaml +14 -0
  175. capsule_engine/guards/wickets/catalog_defs/task_authority.v1.1.yaml +20 -0
  176. capsule_engine/guards/wickets/catalog_defs/task_authority.yaml +8 -0
  177. capsule_engine/guards/wickets/catalog_defs/upfront_amount.v1.1.yaml +19 -0
  178. capsule_engine/guards/wickets/catalog_defs/upfront_amount.yaml +11 -0
  179. capsule_engine/guards/wickets/catalog_defs/verify_before_dispatch.yaml +9 -0
  180. capsule_engine/guards/wickets/definition.py +164 -0
  181. capsule_engine/guards/wickets/errors.py +18 -0
  182. capsule_engine/guards/wickets/loader.py +26 -0
  183. capsule_engine/guards/wickets/retired.py +62 -0
  184. capsule_engine/holds/__init__.py +35 -0
  185. capsule_engine/holds/capsules.py +266 -0
  186. capsule_engine/holds/engine.py +476 -0
  187. capsule_engine/holds/errors.py +29 -0
  188. capsule_engine/holds/policy.py +62 -0
  189. capsule_engine/holds/scope.py +47 -0
  190. capsule_engine/mcp/__init__.py +16 -0
  191. capsule_engine/mcp/config.py +117 -0
  192. capsule_engine/mcp/server.py +338 -0
  193. capsule_engine/mcp/tools.py +424 -0
  194. capsule_engine/packaging.py +60 -0
  195. capsule_engine/packs/__init__.py +45 -0
  196. capsule_engine/packs/backfill_coverage.py +238 -0
  197. capsule_engine/packs/catalog/airline-engagement/AI-BOOTSTRAP.md +53 -0
  198. capsule_engine/packs/catalog/airline-engagement/folds/session_close.yaml +8 -0
  199. capsule_engine/packs/catalog/airline-engagement/pack.yaml +146 -0
  200. capsule_engine/packs/catalog/eu-ai-act/fixtures/trace/good_execution.json +36 -0
  201. capsule_engine/packs/catalog/eu-ai-act/fixtures/trace/oversight_declared.json +36 -0
  202. capsule_engine/packs/catalog/eu-ai-act/fixtures/trace/tampered_execution.json +36 -0
  203. capsule_engine/packs/catalog/eu-ai-act/fixtures/trace/trusted_issuer.jwk.json +5 -0
  204. capsule_engine/packs/catalog/eu-ai-act/obligations-pack-note.md +68 -0
  205. capsule_engine/packs/catalog/eu-ai-act/obligations-register.yaml +761 -0
  206. capsule_engine/packs/catalog/eu-ai-act/pack.yaml +88 -0
  207. capsule_engine/packs/catalog/eu-ai-act/register.yaml +96 -0
  208. capsule_engine/packs/catalog/eu-ai-act-deterministic/fixtures/synthetic_internal_assist_sample.jsonl +6 -0
  209. capsule_engine/packs/catalog/eu-ai-act-deterministic/pack.yaml +580 -0
  210. capsule_engine/packs/catalog/everyday/AI-BOOTSTRAP.md +194 -0
  211. capsule_engine/packs/catalog/everyday/fixtures/mini_ledger.jsonl +45 -0
  212. capsule_engine/packs/catalog/everyday/pack.yaml +480 -0
  213. capsule_engine/packs/catalog/payments-safety/AI-BOOTSTRAP.md +83 -0
  214. capsule_engine/packs/catalog/payments-safety/fixtures/mini_ledger.jsonl +8 -0
  215. capsule_engine/packs/catalog/payments-safety/folds/spend_weekly.yaml +29 -0
  216. capsule_engine/packs/catalog/payments-safety/pack.yaml +112 -0
  217. capsule_engine/packs/catalog/seller/fixtures/mini_ledger.jsonl +83 -0
  218. capsule_engine/packs/catalog/seller/pack.yaml +503 -0
  219. capsule_engine/packs/catalog/standard-vendor/AI-BOOTSTRAP.md +70 -0
  220. capsule_engine/packs/catalog/standard-vendor/folds/session_close.yaml +8 -0
  221. capsule_engine/packs/catalog/standard-vendor/pack.yaml +466 -0
  222. capsule_engine/packs/contract_diff.py +809 -0
  223. capsule_engine/packs/contract_validate.py +185 -0
  224. capsule_engine/packs/corpus_verify.py +126 -0
  225. capsule_engine/packs/enforce.py +81 -0
  226. capsule_engine/packs/errors.py +159 -0
  227. capsule_engine/packs/eu_ai_act_trace_field_map.py +46 -0
  228. capsule_engine/packs/install.py +266 -0
  229. capsule_engine/packs/loader.py +1462 -0
  230. capsule_engine/packs/measurability_report.py +280 -0
  231. capsule_engine/packs/obligation_results.py +72 -0
  232. capsule_engine/packs/pins.py +92 -0
  233. capsule_engine/packs/schema.py +1053 -0
  234. capsule_engine/packs/thresholds.py +146 -0
  235. capsule_engine/packs/trace_attainment.py +188 -0
  236. capsule_engine/packs/trace_reader.py +104 -0
  237. capsule_engine/policy/__init__.py +37 -0
  238. capsule_engine/policy/activation.py +87 -0
  239. capsule_engine/policy/catalog_defs/default.yaml +23 -0
  240. capsule_engine/policy/catalog_defs/holds.yaml +27 -0
  241. capsule_engine/policy/errors.py +46 -0
  242. capsule_engine/policy/limits.py +287 -0
  243. capsule_engine/policy/loader.py +26 -0
  244. capsule_engine/policy/manifest.py +289 -0
  245. capsule_engine/policy/profile.py +281 -0
  246. capsule_engine/policy/resolve.py +224 -0
  247. capsule_engine/register/__init__.py +39 -0
  248. capsule_engine/register/compiler.py +219 -0
  249. capsule_engine/register/errors.py +40 -0
  250. capsule_engine/register/loader.py +247 -0
  251. capsule_engine/register/schema.py +129 -0
  252. capsule_engine/registry/__init__.py +19 -0
  253. capsule_engine/registry/conventions.json +162 -0
  254. capsule_engine/registry/conventions.py +188 -0
  255. capsule_engine/registry/cpb_registry.json +78 -0
  256. capsule_engine/report/__init__.py +62 -0
  257. capsule_engine/report/build.py +267 -0
  258. capsule_engine/report/coverage.py +777 -0
  259. capsule_engine/report/errors.py +35 -0
  260. capsule_engine/report/live_check.py +126 -0
  261. capsule_engine/report/live_history.py +420 -0
  262. capsule_engine/report/model.py +95 -0
  263. capsule_engine/report/render.py +467 -0
  264. capsule_engine/report/replay.py +1677 -0
  265. capsule_engine/report/result.py +504 -0
  266. capsule_engine/report/result_from_folds.py +222 -0
  267. capsule_engine/report/result_from_layers.py +670 -0
  268. capsule_engine/report/sale_bundle.py +864 -0
  269. capsule_engine/report/static/verify.js +451 -0
  270. capsule_engine/schemas/evidence-contract-v0.json +383 -0
  271. capsule_engine/schemas/vendor/epistemic-types.json +21 -0
  272. capsule_engine/schemas/vendor/evidence-result-v0.json +463 -0
  273. capsule_engine/telemetry/__init__.py +9 -0
  274. capsule_engine/telemetry/consent.py +39 -0
  275. capsule_engine/telemetry/events.py +93 -0
  276. capsule_engine/telemetry/fixtures/synthetic_events.jsonl +45 -0
  277. capsule_engine/telemetry/funnel.py +147 -0
  278. capsule_engine/telemetry/record.py +106 -0
  279. capsule_engine/telemetry/sink.py +61 -0
  280. capsule_engine/telemetry/state.py +60 -0
  281. capsule_engine/tenants.py +327 -0
  282. capsule_engine-0.1.0.dist-info/METADATA +47 -0
  283. capsule_engine-0.1.0.dist-info/RECORD +288 -0
  284. capsule_engine-0.1.0.dist-info/WHEEL +5 -0
  285. capsule_engine-0.1.0.dist-info/entry_points.txt +2 -0
  286. capsule_engine-0.1.0.dist-info/licenses/LICENSE +202 -0
  287. capsule_engine-0.1.0.dist-info/licenses/capsule_engine/examples/data/tau2_airline/LICENSE-tau2-bench +21 -0
  288. capsule_engine-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,406 @@
1
+ /* SPDX-License-Identifier: Apache-2.0
2
+ *
3
+ * Component library implementing the Visual Language Spec's product laws.
4
+ * Requires tokens.css to be loaded first.
5
+ *
6
+ * Every rule that touches --asg-brick is confined to the "verification
7
+ * failure" components at the bottom of this file (evaluation-fail-card,
8
+ * verify-stage--fail, staleness-chip--stale-beyond-bound) -- see the
9
+ * file-level comment above that section for why the staleness-bound
10
+ * variant is included, and tests/test_console_product_laws.py for the
11
+ * mechanical check that no other rule in this file references it.
12
+ */
13
+
14
+ * { box-sizing: border-box; }
15
+
16
+ body {
17
+ margin: 0;
18
+ background: var(--asg-cream);
19
+ color: var(--asg-text-body);
20
+ font-family: var(--asg-font-sans);
21
+ font-weight: 300;
22
+ -webkit-font-smoothing: antialiased;
23
+ }
24
+
25
+ .mono { font-family: var(--asg-font-mono); }
26
+ .serif { font-family: var(--asg-font-display); }
27
+
28
+ .eyebrow {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ gap: 8px;
32
+ font-family: var(--asg-font-sans);
33
+ font-size: var(--asg-eyebrow-size);
34
+ font-weight: 500;
35
+ letter-spacing: var(--asg-eyebrow-tracking);
36
+ text-transform: uppercase;
37
+ color: var(--asg-amber);
38
+ }
39
+ .eyebrow::before {
40
+ content: "";
41
+ width: 6px;
42
+ height: 6px;
43
+ background: var(--asg-amber);
44
+ border-radius: 50%;
45
+ }
46
+
47
+ /* ════════════════════════════════════════════════════════════════════
48
+ * 1 · EVALUATION-CLASS MARKS -- Rule 2, "never confusable"
49
+ * Three classes, three marks. deterministic = solid sage square + check.
50
+ * model-assisted = dashed amber square + tilde, never a check.
51
+ * manual = bark circle seal + initials. Each owns its shape, color, and
52
+ * frame; none may borrow another's.
53
+ * ════════════════════════════════════════════════════════════════════ */
54
+
55
+ .eval-mark {
56
+ width: 26px;
57
+ height: 26px;
58
+ border-radius: var(--asg-radius-chip);
59
+ display: inline-flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ font-size: 15px;
63
+ font-weight: 600;
64
+ flex-shrink: 0;
65
+ box-sizing: border-box;
66
+ }
67
+
68
+ .eval-mark--deterministic {
69
+ background: var(--asg-sage);
70
+ color: var(--asg-warm-white);
71
+ }
72
+
73
+ .eval-mark--model {
74
+ border: 2px dashed var(--asg-amber);
75
+ color: var(--asg-amber);
76
+ font-size: 16px;
77
+ }
78
+
79
+ .eval-mark--manual {
80
+ border-radius: 50%;
81
+ background: var(--asg-bark);
82
+ color: var(--asg-cream);
83
+ font-family: var(--asg-font-display);
84
+ font-size: 11px;
85
+ font-style: italic;
86
+ }
87
+
88
+ .eval-card {
89
+ background: var(--asg-warm-white);
90
+ border: 1px solid var(--asg-sand);
91
+ border-radius: var(--asg-radius-card-lg);
92
+ padding: 22px;
93
+ display: flex;
94
+ flex-direction: column;
95
+ gap: 14px;
96
+ }
97
+ .eval-card-head { display: flex; align-items: center; gap: 10px; }
98
+ .eval-card-title { font-weight: 600; font-size: 15px; color: var(--asg-bark); }
99
+ .eval-card-kind { font-size: 12px; color: var(--asg-text-muted); }
100
+ .eval-card-body { font-size: 13.5px; line-height: 1.65; color: var(--asg-text-muted); margin: 0; }
101
+
102
+ /* deterministic example: fact + envelope, sage frame */
103
+ .eval-example--deterministic {
104
+ background: rgba(122, 140, 110, 0.08);
105
+ border: 1px solid rgba(122, 140, 110, 0.25);
106
+ border-radius: var(--asg-radius-card-sm);
107
+ padding: 14px 16px;
108
+ }
109
+
110
+ /* model-assisted example: dashed amber frame, italic quoted claim, never a check */
111
+ .eval-example--model {
112
+ background: rgba(200, 97, 26, 0.05);
113
+ border: 1px dashed rgba(200, 97, 26, 0.45);
114
+ border-radius: var(--asg-radius-card-sm);
115
+ padding: 14px 16px;
116
+ }
117
+ .eval-example--model .eval-claim { font-style: italic; color: var(--asg-text-body); }
118
+ /* every number inside a model sentence is a cited deterministic chip, never prose */
119
+ .eval-cited-chip {
120
+ display: inline-flex;
121
+ align-items: baseline;
122
+ gap: 5px;
123
+ font-style: normal;
124
+ font-family: var(--asg-font-mono);
125
+ font-size: 11px;
126
+ color: var(--asg-text-body);
127
+ background: rgba(122, 140, 110, 0.10);
128
+ border: 1px solid rgba(122, 140, 110, 0.3);
129
+ border-radius: var(--asg-radius-pill);
130
+ padding: 2px 9px;
131
+ white-space: nowrap;
132
+ }
133
+ .eval-cited-chip .eval-mark--deterministic-inline { color: var(--asg-sage); font-weight: 600; }
134
+
135
+ /* manual example: signature card, bark seal */
136
+ .eval-example--manual {
137
+ background: var(--asg-cream);
138
+ border: 1px solid var(--asg-sand-dark);
139
+ border-radius: var(--asg-radius-card-sm);
140
+ padding: 14px 16px;
141
+ }
142
+ .eval-signature-name { font-family: var(--asg-font-display); font-style: italic; font-size: 17px; color: var(--asg-bark); }
143
+
144
+ /* ════════════════════════════════════════════════════════════════════
145
+ * 2 · ENVELOPE LINE -- DM Mono, verbatim literal text, not a font choice.
146
+ * Format pinned by capsule_ledger/cli/format.py:format_envelope_line --
147
+ * "fold <id> · records N-M · checkpoint #X · as of <staleness>"
148
+ * ════════════════════════════════════════════════════════════════════ */
149
+
150
+ .envelope-line {
151
+ font-family: var(--asg-font-mono);
152
+ font-size: 11px;
153
+ color: var(--asg-sage);
154
+ line-height: 1.7;
155
+ }
156
+ .envelope-line--muted { color: var(--asg-text-muted); }
157
+ .envelope-line--amber { color: var(--asg-amber); }
158
+
159
+ /* ════════════════════════════════════════════════════════════════════
160
+ * 3 · RUNG CHIP -- Rule 3, "degradation shown, not hidden"
161
+ * Five rungs: standalone -> countersigned -> locally receipted ->
162
+ * counterparty-visible -> independently witnessed. Orthogonal to
163
+ * evaluation class. Downgrades show the rung *held*, never the hoped-for
164
+ * one ("witnessed 1 of 3 · retrying").
165
+ * ════════════════════════════════════════════════════════════════════ */
166
+
167
+ .rung-row {
168
+ display: grid;
169
+ grid-template-columns: 44px 220px 1fr 150px;
170
+ gap: 20px;
171
+ align-items: center;
172
+ padding: 16px 20px;
173
+ border: 1px solid var(--asg-sand);
174
+ background: var(--asg-warm-white);
175
+ }
176
+ .rung-dot-wrap { display: flex; justify-content: center; }
177
+ .rung-dot { border-radius: 50%; box-sizing: border-box; display: block; }
178
+ .rung-name { font-weight: 600; font-size: 14.5px; color: var(--asg-bark); }
179
+ .rung-mode { font-family: var(--asg-font-mono); font-size: 11px; color: var(--asg-text-muted); margin-top: 2px; }
180
+ .rung-plain { font-size: 13.5px; line-height: 1.6; color: var(--asg-text-muted); }
181
+
182
+ /* the rung chip: a compact standalone label (mono), used inline in headers/rows */
183
+ .rung-chip {
184
+ display: inline-flex;
185
+ align-items: center;
186
+ gap: 8px;
187
+ font-family: var(--asg-font-mono);
188
+ font-size: 11.5px;
189
+ color: var(--asg-text-body);
190
+ background: var(--asg-cream);
191
+ border: 1px solid var(--asg-sand);
192
+ border-radius: var(--asg-radius-pill);
193
+ padding: 5px 12px;
194
+ }
195
+ .rung-chip .rung-dot { width: 8px; height: 8px; }
196
+
197
+ /* "rung held" -- a downgrade in progress. Amber (attention, retrying),
198
+ * never brick: this is degraded assurance, not a verification failure. */
199
+ .rung-chip--held {
200
+ color: var(--asg-amber);
201
+ background: rgba(200, 97, 26, 0.05);
202
+ border: 1px dashed rgba(200, 97, 26, 0.45);
203
+ }
204
+ .rung-chip--held .rung-dot { background: var(--asg-amber); animation: asg-pulse 1.6s var(--asg-ease) infinite; }
205
+
206
+ @keyframes asg-pulse {
207
+ 0%, 100% { opacity: 1; transform: scale(1); }
208
+ 50% { opacity: .4; transform: scale(.6); }
209
+ }
210
+
211
+ /* ════════════════════════════════════════════════════════════════════
212
+ * 4 · STALENESS CHIP -- Rule 3, every aggregate carries its checkpoint age.
213
+ * "stale · older than policy bound" is the one deliberate brick use
214
+ * outside the failure-stage cards -- copied verbatim from the Visual
215
+ * Language Spec file (section 5, "Shared furniture"), and consistent
216
+ * with the HITL Bridge screen's stale-beyond-bound state (brick banner,
217
+ * decide buttons locked). Past its policy bound, an aggregate's
218
+ * freshness claim can no longer be trusted -- the design treats that as
219
+ * failure-adjacent, not merely a normal degraded state like a rung hold.
220
+ * ════════════════════════════════════════════════════════════════════ */
221
+
222
+ .staleness-chip {
223
+ display: inline-flex;
224
+ align-items: center;
225
+ font-family: var(--asg-font-mono);
226
+ font-size: 11.5px;
227
+ border-radius: var(--asg-radius-pill);
228
+ padding: 4px 12px;
229
+ }
230
+
231
+ .staleness-chip--fresh {
232
+ color: var(--asg-text-body);
233
+ background: var(--asg-cream);
234
+ border: 1px solid var(--asg-sand);
235
+ }
236
+
237
+ .staleness-chip--refreshing {
238
+ color: var(--asg-text-body);
239
+ background: var(--asg-cream);
240
+ border: 1px solid var(--asg-sand);
241
+ }
242
+
243
+ .staleness-chip--stale-beyond-bound {
244
+ color: var(--asg-brick);
245
+ background: rgba(169, 63, 43, 0.04);
246
+ border: 1px solid rgba(169, 63, 43, 0.35);
247
+ }
248
+
249
+ /* ════════════════════════════════════════════════════════════════════
250
+ * 5 · VERDICT CHIPS -- presentational categories (Local Console screen).
251
+ * These are display-layer labels, distinct from the data-layer
252
+ * disposition.decision / verdict_class tokens -- do not conflate.
253
+ *
254
+ * Exact colors for confirmed/blocked/needs-decision are given verbatim
255
+ * in the design handoff (README's Local Console section + the Visual
256
+ * Language Spec's evaluation-class and refusal treatments). The
257
+ * handoff bundle's Local Console screen file (not required reading for
258
+ * this task) is the source for dispatched-unconfirmed/errored; only
259
+ * their shapes ("dashed outline arrow", "outline bang") are given in
260
+ * the README prose, without hex values, so their color here is chosen
261
+ * to stay law-compliant: never brick (§ verification failure only),
262
+ * distinct from amber (§ model-assisted / needs-decision) and sage
263
+ * (§ deterministic / confirmed / blocked).
264
+ * ════════════════════════════════════════════════════════════════════ */
265
+
266
+ .verdict-chip {
267
+ display: inline-flex;
268
+ align-items: center;
269
+ gap: 7px;
270
+ font-family: var(--asg-font-mono);
271
+ font-size: 12px;
272
+ border-radius: var(--asg-radius-pill);
273
+ padding: 5px 13px;
274
+ }
275
+
276
+ .verdict-glyph {
277
+ width: 16px;
278
+ height: 16px;
279
+ border-radius: 4px;
280
+ display: inline-flex;
281
+ align-items: center;
282
+ justify-content: center;
283
+ font-size: 10.5px;
284
+ font-weight: 600;
285
+ flex-shrink: 0;
286
+ }
287
+
288
+ /* confirmed: solid sage check */
289
+ .verdict-chip--confirmed {
290
+ color: var(--asg-bark);
291
+ background: rgba(122, 140, 110, 0.08);
292
+ border: 1px solid rgba(122, 140, 110, 0.25);
293
+ }
294
+ .verdict-chip--confirmed .verdict-glyph { background: var(--asg-sage); color: var(--asg-warm-white); border-radius: 50%; }
295
+
296
+ /* dispatched, unconfirmed: dashed neutral outline + arrow -- in flight,
297
+ * neither positive nor negative yet */
298
+ .verdict-chip--dispatched {
299
+ color: var(--asg-text-muted);
300
+ background: transparent;
301
+ border: 1px dashed var(--asg-sand-dark);
302
+ }
303
+ .verdict-chip--dispatched .verdict-glyph { color: var(--asg-text-muted); background: transparent; }
304
+
305
+ /* blocked/denied: solid sage slashed-circle -- proof the guard ran, NOT
306
+ * a failure. Never brick, never red. */
307
+ .verdict-chip--blocked {
308
+ color: var(--asg-bark);
309
+ background: rgba(122, 140, 110, 0.08);
310
+ border: 1px solid rgba(122, 140, 110, 0.25);
311
+ }
312
+ .verdict-chip--blocked .verdict-glyph { background: var(--asg-sage); color: var(--asg-warm-white); border-radius: 50%; }
313
+
314
+ /* needs decision: dashed amber circle + question mark */
315
+ .verdict-chip--needs-decision {
316
+ color: var(--asg-amber);
317
+ background: rgba(200, 97, 26, 0.05);
318
+ border: 1px dashed rgba(200, 97, 26, 0.45);
319
+ }
320
+ .verdict-chip--needs-decision .verdict-glyph { border: 1.5px dashed var(--asg-amber); color: var(--asg-amber); border-radius: 50%; background: transparent; }
321
+ .verdict-subline { display: block; font-family: var(--asg-font-sans); font-size: 10.5px; font-weight: 300; color: var(--asg-text-muted); margin-top: 2px; }
322
+
323
+ /* errored: plain outline + bang -- a runtime/system error, distinct from
324
+ * a verification failure (brick) and from a refusal (sage) */
325
+ .verdict-chip--errored {
326
+ color: var(--asg-text-body);
327
+ background: transparent;
328
+ border: 1px solid var(--asg-sand-dark);
329
+ }
330
+ .verdict-chip--errored .verdict-glyph { color: var(--asg-text-body); background: transparent; }
331
+
332
+ /* ════════════════════════════════════════════════════════════════════
333
+ * 6 · CLI-ECHO BAR -- standing rule: every GUI filter/action shows its
334
+ * live CLI/API equivalent.
335
+ * ════════════════════════════════════════════════════════════════════ */
336
+
337
+ .cli-echo {
338
+ font-family: var(--asg-font-mono);
339
+ font-size: 11.5px;
340
+ color: var(--asg-text-body);
341
+ background: var(--asg-cream);
342
+ border: 1px solid var(--asg-sand);
343
+ border-radius: 8px;
344
+ padding: 10px 14px;
345
+ display: inline-block;
346
+ }
347
+
348
+ /* ════════════════════════════════════════════════════════════════════
349
+ * 7 · BRICK-FAILURE TREATMENT -- Rule 5: #A93F2B reserved EXCLUSIVELY
350
+ * for verification failure (digest_mismatch / signature_invalid /
351
+ * chain_gap / inclusion_unproven). Refusals/blocks are NOT failures --
352
+ * they wear sage ⊘ (see .verdict-chip--blocked above).
353
+ * ════════════════════════════════════════════════════════════════════ */
354
+
355
+ .fail-card {
356
+ border: 1px solid rgba(169, 63, 43, 0.35);
357
+ border-radius: var(--asg-radius-card-sm);
358
+ padding: 16px 18px;
359
+ background: rgba(169, 63, 43, 0.03);
360
+ }
361
+ .fail-card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
362
+ .fail-icon {
363
+ width: 22px;
364
+ height: 22px;
365
+ border-radius: var(--asg-radius-chip);
366
+ background: var(--asg-brick);
367
+ color: var(--asg-cream);
368
+ display: inline-flex;
369
+ align-items: center;
370
+ justify-content: center;
371
+ font-size: 12px;
372
+ font-weight: 600;
373
+ flex-shrink: 0;
374
+ }
375
+ .fail-stage { font-family: var(--asg-font-mono); font-size: 12px; color: var(--asg-brick); }
376
+ .fail-title { font-size: 14px; font-weight: 500; color: var(--asg-bark); margin-bottom: 4px; }
377
+ .fail-render { font-size: 13px; line-height: 1.6; color: var(--asg-text-muted); }
378
+
379
+ /* the verify ritual: 4 stage rows. pass = sage, fail = brick (ONLY
380
+ * failure use besides fail-card/fail-icon above), skipped = neutral
381
+ * outline -- unreachable is rendered distinctly from disproven. */
382
+ .verify-stage {
383
+ display: flex;
384
+ align-items: center;
385
+ gap: 10px;
386
+ padding: 10px 14px;
387
+ border-bottom: 1px solid var(--asg-sand);
388
+ }
389
+ .verify-stage:last-child { border-bottom: none; }
390
+ .verify-stage-glyph {
391
+ width: 18px;
392
+ height: 18px;
393
+ border-radius: 5px;
394
+ display: inline-flex;
395
+ align-items: center;
396
+ justify-content: center;
397
+ font-size: 11px;
398
+ font-weight: 600;
399
+ flex-shrink: 0;
400
+ }
401
+ .verify-stage-name { font-size: 13px; color: var(--asg-bark); min-width: 120px; }
402
+ .verify-stage-detail { font-size: 12.5px; color: var(--asg-text-muted); }
403
+
404
+ .verify-stage--pass .verify-stage-glyph { background: var(--asg-sage); color: var(--asg-warm-white); }
405
+ .verify-stage--fail .verify-stage-glyph { background: var(--asg-brick); color: var(--asg-cream); }
406
+ .verify-stage--skip .verify-stage-glyph { border: 1px solid var(--asg-sand-dark); color: var(--asg-text-muted); background: transparent; }
@@ -0,0 +1,130 @@
1
+ /* SPDX-License-Identifier: Apache-2.0
2
+ *
3
+ * Layout only for the local console (`capsule console`). Every color,
4
+ * radius, shadow, and font referenced below is a var(--asg-*) token from
5
+ * tokens.css, or a component reused from components.css (verdict chips,
6
+ * eval marks, envelope lines, the verify ritual, the CLI-echo bar) -- this
7
+ * file declares no new visual token and no new hex color literal (see
8
+ * tests/test_console_server_product_laws.py). Requires tokens.css +
9
+ * components.css to be loaded first.
10
+ */
11
+
12
+ .console-wrap { max-width: 1320px; margin: 0 auto; padding: 40px 40px 80px; }
13
+
14
+ .console-header {
15
+ display: flex;
16
+ align-items: baseline;
17
+ justify-content: space-between;
18
+ border-bottom: 1px solid var(--asg-sand);
19
+ padding-bottom: 18px;
20
+ margin-bottom: 20px;
21
+ flex-wrap: wrap;
22
+ gap: 10px;
23
+ }
24
+ .console-title { font-family: var(--asg-font-display); font-size: 26px; font-weight: 700; color: var(--asg-bark); margin: 8px 0 0; }
25
+ .console-checkpoint { color: var(--asg-text-muted); }
26
+
27
+ .console-filters { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 12px; align-items: center; }
28
+ .console-filters input {
29
+ font-family: var(--asg-font-mono);
30
+ font-size: 12px;
31
+ color: var(--asg-text-body);
32
+ background: var(--asg-warm-white);
33
+ border: 1px solid var(--asg-sand);
34
+ border-radius: var(--asg-radius-pill);
35
+ padding: 7px 14px;
36
+ min-width: 140px;
37
+ }
38
+ .console-filters button {
39
+ font-family: var(--asg-font-sans);
40
+ font-size: 12px;
41
+ font-weight: 500;
42
+ color: var(--asg-warm-white);
43
+ background: var(--asg-amber);
44
+ border: none;
45
+ border-radius: var(--asg-radius-pill);
46
+ padding: 8px 18px;
47
+ cursor: pointer;
48
+ }
49
+
50
+ .console-body { display: grid; grid-template-columns: 1.3fr 1fr; gap: 24px; margin-top: 18px; align-items: start; }
51
+
52
+ .console-stream { display: flex; flex-direction: column; gap: 10px; }
53
+ .record-row {
54
+ display: grid;
55
+ grid-template-columns: 90px 1fr auto;
56
+ align-items: center;
57
+ gap: 14px;
58
+ background: var(--asg-warm-white);
59
+ border: 1px solid var(--asg-sand);
60
+ border-radius: var(--asg-radius-card-sm);
61
+ padding: 12px 16px;
62
+ cursor: pointer;
63
+ }
64
+ .record-row:hover { border-color: var(--asg-sand-dark); }
65
+ .record-row.selected { border-color: var(--asg-amber); background: rgba(200, 97, 26, 0.04); }
66
+ .record-fp { font-family: var(--asg-font-mono); font-size: 11px; color: var(--asg-text-muted); }
67
+ .record-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
68
+ .record-action { font-size: 13.5px; color: var(--asg-bark); }
69
+ .record-meta { font-family: var(--asg-font-mono); font-size: 10.5px; color: var(--asg-text-muted); }
70
+ .console-stream-status { font-family: var(--asg-font-mono); font-size: 11px; color: var(--asg-text-muted); margin-top: 4px; }
71
+
72
+ .console-inspector {
73
+ background: var(--asg-warm-white);
74
+ border: 1px solid var(--asg-sand);
75
+ border-radius: var(--asg-radius-card-lg);
76
+ padding: 22px;
77
+ position: sticky;
78
+ top: 20px;
79
+ min-width: 0;
80
+ overflow-wrap: anywhere;
81
+ }
82
+ /* Real fold envelope lines carry the fold's definition digest (a 64-hex
83
+ * string, per cli/format.py's own docstring), much longer than gallery.html's
84
+ * illustrative short example -- this fixed-width sidebar must wrap it. */
85
+ .console-inspector .envelope-line { overflow-wrap: anywhere; }
86
+ .inspector-empty { font-size: 13px; color: var(--asg-text-muted); }
87
+ .inspector-section { margin-bottom: 18px; }
88
+ .inspector-section:last-child { margin-bottom: 0; }
89
+ .inspector-section-title {
90
+ font-family: var(--asg-font-sans);
91
+ font-size: 10.5px;
92
+ font-weight: 600;
93
+ letter-spacing: 1.5px;
94
+ text-transform: uppercase;
95
+ color: var(--asg-text-muted);
96
+ margin-bottom: 8px;
97
+ }
98
+ .inspector-chain-row { font-family: var(--asg-font-mono); font-size: 11.5px; color: var(--asg-text-body); padding: 3px 0; cursor: pointer; background: none; border: none; text-align: left; display: block; }
99
+ .inspector-chain-row:hover { color: var(--asg-amber); }
100
+ .inspector-chain-empty { font-size: 12px; color: var(--asg-text-muted); }
101
+ .inspector-fold-row { display: flex; flex-direction: column; gap: 2px; padding: 6px 0; border-bottom: 1px solid var(--asg-sand); }
102
+ .inspector-fold-row:last-child { border-bottom: none; }
103
+ .inspector-fold-value { font-size: 13px; color: var(--asg-text-body); }
104
+ .inspector-sealed {
105
+ font-family: var(--asg-font-mono);
106
+ font-size: 10.5px;
107
+ color: var(--asg-text-muted);
108
+ background: var(--asg-cream);
109
+ border: 1px solid var(--asg-sand);
110
+ border-radius: var(--asg-radius-card-sm);
111
+ padding: 10px 12px;
112
+ max-height: 220px;
113
+ overflow: auto;
114
+ white-space: pre-wrap;
115
+ word-break: break-all;
116
+ }
117
+ .inspector-check-list { display: flex; flex-wrap: wrap; gap: 8px; }
118
+ .inspector-cli-echo { margin-top: 10px; }
119
+
120
+ .console-links {
121
+ margin-top: 28px;
122
+ padding-top: 18px;
123
+ border-top: 1px solid var(--asg-sand);
124
+ display: flex;
125
+ flex-direction: column;
126
+ gap: 6px;
127
+ font-size: 12px;
128
+ color: var(--asg-text-muted);
129
+ }
130
+ .console-links code { font-family: var(--asg-font-mono); color: var(--asg-text-body); }
@@ -0,0 +1,51 @@
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 console</title>
7
+ <!-- No Google Fonts <link>, matching gallery.html and report/render.py's
8
+ verify surface: this page is served locally and makes no outbound
9
+ network calls. -->
10
+ <link rel="stylesheet" href="tokens.css">
11
+ <link rel="stylesheet" href="components.css">
12
+ <link rel="stylesheet" href="console.css">
13
+ </head>
14
+ <body>
15
+ <div class="console-wrap">
16
+
17
+ <header class="console-header">
18
+ <div>
19
+ <div class="eyebrow">capsule console</div>
20
+ <h1 class="console-title">Record stream</h1>
21
+ </div>
22
+ <div class="console-checkpoint mono" id="checkpoint-line">checkpoint — · as of — · verifies offline</div>
23
+ </header>
24
+
25
+ <div class="console-filters">
26
+ <input type="text" id="filter-agent" placeholder="agent">
27
+ <input type="text" id="filter-verdict" placeholder="verdict">
28
+ <input type="text" id="filter-since" placeholder="since (ISO-8601)">
29
+ <input type="text" id="filter-until" placeholder="until (ISO-8601)">
30
+ <button type="button" id="filter-apply">apply</button>
31
+ </div>
32
+ <div class="cli-echo" id="cli-echo-bar">≡ capsule log</div>
33
+ <div class="console-stream-status" id="console-stream-status"></div>
34
+
35
+ <div class="console-body">
36
+ <div class="console-stream" id="record-stream"></div>
37
+ <aside class="console-inspector" id="inspector">
38
+ <div class="inspector-empty">select a record to inspect it</div>
39
+ </aside>
40
+ </div>
41
+
42
+ <div class="console-links">
43
+ <span class="mono">Deeper views (run locally, offline):</span>
44
+ <span class="mono">dry-run report — <code>capsule guard dry-run --ledger &lt;ledger&gt; --share</code></span>
45
+ <span class="mono">no-account verify — <code>capsule verify --bundle &lt;bundle.json&gt;</code></span>
46
+ </div>
47
+
48
+ </div>
49
+ <script src="console.js"></script>
50
+ </body>
51
+ </html>