aura-code 0.3.7 → 0.6.3

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 (160) hide show
  1. package/README.md +56 -4
  2. package/dist/agent/compactor.d.ts +26 -0
  3. package/dist/agent/compactor.js +156 -0
  4. package/dist/agent/compactor.js.map +1 -0
  5. package/dist/agent/context.d.ts +4 -0
  6. package/dist/agent/context.js +38 -0
  7. package/dist/agent/context.js.map +1 -1
  8. package/dist/agent/design.d.ts +17 -0
  9. package/dist/agent/design.js +175 -0
  10. package/dist/agent/design.js.map +1 -0
  11. package/dist/agent/loop.js +24 -1
  12. package/dist/agent/loop.js.map +1 -1
  13. package/dist/agent/system-prompt.d.ts +1 -1
  14. package/dist/agent/system-prompt.js +14 -3
  15. package/dist/agent/system-prompt.js.map +1 -1
  16. package/dist/cli/display.js +46 -5
  17. package/dist/cli/display.js.map +1 -1
  18. package/dist/cli/index.js +323 -46
  19. package/dist/cli/index.js.map +1 -1
  20. package/dist/config/defaults.js +8 -1
  21. package/dist/config/defaults.js.map +1 -1
  22. package/dist/config/project-config.d.ts +6 -0
  23. package/dist/config/project-config.js +2 -0
  24. package/dist/config/project-config.js.map +1 -1
  25. package/dist/dream/dream.d.ts +71 -0
  26. package/dist/dream/dream.js +217 -0
  27. package/dist/dream/dream.js.map +1 -0
  28. package/dist/dream/okf.d.ts +10 -0
  29. package/dist/dream/okf.js +280 -0
  30. package/dist/dream/okf.js.map +1 -0
  31. package/dist/dream/parser.d.ts +60 -0
  32. package/dist/dream/parser.js +176 -0
  33. package/dist/dream/parser.js.map +1 -0
  34. package/dist/dream/reconcile.d.ts +69 -0
  35. package/dist/dream/reconcile.js +303 -0
  36. package/dist/dream/reconcile.js.map +1 -0
  37. package/dist/kanban/index.d.ts +5 -0
  38. package/dist/kanban/index.js +11 -0
  39. package/dist/kanban/index.js.map +1 -0
  40. package/dist/kanban/pipeline.d.ts +16 -0
  41. package/dist/kanban/pipeline.js +910 -0
  42. package/dist/kanban/pipeline.js.map +1 -0
  43. package/dist/kanban/server.d.ts +5 -0
  44. package/dist/kanban/server.js +820 -0
  45. package/dist/kanban/server.js.map +1 -0
  46. package/dist/kanban/types.d.ts +75 -0
  47. package/dist/kanban/types.js +6 -0
  48. package/dist/kanban/types.js.map +1 -0
  49. package/dist/learnlight/driven.d.ts +2 -0
  50. package/dist/learnlight/driven.js +109 -0
  51. package/dist/learnlight/driven.js.map +1 -0
  52. package/dist/learnlight/index.d.ts +4 -0
  53. package/dist/learnlight/index.js +32 -0
  54. package/dist/learnlight/index.js.map +1 -0
  55. package/dist/learnlight/lesson-prep.d.ts +36 -0
  56. package/dist/learnlight/lesson-prep.js +224 -0
  57. package/dist/learnlight/lesson-prep.js.map +1 -0
  58. package/dist/learnlight/report.d.ts +2 -0
  59. package/dist/learnlight/report.js +37 -0
  60. package/dist/learnlight/report.js.map +1 -0
  61. package/dist/learnlight/types.d.ts +72 -0
  62. package/dist/learnlight/types.js +6 -0
  63. package/dist/learnlight/types.js.map +1 -0
  64. package/dist/machina/index.d.ts +16 -0
  65. package/dist/machina/index.js +61 -0
  66. package/dist/machina/index.js.map +1 -0
  67. package/dist/machina/render-html.d.ts +2 -0
  68. package/dist/machina/render-html.js +189 -0
  69. package/dist/machina/render-html.js.map +1 -0
  70. package/dist/machina/render-terminal.d.ts +2 -0
  71. package/dist/machina/render-terminal.js +92 -0
  72. package/dist/machina/render-terminal.js.map +1 -0
  73. package/dist/machina/spec.d.ts +61 -0
  74. package/dist/machina/spec.js +124 -0
  75. package/dist/machina/spec.js.map +1 -0
  76. package/dist/machina/verify.d.ts +27 -0
  77. package/dist/machina/verify.js +85 -0
  78. package/dist/machina/verify.js.map +1 -0
  79. package/dist/perception/graph-store.d.ts +11 -0
  80. package/dist/perception/graph-store.js +33 -0
  81. package/dist/perception/graph-store.js.map +1 -1
  82. package/dist/perception/index.d.ts +1 -1
  83. package/dist/perception/index.js +2 -1
  84. package/dist/perception/index.js.map +1 -1
  85. package/dist/providers/anthropic.js +1 -1
  86. package/dist/providers/anthropic.js.map +1 -1
  87. package/dist/providers/factory.d.ts +49 -0
  88. package/dist/providers/factory.js +99 -0
  89. package/dist/providers/factory.js.map +1 -1
  90. package/dist/providers/google.js +1 -1
  91. package/dist/providers/google.js.map +1 -1
  92. package/dist/providers/openai-compatible.js +81 -50
  93. package/dist/providers/openai-compatible.js.map +1 -1
  94. package/dist/rem/graph.d.ts +72 -0
  95. package/dist/rem/graph.js +139 -0
  96. package/dist/rem/graph.js.map +1 -0
  97. package/dist/rem/index.d.ts +16 -0
  98. package/dist/rem/index.js +60 -0
  99. package/dist/rem/index.js.map +1 -0
  100. package/dist/rem/render-html.d.ts +2 -0
  101. package/dist/rem/render-html.js +189 -0
  102. package/dist/rem/render-html.js.map +1 -0
  103. package/dist/rem/render-terminal.d.ts +4 -0
  104. package/dist/rem/render-terminal.js +94 -0
  105. package/dist/rem/render-terminal.js.map +1 -0
  106. package/dist/research/council.d.ts +27 -0
  107. package/dist/research/council.js +263 -0
  108. package/dist/research/council.js.map +1 -0
  109. package/dist/research/research.d.ts +24 -0
  110. package/dist/research/research.js +116 -0
  111. package/dist/research/research.js.map +1 -0
  112. package/dist/ruby/alternator.d.ts +36 -1
  113. package/dist/ruby/alternator.js +40 -31
  114. package/dist/ruby/alternator.js.map +1 -1
  115. package/dist/ruby/stats.js +10 -11
  116. package/dist/ruby/stats.js.map +1 -1
  117. package/dist/ruby/types.js +1 -1
  118. package/dist/ruby/types.js.map +1 -1
  119. package/dist/safety/permissions.d.ts +8 -0
  120. package/dist/safety/permissions.js +12 -0
  121. package/dist/safety/permissions.js.map +1 -1
  122. package/dist/setup/provider-registry.js +14 -0
  123. package/dist/setup/provider-registry.js.map +1 -1
  124. package/dist/setup/provider-test.js +24 -2
  125. package/dist/setup/provider-test.js.map +1 -1
  126. package/dist/setup/telegram-wizard.d.ts +57 -0
  127. package/dist/setup/telegram-wizard.js +343 -0
  128. package/dist/setup/telegram-wizard.js.map +1 -0
  129. package/dist/tools/audio-transcribe.d.ts +20 -0
  130. package/dist/tools/audio-transcribe.js +39 -28
  131. package/dist/tools/audio-transcribe.js.map +1 -1
  132. package/dist/tools/browser.js +8 -10
  133. package/dist/tools/browser.js.map +1 -1
  134. package/dist/tools/gmail-tool.d.ts +15 -0
  135. package/dist/tools/gmail-tool.js +361 -0
  136. package/dist/tools/gmail-tool.js.map +1 -0
  137. package/dist/tools/read-file.js +13 -0
  138. package/dist/tools/read-file.js.map +1 -1
  139. package/dist/tools/telegram-bot.js +103 -20
  140. package/dist/tools/telegram-bot.js.map +1 -1
  141. package/dist/tools/telegram-voice.d.ts +22 -0
  142. package/dist/tools/telegram-voice.js +203 -0
  143. package/dist/tools/telegram-voice.js.map +1 -0
  144. package/dist/tools/telegram.d.ts +6 -1
  145. package/dist/tools/telegram.js +115 -5
  146. package/dist/tools/telegram.js.map +1 -1
  147. package/dist/tools/video-render.d.ts +11 -0
  148. package/dist/tools/video-render.js +189 -0
  149. package/dist/tools/video-render.js.map +1 -0
  150. package/dist/tools/web-search.d.ts +20 -0
  151. package/dist/tools/web-search.js +134 -38
  152. package/dist/tools/web-search.js.map +1 -1
  153. package/dist/util/errors.js +6 -0
  154. package/dist/util/errors.js.map +1 -1
  155. package/dist/viz/index.js +816 -30
  156. package/dist/viz/index.js.map +1 -1
  157. package/dist/viz/reader.d.ts +33 -0
  158. package/dist/viz/reader.js +343 -0
  159. package/dist/viz/reader.js.map +1 -0
  160. package/package.json +3 -1
