tribunal-kit 4.4.0 → 4.4.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/.agent/agents/api-architect.md +66 -66
- package/.agent/agents/db-latency-auditor.md +216 -216
- package/.agent/agents/precedence-reviewer.md +250 -250
- package/.agent/agents/resilience-reviewer.md +88 -88
- package/.agent/agents/schema-reviewer.md +67 -67
- package/.agent/agents/throughput-optimizer.md +299 -299
- package/.agent/agents/ui-ux-auditor.md +292 -292
- package/.agent/agents/vitals-reviewer.md +223 -223
- package/.agent/scripts/_colors.js +18 -18
- package/.agent/scripts/_utils.js +42 -42
- package/.agent/scripts/append_flow.js +72 -72
- package/.agent/scripts/auto_preview.js +197 -197
- package/.agent/scripts/bundle_analyzer.js +290 -290
- package/.agent/scripts/case_law_manager.js +17 -6
- package/.agent/scripts/checklist.js +266 -266
- package/.agent/scripts/colors.js +17 -17
- package/.agent/scripts/compress_skills.js +141 -141
- package/.agent/scripts/consolidate_skills.js +149 -149
- package/.agent/scripts/context_broker.js +611 -609
- package/.agent/scripts/deep_compress.js +150 -150
- package/.agent/scripts/dependency_analyzer.js +272 -272
- package/.agent/scripts/graph_builder.js +313 -311
- package/.agent/scripts/graph_visualizer.js +384 -384
- package/.agent/scripts/inner_loop_validator.js +451 -465
- package/.agent/scripts/lint_runner.js +187 -187
- package/.agent/scripts/minify_context.js +100 -100
- package/.agent/scripts/mutation_runner.js +280 -280
- package/.agent/scripts/patch_skills_meta.js +156 -156
- package/.agent/scripts/patch_skills_output.js +244 -244
- package/.agent/scripts/schema_validator.js +297 -297
- package/.agent/scripts/security_scan.js +303 -303
- package/.agent/scripts/session_manager.js +276 -276
- package/.agent/scripts/skill_evolution.js +644 -644
- package/.agent/scripts/skill_integrator.js +313 -313
- package/.agent/scripts/strengthen_skills.js +193 -193
- package/.agent/scripts/strip_tribunal.js +47 -47
- package/.agent/scripts/swarm_dispatcher.js +360 -360
- package/.agent/scripts/test_runner.js +193 -193
- package/.agent/scripts/utils.js +32 -32
- package/.agent/scripts/verify_all.js +257 -256
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +1 -1
- package/.agent/skills/doc.md +1 -1
- package/.agent/skills/knowledge-graph/SKILL.md +52 -52
- package/.agent/skills/ui-ux-pro-max/SKILL.md +562 -562
- package/.agent/workflows/generate.md +183 -183
- package/.agent/workflows/tribunal-speed.md +183 -183
- package/README.md +1 -1
- package/bin/tribunal-kit.js +76 -87
- package/package.json +6 -3
- package/scripts/changelog.js +167 -167
- package/scripts/sync-version.js +81 -81
- package/.agent/history/architecture-explorer.html +0 -352
- package/.agent/history/architecture-graph.yaml +0 -109
- package/.agent/history/graph-cache.json +0 -215
- package/.agent/history/snapshots/migrate_refs.js.json +0 -11
- package/.agent/history/snapshots/scripts__changelog.js.json +0 -12
- package/.agent/history/snapshots/scripts__sync-version.js.json +0 -11
- package/.agent/history/snapshots/scripts__validate-payload.js.json +0 -11
- package/.agent/history/snapshots/test__integration__bridges.test.js.json +0 -13
- package/.agent/history/snapshots/test__integration__init.test.js.json +0 -13
- package/.agent/history/snapshots/test__integration__routing.test.js.json +0 -11
- package/.agent/history/snapshots/test__integration__swarm_dispatcher.test.js.json +0 -13
- package/.agent/history/snapshots/test__integration__wave2.test.js.json +0 -13
- package/.agent/history/snapshots/test__unit__args.test.js.json +0 -10
- package/.agent/history/snapshots/test__unit__case_law_manager.test.js.json +0 -10
- package/.agent/history/snapshots/test__unit__copyDir.test.js.json +0 -13
- package/.agent/history/snapshots/test__unit__graph_tools.test.js.json +0 -11
- package/.agent/history/snapshots/test__unit__selfInstall.test.js.json +0 -13
- package/.agent/history/snapshots/test__unit__semver.test.js.json +0 -10
- package/.agent/history/snapshots/test__unit__swarm_dispatcher.test.js.json +0 -11
- package/.agent/scripts/__pycache__/_colors.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/_utils.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/case_law_manager.cpython-311.pyc +0 -0
|
@@ -1,276 +1,276 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* session_manager.js — Agent session state tracking for multi-conversation work.
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* node .agent/scripts/session_manager.js save "working on auth"
|
|
7
|
-
* node .agent/scripts/session_manager.js load
|
|
8
|
-
* node .agent/scripts/session_manager.js show
|
|
9
|
-
* node .agent/scripts/session_manager.js clear
|
|
10
|
-
* node .agent/scripts/session_manager.js status
|
|
11
|
-
* node .agent/scripts/session_manager.js tag <label>
|
|
12
|
-
* node .agent/scripts/session_manager.js list [--all]
|
|
13
|
-
* node .agent/scripts/session_manager.js export [--stdout]
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
'use strict';
|
|
17
|
-
|
|
18
|
-
const fs = require('fs');
|
|
19
|
-
const path = require('path');
|
|
20
|
-
|
|
21
|
-
const STATE_FILE = ".agent_session.json";
|
|
22
|
-
|
|
23
|
-
const GREEN = "\x1b[92m";
|
|
24
|
-
const YELLOW = "\x1b[93m";
|
|
25
|
-
const BLUE = "\x1b[94m";
|
|
26
|
-
const CYAN = "\x1b[96m";
|
|
27
|
-
const RED = "\x1b[91m";
|
|
28
|
-
const BOLD = "\x1b[1m";
|
|
29
|
-
const RESET = "\x1b[0m";
|
|
30
|
-
|
|
31
|
-
const VALID_COMMANDS = new Set(["save", "load", "show", "clear", "status", "tag", "list", "export"]);
|
|
32
|
-
const LIST_PAGE_SIZE = 10;
|
|
33
|
-
|
|
34
|
-
function loadState() {
|
|
35
|
-
if (!fs.existsSync(STATE_FILE)) return {};
|
|
36
|
-
try {
|
|
37
|
-
const content = fs.readFileSync(STATE_FILE, 'utf8');
|
|
38
|
-
return JSON.parse(content);
|
|
39
|
-
} catch {
|
|
40
|
-
return {};
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function saveState(state) {
|
|
45
|
-
fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2), 'utf8');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function cmdSave(note) {
|
|
49
|
-
const state = loadState();
|
|
50
|
-
const entry = {
|
|
51
|
-
timestamp: new Date().toISOString(),
|
|
52
|
-
note: note,
|
|
53
|
-
session: (state.history || []).length + 1,
|
|
54
|
-
tags: []
|
|
55
|
-
};
|
|
56
|
-
if (!state.history) state.history = [];
|
|
57
|
-
state.history.push(entry);
|
|
58
|
-
state.current = entry;
|
|
59
|
-
saveState(state);
|
|
60
|
-
|
|
61
|
-
console.log(`${GREEN}✅ Session saved:${RESET} ${note}`);
|
|
62
|
-
console.log(` Time: ${entry.timestamp}`);
|
|
63
|
-
console.log(` Session: #${entry.session}`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function cmdLoad() {
|
|
67
|
-
const state = loadState();
|
|
68
|
-
const current = state.current;
|
|
69
|
-
if (!current) {
|
|
70
|
-
console.log(`${YELLOW}No active session — use 'save' first.${RESET}`);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
const tagsStr = (current.tags || []).join(", ") || "none";
|
|
74
|
-
console.log(`${BOLD}Current session:${RESET}`);
|
|
75
|
-
console.log(` Session: #${current.session}`);
|
|
76
|
-
console.log(` Time: ${current.timestamp}`);
|
|
77
|
-
console.log(` Note: ${current.note}`);
|
|
78
|
-
console.log(` Tags: ${tagsStr}`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function cmdShow() {
|
|
82
|
-
const state = loadState();
|
|
83
|
-
const history = state.history || [];
|
|
84
|
-
if (!history.length) {
|
|
85
|
-
console.log(`${YELLOW}No session history.${RESET}`);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
console.log(`${BOLD}Session History (${history.length} total):${RESET}`);
|
|
89
|
-
const recent = history.slice(-10).reverse();
|
|
90
|
-
for (const entry of recent) {
|
|
91
|
-
const tagsStr = (entry.tags || []).join(", ") || "";
|
|
92
|
-
const tagsDisplay = tagsStr ? ` [${tagsStr}]` : "";
|
|
93
|
-
console.log(`\n ${BLUE}#${entry.session}${RESET} — ${entry.timestamp.slice(0, 16)}${tagsDisplay}`);
|
|
94
|
-
console.log(` ${entry.note}`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function cmdClear() {
|
|
99
|
-
if (fs.existsSync(STATE_FILE)) {
|
|
100
|
-
fs.unlinkSync(STATE_FILE);
|
|
101
|
-
console.log(`${GREEN}✅ Session state cleared.${RESET}`);
|
|
102
|
-
} else {
|
|
103
|
-
console.log(`${YELLOW}No session file found — nothing to clear.${RESET}`);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function cmdStatus() {
|
|
108
|
-
const state = loadState();
|
|
109
|
-
const history = state.history || [];
|
|
110
|
-
const current = state.current;
|
|
111
|
-
|
|
112
|
-
if (!history.length) {
|
|
113
|
-
console.log(`${YELLOW}No session history — use 'save' to start tracking.${RESET}`);
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const total = history.length;
|
|
118
|
-
const recent = history.slice(-3).reverse();
|
|
119
|
-
|
|
120
|
-
console.log(`\n${BOLD}${CYAN}━━━ Session Status ━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
|
|
121
|
-
console.log(` Total sessions: ${total}`);
|
|
122
|
-
if (current) {
|
|
123
|
-
console.log(` Active: #${current.session} — ${current.note.slice(0, 60)}`);
|
|
124
|
-
}
|
|
125
|
-
console.log(`\n${BOLD} Last 3 sessions:${RESET}`);
|
|
126
|
-
for (const entry of recent) {
|
|
127
|
-
const tagsStr = (entry.tags || []).join(", ") || "";
|
|
128
|
-
const tagsDisplay = tagsStr ? ` [${tagsStr}]` : "";
|
|
129
|
-
const ts = entry.timestamp.slice(0, 16);
|
|
130
|
-
console.log(` ${BLUE}#${entry.session}${RESET} ${ts}${tagsDisplay}`);
|
|
131
|
-
console.log(` ${entry.note.slice(0, 70)}`);
|
|
132
|
-
}
|
|
133
|
-
console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function cmdTag(label) {
|
|
137
|
-
if (!label) {
|
|
138
|
-
console.log(`${RED}Error: provide a tag label. Example: node session_manager.js tag v2-feature${RESET}`);
|
|
139
|
-
process.exit(1);
|
|
140
|
-
}
|
|
141
|
-
const state = loadState();
|
|
142
|
-
const current = state.current;
|
|
143
|
-
if (!current) {
|
|
144
|
-
console.log(`${YELLOW}No active session — use 'save' first before tagging.${RESET}`);
|
|
145
|
-
process.exit(1);
|
|
146
|
-
}
|
|
147
|
-
if (!current.tags) current.tags = [];
|
|
148
|
-
if (current.tags.includes(label)) {
|
|
149
|
-
console.log(`${YELLOW}Tag '${label}' already exists on session #${current.session}.${RESET}`);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
current.tags.push(label);
|
|
154
|
-
state.current = current;
|
|
155
|
-
|
|
156
|
-
if (state.history) {
|
|
157
|
-
for (const entry of state.history) {
|
|
158
|
-
if (entry.session === current.session) {
|
|
159
|
-
if (!entry.tags) entry.tags = [];
|
|
160
|
-
if (!entry.tags.includes(label)) {
|
|
161
|
-
entry.tags.push(label);
|
|
162
|
-
}
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
saveState(state);
|
|
169
|
-
console.log(`${GREEN}✅ Tagged session #${current.session} with '${label}'.${RESET}`);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function cmdList(showAll) {
|
|
173
|
-
const state = loadState();
|
|
174
|
-
const history = state.history || [];
|
|
175
|
-
if (!history.length) {
|
|
176
|
-
console.log(`${YELLOW}No session history.${RESET}`);
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const total = history.length;
|
|
181
|
-
const pageSize = showAll ? total : LIST_PAGE_SIZE;
|
|
182
|
-
const recent = history.slice().reverse().slice(0, pageSize);
|
|
183
|
-
|
|
184
|
-
console.log(`\n${BOLD}${CYAN}━━━ Session List (${total} total, showing ${recent.length}) ━━━━━━━${RESET}`);
|
|
185
|
-
|
|
186
|
-
for (const entry of recent) {
|
|
187
|
-
const tagsStr = (entry.tags || []).join(", ");
|
|
188
|
-
const tagsDisplay = tagsStr ? ` [${YELLOW}${tagsStr}${RESET}]` : "";
|
|
189
|
-
const ts = entry.timestamp.slice(0, 16);
|
|
190
|
-
console.log(`\n ${BOLD}${BLUE}#${entry.session}${RESET} — ${ts}${tagsDisplay}`);
|
|
191
|
-
console.log(` ${entry.note}`);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (!showAll && total > pageSize) {
|
|
195
|
-
const remaining = total - pageSize;
|
|
196
|
-
console.log(`\n ${YELLOW}... ${remaining} older session(s) not shown. Use '--all' to see all.${RESET}`);
|
|
197
|
-
}
|
|
198
|
-
console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function cmdExport(toStdout) {
|
|
202
|
-
const state = loadState();
|
|
203
|
-
const history = state.history || [];
|
|
204
|
-
if (!history.length) {
|
|
205
|
-
console.log(`${YELLOW}No session history to export.${RESET}`);
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const lines = ["# Session Export\n"];
|
|
210
|
-
lines.push(`Generated: ${new Date().toISOString().slice(0, 16)}\n`);
|
|
211
|
-
lines.push(`Total sessions: ${history.length}\n\n---\n`);
|
|
212
|
-
|
|
213
|
-
const reversed = history.slice().reverse();
|
|
214
|
-
for (const entry of reversed) {
|
|
215
|
-
const sessionNum = entry.session || "?";
|
|
216
|
-
const ts = (entry.timestamp || "").slice(0, 16);
|
|
217
|
-
const note = entry.note || "";
|
|
218
|
-
const tags = entry.tags || [];
|
|
219
|
-
const tagsStr = tags.length ? `\n**Tags:** ${tags.join(", ")}` : "";
|
|
220
|
-
|
|
221
|
-
lines.push(`## Session #${sessionNum} — ${ts}\n`);
|
|
222
|
-
lines.push(`${note}${tagsStr}\n\n---\n`);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const content = lines.join("\n");
|
|
226
|
-
if (toStdout) {
|
|
227
|
-
console.log(content);
|
|
228
|
-
} else {
|
|
229
|
-
const exportPath = path.resolve("session_export.md");
|
|
230
|
-
fs.writeFileSync(exportPath, content, "utf8");
|
|
231
|
-
console.log(`${GREEN}✅ Exported ${history.length} sessions to${RESET} ${exportPath}`);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function main() {
|
|
236
|
-
const args = process.argv.slice(2);
|
|
237
|
-
if (!args.length) {
|
|
238
|
-
console.log(`Usage: node session_manager.js [save <note>|load|show|clear|status|tag <label>|list [--all]|export [--stdout]]`);
|
|
239
|
-
process.exit(1);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const cmd = args[0].toLowerCase();
|
|
243
|
-
|
|
244
|
-
if (!VALID_COMMANDS.has(cmd)) {
|
|
245
|
-
console.log(`${RED}Unknown command: '${cmd}'${RESET}`);
|
|
246
|
-
console.log(`Valid commands: ${[...VALID_COMMANDS].sort().join(', ')}`);
|
|
247
|
-
process.exit(1);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
if (cmd === "save") {
|
|
251
|
-
let note = args.slice(1).join(" ").trim();
|
|
252
|
-
if (!note) note = `session ${new Date().toISOString().slice(0,16).replace('T', ' ')}`;
|
|
253
|
-
cmdSave(note);
|
|
254
|
-
} else if (cmd === "load") {
|
|
255
|
-
cmdLoad();
|
|
256
|
-
} else if (cmd === "show") {
|
|
257
|
-
cmdShow();
|
|
258
|
-
} else if (cmd === "clear") {
|
|
259
|
-
cmdClear();
|
|
260
|
-
} else if (cmd === "status") {
|
|
261
|
-
cmdStatus();
|
|
262
|
-
} else if (cmd === "tag") {
|
|
263
|
-
const label = args.slice(1).join(" ").trim();
|
|
264
|
-
cmdTag(label);
|
|
265
|
-
} else if (cmd === "list") {
|
|
266
|
-
const showAll = args.includes("--all");
|
|
267
|
-
cmdList(showAll);
|
|
268
|
-
} else if (cmd === "export") {
|
|
269
|
-
const toStdout = args.includes("--stdout");
|
|
270
|
-
cmdExport(toStdout);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (require.main === module) {
|
|
275
|
-
main();
|
|
276
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* session_manager.js — Agent session state tracking for multi-conversation work.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node .agent/scripts/session_manager.js save "working on auth"
|
|
7
|
+
* node .agent/scripts/session_manager.js load
|
|
8
|
+
* node .agent/scripts/session_manager.js show
|
|
9
|
+
* node .agent/scripts/session_manager.js clear
|
|
10
|
+
* node .agent/scripts/session_manager.js status
|
|
11
|
+
* node .agent/scripts/session_manager.js tag <label>
|
|
12
|
+
* node .agent/scripts/session_manager.js list [--all]
|
|
13
|
+
* node .agent/scripts/session_manager.js export [--stdout]
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
'use strict';
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
const STATE_FILE = ".agent_session.json";
|
|
22
|
+
|
|
23
|
+
const GREEN = "\x1b[92m";
|
|
24
|
+
const YELLOW = "\x1b[93m";
|
|
25
|
+
const BLUE = "\x1b[94m";
|
|
26
|
+
const CYAN = "\x1b[96m";
|
|
27
|
+
const RED = "\x1b[91m";
|
|
28
|
+
const BOLD = "\x1b[1m";
|
|
29
|
+
const RESET = "\x1b[0m";
|
|
30
|
+
|
|
31
|
+
const VALID_COMMANDS = new Set(["save", "load", "show", "clear", "status", "tag", "list", "export"]);
|
|
32
|
+
const LIST_PAGE_SIZE = 10;
|
|
33
|
+
|
|
34
|
+
function loadState() {
|
|
35
|
+
if (!fs.existsSync(STATE_FILE)) return {};
|
|
36
|
+
try {
|
|
37
|
+
const content = fs.readFileSync(STATE_FILE, 'utf8');
|
|
38
|
+
return JSON.parse(content);
|
|
39
|
+
} catch {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function saveState(state) {
|
|
45
|
+
fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2), 'utf8');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function cmdSave(note) {
|
|
49
|
+
const state = loadState();
|
|
50
|
+
const entry = {
|
|
51
|
+
timestamp: new Date().toISOString(),
|
|
52
|
+
note: note,
|
|
53
|
+
session: (state.history || []).length + 1,
|
|
54
|
+
tags: []
|
|
55
|
+
};
|
|
56
|
+
if (!state.history) state.history = [];
|
|
57
|
+
state.history.push(entry);
|
|
58
|
+
state.current = entry;
|
|
59
|
+
saveState(state);
|
|
60
|
+
|
|
61
|
+
console.log(`${GREEN}✅ Session saved:${RESET} ${note}`);
|
|
62
|
+
console.log(` Time: ${entry.timestamp}`);
|
|
63
|
+
console.log(` Session: #${entry.session}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function cmdLoad() {
|
|
67
|
+
const state = loadState();
|
|
68
|
+
const current = state.current;
|
|
69
|
+
if (!current) {
|
|
70
|
+
console.log(`${YELLOW}No active session — use 'save' first.${RESET}`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const tagsStr = (current.tags || []).join(", ") || "none";
|
|
74
|
+
console.log(`${BOLD}Current session:${RESET}`);
|
|
75
|
+
console.log(` Session: #${current.session}`);
|
|
76
|
+
console.log(` Time: ${current.timestamp}`);
|
|
77
|
+
console.log(` Note: ${current.note}`);
|
|
78
|
+
console.log(` Tags: ${tagsStr}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function cmdShow() {
|
|
82
|
+
const state = loadState();
|
|
83
|
+
const history = state.history || [];
|
|
84
|
+
if (!history.length) {
|
|
85
|
+
console.log(`${YELLOW}No session history.${RESET}`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
console.log(`${BOLD}Session History (${history.length} total):${RESET}`);
|
|
89
|
+
const recent = history.slice(-10).reverse();
|
|
90
|
+
for (const entry of recent) {
|
|
91
|
+
const tagsStr = (entry.tags || []).join(", ") || "";
|
|
92
|
+
const tagsDisplay = tagsStr ? ` [${tagsStr}]` : "";
|
|
93
|
+
console.log(`\n ${BLUE}#${entry.session}${RESET} — ${entry.timestamp.slice(0, 16)}${tagsDisplay}`);
|
|
94
|
+
console.log(` ${entry.note}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function cmdClear() {
|
|
99
|
+
if (fs.existsSync(STATE_FILE)) {
|
|
100
|
+
fs.unlinkSync(STATE_FILE);
|
|
101
|
+
console.log(`${GREEN}✅ Session state cleared.${RESET}`);
|
|
102
|
+
} else {
|
|
103
|
+
console.log(`${YELLOW}No session file found — nothing to clear.${RESET}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function cmdStatus() {
|
|
108
|
+
const state = loadState();
|
|
109
|
+
const history = state.history || [];
|
|
110
|
+
const current = state.current;
|
|
111
|
+
|
|
112
|
+
if (!history.length) {
|
|
113
|
+
console.log(`${YELLOW}No session history — use 'save' to start tracking.${RESET}`);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const total = history.length;
|
|
118
|
+
const recent = history.slice(-3).reverse();
|
|
119
|
+
|
|
120
|
+
console.log(`\n${BOLD}${CYAN}━━━ Session Status ━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
|
|
121
|
+
console.log(` Total sessions: ${total}`);
|
|
122
|
+
if (current) {
|
|
123
|
+
console.log(` Active: #${current.session} — ${current.note.slice(0, 60)}`);
|
|
124
|
+
}
|
|
125
|
+
console.log(`\n${BOLD} Last 3 sessions:${RESET}`);
|
|
126
|
+
for (const entry of recent) {
|
|
127
|
+
const tagsStr = (entry.tags || []).join(", ") || "";
|
|
128
|
+
const tagsDisplay = tagsStr ? ` [${tagsStr}]` : "";
|
|
129
|
+
const ts = entry.timestamp.slice(0, 16);
|
|
130
|
+
console.log(` ${BLUE}#${entry.session}${RESET} ${ts}${tagsDisplay}`);
|
|
131
|
+
console.log(` ${entry.note.slice(0, 70)}`);
|
|
132
|
+
}
|
|
133
|
+
console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function cmdTag(label) {
|
|
137
|
+
if (!label) {
|
|
138
|
+
console.log(`${RED}Error: provide a tag label. Example: node session_manager.js tag v2-feature${RESET}`);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
const state = loadState();
|
|
142
|
+
const current = state.current;
|
|
143
|
+
if (!current) {
|
|
144
|
+
console.log(`${YELLOW}No active session — use 'save' first before tagging.${RESET}`);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
if (!current.tags) current.tags = [];
|
|
148
|
+
if (current.tags.includes(label)) {
|
|
149
|
+
console.log(`${YELLOW}Tag '${label}' already exists on session #${current.session}.${RESET}`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
current.tags.push(label);
|
|
154
|
+
state.current = current;
|
|
155
|
+
|
|
156
|
+
if (state.history) {
|
|
157
|
+
for (const entry of state.history) {
|
|
158
|
+
if (entry.session === current.session) {
|
|
159
|
+
if (!entry.tags) entry.tags = [];
|
|
160
|
+
if (!entry.tags.includes(label)) {
|
|
161
|
+
entry.tags.push(label);
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
saveState(state);
|
|
169
|
+
console.log(`${GREEN}✅ Tagged session #${current.session} with '${label}'.${RESET}`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function cmdList(showAll) {
|
|
173
|
+
const state = loadState();
|
|
174
|
+
const history = state.history || [];
|
|
175
|
+
if (!history.length) {
|
|
176
|
+
console.log(`${YELLOW}No session history.${RESET}`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const total = history.length;
|
|
181
|
+
const pageSize = showAll ? total : LIST_PAGE_SIZE;
|
|
182
|
+
const recent = history.slice().reverse().slice(0, pageSize);
|
|
183
|
+
|
|
184
|
+
console.log(`\n${BOLD}${CYAN}━━━ Session List (${total} total, showing ${recent.length}) ━━━━━━━${RESET}`);
|
|
185
|
+
|
|
186
|
+
for (const entry of recent) {
|
|
187
|
+
const tagsStr = (entry.tags || []).join(", ");
|
|
188
|
+
const tagsDisplay = tagsStr ? ` [${YELLOW}${tagsStr}${RESET}]` : "";
|
|
189
|
+
const ts = entry.timestamp.slice(0, 16);
|
|
190
|
+
console.log(`\n ${BOLD}${BLUE}#${entry.session}${RESET} — ${ts}${tagsDisplay}`);
|
|
191
|
+
console.log(` ${entry.note}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!showAll && total > pageSize) {
|
|
195
|
+
const remaining = total - pageSize;
|
|
196
|
+
console.log(`\n ${YELLOW}... ${remaining} older session(s) not shown. Use '--all' to see all.${RESET}`);
|
|
197
|
+
}
|
|
198
|
+
console.log(`${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function cmdExport(toStdout) {
|
|
202
|
+
const state = loadState();
|
|
203
|
+
const history = state.history || [];
|
|
204
|
+
if (!history.length) {
|
|
205
|
+
console.log(`${YELLOW}No session history to export.${RESET}`);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const lines = ["# Session Export\n"];
|
|
210
|
+
lines.push(`Generated: ${new Date().toISOString().slice(0, 16)}\n`);
|
|
211
|
+
lines.push(`Total sessions: ${history.length}\n\n---\n`);
|
|
212
|
+
|
|
213
|
+
const reversed = history.slice().reverse();
|
|
214
|
+
for (const entry of reversed) {
|
|
215
|
+
const sessionNum = entry.session || "?";
|
|
216
|
+
const ts = (entry.timestamp || "").slice(0, 16);
|
|
217
|
+
const note = entry.note || "";
|
|
218
|
+
const tags = entry.tags || [];
|
|
219
|
+
const tagsStr = tags.length ? `\n**Tags:** ${tags.join(", ")}` : "";
|
|
220
|
+
|
|
221
|
+
lines.push(`## Session #${sessionNum} — ${ts}\n`);
|
|
222
|
+
lines.push(`${note}${tagsStr}\n\n---\n`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const content = lines.join("\n");
|
|
226
|
+
if (toStdout) {
|
|
227
|
+
console.log(content);
|
|
228
|
+
} else {
|
|
229
|
+
const exportPath = path.resolve("session_export.md");
|
|
230
|
+
fs.writeFileSync(exportPath, content, "utf8");
|
|
231
|
+
console.log(`${GREEN}✅ Exported ${history.length} sessions to${RESET} ${exportPath}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function main() {
|
|
236
|
+
const args = process.argv.slice(2);
|
|
237
|
+
if (!args.length) {
|
|
238
|
+
console.log(`Usage: node session_manager.js [save <note>|load|show|clear|status|tag <label>|list [--all]|export [--stdout]]`);
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const cmd = args[0].toLowerCase();
|
|
243
|
+
|
|
244
|
+
if (!VALID_COMMANDS.has(cmd)) {
|
|
245
|
+
console.log(`${RED}Unknown command: '${cmd}'${RESET}`);
|
|
246
|
+
console.log(`Valid commands: ${[...VALID_COMMANDS].sort().join(', ')}`);
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (cmd === "save") {
|
|
251
|
+
let note = args.slice(1).join(" ").trim();
|
|
252
|
+
if (!note) note = `session ${new Date().toISOString().slice(0,16).replace('T', ' ')}`;
|
|
253
|
+
cmdSave(note);
|
|
254
|
+
} else if (cmd === "load") {
|
|
255
|
+
cmdLoad();
|
|
256
|
+
} else if (cmd === "show") {
|
|
257
|
+
cmdShow();
|
|
258
|
+
} else if (cmd === "clear") {
|
|
259
|
+
cmdClear();
|
|
260
|
+
} else if (cmd === "status") {
|
|
261
|
+
cmdStatus();
|
|
262
|
+
} else if (cmd === "tag") {
|
|
263
|
+
const label = args.slice(1).join(" ").trim();
|
|
264
|
+
cmdTag(label);
|
|
265
|
+
} else if (cmd === "list") {
|
|
266
|
+
const showAll = args.includes("--all");
|
|
267
|
+
cmdList(showAll);
|
|
268
|
+
} else if (cmd === "export") {
|
|
269
|
+
const toStdout = args.includes("--stdout");
|
|
270
|
+
cmdExport(toStdout);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (require.main === module) {
|
|
275
|
+
main();
|
|
276
|
+
}
|