@iowarp/clio-coder 0.3.0

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 (226) hide show
  1. package/CHANGELOG.md +407 -0
  2. package/CODE_OF_CONDUCT.md +21 -0
  3. package/CONTRIBUTING.md +224 -0
  4. package/LICENSE +202 -0
  5. package/NOTICE +9 -0
  6. package/README.md +798 -0
  7. package/SECURITY.md +72 -0
  8. package/assets/clio-coder-logo-128.webp +0 -0
  9. package/damage-control-rules.yaml +419 -0
  10. package/dist/acp-UMLFVA3F.js +92 -0
  11. package/dist/agents-Q4MYPMUW.js +91 -0
  12. package/dist/auth-O6HYIJ6J.js +521 -0
  13. package/dist/chunk-262G75JS.js +35 -0
  14. package/dist/chunk-26BZQOAD.js +1281 -0
  15. package/dist/chunk-2J63S4SF.js +508 -0
  16. package/dist/chunk-3DANZDGR.js +717 -0
  17. package/dist/chunk-4UQA7NCT.js +29 -0
  18. package/dist/chunk-527KG6XR.js +497 -0
  19. package/dist/chunk-5LDRNKX2.js +1063 -0
  20. package/dist/chunk-5N2FG33Q.js +25 -0
  21. package/dist/chunk-67MTHP2E.js +135 -0
  22. package/dist/chunk-6CWDTGUC.js +20 -0
  23. package/dist/chunk-7BHLZB3A.js +2115 -0
  24. package/dist/chunk-7RBKDI66.js +348 -0
  25. package/dist/chunk-AMFR5YA3.js +541 -0
  26. package/dist/chunk-BBUH4VAA.js +1224 -0
  27. package/dist/chunk-BYEU76JP.js +899 -0
  28. package/dist/chunk-CLJ5HLUD.js +458 -0
  29. package/dist/chunk-D5YD55AR.js +116 -0
  30. package/dist/chunk-DXQNI4PC.js +61 -0
  31. package/dist/chunk-E3NYWENM.js +1004 -0
  32. package/dist/chunk-GNGDQYDU.js +34688 -0
  33. package/dist/chunk-GOTUR54M.js +9 -0
  34. package/dist/chunk-HBU5MTAM.js +41 -0
  35. package/dist/chunk-HMYNFFY4.js +28 -0
  36. package/dist/chunk-JPOWPFCU.js +1010 -0
  37. package/dist/chunk-JWHCJDCI.js +1215 -0
  38. package/dist/chunk-KBR4MZZR.js +41 -0
  39. package/dist/chunk-KKKPTZLM.js +93 -0
  40. package/dist/chunk-ME6DNWIU.js +66 -0
  41. package/dist/chunk-NI4DEJMC.js +88 -0
  42. package/dist/chunk-O4EJEDHO.js +659 -0
  43. package/dist/chunk-PIDUD6M2.js +31 -0
  44. package/dist/chunk-PS4PFJQP.js +29459 -0
  45. package/dist/chunk-QV47YRF4.js +48 -0
  46. package/dist/chunk-RQDWMVRB.js +279 -0
  47. package/dist/chunk-TFSSEXL6.js +136 -0
  48. package/dist/chunk-TKHQ4DGZ.js +8290 -0
  49. package/dist/chunk-TPOCL34A.js +2876 -0
  50. package/dist/chunk-UGYAX5YI.js +565 -0
  51. package/dist/chunk-UHTSULZS.js +461 -0
  52. package/dist/chunk-UU3R62TT.js +128 -0
  53. package/dist/chunk-UWIJNAOB.js +3906 -0
  54. package/dist/chunk-VOO7NYPP.js +914 -0
  55. package/dist/chunk-VPAWTYLY.js +117 -0
  56. package/dist/chunk-WD6AJM35.js +1216 -0
  57. package/dist/chunk-X3BR7HWV.js +115 -0
  58. package/dist/chunk-X3NE4WVW.js +120 -0
  59. package/dist/chunk-XNISANGE.js +1395 -0
  60. package/dist/chunk-XV4ZJ6ZM.js +3177 -0
  61. package/dist/cli/index.js +236 -0
  62. package/dist/clio-KIQ5SNDS.js +53 -0
  63. package/dist/components-JVHMUBEB.js +653 -0
  64. package/dist/config-ZFCDBMDC.js +372 -0
  65. package/dist/configure-G4E3A2PG.js +27 -0
  66. package/dist/context-CDXTP2MP.js +293 -0
  67. package/dist/context-E3KIFVXI.js +185 -0
  68. package/dist/context-clear-3F4PLXOS.js +102 -0
  69. package/dist/context-index-Q7YSYTR3.js +106 -0
  70. package/dist/docs-YIETIWZI.js +280 -0
  71. package/dist/doctor-M5HJJZOL.js +61 -0
  72. package/dist/domains/agents/builtins/architect.md +33 -0
  73. package/dist/domains/agents/builtins/coder.md +31 -0
  74. package/dist/domains/agents/builtins/context-bootstrap.md +38 -0
  75. package/dist/domains/agents/builtins/debugger.md +30 -0
  76. package/dist/domains/agents/builtins/documenter.md +31 -0
  77. package/dist/domains/agents/builtins/git-master.md +30 -0
  78. package/dist/domains/agents/builtins/provenance.md +30 -0
  79. package/dist/domains/agents/builtins/researcher.md +71 -0
  80. package/dist/domains/agents/builtins/scout.md +42 -0
  81. package/dist/domains/agents/builtins/tester.md +31 -0
  82. package/dist/domains/agents/builtins/verifier.md +30 -0
  83. package/dist/domains/agents/builtins/wiki-writer.md +41 -0
  84. package/dist/eval-B3KZZESM.js +2674 -0
  85. package/dist/evidence-V67CHM35.js +233 -0
  86. package/dist/evolve-YDZSUQYA.js +518 -0
  87. package/dist/extensions-SRG7XCAH.js +207 -0
  88. package/dist/fleet-CA2CRTVG.js +760 -0
  89. package/dist/fleet-preflight-CLIAX7YR.js +21 -0
  90. package/dist/init-2OZDJE2D.js +227 -0
  91. package/dist/memory-3PIQQAKX.js +207 -0
  92. package/dist/models-DY35XI7Y.js +237 -0
  93. package/dist/paths-5OMXW7Z4.js +57 -0
  94. package/dist/preload-KZVHET2B.js +11 -0
  95. package/dist/reset-PIFYNOS3.js +216 -0
  96. package/dist/run-3VSPP24F.js +735 -0
  97. package/dist/share-D36RQCXM.js +241 -0
  98. package/dist/skills-F2MRLELY.js +445 -0
  99. package/dist/skills-eval-E2ZTW4PL.js +932 -0
  100. package/dist/targets-DZMEZAH4.js +977 -0
  101. package/dist/trace-7NYCUI2J.js +250 -0
  102. package/dist/uninstall-AD3JWHBB.js +322 -0
  103. package/dist/upgrade-WYYBKGDY.js +301 -0
  104. package/dist/usage-ULIDAGFF.js +755 -0
  105. package/dist/version-ROZ6CZKH.js +16 -0
  106. package/dist/wiki-generate-PKFIX6OB.js +377 -0
  107. package/dist/worker/entry.js +1739 -0
  108. package/docs/README.md +93 -0
  109. package/docs/acp.md +120 -0
  110. package/docs/alcf-provider.md +72 -0
  111. package/docs/architecture.md +172 -0
  112. package/docs/artifact-versions.md +54 -0
  113. package/docs/built-in-agents.md +265 -0
  114. package/docs/capacity-and-scheduling.md +97 -0
  115. package/docs/commands-and-modes.md +554 -0
  116. package/docs/config-knobs-audit.md +115 -0
  117. package/docs/configuration-and-targets.md +812 -0
  118. package/docs/context-engine.md +236 -0
  119. package/docs/dispatch-architecture-rationale.md +126 -0
  120. package/docs/documentation-coverage.md +46 -0
  121. package/docs/documentation-guide.md +166 -0
  122. package/docs/environment-variables.md +105 -0
  123. package/docs/eval-runner.md +205 -0
  124. package/docs/evals-internal.md +298 -0
  125. package/docs/evidence-and-memory.md +243 -0
  126. package/docs/evolution.md +143 -0
  127. package/docs/exit-codes-and-output.md +74 -0
  128. package/docs/extensions-and-sharing.md +306 -0
  129. package/docs/fleet-demo-runbook.md +179 -0
  130. package/docs/fleet-dispatch.md +591 -0
  131. package/docs/glossary.md +75 -0
  132. package/docs/html/agents_blueprint.html +936 -0
  133. package/docs/html/alcf_blueprint.html +324 -0
  134. package/docs/html/architecture_blueprint.html +850 -0
  135. package/docs/html/commands_blueprint.html +794 -0
  136. package/docs/html/config_knobs_audit_blueprint.html +178 -0
  137. package/docs/html/configuration_blueprint.html +1080 -0
  138. package/docs/html/context_blueprint.html +603 -0
  139. package/docs/html/documentation_blueprint.html +832 -0
  140. package/docs/html/environment_blueprint.html +404 -0
  141. package/docs/html/eval_blueprint.html +743 -0
  142. package/docs/html/evals_internal_blueprint.html +190 -0
  143. package/docs/html/evolution_blueprint.html +674 -0
  144. package/docs/html/extensions_blueprint.html +2065 -0
  145. package/docs/html/fleet_dispatch_blueprint.html +286 -0
  146. package/docs/html/index.html +919 -0
  147. package/docs/html/lifecycle_blueprint.html +723 -0
  148. package/docs/html/memory_blueprint.html +699 -0
  149. package/docs/html/middleware_blueprint.html +664 -0
  150. package/docs/html/models_blueprint.html +2366 -0
  151. package/docs/html/observability_blueprint.html +683 -0
  152. package/docs/html/provider_adapter_blueprint.html +245 -0
  153. package/docs/html/safety_blueprint.html +1386 -0
  154. package/docs/html/shared.css +571 -0
  155. package/docs/html/shared.js +143 -0
  156. package/docs/html/skills_blueprint.html +671 -0
  157. package/docs/html/soak_blueprint.html +182 -0
  158. package/docs/html/tool_usage_blueprint.html +350 -0
  159. package/docs/html/tools_blueprint.html +2249 -0
  160. package/docs/html/trace_blueprint.html +235 -0
  161. package/docs/html/tui_design_blueprint.html +314 -0
  162. package/docs/html/validation_blueprint.html +961 -0
  163. package/docs/html/worker_dispatch_blueprint.html +231 -0
  164. package/docs/installation-and-lifecycle.md +308 -0
  165. package/docs/middleware-and-components.md +148 -0
  166. package/docs/model-catalog.md +189 -0
  167. package/docs/observability.md +233 -0
  168. package/docs/proactive-memory.md +452 -0
  169. package/docs/prompt-envelope-and-tools.md +142 -0
  170. package/docs/provider-adapter-cookbook.md +148 -0
  171. package/docs/release-cut-checklist.md +138 -0
  172. package/docs/safety-model.md +357 -0
  173. package/docs/scientific-validation.md +105 -0
  174. package/docs/session-lifecycle.md +156 -0
  175. package/docs/skills-marketplace.md +46 -0
  176. package/docs/tool-usage.md +527 -0
  177. package/docs/trace-store.md +132 -0
  178. package/docs/troubleshooting.md +33 -0
  179. package/docs/tui-design.md +239 -0
  180. package/docs/worker-dispatch-mechanics.md +242 -0
  181. package/package.json +132 -0
  182. package/skills/README.md +408 -0
  183. package/skills/git/commit-crafting/SKILL.md +79 -0
  184. package/skills/git/commit-crafting/evals.md +92 -0
  185. package/skills/git/create-pr/SKILL.md +116 -0
  186. package/skills/git/create-pr/evals.md +114 -0
  187. package/skills/git/investigate-issue/SKILL.md +139 -0
  188. package/skills/git/investigate-issue/evals.md +94 -0
  189. package/skills/git/resolve-merge-conflicts/SKILL.md +96 -0
  190. package/skills/git/resolve-merge-conflicts/evals.md +58 -0
  191. package/skills/git/review-changes/SKILL.md +103 -0
  192. package/skills/git/review-changes/evals.md +85 -0
  193. package/skills/git/worktree-create/SKILL.md +92 -0
  194. package/skills/git/worktree-create/evals.md +97 -0
  195. package/skills/git/worktree-create/references/worktree-setup.md +66 -0
  196. package/skills/git/worktree-merge/SKILL.md +95 -0
  197. package/skills/git/worktree-merge/evals.md +114 -0
  198. package/skills/skill-marketplace.json +261 -0
  199. package/skills/workflow/cut-it/SKILL.md +86 -0
  200. package/skills/workflow/cut-it/evals.md +42 -0
  201. package/src/domains/agents/builtins/architect.md +33 -0
  202. package/src/domains/agents/builtins/coder.md +31 -0
  203. package/src/domains/agents/builtins/context-bootstrap.md +38 -0
  204. package/src/domains/agents/builtins/debugger.md +30 -0
  205. package/src/domains/agents/builtins/documenter.md +31 -0
  206. package/src/domains/agents/builtins/git-master.md +30 -0
  207. package/src/domains/agents/builtins/provenance.md +30 -0
  208. package/src/domains/agents/builtins/researcher.md +71 -0
  209. package/src/domains/agents/builtins/scout.md +42 -0
  210. package/src/domains/agents/builtins/tester.md +31 -0
  211. package/src/domains/agents/builtins/verifier.md +30 -0
  212. package/src/domains/agents/builtins/wiki-writer.md +41 -0
  213. package/src/domains/agents/fleets/build-review.md +34 -0
  214. package/src/domains/agents/fleets/build-test.md +35 -0
  215. package/src/domains/agents/fleets/sdlc.md +86 -0
  216. package/src/domains/prompts/fragments/identity/clio-worker.md +11 -0
  217. package/src/domains/prompts/fragments/identity/clio.md +26 -0
  218. package/src/domains/prompts/fragments/operating/contract.md +64 -0
  219. package/src/domains/prompts/fragments/safety/auto-edit.md +14 -0
  220. package/src/domains/prompts/fragments/safety/full-auto.md +14 -0
  221. package/src/domains/prompts/fragments/safety/read-only.md +13 -0
  222. package/src/domains/prompts/fragments/safety/suggest.md +13 -0
  223. package/src/domains/prompts/fragments/wiki/page.md +75 -0
  224. package/src/domains/prompts/fragments/wiki/plan.md +48 -0
  225. package/src/domains/providers/models/cloud-models/alcf.yaml +40 -0
  226. package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +993 -0