@@ -0,0 +1,820 @@
1
+ "use strict";
2
+ // ─────────────────────────────────────────────────────────────────────────────
3
+ // Kanban Pipeline Server
4
+ // Serves the interactive board + runs the Read→Plan→Execute→Verify→Report
5
+ // pipeline via API + WebSocket progress events.
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ var __importDefault = (this && this.__importDefault) || function (mod) {
41
+ return (mod && mod.__esModule) ? mod : { "default": mod };
42
+ };
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.startKanbanServer = startKanbanServer;
45
+ const http = __importStar(require("http"));
46
+ const express_1 = __importDefault(require("express"));
47
+ const ws_1 = require("ws");
48
+ const pipeline_js_1 = require("./pipeline.js");
49
+ async function startKanbanServer(opts) {
50
+ const app = (0, express_1.default)();
51
+ const server = http.createServer(app);
52
+ const wss = new ws_1.WebSocketServer({ server });
53
+ app.use(express_1.default.json());
54
+ let lastReport = null;
55
+ let isRunning = false;
56
+ const progressClients = new Set();
57
+ // ── Serve the Kanban board ───────────────────────────────────────────────
58
+ app.get('/', (_req, res) => {
59
+ res.setHeader('Content-Type', 'text/html');
60
+ res.send(buildKanbanUI());
61
+ });
62
+ // ── API: Get all tasks ──────────────────────────────────────────────────
63
+ app.get('/api/tasks', (_req, res) => {
64
+ res.json((0, pipeline_js_1.getBoardTasks)());
65
+ });
66
+ // ── API: Execute the full pipeline ──────────────────────────────────────
67
+ app.post('/api/execute', async (_req, res) => {
68
+ if (isRunning) {
69
+ res.status(409).json({ error: 'Pipeline already running' });
70
+ return;
71
+ }
72
+ isRunning = true;
73
+ const start = Date.now();
74
+ try {
75
+ const report = await (0, pipeline_js_1.runPipeline)({
76
+ projectRoot: opts.cwd,
77
+ onProgress: (event) => {
78
+ for (const ws of progressClients) {
79
+ if (ws.readyState === ws_1.WebSocket.OPEN) {
80
+ ws.send(JSON.stringify(event));
81
+ }
82
+ }
83
+ },
84
+ });
85
+ lastReport = report;
86
+ res.json(report);
87
+ }
88
+ catch (e) {
89
+ res.status(500).json({ error: String(e) });
90
+ }
91
+ finally {
92
+ isRunning = false;
93
+ }
94
+ });
95
+ // ── API: Get last report ────────────────────────────────────────────────
96
+ app.get('/api/report', (_req, res) => {
97
+ if (!lastReport) {
98
+ res.status(404).json({ error: 'No report yet. POST /api/execute first.' });
99
+ return;
100
+ }
101
+ res.json(lastReport);
102
+ });
103
+ // ── API: Report as Markdown ─────────────────────────────────────────────
104
+ app.get('/api/report.md', (_req, res) => {
105
+ if (!lastReport) {
106
+ res.status(404).send('No report yet. Run the pipeline first.');
107
+ return;
108
+ }
109
+ res.setHeader('Content-Type', 'text/markdown');
110
+ res.send(renderReportMarkdown(lastReport));
111
+ });
112
+ // ── WebSocket: real-time progress ───────────────────────────────────────
113
+ wss.on('connection', (ws) => {
114
+ progressClients.add(ws);
115
+ ws.on('close', () => progressClients.delete(ws));
116
+ ws.send(JSON.stringify({ type: 'connected', running: isRunning }));
117
+ });
118
+ // ── Start listening ─────────────────────────────────────────────────────
119
+ server.listen(opts.port, () => {
120
+ console.log('');
121
+ console.log(' ◆ Aura Kanban Pipeline Server');
122
+ console.log(` ├─ Board: http://localhost:${opts.port}`);
123
+ console.log(` ├─ API: http://localhost:${opts.port}/api/tasks`);
124
+ console.log(` ├─ Execute: POST http://localhost:${opts.port}/api/execute`);
125
+ console.log(` ├─ Report: http://localhost:${opts.port}/api/report`);
126
+ console.log(` ├─ Report: http://localhost:${opts.port}/api/report.md`);
127
+ console.log(` └─ WebSocket ws://localhost:${opts.port}`);
128
+ console.log('');
129
+ });
130
+ }
131
+ // ─────────────────────────────────────────────────────────────────────────────
132
+ // Build the Kanban board HTML (enhanced version of the original)
133
+ // ─────────────────────────────────────────────────────────────────────────────
134
+ function buildKanbanUI() {
135
+ const tasks = (0, pipeline_js_1.getBoardTasks)();
136
+ // Organize tasks into a grid: row × phase
137
+ const grid = new Map();
138
+ for (const t of tasks) {
139
+ const key = `${t.row}|${t.phase}`;
140
+ const arr = grid.get(key) ?? [];
141
+ arr.push(t);
142
+ grid.set(key, arr);
143
+ }
144
+ const ROWS = [
145
+ { id: 'orchestrate', label: 'Orchestrate', sub: 'Multi-Agent' },
146
+ { id: 'architect', label: 'Architect', sub: 'Design Phase' },
147
+ { id: 'verify', label: 'Verify', sub: 'Self-Correction' },
148
+ { id: 'ruby-alternator', label: 'RubyAlternator', sub: 'Improvement' },
149
+ ];
150
+ const PHASES = [
151
+ { id: 'read', label: 'Read', sub: 'Context' },
152
+ { id: 'plan', label: 'Plan', sub: 'Strategy' },
153
+ { id: 'execute', label: 'Execute', sub: 'Ignite' },
154
+ { id: 'verify', label: 'Verify', sub: 'Test' },
155
+ { id: 'report', label: 'Report', sub: 'Done' },
156
+ ];
157
+ function renderCard(t, phaseId, rowLabel) {
158
+ const isOrigin = t.phase === phaseId;
159
+ const border = isOrigin ? 'border-left: 3px solid #a63f2b;' : '';
160
+ const priority = t.highPriority ? ' high-priority' : '';
161
+ return `
162
+ <div class="kanban-card${priority}" style="${border}" data-id="${t.id}" data-phase="${phaseId}" data-row="${esc(rowLabel)}">
163
+ <div>
164
+ <span class="priority-badge">${esc(t.badge)}</span>
165
+ <h4 class="card-title">${esc(t.title)}</h4>
166
+ <p class="card-desc">${esc(t.description)}</p>
167
+ </div>
168
+ <div class="card-footer">
169
+ <span class="provider-tag">${esc(t.tag)}</span>
170
+ <div class="avatar">${t.title.substring(0, 2).toUpperCase()}</div>
171
+ </div>
172
+ </div>`;
173
+ }
174
+ // Build column HTML
175
+ const columnsHtml = PHASES.map(phase => {
176
+ const header = `<div class="column-header">${phase.label} <span>${phase.sub}</span></div>`;
177
+ const cells = ROWS.map(row => {
178
+ const key = `${row.id}|${phase.id}`;
179
+ const tasksInCell = grid.get(key) ?? [];
180
+ if (tasksInCell.length === 0) {
181
+ return `<div class="empty-slot" data-row="${esc(row.label)}">Empty</div>`;
182
+ }
183
+ return tasksInCell.map(t => renderCard(t, phase.id, row.label)).join('\n');
184
+ }).join('\n');
185
+ return `<div class="kanban-column" data-col="${phase.id}">${header}\n${cells}</div>`;
186
+ }).join('\n');
187
+ // Row headers
188
+ const rowHeaders = ROWS.map(r => `<div class="row-header-card"><h3>${r.label}</h3><span>${r.sub}</span></div>`).join('\n');
189
+ return `<!DOCTYPE html>
190
+ <html lang="en" data-theme="light">
191
+ <head>
192
+ <meta charset="UTF-8">
193
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
194
+ <title>Aura — Kanban Pipeline</title>
195
+ <style>
196
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,400;0,600;1,400&display=swap');
197
+
198
+ :root {
199
+ --bg-base: #ebd5c9; --bg-board: #d6bdae; --bg-column: #e8d0c3;
200
+ --bg-card: #fcf9f7; --text-main: #3d2b25; --text-muted: #7a5f54;
201
+ --accent-red: #a34c38; --accent-glow: rgba(163, 76, 56, 0.4);
202
+ --gold: #b38b59; --border-light: rgba(179, 139, 89, 0.25);
203
+ --border-strong: rgba(179, 139, 89, 0.6);
204
+ --shadow-soft: 0 8px 24px rgba(61, 43, 37, 0.08);
205
+ --shadow-hover: 0 12px 32px rgba(61, 43, 37, 0.15);
206
+ --pattern-opacity: 0.06; --btn-text: #ffffff;
207
+ --accent-green: #5a9e6e; --accent-gold: #d4903a;
208
+ }
209
+ [data-theme="dark"] {
210
+ --bg-base: #1c1311; --bg-board: #2b1d1a; --bg-column: #382622;
211
+ --bg-card: #45302b; --text-main: #f5ebe6; --text-muted: #bda399;
212
+ --accent-red: #d9684f; --accent-glow: rgba(217, 104, 79, 0.6);
213
+ --gold: #d6af7a; --border-light: rgba(214, 175, 122, 0.15);
214
+ --border-strong: rgba(214, 175, 122, 0.4);
215
+ --shadow-soft: 0 8px 24px rgba(0, 0, 0, 0.4);
216
+ --shadow-hover: 0 12px 32px rgba(0, 0, 0, 0.6);
217
+ --pattern-opacity: 0.03; --btn-text: #1c1311;
218
+ }
219
+ * { box-sizing: border-box; margin: 0; padding: 0; }
220
+ body {
221
+ padding: 30px 20px; background-color: var(--bg-base);
222
+ background-image:
223
+ radial-gradient(circle at 15% 50%, rgba(179, 139, 89, var(--pattern-opacity)), transparent 25%),
224
+ radial-gradient(circle at 85% 30%, rgba(163, 76, 56, var(--pattern-opacity)), transparent 25%);
225
+ font-family: 'Inter', sans-serif; color: var(--text-main);
226
+ display: flex; flex-direction: column; align-items: center;
227
+ min-height: 100vh; transition: background-color 0.4s ease, color 0.4s ease;
228
+ }
229
+ .theme-toggle-wrapper { position: absolute; top: 30px; right: 40px; }
230
+ .theme-toggle {
231
+ background: var(--bg-card); border: 1px solid var(--border-strong);
232
+ color: var(--text-main); padding: 10px 18px; border-radius: 30px;
233
+ cursor: pointer; font-family: 'Inter', sans-serif; font-weight: 600;
234
+ font-size: 0.85rem; display: flex; align-items: center; gap: 8px;
235
+ box-shadow: var(--shadow-soft); transition: all 0.3s ease;
236
+ }
237
+ .theme-toggle:hover { transform: translateY(-2px); border-color: var(--gold); box-shadow: var(--shadow-hover); }
238
+ header { text-align: center; margin-bottom: 40px; width: 100%; }
239
+ .project-subtitle {
240
+ font-size: 0.85rem; text-transform: uppercase; letter-spacing: 5px;
241
+ color: var(--gold); margin: 0 0 10px 0; font-weight: 600;
242
+ }
243
+ h1 {
244
+ font-family: 'Playfair Display', serif; font-size: 4.5rem; font-weight: 400;
245
+ letter-spacing: 12px; color: var(--text-main); margin: 0; text-indent: 12px;
246
+ text-shadow: 0 4px 20px rgba(0,0,0,0.05);
247
+ }
248
+ .project-motto {
249
+ font-family: 'Playfair Display', serif; font-style: italic;
250
+ font-size: 1.1rem; color: var(--text-muted); margin-top: 10px;
251
+ }
252
+
253
+ /* ── Control bar ──────────────────────────────── */
254
+ .controls { display: flex; justify-content: center; gap: 12px; margin-bottom: 20px; z-index: 10; }
255
+ .btn {
256
+ padding: 12px 28px; border-radius: 30px; border: none; font-weight: 700;
257
+ cursor: pointer; font-size: 0.95rem; letter-spacing: 0.5px; transition: all 0.2s;
258
+ }
259
+ .btn-run { background: var(--accent-red); color: #fff; box-shadow: 0 4px 15px var(--accent-glow); }
260
+ .btn-run:hover { transform: translateY(-2px); box-shadow: 0 6px 20px var(--accent-glow); }
261
+ .btn-run:disabled { background: #999; cursor: not-allowed; transform: none; box-shadow: none; }
262
+ .btn-report { background: var(--gold); color: var(--btn-text); }
263
+ .btn-report:hover { transform: translateY(-2px); box-shadow: 0 4px 15px rgba(179, 139, 89, 0.4); }
264
+
265
+ /* ── Status bar ───────────────────────────────── */
266
+ .status-bar {
267
+ text-align: center; padding: 14px 24px; margin-bottom: 24px;
268
+ border-radius: 16px; font-size: 0.95rem; font-weight: 600;
269
+ border: 1px solid var(--border-light); transition: .3s;
270
+ box-shadow: var(--shadow-soft);
271
+ }
272
+ .status-bar.idle { background: var(--bg-card); color: var(--text-muted); }
273
+ .status-bar.running { background: var(--accent-gold); color: #fff; animation: pulse 1.5s infinite; }
274
+ .status-bar.done { background: var(--accent-green); color: #fff; }
275
+ .status-bar.error { background: var(--accent-red); color: #fff; }
276
+ @keyframes pulse { 0%,100% { opacity:1 } 50% { opacity:0.7 } }
277
+
278
+ /* ── Board ────────────────────────────────────── */
279
+ .kanban-container {
280
+ display: grid; grid-template-columns: 220px repeat(5, 1fr); gap: 16px;
281
+ width: 100%; max-width: 1500px; background-color: var(--bg-board);
282
+ padding: 24px; border-radius: 24px; border: 1px solid var(--border-light);
283
+ box-shadow: var(--shadow-soft); overflow-x: auto;
284
+ transition: background-color 0.4s ease, border-color 0.4s ease;
285
+ }
286
+ .row-headers-column { display: grid; grid-template-rows: 60px repeat(4, 1fr); gap: 16px; }
287
+ .board-corner { height: 60px; }
288
+ .row-header-card {
289
+ background-color: transparent; border-right: 2px solid var(--border-strong);
290
+ display: flex; flex-direction: column; justify-content: center;
291
+ padding-right: 15px; text-align: right;
292
+ }
293
+ .row-header-card h3 { margin: 0; font-family: 'Playfair Display', serif; font-size: 1.1rem; font-weight: 600; }
294
+ .row-header-card span { font-size: 0.75rem; color: var(--text-muted); margin-top: 4px; text-transform: uppercase; letter-spacing: 2px; }
295
+
296
+ .kanban-column { display: grid; grid-template-rows: 60px repeat(4, 1fr); gap: 16px; }
297
+ .column-header {
298
+ display: flex; flex-direction: column; justify-content: center; align-items: center;
299
+ background-color: var(--bg-column); border-radius: 12px;
300
+ font-family: 'Playfair Display', serif; font-size: 1.1rem;
301
+ border: 1px solid var(--border-light);
302
+ box-shadow: inset 0 2px 5px rgba(255,255,255,0.05);
303
+ }
304
+ .column-header span {
305
+ font-family: 'Inter', sans-serif; font-size: 0.7rem; font-weight: 600;
306
+ text-transform: uppercase; letter-spacing: 2px; color: var(--gold); margin-top: 2px;
307
+ }
308
+
309
+ .kanban-card, .empty-slot { cursor: pointer; transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1); }
310
+ .kanban-card {
311
+ background-color: var(--bg-card); border-radius: 16px; padding: 20px;
312
+ box-shadow: var(--shadow-soft); display: flex; flex-direction: column;
313
+ border: 1px solid var(--border-light); position: relative; overflow: hidden;
314
+ }
315
+ .kanban-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-hover); border-color: var(--gold); }
316
+ .kanban-card::after {
317
+ content: "\\2726"; position: absolute; top: 15px; right: 15px;
318
+ font-size: 0.9rem; color: var(--gold); opacity: 0.4; transition: opacity 0.3s;
319
+ }
320
+ .kanban-card:hover::after { opacity: 1; }
321
+
322
+ .kanban-card.phase-active { box-shadow: 0 0 0 3px var(--accent-gold), var(--shadow-hover); }
323
+ .kanban-card.phase-done { box-shadow: 0 0 0 3px var(--accent-green), var(--shadow-soft); }
324
+ .kanban-card.phase-failed { box-shadow: 0 0 0 3px var(--accent-red), var(--shadow-soft); }
325
+
326
+ .kanban-card.high-priority {
327
+ background-color: var(--accent-red); color: #ffffff;
328
+ border-color: var(--accent-red); box-shadow: 0 8px 24px var(--accent-glow);
329
+ }
330
+ .kanban-card.high-priority::after { color: #ffffff; opacity: 0.8; }
331
+ .kanban-card.high-priority .card-desc, .kanban-card.high-priority .card-title { color: #ffffff; }
332
+
333
+ .priority-badge {
334
+ font-size: 0.65rem; text-transform: uppercase; letter-spacing: 1.5px; font-weight: 700;
335
+ margin-bottom: 12px; display: inline-block; background: var(--bg-base);
336
+ color: var(--text-main); padding: 4px 10px; border-radius: 20px; border: 1px solid var(--border-light);
337
+ }
338
+ .kanban-card.high-priority .priority-badge {
339
+ background: rgba(255,255,255,0.15); color: #ffffff; border-color: rgba(255,255,255,0.3);
340
+ }
341
+ .card-title { font-family: 'Playfair Display', serif; font-size: 1.1rem; margin: 0 0 8px 0; font-weight: 600; line-height: 1.3; }
342
+ .card-desc { font-size: 0.85rem; line-height: 1.5; margin: 0 0 16px 0; color: var(--text-muted); }
343
+ .card-footer { display: flex; justify-content: space-between; align-items: center; font-size: 0.8rem; border-top: 1px solid var(--border-light); padding-top: 12px; margin-top: auto; }
344
+ .kanban-card.high-priority .card-footer { border-top-color: rgba(255,255,255,0.2); }
345
+ .provider-tag { font-weight: 600; letter-spacing: 0.5px; color: var(--gold); }
346
+ .kanban-card.high-priority .provider-tag { color: #ffffff; }
347
+ .avatar {
348
+ width: 26px; height: 26px; border-radius: 50%; background-color: var(--bg-base);
349
+ display: flex; align-items: center; justify-content: center;
350
+ font-weight: 700; font-size: 0.65rem; border: 1px solid var(--border-strong);
351
+ }
352
+ .empty-slot {
353
+ border: 1px dashed var(--border-strong); border-radius: 16px; display: flex;
354
+ align-items: center; justify-content: center; color: var(--text-muted);
355
+ font-size: 0.8rem; font-weight: 500; letter-spacing: 1px; position: relative;
356
+ }
357
+ .empty-slot::before { content: "+"; font-size: 1.5rem; margin-right: 8px; font-weight: 300; }
358
+ .empty-slot:hover { border-style: solid; border-color: var(--gold); background-color: rgba(179, 139, 89, 0.05); color: var(--gold); }
359
+
360
+ /* ── Report panel ─────────────────────────────── */
361
+ #report-panel {
362
+ display: none; max-width: 1000px; margin: 0 auto 20px;
363
+ background: var(--bg-card); border-radius: 24px; padding: 32px;
364
+ box-shadow: var(--shadow-soft); border: 1px solid var(--border-light);
365
+ }
366
+ #report-panel h2 { font-family: 'Playfair Display', serif; margin-bottom: 16px; }
367
+ #report-panel pre {
368
+ background: #2c1e14; color: #ede0cc; padding: 16px; border-radius: 12px;
369
+ font-size: 0.85rem; line-height: 1.6; overflow-x: auto; white-space: pre-wrap;
370
+ }
371
+ .report-stats { display: flex; gap: 20px; margin-bottom: 16px; flex-wrap: wrap; }
372
+ .stat-box {
373
+ background: var(--bg-column); padding: 12px 20px; border-radius: 12px;
374
+ text-align: center; min-width: 100px; border: 1px solid var(--border-light);
375
+ }
376
+ .stat-box .num { font-size: 1.8rem; font-weight: 700; font-family: 'Playfair Display', serif; }
377
+ .stat-box .label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 1px; color: var(--text-muted); }
378
+
379
+ /* ── Progress log ─────────────────────────────── */
380
+ #progress-log {
381
+ max-width: 1000px; margin: 0 auto 20px; background: #2c1e14; color: #ede0cc;
382
+ border-radius: 12px; padding: 16px; font-family: monospace; font-size: 0.8rem;
383
+ max-height: 200px; overflow-y: auto; display: none;
384
+ }
385
+ .log-line { padding: 2px 0; border-bottom: 1px solid rgba(255,255,255,0.05); }
386
+ .log-line.start { color: var(--accent-gold); }
387
+ .log-line.done { color: var(--accent-green); }
388
+ .log-line.fail { color: var(--accent-red); }
389
+
390
+ footer {
391
+ margin-top: 50px; font-family: 'Playfair Display', serif; font-size: 1.2rem;
392
+ font-style: italic; color: var(--text-muted); letter-spacing: 2px;
393
+ display: flex; align-items: center; gap: 15px;
394
+ }
395
+ footer::before, footer::after {
396
+ content: ""; display: block; width: 40px; height: 1px;
397
+ background: var(--gold); opacity: 0.5;
398
+ }
399
+
400
+ /* ── Modal ────────────────────────────────────── */
401
+ .modal-overlay {
402
+ position: fixed; top: 0; left: 0; width: 100%; height: 100%;
403
+ background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(8px);
404
+ display: flex; align-items: center; justify-content: center;
405
+ z-index: 1000; opacity: 0; pointer-events: none;
406
+ transition: opacity 0.3s ease;
407
+ }
408
+ .modal-overlay.active { opacity: 1; pointer-events: auto; }
409
+ .modal-box {
410
+ background-color: var(--bg-card); padding: 40px; border-radius: 24px;
411
+ border: 1px solid var(--border-light); width: 100%; max-width: 500px;
412
+ box-shadow: 0 24px 60px rgba(0,0,0,0.4);
413
+ transform: translateY(20px) scale(0.95);
414
+ transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
415
+ }
416
+ .modal-overlay.active .modal-box { transform: translateY(0) scale(1); }
417
+ .modal-box h2 {
418
+ font-family: 'Playfair Display', serif; margin: 0 0 24px 0;
419
+ color: var(--text-main); font-size: 1.8rem; font-weight: 400; text-align: center;
420
+ }
421
+ .form-group { margin-bottom: 20px; display: flex; flex-direction: column; }
422
+ .form-group label {
423
+ font-size: 0.75rem; text-transform: uppercase; letter-spacing: 2px;
424
+ margin-bottom: 8px; font-weight: 600; color: var(--text-muted);
425
+ }
426
+ .form-group input, .form-group textarea, .form-group select {
427
+ padding: 14px; border-radius: 12px; border: 1px solid var(--border-strong);
428
+ background: var(--bg-base); font-family: 'Inter', sans-serif;
429
+ font-size: 0.95rem; color: var(--text-main); transition: all 0.2s ease;
430
+ }
431
+ .form-group input:focus, .form-group textarea:focus, .form-group select:focus {
432
+ outline: none; border-color: var(--gold);
433
+ box-shadow: 0 0 0 3px rgba(179, 139, 89, 0.15);
434
+ }
435
+ .form-group textarea { resize: vertical; min-height: 100px; }
436
+ .modal-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 30px; }
437
+ .btn-cancel { background: var(--bg-board); color: var(--text-main); }
438
+ .btn-cancel:hover { background: var(--border-strong); }
439
+ .btn-save { background: var(--gold); color: var(--btn-text); }
440
+ .btn-save:hover { transform: translateY(-2px); box-shadow: 0 4px 15px rgba(179, 139, 89, 0.4); }
441
+ .btn-clear {
442
+ background: transparent; color: var(--accent-red); margin-right: auto;
443
+ border: 1px dashed var(--accent-red);
444
+ }
445
+ .btn-clear:hover { background: rgba(163, 76, 56, 0.05); }
446
+ </style>
447
+ </head>
448
+ <body>
449
+
450
+ <div class="theme-toggle-wrapper">
451
+ <button id="themeToggle" class="theme-toggle">
452
+ <span id="themeIcon">\\uD83C\\uDF19</span> <span id="themeText">Dark Mode</span>
453
+ </button>
454
+ </div>
455
+
456
+ <header>
457
+ <div class="project-subtitle">Autonomous Coding Agent</div>
458
+ <h1>AURA</h1>
459
+ <div class="project-motto">"I don't try. I verify."</div>
460
+ </header>
461
+
462
+ <div class="controls">
463
+ <button class="btn btn-run" id="runBtn" onclick="runPipeline()">\\u25B6 Execute Pipeline</button>
464
+ <button class="btn btn-report" id="reportBtn" onclick="showReport()" style="display:none">\\uD83D\\uDCCB Show Report</button>
465
+ </div>
466
+
467
+ <div class="status-bar idle" id="statusBar">Ready \\u2014 Click "Execute Pipeline" to run all tasks through Read \\u2192 Plan \\u2192 Execute \\u2192 Verify \\u2192 Report</div>
468
+
469
+ <div id="progress-log"></div>
470
+
471
+ <div class="kanban-container" id="board">
472
+ <div class="row-headers-column">
473
+ <div class="board-corner"></div>
474
+ ${rowHeaders}
475
+ </div>
476
+ ${columnsHtml}
477
+ </div>
478
+
479
+ <div id="report-panel">
480
+ <h2>\\uD83D\\uDCCA Pipeline Execution Report</h2>
481
+ <div class="report-stats" id="reportStats"></div>
482
+ <pre id="reportContent"></pre>
483
+ </div>
484
+
485
+ <footer>let me be your Aura.</footer>
486
+
487
+ <!-- Edit / Create Modal -->
488
+ <div class="modal-overlay" id="editModal">
489
+ <div class="modal-box">
490
+ <h2 id="modalTitleHeader">Edit Crystal</h2>
491
+ <form id="editForm">
492
+ <div class="form-group">
493
+ <label for="taskBadge">Context Badge</label>
494
+ <input type="text" id="taskBadge" placeholder="e.g., Active Coder">
495
+ </div>
496
+ <div class="form-group">
497
+ <label for="taskTitle">Objective Title</label>
498
+ <input type="text" id="taskTitle" required placeholder="What needs to be done?">
499
+ </div>
500
+ <div class="form-group">
501
+ <label for="taskDesc">Details</label>
502
+ <textarea id="taskDesc" placeholder="Provide deeper architectural context..."></textarea>
503
+ </div>
504
+ <div class="form-group">
505
+ <label for="taskTag">System Tag</label>
506
+ <input type="text" id="taskTag" placeholder="e.g., GPT-4o, Vitest">
507
+ </div>
508
+ <div class="form-group">
509
+ <label for="taskPriority">Energy Level</label>
510
+ <select id="taskPriority">
511
+ <option value="normal">Standard (Base Flow)</option>
512
+ <option value="high">Ignited (High Priority)</option>
513
+ </select>
514
+ </div>
515
+ <div class="modal-actions">
516
+ <button type="button" class="btn btn-clear" id="clearCardBtn" style="display:none">Clear Slot</button>
517
+ <button type="button" class="btn btn-cancel" id="closeModalBtn">Cancel</button>
518
+ <button type="submit" class="btn btn-save">Imprint Changes</button>
519
+ </div>
520
+ </form>
521
+ </div>
522
+ </div>
523
+
524
+ <script>
525
+ // Theme toggle
526
+ (function() {
527
+ var tt = document.getElementById('themeToggle');
528
+ var ti = document.getElementById('themeIcon');
529
+ var tx = document.getElementById('themeText');
530
+ if (localStorage.getItem('aura-theme') === 'dark') {
531
+ document.documentElement.setAttribute('data-theme', 'dark');
532
+ ti.textContent = '\\u2600\\uFE0F'; tx.textContent = 'Light Mode';
533
+ }
534
+ tt.addEventListener('click', function() {
535
+ var r = document.documentElement;
536
+ if (r.getAttribute('data-theme') === 'dark') {
537
+ r.setAttribute('data-theme', 'light');
538
+ localStorage.setItem('aura-theme', 'light');
539
+ ti.textContent = '\\uD83C\\uDF19'; tx.textContent = 'Dark Mode';
540
+ } else {
541
+ r.setAttribute('data-theme', 'dark');
542
+ localStorage.setItem('aura-theme', 'dark');
543
+ ti.textContent = '\\u2600\\uFE0F'; tx.textContent = 'Light Mode';
544
+ }
545
+ });
546
+ })();
547
+
548
+ // Pipeline
549
+ var ws;
550
+ var logEl = document.getElementById('progress-log');
551
+ var statusBar = document.getElementById('statusBar');
552
+
553
+ function connect() {
554
+ ws = new WebSocket('ws://' + location.host);
555
+ ws.onmessage = function(e) { handleProgress(JSON.parse(e.data)); };
556
+ ws.onclose = function() { setTimeout(connect, 2000); };
557
+ }
558
+
559
+ function handleProgress(ev) {
560
+ if (ev.type === 'phase_start') {
561
+ setStatus('running', 'Running: ' + ev.phase.toUpperCase() + ' \\u2014 ' + ev.taskId);
562
+ highlightCard(ev.taskId, 'active');
563
+ addLog('\\u25B6 ' + ev.phase.toUpperCase() + ' \\u2192 ' + ev.taskId, 'start');
564
+ } else if (ev.type === 'phase_done') {
565
+ var icon = ev.status === 'done' ? '\\u2713' : ev.status === 'failed' ? '\\u2717' : '\\u25CB';
566
+ highlightCard(ev.taskId, ev.status === 'done' ? 'done' : ev.status === 'failed' ? 'failed' : '');
567
+ addLog(icon + ' ' + ev.phase.toUpperCase() + ' \\u2192 ' + ev.taskId + ' [' + ev.status + ']', ev.status === 'done' ? 'done' : 'fail');
568
+ } else if (ev.type === 'row_done') {
569
+ addLog('\\u2500\\u2500 Row ' + ev.row + ' complete: ' + ev.status, 'done');
570
+ } else if (ev.type === 'pipeline_done') {
571
+ setStatus('done', 'Pipeline complete!');
572
+ document.getElementById('runBtn').disabled = false;
573
+ document.getElementById('runBtn').textContent = '\\u25B6 Execute Pipeline';
574
+ document.getElementById('reportBtn').style.display = 'inline-block';
575
+ loadReport();
576
+ } else if (ev.type === 'error') {
577
+ setStatus('error', 'Error: ' + ev.message);
578
+ document.getElementById('runBtn').disabled = false;
579
+ }
580
+ }
581
+
582
+ function setStatus(cls, text) { statusBar.className = 'status-bar ' + cls; statusBar.textContent = text; }
583
+
584
+ function highlightCard(taskId, cls) {
585
+ var el = document.querySelector('[data-id="' + taskId + '"]');
586
+ if (!el) return;
587
+ el.classList.remove('phase-active', 'phase-done', 'phase-failed');
588
+ if (cls) el.classList.add('phase-' + cls);
589
+ }
590
+
591
+ function addLog(text, cls) {
592
+ logEl.style.display = 'block';
593
+ var line = document.createElement('div');
594
+ line.className = 'log-line ' + (cls || '');
595
+ line.textContent = text;
596
+ logEl.appendChild(line);
597
+ logEl.scrollTop = logEl.scrollHeight;
598
+ }
599
+
600
+ function runPipeline() {
601
+ var btn = document.getElementById('runBtn');
602
+ btn.disabled = true; btn.textContent = '\\u23F3 Running...';
603
+ document.getElementById('reportBtn').style.display = 'none';
604
+ logEl.innerHTML = ''; logEl.style.display = 'block';
605
+ setStatus('running', 'Starting pipeline execution...');
606
+ addLog('Pipeline started', 'start');
607
+ document.querySelectorAll('.kanban-card').forEach(function(c) {
608
+ c.classList.remove('phase-active', 'phase-done', 'phase-failed');
609
+ });
610
+ fetch('/api/execute', { method: 'POST' })
611
+ .then(function(r) { return r.json(); })
612
+ .then(function(report) {
613
+ if (report.error) {
614
+ setStatus('error', 'Error: ' + report.error);
615
+ btn.disabled = false; btn.textContent = '\\u25B6 Execute Pipeline';
616
+ }
617
+ })
618
+ .catch(function(e) {
619
+ setStatus('error', 'Network error: ' + e.message);
620
+ btn.disabled = false; btn.textContent = '\\u25B6 Execute Pipeline';
621
+ });
622
+ }
623
+
624
+ function loadReport() {
625
+ fetch('/api/report').then(function(r) { return r.json(); }).then(function(report) { renderReport(report); });
626
+ }
627
+
628
+ function renderReport(report) {
629
+ document.getElementById('report-panel').style.display = 'block';
630
+ document.getElementById('reportStats').innerHTML =
631
+ '<div class="stat-box"><div class="num">' + report.stats.totalTasks + '</div><div class="label">Total Tasks</div></div>' +
632
+ '<div class="stat-box"><div class="num" style="color:var(--accent-green)">' + report.stats.completed + '</div><div class="label">Completed</div></div>' +
633
+ '<div class="stat-box"><div class="num" style="color:var(--accent-red)">' + report.stats.failed + '</div><div class="label">Failed</div></div>' +
634
+ '<div class="stat-box"><div class="num" style="color:var(--accent-gold)">' + Math.round(report.totalDurationMs / 1000) + 's</div><div class="label">Duration</div></div>';
635
+ var lines = [];
636
+ lines.push('\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550');
637
+ lines.push(' AURA \\u2014 PIPELINE EXECUTION REPORT');
638
+ lines.push(' Generated: ' + report.generatedAt);
639
+ lines.push(' Duration: ' + Math.round(report.totalDurationMs / 1000) + ' seconds');
640
+ lines.push('\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550\\u2550');
641
+ report.rows.forEach(function(row) {
642
+ lines.push('');
643
+ lines.push('\\u250C\\u2500 ' + row.label + ' [' + row.status.toUpperCase() + ']');
644
+ row.executions.forEach(function(exec) {
645
+ var icon = exec.status === 'done' ? '\\u2713' : exec.status === 'failed' ? '\\u2717' : '\\u25CB';
646
+ lines.push('\\u2502');
647
+ lines.push('\\u2502 ' + icon + ' ' + exec.task.title);
648
+ lines.push('\\u2502 Badge: ' + exec.task.badge + ' | Tag: ' + exec.task.tag);
649
+ exec.phases.forEach(function(phase) {
650
+ var pIcon = phase.status === 'done' ? '\\u2713' : phase.status === 'failed' ? '\\u2717' : '\\u2580';
651
+ lines.push('\\u2502 [' + pIcon + ' ' + phase.phase.toUpperCase() + '] ' + phase.status + ' (' + phase.durationMs + 'ms)');
652
+ if (phase.output) phase.output.split('\\n').forEach(function(l) { lines.push('\\u2502 ' + l); });
653
+ });
654
+ lines.push('\\u2502');
655
+ });
656
+ lines.push('\\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500');
657
+ });
658
+ lines.push('');
659
+ lines.push(' SUMMARY: ' + report.stats.totalTasks + ' tasks, ' + report.stats.completed + ' completed, ' + report.stats.failed + ' failed');
660
+ document.getElementById('reportContent').textContent = lines.join('\\n');
661
+ }
662
+
663
+ function showReport() { document.getElementById('report-panel').scrollIntoView({ behavior: 'smooth' }); }
664
+
665
+ // ── Board interaction: click card → modal, click empty → modal, save/clear ──
666
+ (function() {
667
+ var currentTarget = null;
668
+ var board = document.getElementById('board');
669
+ var modal = document.getElementById('editModal');
670
+ var editForm = document.getElementById('editForm');
671
+ var taskBadge = document.getElementById('taskBadge');
672
+ var taskTitle = document.getElementById('taskTitle');
673
+ var taskDesc = document.getElementById('taskDesc');
674
+ var taskTag = document.getElementById('taskTag');
675
+ var taskPriority = document.getElementById('taskPriority');
676
+ var closeModalBtn = document.getElementById('closeModalBtn');
677
+ var clearCardBtn = document.getElementById('clearCardBtn');
678
+
679
+ board.addEventListener('click', function(e) {
680
+ var square = e.target.closest('.kanban-card, .empty-slot');
681
+ if (!square) return;
682
+ currentTarget = square;
683
+ var isCard = square.classList.contains('kanban-card');
684
+
685
+ if (isCard) {
686
+ taskBadge.value = square.querySelector('.priority-badge') ? square.querySelector('.priority-badge').innerText : '';
687
+ taskTitle.value = square.querySelector('.card-title') ? square.querySelector('.card-title').innerText : '';
688
+ taskDesc.value = square.querySelector('.card-desc') ? square.querySelector('.card-desc').innerText : '';
689
+ taskTag.value = square.querySelector('.provider-tag') ? square.querySelector('.provider-tag').innerText : '';
690
+ taskPriority.value = square.classList.contains('high-priority') ? 'high' : 'normal';
691
+ clearCardBtn.style.display = 'block';
692
+ } else {
693
+ taskBadge.value = '';
694
+ taskTitle.value = '';
695
+ taskDesc.value = '';
696
+ taskTag.value = '';
697
+ taskPriority.value = 'normal';
698
+ clearCardBtn.style.display = 'none';
699
+ }
700
+ modal.classList.add('active');
701
+ });
702
+
703
+ function closeModal() { modal.classList.remove('active'); currentTarget = null; }
704
+ closeModalBtn.addEventListener('click', closeModal);
705
+ modal.addEventListener('click', function(e) { if (e.target === modal) closeModal(); });
706
+
707
+ clearCardBtn.addEventListener('click', function() {
708
+ if (!currentTarget) return;
709
+ var rowAttr = currentTarget.getAttribute('data-row');
710
+ var emptySlot = document.createElement('div');
711
+ emptySlot.className = 'empty-slot';
712
+ if (rowAttr) emptySlot.setAttribute('data-row', rowAttr);
713
+ emptySlot.textContent = 'Empty';
714
+ currentTarget.replaceWith(emptySlot);
715
+ closeModal();
716
+ });
717
+
718
+ editForm.addEventListener('submit', function(e) {
719
+ e.preventDefault();
720
+ if (!currentTarget) return;
721
+ var rowAttr = currentTarget.getAttribute('data-row');
722
+ var card = document.createElement('div');
723
+ card.className = 'kanban-card';
724
+ if (taskPriority.value === 'high') card.classList.add('high-priority');
725
+ if (rowAttr) card.setAttribute('data-row', rowAttr);
726
+
727
+ var topDiv = document.createElement('div');
728
+ if (taskBadge.value.trim()) {
729
+ var badge = document.createElement('span');
730
+ badge.className = 'priority-badge';
731
+ badge.innerText = taskBadge.value;
732
+ topDiv.appendChild(badge);
733
+ }
734
+ var h4 = document.createElement('h4');
735
+ h4.className = 'card-title';
736
+ h4.innerText = taskTitle.value || 'New Objective';
737
+ topDiv.appendChild(h4);
738
+
739
+ var p = document.createElement('p');
740
+ p.className = 'card-desc';
741
+ p.innerText = taskDesc.value || 'No description provided.';
742
+ topDiv.appendChild(p);
743
+
744
+ var footer = document.createElement('div');
745
+ footer.className = 'card-footer';
746
+ var tagSpan = document.createElement('span');
747
+ tagSpan.className = 'provider-tag';
748
+ tagSpan.innerText = taskTag.value || 'System';
749
+ footer.appendChild(tagSpan);
750
+ var avatar = document.createElement('div');
751
+ avatar.className = 'avatar';
752
+ avatar.innerText = (taskTitle.value || 'XX').substring(0, 2).toUpperCase();
753
+ footer.appendChild(avatar);
754
+
755
+ card.appendChild(topDiv);
756
+ card.appendChild(footer);
757
+ currentTarget.replaceWith(card);
758
+ closeModal();
759
+ });
760
+ })();
761
+
762
+ connect();
763
+ </script>
764
+ </body>
765
+ </html>`;
766
+ }
767
+ // ─────────────────────────────────────────────────────────────────────────────
768
+ // Markdown report renderer
769
+ // ─────────────────────────────────────────────────────────────────────────────
770
+ function renderReportMarkdown(report) {
771
+ const lines = [];
772
+ lines.push('# Aura Code — Pipeline Execution Report');
773
+ lines.push('');
774
+ lines.push(`**Generated:** ${report.generatedAt}`);
775
+ lines.push(`**Duration:** ${(report.totalDurationMs / 1000).toFixed(1)}s`);
776
+ lines.push('');
777
+ lines.push('## Summary');
778
+ lines.push('');
779
+ lines.push(`| Metric | Count |`);
780
+ lines.push(`|--------|-------|`);
781
+ lines.push(`| Total Tasks | ${report.stats.totalTasks} |`);
782
+ lines.push(`| Completed | ${report.stats.completed} |`);
783
+ lines.push(`| Failed | ${report.stats.failed} |`);
784
+ lines.push(`| Skipped | ${report.stats.skipped} |`);
785
+ lines.push('');
786
+ for (const row of report.rows) {
787
+ lines.push(`## ${row.label} — ${row.status.toUpperCase()}`);
788
+ lines.push('');
789
+ for (const exec of row.executions) {
790
+ const icon = exec.status === 'done' ? '✅' : exec.status === 'failed' ? '❌' : '⏭️';
791
+ lines.push(`### ${icon} ${exec.task.title}`);
792
+ lines.push('');
793
+ lines.push(`- **Badge:** ${exec.task.badge}`);
794
+ lines.push(`- **Tag:** ${exec.task.tag}`);
795
+ lines.push(`- **Priority:** ${exec.task.highPriority ? 'HIGH' : 'Normal'}`);
796
+ lines.push(`- **Status:** ${exec.status}`);
797
+ lines.push('');
798
+ for (const phase of exec.phases) {
799
+ const pIcon = phase.status === 'done' ? '✓' : phase.status === 'failed' ? '✗' : '⊘';
800
+ lines.push(`**${pIcon} ${phase.phase.toUpperCase()}** (${phase.durationMs}ms) — ${phase.status}`);
801
+ if (phase.output) {
802
+ lines.push('```');
803
+ lines.push(phase.output);
804
+ lines.push('```');
805
+ }
806
+ lines.push('');
807
+ }
808
+ }
809
+ }
810
+ lines.push('---');
811
+ lines.push('*Generated by Aura Code Kanban Pipeline Server*');
812
+ return lines.join('\n');
813
+ }
814
+ // ─────────────────────────────────────────────────────────────────────────────
815
+ // Helpers
816
+ // ─────────────────────────────────────────────────────────────────────────────
817
+ function esc(s) {
818
+ return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
819
+ }
820
+ //# sourceMappingURL=server.js.map