@dewtech/dare-cli 3.10.0 → 3.11.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 (150) hide show
  1. package/README.md +5 -1
  2. package/dist/__tests__/ci-pr-regression.test.d.ts +2 -0
  3. package/dist/__tests__/ci-pr-regression.test.d.ts.map +1 -0
  4. package/dist/__tests__/ci-pr-regression.test.js +76 -0
  5. package/dist/__tests__/ci-pr-regression.test.js.map +1 -0
  6. package/dist/__tests__/dashboard-front.test.d.ts +2 -0
  7. package/dist/__tests__/dashboard-front.test.d.ts.map +1 -0
  8. package/dist/__tests__/dashboard-front.test.js +37 -0
  9. package/dist/__tests__/dashboard-front.test.js.map +1 -0
  10. package/dist/__tests__/dashboard-regression.test.d.ts +2 -0
  11. package/dist/__tests__/dashboard-regression.test.d.ts.map +1 -0
  12. package/dist/__tests__/dashboard-regression.test.js +68 -0
  13. package/dist/__tests__/dashboard-regression.test.js.map +1 -0
  14. package/dist/__tests__/dynamic-dag-regression.test.d.ts +2 -0
  15. package/dist/__tests__/dynamic-dag-regression.test.d.ts.map +1 -0
  16. package/dist/__tests__/dynamic-dag-regression.test.js +464 -0
  17. package/dist/__tests__/dynamic-dag-regression.test.js.map +1 -0
  18. package/dist/__tests__/ide-command-parity.test.js +1 -0
  19. package/dist/__tests__/ide-command-parity.test.js.map +1 -1
  20. package/dist/bin/dare.js +2 -0
  21. package/dist/bin/dare.js.map +1 -1
  22. package/dist/commands/__tests__/dashboard-command.test.d.ts +2 -0
  23. package/dist/commands/__tests__/dashboard-command.test.d.ts.map +1 -0
  24. package/dist/commands/__tests__/dashboard-command.test.js +62 -0
  25. package/dist/commands/__tests__/dashboard-command.test.js.map +1 -0
  26. package/dist/commands/__tests__/gate-flags.test.d.ts +2 -0
  27. package/dist/commands/__tests__/gate-flags.test.d.ts.map +1 -0
  28. package/dist/commands/__tests__/gate-flags.test.js +58 -0
  29. package/dist/commands/__tests__/gate-flags.test.js.map +1 -0
  30. package/dist/commands/__tests__/persist-viz.test.d.ts +2 -0
  31. package/dist/commands/__tests__/persist-viz.test.d.ts.map +1 -0
  32. package/dist/commands/__tests__/persist-viz.test.js +178 -0
  33. package/dist/commands/__tests__/persist-viz.test.js.map +1 -0
  34. package/dist/commands/__tests__/refine-apply.test.d.ts +2 -0
  35. package/dist/commands/__tests__/refine-apply.test.d.ts.map +1 -0
  36. package/dist/commands/__tests__/refine-apply.test.js +118 -0
  37. package/dist/commands/__tests__/refine-apply.test.js.map +1 -0
  38. package/dist/commands/__tests__/replan-splice.test.d.ts +2 -0
  39. package/dist/commands/__tests__/replan-splice.test.d.ts.map +1 -0
  40. package/dist/commands/__tests__/replan-splice.test.js +295 -0
  41. package/dist/commands/__tests__/replan-splice.test.js.map +1 -0
  42. package/dist/commands/dag.d.ts.map +1 -1
  43. package/dist/commands/dag.js +2 -0
  44. package/dist/commands/dag.js.map +1 -1
  45. package/dist/commands/dashboard.d.ts +17 -0
  46. package/dist/commands/dashboard.d.ts.map +1 -0
  47. package/dist/commands/dashboard.js +77 -0
  48. package/dist/commands/dashboard.js.map +1 -0
  49. package/dist/commands/execute.d.ts.map +1 -1
  50. package/dist/commands/execute.js +108 -2
  51. package/dist/commands/execute.js.map +1 -1
  52. package/dist/commands/graph.d.ts.map +1 -1
  53. package/dist/commands/graph.js +33 -5
  54. package/dist/commands/graph.js.map +1 -1
  55. package/dist/commands/guard.d.ts.map +1 -1
  56. package/dist/commands/guard.js +27 -3
  57. package/dist/commands/guard.js.map +1 -1
  58. package/dist/commands/refine.d.ts +2 -0
  59. package/dist/commands/refine.d.ts.map +1 -1
  60. package/dist/commands/refine.js +71 -20
  61. package/dist/commands/refine.js.map +1 -1
  62. package/dist/commands/review.d.ts.map +1 -1
  63. package/dist/commands/review.js +36 -5
  64. package/dist/commands/review.js.map +1 -1
  65. package/dist/dag-runner/__tests__/maxdepth-config.test.d.ts +2 -0
  66. package/dist/dag-runner/__tests__/maxdepth-config.test.d.ts.map +1 -0
  67. package/dist/dag-runner/__tests__/maxdepth-config.test.js +28 -0
  68. package/dist/dag-runner/__tests__/maxdepth-config.test.js.map +1 -0
  69. package/dist/dag-runner/__tests__/sub-dag.test.d.ts +2 -0
  70. package/dist/dag-runner/__tests__/sub-dag.test.d.ts.map +1 -0
  71. package/dist/dag-runner/__tests__/sub-dag.test.js +127 -0
  72. package/dist/dag-runner/__tests__/sub-dag.test.js.map +1 -0
  73. package/dist/dag-runner/run_dag.d.ts +2 -0
  74. package/dist/dag-runner/run_dag.d.ts.map +1 -1
  75. package/dist/dag-runner/run_dag.js.map +1 -1
  76. package/dist/dag-runner/state-store.d.ts +2 -0
  77. package/dist/dag-runner/state-store.d.ts.map +1 -1
  78. package/dist/dag-runner/state-store.js +44 -8
  79. package/dist/dag-runner/state-store.js.map +1 -1
  80. package/dist/dag-runner/sub-dag.d.ts +23 -0
  81. package/dist/dag-runner/sub-dag.d.ts.map +1 -0
  82. package/dist/dag-runner/sub-dag.js +117 -0
  83. package/dist/dag-runner/sub-dag.js.map +1 -0
  84. package/dist/dashboard/__tests__/dashboard-routes.test.d.ts +2 -0
  85. package/dist/dashboard/__tests__/dashboard-routes.test.d.ts.map +1 -0
  86. package/dist/dashboard/__tests__/dashboard-routes.test.js +102 -0
  87. package/dist/dashboard/__tests__/dashboard-routes.test.js.map +1 -0
  88. package/dist/dashboard/routes.d.ts +8 -0
  89. package/dist/dashboard/routes.d.ts.map +1 -0
  90. package/dist/dashboard/routes.js +70 -0
  91. package/dist/dashboard/routes.js.map +1 -0
  92. package/dist/graphrag/__tests__/hybrid-integration.test.js +1 -1
  93. package/dist/graphrag/__tests__/hybrid-integration.test.js.map +1 -1
  94. package/dist/graphrag/__tests__/no-heavy-dep-in-core.test.js +2 -2
  95. package/dist/graphrag/__tests__/no-heavy-dep-in-core.test.js.map +1 -1
  96. package/dist/graphrag/embeddings.js +1 -1
  97. package/dist/graphrag/embeddings.js.map +1 -1
  98. package/dist/http/__tests__/shared-app.test.d.ts +2 -0
  99. package/dist/http/__tests__/shared-app.test.d.ts.map +1 -0
  100. package/dist/http/__tests__/shared-app.test.js +57 -0
  101. package/dist/http/__tests__/shared-app.test.js.map +1 -0
  102. package/dist/http/app.d.ts +15 -0
  103. package/dist/http/app.d.ts.map +1 -0
  104. package/dist/http/app.js +32 -0
  105. package/dist/http/app.js.map +1 -0
  106. package/dist/mcp-server/server.d.ts.map +1 -1
  107. package/dist/mcp-server/server.js +5 -15
  108. package/dist/mcp-server/server.js.map +1 -1
  109. package/dist/reporters/__tests__/github-reporter.test.d.ts +2 -0
  110. package/dist/reporters/__tests__/github-reporter.test.d.ts.map +1 -0
  111. package/dist/reporters/__tests__/github-reporter.test.js +93 -0
  112. package/dist/reporters/__tests__/github-reporter.test.js.map +1 -0
  113. package/dist/reporters/ci-gate.d.ts +27 -0
  114. package/dist/reporters/ci-gate.d.ts.map +1 -0
  115. package/dist/reporters/ci-gate.js +100 -0
  116. package/dist/reporters/ci-gate.js.map +1 -0
  117. package/dist/reporters/github.d.ts +36 -0
  118. package/dist/reporters/github.d.ts.map +1 -0
  119. package/dist/reporters/github.js +142 -0
  120. package/dist/reporters/github.js.map +1 -0
  121. package/dist/telemetry/__tests__/aggregator.test.d.ts +2 -0
  122. package/dist/telemetry/__tests__/aggregator.test.d.ts.map +1 -0
  123. package/dist/telemetry/__tests__/aggregator.test.js +164 -0
  124. package/dist/telemetry/__tests__/aggregator.test.js.map +1 -0
  125. package/dist/telemetry/aggregator.d.ts +43 -0
  126. package/dist/telemetry/aggregator.d.ts.map +1 -0
  127. package/dist/telemetry/aggregator.js +282 -0
  128. package/dist/telemetry/aggregator.js.map +1 -0
  129. package/dist/utils/excalidraw-renderer.d.ts.map +1 -1
  130. package/dist/utils/excalidraw-renderer.js +1 -0
  131. package/dist/utils/excalidraw-renderer.js.map +1 -1
  132. package/dist/utils/graph-renderer.d.ts +2 -0
  133. package/dist/utils/graph-renderer.d.ts.map +1 -1
  134. package/dist/utils/graph-renderer.js +188 -14
  135. package/dist/utils/graph-renderer.js.map +1 -1
  136. package/dist/verification/__tests__/decay-policy.test.js +1 -0
  137. package/dist/verification/__tests__/decay-policy.test.js.map +1 -1
  138. package/dist/verification/config.d.ts.map +1 -1
  139. package/dist/verification/config.js +2 -0
  140. package/dist/verification/config.js.map +1 -1
  141. package/dist/verification/types.d.ts +2 -0
  142. package/dist/verification/types.d.ts.map +1 -1
  143. package/package.json +2 -2
  144. package/templates/.github/workflows/dare-pr.yml +26 -0
  145. package/templates/dashboard/app.js +184 -0
  146. package/templates/dashboard/index.html +63 -0
  147. package/templates/dashboard/style.css +134 -0
  148. package/templates/ide/antigravity/.agents/skills/dare-dashboard/SKILL.md +18 -0
  149. package/templates/ide/claude/.claude/commands/dare-dashboard.md +18 -0
  150. package/templates/ide/cursor/.cursor/commands/dare-dashboard.md +18 -0