@@ -0,0 +1,2249 @@
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.0">
6
+ <title>Clio Coder Prompt Envelope & Tools Blueprint</title>
7
+ <!-- Typography Fonts -->
8
+
9
+ <style>
10
+ :root {
11
+ --bg-dark: #090d16;
12
+ --bg-card: rgba(17, 24, 39, 0.7);
13
+ --border-card: rgba(255, 255, 255, 0.08);
14
+ --text-main: #f3f4f6;
15
+ --text-muted: #9ca3af;
16
+ --text-dark: #4b5563;
17
+
18
+ /* Glowing Neon Colors */
19
+ --color-cyan: #00f0ff;
20
+ --color-cyan-rgb: 0, 240, 255;
21
+ --color-purple: #bd00ff;
22
+ --color-purple-rgb: 189, 0, 255;
23
+ --color-emerald: #10b981;
24
+ --color-emerald-rgb: 16, 185, 129;
25
+ --color-amber: #f59e0b;
26
+ --color-amber-rgb: 245, 158, 11;
27
+ --color-rose: #ef4444;
28
+ --color-rose-rgb: 239, 68, 68;
29
+
30
+ --gradient-main: linear-gradient(135deg, var(--color-cyan), var(--color-purple));
31
+ --shadow-glow: 0 0 20px rgba(var(--color-cyan-rgb), 0.15);
32
+ --font-sans: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif;
33
+ --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
34
+ }
35
+
36
+ * {
37
+ box-sizing: border-box;
38
+ margin: 0;
39
+ padding: 0;
40
+ }
41
+
42
+ body {
43
+ background-color: var(--bg-dark);
44
+ background-image:
45
+ radial-gradient(circle at 5% 15%, rgba(var(--color-cyan-rgb), 0.04) 0%, transparent 35%),
46
+ radial-gradient(circle at 95% 85%, rgba(var(--color-purple-rgb), 0.04) 0%, transparent 35%),
47
+ radial-gradient(circle at 50% 50%, #0c1220 0%, var(--bg-dark) 100%);
48
+ color: var(--text-main);
49
+ font-family: var(--font-sans);
50
+ min-height: 100vh;
51
+ line-height: 1.6;
52
+ overflow-x: hidden;
53
+ }
54
+
55
+ /* Scrollbar */
56
+ ::-webkit-scrollbar {
57
+ width: 8px;
58
+ height: 8px;
59
+ }
60
+ ::-webkit-scrollbar-track {
61
+ background: rgba(255, 255, 255, 0.01);
62
+ }
63
+ ::-webkit-scrollbar-thumb {
64
+ background: rgba(255, 255, 255, 0.08);
65
+ border-radius: 4px;
66
+ }
67
+ ::-webkit-scrollbar-thumb:hover {
68
+ background: rgba(var(--color-cyan-rgb), 0.25);
69
+ }
70
+
71
+ .container {
72
+ max-width: 1400px;
73
+ margin: 0 auto;
74
+ padding: 2rem;
75
+ }
76
+
77
+ /* Header */
78
+ header {
79
+ position: relative;
80
+ margin-bottom: 2.5rem;
81
+ padding-bottom: 2rem;
82
+ border-bottom: 1px solid var(--border-card);
83
+ }
84
+
85
+ .header-top {
86
+ display: flex;
87
+ justify-content: space-between;
88
+ align-items: center;
89
+ flex-wrap: wrap;
90
+ gap: 1rem;
91
+ }
92
+
93
+ .logo-area {
94
+ display: flex;
95
+ align-items: center;
96
+ gap: 1rem;
97
+ }
98
+
99
+ .logo-hex {
100
+ width: 48px;
101
+ height: 48px;
102
+ background: rgba(var(--color-cyan-rgb), 0.1);
103
+ border: 1.5px solid var(--color-cyan);
104
+ border-radius: 12px;
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: center;
108
+ box-shadow: 0 0 15px rgba(var(--color-cyan-rgb), 0.2);
109
+ }
110
+
111
+ .logo-hex img {
112
+ width: 78%;
113
+ height: 78%;
114
+ object-fit: contain;
115
+ filter: drop-shadow(0 0 8px rgba(0, 240, 255, 0.35));
116
+ }
117
+
118
+ h1 {
119
+ font-size: 2.25rem;
120
+ font-weight: 800;
121
+ letter-spacing: -0.04em;
122
+ background: linear-gradient(to right, #ffffff, #c7d2fe, var(--color-cyan));
123
+ -webkit-background-clip: text;
124
+ -webkit-text-fill-color: transparent;
125
+ }
126
+
127
+ .version-tag {
128
+ background: rgba(255, 255, 255, 0.05);
129
+ border: 1px solid var(--border-card);
130
+ border-radius: 9999px;
131
+ padding: 0.25rem 0.85rem;
132
+ font-family: var(--font-mono);
133
+ font-size: 0.85rem;
134
+ color: var(--color-cyan);
135
+ display: flex;
136
+ align-items: center;
137
+ gap: 0.35rem;
138
+ font-weight: 600;
139
+ }
140
+
141
+ .version-dot {
142
+ width: 6px;
143
+ height: 6px;
144
+ background-color: var(--color-emerald);
145
+ border-radius: 50%;
146
+ box-shadow: 0 0 8px var(--color-emerald);
147
+ }
148
+
149
+ .header-desc {
150
+ color: var(--text-muted);
151
+ font-size: 1.05rem;
152
+ margin-top: 0.5rem;
153
+ max-width: 800px;
154
+ }
155
+
156
+ /* Tabs */
157
+ .tabs-nav {
158
+ display: flex;
159
+ gap: 0.75rem;
160
+ margin-bottom: 2rem;
161
+ border-bottom: 1px solid var(--border-card);
162
+ padding-bottom: 0.75rem;
163
+ flex-wrap: wrap;
164
+ }
165
+
166
+ .tab-btn {
167
+ background: rgba(255, 255, 255, 0.02);
168
+ border: 1px solid var(--border-card);
169
+ color: var(--text-muted);
170
+ padding: 0.65rem 1.25rem;
171
+ border-radius: 8px;
172
+ font-weight: 600;
173
+ font-size: 0.95rem;
174
+ cursor: pointer;
175
+ display: flex;
176
+ align-items: center;
177
+ gap: 0.5rem;
178
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
179
+ }
180
+
181
+ .tab-btn:hover {
182
+ background: rgba(255, 255, 255, 0.06);
183
+ color: var(--text-main);
184
+ border-color: rgba(var(--color-cyan-rgb), 0.3);
185
+ }
186
+
187
+ .tab-btn.active {
188
+ background: rgba(var(--color-cyan-rgb), 0.1);
189
+ color: var(--color-cyan);
190
+ border-color: var(--color-cyan);
191
+ box-shadow: 0 0 15px rgba(var(--color-cyan-rgb), 0.1);
192
+ }
193
+
194
+ .tab-pane {
195
+ display: none;
196
+ animation: fadeIn 0.35s ease-out forwards;
197
+ }
198
+
199
+ .tab-pane.active {
200
+ display: block;
201
+ }
202
+
203
+ @keyframes fadeIn {
204
+ from { opacity: 0; transform: translateY(8px); }
205
+ to { opacity: 1; transform: translateY(0); }
206
+ }
207
+
208
+ /* Grid & Cards */
209
+ .grid-2 {
210
+ display: grid;
211
+ grid-template-columns: 1fr 1fr;
212
+ gap: 1.5rem;
213
+ align-items: start;
214
+ }
215
+
216
+ @media (max-width: 1024px) {
217
+ .grid-2 {
218
+ grid-template-columns: 1fr;
219
+ }
220
+ }
221
+
222
+ .glass-card {
223
+ background: var(--bg-card);
224
+ border: 1px solid var(--border-card);
225
+ backdrop-filter: blur(16px);
226
+ -webkit-backdrop-filter: blur(16px);
227
+ border-radius: 12px;
228
+ padding: 1.5rem;
229
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
230
+ margin-bottom: 1.5rem;
231
+ }
232
+
233
+ .card-title {
234
+ font-size: 1.25rem;
235
+ font-weight: 700;
236
+ margin-bottom: 1.25rem;
237
+ display: flex;
238
+ align-items: center;
239
+ gap: 0.5rem;
240
+ color: #ffffff;
241
+ border-left: 3px solid var(--color-cyan);
242
+ padding-left: 0.65rem;
243
+ }
244
+
245
+ .card-subtitle {
246
+ font-size: 0.9rem;
247
+ color: var(--text-muted);
248
+ margin-top: -0.85rem;
249
+ margin-bottom: 1.25rem;
250
+ }
251
+
252
+ /* Inputs Form Controls */
253
+ .form-group {
254
+ margin-bottom: 1.25rem;
255
+ }
256
+
257
+ .form-row {
258
+ display: grid;
259
+ grid-template-columns: 1fr 1fr;
260
+ gap: 1rem;
261
+ margin-bottom: 1.25rem;
262
+ }
263
+
264
+ @media (max-width: 640px) {
265
+ .form-row {
266
+ grid-template-columns: 1fr;
267
+ }
268
+ }
269
+
270
+ label {
271
+ display: block;
272
+ font-size: 0.85rem;
273
+ font-weight: 600;
274
+ margin-bottom: 0.45rem;
275
+ color: var(--text-muted);
276
+ text-transform: uppercase;
277
+ letter-spacing: 0.05em;
278
+ }
279
+
280
+ input[type="text"], input[type="number"], select, textarea {
281
+ width: 100%;
282
+ background: rgba(0, 0, 0, 0.3);
283
+ border: 1px solid var(--border-card);
284
+ border-radius: 6px;
285
+ padding: 0.65rem 0.85rem;
286
+ color: #ffffff;
287
+ font-family: var(--font-sans);
288
+ font-size: 0.9rem;
289
+ outline: none;
290
+ transition: all 0.2s;
291
+ }
292
+
293
+ input:focus, select:focus, textarea:focus {
294
+ border-color: var(--color-cyan);
295
+ box-shadow: 0 0 10px rgba(var(--color-cyan-rgb), 0.15);
296
+ background: rgba(0, 0, 0, 0.4);
297
+ }
298
+
299
+ textarea.code-editor {
300
+ font-family: var(--font-mono);
301
+ font-size: 0.85rem;
302
+ resize: vertical;
303
+ background: rgba(5, 8, 16, 0.6);
304
+ line-height: 1.5;
305
+ }
306
+
307
+ .checkbox-grid {
308
+ display: grid;
309
+ grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
310
+ gap: 0.5rem;
311
+ background: rgba(0, 0, 0, 0.2);
312
+ border: 1px solid var(--border-card);
313
+ border-radius: 6px;
314
+ padding: 0.75rem;
315
+ max-height: 160px;
316
+ overflow-y: auto;
317
+ }
318
+
319
+ .checkbox-label {
320
+ display: flex;
321
+ align-items: center;
322
+ gap: 0.4rem;
323
+ font-size: 0.8rem;
324
+ color: var(--text-main);
325
+ cursor: pointer;
326
+ user-select: none;
327
+ text-transform: none;
328
+ letter-spacing: normal;
329
+ font-weight: 400;
330
+ margin-bottom: 0;
331
+ }
332
+
333
+ .checkbox-label input[type="checkbox"] {
334
+ accent-color: var(--color-cyan);
335
+ cursor: pointer;
336
+ }
337
+
338
+ /* Buttons */
339
+ .btn {
340
+ background: rgba(255, 255, 255, 0.04);
341
+ border: 1px solid var(--border-card);
342
+ color: #ffffff;
343
+ padding: 0.6rem 1.2rem;
344
+ border-radius: 6px;
345
+ font-weight: 600;
346
+ font-size: 0.9rem;
347
+ cursor: pointer;
348
+ transition: all 0.2s;
349
+ display: inline-flex;
350
+ align-items: center;
351
+ gap: 0.5rem;
352
+ }
353
+
354
+ .btn:hover {
355
+ background: rgba(255, 255, 255, 0.08);
356
+ border-color: rgba(var(--color-cyan-rgb), 0.4);
357
+ }
358
+
359
+ .btn-primary {
360
+ background: var(--gradient-main);
361
+ color: #050812;
362
+ border-color: transparent;
363
+ box-shadow: 0 4px 12px rgba(var(--color-cyan-rgb), 0.25);
364
+ }
365
+
366
+ .btn-primary:hover {
367
+ opacity: 0.9;
368
+ transform: translateY(-1px);
369
+ box-shadow: 0 4px 18px rgba(var(--color-cyan-rgb), 0.4);
370
+ }
371
+
372
+ .btn-danger {
373
+ background: rgba(var(--color-rose-rgb), 0.15);
374
+ border-color: var(--color-rose);
375
+ color: #ff8585;
376
+ }
377
+
378
+ .btn-danger:hover {
379
+ background: rgba(var(--color-rose-rgb), 0.25);
380
+ }
381
+
382
+ /* Calculator Results Panels */
383
+ .pressure-panel {
384
+ display: flex;
385
+ flex-direction: column;
386
+ gap: 1rem;
387
+ }
388
+
389
+ .progress-bar-container {
390
+ width: 100%;
391
+ height: 12px;
392
+ background: rgba(255, 255, 255, 0.05);
393
+ border: 1px solid var(--border-card);
394
+ border-radius: 9999px;
395
+ overflow: hidden;
396
+ position: relative;
397
+ }
398
+
399
+ .progress-bar-fill {
400
+ height: 100%;
401
+ width: 0%;
402
+ background: var(--color-emerald);
403
+ border-radius: 9999px;
404
+ transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.3s;
405
+ }
406
+
407
+ .status-pill {
408
+ display: inline-flex;
409
+ align-items: center;
410
+ gap: 0.35rem;
411
+ font-size: 0.8rem;
412
+ font-weight: 700;
413
+ text-transform: uppercase;
414
+ padding: 0.2rem 0.6rem;
415
+ border-radius: 4px;
416
+ background: rgba(255, 255, 255, 0.05);
417
+ border: 1px solid var(--border-card);
418
+ }
419
+
420
+ .pill-cyan { color: var(--color-cyan); border-color: rgba(var(--color-cyan-rgb), 0.3); background: rgba(var(--color-cyan-rgb), 0.05); }
421
+ .pill-emerald { color: var(--color-emerald); border-color: rgba(var(--color-emerald-rgb), 0.3); background: rgba(var(--color-emerald-rgb), 0.05); }
422
+ .pill-amber { color: var(--color-amber); border-color: rgba(var(--color-amber-rgb), 0.3); background: rgba(var(--color-amber-rgb), 0.05); }
423
+ .pill-rose { color: var(--color-rose); border-color: rgba(var(--color-rose-rgb), 0.3); background: rgba(var(--color-rose-rgb), 0.05); }
424
+
425
+ .data-grid {
426
+ display: grid;
427
+ grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
428
+ gap: 1rem;
429
+ margin-bottom: 1rem;
430
+ }
431
+
432
+ .data-card {
433
+ background: rgba(0, 0, 0, 0.2);
434
+ border: 1px solid var(--border-card);
435
+ border-radius: 8px;
436
+ padding: 0.75rem;
437
+ text-align: center;
438
+ }
439
+
440
+ .data-val {
441
+ font-family: var(--font-mono);
442
+ font-size: 1.25rem;
443
+ font-weight: 700;
444
+ margin-bottom: 0.2rem;
445
+ }
446
+
447
+ .data-label {
448
+ font-size: 0.75rem;
449
+ color: var(--text-muted);
450
+ text-transform: uppercase;
451
+ letter-spacing: 0.05em;
452
+ }
453
+
454
+ .segment-table {
455
+ width: 100%;
456
+ border-collapse: collapse;
457
+ font-size: 0.85rem;
458
+ margin-top: 1rem;
459
+ }
460
+
461
+ .segment-table th, .segment-table td {
462
+ border: 1px solid var(--border-card);
463
+ padding: 0.55rem 0.75rem;
464
+ text-align: left;
465
+ }
466
+
467
+ .segment-table th {
468
+ background: rgba(255, 255, 255, 0.03);
469
+ color: var(--text-muted);
470
+ font-weight: 600;
471
+ }
472
+
473
+ .segment-table tr:hover td {
474
+ background: rgba(255, 255, 255, 0.02);
475
+ }
476
+
477
+ .hash-badge {
478
+ font-family: var(--font-mono);
479
+ font-size: 0.75rem;
480
+ background: rgba(0, 0, 0, 0.4);
481
+ border: 1px solid rgba(255,255,255,0.05);
482
+ border-radius: 4px;
483
+ padding: 0.15rem 0.4rem;
484
+ color: #a5b4fc;
485
+ max-width: 100px;
486
+ display: inline-block;
487
+ text-overflow: ellipsis;
488
+ overflow: hidden;
489
+ white-space: nowrap;
490
+ vertical-align: middle;
491
+ }
492
+
493
+ /* Output console */
494
+ .console-out {
495
+ background: #04070e;
496
+ border: 1px solid var(--border-card);
497
+ border-radius: 8px;
498
+ padding: 1rem;
499
+ font-family: var(--font-mono);
500
+ font-size: 0.825rem;
501
+ color: #8bebff;
502
+ max-height: 400px;
503
+ overflow-y: auto;
504
+ white-space: pre-wrap;
505
+ position: relative;
506
+ }
507
+
508
+ .console-header {
509
+ display: flex;
510
+ justify-content: space-between;
511
+ align-items: center;
512
+ margin-bottom: 0.5rem;
513
+ font-family: var(--font-sans);
514
+ font-size: 0.75rem;
515
+ text-transform: uppercase;
516
+ letter-spacing: 0.05em;
517
+ color: var(--text-muted);
518
+ }
519
+
520
+ .copy-btn {
521
+ background: transparent;
522
+ border: none;
523
+ color: var(--color-cyan);
524
+ cursor: pointer;
525
+ font-size: 0.8rem;
526
+ font-weight: 600;
527
+ display: flex;
528
+ align-items: center;
529
+ gap: 0.25rem;
530
+ }
531
+
532
+ .copy-btn:hover {
533
+ text-decoration: underline;
534
+ }
535
+
536
+ /* Preset Scenarios */
537
+ .scenario-grid {
538
+ display: flex;
539
+ gap: 0.5rem;
540
+ margin-bottom: 1.25rem;
541
+ flex-wrap: wrap;
542
+ }
543
+
544
+ .scenario-pill {
545
+ background: rgba(255, 255, 255, 0.03);
546
+ border: 1px solid var(--border-card);
547
+ border-radius: 6px;
548
+ padding: 0.4rem 0.8rem;
549
+ font-size: 0.8rem;
550
+ cursor: pointer;
551
+ transition: all 0.2s;
552
+ color: var(--text-muted);
553
+ font-weight: 500;
554
+ }
555
+
556
+ .scenario-pill:hover {
557
+ background: rgba(var(--color-cyan-rgb), 0.08);
558
+ color: var(--color-cyan);
559
+ border-color: rgba(var(--color-cyan-rgb), 0.3);
560
+ }
561
+
562
+ /* Diagrams Layout */
563
+ .diagrams-container {
564
+ display: flex;
565
+ flex-direction: column;
566
+ gap: 2.5rem;
567
+ }
568
+
569
+ .diagram-card {
570
+ background: var(--bg-card);
571
+ border: 1px solid var(--border-card);
572
+ border-radius: 16px;
573
+ padding: 1.5rem;
574
+ }
575
+
576
+ .diagram-desc {
577
+ font-size: 0.9rem;
578
+ color: var(--text-muted);
579
+ margin-bottom: 1.5rem;
580
+ max-width: 900px;
581
+ }
582
+
583
+ .svg-wrapper {
584
+ width: 100%;
585
+ background: rgba(4, 7, 14, 0.8);
586
+ border: 1px solid var(--border-card);
587
+ border-radius: 12px;
588
+ padding: 1.5rem;
589
+ display: flex;
590
+ justify-content: center;
591
+ align-items: center;
592
+ overflow-x: auto;
593
+ }
594
+
595
+ .svg-wrapper svg {
596
+ max-width: 100%;
597
+ height: auto;
598
+ display: block;
599
+ }
600
+
601
+ /* Tool Call Simulator Details */
602
+ .history-list {
603
+ max-height: 180px;
604
+ overflow-y: auto;
605
+ border: 1px solid var(--border-card);
606
+ border-radius: 6px;
607
+ padding: 0.5rem;
608
+ background: rgba(0, 0, 0, 0.2);
609
+ }
610
+
611
+ .history-item {
612
+ font-size: 0.78rem;
613
+ font-family: var(--font-mono);
614
+ padding: 0.35rem;
615
+ border-bottom: 1px solid rgba(255,255,255,0.03);
616
+ display: flex;
617
+ justify-content: space-between;
618
+ align-items: center;
619
+ }
620
+
621
+ .history-item:last-child {
622
+ border-bottom: none;
623
+ }
624
+
625
+ .history-timestamp {
626
+ color: var(--text-dark);
627
+ font-size: 0.7rem;
628
+ }
629
+
630
+ .verdict-box {
631
+ border-radius: 6px;
632
+ padding: 1rem;
633
+ margin-bottom: 1.25rem;
634
+ font-size: 0.88rem;
635
+ display: none;
636
+ }
637
+
638
+ .verdict-box.show {
639
+ display: block;
640
+ }
641
+
642
+ .verdict-box.allow {
643
+ background: rgba(16, 185, 129, 0.1);
644
+ border: 1px solid var(--color-emerald);
645
+ color: #a7f3d0;
646
+ }
647
+
648
+ .verdict-box.block {
649
+ background: rgba(239, 68, 68, 0.1);
650
+ border: 1px solid var(--color-rose);
651
+ color: #fecaca;
652
+ }
653
+
654
+ .verdict-box.elevated {
655
+ background: rgba(245, 158, 11, 0.1);
656
+ border: 1px solid var(--color-amber);
657
+ color: #fde68a;
658
+ }
659
+
660
+ /* Interactive Badge */
661
+ .pulse-badge {
662
+ display: inline-flex;
663
+ align-items: center;
664
+ gap: 0.35rem;
665
+ font-size: 0.725rem;
666
+ font-weight: 700;
667
+ color: var(--color-cyan);
668
+ background: rgba(var(--color-cyan-rgb), 0.1);
669
+ border: 1px solid rgba(var(--color-cyan-rgb), 0.3);
670
+ padding: 0.15rem 0.45rem;
671
+ border-radius: 4px;
672
+ margin-left: 0.5rem;
673
+ vertical-align: middle;
674
+ text-transform: uppercase;
675
+ letter-spacing: 0.05em;
676
+ }
677
+
678
+ .pulse-dot {
679
+ width: 5px;
680
+ height: 5px;
681
+ background-color: var(--color-cyan);
682
+ border-radius: 50%;
683
+ animation: pulse 1.8s infinite;
684
+ }
685
+
686
+ @keyframes pulse {
687
+ 0% { transform: scale(0.9); box-shadow: 0 0 0 0 rgba(var(--color-cyan-rgb), 0.5); }
688
+ 70% { transform: scale(1.1); box-shadow: 0 0 0 5px rgba(var(--color-cyan-rgb), 0); }
689
+ 100% { transform: scale(0.9); box-shadow: 0 0 0 0 rgba(var(--color-cyan-rgb), 0); }
690
+ }
691
+ </style>
692
+ </head>
693
+ <body>
694
+
695
+ <div class="container">
696
+ <header>
697
+ <div class="header-left">
698
+ <div class="header-logo">
699
+ <svg viewBox="0 0 64 64" width="48" height="48" role="img" aria-label="Clio Coder logo"><title>Clio Coder logo</title><rect x="8" y="8" width="48" height="48" rx="12" fill="rgba(0,240,255,0.12)" stroke="rgba(0,240,255,0.65)"/><path d="M32 14 16 23l16 9 16-9-16-9Z" fill="none" stroke="#00f0ff" stroke-width="3" stroke-linejoin="round"/><path d="M16 32l16 9 16-9M16 41l16 9 16-9" fill="none" stroke="#bd00ff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></svg>
700
+ </div>
701
+ <div class="header-title-wrapper">
702
+ <h1>Prompt Envelopes & Tools Spec</h1>
703
+ <p>Technical architecture specification, compiler calculator, and registry simulator for Clio Coder's secure LLM delivery.</p>
704
+ <div class="meta-chips-row">
705
+ <span class="chip">Source: docs/prompt-envelope-and-tools.md</span>
706
+ <span class="chip chip-orange">clio-coder docs tools</span>
707
+ </div>
708
+ </div>
709
+ </div>
710
+ <div class="header-right">
711
+ <span class="version-badge">Clio Coder v0.3.0</span>
712
+ <a href="index.html" class="back-btn">
713
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><title>Icon</title><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>
714
+ Dashboard Hub
715
+ </a>
716
+ </div>
717
+ </header>
718
+
719
+
720
+ <!-- Navigation Tabs -->
721
+ <div class="tabs-nav">
722
+ <button type="button" class="tab-btn active" onclick="_switchTab('tab-diagrams')">
723
+ <svg aria-hidden="true" viewBox="0 0 24 24"><title>Icon</title><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zM7 10h2v7H7zm4-3h2v10h-2zm4 6h2v4h-2z"/></svg>
724
+ Architecture & Visual Flowcharts
725
+ </button>
726
+ <button type="button" class="tab-btn" onclick="_switchTab('tab-calculator')">
727
+ <svg aria-hidden="true" viewBox="0 0 24 24"><title>Icon</title><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 14h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V7h2v2zm-4 8H7v-2h2v2zm0-4H7v-2h2v2zm0-4H7V7h2v2z"/></svg>
728
+ Token Pressure Calculator
729
+ </button>
730
+ <button type="button" class="tab-btn" onclick="_switchTab('tab-simulator')">
731
+ <svg aria-hidden="true" viewBox="0 0 24 24"><title>Icon</title><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H7c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.04-.42 1.99-1.07 2.75z"/></svg>
732
+ Tool & Registry Simulator
733
+ </button>
734
+ <button type="button" class="tab-btn" onclick="_switchTab('tab-recompiler')">
735
+ <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><title>Icon</title><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/></svg>
736
+ Prompt Recompiler & Capping
737
+ <span class="pulse-badge"><span class="pulse-dot"></span>New</span>
738
+ </button>
739
+ </div>
740
+
741
+ <!-- Tab: Diagrams -->
742
+ <div id="tab-diagrams" class="tab-pane active">
743
+ <div class="diagrams-container">
744
+
745
+ <!-- Diagram 1 -->
746
+ <div class="diagram-card">
747
+ <h2 class="card-title">1. Provider Tool Schema Delivery</h2>
748
+ <div class="diagram-desc">
749
+ Unlike legacy prompt-based wrappers, Clio converts TypeBox schemas into formal provider tool schemas.
750
+ The model calls tools natively through the LLM API's structural JSON envelope rather than parsing text logs.
751
+ </div>
752
+ <div class="svg-wrapper">
753
+ <svg aria-hidden="true" width="900" height="280" viewBox="0 0 900 280" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Icon</title>
754
+ <!-- Background grids -->
755
+ <rect width="900" height="280" rx="8" fill="#04070e" />
756
+
757
+ <!-- Nodes -->
758
+ <!-- Node A: TypeBox Code Spec -->
759
+ <rect x="30" y="80" width="180" height="90" rx="8" fill="rgba(189, 0, 255, 0.1)" stroke="#bd00ff" stroke-width="1.5" />
760
+ <text x="120" y="115" fill="#ffffff" font-family="var(--font-sans)" font-size="14" font-weight="700" text-anchor="middle">TypeBox Spec</text>
761
+ <text x="120" y="135" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="11" text-anchor="middle">src/tools/*.ts</text>
762
+ <text x="120" y="152" fill="#bd00ff" font-family="var(--font-mono)" font-size="10" text-anchor="middle">Type.Object({path:...})</text>
763
+
764
+ <!-- Connector A -> B -->
765
+ <path d="M210 125 H260" stroke="rgba(189, 0, 255, 0.4)" stroke-width="2" stroke-dasharray="4" />
766
+ <polygon points="260,125 252,121 252,129" fill="#bd00ff" />
767
+
768
+ <!-- Node B: Registry.ts -->
769
+ <rect x="270" y="80" width="180" height="90" rx="8" fill="rgba(0, 240, 255, 0.1)" stroke="#00f0ff" stroke-width="1.5" />
770
+ <text x="360" y="115" fill="#ffffff" font-family="var(--font-sans)" font-size="14" font-weight="700" text-anchor="middle">ToolRegistry</text>
771
+ <text x="360" y="135" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="11" text-anchor="middle">src/tools/registry.ts</text>
772
+ <text x="360" y="152" fill="#00f0ff" font-family="var(--font-mono)" font-size="10" text-anchor="middle">listForMode(mode)</text>
773
+
774
+ <!-- Connector B -> C -->
775
+ <path d="M450 125 H500" stroke="rgba(0, 240, 255, 0.4)" stroke-width="2" />
776
+ <polygon points="500,125 492,121 492,129" fill="#00f0ff" />
777
+
778
+ <!-- Node C: worker-tools.ts -->
779
+ <rect x="510" y="80" width="180" height="90" rx="8" fill="rgba(16, 185, 129, 0.1)" stroke="#10b981" stroke-width="1.5" />
780
+ <text x="600" y="115" fill="#ffffff" font-family="var(--font-sans)" font-size="14" font-weight="700" text-anchor="middle">Worker Resolver</text>
781
+ <text x="600" y="135" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="11" text-anchor="middle">src/engine/worker-tools.ts</text>
782
+ <text x="600" y="152" fill="#10b981" font-family="var(--font-mono)" font-size="10" text-anchor="middle">resolveAgentTools()</text>
783
+
784
+ <!-- Connector C -> D -->
785
+ <path d="M690 125 H740" stroke="rgba(16, 185, 129, 0.4)" stroke-width="2" stroke-dasharray="4" />
786
+ <polygon points="740,125 732,121 732,129" fill="#10b981" />
787
+
788
+ <!-- Node D: LLM Provider Client -->
789
+ <rect x="750" y="60" width="120" height="130" rx="8" fill="rgba(245, 158, 11, 0.1)" stroke="#f59e0b" stroke-width="1.5" />
790
+ <text x="810" y="90" fill="#ffffff" font-family="var(--font-sans)" font-size="13" font-weight="700" text-anchor="middle">LLM Provider</text>
791
+ <text x="810" y="110" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="11" text-anchor="middle">Format Mapping</text>
792
+ <text x="810" y="135" fill="#f59e0b" font-family="var(--font-mono)" font-size="9" text-anchor="middle">• tools: [...]</text>
793
+ <text x="810" y="150" fill="#f59e0b" font-family="var(--font-mono)" font-size="9" text-anchor="middle">• type: "function"</text>
794
+ <text x="810" y="165" fill="#f59e0b" font-family="var(--font-mono)" font-size="9" text-anchor="middle">• parameters: json</text>
795
+
796
+ <!-- Flow annotations -->
797
+ <text x="235" y="112" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10" text-anchor="middle">registers</text>
798
+ <text x="475" y="112" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10" text-anchor="middle">exposes</text>
799
+ <text x="715" y="112" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10" text-anchor="middle">delivers</text>
800
+ </svg>
801
+ </div>
802
+ </div>
803
+
804
+ <!-- Diagram 2 -->
805
+ <div class="diagram-card">
806
+ <h2 class="card-title">2. Prompt Wrapping Envelope & Cache Decision Flow</h2>
807
+ <div class="diagram-desc">
808
+ Clio splits prompts into three tiers (Static, Session, Dynamic) and generates distinct hashes.
809
+ When supported by targets (e.g. llamacpp or cloud cache), Clio leverages these hashes to skip resending the session shell prompt if it has not changed.
810
+ </div>
811
+ <div class="svg-wrapper">
812
+ <svg aria-hidden="true" width="900" height="350" viewBox="0 0 900 350" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Icon</title>
813
+ <rect width="900" height="350" rx="8" fill="#04070e" />
814
+
815
+ <!-- Box: Full Rendered Prompt Envelope -->
816
+ <rect x="20" y="30" width="300" height="290" rx="8" fill="rgba(255, 255, 255, 0.02)" stroke="var(--border-card)" stroke-width="1.5" />
817
+ <text x="35" y="55" fill="#ffffff" font-family="var(--font-sans)" font-size="13" font-weight="700">PROMPT ENVELOPE SECTIONS</text>
818
+
819
+ <!-- Section 1: Static Shell -->
820
+ <rect x="35" y="75" width="270" height="65" rx="6" fill="rgba(0, 240, 255, 0.05)" stroke="var(--color-cyan)" stroke-opacity="0.5" />
821
+ <text x="45" y="95" fill="#ffffff" font-family="var(--font-sans)" font-size="11" font-weight="600">Static Shell (Tier: static-shell)</text>
822
+ <text x="45" y="112" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10">Identity / Selected Mode / Safety instructions</text>
823
+ <text x="45" y="128" fill="var(--color-cyan)" font-family="var(--font-mono)" font-size="9">staticShellHash: SHA-256</text>
824
+
825
+ <!-- Section 2: Session Shell -->
826
+ <rect x="35" y="150" width="270" height="75" rx="6" fill="rgba(189, 0, 255, 0.05)" stroke="var(--color-purple)" stroke-opacity="0.5" />
827
+ <text x="45" y="170" fill="#ffffff" font-family="var(--font-sans)" font-size="11" font-weight="600">Session Shell (Tier: session-shell)</text>
828
+ <text x="45" y="187" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10">Runtime Config / Tool Surface / Retrieval Hints</text>
829
+ <text x="45" y="202" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10">Skills list (when active)</text>
830
+ <text x="45" y="217" fill="var(--color-purple)" font-family="var(--font-mono)" font-size="9">sessionShellHash: SHA-256 (System Prompt)</text>
831
+
832
+ <!-- Section 3: Dynamic Turn -->
833
+ <rect x="35" y="235" width="270" height="70" rx="6" fill="rgba(16, 185, 129, 0.05)" stroke="var(--color-emerald)" stroke-opacity="0.5" />
834
+ <text x="45" y="255" fill="#ffffff" font-family="var(--font-sans)" font-size="11" font-weight="600">Dynamic Turn (Tier: dynamic-turn)</text>
835
+ <text x="45" y="272" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10">Memory / Project Context Files / Turn Counts</text>
836
+ <text x="45" y="290" fill="var(--color-emerald)" font-family="var(--font-mono)" font-size="9">dynamicHash: SHA-256 (Dynamic Fragments)</text>
837
+
838
+ <!-- Flow Arrows from Envelope to decision point -->
839
+ <path d="M320 175 H400" stroke="#a5b4fc" stroke-width="2" />
840
+ <polygon points="400,175 392,171 392,179" fill="#a5b4fc" />
841
+
842
+ <!-- Decision Point Box -->
843
+ <rect x="410" y="125" width="180" height="100" rx="8" fill="rgba(245, 158, 11, 0.1)" stroke="var(--color-amber)" stroke-width="1.5" />
844
+ <text x="500" y="150" fill="#ffffff" font-family="var(--font-sans)" font-size="12" font-weight="700" text-anchor="middle">Delivery Check</text>
845
+ <text x="500" y="170" fill="var(--color-amber)" font-family="var(--font-sans)" font-size="10" font-weight="600" text-anchor="middle">Has sessionShellHash</text>
846
+ <text x="500" y="185" fill="var(--color-amber)" font-family="var(--font-sans)" font-size="10" font-weight="600" text-anchor="middle">changed since last turn?</text>
847
+ <text x="500" y="208" fill="var(--text-muted)" font-family="var(--font-mono)" font-size="9" text-anchor="middle">reduced-repeated-envelope</text>
848
+
849
+ <!-- Choice: YES (Changed / First Turn) -->
850
+ <path d="M590 150 H670" stroke="var(--color-rose)" stroke-width="1.5" />
851
+ <polygon points="670,150 662,146 662,154" fill="var(--color-rose)" />
852
+ <text x="630" y="142" fill="var(--color-rose)" font-family="var(--font-sans)" font-size="10" text-anchor="middle" font-weight="600">YES</text>
853
+
854
+ <!-- Action: Send Full Envelope -->
855
+ <rect x="680" y="105" width="190" height="60" rx="6" fill="rgba(239, 68, 68, 0.05)" stroke="var(--color-rose)" stroke-width="1" />
856
+ <text x="775" y="128" fill="#ffffff" font-family="var(--font-sans)" font-size="11" font-weight="600" text-anchor="middle">Full System Reset</text>
857
+ <text x="775" y="145" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10" text-anchor="middle">Send Static + Session Shell prompts</text>
858
+
859
+ <!-- Choice: NO (Not Changed) -->
860
+ <path d="M590 200 H670" stroke="var(--color-emerald)" stroke-width="1.5" />
861
+ <polygon points="670,200 662,196 662,204" fill="var(--color-emerald)" />
862
+ <text x="630" y="192" fill="var(--color-emerald)" font-family="var(--font-sans)" font-size="10" text-anchor="middle" font-weight="600">NO</text>
863
+
864
+ <!-- Action: Reuse Cache -->
865
+ <rect x="680" y="180" width="190" height="70" rx="6" fill="rgba(16, 185, 129, 0.05)" stroke="var(--color-emerald)" stroke-width="1" />
866
+ <text x="775" y="202" fill="#ffffff" font-family="var(--font-sans)" font-size="11" font-weight="600" text-anchor="middle">Reuse System Prompt</text>
867
+ <text x="775" y="218" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10" text-anchor="middle">Send ONLY Dynamic fragments</text>
868
+ <text x="775" y="233" fill="var(--color-emerald)" font-family="var(--font-sans)" font-size="9" text-anchor="middle" font-weight="600">Saves substantial context/time</text>
869
+ </svg>
870
+ </div>
871
+ </div>
872
+
873
+ <!-- Diagram 3 -->
874
+ <div class="diagram-card">
875
+ <h2 class="card-title">3. Tool Invocation & Result Shaping Lifecycle</h2>
876
+ <div class="diagram-desc">
877
+ Every tool invocation goes through the registry checks, classifying arguments, detecting loop locks, and evaluating security policies.
878
+ Upon execution, outputs are bounded to respect context pressure through safe UTF-8 truncation and suffix injection.
879
+ </div>
880
+ <div class="svg-wrapper">
881
+ <svg aria-hidden="true" width="900" height="340" viewBox="0 0 900 340" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Icon</title>
882
+ <rect width="900" height="340" rx="8" fill="#04070e" />
883
+
884
+ <!-- Path Timeline -->
885
+ <!-- Step 1: LLM Tool Call Request -->
886
+ <rect x="30" y="40" width="150" height="60" rx="6" fill="rgba(255, 255, 255, 0.03)" stroke="var(--border-card)" />
887
+ <text x="105" y="65" fill="#ffffff" font-family="var(--font-sans)" font-size="12" font-weight="700" text-anchor="middle">Model Call Request</text>
888
+ <text x="105" y="82" fill="var(--color-cyan)" font-family="var(--font-mono)" font-size="10" text-anchor="middle">{name, arguments}</text>
889
+
890
+ <!-- Arrow 1 -> 2 -->
891
+ <path d="M180 70 H220" stroke="var(--border-card)" stroke-width="1.5" />
892
+ <polygon points="220,70 214,66 214,74" fill="var(--text-muted)" />
893
+
894
+ <!-- Step 2: Loop Guard & Classification -->
895
+ <rect x="230" y="30" width="180" height="80" rx="6" fill="rgba(189, 0, 255, 0.05)" stroke="var(--color-purple)" />
896
+ <text x="320" y="52" fill="#ffffff" font-family="var(--font-sans)" font-size="12" font-weight="700" text-anchor="middle">Registry Admission Gates</text>
897
+ <text x="320" y="70" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10" text-anchor="middle">1. Visible in Mode?</text>
898
+ <text x="320" y="85" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10" text-anchor="middle">2. Action Class allowed?</text>
899
+ <text x="320" y="99" fill="var(--color-purple)" font-family="var(--font-mono)" font-size="9" text-anchor="middle">Loop Guard & Safety Policy</text>
900
+
901
+ <!-- Arrow 2 -> 3 -->
902
+ <path d="M410 70 H450" stroke="var(--border-card)" stroke-width="1.5" />
903
+ <polygon points="450,70 444,66 444,74" fill="var(--text-muted)" />
904
+
905
+ <!-- Step 3: Tool Execution -->
906
+ <rect x="460" y="40" width="160" height="60" rx="6" fill="rgba(16, 185, 129, 0.05)" stroke="var(--color-emerald)" />
907
+ <text x="540" y="65" fill="#ffffff" font-family="var(--font-sans)" font-size="12" font-weight="700" text-anchor="middle">Tool Execution (run)</text>
908
+ <text x="540" y="82" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10" text-anchor="middle">Isolated execution scope</text>
909
+
910
+ <!-- Arrow 3 -> 4 (Down and Right to Shaping) -->
911
+ <path d="M620 70 H710 V140" stroke="var(--border-card)" stroke-width="1.5" fill="none" />
912
+ <polygon points="710,140 706,134 714,134" fill="var(--text-muted)" />
913
+
914
+ <!-- Step 4: Result Shaper Gate -->
915
+ <rect x="580" y="150" width="260" height="155" rx="8" fill="rgba(245, 158, 11, 0.05)" stroke="var(--color-amber)" stroke-width="1.5" />
916
+ <text x="710" y="175" fill="#ffffff" font-family="var(--font-sans)" font-size="13" font-weight="700" text-anchor="middle">Result Shaper</text>
917
+ <text x="710" y="195" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10" text-anchor="middle">Checks byte size of result against tool limit.</text>
918
+
919
+ <rect x="595" y="210" width="230" height="40" rx="4" fill="rgba(0,0,0,0.3)" stroke="var(--border-card)" />
920
+ <text x="710" y="226" fill="var(--color-amber)" font-family="var(--font-sans)" font-size="10" font-weight="600" text-anchor="middle">Is Size &gt; maxBytes? 8KB backstop</text>
921
+ <text x="710" y="238" fill="var(--text-muted)" font-family="var(--font-mono)" font-size="9" text-anchor="middle">UTF-8 Safe Truncation</text>
922
+
923
+ <text x="710" y="270" fill="var(--text-muted)" font-family="var(--font-sans)" font-size="10" text-anchor="middle">Appends follow-up hint + details metadata</text>
924
+ <text x="710" y="285" fill="var(--color-cyan)" font-family="var(--font-mono)" font-size="9" text-anchor="middle">resultSize: {truncated, offloadPath?}</text>
925
+
926
+ <!-- Arrow 4 -> 5 -->
927
+ <path d="M580 220 H340" stroke="var(--color-cyan)" stroke-width="1.5" />
928
+ <polygon points="340,220 348,224 348,216" fill="var(--color-cyan)" />
929
+
930
+ <!-- Step 5: Final Clean Delivery Envelope -->
931
+ <rect x="40" y="160" width="280" height="130" rx="8" fill="rgba(0, 240, 255, 0.05)" stroke="var(--color-cyan)" stroke-width="1.5" />
932
+ <text x="180" y="185" fill="#ffffff" font-family="var(--font-sans)" font-size="13" font-weight="700" text-anchor="middle">Final Delivery</text>
933
+
934
+ <rect x="55" y="200" width="250" height="75" rx="4" fill="#04070e" stroke="var(--border-card)" />
935
+ <text x="65" y="218" fill="var(--color-emerald)" font-family="var(--font-mono)" font-size="10">kind: "ok"</text>
936
+ <text x="65" y="234" fill="var(--text-muted)" font-family="var(--font-mono)" font-size="9">output: "...[truncated]\n\n[Use a narrower query...]"</text>
937
+ <text x="65" y="250" fill="var(--text-muted)" font-family="var(--font-mono)" font-size="9">details: { resultSize: { truncated: true, offloadPath } }</text>
938
+ <text x="65" y="265" fill="var(--text-muted)" font-family="var(--font-mono)" font-size="9">scratch cap: 10MB under state/scratch</text>
939
+ <text x="65" y="280" fill="var(--color-cyan)" font-family="var(--font-mono)" font-size="9">terminate: true/false</text>
940
+
941
+ </svg>
942
+ </div>
943
+ </div>
944
+
945
+ </div>
946
+ </div>
947
+
948
+ <!-- Tab: Calculator -->
949
+ <div id="tab-calculator" class="tab-pane">
950
+ <div class="grid-2">
951
+ <!-- Input Panel -->
952
+ <div class="glass-card">
953
+ <h2 class="card-title">Prompt Envelope Settings</h2>
954
+
955
+ <div class="scenario-grid">
956
+ <button type="button" class="scenario-pill" onclick="loadScenario('standard')">Standard Code Turn</button>
957
+ <button type="button" class="scenario-pill" onclick="loadScenario('planning')">Planning Phase</button>
958
+ <button type="button" class="scenario-pill" onclick="loadScenario('constrained')">Constrained Context</button>
959
+ <button type="button" class="scenario-pill" onclick="loadScenario('no-tools')">Fallback (No Tools)</button>
960
+ </div>
961
+
962
+ <div class="form-row">
963
+ <div class="form-group">
964
+ <label for="context-window">Context Window Size</label>
965
+ <select id="context-window" onchange="calculateTokenPressure()">
966
+ <option value="4096">4,096 tokens (Llama-3-8B-local)</option>
967
+ <option value="8192">8,192 tokens</option>
968
+ <option value="16384">16,384 tokens</option>
969
+ <option value="32768" selected>32,768 tokens (Mistral-Large-local)</option>
970
+ <option value="65536">65,536 tokens</option>
971
+ <option value="131072">131,072 tokens (Claude 3.5 Sonnet / Gemini)</option>
972
+ </select>
973
+ </div>
974
+ <div class="form-group">
975
+ <label for="mode-select">Active Mode Profile</label>
976
+ <select id="mode-select" onchange="_onModeChange()">
977
+ <option value="default" selected>default (Read, Write, Exec, Dispatch)</option>
978
+ <option value="advise">advise (Read, Dispatch only; restricted write)</option>
979
+ <option value="super">super (Read, Write, Exec, Dispatch, Sys-Modify)</option>
980
+ </select>
981
+ </div>
982
+ </div>
983
+
984
+ <div class="form-row">
985
+ <div class="form-group">
986
+ <label for="delivery-mode">Delivery Mode</label>
987
+ <select id="delivery-mode" onchange="calculateTokenPressure()">
988
+ <option value="reduced-repeated-envelope" selected>reduced-repeated-envelope</option>
989
+ <option value="prefix-cache-deterministic">prefix-cache-deterministic</option>
990
+ <option value="no-tools-fallback">no-tools-fallback</option>
991
+ </select>
992
+ </div>
993
+ <div class="form-group">
994
+ <label for="thinking-applied">Thinking Configuration</label>
995
+ <select id="thinking-applied" onchange="calculateTokenPressure()">
996
+ <option value="applied" selected>applied (budget: medium, mechanism: thinking)</option>
997
+ <option value="unsupported">unsupported</option>
998
+ <option value="always-on">always-on</option>
999
+ </select>
1000
+ </div>
1001
+ </div>
1002
+
1003
+ <div class="form-group">
1004
+ <label>Active Tools & Schemas this Turn</label>
1005
+ <div class="checkbox-grid" id="tools-checkboxes">
1006
+ <!-- Populated dynamically by javascript -->
1007
+ </div>
1008
+ </div>
1009
+
1010
+ <div class="form-group">
1011
+ <label for="static-shell-input">Static Shell Parts (Verbatim Harness/Identity/Safety)</label>
1012
+ <textarea id="static-shell-input" class="code-editor" rows="5" oninput="calculateTokenPressure()"></textarea>
1013
+ </div>
1014
+
1015
+ <div class="form-group">
1016
+ <label for="dynamic-memory-input">Dynamic Turn: Memory Section</label>
1017
+ <textarea id="dynamic-memory-input" class="code-editor" rows="2" oninput="calculateTokenPressure()"></textarea>
1018
+ </div>
1019
+
1020
+ <div class="form-group">
1021
+ <label for="dynamic-project-input">Dynamic Turn: Project Files & Context</label>
1022
+ <textarea id="dynamic-project-input" class="code-editor" rows="3" oninput="calculateTokenPressure()"></textarea>
1023
+ </div>
1024
+
1025
+ <div class="form-group">
1026
+ <label for="user-query-input">Dynamic Turn: User Request (Query)</label>
1027
+ <textarea id="user-query-input" class="code-editor" rows="3" oninput="calculateTokenPressure()"></textarea>
1028
+ </div>
1029
+ </div>
1030
+
1031
+ <!-- Result Panel -->
1032
+ <div class="glass-card">
1033
+ <h2 class="card-title">Envelope Pressure Diagnostics</h2>
1034
+
1035
+ <div class="pressure-panel">
1036
+
1037
+ <div style="display:flex; justify-content:space-between; align-items:center;">
1038
+ <span style="font-weight:700;">Context Window Pressure</span>
1039
+ <span id="pressure-ratio" style="font-family:var(--font-mono); font-weight:700;">0 / 32,768 (0.00%)</span>
1040
+ </div>
1041
+
1042
+ <div class="progress-bar-container">
1043
+ <div class="progress-bar-fill" id="pressure-bar"></div>
1044
+ </div>
1045
+
1046
+ <div style="display:flex; justify-content:space-between; align-items:center; margin-top: -0.25rem;">
1047
+ <span class="status-pill pill-emerald" id="capacity-status">Optimal</span>
1048
+ <span id="capacity-left" style="font-size:0.85rem; color:var(--text-muted);">32,768 tokens remaining</span>
1049
+ </div>
1050
+
1051
+ <div class="data-grid" style="margin-top: 1rem;">
1052
+ <div class="data-card">
1053
+ <div class="data-val" id="val-static">0</div>
1054
+ <div class="data-label">Static Shell</div>
1055
+ </div>
1056
+ <div class="data-card">
1057
+ <div class="data-val" id="val-session">0</div>
1058
+ <div class="data-label">Session Shell</div>
1059
+ </div>
1060
+ <div class="data-card">
1061
+ <div class="data-val" id="val-dynamic">0</div>
1062
+ <div class="data-label">Dynamic Turn</div>
1063
+ </div>
1064
+ <div class="data-card">
1065
+ <div class="data-val" id="val-tools">0</div>
1066
+ <div class="data-label">Tool Schemas</div>
1067
+ </div>
1068
+ </div>
1069
+
1070
+ <table class="segment-table">
1071
+ <thead>
1072
+ <tr>
1073
+ <th>Segment ID</th>
1074
+ <th>Tier</th>
1075
+ <th>Hash (SHA-256)</th>
1076
+ <th>Tokens</th>
1077
+ <th>Status</th>
1078
+ </tr>
1079
+ </thead>
1080
+ <tbody id="segments-table-body">
1081
+ <!-- Populated dynamically by javascript -->
1082
+ </tbody>
1083
+ </table>
1084
+
1085
+ <div class="form-group" style="margin-top:1rem;">
1086
+ <div class="console-header">
1087
+ <span>Resulting compiled Prompt Envelope Signature (JSON)</span>
1088
+ <button type="button" class="copy-btn" onclick="_copyText('envelope-signature-out')">Copy JSON</button>
1089
+ </div>
1090
+ <pre class="console-out" id="envelope-signature-out"></pre>
1091
+ </div>
1092
+
1093
+ <div class="form-group">
1094
+ <div class="console-header">
1095
+ <span>Verbatim System Prompt Sent to Provider</span>
1096
+ <button type="button" class="copy-btn" onclick="_copyText('system-prompt-out')">Copy Prompt</button>
1097
+ </div>
1098
+ <pre class="console-out" id="system-prompt-out"></pre>
1099
+ </div>
1100
+
1101
+ </div>
1102
+ </div>
1103
+ </div>
1104
+ </div>
1105
+
1106
+ <!-- Tab: Simulator -->
1107
+ <div id="tab-simulator" class="tab-pane">
1108
+ <div class="grid-2">
1109
+ <!-- Left side: Tool Call Form -->
1110
+ <div class="glass-card">
1111
+ <h2 class="card-title">Tool Call Invocation</h2>
1112
+ <p class="card-subtitle">Format tool arguments into Canonical JSON, check loop detectors, and trigger security validation policies.</p>
1113
+
1114
+ <div class="form-group">
1115
+ <label for="sim-mode-select">Simulated Current Mode</label>
1116
+ <select id="sim-mode-select" onchange="onSimModeChange()">
1117
+ <option value="default" selected>default (Normal operations)</option>
1118
+ <option value="advise">advise (Read/Dispatch only)</option>
1119
+ <option value="super">super (Full privileges)</option>
1120
+ </select>
1121
+ </div>
1122
+
1123
+ <div class="form-row">
1124
+ <div class="form-group">
1125
+ <label for="sim-tool-select">Select Tool Name</label>
1126
+ <select id="sim-tool-select" onchange="onSimToolChange()">
1127
+ <!-- Populated dynamically -->
1128
+ </select>
1129
+ </div>
1130
+ <div class="form-group">
1131
+ <label for="sim-max-bytes">Result Bounded Limit (Max Bytes)</label>
1132
+ <input type="number" id="sim-max-bytes" value="200" min="50" max="60000" oninput="simulateToolFlow()">
1133
+ </div>
1134
+ </div>
1135
+
1136
+ <div class="form-group">
1137
+ <label for="sim-args">Arguments (JSON Format)</label>
1138
+ <textarea id="sim-args" class="code-editor" rows="5" oninput="simulateToolFlow()"></textarea>
1139
+ <div id="args-json-err" style="color:var(--color-rose); font-size:0.8rem; margin-top:0.25rem; display:none;">Invalid JSON format</div>
1140
+ </div>
1141
+
1142
+ <div class="form-group">
1143
+ <label for="sim-raw-output">Simulated Raw Output from Tool Execution</label>
1144
+ <textarea id="sim-raw-output" class="code-editor" rows="5" oninput="simulateToolFlow()">[
1145
+ {"id": 1, "symbol": "compile", "path": "src/domains/prompts/compiler.ts", "line": 402},
1146
+ {"id": 2, "symbol": "buildPromptEnvelope", "path": "src/domains/prompts/compiler.ts", "line": 362},
1147
+ {"id": 3, "symbol": "estimatePromptTokens", "path": "src/domains/prompts/compiler.ts", "line": 316},
1148
+ {"id": 4, "symbol": "renderToolContractBlock", "path": "src/domains/prompts/compiler.ts", "line": 184},
1149
+ {"id": 5, "symbol": "renderRuntimeBlock", "path": "src/domains/prompts/compiler.ts", "line": 147},
1150
+ {"id": 6, "symbol": "lookupFragment", "path": "src/domains/prompts/compiler.ts", "line": 120}
1151
+ ]</textarea>
1152
+ </div>
1153
+
1154
+ <div class="form-row">
1155
+ <button type="button" class="btn btn-primary" onclick="_executeSimulatedCall()">Submit Call to Registry</button>
1156
+ <button type="button" class="btn btn-danger" onclick="_clearSimHistory()">Clear History & Reset Loop</button>
1157
+ </div>
1158
+
1159
+ <div class="form-group" style="margin-top:1.5rem;">
1160
+ <label>Sliding Window History (10s window, max 50 calls)</label>
1161
+ <div class="history-list" id="history-items">
1162
+ <div style="color:var(--text-dark); text-align:center; padding:1.5rem 0; font-size:0.85rem;">No recent calls in buffer</div>
1163
+ </div>
1164
+ </div>
1165
+
1166
+ </div>
1167
+
1168
+ <!-- Right side: Registry & Shaping Results -->
1169
+ <div class="glass-card">
1170
+ <h2 class="card-title">Registry Gates & Result Shaping Verdict</h2>
1171
+
1172
+ <div id="verdict-display" class="verdict-box">
1173
+ <!-- Populated by JavaScript -->
1174
+ </div>
1175
+
1176
+ <div class="form-group">
1177
+ <label>Parsed & Canonical Serialized Args (canonicalJson)</label>
1178
+ <pre class="console-out" id="canonical-args-out" style="max-height: 100px;"></pre>
1179
+ </div>
1180
+
1181
+ <div class="form-row">
1182
+ <div class="form-group">
1183
+ <label>Tool Call Fingerprint (Hash)</label>
1184
+ <pre class="console-out" id="call-hash-out" style="max-height: 50px; padding:0.4rem 0.8rem; overflow:hidden; text-overflow:ellipsis;"></pre>
1185
+ </div>
1186
+ <div class="form-group">
1187
+ <label>Safety Classification Class</label>
1188
+ <pre class="console-out" id="class-out" style="max-height: 50px; padding:0.4rem 0.8rem; overflow:hidden; text-overflow:ellipsis;"></pre>
1189
+ </div>
1190
+ </div>
1191
+
1192
+ <div class="form-group">
1193
+ <div class="console-header">
1194
+ <span>Registry Output Delivered to Model (Bounded result)</span>
1195
+ <button type="button" class="copy-btn" onclick="_copyText('shaped-result-out')">Copy Output</button>
1196
+ </div>
1197
+ <pre class="console-out" id="shaped-result-out" style="max-height: 250px; color:#4ef1a6;"></pre>
1198
+ </div>
1199
+
1200
+ <div class="form-group">
1201
+ <div class="console-header">
1202
+ <span>Full ToolResult Details Payload (Diagnostic evidence metadata)</span>
1203
+ <button type="button" class="copy-btn" onclick="_copyText('result-details-out')">Copy Details</button>
1204
+ </div>
1205
+ <pre class="console-out" id="result-details-out" style="max-height: 180px; color:#c084fc;"></pre>
1206
+ </div>
1207
+ </div>
1208
+ </div>
1209
+ </div>
1210
+
1211
+ <!-- Tab: Prompt Recompiler & Tool Result Capping Validator -->
1212
+ <div id="tab-recompiler" class="tab-pane">
1213
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; margin-top: 1.5rem;">
1214
+ <!-- Section 1: System Prompt Recompile Simulator -->
1215
+ <div class="glass-card" style="padding: 1.5rem; background: var(--bg-card); border: 1px solid var(--border-card); border-radius: 12px; display: flex; flex-direction: column; gap: 1.25rem;">
1216
+ <h3 style="color: var(--color-cyan); font-family: var(--font-sans); font-size: 1.2rem; display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; margin-top: 0;">
1217
+ <svg width="20" height="20" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><title>Icon</title><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/></svg>
1218
+ System Prompt Recompile Simulator
1219
+ </h3>
1220
+ <p style="font-size: 0.85rem; color: var(--text-muted); margin-bottom: 0.5rem;">
1221
+ Clio Coder compiles one provider-facing system prompt per session. It recompiles only when the compile key (<code style="font-family: var(--font-mono); color: var(--color-purple);">target|model|autonomy|sessionId</code>) changes or configuration is hot-reloaded.
1222
+ </p>
1223
+
1224
+ <div class="form-group" style="margin-bottom: 1rem;">
1225
+ <label for="recomp-endpoint" style="font-size: 0.8rem; color: var(--text-main); display: block; margin-bottom: 0.25rem;">Endpoint</label>
1226
+ <select id="recomp-endpoint" class="form-control" onchange="simulateRecompilerAndCapping()" style="width: 100%; padding: 0.5rem; background: rgba(0,0,0,0.3); border: 1px solid var(--border-card); border-radius: 6px; color: #fff;">
1227
+ <option value="http://localhost:11434">ollama (http://localhost:11434)</option>
1228
+ <option value="http://localhost:1234">lmstudio (http://localhost:1234)</option>
1229
+ <option value="https://api.openai.com/v1">openai-completions (https://api.openai.com)</option>
1230
+ </select>
1231
+ </div>
1232
+
1233
+ <div class="form-group" style="margin-bottom: 1rem;">
1234
+ <label for="recomp-model" style="font-size: 0.8rem; color: var(--text-main); display: block; margin-bottom: 0.25rem;">Model ID</label>
1235
+ <select id="recomp-model" class="form-control" onchange="simulateRecompilerAndCapping()" style="width: 100%; padding: 0.5rem; background: rgba(0,0,0,0.3); border: 1px solid var(--border-card); border-radius: 6px; color: #fff;">
1236
+ <option value="deepseek-r1:8b">deepseek-r1:8b</option>
1237
+ <option value="phi-4">phi-4</option>
1238
+ <option value="gpt-5.4">gpt-5.4</option>
1239
+ <option value="o1-mini">o1-mini</option>
1240
+ </select>
1241
+ </div>
1242
+
1243
+ <div class="form-group" style="margin-bottom: 1rem;">
1244
+ <label for="recomp-autonomy" style="font-size: 0.8rem; color: var(--text-main); display: block; margin-bottom: 0.25rem;">Autonomy Level</label>
1245
+ <select id="recomp-autonomy" class="form-control" onchange="simulateRecompilerAndCapping()" style="width: 100%; padding: 0.5rem; background: rgba(0,0,0,0.3); border: 1px solid var(--border-card); border-radius: 6px; color: #fff;">
1246
+ <option value="read-only">read-only</option>
1247
+ <option value="suggest">suggest</option>
1248
+ <option value="auto-edit">auto-edit</option>
1249
+ <option value="full-auto">full-auto</option>
1250
+ </select>
1251
+ </div>
1252
+
1253
+ <div class="form-group" style="margin-bottom: 1rem;">
1254
+ <label for="recomp-session" style="font-size: 0.8rem; color: var(--text-main); display: block; margin-bottom: 0.25rem;">Session ID</label>
1255
+ <input type="text" id="recomp-session" value="sess_7a3d90f" oninput="simulateRecompilerAndCapping()" style="width: 100%; padding: 0.5rem; background: rgba(0,0,0,0.3); border: 1px solid var(--border-card); border-radius: 6px; color: #fff; font-family: var(--font-mono);">
1256
+ </div>
1257
+
1258
+ <div class="form-group" style="display: flex; align-items: center; gap: 0.5rem; margin-top: 0.5rem; margin-bottom: 1rem;">
1259
+ <input type="checkbox" id="recomp-hotreload" onchange="simulateRecompilerAndCapping()" style="cursor: pointer;">
1260
+ <label for="recomp-hotreload" style="font-size: 0.85rem; color: var(--text-main); cursor: pointer;">Simulate Config Hot-Reload Invalidation</label>
1261
+ </div>
1262
+
1263
+ <div style="border-top: 1px solid var(--border-card); padding-top: 1rem; margin-top: auto; display: flex; flex-direction: column; gap: 0.75rem;">
1264
+ <div style="font-size: 0.85rem;">
1265
+ <span style="color: var(--text-muted);">Current Compile Key:</span>
1266
+ <pre id="recomp-key-out" style="background: #05080e; padding: 0.5rem; border-radius: 6px; font-family: var(--font-mono); font-size: 0.75rem; color: var(--color-purple); margin-top: 0.25rem; overflow-x: auto; white-space: nowrap; border: 1px solid var(--border-card);"></pre>
1267
+ </div>
1268
+ <div style="font-size: 0.85rem;">
1269
+ <span style="color: var(--text-muted);">Active Compile Key Hash:</span>
1270
+ <pre id="recomp-hash-out" style="background: #05080e; padding: 0.5rem; border-radius: 6px; font-family: var(--font-mono); font-size: 0.75rem; color: var(--color-cyan); margin-top: 0.25rem; overflow-x: auto; white-space: nowrap; border: 1px solid var(--border-card);"></pre>
1271
+ </div>
1272
+ </div>
1273
+ </div>
1274
+
1275
+ <!-- Section 2: Session Ledger & Capping Validator -->
1276
+ <div style="display: flex; flex-direction: column; gap: 1.5rem;">
1277
+ <!-- Ledger Output -->
1278
+ <div class="glass-card" style="padding: 1.5rem; background: var(--bg-card); border: 1px solid var(--border-card); border-radius: 12px; display: flex; flex-direction: column; gap: 0.75rem; flex: 1;">
1279
+ <h3 style="color: var(--color-emerald); font-family: var(--font-sans); font-size: 1.1rem; display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.25rem; margin-top: 0;">
1280
+ <svg width="18" height="18" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><title>Icon</title><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><line x1="9" y1="9" x2="15" y2="9"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="13" y2="17"/></svg>
1281
+ Session Ledger Logs (System Recompiler)
1282
+ </h3>
1283
+ <div id="recomp-ledger-out" style="background: #05080e; border: 1px solid var(--border-card); border-radius: 8px; padding: 1rem; font-family: var(--font-mono); font-size: 0.8rem; overflow-y: auto; max-height: 200px; flex: 1; display: flex; flex-direction: column; gap: 0.4rem; min-height: 150px;">
1284
+ </div>
1285
+ </div>
1286
+
1287
+ <!-- Tool Result Capping Validator -->
1288
+ <div class="glass-card" style="padding: 1.5rem; background: var(--bg-card); border: 1px solid var(--border-card); border-radius: 12px; display: flex; flex-direction: column; gap: 1rem;">
1289
+ <h3 style="color: var(--color-amber); font-family: var(--font-sans); font-size: 1.1rem; display: flex; align-items: center; gap: 0.5rem; margin-top: 0; margin-bottom: 0.5rem;">
1290
+ <svg width="18" height="18" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><title>Icon</title><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
1291
+ Tool Result Capping Validator
1292
+ </h3>
1293
+
1294
+ <div class="form-group" style="margin-bottom: 1rem;">
1295
+ <label for="capping-tool" style="font-size: 0.8rem; color: var(--text-main); display: block; margin-bottom: 0.25rem;">Tool / Policy Group</label>
1296
+ <select id="capping-tool" class="form-control" onchange="simulateRecompilerAndCapping()" style="width: 100%; padding: 0.5rem; background: rgba(0,0,0,0.3); border: 1px solid var(--border-card); border-radius: 6px; color: #fff;">
1297
+ <option value="read">read / read-kind (Cap: 6KB, Backstop: 8KB)</option>
1298
+ <option value="bash">bash / verify / web_fetch / summary-kind (Cap: 16KB)</option>
1299
+ <option value="ask_user">ask_user (Cap: 20KB)</option>
1300
+ </select>
1301
+ </div>
1302
+
1303
+ <div class="form-group" style="margin-bottom: 1rem;">
1304
+ <label for="capping-size" style="font-size: 0.8rem; color: var(--text-main); display: block; margin-bottom: 0.25rem;">Generated Output Size (KB)</label>
1305
+ <div style="display: flex; align-items: center; gap: 1rem;">
1306
+ <input type="range" id="capping-size" min="1" max="35" value="10" oninput="simulateRecompilerAndCapping()" style="flex: 1;">
1307
+ <span id="capping-size-val" style="font-family: var(--font-mono); font-size: 0.9rem; color: var(--color-amber); font-weight: 700; width: 60px;">10 KB</span>
1308
+ </div>
1309
+ </div>
1310
+
1311
+ <div style="border-top: 1px solid var(--border-card); padding-top: 1rem; display: flex; flex-direction: column; gap: 0.5rem;">
1312
+ <div style="display: flex; justify-content: space-between; font-size: 0.8rem;">
1313
+ <span style="color: var(--text-muted);">Result Truncated:</span>
1314
+ <span id="capping-truncated-badge" style="font-weight: 700;">No</span>
1315
+ </div>
1316
+ <div style="display: flex; justify-content: space-between; font-size: 0.8rem;">
1317
+ <span style="color: var(--text-muted);">Policy Limit Applied:</span>
1318
+ <span id="capping-limit-val" style="font-family: var(--font-mono); color: var(--color-cyan);">6 KB</span>
1319
+ </div>
1320
+ <div style="display: flex; justify-content: space-between; font-size: 0.8rem;">
1321
+ <span style="color: var(--text-muted);">Final Output Payload Size:</span>
1322
+ <span id="capping-final-val" style="font-family: var(--font-mono); color: var(--color-emerald);">10 KB</span>
1323
+ </div>
1324
+ <div id="capping-hint-box" style="margin-top: 0.5rem; background: rgba(245, 158, 11, 0.05); border: 1px dashed rgba(245, 158, 11, 0.2); padding: 0.5rem; border-radius: 6px; font-size: 0.75rem; color: var(--color-amber); line-height: 1.4;">
1325
+ </div>
1326
+ </div>
1327
+ </div>
1328
+ </div>
1329
+ </div>
1330
+ </div>
1331
+
1332
+ </div>
1333
+
1334
+ <script>
1335
+ // Navigation Tabs logic
1336
+ function _switchTab(tabId) {
1337
+ document.querySelectorAll('.tab-btn').forEach(btn => { btn.classList.remove('active'); });
1338
+ document.querySelectorAll('.tab-pane').forEach(pane => { pane.classList.remove('active'); });
1339
+
1340
+ // Find button
1341
+ const btn = Array.from(document.querySelectorAll('.tab-btn')).find(b => b.onclick.toString().includes(tabId));
1342
+ if (btn) btn.classList.add('active');
1343
+
1344
+ document.getElementById(tabId).classList.add('active');
1345
+
1346
+ if (tabId === 'tab-calculator') {
1347
+ calculateTokenPressure();
1348
+ } else if (tabId === 'tab-simulator') {
1349
+ simulateToolFlow();
1350
+ }
1351
+ }
1352
+
1353
+ // --- SCENARIO DATA & CALCULATOR STATE ---
1354
+ const MOCK_FRAGMENTS = {
1355
+ identity: `You are Clio Coder, an advanced AI coding assistant engineered for scientific software development, high-performance computing (HPC), and numerical simulation workflows. Your goal is to guide the user in designing, compiling, testing, and debugging complex source code repositories while maintaining safety boundary restrictions. You are running as Clio Coder version 0.3.0.`,
1356
+
1357
+ mode_default: `Advisory: You are in default mode. Edits within the workspace are permitted. You have access to active inspection, modification, and execution tools. Ensure that you run tests to verify compilation.`,
1358
+ mode_advise: `Advisory: You are in advise mode. You may NOT edit codebase files directly, and you may NOT run execution tools (like bash). You can inspect files, write reviews, and write plans. Output an advisory markdown report as your final step.`,
1359
+ mode_super: `Advisory: You are in super mode. Full escalation is active. You have access to execution-class and system-modification tools. Execute effectful commands with precision.`,
1360
+
1361
+ safety_suggest: `Safety directive: suggest. Describe the proposed modifications, build procedures, or commands. Do not write file changes or execute commands.`,
1362
+ safety_auto_edit: `Safety directive: auto-edit. Edits inside the repository workspace are permitted without confirmation. Execution-class actions (like running bash commands) require confirmation.`,
1363
+ safety_full_auto: `Safety directive: full-auto. Edits and local commands are allowed to run automatically. System-level modifications and destructive git operations require explicit confirmations.`,
1364
+ };
1365
+
1366
+ const SCENARIOS = {
1367
+ standard: {
1368
+ mode: 'default',
1369
+ policy: 'reduced-repeated-envelope',
1370
+ thinking: 'applied',
1371
+ window: 32768,
1372
+ tools: ['read', 'write', 'edit', 'bash', 'grep', 'find', 'context'],
1373
+ memory: `Project goal: Refactor the MPI communicator wrapper in src/hpc/comm.ts to resolve thread races.\nRecent observation: The custom barrier function drifts during heavy MPI ranks exchange.`,
1374
+ project: `Language: TypeScript\nTarget: node\nActive workspace files:\n- src/hpc/comm.ts (3,400 bytes)\n- src/hpc/barrier.ts (1,200 bytes)\n- tests/comm.test.ts (2,500 bytes)`,
1375
+ notes: `Turn count: 4\nPrevious step: read src/hpc/comm.ts successfully.\nPending action: Locate race conditions inside MPI_Comm_dup wrapper.`,
1376
+ query: `Identify the thread race in src/hpc/comm.ts and write a replacement chunk using the edit tool.`
1377
+ },
1378
+ planning: {
1379
+ mode: 'advise',
1380
+ policy: 'reduced-repeated-envelope',
1381
+ thinking: 'applied',
1382
+ window: 32768,
1383
+ tools: ['read', 'grep', 'find', 'context', 'artifact'],
1384
+ memory: `Architecture review for compiler pipeline. Target is prefix cache friendly layout.\nGoal: Draft a 5-step plan to integrate TypeBox schemas into the worker subprocess layer safely.`,
1385
+ project: `Language: C++\nWorkspace files:\n- include/compiler.h\n- src/compiler.cpp`,
1386
+ notes: `Turn count: 1\nSession initialized.`,
1387
+ query: `Inspect include/compiler.h and write a plan inside docs/plans/typebox_migration.md to outline the migration steps.`
1388
+ },
1389
+ constrained: {
1390
+ mode: 'default',
1391
+ policy: 'prefix-cache-deterministic',
1392
+ thinking: 'always-on',
1393
+ window: 4096,
1394
+ tools: ['read', 'write', 'edit', 'grep'],
1395
+ memory: `Local model, minimal context window budget constraint.`,
1396
+ project: `Language: Python\nActive files: main.py`,
1397
+ notes: `Turn count: 8`,
1398
+ query: `Replace the division in main.py line 42 with a safe division wrapper.`
1399
+ },
1400
+ 'no-tools': {
1401
+ mode: 'advise',
1402
+ policy: 'no-tools-fallback',
1403
+ thinking: 'unsupported',
1404
+ window: 8192,
1405
+ tools: [],
1406
+ memory: `Model has no active tool capabilities this turn.`,
1407
+ project: `Language: Markdown`,
1408
+ notes: `Turn count: 2`,
1409
+ query: `Explain the difference between a prompt envelope and a tool contract.`
1410
+ }
1411
+ };
1412
+
1413
+ // Tools Metadata & Presets for Simulator. Toolkit v2: 18 tools across seven
1414
+ // planes (OBSERVE, MUTATE, EXECUTE, ORCHESTRATE, RETRIEVE, INTERACT, ARTIFACT).
1415
+ const ALL_TOOLS = {
1416
+ // OBSERVE
1417
+ read: { actionClass: 'read', estimate: 140, preset: '{\n "path": "src/domains/prompts/compiler.ts",\n "offset": 1,\n "limit": 100\n}' },
1418
+ grep: { actionClass: 'read', estimate: 120, preset: '{\n "pattern": "compileResult",\n "path": "src/",\n "mode": "content"\n}' },
1419
+ find: { actionClass: 'read', estimate: 110, preset: '{\n "pattern": "src/**/*.ts",\n "path": "src/"\n}' },
1420
+ ls: { actionClass: 'read', estimate: 100, preset: '{\n "path": "src/domains/prompts"\n}' },
1421
+ code_nav: { actionClass: 'read', estimate: 110, preset: '{\n "mode": "symbol",\n "query": "compile"\n}' },
1422
+ context: { actionClass: 'read', estimate: 120, preset: '{\n "scope": "docs",\n "query": "observation envelope"\n}' },
1423
+ credential_present: { actionClass: 'read', estimate: 90, preset: '{\n "name": "OPENAI_API_KEY"\n}' },
1424
+ // MUTATE
1425
+ write: { actionClass: 'write', estimate: 180, preset: '{\n "path": "src/domains/prompts/compiler.ts",\n "content": "// Modifying compile results"\n}' },
1426
+ edit: { actionClass: 'write', estimate: 220, preset: '{\n "path": "src/domains/prompts/compiler.ts",\n "edits": [\n {\n "oldText": "function lookupFragment() {",\n "newText": "function lookupFragment() {\\n // Optimized lookup"\n }\n ]\n}' },
1427
+ // EXECUTE
1428
+ bash: { actionClass: 'execute', estimate: 160, preset: '{\n "command": "npm run build && npm run test",\n "cwd": "/workspace"\n}' },
1429
+ git: { actionClass: 'read', estimate: 90, preset: '{\n "op": "status"\n}' },
1430
+ verify: { actionClass: 'execute', estimate: 110, preset: '{\n "check": "test"\n}' },
1431
+ // ORCHESTRATE
1432
+ dispatch: { actionClass: 'dispatch', estimate: 150, preset: '{\n "tasks": [\n {\n "agent": "coder",\n "task": "Rewrite compiler.ts with optimizations"\n }\n ]\n}' },
1433
+ monitor: { actionClass: 'read', estimate: 100, preset: '{\n "mode": "list"\n}' },
1434
+ steer: { actionClass: 'dispatch', estimate: 110, preset: '{\n "run_id": "run-01H...",\n "action": "guide",\n "message": "Limit the fix to tests/contracts."\n}' },
1435
+ // RETRIEVE
1436
+ web_fetch: { actionClass: 'read', estimate: 130, preset: '{\n "url": "https://iowarp.ai/docs/tools"\n}' },
1437
+ // INTERACT
1438
+ ask_user: { actionClass: 'read', estimate: 100, preset: '{\n "action": "ask",\n "questions": [\n {\n "question": "Proceed with the migration?"\n }\n ]\n}' },
1439
+ // ARTIFACT
1440
+ artifact: { actionClass: 'write', estimate: 140, preset: '{\n "kind": "plan",\n "content": "# Migration Plan\\n1. Move files\\n2. Build types"\n}' }
1441
+ };
1442
+
1443
+ const MODE_PROFILES = {
1444
+ default: {
1445
+ tools: ['read', 'grep', 'find', 'ls', 'code_nav', 'context', 'credential_present', 'write', 'edit', 'bash', 'git', 'verify', 'dispatch', 'monitor', 'steer', 'web_fetch', 'ask_user', 'artifact'],
1446
+ allowedActions: ['read', 'write', 'execute', 'dispatch'],
1447
+ dispatchScope: 'any'
1448
+ },
1449
+ advise: {
1450
+ tools: ['read', 'grep', 'find', 'ls', 'code_nav', 'context', 'credential_present', 'git', 'web_fetch', 'dispatch', 'monitor', 'steer', 'artifact'],
1451
+ allowedActions: ['read', 'write', 'dispatch'],
1452
+ dispatchScope: 'readonly'
1453
+ },
1454
+ super: {
1455
+ tools: ['read', 'grep', 'find', 'ls', 'code_nav', 'context', 'credential_present', 'write', 'edit', 'bash', 'git', 'verify', 'dispatch', 'monitor', 'steer', 'web_fetch', 'ask_user', 'artifact'],
1456
+ allowedActions: ['read', 'write', 'execute', 'dispatch', 'system_modify'],
1457
+ dispatchScope: 'any'
1458
+ }
1459
+ };
1460
+
1461
+ // State
1462
+ const selectedScenarioTools = new Set();
1463
+ let simHistory = [];
1464
+
1465
+ // Initialize
1466
+ window.addEventListener('DOMContentLoaded', () => {
1467
+ // Populate calculator tools checklists
1468
+ renderCalculatorToolsCheckboxes();
1469
+ loadScenario('standard');
1470
+
1471
+ // Populate simulator tools dropdown
1472
+ onSimModeChange();
1473
+ });
1474
+
1475
+ function renderCalculatorToolsCheckboxes() {
1476
+ const container = document.getElementById('tools-checkboxes');
1477
+ container.innerHTML = '';
1478
+
1479
+ Object.keys(ALL_TOOLS).forEach(toolName => {
1480
+ const label = document.createElement('label');
1481
+ label.className = 'checkbox-label';
1482
+
1483
+ const checkbox = document.createElement('input');
1484
+ checkbox.type = 'checkbox';
1485
+ checkbox.value = toolName;
1486
+ checkbox.id = `calc-tool-${toolName}`;
1487
+ checkbox.onchange = (e) => {
1488
+ if (e.target.checked) {
1489
+ selectedScenarioTools.add(toolName);
1490
+ } else {
1491
+ selectedScenarioTools.delete(toolName);
1492
+ }
1493
+ calculateTokenPressure();
1494
+ };
1495
+
1496
+ label.appendChild(checkbox);
1497
+ label.appendChild(document.createTextNode(toolName));
1498
+ container.appendChild(label);
1499
+ });
1500
+ }
1501
+
1502
+ function loadScenario(name) {
1503
+ const scenario = SCENARIOS[name];
1504
+ if (!scenario) return;
1505
+
1506
+ document.getElementById('context-window').value = scenario.window;
1507
+ document.getElementById('mode-select').value = scenario.mode;
1508
+ document.getElementById('delivery-mode').value = scenario.policy;
1509
+ document.getElementById('thinking-applied').value = scenario.thinking;
1510
+
1511
+ // Populate inputs
1512
+ let staticText = `[Fragment: identity/clio.md]\n${MOCK_FRAGMENTS.identity}\n\n`;
1513
+ staticText += `[Fragment: modes/${scenario.mode}.md]\n${MOCK_FRAGMENTS[`mode_${scenario.mode}`]}\n\n`;
1514
+
1515
+ // Set appropriate safety fragment based on mode
1516
+ let autonomyLevel = 'suggest';
1517
+ if (scenario.mode === 'default') autonomyLevel = 'auto-edit';
1518
+ if (scenario.mode === 'super') autonomyLevel = 'full-auto';
1519
+ const safetyFragmentKey = autonomyLevel.replace(/-/g, '_');
1520
+
1521
+ staticText += `[Fragment: safety/${autonomyLevel}.md]\n${MOCK_FRAGMENTS[`safety_${safetyFragmentKey}`]}`;
1522
+
1523
+ document.getElementById('static-shell-input').value = staticText;
1524
+ document.getElementById('dynamic-memory-input').value = scenario.memory;
1525
+ document.getElementById('dynamic-project-input').value = scenario.project;
1526
+ document.getElementById('user-query-input').value = scenario.query;
1527
+
1528
+ // Set checked tools
1529
+ selectedScenarioTools.clear();
1530
+ scenario.tools.forEach(t => { selectedScenarioTools.add(t); });
1531
+
1532
+ // Update DOM checkboxes
1533
+ Object.keys(ALL_TOOLS).forEach(t => {
1534
+ const el = document.getElementById(`calc-tool-${t}`);
1535
+ if (el) {
1536
+ el.checked = scenario.tools.includes(t);
1537
+ // Show/hide based on mode visibility rules
1538
+ const isVisible = MODE_PROFILES[scenario.mode].tools.includes(t);
1539
+ el.parentElement.style.opacity = isVisible ? '1' : '0.4';
1540
+ }
1541
+ });
1542
+
1543
+ calculateTokenPressure();
1544
+ }
1545
+
1546
+ function _onModeChange() {
1547
+ const mode = document.getElementById('mode-select').value;
1548
+
1549
+ // Disable/enable tools that are not visible in this mode
1550
+ Object.keys(ALL_TOOLS).forEach(t => {
1551
+ const el = document.getElementById(`calc-tool-${t}`);
1552
+ if (el) {
1553
+ const isVisible = MODE_PROFILES[mode].tools.includes(t);
1554
+ el.parentElement.style.opacity = isVisible ? '1' : '0.4';
1555
+ if (!isVisible && el.checked) {
1556
+ el.checked = false;
1557
+ selectedScenarioTools.delete(t);
1558
+ }
1559
+ }
1560
+ });
1561
+
1562
+ // Reload standard static prompt content for that mode
1563
+ let staticText = `[Fragment: identity/clio.md]\n${MOCK_FRAGMENTS.identity}\n\n`;
1564
+ staticText += `[Fragment: modes/${mode}.md]\n${MOCK_FRAGMENTS[`mode_${mode}`]}\n\n`;
1565
+
1566
+ let autonomyLevel = 'suggest';
1567
+ if (mode === 'default') autonomyLevel = 'auto-edit';
1568
+ if (mode === 'super') autonomyLevel = 'full-auto';
1569
+ const safetyFragmentKey = autonomyLevel.replace(/-/g, '_');
1570
+
1571
+ staticText += `[Fragment: safety/${autonomyLevel}.md]\n${MOCK_FRAGMENTS[`safety_${safetyFragmentKey}`]}`;
1572
+ document.getElementById('static-shell-input').value = staticText;
1573
+
1574
+ calculateTokenPressure();
1575
+ }
1576
+
1577
+ // Helper token estimator
1578
+ function estimateTokens(text) {
1579
+ const trimmed = text.trim();
1580
+ if (trimmed.length === 0) return 0;
1581
+ return Math.ceil(trimmed.length / 4);
1582
+ }
1583
+
1584
+ // Simple string hashing helper for simulated visual output
1585
+ async function computeHash(text) {
1586
+ if (!text) return "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; // Empty hash
1587
+ const msgBuffer = new TextEncoder().encode(text);
1588
+ try {
1589
+ const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
1590
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
1591
+ return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
1592
+ } catch (e) {
1593
+ // Fallback simple hash for offline environments
1594
+ let hash = 0;
1595
+ for (let i = 0; i < text.length; i++) {
1596
+ hash = (hash << 5) - hash + text.charCodeAt(i);
1597
+ hash |= 0;
1598
+ }
1599
+ return `mocked_hash_${Math.abs(hash).toString(16).padStart(16, '0')}`;
1600
+ }
1601
+ }
1602
+
1603
+ async function calculateTokenPressure() {
1604
+ const contextLimit = parseInt(document.getElementById('context-window').value, 10);
1605
+ const mode = document.getElementById('mode-select').value;
1606
+ const deliveryMode = document.getElementById('delivery-mode').value;
1607
+ const thinking = document.getElementById('thinking-applied').value;
1608
+
1609
+ // Inputs
1610
+ const staticText = document.getElementById('static-shell-input').value;
1611
+ const memory = document.getElementById('dynamic-memory-input').value;
1612
+ const project = document.getElementById('dynamic-project-input').value;
1613
+ const query = document.getElementById('user-query-input').value;
1614
+
1615
+ // Tokens estimates
1616
+ const staticTokens = estimateTokens(staticText);
1617
+
1618
+ // Build runtime section (Simulating renderRuntimeBlock)
1619
+ let runtimeText = `# Runtime\nProvider: local-harness\nModel: local-32b\nContext window: ${contextLimit}\nPrompt delivery mode: ${deliveryMode}`;
1620
+ if (thinking === 'applied') {
1621
+ runtimeText += `\nThinking level: medium\nThinking mechanism: thinking\nThinking applied: applied`;
1622
+ }
1623
+ const runtimeTokens = estimateTokens(runtimeText);
1624
+
1625
+ // Build tool contract block (Simulating renderToolContractBlock)
1626
+ let toolContractText = `# Tool Contract\nProvider tool calls: ${deliveryMode !== 'no-tools-fallback' ? 'available' : 'unavailable'}.\n`;
1627
+ if (deliveryMode === 'no-tools-fallback' || selectedScenarioTools.size === 0) {
1628
+ toolContractText += `Active tools this turn: none.\nAnswer directly. Do not claim repository facts that require inspection.`;
1629
+ } else {
1630
+ toolContractText += `Active tools this turn: ${Array.from(selectedScenarioTools).join(', ')}.\n`;
1631
+ toolContractText += `Only call tools in the active list, and only for concrete inspection or changes.`;
1632
+ }
1633
+ const contractTokens = estimateTokens(toolContractText);
1634
+
1635
+ // Tools schemas token estimate
1636
+ let toolSchemasTokens = 0;
1637
+ if (deliveryMode !== 'no-tools-fallback') {
1638
+ selectedScenarioTools.forEach(t => {
1639
+ toolSchemasTokens += ALL_TOOLS[t]?.estimate || 50;
1640
+ });
1641
+ }
1642
+
1643
+ // Dynamic Turn items
1644
+ const memoryText = memory ? `# Memory\n\n${memory}` : '';
1645
+ const memoryTokens = estimateTokens(memoryText);
1646
+
1647
+ const projectText = project ? `# Project\n\n${project}` : '';
1648
+ const projectTokens = estimateTokens(projectText);
1649
+
1650
+ const sessionText = `# Session\nTurn count: 1\nNotes: active debugging session`;
1651
+ const sessionTokens = estimateTokens(sessionText);
1652
+
1653
+ const queryText = query ? `# Request\n\n${query}` : '';
1654
+ const queryTokens = estimateTokens(queryText);
1655
+
1656
+ // Retrieval Hints
1657
+ let hintsText = '';
1658
+ if (deliveryMode !== 'no-tools-fallback' && selectedScenarioTools.size > 0) {
1659
+ hintsText = `# Retrieval Hints\nRepository structure and CLIO-CODER.md are not preloaded. Use context(scope="workspace").`;
1660
+ }
1661
+ const hintsTokens = estimateTokens(hintsText);
1662
+
1663
+ // Tiers mapping
1664
+ // static-shell: staticText
1665
+ // session-shell: runtimeText, toolContractText, hintsText
1666
+ // dynamic-turn: memoryText, projectText, sessionText, queryText
1667
+ const staticShellTotal = staticTokens;
1668
+ const sessionShellTotal = runtimeTokens + contractTokens + hintsTokens;
1669
+ const dynamicTurnTotal = memoryTokens + projectTokens + sessionTokens + queryTokens;
1670
+
1671
+ const totalPromptTokens = staticShellTotal + sessionShellTotal + dynamicTurnTotal + toolSchemasTokens;
1672
+ const remainingCapacity = Math.max(0, contextLimit - totalPromptTokens);
1673
+ const pressurePercent = ((totalPromptTokens / contextLimit) * 100).toFixed(2);
1674
+
1675
+ // UI Updates
1676
+ document.getElementById('val-static').innerText = staticShellTotal.toLocaleString();
1677
+ document.getElementById('val-session').innerText = sessionShellTotal.toLocaleString();
1678
+ document.getElementById('val-dynamic').innerText = dynamicTurnTotal.toLocaleString();
1679
+ document.getElementById('val-tools').innerText = toolSchemasTokens.toLocaleString();
1680
+
1681
+ document.getElementById('pressure-ratio').innerText = `${totalPromptTokens.toLocaleString()} / ${contextLimit.toLocaleString()} (${pressurePercent}%)`;
1682
+
1683
+ const pressureBar = document.getElementById('pressure-bar');
1684
+ pressureBar.style.width = `${Math.min(100, parseFloat(pressurePercent))}%`;
1685
+
1686
+ const capacityStatus = document.getElementById('capacity-status');
1687
+ const capacityLeft = document.getElementById('capacity-left');
1688
+ capacityLeft.innerText = `${remainingCapacity.toLocaleString()} tokens remaining`;
1689
+
1690
+ if (totalPromptTokens > contextLimit) {
1691
+ pressureBar.style.backgroundColor = 'var(--color-rose)';
1692
+ capacityStatus.innerText = 'OVERFLOW';
1693
+ capacityStatus.className = 'status-pill pill-rose';
1694
+ } else if (parseFloat(pressurePercent) > 85) {
1695
+ pressureBar.style.backgroundColor = 'var(--color-rose)';
1696
+ capacityStatus.innerText = 'CRITICAL';
1697
+ capacityStatus.className = 'status-pill pill-rose';
1698
+ } else if (parseFloat(pressurePercent) > 60) {
1699
+ pressureBar.style.backgroundColor = 'var(--color-amber)';
1700
+ capacityStatus.innerText = 'WARNING';
1701
+ capacityStatus.className = 'status-pill pill-amber';
1702
+ } else {
1703
+ pressureBar.style.backgroundColor = 'var(--color-emerald)';
1704
+ capacityStatus.innerText = 'OPTIMAL';
1705
+ capacityStatus.className = 'status-pill pill-emerald';
1706
+ }
1707
+
1708
+ // Hashes recomputation
1709
+ const staticTextHash = await computeHash(staticText);
1710
+ const sessionTextHash = await computeHash(`${runtimeText}\n\n${toolContractText}\n\n${hintsText}`);
1711
+ const dynamicTextHash = await computeHash(`${memoryText}\n\n${projectText}\n\n${sessionText}\n\n${queryText}`);
1712
+
1713
+ const fullPromptText = [staticText, runtimeText, toolContractText, hintsText, memoryText, projectText, sessionText, queryText]
1714
+ .filter(x => x.trim().length > 0).join("\n\n");
1715
+ const fullTextHash = await computeHash(fullPromptText);
1716
+
1717
+ // System prompt sent
1718
+ const systemPromptCompiled = [staticText, runtimeText, toolContractText, hintsText].filter(x => x.trim().length > 0).join("\n\n");
1719
+ document.getElementById('system-prompt-out').innerText = systemPromptCompiled || "[Empty]";
1720
+
1721
+ // Fill table
1722
+ const segmentsTable = document.getElementById('segments-table-body');
1723
+ segmentsTable.innerHTML = '';
1724
+
1725
+ const segments = [
1726
+ { id: 'identity', tier: 'static-shell', hash: await computeHash(MOCK_FRAGMENTS.identity), tokens: estimateTokens(MOCK_FRAGMENTS.identity), incl: true },
1727
+ { id: 'mode', tier: 'static-shell', hash: await computeHash(MOCK_FRAGMENTS[`mode_${mode}`]), tokens: estimateTokens(MOCK_FRAGMENTS[`mode_${mode}`]), incl: true },
1728
+ { id: 'runtime', tier: 'session-shell', hash: await computeHash(runtimeText), tokens: runtimeTokens, incl: true },
1729
+ { id: 'tool-contract', tier: 'session-shell', hash: await computeHash(toolContractText), tokens: contractTokens, incl: true },
1730
+ { id: 'retrieval-hints', tier: 'session-shell', hash: await computeHash(hintsText), tokens: hintsTokens, incl: hintsText.length > 0 },
1731
+ { id: 'memory', tier: 'dynamic-turn', hash: await computeHash(memoryText), tokens: memoryTokens, incl: memoryText.length > 0 },
1732
+ { id: 'project-context', tier: 'dynamic-turn', hash: await computeHash(projectText), tokens: projectTokens, incl: projectText.length > 0 },
1733
+ { id: 'user-request', tier: 'dynamic-turn', hash: await computeHash(queryText), tokens: queryTokens, incl: queryText.length > 0 }
1734
+ ];
1735
+
1736
+ segments.forEach(s => {
1737
+ const row = document.createElement('tr');
1738
+ row.style.opacity = s.incl ? '1' : '0.4';
1739
+ row.innerHTML = `
1740
+ <td style="font-family:var(--font-mono); font-weight:600;">${s.id}</td>
1741
+ <td><span class="status-pill ${s.tier === 'static-shell' ? 'pill-cyan' : s.tier === 'session-shell' ? 'pill-purple' : 'pill-emerald'}">${s.tier}</span></td>
1742
+ <td><span class="hash-badge" title="${s.hash}">${s.hash}</span></td>
1743
+ <td style="font-family:var(--font-mono); text-align:right;">${s.tokens}</td>
1744
+ <td>${s.incl ? 'Included' : 'Skipped'}</td>
1745
+ `;
1746
+ segmentsTable.appendChild(row);
1747
+ });
1748
+
1749
+ // Envelope Signature JSON output
1750
+ const envelopeSig = {
1751
+ version: 1,
1752
+ promptSignature: fullTextHash,
1753
+ staticShellHash: staticTextHash,
1754
+ sessionShellHash: sessionTextHash,
1755
+ dynamicHash: dynamicTextHash,
1756
+ parts: [
1757
+ { id: "pinnedHarness", tier: "static-shell", contentHash: staticTextHash, tokenEstimate: staticShellTotal, included: true },
1758
+ { id: "pinnedRuntime", tier: "session-shell", contentHash: await computeHash(runtimeText), tokenEstimate: runtimeTokens, included: true },
1759
+ { id: "pinnedToolContract", tier: "session-shell", contentHash: await computeHash(toolContractText), tokenEstimate: contractTokens, included: true },
1760
+ { id: "sessionContext", tier: "dynamic-turn", contentHash: await computeHash(`${memoryText}\n\n${sessionText}`), tokenEstimate: memoryTokens + sessionTokens, included: true },
1761
+ { id: "turnContext", tier: "dynamic-turn", contentHash: await computeHash(`${projectText}\n\n${queryText}`), tokenEstimate: projectTokens + queryTokens, included: true },
1762
+ { id: "retrievalHints", tier: "session-shell", contentHash: await computeHash(hintsText), tokenEstimate: hintsTokens, included: hintsText.length > 0 }
1763
+ ]
1764
+ };
1765
+
1766
+ document.getElementById('envelope-signature-out').innerText = JSON.stringify(envelopeSig, null, 2);
1767
+ }
1768
+
1769
+ // --- SIMULATOR LOGIC ---
1770
+ function onSimModeChange() {
1771
+ const mode = document.getElementById('sim-mode-select').value;
1772
+ const toolSelect = document.getElementById('sim-tool-select');
1773
+ toolSelect.innerHTML = '';
1774
+
1775
+ const visibleTools = MODE_PROFILES[mode].tools;
1776
+ visibleTools.forEach(toolName => {
1777
+ const opt = document.createElement('option');
1778
+ opt.value = toolName;
1779
+ opt.innerText = `${toolName} (Action: ${ALL_TOOLS[toolName].actionClass})`;
1780
+ toolSelect.appendChild(opt);
1781
+ });
1782
+
1783
+ onSimToolChange();
1784
+ }
1785
+
1786
+ function onSimToolChange() {
1787
+ const toolName = document.getElementById('sim-tool-select').value;
1788
+ if (!toolName || !ALL_TOOLS[toolName]) return;
1789
+
1790
+ document.getElementById('sim-args').value = ALL_TOOLS[toolName].preset;
1791
+ simulateToolFlow();
1792
+ }
1793
+
1794
+ // Canonical JSON implementation in JS
1795
+ function canonicalJson(value) {
1796
+ if (value === undefined) {
1797
+ throw new Error("canonicalJson: undefined is not representable at root");
1798
+ }
1799
+ return canonicalSerialize(value, new WeakSet());
1800
+ }
1801
+
1802
+ function canonicalSerialize(value, seen) {
1803
+ if (value === null) return "null";
1804
+ if (typeof value === "number") {
1805
+ if (!Number.isFinite(value)) {
1806
+ throw new Error("canonicalJson: non-finite number is not representable");
1807
+ }
1808
+ return JSON.stringify(value);
1809
+ }
1810
+ if (typeof value === "string" || typeof value === "boolean") {
1811
+ return JSON.stringify(value);
1812
+ }
1813
+ if (typeof value === "bigint") {
1814
+ throw new Error("canonicalJson: bigint is not representable");
1815
+ }
1816
+ if (typeof value === "symbol" || typeof value === "function") {
1817
+ throw new Error("canonicalJson: unsupported type");
1818
+ }
1819
+ if (Array.isArray(value)) {
1820
+ if (seen.has(value)) throw new Error("canonicalJson: circular reference");
1821
+ seen.add(value);
1822
+ try {
1823
+ const parts = [];
1824
+ for (let i = 0; i < value.length; i++) {
1825
+ if (!(i in value) || value[i] === undefined) {
1826
+ parts.push("null");
1827
+ continue;
1828
+ }
1829
+ parts.push(canonicalSerialize(value[i], seen));
1830
+ }
1831
+ return `[${parts.join(",")}]`;
1832
+ } finally {
1833
+ seen.delete(value);
1834
+ }
1835
+ }
1836
+ if (typeof value === "object") {
1837
+ if (value instanceof Date) {
1838
+ return JSON.stringify(value.toJSON());
1839
+ }
1840
+ if (seen.has(value)) throw new Error("canonicalJson: circular reference");
1841
+ seen.add(value);
1842
+ try {
1843
+ const keys = Object.keys(value).sort();
1844
+ const parts = [];
1845
+ for (const key of keys) {
1846
+ const child = value[key];
1847
+ if (child === undefined) continue;
1848
+ parts.push(`${JSON.stringify(key)}:${canonicalSerialize(child, seen)}`);
1849
+ }
1850
+ return `{${parts.join(",")}}`;
1851
+ } finally {
1852
+ seen.delete(value);
1853
+ }
1854
+ }
1855
+ throw new Error("canonicalJson: unsupported type");
1856
+ }
1857
+
1858
+ // Simple UTF-8 byte truncation matching truncate-utf8
1859
+ function truncateUtf8(str, maxBytes, marker = "") {
1860
+ const encoder = new TextEncoder();
1861
+ const encoded = encoder.encode(str);
1862
+ if (encoded.length <= maxBytes) return str;
1863
+
1864
+ // Account for marker length
1865
+ const markerEncoded = encoder.encode(marker);
1866
+ const limit = maxBytes - markerEncoded.length;
1867
+
1868
+ if (limit <= 0) return marker;
1869
+
1870
+ // Find valid UTF-8 character boundary
1871
+ let index = limit;
1872
+ // In UTF-8, continuation bytes start with bits 10xxxxxx (0x80 to 0xBF)
1873
+ // We backtrack until we find a byte that does not match this pattern
1874
+ while (index > 0 && (encoded[index] & 0xC0) === 0x80) {
1875
+ index--;
1876
+ }
1877
+
1878
+ const truncatedBytes = encoded.slice(0, index);
1879
+ const decoder = new TextDecoder("utf-8");
1880
+ return decoder.decode(truncatedBytes) + marker;
1881
+ }
1882
+
1883
+ function getByteLength(str) {
1884
+ return new TextEncoder().encode(str).length;
1885
+ }
1886
+
1887
+ async function simulateToolFlow() {
1888
+ const toolName = document.getElementById('sim-tool-select').value;
1889
+ const mode = document.getElementById('sim-mode-select').value;
1890
+ const rawArgsText = document.getElementById('sim-args').value;
1891
+ const rawOutput = document.getElementById('sim-raw-output').value;
1892
+ const maxBytes = parseInt(document.getElementById('sim-max-bytes').value, 10) || 200;
1893
+
1894
+ const errEl = document.getElementById('args-json-err');
1895
+ errEl.style.display = 'none';
1896
+
1897
+ let parsedArgs = {};
1898
+ try {
1899
+ parsedArgs = JSON.parse(rawArgsText);
1900
+ } catch (e) {
1901
+ errEl.style.display = 'block';
1902
+ return;
1903
+ }
1904
+
1905
+ // 1. Canonical Serialization
1906
+ let canonical = "";
1907
+ try {
1908
+ canonical = canonicalJson(parsedArgs);
1909
+ document.getElementById('canonical-args-out').innerText = canonical;
1910
+ } catch (e) {
1911
+ document.getElementById('canonical-args-out').innerText = `Error serializing: ${e.message}`;
1912
+ return;
1913
+ }
1914
+
1915
+ // 2. Hash compute
1916
+ const hash = await computeHash(`${toolName}${canonical}`);
1917
+ document.getElementById('call-hash-out').innerText = hash;
1918
+
1919
+ // 3. Classification
1920
+ const toolMeta = ALL_TOOLS[toolName];
1921
+ const actionClass = toolMeta ? toolMeta.actionClass : 'unknown';
1922
+ document.getElementById('class-out').innerText = actionClass;
1923
+
1924
+ // 4. Registry Gate evaluation
1925
+ const verdictBox = document.getElementById('verdict-display');
1926
+ const profile = MODE_PROFILES[mode];
1927
+
1928
+ let verdictKind = "ok";
1929
+ let blockReason = "";
1930
+
1931
+ // Check Visibility
1932
+ if (!profile.tools.includes(toolName)) {
1933
+ verdictKind = "not_visible";
1934
+ blockReason = `Registry rejection: Tool '${toolName}' is not visible in mode '${mode}'.`;
1935
+ }
1936
+ // Check Action Class
1937
+ else if (!profile.allowedActions.includes(actionClass)) {
1938
+ // artifact (kind=plan/review) is the advise-mode write: plans and reviews
1939
+ if (mode === 'advise' && actionClass === 'write' && toolName === 'artifact') {
1940
+ // permitted
1941
+ } else {
1942
+ verdictKind = "blocked";
1943
+ blockReason = `Registry Blocked: Action class '${actionClass}' is not allowed in mode '${mode}'.`;
1944
+ }
1945
+ }
1946
+ // Hard-blocks simulation: project rules & protected paths
1947
+ else if (actionClass === 'execute' && rawArgsText.includes('rm -rf')) {
1948
+ verdictKind = "blocked";
1949
+ blockReason = `Safety Gate Blocked: Command contains destructive pattern 'rm -rf'. Hard-blocked by damage-control rules.`;
1950
+ }
1951
+ else if (rawArgsText.includes('.git/config') || rawArgsText.includes('/etc/passwd')) {
1952
+ verdictKind = "blocked";
1953
+ blockReason = `Safety Gate Blocked: Path is protected. Write/read actions on configuration artifacts are denied.`;
1954
+ }
1955
+
1956
+ // Check loop detection (repetition check)
1957
+ // Filter history to last 10 seconds
1958
+ const now = Date.now();
1959
+ const activeHistory = simHistory.filter(h => now - h.timestamp < 10000);
1960
+ const matches = activeHistory.filter(h => h.hash === hash);
1961
+
1962
+ if (verdictKind === "ok") {
1963
+ if (matches.length > 0) {
1964
+ verdictKind = "blocked";
1965
+ blockReason = `Loop Guard Blocked: Tool '${toolName}' with identical arguments repeated ${matches.length + 1} times in 10000ms. Aborting to prevent runaway execution.`;
1966
+ } else if (simHistory.length >= 50) {
1967
+ verdictKind = "blocked";
1968
+ blockReason = `Registry Cap Blocked: Turn tool-call cap reached (50 calls). Invocation denied.`;
1969
+ }
1970
+ }
1971
+
1972
+ // Show Verdict Pill
1973
+ verdictBox.className = "verdict-box show";
1974
+ if (verdictKind === "ok") {
1975
+ verdictBox.innerText = `Verdict: Admitted & Executed successfully.`;
1976
+ verdictBox.classList.add('allow');
1977
+ } else {
1978
+ verdictBox.innerText = verdictKind === 'not_visible' ? `Verdict: Rejected (Not Visible)\n${blockReason}` : `Verdict: Blocked\n${blockReason}`;
1979
+ verdictBox.classList.add('block');
1980
+ }
1981
+
1982
+ // 5. Result Shaping (If Admitted)
1983
+ if (verdictKind === "ok") {
1984
+ const byteSize = getByteLength(rawOutput);
1985
+ const isTruncated = byteSize > maxBytes;
1986
+ const followUp = "Use offset/limit arguments or narrow the path query to inspect omitted contents.";
1987
+
1988
+ let finalOutputText = rawOutput;
1989
+ const resultSizeDetails = {
1990
+ bytes: byteSize,
1991
+ shownBytes: byteSize,
1992
+ maxBytes: maxBytes,
1993
+ truncated: false,
1994
+ policy: "truncate",
1995
+ followUpHint: followUp
1996
+ };
1997
+
1998
+ if (isTruncated) {
1999
+ const truncatedContent = truncateUtf8(rawOutput, maxBytes, "\n[tool result truncated]");
2000
+ finalOutputText = `${truncatedContent}\n\n[${followUp}]`;
2001
+ resultSizeDetails.shownBytes = getByteLength(finalOutputText);
2002
+ resultSizeDetails.truncated = true;
2003
+ }
2004
+
2005
+ const toolResult = {
2006
+ kind: "ok",
2007
+ output: finalOutputText
2008
+ };
2009
+
2010
+ const detailsPayload = {
2011
+ resultSize: resultSizeDetails
2012
+ };
2013
+
2014
+ document.getElementById('shaped-result-out').innerText = JSON.stringify(toolResult, null, 2);
2015
+ document.getElementById('result-details-out').innerText = JSON.stringify(detailsPayload, null, 2);
2016
+ } else {
2017
+ // Return Blocked / Error Result
2018
+ const toolResult = {
2019
+ kind: "error",
2020
+ message: blockReason
2021
+ };
2022
+ document.getElementById('shaped-result-out').innerText = JSON.stringify(toolResult, null, 2);
2023
+ document.getElementById('result-details-out').innerText = JSON.stringify({ errorDetails: { verdict: verdictKind, reason: blockReason } }, null, 2);
2024
+ }
2025
+ }
2026
+
2027
+ function _executeSimulatedCall() {
2028
+ const toolName = document.getElementById('sim-tool-select').value;
2029
+ const rawArgsText = document.getElementById('sim-args').value;
2030
+
2031
+ let parsedArgs = {};
2032
+ try {
2033
+ parsedArgs = JSON.parse(rawArgsText);
2034
+ } catch (e) {
2035
+ alert("Invalid JSON arguments!");
2036
+ return;
2037
+ }
2038
+
2039
+ const canonical = canonicalJson(parsedArgs);
2040
+ computeHash(`${toolName}${canonical}`).then(hash => {
2041
+ // Add to history
2042
+ simHistory.push({
2043
+ tool: toolName,
2044
+ args: canonical,
2045
+ hash: hash,
2046
+ timestamp: Date.now()
2047
+ });
2048
+
2049
+ renderHistory();
2050
+ simulateToolFlow();
2051
+ });
2052
+ }
2053
+
2054
+ function renderHistory() {
2055
+ const container = document.getElementById('history-items');
2056
+ container.innerHTML = '';
2057
+
2058
+ if (simHistory.length === 0) {
2059
+ container.innerHTML = `<div style="color:var(--text-dark); text-align:center; padding:1.5rem 0; font-size:0.85rem;">No recent calls in buffer</div>`;
2060
+ return;
2061
+ }
2062
+
2063
+ // Sort showing newest first
2064
+ const reversed = [...simHistory].reverse();
2065
+ reversed.forEach(item => {
2066
+ const el = document.createElement('div');
2067
+ el.className = 'history-item';
2068
+
2069
+ const timeStr = new Date(item.timestamp).toLocaleTimeString();
2070
+ const summaryArgs = item.args.length > 30 ? `${item.args.slice(0, 30)}...` : item.args;
2071
+
2072
+ el.innerHTML = `
2073
+ <div>
2074
+ <span style="color:var(--color-cyan); font-weight:700;">${item.tool}</span>
2075
+ <span style="color:var(--text-muted); font-size:0.75rem;">${summaryArgs}</span>
2076
+ </div>
2077
+ <div class="history-timestamp">${timeStr}</div>
2078
+ `;
2079
+ container.appendChild(el);
2080
+ });
2081
+ }
2082
+
2083
+ function _clearSimHistory() {
2084
+ simHistory = [];
2085
+ renderHistory();
2086
+ simulateToolFlow();
2087
+ }
2088
+
2089
+ // Copy helper
2090
+ function _copyText(elementId) {
2091
+ const text = document.getElementById(elementId).innerText;
2092
+ navigator.clipboard.writeText(text).then(() => {
2093
+ alert("Copied to clipboard!");
2094
+ }).catch(err => {
2095
+ console.error('Could not copy text: ', err);
2096
+ });
2097
+ }
2098
+
2099
+ // --- RECOMPILER AND CAPPING VALIDATOR SIMULATOR ---
2100
+ let lastCompileKey = "";
2101
+ let lastCompileHash = "";
2102
+ const recompileLedger = [];
2103
+
2104
+ function cyrb128(str) {
2105
+ let h1 = 1779033703, h2 = 3024733165, h3 = 3362453605, h4 = 502492259;
2106
+ for (let i = 0, k; i < str.length; i++) {
2107
+ k = str.charCodeAt(i);
2108
+ h1 = h2 ^ Math.imul(h1 ^ k, 597399067);
2109
+ h2 = h3 ^ Math.imul(h2 ^ k, 2869860233);
2110
+ h3 = h4 ^ Math.imul(h3 ^ k, 951274213);
2111
+ h4 = h1 ^ Math.imul(h4 ^ k, 2716044179);
2112
+ }
2113
+ h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067);
2114
+ h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233);
2115
+ h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213);
2116
+ h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179);
2117
+ return [(h1^h2^h3^h4)>>>0, (h2^h1)>>>0, (h3^h1)>>>0, (h4^h1)>>>0];
2118
+ }
2119
+ function simpleHash(str) {
2120
+ const hashes = cyrb128(str);
2121
+ return hashes.map(h => h.toString(16).padStart(8, '0')).join('');
2122
+ }
2123
+
2124
+ function simulateRecompilerAndCapping() {
2125
+ // 1. Recompiler Logic
2126
+ const ep = document.getElementById("recomp-endpoint").value;
2127
+ const model = document.getElementById("recomp-model").value;
2128
+ const autonomy = document.getElementById("recomp-autonomy").value;
2129
+ const session = document.getElementById("recomp-session").value.trim() || "sess_default";
2130
+ const hotReload = document.getElementById("recomp-hotreload").checked;
2131
+
2132
+ const compileKey = `${ep}|${model}|${autonomy}|${session}`;
2133
+ const compileHash = simpleHash(compileKey).substring(0, 16);
2134
+
2135
+ document.getElementById("recomp-key-out").innerText = compileKey;
2136
+ document.getElementById("recomp-hash-out").innerText = compileHash;
2137
+
2138
+ const ledgerEl = document.getElementById("recomp-ledger-out");
2139
+
2140
+ let forced = false;
2141
+ let compiled = false;
2142
+
2143
+ if (compileKey !== lastCompileKey || hotReload) {
2144
+ compiled = true;
2145
+ if (hotReload) {
2146
+ forced = true;
2147
+ document.getElementById("recomp-hotreload").checked = false; // Reset toggle
2148
+ }
2149
+
2150
+ const prevHash = lastCompileHash || "none";
2151
+ const tokenEst = 3500 + Math.floor(Math.random() * 800) + (autonomy.length * 20);
2152
+
2153
+ const logEntry = {
2154
+ timestamp: new Date().toLocaleTimeString(),
2155
+ event: "promptRecompiled",
2156
+ prevHash: prevHash,
2157
+ newHash: compileHash,
2158
+ tokenEstimate: tokenEst,
2159
+ reason: forced ? "Config Hot-Reload Invalidation" : "Compile Key Changed"
2160
+ };
2161
+
2162
+ recompileLedger.unshift(logEntry);
2163
+
2164
+ lastCompileKey = compileKey;
2165
+ lastCompileHash = compileHash;
2166
+ }
2167
+
2168
+ // Render Ledger
2169
+ ledgerEl.innerHTML = "";
2170
+ if (recompileLedger.length === 0) {
2171
+ ledgerEl.innerHTML = `<div style="color:var(--text-dark); text-align:center; padding:1rem 0;">No ledger entries yet</div>`;
2172
+ } else {
2173
+ recompileLedger.forEach(entry => {
2174
+ const item = document.createElement("div");
2175
+ item.style.paddingBottom = "0.4rem";
2176
+ item.style.borderBottom = "1px solid rgba(255,255,255,0.02)";
2177
+ item.innerHTML = `
2178
+ <span style="color:var(--text-muted); font-size:0.75rem;">[${entry.timestamp}]</span>
2179
+ <span style="color:var(--color-purple); font-weight:bold;">${entry.event}</span>:
2180
+ prev=<span style="color:var(--text-dark);">${entry.prevHash}</span>,
2181
+ new=<span style="color:var(--color-cyan);">${entry.newHash}</span>,
2182
+ tokens=<span style="color:var(--color-amber);">${entry.tokenEstimate}</span>
2183
+ <span style="color:var(--text-dark); font-size:0.75rem;">(${entry.reason})</span>
2184
+ `;
2185
+ ledgerEl.appendChild(item);
2186
+ });
2187
+ }
2188
+
2189
+ if (compiled) {
2190
+ ledgerEl.style.borderColor = "var(--color-cyan)";
2191
+ setTimeout(() => { ledgerEl.style.borderColor = "var(--border-card)"; }, 3000);
2192
+ }
2193
+
2194
+ // 2. Capping Validator Logic
2195
+ const capTool = document.getElementById("capping-tool").value;
2196
+ const mockSizeKB = parseInt(document.getElementById("capping-size").value, 10);
2197
+ document.getElementById("capping-size-val").innerText = `${mockSizeKB} KB`;
2198
+
2199
+ let limitKB = 6;
2200
+ let hint = "";
2201
+ let truncated = false;
2202
+
2203
+ if (capTool === "read") {
2204
+ limitKB = 6;
2205
+ truncated = mockSizeKB > limitKB;
2206
+ if (truncated) {
2207
+ hint = `Result capped at source policy limit of 6KB. Continuation text added: "Use offset/limit arguments or narrow the path query to inspect omitted contents."`;
2208
+ } else {
2209
+ hint = "Result is within the 6KB safety limit and delivered in full.";
2210
+ }
2211
+ } else if (capTool === "bash") {
2212
+ limitKB = 16;
2213
+ truncated = mockSizeKB > limitKB;
2214
+ if (truncated) {
2215
+ hint = `Result capped at summary-kind policy limit of 16KB. Trailing terminal lines omitted.`;
2216
+ } else {
2217
+ hint = "Result is within the 16KB summary safety limit and delivered in full.";
2218
+ }
2219
+ } else if (capTool === "ask_user") {
2220
+ limitKB = 20;
2221
+ truncated = mockSizeKB > limitKB;
2222
+ if (truncated) {
2223
+ hint = `Result capped at ask_user policy limit of 20KB. Excess query context removed.`;
2224
+ } else {
2225
+ hint = "Result is within the 20KB ask_user safety limit and delivered in full.";
2226
+ }
2227
+ }
2228
+
2229
+ const finalSizeKB = truncated ? limitKB : mockSizeKB;
2230
+
2231
+ const truncBadge = document.getElementById("capping-truncated-badge");
2232
+ truncBadge.innerText = truncated ? "YES (Capped)" : "NO";
2233
+ truncBadge.style.color = truncated ? "var(--color-rose)" : "var(--color-emerald)";
2234
+
2235
+ document.getElementById("capping-limit-val").innerText = `${limitKB} KB`;
2236
+ document.getElementById("capping-final-val").innerText = `${finalSizeKB} KB`;
2237
+
2238
+ const hintBox = document.getElementById("capping-hint-box");
2239
+ hintBox.innerText = hint;
2240
+ hintBox.style.borderColor = truncated ? "rgba(239, 68, 68, 0.3)" : "rgba(16, 185, 129, 0.3)";
2241
+ hintBox.style.background = truncated ? "rgba(239, 68, 68, 0.03)" : "rgba(16, 185, 129, 0.03)";
2242
+ hintBox.style.color = truncated ? "var(--color-rose)" : "var(--text-main)";
2243
+ }
2244
+
2245
+ // Initialize recompiler
2246
+ simulateRecompilerAndCapping();
2247
+ </script>
2248
+ </body>
2249
+ </html>