iikit-dashboard 1.4.0 → 1.5.1
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 +30 -21
- package/bin/iikit-dashboard.js +4 -2
- package/package.json +5 -2
- package/src/public/index.html +19 -2
- package/src/server.js +36 -2
package/README.md
CHANGED
|
@@ -11,11 +11,12 @@ The dashboard launches automatically early in the IIKit workflow — no manual s
|
|
|
11
11
|
You can also start it standalone to browse historical data for any project that has feature specs:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npx iikit-dashboard
|
|
15
|
-
npx iikit-dashboard /path/to/project
|
|
14
|
+
npx iikit-dashboard # current directory
|
|
15
|
+
npx iikit-dashboard /path/to/project # specific project
|
|
16
|
+
npx iikit-dashboard --port 3001 # custom port
|
|
16
17
|
```
|
|
17
18
|
|
|
18
|
-
The dashboard opens at `http://localhost:3000`.
|
|
19
|
+
The dashboard opens at `http://localhost:3000` by default. A pidfile (`.specify/dashboard.pid.json`) is written on startup so external tools can discover which project a running dashboard serves and at which port.
|
|
19
20
|
|
|
20
21
|
## Views
|
|
21
22
|
|
|
@@ -23,40 +24,48 @@ The pipeline bar at the top shows all nine IIKit workflow phases. Click any phas
|
|
|
23
24
|
|
|
24
25
|
| Phase | View |
|
|
25
26
|
|-------|------|
|
|
26
|
-
| **Constitution** | Radar chart of governance principles with obligation levels (MUST / SHOULD / MAY) |
|
|
27
|
-
| **Spec** | Story map with swim lanes by priority + interactive requirements graph (US / FR / SC nodes and edges) |
|
|
28
|
-
| **Clarify** | Q&A trail from clarification sessions, with clickable spec-item references that navigate
|
|
29
|
-
| **Plan** | Tech
|
|
27
|
+
| **Constitution** | Radar chart of governance principles with obligation levels (MUST / SHOULD / MAY) and version timeline |
|
|
28
|
+
| **Spec** | Story map with swim lanes by priority + interactive force-directed requirements graph (US / FR / SC nodes and edges) with detail side-panel |
|
|
29
|
+
| **Clarify** | Q&A trail from clarification sessions grouped by date, with clickable spec-item references that navigate to the Spec view |
|
|
30
|
+
| **Plan** | Tech context key-value pairs, interactive file-structure tree (existing vs. planned files), rendered architecture diagram, and Tessl tile cards with live eval scores |
|
|
30
31
|
| **Checklist** | Progress rings per checklist file with color coding (red/yellow/green), gate traffic light (OPEN/BLOCKED), and accordion detail view with CHK IDs and tag badges |
|
|
31
|
-
| **Testify** |
|
|
32
|
-
| **Tasks** |
|
|
33
|
-
| **Analyze** |
|
|
34
|
-
| **Implement** | Kanban board with cards sliding Todo → In Progress → Done as the agent checks off tasks |
|
|
32
|
+
| **Testify** | Assertion integrity seal (Verified/Tampered/Missing), Sankey traceability diagram (Requirements → Test Specs → Tasks), test pyramid, and gap highlighting for untested requirements |
|
|
33
|
+
| **Tasks** | Redirects to the Implement board (tasks are managed there) |
|
|
34
|
+
| **Analyze** | Health gauge (0–100) with four weighted factors, coverage heatmap (Tasks/Tests/Plan per requirement), and sortable/filterable severity table of analysis findings |
|
|
35
|
+
| **Implement** | Kanban board with cards sliding Todo → In Progress → Done as the agent checks off tasks, with collapsible per-story task lists |
|
|
35
36
|
|
|
36
37
|
## Features
|
|
37
38
|
|
|
38
39
|
- **Live updates** — all views refresh in real time via WebSocket as project files change
|
|
39
40
|
- **Pipeline navigation** — phase nodes show status (complete / in-progress / skipped / not started) with progress percentages
|
|
41
|
+
- **Cross-panel navigation** — Cmd/Ctrl+click any FR, US, SC, or task identifier to jump to its linked panel (Spec, Testify, Implement, Checklist, or Clarify)
|
|
40
42
|
- **Feature selector** — dropdown to switch between features in `specs/`, sorted newest-first
|
|
41
|
-
- **
|
|
42
|
-
- **Integrity badges** — shows whether test assertions have been tampered with
|
|
43
|
+
- **Project label** — header shows the project directory name with full path on hover, so you know which project a dashboard tab belongs to
|
|
44
|
+
- **Integrity badges** — shows whether test assertions have been tampered with (verified / tampered / missing)
|
|
45
|
+
- **Tessl eval scores** — Plan view tile cards display live eval data (score, pass/fail chart) when available
|
|
46
|
+
- **Activity indicator** — green dot pulses in the header when files are actively changing
|
|
47
|
+
- **Multi-project support** — pidfile at `.specify/dashboard.pid.json` lets external scripts identify running instances per project
|
|
43
48
|
- **Three-state theme** — cycles System (OS preference) → Light → Dark
|
|
44
49
|
- **Zero build step** — single HTML file with inline CSS and JS
|
|
45
50
|
|
|
46
51
|
## How It Works
|
|
47
52
|
|
|
48
|
-
The server reads directly from your project's
|
|
53
|
+
The server reads directly from your project's directory:
|
|
49
54
|
|
|
50
55
|
| File | Purpose |
|
|
51
56
|
|------|---------|
|
|
52
|
-
| `spec.md` | User stories, requirements, success criteria, and clarification Q&A |
|
|
53
|
-
| `plan.md` | Tech stack, file structure, and architecture diagram |
|
|
54
|
-
| `tasks.md` | Task checkboxes grouped by `[US1]`, `[US2]` tags |
|
|
55
|
-
| `checklists/*.md` | Checklist items with completion status, CHK IDs, and category groupings |
|
|
56
57
|
| `CONSTITUTION.md` | Governance principles and obligation levels |
|
|
57
|
-
| `
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
| `specs/<feature>/spec.md` | User stories, requirements, success criteria, and clarification Q&A |
|
|
59
|
+
| `specs/<feature>/plan.md` | Tech stack, file structure, and architecture diagram |
|
|
60
|
+
| `specs/<feature>/research.md` | Research decisions (displayed as tooltips in Plan view) |
|
|
61
|
+
| `specs/<feature>/tasks.md` | Task checkboxes grouped by `[US1]`, `[US2]` tags |
|
|
62
|
+
| `specs/<feature>/checklists/*.md` | Checklist items with completion status, CHK IDs, and category groupings |
|
|
63
|
+
| `specs/<feature>/tests/test-specs.md` | Test specifications for the Testify traceability view |
|
|
64
|
+
| `specs/<feature>/context.json` | Assertion hash for integrity verification |
|
|
65
|
+
| `specs/<feature>/analysis.md` | Consistency analysis findings, coverage, and metrics |
|
|
66
|
+
| `tessl.json` | Installed Tessl tiles for the Plan dependency panel |
|
|
67
|
+
|
|
68
|
+
A file watcher (chokidar) monitors the project tree (excluding `node_modules` and `.git`) and pushes updates to the browser via WebSocket with 300 ms debounce.
|
|
60
69
|
|
|
61
70
|
## Requirements
|
|
62
71
|
|
package/bin/iikit-dashboard.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const { createServer } = require('../src/server');
|
|
5
|
+
const { createServer, removePidfile } = require('../src/server');
|
|
6
6
|
|
|
7
7
|
// Parse arguments
|
|
8
8
|
const args = process.argv.slice(2);
|
|
9
|
-
let projectPath = process.cwd();
|
|
9
|
+
let projectPath = path.resolve(process.cwd());
|
|
10
10
|
let port = 3000;
|
|
11
11
|
|
|
12
12
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -46,6 +46,7 @@ async function main() {
|
|
|
46
46
|
// Handle graceful shutdown
|
|
47
47
|
process.on('SIGINT', () => {
|
|
48
48
|
console.log('\n Shutting down...');
|
|
49
|
+
removePidfile(projectPath);
|
|
49
50
|
result.server.close(() => {
|
|
50
51
|
if (result.watcher) result.watcher.close();
|
|
51
52
|
process.exit(0);
|
|
@@ -53,6 +54,7 @@ async function main() {
|
|
|
53
54
|
});
|
|
54
55
|
|
|
55
56
|
process.on('SIGTERM', () => {
|
|
57
|
+
removePidfile(projectPath);
|
|
56
58
|
result.server.close(() => {
|
|
57
59
|
if (result.watcher) result.watcher.close();
|
|
58
60
|
process.exit(0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iikit-dashboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "Real-time dashboard for Intent Integrity Kit (IIKit) — visualizes every phase of specification-driven AI development",
|
|
5
5
|
"main": "src/server.js",
|
|
6
6
|
"bin": {
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
14
|
"start": "node bin/iikit-dashboard.js",
|
|
15
|
-
"test": "jest --forceExit"
|
|
15
|
+
"test": "jest --forceExit --testPathIgnorePatterns=test/visual",
|
|
16
|
+
"test:visual": "npx playwright test",
|
|
17
|
+
"test:visual:update": "npx playwright test --update-snapshots"
|
|
16
18
|
},
|
|
17
19
|
"keywords": [
|
|
18
20
|
"iikit",
|
|
@@ -40,6 +42,7 @@
|
|
|
40
42
|
"ws": "^8.19.0"
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
45
|
+
"@playwright/test": "^1.58.2",
|
|
43
46
|
"jest": "^30.2.0"
|
|
44
47
|
}
|
|
45
48
|
}
|
package/src/public/index.html
CHANGED
|
@@ -93,6 +93,17 @@
|
|
|
93
93
|
flex: 1 1 auto;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
.project-label {
|
|
97
|
+
font-size: 12px;
|
|
98
|
+
color: var(--color-text-muted);
|
|
99
|
+
max-width: 160px;
|
|
100
|
+
overflow: hidden;
|
|
101
|
+
text-overflow: ellipsis;
|
|
102
|
+
white-space: nowrap;
|
|
103
|
+
border-left: 1px solid var(--color-border);
|
|
104
|
+
padding-left: 12px;
|
|
105
|
+
}
|
|
106
|
+
|
|
96
107
|
.feature-selector {
|
|
97
108
|
position: relative;
|
|
98
109
|
min-width: 100px;
|
|
@@ -713,8 +724,7 @@
|
|
|
713
724
|
border-radius: var(--radius-md);
|
|
714
725
|
cursor: pointer;
|
|
715
726
|
transition: background var(--transition-fast), transform var(--transition-fast);
|
|
716
|
-
flex: 0 1
|
|
717
|
-
width: 96px;
|
|
727
|
+
flex: 0 1 auto;
|
|
718
728
|
min-width: 40px;
|
|
719
729
|
position: relative;
|
|
720
730
|
border: 1px solid var(--color-border-subtle);
|
|
@@ -2368,6 +2378,7 @@
|
|
|
2368
2378
|
<div class="logo-icon" aria-hidden="true">D</div>
|
|
2369
2379
|
<span>IIKit Dashboard</span>
|
|
2370
2380
|
</div>
|
|
2381
|
+
<div class="project-label" id="projectLabel" title=""></div>
|
|
2371
2382
|
<div class="feature-selector" role="navigation" aria-label="Feature selector">
|
|
2372
2383
|
<select id="featureSelect" aria-label="Select feature to display" tabindex="0">
|
|
2373
2384
|
<option value="">Loading features...</option>
|
|
@@ -5188,6 +5199,12 @@
|
|
|
5188
5199
|
applyTheme(themeMode);
|
|
5189
5200
|
|
|
5190
5201
|
// ====== Init ======
|
|
5202
|
+
fetch('/api/meta').then(r => r.json()).then(meta => {
|
|
5203
|
+
const label = document.getElementById('projectLabel');
|
|
5204
|
+
const dirName = meta.projectPath.split('/').pop();
|
|
5205
|
+
label.textContent = dirName;
|
|
5206
|
+
label.title = meta.projectPath;
|
|
5207
|
+
}).catch(() => {});
|
|
5191
5208
|
loadFeatures();
|
|
5192
5209
|
connectWebSocket();
|
|
5193
5210
|
})();
|
package/src/server.js
CHANGED
|
@@ -98,6 +98,33 @@ function getBoardState(projectPath, featureId) {
|
|
|
98
98
|
return { ...board, integrity };
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Write a pidfile with metadata so external scripts can identify this dashboard instance.
|
|
103
|
+
*/
|
|
104
|
+
function writePidfile(projectPath, port) {
|
|
105
|
+
const resolved = path.resolve(projectPath);
|
|
106
|
+
const specifyDir = path.join(resolved, '.specify');
|
|
107
|
+
fs.mkdirSync(specifyDir, { recursive: true });
|
|
108
|
+
const pidData = {
|
|
109
|
+
pid: process.pid,
|
|
110
|
+
port,
|
|
111
|
+
directory: resolved,
|
|
112
|
+
startedAt: new Date().toISOString()
|
|
113
|
+
};
|
|
114
|
+
fs.writeFileSync(path.join(specifyDir, 'dashboard.pid.json'), JSON.stringify(pidData, null, 2));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Remove the pidfile on shutdown.
|
|
119
|
+
*/
|
|
120
|
+
function removePidfile(projectPath) {
|
|
121
|
+
try {
|
|
122
|
+
fs.unlinkSync(path.join(path.resolve(projectPath), '.specify', 'dashboard.pid.json'));
|
|
123
|
+
} catch (err) {
|
|
124
|
+
if (err.code !== 'ENOENT') throw err;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
101
128
|
/**
|
|
102
129
|
* Create and configure the Express server with WebSocket support.
|
|
103
130
|
*
|
|
@@ -107,11 +134,17 @@ function getBoardState(projectPath, featureId) {
|
|
|
107
134
|
* @returns {Promise<{server: http.Server, port: number, wss: WebSocketServer}>}
|
|
108
135
|
*/
|
|
109
136
|
function createServer({ projectPath, port = 3000 }) {
|
|
137
|
+
const resolvedPath = path.resolve(projectPath);
|
|
110
138
|
const app = express();
|
|
111
139
|
|
|
112
140
|
// Serve static files from src/public
|
|
113
141
|
app.use(express.static(path.join(__dirname, 'public')));
|
|
114
142
|
|
|
143
|
+
// API: project metadata
|
|
144
|
+
app.get('/api/meta', (req, res) => {
|
|
145
|
+
res.json({ projectPath: resolvedPath });
|
|
146
|
+
});
|
|
147
|
+
|
|
115
148
|
// API: list features
|
|
116
149
|
app.get('/api/features', (req, res) => {
|
|
117
150
|
try {
|
|
@@ -363,9 +396,10 @@ function createServer({ projectPath, port = 3000 }) {
|
|
|
363
396
|
return new Promise((resolve) => {
|
|
364
397
|
server.listen(port, () => {
|
|
365
398
|
const actualPort = server.address().port;
|
|
366
|
-
|
|
399
|
+
writePidfile(resolvedPath, actualPort);
|
|
400
|
+
resolve({ server, port: actualPort, wss, watcher, projectPath: resolvedPath });
|
|
367
401
|
});
|
|
368
402
|
});
|
|
369
403
|
}
|
|
370
404
|
|
|
371
|
-
module.exports = { createServer, listFeatures, getBoardState };
|
|
405
|
+
module.exports = { createServer, listFeatures, getBoardState, removePidfile };
|