@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.
- package/CHANGELOG.md +407 -0
- package/CODE_OF_CONDUCT.md +21 -0
- package/CONTRIBUTING.md +224 -0
- package/LICENSE +202 -0
- package/NOTICE +9 -0
- package/README.md +798 -0
- package/SECURITY.md +72 -0
- package/assets/clio-coder-logo-128.webp +0 -0
- package/damage-control-rules.yaml +419 -0
- package/dist/acp-UMLFVA3F.js +92 -0
- package/dist/agents-Q4MYPMUW.js +91 -0
- package/dist/auth-O6HYIJ6J.js +521 -0
- package/dist/chunk-262G75JS.js +35 -0
- package/dist/chunk-26BZQOAD.js +1281 -0
- package/dist/chunk-2J63S4SF.js +508 -0
- package/dist/chunk-3DANZDGR.js +717 -0
- package/dist/chunk-4UQA7NCT.js +29 -0
- package/dist/chunk-527KG6XR.js +497 -0
- package/dist/chunk-5LDRNKX2.js +1063 -0
- package/dist/chunk-5N2FG33Q.js +25 -0
- package/dist/chunk-67MTHP2E.js +135 -0
- package/dist/chunk-6CWDTGUC.js +20 -0
- package/dist/chunk-7BHLZB3A.js +2115 -0
- package/dist/chunk-7RBKDI66.js +348 -0
- package/dist/chunk-AMFR5YA3.js +541 -0
- package/dist/chunk-BBUH4VAA.js +1224 -0
- package/dist/chunk-BYEU76JP.js +899 -0
- package/dist/chunk-CLJ5HLUD.js +458 -0
- package/dist/chunk-D5YD55AR.js +116 -0
- package/dist/chunk-DXQNI4PC.js +61 -0
- package/dist/chunk-E3NYWENM.js +1004 -0
- package/dist/chunk-GNGDQYDU.js +34688 -0
- package/dist/chunk-GOTUR54M.js +9 -0
- package/dist/chunk-HBU5MTAM.js +41 -0
- package/dist/chunk-HMYNFFY4.js +28 -0
- package/dist/chunk-JPOWPFCU.js +1010 -0
- package/dist/chunk-JWHCJDCI.js +1215 -0
- package/dist/chunk-KBR4MZZR.js +41 -0
- package/dist/chunk-KKKPTZLM.js +93 -0
- package/dist/chunk-ME6DNWIU.js +66 -0
- package/dist/chunk-NI4DEJMC.js +88 -0
- package/dist/chunk-O4EJEDHO.js +659 -0
- package/dist/chunk-PIDUD6M2.js +31 -0
- package/dist/chunk-PS4PFJQP.js +29459 -0
- package/dist/chunk-QV47YRF4.js +48 -0
- package/dist/chunk-RQDWMVRB.js +279 -0
- package/dist/chunk-TFSSEXL6.js +136 -0
- package/dist/chunk-TKHQ4DGZ.js +8290 -0
- package/dist/chunk-TPOCL34A.js +2876 -0
- package/dist/chunk-UGYAX5YI.js +565 -0
- package/dist/chunk-UHTSULZS.js +461 -0
- package/dist/chunk-UU3R62TT.js +128 -0
- package/dist/chunk-UWIJNAOB.js +3906 -0
- package/dist/chunk-VOO7NYPP.js +914 -0
- package/dist/chunk-VPAWTYLY.js +117 -0
- package/dist/chunk-WD6AJM35.js +1216 -0
- package/dist/chunk-X3BR7HWV.js +115 -0
- package/dist/chunk-X3NE4WVW.js +120 -0
- package/dist/chunk-XNISANGE.js +1395 -0
- package/dist/chunk-XV4ZJ6ZM.js +3177 -0
- package/dist/cli/index.js +236 -0
- package/dist/clio-KIQ5SNDS.js +53 -0
- package/dist/components-JVHMUBEB.js +653 -0
- package/dist/config-ZFCDBMDC.js +372 -0
- package/dist/configure-G4E3A2PG.js +27 -0
- package/dist/context-CDXTP2MP.js +293 -0
- package/dist/context-E3KIFVXI.js +185 -0
- package/dist/context-clear-3F4PLXOS.js +102 -0
- package/dist/context-index-Q7YSYTR3.js +106 -0
- package/dist/docs-YIETIWZI.js +280 -0
- package/dist/doctor-M5HJJZOL.js +61 -0
- package/dist/domains/agents/builtins/architect.md +33 -0
- package/dist/domains/agents/builtins/coder.md +31 -0
- package/dist/domains/agents/builtins/context-bootstrap.md +38 -0
- package/dist/domains/agents/builtins/debugger.md +30 -0
- package/dist/domains/agents/builtins/documenter.md +31 -0
- package/dist/domains/agents/builtins/git-master.md +30 -0
- package/dist/domains/agents/builtins/provenance.md +30 -0
- package/dist/domains/agents/builtins/researcher.md +71 -0
- package/dist/domains/agents/builtins/scout.md +42 -0
- package/dist/domains/agents/builtins/tester.md +31 -0
- package/dist/domains/agents/builtins/verifier.md +30 -0
- package/dist/domains/agents/builtins/wiki-writer.md +41 -0
- package/dist/eval-B3KZZESM.js +2674 -0
- package/dist/evidence-V67CHM35.js +233 -0
- package/dist/evolve-YDZSUQYA.js +518 -0
- package/dist/extensions-SRG7XCAH.js +207 -0
- package/dist/fleet-CA2CRTVG.js +760 -0
- package/dist/fleet-preflight-CLIAX7YR.js +21 -0
- package/dist/init-2OZDJE2D.js +227 -0
- package/dist/memory-3PIQQAKX.js +207 -0
- package/dist/models-DY35XI7Y.js +237 -0
- package/dist/paths-5OMXW7Z4.js +57 -0
- package/dist/preload-KZVHET2B.js +11 -0
- package/dist/reset-PIFYNOS3.js +216 -0
- package/dist/run-3VSPP24F.js +735 -0
- package/dist/share-D36RQCXM.js +241 -0
- package/dist/skills-F2MRLELY.js +445 -0
- package/dist/skills-eval-E2ZTW4PL.js +932 -0
- package/dist/targets-DZMEZAH4.js +977 -0
- package/dist/trace-7NYCUI2J.js +250 -0
- package/dist/uninstall-AD3JWHBB.js +322 -0
- package/dist/upgrade-WYYBKGDY.js +301 -0
- package/dist/usage-ULIDAGFF.js +755 -0
- package/dist/version-ROZ6CZKH.js +16 -0
- package/dist/wiki-generate-PKFIX6OB.js +377 -0
- package/dist/worker/entry.js +1739 -0
- package/docs/README.md +93 -0
- package/docs/acp.md +120 -0
- package/docs/alcf-provider.md +72 -0
- package/docs/architecture.md +172 -0
- package/docs/artifact-versions.md +54 -0
- package/docs/built-in-agents.md +265 -0
- package/docs/capacity-and-scheduling.md +97 -0
- package/docs/commands-and-modes.md +554 -0
- package/docs/config-knobs-audit.md +115 -0
- package/docs/configuration-and-targets.md +812 -0
- package/docs/context-engine.md +236 -0
- package/docs/dispatch-architecture-rationale.md +126 -0
- package/docs/documentation-coverage.md +46 -0
- package/docs/documentation-guide.md +166 -0
- package/docs/environment-variables.md +105 -0
- package/docs/eval-runner.md +205 -0
- package/docs/evals-internal.md +298 -0
- package/docs/evidence-and-memory.md +243 -0
- package/docs/evolution.md +143 -0
- package/docs/exit-codes-and-output.md +74 -0
- package/docs/extensions-and-sharing.md +306 -0
- package/docs/fleet-demo-runbook.md +179 -0
- package/docs/fleet-dispatch.md +591 -0
- package/docs/glossary.md +75 -0
- package/docs/html/agents_blueprint.html +936 -0
- package/docs/html/alcf_blueprint.html +324 -0
- package/docs/html/architecture_blueprint.html +850 -0
- package/docs/html/commands_blueprint.html +794 -0
- package/docs/html/config_knobs_audit_blueprint.html +178 -0
- package/docs/html/configuration_blueprint.html +1080 -0
- package/docs/html/context_blueprint.html +603 -0
- package/docs/html/documentation_blueprint.html +832 -0
- package/docs/html/environment_blueprint.html +404 -0
- package/docs/html/eval_blueprint.html +743 -0
- package/docs/html/evals_internal_blueprint.html +190 -0
- package/docs/html/evolution_blueprint.html +674 -0
- package/docs/html/extensions_blueprint.html +2065 -0
- package/docs/html/fleet_dispatch_blueprint.html +286 -0
- package/docs/html/index.html +919 -0
- package/docs/html/lifecycle_blueprint.html +723 -0
- package/docs/html/memory_blueprint.html +699 -0
- package/docs/html/middleware_blueprint.html +664 -0
- package/docs/html/models_blueprint.html +2366 -0
- package/docs/html/observability_blueprint.html +683 -0
- package/docs/html/provider_adapter_blueprint.html +245 -0
- package/docs/html/safety_blueprint.html +1386 -0
- package/docs/html/shared.css +571 -0
- package/docs/html/shared.js +143 -0
- package/docs/html/skills_blueprint.html +671 -0
- package/docs/html/soak_blueprint.html +182 -0
- package/docs/html/tool_usage_blueprint.html +350 -0
- package/docs/html/tools_blueprint.html +2249 -0
- package/docs/html/trace_blueprint.html +235 -0
- package/docs/html/tui_design_blueprint.html +314 -0
- package/docs/html/validation_blueprint.html +961 -0
- package/docs/html/worker_dispatch_blueprint.html +231 -0
- package/docs/installation-and-lifecycle.md +308 -0
- package/docs/middleware-and-components.md +148 -0
- package/docs/model-catalog.md +189 -0
- package/docs/observability.md +233 -0
- package/docs/proactive-memory.md +452 -0
- package/docs/prompt-envelope-and-tools.md +142 -0
- package/docs/provider-adapter-cookbook.md +148 -0
- package/docs/release-cut-checklist.md +138 -0
- package/docs/safety-model.md +357 -0
- package/docs/scientific-validation.md +105 -0
- package/docs/session-lifecycle.md +156 -0
- package/docs/skills-marketplace.md +46 -0
- package/docs/tool-usage.md +527 -0
- package/docs/trace-store.md +132 -0
- package/docs/troubleshooting.md +33 -0
- package/docs/tui-design.md +239 -0
- package/docs/worker-dispatch-mechanics.md +242 -0
- package/package.json +132 -0
- package/skills/README.md +408 -0
- package/skills/git/commit-crafting/SKILL.md +79 -0
- package/skills/git/commit-crafting/evals.md +92 -0
- package/skills/git/create-pr/SKILL.md +116 -0
- package/skills/git/create-pr/evals.md +114 -0
- package/skills/git/investigate-issue/SKILL.md +139 -0
- package/skills/git/investigate-issue/evals.md +94 -0
- package/skills/git/resolve-merge-conflicts/SKILL.md +96 -0
- package/skills/git/resolve-merge-conflicts/evals.md +58 -0
- package/skills/git/review-changes/SKILL.md +103 -0
- package/skills/git/review-changes/evals.md +85 -0
- package/skills/git/worktree-create/SKILL.md +92 -0
- package/skills/git/worktree-create/evals.md +97 -0
- package/skills/git/worktree-create/references/worktree-setup.md +66 -0
- package/skills/git/worktree-merge/SKILL.md +95 -0
- package/skills/git/worktree-merge/evals.md +114 -0
- package/skills/skill-marketplace.json +261 -0
- package/skills/workflow/cut-it/SKILL.md +86 -0
- package/skills/workflow/cut-it/evals.md +42 -0
- package/src/domains/agents/builtins/architect.md +33 -0
- package/src/domains/agents/builtins/coder.md +31 -0
- package/src/domains/agents/builtins/context-bootstrap.md +38 -0
- package/src/domains/agents/builtins/debugger.md +30 -0
- package/src/domains/agents/builtins/documenter.md +31 -0
- package/src/domains/agents/builtins/git-master.md +30 -0
- package/src/domains/agents/builtins/provenance.md +30 -0
- package/src/domains/agents/builtins/researcher.md +71 -0
- package/src/domains/agents/builtins/scout.md +42 -0
- package/src/domains/agents/builtins/tester.md +31 -0
- package/src/domains/agents/builtins/verifier.md +30 -0
- package/src/domains/agents/builtins/wiki-writer.md +41 -0
- package/src/domains/agents/fleets/build-review.md +34 -0
- package/src/domains/agents/fleets/build-test.md +35 -0
- package/src/domains/agents/fleets/sdlc.md +86 -0
- package/src/domains/prompts/fragments/identity/clio-worker.md +11 -0
- package/src/domains/prompts/fragments/identity/clio.md +26 -0
- package/src/domains/prompts/fragments/operating/contract.md +64 -0
- package/src/domains/prompts/fragments/safety/auto-edit.md +14 -0
- package/src/domains/prompts/fragments/safety/full-auto.md +14 -0
- package/src/domains/prompts/fragments/safety/read-only.md +13 -0
- package/src/domains/prompts/fragments/safety/suggest.md +13 -0
- package/src/domains/prompts/fragments/wiki/page.md +75 -0
- package/src/domains/prompts/fragments/wiki/plan.md +48 -0
- package/src/domains/providers/models/cloud-models/alcf.yaml +40 -0
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +993 -0
|
@@ -0,0 +1,1386 @@
|
|
|
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 Safety Model Blueprint (v0.3.0)</title>
|
|
7
|
+
|
|
8
|
+
<style>
|
|
9
|
+
:root {
|
|
10
|
+
--bg-dark: #090d16;
|
|
11
|
+
--bg-grid: rgba(255, 255, 255, 0.02);
|
|
12
|
+
--bg-card: rgba(13, 20, 38, 0.45);
|
|
13
|
+
--bg-card-hover: rgba(20, 30, 58, 0.6);
|
|
14
|
+
--border-card: rgba(255, 255, 255, 0.08);
|
|
15
|
+
--border-card-hover: rgba(0, 240, 255, 0.3);
|
|
16
|
+
--text-main: #f3f4f6;
|
|
17
|
+
--text-muted: #9ca3af;
|
|
18
|
+
--text-dim: #6b7280;
|
|
19
|
+
|
|
20
|
+
--color-cyan: #00f0ff;
|
|
21
|
+
--color-cyan-rgb: 0, 240, 255;
|
|
22
|
+
--color-purple: #bd00ff;
|
|
23
|
+
--color-purple-rgb: 189, 0, 255;
|
|
24
|
+
--color-emerald: #10b981;
|
|
25
|
+
--color-emerald-rgb: 16, 185, 129;
|
|
26
|
+
--color-amber: #f59e0b;
|
|
27
|
+
--color-amber-rgb: 245, 158, 11;
|
|
28
|
+
--color-rose: #ef4444;
|
|
29
|
+
--color-rose-rgb: 239, 68, 68;
|
|
30
|
+
|
|
31
|
+
--gradient-main: linear-gradient(135deg, var(--color-cyan), var(--color-purple));
|
|
32
|
+
--shadow-glow: 0 0 25px rgba(0, 240, 255, 0.15);
|
|
33
|
+
--font-sans: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
34
|
+
--font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
|
|
35
|
+
|
|
36
|
+
--glass-blur: blur(12px);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
* {
|
|
40
|
+
box-sizing: border-box;
|
|
41
|
+
margin: 0;
|
|
42
|
+
padding: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
body {
|
|
46
|
+
background-color: var(--bg-dark);
|
|
47
|
+
background-image:
|
|
48
|
+
radial-gradient(circle at 10% 20%, rgba(var(--color-cyan-rgb), 0.05) 0%, transparent 40%),
|
|
49
|
+
radial-gradient(circle at 90% 80%, rgba(var(--color-purple-rgb), 0.05) 0%, transparent 40%),
|
|
50
|
+
radial-gradient(circle at 50% 50%, #0d1527 0%, var(--bg-dark) 100%);
|
|
51
|
+
color: var(--text-main);
|
|
52
|
+
font-family: var(--font-sans);
|
|
53
|
+
min-height: 100vh;
|
|
54
|
+
line-height: 1.6;
|
|
55
|
+
overflow-x: hidden;
|
|
56
|
+
position: relative;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
body::before {
|
|
60
|
+
content: '';
|
|
61
|
+
position: absolute;
|
|
62
|
+
inset: 0;
|
|
63
|
+
background-image: linear-gradient(var(--bg-grid) 1px, transparent 1px),
|
|
64
|
+
linear-gradient(90deg, var(--bg-grid) 1px, transparent 1px);
|
|
65
|
+
background-size: 40px 40px;
|
|
66
|
+
background-position: center top;
|
|
67
|
+
pointer-events: none;
|
|
68
|
+
z-index: 0;
|
|
69
|
+
opacity: 0.8;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.container {
|
|
73
|
+
max-width: 1400px;
|
|
74
|
+
margin: 0 auto;
|
|
75
|
+
padding: 2rem;
|
|
76
|
+
position: relative;
|
|
77
|
+
z-index: 1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Header Styling */
|
|
81
|
+
header {
|
|
82
|
+
display: flex;
|
|
83
|
+
justify-content: space-between;
|
|
84
|
+
align-items: center;
|
|
85
|
+
margin-bottom: 2.5rem;
|
|
86
|
+
padding-bottom: 1.5rem;
|
|
87
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.header-left {
|
|
91
|
+
display: flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
gap: 1rem;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.header-logo {
|
|
97
|
+
display: inline-flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
justify-content: center;
|
|
100
|
+
width: 48px;
|
|
101
|
+
height: 48px;
|
|
102
|
+
background: rgba(255, 255, 255, 0.02);
|
|
103
|
+
border: 1px solid var(--border-card);
|
|
104
|
+
border-radius: 12px;
|
|
105
|
+
position: relative;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.header-logo svg {
|
|
109
|
+
width: 28px;
|
|
110
|
+
height: 28px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.header-title-wrapper h1 {
|
|
114
|
+
font-size: 1.5rem;
|
|
115
|
+
font-weight: 800;
|
|
116
|
+
letter-spacing: -0.03em;
|
|
117
|
+
background: linear-gradient(to right, #ffffff, #c7d2fe, var(--color-cyan));
|
|
118
|
+
-webkit-background-clip: text;
|
|
119
|
+
-webkit-text-fill-color: transparent;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.header-title-wrapper p {
|
|
123
|
+
font-size: 0.825rem;
|
|
124
|
+
color: var(--text-muted);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.header-right {
|
|
128
|
+
display: flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
gap: 1rem;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.back-btn {
|
|
134
|
+
background: rgba(255, 255, 255, 0.03);
|
|
135
|
+
border: 1px solid var(--border-card);
|
|
136
|
+
color: var(--text-muted);
|
|
137
|
+
padding: 0.5rem 1rem;
|
|
138
|
+
border-radius: 8px;
|
|
139
|
+
font-size: 0.875rem;
|
|
140
|
+
font-weight: 600;
|
|
141
|
+
text-decoration: none;
|
|
142
|
+
display: inline-flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
gap: 0.5rem;
|
|
145
|
+
transition: all 0.2s;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.back-btn:hover {
|
|
149
|
+
background: rgba(255, 255, 255, 0.08);
|
|
150
|
+
color: var(--text-main);
|
|
151
|
+
border-color: rgba(var(--color-cyan-rgb), 0.3);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.version-badge {
|
|
155
|
+
background: rgba(0, 240, 255, 0.08);
|
|
156
|
+
border: 1px solid rgba(0, 240, 255, 0.25);
|
|
157
|
+
color: var(--color-cyan);
|
|
158
|
+
padding: 0.35rem 0.75rem;
|
|
159
|
+
border-radius: 50px;
|
|
160
|
+
font-size: 0.75rem;
|
|
161
|
+
font-weight: 600;
|
|
162
|
+
font-family: var(--font-mono);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Tabs Navigation */
|
|
166
|
+
.tabs-nav {
|
|
167
|
+
display: flex;
|
|
168
|
+
gap: 0.75rem;
|
|
169
|
+
margin-bottom: 2rem;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.tab-btn {
|
|
173
|
+
background: rgba(255, 255, 255, 0.03);
|
|
174
|
+
border: 1px solid var(--border-card);
|
|
175
|
+
color: var(--text-muted);
|
|
176
|
+
padding: 0.6rem 1.25rem;
|
|
177
|
+
border-radius: 8px;
|
|
178
|
+
font-size: 0.875rem;
|
|
179
|
+
font-weight: 600;
|
|
180
|
+
cursor: pointer;
|
|
181
|
+
display: flex;
|
|
182
|
+
align-items: center;
|
|
183
|
+
gap: 0.5rem;
|
|
184
|
+
transition: all 0.2s;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.tab-btn:hover {
|
|
188
|
+
background: rgba(255, 255, 255, 0.06);
|
|
189
|
+
color: var(--text-main);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.tab-btn.active {
|
|
193
|
+
background: var(--gradient-main);
|
|
194
|
+
color: #090d16;
|
|
195
|
+
border-color: transparent;
|
|
196
|
+
box-shadow: 0 4px 15px rgba(var(--color-cyan-rgb), 0.25);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Content Layout */
|
|
200
|
+
.tab-pane {
|
|
201
|
+
display: none;
|
|
202
|
+
animation: fadeIn 0.3s ease-out forwards;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.tab-pane.active {
|
|
206
|
+
display: block;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
@keyframes fadeIn {
|
|
210
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
211
|
+
to { opacity: 1; transform: translateY(0); }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/* Split layout: Specs + Simulator */
|
|
215
|
+
.blueprint-layout {
|
|
216
|
+
display: grid;
|
|
217
|
+
grid-template-columns: 1.1fr 0.9fr;
|
|
218
|
+
gap: 2rem;
|
|
219
|
+
align-items: start;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@media (max-width: 1100px) {
|
|
223
|
+
.blueprint-layout {
|
|
224
|
+
grid-template-columns: 1fr;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.glass-card {
|
|
229
|
+
background: var(--bg-card);
|
|
230
|
+
border: 1px solid var(--border-card);
|
|
231
|
+
border-radius: 16px;
|
|
232
|
+
padding: 1.75rem;
|
|
233
|
+
margin-bottom: 2rem;
|
|
234
|
+
backdrop-filter: var(--glass-blur);
|
|
235
|
+
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.glass-card h2 {
|
|
239
|
+
font-size: 1.25rem;
|
|
240
|
+
font-weight: 700;
|
|
241
|
+
color: #ffffff;
|
|
242
|
+
margin-bottom: 1.25rem;
|
|
243
|
+
display: flex;
|
|
244
|
+
align-items: center;
|
|
245
|
+
gap: 0.5rem;
|
|
246
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
247
|
+
padding-bottom: 0.75rem;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.glass-card h2 svg {
|
|
251
|
+
width: 18px;
|
|
252
|
+
height: 18px;
|
|
253
|
+
color: var(--color-cyan);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.glass-card p {
|
|
257
|
+
font-size: 0.925rem;
|
|
258
|
+
color: var(--text-muted);
|
|
259
|
+
margin-bottom: 1rem;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/* Autonomy Matrix Style */
|
|
263
|
+
.matrix-wrapper {
|
|
264
|
+
overflow-x: auto;
|
|
265
|
+
margin-bottom: 1.5rem;
|
|
266
|
+
border-radius: 8px;
|
|
267
|
+
border: 1px solid var(--border-card);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.matrix-table {
|
|
271
|
+
width: 100%;
|
|
272
|
+
border-collapse: collapse;
|
|
273
|
+
font-size: 0.85rem;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.matrix-table th, .matrix-table td {
|
|
277
|
+
padding: 0.75rem 1rem;
|
|
278
|
+
text-align: left;
|
|
279
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.matrix-table th {
|
|
283
|
+
background: rgba(0,0,0,0.3);
|
|
284
|
+
color: var(--text-muted);
|
|
285
|
+
font-weight: 600;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.matrix-table td.col-hdr {
|
|
289
|
+
font-weight: 600;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.matrix-table td {
|
|
293
|
+
color: var(--text-main);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Matrix Highlight Columns */
|
|
297
|
+
.matrix-table th.highlight, .matrix-table td.highlight {
|
|
298
|
+
background: rgba(var(--color-cyan-rgb), 0.08);
|
|
299
|
+
border-left: 1px solid rgba(var(--color-cyan-rgb), 0.15);
|
|
300
|
+
border-right: 1px solid rgba(var(--color-cyan-rgb), 0.15);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.matrix-table tr:hover td {
|
|
304
|
+
background: rgba(255,255,255,0.02);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.badge-decision {
|
|
308
|
+
display: inline-block;
|
|
309
|
+
padding: 0.15rem 0.5rem;
|
|
310
|
+
border-radius: 4px;
|
|
311
|
+
font-weight: 700;
|
|
312
|
+
font-size: 0.75rem;
|
|
313
|
+
text-transform: uppercase;
|
|
314
|
+
font-family: var(--font-mono);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.badge-decision.allow { background: rgba(16, 185, 129, 0.1); border: 1px solid rgba(16, 185, 129, 0.25); color: var(--color-emerald); }
|
|
318
|
+
.badge-decision.ask { background: rgba(245, 158, 11, 0.1); border: 1px solid rgba(245, 158, 11, 0.25); color: var(--color-amber); }
|
|
319
|
+
.badge-decision.deny { background: rgba(239, 68, 68, 0.1); border: 1px solid rgba(239, 68, 68, 0.25); color: var(--color-rose); }
|
|
320
|
+
.badge-decision.block { background: rgba(239, 68, 68, 0.15); border: 1px solid rgba(239, 68, 68, 0.4); color: var(--color-rose); text-shadow: 0 0 5px rgba(239, 68, 68, 0.3); }
|
|
321
|
+
|
|
322
|
+
/* SVG Flowchart */
|
|
323
|
+
.flowchart-container {
|
|
324
|
+
background: rgba(9, 13, 22, 0.6);
|
|
325
|
+
border: 1px solid var(--border-card);
|
|
326
|
+
border-radius: 12px;
|
|
327
|
+
padding: 1.5rem;
|
|
328
|
+
text-align: center;
|
|
329
|
+
margin: 1.5rem 0;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.flowchart-container svg {
|
|
333
|
+
width: 100%;
|
|
334
|
+
height: auto;
|
|
335
|
+
max-height: 280px;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* Simulator Panel Styling */
|
|
339
|
+
.simulator-panel {
|
|
340
|
+
position: sticky;
|
|
341
|
+
top: 2rem;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.form-group {
|
|
345
|
+
margin-bottom: 1.25rem;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.form-group label {
|
|
349
|
+
display: block;
|
|
350
|
+
font-size: 0.8rem;
|
|
351
|
+
font-weight: 600;
|
|
352
|
+
color: var(--text-muted);
|
|
353
|
+
margin-bottom: 0.5rem;
|
|
354
|
+
text-transform: uppercase;
|
|
355
|
+
letter-spacing: 0.05em;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.form-row {
|
|
359
|
+
display: grid;
|
|
360
|
+
grid-template-columns: 1fr 1fr;
|
|
361
|
+
gap: 1rem;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
select, input, textarea {
|
|
365
|
+
width: 100%;
|
|
366
|
+
background: rgba(9, 13, 22, 0.7);
|
|
367
|
+
border: 1px solid var(--border-card);
|
|
368
|
+
border-radius: 8px;
|
|
369
|
+
padding: 0.65rem 0.85rem;
|
|
370
|
+
color: #fff;
|
|
371
|
+
font-family: var(--font-sans);
|
|
372
|
+
font-size: 0.9rem;
|
|
373
|
+
outline: none;
|
|
374
|
+
transition: all 0.2s;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
select:focus, input:focus, textarea:focus {
|
|
378
|
+
border-color: var(--color-cyan);
|
|
379
|
+
box-shadow: 0 0 10px rgba(var(--color-cyan-rgb), 0.15);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
textarea {
|
|
383
|
+
font-family: var(--font-mono);
|
|
384
|
+
font-size: 0.8rem;
|
|
385
|
+
resize: vertical;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/* Preset list */
|
|
389
|
+
.presets-list {
|
|
390
|
+
display: flex;
|
|
391
|
+
flex-wrap: wrap;
|
|
392
|
+
gap: 0.4rem;
|
|
393
|
+
margin-bottom: 1.25rem;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.preset-btn {
|
|
397
|
+
background: rgba(255, 255, 255, 0.03);
|
|
398
|
+
border: 1px solid var(--border-card);
|
|
399
|
+
color: var(--text-muted);
|
|
400
|
+
padding: 0.3rem 0.6rem;
|
|
401
|
+
border-radius: 4px;
|
|
402
|
+
font-size: 0.725rem;
|
|
403
|
+
cursor: pointer;
|
|
404
|
+
font-family: var(--font-mono);
|
|
405
|
+
transition: all 0.2s;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.preset-btn:hover {
|
|
409
|
+
background: rgba(0, 240, 255, 0.08);
|
|
410
|
+
border-color: var(--color-cyan);
|
|
411
|
+
color: #fff;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/* Simulation Verdict Displays */
|
|
415
|
+
.verdict-header {
|
|
416
|
+
font-size: 0.8rem;
|
|
417
|
+
font-weight: 600;
|
|
418
|
+
color: var(--text-muted);
|
|
419
|
+
margin-bottom: 0.5rem;
|
|
420
|
+
text-transform: uppercase;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.verdict-card {
|
|
424
|
+
border-radius: 12px;
|
|
425
|
+
padding: 1.25rem;
|
|
426
|
+
margin-bottom: 1.5rem;
|
|
427
|
+
display: flex;
|
|
428
|
+
align-items: center;
|
|
429
|
+
justify-content: space-between;
|
|
430
|
+
transition: all 0.3s ease;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.verdict-info h3 {
|
|
434
|
+
font-size: 1.35rem;
|
|
435
|
+
font-weight: 800;
|
|
436
|
+
letter-spacing: 0.05em;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.verdict-info p {
|
|
440
|
+
font-size: 0.825rem;
|
|
441
|
+
color: var(--text-main);
|
|
442
|
+
margin: 0.25rem 0 0 0;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.verdict-status-badge {
|
|
446
|
+
font-size: 2.25rem;
|
|
447
|
+
font-weight: 900;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* Verdict classes */
|
|
451
|
+
.v-allow {
|
|
452
|
+
background: rgba(16, 185, 129, 0.08);
|
|
453
|
+
border: 1px solid rgba(16, 185, 129, 0.3);
|
|
454
|
+
color: var(--color-emerald);
|
|
455
|
+
box-shadow: 0 0 15px rgba(16, 185, 129, 0.08);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.v-ask {
|
|
459
|
+
background: rgba(245, 158, 11, 0.08);
|
|
460
|
+
border: 1px solid rgba(245, 158, 11, 0.3);
|
|
461
|
+
color: var(--color-amber);
|
|
462
|
+
box-shadow: 0 0 15px rgba(245, 158, 11, 0.08);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.v-deny {
|
|
466
|
+
background: rgba(239, 68, 68, 0.08);
|
|
467
|
+
border: 1px solid rgba(239, 68, 68, 0.3);
|
|
468
|
+
color: var(--color-rose);
|
|
469
|
+
box-shadow: 0 0 15px rgba(239, 68, 68, 0.08);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.v-block {
|
|
473
|
+
background: rgba(239, 68, 68, 0.12);
|
|
474
|
+
border: 1px solid rgba(239, 68, 68, 0.45);
|
|
475
|
+
color: var(--color-rose);
|
|
476
|
+
box-shadow: 0 0 20px rgba(239, 68, 68, 0.12);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/* Live trace console */
|
|
480
|
+
.console-header {
|
|
481
|
+
display: flex;
|
|
482
|
+
justify-content: space-between;
|
|
483
|
+
align-items: center;
|
|
484
|
+
margin-bottom: 0.5rem;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.console-title {
|
|
488
|
+
font-size: 0.8rem;
|
|
489
|
+
font-weight: 600;
|
|
490
|
+
color: var(--text-muted);
|
|
491
|
+
text-transform: uppercase;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
.console-body {
|
|
495
|
+
background: #020408;
|
|
496
|
+
border: 1px solid var(--border-card);
|
|
497
|
+
border-radius: 8px;
|
|
498
|
+
padding: 1rem;
|
|
499
|
+
font-family: var(--font-mono);
|
|
500
|
+
font-size: 0.8rem;
|
|
501
|
+
height: 180px;
|
|
502
|
+
overflow-y: auto;
|
|
503
|
+
white-space: pre-wrap;
|
|
504
|
+
color: #a5b4fc;
|
|
505
|
+
box-shadow: inset 0 2px 10px rgba(0,0,0,0.8);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/* Code block style */
|
|
509
|
+
pre {
|
|
510
|
+
background: rgba(0,0,0,0.3);
|
|
511
|
+
border: 1px solid var(--border-card);
|
|
512
|
+
border-radius: 8px;
|
|
513
|
+
padding: 1rem;
|
|
514
|
+
overflow-x: auto;
|
|
515
|
+
margin: 1rem 0;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
code {
|
|
519
|
+
font-family: var(--font-mono);
|
|
520
|
+
font-size: 0.85rem;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/* Markdown styling classes */
|
|
524
|
+
.ref-table {
|
|
525
|
+
width: 100%;
|
|
526
|
+
border-collapse: collapse;
|
|
527
|
+
margin: 1.5rem 0;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
.ref-table th, .ref-table td {
|
|
531
|
+
padding: 0.65rem 0.85rem;
|
|
532
|
+
border: 1px solid var(--border-card);
|
|
533
|
+
text-align: left;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.ref-table th {
|
|
537
|
+
background: rgba(255,255,255,0.03);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
.alert-tip {
|
|
541
|
+
background: rgba(16, 185, 129, 0.06);
|
|
542
|
+
border-left: 4px solid var(--color-emerald);
|
|
543
|
+
padding: 1rem;
|
|
544
|
+
border-radius: 0 8px 8px 0;
|
|
545
|
+
margin: 1.5rem 0;
|
|
546
|
+
font-size: 0.9rem;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
.alert-tip strong {
|
|
550
|
+
color: var(--color-emerald);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/* Footer */
|
|
554
|
+
footer {
|
|
555
|
+
text-align: center;
|
|
556
|
+
margin-top: 4rem;
|
|
557
|
+
padding-top: 2rem;
|
|
558
|
+
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
|
559
|
+
color: var(--text-dim);
|
|
560
|
+
font-size: 0.875rem;
|
|
561
|
+
}
|
|
562
|
+
</style>
|
|
563
|
+
</head>
|
|
564
|
+
<body>
|
|
565
|
+
<div class="container">
|
|
566
|
+
<header>
|
|
567
|
+
<div class="header-left">
|
|
568
|
+
<div class="header-logo">
|
|
569
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="color: var(--color-cyan);"><title>Icon</title>
|
|
570
|
+
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
|
|
571
|
+
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
|
|
572
|
+
</svg>
|
|
573
|
+
</div>
|
|
574
|
+
<div class="header-title-wrapper">
|
|
575
|
+
<h1>Clio Coder Safety Model</h1>
|
|
576
|
+
<p>Execution-gated guardrails, autonomy mappings, and policy enforcement engine</p>
|
|
577
|
+
<div class="meta-chips-row">
|
|
578
|
+
<span class="chip">Source: docs/safety-model.md</span>
|
|
579
|
+
<span class="chip chip-orange">clio-coder docs safety</span>
|
|
580
|
+
</div>
|
|
581
|
+
</div>
|
|
582
|
+
</div>
|
|
583
|
+
<div class="header-right">
|
|
584
|
+
<span class="version-badge">Clio Coder v0.3.0</span>
|
|
585
|
+
<a href="index.html" class="back-btn">
|
|
586
|
+
<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>
|
|
587
|
+
Dashboard Hub
|
|
588
|
+
</a>
|
|
589
|
+
</div>
|
|
590
|
+
</header>
|
|
591
|
+
|
|
592
|
+
<div class="tabs-nav">
|
|
593
|
+
<button type="button" class="tab-btn active" onclick="switchTab('interactive')">
|
|
594
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><title>Icon</title><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline></svg>
|
|
595
|
+
Interactive Spec & Simulator
|
|
596
|
+
</button>
|
|
597
|
+
<button type="button" class="tab-btn" onclick="switchTab('reference')">
|
|
598
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><title>Icon</title><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
|
|
599
|
+
Full Technical Reference
|
|
600
|
+
</button>
|
|
601
|
+
</div>
|
|
602
|
+
|
|
603
|
+
<!-- TAB 1: INTERACTIVE -->
|
|
604
|
+
<main class="tab-pane active" id="pane-interactive">
|
|
605
|
+
<div class="blueprint-layout">
|
|
606
|
+
|
|
607
|
+
<!-- Left: Matrix & Flows -->
|
|
608
|
+
<div class="specs-col">
|
|
609
|
+
|
|
610
|
+
<div class="glass-card">
|
|
611
|
+
<h2>
|
|
612
|
+
<svg width="18" height="18" 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"></path></svg>
|
|
613
|
+
Autonomy Level Matrix
|
|
614
|
+
</h2>
|
|
615
|
+
<p>The <code>autonomy</code> setting in <code>settings.yaml</code> (read-only | suggest | auto-edit | full-auto) controls tool execution gates. The safety net blocks apply regardless of this level.</p>
|
|
616
|
+
|
|
617
|
+
<div class="matrix-wrapper">
|
|
618
|
+
<table class="matrix-table" id="matrixTable">
|
|
619
|
+
<thead>
|
|
620
|
+
<tr>
|
|
621
|
+
<th>Action Class</th>
|
|
622
|
+
<th id="hdr-read-only">read-only</th>
|
|
623
|
+
<th id="hdr-suggest">suggest</th>
|
|
624
|
+
<th id="hdr-auto-edit" class="highlight">auto-edit (default)</th>
|
|
625
|
+
<th id="hdr-full-auto">full-auto</th>
|
|
626
|
+
</tr>
|
|
627
|
+
</thead>
|
|
628
|
+
<tbody>
|
|
629
|
+
<tr id="row-read">
|
|
630
|
+
<td class="col-hdr">read</td>
|
|
631
|
+
<td><span class="badge-decision allow">allow</span></td>
|
|
632
|
+
<td><span class="badge-decision allow">allow</span></td>
|
|
633
|
+
<td class="highlight"><span class="badge-decision allow">allow</span></td>
|
|
634
|
+
<td><span class="badge-decision allow">allow</span></td>
|
|
635
|
+
</tr>
|
|
636
|
+
<tr id="row-write">
|
|
637
|
+
<td class="col-hdr">write</td>
|
|
638
|
+
<td><span class="badge-decision deny">deny</span></td>
|
|
639
|
+
<td><span class="badge-decision ask">ask</span></td>
|
|
640
|
+
<td class="highlight"><span class="badge-decision allow">allow</span></td>
|
|
641
|
+
<td><span class="badge-decision allow">allow</span></td>
|
|
642
|
+
</tr>
|
|
643
|
+
<tr id="row-execute-builtin">
|
|
644
|
+
<td class="col-hdr">execute (builtin / project command)</td>
|
|
645
|
+
<td><span class="badge-decision deny">deny</span></td>
|
|
646
|
+
<td><span class="badge-decision ask">ask</span></td>
|
|
647
|
+
<td class="highlight"><span class="badge-decision allow">allow</span></td>
|
|
648
|
+
<td><span class="badge-decision allow">allow</span></td>
|
|
649
|
+
</tr>
|
|
650
|
+
<tr id="row-execute-other">
|
|
651
|
+
<td class="col-hdr">execute (any other bash)</td>
|
|
652
|
+
<td><span class="badge-decision deny">deny</span></td>
|
|
653
|
+
<td><span class="badge-decision ask">ask</span></td>
|
|
654
|
+
<td class="highlight"><span class="badge-decision ask">ask</span></td>
|
|
655
|
+
<td><span class="badge-decision allow">allow</span></td>
|
|
656
|
+
</tr>
|
|
657
|
+
<tr id="row-dispatch">
|
|
658
|
+
<td class="col-hdr">dispatch</td>
|
|
659
|
+
<td><span class="badge-decision deny">deny</span></td>
|
|
660
|
+
<td><span class="badge-decision ask">ask</span></td>
|
|
661
|
+
<td class="highlight"><span class="badge-decision allow">allow</span></td>
|
|
662
|
+
<td><span class="badge-decision allow">allow</span></td>
|
|
663
|
+
</tr>
|
|
664
|
+
<tr id="row-system-modify">
|
|
665
|
+
<td class="col-hdr">system_modify</td>
|
|
666
|
+
<td><span class="badge-decision deny">deny</span></td>
|
|
667
|
+
<td><span class="badge-decision ask">ask</span></td>
|
|
668
|
+
<td class="highlight"><span class="badge-decision ask">ask</span></td>
|
|
669
|
+
<td><span class="badge-decision ask">ask</span></td>
|
|
670
|
+
</tr>
|
|
671
|
+
<tr id="row-git-destructive">
|
|
672
|
+
<td class="col-hdr">git_destructive</td>
|
|
673
|
+
<td><span class="badge-decision block">net block</span></td>
|
|
674
|
+
<td><span class="badge-decision block">net block</span></td>
|
|
675
|
+
<td class="highlight"><span class="badge-decision block">net block</span></td>
|
|
676
|
+
<td><span class="badge-decision block">net block</span></td>
|
|
677
|
+
</tr>
|
|
678
|
+
<tr id="row-unknown">
|
|
679
|
+
<td class="col-hdr">unknown</td>
|
|
680
|
+
<td><span class="badge-decision deny">deny</span></td>
|
|
681
|
+
<td><span class="badge-decision ask">ask</span></td>
|
|
682
|
+
<td class="highlight"><span class="badge-decision ask">ask</span></td>
|
|
683
|
+
<td><span class="badge-decision ask">ask</span></td>
|
|
684
|
+
</tr>
|
|
685
|
+
</tbody>
|
|
686
|
+
</table>
|
|
687
|
+
</div>
|
|
688
|
+
</div>
|
|
689
|
+
|
|
690
|
+
<div class="glass-card">
|
|
691
|
+
<h2>
|
|
692
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><title>Icon</title><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline></svg>
|
|
693
|
+
Enforcement Path Flow
|
|
694
|
+
</h2>
|
|
695
|
+
<p>Every tool call evaluates through the Safety Net filters first, followed by Autonomy level mapping, and finally queues through the Approvals resolver.</p>
|
|
696
|
+
|
|
697
|
+
<div class="flowchart-container">
|
|
698
|
+
<svg viewBox="0 0 600 220" fill="none" xmlns="http://www.w3.org/2000/svg"><title>Icon</title>
|
|
699
|
+
<!-- Marker def -->
|
|
700
|
+
<defs>
|
|
701
|
+
<marker id="arrow" viewBox="0 0 10 10" refX="6" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
|
702
|
+
<path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="var(--color-cyan)"/>
|
|
703
|
+
</marker>
|
|
704
|
+
</defs>
|
|
705
|
+
|
|
706
|
+
<!-- Box 1 -->
|
|
707
|
+
<rect x="10" y="70" width="115" height="50" rx="8" fill="rgba(255,255,255,0.02)" stroke="var(--border-card)" stroke-width="1"/>
|
|
708
|
+
<text x="67" y="94" fill="#fff" font-size="10" font-family="var(--font-sans)" text-anchor="middle" font-weight="600">Tool Call Input</text>
|
|
709
|
+
<text x="67" y="108" fill="var(--text-muted)" font-size="8" font-family="var(--font-sans)" text-anchor="middle">(bash, write, etc.)</text>
|
|
710
|
+
|
|
711
|
+
<!-- Arrow 1 -> 2 -->
|
|
712
|
+
<path d="M 125 95 L 150 95" fill="none" stroke="var(--color-cyan)" stroke-width="1.5" marker-end="url(#arrow)"/>
|
|
713
|
+
|
|
714
|
+
<!-- Box 2 -->
|
|
715
|
+
<rect id="flow-net" x="160" y="60" width="110" height="70" rx="8" fill="rgba(255,255,255,0.02)" stroke="var(--border-card)" stroke-width="1"/>
|
|
716
|
+
<text x="215" y="85" fill="#fff" font-size="11" font-family="var(--font-sans)" text-anchor="middle" font-weight="700">1. Safety Net</text>
|
|
717
|
+
<text x="215" y="100" fill="var(--color-rose)" font-size="8" font-family="var(--font-sans)" text-anchor="middle" font-weight="600">Block / Confirm</text>
|
|
718
|
+
<text x="215" y="115" fill="var(--color-emerald)" font-size="8" font-family="var(--font-sans)" text-anchor="middle" font-weight="600">Pass →</text>
|
|
719
|
+
|
|
720
|
+
<!-- Arrow 2 -> 3 -->
|
|
721
|
+
<path d="M 270 95 L 295 95" fill="none" stroke="var(--color-cyan)" stroke-width="1.5" marker-end="url(#arrow)"/>
|
|
722
|
+
|
|
723
|
+
<!-- Box 3 -->
|
|
724
|
+
<rect id="flow-autonomy" x="305" y="60" width="110" height="70" rx="8" fill="rgba(0, 240, 255, 0.03)" stroke="var(--color-cyan)" stroke-width="1.5"/>
|
|
725
|
+
<text x="360" y="85" fill="#fff" font-size="11" font-family="var(--font-sans)" text-anchor="middle" font-weight="700">2. Autonomy</text>
|
|
726
|
+
<text x="360" y="100" fill="var(--text-muted)" font-size="8" font-family="var(--font-sans)" text-anchor="middle">Mapping Matrix</text>
|
|
727
|
+
<text x="360" y="115" fill="var(--color-cyan)" font-size="8" font-family="var(--font-sans)" text-anchor="middle" font-weight="600">Allow / Ask / Deny</text>
|
|
728
|
+
|
|
729
|
+
<!-- Arrow 3 -> 4 -->
|
|
730
|
+
<path d="M 415 95 L 440 95" fill="none" stroke="var(--color-cyan)" stroke-width="1.5" marker-end="url(#arrow)"/>
|
|
731
|
+
|
|
732
|
+
<!-- Box 4 -->
|
|
733
|
+
<rect id="flow-approvals" x="450" y="60" width="130" height="70" rx="8" fill="rgba(255,255,255,0.02)" stroke="var(--border-card)" stroke-width="1"/>
|
|
734
|
+
<text x="515" y="85" fill="#fff" font-size="11" font-family="var(--font-sans)" text-anchor="middle" font-weight="700">3. Approvals Flow</text>
|
|
735
|
+
<text x="515" y="100" fill="var(--color-amber)" font-size="8" font-family="var(--font-sans)" text-anchor="middle">TUI: Queue overlay</text>
|
|
736
|
+
<text x="515" y="115" fill="var(--color-rose)" font-size="8" font-family="var(--font-sans)" text-anchor="middle">Headless: Deny</text>
|
|
737
|
+
|
|
738
|
+
<!-- Safety Net reject branch -->
|
|
739
|
+
<path d="M 215 130 L 215 170 L 450 170" fill="none" stroke="var(--color-rose)" stroke-width="1" stroke-dasharray="3 3" marker-end="url(#arrow)"/>
|
|
740
|
+
<text x="330" y="165" fill="var(--color-rose)" font-size="8" font-family="var(--font-sans)">Safety block / escape block</text>
|
|
741
|
+
</svg>
|
|
742
|
+
</div>
|
|
743
|
+
</div>
|
|
744
|
+
|
|
745
|
+
</div>
|
|
746
|
+
|
|
747
|
+
<!-- Right: Simulator -->
|
|
748
|
+
<div class="simulator-panel">
|
|
749
|
+
<div class="glass-card">
|
|
750
|
+
<h2>
|
|
751
|
+
<svg width="18" height="18" 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"></path></svg>
|
|
752
|
+
Safety Evaluation Simulator
|
|
753
|
+
</h2>
|
|
754
|
+
|
|
755
|
+
<div class="presets-list">
|
|
756
|
+
<span class="preset-btn" onclick="loadPreset('status')">git status</span>
|
|
757
|
+
<span class="preset-btn" onclick="loadPreset('npm-test')">npm test</span>
|
|
758
|
+
<span class="preset-btn" onclick="loadPreset('write-src')">write index.ts</span>
|
|
759
|
+
<span class="preset-btn" onclick="loadPreset('write-env')">write .env</span>
|
|
760
|
+
<span class="preset-btn" onclick="loadPreset('rm-rf')">rm -rf /</span>
|
|
761
|
+
<span class="preset-btn" onclick="loadPreset('stash-drop')">git stash drop</span>
|
|
762
|
+
<span class="preset-btn" onclick="loadPreset('force-push')">git push --force</span>
|
|
763
|
+
<span class="preset-btn" onclick="loadPreset('escape-write')">write /etc/hosts</span>
|
|
764
|
+
<span class="preset-btn" onclick="loadPreset('unrecognized-exec')">apt-get install</span>
|
|
765
|
+
</div>
|
|
766
|
+
|
|
767
|
+
<div class="form-row">
|
|
768
|
+
<div class="form-group">
|
|
769
|
+
<label for="autonomyLevel">Autonomy Level</label>
|
|
770
|
+
<select id="autonomyLevel" onchange="runSimulation()">
|
|
771
|
+
<option value="read-only">read-only</option>
|
|
772
|
+
<option value="suggest">suggest</option>
|
|
773
|
+
<option value="auto-edit" selected>auto-edit (default)</option>
|
|
774
|
+
<option value="full-auto">full-auto</option>
|
|
775
|
+
</select>
|
|
776
|
+
</div>
|
|
777
|
+
<div class="form-group">
|
|
778
|
+
<label for="operatingPosture">Posture Mode</label>
|
|
779
|
+
<select id="operatingPosture" onchange="runSimulation()">
|
|
780
|
+
<option value="interactive">Interactive TUI</option>
|
|
781
|
+
<option value="headless">Headless (clio-coder run)</option>
|
|
782
|
+
</select>
|
|
783
|
+
</div>
|
|
784
|
+
</div>
|
|
785
|
+
|
|
786
|
+
<div class="form-row">
|
|
787
|
+
<div class="form-group">
|
|
788
|
+
<label for="toolGroup">Tool Group</label>
|
|
789
|
+
<select id="toolGroup" onchange="onToolChange()">
|
|
790
|
+
<option value="read">read (read, grep, find, ls)</option>
|
|
791
|
+
<option value="write" selected>write / edit</option>
|
|
792
|
+
<option value="git">git (status, diff, log, checkout)</option>
|
|
793
|
+
<option value="bash">bash (general commands)</option>
|
|
794
|
+
<option value="dispatch">dispatch (worker delegation)</option>
|
|
795
|
+
</select>
|
|
796
|
+
</div>
|
|
797
|
+
<div class="form-group">
|
|
798
|
+
<label for="cmdCwd">Working Directory</label>
|
|
799
|
+
<input type="text" id="cmdCwd" value="/workspace/project" oninput="runSimulation()">
|
|
800
|
+
</div>
|
|
801
|
+
</div>
|
|
802
|
+
|
|
803
|
+
<div class="form-group" id="group-command" style="display:none;">
|
|
804
|
+
<label for="commandInput">Shell Command</label>
|
|
805
|
+
<input type="text" id="commandInput" value="" placeholder="e.g. npm test" oninput="runSimulation()">
|
|
806
|
+
</div>
|
|
807
|
+
|
|
808
|
+
<div class="form-group" id="group-filepath">
|
|
809
|
+
<label for="filepathInput">File Path</label>
|
|
810
|
+
<input type="text" id="filepathInput" value="src/core/config.ts" placeholder="e.g. src/index.ts" oninput="runSimulation()">
|
|
811
|
+
</div>
|
|
812
|
+
|
|
813
|
+
<div class="form-group">
|
|
814
|
+
<label for="projectPolicy">Simulated .clio-coder/safety.yaml</label>
|
|
815
|
+
<textarea id="projectPolicy" rows="6" oninput="runSimulation()">zeroAccessPaths:
|
|
816
|
+
- secrets/
|
|
817
|
+
- .env
|
|
818
|
+
readOnlyPaths:
|
|
819
|
+
- vendor/
|
|
820
|
+
noDeletePaths:
|
|
821
|
+
- out/validated/
|
|
822
|
+
commands:
|
|
823
|
+
- id: local-test
|
|
824
|
+
command: npm test
|
|
825
|
+
cwd: .
|
|
826
|
+
requireConfirmation: false</textarea>
|
|
827
|
+
</div>
|
|
828
|
+
|
|
829
|
+
<div class="verdict-header">Evaluation Verdict</div>
|
|
830
|
+
<div id="verdictCard" class="verdict-card v-allow">
|
|
831
|
+
<div class="verdict-info">
|
|
832
|
+
<h3 id="verdictTitle">ALLOW</h3>
|
|
833
|
+
<p id="verdictDesc">Tool call passes all checks and runs immediately.</p>
|
|
834
|
+
</div>
|
|
835
|
+
<div id="verdictIcon" class="verdict-status-badge">✓</div>
|
|
836
|
+
</div>
|
|
837
|
+
|
|
838
|
+
<div class="console-header">
|
|
839
|
+
<span class="console-title">Engine Decision Trace</span>
|
|
840
|
+
<span class="preset-btn" style="padding: 0.15rem 0.4rem; font-size:0.65rem;" onclick="clearConsole()">Clear</span>
|
|
841
|
+
</div>
|
|
842
|
+
<div id="traceConsole" class="console-body">Initializing Safety Policy Engine...</div>
|
|
843
|
+
</div>
|
|
844
|
+
</div>
|
|
845
|
+
|
|
846
|
+
</div>
|
|
847
|
+
</main>
|
|
848
|
+
|
|
849
|
+
<!-- TAB 2: TECHNICAL REFERENCE -->
|
|
850
|
+
<main class="tab-pane" id="pane-reference">
|
|
851
|
+
<div class="glass-card">
|
|
852
|
+
<h2>Clio Coder Safety Model Specification</h2>
|
|
853
|
+
|
|
854
|
+
<div class="alert-tip">
|
|
855
|
+
<strong>Interactive Spec Available:</strong> Use the <strong>Interactive Spec & Simulator</strong> tab above to simulate policy enforcement runs in real-time.
|
|
856
|
+
</div>
|
|
857
|
+
|
|
858
|
+
<p>Clio Coder's safety posture is code-enforced, not prompt-only. Prompt text tells the model how to behave, but execution is gated by target capabilities, the tool registry, safety policy engine, project policy, protected-artifact checks, and receipts.</p>
|
|
859
|
+
<p>Source of truth: <code>src/domains/safety/**</code>, <code>src/tools/registry.ts</code>, <code>src/tools/bootstrap.ts</code>, and <code>damage-control-rules.yaml</code>.</p>
|
|
860
|
+
|
|
861
|
+
<h3 style="margin: 1.5rem 0 0.5rem 0; color:#fff;">Two axes: autonomy and the safety net</h3>
|
|
862
|
+
<p>The <code>autonomy</code> setting (<code>read-only</code> | <code>suggest</code> | <code>auto-edit</code> | <code>full-auto</code>) is an enforced dial. It controls exactly one thing: which action classes run immediately, which park for operator approval, and which are auto-denied. Effective autonomy is resolved through <code>resolveEffectiveAutonomy</code> and <code>resolveBaselineAutonomy</code> in <code>src/entry/orchestrator.ts</code> across all admission surfaces. The safety net (damage-control rules, path policy, protected artifacts, loop guard, dispatch scope admission) is independent of the dial and identical at every level.</p>
|
|
863
|
+
|
|
864
|
+
<h3 style="margin: 1.5rem 0 0.5rem 0; color:#fff;">Enforcement path</h3>
|
|
865
|
+
<p>Every tool call, orchestrator or worker, evaluates in this order:</p>
|
|
866
|
+
<ol style="margin-left: 2rem; margin-bottom: 1rem; font-size: 0.925rem; color: var(--text-muted);">
|
|
867
|
+
<li style="margin-bottom: 0.5rem;"><strong>Safety net</strong> (policy engine + middleware guards): <code>block</code> is final at every level; <code>ask</code> is a confirm rail (damage-control <code>ask</code> rules, project <code>requireConfirmation</code>) that parks at every level; <code>pass</code> hands off to step 2.</li>
|
|
868
|
+
<li style="margin-bottom: 0.5rem;"><strong>Autonomy mapping</strong>: the action class plus the level produce allow, ask, or deny per the matrix.</li>
|
|
869
|
+
<li style="margin-bottom: 0.5rem;"><strong>Approvals</strong>: whatever asked in step 1 or 2 parks interactively, denies deterministically headless, resolves per <code>workers.onPermission</code> in workers, and non-stall denies in delegations.</li>
|
|
870
|
+
</ol>
|
|
871
|
+
|
|
872
|
+
<h3 style="margin: 1.5rem 0 0.5rem 0; color:#fff;">Damage-control rules</h3>
|
|
873
|
+
<p><code>damage-control-rules.yaml</code> is compiled into rule packs. Base rules apply broadly. Rules with <code>ask: true</code> park for one-shot confirmation (for example <code>git stash drop</code> and remote-branch deletion); hard-block rules and classifier-pattern <code>git_destructive</code> hits are always blocked. Both behaviors apply at every autonomy level.</p>
|
|
874
|
+
|
|
875
|
+
<h3 style="margin: 1.5rem 0 0.5rem 0; color:#fff;">Bash recognition</h3>
|
|
876
|
+
<p>The policy engine tags every bash command as recognized or unrecognized:</p>
|
|
877
|
+
<ul style="margin-left: 2rem; margin-bottom: 1rem; font-size: 0.925rem; color: var(--text-muted);">
|
|
878
|
+
<li style="margin-bottom: 0.5rem;"><strong>Recognized</strong>: a valid <code>.clio-coder/safety.yaml</code> command entry, or the narrow built-in no-prompt set such as <code>pwd</code>, simple <code>ls</code>, <code>git status</code>, bounded <code>git diff/log</code>, common test/lint/build commands. Recognized commands run without prompting at <code>auto-edit</code> and <code>full-auto</code>.</li>
|
|
879
|
+
<li style="margin-bottom: 0.5rem;"><strong>Unrecognized</strong>: anything else. Unrecognized bash asks for one-shot approval at <code>auto-edit</code> and runs at <code>full-auto</code>; at <code>suggest</code> it asks like every mutation, and at <code>read-only</code> it is denied.</li>
|
|
880
|
+
</ul>
|
|
881
|
+
|
|
882
|
+
<h3 style="margin: 1.5rem 0 0.5rem 0; color:#fff;">Project safety policy</h3>
|
|
883
|
+
<p>Clio searches upward from the current working directory for <code>.clio-coder/safety.yaml</code>. Minimum schema is version-locked (v1) and parses into standard path boundaries (<code>zeroAccessPaths</code>, <code>readOnlyPaths</code>, <code>noDeletePaths</code>) and customized command sets.</p>
|
|
884
|
+
|
|
885
|
+
<pre><code>version: 1
|
|
886
|
+
zeroAccessPaths:
|
|
887
|
+
- secrets/
|
|
888
|
+
- .env
|
|
889
|
+
readOnlyPaths:
|
|
890
|
+
- vendor/
|
|
891
|
+
noDeletePaths:
|
|
892
|
+
- out/validated/
|
|
893
|
+
commands:
|
|
894
|
+
- id: local-test
|
|
895
|
+
command: npm test
|
|
896
|
+
cwd: .
|
|
897
|
+
actionClass: execute
|
|
898
|
+
shellOperators: deny
|
|
899
|
+
requireConfirmation: false
|
|
900
|
+
rationale: Standard local test command.</code></pre>
|
|
901
|
+
|
|
902
|
+
<h3 style="margin: 1.5rem 0 0.5rem 0; color:#fff;">Typed validation tools</h3>
|
|
903
|
+
<p>Prefer typed tools over Bash: <code>git</code> (status/diff/log) and <code>verify</code>. <code>verify(check="frontend")</code> accepts <code>.html</code>, <code>.css</code>, <code>.js</code> under the workspace root, performing syntax checks and optionally validating references in headless browsers.</p>
|
|
904
|
+
|
|
905
|
+
<h3 style="margin: 1.5rem 0 0.5rem 0; color:#fff;">Dispatch and delegation runtimes</h3>
|
|
906
|
+
<p>Clio dispatches tasks to worker runtimes and delegation agents under different safety postures:</p>
|
|
907
|
+
<ul style="margin-left: 2rem; margin-bottom: 1rem; font-size: 0.925rem; color: var(--text-muted);">
|
|
908
|
+
<li style="margin-bottom: 0.5rem;"><strong><code>claude-sdk</code> (Enforced Safety):</strong> The Claude Code SDK worker is the <strong>strong safety path</strong>. It gates every tool request through Clio's safety net and active autonomy dial before execution via PreToolUse hooks. Worker denials resolve non-interactively based on <code>workers.onPermission</code>.</li>
|
|
909
|
+
<li style="margin-bottom: 0.5rem;"><strong><code>claude-code</code> (Subprocess Gating):</strong> Drives <code>claude -p</code> as a subprocess. Gating is restricted to command-line parameters mapping the autonomy level to CLI permission modes, without per-tool callbacks.</li>
|
|
910
|
+
<li style="margin-bottom: 0.5rem;"><strong>Claude Code over ACP (Advisory Gating):</strong> Drives the agent over ACP delegation. Gating is <strong>advisory</strong> because Claude self-governs its tools; <code>claude-sdk</code> is preferred for fully enforced safety.</li>
|
|
911
|
+
</ul>
|
|
912
|
+
|
|
913
|
+
<h3 style="margin: 1.5rem 0 0.5rem 0; color:#fff;">Write boundaries: detect-and-rollback</h3>
|
|
914
|
+
<p>Post-run enforcement of declared write boundaries is strictly detect-and-rollback, never sandboxing (<code>src/domains/dispatch/write-boundary.ts</code>). Nothing prevents a write during step execution: no container, no seccomp filter, and no filesystem interception. After execution, the orchestrator compares the checkout against pre-step snapshots, rolls back unpermitted modifications, and fails the step with a <code>WriteBoundaryViolation</code>.</p>
|
|
915
|
+
|
|
916
|
+
<h3 style="margin: 1.5rem 0 0.5rem 0; color:#fff;">Receipts and evidence</h3>
|
|
917
|
+
<p>Safety decisions feed receipts, audit rows, and evidence. The interactive <code>/view</code> surface can inspect receipt artifacts without mutating them, detailing rules matched, command hashes, and active decisions counts.</p>
|
|
918
|
+
</div>
|
|
919
|
+
</main>
|
|
920
|
+
|
|
921
|
+
<footer>
|
|
922
|
+
<p>Clio Coder Safety Model Specification Dashboard • Version 0.3.0</p>
|
|
923
|
+
</footer>
|
|
924
|
+
</div>
|
|
925
|
+
|
|
926
|
+
<script>
|
|
927
|
+
// Tab switching
|
|
928
|
+
function switchTab(tabId) {
|
|
929
|
+
document.querySelectorAll('.tab-btn').forEach(btn => { btn.classList.remove('active'); });
|
|
930
|
+
document.querySelectorAll('.tab-pane').forEach(pane => { pane.classList.remove('active'); });
|
|
931
|
+
|
|
932
|
+
if (tabId === 'interactive') {
|
|
933
|
+
document.querySelector('.tab-btn:nth-child(1)').classList.add('active');
|
|
934
|
+
document.getElementById('pane-interactive').classList.add('active');
|
|
935
|
+
} else {
|
|
936
|
+
document.querySelector('.tab-btn:nth-child(2)').classList.add('active');
|
|
937
|
+
document.getElementById('pane-reference').classList.add('active');
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// Rules Definitions
|
|
942
|
+
const DAMAGE_CONTROL_RULES = [
|
|
943
|
+
{ id: "rm-rf-root", pattern: /\brm\s+-rf?\s+\/(?![a-z0-9]*tmp\/)/, class: "system_modify", block: true, reason: "Destructive filesystem operation on root" },
|
|
944
|
+
{ id: "git-push-force", pattern: /\bgit\s+push\s+.*(--force|-f)(?!-with-lease)\b/, class: "git_destructive", block: true, reason: "Force push overwrites branch history" },
|
|
945
|
+
{ id: "curl-pipe-sh", pattern: /\bcurl\b[^|]*\|\s*(sudo\s+)?(sh|bash|zsh)\b/, class: "execute", block: true, reason: "Remote-script-to-shell installer is prohibited" },
|
|
946
|
+
{ id: "git-stash-drop", pattern: /\bgit\s+stash\s+drop\b/, class: "git_destructive", block: false, ask: true, reason: "Stash drop permanently discards uncommitted code" },
|
|
947
|
+
{ id: "git-restore-dot", pattern: /\bgit\s+restore\s+\.\s*$/, class: "git_destructive", block: false, ask: true, reason: "Git restore discards all local workspace edits" },
|
|
948
|
+
];
|
|
949
|
+
|
|
950
|
+
const BUILTIN_RECOGNIZED = [
|
|
951
|
+
/^pwd$/,
|
|
952
|
+
/^ls(?:\s+-[a-zA-Z0-9]+|\s+[\w./-]+)*$/,
|
|
953
|
+
/^git\s+status$/,
|
|
954
|
+
/^git\s+diff(?:\s+[\w./-]+)*$/,
|
|
955
|
+
/^git\s+log(?:\s+-[0-9]+)?$/,
|
|
956
|
+
/^npm\s+test$/,
|
|
957
|
+
/^npm\s+run\s+test$/
|
|
958
|
+
];
|
|
959
|
+
|
|
960
|
+
// Tool Groups Change
|
|
961
|
+
function onToolChange() {
|
|
962
|
+
const tool = document.getElementById('toolGroup').value;
|
|
963
|
+
const cmdGroup = document.getElementById('group-command');
|
|
964
|
+
const fileGroup = document.getElementById('group-filepath');
|
|
965
|
+
|
|
966
|
+
if (tool === 'bash' || tool === 'git') {
|
|
967
|
+
cmdGroup.style.display = 'block';
|
|
968
|
+
fileGroup.style.display = 'none';
|
|
969
|
+
} else if (tool === 'read' || tool === 'write') {
|
|
970
|
+
cmdGroup.style.display = 'none';
|
|
971
|
+
fileGroup.style.display = 'block';
|
|
972
|
+
} else {
|
|
973
|
+
cmdGroup.style.display = 'none';
|
|
974
|
+
fileGroup.style.display = 'none';
|
|
975
|
+
}
|
|
976
|
+
runSimulation();
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// Load presets
|
|
980
|
+
function loadPreset(presetId) {
|
|
981
|
+
const toolGroup = document.getElementById('toolGroup');
|
|
982
|
+
const commandInput = document.getElementById('commandInput');
|
|
983
|
+
const filepathInput = document.getElementById('filepathInput');
|
|
984
|
+
|
|
985
|
+
switch(presetId) {
|
|
986
|
+
case 'status':
|
|
987
|
+
toolGroup.value = 'git';
|
|
988
|
+
commandInput.value = 'git status';
|
|
989
|
+
break;
|
|
990
|
+
case 'npm-test':
|
|
991
|
+
toolGroup.value = 'bash';
|
|
992
|
+
commandInput.value = 'npm test';
|
|
993
|
+
break;
|
|
994
|
+
case 'write-src':
|
|
995
|
+
toolGroup.value = 'write';
|
|
996
|
+
filepathInput.value = 'src/index.ts';
|
|
997
|
+
break;
|
|
998
|
+
case 'write-env':
|
|
999
|
+
toolGroup.value = 'write';
|
|
1000
|
+
filepathInput.value = '.env';
|
|
1001
|
+
break;
|
|
1002
|
+
case 'rm-rf':
|
|
1003
|
+
toolGroup.value = 'bash';
|
|
1004
|
+
commandInput.value = 'rm -rf /';
|
|
1005
|
+
break;
|
|
1006
|
+
case 'stash-drop':
|
|
1007
|
+
toolGroup.value = 'git';
|
|
1008
|
+
commandInput.value = 'git stash drop';
|
|
1009
|
+
break;
|
|
1010
|
+
case 'force-push':
|
|
1011
|
+
toolGroup.value = 'git';
|
|
1012
|
+
commandInput.value = 'git push origin main --force';
|
|
1013
|
+
break;
|
|
1014
|
+
case 'escape-write':
|
|
1015
|
+
toolGroup.value = 'write';
|
|
1016
|
+
filepathInput.value = '/etc/hosts';
|
|
1017
|
+
break;
|
|
1018
|
+
case 'unrecognized-exec':
|
|
1019
|
+
toolGroup.value = 'bash';
|
|
1020
|
+
commandInput.value = 'sudo apt-get install build-essential';
|
|
1021
|
+
break;
|
|
1022
|
+
}
|
|
1023
|
+
onToolChange();
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
// Clear console
|
|
1027
|
+
function clearConsole() {
|
|
1028
|
+
document.getElementById('traceConsole').innerHTML = '';
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// Log to console helper
|
|
1032
|
+
function logTrace(msg, type = 'info') {
|
|
1033
|
+
const consoleEl = document.getElementById('traceConsole');
|
|
1034
|
+
let prefix = '[INFO]';
|
|
1035
|
+
if (type === 'warn') prefix = '[WARN]';
|
|
1036
|
+
if (type === 'error') prefix = '[ERROR]';
|
|
1037
|
+
if (type === 'success') prefix = '[SUCCESS]';
|
|
1038
|
+
|
|
1039
|
+
consoleEl.innerHTML += `\n${prefix} ${msg}`;
|
|
1040
|
+
consoleEl.scrollTop = consoleEl.scrollHeight;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
// Parse simple yaml zeroAccess/readOnly/noDelete paths
|
|
1044
|
+
function parsePathPolicies(yamlText) {
|
|
1045
|
+
const zeroAccess = [];
|
|
1046
|
+
const readOnly = [];
|
|
1047
|
+
const noDelete = [];
|
|
1048
|
+
|
|
1049
|
+
try {
|
|
1050
|
+
const lines = yamlText.split('\n');
|
|
1051
|
+
let currentSection = null;
|
|
1052
|
+
lines.forEach(line => {
|
|
1053
|
+
const trimmed = line.trim();
|
|
1054
|
+
if (!trimmed || trimmed.startsWith('#')) return;
|
|
1055
|
+
|
|
1056
|
+
if (trimmed.startsWith('zeroAccessPaths:')) {
|
|
1057
|
+
currentSection = 'zero';
|
|
1058
|
+
} else if (trimmed.startsWith('readOnlyPaths:')) {
|
|
1059
|
+
currentSection = 'readonly';
|
|
1060
|
+
} else if (trimmed.startsWith('noDeletePaths:')) {
|
|
1061
|
+
currentSection = 'nodelete';
|
|
1062
|
+
} else if (trimmed.startsWith('commands:')) {
|
|
1063
|
+
currentSection = 'commands';
|
|
1064
|
+
} else if (trimmed.startsWith('-') && currentSection) {
|
|
1065
|
+
const val = trimmed.replace(/^-/, '').trim().replace(/['"]/g, '');
|
|
1066
|
+
if (currentSection === 'zero') zeroAccess.push(val);
|
|
1067
|
+
if (currentSection === 'readonly') readOnly.push(val);
|
|
1068
|
+
if (currentSection === 'nodelete') noDelete.push(val);
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
} catch (_) {
|
|
1072
|
+
// fail silently
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
return { zeroAccess, readOnly, noDelete };
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
// Main simulator algorithm
|
|
1079
|
+
function runSimulation() {
|
|
1080
|
+
const autonomy = document.getElementById('autonomyLevel').value;
|
|
1081
|
+
const posture = document.getElementById('operatingPosture').value;
|
|
1082
|
+
const tool = document.getElementById('toolGroup').value;
|
|
1083
|
+
const cwd = document.getElementById('cmdCwd').value.trim();
|
|
1084
|
+
const command = document.getElementById('commandInput').value.trim();
|
|
1085
|
+
const filepath = document.getElementById('filepathInput').value.trim();
|
|
1086
|
+
const policyYaml = document.getElementById('projectPolicy').value;
|
|
1087
|
+
|
|
1088
|
+
clearConsole();
|
|
1089
|
+
logTrace("Evaluating safety request...", 'info');
|
|
1090
|
+
logTrace(`autonomy_level="${autonomy}" posture_mode="${posture}" tool="${tool}"`, 'info');
|
|
1091
|
+
|
|
1092
|
+
// Highlight active autonomy column in matrix table
|
|
1093
|
+
document.querySelectorAll('#matrixTable th, #matrixTable td').forEach(el => { el.classList.remove('highlight'); });
|
|
1094
|
+
const activeColId = `hdr-${autonomy}`;
|
|
1095
|
+
const colIndex = Array.from(document.querySelectorAll('#matrixTable th')).findIndex(th => th.id === activeColId);
|
|
1096
|
+
if (colIndex !== -1) {
|
|
1097
|
+
document.querySelectorAll(`#matrixTable th:nth-child(${colIndex + 1})`).forEach(el => { el.classList.add('highlight'); });
|
|
1098
|
+
document.querySelectorAll(`#matrixTable td:nth-child(${colIndex + 1})`).forEach(el => { el.classList.add('highlight'); });
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// ----------------------------------------------------
|
|
1102
|
+
// STAGE 1: CLASSIFY ACTION CLASS
|
|
1103
|
+
// ----------------------------------------------------
|
|
1104
|
+
let actionClass = "unknown";
|
|
1105
|
+
|
|
1106
|
+
if (tool === 'read') {
|
|
1107
|
+
actionClass = "read";
|
|
1108
|
+
} else if (tool === 'write') {
|
|
1109
|
+
// Path safety overrides classification
|
|
1110
|
+
const SYSTEM_ROOTS = ['/etc', '/usr', '/var', '/bin', '/sbin', '/run'];
|
|
1111
|
+
const SCRATCH_EXEMPT = ['/var/tmp', '/var/folders'];
|
|
1112
|
+
const underSystemRoot =
|
|
1113
|
+
SYSTEM_ROOTS.some((root) => filepath === root || filepath.startsWith(root + '/')) &&
|
|
1114
|
+
!SCRATCH_EXEMPT.some((root) => filepath === root || filepath.startsWith(root + '/'));
|
|
1115
|
+
if (underSystemRoot) {
|
|
1116
|
+
actionClass = "system_modify";
|
|
1117
|
+
logTrace(`Path Escaping: file write path "${filepath}" is a system directory`, 'warn');
|
|
1118
|
+
} else if (filepath.startsWith('..') || filepath.startsWith('/') && !filepath.startsWith(cwd)) {
|
|
1119
|
+
actionClass = "system_modify";
|
|
1120
|
+
logTrace(`Path Escaping: file write path "${filepath}" escapes workspace root`, 'warn');
|
|
1121
|
+
} else {
|
|
1122
|
+
actionClass = "write";
|
|
1123
|
+
}
|
|
1124
|
+
} else if (tool === 'git') {
|
|
1125
|
+
// Parse git command
|
|
1126
|
+
let isDestructive = false;
|
|
1127
|
+
for (const rule of DAMAGE_CONTROL_RULES) {
|
|
1128
|
+
if (rule.class === 'git_destructive' && rule.pattern.test(command)) {
|
|
1129
|
+
actionClass = "git_destructive";
|
|
1130
|
+
isDestructive = true;
|
|
1131
|
+
break;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
if (!isDestructive) {
|
|
1135
|
+
if (command.startsWith('git diff') || command.startsWith('git status') || command.startsWith('git log')) {
|
|
1136
|
+
actionClass = "read";
|
|
1137
|
+
} else {
|
|
1138
|
+
actionClass = "execute"; // git commit, add, stash, etc.
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
} else if (tool === 'bash') {
|
|
1142
|
+
// Classify bash commands
|
|
1143
|
+
let isDestructive = false;
|
|
1144
|
+
let isSysModify = false;
|
|
1145
|
+
|
|
1146
|
+
for (const rule of DAMAGE_CONTROL_RULES) {
|
|
1147
|
+
if (rule.pattern.test(command)) {
|
|
1148
|
+
if (rule.class === 'git_destructive') {
|
|
1149
|
+
actionClass = "git_destructive";
|
|
1150
|
+
isDestructive = true;
|
|
1151
|
+
} else if (rule.class === 'system_modify') {
|
|
1152
|
+
actionClass = "system_modify";
|
|
1153
|
+
isSysModify = true;
|
|
1154
|
+
}
|
|
1155
|
+
break;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
if (!isDestructive && !isSysModify) {
|
|
1160
|
+
if (command.includes('sudo') || command.includes('apt-get') || command.includes('npm install -g')) {
|
|
1161
|
+
actionClass = "system_modify";
|
|
1162
|
+
} else {
|
|
1163
|
+
// Check if recognized
|
|
1164
|
+
let recognized = false;
|
|
1165
|
+
const hasOtherOperators = /\|\||[;|><\n]/.test(command);
|
|
1166
|
+
const isChain = !hasOtherOperators && command.includes('&&');
|
|
1167
|
+
if (hasOtherOperators) {
|
|
1168
|
+
logTrace(`Sequencing or redirection operator found. Command is unrecognized.`, 'warn');
|
|
1169
|
+
} else if (isChain) {
|
|
1170
|
+
// An && chain is recognized only when every member is, capped at
|
|
1171
|
+
// six members, and it takes the most restrictive member's verdict.
|
|
1172
|
+
const segments = command.split('&&').map((part) => part.trim()).filter(Boolean);
|
|
1173
|
+
const memberRecognized = (segment) =>
|
|
1174
|
+
BUILTIN_RECOGNIZED.some((rx) => rx.test(segment)) || segment === 'npm test' || /^cd\s+\S+$/.test(segment);
|
|
1175
|
+
if (segments.length > 6) {
|
|
1176
|
+
logTrace(`Chain of ${segments.length} members exceeds the six-member cap. Command is unrecognized.`, 'warn');
|
|
1177
|
+
} else if (segments.every(memberRecognized)) {
|
|
1178
|
+
recognized = true;
|
|
1179
|
+
logTrace(`Every member of the && chain is recognized. Chain classified as execute (recognized).`, 'success');
|
|
1180
|
+
} else {
|
|
1181
|
+
logTrace(`One or more && chain members are unrecognized. Command is unrecognized.`, 'warn');
|
|
1182
|
+
}
|
|
1183
|
+
} else {
|
|
1184
|
+
for (const rx of BUILTIN_RECOGNIZED) {
|
|
1185
|
+
if (rx.test(command)) {
|
|
1186
|
+
recognized = true;
|
|
1187
|
+
break;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
// Check project policy command IDs
|
|
1191
|
+
if (command === 'npm test') {
|
|
1192
|
+
recognized = true; // matches simulated policy
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
if (recognized) {
|
|
1197
|
+
actionClass = "execute"; // Recognized no-prompt set
|
|
1198
|
+
logTrace(`Recognized command match: "${command}" classified as execute (recognized)`, 'success');
|
|
1199
|
+
} else {
|
|
1200
|
+
actionClass = "execute_other"; // Unrecognized bash
|
|
1201
|
+
logTrace(`Unrecognized command: "${command}" classified as execute (any other bash)`, 'warn');
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
} else if (tool === 'dispatch') {
|
|
1206
|
+
actionClass = "dispatch";
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
// Highlight active row in matrix
|
|
1210
|
+
document.querySelectorAll('#matrixTable tbody tr').forEach(tr => { tr.style.background = 'none'; });
|
|
1211
|
+
let rowEl = null;
|
|
1212
|
+
if (actionClass === 'read') rowEl = document.getElementById('row-read');
|
|
1213
|
+
else if (actionClass === 'write') rowEl = document.getElementById('row-write');
|
|
1214
|
+
else if (actionClass === 'execute') rowEl = document.getElementById('row-execute-builtin');
|
|
1215
|
+
else if (actionClass === 'execute_other') rowEl = document.getElementById('row-execute-other');
|
|
1216
|
+
else if (actionClass === 'dispatch') rowEl = document.getElementById('row-dispatch');
|
|
1217
|
+
else if (actionClass === 'system_modify') rowEl = document.getElementById('row-system-modify');
|
|
1218
|
+
else if (actionClass === 'git_destructive') rowEl = document.getElementById('row-git-destructive');
|
|
1219
|
+
else rowEl = document.getElementById('row-unknown');
|
|
1220
|
+
|
|
1221
|
+
if (rowEl) {
|
|
1222
|
+
rowEl.style.background = 'rgba(0, 240, 255, 0.04)';
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
logTrace(`Resolved Action Class: "${actionClass === 'execute_other' ? 'execute: other bash' : actionClass}"`, 'info');
|
|
1226
|
+
|
|
1227
|
+
// ----------------------------------------------------
|
|
1228
|
+
// STAGE 2: RUN THROUGH SAFETY NET (Damage Control Rules & Path Policies)
|
|
1229
|
+
// ----------------------------------------------------
|
|
1230
|
+
let safetyNetVerdict = "pass";
|
|
1231
|
+
let safetyNetReason = "";
|
|
1232
|
+
|
|
1233
|
+
// Path policies from YAML
|
|
1234
|
+
const policies = parsePathPolicies(policyYaml);
|
|
1235
|
+
const activeScanPath = tool === 'write' ? filepath : command;
|
|
1236
|
+
|
|
1237
|
+
// Check zeroAccessPaths
|
|
1238
|
+
for (const p of policies.zeroAccess) {
|
|
1239
|
+
if (activeScanPath.includes(p)) {
|
|
1240
|
+
safetyNetVerdict = "block";
|
|
1241
|
+
safetyNetReason = `zeroAccessPaths breach: path contains "${p}"`;
|
|
1242
|
+
break;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
// Check command substitution confirm rail
|
|
1247
|
+
if (safetyNetVerdict === 'pass' && (tool === 'bash' || tool === 'git')) {
|
|
1248
|
+
const hasSubstitution = /\$\(|`/.test(command);
|
|
1249
|
+
if (hasSubstitution) {
|
|
1250
|
+
safetyNetVerdict = "confirm";
|
|
1251
|
+
safetyNetReason = "Command substitution $(...) or backticks is an always-on Safety Net confirm rail";
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
// Check readOnlyPaths (for write commands)
|
|
1256
|
+
if (safetyNetVerdict === 'pass' && tool === 'write') {
|
|
1257
|
+
for (const p of policies.readOnly) {
|
|
1258
|
+
if (filepath.includes(p)) {
|
|
1259
|
+
safetyNetVerdict = "block";
|
|
1260
|
+
safetyNetReason = `readOnlyPaths breach: writing to "${p}" is blocked`;
|
|
1261
|
+
break;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
// Check Damage Control rules regexes
|
|
1267
|
+
if (safetyNetVerdict === 'pass') {
|
|
1268
|
+
for (const rule of DAMAGE_CONTROL_RULES) {
|
|
1269
|
+
if (rule.pattern.test(command) || rule.pattern.test(filepath)) {
|
|
1270
|
+
if (rule.block) {
|
|
1271
|
+
safetyNetVerdict = "block";
|
|
1272
|
+
safetyNetReason = `Damage control match: ${rule.reason} (Rule: ${rule.id})`;
|
|
1273
|
+
} else if (rule.ask) {
|
|
1274
|
+
safetyNetVerdict = "confirm";
|
|
1275
|
+
safetyNetReason = `Damage control confirm check: ${rule.reason} (Rule: ${rule.id})`;
|
|
1276
|
+
}
|
|
1277
|
+
break;
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
logTrace(`[Safety Net Check] Verdict: ${safetyNetVerdict.toUpperCase()} ${safetyNetReason ? `(${safetyNetReason})` : ''}`, safetyNetVerdict === 'block' ? 'error' : (safetyNetVerdict === 'confirm' ? 'warn' : 'success'));
|
|
1283
|
+
|
|
1284
|
+
// ----------------------------------------------------
|
|
1285
|
+
// STAGE 3: AUTONOMY MAPPING
|
|
1286
|
+
// ----------------------------------------------------
|
|
1287
|
+
let autonomyVerdict = "allow";
|
|
1288
|
+
|
|
1289
|
+
if (safetyNetVerdict !== 'block') {
|
|
1290
|
+
// Map matrix
|
|
1291
|
+
if (autonomy === 'read-only') {
|
|
1292
|
+
autonomyVerdict = (actionClass === 'read') ? 'allow' : 'deny';
|
|
1293
|
+
} else if (autonomy === 'suggest') {
|
|
1294
|
+
autonomyVerdict = (actionClass === 'read') ? 'allow' : 'ask';
|
|
1295
|
+
} else if (autonomy === 'auto-edit') {
|
|
1296
|
+
if (actionClass === 'read' || actionClass === 'write' || actionClass === 'execute' || actionClass === 'dispatch') {
|
|
1297
|
+
autonomyVerdict = 'allow';
|
|
1298
|
+
} else {
|
|
1299
|
+
autonomyVerdict = 'ask'; // execute_other, system_modify, unknown
|
|
1300
|
+
}
|
|
1301
|
+
} else if (autonomy === 'full-auto') {
|
|
1302
|
+
if (actionClass === 'system_modify' || actionClass === 'unknown') {
|
|
1303
|
+
autonomyVerdict = 'ask';
|
|
1304
|
+
} else {
|
|
1305
|
+
autonomyVerdict = 'allow';
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
// git_destructive is net block regardless of autonomy level
|
|
1310
|
+
// EXCEPT when it is overridden by an authored damage-control confirm (ask) rule (e.g. git stash drop)
|
|
1311
|
+
const isAskRule = (safetyNetVerdict === 'confirm');
|
|
1312
|
+
if (actionClass === 'git_destructive' && !isAskRule) {
|
|
1313
|
+
autonomyVerdict = 'block';
|
|
1314
|
+
}
|
|
1315
|
+
} else {
|
|
1316
|
+
autonomyVerdict = 'block';
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
logTrace(`[Autonomy Mapping] Matrix result: ${autonomyVerdict.toUpperCase()}`, autonomyVerdict === 'allow' ? 'success' : (autonomyVerdict === 'ask' ? 'warn' : 'error'));
|
|
1320
|
+
|
|
1321
|
+
// ----------------------------------------------------
|
|
1322
|
+
// STAGE 4: RESOLVE APPROVALS / POSTURE
|
|
1323
|
+
// ----------------------------------------------------
|
|
1324
|
+
let finalVerdict = "ALLOW";
|
|
1325
|
+
let finalDetails = "Tool call passes all checks and runs immediately.";
|
|
1326
|
+
let cardClass = "v-allow";
|
|
1327
|
+
let icon = "✓";
|
|
1328
|
+
|
|
1329
|
+
// Combine Safety Net + Autonomy Mappings
|
|
1330
|
+
const resolvesToAsk = (safetyNetVerdict === 'confirm' || autonomyVerdict === 'ask');
|
|
1331
|
+
const resolvesToBlock = (safetyNetVerdict === 'block' || autonomyVerdict === 'block');
|
|
1332
|
+
const resolvesToDeny = (autonomyVerdict === 'deny');
|
|
1333
|
+
|
|
1334
|
+
if (resolvesToBlock) {
|
|
1335
|
+
finalVerdict = "BLOCK";
|
|
1336
|
+
finalDetails = `[safety-net] block: ${safetyNetReason || 'Action classified as destructive and hard blocked by rule.'}`;
|
|
1337
|
+
cardClass = "v-block";
|
|
1338
|
+
icon = "🛑";
|
|
1339
|
+
logTrace(`Safety Net blocked execution. Final status: BLOCKED`, 'error');
|
|
1340
|
+
} else if (resolvesToDeny) {
|
|
1341
|
+
finalVerdict = "DENY";
|
|
1342
|
+
finalDetails = `[autonomy] denied: Operating under "${autonomy}" level. Action is denied.`;
|
|
1343
|
+
cardClass = "v-deny";
|
|
1344
|
+
icon = "✕";
|
|
1345
|
+
logTrace(`Autonomy level denied execution. Final status: DENIED`, 'error');
|
|
1346
|
+
} else if (resolvesToAsk) {
|
|
1347
|
+
if (posture === 'headless') {
|
|
1348
|
+
// Headless mode automatically denies asks deterministically
|
|
1349
|
+
finalVerdict = "DENY (HEADLESS)";
|
|
1350
|
+
finalDetails = `clio-coder run cannot confirm permission requests; rerun interactively to approve this action.`;
|
|
1351
|
+
cardClass = "v-block";
|
|
1352
|
+
icon = "✕";
|
|
1353
|
+
logTrace(`Headless mode auto-denied interactive request. Final status: DENIED`, 'error');
|
|
1354
|
+
} else {
|
|
1355
|
+
// Interactive TUI mode parks for overlay approval
|
|
1356
|
+
finalVerdict = "ASK / PARK";
|
|
1357
|
+
const askedBy = (safetyNetVerdict === 'confirm') ? 'Asked by: Safety Net rule' : 'Asked by: Autonomy Mapping Matrix';
|
|
1358
|
+
finalDetails = `[approval] notice: Parked in TUI queue overlay. (${askedBy})`;
|
|
1359
|
+
cardClass = "v-ask";
|
|
1360
|
+
icon = "⏳";
|
|
1361
|
+
logTrace(`Parked in TUI permission overlay queue. Waiting for operator...`, 'warn');
|
|
1362
|
+
}
|
|
1363
|
+
} else {
|
|
1364
|
+
logTrace(`Tool call successfully allowed. Final status: ALLOWED`, 'success');
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
// Update UI displays
|
|
1368
|
+
document.getElementById('verdictTitle').innerText = finalVerdict;
|
|
1369
|
+
document.getElementById('verdictDesc').innerText = finalDetails;
|
|
1370
|
+
|
|
1371
|
+
const vCard = document.getElementById('verdictCard');
|
|
1372
|
+
vCard.className = `verdict-card ${cardClass}`;
|
|
1373
|
+
document.getElementById('verdictIcon').innerText = icon;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
window.switchTab = switchTab;
|
|
1377
|
+
window.loadPreset = loadPreset;
|
|
1378
|
+
window.clearConsole = clearConsole;
|
|
1379
|
+
|
|
1380
|
+
// Initialize Simulator on load
|
|
1381
|
+
window.onload = () => {
|
|
1382
|
+
onToolChange();
|
|
1383
|
+
};
|
|
1384
|
+
</script>
|
|
1385
|
+
</body>
|
|
1386
|
+
</html>
|