reflectt-node 0.1.3 โ 0.1.5
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.
- package/README.md +60 -151
- package/dist/alert-preflight.d.ts +28 -0
- package/dist/alert-preflight.d.ts.map +1 -1
- package/dist/alert-preflight.js +178 -0
- package/dist/alert-preflight.js.map +1 -1
- package/dist/boardHealthWorker.d.ts.map +1 -1
- package/dist/boardHealthWorker.js +25 -12
- package/dist/boardHealthWorker.js.map +1 -1
- package/dist/chat-approval-detector.d.ts.map +1 -1
- package/dist/chat-approval-detector.js +29 -11
- package/dist/chat-approval-detector.js.map +1 -1
- package/dist/chat.d.ts +1 -0
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +14 -3
- package/dist/chat.js.map +1 -1
- package/dist/cli.js +187 -22
- package/dist/cli.js.map +1 -1
- package/dist/cloud.d.ts +28 -1
- package/dist/cloud.d.ts.map +1 -1
- package/dist/cloud.js +55 -20
- package/dist/cloud.js.map +1 -1
- package/dist/compliance-detector.d.ts +42 -0
- package/dist/compliance-detector.d.ts.map +1 -0
- package/dist/compliance-detector.js +286 -0
- package/dist/compliance-detector.js.map +1 -0
- package/dist/continuity-loop.d.ts.map +1 -1
- package/dist/continuity-loop.js +7 -3
- package/dist/continuity-loop.js.map +1 -1
- package/dist/dashboard.d.ts +6 -2
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/dashboard.js +56 -26
- package/dist/dashboard.js.map +1 -1
- package/dist/doctor.d.ts +2 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +78 -11
- package/dist/doctor.js.map +1 -1
- package/dist/executionSweeper.d.ts.map +1 -1
- package/dist/executionSweeper.js +12 -0
- package/dist/executionSweeper.js.map +1 -1
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +30 -7
- package/dist/health.js.map +1 -1
- package/dist/hostConnectGuard.d.ts +25 -0
- package/dist/hostConnectGuard.d.ts.map +1 -0
- package/dist/hostConnectGuard.js +27 -0
- package/dist/hostConnectGuard.js.map +1 -0
- package/dist/index.js +144 -29
- package/dist/index.js.map +1 -1
- package/dist/insight-task-bridge.d.ts +22 -1
- package/dist/insight-task-bridge.d.ts.map +1 -1
- package/dist/insight-task-bridge.js +19 -4
- package/dist/insight-task-bridge.js.map +1 -1
- package/dist/mcp.js +6 -6
- package/dist/mcp.js.map +1 -1
- package/dist/notificationDedupeGuard.d.ts +33 -0
- package/dist/notificationDedupeGuard.d.ts.map +1 -0
- package/dist/notificationDedupeGuard.js +88 -0
- package/dist/notificationDedupeGuard.js.map +1 -0
- package/dist/policy.d.ts +1 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +3 -1
- package/dist/policy.js.map +1 -1
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +7 -8
- package/dist/preflight.js.map +1 -1
- package/dist/reflection-automation.d.ts.map +1 -1
- package/dist/reflection-automation.js +38 -0
- package/dist/reflection-automation.js.map +1 -1
- package/dist/request-tracker.d.ts +13 -0
- package/dist/request-tracker.d.ts.map +1 -1
- package/dist/request-tracker.js +95 -16
- package/dist/request-tracker.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +244 -58
- package/dist/server.js.map +1 -1
- package/dist/service-probe.d.ts.map +1 -1
- package/dist/service-probe.js +39 -2
- package/dist/service-probe.js.map +1 -1
- package/dist/shipped-heartbeat.d.ts +1 -1
- package/dist/shipped-heartbeat.js +1 -1
- package/dist/taskPrecheck.js +6 -6
- package/dist/taskPrecheck.js.map +1 -1
- package/dist/tasks.d.ts +1 -1
- package/dist/tasks.d.ts.map +1 -1
- package/dist/tasks.js +8 -5
- package/dist/tasks.js.map +1 -1
- package/dist/todoHoardingGuard.d.ts +35 -0
- package/dist/todoHoardingGuard.d.ts.map +1 -0
- package/dist/todoHoardingGuard.js +150 -0
- package/dist/todoHoardingGuard.js.map +1 -0
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/working-contract.d.ts.map +1 -1
- package/dist/working-contract.js +59 -3
- package/dist/working-contract.js.map +1 -1
- package/package.json +1 -1
- package/public/dashboard.js +94 -27
- package/public/docs.md +17 -2
- package/public/intensity-mock.html +413 -0
- package/public/polls-mock.html +610 -0
package/public/docs.md
CHANGED
|
@@ -41,6 +41,16 @@ Returns `text/html`. No parameters.
|
|
|
41
41
|
open http://localhost:4445/ui-kit
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
### `GET /dashboard`
|
|
45
|
+
|
|
46
|
+
Main `reflectt-node` dashboard UI.
|
|
47
|
+
|
|
48
|
+
Returns `text/html`.
|
|
49
|
+
|
|
50
|
+
Internal/cockpit controls are hidden by default. To enable them (for operators debugging their own host), start the server with `REFLECTT_INTERNAL_UI=1` **and** open:
|
|
51
|
+
|
|
52
|
+
- `http://localhost:4445/dashboard?internal=1`
|
|
53
|
+
|
|
44
54
|
---
|
|
45
55
|
|
|
46
56
|
## Error Envelope (all endpoints)
|
|
@@ -102,6 +112,7 @@ Remote hosts (multi-host installs) phone-home via a lightweight heartbeat so the
|
|
|
102
112
|
| GET | `/health/team` | Team health metrics with compliance + `staleDoing` snapshot. Per-agent rows include `activeTaskTitle` and `activeTaskPrLink` when an agent has a doing task with PR evidence. Flagged agents also include `actionable_reason` (last comment age, last transition, last mention age, suggested action). |
|
|
103
113
|
| GET | `/health/agents` | Per-agent health summary (`last_seen`, `active_task`, `heartbeat_age_ms`, `last_shipped_at`, `stale_reason`, state) |
|
|
104
114
|
| GET | `/health/compliance` | Compliance check results |
|
|
115
|
+
| GET | `/compliance/violations` | State-read-before-assertion compliance violations. Query: `agent`, `severity`, `limit` (max 1000), `since` (epoch ms). Returns `{ violations, count, summary, query }`. |
|
|
105
116
|
| GET | `/health/backlog` | Backlog readiness health by lane (ready counts, floor compliance, breach status, blocked/todo/doing/validating rollups). Query: `include_test=1` to include test-harness tasks. |
|
|
106
117
|
| GET | `/health/system` | System + loop/timer health (quiet-hours suppression, sweeper status, watchdog tick timestamps, uptime/memory) |
|
|
107
118
|
| GET | `/health/build` | Build/runtime identity (version, git SHA, branch, build timestamp, PID, uptime) |
|
|
@@ -109,9 +120,11 @@ Remote hosts (multi-host installs) phone-home via a lightweight heartbeat so the
|
|
|
109
120
|
| GET | `/health/team/summary` | Compact team health summary |
|
|
110
121
|
| GET | `/health/team/history` | Historical team health data |
|
|
111
122
|
| GET | `/health/workflow` | Unified per-agent workflow state: doing-task age, last shipped timestamp, blocker flag, artifact path, and linked PR state. Query: `include_test=1` to include test-harness tasks. |
|
|
112
|
-
| GET | `/health/reflection-pipeline` | ReflectionโInsightโPromotion health signal. Returns recent reflection/insight/promotion counts, status (`healthy`\|`at_risk`\|`broken`), and alert timestamps.
|
|
123
|
+
| GET | `/health/reflection-pipeline` | ReflectionโInsightโPromotion health signal. Returns recent reflection/insight/promotion counts, status (`idle`\|`healthy`\|`at_risk`\|`broken`), and alert timestamps. Status is `idle` when no reflections are flowing; `healthy` when reflections produce insightActivity (created+updated); `at_risk`โ`broken` when reflections flow but zero insightActivity past threshold. |
|
|
113
124
|
| GET | `/health/backlog` | Backlog readiness snapshot by lane/agent with ready-floor breach detection and stale-validating summary. Query: `include_test=1` to include test-harness tasks. |
|
|
114
125
|
| GET | `/health/alert-preflight` | Alert-preflight guard metrics: total checked, canary-flagged, suppressed, false-positive rate, mode (canary/enforce/off). |
|
|
126
|
+
| GET | `/health/alert-preflight/history` | Daily alert-preflight snapshots for observation window tracking. Returns per-day metrics + current session. |
|
|
127
|
+
| GET | `/health/hoarding` | Todo hoarding guard status: orphaned todos, auto-unassign actions, config. Query: `dry_run=0` to run live (default: dry run). |
|
|
115
128
|
| GET | `/health/mention-ack` | Mention-ack lifecycle metrics (pending, timeout, latency counters) |
|
|
116
129
|
| GET | `/health/mention-ack/recent` | Recent mention-ack entries for debugging. Query: `limit` (max 100) |
|
|
117
130
|
| GET | `/health/mention-ack/:agent` | Pending mention-ack entries for one agent |
|
|
@@ -179,7 +192,7 @@ If your deployment needs quiet-hours behavior today, enforce it in scheduler/gat
|
|
|
179
192
|
| POST | `/tasks` | Create task. Required: `title`, `createdBy`, `assignee`, `reviewer`, `done_criteria` (string[]), `eta`. Optional: `description`, `priority` (P0-P3), `status`, `tags`, `metadata`. **Reflection-origin invariant:** `metadata.source_reflection` or `metadata.source_insight` required (or `metadata.reflection_exempt=true` with `reflection_exempt_reason`). Status contract: `validating` also requires `metadata.artifact_path` under `process/`. |
|
|
180
193
|
| PATCH | `/tasks/:id` | Update task (partial). Any task field, plus optional `actor` for history attribution. Status contract: `doing` requires reviewer + `metadata.eta`; `validating` requires `metadata.artifact_path` under `process/` (workspace-agnostic). |
|
|
181
194
|
| DELETE | `/tasks/:id` | Delete task |
|
|
182
|
-
| GET | `/tasks/next` | Pull-based assignment. Query: `agent`, `compact` |
|
|
195
|
+
| GET | `/tasks/next` | Pull-based assignment. Query: `agent`, `compact`, `claim=1` (auto-transitions todoโdoing on pull) |
|
|
183
196
|
| GET | `/tasks/active` | Get active (doing) task for agent. Query: `agent`, `compact`. Returns null if no doing tasks. |
|
|
184
197
|
| GET | `/heartbeat/:agent` | Single compact heartbeat payload (~200 tokens). Returns active task, next task, slim inbox, queue counts, and suggested action. Replaces 3 separate API calls. |
|
|
185
198
|
| GET | `/bootstrap/heartbeat/:agent` | Generate optimal HEARTBEAT.md content for agent. References best endpoints. Includes version stamp and content hash for change detection. |
|
|
@@ -202,6 +215,7 @@ If your deployment needs quiet-hours behavior today, enforce it in scheduler/gat
|
|
|
202
215
|
| GET | `/tasks/board-health` | Board-level health metrics for backlog replenishment. Returns per-agent breakdown (doing, validating, todo, active counts), `needsWork`/`lowWatermark` flags, and `replenishNeeded` trigger (fires when 2+ agents idle or <3 backlog tasks). Query: `include_test=1` to include test-harness tasks. |
|
|
203
216
|
| GET | `/agents/roles` | Agent role registry with live WIP status. Returns all agents with `name`, `displayName`, `role`, `affinityTags`, `protectedDomains`, `wipCap`, `wipCount`, `overCap`. |
|
|
204
217
|
| POST | `/config/identity` | Set an agent's display name. Body: `{ "agent": "agent-1", "displayName": "Juniper" }`. Persists to TEAM-ROLES.yaml, hot-reloads. Dashboard and mentions use display name. |
|
|
218
|
+
| PUT | `/config/team-roles` | Write TEAM-ROLES.yaml. Body: `{ "yaml": "agents:\n - name: link\n role: engineer..." }`. Hot-reloads on save. Used by bootstrap agent to configure team from user intent. |
|
|
205
219
|
| GET | `/resolve/mention/:mention` | Resolve a mention string (name, displayName, or alias) to canonical agent ID. Returns `{ agent, displayName, role }`. |
|
|
206
220
|
| POST | `/tasks/suggest-assignee` | Suggest best assignee for a task. Body: `{ "title": "...", "tags": [...], "done_criteria": [...] }`. Returns `suggested` agent name, `scores` array with affinity/WIP/throughput breakdown, and `protectedMatch` if a protected domain applies. |
|
|
207
221
|
| GET | `/team/manifest` | Serve TEAM.md from `~/.reflectt/` (falls back to defaults). Returns `manifest` object with `raw_markdown`, parsed `sections` array, `version` (SHA-256 hash), `updated_at`, `path`, and `source`. |
|
|
@@ -479,6 +493,7 @@ Preflight checks reconcile live task state (status, assignee, reviewer, recent c
|
|
|
479
493
|
| Method | Path | Description |
|
|
480
494
|
|--------|------|-------------|
|
|
481
495
|
| GET | `/cloud/status` | Cloud connection state (registered, heartbeat age, sync status). Only active when `REFLECTT_HOST_TOKEN` is set. |
|
|
496
|
+
| GET | `/cloud/events` | Connection lifecycle events (connect, disconnect, heartbeat failures/recoveries). Query: `?limit=N` (max 100). |
|
|
482
497
|
| POST | `/cloud/reload` | Hot-reload cloud config from `~/.reflectt/config.json` without server restart. Updates env vars and restarts heartbeat/sync loops. Used by CLI after `host connect` enrollment. |
|
|
483
498
|
| GET | `/provisioning/status` | Host provisioning state: phase, enrollment, config/secrets pull status, webhook routes. Dashboard-safe (no credentials). |
|
|
484
499
|
| POST | `/provisioning/provision` | Full provisioning flow: enroll with cloud (join token or API key), pull config + secrets, configure webhooks. Body: `{ cloudUrl, hostName, joinToken?, apiKey?, capabilities? }`. |
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Agent Intensity Toggle โ Design Mock</title>
|
|
7
|
+
<style>
|
|
8
|
+
/* === Reflectt Node Tokens (subset) === */
|
|
9
|
+
:root {
|
|
10
|
+
--bg: #0a0e14;
|
|
11
|
+
--surface: #141920;
|
|
12
|
+
--surface-raised: #1a2028;
|
|
13
|
+
--border: #252d38;
|
|
14
|
+
--border-subtle: #1e2530;
|
|
15
|
+
--text: #d4dae3;
|
|
16
|
+
--text-bright: #eef1f5;
|
|
17
|
+
--text-muted: #6b7a8d;
|
|
18
|
+
--accent: #4da6ff;
|
|
19
|
+
--accent-dim: rgba(77, 166, 255, 0.12);
|
|
20
|
+
--yellow: #d4a017;
|
|
21
|
+
--yellow-dim: rgba(212, 160, 23, 0.12);
|
|
22
|
+
--orange: #e08a20;
|
|
23
|
+
--orange-dim: rgba(224, 138, 32, 0.12);
|
|
24
|
+
--green: #3fb950;
|
|
25
|
+
--green-dim: rgba(63, 185, 80, 0.12);
|
|
26
|
+
--red: #f85149;
|
|
27
|
+
--radius-sm: 6px;
|
|
28
|
+
--radius-md: 8px;
|
|
29
|
+
--space-2: 8px;
|
|
30
|
+
--space-3: 12px;
|
|
31
|
+
--space-4: 16px;
|
|
32
|
+
--space-5: 20px;
|
|
33
|
+
--text-xs: 10px;
|
|
34
|
+
--text-sm: 11px;
|
|
35
|
+
--text-base: 13px;
|
|
36
|
+
--text-md: 14px;
|
|
37
|
+
--font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
38
|
+
--font-weight-normal: 400;
|
|
39
|
+
--font-weight-medium: 500;
|
|
40
|
+
--font-weight-semibold: 600;
|
|
41
|
+
--focus-ring: 0 0 0 2px rgba(77, 166, 255, 0.5);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
45
|
+
|
|
46
|
+
body {
|
|
47
|
+
font-family: var(--font-family);
|
|
48
|
+
background: var(--bg);
|
|
49
|
+
color: var(--text);
|
|
50
|
+
min-height: 100vh;
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-direction: column;
|
|
53
|
+
align-items: center;
|
|
54
|
+
padding: 40px 20px;
|
|
55
|
+
-webkit-font-smoothing: antialiased;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
h1 {
|
|
59
|
+
font-size: 18px;
|
|
60
|
+
font-weight: 700;
|
|
61
|
+
color: var(--text-bright);
|
|
62
|
+
margin-bottom: 8px;
|
|
63
|
+
}
|
|
64
|
+
.subtitle {
|
|
65
|
+
font-size: var(--text-base);
|
|
66
|
+
color: var(--text-muted);
|
|
67
|
+
margin-bottom: 32px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* === Mock Dashboard Panel === */
|
|
71
|
+
.panel {
|
|
72
|
+
background: var(--surface);
|
|
73
|
+
border: 1px solid var(--border);
|
|
74
|
+
border-radius: var(--radius-md);
|
|
75
|
+
width: 100%;
|
|
76
|
+
max-width: 480px;
|
|
77
|
+
overflow: hidden;
|
|
78
|
+
}
|
|
79
|
+
.panel-header {
|
|
80
|
+
padding: var(--space-3) var(--space-4);
|
|
81
|
+
border-bottom: 1px solid var(--border);
|
|
82
|
+
font-size: var(--text-md);
|
|
83
|
+
font-weight: var(--font-weight-semibold);
|
|
84
|
+
color: var(--text-bright);
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
gap: 8px;
|
|
88
|
+
}
|
|
89
|
+
.panel-body {
|
|
90
|
+
padding: var(--space-4) var(--space-5);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* === Runtime Stats (mock) === */
|
|
94
|
+
.runtime-stats {
|
|
95
|
+
display: grid;
|
|
96
|
+
grid-template-columns: 1fr 1fr;
|
|
97
|
+
gap: var(--space-3);
|
|
98
|
+
margin-bottom: 0;
|
|
99
|
+
}
|
|
100
|
+
.stat {
|
|
101
|
+
display: flex;
|
|
102
|
+
flex-direction: column;
|
|
103
|
+
gap: 2px;
|
|
104
|
+
}
|
|
105
|
+
.stat-label {
|
|
106
|
+
font-size: var(--text-xs);
|
|
107
|
+
color: var(--text-muted);
|
|
108
|
+
text-transform: uppercase;
|
|
109
|
+
letter-spacing: 0.05em;
|
|
110
|
+
}
|
|
111
|
+
.stat-value {
|
|
112
|
+
font-size: var(--text-md);
|
|
113
|
+
font-weight: var(--font-weight-semibold);
|
|
114
|
+
color: var(--text);
|
|
115
|
+
}
|
|
116
|
+
.stat-value.online { color: var(--green); }
|
|
117
|
+
|
|
118
|
+
/* === Intensity Control === */
|
|
119
|
+
.intensity-control {
|
|
120
|
+
margin-top: var(--space-4);
|
|
121
|
+
padding-top: var(--space-4);
|
|
122
|
+
border-top: 1px solid var(--border);
|
|
123
|
+
}
|
|
124
|
+
.intensity-label {
|
|
125
|
+
font-size: var(--text-sm);
|
|
126
|
+
font-weight: var(--font-weight-semibold);
|
|
127
|
+
color: var(--text);
|
|
128
|
+
margin-bottom: var(--space-2);
|
|
129
|
+
}
|
|
130
|
+
.intensity-segments {
|
|
131
|
+
display: flex;
|
|
132
|
+
gap: 2px;
|
|
133
|
+
background: var(--surface);
|
|
134
|
+
border: 1px solid var(--border);
|
|
135
|
+
border-radius: var(--radius-md);
|
|
136
|
+
padding: 3px;
|
|
137
|
+
}
|
|
138
|
+
.intensity-seg {
|
|
139
|
+
flex: 1;
|
|
140
|
+
padding: 8px 12px;
|
|
141
|
+
border: 1px solid transparent;
|
|
142
|
+
border-radius: var(--radius-sm);
|
|
143
|
+
background: transparent;
|
|
144
|
+
color: var(--text-muted);
|
|
145
|
+
font-size: var(--text-sm);
|
|
146
|
+
font-weight: var(--font-weight-medium);
|
|
147
|
+
cursor: pointer;
|
|
148
|
+
transition: all 150ms ease;
|
|
149
|
+
min-height: 44px;
|
|
150
|
+
display: flex;
|
|
151
|
+
align-items: center;
|
|
152
|
+
justify-content: center;
|
|
153
|
+
gap: 4px;
|
|
154
|
+
font-family: inherit;
|
|
155
|
+
}
|
|
156
|
+
.intensity-seg:focus-visible {
|
|
157
|
+
outline: none;
|
|
158
|
+
box-shadow: var(--focus-ring);
|
|
159
|
+
}
|
|
160
|
+
.intensity-seg:hover:not(.active) {
|
|
161
|
+
color: var(--text);
|
|
162
|
+
background: rgba(255,255,255,0.03);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Active states โ color-coded by level */
|
|
166
|
+
.intensity-seg.active[data-level="low"] {
|
|
167
|
+
background: var(--yellow-dim);
|
|
168
|
+
color: var(--yellow);
|
|
169
|
+
border-color: var(--yellow);
|
|
170
|
+
font-weight: var(--font-weight-semibold);
|
|
171
|
+
}
|
|
172
|
+
.intensity-seg.active[data-level="normal"] {
|
|
173
|
+
background: var(--accent-dim);
|
|
174
|
+
color: var(--accent);
|
|
175
|
+
border-color: var(--accent);
|
|
176
|
+
font-weight: var(--font-weight-semibold);
|
|
177
|
+
}
|
|
178
|
+
.intensity-seg.active[data-level="high"] {
|
|
179
|
+
background: var(--orange-dim);
|
|
180
|
+
color: var(--orange);
|
|
181
|
+
border-color: var(--orange);
|
|
182
|
+
font-weight: var(--font-weight-semibold);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.intensity-desc {
|
|
186
|
+
font-size: var(--text-xs);
|
|
187
|
+
color: var(--text-muted);
|
|
188
|
+
margin-top: var(--space-2);
|
|
189
|
+
line-height: 1.5;
|
|
190
|
+
min-height: 30px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* === Toast === */
|
|
194
|
+
.toast {
|
|
195
|
+
position: fixed;
|
|
196
|
+
bottom: 24px;
|
|
197
|
+
left: 50%;
|
|
198
|
+
transform: translateX(-50%) translateY(80px);
|
|
199
|
+
background: var(--surface-raised);
|
|
200
|
+
border: 1px solid var(--border);
|
|
201
|
+
border-radius: var(--radius-md);
|
|
202
|
+
padding: 10px 20px;
|
|
203
|
+
font-size: var(--text-sm);
|
|
204
|
+
color: var(--text);
|
|
205
|
+
opacity: 0;
|
|
206
|
+
transition: all 300ms ease;
|
|
207
|
+
pointer-events: none;
|
|
208
|
+
white-space: nowrap;
|
|
209
|
+
}
|
|
210
|
+
.toast.show {
|
|
211
|
+
transform: translateX(-50%) translateY(0);
|
|
212
|
+
opacity: 1;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* === Mapping Table === */
|
|
216
|
+
.mapping-section {
|
|
217
|
+
margin-top: 40px;
|
|
218
|
+
width: 100%;
|
|
219
|
+
max-width: 640px;
|
|
220
|
+
}
|
|
221
|
+
.mapping-section h2 {
|
|
222
|
+
font-size: 15px;
|
|
223
|
+
font-weight: 700;
|
|
224
|
+
color: var(--text-bright);
|
|
225
|
+
margin-bottom: 12px;
|
|
226
|
+
}
|
|
227
|
+
table {
|
|
228
|
+
width: 100%;
|
|
229
|
+
border-collapse: collapse;
|
|
230
|
+
font-size: var(--text-sm);
|
|
231
|
+
}
|
|
232
|
+
th, td {
|
|
233
|
+
padding: 8px 12px;
|
|
234
|
+
text-align: left;
|
|
235
|
+
border-bottom: 1px solid var(--border);
|
|
236
|
+
}
|
|
237
|
+
th {
|
|
238
|
+
color: var(--text-muted);
|
|
239
|
+
font-weight: var(--font-weight-semibold);
|
|
240
|
+
text-transform: uppercase;
|
|
241
|
+
letter-spacing: 0.05em;
|
|
242
|
+
font-size: var(--text-xs);
|
|
243
|
+
}
|
|
244
|
+
td { color: var(--text); }
|
|
245
|
+
td.highlight { color: var(--accent); font-weight: var(--font-weight-medium); }
|
|
246
|
+
|
|
247
|
+
/* === Footer === */
|
|
248
|
+
.mock-footer {
|
|
249
|
+
margin-top: 40px;
|
|
250
|
+
font-size: var(--text-xs);
|
|
251
|
+
color: var(--text-muted);
|
|
252
|
+
text-align: center;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
@media (hover: hover) and (pointer: fine) {
|
|
256
|
+
.intensity-seg:hover:not(.active) {
|
|
257
|
+
color: var(--text);
|
|
258
|
+
background: rgba(255,255,255,0.03);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
@media not all and (hover: hover) {
|
|
262
|
+
.intensity-seg:hover:not(.active) {
|
|
263
|
+
color: var(--text-muted);
|
|
264
|
+
background: transparent;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
</style>
|
|
268
|
+
</head>
|
|
269
|
+
<body>
|
|
270
|
+
|
|
271
|
+
<h1>Agent Intensity Toggle</h1>
|
|
272
|
+
<p class="subtitle">Design mock โ where it lives in the dashboard</p>
|
|
273
|
+
|
|
274
|
+
<!-- Mock Runtime Truth Card panel -->
|
|
275
|
+
<div class="panel">
|
|
276
|
+
<div class="panel-header">๐งญ Runtime Truth Card</div>
|
|
277
|
+
<div class="panel-body">
|
|
278
|
+
|
|
279
|
+
<!-- Existing runtime stats (mock) -->
|
|
280
|
+
<div class="runtime-stats">
|
|
281
|
+
<div class="stat">
|
|
282
|
+
<span class="stat-label">Agents</span>
|
|
283
|
+
<span class="stat-value online">6 online</span>
|
|
284
|
+
</div>
|
|
285
|
+
<div class="stat">
|
|
286
|
+
<span class="stat-label">Tasks</span>
|
|
287
|
+
<span class="stat-value">3 active</span>
|
|
288
|
+
</div>
|
|
289
|
+
<div class="stat">
|
|
290
|
+
<span class="stat-label">Heartbeat</span>
|
|
291
|
+
<span class="stat-value">30s</span>
|
|
292
|
+
</div>
|
|
293
|
+
<div class="stat">
|
|
294
|
+
<span class="stat-label">Uptime</span>
|
|
295
|
+
<span class="stat-value">4h 22m</span>
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
298
|
+
|
|
299
|
+
<!-- โจ NEW: Intensity Control -->
|
|
300
|
+
<div class="intensity-control" role="radiogroup" aria-label="Agent intensity">
|
|
301
|
+
<div class="intensity-label">โก Agent Intensity</div>
|
|
302
|
+
<div class="intensity-segments">
|
|
303
|
+
<button role="radio" aria-checked="false" data-level="low" class="intensity-seg" onclick="setIntensity('low')">
|
|
304
|
+
๐ข Low
|
|
305
|
+
</button>
|
|
306
|
+
<button role="radio" aria-checked="true" data-level="normal" class="intensity-seg active" onclick="setIntensity('normal')">
|
|
307
|
+
โก Normal
|
|
308
|
+
</button>
|
|
309
|
+
<button role="radio" aria-checked="false" data-level="high" class="intensity-seg" onclick="setIntensity('high')">
|
|
310
|
+
๐ฅ High
|
|
311
|
+
</button>
|
|
312
|
+
</div>
|
|
313
|
+
<div class="intensity-desc" id="intensity-desc">
|
|
314
|
+
Agents work at standard pace. Tasks processed each heartbeat.
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
|
|
321
|
+
<!-- Mapping reference table -->
|
|
322
|
+
<div class="mapping-section">
|
|
323
|
+
<h2>What each level changes</h2>
|
|
324
|
+
<table>
|
|
325
|
+
<thead>
|
|
326
|
+
<tr>
|
|
327
|
+
<th>Setting</th>
|
|
328
|
+
<th>๐ข Low</th>
|
|
329
|
+
<th>โก Normal</th>
|
|
330
|
+
<th>๐ฅ High</th>
|
|
331
|
+
</tr>
|
|
332
|
+
</thead>
|
|
333
|
+
<tbody>
|
|
334
|
+
<tr>
|
|
335
|
+
<td>Heartbeat</td>
|
|
336
|
+
<td>2ร slower</td>
|
|
337
|
+
<td class="highlight">Default</td>
|
|
338
|
+
<td>2ร faster</td>
|
|
339
|
+
</tr>
|
|
340
|
+
<tr>
|
|
341
|
+
<td>Tasks / cycle</td>
|
|
342
|
+
<td>Max 1</td>
|
|
343
|
+
<td class="highlight">Config default</td>
|
|
344
|
+
<td>Unlimited</td>
|
|
345
|
+
</tr>
|
|
346
|
+
<tr>
|
|
347
|
+
<td>Approval</td>
|
|
348
|
+
<td>All manual</td>
|
|
349
|
+
<td class="highlight">Routine auto</td>
|
|
350
|
+
<td>All auto (except close)</td>
|
|
351
|
+
</tr>
|
|
352
|
+
<tr>
|
|
353
|
+
<td>Parallel tasks</td>
|
|
354
|
+
<td>No</td>
|
|
355
|
+
<td class="highlight">No</td>
|
|
356
|
+
<td>Yes</td>
|
|
357
|
+
</tr>
|
|
358
|
+
</tbody>
|
|
359
|
+
</table>
|
|
360
|
+
</div>
|
|
361
|
+
|
|
362
|
+
<!-- Toast -->
|
|
363
|
+
<div class="toast" id="toast"></div>
|
|
364
|
+
|
|
365
|
+
<div class="mock-footer">
|
|
366
|
+
Design mock by pixel ๐จ ยท task-1772244618727-695h6hdsk ยท reflectt-node
|
|
367
|
+
</div>
|
|
368
|
+
|
|
369
|
+
<script>
|
|
370
|
+
const COPY = {
|
|
371
|
+
low: 'Agents check in less often. Tasks batch up.',
|
|
372
|
+
normal: 'Agents work at standard pace. Tasks processed each heartbeat.',
|
|
373
|
+
high: 'Agents move fast. Parallel tasks enabled.',
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
const TOAST_MSG = {
|
|
377
|
+
low: '๐ข Intensity โ Low โ agents will slow down',
|
|
378
|
+
normal: 'โก Intensity โ Normal โ standard pace',
|
|
379
|
+
high: '๐ฅ Intensity โ High โ agents moving fast',
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
function setIntensity(level) {
|
|
383
|
+
document.querySelectorAll('.intensity-seg').forEach(btn => {
|
|
384
|
+
const active = btn.dataset.level === level;
|
|
385
|
+
btn.classList.toggle('active', active);
|
|
386
|
+
btn.setAttribute('aria-checked', active);
|
|
387
|
+
});
|
|
388
|
+
document.getElementById('intensity-desc').textContent = COPY[level];
|
|
389
|
+
showToast(TOAST_MSG[level]);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
let toastTimer;
|
|
393
|
+
function showToast(msg) {
|
|
394
|
+
const el = document.getElementById('toast');
|
|
395
|
+
el.textContent = msg;
|
|
396
|
+
el.classList.add('show');
|
|
397
|
+
clearTimeout(toastTimer);
|
|
398
|
+
toastTimer = setTimeout(() => el.classList.remove('show'), 2500);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Keyboard nav for radiogroup
|
|
402
|
+
document.querySelector('.intensity-segments').addEventListener('keydown', e => {
|
|
403
|
+
const btns = [...document.querySelectorAll('.intensity-seg')];
|
|
404
|
+
const idx = btns.indexOf(document.activeElement);
|
|
405
|
+
if (idx < 0) return;
|
|
406
|
+
let next;
|
|
407
|
+
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') next = btns[(idx + 1) % btns.length];
|
|
408
|
+
if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') next = btns[(idx - 1 + btns.length) % btns.length];
|
|
409
|
+
if (next) { e.preventDefault(); next.focus(); next.click(); }
|
|
410
|
+
});
|
|
411
|
+
</script>
|
|
412
|
+
</body>
|
|
413
|
+
</html>
|