create-claude-cabinet 0.13.1 → 0.14.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/package.json +1 -1
- package/templates/hooks/omega-memory-guard.sh +1 -1
- package/templates/scripts/work-tracker-server.mjs +39 -6
- package/templates/scripts/work-tracker-ui.html +8 -2
- package/templates/skills/cc-publish/SKILL.md +18 -0
- package/templates/skills/debrief/SKILL.md +6 -0
- package/templates/skills/debrief/phases/close-work.md +27 -0
package/package.json
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
import { createServer } from 'node:http';
|
|
9
9
|
import { readFile } from 'node:fs/promises';
|
|
10
|
-
import { existsSync } from 'node:fs';
|
|
10
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
|
-
import { dirname, join, resolve } from 'node:path';
|
|
12
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
13
13
|
import Database from 'better-sqlite3';
|
|
14
14
|
|
|
15
15
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
const
|
|
16
|
+
const PREFERRED_PORT = parseInt(process.env.PORT || process.argv.find((_, i, a) => a[i - 1] === '--port') || '3458');
|
|
17
17
|
const DB_PATH = resolve(process.argv.find((_, i, a) => a[i - 1] === '--db') || 'pib.db');
|
|
18
18
|
|
|
19
19
|
if (!existsSync(DB_PATH)) {
|
|
@@ -22,6 +22,18 @@ if (!existsSync(DB_PATH)) {
|
|
|
22
22
|
process.exit(1);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
// Derive project name from .ccrc.json, package.json, or directory name
|
|
26
|
+
function getProjectName() {
|
|
27
|
+
for (const file of ['.ccrc.json', 'package.json']) {
|
|
28
|
+
try {
|
|
29
|
+
const data = JSON.parse(readFileSync(resolve(file), 'utf-8'));
|
|
30
|
+
if (file === 'package.json' && data.name) return data.name;
|
|
31
|
+
} catch {}
|
|
32
|
+
}
|
|
33
|
+
return basename(resolve('.'));
|
|
34
|
+
}
|
|
35
|
+
const PROJECT_NAME = getProjectName();
|
|
36
|
+
|
|
25
37
|
const db = new Database(DB_PATH, { readonly: false });
|
|
26
38
|
db.pragma('journal_mode = WAL');
|
|
27
39
|
|
|
@@ -42,7 +54,7 @@ async function readBody(req) {
|
|
|
42
54
|
}
|
|
43
55
|
|
|
44
56
|
const server = createServer(async (req, res) => {
|
|
45
|
-
const url = new URL(req.url, `http://localhost:${
|
|
57
|
+
const url = new URL(req.url, `http://localhost:${server.address()?.port || PREFERRED_PORT}`);
|
|
46
58
|
|
|
47
59
|
if (req.method === 'OPTIONS') {
|
|
48
60
|
res.writeHead(204, {
|
|
@@ -159,6 +171,11 @@ const server = createServer(async (req, res) => {
|
|
|
159
171
|
return json(res, { ok: true });
|
|
160
172
|
}
|
|
161
173
|
|
|
174
|
+
// GET /api/meta — project name and server info
|
|
175
|
+
if (req.method === 'GET' && url.pathname === '/api/meta') {
|
|
176
|
+
return json(res, { projectName: PROJECT_NAME });
|
|
177
|
+
}
|
|
178
|
+
|
|
162
179
|
// GET /api/stats — dashboard summary
|
|
163
180
|
if (req.method === 'GET' && url.pathname === '/api/stats') {
|
|
164
181
|
const projects = db.prepare(`
|
|
@@ -182,7 +199,23 @@ const server = createServer(async (req, res) => {
|
|
|
182
199
|
}
|
|
183
200
|
});
|
|
184
201
|
|
|
185
|
-
server.listen(
|
|
186
|
-
|
|
202
|
+
server.listen(PREFERRED_PORT, () => {
|
|
203
|
+
const actualPort = server.address().port;
|
|
204
|
+
console.log(`Work tracker at http://localhost:${actualPort}`);
|
|
187
205
|
console.log(`Database: ${DB_PATH}`);
|
|
206
|
+
console.log(`Project: ${PROJECT_NAME}`);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
server.on('error', (err) => {
|
|
210
|
+
if (err.code === 'EADDRINUSE') {
|
|
211
|
+
console.log(`Port ${PREFERRED_PORT} in use, finding a free port...`);
|
|
212
|
+
server.listen(0, () => {
|
|
213
|
+
const actualPort = server.address().port;
|
|
214
|
+
console.log(`Work tracker at http://localhost:${actualPort}`);
|
|
215
|
+
console.log(`Database: ${DB_PATH}`);
|
|
216
|
+
console.log(`Project: ${PROJECT_NAME}`);
|
|
217
|
+
});
|
|
218
|
+
} else {
|
|
219
|
+
throw err;
|
|
220
|
+
}
|
|
188
221
|
});
|
|
@@ -410,7 +410,7 @@
|
|
|
410
410
|
</head>
|
|
411
411
|
<body>
|
|
412
412
|
<header>
|
|
413
|
-
<h1>Work Tracker</h1>
|
|
413
|
+
<h1><span id="project-name" style="color: #7048e8;"></span> <span style="color: #5c5f66; font-weight: 400;">Work Tracker</span></h1>
|
|
414
414
|
<div class="stats" id="stats"></div>
|
|
415
415
|
</header>
|
|
416
416
|
|
|
@@ -456,14 +456,20 @@
|
|
|
456
456
|
// Fetch data
|
|
457
457
|
async function load() {
|
|
458
458
|
try {
|
|
459
|
-
const [projRes, actRes, statsRes] = await Promise.all([
|
|
459
|
+
const [projRes, actRes, statsRes, metaRes] = await Promise.all([
|
|
460
460
|
fetch(`/api/projects?status=${currentStatus}`),
|
|
461
461
|
fetch('/api/actions?status=all'),
|
|
462
462
|
fetch('/api/stats'),
|
|
463
|
+
fetch('/api/meta'),
|
|
463
464
|
]);
|
|
464
465
|
projects = await projRes.json();
|
|
465
466
|
actions = await actRes.json();
|
|
466
467
|
const stats = await statsRes.json();
|
|
468
|
+
const meta = await metaRes.json();
|
|
469
|
+
if (meta.projectName) {
|
|
470
|
+
document.title = `${meta.projectName} — Work Tracker`;
|
|
471
|
+
document.getElementById('project-name').textContent = meta.projectName;
|
|
472
|
+
}
|
|
467
473
|
renderStats(stats);
|
|
468
474
|
document.getElementById('loading').style.display = 'none';
|
|
469
475
|
render();
|
|
@@ -78,3 +78,21 @@ With user confirmation:
|
|
|
78
78
|
no unexpected fields were added or existing fields changed.
|
|
79
79
|
- Update `system-status.md` if it exists
|
|
80
80
|
- Report the published version and npm URL
|
|
81
|
+
|
|
82
|
+
### 6. Update Local Consumers
|
|
83
|
+
|
|
84
|
+
Read `~/.claude/cc-registry.json` for all registered CC projects. For
|
|
85
|
+
each project that is NOT the CC source repo itself:
|
|
86
|
+
|
|
87
|
+
1. Check its current version (`cat <path>/.ccrc.json | jq -r .version`)
|
|
88
|
+
2. If it's older than the just-published version, update it:
|
|
89
|
+
- `cd <path> && npx create-claude-cabinet@latest --yes`
|
|
90
|
+
- Verify the install succeeded (`.ccrc.json` version matches)
|
|
91
|
+
3. Report which consumers were updated and which were already current
|
|
92
|
+
|
|
93
|
+
**Important:**
|
|
94
|
+
- Never force-install or pass flags beyond `--yes` — the installer
|
|
95
|
+
reads the existing `.ccrc.json` to determine install type
|
|
96
|
+
- If a consumer's path doesn't exist, note it (stale registry entry)
|
|
97
|
+
but don't error — mention it in the report
|
|
98
|
+
- If an install fails, report the error but continue with other consumers
|
|
@@ -139,6 +139,12 @@ initialized, skip gracefully.
|
|
|
139
139
|
sqlite3 pib.db "UPDATE actions SET completed = 1, completed_at = date('now') WHERE fid = '<fid>'"
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
**Field feedback resolution:** After closing actions, check `feedback/`
|
|
143
|
+
for `.md` files from consuming projects. For each, compare the described
|
|
144
|
+
friction against this session's commits. If the friction was addressed,
|
|
145
|
+
propose deleting the feedback file (it's a queue, not a ledger — the
|
|
146
|
+
fix lives in git history). Partially addressed feedback stays open.
|
|
147
|
+
|
|
142
148
|
**Project completion scan:** After closing actions, check for projects
|
|
143
149
|
where all actions are now done:
|
|
144
150
|
|
|
@@ -87,6 +87,33 @@ notes, create new items for each. Known work that lives only in completed
|
|
|
87
87
|
items' notes will be forgotten. There is no "later" — create it now.
|
|
88
88
|
-->
|
|
89
89
|
|
|
90
|
+
## Resolve Field Feedback
|
|
91
|
+
|
|
92
|
+
After closing actions, check the `feedback/` directory for field feedback
|
|
93
|
+
files from consuming projects. For each file, evaluate whether this
|
|
94
|
+
session's work addressed the friction described.
|
|
95
|
+
|
|
96
|
+
**How to check:**
|
|
97
|
+
1. Scan `feedback/` for `.md` files (skip `.gitkeep`)
|
|
98
|
+
2. For each file, read the `component` from frontmatter and the friction
|
|
99
|
+
description
|
|
100
|
+
3. Cross-reference against this session's git log and changed files —
|
|
101
|
+
did the session fix or address the reported friction?
|
|
102
|
+
4. For each resolved item, present to the user:
|
|
103
|
+
> "Field feedback resolved: [title] from [source] — [one-line summary
|
|
104
|
+
> of what fixed it]. Delete the feedback file? (yes/no)"
|
|
105
|
+
5. On confirmation, delete the feedback file. It served its purpose —
|
|
106
|
+
the friction was addressed and the fix is in the commit history.
|
|
107
|
+
|
|
108
|
+
**Why delete rather than mark resolved?** Feedback files are a queue, not
|
|
109
|
+
a ledger. The commit history records what was fixed and when. Keeping
|
|
110
|
+
resolved feedback files around creates stale noise that orient has to
|
|
111
|
+
filter through every session.
|
|
112
|
+
|
|
113
|
+
**Partially addressed feedback** stays open. If the session fixed one
|
|
114
|
+
aspect but not another, note what was fixed in the file (append a
|
|
115
|
+
`## Partial resolution` section) but don't delete it.
|
|
116
|
+
|
|
90
117
|
## Project Completion Scan
|
|
91
118
|
|
|
92
119
|
After closing individual actions, check for projects that may be ready
|