@sienklogic/plan-build-run 2.27.2 → 2.29.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.
- package/CHANGELOG.md +14 -0
- package/dashboard/bin/cli.js +3 -3
- package/dashboard/package.json +8 -5
- package/dashboard/public/css/command-center.css +382 -0
- package/dashboard/public/css/layout.css +481 -254
- package/dashboard/public/css/tokens.css +70 -61
- package/dashboard/public/js/sse-client.js +52 -82
- package/dashboard/public/js/theme-toggle.js +19 -14
- package/dashboard/src/components/Layout.tsx +99 -0
- package/dashboard/src/components/partials/ActivityStream.tsx +58 -0
- package/dashboard/src/components/partials/AttentionPanel.tsx +48 -0
- package/dashboard/src/components/partials/CurrentPhaseCard.tsx +50 -0
- package/dashboard/src/components/partials/PhaseTimeline.tsx +38 -0
- package/dashboard/src/components/partials/ProgressRing.tsx +51 -0
- package/dashboard/src/components/partials/QuickActions.tsx +30 -0
- package/dashboard/src/components/partials/StatusHeader.tsx +45 -0
- package/dashboard/src/global.d.ts +10 -0
- package/dashboard/src/index.tsx +134 -0
- package/dashboard/src/middleware/current-phase.ts +23 -0
- package/dashboard/src/routes/command-center.routes.tsx +69 -0
- package/dashboard/src/routes/index.routes.tsx +106 -0
- package/dashboard/src/services/dashboard.service.d.ts +39 -0
- package/dashboard/src/services/sse.service.ts +34 -0
- package/dashboard/src/services/todo.service.d.ts +21 -0
- package/dashboard/src/services/watcher.service.ts +35 -0
- package/dashboard/src/sse-handler.tsx +37 -0
- package/dashboard/src/watcher-setup.ts +25 -0
- package/package.json +1 -1
- package/plugins/copilot-pbr/plugin.json +1 -1
- package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
- package/plugins/pbr/.claude-plugin/plugin.json +1 -1
- package/dashboard/src/services/sse.service.js +0 -58
- package/dashboard/src/services/watcher.service.js +0 -48
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createWatcher, type WatchEvent } from './services/watcher.service.js';
|
|
2
|
+
import { broadcast } from './services/sse.service.js';
|
|
3
|
+
import type { FSWatcher } from 'chokidar';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Start the file watcher for the project's .planning/ directory.
|
|
7
|
+
*
|
|
8
|
+
* On every file-change event, optionally invalidates caches (via the
|
|
9
|
+
* onCacheInvalidate callback) and broadcasts an SSE 'file-change' event
|
|
10
|
+
* to all connected clients.
|
|
11
|
+
*
|
|
12
|
+
* @param projectDir - Absolute path to the project root directory
|
|
13
|
+
* @param onCacheInvalidate - Optional callback to clear service-level caches
|
|
14
|
+
* @returns The FSWatcher instance (call .close() for graceful shutdown)
|
|
15
|
+
*/
|
|
16
|
+
export function startWatcher(
|
|
17
|
+
projectDir: string,
|
|
18
|
+
onCacheInvalidate?: () => void
|
|
19
|
+
): FSWatcher {
|
|
20
|
+
const watcher = createWatcher(projectDir, async (event: WatchEvent) => {
|
|
21
|
+
onCacheInvalidate?.();
|
|
22
|
+
await broadcast('file-change', event);
|
|
23
|
+
});
|
|
24
|
+
return watcher;
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
3
|
"displayName": "Plan-Build-Run",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.29.0",
|
|
5
5
|
"description": "Plan-Build-Run — Structured development workflow for GitHub Copilot CLI. Solves context rot through disciplined agent delegation, structured planning, atomic execution, and goal-backward verification.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "SienkLogic",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
3
|
"displayName": "Plan-Build-Run",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.29.0",
|
|
5
5
|
"description": "Plan-Build-Run — Structured development workflow for Cursor. Solves context rot through disciplined subagent delegation, structured planning, atomic execution, and goal-backward verification.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "SienkLogic",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pbr",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.29.0",
|
|
4
4
|
"description": "Plan-Build-Run — Structured development workflow for Claude Code. Solves context rot through disciplined subagent delegation, structured planning, atomic execution, and goal-backward verification.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "SienkLogic",
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SSE (Server-Sent Events) service.
|
|
3
|
-
* Manages a Set of active client response objects and provides
|
|
4
|
-
* broadcast functionality to send events to all connected browsers.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** @type {Set<import('http').ServerResponse>} */
|
|
8
|
-
const clients = new Set();
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Register a client response object for SSE broadcasting.
|
|
12
|
-
* @param {import('http').ServerResponse} res
|
|
13
|
-
*/
|
|
14
|
-
export function addClient(res) {
|
|
15
|
-
clients.add(res);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Remove a client response object (called on disconnect).
|
|
20
|
-
* @param {import('http').ServerResponse} res
|
|
21
|
-
*/
|
|
22
|
-
export function removeClient(res) {
|
|
23
|
-
clients.delete(res);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Broadcast an SSE event to all connected clients.
|
|
28
|
-
* Clients that throw on write are automatically removed.
|
|
29
|
-
* @param {string} eventType - SSE event name (e.g. 'file-change')
|
|
30
|
-
* @param {object} data - Payload to JSON-serialize in the data field
|
|
31
|
-
*/
|
|
32
|
-
export function broadcast(eventType, data) {
|
|
33
|
-
const id = Date.now();
|
|
34
|
-
const message = `event: ${eventType}\ndata: ${JSON.stringify(data)}\nid: ${id}\n\n`;
|
|
35
|
-
|
|
36
|
-
for (const client of clients) {
|
|
37
|
-
try {
|
|
38
|
-
client.write(message);
|
|
39
|
-
} catch {
|
|
40
|
-
clients.delete(client);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Return the number of currently connected clients.
|
|
47
|
-
* @returns {number}
|
|
48
|
-
*/
|
|
49
|
-
export function getClientCount() {
|
|
50
|
-
return clients.size;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Remove all clients. Used in tests to reset state between test cases.
|
|
55
|
-
*/
|
|
56
|
-
export function clearClients() {
|
|
57
|
-
clients.clear();
|
|
58
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import chokidar from 'chokidar';
|
|
2
|
-
import { join, relative } from 'node:path';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Create a chokidar file watcher for the .planning/ directory.
|
|
6
|
-
*
|
|
7
|
-
* Watches **\/*.md files with awaitWriteFinish to debounce editor saves.
|
|
8
|
-
* Calls onChange with a normalized event object on add, change, and unlink.
|
|
9
|
-
*
|
|
10
|
-
* @param {string} watchPath - Absolute path to the project directory
|
|
11
|
-
* @param {(event: {path: string, type: string, timestamp: number}) => void} onChange
|
|
12
|
-
* @returns {import('chokidar').FSWatcher}
|
|
13
|
-
*/
|
|
14
|
-
export function createWatcher(watchPath, onChange) {
|
|
15
|
-
const planningDir = join(watchPath, '.planning');
|
|
16
|
-
|
|
17
|
-
const watcher = chokidar.watch(join(planningDir, '**/*.md'), {
|
|
18
|
-
ignored: [
|
|
19
|
-
'**/node_modules/**',
|
|
20
|
-
'**/.git/**'
|
|
21
|
-
],
|
|
22
|
-
persistent: true,
|
|
23
|
-
ignoreInitial: true,
|
|
24
|
-
awaitWriteFinish: {
|
|
25
|
-
stabilityThreshold: 500,
|
|
26
|
-
pollInterval: 100
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const handleEvent = (type) => (filePath) => {
|
|
31
|
-
const relativePath = relative(watchPath, filePath);
|
|
32
|
-
onChange({
|
|
33
|
-
path: relativePath,
|
|
34
|
-
type,
|
|
35
|
-
timestamp: Date.now()
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
watcher.on('add', handleEvent('add'));
|
|
40
|
-
watcher.on('change', handleEvent('change'));
|
|
41
|
-
watcher.on('unlink', handleEvent('unlink'));
|
|
42
|
-
|
|
43
|
-
watcher.on('error', (error) => {
|
|
44
|
-
console.error('Watcher error:', error.message);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return watcher;
|
|
48
|
-
}
|