parapet-rails 0.1.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 (231) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +48 -0
  4. data/Rakefile +7 -0
  5. data/app/assets/config/parapet/grammar-registry.json +52 -0
  6. data/app/assets/images/parapet/icons/activities/component-inspector.svg +4 -0
  7. data/app/assets/images/parapet/icons/activities/coverage-heatmap.svg +3 -0
  8. data/app/assets/images/parapet/icons/activities/discovery-sidebar.svg +3 -0
  9. data/app/assets/images/parapet/icons/activities/environment-toggles.svg +4 -0
  10. data/app/assets/images/parapet/icons/activities/failure-inspector.svg +5 -0
  11. data/app/assets/images/parapet/icons/activities/flaky-history.svg +3 -0
  12. data/app/assets/images/parapet/icons/activities/flight-recorder.svg +5 -0
  13. data/app/assets/images/parapet/icons/activities/health-graph.svg +3 -0
  14. data/app/assets/images/parapet/icons/activities/injection-engine.svg +3 -0
  15. data/app/assets/images/parapet/icons/activities/live-sql-stream.svg +5 -0
  16. data/app/assets/images/parapet/icons/activities/live-web-preview.svg +4 -0
  17. data/app/assets/images/parapet/icons/activities/monaco-editor.svg +5 -0
  18. data/app/assets/images/parapet/icons/activities/progress-area.svg +3 -0
  19. data/app/assets/images/parapet/icons/activities/registry-metadata.svg +5 -0
  20. data/app/assets/images/parapet/icons/activities/seed-inspector.svg +4 -0
  21. data/app/assets/images/parapet/icons/activities/slow-test-bottlenecks.svg +4 -0
  22. data/app/assets/images/parapet/icons/activities/smart-search.svg +4 -0
  23. data/app/assets/images/parapet/icons/activities/snippet-library.svg +4 -0
  24. data/app/assets/images/parapet/icons/activities/terminal.svg +4 -0
  25. data/app/assets/images/parapet/icons/activities/unified-schema-view.svg +4 -0
  26. data/app/assets/images/parapet/icons/activities/visual-comparison.svg +3 -0
  27. data/app/assets/images/parapet/icons/activities/visual-summary-bar.svg +5 -0
  28. data/app/assets/images/parapet/icons/nav/ideas.svg +4 -0
  29. data/app/assets/images/parapet/icons/nav/languages.svg +8 -0
  30. data/app/assets/images/parapet/icons/nav/profile.svg +4 -0
  31. data/app/assets/images/parapet/icons/nav/pulse.svg +7 -0
  32. data/app/assets/images/parapet/icons/nav/settings.svg +4 -0
  33. data/app/assets/images/parapet/icons/nav/state.svg +5 -0
  34. data/app/assets/images/parapet/icons/nav/styles.svg +7 -0
  35. data/app/assets/images/parapet/icons/nav/tests.svg +4 -0
  36. data/app/assets/images/parapet/icons/nav/traffic.svg +12 -0
  37. data/app/assets/javascripts/parapet/activity-card.js +439 -0
  38. data/app/assets/javascripts/parapet/activity-cards.js +291 -0
  39. data/app/assets/javascripts/parapet/activity-registry.js +181 -0
  40. data/app/assets/javascripts/parapet/activity-toggles.js +76 -0
  41. data/app/assets/javascripts/parapet/application.js +37 -0
  42. data/app/assets/javascripts/parapet/card-failure-inspector.js +134 -0
  43. data/app/assets/javascripts/parapet/card-file-editor.js +1722 -0
  44. data/app/assets/javascripts/parapet/card-progress-area.js +297 -0
  45. data/app/assets/javascripts/parapet/card-smart-search.js +114 -0
  46. data/app/assets/javascripts/parapet/card-snippet-library.js +251 -0
  47. data/app/assets/javascripts/parapet/explorer-resizer.js +92 -0
  48. data/app/assets/javascripts/parapet/parapet_qss.js +342 -0
  49. data/app/assets/javascripts/parapet/proficiency-filter.js +53 -0
  50. data/app/assets/javascripts/parapet/sidebar-resizer.js +197 -0
  51. data/app/assets/javascripts/parapet/styles-workbench.js +819 -0
  52. data/app/assets/javascripts/parapet/tree-logic.js +320 -0
  53. data/app/assets/stylesheets/parapet/_qss_variables.scss +122 -0
  54. data/app/assets/stylesheets/parapet/parapet_qss.scss +69 -0
  55. data/app/assets/stylesheets/parapet/qss_application.css +260940 -0
  56. data/app/assets/stylesheets/parapet/qss_application.css.map +1 -0
  57. data/app/assets/stylesheets/parapet/qss_application.scss +5 -0
  58. data/app/assets/stylesheets/parapet/qss_workspace.scss +209 -0
  59. data/app/assets/stylesheets/parapet/sample.qss +22 -0
  60. data/app/controllers/parapet/application_controller.rb +54 -0
  61. data/app/controllers/parapet/base_controller.rb +18 -0
  62. data/app/controllers/parapet/build_suite/dashboard_controller.rb +10 -0
  63. data/app/controllers/parapet/css_suite/compiler_controller.rb +95 -0
  64. data/app/controllers/parapet/css_suite/dashboard_controller.rb +10 -0
  65. data/app/controllers/parapet/css_suite/preview_controller.rb +46 -0
  66. data/app/controllers/parapet/dashboard_controller.rb +8 -0
  67. data/app/controllers/parapet/drafts_controller.rb +30 -0
  68. data/app/controllers/parapet/explorers_controller.rb +53 -0
  69. data/app/controllers/parapet/files_controller.rb +208 -0
  70. data/app/controllers/parapet/footers_controller.rb +24 -0
  71. data/app/controllers/parapet/intentions_suite/dashboard_controller.rb +10 -0
  72. data/app/controllers/parapet/landing_controller.rb +14 -0
  73. data/app/controllers/parapet/monitor_suite/dashboard_controller.rb +10 -0
  74. data/app/controllers/parapet/pm_suite/publish_controller.rb +16 -0
  75. data/app/controllers/parapet/polyglot_suite/dashboard_controller.rb +10 -0
  76. data/app/controllers/parapet/runner_controller.rb +34 -0
  77. data/app/controllers/parapet/sessions_controller.rb +35 -0
  78. data/app/controllers/parapet/signal_suite/dashboard_controller.rb +10 -0
  79. data/app/controllers/parapet/test_suite/dashboard_controller.rb +10 -0
  80. data/app/controllers/parapet/widgets_controller.rb +33 -0
  81. data/app/helpers/parapet/application_helper.rb +23 -0
  82. data/app/helpers/parapet/icon_helper.rb +57 -0
  83. data/app/jobs/parapet/application_job.rb +4 -0
  84. data/app/mailers/parapet/application_mailer.rb +6 -0
  85. data/app/models/parapet/activity.rb +14 -0
  86. data/app/models/parapet/application_record.rb +5 -0
  87. data/app/models/parapet/current.rb +6 -0
  88. data/app/models/parapet/draft_recovery.rb +9 -0
  89. data/app/models/parapet/internal_record.rb +34 -0
  90. data/app/models/parapet/run_history.rb +22 -0
  91. data/app/models/parapet/runtime_setting.rb +8 -0
  92. data/app/models/parapet/session.rb +7 -0
  93. data/app/models/parapet/suite_assignment.rb +30 -0
  94. data/app/models/parapet/user.rb +12 -0
  95. data/app/services/parapet/activity_phrase_renderer.rb +35 -0
  96. data/app/services/parapet/activity_writer.rb +26 -0
  97. data/app/services/parapet/authorization.rb +198 -0
  98. data/app/services/parapet/consistency_auditor.rb +58 -0
  99. data/app/services/parapet/directory_scanner.rb +159 -0
  100. data/app/services/parapet/draft_recovery_store.rb +18 -0
  101. data/app/services/parapet/explorer_manager.rb +402 -0
  102. data/app/services/parapet/file_save_service.rb +21 -0
  103. data/app/services/parapet/git_side_ref_committer.rb +50 -0
  104. data/app/services/parapet/noun_discovery.rb +26 -0
  105. data/app/services/parapet/publish_gate.rb +83 -0
  106. data/app/services/parapet/test_runner.rb +178 -0
  107. data/app/views/layouts/parapet/application.html.erb +83 -0
  108. data/app/views/layouts/parapet/landing.html.erb +19 -0
  109. data/app/views/parapet/activities/_ai_error_explainer.html.erb +33 -0
  110. data/app/views/parapet/activities/_ai_explainer_widget.html.erb +20 -0
  111. data/app/views/parapet/activities/_calendar_widget.html.erb +31 -0
  112. data/app/views/parapet/activities/_code_snippets_widget.html.erb +22 -0
  113. data/app/views/parapet/activities/_coverage_explorer.html.erb +1 -0
  114. data/app/views/parapet/activities/_dropdown_test.html.erb +20 -0
  115. data/app/views/parapet/activities/_explorer_node.html.erb +102 -0
  116. data/app/views/parapet/activities/_explorer_tree.html.erb +16 -0
  117. data/app/views/parapet/activities/_file_editor.html.erb +183 -0
  118. data/app/views/parapet/activities/_file_explorer.html.erb +23 -0
  119. data/app/views/parapet/activities/_fix_suggestions_widget.html.erb +13 -0
  120. data/app/views/parapet/activities/_generic.html.erb +6 -0
  121. data/app/views/parapet/activities/_live_preview.html.erb +13 -0
  122. data/app/views/parapet/activities/_perspective_filters.html.erb +36 -0
  123. data/app/views/parapet/activities/_progress_area.html.erb +37 -0
  124. data/app/views/parapet/activities/_project_explorer.html.erb +1 -0
  125. data/app/views/parapet/activities/_registry_explorer.html.erb +1 -0
  126. data/app/views/parapet/activities/_run_history.html.erb +2 -0
  127. data/app/views/parapet/activities/_smart_search.html.erb +11 -0
  128. data/app/views/parapet/activities/file_explorer/_perspective_scripts.html.erb +58 -0
  129. data/app/views/parapet/activities/file_explorer/_perspectives.html.erb +0 -0
  130. data/app/views/parapet/activities/file_explorer/_viewport_scripts.html.erb +33 -0
  131. data/app/views/parapet/css_suite/_workbench.html.erb +51 -0
  132. data/app/views/parapet/dashboards/index.html.erb +113 -0
  133. data/app/views/parapet/debug_panel.html.erb +79 -0
  134. data/app/views/parapet/debug_panel_tailwind.html.erb +98 -0
  135. data/app/views/parapet/erb_patch_test.html.erb +5 -0
  136. data/app/views/parapet/explorers/show.html.erb +1 -0
  137. data/app/views/parapet/git_viewer.html.erb +62 -0
  138. data/app/views/parapet/git_viewer_after.html.erb +14 -0
  139. data/app/views/parapet/git_viewer_before.html.erb +14 -0
  140. data/app/views/parapet/git_viewer_governed.html.erb +88 -0
  141. data/app/views/parapet/git_viewer_governed_after.html.erb +36 -0
  142. data/app/views/parapet/git_viewer_governed_before.html.erb +36 -0
  143. data/app/views/parapet/git_viewer_tailwind.html.erb +88 -0
  144. data/app/views/parapet/git_viewer_thin_wrapper.html.erb +85 -0
  145. data/app/views/parapet/hierarchical_layout_test.html.erb +85 -0
  146. data/app/views/parapet/hybrid_stress_test.html.erb +25 -0
  147. data/app/views/parapet/index.html.erb +35 -0
  148. data/app/views/parapet/mutation_stress_test.html.erb +82 -0
  149. data/app/views/parapet/recursive_anchoring_test.html.erb +66 -0
  150. data/app/views/parapet/sessions/new.html.erb +28 -0
  151. data/app/views/parapet/shared/_cad_inspector.html.erb +92 -0
  152. data/app/views/parapet/shared/_discovery_sidebar.html.erb +48 -0
  153. data/app/views/parapet/shared/_explorer_bar.html.erb +71 -0
  154. data/app/views/parapet/shared/_footer.html.erb +10 -0
  155. data/app/views/parapet/shared/_footer_ideas.html.erb +36 -0
  156. data/app/views/parapet/shared/_footer_languages.html.erb +33 -0
  157. data/app/views/parapet/shared/_footer_pulse.html.erb +33 -0
  158. data/app/views/parapet/shared/_footer_state.html.erb +33 -0
  159. data/app/views/parapet/shared/_footer_styles.html.erb +37 -0
  160. data/app/views/parapet/shared/_footer_tests.html.erb +39 -0
  161. data/app/views/parapet/shared/_footer_traffic.html.erb +45 -0
  162. data/app/views/parapet/shared/_global_nav.html.erb +55 -0
  163. data/app/views/parapet/shared/_head.html.erb +4 -0
  164. data/app/views/parapet/shared/_header.html.erb +20 -0
  165. data/app/views/parapet/shared/_object_inspector.html.erb +76 -0
  166. data/app/views/parapet/shared/_ribbon_header.html.erb +3 -0
  167. data/app/views/parapet/shared/_root_selector_modal.html.erb +15 -0
  168. data/app/views/parapet/shared/_tab_bar.html.erb +62 -0
  169. data/app/views/parapet/shared/activities_ribbon/_agent_group.html.erb +15 -0
  170. data/app/views/parapet/shared/activities_ribbon/_analysis_group.html.erb +15 -0
  171. data/app/views/parapet/shared/activities_ribbon/_architect_group.html.erb +21 -0
  172. data/app/views/parapet/shared/activities_ribbon/_explorer_group.html.erb +12 -0
  173. data/app/views/parapet/shared/activities_ribbon/_inspector_group.html.erb +15 -0
  174. data/app/views/parapet/shared/activities_ribbon/_proficiency_filter.html.erb +24 -0
  175. data/app/views/parapet/shared/activities_ribbon/_runner_group.html.erb +21 -0
  176. data/app/views/parapet/shared/activities_ribbon/_spatial_inspector_group.html.erb +18 -0
  177. data/app/views/parapet/shared/activities_ribbon/_studio_group.html.erb +18 -0
  178. data/app/views/parapet/shared/activities_ribbon/_stylist_group.html.erb +18 -0
  179. data/app/views/parapet/shared/explorers/_base.html.erb +107 -0
  180. data/app/views/parapet/shared/explorers/_css.html.erb +1 -0
  181. data/app/views/parapet/shared/explorers/_intentions.html.erb +1 -0
  182. data/app/views/parapet/shared/explorers/_project.html.erb +1 -0
  183. data/app/views/parapet/shared/explorers/_tests.html.erb +1 -0
  184. data/app/views/parapet/shared/head/_meta.html.erb +3 -0
  185. data/app/views/parapet/shared/head/_styles_activities.html.erb +152 -0
  186. data/app/views/parapet/shared/head/_styles_shared.html.erb +52 -0
  187. data/app/views/parapet/shared/head/_styles_workspace.html.erb +67 -0
  188. data/app/views/parapet/shared/ribbon_header/_diagnostic_controls.html.erb +17 -0
  189. data/app/views/parapet/shared/ribbon_header/_execution_controls.html.erb +28 -0
  190. data/app/views/parapet/shared/ribbon_header/_focus_search.html.erb +5 -0
  191. data/app/views/parapet/shared/root_selector/_header.html.erb +10 -0
  192. data/app/views/parapet/shared/root_selector/_path_input.html.erb +13 -0
  193. data/app/views/parapet/shared/root_selector/_quick_select.html.erb +20 -0
  194. data/app/views/parapet/shared/root_selector/_scripts.html.erb +61 -0
  195. data/app/views/parapet/shared/root_selector/_warning.html.erb +11 -0
  196. data/app/views/parapet/shared/widgets/_base.html.erb +6 -0
  197. data/app/views/parapet/shared/widgets/_css.html.erb +79 -0
  198. data/app/views/parapet/widgets/_explainer.html.erb +17 -0
  199. data/app/views/parapet/widgets/_hotkeys.html.erb +20 -0
  200. data/app/views/parapet/widgets/_search.html.erb +68 -0
  201. data/app/views/parapet/widgets/_spatial_inspector.html.erb +54 -0
  202. data/app/views/parapet/widgets/_widget-explainer.html.erb +17 -0
  203. data/app/views/parapet/widgets/_widget-hotkeys.html.erb +20 -0
  204. data/app/views/parapet/widgets/_widget-search.html.erb +68 -0
  205. data/app/views/parapet/widgets/_widget-snippets.html.erb +18 -0
  206. data/app/views/parapet/widgets/_widget-suggestions.html.erb +15 -0
  207. data/app/views/parapet/widgets/show.html.erb +3 -0
  208. data/app/views/shared/_footer.html.erb +0 -0
  209. data/config/parapet/qss_config.yml +117 -0
  210. data/config/parapet/qss_registry.yml +14 -0
  211. data/config/routes.rb +40 -0
  212. data/db/migrate/20260916035300_create_run_histories.rb +16 -0
  213. data/db/migrate/20261002000000_expand_run_histories_for_activity_tracking.rb +7 -0
  214. data/db/parapet_migrate/20260929184200_create_parapet_users.rb +12 -0
  215. data/db/parapet_migrate/20260929184300_create_parapet_sessions.rb +9 -0
  216. data/db/parapet_migrate/20260930000000_create_parapet_runtime_settings.rb +12 -0
  217. data/db/parapet_migrate/20260930000100_create_parapet_suite_assignments.rb +14 -0
  218. data/db/parapet_migrate/20261002000000_create_parapet_activities.rb +16 -0
  219. data/db/parapet_migrate/20261002000100_create_parapet_draft_recoveries.rb +13 -0
  220. data/db/parapet_schema.rb +64 -0
  221. data/db/schema.rb +21 -0
  222. data/db/schema.released.rb +0 -0
  223. data/lib/parapet/engine.rb +11 -0
  224. data/lib/parapet/environment_guard.rb +14 -0
  225. data/lib/parapet/version.rb +3 -0
  226. data/lib/parapet-rails.rb +1 -0
  227. data/lib/parapet.rb +59 -0
  228. data/lib/tasks/parapet_qss.rake +26 -0
  229. data/lib/tasks/parapet_tasks.rake +25 -0
  230. data/lib/tasks/randomize_explorer_health.rb +101 -0
  231. metadata +423 -0
