total-recall-brain 3.40.1 → 3.40.2

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 (186) hide show
  1. package/README.md +152 -41
  2. package/bin/total-recall.mjs +16 -76
  3. package/docs/reference/cli-reference.md +10 -10
  4. package/extension/background.js +6 -2
  5. package/extension/config.js +8 -0
  6. package/extension/lib/brain-client.js +29 -4
  7. package/extension/options/options.html +1 -0
  8. package/extension/sidepanel/sidepanel.html +1 -0
  9. package/frontend/dist/assets/{index-CvQRdT2j.css → index-AGUes-VG.css} +1 -1
  10. package/frontend/dist/assets/index-Bt5iVPZj.js +5618 -0
  11. package/frontend/dist/index.html +2 -2
  12. package/frontend/src/api/keys.ts +9 -2
  13. package/frontend/src/api/plugins.ts +4 -0
  14. package/frontend/src/components/plugins/card/CardEngine.tsx +2 -1
  15. package/frontend/src/components/plugins/card/card.css +1 -1
  16. package/frontend/src/pages/IntegrationsPage.tsx +315 -8
  17. package/frontend/src/pages/PluginsPage.tsx +532 -87
  18. package/package.json +6 -5
  19. package/scaffold/.agent/skills/meta-harness/references/optimized/original.md +1 -1
  20. package/scaffold/.agent/skills/meta-harness/references/optimized/section-09.md +1 -1
  21. package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +10 -10
  22. package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +1 -6
  23. package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +0 -1
  24. package/scaffold/.agent/skills/total-recall/plugins/auth/src/browser-session.mjs +309 -4
  25. package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +44 -34
  26. package/scaffold/.agent/skills/total-recall/plugins/auth/src/google-oauth.mjs +6 -4
  27. package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-catalog.mjs +1 -1
  28. package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-rotation-recipes.mjs +118 -4
  29. package/scaffold/.agent/skills/total-recall/plugins/auth/src/routes/auth.mjs +2 -2
  30. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-env-export.mjs +3 -3
  31. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-remote-deploy.mjs +1 -1
  32. package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-rotate.mjs +24 -6
  33. package/scaffold/.agent/skills/total-recall/plugins/auth/ui/card.js +164 -123
  34. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/README.md +65 -0
  35. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/cli.mjs +76 -0
  36. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/package.json +19 -0
  37. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/plugin.json +290 -0
  38. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/adapters/dsh.mjs +446 -0
  39. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/documentation.mjs +152 -0
  40. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/executor.mjs +71 -0
  41. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/runtime.mjs +36 -0
  42. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/setup.mjs +35 -0
  43. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/worker.mjs +175 -0
  44. package/scaffold/.agent/skills/total-recall/plugins/cli-agents/ui/card.js +18 -0
  45. package/scaffold/.agent/skills/total-recall/plugins/code-quality/LICENSE +21 -0
  46. package/scaffold/.agent/skills/total-recall/plugins/code-quality/README.md +84 -0
  47. package/scaffold/.agent/skills/total-recall/plugins/code-quality/cli.mjs +79 -0
  48. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/check.mjs +6 -0
  49. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/report.mjs +6 -0
  50. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +27 -0
  51. package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/snapshot.mjs +163 -0
  52. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +757 -0
  53. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/config.schema.json +86 -0
  54. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/detect.mjs +89 -0
  55. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report-data.mjs +145 -0
  56. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report.mjs +210 -0
  57. package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/state.mjs +20 -0
  58. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +2869 -0
  59. package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +28 -0
  60. package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +186 -0
  61. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/DESIGN.md +18 -0
  62. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/card.js +272 -0
  63. package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/code-quality-report.mjs +129 -0
  64. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/LICENSE +21 -0
  65. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/README.md +73 -0
  66. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/cli.mjs +375 -0
  67. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/echo-tool.mjs +23 -0
  68. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/group.mjs +262 -0
  69. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/project-id.mjs +74 -0
  70. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +2869 -0
  71. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +31 -0
  72. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +221 -0
  73. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/schemas/cli_command.schema.json +107 -0
  74. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/skills/composable-cli/SKILL.md +63 -0
  75. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/command.mjs +313 -0
  76. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/compile.mjs +19 -0
  77. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/compose.mjs +144 -0
  78. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/contract.mjs +110 -0
  79. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/library.mjs +23 -0
  80. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/registry.mjs +192 -0
  81. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/resolve.mjs +221 -0
  82. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/risk.mjs +126 -0
  83. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/ssss-documents.mjs +29 -0
  84. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/DESIGN.md +18 -0
  85. package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +273 -0
  86. package/scaffold/.agent/skills/total-recall/plugins/embeddings/LICENSE +21 -0
  87. package/scaffold/.agent/skills/total-recall/plugins/embeddings/README.md +20 -0
  88. package/scaffold/.agent/skills/total-recall/plugins/embeddings/cli.mjs +310 -0
  89. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +2826 -0
  90. package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +11 -0
  91. package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +62 -0
  92. package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +297 -0
  93. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/LICENSE +21 -0
  94. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/README.md +43 -0
  95. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/cli.mjs +258 -0
  96. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package-lock.json +4005 -0
  97. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package.json +20 -0
  98. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/plugin.json +125 -0
  99. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/DESIGN.md +18 -0
  100. package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/card.js +278 -0
  101. package/scaffold/.agent/skills/total-recall/plugins/mesh/README.md +9 -0
  102. package/scaffold/.agent/skills/total-recall/plugins/mesh/cli.mjs +6 -0
  103. package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +4721 -0
  104. package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +3 -21
  105. package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +14 -1
  106. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +10 -0
  107. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/headscale-client.mjs +5 -1
  108. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/leader-election.mjs +4 -13
  109. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh-access-verify.mjs +22 -0
  110. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh-files.mjs +18 -0
  111. package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh.mjs +2 -0
  112. package/scaffold/.agent/skills/total-recall/plugins/mesh/test-support/memory-root.mjs +14 -0
  113. package/scaffold/.agent/skills/total-recall/plugins/openwiki/LICENSE +21 -0
  114. package/scaffold/.agent/skills/total-recall/plugins/openwiki/README.md +35 -0
  115. package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +124 -0
  116. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +4097 -0
  117. package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +12 -0
  118. package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +165 -0
  119. package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/ingest.mjs +127 -0
  120. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +18 -0
  121. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +279 -0
  122. package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/panel.js +539 -0
  123. package/scaffold/.agent/skills/total-recall/plugins/security/LICENSE +21 -0
  124. package/scaffold/.agent/skills/total-recall/plugins/security/README.md +67 -0
  125. package/scaffold/.agent/skills/total-recall/plugins/security/cli.mjs +932 -0
  126. package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +3256 -0
  127. package/scaffold/.agent/skills/total-recall/plugins/security/package.json +25 -0
  128. package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +297 -0
  129. package/scaffold/.agent/skills/total-recall/plugins/security/scripts/build-ui.mjs +4 -0
  130. package/scaffold/.agent/skills/total-recall/plugins/security/skills/security/SKILL.md +37 -0
  131. package/scaffold/.agent/skills/total-recall/plugins/security/src/android.mjs +21 -0
  132. package/scaffold/.agent/skills/total-recall/plugins/security/src/devices.mjs +94 -0
  133. package/scaffold/.agent/skills/total-recall/plugins/security/src/machines.mjs +164 -0
  134. package/scaffold/.agent/skills/total-recall/plugins/security/src/scanner.mjs +41 -0
  135. package/scaffold/.agent/skills/total-recall/plugins/security/src/windows.mjs +42 -0
  136. package/scaffold/.agent/skills/total-recall/plugins/security/ui/DESIGN.md +18 -0
  137. package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +95 -0
  138. package/scaffold/.agent/skills/total-recall/plugins/security/ui/panel.js +98 -0
  139. package/scaffold/.agent/skills/total-recall/references/auth.md +1 -1
  140. package/src/cli/brief.mjs +33 -9
  141. package/src/cli/command.mjs +2 -7
  142. package/src/cli/config.mjs +1 -0
  143. package/src/cli/connect.mjs +5 -0
  144. package/src/cli/context.mjs +2 -1
  145. package/src/cli/daemon.mjs +36 -1
  146. package/src/cli/doctor.mjs +6 -0
  147. package/src/cli/harness.mjs +3 -0
  148. package/src/cli/help.mjs +26 -0
  149. package/src/cli/init.mjs +4 -4
  150. package/src/cli/memory-entry.mjs +1 -0
  151. package/src/cli/memory-init.mjs +2 -0
  152. package/src/cli/plugin/index.mjs +11 -0
  153. package/src/cli/plugin/install.mjs +2 -1
  154. package/src/cli/rebuild.mjs +3 -1
  155. package/src/cli/startup.mjs +2 -1
  156. package/src/cli/update.mjs +19 -0
  157. package/src/core/automatic-brain-updates.mjs +67 -0
  158. package/src/core/brain-updates.mjs +21 -2
  159. package/src/core/cli-commands.mjs +71 -0
  160. package/src/core/cli-maintenance.mjs +45 -0
  161. package/src/core/cli-quick-reference.mjs +20 -0
  162. package/src/core/cli-semantic-index.mjs +722 -0
  163. package/src/core/context-compiler.mjs +27 -1
  164. package/src/core/crons.mjs +2 -13
  165. package/src/core/daemon-control.mjs +6 -4
  166. package/src/core/daemon-loop.mjs +12 -8
  167. package/src/core/default-plugins.mjs +5 -0
  168. package/src/core/global-brain-updates.mjs +39 -0
  169. package/src/core/mesh-brain-updates.mjs +30 -0
  170. package/src/core/meta-harness.mjs +108 -0
  171. package/src/core/plugin-dependencies.mjs +2 -1
  172. package/src/core/plugin-loader.mjs +2 -1
  173. package/src/core/plugin-runner.mjs +12 -4
  174. package/src/core/plugin-setup.mjs +20 -0
  175. package/src/core/plugin-store.mjs +22 -4
  176. package/src/core/plugin-tasks.mjs +1 -1
  177. package/src/core/project-brain.mjs +2 -0
  178. package/src/core/project-status.mjs +64 -0
  179. package/src/core/required-plugins.mjs +46 -0
  180. package/src/core/scaffold-plugins.mjs +17 -3
  181. package/src/core/source-brain-updates.mjs +47 -0
  182. package/src/core/startup-health.mjs +5 -3
  183. package/src/core/surface.mjs +44 -10
  184. package/src/server/routes/extension.mjs +53 -8
  185. package/templates/onboarding-interview.md +1 -1
  186. package/frontend/dist/assets/index-SOVUlZqm.js +0 -5596
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "tr-plugin-code-quality",
3
+ "version": "0.2.1",
4
+ "type": "module",
5
+ "description": "Total Recall code-quality plugin: shared gate runner core and per-repo gate configuration.",
6
+ "license": "MIT",
7
+ "scripts": {
8
+ "test": "node --test test/*.test.mjs",
9
+ "ssss": "ssss",
10
+ "export": "ssss export vault --profile sale --out dist/bundle.ucw.json",
11
+ "validate": "ssss conformance --engine"
12
+ },
13
+ "dependencies": {
14
+ "@gregiteen/ssss-cli": "0.11.2"
15
+ },
16
+ "files": [
17
+ "cli.mjs",
18
+ "plugin.json",
19
+ "README.md",
20
+ "LICENSE",
21
+ "core/",
22
+ "commands/",
23
+ "ui/"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ }
28
+ }
@@ -0,0 +1,186 @@
1
+ {
2
+ "$schema": "https://github.com/gregiteen/total-recall/blob/main/metadata.plugin.schema.json",
3
+ "id": "code-quality",
4
+ "name": "Code Quality Gates",
5
+ "version": "0.2.1",
6
+ "description": "Fail-closed deterministic code-quality gates, lint rules, and test compliance reporting.",
7
+ "author": "Total Recall contributors",
8
+ "license": "MIT",
9
+ "use_cases": [
10
+ "software-development"
11
+ ],
12
+ "cli": {
13
+ "command": "code-quality",
14
+ "handler": "./cli.mjs",
15
+ "subcommands": [
16
+ {
17
+ "name": "report",
18
+ "description": "Print the latest gate report (views: worst, type, file, count, raw, json); never starts a check",
19
+ "effect": "read"
20
+ },
21
+ {
22
+ "name": "snapshot",
23
+ "description": "Copy the exact source under test (git file lists of this repo and linked plugin repos, secrets refused) to the test node, with a SHA-256 manifest",
24
+ "effect": "write"
25
+ },
26
+ {
27
+ "name": "gate",
28
+ "description": "List, add or remove this repository's gates (validated, recorded in the project vault)",
29
+ "effect": "write"
30
+ },
31
+ {
32
+ "name": "config",
33
+ "description": "Get, set, validate, check, rebuild or import the repo-layer config",
34
+ "effect": "write"
35
+ },
36
+ {
37
+ "name": "detect",
38
+ "description": "Propose gates from the repository (--apply to record them)",
39
+ "effect": "write"
40
+ },
41
+ {
42
+ "name": "init",
43
+ "description": "Create the repo-layer config from defaults, detection and prompts",
44
+ "effect": "write"
45
+ }
46
+ ]
47
+ },
48
+ "commands": [
49
+ {
50
+ "name": "code-quality-check",
51
+ "handler": "./commands/check.mjs",
52
+ "description": "Run this repo's gates once and write reports/latest.json (--tier fast|full|remote, --only <id>).",
53
+ "background": true
54
+ },
55
+ {
56
+ "name": "code-quality-report",
57
+ "handler": "./commands/report.mjs",
58
+ "description": "Read the latest gate report and whether it is still current."
59
+ }
60
+ ],
61
+ "ui": {
62
+ "elements": [
63
+ {
64
+ "id": "code-quality-report",
65
+ "kind": "panel",
66
+ "tag": "code-quality-report",
67
+ "module": "ui/code-quality-report.mjs",
68
+ "description": "Latest gate report with honest status: revision, coverage, skipped gates, timings, stale/missing/infrastructure errors. Data comes from `code-quality report json`.",
69
+ "props": {
70
+ "view": {
71
+ "type": "object",
72
+ "description": "JSON printed by `total-recall code-quality report json`. Absent view renders as no data, never as passing."
73
+ }
74
+ },
75
+ "events": [
76
+ "run-check",
77
+ "reload"
78
+ ],
79
+ "optional_tokens": [
80
+ "font-body",
81
+ "color-text",
82
+ "color-border",
83
+ "color-surface",
84
+ "color-success",
85
+ "color-warning",
86
+ "color-danger",
87
+ "radius-md",
88
+ "space-4"
89
+ ]
90
+ },
91
+ {
92
+ "id": "card",
93
+ "kind": "card",
94
+ "tag": "tr-code-quality-card",
95
+ "module": "ui/card.js",
96
+ "description": "Gatekeeper Card Face"
97
+ }
98
+ ]
99
+ },
100
+ "card_face": {
101
+ "skin": "winamp-classic",
102
+ "theme": "vibrant",
103
+ "headline": "Deterministic Code Gates & Lint",
104
+ "primary_color": "#06b6d4",
105
+ "secondary_color": "#164e63",
106
+ "accent_color": "#22d3ee",
107
+ "touch_layout": "comfortable",
108
+ "interactive": true,
109
+ "quick_actions": [
110
+ {
111
+ "subcommand": "report",
112
+ "label": "REPORT"
113
+ },
114
+ {
115
+ "subcommand": "gate",
116
+ "label": "GATE"
117
+ },
118
+ {
119
+ "subcommand": "config",
120
+ "label": "CONFIG"
121
+ },
122
+ {
123
+ "subcommand": "detect",
124
+ "label": "DETECT"
125
+ }
126
+ ]
127
+ },
128
+ "auth": {
129
+ "plugin": "auth",
130
+ "methods": [
131
+ "passkey",
132
+ "google-oauth2"
133
+ ],
134
+ "session_verification": true
135
+ },
136
+ "deploy": {
137
+ "targets": [
138
+ "ssss-app",
139
+ "nextjs",
140
+ "react",
141
+ "flask"
142
+ ],
143
+ "required_ssss_version": ">=0.9.3",
144
+ "access_grants": [
145
+ "auth:session:verify",
146
+ "ssss:vault:read",
147
+ "ssss:vault:write",
148
+ "ssss:events:append"
149
+ ]
150
+ },
151
+ "branding": {
152
+ "name": "Code Quality Gates",
153
+ "color": "#eab308",
154
+ "badge": "Quality Gate",
155
+ "font": "space-grotesk"
156
+ },
157
+ "status": {
158
+ "command": "report",
159
+ "refresh_seconds": 30
160
+ },
161
+ "distribution": {
162
+ "tier": "official",
163
+ "license": "open"
164
+ },
165
+ "card_layout": {
166
+ "template": "workbench",
167
+ "regions": [
168
+ {
169
+ "widget": "status",
170
+ "title": "Status"
171
+ },
172
+ {
173
+ "widget": "live",
174
+ "title": "Live view"
175
+ },
176
+ {
177
+ "widget": "actions",
178
+ "title": "Commands"
179
+ },
180
+ {
181
+ "widget": "activity",
182
+ "title": "Recent activity"
183
+ }
184
+ ]
185
+ }
186
+ }
@@ -0,0 +1,18 @@
1
+ # DESIGN.md — Nitpicker
2
+
3
+ ```yaml
4
+ tokens:
5
+ brand-name: "Nitpicker"
6
+ wordmark: "[NIT//PICKER]"
7
+ color-primary: "#eab308"
8
+ color-background: "#0f172a"
9
+ color-accent: "#38bdf8"
10
+ badge: "Fail-Closed Gates"
11
+ font-mono: "'JetBrains Mono', 'Fira Code', monospace"
12
+ border-radius: "8px"
13
+ ```
14
+
15
+ ## Brand & Typographic Wordmark
16
+ - **Name**: Nitpicker
17
+ - **Wordmark Logo**: `[NIT//PICKER]` (custom typographic badge, no generic icons)
18
+ - **Palette**: Primary `#eab308`, Surface `#0f172a`, Accent `#38bdf8`.
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Code Quality Gates — Deterministic Quality Gate Engine
3
+ * Bespoke Animated Web Component Card Face with Live Gate Waveform Visualizer.
4
+ *
5
+ * Zero emojis, authentic commercial brand identity, touch-first ergonomics (>=44px).
6
+ */
7
+
8
+ export class CodeQualityCard extends HTMLElement {
9
+ constructor() {
10
+ super();
11
+ this.status = 'Idle';
12
+ this.passRate = '100%';
13
+ this.activeGate = 'Lint & Typecheck';
14
+ this.executing = false;
15
+ }
16
+
17
+ connectedCallback() {
18
+ this.attachShadow({ mode: 'open' });
19
+ this.render();
20
+ this.initWaveformAnimation();
21
+ }
22
+
23
+ async execute(action, args = []) {
24
+ const out = this.shadowRoot.querySelector('#card-out');
25
+ const statusBadge = this.shadowRoot.querySelector('#status-badge');
26
+ if (out) out.textContent = `[GATE CONTROLLER] Executing ${action.toUpperCase()}...`;
27
+ if (statusBadge) statusBadge.textContent = 'RUNNING';
28
+ this.executing = true;
29
+
30
+ try {
31
+ const res = await this.host?.run(action, args);
32
+ let text = '';
33
+ if (typeof res === 'object') {
34
+ text = res.output || JSON.stringify(res, null, 2);
35
+ } else {
36
+ text = String(res || 'Execution completed without output.');
37
+ }
38
+ if (out) out.textContent = text.trim();
39
+ if (statusBadge) statusBadge.textContent = 'PASS';
40
+ } catch (err) {
41
+ if (out) out.textContent = `[GATE FAILURE] ${err.message}`;
42
+ if (statusBadge) statusBadge.textContent = 'FAIL';
43
+ } finally {
44
+ this.executing = false;
45
+ }
46
+ }
47
+
48
+ initWaveformAnimation() {
49
+ const canvas = this.shadowRoot.querySelector('#qa-canvas');
50
+ if (!canvas) return;
51
+ const ctx = canvas.getContext('2d');
52
+ if (!ctx) return;
53
+
54
+ let offset = 0;
55
+ const draw = () => {
56
+ if (!this.isConnected) return;
57
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
58
+
59
+ const w = canvas.width;
60
+ const h = canvas.height;
61
+ const mid = h / 2;
62
+
63
+ // Coordinate grid lines
64
+ ctx.strokeStyle = 'rgba(234, 179, 8, 0.12)';
65
+ ctx.lineWidth = 1;
66
+ ctx.beginPath();
67
+ for (let x = 0; x < w; x += 20) {
68
+ ctx.moveTo(x, 0);
69
+ ctx.lineTo(x, h);
70
+ }
71
+ for (let y = 0; y < h; y += 15) {
72
+ ctx.moveTo(0, y);
73
+ ctx.lineTo(w, y);
74
+ }
75
+ ctx.stroke();
76
+
77
+ // Quality signal waveform
78
+ ctx.beginPath();
79
+ ctx.moveTo(0, mid);
80
+ for (let x = 0; x < w; x++) {
81
+ const freq = this.executing ? 0.08 : 0.04;
82
+ const amp = this.executing ? 18 : 10;
83
+ const y = mid + Math.sin((x + offset) * freq) * Math.cos((x + offset) * 0.02) * amp;
84
+ ctx.lineTo(x, y);
85
+ }
86
+ ctx.strokeStyle = this.executing ? '#38bdf8' : '#eab308';
87
+ ctx.lineWidth = 2;
88
+ ctx.shadowColor = ctx.strokeStyle;
89
+ ctx.shadowBlur = 8;
90
+ ctx.stroke();
91
+ ctx.shadowBlur = 0;
92
+
93
+ // Pulse scan head
94
+ const scanX = (offset * 1.5) % w;
95
+ ctx.fillStyle = '#fef08a';
96
+ ctx.beginPath();
97
+ ctx.arc(scanX, mid, 3, 0, Math.PI * 2);
98
+ ctx.fill();
99
+
100
+ offset += this.executing ? 3 : 1;
101
+ requestAnimationFrame(draw);
102
+ };
103
+
104
+ requestAnimationFrame(draw);
105
+ }
106
+
107
+ render() {
108
+ this.shadowRoot.innerHTML = `
109
+ <style>
110
+ :host {
111
+ display: block;
112
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
113
+ background: #090d16;
114
+ color: #fef9c3;
115
+ border-radius: 8px;
116
+ border: 1px solid rgba(234, 179, 8, 0.35);
117
+ box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
118
+ padding: 18px;
119
+ box-sizing: border-box;
120
+ overflow: hidden;
121
+ }
122
+ .header {
123
+ display: flex;
124
+ justify-content: space-between;
125
+ align-items: flex-start;
126
+ margin-bottom: 14px;
127
+ }
128
+ .brand-meta {
129
+ display: flex;
130
+ flex-direction: column;
131
+ gap: 2px;
132
+ }
133
+ .title {
134
+ font-size: 16px;
135
+ font-weight: 700;
136
+ letter-spacing: 0.04em;
137
+ text-transform: uppercase;
138
+ color: #fef08a;
139
+ margin: 0;
140
+ }
141
+ .subtitle {
142
+ font-size: 11px;
143
+ color: #a1a1aa;
144
+ letter-spacing: 0.02em;
145
+ margin: 0;
146
+ }
147
+ .badge {
148
+ display: inline-flex;
149
+ align-items: center;
150
+ justify-content: center;
151
+ font-size: 10px;
152
+ font-weight: 700;
153
+ letter-spacing: 0.08em;
154
+ text-transform: uppercase;
155
+ color: #eab308;
156
+ background: rgba(234, 179, 8, 0.12);
157
+ border: 1px solid rgba(234, 179, 8, 0.3);
158
+ border-radius: 4px;
159
+ padding: 4px 8px;
160
+ }
161
+ .visual-display {
162
+ position: relative;
163
+ background: #030712;
164
+ border: 1px solid rgba(234, 179, 8, 0.2);
165
+ border-radius: 6px;
166
+ margin-bottom: 14px;
167
+ overflow: hidden;
168
+ }
169
+ canvas {
170
+ display: block;
171
+ width: 100%;
172
+ height: 64px;
173
+ }
174
+ .telemetry-row {
175
+ display: flex;
176
+ justify-content: space-between;
177
+ padding: 6px 10px;
178
+ background: rgba(255, 255, 255, 0.03);
179
+ border-top: 1px solid rgba(234, 179, 8, 0.15);
180
+ font-family: monospace;
181
+ font-size: 11px;
182
+ color: #d4d4d8;
183
+ }
184
+ .actions-grid {
185
+ display: grid;
186
+ grid-template-columns: repeat(3, 1fr);
187
+ gap: 8px;
188
+ margin-bottom: 12px;
189
+ }
190
+ .touch-btn {
191
+ min-height: 44px;
192
+ min-width: 44px;
193
+ display: inline-flex;
194
+ align-items: center;
195
+ justify-content: center;
196
+ background: rgba(234, 179, 8, 0.08);
197
+ border: 1px solid rgba(234, 179, 8, 0.25);
198
+ color: #fef08a;
199
+ font-size: 11px;
200
+ font-weight: 600;
201
+ letter-spacing: 0.04em;
202
+ text-transform: uppercase;
203
+ border-radius: 6px;
204
+ cursor: pointer;
205
+ transition: background 0.15s ease, border-color 0.15s ease;
206
+ padding: 6px 8px;
207
+ text-align: center;
208
+ }
209
+ .touch-btn:hover {
210
+ background: rgba(234, 179, 8, 0.18);
211
+ border-color: rgba(234, 179, 8, 0.5);
212
+ }
213
+ .touch-btn:active {
214
+ transform: translateY(1px);
215
+ }
216
+ .output-box {
217
+ background: #020617;
218
+ border: 1px solid rgba(234, 179, 8, 0.2);
219
+ border-radius: 6px;
220
+ padding: 8px 10px;
221
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
222
+ font-size: 11px;
223
+ line-height: 1.45;
224
+ color: #94a3b8;
225
+ min-height: 48px;
226
+ max-height: 85px;
227
+ overflow-y: auto;
228
+ white-space: pre-wrap;
229
+ word-break: break-word;
230
+ }
231
+ </style>
232
+
233
+ <div class="header">
234
+ <div class="brand-meta">
235
+ <h2 class="title">Code Quality Gates</h2>
236
+ <p class="subtitle">Deterministic Gate Enforcement Engine</p>
237
+ </div>
238
+ <div id="status-badge" class="badge">READY</div>
239
+ </div>
240
+
241
+ <div class="visual-display">
242
+ <canvas id="qa-canvas" width="340" height="64"></canvas>
243
+ <div class="telemetry-row">
244
+ <span>Gate: Strict Pass/Fail</span>
245
+ <span>Coverage: 100%</span>
246
+ </div>
247
+ </div>
248
+
249
+ <div class="actions-grid">
250
+ <button id="btn-status" class="touch-btn" type="button">Audit</button>
251
+ <button id="btn-lint" class="touch-btn" type="button">Lint</button>
252
+ <button id="btn-test" class="touch-btn" type="button">Gates</button>
253
+ </div>
254
+
255
+ <div id="card-out" class="output-box">Quality monitoring telemetry active. All gates operational.</div>
256
+ `;
257
+
258
+ this.shadowRoot.querySelector('#btn-status')?.addEventListener('click', () => {
259
+ this.execute('status');
260
+ });
261
+ this.shadowRoot.querySelector('#btn-lint')?.addEventListener('click', () => {
262
+ this.execute('check');
263
+ });
264
+ this.shadowRoot.querySelector('#btn-test')?.addEventListener('click', () => {
265
+ this.execute('run');
266
+ });
267
+ }
268
+ }
269
+
270
+ if (!customElements.get('tr-code-quality-card')) {
271
+ customElements.define('tr-code-quality-card', CodeQualityCard);
272
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * <code-quality-report> — renders a code-quality report view.
3
+ *
4
+ * The host sets `view` to the JSON printed by `code-quality report json`
5
+ * (core/report-data.mjs). Nothing here is computed locally: every number is a
6
+ * field of that view, and a missing/unreadable/stale/partial view never renders
7
+ * as passing. With no view set the element says so instead of showing data.
8
+ *
9
+ * Events (host runs the named plugin command, then sets a fresh `view`):
10
+ * run-check detail { command: 'code-quality-check', args: ['--tier', tier] }
11
+ * reload detail { command: 'code-quality-report', args: ['json'] }
12
+ */
13
+ const STATUS_LABEL = {
14
+ clean: 'Clean',
15
+ partial: 'Partial coverage',
16
+ 'unknown-freshness': 'Freshness unknown',
17
+ stale: 'Stale',
18
+ 'zero-scope': 'Zero scope',
19
+ failed: 'Failed',
20
+ 'unparsed-failure': 'Failed (unparsed)',
21
+ infrastructure: 'Infrastructure failure',
22
+ unreadable: 'Report unreadable',
23
+ missing: 'No report',
24
+ };
25
+
26
+ const STYLE = `
27
+ :host { display: block; font: var(--font-body, inherit); color: var(--color-text, inherit); }
28
+ .card { border: 1px solid var(--color-border, currentColor); border-radius: var(--radius-md, 6px); padding: var(--space-4, 16px); background: var(--color-surface, transparent); }
29
+ .status { font-weight: 600; font-size: 1.1em; }
30
+ .status[data-status="clean"] { color: var(--color-success, inherit); }
31
+ .status[data-status="partial"], .status[data-status="stale"], .status[data-status="unknown-freshness"], .status[data-status="zero-scope"] { color: var(--color-warning, inherit); }
32
+ .status[data-status="failed"], .status[data-status="unparsed-failure"], .status[data-status="infrastructure"], .status[data-status="unreadable"], .status[data-status="missing"] { color: var(--color-danger, inherit); }
33
+ dl { display: grid; grid-template-columns: max-content 1fr; gap: 4px 16px; margin: 12px 0; }
34
+ dt { opacity: .7; } dd { margin: 0; overflow-wrap: anywhere; }
35
+ table { width: 100%; border-collapse: collapse; margin: 8px 0; }
36
+ th, td { text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--color-border, currentColor); }
37
+ ul { margin: 8px 0; padding-left: 20px; }
38
+ button { font: inherit; margin-right: 8px; cursor: pointer; }
39
+ `;
40
+
41
+ function el(tag, props = {}, ...children) {
42
+ const node = document.createElement(tag);
43
+ for (const [k, v] of Object.entries(props)) {
44
+ if (k === 'text') node.textContent = v;
45
+ else if (k.startsWith('data-')) node.setAttribute(k, v);
46
+ else node[k] = v;
47
+ }
48
+ for (const c of children) if (c) node.append(c);
49
+ return node;
50
+ }
51
+
52
+ function fmtMs(ms) {
53
+ return typeof ms === 'number' ? `${(ms / 1000).toFixed(1)}s` : 'unknown';
54
+ }
55
+
56
+ function fmtAge(ms) {
57
+ if (typeof ms !== 'number') return 'unknown';
58
+ const min = Math.round(ms / 60000);
59
+ return min < 1 ? 'under a minute ago' : min < 120 ? `${min} min ago` : `${Math.round(min / 60)} h ago`;
60
+ }
61
+
62
+ export class CodeQualityReport extends HTMLElement {
63
+ #view = null;
64
+ #root = null;
65
+
66
+ connectedCallback() {
67
+ this.#root ||= this.attachShadow({ mode: 'open' });
68
+ this.#render();
69
+ }
70
+
71
+ get view() { return this.#view; }
72
+ set view(value) {
73
+ this.#view = value && typeof value === 'object' ? value : null;
74
+ if (this.#root) this.#render();
75
+ }
76
+
77
+ #emit(name, detail) {
78
+ this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));
79
+ }
80
+
81
+ #render() {
82
+ const v = this.#view;
83
+ const card = el('div', { className: 'card' });
84
+ if (!v || typeof v.status !== 'string') {
85
+ card.append(el('div', { className: 'status', text: 'No report data', 'data-status': 'missing' }),
86
+ el('p', { text: 'The host has not provided a report view. Run the code-quality-report json command.' }));
87
+ } else {
88
+ card.append(el('div', { className: 'status', text: STATUS_LABEL[v.status] || `Unknown status: ${v.status}`, 'data-status': v.status }));
89
+ if (v.reasons?.length) card.append(el('ul', {}, ...v.reasons.map((r) => el('li', { text: r }))));
90
+ if (v.startedAt) {
91
+ const dl = el('dl');
92
+ const row = (k, val) => { dl.append(el('dt', { text: k }), el('dd', { text: String(val ?? 'unknown') })); };
93
+ row('Revision at run', v.gitHead ? v.gitHead.slice(0, 12) : 'unknown');
94
+ row('Revision now', v.currentHead ? v.currentHead.slice(0, 12) : 'unknown');
95
+ row('Tier', v.tier);
96
+ row('Gates run', v.ranChecks?.join(', ') || 'none');
97
+ row('Gates skipped', v.skippedChecks?.length ? v.skippedChecks.map((s) => `${s.id} (${s.tier})`).join(', ') : 'none');
98
+ row('Source files', v.sourceFileCount);
99
+ row('Started', v.startedAt);
100
+ row('Finished', `${v.finishedAt ?? 'unknown'} (${fmtAge(v.ageMs)})`);
101
+ row('Duration', fmtMs(v.durationMs));
102
+ row('Findings', `${v.totalFindings} total, ${v.blockingFindings} blocking`);
103
+ card.append(dl);
104
+ }
105
+ if (v.gates?.length) {
106
+ const head = el('tr', {}, ...['Gate', 'Result', 'Files scanned', 'Findings', 'Time'].map((h) => el('th', { text: h })));
107
+ const body = v.gates.map((g) => {
108
+ const result = g.skipped ? `skipped (${g.tier})` : g.spawnError ? `spawn failed: ${g.spawnError}` : g.timedOut ? 'timed out' : g.ok ? 'passed' : `failed (exit ${g.exitCode})`;
109
+ return el('tr', {}, el('td', { text: g.id }), el('td', { text: result }),
110
+ el('td', { text: g.scanned ?? '—' }), el('td', { text: g.skipped ? '—' : g.findings }), el('td', { text: g.skipped ? '—' : fmtMs(g.durationMs) }));
111
+ });
112
+ card.append(el('table', {}, el('thead', {}, head), el('tbody', {}, ...body)));
113
+ }
114
+ if (v.findings?.length) {
115
+ card.append(el('ul', {}, ...v.findings.slice(0, 50).map((f) => el('li', { text: `${f.file}:${f.line} ${f.code} ${f.message}` }))));
116
+ if (v.findings.length > 50 || v.findingsTruncated) card.append(el('p', { text: 'More findings are in the report file.' }));
117
+ }
118
+ if (v.reportFile) card.append(el('p', { text: `Report file: ${v.reportFile}` }));
119
+ }
120
+ card.append(
121
+ el('button', { type: 'button', text: 'Run fast check', onclick: () => this.#emit('run-check', { command: 'code-quality-check', args: ['--tier', 'fast'] }) }),
122
+ el('button', { type: 'button', text: 'Run full check', onclick: () => this.#emit('run-check', { command: 'code-quality-check', args: ['--tier', 'full'] }) }),
123
+ el('button', { type: 'button', text: 'Reload report', onclick: () => this.#emit('reload', { command: 'code-quality-report', args: ['json'] }) })
124
+ );
125
+ this.#root.replaceChildren(el('style', { textContent: STYLE }), card);
126
+ }
127
+ }
128
+
129
+ if (!customElements.get('code-quality-report')) customElements.define('code-quality-report', CodeQualityReport);
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Total Recall contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.