@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,2065 @@
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 Extensions & Skills Subsystem Blueprint</title>
7
+ <!-- Modern Google Font -->
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: #6b7280;
17
+
18
+ /* Vibrant Color Palettes */
19
+ --color-primary: #00f0ff; /* Glowing Cyan */
20
+ --color-primary-rgb: 0, 240, 255;
21
+ --color-secondary: #bd00ff; /* Glowing Purple */
22
+ --color-secondary-rgb: 189, 0, 255;
23
+ --color-accent: #10b981; /* Emerald Green */
24
+ --color-warn: #f59e0b; /* Amber */
25
+ --color-danger: #ef4444; /* Rose Red */
26
+ --color-info: #3b82f6; /* Blue */
27
+
28
+ --gradient-main: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
29
+ --shadow-glow: 0 0 20px rgba(var(--color-primary-rgb), 0.15);
30
+ --font-sans: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif;
31
+ --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
32
+ }
33
+
34
+ * {
35
+ box-sizing: border-box;
36
+ margin: 0;
37
+ padding: 0;
38
+ }
39
+
40
+ body {
41
+ background-color: var(--bg-dark);
42
+ background-image:
43
+ radial-gradient(circle at 10% 20%, rgba(var(--color-primary-rgb), 0.05) 0%, transparent 40%),
44
+ radial-gradient(circle at 90% 80%, rgba(var(--color-secondary-rgb), 0.05) 0%, transparent 40%),
45
+ radial-gradient(circle at 50% 50%, #0d1527 0%, var(--bg-dark) 100%);
46
+ color: var(--text-main);
47
+ font-family: var(--font-sans);
48
+ min-height: 100vh;
49
+ line-height: 1.6;
50
+ overflow-x: hidden;
51
+ }
52
+
53
+ /* Scrollbar Styling */
54
+ ::-webkit-scrollbar {
55
+ width: 8px;
56
+ height: 8px;
57
+ }
58
+ ::-webkit-scrollbar-track {
59
+ background: rgba(255, 255, 255, 0.02);
60
+ }
61
+ ::-webkit-scrollbar-thumb {
62
+ background: rgba(255, 255, 255, 0.1);
63
+ border-radius: 4px;
64
+ }
65
+ ::-webkit-scrollbar-thumb:hover {
66
+ background: rgba(var(--color-primary-rgb), 0.3);
67
+ }
68
+
69
+ /* Container */
70
+ .container {
71
+ max-width: 1400px;
72
+ margin: 0 auto;
73
+ padding: 2rem;
74
+ }
75
+
76
+ /* Header */
77
+ header {
78
+ text-align: center;
79
+ margin-bottom: 3rem;
80
+ position: relative;
81
+ }
82
+
83
+ .header-logo {
84
+ display: inline-flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ width: 72px;
88
+ height: 72px;
89
+ background: rgba(255, 255, 255, 0.03);
90
+ border: 1px solid var(--border-card);
91
+ border-radius: 18px;
92
+ margin-bottom: 1rem;
93
+ box-shadow: var(--shadow-glow);
94
+ position: relative;
95
+ }
96
+
97
+ .header-logo::after {
98
+ content: '';
99
+ position: absolute;
100
+ inset: -2px;
101
+ border-radius: 20px;
102
+ background: var(--gradient-main);
103
+ z-index: -1;
104
+ opacity: 0.3;
105
+ filter: blur(4px);
106
+ }
107
+
108
+ .header-logo img {
109
+ width: 78%;
110
+ height: 78%;
111
+ object-fit: contain;
112
+ filter: drop-shadow(0 0 8px rgba(0, 240, 255, 0.35));
113
+ }
114
+
115
+ h1 {
116
+ font-size: 2.5rem;
117
+ font-weight: 800;
118
+ letter-spacing: -0.05em;
119
+ margin-bottom: 0.5rem;
120
+ background: linear-gradient(to right, #ffffff, #a5b4fc, var(--color-primary));
121
+ -webkit-background-clip: text;
122
+ -webkit-text-fill-color: transparent;
123
+ }
124
+
125
+ .subtitle {
126
+ font-size: 1.05rem;
127
+ color: var(--text-muted);
128
+ max-width: 700px;
129
+ margin: 0 auto 1.5rem auto;
130
+ font-weight: 400;
131
+ }
132
+
133
+ .meta-badge-container {
134
+ display: flex;
135
+ justify-content: center;
136
+ gap: 0.75rem;
137
+ flex-wrap: wrap;
138
+ }
139
+
140
+ .meta-badge {
141
+ background: rgba(255, 255, 255, 0.04);
142
+ border: 1px solid var(--border-card);
143
+ padding: 0.35rem 0.85rem;
144
+ border-radius: 9999px;
145
+ font-size: 0.8rem;
146
+ font-family: var(--font-mono);
147
+ color: var(--text-muted);
148
+ }
149
+
150
+ .meta-badge span {
151
+ color: var(--color-primary);
152
+ font-weight: 600;
153
+ }
154
+
155
+ /* Tabs Navigation */
156
+ .tabs-nav {
157
+ display: flex;
158
+ justify-content: center;
159
+ gap: 0.75rem;
160
+ margin-bottom: 2.5rem;
161
+ flex-wrap: wrap;
162
+ border-bottom: 1px solid var(--border-card);
163
+ padding-bottom: 1rem;
164
+ }
165
+
166
+ .tab-btn {
167
+ background: transparent;
168
+ border: 1px solid transparent;
169
+ color: var(--text-muted);
170
+ padding: 0.6rem 1.2rem;
171
+ border-radius: 8px;
172
+ font-weight: 600;
173
+ font-family: var(--font-sans);
174
+ cursor: pointer;
175
+ transition: all 0.2s ease;
176
+ }
177
+
178
+ .tab-btn:hover {
179
+ color: var(--text-main);
180
+ background: rgba(255, 255, 255, 0.03);
181
+ }
182
+
183
+ .tab-btn.active {
184
+ color: var(--bg-dark);
185
+ background: var(--gradient-main);
186
+ border-color: transparent;
187
+ box-shadow: 0 4px 15px rgba(var(--color-primary-rgb), 0.25);
188
+ }
189
+
190
+ /* Tab Contents */
191
+ .tab-content {
192
+ display: none;
193
+ }
194
+
195
+ .tab-content.active {
196
+ display: block;
197
+ animation: fadeIn 0.4s ease-out;
198
+ }
199
+
200
+ @keyframes fadeIn {
201
+ from { opacity: 0; transform: translateY(8px); }
202
+ to { opacity: 1; transform: translateY(0); }
203
+ }
204
+
205
+ /* Glass Cards */
206
+ .glass-card {
207
+ background: var(--bg-card);
208
+ border: 1px solid var(--border-card);
209
+ backdrop-filter: blur(16px);
210
+ -webkit-backdrop-filter: blur(16px);
211
+ border-radius: 16px;
212
+ padding: 2rem;
213
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
214
+ margin-bottom: 2rem;
215
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
216
+ }
217
+
218
+ .glass-card:hover {
219
+ border-color: rgba(var(--color-primary-rgb), 0.15);
220
+ }
221
+
222
+ .glass-card h2 {
223
+ font-size: 1.5rem;
224
+ font-weight: 700;
225
+ margin-bottom: 1.2rem;
226
+ color: #ffffff;
227
+ display: flex;
228
+ align-items: center;
229
+ gap: 0.5rem;
230
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
231
+ padding-bottom: 0.75rem;
232
+ }
233
+
234
+ .glass-card h2::before {
235
+ content: '';
236
+ display: inline-block;
237
+ width: 4px;
238
+ height: 1.25rem;
239
+ background: var(--gradient-main);
240
+ border-radius: 2px;
241
+ }
242
+
243
+ /* Grid layout */
244
+ .grid-2 {
245
+ display: grid;
246
+ grid-template-columns: 1fr 1fr;
247
+ gap: 1.5rem;
248
+ }
249
+
250
+ @media (max-width: 900px) {
251
+ .grid-2 {
252
+ grid-template-columns: 1fr;
253
+ }
254
+ }
255
+
256
+ /* Forms */
257
+ .form-group {
258
+ margin-bottom: 1.25rem;
259
+ }
260
+
261
+ .form-row {
262
+ display: grid;
263
+ grid-template-columns: 1fr 1fr;
264
+ gap: 1rem;
265
+ }
266
+
267
+ label {
268
+ display: block;
269
+ font-size: 0.85rem;
270
+ font-weight: 600;
271
+ color: var(--text-muted);
272
+ margin-bottom: 0.4rem;
273
+ }
274
+
275
+ input[type="text"], select, textarea {
276
+ width: 100%;
277
+ background: rgba(0, 0, 0, 0.4);
278
+ border: 1px solid var(--border-card);
279
+ border-radius: 8px;
280
+ color: var(--text-main);
281
+ padding: 0.75rem;
282
+ font-family: var(--font-sans);
283
+ font-size: 0.9rem;
284
+ transition: all 0.2s ease;
285
+ }
286
+
287
+ input[type="text"]:focus, select:focus, textarea:focus {
288
+ outline: none;
289
+ border-color: var(--color-primary);
290
+ box-shadow: 0 0 10px rgba(var(--color-primary-rgb), 0.15);
291
+ background: rgba(0, 0, 0, 0.6);
292
+ }
293
+
294
+ textarea {
295
+ font-family: var(--font-mono);
296
+ font-size: 0.85rem;
297
+ resize: vertical;
298
+ }
299
+
300
+ .btn {
301
+ background: rgba(255, 255, 255, 0.05);
302
+ border: 1px solid var(--border-card);
303
+ color: var(--text-main);
304
+ padding: 0.65rem 1.25rem;
305
+ border-radius: 8px;
306
+ font-weight: 600;
307
+ cursor: pointer;
308
+ font-family: var(--font-sans);
309
+ display: inline-flex;
310
+ align-items: center;
311
+ gap: 0.5rem;
312
+ transition: all 0.2s ease;
313
+ }
314
+
315
+ .btn:hover {
316
+ background: rgba(255, 255, 255, 0.1);
317
+ border-color: var(--text-muted);
318
+ }
319
+
320
+ .btn-primary {
321
+ background: var(--gradient-main);
322
+ color: var(--bg-dark);
323
+ border: none;
324
+ }
325
+
326
+ .btn-primary:hover {
327
+ opacity: 0.9;
328
+ transform: translateY(-1px);
329
+ box-shadow: 0 4px 12px rgba(var(--color-primary-rgb), 0.2);
330
+ }
331
+
332
+ /* Diagnostics list styling */
333
+ .diagnostic-panel {
334
+ font-family: var(--font-mono);
335
+ font-size: 0.85rem;
336
+ border-radius: 8px;
337
+ background: rgba(0, 0, 0, 0.4);
338
+ border: 1px solid var(--border-card);
339
+ padding: 1rem;
340
+ height: 250px;
341
+ overflow-y: auto;
342
+ }
343
+
344
+ .diagnostic-entry {
345
+ margin-bottom: 0.5rem;
346
+ border-left: 3px solid transparent;
347
+ padding-left: 0.6rem;
348
+ line-height: 1.4;
349
+ }
350
+
351
+ .diagnostic-entry.info {
352
+ border-color: var(--color-primary);
353
+ color: #93c5fd;
354
+ }
355
+
356
+ .diagnostic-entry.warning {
357
+ border-color: var(--color-warn);
358
+ color: #fde047;
359
+ }
360
+
361
+ .diagnostic-entry.error {
362
+ border-color: var(--color-danger);
363
+ color: #fda4af;
364
+ }
365
+
366
+ .diagnostic-entry.collision {
367
+ border-color: var(--color-secondary);
368
+ color: #f472b6;
369
+ }
370
+
371
+ /* Code Pane Display */
372
+ .code-container {
373
+ position: relative;
374
+ }
375
+
376
+ .code-pane {
377
+ background: #020617;
378
+ border: 1px solid var(--border-card);
379
+ border-radius: 8px;
380
+ padding: 1.2rem;
381
+ overflow-x: auto;
382
+ font-family: var(--font-mono);
383
+ font-size: 0.85rem;
384
+ color: #e2e8f0;
385
+ white-space: pre;
386
+ line-height: 1.5;
387
+ }
388
+
389
+ .copy-btn {
390
+ position: absolute;
391
+ top: 0.5rem;
392
+ right: 0.5rem;
393
+ background: rgba(255, 255, 255, 0.05);
394
+ border: 1px solid var(--border-card);
395
+ color: var(--text-muted);
396
+ font-size: 0.75rem;
397
+ padding: 0.25rem 0.5rem;
398
+ border-radius: 4px;
399
+ cursor: pointer;
400
+ transition: all 0.2s ease;
401
+ }
402
+
403
+ .copy-btn:hover {
404
+ color: var(--text-main);
405
+ background: rgba(255, 255, 255, 0.1);
406
+ }
407
+
408
+ /* Table styles */
409
+ table {
410
+ width: 100%;
411
+ border-collapse: collapse;
412
+ margin-bottom: 1.5rem;
413
+ font-size: 0.9rem;
414
+ }
415
+
416
+ th, td {
417
+ padding: 0.75rem 1rem;
418
+ text-align: left;
419
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
420
+ }
421
+
422
+ th {
423
+ font-weight: 700;
424
+ color: var(--color-primary);
425
+ text-transform: uppercase;
426
+ font-size: 0.75rem;
427
+ letter-spacing: 0.05em;
428
+ }
429
+
430
+ tr:hover td {
431
+ background: rgba(255, 255, 255, 0.02);
432
+ }
433
+
434
+ /* Precedence tiers indicator colors */
435
+ .prec-60 { color: var(--color-primary); font-weight: 600; }
436
+ .prec-50 { color: var(--color-accent); font-weight: 600; }
437
+ .prec-40 { color: var(--color-warn); }
438
+ .prec-30 { color: #3b82f6; }
439
+ .prec-20 { color: #a855f7; }
440
+ .prec-10 { color: var(--text-dark); }
441
+
442
+ /* SVG Diagram Enhancements */
443
+ .flowchart-svg {
444
+ background: rgba(10, 15, 28, 0.5);
445
+ border: 1px solid var(--border-card);
446
+ border-radius: 12px;
447
+ padding: 1rem;
448
+ box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.5);
449
+ margin-top: 1rem;
450
+ }
451
+
452
+ .svg-node {
453
+ transition: all 0.3s ease;
454
+ cursor: pointer;
455
+ }
456
+
457
+ .svg-node:hover rect, .svg-node.active rect {
458
+ stroke: var(--color-primary);
459
+ fill: rgba(0, 240, 255, 0.1);
460
+ filter: drop-shadow(0 0 6px rgba(0, 240, 255, 0.4));
461
+ }
462
+
463
+ .svg-edge-path {
464
+ stroke-dasharray: 1000;
465
+ stroke-dashoffset: 1000;
466
+ animation: dash 10s linear infinite;
467
+ }
468
+
469
+ @keyframes dash {
470
+ to {
471
+ stroke-dashoffset: 0;
472
+ }
473
+ }
474
+
475
+ .flow-info-box {
476
+ margin-top: 1rem;
477
+ padding: 1rem;
478
+ background: rgba(255, 255, 255, 0.03);
479
+ border: 1px dashed var(--border-card);
480
+ border-radius: 8px;
481
+ font-size: 0.9rem;
482
+ min-height: 80px;
483
+ }
484
+
485
+ /* Virtual Files Explorer CSS */
486
+ .vfile-explorer {
487
+ display: grid;
488
+ grid-template-columns: 280px 1fr;
489
+ border: 1px solid var(--border-card);
490
+ border-radius: 8px;
491
+ overflow: hidden;
492
+ height: 480px;
493
+ }
494
+
495
+ .vfile-sidebar {
496
+ background: rgba(0, 0, 0, 0.3);
497
+ border-right: 1px solid var(--border-card);
498
+ display: flex;
499
+ flex-direction: column;
500
+ }
501
+
502
+ .vfile-sidebar-header {
503
+ padding: 0.75rem 1rem;
504
+ border-bottom: 1px solid var(--border-card);
505
+ display: flex;
506
+ justify-content: space-between;
507
+ align-items: center;
508
+ font-weight: 700;
509
+ font-size: 0.8rem;
510
+ text-transform: uppercase;
511
+ letter-spacing: 0.05em;
512
+ color: var(--text-muted);
513
+ }
514
+
515
+ .vfile-list {
516
+ flex: 1;
517
+ overflow-y: auto;
518
+ padding: 0.5rem 0;
519
+ }
520
+
521
+ .vfile-item {
522
+ padding: 0.5rem 1rem;
523
+ font-family: var(--font-mono);
524
+ font-size: 0.8rem;
525
+ display: flex;
526
+ align-items: center;
527
+ justify-content: space-between;
528
+ cursor: pointer;
529
+ color: var(--text-muted);
530
+ transition: all 0.2s ease;
531
+ }
532
+
533
+ .vfile-item:hover {
534
+ background: rgba(255, 255, 255, 0.04);
535
+ color: var(--text-main);
536
+ }
537
+
538
+ .vfile-item.active {
539
+ background: rgba(var(--color-primary-rgb), 0.15);
540
+ border-left: 3px solid var(--color-primary);
541
+ color: var(--text-main);
542
+ }
543
+
544
+ .vfile-item-actions {
545
+ opacity: 0;
546
+ transition: opacity 0.2s ease;
547
+ }
548
+
549
+ .vfile-item:hover .vfile-item-actions {
550
+ opacity: 1;
551
+ }
552
+
553
+ .vfile-action-btn {
554
+ background: transparent;
555
+ border: none;
556
+ color: var(--text-dark);
557
+ cursor: pointer;
558
+ padding: 0 0.2rem;
559
+ }
560
+
561
+ .vfile-action-btn:hover {
562
+ color: var(--color-danger);
563
+ }
564
+
565
+ .vfile-editor-area {
566
+ display: flex;
567
+ flex-direction: column;
568
+ height: 100%;
569
+ }
570
+
571
+ .vfile-editor-header {
572
+ padding: 0.75rem 1rem;
573
+ background: rgba(0, 0, 0, 0.2);
574
+ border-bottom: 1px solid var(--border-card);
575
+ font-family: var(--font-mono);
576
+ font-size: 0.8rem;
577
+ display: flex;
578
+ justify-content: space-between;
579
+ align-items: center;
580
+ }
581
+
582
+ .vfile-editor-textarea {
583
+ flex: 1;
584
+ border: none;
585
+ border-radius: 0;
586
+ background: #020617;
587
+ padding: 1rem;
588
+ font-family: var(--font-mono);
589
+ font-size: 0.85rem;
590
+ color: #e2e8f0;
591
+ height: 100%;
592
+ }
593
+
594
+ .vfile-editor-textarea:focus {
595
+ border: none;
596
+ box-shadow: none;
597
+ background: #020617;
598
+ }
599
+
600
+ /* Template selectors */
601
+ .template-selector {
602
+ display: flex;
603
+ gap: 0.5rem;
604
+ margin-bottom: 1rem;
605
+ }
606
+
607
+ .template-btn {
608
+ background: rgba(255, 255, 255, 0.04);
609
+ border: 1px solid var(--border-card);
610
+ color: var(--text-muted);
611
+ font-size: 0.75rem;
612
+ padding: 0.4rem 0.8rem;
613
+ border-radius: 6px;
614
+ cursor: pointer;
615
+ transition: all 0.2s ease;
616
+ }
617
+
618
+ .template-btn:hover, .template-btn.active {
619
+ color: var(--color-primary);
620
+ border-color: rgba(var(--color-primary-rgb), 0.3);
621
+ background: rgba(var(--color-primary-rgb), 0.05);
622
+ }
623
+
624
+ .action-row {
625
+ display: flex;
626
+ justify-content: space-between;
627
+ align-items: center;
628
+ margin-top: 1rem;
629
+ }
630
+
631
+ /* Precedence table badge */
632
+ .badge {
633
+ display: inline-block;
634
+ padding: 0.15rem 0.45rem;
635
+ border-radius: 4px;
636
+ font-size: 0.75rem;
637
+ font-weight: 700;
638
+ text-transform: uppercase;
639
+ font-family: var(--font-sans);
640
+ }
641
+
642
+ .badge-user {
643
+ background: rgba(59, 130, 246, 0.15);
644
+ color: #93c5fd;
645
+ border: 1px solid rgba(59, 130, 246, 0.3);
646
+ }
647
+
648
+ .badge-project {
649
+ background: rgba(16, 185, 129, 0.15);
650
+ color: #a7f3d0;
651
+ border: 1px solid rgba(16, 185, 129, 0.3);
652
+ }
653
+
654
+ .badge-package {
655
+ background: rgba(139, 92, 246, 0.15);
656
+ color: #ddd6fe;
657
+ border: 1px solid rgba(139, 92, 246, 0.3);
658
+ }
659
+
660
+ .badge-cli {
661
+ background: rgba(239, 68, 68, 0.15);
662
+ color: #fecaca;
663
+ border: 1px solid rgba(239, 68, 68, 0.3);
664
+ }
665
+ </style>
666
+ </head>
667
+ <body>
668
+
669
+ <div class="container">
670
+ <header>
671
+ <div class="header-left">
672
+ <div class="header-logo">
673
+ <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>
674
+ </div>
675
+ <div class="header-title-wrapper">
676
+ <h1>Extensions & Custom Skills Spec</h1>
677
+ <p>Architectural design and verification testing suite for Clio Coder's resource packaging, registries injection, and sharing archive subsystems.</p>
678
+ <div class="meta-chips-row">
679
+ <span class="chip">Source: docs/extensions-and-sharing.md</span>
680
+ <span class="chip chip-orange">clio-coder docs extensions</span>
681
+ </div>
682
+ </div>
683
+ </div>
684
+ <div class="header-right">
685
+ <span class="version-badge">Clio Coder v0.3.0</span>
686
+ <a href="index.html" class="back-btn">
687
+ <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>
688
+ Dashboard Hub
689
+ </a>
690
+ </div>
691
+ </header>
692
+
693
+
694
+ <!-- Navigation Tabs -->
695
+ <div class="tabs-nav">
696
+ <button type="button" class="tab-btn active" onclick="_switchTab(event, 'tab-overview')">Subsystem Overview</button>
697
+ <button type="button" class="tab-btn" onclick="_switchTab(event, 'tab-architecture')">Workflows & Architectures</button>
698
+ <button type="button" class="tab-btn" onclick="_switchTab(event, 'tab-builder')">Manifest Builder</button>
699
+ <button type="button" class="tab-btn" onclick="_switchTab(event, 'tab-validator')">Structure Validator Sandbox</button>
700
+ <button type="button" class="tab-btn" onclick="_switchTab(event, 'tab-sharer')">Share Archive Simulator</button>
701
+ </div>
702
+
703
+ <!-- TAB: Overview -->
704
+ <div id="tab-overview" class="tab-content active">
705
+ <div class="glass-card">
706
+ <h2>Resource Precedence & Scoping Hierarchy</h2>
707
+ <p style="margin-bottom: 1rem;">Clio Coder resolves resource conflicts deterministically using ranked precedence tiers. Native project configurations outrank user configurations, which outrank compatibility layers and package-contributed roots.</p>
708
+
709
+ <h3>Prompts Precedence Tiering</h3>
710
+ <table>
711
+ <thead>
712
+ <tr>
713
+ <th>Rank</th>
714
+ <th>Scope</th>
715
+ <th>Origin Source</th>
716
+ <th>Default Directory Path</th>
717
+ </tr>
718
+ </thead>
719
+ <tbody>
720
+ <tr>
721
+ <td><span class="prec-10">0</span></td>
722
+ <td><span class="badge badge-package">package</span></td>
723
+ <td>Enabled extension resource directories</td>
724
+ <td><code>&lt;configDir&gt;/extensions/&lt;id&gt;/prompts</code></td>
725
+ </tr>
726
+ <tr>
727
+ <td><span class="prec-30">1</span></td>
728
+ <td><span class="badge badge-user">user</span></td>
729
+ <td>Clio User Prompts Folder</td>
730
+ <td><code>~/.config/clio-coder/prompts</code></td>
731
+ </tr>
732
+ <tr>
733
+ <td><span class="prec-50">2</span></td>
734
+ <td><span class="badge badge-project">project</span></td>
735
+ <td>Clio Project Local Prompts Folder</td>
736
+ <td><code>.clio-coder/prompts</code></td>
737
+ </tr>
738
+ <tr>
739
+ <td><span class="prec-60">3</span></td>
740
+ <td><span class="badge badge-cli">cli</span></td>
741
+ <td>Call-site Injected Templates</td>
742
+ <td>Direct inline strings or temporary buffers</td>
743
+ </tr>
744
+ </tbody>
745
+ </table>
746
+
747
+ <h3 style="margin-top: 2rem;">Skills Precedence Tiering</h3>
748
+ <p style="font-size: 0.9rem; color: var(--text-muted); margin-bottom: 1rem;">Skills add Agent Skills compatibility roots, allowing shared access across various agent frameworks. Native Clio folders outrank compatibility ones at the same scope.</p>
749
+ <table>
750
+ <thead>
751
+ <tr>
752
+ <th>Precedence</th>
753
+ <th>Scope</th>
754
+ <th>Agent Category</th>
755
+ <th>Standard Directory Path</th>
756
+ <th>Model Visibility</th>
757
+ </tr>
758
+ </thead>
759
+ <tbody>
760
+ <tr>
761
+ <td><span class="prec-10">10</span></td>
762
+ <td><span class="badge badge-package">package</span></td>
763
+ <td>Extension</td>
764
+ <td><code>&lt;configDir&gt;/extensions/&lt;id&gt;/skills</code></td>
765
+ <td>Visible (if enabled)</td>
766
+ </tr>
767
+ <tr>
768
+ <td><span class="prec-20">20</span></td>
769
+ <td><span class="badge badge-user">user</span></td>
770
+ <td>Compatibility (agents/claude/codex/etc.)</td>
771
+ <td><code>~/.agents/skills</code>, <code>~/.claude/skills</code>, etc.</td>
772
+ <td>Visible</td>
773
+ </tr>
774
+ <tr>
775
+ <td><span class="prec-30">30</span></td>
776
+ <td><span class="badge badge-user">user</span></td>
777
+ <td>Clio Native User</td>
778
+ <td><code>~/.config/clio-coder/skills</code></td>
779
+ <td>Visible</td>
780
+ </tr>
781
+ <tr>
782
+ <td><span class="prec-40">40</span></td>
783
+ <td><span class="badge badge-project">project</span></td>
784
+ <td>Compatibility (agents/claude/codex/etc.)</td>
785
+ <td><code>.agents/skills</code>, <code>.codex/skills</code>, etc.</td>
786
+ <td>Untrusted by default (requires opt-in)</td>
787
+ </tr>
788
+ <tr>
789
+ <td><span class="prec-50">50</span></td>
790
+ <td><span class="badge badge-project">project</span></td>
791
+ <td>Clio Native Project</td>
792
+ <td><code>.clio-coder/skills</code></td>
793
+ <td>Visible</td>
794
+ </tr>
795
+ <tr>
796
+ <td><span class="prec-60">60</span></td>
797
+ <td><span class="badge badge-cli">cli</span></td>
798
+ <td>Explicit Paths</td>
799
+ <td>CLI parameter <code>--skill &lt;path&gt;</code></td>
800
+ <td>Visible (Forced injection)</td>
801
+ </tr>
802
+ </tbody>
803
+ </table>
804
+ </div>
805
+
806
+ <div class="grid-2">
807
+ <div class="glass-card">
808
+ <h2>Extension Package Layout</h2>
809
+ <p style="margin-bottom: 1rem; font-size: 0.95rem;">Extension roots package reusable skills and prompts. The layout follows standard modular separation:</p>
810
+ <pre class="code-pane" style="font-size:0.8rem;">
811
+ clio-kit/ # Ext package root
812
+ clio-coder-extension.yaml # Package manifest
813
+ prompts/ # Contributed prompt templates
814
+ hdf5-fix.md
815
+ skills/ # Contributed custom skills
816
+ scientific-audit/
817
+ SKILL.md # Standard skill md
818
+ scripts/ # Custom auxiliary scripts
819
+ references/ # References files
820
+ </pre>
821
+ </div>
822
+ <div class="glass-card">
823
+ <h2>Diagnostics & Safety</h2>
824
+ <p style="margin-bottom: 0.75rem; font-size:0.95rem;"><strong>Untrusted project roots:</strong> Shared local project compatibility roots (like <code>.agents/skills</code>) are deactivated by default to prevent arbitrary code/instruction injections. Opt-in is configured via <code>skills.trustProjectCompatRoots: true</code> in <code>settings.yaml</code> or setting the environment variable <code>CLIO_CODER_TRUST_PROJECT_SKILLS=1</code>.</p>
825
+ <p style="font-size:0.95rem;"><strong>Graceful Degradations:</strong> Only a missing <code>description</code> inside a skill frontmatter is a hard rejection. All other validation anomalies (consecutive hyphens in names, name-directory mismatches, frontmatter format failures) degrade to warnings, enabling the skill or template to still load with diagnostics.</p>
826
+ </div>
827
+ </div>
828
+ </div>
829
+
830
+ <!-- TAB: Architecture and Workflows -->
831
+ <div id="tab-architecture" class="tab-content">
832
+ <div class="glass-card">
833
+ <h2>Extension Resolution Workflow</h2>
834
+ <p class="subtitle">Scans user and project extensions, parses manifest metadata, looks up status in state files, and implements shadowing override logic (Project scope outranks User scope).</p>
835
+
836
+ <svg aria-hidden="true" class="flowchart-svg" viewBox="0 0 900 280" width="100%"><title>Icon</title>
837
+ <defs>
838
+ <marker id="arrow" viewBox="0 0 10 10" refX="6" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
839
+ <path d="M 0 0 L 10 5 L 0 10 z" fill="#00f0ff" />
840
+ </marker>
841
+ </defs>
842
+
843
+ <!-- Column 1: Scans -->
844
+ <g class="svg-node" id="node-res-scan" onclick="_showFlowInfo('resolution', 'scan')">
845
+ <rect x="30" y="70" width="160" height="60" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
846
+ <text x="110" y="95" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Scan Extension Roots</text>
847
+ <text x="110" y="115" fill="var(--color-primary)" font-size="10" font-family="var(--font-mono)" text-anchor="middle">~/.config/ & .clio-coder/</text>
848
+ </g>
849
+
850
+ <!-- Column 2: Manifest -->
851
+ <g class="svg-node" id="node-res-manifest" onclick="_showFlowInfo('resolution', 'manifest')">
852
+ <rect x="240" y="70" width="160" height="60" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
853
+ <text x="320" y="95" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Parse manifests</text>
854
+ <text x="320" y="115" fill="#bd00ff" font-size="10" font-family="var(--font-mono)" text-anchor="middle">clio-coder-extension.yaml</text>
855
+ </g>
856
+
857
+ <!-- Column 3: State check -->
858
+ <g class="svg-node" id="node-res-state" onclick="_showFlowInfo('resolution', 'state')">
859
+ <rect x="450" y="70" width="160" height="60" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
860
+ <text x="530" y="95" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Status Filter Check</text>
861
+ <text x="530" y="115" fill="var(--color-warn)" font-size="10" font-family="var(--font-mono)" text-anchor="middle">state.json disabled[]</text>
862
+ </g>
863
+
864
+ <!-- Column 4: Shadow Override -->
865
+ <g class="svg-node" id="node-res-shadow" onclick="_showFlowInfo('resolution', 'shadow')">
866
+ <rect x="660" y="70" width="180" height="60" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
867
+ <text x="750" y="95" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Deduplicate & Override</text>
868
+ <text x="750" y="115" fill="var(--color-accent)" font-size="10" font-family="var(--font-mono)" text-anchor="middle">Project shadows User</text>
869
+ </g>
870
+
871
+ <!-- Bottom: Resource Injection -->
872
+ <g class="svg-node" id="node-res-inject" onclick="_showFlowInfo('resolution', 'inject')">
873
+ <rect x="340" y="190" width="220" height="60" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
874
+ <text x="450" y="215" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Resource Path Injection</text>
875
+ <text x="450" y="235" fill="var(--color-primary)" font-size="10" font-family="var(--font-mono)" text-anchor="middle">Feed Prompts & Skills Roots</text>
876
+ </g>
877
+
878
+ <!-- Paths / Connections -->
879
+ <path d="M 190 100 L 232 100" fill="none" stroke="#00f0ff" stroke-width="2" marker-end="url(#arrow)" class="svg-edge-path" />
880
+ <path d="M 400 100 L 442 100" fill="none" stroke="#00f0ff" stroke-width="2" marker-end="url(#arrow)" class="svg-edge-path" />
881
+ <path d="M 610 100 L 652 100" fill="none" stroke="#00f0ff" stroke-width="2" marker-end="url(#arrow)" class="svg-edge-path" />
882
+ <path d="M 750 130 L 750 160 L 450 160 L 450 182" fill="none" stroke="#bd00ff" stroke-width="2" marker-end="url(#arrow)" />
883
+ </svg>
884
+ <div id="flow-resolution-info" class="flow-info-box">
885
+ <em>Click on any workflow step node above to view technical integration details.</em>
886
+ </div>
887
+ </div>
888
+
889
+ <div class="glass-card">
890
+ <h2>Skill Registry Injection & Collision Resolution</h2>
891
+ <p class="subtitle">Scans multiple native and third-party compatibility folders, parses frontmatters, executes path-canonicalization checks, and handles identical namespace overrides by precedence ranks.</p>
892
+
893
+ <svg aria-hidden="true" class="flowchart-svg" viewBox="0 0 900 320" width="100%"><title>Icon</title>
894
+ <!-- Column 1: Roots -->
895
+ <g class="svg-node" id="node-skill-roots" onclick="_showFlowInfo('skill', 'roots')">
896
+ <rect x="30" y="90" width="160" height="90" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
897
+ <text x="110" y="115" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Collect Skill Roots</text>
898
+ <text x="110" y="135" fill="var(--color-primary)" font-size="9" font-family="var(--font-mono)" text-anchor="middle">6 Scopes (CLI down to</text>
899
+ <text x="110" y="150" fill="var(--color-primary)" font-size="9" font-family="var(--font-mono)" text-anchor="middle">Package extension)</text>
900
+ </g>
901
+
902
+ <!-- Column 2: Parser & Hashing -->
903
+ <g class="svg-node" id="node-skill-parse" onclick="_showFlowInfo('skill', 'parse')">
904
+ <rect x="240" y="90" width="160" height="90" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
905
+ <text x="320" y="115" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Read & Hash</text>
906
+ <text x="320" y="135" fill="#bd00ff" font-size="9" font-family="var(--font-mono)" text-anchor="middle">Verify YAML object</text>
907
+ <text x="320" y="150" fill="#bd00ff" font-size="9" font-family="var(--font-mono)" text-anchor="middle">SHA-256 raw file hash</text>
908
+ </g>
909
+
910
+ <!-- Column 3: Precedence Comparator -->
911
+ <g class="svg-node" id="node-skill-precedence" onclick="_showFlowInfo('skill', 'precedence')">
912
+ <rect x="450" y="90" width="160" height="90" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
913
+ <text x="530" y="115" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Collision Resolver</text>
914
+ <text x="530" y="135" fill="var(--color-warn)" font-size="9" font-family="var(--font-mono)" text-anchor="middle">Sort by Precedence</text>
915
+ <text x="530" y="150" fill="var(--color-warn)" font-size="9" font-family="var(--font-mono)" text-anchor="middle">Tiebreaker: File Path</text>
916
+ </g>
917
+
918
+ <!-- Column 4: Registry injection -->
919
+ <g class="svg-node" id="node-skill-inject" onclick="_showFlowInfo('skill', 'inject')">
920
+ <rect x="660" y="90" width="180" height="90" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
921
+ <text x="750" y="115" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Catalog Integration</text>
922
+ <text x="750" y="135" fill="var(--color-accent)" font-size="9" font-family="var(--font-mono)" text-anchor="middle">Assemble hashes &</text>
923
+ <text x="750" y="150" fill="var(--color-accent)" font-size="9" font-family="var(--font-mono)" text-anchor="middle">publish catalog_hash</text>
924
+ </g>
925
+
926
+ <!-- Paths / Connections -->
927
+ <path d="M 190 135 L 232 135" fill="none" stroke="#00f0ff" stroke-width="2" marker-end="url(#arrow)" class="svg-edge-path" />
928
+ <path d="M 400 135 L 442 135" fill="none" stroke="#00f0ff" stroke-width="2" marker-end="url(#arrow)" class="svg-edge-path" />
929
+ <path d="M 610 135 L 652 135" fill="none" stroke="#00f0ff" stroke-width="2" marker-end="url(#arrow)" class="svg-edge-path" />
930
+ </svg>
931
+ <div id="flow-skill-info" class="flow-info-box">
932
+ <em>Click on any workflow step node above to view technical integration details.</em>
933
+ </div>
934
+ </div>
935
+
936
+ <div class="glass-card">
937
+ <h2>Share Archive Export / Import Workflow</h2>
938
+ <p class="subtitle">Moves resources across scopes and systems, verifying format versions, re-checking data hashes, generating import dry-runs, and merging settings.</p>
939
+
940
+ <svg aria-hidden="true" class="flowchart-svg" viewBox="0 0 900 280" width="100%"><title>Icon</title>
941
+ <!-- Column 1: Import file -->
942
+ <g class="svg-node" id="node-share-file" onclick="_showFlowInfo('share', 'file')">
943
+ <rect x="30" y="70" width="160" height="60" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
944
+ <text x="110" y="95" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Read Share Archive</text>
945
+ <text x="110" y="115" fill="var(--color-primary)" font-size="10" font-family="var(--font-mono)" text-anchor="middle">JSON format verify</text>
946
+ </g>
947
+
948
+ <!-- Column 2: Checksum check -->
949
+ <g class="svg-node" id="node-share-checksum" onclick="_showFlowInfo('share', 'checksum')">
950
+ <rect x="240" y="70" width="160" height="60" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
951
+ <text x="320" y="95" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Checksum validation</text>
952
+ <text x="320" y="115" fill="var(--color-warn)" font-size="10" font-family="var(--font-mono)" text-anchor="middle">SHA-256 mismatch block</text>
953
+ </g>
954
+
955
+ <!-- Column 3: Plan action -->
956
+ <g class="svg-node" id="node-share-plan" onclick="_showFlowInfo('share', 'plan')">
957
+ <rect x="450" y="70" width="160" height="60" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
958
+ <text x="530" y="95" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Import dry-run plan</text>
959
+ <text x="530" y="115" fill="var(--color-warn)" font-size="10" font-family="var(--font-mono)" text-anchor="middle">Skip/write/overwrite</text>
960
+ </g>
961
+
962
+ <!-- Column 4: Commit settings merge -->
963
+ <g class="svg-node" id="node-share-commit" onclick="_showFlowInfo('share', 'commit')">
964
+ <rect x="660" y="70" width="180" height="60" rx="8" fill="rgba(17,24,39,0.9)" stroke="rgba(255,255,255,0.1)" stroke-width="1.5" />
965
+ <text x="750" y="95" fill="#fff" font-size="12" font-weight="700" text-anchor="middle">Commit transaction</text>
966
+ <text x="750" y="115" fill="var(--color-accent)" font-size="10" font-family="var(--font-mono)" text-anchor="middle">Write files & merge fragment</text>
967
+ </g>
968
+
969
+ <!-- Paths / Connections -->
970
+ <path d="M 190 100 L 232 100" fill="none" stroke="#00f0ff" stroke-width="2" marker-end="url(#arrow)" class="svg-edge-path" />
971
+ <path d="M 400 100 L 442 100" fill="none" stroke="#00f0ff" stroke-width="2" marker-end="url(#arrow)" class="svg-edge-path" />
972
+ <path d="M 610 100 L 652 100" fill="none" stroke="#00f0ff" stroke-width="2" marker-end="url(#arrow)" class="svg-edge-path" />
973
+ </svg>
974
+ <div id="flow-share-info" class="flow-info-box">
975
+ <em>Click on any workflow step node above to view technical integration details.</em>
976
+ </div>
977
+ </div>
978
+ </div>
979
+
980
+ <!-- TAB: Manifest Builder -->
981
+ <div id="tab-builder" class="tab-content">
982
+ <div class="glass-card">
983
+ <h2>Interactive Manifest Builder</h2>
984
+ <p class="subtitle">Interactively construct and validate a package manifest configuration for a custom Clio Coder extension. Generates standard YAML/JSON outputs in real-time.</p>
985
+
986
+ <div class="grid-2">
987
+ <!-- Form controls -->
988
+ <div>
989
+ <div class="form-row">
990
+ <div class="form-group">
991
+ <label for="mb-id">Extension ID (Lowercase, dots/underscores/hyphens)</label>
992
+ <input type="text" id="mb-id" value="scientist-helper" oninput="generateManifest()">
993
+ </div>
994
+ <div class="form-group">
995
+ <label for="mb-name">Display Name (defaults to ID if empty)</label>
996
+ <input type="text" id="mb-name" value="Scientist Helper Pack" oninput="generateManifest()">
997
+ </div>
998
+ </div>
999
+
1000
+ <div class="form-row">
1001
+ <div class="form-group">
1002
+ <label for="mb-version">Version</label>
1003
+ <input type="text" id="mb-version" value="1.0.0" oninput="generateManifest()">
1004
+ </div>
1005
+ <div class="form-group">
1006
+ <label for="mb-clio-compat">Clio Compatibility Constraint</label>
1007
+ <input type="text" id="mb-clio-compat" value=">=0.2.0" oninput="generateManifest()">
1008
+ </div>
1009
+ </div>
1010
+
1011
+ <div class="form-group">
1012
+ <label for="mb-desc">Description</label>
1013
+ <textarea id="mb-desc" rows="2" oninput="generateManifest()">Custom helper prompts and skills designed for high performance computing simulations.</textarea>
1014
+ </div>
1015
+
1016
+ <div class="form-row">
1017
+ <div class="form-group">
1018
+ <label for="mb-prompts">Prompts Folder Path</label>
1019
+ <input type="text" id="mb-prompts" value="prompts" oninput="generateManifest()">
1020
+ </div>
1021
+ <div class="form-group">
1022
+ <label for="mb-skills">Skills Folder Path</label>
1023
+ <input type="text" id="mb-skills" value="skills" oninput="generateManifest()">
1024
+ </div>
1025
+ </div>
1026
+
1027
+ <div class="form-row">
1028
+ <div class="form-group">
1029
+ <label for="mb-tools">Allowed Tools (Comma-separated)</label>
1030
+ <input type="text" id="mb-tools" value="Read, Grep, run_command" oninput="generateManifest()">
1031
+ </div>
1032
+ <div class="form-group">
1033
+ <label for="mb-settings">Settings Contributed (Comma-separated)</label>
1034
+ <input type="text" id="mb-settings" value="autonomy" oninput="generateManifest()">
1035
+ </div>
1036
+ </div>
1037
+
1038
+ <div class="form-group">
1039
+ <label>Output Format</label>
1040
+ <select id="mb-format" onchange="generateManifest()">
1041
+ <option value="yaml">YAML Format (clio-coder-extension.yaml)</option>
1042
+ <option value="json">JSON Format (clio-coder-extension.json)</option>
1043
+ </select>
1044
+ </div>
1045
+ </div>
1046
+
1047
+ <!-- Code Outputs -->
1048
+ <div>
1049
+ <label>Live Manifest Output</label>
1050
+ <div class="code-container">
1051
+ <button type="button" class="copy-btn" onclick="_copyManifestContent()">Copy</button>
1052
+ <pre class="code-pane" id="mb-code-output" style="height: 330px;">Loading manifest generator...</pre>
1053
+ </div>
1054
+
1055
+ <label style="margin-top: 1rem;">Live Validation Diagnostics</label>
1056
+ <div class="diagnostic-panel" id="mb-diagnostics-panel" style="height: 120px;">
1057
+ No diagnostics compiled.
1058
+ </div>
1059
+ </div>
1060
+ </div>
1061
+ </div>
1062
+ </div>
1063
+
1064
+ <!-- TAB: Structure Validator Sandbox -->
1065
+ <div id="tab-validator" class="tab-content">
1066
+ <div class="glass-card">
1067
+ <h2>Extension Package Sandbox & Resource Compiler Validator</h2>
1068
+ <p class="subtitle">Paste or edit files in a simulated directory tree representing a custom extension package. Runs the absolute Clio validation suite in real-time in the browser.</p>
1069
+
1070
+ <div class="template-selector">
1071
+ <button type="button" class="template-btn active" id="btn-tpl-hpc" onclick="loadVirtualTemplate('hpc')">HPC Pack (Valid)</button>
1072
+ <button type="button" class="template-btn" id="btn-tpl-invalid" onclick="loadVirtualTemplate('invalid')">Broken Frontmatter & Format (Warnings)</button>
1073
+ <button type="button" class="template-btn" id="btn-tpl-collision" onclick="loadVirtualTemplate('collision')">Duplicate Names (Collision)</button>
1074
+ </div>
1075
+
1076
+ <div class="vfile-explorer">
1077
+ <!-- Sidebar: File Tree -->
1078
+ <div class="vfile-sidebar">
1079
+ <div class="vfile-sidebar-header">
1080
+ <span>Files Tree</span>
1081
+ <button type="button" class="btn" style="padding: 0.15rem 0.4rem; font-size: 0.75rem;" onclick="_addVirtualFilePrompt()">+ New File</button>
1082
+ </div>
1083
+ <div class="vfile-list" id="vfile-list-container">
1084
+ <!-- Dynamically populated -->
1085
+ </div>
1086
+ </div>
1087
+
1088
+ <!-- Main: Content Editor -->
1089
+ <div class="vfile-editor-area">
1090
+ <div class="vfile-editor-header">
1091
+ <span id="vfile-current-name">clio-coder-extension.yaml</span>
1092
+ <span style="color: var(--text-dark); font-size:0.75rem;">Modify content below to trigger live compilation validation</span>
1093
+ </div>
1094
+ <textarea class="vfile-editor-textarea" id="vfile-editor-box" oninput="_updateCurrentVirtualFileContent()"></textarea>
1095
+ </div>
1096
+ </div>
1097
+
1098
+ <div class="action-row">
1099
+ <button type="button" class="btn btn-primary" onclick="runPackageValidation()">Run Validation Suite</button>
1100
+ <span style="color: var(--text-muted); font-size:0.85rem;" id="validation-time-log">Modified files sync automatically. Click compile to parse.</span>
1101
+ </div>
1102
+
1103
+ <h3 style="margin-top: 2rem; margin-bottom: 0.5rem;">Compilation Diagnostics Panel</h3>
1104
+ <div class="diagnostic-panel" id="val-diagnostics-output" style="height: 180px;">
1105
+ Click "Run Validation Suite" to compile files tree.
1106
+ </div>
1107
+ </div>
1108
+ </div>
1109
+
1110
+ <!-- TAB: Sharing Archive Simulator -->
1111
+ <div id="tab-sharer" class="tab-content">
1112
+ <div class="glass-card">
1113
+ <h2>Sharing Archive Inspect & Dry-Run Planner</h2>
1114
+ <p class="subtitle">Validates simulated <code>.clio-coder-share.json</code> export structures and calculates import dry-runs mapping to native user/project file paths, including conflict detections.</p>
1115
+
1116
+ <div class="grid-2">
1117
+ <!-- Left: JSON representation -->
1118
+ <div>
1119
+ <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.4rem;">
1120
+ <label style="margin-bottom:0;">Archive Content JSON</label>
1121
+ <button type="button" class="btn" style="padding:0.2rem 0.5rem; font-size:0.75rem;" onclick="_generateShareArchiveFromSandbox()">Generate from Sandbox</button>
1122
+ </div>
1123
+ <div class="code-container">
1124
+ <textarea id="share-json-editor" rows="18" style="font-family:var(--font-mono); font-size:0.8rem; height: 350px;">{
1125
+ "kind": "clio-share-archive",
1126
+ "formatVersion": 1,
1127
+ "manifest": {
1128
+ "format": "clio.share.v1",
1129
+ "clioVersion": "0.3.0",
1130
+ "createdAt": "2026-06-06T17:53:00Z",
1131
+ "files": [
1132
+ {
1133
+ "type": "project-context",
1134
+ "scope": "project",
1135
+ "archivePath": "project/CLIO-CODER.md",
1136
+ "relativePath": "CLIO-CODER.md",
1137
+ "sha256": "4b684bc5e171b3e945c92984534125aa30164c676643de5847e62a04873c3325",
1138
+ "size": 182
1139
+ },
1140
+ {
1141
+ "type": "prompt",
1142
+ "scope": "user",
1143
+ "archivePath": "user/prompts/refactor.md",
1144
+ "relativePath": "refactor.md",
1145
+ "sha256": "843818e6978438db29239843a908cf8f7f7a7da09f0dfbe98471e9882260ef9a",
1146
+ "size": 195
1147
+ },
1148
+ {
1149
+ "type": "settings",
1150
+ "scope": "user",
1151
+ "archivePath": "settings.fragment.yaml",
1152
+ "relativePath": "settings.fragment.yaml",
1153
+ "sha256": "fb6305a4155f9a7db8e96bf38ea2d1c67ea95759efc9ff28ba1207e382b6b553",
1154
+ "size": 120
1155
+ }
1156
+ ]
1157
+ },
1158
+ "files": [
1159
+ {
1160
+ "type": "project-context",
1161
+ "scope": "project",
1162
+ "archivePath": "project/CLIO-CODER.md",
1163
+ "relativePath": "CLIO-CODER.md",
1164
+ "sha256": "4b684bc5e171b3e945c92984534125aa30164c676643de5847e62a04873c3325",
1165
+ "size": 182,
1166
+ "encoding": "base64",
1167
+ "data": "IyBDTElPIENPREVSIENPTlRFWFQKClRoaXMgcmVwb3NpdG9yeSBjb250YWlucyBjb2RlIGZvciBIUEMgc2ltdWxhdGlvbnMu"
1168
+ },
1169
+ {
1170
+ "type": "prompt",
1171
+ "scope": "user",
1172
+ "archivePath": "user/prompts/refactor.md",
1173
+ "relativePath": "refactor.md",
1174
+ "sha256": "843818e6978438db29239843a908cf8f7f7a7da09f0dfbe98471e9882260ef9a",
1175
+ "size": 195,
1176
+ "encoding": "base64",
1177
+ "data": "LS0tCmRlc2NyaXB0aW9uOiBSZWZhY3RvciBhIGZ1bmN0aW9uCmFyZ3VtZW50LWhpbnQ6ICI8ZnVuY3Rpb25fa2V5PiIKLS0tCgpSZWZhY3RvciB0aGlzIG1vZHVsZSBhY2NvcmRpbmcgdG8gSFBDIGJlc3QgcHJhY3RpY2VzIGZvciB7ezF9fS4="
1178
+ },
1179
+ {
1180
+ "type": "settings",
1181
+ "scope": "user",
1182
+ "archivePath": "settings.fragment.yaml",
1183
+ "relativePath": "settings.fragment.yaml",
1184
+ "sha256": "fb6305a4155f9a7db8e96bf38ea2d1c67ea95759efc9ff28ba1207e382b6b553",
1185
+ "size": 120,
1186
+ "encoding": "base64",
1187
+ "data": "ZGVmYXVsdE1vZGU6IGF1dG8Kc2FmZXR5TGV2ZWw6IG1vZGVyYXRlCnNjb3BlOiBwcm9qZWN0CmJ1ZGdldDogNTAwMA=="
1188
+ }
1189
+ ]
1190
+ }</textarea>
1191
+ </div>
1192
+ </div>
1193
+
1194
+ <!-- Right: Import Config & Actions Plan -->
1195
+ <div>
1196
+ <div class="form-row">
1197
+ <div class="form-group">
1198
+ <label for="sh-scope">Target Import Scope Override</label>
1199
+ <select id="sh-scope">
1200
+ <option value="default">Use Scope Configured In File</option>
1201
+ <option value="user">Force User Scope (Global config)</option>
1202
+ <option value="project">Force Project Scope (.clio-coder/ folder)</option>
1203
+ </select>
1204
+ </div>
1205
+ <div class="form-group">
1206
+ <label for="sh-conflict">Conflict Resolution Rule</label>
1207
+ <select id="sh-conflict">
1208
+ <option value="strict">Strict (Fail/Block conflicts)</option>
1209
+ <option value="force">Force Overwrite (Overwrite existing files)</option>
1210
+ </select>
1211
+ </div>
1212
+ </div>
1213
+
1214
+ <!-- Simulated Files already on Disk -->
1215
+ <div class="form-group">
1216
+ <label>Simulated Local Files Present on Disk (Check boxes to simulate conflict paths):</label>
1217
+ <div style="background:rgba(0,0,0,0.3); border: 1px solid var(--border-card); padding: 0.75rem; border-radius: 8px;">
1218
+ <div style="margin-bottom:0.4rem; font-size:0.85rem;">
1219
+ <input type="checkbox" id="sim-disk-clio" checked> <label style="display:inline; color:var(--text-main);" for="sim-disk-clio">CLIO-CODER.md (at project root)</label>
1220
+ </div>
1221
+ <div style="margin-bottom:0.4rem; font-size:0.85rem;">
1222
+ <input type="checkbox" id="sim-disk-prompt"> <label style="display:inline; color:var(--text-main);" for="sim-disk-prompt">prompts/refactor.md (at user config)</label>
1223
+ </div>
1224
+ <div style="font-size:0.85rem;">
1225
+ <input type="checkbox" id="sim-disk-settings" checked> <label style="display:inline; color:var(--text-main);" for="sim-disk-settings">settings.yaml (present, non-empty)</label>
1226
+ </div>
1227
+ </div>
1228
+ </div>
1229
+
1230
+ <button type="button" class="btn btn-primary" onclick="_simulateDryRunImport()">Plan Import & Validate Checksums</button>
1231
+
1232
+ <h3 style="margin-top: 1.5rem; margin-bottom: 0.5rem; font-size: 1rem;">Generated Import Actions Plan</h3>
1233
+ <div class="diagnostic-panel" id="share-plan-output" style="height: 160px;">
1234
+ Click "Plan Import" to execute dry-run simulation.
1235
+ </div>
1236
+ </div>
1237
+ </div>
1238
+ </div>
1239
+ </div>
1240
+ </div>
1241
+
1242
+ <!-- Javascript Core Logic -->
1243
+ <script>
1244
+ // Tab switching
1245
+ function _switchTab(evt, tabId) {
1246
+ const tabContents = document.getElementsByClassName("tab-content");
1247
+ for (let i = 0; i < tabContents.length; i++) {
1248
+ tabContents[i].classList.remove("active");
1249
+ }
1250
+ const tabBtns = document.getElementsByClassName("tab-btn");
1251
+ for (let i = 0; i < tabBtns.length; i++) {
1252
+ tabBtns[i].classList.remove("active");
1253
+ }
1254
+ document.getElementById(tabId).classList.add("active");
1255
+ evt.currentTarget.classList.add("active");
1256
+ }
1257
+
1258
+ // SVG node info box hooks
1259
+ const flowDescriptions = {
1260
+ resolution: {
1261
+ scan: "<strong>Scan Extension Roots:</strong> The loader queries user and project extensions directories (e.g. <code>~/.config/clio-coder/extensions</code> and <code>.clio-coder/extensions</code>) dynamically on startup. It identifies folders that contain extension manifests.",
1262
+ manifest: "<strong>Parse Manifests:</strong> Inspects each directory for manifest files (<code>clio-coder-extension.yaml</code>, <code>.yml</code>, or <code>.json</code>). Validates required version (must be 1), identity tags (ID, version), and parses custom prompts/skills resource path mapping keys.",
1263
+ state: "<strong>Status Filter Check:</strong> Resolves states using <code>state.json</code> located in each scope's extension base. If an extension's ID is registered in the <code>disabled</code> array, it is excluded from effective execution.",
1264
+ shadow: "<strong>Deduplicate & Override:</strong> When an extension ID is found in both project and user-level scopes, Clio ranks scopes (Project = 2, User = 1). The project-scoped extension shadows (overrides) the user-scoped package. The user package is flagged as <code>effective: false</code> and <code>overriddenBy: 'project'</code>.",
1265
+ inject: "<strong>Resource Path Injection:</strong> The paths of enabled, effective extension resources are injected into global loaders. E.g. skill directories are fed into the <code>skills()</code> registry as scope <code>package</code> roots, resolving to source: <code>extension:&lt;scope&gt;:&lt;id&gt;</code>."
1266
+ },
1267
+ skill: {
1268
+ roots: "<strong>Collect Skill Roots:</strong> The loader scans native Clio user/project roots, compatibility folders from other agents (like Codex, Claude, Copilot), package directories, and CLI flags (<code>--skill</code> paths). Rules of precedence: CLI (60) > Project native (50) > Project compat (40) > User native (30) > User compat (20) > Package extension (10).",
1269
+ parse: "<strong>Read & Hash:</strong> The registry reads each file, splits YAML frontmatter from markdown body. Generates a unique SHA-256 hash representing the raw content (catalog identity hash) and extracts metadata details.",
1270
+ precedence: "<strong>Precedence & Collision Resolver:</strong> If multiple files declare the same skill name, they are sorted by precedence rank. Ranks are derived from scope/source. If two candidates possess identical precedence, the resolver sorts file paths alphabetically. Overridden skills are logged with collision diagnostics.",
1271
+ inject: "<strong>Catalog Integration:</strong> Active trusted skills are published to the model-visible catalog. Prompts assemble short hashes and a combined <code>catalog_hash</code> to minimize token cost. The full markdown body is hidden until the model explicitly loads it via <code>context(scope=\"skills\")</code>."
1272
+ },
1273
+ share: {
1274
+ file: "<strong>Read Share Archive:</strong> The CLI loads share packages structured as single JSON files. Verification checks verify root <code>kind: \"clio-share-archive\"</code>, formatVersion = 1, and manifest layout constraints.",
1275
+ checksum: "<strong>Checksum Validation:</strong> Iterates over files array, decodes Base64 data strings, computes SHA-256 hash. If it does not match the manifest's declared checksum, the loader throws a hard error and halts.",
1276
+ plan: "<strong>Import Dry-run Plan:</strong> Compares files in the archive against active files on the local filesystem. Flags actions as <code>write</code> (new file), <code>overwrite</code> (existing conflict), <code>skip</code> (conflict block in strict mode), or <code>settings</code> (merge settings preference fragment).",
1277
+ commit: "<strong>Commit Transaction:</strong> Writes verified data into the mapped folders. Overwrites files only when <code>--force</code> is specified. Extracts non-secret settings preferences (autonomy, scope, budget, theme, terminal, keybindings, compaction, retry) and safely merges them into <code>settings.yaml</code>."
1278
+ }
1279
+ };
1280
+
1281
+ function _showFlowInfo(subsystem, nodeType) {
1282
+ const infoBox = document.getElementById(`flow-${subsystem}-info`);
1283
+ if (flowDescriptions[subsystem]?.[nodeType]) {
1284
+ infoBox.innerHTML = flowDescriptions[subsystem][nodeType];
1285
+
1286
+ // Highlight active node in SVG
1287
+ const nodes = document.querySelectorAll(`#tab-architecture svg .svg-node`);
1288
+ nodes.forEach(n => { n.classList.remove('active'); });
1289
+ document.getElementById(`node-${subsystem}-${nodeType}`).classList.add('active');
1290
+ }
1291
+ }
1292
+
1293
+ // Simple YAML Parser Helper
1294
+ function parseSimpleYaml(yamlString) {
1295
+ const lines = yamlString.split(/\r?\n/);
1296
+ const result = {};
1297
+ let currentKey = null;
1298
+
1299
+ for (const line of lines) {
1300
+ const trimmed = line.trim();
1301
+ if (!trimmed || trimmed.startsWith('#')) continue;
1302
+
1303
+ if (trimmed.endsWith(':')) {
1304
+ currentKey = trimmed.slice(0, -1).trim();
1305
+ result[currentKey] = {};
1306
+ continue;
1307
+ }
1308
+
1309
+ const match = trimmed.match(/^([^:]+):(.*)$/);
1310
+ if (match) {
1311
+ const key = match[1].trim();
1312
+ const valStr = match[2].trim();
1313
+
1314
+ let value = valStr;
1315
+ if (valStr.startsWith('"') && valStr.endsWith('"')) {
1316
+ value = valStr.slice(1, -1);
1317
+ } else if (valStr.startsWith("'") && valStr.endsWith("'")) {
1318
+ value = valStr.slice(1, -1);
1319
+ } else if (valStr === 'true') {
1320
+ value = true;
1321
+ } else if (valStr === 'false') {
1322
+ value = false;
1323
+ } else if (!Number.isNaN(valStr) && valStr !== '') {
1324
+ value = Number(valStr);
1325
+ }
1326
+
1327
+ const indent = line.search(/\S/);
1328
+ if (indent > 0 && currentKey) {
1329
+ result[currentKey][key] = value;
1330
+ } else {
1331
+ currentKey = null;
1332
+ result[key] = value;
1333
+ }
1334
+ } else if (trimmed.startsWith('-') && currentKey) {
1335
+ if (!Array.isArray(result[currentKey])) {
1336
+ result[currentKey] = [];
1337
+ }
1338
+ const itemVal = trimmed.slice(1).trim().replace(/^['"]|['"]$/g, '');
1339
+ result[currentKey].push(itemVal);
1340
+ }
1341
+ }
1342
+ return result;
1343
+ }
1344
+
1345
+ // Simple Hash Generator for Simulation
1346
+ function mockSha256(text) {
1347
+ let hash = 0;
1348
+ for (let i = 0; i < text.length; i++) {
1349
+ const char = text.charCodeAt(i);
1350
+ hash = (hash << 5) - hash + char;
1351
+ hash = hash & hash;
1352
+ }
1353
+ return `${Math.abs(hash).toString(16).padStart(8, '0')}e59f4277b095e69e`;
1354
+ }
1355
+
1356
+ // --- TAB: MANIFEST BUILDER LOGIC ---
1357
+ function generateManifest() {
1358
+ const id = document.getElementById("mb-id").value.trim();
1359
+ const name = document.getElementById("mb-name").value.trim() || id;
1360
+ const version = document.getElementById("mb-version").value.trim();
1361
+ const clioCompat = document.getElementById("mb-clio-compat").value.trim();
1362
+ const desc = document.getElementById("mb-desc").value.trim();
1363
+ const prompts = document.getElementById("mb-prompts").value.trim();
1364
+ const skills = document.getElementById("mb-skills").value.trim();
1365
+ const tools = document.getElementById("mb-tools").value.split(",").map(s => s.trim()).filter(Boolean);
1366
+ const settings = document.getElementById("mb-settings").value.split(",").map(s => s.trim()).filter(Boolean);
1367
+ const format = document.getElementById("mb-format").value;
1368
+
1369
+ const manifestObj = {
1370
+ manifestVersion: 1,
1371
+ id: id,
1372
+ name: name,
1373
+ version: version,
1374
+ description: desc,
1375
+ resources: {}
1376
+ };
1377
+
1378
+ if (prompts) manifestObj.resources.prompts = prompts;
1379
+ if (skills) manifestObj.resources.skills = skills;
1380
+ if (tools.length > 0) manifestObj.tools = tools;
1381
+ if (settings.length > 0) manifestObj.settings = settings;
1382
+ if (clioCompat) manifestObj.compatibility = { clio: clioCompat };
1383
+
1384
+ // Validation
1385
+ const diagnostics = [];
1386
+ const idRegex = /^[a-z0-9][a-z0-9._-]*[a-z0-9]$/;
1387
+
1388
+ if (!id) {
1389
+ diagnostics.push({ type: 'error', message: "Manifest validation failed: 'id' key is required." });
1390
+ } else {
1391
+ if (id.length > 80) {
1392
+ diagnostics.push({ type: 'error', message: "Manifest validation failed: 'id' exceeds 80 characters." });
1393
+ }
1394
+ if (!idRegex.test(id)) {
1395
+ diagnostics.push({ type: 'error', message: "Manifest validation failed: 'id' must consist of lowercase alphanumeric characters, dots, underscores, or hyphens, and start/end alphanumeric." });
1396
+ }
1397
+ }
1398
+
1399
+ if (!version) {
1400
+ diagnostics.push({ type: 'error', message: "Manifest validation failed: 'version' key is required." });
1401
+ }
1402
+ if (!desc) {
1403
+ diagnostics.push({ type: 'error', message: "Manifest validation failed: 'description' key is required." });
1404
+ }
1405
+
1406
+ // Populate Outputs
1407
+ const outputBox = document.getElementById("mb-code-output");
1408
+ if (format === 'json') {
1409
+ outputBox.textContent = JSON.stringify(manifestObj, null, 2);
1410
+ } else {
1411
+ // Output YAML manually for clean aesthetics
1412
+ let yaml = `manifestVersion: ${manifestObj.manifestVersion}\n`;
1413
+ yaml += `id: "${manifestObj.id}"\n`;
1414
+ yaml += `name: "${manifestObj.name}"\n`;
1415
+ yaml += `version: "${manifestObj.version}"\n`;
1416
+ yaml += `description: "${manifestObj.description}"\n`;
1417
+ yaml += `resources:\n`;
1418
+ if (prompts) yaml += ` prompts: "${prompts}"\n`;
1419
+ if (skills) yaml += ` skills: "${skills}"\n`;
1420
+ if (clioCompat) yaml += `compatibility:\n clio: "${clioCompat}"\n`;
1421
+ if (tools.length > 0) {
1422
+ yaml += `tools:\n`;
1423
+ tools.forEach(t => { yaml += ` - ${t}\n`; });
1424
+ }
1425
+ if (settings.length > 0) {
1426
+ yaml += `settings:\n`;
1427
+ settings.forEach(s => { yaml += ` - ${s}\n`; });
1428
+ }
1429
+ outputBox.textContent = yaml;
1430
+ }
1431
+
1432
+ // Render diagnostics
1433
+ const diagPanel = document.getElementById("mb-diagnostics-panel");
1434
+ diagPanel.innerHTML = "";
1435
+ if (diagnostics.length === 0) {
1436
+ diagPanel.innerHTML = `<div class="diagnostic-entry info">[SUCCESS] Manifest compiles successfully. Valid structure verified.</div>`;
1437
+ } else {
1438
+ diagnostics.forEach(d => {
1439
+ diagPanel.innerHTML += `<div class="diagnostic-entry ${d.type}">[${d.type.toUpperCase()}] ${d.message}</div>`;
1440
+ });
1441
+ }
1442
+ }
1443
+
1444
+ function _copyManifestContent() {
1445
+ const content = document.getElementById("mb-code-output").textContent;
1446
+ navigator.clipboard.writeText(content).then(() => {
1447
+ alert("Manifest copied to clipboard!");
1448
+ });
1449
+ }
1450
+
1451
+
1452
+ // --- TAB: PACKAGE STRUCTURE VALIDATOR ---
1453
+ let virtualFiles = [];
1454
+ let currentVFileIndex = 0;
1455
+
1456
+ const templates = {
1457
+ hpc: [
1458
+ {
1459
+ path: 'clio-coder-extension.yaml',
1460
+ content: `manifestVersion: 1
1461
+ id: scientist-pack
1462
+ name: Scientific Computing Pack
1463
+ version: 1.2.0
1464
+ description: Core skills and prompts for MPI and HDF5 debugging.
1465
+ resources:
1466
+ prompts: prompts
1467
+ skills: skills
1468
+ compatibility:
1469
+ clio: ">=0.2.0" contribute: themes`
1470
+ },
1471
+ {
1472
+ path: 'prompts/audit-hpc.md',
1473
+ content: `---
1474
+ description: Perform validation check on HPC code
1475
+ argument-hint: "<filename>"
1476
+ ---
1477
+ Analyze {{1}} to inspect openmp loop scheduling. Identify bottleneck loops.`
1478
+ },
1479
+ {
1480
+ path: 'skills/mpi-audit/SKILL.md',
1481
+ content: `---
1482
+ name: mpi-audit
1483
+ description: Check MPI send/recv mismatch configurations
1484
+ allowed-tools:
1485
+ - Read
1486
+ - Grep
1487
+ ---
1488
+ When MPI deadlock is suspected:
1489
+ - Identify calls to MPI_Send and MPI_Recv.
1490
+ - Search for corresponding buffer sizes.
1491
+ - Verify block/nonblock combinations.`
1492
+ }
1493
+ ],
1494
+ invalid: [
1495
+ {
1496
+ path: 'clio-coder-extension.yaml',
1497
+ content: `manifestVersion: 1
1498
+ id: BAD-NAME-Pack!
1499
+ version: ""
1500
+ description: Missing description parameters
1501
+ resources:
1502
+ prompts: prompts
1503
+ skills: skills`
1504
+ },
1505
+ {
1506
+ path: 'prompts/broken-template.md',
1507
+ content: `---
1508
+ description: Test broken frontmatter template
1509
+ argumentHint: "<broken>"
1510
+ missing-closing-delimiter-tag
1511
+
1512
+ Some markdown body content that exists here.`
1513
+ },
1514
+ {
1515
+ path: 'skills/ill-formatted-skill/SKILL.md',
1516
+ content: `---
1517
+ name: bad_skill_name_format_123
1518
+ license: MIT
1519
+ ---
1520
+ My body content is here, but wait, where is the description key inside the frontmatter? This should cause a rejection.`
1521
+ }
1522
+ ],
1523
+ collision: [
1524
+ {
1525
+ path: 'clio-coder-extension.yaml',
1526
+ content: `manifestVersion: 1
1527
+ id: colliders
1528
+ version: 1.0.0
1529
+ description: Demonstrating collision override mechanics
1530
+ resources:
1531
+ skills: skills`
1532
+ },
1533
+ {
1534
+ path: 'skills/mpi-helper/SKILL.md',
1535
+ content: `---
1536
+ name: mpi-helper
1537
+ description: Native package skill for MPI assistance
1538
+ ---
1539
+ Provide helper guidance on MPI bindings.`
1540
+ },
1541
+ // We will mock loading another root containing "mpi-helper" at a higher precedence
1542
+ {
1543
+ path: 'user-skills/mpi-helper/SKILL.md',
1544
+ content: `---
1545
+ name: mpi-helper
1546
+ description: Overriding User skill for MPI assistance (Should win over package)
1547
+ ---
1548
+ Provide advanced custom guidance on MPI bindings.`
1549
+ }
1550
+ ]
1551
+ };
1552
+
1553
+ function loadVirtualTemplate(key) {
1554
+ // Set active buttons style
1555
+ document.getElementById('btn-tpl-hpc').classList.remove('active');
1556
+ document.getElementById('btn-tpl-invalid').classList.remove('active');
1557
+ document.getElementById('btn-tpl-collision').classList.remove('active');
1558
+ document.getElementById(`btn-tpl-${key}`).classList.add('active');
1559
+
1560
+ virtualFiles = JSON.parse(JSON.stringify(templates[key]));
1561
+ currentVFileIndex = 0;
1562
+ renderVirtualExplorer();
1563
+ runPackageValidation();
1564
+ }
1565
+
1566
+ function renderVirtualExplorer() {
1567
+ const container = document.getElementById('vfile-list-container');
1568
+ container.innerHTML = "";
1569
+
1570
+ virtualFiles.forEach((file, index) => {
1571
+ const item = document.createElement('div');
1572
+ item.className = `vfile-item ${index === currentVFileIndex ? 'active' : ''}`;
1573
+ item.onclick = () => selectVirtualFile(index);
1574
+ item.innerHTML = `
1575
+ <span>📄 ${file.path}</span>
1576
+ <span class="vfile-item-actions">
1577
+ <button type="button" class="vfile-action-btn" onclick="_deleteVirtualFile(event, ${index})">🗑️</button>
1578
+ </span>
1579
+ `;
1580
+ container.appendChild(item);
1581
+ });
1582
+
1583
+ if (virtualFiles[currentVFileIndex]) {
1584
+ document.getElementById('vfile-current-name').textContent = virtualFiles[currentVFileIndex].path;
1585
+ document.getElementById('vfile-editor-box').value = virtualFiles[currentVFileIndex].content;
1586
+ } else {
1587
+ document.getElementById('vfile-current-name').textContent = "No File Selected";
1588
+ document.getElementById('vfile-editor-box').value = "";
1589
+ }
1590
+ }
1591
+
1592
+ function selectVirtualFile(index) {
1593
+ currentVFileIndex = index;
1594
+ renderVirtualExplorer();
1595
+ }
1596
+
1597
+ function _updateCurrentVirtualFileContent() {
1598
+ if (virtualFiles[currentVFileIndex]) {
1599
+ virtualFiles[currentVFileIndex].content = document.getElementById('vfile-editor-box').value;
1600
+ }
1601
+ }
1602
+
1603
+ function _addVirtualFilePrompt() {
1604
+ const filename = prompt("Enter simulated relative file path (e.g. skills/new-skill/SKILL.md):", "skills/my-skill/SKILL.md");
1605
+ if (!filename) return;
1606
+
1607
+ // Check duplicate
1608
+ const exists = virtualFiles.find(f => f.path === filename);
1609
+ if (exists) {
1610
+ alert("File already exists!");
1611
+ return;
1612
+ }
1613
+
1614
+ virtualFiles.push({
1615
+ path: filename,
1616
+ content: `---\nname: ${filename.split('/').slice(-2)[0] || 'custom-name'}\ndescription: Write a brief description here\n---\nBody instructions details here.`
1617
+ });
1618
+
1619
+ currentVFileIndex = virtualFiles.length - 1;
1620
+ renderVirtualExplorer();
1621
+ }
1622
+
1623
+ function _deleteVirtualFile(evt, index) {
1624
+ evt.stopPropagation();
1625
+ if (confirm(`Delete file "${virtualFiles[index].path}"?`)) {
1626
+ virtualFiles.splice(index, 1);
1627
+ if (currentVFileIndex >= virtualFiles.length) {
1628
+ currentVFileIndex = Math.max(0, virtualFiles.length - 1);
1629
+ }
1630
+ renderVirtualExplorer();
1631
+ runPackageValidation();
1632
+ }
1633
+ }
1634
+
1635
+ function runPackageValidation() {
1636
+ const diagOutput = document.getElementById('val-diagnostics-output');
1637
+ diagOutput.innerHTML = `<div class="diagnostic-entry info">[COMPILING] Compiling sandbox workspace files...</div>`;
1638
+
1639
+ setTimeout(() => {
1640
+ diagOutput.innerHTML = "";
1641
+
1642
+ // Find manifest file
1643
+ const manifestFile = virtualFiles.find(f =>
1644
+ f.path === 'clio-coder-extension.yaml' ||
1645
+ f.path === 'clio-coder-extension.json' ||
1646
+ f.path === 'clio-coder-extension.yml'
1647
+ );
1648
+
1649
+ if (!manifestFile) {
1650
+ diagOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] extension manifest (clio-coder-extension.yaml) not found. Loader aborted.</div>`;
1651
+ return;
1652
+ }
1653
+
1654
+ // Parse Manifest
1655
+ let manifest = {};
1656
+ try {
1657
+ if (manifestFile.path.endsWith('.json')) {
1658
+ manifest = JSON.parse(manifestFile.content);
1659
+ } else {
1660
+ manifest = parseSimpleYaml(manifestFile.content);
1661
+ }
1662
+ diagOutput.innerHTML += `<div class="diagnostic-entry info">[INFO] Manifest loaded: ID "${manifest.id || 'none'}", version "${manifest.version || 'none'}"</div>`;
1663
+ } catch(e) {
1664
+ diagOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Manifest parse failed: ${e.message}</div>`;
1665
+ return;
1666
+ }
1667
+
1668
+ // Validate Manifest Identity Keys
1669
+ let validManifest = true;
1670
+ if (!manifest.id) {
1671
+ diagOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Manifest key 'id' is required and missing.</div>`;
1672
+ validManifest = false;
1673
+ } else {
1674
+ const idRegex = /^[a-z0-9][a-z0-9._-]*[a-z0-9]$/;
1675
+ if (!idRegex.test(manifest.id)) {
1676
+ diagOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Manifest ID "${manifest.id}" must consist of lowercase letters, numbers, dots, underscores, or hyphens, starting/ending alphanumeric.</div>`;
1677
+ validManifest = false;
1678
+ }
1679
+ if (manifest.id.length > 80) {
1680
+ diagOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Manifest ID exceeds 80 characters limit.</div>`;
1681
+ validManifest = false;
1682
+ }
1683
+ }
1684
+
1685
+ if (manifest.version === undefined || manifest.version === "") {
1686
+ diagOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Manifest key 'version' is required and missing.</div>`;
1687
+ validManifest = false;
1688
+ }
1689
+ if (manifest.description === undefined || manifest.description === "") {
1690
+ diagOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Manifest key 'description' is required and missing.</div>`;
1691
+ validManifest = false;
1692
+ }
1693
+
1694
+ if (!validManifest) {
1695
+ diagOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Extension load rejected due to manifest critical errors.</div>`;
1696
+ return;
1697
+ }
1698
+
1699
+ // Load configured resources folders
1700
+ const resourceFolders = manifest.resources || {};
1701
+ const promptsFolder = resourceFolders.prompts || 'prompts';
1702
+ const skillsFolder = resourceFolders.skills || 'skills';
1703
+
1704
+ diagOutput.innerHTML += `<div class="diagnostic-entry info">[INFO] Discovering resources matching configuration folders (prompts: "${promptsFolder}", skills: "${skillsFolder}")</div>`;
1705
+
1706
+ // Process Prompts
1707
+ const promptsDiscovered = [];
1708
+ virtualFiles.forEach(f => {
1709
+ if (f.path.startsWith(`${promptsFolder}/`)) {
1710
+ if (!f.path.endsWith('.md')) {
1711
+ diagOutput.innerHTML += `<div class="diagnostic-entry warning">[WARNING] File ${f.path} inside prompts folder does not end in '.md'. Ignored.</div>`;
1712
+ return;
1713
+ }
1714
+
1715
+ // Extract prompt identity
1716
+ const name = f.path.split('/').pop().replace(/\.md$/, '');
1717
+ let frontmatter = {};
1718
+ let body = f.content;
1719
+
1720
+ // Check frontmatter
1721
+ if (f.content.startsWith('---')) {
1722
+ const parts = f.content.split('---');
1723
+ if (parts.length >= 3) {
1724
+ try {
1725
+ frontmatter = parseSimpleYaml(parts[1]);
1726
+ body = parts.slice(2).join('---').trim();
1727
+ } catch(e) {
1728
+ diagOutput.innerHTML += `<div class="diagnostic-entry warning">[WARNING] Prompt ${f.path} has malformed frontmatter. Plain markdown fallback active.</div>`;
1729
+ }
1730
+ } else {
1731
+ diagOutput.innerHTML += `<div class="diagnostic-entry warning">[WARNING] Prompt ${f.path} missing closing frontmatter delimiter. Plain markdown fallback active.</div>`;
1732
+ }
1733
+ }
1734
+
1735
+ // Fallback description
1736
+ let description = frontmatter.description;
1737
+ if (!description) {
1738
+ const lines = body.split('\n').map(l => l.trim()).filter(l => l.length > 0);
1739
+ const firstLine = lines[0] || "";
1740
+ const cleanFirstLine = firstLine.replace(/^#{1,6}\s+/, '');
1741
+ description = cleanFirstLine.length > 60 ? `${cleanFirstLine.slice(0, 57)}...` : cleanFirstLine || 'Prompt template';
1742
+ diagOutput.innerHTML += `<div class="diagnostic-entry info">[INFO] Prompt "${name}" has no explicit description; using fallback: "${description}"</div>`;
1743
+ }
1744
+
1745
+ promptsDiscovered.push({
1746
+ name,
1747
+ description,
1748
+ argumentHint: frontmatter['argument-hint'] || frontmatter.argumentHint || 'none',
1749
+ path: f.path
1750
+ });
1751
+
1752
+ diagOutput.innerHTML += `<div class="diagnostic-entry info">[SUCCESS] Discovered prompt template: "${name}" - "${description}" (Hint: "${frontmatter['argument-hint'] || 'none'}")</div>`;
1753
+ }
1754
+ });
1755
+
1756
+ // Process Skills
1757
+ const skillsDiscovered = [];
1758
+ virtualFiles.forEach(f => {
1759
+ // Detect both single file or directory SKILL.md
1760
+ if (f.path.startsWith(`${skillsFolder}/`)) {
1761
+ const isSkillMd = f.path.endsWith('SKILL.md');
1762
+ const isSingleMd = f.path.endsWith('.md') && !f.path.includes('/SKILL.md');
1763
+
1764
+ if (!isSkillMd && !isSingleMd) return;
1765
+
1766
+ let frontmatter = {};
1767
+ let body = f.content;
1768
+ let _splitOk = false;
1769
+
1770
+ if (f.content.startsWith('---')) {
1771
+ const parts = f.content.split('---');
1772
+ if (parts.length >= 3) {
1773
+ try {
1774
+ frontmatter = parseSimpleYaml(parts[1]);
1775
+ body = parts.slice(2).join('---').trim();
1776
+ _splitOk = true;
1777
+ } catch(e) {
1778
+ diagOutput.innerHTML += `<div class="diagnostic-entry warning">[WARNING] Skill file "${f.path}" YAML frontmatter is not an object. Reconciling.</div>`;
1779
+ }
1780
+ } else {
1781
+ diagOutput.innerHTML += `<div class="diagnostic-entry warning">[WARNING] Skill file "${f.path}" missing closing frontmatter delimiter.</div>`;
1782
+ }
1783
+ } else {
1784
+ diagOutput.innerHTML += `<div class="diagnostic-entry warning">[WARNING] Skill file "${f.path}" is missing YAML frontmatter.</div>`;
1785
+ }
1786
+
1787
+ // Hard Rejection rules: Missing Description
1788
+ const description = frontmatter.description;
1789
+ if (!description) {
1790
+ diagOutput.innerHTML += `<div class="diagnostic-entry error">[REJECTED] Skill "${f.path}" load failed: 'description' is required and missing in frontmatter.</div>`;
1791
+ return;
1792
+ }
1793
+
1794
+ // Name format rules
1795
+ // Path subject is folder name or file base
1796
+ let pathSubject = "";
1797
+ if (isSkillMd) {
1798
+ const folders = f.path.split('/');
1799
+ pathSubject = folders[folders.length - 2];
1800
+ } else {
1801
+ pathSubject = f.path.split('/').pop().replace(/\.md$/, '');
1802
+ }
1803
+
1804
+ const frontmatterName = frontmatter.name;
1805
+ const finalName = frontmatterName || pathSubject;
1806
+
1807
+ if (frontmatterName && frontmatterName !== pathSubject) {
1808
+ diagOutput.innerHTML += `<div class="diagnostic-entry warning">[WARNING] Skill name "${frontmatterName}" differs from path folder name "${pathSubject}"; using frontmatter name.</div>`;
1809
+ }
1810
+
1811
+ // Check format naming (lowercase, numbers, single hyphens)
1812
+ const nameErr = [];
1813
+ if (finalName.length > 64) nameErr.push("name exceeds 64 characters limit.");
1814
+ if (!/^[a-z0-9-]+$/.test(finalName)) nameErr.push("name must contain lowercase letters, numbers, and hyphens only.");
1815
+ if (finalName.startsWith('-') || finalName.endsWith('-')) nameErr.push("name must not start or end with a hyphen.");
1816
+ if (finalName.includes('--')) nameErr.push("name must not contain consecutive hyphens.");
1817
+
1818
+ nameErr.forEach(err => {
1819
+ diagOutput.innerHTML += `<div class="diagnostic-entry warning">[WARNING] Skill name "${finalName}" format validation: ${err}</div>`;
1820
+ });
1821
+
1822
+ if (description.length > 1024) {
1823
+ diagOutput.innerHTML += `<div class="diagnostic-entry warning">[WARNING] Skill description exceeds 1024 characters limit (${description.length}).</div>`;
1824
+ }
1825
+
1826
+ skillsDiscovered.push({
1827
+ name: finalName,
1828
+ description,
1829
+ path: f.path,
1830
+ precedence: 10, // Package precedence
1831
+ source: 'extension',
1832
+ hash: mockSha256(f.content)
1833
+ });
1834
+
1835
+ diagOutput.innerHTML += `<div class="diagnostic-entry info">[SUCCESS] Loaded skill: "${finalName}" (Hash: ${mockSha256(f.content).slice(0,12)})</div>`;
1836
+ }
1837
+ });
1838
+
1839
+ // Simulating loading User/CLI level skills to show collision resolver
1840
+ // Search if "user-skills" exist in our virtual file list
1841
+ virtualFiles.forEach(f => {
1842
+ if (f.path.startsWith('user-skills/')) {
1843
+ const name = f.path.split('/')[1];
1844
+ if (f.content.startsWith('---')) {
1845
+ const parts = f.content.split('---');
1846
+ if (parts.length >= 3) {
1847
+ const fm = parseSimpleYaml(parts[1]);
1848
+ if (fm.description) {
1849
+ skillsDiscovered.push({
1850
+ name: fm.name || name,
1851
+ description: fm.description,
1852
+ path: f.path,
1853
+ precedence: 30, // User native scope precedence
1854
+ source: 'user-native',
1855
+ hash: mockSha256(f.content)
1856
+ });
1857
+ diagOutput.innerHTML += `<div class="diagnostic-entry info">[INFO] Local User folder skill discovered: "${fm.name || name}" (Precedence: 30)</div>`;
1858
+ }
1859
+ }
1860
+ }
1861
+ }
1862
+ });
1863
+
1864
+ // Run Collision checks
1865
+ diagOutput.innerHTML += `<div class="diagnostic-entry info">[COMPILING] Running collision resolver...</div>`;
1866
+ const uniqueSkills = {};
1867
+ skillsDiscovered.forEach(skill => {
1868
+ if (!uniqueSkills[skill.name]) {
1869
+ uniqueSkills[skill.name] = [];
1870
+ }
1871
+ uniqueSkills[skill.name].push(skill);
1872
+ });
1873
+
1874
+ Object.keys(uniqueSkills).forEach(name => {
1875
+ const list = uniqueSkills[name];
1876
+ if (list.length > 1) {
1877
+ // Sort by precedence (descending)
1878
+ list.sort((a, b) => b.precedence - a.precedence);
1879
+ const winner = list[0];
1880
+ diagOutput.innerHTML += `<div class="diagnostic-entry collision">[COLLISION] Skill Name "${name}" collision detected. Winner: "${winner.source}" (${winner.path}) outranks:</div>`;
1881
+ for(let i = 1; i < list.length; i++) {
1882
+ diagOutput.innerHTML += `<div class="diagnostic-entry warning"> -> Overridden: "${list[i].source}" (${list[i].path}) with precedence ${list[i].precedence}</div>`;
1883
+ }
1884
+ }
1885
+ });
1886
+
1887
+ diagOutput.innerHTML += `<div class="diagnostic-entry info">[SUCCESS] Compilation completed. ${promptsDiscovered.length} prompt templates and ${Object.keys(uniqueSkills).length} unique skills successfully cached.</div>`;
1888
+ }, 500);
1889
+ }
1890
+
1891
+
1892
+ // --- TAB: SHARING ARCHIVE SIMULATOR LOGIC ---
1893
+ function _generateShareArchiveFromSandbox() {
1894
+ const files = [];
1895
+ const manifestFiles = [];
1896
+
1897
+ virtualFiles.forEach(f => {
1898
+ let type = 'extension';
1899
+ let scope = 'user';
1900
+ if (f.path.startsWith('prompts/')) { type = 'prompt'; scope = 'project'; }
1901
+ else if (f.path.startsWith('skills/')) { type = 'skill'; scope = 'project'; }
1902
+ else if (f.path.startsWith('clio-coder-extension')) { type = 'extension'; scope = 'project'; }
1903
+ else if (f.path.startsWith('user-skills/')) { type = 'skill'; scope = 'user'; }
1904
+
1905
+ const hash = mockSha256(f.content);
1906
+ const bytes = f.content.length;
1907
+ const b64 = btoa(f.content);
1908
+
1909
+ manifestFiles.push({
1910
+ type,
1911
+ scope,
1912
+ archivePath: `${scope}/${f.path}`,
1913
+ relativePath: f.path,
1914
+ sha256: hash,
1915
+ size: bytes
1916
+ });
1917
+
1918
+ files.push({
1919
+ type,
1920
+ scope,
1921
+ archivePath: `${scope}/${f.path}`,
1922
+ relativePath: f.path,
1923
+ sha256: hash,
1924
+ size: bytes,
1925
+ encoding: 'base64',
1926
+ data: b64
1927
+ });
1928
+ });
1929
+
1930
+ const archive = {
1931
+ kind: 'clio-share-archive',
1932
+ formatVersion: 1,
1933
+ manifest: {
1934
+ format: 'clio.share.v1',
1935
+ clioVersion: '0.3.0',
1936
+ createdAt: new Date().toISOString(),
1937
+ files: manifestFiles
1938
+ },
1939
+ files: files
1940
+ };
1941
+
1942
+ document.getElementById('share-json-editor').value = JSON.stringify(archive, null, 2);
1943
+ alert("Sharing archive JSON generated successfully from active sandbox files!");
1944
+ }
1945
+
1946
+ function _simulateDryRunImport() {
1947
+ const rawText = document.getElementById('share-json-editor').value;
1948
+ const targetScopeOverride = document.getElementById('sh-scope').value;
1949
+ const conflictRule = document.getElementById('sh-conflict').value;
1950
+
1951
+ const planOutput = document.getElementById('share-plan-output');
1952
+ planOutput.innerHTML = `<div class="diagnostic-entry info">[PROCESSING] Parsing share archive...</div>`;
1953
+
1954
+ setTimeout(() => {
1955
+ planOutput.innerHTML = "";
1956
+ let archive = null;
1957
+ try {
1958
+ archive = JSON.parse(rawText);
1959
+ } catch(e) {
1960
+ planOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] JSON Syntax check failed: ${e.message}</div>`;
1961
+ return;
1962
+ }
1963
+
1964
+ // Validate basic archive wrappers
1965
+ if (archive.kind !== 'clio-share-archive' || archive.formatVersion !== 1) {
1966
+ planOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Validation failed: Not a valid Clio share archive v1 (Check 'kind' and 'formatVersion').</div>`;
1967
+ return;
1968
+ }
1969
+
1970
+ if (!archive.manifest || archive.manifest.format !== 'clio.share.v1' || !Array.isArray(archive.files)) {
1971
+ planOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Validation failed: manifest schema format is malformed.</div>`;
1972
+ return;
1973
+ }
1974
+
1975
+ planOutput.innerHTML += `<div class="diagnostic-entry info">[INFO] Archive source version: ${archive.manifest.clioVersion || 'unknown'} | Created: ${archive.manifest.createdAt}</div>`;
1976
+
1977
+ // Check file checksum integrity
1978
+ let checksumSuccess = true;
1979
+ archive.files.forEach(file => {
1980
+ try {
1981
+ const decoded = atob(file.data);
1982
+ const computedHash = mockSha256(decoded);
1983
+ if (computedHash !== file.sha256) {
1984
+ planOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Checksum mismatch for file "${file.archivePath}". Expected: ${file.sha256}, Actual decoded: ${computedHash}</div>`;
1985
+ checksumSuccess = false;
1986
+ }
1987
+ } catch(e) {
1988
+ planOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Failed to decode base64 stream for "${file.archivePath}": ${e.message}</div>`;
1989
+ checksumSuccess = false;
1990
+ }
1991
+ });
1992
+
1993
+ if (!checksumSuccess) {
1994
+ planOutput.innerHTML += `<div class="diagnostic-entry error">[ERROR] Import halted. Package contents corrupted.</div>`;
1995
+ return;
1996
+ }
1997
+
1998
+ planOutput.innerHTML += `<div class="diagnostic-entry info">[SUCCESS] All SHA-256 integrity checks passed. Simulating filesystem mapping...</div>`;
1999
+
2000
+ // Build disk checks
2001
+ const simDiskClioExists = document.getElementById('sim-disk-clio').checked;
2002
+ const simDiskPromptExists = document.getElementById('sim-disk-prompt').checked;
2003
+ const simDiskSettingsExists = document.getElementById('sim-disk-settings').checked;
2004
+
2005
+ // Perform mock dry-run plan actions
2006
+ let conflictDetected = false;
2007
+
2008
+ archive.files.forEach(file => {
2009
+ const resolvedScope = targetScopeOverride === 'default' ? file.scope : targetScopeOverride;
2010
+ let mappedPath = "";
2011
+ let fileExistsOnDisk = false;
2012
+
2013
+ // Mapping paths logic
2014
+ if (file.type === 'project-context') {
2015
+ mappedPath = `./${file.relativePath}`;
2016
+ fileExistsOnDisk = (file.relativePath === 'CLIO-CODER.md' && simDiskClioExists);
2017
+ } else if (file.type === 'prompt') {
2018
+ mappedPath = resolvedScope === 'user' ? `~/.config/clio-coder/prompts/${file.relativePath}` : `.clio-coder/prompts/${file.relativePath}`;
2019
+ fileExistsOnDisk = (file.relativePath === 'refactor.md' && resolvedScope === 'user' && simDiskPromptExists);
2020
+ } else if (file.type === 'skill') {
2021
+ mappedPath = resolvedScope === 'user' ? `~/.config/clio-coder/skills/${file.relativePath}` : `.clio-coder/skills/${file.relativePath}`;
2022
+ fileExistsOnDisk = false;
2023
+ } else if (file.type === 'settings') {
2024
+ mappedPath = `~/.config/clio-coder/settings.yaml`;
2025
+ fileExistsOnDisk = simDiskSettingsExists;
2026
+ } else if (file.type === 'extension') {
2027
+ mappedPath = resolvedScope === 'user' ? `~/.config/clio-coder/extensions/${file.relativePath}` : `.clio-coder/extensions/${file.relativePath}`;
2028
+ fileExistsOnDisk = false;
2029
+ }
2030
+
2031
+ let action = "write";
2032
+ let classStyle = "info";
2033
+
2034
+ if (fileExistsOnDisk) {
2035
+ conflictDetected = true;
2036
+ if (file.type === 'settings') {
2037
+ action = "merge settings fragment (Safe UI merge)";
2038
+ classStyle = "info";
2039
+ } else if (conflictRule === 'force') {
2040
+ action = "overwrite existing (forced)";
2041
+ classStyle = "warning";
2042
+ } else {
2043
+ action = "conflict blocked (needs --force)";
2044
+ classStyle = "error";
2045
+ }
2046
+ }
2047
+
2048
+ planOutput.innerHTML += `<div class="diagnostic-entry ${classStyle}">[PLAN - ${action.toUpperCase()}] type: "${file.type}" | scope: "${resolvedScope}" -> Destination: ${mappedPath}</div>`;
2049
+ });
2050
+
2051
+ if (conflictDetected && conflictRule === 'strict') {
2052
+ planOutput.innerHTML += `<div class="diagnostic-entry error">[FAILURE] Dry-run import aborted. Conflicting destination files block write. Toggle conflict resolution to 'Force Overwrite' to bypass.</div>`;
2053
+ } else {
2054
+ planOutput.innerHTML += `<div class="diagnostic-entry info">[SUCCESS] Import Plan compiled successfully. Ready for commit execution.</div>`;
2055
+ }
2056
+
2057
+ }, 500);
2058
+ }
2059
+
2060
+ // Initialize defaults
2061
+ generateManifest();
2062
+ loadVirtualTemplate('hpc');
2063
+ </script>
2064
+ </body>
2065
+ </html>