@@ -0,0 +1,184 @@
1
+ /** Vanilla dashboard — fetch /api/telemetry and render panels (no bundler). */
2
+
3
+ const STATUS_COLORS = {
4
+ DONE: 'bar-pass',
5
+ FAILED: 'bar-fail',
6
+ RUNNING: 'bar-accent',
7
+ PENDING: 'bar-warn',
8
+ SKIPPED: 'bar-warn',
9
+ };
10
+
11
+ function el(id) {
12
+ const node = document.getElementById(id);
13
+ if (!node) throw new Error(`Missing #${id}`);
14
+ return node;
15
+ }
16
+
17
+ function setText(id, html) {
18
+ el(id).innerHTML = html;
19
+ }
20
+
21
+ function show(id, visible) {
22
+ el(id).classList.toggle('hidden', !visible);
23
+ }
24
+
25
+ function metric(label, value) {
26
+ return `<div class="metric"><span class="label">${label}</span><span class="value">${value}</span></div>`;
27
+ }
28
+
29
+ function barChart(entries, className = 'bar-accent') {
30
+ if (!entries.length) return '<p class="muted">No data</p>';
31
+ const max = Math.max(...entries.map((e) => e.value), 1);
32
+ const barW = 36;
33
+ const gap = 12;
34
+ const height = 120;
35
+ const width = entries.length * (barW + gap) + gap;
36
+ const bars = entries
37
+ .map((entry, i) => {
38
+ const h = Math.max(4, (entry.value / max) * (height - 24));
39
+ const x = gap + i * (barW + gap);
40
+ const y = height - h - 16;
41
+ return `<rect class="${className}" x="${x}" y="${y}" width="${barW}" height="${h}" rx="4"><title>${entry.label}: ${entry.value}</title></rect>
42
+ <text x="${x + barW / 2}" y="${height - 2}" text-anchor="middle" font-size="10" fill="currentColor">${entry.label}</text>`;
43
+ })
44
+ .join('');
45
+ return `<svg viewBox="0 0 ${width} ${height}" role="img" aria-label="bar chart">${bars}</svg>`;
46
+ }
47
+
48
+ function renderEmptyHints(hints) {
49
+ if (!hints || hints.length === 0) {
50
+ show('empty-hints', false);
51
+ return;
52
+ }
53
+ show('empty-hints', true);
54
+ setText('empty-hints', `<h2>Hints</h2><ul>${hints.map((h) => `<li>${h}</li>`).join('')}</ul>`);
55
+ }
56
+
57
+ function renderDag(dag) {
58
+ setText(
59
+ 'dag-summary',
60
+ metric('Total tasks', dag.total) + metric('Ranks', dag.ranks),
61
+ );
62
+ const entries = Object.entries(dag.byStatus || {}).map(([label, value]) => ({
63
+ label,
64
+ value,
65
+ className: STATUS_COLORS[label] || 'bar-accent',
66
+ }));
67
+ setText(
68
+ 'dag-chart',
69
+ entries.length
70
+ ? entries
71
+ .map((e) => barChart([e], e.className))
72
+ .join('')
73
+ : '<p>No task status data</p>',
74
+ );
75
+ }
76
+
77
+ function renderGates(gates) {
78
+ setText(
79
+ 'gates-summary',
80
+ metric('Verified', gates.verified) +
81
+ metric('Proven', gates.proven) +
82
+ (gates.mutationAvg !== undefined ? metric('Mutation avg', gates.mutationAvg.toFixed(2)) : ''),
83
+ );
84
+ setText(
85
+ 'gates-chart',
86
+ barChart(
87
+ [
88
+ { label: 'verified', value: gates.verified },
89
+ { label: 'proven', value: gates.proven },
90
+ ],
91
+ 'bar-pass',
92
+ ),
93
+ );
94
+ }
95
+
96
+ function renderCost(cost) {
97
+ setText(
98
+ 'cost-summary',
99
+ metric('Total USD', `$${cost.totalUsd.toFixed(4)}`) + metric('Total tokens', cost.totalTokens),
100
+ );
101
+ const entries = (cost.byTask || []).slice(0, 8).map((t) => ({
102
+ label: t.id.replace(/^task[-:]/, '').slice(0, 8),
103
+ value: t.tokens || t.usd * 1000,
104
+ }));
105
+ setText('cost-chart', barChart(entries, 'bar-accent'));
106
+
107
+ const tbody = el('cost-table').querySelector('tbody');
108
+ tbody.innerHTML = (cost.byTask || [])
109
+ .map(
110
+ (t) =>
111
+ `<tr><td>${t.id}</td><td>${t.usd.toFixed(4)}</td><td>${t.tokens}</td></tr>`,
112
+ )
113
+ .join('');
114
+ }
115
+
116
+ function renderOptionalPanels(data) {
117
+ if (data.bestOfN) {
118
+ show('bestof-panel', true);
119
+ setText(
120
+ 'bestof-summary',
121
+ metric('Tasks', data.bestOfN.tasks) +
122
+ metric('Avg candidates', data.bestOfN.avgCandidates),
123
+ );
124
+ } else {
125
+ show('bestof-panel', false);
126
+ }
127
+
128
+ if (data.guard) {
129
+ show('guard-panel', true);
130
+ setText(
131
+ 'guard-summary',
132
+ metric('Pass', data.guard.pass) +
133
+ metric('Warn', data.guard.warn) +
134
+ metric('Fail', data.guard.fail),
135
+ );
136
+ setText(
137
+ 'guard-chart',
138
+ barChart(
139
+ [
140
+ { label: 'pass', value: data.guard.pass },
141
+ { label: 'warn', value: data.guard.warn },
142
+ { label: 'fail', value: data.guard.fail },
143
+ ],
144
+ 'bar-pass',
145
+ ),
146
+ );
147
+ } else {
148
+ show('guard-panel', false);
149
+ }
150
+
151
+ if (data.drift) {
152
+ show('drift-panel', true);
153
+ setText(
154
+ 'drift-summary',
155
+ metric('Orphan reqs', data.drift.orphanReqs) +
156
+ metric('Orphan code', data.drift.orphanCode) +
157
+ metric('Stale', data.drift.stale),
158
+ );
159
+ } else {
160
+ show('drift-panel', false);
161
+ }
162
+ }
163
+
164
+ async function loadTelemetry() {
165
+ const status = el('status-line');
166
+ try {
167
+ const res = await fetch('/api/telemetry');
168
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
169
+ const data = await res.json();
170
+ renderEmptyHints(data.emptyHints);
171
+ renderDag(data.dag);
172
+ renderGates(data.gates);
173
+ renderCost(data.cost);
174
+ renderOptionalPanels(data);
175
+ status.textContent = `Updated ${new Date().toLocaleTimeString()}`;
176
+ } catch (err) {
177
+ status.textContent = `Error: ${err instanceof Error ? err.message : String(err)}`;
178
+ show('empty-hints', true);
179
+ setText('empty-hints', `<h2>Error</h2><p>Could not load telemetry. Is the server running with a valid token?</p>`);
180
+ }
181
+ }
182
+
183
+ loadTelemetry();
184
+ setInterval(loadTelemetry, 30_000);
@@ -0,0 +1,63 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>DARE Telemetry</title>
7
+ <link rel="stylesheet" href="/dashboard/assets/style.css">
8
+ </head>
9
+ <body>
10
+ <header class="site-header">
11
+ <h1>DARE Telemetry</h1>
12
+ <p class="subtitle">Local read-only dashboard</p>
13
+ </header>
14
+
15
+ <main id="app">
16
+ <section id="empty-hints" class="panel hints hidden" aria-live="polite"></section>
17
+
18
+ <section id="dag-panel" class="panel">
19
+ <h2>DAG Progress</h2>
20
+ <div id="dag-summary" class="metrics"></div>
21
+ <div id="dag-chart" class="chart"></div>
22
+ </section>
23
+
24
+ <section id="gates-panel" class="panel">
25
+ <h2>Verification Gates</h2>
26
+ <div id="gates-summary" class="metrics"></div>
27
+ <div id="gates-chart" class="chart"></div>
28
+ </section>
29
+
30
+ <section id="cost-panel" class="panel">
31
+ <h2>Cost</h2>
32
+ <div id="cost-summary" class="metrics"></div>
33
+ <div id="cost-chart" class="chart"></div>
34
+ <table id="cost-table" class="data-table">
35
+ <thead><tr><th>Task</th><th>USD</th><th>Tokens</th></tr></thead>
36
+ <tbody></tbody>
37
+ </table>
38
+ </section>
39
+
40
+ <section id="bestof-panel" class="panel hidden">
41
+ <h2>Best-of-N</h2>
42
+ <div id="bestof-summary" class="metrics"></div>
43
+ </section>
44
+
45
+ <section id="guard-panel" class="panel hidden">
46
+ <h2>Guard</h2>
47
+ <div id="guard-summary" class="metrics"></div>
48
+ <div id="guard-chart" class="chart"></div>
49
+ </section>
50
+
51
+ <section id="drift-panel" class="panel hidden">
52
+ <h2>Drift</h2>
53
+ <div id="drift-summary" class="metrics"></div>
54
+ </section>
55
+ </main>
56
+
57
+ <footer class="site-footer">
58
+ <span id="status-line">Loading…</span>
59
+ </footer>
60
+
61
+ <script src="/dashboard/assets/app.js"></script>
62
+ </body>
63
+ </html>
@@ -0,0 +1,134 @@
1
+ :root {
2
+ color-scheme: light dark;
3
+ --bg: #0f1419;
4
+ --surface: #1a2332;
5
+ --border: #2d3a4d;
6
+ --text: #e7ecf3;
7
+ --muted: #9aa8bc;
8
+ --accent: #5b9fd4;
9
+ --pass: #3ecf8e;
10
+ --warn: #f0c14b;
11
+ --fail: #ef6461;
12
+ font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
13
+ }
14
+
15
+ @media (prefers-color-scheme: light) {
16
+ :root {
17
+ --bg: #f4f6fa;
18
+ --surface: #ffffff;
19
+ --border: #d8dee9;
20
+ --text: #1b2430;
21
+ --muted: #5c677d;
22
+ --accent: #2563eb;
23
+ }
24
+ }
25
+
26
+ * { box-sizing: border-box; }
27
+
28
+ body {
29
+ margin: 0;
30
+ background: var(--bg);
31
+ color: var(--text);
32
+ line-height: 1.5;
33
+ }
34
+
35
+ .site-header, .site-footer {
36
+ padding: 1rem 1.5rem;
37
+ border-bottom: 1px solid var(--border);
38
+ }
39
+
40
+ .site-footer {
41
+ border-top: 1px solid var(--border);
42
+ border-bottom: none;
43
+ color: var(--muted);
44
+ font-size: 0.875rem;
45
+ }
46
+
47
+ .site-header h1 {
48
+ margin: 0;
49
+ font-size: 1.5rem;
50
+ }
51
+
52
+ .subtitle {
53
+ margin: 0.25rem 0 0;
54
+ color: var(--muted);
55
+ }
56
+
57
+ #app {
58
+ display: grid;
59
+ gap: 1rem;
60
+ padding: 1rem 1.5rem 2rem;
61
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
62
+ }
63
+
64
+ .panel {
65
+ background: var(--surface);
66
+ border: 1px solid var(--border);
67
+ border-radius: 10px;
68
+ padding: 1rem 1.25rem;
69
+ }
70
+
71
+ .panel h2 {
72
+ margin: 0 0 0.75rem;
73
+ font-size: 1.1rem;
74
+ }
75
+
76
+ .hidden { display: none; }
77
+
78
+ .hints {
79
+ grid-column: 1 / -1;
80
+ border-color: var(--warn);
81
+ }
82
+
83
+ .hints ul {
84
+ margin: 0;
85
+ padding-left: 1.25rem;
86
+ }
87
+
88
+ .metrics {
89
+ display: flex;
90
+ flex-wrap: wrap;
91
+ gap: 0.75rem 1.25rem;
92
+ margin-bottom: 0.75rem;
93
+ }
94
+
95
+ .metric {
96
+ min-width: 5rem;
97
+ }
98
+
99
+ .metric .label {
100
+ display: block;
101
+ font-size: 0.75rem;
102
+ color: var(--muted);
103
+ text-transform: uppercase;
104
+ letter-spacing: 0.04em;
105
+ }
106
+
107
+ .metric .value {
108
+ font-size: 1.25rem;
109
+ font-weight: 600;
110
+ }
111
+
112
+ .chart svg {
113
+ width: 100%;
114
+ height: auto;
115
+ max-height: 160px;
116
+ }
117
+
118
+ .data-table {
119
+ width: 100%;
120
+ border-collapse: collapse;
121
+ font-size: 0.875rem;
122
+ }
123
+
124
+ .data-table th,
125
+ .data-table td {
126
+ text-align: left;
127
+ padding: 0.35rem 0.5rem;
128
+ border-bottom: 1px solid var(--border);
129
+ }
130
+
131
+ .bar-pass { fill: var(--pass); }
132
+ .bar-warn { fill: var(--warn); }
133
+ .bar-fail { fill: var(--fail); }
134
+ .bar-accent { fill: var(--accent); }
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: dare-dashboard
3
+ description: Start the local read-only telemetry dashboard (dare dashboard).
4
+ ---
5
+
6
+ # /dare-dashboard
7
+
8
+ Sobe o dashboard local de telemetria (`dare dashboard`) — read-only, loopback + token.
9
+
10
+ ```bash
11
+ dare dashboard [--port <n>] [--no-open]
12
+ ```
13
+
14
+ - Default: `127.0.0.1:4100`
15
+ - API: `GET /api/telemetry` (JSON read-only)
16
+ - UI: `GET /dashboard` (HTML/CSS/JS vanilla)
17
+
18
+ Reusa hardening do MCP (auth + bind loopback). Não muta grafo/estado.
@@ -0,0 +1,18 @@
1
+ # Comando: /dare-dashboard
2
+
3
+ Sobe o dashboard local de telemetria (`dare dashboard`) — read-only, loopback + token.
4
+
5
+ ## Como rodar
6
+
7
+ ```bash
8
+ dare dashboard [--port <n>] [--no-open]
9
+ ```
10
+
11
+ - Default: `127.0.0.1:4100`
12
+ - Reusa auth/bind do MCP (token via `DARE_MCP_TOKEN` ou gerado na subida)
13
+ - Front vanilla em `/dashboard`; API JSON em `/api/telemetry`
14
+
15
+ ## Notas
16
+
17
+ - **Read-only** — nenhuma rota muta grafo ou estado.
18
+ - Abre o navegador automaticamente (use `--no-open` para desabilitar).
@@ -0,0 +1,18 @@
1
+ # Comando: /dare-dashboard
2
+
3
+ Sobe o dashboard local de telemetria (`dare dashboard`) — read-only, loopback + token.
4
+
5
+ ## Como rodar
6
+
7
+ ```bash
8
+ dare dashboard [--port <n>] [--no-open]
9
+ ```
10
+
11
+ - Default: `127.0.0.1:4100`
12
+ - Reusa auth/bind do MCP (token via `DARE_MCP_TOKEN` ou gerado na subida)
13
+ - Front vanilla em `/dashboard`; API JSON em `/api/telemetry`
14
+
15
+ ## Notas
16
+
17
+ - **Read-only** — nenhuma rota muta grafo ou estado.
18
+ - Abre o navegador automaticamente (use `--no-open` para desabilitar).