specweave 1.0.569 → 1.0.571
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/bin/specweave.js +83 -0
- package/dist/src/cli/commands/analytics-push.d.ts +27 -0
- package/dist/src/cli/commands/analytics-push.d.ts.map +1 -0
- package/dist/src/cli/commands/analytics-push.js +74 -0
- package/dist/src/cli/commands/analytics-push.js.map +1 -0
- package/dist/src/cli/commands/session.d.ts +34 -0
- package/dist/src/cli/commands/session.d.ts.map +1 -0
- package/dist/src/cli/commands/session.js +142 -0
- package/dist/src/cli/commands/session.js.map +1 -0
- package/dist/src/cli/commands/sync-flush.d.ts +31 -0
- package/dist/src/cli/commands/sync-flush.d.ts.map +1 -0
- package/dist/src/cli/commands/sync-flush.js +114 -0
- package/dist/src/cli/commands/sync-flush.js.map +1 -0
- package/dist/src/core/analytics/event-writer.d.ts +33 -0
- package/dist/src/core/analytics/event-writer.d.ts.map +1 -0
- package/dist/src/core/analytics/event-writer.js +63 -0
- package/dist/src/core/analytics/event-writer.js.map +1 -0
- package/dist/src/core/hooks/handlers/hook-router.d.ts +1 -1
- package/dist/src/core/hooks/handlers/hook-router.d.ts.map +1 -1
- package/dist/src/core/hooks/handlers/hook-router.js +7 -10
- package/dist/src/core/hooks/handlers/hook-router.js.map +1 -1
- package/dist/src/core/hooks/handlers/pre-tool-use.d.ts.map +1 -1
- package/dist/src/core/hooks/handlers/pre-tool-use.js +23 -17
- package/dist/src/core/hooks/handlers/pre-tool-use.js.map +1 -1
- package/dist/src/core/hooks/handlers/types.d.ts +1 -1
- package/dist/src/core/hooks/handlers/types.d.ts.map +1 -1
- package/dist/src/core/hooks/handlers/types.js +0 -7
- package/dist/src/core/hooks/handlers/types.js.map +1 -1
- package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts.map +1 -1
- package/dist/src/core/hooks/handlers/user-prompt-submit.js +21 -14
- package/dist/src/core/hooks/handlers/user-prompt-submit.js.map +1 -1
- package/dist/src/core/session/auto-scanner.d.ts +37 -0
- package/dist/src/core/session/auto-scanner.d.ts.map +1 -0
- package/dist/src/core/{hooks/handlers/stop-auto.js → session/auto-scanner.js} +33 -43
- package/dist/src/core/session/auto-scanner.js.map +1 -0
- package/dist/src/core/session/reflect-checker.d.ts +19 -0
- package/dist/src/core/session/reflect-checker.d.ts.map +1 -0
- package/dist/src/core/session/reflect-checker.js +30 -0
- package/dist/src/core/session/reflect-checker.js.map +1 -0
- package/dist/src/core/session/session-lifecycle.d.ts +44 -0
- package/dist/src/core/session/session-lifecycle.d.ts.map +1 -0
- package/dist/src/core/{hooks/handlers/session-start.js → session/session-lifecycle.js} +71 -32
- package/dist/src/core/session/session-lifecycle.js.map +1 -0
- package/dist/src/core/sync/event-queue-ops.d.ts +39 -0
- package/dist/src/core/sync/event-queue-ops.d.ts.map +1 -0
- package/dist/src/core/sync/event-queue-ops.js +109 -0
- package/dist/src/core/sync/event-queue-ops.js.map +1 -0
- package/dist/src/hooks/generate-settings.d.ts.map +1 -1
- package/dist/src/hooks/generate-settings.js +12 -13
- package/dist/src/hooks/generate-settings.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts +0 -11
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts.map +0 -1
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.js +0 -75
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.js.map +0 -1
- package/dist/src/core/hooks/handlers/post-tool-use.d.ts +0 -11
- package/dist/src/core/hooks/handlers/post-tool-use.d.ts.map +0 -1
- package/dist/src/core/hooks/handlers/post-tool-use.js +0 -76
- package/dist/src/core/hooks/handlers/post-tool-use.js.map +0 -1
- package/dist/src/core/hooks/handlers/pre-compact.d.ts +0 -11
- package/dist/src/core/hooks/handlers/pre-compact.d.ts.map +0 -1
- package/dist/src/core/hooks/handlers/pre-compact.js +0 -77
- package/dist/src/core/hooks/handlers/pre-compact.js.map +0 -1
- package/dist/src/core/hooks/handlers/session-start.d.ts +0 -9
- package/dist/src/core/hooks/handlers/session-start.d.ts.map +0 -1
- package/dist/src/core/hooks/handlers/session-start.js.map +0 -1
- package/dist/src/core/hooks/handlers/stop-auto.d.ts +0 -16
- package/dist/src/core/hooks/handlers/stop-auto.d.ts.map +0 -1
- package/dist/src/core/hooks/handlers/stop-auto.js.map +0 -1
- package/dist/src/core/hooks/handlers/stop-reflect.d.ts +0 -14
- package/dist/src/core/hooks/handlers/stop-reflect.d.ts.map +0 -1
- package/dist/src/core/hooks/handlers/stop-reflect.js +0 -43
- package/dist/src/core/hooks/handlers/stop-reflect.js.map +0 -1
- package/dist/src/core/hooks/handlers/stop-sync.d.ts +0 -15
- package/dist/src/core/hooks/handlers/stop-sync.d.ts.map +0 -1
- package/dist/src/core/hooks/handlers/stop-sync.js +0 -68
- package/dist/src/core/hooks/handlers/stop-sync.js.map +0 -1
package/bin/specweave.js
CHANGED
|
@@ -857,6 +857,28 @@ program
|
|
|
857
857
|
});
|
|
858
858
|
});
|
|
859
859
|
|
|
860
|
+
// Analytics push command - Record analytics events (replaces PostToolUse analytics hook)
|
|
861
|
+
program
|
|
862
|
+
.command('analytics-push')
|
|
863
|
+
.description('Record a skill or agent analytics event (replaces PostToolUse analytics hook)')
|
|
864
|
+
.requiredOption('--type <type>', 'Event type: skill or agent')
|
|
865
|
+
.requiredOption('--name <name>', 'Skill or agent name')
|
|
866
|
+
.option('--plugin <plugin>', 'Source plugin name')
|
|
867
|
+
.option('--json', 'Output as JSON')
|
|
868
|
+
.option('--silent', 'Suppress output')
|
|
869
|
+
.action(async (options) => {
|
|
870
|
+
const { analyticsPushCommand } = await import('../dist/src/cli/commands/analytics-push.js');
|
|
871
|
+
const result = await analyticsPushCommand({
|
|
872
|
+
projectRoot: process.cwd(),
|
|
873
|
+
type: options.type,
|
|
874
|
+
name: options.name,
|
|
875
|
+
plugin: options.plugin,
|
|
876
|
+
json: options.json,
|
|
877
|
+
silent: options.silent,
|
|
878
|
+
});
|
|
879
|
+
if (!result.success) process.exit(1);
|
|
880
|
+
});
|
|
881
|
+
|
|
860
882
|
// LSP command - Code intelligence operations
|
|
861
883
|
const lspCmd = program
|
|
862
884
|
.command('lsp')
|
|
@@ -945,6 +967,30 @@ program
|
|
|
945
967
|
await commitsCommand();
|
|
946
968
|
});
|
|
947
969
|
|
|
970
|
+
// Sync flush command - Flush or queue sync events (replaces PostToolUse/stop-sync hooks)
|
|
971
|
+
const syncFlushCmd = program
|
|
972
|
+
.command('sync')
|
|
973
|
+
.description('Sync operations');
|
|
974
|
+
|
|
975
|
+
syncFlushCmd
|
|
976
|
+
.command('flush')
|
|
977
|
+
.description('Flush pending sync events or queue new ones (replaces PostToolUse hook)')
|
|
978
|
+
.option('--queue <json>', 'Queue a new event instead of flushing')
|
|
979
|
+
.option('--dry-run', 'Report what would be flushed without clearing')
|
|
980
|
+
.option('--json', 'Output as JSON')
|
|
981
|
+
.option('--silent', 'Suppress output')
|
|
982
|
+
.action(async (options) => {
|
|
983
|
+
const { syncFlushCommand } = await import('../dist/src/cli/commands/sync-flush.js');
|
|
984
|
+
const result = await syncFlushCommand({
|
|
985
|
+
projectRoot: process.cwd(),
|
|
986
|
+
queue: options.queue,
|
|
987
|
+
dryRun: options.dryRun,
|
|
988
|
+
json: options.json,
|
|
989
|
+
silent: options.silent,
|
|
990
|
+
});
|
|
991
|
+
if (!result.success) process.exit(1);
|
|
992
|
+
});
|
|
993
|
+
|
|
948
994
|
// Sync-scheduled command - Execute due scheduled sync jobs (for cron/CI)
|
|
949
995
|
program
|
|
950
996
|
.command('sync-scheduled')
|
|
@@ -1244,6 +1290,43 @@ program
|
|
|
1244
1290
|
}
|
|
1245
1291
|
});
|
|
1246
1292
|
|
|
1293
|
+
// Session command - Session lifecycle management (replaces SessionStart/Stop hooks)
|
|
1294
|
+
const sessionCmd = program
|
|
1295
|
+
.command('session')
|
|
1296
|
+
.description('Session lifecycle management (start, end)');
|
|
1297
|
+
|
|
1298
|
+
sessionCmd
|
|
1299
|
+
.command('start')
|
|
1300
|
+
.description('Initialize session (replaces SessionStart hook)')
|
|
1301
|
+
.option('--session-id <id>', 'Session identifier for isolated state')
|
|
1302
|
+
.option('--json', 'Output as JSON')
|
|
1303
|
+
.option('--silent', 'Suppress output')
|
|
1304
|
+
.action(async (options) => {
|
|
1305
|
+
const { sessionStartCommand } = await import('../dist/src/cli/commands/session.js');
|
|
1306
|
+
const result = await sessionStartCommand({
|
|
1307
|
+
projectRoot: process.cwd(),
|
|
1308
|
+
sessionId: options.sessionId,
|
|
1309
|
+
json: options.json,
|
|
1310
|
+
silent: options.silent,
|
|
1311
|
+
});
|
|
1312
|
+
if (!result.success) process.exit(1);
|
|
1313
|
+
});
|
|
1314
|
+
|
|
1315
|
+
sessionCmd
|
|
1316
|
+
.command('end')
|
|
1317
|
+
.description('End session: reflect check, auto scan, sync flush (replaces Stop hooks)')
|
|
1318
|
+
.option('--json', 'Output as JSON')
|
|
1319
|
+
.option('--silent', 'Suppress output')
|
|
1320
|
+
.action(async (options) => {
|
|
1321
|
+
const { sessionEndCommand } = await import('../dist/src/cli/commands/session.js');
|
|
1322
|
+
const result = await sessionEndCommand({
|
|
1323
|
+
projectRoot: process.cwd(),
|
|
1324
|
+
json: options.json,
|
|
1325
|
+
silent: options.silent,
|
|
1326
|
+
});
|
|
1327
|
+
if (!result.success) process.exit(1);
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1247
1330
|
// Hook command - CLI delegation entry point for Claude Code hooks (internal)
|
|
1248
1331
|
program
|
|
1249
1332
|
.command('hook <event-type>')
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics push CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Replaces PostToolUse analytics hook with explicit CLI invocation.
|
|
5
|
+
*
|
|
6
|
+
* specweave analytics push --type skill --name sw:pm
|
|
7
|
+
* specweave analytics push --type agent --name general
|
|
8
|
+
*
|
|
9
|
+
* @module cli/commands/analytics-push
|
|
10
|
+
*/
|
|
11
|
+
export interface AnalyticsPushResult {
|
|
12
|
+
success: boolean;
|
|
13
|
+
eventsWritten: number;
|
|
14
|
+
}
|
|
15
|
+
export interface AnalyticsPushOptions {
|
|
16
|
+
type?: 'skill' | 'agent';
|
|
17
|
+
name?: string;
|
|
18
|
+
plugin?: string;
|
|
19
|
+
projectRoot?: string;
|
|
20
|
+
json?: boolean;
|
|
21
|
+
silent?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Execute `specweave analytics push`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function analyticsPushCommand(options?: AnalyticsPushOptions): Promise<AnalyticsPushResult>;
|
|
27
|
+
//# sourceMappingURL=analytics-push.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-push.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/analytics-push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AASD;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAgD9B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics push CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Replaces PostToolUse analytics hook with explicit CLI invocation.
|
|
5
|
+
*
|
|
6
|
+
* specweave analytics push --type skill --name sw:pm
|
|
7
|
+
* specweave analytics push --type agent --name general
|
|
8
|
+
*
|
|
9
|
+
* @module cli/commands/analytics-push
|
|
10
|
+
*/
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import { writeSkillEvent, writeAgentEvent, } from '../../core/analytics/event-writer.js';
|
|
14
|
+
function resolveProjectRoot(provided) {
|
|
15
|
+
const root = provided ?? process.cwd();
|
|
16
|
+
const configPath = path.join(root, '.specweave', 'config.json');
|
|
17
|
+
if (!fs.existsSync(configPath))
|
|
18
|
+
return null;
|
|
19
|
+
return root;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Execute `specweave analytics push`.
|
|
23
|
+
*/
|
|
24
|
+
export async function analyticsPushCommand(options = {}) {
|
|
25
|
+
// Validate required flags
|
|
26
|
+
if (!options.type) {
|
|
27
|
+
if (!options.silent)
|
|
28
|
+
console.error('Missing required flag: --type <skill|agent>');
|
|
29
|
+
return { success: false, eventsWritten: 0 };
|
|
30
|
+
}
|
|
31
|
+
if (!options.name) {
|
|
32
|
+
if (!options.silent)
|
|
33
|
+
console.error('Missing required flag: --name <string>');
|
|
34
|
+
return { success: false, eventsWritten: 0 };
|
|
35
|
+
}
|
|
36
|
+
if (options.type !== 'skill' && options.type !== 'agent') {
|
|
37
|
+
if (!options.silent)
|
|
38
|
+
console.error('--type must be "skill" or "agent"');
|
|
39
|
+
return { success: false, eventsWritten: 0 };
|
|
40
|
+
}
|
|
41
|
+
const projectRoot = resolveProjectRoot(options.projectRoot);
|
|
42
|
+
if (!projectRoot) {
|
|
43
|
+
const msg = 'Not a SpecWeave project (no .specweave/config.json found)';
|
|
44
|
+
if (!options.silent)
|
|
45
|
+
console.error(msg);
|
|
46
|
+
return { success: false, eventsWritten: 0 };
|
|
47
|
+
}
|
|
48
|
+
const analyticsDir = path.join(projectRoot, '.specweave', 'state', 'analytics');
|
|
49
|
+
const timestamp = new Date().toISOString();
|
|
50
|
+
let writeResult;
|
|
51
|
+
if (options.type === 'skill') {
|
|
52
|
+
writeResult = writeSkillEvent(analyticsDir, options.name, options.plugin, timestamp);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
writeResult = writeAgentEvent(analyticsDir, options.name, timestamp);
|
|
56
|
+
}
|
|
57
|
+
const result = {
|
|
58
|
+
success: writeResult.written > 0,
|
|
59
|
+
eventsWritten: writeResult.written,
|
|
60
|
+
};
|
|
61
|
+
if (!options.silent) {
|
|
62
|
+
if (options.json) {
|
|
63
|
+
console.log(JSON.stringify(result, null, 2));
|
|
64
|
+
}
|
|
65
|
+
else if (result.success) {
|
|
66
|
+
console.log(`Recorded ${options.type} event: ${options.name}`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
console.error('Failed to write analytics event');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=analytics-push.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-push.js","sourceRoot":"","sources":["../../../../src/cli/commands/analytics-push.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session lifecycle CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Replaces SessionStart and Stop hooks with explicit CLI subcommands:
|
|
5
|
+
* specweave session start — session initialization
|
|
6
|
+
* specweave session end — session cleanup (reflect + auto + sync flush)
|
|
7
|
+
*
|
|
8
|
+
* @module cli/commands/session
|
|
9
|
+
*/
|
|
10
|
+
export interface SessionCommandResult {
|
|
11
|
+
success: boolean;
|
|
12
|
+
action: 'start' | 'end';
|
|
13
|
+
details: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface SessionStartOptions {
|
|
16
|
+
projectRoot?: string;
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
silent?: boolean;
|
|
19
|
+
json?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface SessionEndOptions {
|
|
22
|
+
projectRoot?: string;
|
|
23
|
+
silent?: boolean;
|
|
24
|
+
json?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Execute `specweave session start`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function sessionStartCommand(options?: SessionStartOptions): Promise<SessionCommandResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Execute `specweave session end`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function sessionEndCommand(options?: SessionEndOptions): Promise<SessionCommandResult>;
|
|
34
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAeH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,KAAK,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AASD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,oBAAoB,CAAC,CA0D/B;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,oBAAoB,CAAC,CAuD/B"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session lifecycle CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Replaces SessionStart and Stop hooks with explicit CLI subcommands:
|
|
5
|
+
* specweave session start — session initialization
|
|
6
|
+
* specweave session end — session cleanup (reflect + auto + sync flush)
|
|
7
|
+
*
|
|
8
|
+
* @module cli/commands/session
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from 'fs';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import { clearStaleAutoFiles, resetPressureFiles, writeBaselineHealth, cleanOrphaned, } from '../../core/session/session-lifecycle.js';
|
|
13
|
+
import { checkReflectConfig } from '../../core/session/reflect-checker.js';
|
|
14
|
+
import { scanAutoSession } from '../../core/session/auto-scanner.js';
|
|
15
|
+
import { flushEventQueue } from '../../core/sync/event-queue-ops.js';
|
|
16
|
+
import { createSessionDir } from '../../core/session/session-state-manager.js';
|
|
17
|
+
function resolveProjectRoot(provided) {
|
|
18
|
+
const root = provided ?? process.cwd();
|
|
19
|
+
const configPath = path.join(root, '.specweave', 'config.json');
|
|
20
|
+
if (!fs.existsSync(configPath))
|
|
21
|
+
return null;
|
|
22
|
+
return root;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Execute `specweave session start`.
|
|
26
|
+
*/
|
|
27
|
+
export async function sessionStartCommand(options = {}) {
|
|
28
|
+
const projectRoot = resolveProjectRoot(options.projectRoot);
|
|
29
|
+
if (!projectRoot) {
|
|
30
|
+
const msg = 'Not a SpecWeave project (no .specweave/config.json found)';
|
|
31
|
+
if (!options.silent)
|
|
32
|
+
console.error(msg);
|
|
33
|
+
return { success: false, action: 'start', details: { error: msg } };
|
|
34
|
+
}
|
|
35
|
+
const stateDir = path.join(projectRoot, '.specweave', 'state');
|
|
36
|
+
const timestamp = new Date().toISOString();
|
|
37
|
+
try {
|
|
38
|
+
fs.mkdirSync(stateDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return { success: false, action: 'start', details: { error: 'Cannot create state directory' } };
|
|
42
|
+
}
|
|
43
|
+
const details = {};
|
|
44
|
+
// 1. Clear stale auto files
|
|
45
|
+
details.staleFilesCleaned = clearStaleAutoFiles(stateDir);
|
|
46
|
+
// 2. Reset pressure files
|
|
47
|
+
details.pressureReset = resetPressureFiles(stateDir);
|
|
48
|
+
// 3. Baseline health check
|
|
49
|
+
const health = writeBaselineHealth(projectRoot, stateDir, timestamp);
|
|
50
|
+
details.healthWritten = health !== null;
|
|
51
|
+
if (health)
|
|
52
|
+
details.warningLevel = health.warningLevel;
|
|
53
|
+
// 4. Session directory
|
|
54
|
+
if (options.sessionId) {
|
|
55
|
+
try {
|
|
56
|
+
createSessionDir(options.sessionId, projectRoot);
|
|
57
|
+
details.sessionDirCreated = true;
|
|
58
|
+
details.sessionId = options.sessionId;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
details.sessionDirCreated = false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// 5. Clean orphaned state files
|
|
65
|
+
details.orphansCleaned = cleanOrphaned(stateDir);
|
|
66
|
+
const result = { success: true, action: 'start', details };
|
|
67
|
+
if (!options.silent) {
|
|
68
|
+
if (options.json) {
|
|
69
|
+
console.log(JSON.stringify(result, null, 2));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.log('Session started');
|
|
73
|
+
if (details.staleFilesCleaned)
|
|
74
|
+
console.log(` Cleaned ${details.staleFilesCleaned} stale auto-mode files`);
|
|
75
|
+
if (health)
|
|
76
|
+
console.log(` Prompt health: ${health.warningLevel} (baseline: ${health.baseline})`);
|
|
77
|
+
if (options.sessionId)
|
|
78
|
+
console.log(` Session ID: ${options.sessionId}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Execute `specweave session end`.
|
|
85
|
+
*/
|
|
86
|
+
export async function sessionEndCommand(options = {}) {
|
|
87
|
+
const projectRoot = resolveProjectRoot(options.projectRoot);
|
|
88
|
+
if (!projectRoot) {
|
|
89
|
+
const msg = 'Not a SpecWeave project (no .specweave/config.json found)';
|
|
90
|
+
if (!options.silent)
|
|
91
|
+
console.error(msg);
|
|
92
|
+
return { success: false, action: 'end', details: { error: msg } };
|
|
93
|
+
}
|
|
94
|
+
const stateDir = path.join(projectRoot, '.specweave', 'state');
|
|
95
|
+
const configPath = path.join(projectRoot, '.specweave', 'config.json');
|
|
96
|
+
const details = {};
|
|
97
|
+
// 1. Reflect check — errors do not abort other operations
|
|
98
|
+
try {
|
|
99
|
+
const reflectResult = checkReflectConfig(configPath);
|
|
100
|
+
details.reflect = reflectResult;
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
details.reflect = { error: String(err) };
|
|
104
|
+
}
|
|
105
|
+
// 2. Auto-mode scan — errors do not abort other operations
|
|
106
|
+
try {
|
|
107
|
+
const autoResult = scanAutoSession(stateDir, projectRoot, configPath);
|
|
108
|
+
details.auto = autoResult;
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
details.auto = { error: String(err) };
|
|
112
|
+
}
|
|
113
|
+
// 3. Event queue flush — errors do not abort other operations
|
|
114
|
+
try {
|
|
115
|
+
const flushResult = flushEventQueue(stateDir);
|
|
116
|
+
details.sync = flushResult;
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
details.sync = { error: String(err) };
|
|
120
|
+
}
|
|
121
|
+
const result = { success: true, action: 'end', details };
|
|
122
|
+
if (!options.silent) {
|
|
123
|
+
if (options.json) {
|
|
124
|
+
console.log(JSON.stringify(result, null, 2));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
console.log('Session ended');
|
|
128
|
+
const reflect = details.reflect;
|
|
129
|
+
if (reflect?.enabled)
|
|
130
|
+
console.log(' Reflection requested');
|
|
131
|
+
const auto = details.auto;
|
|
132
|
+
if (auto?.active && auto?.pendingTasks?.pending) {
|
|
133
|
+
console.log(` Auto-mode: ${auto.pendingTasks.pending} pending tasks`);
|
|
134
|
+
}
|
|
135
|
+
const sync = details.sync;
|
|
136
|
+
if (sync?.flushed)
|
|
137
|
+
console.log(` Flushed ${sync.flushed} unique increment(s)`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../../src/cli/commands/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync flush CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Replaces PostToolUse event queuing (--queue mode) and
|
|
5
|
+
* stop-sync event flushing (default mode).
|
|
6
|
+
*
|
|
7
|
+
* specweave sync flush — flush pending events
|
|
8
|
+
* specweave sync flush --queue JSON — append event to queue
|
|
9
|
+
* specweave sync flush --dry-run — report without clearing
|
|
10
|
+
*
|
|
11
|
+
* @module cli/commands/sync-flush
|
|
12
|
+
*/
|
|
13
|
+
export interface SyncFlushResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
mode: 'queue' | 'flush';
|
|
16
|
+
eventsQueued?: number;
|
|
17
|
+
eventsFlushed?: number;
|
|
18
|
+
incrementIds?: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface SyncFlushOptions {
|
|
21
|
+
queue?: string;
|
|
22
|
+
projectRoot?: string;
|
|
23
|
+
silent?: boolean;
|
|
24
|
+
json?: boolean;
|
|
25
|
+
dryRun?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Execute `specweave sync flush`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function syncFlushCommand(options?: SyncFlushOptions): Promise<SyncFlushResult>;
|
|
31
|
+
//# sourceMappingURL=sync-flush.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-flush.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/sync-flush.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AASD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CA2F1B"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync flush CLI command.
|
|
3
|
+
*
|
|
4
|
+
* Replaces PostToolUse event queuing (--queue mode) and
|
|
5
|
+
* stop-sync event flushing (default mode).
|
|
6
|
+
*
|
|
7
|
+
* specweave sync flush — flush pending events
|
|
8
|
+
* specweave sync flush --queue JSON — append event to queue
|
|
9
|
+
* specweave sync flush --dry-run — report without clearing
|
|
10
|
+
*
|
|
11
|
+
* @module cli/commands/sync-flush
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'fs';
|
|
14
|
+
import * as path from 'path';
|
|
15
|
+
import { queueEvent, flushEventQueue, readPendingEvents, } from '../../core/sync/event-queue-ops.js';
|
|
16
|
+
function resolveProjectRoot(provided) {
|
|
17
|
+
const root = provided ?? process.cwd();
|
|
18
|
+
const configPath = path.join(root, '.specweave', 'config.json');
|
|
19
|
+
if (!fs.existsSync(configPath))
|
|
20
|
+
return null;
|
|
21
|
+
return root;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Execute `specweave sync flush`.
|
|
25
|
+
*/
|
|
26
|
+
export async function syncFlushCommand(options = {}) {
|
|
27
|
+
const projectRoot = resolveProjectRoot(options.projectRoot);
|
|
28
|
+
if (!projectRoot) {
|
|
29
|
+
const msg = 'Not a SpecWeave project (no .specweave/config.json found)';
|
|
30
|
+
if (!options.silent)
|
|
31
|
+
console.error(msg);
|
|
32
|
+
return { success: false, mode: options.queue ? 'queue' : 'flush' };
|
|
33
|
+
}
|
|
34
|
+
const stateDir = path.join(projectRoot, '.specweave', 'state');
|
|
35
|
+
// Queue mode
|
|
36
|
+
if (options.queue) {
|
|
37
|
+
try {
|
|
38
|
+
const parsed = JSON.parse(options.queue);
|
|
39
|
+
const event = parsed.event ?? 'unknown';
|
|
40
|
+
const incrementId = parsed.incrementId ?? 'unknown';
|
|
41
|
+
const timestamp = parsed.timestamp ?? new Date().toISOString();
|
|
42
|
+
const data = parsed.data;
|
|
43
|
+
const qResult = queueEvent(stateDir, event, incrementId, timestamp, data);
|
|
44
|
+
const result = {
|
|
45
|
+
success: qResult.queued > 0,
|
|
46
|
+
mode: 'queue',
|
|
47
|
+
eventsQueued: qResult.queued,
|
|
48
|
+
};
|
|
49
|
+
if (!options.silent) {
|
|
50
|
+
if (options.json) {
|
|
51
|
+
console.log(JSON.stringify(result, null, 2));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
console.log(`Queued event: ${event} for increment ${incrementId}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
const msg = 'Invalid JSON in --queue argument';
|
|
61
|
+
if (!options.silent)
|
|
62
|
+
console.error(msg);
|
|
63
|
+
return { success: false, mode: 'queue', eventsQueued: 0 };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Dry-run mode
|
|
67
|
+
if (options.dryRun) {
|
|
68
|
+
const events = readPendingEvents(stateDir);
|
|
69
|
+
const uniqueIds = [...new Set(events.map((e) => e.incrementId).filter(Boolean))];
|
|
70
|
+
const result = {
|
|
71
|
+
success: true,
|
|
72
|
+
mode: 'flush',
|
|
73
|
+
eventsFlushed: uniqueIds.length,
|
|
74
|
+
incrementIds: uniqueIds,
|
|
75
|
+
};
|
|
76
|
+
if (!options.silent) {
|
|
77
|
+
if (options.json) {
|
|
78
|
+
console.log(JSON.stringify(result, null, 2));
|
|
79
|
+
}
|
|
80
|
+
else if (uniqueIds.length === 0) {
|
|
81
|
+
console.log('No pending events to flush');
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log(`Would flush ${uniqueIds.length} unique increment(s):`);
|
|
85
|
+
for (const id of uniqueIds)
|
|
86
|
+
console.log(` - ${id}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
// Flush mode (default)
|
|
92
|
+
const fResult = flushEventQueue(stateDir);
|
|
93
|
+
const result = {
|
|
94
|
+
success: true,
|
|
95
|
+
mode: 'flush',
|
|
96
|
+
eventsFlushed: fResult.flushed,
|
|
97
|
+
incrementIds: fResult.incrementIds,
|
|
98
|
+
};
|
|
99
|
+
if (!options.silent) {
|
|
100
|
+
if (options.json) {
|
|
101
|
+
console.log(JSON.stringify(result, null, 2));
|
|
102
|
+
}
|
|
103
|
+
else if (fResult.flushed === 0) {
|
|
104
|
+
console.log('No pending events to flush');
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
console.log(`Flushed ${fResult.flushed} unique increment(s):`);
|
|
108
|
+
for (const id of fResult.incrementIds)
|
|
109
|
+
console.log(` - ${id}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=sync-flush.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-flush.js","sourceRoot":"","sources":["../../../../src/cli/commands/sync-flush.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics event writer core module.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from hooks/handlers/post-tool-use-analytics.ts.
|
|
5
|
+
* Appends analytics events to events.jsonl.
|
|
6
|
+
*
|
|
7
|
+
* Never throws.
|
|
8
|
+
*
|
|
9
|
+
* @module core/analytics/event-writer
|
|
10
|
+
*/
|
|
11
|
+
import type { AnalyticsEvent } from './types.js';
|
|
12
|
+
export interface WriteResult {
|
|
13
|
+
written: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Extract plugin name from a skill name.
|
|
17
|
+
* "sw:pm" → "specweave", "frontend-design:component" → "frontend-design", "my-skill" → "specweave"
|
|
18
|
+
*/
|
|
19
|
+
export declare function extractPlugin(skillName: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Append an analytics event to events.jsonl.
|
|
22
|
+
* Creates the analytics directory if it does not exist.
|
|
23
|
+
*/
|
|
24
|
+
export declare function appendAnalyticsEvent(analyticsDir: string, event: AnalyticsEvent): WriteResult;
|
|
25
|
+
/**
|
|
26
|
+
* Build and append a skill analytics event.
|
|
27
|
+
*/
|
|
28
|
+
export declare function writeSkillEvent(analyticsDir: string, name: string, plugin?: string, timestamp?: string): WriteResult;
|
|
29
|
+
/**
|
|
30
|
+
* Build and append an agent analytics event.
|
|
31
|
+
*/
|
|
32
|
+
export declare function writeAgentEvent(analyticsDir: string, name: string, timestamp?: string): WriteResult;
|
|
33
|
+
//# sourceMappingURL=event-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-writer.d.ts","sourceRoot":"","sources":["../../../../src/core/analytics/event-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,cAAc,GACpB,WAAW,CAWb;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,WAAW,CASb;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,GACjB,WAAW,CASb"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics event writer core module.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from hooks/handlers/post-tool-use-analytics.ts.
|
|
5
|
+
* Appends analytics events to events.jsonl.
|
|
6
|
+
*
|
|
7
|
+
* Never throws.
|
|
8
|
+
*
|
|
9
|
+
* @module core/analytics/event-writer
|
|
10
|
+
*/
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
/**
|
|
14
|
+
* Extract plugin name from a skill name.
|
|
15
|
+
* "sw:pm" → "specweave", "frontend-design:component" → "frontend-design", "my-skill" → "specweave"
|
|
16
|
+
*/
|
|
17
|
+
export function extractPlugin(skillName) {
|
|
18
|
+
if (!skillName.includes(':'))
|
|
19
|
+
return 'specweave';
|
|
20
|
+
const prefix = skillName.split(':')[0];
|
|
21
|
+
return prefix === 'sw' ? 'specweave' : prefix;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Append an analytics event to events.jsonl.
|
|
25
|
+
* Creates the analytics directory if it does not exist.
|
|
26
|
+
*/
|
|
27
|
+
export function appendAnalyticsEvent(analyticsDir, event) {
|
|
28
|
+
try {
|
|
29
|
+
fs.mkdirSync(analyticsDir, { recursive: true });
|
|
30
|
+
fs.appendFileSync(path.join(analyticsDir, 'events.jsonl'), JSON.stringify(event) + '\n');
|
|
31
|
+
return { written: 1 };
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { written: 0 };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build and append a skill analytics event.
|
|
39
|
+
*/
|
|
40
|
+
export function writeSkillEvent(analyticsDir, name, plugin, timestamp) {
|
|
41
|
+
const event = {
|
|
42
|
+
timestamp: timestamp ?? new Date().toISOString(),
|
|
43
|
+
type: 'skill',
|
|
44
|
+
name,
|
|
45
|
+
success: true,
|
|
46
|
+
plugin: plugin ?? extractPlugin(name),
|
|
47
|
+
};
|
|
48
|
+
return appendAnalyticsEvent(analyticsDir, event);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build and append an agent analytics event.
|
|
52
|
+
*/
|
|
53
|
+
export function writeAgentEvent(analyticsDir, name, timestamp) {
|
|
54
|
+
const event = {
|
|
55
|
+
timestamp: timestamp ?? new Date().toISOString(),
|
|
56
|
+
type: 'agent',
|
|
57
|
+
name,
|
|
58
|
+
success: true,
|
|
59
|
+
plugin: 'specweave',
|
|
60
|
+
};
|
|
61
|
+
return appendAnalyticsEvent(analyticsDir, event);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=event-writer.js.map
|