@@ -0,0 +1,79 @@
1
+ <turbo-frame id="qss-widget-content" class="anchored vertical h-full">
2
+ <div class="anchored vertical p[8] gap[10]">
3
+ <!-- Audit Monitors -->
4
+ <div class="anchored vertical gap[6]">
5
+ <!-- Legibility Floor -->
6
+ <%
7
+ legibility_issues = @audit_stats['legibility'] || 0
8
+ legibility_status = legibility_issues > 0 ? 'orange' : 'emerald'
9
+ %>
10
+ <div class="anchored vertical gap[2] group/monitor">
11
+ <div class="anchored horizontal v-mid gap[4]">
12
+ <i class="icon-type text-slate-500 text-size[6]"></i>
13
+ <span class="anchored text-size[6] text-slate-400 weight[500]">Legibility Floor</span>
14
+ <span class="anchored ml-auto text-size[6] text-<%= legibility_status %>-500"><%= legibility_issues %> issues</span>
15
+ </div>
16
+ <div class="anchored w-full h[2] bg-white/5 rounded-full">
17
+ <div class="anchored h-full <%= legibility_issues > 0 ? 'w-[70%] bg-amber-500/50' : 'w-full bg-emerald-500/50' %> rounded-full"></div>
18
+ </div>
19
+ </div>
20
+
21
+ <!-- Ergonomic Scan -->
22
+ <%
23
+ ergo_issues = @audit_stats['ergonomic'] || 0
24
+ ergo_status = ergo_issues > 0 ? 'orange' : 'emerald'
25
+ %>
26
+ <div class="anchored vertical gap[2] group/monitor">
27
+ <div class="anchored horizontal v-mid gap[4]">
28
+ <i class="icon-mouse-pointer text-slate-500 text-size[6]"></i>
29
+ <span class="anchored text-size[6] text-slate-400 weight[500]">Ergonomic Scan</span>
30
+ <span class="anchored ml-auto text-size[6] text-<%= ergo_status %>-500"><%= ergo_issues %> issues</span>
31
+ </div>
32
+ <div class="anchored w-full h[2] bg-white/5 rounded-full">
33
+ <div class="anchored h-full <%= ergo_issues > 0 ? 'w-[85%] bg-amber-500/50' : 'w-full bg-emerald-500/50' %> rounded-full"></div>
34
+ </div>
35
+ </div>
36
+
37
+ <!-- Protocol & Grammar Failures -->
38
+ <%
39
+ protocol_issues = (@audit_stats['protocol'] || 0) + (@audit_stats['grammar'] || 0)
40
+ protocol_status = protocol_issues > 0 ? 'red' : 'emerald'
41
+ %>
42
+ <div class="anchored vertical gap[2] group/monitor">
43
+ <div class="anchored horizontal v-mid gap[4]">
44
+ <i class="icon-shield-alert text-slate-500 text-size[6]"></i>
45
+ <span class="anchored text-size[6] text-slate-400 weight[500]">Protocol Status</span>
46
+ <span class="anchored ml-auto text-size[5] text-<%= protocol_status %>-400 uppercase weight[900] tracking[tighter]"><%= protocol_issues > 0 ? 'Violations' : 'Safe' %></span>
47
+ </div>
48
+ <div class="anchored w-full h[2] bg-white/5 rounded-full">
49
+ <div class="anchored h-full <%= protocol_issues > 0 ? 'w-[95%] bg-red-500/50' : 'w-full bg-emerald-500/50' %> rounded-full"></div>
50
+ </div>
51
+ </div>
52
+ </div>
53
+
54
+ <!-- Toolbar Adjectives / Grammar Registry -->
55
+ <div class="anchored vertical border-t[1] border-slate-800 pt[8] gap[4]">
56
+ <span class="anchored text-size[5] text-slate-500 weight[900] uppercase tracking[widest]">Controls</span>
57
+ <div class="anchored horizontal gap[4]">
58
+ <button class="anchored flex-1 h[20] centered bg-white/5 border[1] border-slate-700 rounded[2] hover:bg-indigo-500/20 hover:border-indigo-500/50 clickable smooth group/btn" onclick="QSSEngine.showAdjectivePalette()">
59
+ <i class="icon-palette text-slate-400 group-hover/btn:text-indigo-400 text-size[6]"></i>
60
+ <span class="ml[4] text-size[5] text-slate-400 group-hover/btn:text-indigo-300">Palette</span>
61
+ </button>
62
+ <button class="anchored flex-1 h[20] centered bg-white/5 border[1] border-slate-700 rounded[2] hover:bg-amber-500/20 hover:border-amber-500/50 clickable smooth group/btn" onclick="QSSEngine.toggleStateLocker()">
63
+ <i class="icon-lock text-slate-400 group-hover/btn:text-amber-400 text-size[6]"></i>
64
+ <span class="ml[4] text-size[5] text-slate-400 group-hover/btn:text-amber-300">Locker</span>
65
+ </button>
66
+ </div>
67
+ <div class="anchored horizontal gap[4] mt[4]">
68
+ <button class="anchored flex-1 h[20] centered bg-white/5 border[1] border-slate-700 rounded[2] hover:bg-emerald-500/20 hover:border-emerald-500/50 clickable smooth group/btn" onclick="QSSEngine.showAIExplainer()">
69
+ <i class="icon-sparkles text-slate-400 group-hover/btn:text-emerald-400 text-size[6]"></i>
70
+ <span class="ml[4] text-size[5] text-slate-400 group-hover/btn:text-emerald-300">Explain</span>
71
+ </button>
72
+ <button class="anchored flex-1 h[20] centered bg-white/5 border[1] border-slate-700 rounded[2] hover:bg-violet-500/20 hover:border-violet-500/50 clickable smooth group/btn" onclick="QSSEngine.showSnippets()">
73
+ <i class="icon-code text-slate-400 group-hover/btn:text-violet-400 text-size[6]"></i>
74
+ <span class="ml[4] text-size[5] text-slate-400 group-hover/btn:text-violet-300">Snippets</span>
75
+ </button>
76
+ </div>
77
+ </div>
78
+ </div>
79
+ </turbo-frame>
@@ -0,0 +1,17 @@
1
+ <turbo-frame id="active-widget">
2
+ <div class="qss-p-3 qss-flex qss-flex-col qss-h-full qss-overflow-hidden">
3
+ <div class="qss-flex qss-items-center qss-gap-2 qss-mb-2">
4
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="qss-text-indigo-400">
5
+ <path d="M12 8V4H8"></path><rect width="16" height="12" x="4" y="8" rx="2"></rect><path d="M2 14h2"></path><path d="M20 14h2"></path><path d="M15 13v2"></path><path d="M9 13v2"></path>
6
+ </svg>
7
+ <span class="qss-text-[10px] qss-font-bold qss-uppercase qss-tracking-widest qss-text-slate-400">AI Explainer</span>
8
+ </div>
9
+ <div class="qss-flex-1 qss-overflow-y-auto custom-scrollbar">
10
+ <div class="qss-bg-indigo-500/5 qss-border qss-border-indigo-500/10 qss-rounded qss-p-2 qss-mb-2">
11
+ <p class="qss-text-[10px] qss-text-slate-400 qss-leading-relaxed qss-italic">
12
+ Analyzing context... Focus on a failing node to generate explanation.
13
+ </p>
14
+ </div>
15
+ </div>
16
+ </div>
17
+ </turbo-frame>
@@ -0,0 +1,20 @@
1
+ <turbo-frame id="active-widget">
2
+ <div class="qss-p-3 qss-flex qss-flex-col qss-h-full qss-overflow-hidden">
3
+ <div class="qss-flex qss-items-center qss-gap-2 qss-mb-2">
4
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="qss-text-emerald-400">
5
+ <rect width="20" height="16" x="2" y="4" rx="2" ry="2"></rect><path d="M6 8h.01"></path><path d="M10 8h.01"></path><path d="M14 8h.01"></path><path d="M18 8h.01"></path><path d="M8 12h.01"></path><path d="M12 12h.01"></path><path d="M16 12h.01"></path><path d="M7 16h10"></path>
6
+ </svg>
7
+ <span class="qss-text-[10px] qss-font-bold qss-uppercase qss-tracking-widest qss-text-slate-400">Hotkeys</span>
8
+ </div>
9
+ <div class="qss-flex-1 qss-overflow-y-auto custom-scrollbar qss-space-y-2">
10
+ <div class="qss-flex qss-justify-between qss-items-center qss-border-b qss-border-slate-800/50 qss-pb-1">
11
+ <span class="qss-text-[9px] qss-text-slate-500 qss-uppercase">Run Focused Test</span>
12
+ <kbd class="qss-px-1.5 qss-py-0.5 qss-rounded qss-bg-slate-800 qss-text-slate-300 qss-text-[9px] qss-font-mono qss-border qss-border-slate-700">Cmd+R</kbd>
13
+ </div>
14
+ <div class="qss-flex qss-justify-between qss-items-center qss-border-b qss-border-slate-800/50 qss-pb-1">
15
+ <span class="qss-text-[9px] qss-text-slate-500 qss-uppercase">Smart Search</span>
16
+ <kbd class="qss-px-1.5 qss-py-0.5 qss-rounded qss-bg-slate-800 qss-text-slate-300 qss-text-[9px] qss-font-mono qss-border qss-border-slate-700">Cmd+K</kbd>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ </turbo-frame>
@@ -0,0 +1,68 @@
1
+ <turbo-frame id="active-widget">
2
+ <div class="qss-flex qss-flex-col qss-h-full qss-bg-[#111418] qss-overflow-hidden">
3
+ <div class="qss-p-3 qss-border-b qss-border-slate-800/50">
4
+ <div class="qss-flex qss-items-center qss-gap-2 qss-mb-2">
5
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-text-indigo-400">
6
+ <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>
7
+ </svg>
8
+ <span class="qss-text-[10px] qss-font-bold qss-uppercase qss-tracking-widest qss-text-slate-400">Smart Search</span>
9
+ </div>
10
+ <div class="qss-relative qss-group">
11
+ <input type="text"
12
+ class="qss-w-full qss-bg-[#0f1115] qss-border qss-border-slate-700/50 qss-rounded qss-px-8 qss-py-1.5 qss-text-[11px] qss-text-slate-300 focus:qss-outline-none focus:qss-border-indigo-500/50 qss-transition-all placeholder:qss-text-slate-600"
13
+ placeholder="Ask anything or search code...">
14
+ <div class="qss-absolute qss-left-2.5 qss-top-1/2 -qss-translate-y-1/2 qss-text-slate-500 group-focus-within:qss-text-indigo-400 qss-transition-colors">
15
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
16
+ <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>
17
+ </svg>
18
+ </div>
19
+ </div>
20
+ <div class="qss-flex qss-gap-1.5 qss-mt-2 qss-overflow-x-auto qss-pb-1 qss-no-scrollbar">
21
+ <span class="qss-text-[9px] qss-bg-slate-800/50 qss-text-slate-400 qss-px-1.5 qss-py-0.5 qss-rounded qss-border qss-border-slate-700/30 qss-whitespace-nowrap qss-cursor-pointer hover:qss-bg-slate-700/50 qss-transition-colors">Files</span>
22
+ <span class="qss-text-[9px] qss-bg-slate-800/50 qss-text-slate-400 qss-px-1.5 qss-py-0.5 qss-rounded qss-border qss-border-slate-700/30 qss-whitespace-nowrap qss-cursor-pointer hover:qss-bg-slate-700/50 qss-transition-colors">Symbols</span>
23
+ <span class="qss-text-[9px] qss-bg-slate-800/50 qss-text-slate-400 qss-px-1.5 qss-py-0.5 qss-rounded qss-border qss-border-slate-700/30 qss-whitespace-nowrap qss-cursor-pointer hover:qss-bg-slate-700/50 qss-transition-colors">AI Help</span>
24
+ </div>
25
+ </div>
26
+
27
+ <div class="qss-flex-1 qss-overflow-y-auto qss-p-2 custom-scrollbar qss-space-y-3">
28
+ <div>
29
+ <div class="qss-text-[9px] qss-font-bold qss-text-slate-500 qss-uppercase qss-tracking-widest qss-px-1 qss-mb-2">Recent & Relevant</div>
30
+ <div class="qss-space-y-1">
31
+ <div class="qss-flex qss-items-center qss-gap-2 qss-p-1.5 qss-rounded hover:qss-bg-white/5 qss-cursor-pointer qss-group qss-transition-colors">
32
+ <div class="qss-w-6 qss-h-6 qss-rounded qss-bg-indigo-500/10 qss-flex qss-items-center qss-justify-center qss-text-indigo-400">
33
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
34
+ <path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><line x1="10" y1="9" x2="8" y2="9"></line>
35
+ </svg>
36
+ </div>
37
+ <div class="qss-flex-1 qss-min-w-0">
38
+ <div class="qss-text-[10px] qss-text-slate-300 qss-truncate">dashboard_controller.rb</div>
39
+ <div class="qss-text-[8px] qss-text-slate-500 qss-truncate">app/controllers/parapet/</div>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ <div>
46
+ <div class="qss-text-[9px] qss-font-bold qss-text-slate-500 qss-uppercase qss-tracking-widest qss-px-1 qss-mb-2">Try searching for...</div>
47
+ <div class="qss-grid qss-grid-cols-1 qss-gap-1">
48
+ <div class="qss-text-[10px] qss-text-slate-400 qss-bg-white/5 qss-p-2 qss-rounded qss-border qss-border-slate-700/20 hover:qss-border-indigo-500/30 qss-cursor-pointer qss-transition-all">
49
+ "How do I add a new activity card?"
50
+ </div>
51
+ <div class="qss-text-[10px] qss-text-slate-400 qss-bg-white/5 qss-p-2 qss-rounded qss-border qss-border-slate-700/20 hover:qss-border-indigo-500/30 qss-cursor-pointer qss-transition-all">
52
+ "Find all Novice proficiency elements"
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
57
+
58
+ <div class="qss-px-3 qss-py-2 qss-border-t qss-border-slate-800/50 qss-bg-[#0f1115]/50 qss-flex qss-items-center qss-justify-between">
59
+ <div class="qss-flex qss-items-center qss-gap-1.5 qss-text-[9px] qss-text-slate-500">
60
+ <div class="qss-w-1.5 qss-h-1.5 qss-rounded-full qss-bg-emerald-500/50"></div>
61
+ <span>AI Index Ready</span>
62
+ </div>
63
+ <div class="qss-text-[9px] qss-text-slate-600">
64
+ <span class="qss-bg-slate-800 qss-px-1 qss-rounded qss-border qss-border-slate-700/50">⌘K</span>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ </turbo-frame>
@@ -0,0 +1,54 @@
1
+ <div class="qss-flex qss-flex-col qss-gap-3">
2
+ <!-- Selection Info -->
3
+ <div class="qss-flex qss-items-center qss-justify-between">
4
+ <div class="qss-flex qss-items-center qss-gap-2">
5
+ <div class="qss-w-3 qss-h-3 qss-rounded-sm qss-bg-indigo-500"></div>
6
+ <span class="qss-text-[10px] qss-font-bold qss-text-white qss-uppercase">#selected-element</span>
7
+ </div>
8
+ <span class="qss-text-[9px] qss-text-slate-500 qss-font-mono">div.qss-absolute</span>
9
+ </div>
10
+
11
+ <!-- Spatial Grid -->
12
+ <div class="qss-grid qss-grid-cols-2 qss-gap-2">
13
+ <div class="qss-flex qss-flex-col qss-gap-1">
14
+ <label class="qss-text-[8px] qss-font-bold qss-text-slate-500 qss-uppercase">X-Position</label>
15
+ <div class="qss-flex qss-items-center qss-gap-2 qss-bg-slate-800/50 qss-px-2 qss-py-1 qss-rounded qss-border qss-border-slate-700">
16
+ <span class="qss-text-[10px] qss-font-mono qss-text-indigo-400">120</span>
17
+ <span class="qss-text-[8px] qss-text-slate-600">units</span>
18
+ </div>
19
+ </div>
20
+ <div class="qss-flex qss-flex-col qss-gap-1">
21
+ <label class="qss-text-[8px] qss-font-bold qss-text-slate-500 qss-uppercase">Y-Position</label>
22
+ <div class="qss-flex qss-items-center qss-gap-2 qss-bg-slate-800/50 qss-px-2 qss-py-1 qss-rounded qss-border qss-border-slate-700">
23
+ <span class="qss-text-[10px] qss-font-mono qss-text-indigo-400">45</span>
24
+ <span class="qss-text-[8px] qss-text-slate-600">units</span>
25
+ </div>
26
+ </div>
27
+ <div class="qss-flex qss-flex-col qss-gap-1">
28
+ <label class="qss-text-[8px] qss-font-bold qss-text-slate-500 qss-uppercase">Width</label>
29
+ <div class="qss-flex qss-items-center qss-gap-2 qss-bg-slate-800/50 qss-px-2 qss-py-1 qss-rounded qss-border qss-border-slate-700">
30
+ <span class="qss-text-[10px] qss-font-mono qss-text-indigo-400">400</span>
31
+ <span class="qss-text-[8px] qss-text-slate-600">units</span>
32
+ </div>
33
+ </div>
34
+ <div class="qss-flex qss-flex-col qss-gap-1">
35
+ <label class="qss-text-[8px] qss-font-bold qss-text-slate-500 qss-uppercase">Height</label>
36
+ <div class="qss-flex qss-items-center qss-gap-2 qss-bg-slate-800/50 qss-px-2 qss-py-1 qss-rounded qss-border qss-border-slate-700">
37
+ <span class="qss-text-[10px] qss-font-mono qss-text-indigo-400">300</span>
38
+ <span class="qss-text-[8px] qss-text-slate-600">units</span>
39
+ </div>
40
+ </div>
41
+ </div>
42
+
43
+ <!-- Depth Control -->
44
+ <div class="qss-flex qss-flex-col qss-gap-1">
45
+ <label class="qss-text-[8px] qss-font-bold qss-text-slate-500 qss-uppercase">Visual Depth (Z)</label>
46
+ <div class="qss-flex qss-items-center qss-gap-1">
47
+ <% ['canvas', 'content', 'ui', 'overlay', 'modal'].each do |d| %>
48
+ <div class="qss-flex-1 qss-text-center qss-py-1 qss-rounded qss-text-[8px] qss-bg-slate-800/30 qss-border qss-border-slate-800 qss-text-slate-500 hover:qss-text-white qss-cursor-pointer <%= 'qss-bg-indigo-500/10 qss-border-indigo-500/30 qss-text-indigo-400' if d == 'content' %>">
49
+ <%= d.capitalize %>
50
+ </div>
51
+ <% end %>
52
+ </div>
53
+ </div>
54
+ </div>
@@ -0,0 +1,17 @@
1
+ <turbo-frame id="active-widget">
2
+ <div class="qss-p-3 qss-flex qss-flex-col qss-h-full qss-overflow-hidden">
3
+ <div class="qss-flex qss-items-center qss-gap-2 qss-mb-2">
4
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="qss-text-indigo-400">
5
+ <path d="M12 8V4H8"></path><rect width="16" height="12" x="4" y="8" rx="2"></rect><path d="M2 14h2"></path><path d="M20 14h2"></path><path d="M15 13v2"></path><path d="M9 13v2"></path>
6
+ </svg>
7
+ <span class="qss-text-[10px] qss-font-bold qss-uppercase qss-tracking-widest qss-text-slate-400">AI Explainer</span>
8
+ </div>
9
+ <div class="qss-flex-1 qss-overflow-y-auto custom-scrollbar">
10
+ <div class="qss-bg-indigo-500/5 qss-border qss-border-indigo-500/10 qss-rounded qss-p-2 qss-mb-2">
11
+ <p class="qss-text-[10px] qss-text-slate-400 qss-leading-relaxed qss-italic">
12
+ Analyzing context... Focus on a failing node to generate explanation.
13
+ </p>
14
+ </div>
15
+ </div>
16
+ </div>
17
+ </turbo-frame>
@@ -0,0 +1,20 @@
1
+ <turbo-frame id="active-widget">
2
+ <div class="qss-p-3 qss-flex qss-flex-col qss-h-full qss-overflow-hidden">
3
+ <div class="qss-flex qss-items-center qss-gap-2 qss-mb-2">
4
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="qss-text-emerald-400">
5
+ <rect width="20" height="16" x="2" y="4" rx="2" ry="2"></rect><path d="M6 8h.01"></path><path d="M10 8h.01"></path><path d="M14 8h.01"></path><path d="M18 8h.01"></path><path d="M8 12h.01"></path><path d="M12 12h.01"></path><path d="M16 12h.01"></path><path d="M7 16h10"></path>
6
+ </svg>
7
+ <span class="qss-text-[10px] qss-font-bold qss-uppercase qss-tracking-widest qss-text-slate-400">Hotkeys</span>
8
+ </div>
9
+ <div class="qss-flex-1 qss-overflow-y-auto custom-scrollbar qss-space-y-2">
10
+ <div class="qss-flex qss-justify-between qss-items-center qss-border-b qss-border-slate-800/50 qss-pb-1">
11
+ <span class="qss-text-[9px] qss-text-slate-500 qss-uppercase">Run Focused Test</span>
12
+ <kbd class="qss-px-1.5 qss-py-0.5 qss-rounded qss-bg-slate-800 qss-text-slate-300 qss-text-[9px] qss-font-mono qss-border qss-border-slate-700">Cmd+R</kbd>
13
+ </div>
14
+ <div class="qss-flex qss-justify-between qss-items-center qss-border-b qss-border-slate-800/50 qss-pb-1">
15
+ <span class="qss-text-[9px] qss-text-slate-500 qss-uppercase">Smart Search</span>
16
+ <kbd class="qss-px-1.5 qss-py-0.5 qss-rounded qss-bg-slate-800 qss-text-slate-300 qss-text-[9px] qss-font-mono qss-border qss-border-slate-700">Cmd+K</kbd>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ </turbo-frame>
@@ -0,0 +1,68 @@
1
+ <turbo-frame id="active-widget">
2
+ <div class="qss-flex qss-flex-col qss-h-full qss-bg-[#111418] qss-overflow-hidden">
3
+ <div class="qss-p-3 qss-border-b qss-border-slate-800/50">
4
+ <div class="qss-flex qss-items-center qss-gap-2 qss-mb-2">
5
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-text-indigo-400">
6
+ <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>
7
+ </svg>
8
+ <span class="qss-text-[10px] qss-font-bold qss-uppercase qss-tracking-widest qss-text-slate-400">Smart Search</span>
9
+ </div>
10
+ <div class="qss-relative qss-group">
11
+ <input type="text"
12
+ class="qss-w-full qss-bg-[#0f1115] qss-border qss-border-slate-700/50 qss-rounded qss-px-8 qss-py-1.5 qss-text-[11px] qss-text-slate-300 focus:qss-outline-none focus:qss-border-indigo-500/50 qss-transition-all placeholder:qss-text-slate-600"
13
+ placeholder="Ask anything or search code...">
14
+ <div class="qss-absolute qss-left-2.5 qss-top-1/2 -qss-translate-y-1/2 qss-text-slate-500 group-focus-within:qss-text-indigo-400 qss-transition-colors">
15
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
16
+ <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>
17
+ </svg>
18
+ </div>
19
+ </div>
20
+ <div class="qss-flex qss-gap-1.5 qss-mt-2 qss-overflow-x-auto qss-pb-1 qss-no-scrollbar">
21
+ <span class="qss-text-[9px] qss-bg-slate-800/50 qss-text-slate-400 qss-px-1.5 qss-py-0.5 qss-rounded qss-border qss-border-slate-700/30 qss-whitespace-nowrap qss-cursor-pointer hover:qss-bg-slate-700/50 qss-transition-colors">Files</span>
22
+ <span class="qss-text-[9px] qss-bg-slate-800/50 qss-text-slate-400 qss-px-1.5 qss-py-0.5 qss-rounded qss-border qss-border-slate-700/30 qss-whitespace-nowrap qss-cursor-pointer hover:qss-bg-slate-700/50 qss-transition-colors">Symbols</span>
23
+ <span class="qss-text-[9px] qss-bg-slate-800/50 qss-text-slate-400 qss-px-1.5 qss-py-0.5 qss-rounded qss-border qss-border-slate-700/30 qss-whitespace-nowrap qss-cursor-pointer hover:qss-bg-slate-700/50 qss-transition-colors">AI Help</span>
24
+ </div>
25
+ </div>
26
+
27
+ <div class="qss-flex-1 qss-overflow-y-auto qss-p-2 custom-scrollbar qss-space-y-3">
28
+ <div>
29
+ <div class="qss-text-[9px] qss-font-bold qss-text-slate-500 qss-uppercase qss-tracking-widest qss-px-1 qss-mb-2">Recent & Relevant</div>
30
+ <div class="qss-space-y-1">
31
+ <div class="qss-flex qss-items-center qss-gap-2 qss-p-1.5 qss-rounded hover:qss-bg-white/5 qss-cursor-pointer qss-group qss-transition-colors">
32
+ <div class="qss-w-6 qss-h-6 qss-rounded qss-bg-indigo-500/10 qss-flex qss-items-center qss-justify-center qss-text-indigo-400">
33
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
34
+ <path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><line x1="10" y1="9" x2="8" y2="9"></line>
35
+ </svg>
36
+ </div>
37
+ <div class="qss-flex-1 qss-min-w-0">
38
+ <div class="qss-text-[10px] qss-text-slate-300 qss-truncate">dashboard_controller.rb</div>
39
+ <div class="qss-text-[8px] qss-text-slate-500 qss-truncate">app/controllers/parapet/</div>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ <div>
46
+ <div class="qss-text-[9px] qss-font-bold qss-text-slate-500 qss-uppercase qss-tracking-widest qss-px-1 qss-mb-2">Try searching for...</div>
47
+ <div class="qss-grid qss-grid-cols-1 qss-gap-1">
48
+ <div class="qss-text-[10px] qss-text-slate-400 qss-bg-white/5 qss-p-2 qss-rounded qss-border qss-border-slate-700/20 hover:qss-border-indigo-500/30 qss-cursor-pointer qss-transition-all">
49
+ "How do I add a new activity card?"
50
+ </div>
51
+ <div class="qss-text-[10px] qss-text-slate-400 qss-bg-white/5 qss-p-2 qss-rounded qss-border qss-border-slate-700/20 hover:qss-border-indigo-500/30 qss-cursor-pointer qss-transition-all">
52
+ "Find all Novice proficiency elements"
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
57
+
58
+ <div class="qss-px-3 qss-py-2 qss-border-t qss-border-slate-800/50 qss-bg-[#0f1115]/50 qss-flex qss-items-center qss-justify-between">
59
+ <div class="qss-flex qss-items-center qss-gap-1.5 qss-text-[9px] qss-text-slate-500">
60
+ <div class="qss-w-1.5 qss-h-1.5 qss-rounded-full qss-bg-emerald-500/50"></div>
61
+ <span>AI Index Ready</span>
62
+ </div>
63
+ <div class="qss-text-[9px] qss-text-slate-600">
64
+ <span class="qss-bg-slate-800 qss-px-1 qss-rounded qss-border qss-border-slate-700/50">⌘K</span>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ </turbo-frame>
@@ -0,0 +1,18 @@
1
+ <turbo-frame id="active-widget">
2
+ <div class="qss-p-3 qss-flex qss-flex-col qss-h-full qss-overflow-hidden">
3
+ <div class="qss-flex qss-items-center qss-gap-2 qss-mb-2">
4
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="qss-text-blue-400">
5
+ <polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline>
6
+ </svg>
7
+ <span class="qss-text-[10px] qss-font-bold qss-uppercase qss-tracking-widest qss-text-slate-400">Snippets & Syntax</span>
8
+ </div>
9
+ <div class="qss-flex-1 qss-overflow-y-auto custom-scrollbar qss-space-y-2">
10
+ <div class="qss-group qss-cursor-pointer">
11
+ <div class="qss-text-[9px] qss-text-slate-500 group-hover:qss-text-blue-400 qss-transition-colors qss-uppercase qss-font-mono">expect().to receive()</div>
12
+ <div class="qss-bg-black/20 qss-rounded qss-p-1.5 qss-border qss-border-slate-800/50 qss-mt-1">
13
+ <code class="qss-text-[9px] qss-text-slate-300">expect(obj).to receive(:msg)</code>
14
+ </div>
15
+ </div>
16
+ </div>
17
+ </div>
18
+ </turbo-frame>
@@ -0,0 +1,15 @@
1
+ <turbo-frame id="active-widget">
2
+ <div class="qss-p-3 qss-flex qss-flex-col qss-h-full qss-overflow-hidden">
3
+ <div class="qss-flex qss-items-center qss-gap-2 qss-mb-2">
4
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="qss-text-amber-400">
5
+ <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path>
6
+ </svg>
7
+ <span class="qss-text-[10px] qss-font-bold qss-uppercase qss-tracking-widest qss-text-slate-400">Fix Suggestions</span>
8
+ </div>
9
+ <div class="qss-flex-1 qss-overflow-y-auto custom-scrollbar">
10
+ <div class="qss-text-[10px] qss-text-slate-500 qss-italic qss-px-1">
11
+ No active failures detected.
12
+ </div>
13
+ </div>
14
+ </div>
15
+ </turbo-frame>
@@ -0,0 +1,3 @@
1
+ <%= turbo_frame_tag "auxiliary-widget-frame" do %>
2
+ <%= render @partial_path %>
3
+ <% end %>
File without changes
@@ -0,0 +1,117 @@
1
+ # Parapet's QSS configuration -- deep-merged over the core defaults in
2
+ # config/qss/grammar.yml by bin/qss-sync.rb. Created 2026-09-23 (QSS item C).
3
+
4
+ config:
5
+ anchor: "#qss-canvas"
6
+ portal_root: "#pp-portal-root"
7
+
8
+ # Colors added to (never replacing) the core default palette. This is the set that was
9
+ # actually compiled into _qss_variables.scss on 2026-09-23 (64 total with the core
10
+ # defaults) so moving it here changes no rendering.
11
+ palette:
12
+ brand-header: "#1a1d23"
13
+ brand-main: "#0f1115"
14
+ novice: "#10b981"
15
+ intermediate: "#f59e0b"
16
+ advanced: "#6366f1"
17
+ pro: "#8b5cf6"
18
+ power: "#ec4899"
19
+ shared: "#64748b"
20
+ floating: "#94a3b8"
21
+ indigo-300: "#a5b4fc"
22
+ indigo-400: "#818cf8"
23
+ indigo-500: "#6366f1"
24
+ indigo-600: "#4f46e5"
25
+ rose-400: "#fb7185"
26
+ rose-600: "#e11d48"
27
+ emerald-300: "#6ee7b7"
28
+ emerald-400: "#34d399"
29
+ emerald-500: "#10b981"
30
+ emerald-600: "#059669"
31
+ emerald-950: "#064e3b"
32
+ amber-200: "#fde68a"
33
+ amber-300: "#fcd34d"
34
+ amber-400: "#fbbf24"
35
+ amber-500: "#f59e0b"
36
+ amber-600: "#d97706"
37
+ blue-50: "#eff6ff"
38
+ blue-400: "#60a5fa"
39
+ blue-500: "#3b82f6"
40
+ blue-600: "#2563eb"
41
+ blue-700: "#1d4ed8"
42
+ blue-900: "#1e3a8a"
43
+ red-300: "#fca5a5"
44
+ red-400: "#f87171"
45
+ red-500: "#ef4444"
46
+ red-600: "#dc2626"
47
+ red-900: "#7f1d1d"
48
+ red-950: "#450a0a"
49
+ violet-300: "#c4b5fd"
50
+ violet-400: "#a78bfa"
51
+ violet-500: "#8b5cf6"
52
+ violet-600: "#7c3aed"
53
+ sky-400: "#38bdf8"
54
+ gray-100: "#f3f4f6"
55
+ gray-500: "#6b7280"
56
+ gray-600: "#4b5563"
57
+ orange-500: "#f97316"
58
+ yellow-500: "#eab308"
59
+ pink-500: "#ec4899"
60
+ # --- Present in the old grammar.yml palette (81 colors, "live census" 2026-09-22) but
61
+ # --- NEVER compiled into the live CSS (variables file had 64). Uncommenting activates
62
+ # --- them (a rendering change: views using cyan/lime/teal/etc. would start to color).
63
+ # sky-500: "#0ea5e9"
64
+ # sky-600: "#0284c7"
65
+ # orange-400: "#fb923c"
66
+ # orange-600: "#ea580c"
67
+ # yellow-400: "#facc15"
68
+ # pink-400: "#f472b6"
69
+ # pink-600: "#db2777"
70
+ # cyan-400: "#22d3ee"
71
+ # cyan-500: "#06b6d4"
72
+ # cyan-600: "#0891b2"
73
+ # green-400: "#4ade80"
74
+ # lime-400: "#a3e635"
75
+ # lime-500: "#84cc16"
76
+ # lime-600: "#65a30d"
77
+ # teal-400: "#2dd4bf"
78
+ # teal-500: "#14b8a6"
79
+ # teal-600: "#0d9488"
80
+
81
+ group_names:
82
+ - row
83
+ - eye
84
+ - focus
85
+ - mini-explorer
86
+ - new-menu
87
+ - link-menu
88
+ - btn
89
+
90
+ # Adjectives Parapet adds to the core whitelist, by category.
91
+ grammar_extensions:
92
+ internal:
93
+ - qss-inspector-selected
94
+ - qss-canvas # anchor id, also used as a class in 4 layout test views
95
+ # Parapet structural frame names; the auditor specs (spec/services/parapet/qss_auditor_spec.rb,
96
+ # qss_native_auditor_spec.rb) treat these as legitimate first-party classes.
97
+ - pp-content
98
+ - pp-frame
99
+ - pp-header
100
+ - pp-sidebar
101
+ - pp-workspace
102
+
103
+ # Auditor settings for Parapet. INTERIM: the prefix and word lists are a stopgap until item B
104
+ # (id parser / base-object vocabulary) decides how structural elements are identified.
105
+ # The extra words are the CSS Suite / IDE panel names (physics, chemistry, alchemy, ...) that
106
+ # were appended to the auditor regex in commit e4704ef (2026-09-01).
107
+ auditor:
108
+ id_prefix: "pp-"
109
+ structural_words: [header, footer, sidebar, workspace, main, panel, frame, wrapper, nav, aside, portal, dropdown, modal, overlay, tooltip, root, canvas, section, container, stage, source, compiled, bar, content, interface, widgets, resizer, branding, tagline, grammar, physics, chemistry, alchemy, stats, stat, target, button, dot, title, list, item, input, editor]
110
+ narrow_words: [header, footer, sidebar, workspace, main, panel, frame, wrapper, nav, aside]
111
+ icon_prefixes: [fa-, bi-, icon-]
112
+ registry_path: "config/parapet/qss_registry.yml"
113
+
114
+ # Where bin/qss-sync.rb writes Parapet's own SCSS settings (imported by qss_application.scss before core).
115
+ # Run the sync with: bundle exec rake app:parapet:qss:sync
116
+ sync_targets:
117
+ variables: app/assets/stylesheets/parapet/_qss_variables.scss
@@ -0,0 +1,14 @@
1
+ # Parapet's QSS registry (item B): the project's own vocabulary, read at runtime by QSS::QssNativeAuditor.
2
+ # See lib/qss/qss_native_auditor.rb (Registry) for the schema. Nothing here is required; an empty registry
3
+ # simply means every QSS-actor id is reported as unregistered.
4
+ #
5
+ # allow_digits: true # only if names such as oauth2 are wanted (default false)
6
+ # functions: [save, delete] # the open qss-function vocabulary (at least 3 letters, hyphens only)
7
+ # types: # each entry records ONLY what the type adds over its base
8
+ # divider-hr: # {qualifier}-{nativeTag}
9
+ # dimensions: { height: 1 } # exact facts in QSS units, a percentage, or an aspect-ratio
10
+ # workspace-QSSObject: # {qualifier}-QSSObject
11
+ # structural: true
12
+ allow_digits: false
13
+ functions: []
14
+ types: {}
data/config/routes.rb ADDED
@@ -0,0 +1,40 @@
1
+ Parapet::Engine.routes.draw do
2
+ root to: "dashboard#index"
3
+ get "login", to: "sessions#new", as: :login
4
+ post "login", to: "sessions#create"
5
+ delete "logout", to: "sessions#destroy", as: :logout
6
+ get "dashboard", to: "dashboard#index", as: :dashboard
7
+
8
+ # Suite Top-Level Routes
9
+ get "css", to: "css_suite/dashboard#index", as: :css_suite
10
+ get "intentions", to: "intentions_suite/dashboard#index", as: :intentions_suite
11
+ get "tests", to: "test_suite/dashboard#index", as: :tests_suite
12
+ get "signal", to: "signal_suite/dashboard#index", as: :signal_suite
13
+ get "monitor", to: "monitor_suite/dashboard#index", as: :monitor_suite
14
+ get "polyglot", to: "polyglot_suite/dashboard#index", as: :polyglot_suite
15
+ get "build", to: "build_suite/dashboard#index", as: :build_suite
16
+
17
+ namespace :pm_suite do
18
+ post "publish", to: "publish#create"
19
+ end
20
+
21
+ get "files", to: "files#index"
22
+ get "files/content", to: "files#show"
23
+ get "files/assets", to: "files#assets"
24
+ get "css_suite/grammar", to: "css_suite/compiler#grammar"
25
+ get "css_suite/live", to: "css_suite/compiler#live"
26
+ post "css_suite/compile", to: "css_suite/compiler#compile"
27
+ post "css_suite/flush", to: "css_suite/compiler#flush"
28
+ get "css_suite/preview", to: "css_suite/preview#show"
29
+ get "files/draft", to: "drafts#show"
30
+ patch "files/draft", to: "drafts#update"
31
+ delete "files/draft", to: "drafts#destroy"
32
+ patch "files", to: "files#update"
33
+ post "files/move", to: "files#move"
34
+ post "runner/execute", to: "runner#execute"
35
+ get "runner/detect", to: "runner#detect_frameworks"
36
+ get "runner/status", to: "runner#status"
37
+ get "widgets/:type", to: "widgets#show", as: :widget
38
+ get "explorers/:type", to: "explorers#show", as: :explorer
39
+ get "footers/:suite", to: "footers#show", as: :footer
40
+ end
@@ -0,0 +1,16 @@
1
+ class CreateRunHistories < ActiveRecord::Migration[7.1]
2
+ def change
3
+ create_table :run_history do |t|
4
+ t.string :run_type, null: false
5
+ t.string :command, null: false
6
+ t.string :status, null: false
7
+ t.integer :exit_code
8
+ t.text :raw_output
9
+ t.string :triggered_by_actor_type, null: false
10
+ t.datetime :started_at, null: false
11
+ t.datetime :finished_at
12
+
13
+ t.timestamps
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ class ExpandRunHistoriesForActivityTracking < ActiveRecord::Migration[7.1]
2
+ def change
3
+ add_column :run_history, :user_id, :integer
4
+ add_column :run_history, :performed_via, :string, null: false, default: "human"
5
+ add_index :run_history, :user_id
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ class CreateParapetUsers < ActiveRecord::Migration[8.1]
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :email_address, null: false
5
+ t.string :password_digest, null: false
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :users, :email_address, unique: true
11
+ end
12
+ end