pi-continuous-learning 0.4.0 → 0.5.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/README.md +35 -5
- package/dist/cli/analyze-logger.d.ts +63 -0
- package/dist/cli/analyze-logger.d.ts.map +1 -0
- package/dist/cli/analyze-logger.js +140 -0
- package/dist/cli/analyze-logger.js.map +1 -0
- package/dist/cli/analyze.js +126 -32
- package/dist/cli/analyze.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/analyze-logger.ts +209 -0
- package/src/cli/analyze.ts +173 -32
- package/src/config.ts +1 -0
- package/src/types.ts +1 -0
package/README.md
CHANGED
|
@@ -95,6 +95,32 @@ The script:
|
|
|
95
95
|
- **Global timeout:** The process exits after 5 minutes regardless of progress.
|
|
96
96
|
- **Stale lock detection:** If a previous run crashed, the lockfile is automatically cleaned up after 10 minutes or if the owning process is no longer alive.
|
|
97
97
|
|
|
98
|
+
### Logging
|
|
99
|
+
|
|
100
|
+
The analyzer writes structured JSON logs to `~/.pi/continuous-learning/analyzer.log` (configurable via `log_path` in config). Each run logs:
|
|
101
|
+
|
|
102
|
+
- **Run timing** - total duration and per-project duration
|
|
103
|
+
- **Token usage** - input, output, cache read/write, total
|
|
104
|
+
- **Cost** - USD cost per project and total
|
|
105
|
+
- **Instinct changes** - counts of created, updated, and deleted instincts
|
|
106
|
+
- **Skip reasons** - why projects were skipped (no new observations, below threshold, etc.)
|
|
107
|
+
- **Errors** - full error details with stack traces
|
|
108
|
+
|
|
109
|
+
Each log line is a JSON object, making it easy to parse with `jq`:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# View recent run summaries
|
|
113
|
+
cat ~/.pi/continuous-learning/analyzer.log | jq 'select(.event == "run_complete")'
|
|
114
|
+
|
|
115
|
+
# Check total cost over time
|
|
116
|
+
cat ~/.pi/continuous-learning/analyzer.log | jq 'select(.event == "run_complete") | .total_cost_usd'
|
|
117
|
+
|
|
118
|
+
# See which projects were processed
|
|
119
|
+
cat ~/.pi/continuous-learning/analyzer.log | jq 'select(.event == "project_complete") | {project: .project_name, duration_s: (.duration_ms/1000), cost: .cost_usd}'
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The log file auto-rotates at 10 MB (old content moved to `analyzer.log.old`). When the log file is not writable, output falls back to stderr.
|
|
123
|
+
|
|
98
124
|
### Setting up a schedule (macOS)
|
|
99
125
|
|
|
100
126
|
The recommended way to run the analyzer on a recurring schedule on macOS is with `launchd`, which persists across reboots and handles log rotation.
|
|
@@ -124,9 +150,9 @@ cat > ~/Library/LaunchAgents/com.pi-continuous-learning.analyze.plist << EOF
|
|
|
124
150
|
<key>StartInterval</key>
|
|
125
151
|
<integer>300</integer>
|
|
126
152
|
<key>StandardOutPath</key>
|
|
127
|
-
<string>/tmp/pi-cl-analyze.log</string>
|
|
153
|
+
<string>/tmp/pi-cl-analyze-stdout.log</string>
|
|
128
154
|
<key>StandardErrorPath</key>
|
|
129
|
-
<string>/tmp/pi-cl-analyze.log</string>
|
|
155
|
+
<string>/tmp/pi-cl-analyze-stderr.log</string>
|
|
130
156
|
<key>EnvironmentVariables</key>
|
|
131
157
|
<dict>
|
|
132
158
|
<key>PATH</key>
|
|
@@ -153,8 +179,11 @@ The analyzer will now run every 5 minutes (300 seconds) in the background, start
|
|
|
153
179
|
# Check if the job is loaded
|
|
154
180
|
launchctl list | grep pi-continuous-learning
|
|
155
181
|
|
|
156
|
-
# View recent
|
|
157
|
-
tail -
|
|
182
|
+
# View recent log entries (structured JSON)
|
|
183
|
+
tail -5 ~/.pi/continuous-learning/analyzer.log | jq .
|
|
184
|
+
|
|
185
|
+
# View stderr output (fallback only)
|
|
186
|
+
tail -20 /tmp/pi-cl-analyze-stderr.log
|
|
158
187
|
```
|
|
159
188
|
|
|
160
189
|
#### Disabling the schedule
|
|
@@ -186,7 +215,7 @@ Use cron:
|
|
|
186
215
|
crontab -e
|
|
187
216
|
|
|
188
217
|
# Add this line (runs every 5 minutes):
|
|
189
|
-
*/5 * * * * pi-cl-analyze >> /tmp/pi-cl-analyze.log
|
|
218
|
+
*/5 * * * * pi-cl-analyze 2>> /tmp/pi-cl-analyze-stderr.log
|
|
190
219
|
```
|
|
191
220
|
|
|
192
221
|
To disable, remove the line from `crontab -e`.
|
|
@@ -273,6 +302,7 @@ Only include the fields you want to change — missing fields use the defaults a
|
|
|
273
302
|
| `max_injection_chars` | 4000 | Character budget for the injection block (~1000 tokens) |
|
|
274
303
|
| `model` | `claude-haiku-4-5` | Model for the background analyzer (lightweight models recommended to minimize cost) |
|
|
275
304
|
| `timeout_seconds` | 120 | Per-project timeout for the analyzer LLM session |
|
|
305
|
+
| `log_path` | `~/.pi/continuous-learning/analyzer.log` | Path to the analyzer log file |
|
|
276
306
|
|
|
277
307
|
## Storage
|
|
278
308
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logging for the background analyzer CLI.
|
|
3
|
+
* Writes to a configurable log file (default: ~/.pi/continuous-learning/analyzer.log).
|
|
4
|
+
* Each line is a JSON object for easy parsing and grep-ability.
|
|
5
|
+
*
|
|
6
|
+
* Log levels: info, warn, error
|
|
7
|
+
* Never throws - all I/O failures fall back to stderr.
|
|
8
|
+
*/
|
|
9
|
+
export interface ProjectRunStats {
|
|
10
|
+
readonly project_id: string;
|
|
11
|
+
readonly project_name: string;
|
|
12
|
+
readonly duration_ms: number;
|
|
13
|
+
readonly observations_processed: number;
|
|
14
|
+
readonly observations_total: number;
|
|
15
|
+
readonly instincts_created: number;
|
|
16
|
+
readonly instincts_updated: number;
|
|
17
|
+
readonly instincts_deleted: number;
|
|
18
|
+
readonly tokens_input: number;
|
|
19
|
+
readonly tokens_output: number;
|
|
20
|
+
readonly tokens_cache_read: number;
|
|
21
|
+
readonly tokens_cache_write: number;
|
|
22
|
+
readonly tokens_total: number;
|
|
23
|
+
readonly cost_usd: number;
|
|
24
|
+
readonly model: string;
|
|
25
|
+
readonly skipped_reason?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface RunSummary {
|
|
28
|
+
readonly total_duration_ms: number;
|
|
29
|
+
readonly projects_processed: number;
|
|
30
|
+
readonly projects_skipped: number;
|
|
31
|
+
readonly projects_errored: number;
|
|
32
|
+
readonly projects_total: number;
|
|
33
|
+
readonly total_tokens: number;
|
|
34
|
+
readonly total_cost_usd: number;
|
|
35
|
+
readonly total_instincts_created: number;
|
|
36
|
+
readonly total_instincts_updated: number;
|
|
37
|
+
readonly total_instincts_deleted: number;
|
|
38
|
+
readonly project_stats: readonly ProjectRunStats[];
|
|
39
|
+
}
|
|
40
|
+
export declare class AnalyzeLogger {
|
|
41
|
+
private readonly logPath;
|
|
42
|
+
constructor(logPath?: string);
|
|
43
|
+
getLogPath(): string;
|
|
44
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
45
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
46
|
+
error(message: string, error?: unknown, data?: Record<string, unknown>): void;
|
|
47
|
+
/** Log the start of a full analyzer run */
|
|
48
|
+
runStart(projectCount: number): void;
|
|
49
|
+
/** Log that a project was skipped (with reason) */
|
|
50
|
+
projectSkipped(projectId: string, projectName: string, reason: string): void;
|
|
51
|
+
/** Log the start of a project analysis */
|
|
52
|
+
projectStart(projectId: string, projectName: string, newObservations: number, totalObservations: number): void;
|
|
53
|
+
/** Log per-project results after analysis completes */
|
|
54
|
+
projectComplete(stats: ProjectRunStats): void;
|
|
55
|
+
/** Log a project that errored during analysis */
|
|
56
|
+
projectError(projectId: string, projectName: string, error: unknown): void;
|
|
57
|
+
/** Log the full run summary */
|
|
58
|
+
runComplete(summary: RunSummary): void;
|
|
59
|
+
private ensureLogDir;
|
|
60
|
+
private write;
|
|
61
|
+
private rotateIfNeeded;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=analyze-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-logger.d.ts","sourceRoot":"","sources":["../../src/cli/analyze-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logging for the background analyzer CLI.
|
|
3
|
+
* Writes to a configurable log file (default: ~/.pi/continuous-learning/analyzer.log).
|
|
4
|
+
* Each line is a JSON object for easy parsing and grep-ability.
|
|
5
|
+
*
|
|
6
|
+
* Log levels: info, warn, error
|
|
7
|
+
* Never throws - all I/O failures fall back to stderr.
|
|
8
|
+
*/
|
|
9
|
+
import { appendFileSync, mkdirSync, renameSync, statSync } from "node:fs";
|
|
10
|
+
import { dirname } from "node:path";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { getBaseDir } from "../storage.js";
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Constants
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
const DEFAULT_LOG_FILENAME = "analyzer.log";
|
|
17
|
+
const MAX_LOG_SIZE_BYTES = 10 * 1024 * 1024; // 10 MB - rotate beyond this
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Logger
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
export class AnalyzeLogger {
|
|
22
|
+
logPath;
|
|
23
|
+
constructor(logPath) {
|
|
24
|
+
this.logPath = logPath ?? join(getBaseDir(), DEFAULT_LOG_FILENAME);
|
|
25
|
+
this.ensureLogDir();
|
|
26
|
+
}
|
|
27
|
+
getLogPath() {
|
|
28
|
+
return this.logPath;
|
|
29
|
+
}
|
|
30
|
+
info(message, data) {
|
|
31
|
+
this.write("info", message, data);
|
|
32
|
+
}
|
|
33
|
+
warn(message, data) {
|
|
34
|
+
this.write("warn", message, data);
|
|
35
|
+
}
|
|
36
|
+
error(message, error, data) {
|
|
37
|
+
const errorData = { ...data };
|
|
38
|
+
if (error instanceof Error) {
|
|
39
|
+
errorData.error_message = error.message;
|
|
40
|
+
errorData.error_stack = error.stack;
|
|
41
|
+
}
|
|
42
|
+
else if (error !== undefined) {
|
|
43
|
+
errorData.error_message = String(error);
|
|
44
|
+
}
|
|
45
|
+
this.write("error", message, errorData);
|
|
46
|
+
}
|
|
47
|
+
/** Log the start of a full analyzer run */
|
|
48
|
+
runStart(projectCount) {
|
|
49
|
+
this.info("Analyzer run started", {
|
|
50
|
+
event: "run_start",
|
|
51
|
+
project_count: projectCount,
|
|
52
|
+
pid: process.pid,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/** Log that a project was skipped (with reason) */
|
|
56
|
+
projectSkipped(projectId, projectName, reason) {
|
|
57
|
+
this.info(`Skipped ${projectName}`, {
|
|
58
|
+
event: "project_skipped",
|
|
59
|
+
project_id: projectId,
|
|
60
|
+
project_name: projectName,
|
|
61
|
+
reason,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/** Log the start of a project analysis */
|
|
65
|
+
projectStart(projectId, projectName, newObservations, totalObservations) {
|
|
66
|
+
this.info(`Processing ${projectName}`, {
|
|
67
|
+
event: "project_start",
|
|
68
|
+
project_id: projectId,
|
|
69
|
+
project_name: projectName,
|
|
70
|
+
new_observations: newObservations,
|
|
71
|
+
total_observations: totalObservations,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/** Log per-project results after analysis completes */
|
|
75
|
+
projectComplete(stats) {
|
|
76
|
+
const durationSec = (stats.duration_ms / 1000).toFixed(1);
|
|
77
|
+
const costFormatted = stats.cost_usd.toFixed(4);
|
|
78
|
+
this.info(`Completed ${stats.project_name} in ${durationSec}s - ` +
|
|
79
|
+
`tokens: ${stats.tokens_total}, cost: $${costFormatted}, ` +
|
|
80
|
+
`instincts: +${stats.instincts_created} ~${stats.instincts_updated} -${stats.instincts_deleted}`, { event: "project_complete", ...stats });
|
|
81
|
+
}
|
|
82
|
+
/** Log a project that errored during analysis */
|
|
83
|
+
projectError(projectId, projectName, error) {
|
|
84
|
+
this.error(`Error processing ${projectName}`, error, {
|
|
85
|
+
event: "project_error",
|
|
86
|
+
project_id: projectId,
|
|
87
|
+
project_name: projectName,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/** Log the full run summary */
|
|
91
|
+
runComplete(summary) {
|
|
92
|
+
const durationSec = (summary.total_duration_ms / 1000).toFixed(1);
|
|
93
|
+
const costFormatted = summary.total_cost_usd.toFixed(4);
|
|
94
|
+
this.info(`Run complete in ${durationSec}s - ` +
|
|
95
|
+
`${summary.projects_processed}/${summary.projects_total} projects processed, ` +
|
|
96
|
+
`${summary.projects_skipped} skipped, ${summary.projects_errored} errored - ` +
|
|
97
|
+
`tokens: ${summary.total_tokens}, cost: $${costFormatted}, ` +
|
|
98
|
+
`instincts: +${summary.total_instincts_created} ~${summary.total_instincts_updated} -${summary.total_instincts_deleted}`, { event: "run_complete", ...summary });
|
|
99
|
+
}
|
|
100
|
+
// -------------------------------------------------------------------------
|
|
101
|
+
// Internal
|
|
102
|
+
// -------------------------------------------------------------------------
|
|
103
|
+
ensureLogDir() {
|
|
104
|
+
try {
|
|
105
|
+
mkdirSync(dirname(this.logPath), { recursive: true });
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Best effort
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
write(level, message, data) {
|
|
112
|
+
const entry = {
|
|
113
|
+
timestamp: new Date().toISOString(),
|
|
114
|
+
level,
|
|
115
|
+
message,
|
|
116
|
+
...data,
|
|
117
|
+
};
|
|
118
|
+
const line = JSON.stringify(entry) + "\n";
|
|
119
|
+
try {
|
|
120
|
+
this.rotateIfNeeded();
|
|
121
|
+
appendFileSync(this.logPath, line, "utf-8");
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Fall back to stderr - never lose log entries entirely
|
|
125
|
+
process.stderr.write(`[analyze] ${line}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
rotateIfNeeded() {
|
|
129
|
+
try {
|
|
130
|
+
const stat = statSync(this.logPath);
|
|
131
|
+
if (stat.size > MAX_LOG_SIZE_BYTES) {
|
|
132
|
+
renameSync(this.logPath, this.logPath + ".old");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// File doesn't exist yet or stat failed - fine
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=analyze-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-logger.js","sourceRoot":"","sources":["../../src/cli/analyze-logger.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/analyze.js
CHANGED
|
@@ -12,11 +12,12 @@ import { buildAnalyzerSystemPrompt } from "./analyze-prompt.js";
|
|
|
12
12
|
import { createInstinctListTool, createInstinctReadTool, createInstinctWriteTool, createInstinctDeleteTool, } from "../instinct-tools.js";
|
|
13
13
|
import { readAgentsMd } from "../agents-md.js";
|
|
14
14
|
import { homedir } from "node:os";
|
|
15
|
+
import { AnalyzeLogger } from "./analyze-logger.js";
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
16
|
-
// Lockfile guard
|
|
17
|
+
// Lockfile guard - ensures only one instance runs at a time
|
|
17
18
|
// ---------------------------------------------------------------------------
|
|
18
19
|
const LOCKFILE_NAME = "analyze.lock";
|
|
19
|
-
const LOCK_STALE_MS = 10 * 60 * 1000; // 10 minutes
|
|
20
|
+
const LOCK_STALE_MS = 10 * 60 * 1000; // 10 minutes - stale lock threshold
|
|
20
21
|
function getLockfilePath(baseDir) {
|
|
21
22
|
return join(baseDir, LOCKFILE_NAME);
|
|
22
23
|
}
|
|
@@ -33,14 +34,14 @@ function acquireLock(baseDir) {
|
|
|
33
34
|
if (age < LOCK_STALE_MS) {
|
|
34
35
|
return false; // Process alive and lock is fresh
|
|
35
36
|
}
|
|
36
|
-
// Process alive but lock is stale
|
|
37
|
+
// Process alive but lock is stale - treat as abandoned
|
|
37
38
|
}
|
|
38
39
|
catch {
|
|
39
|
-
// Process is dead
|
|
40
|
+
// Process is dead - lock is orphaned, safe to take over
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
catch {
|
|
43
|
-
// Malformed lockfile
|
|
44
|
+
// Malformed lockfile - remove and proceed
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
writeFileSync(lockPath, JSON.stringify({ pid: process.pid, started_at: new Date().toISOString() }), "utf-8");
|
|
@@ -53,19 +54,55 @@ function releaseLock(baseDir) {
|
|
|
53
54
|
unlinkSync(lockPath);
|
|
54
55
|
}
|
|
55
56
|
catch {
|
|
56
|
-
// Best effort
|
|
57
|
+
// Best effort - don't crash on cleanup
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
// ---------------------------------------------------------------------------
|
|
60
61
|
// Global timeout
|
|
61
62
|
// ---------------------------------------------------------------------------
|
|
62
63
|
const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes total
|
|
63
|
-
function startGlobalTimeout(timeoutMs) {
|
|
64
|
+
function startGlobalTimeout(timeoutMs, logger) {
|
|
64
65
|
setTimeout(() => {
|
|
65
|
-
|
|
66
|
+
logger.error("Global timeout reached, forcing exit");
|
|
66
67
|
process.exit(2);
|
|
67
68
|
}, timeoutMs).unref();
|
|
68
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Wraps instinct tools to count create/update/delete operations.
|
|
72
|
+
* Returns new tool instances that increment the provided counts.
|
|
73
|
+
*/
|
|
74
|
+
function wrapInstinctToolsWithTracking(projectId, projectName, baseDir, counts) {
|
|
75
|
+
const writeTool = createInstinctWriteTool(projectId, projectName, baseDir);
|
|
76
|
+
const deleteTool = createInstinctDeleteTool(projectId, baseDir);
|
|
77
|
+
const trackedWrite = {
|
|
78
|
+
...writeTool,
|
|
79
|
+
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
80
|
+
const result = await writeTool.execute(toolCallId, params, signal, onUpdate, ctx);
|
|
81
|
+
const details = result.details;
|
|
82
|
+
if (details?.action === "created") {
|
|
83
|
+
counts.created++;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
counts.updated++;
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
const trackedDelete = {
|
|
92
|
+
...deleteTool,
|
|
93
|
+
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
94
|
+
const result = await deleteTool.execute(toolCallId, params, signal, onUpdate, ctx);
|
|
95
|
+
counts.deleted++;
|
|
96
|
+
return result;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
return {
|
|
100
|
+
listTool: createInstinctListTool(projectId, baseDir),
|
|
101
|
+
readTool: createInstinctReadTool(projectId, baseDir),
|
|
102
|
+
writeTool: trackedWrite,
|
|
103
|
+
deleteTool: trackedDelete,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
69
106
|
function loadProjectsRegistry(baseDir) {
|
|
70
107
|
const path = getProjectsRegistryPath(baseDir);
|
|
71
108
|
if (!existsSync(path))
|
|
@@ -104,19 +141,23 @@ function hasNewObservations(projectId, meta, baseDir) {
|
|
|
104
141
|
}
|
|
105
142
|
return true;
|
|
106
143
|
}
|
|
107
|
-
async function analyzeProject(project, config, baseDir) {
|
|
144
|
+
async function analyzeProject(project, config, baseDir, logger) {
|
|
108
145
|
const meta = loadProjectMeta(project.id, baseDir);
|
|
109
|
-
if (!hasNewObservations(project.id, meta, baseDir))
|
|
110
|
-
return false;
|
|
146
|
+
if (!hasNewObservations(project.id, meta, baseDir)) {
|
|
147
|
+
return { ran: false, skippedReason: "no new observations" };
|
|
148
|
+
}
|
|
111
149
|
const obsPath = getObservationsPath(project.id, baseDir);
|
|
112
150
|
const sinceLineCount = meta.last_observation_line_count ?? 0;
|
|
113
151
|
const { lines: newObsLines, totalLineCount } = tailObservationsSince(obsPath, sinceLineCount);
|
|
114
|
-
if (newObsLines.length === 0)
|
|
115
|
-
return false;
|
|
152
|
+
if (newObsLines.length === 0) {
|
|
153
|
+
return { ran: false, skippedReason: "no new observation lines" };
|
|
154
|
+
}
|
|
116
155
|
const obsCount = countObservations(project.id, baseDir);
|
|
117
|
-
if (obsCount < config.min_observations_to_analyze)
|
|
118
|
-
return false;
|
|
119
|
-
|
|
156
|
+
if (obsCount < config.min_observations_to_analyze) {
|
|
157
|
+
return { ran: false, skippedReason: `below threshold (${obsCount}/${config.min_observations_to_analyze})` };
|
|
158
|
+
}
|
|
159
|
+
const startTime = Date.now();
|
|
160
|
+
logger.projectStart(project.id, project.name, newObsLines.length, obsCount);
|
|
120
161
|
runDecayPass(project.id, baseDir);
|
|
121
162
|
const instinctsDir = join(getProjectDir(project.id, baseDir), "instincts", "personal");
|
|
122
163
|
const agentsMdProject = readAgentsMd(join(project.root, "AGENTS.md"));
|
|
@@ -131,7 +172,7 @@ async function analyzeProject(project, config, baseDir) {
|
|
|
131
172
|
}));
|
|
132
173
|
}
|
|
133
174
|
catch {
|
|
134
|
-
// Skills loading is best-effort
|
|
175
|
+
// Skills loading is best-effort - continue without them
|
|
135
176
|
}
|
|
136
177
|
const userPrompt = buildAnalyzerUserPrompt(obsPath, instinctsDir, project, {
|
|
137
178
|
agentsMdProject,
|
|
@@ -143,11 +184,14 @@ async function analyzeProject(project, config, baseDir) {
|
|
|
143
184
|
const modelRegistry = new ModelRegistry(authStorage);
|
|
144
185
|
const modelId = (config.model || DEFAULT_CONFIG.model);
|
|
145
186
|
const model = getModel("anthropic", modelId);
|
|
187
|
+
// Track instinct operations
|
|
188
|
+
const instinctCounts = { created: 0, updated: 0, deleted: 0 };
|
|
189
|
+
const trackedTools = wrapInstinctToolsWithTracking(project.id, project.name, baseDir, instinctCounts);
|
|
146
190
|
const customTools = [
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
191
|
+
trackedTools.listTool,
|
|
192
|
+
trackedTools.readTool,
|
|
193
|
+
trackedTools.writeTool,
|
|
194
|
+
trackedTools.deleteTool,
|
|
151
195
|
];
|
|
152
196
|
const loader = new DefaultResourceLoader({
|
|
153
197
|
systemPromptOverride: () => buildAnalyzerSystemPrompt(),
|
|
@@ -167,40 +211,88 @@ async function analyzeProject(project, config, baseDir) {
|
|
|
167
211
|
finally {
|
|
168
212
|
session.dispose();
|
|
169
213
|
}
|
|
214
|
+
// Collect stats after session completes
|
|
215
|
+
const sessionStats = session.getSessionStats();
|
|
216
|
+
const durationMs = Date.now() - startTime;
|
|
217
|
+
const stats = {
|
|
218
|
+
project_id: project.id,
|
|
219
|
+
project_name: project.name,
|
|
220
|
+
duration_ms: durationMs,
|
|
221
|
+
observations_processed: newObsLines.length,
|
|
222
|
+
observations_total: obsCount,
|
|
223
|
+
instincts_created: instinctCounts.created,
|
|
224
|
+
instincts_updated: instinctCounts.updated,
|
|
225
|
+
instincts_deleted: instinctCounts.deleted,
|
|
226
|
+
tokens_input: sessionStats.tokens.input,
|
|
227
|
+
tokens_output: sessionStats.tokens.output,
|
|
228
|
+
tokens_cache_read: sessionStats.tokens.cacheRead,
|
|
229
|
+
tokens_cache_write: sessionStats.tokens.cacheWrite,
|
|
230
|
+
tokens_total: sessionStats.tokens.total,
|
|
231
|
+
cost_usd: sessionStats.cost,
|
|
232
|
+
model: modelId,
|
|
233
|
+
};
|
|
234
|
+
logger.projectComplete(stats);
|
|
170
235
|
saveProjectMeta(project.id, { ...meta, last_analyzed_at: new Date().toISOString(), last_observation_line_count: totalLineCount }, baseDir);
|
|
171
|
-
|
|
172
|
-
return true;
|
|
236
|
+
return { ran: true, stats };
|
|
173
237
|
}
|
|
174
238
|
// ---------------------------------------------------------------------------
|
|
175
239
|
// Main
|
|
176
240
|
// ---------------------------------------------------------------------------
|
|
177
241
|
async function main() {
|
|
178
242
|
const baseDir = getBaseDir();
|
|
243
|
+
const config = loadConfig();
|
|
244
|
+
const logger = new AnalyzeLogger(config.log_path);
|
|
179
245
|
if (!acquireLock(baseDir)) {
|
|
180
|
-
|
|
246
|
+
logger.info("Another instance is already running, exiting");
|
|
181
247
|
process.exit(0);
|
|
182
248
|
}
|
|
183
|
-
startGlobalTimeout(DEFAULT_TIMEOUT_MS);
|
|
249
|
+
startGlobalTimeout(DEFAULT_TIMEOUT_MS, logger);
|
|
250
|
+
const runStart = Date.now();
|
|
184
251
|
try {
|
|
185
|
-
const config = loadConfig();
|
|
186
252
|
const registry = loadProjectsRegistry(baseDir);
|
|
187
253
|
const projects = Object.values(registry);
|
|
188
254
|
if (projects.length === 0) {
|
|
189
|
-
|
|
255
|
+
logger.info("No projects registered");
|
|
190
256
|
return;
|
|
191
257
|
}
|
|
258
|
+
logger.runStart(projects.length);
|
|
192
259
|
let processed = 0;
|
|
260
|
+
let skipped = 0;
|
|
261
|
+
let errored = 0;
|
|
262
|
+
const allProjectStats = [];
|
|
193
263
|
for (const project of projects) {
|
|
194
264
|
try {
|
|
195
|
-
const
|
|
196
|
-
if (
|
|
265
|
+
const result = await analyzeProject(project, config, baseDir, logger);
|
|
266
|
+
if (result.ran && result.stats) {
|
|
197
267
|
processed++;
|
|
268
|
+
allProjectStats.push(result.stats);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
skipped++;
|
|
272
|
+
if (result.skippedReason) {
|
|
273
|
+
logger.projectSkipped(project.id, project.name, result.skippedReason);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
198
276
|
}
|
|
199
277
|
catch (err) {
|
|
200
|
-
|
|
278
|
+
errored++;
|
|
279
|
+
logger.projectError(project.id, project.name, err);
|
|
201
280
|
}
|
|
202
281
|
}
|
|
203
|
-
|
|
282
|
+
const summary = {
|
|
283
|
+
total_duration_ms: Date.now() - runStart,
|
|
284
|
+
projects_processed: processed,
|
|
285
|
+
projects_skipped: skipped,
|
|
286
|
+
projects_errored: errored,
|
|
287
|
+
projects_total: projects.length,
|
|
288
|
+
total_tokens: allProjectStats.reduce((sum, s) => sum + s.tokens_total, 0),
|
|
289
|
+
total_cost_usd: allProjectStats.reduce((sum, s) => sum + s.cost_usd, 0),
|
|
290
|
+
total_instincts_created: allProjectStats.reduce((sum, s) => sum + s.instincts_created, 0),
|
|
291
|
+
total_instincts_updated: allProjectStats.reduce((sum, s) => sum + s.instincts_updated, 0),
|
|
292
|
+
total_instincts_deleted: allProjectStats.reduce((sum, s) => sum + s.instincts_deleted, 0),
|
|
293
|
+
project_stats: allProjectStats,
|
|
294
|
+
};
|
|
295
|
+
logger.runComplete(summary);
|
|
204
296
|
}
|
|
205
297
|
finally {
|
|
206
298
|
releaseLock(baseDir);
|
|
@@ -208,7 +300,9 @@ async function main() {
|
|
|
208
300
|
}
|
|
209
301
|
main().catch((err) => {
|
|
210
302
|
releaseLock(getBaseDir());
|
|
211
|
-
|
|
303
|
+
// Last-resort logging - config may not have loaded
|
|
304
|
+
const logger = new AnalyzeLogger();
|
|
305
|
+
logger.error("Fatal error", err);
|
|
212
306
|
process.exit(1);
|
|
213
307
|
});
|
|
214
308
|
//# sourceMappingURL=analyze.js.map
|
package/dist/cli/analyze.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/cli/analyze.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/cli/analyze.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAMzC;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAWhD,CAAC;AAEF,eAAO,MAAM,WAAW,QAKvB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAW5B,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAMzC;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAWhD,CAAC;AAEF,eAAO,MAAM,WAAW,QAKvB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAW5B,CAAC;AA4BF;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CA2BnC"}
|
package/dist/config.js
CHANGED
|
@@ -53,6 +53,7 @@ const PartialConfigSchema = Type.Partial(Type.Object({
|
|
|
53
53
|
active_hours_start: Type.Number(),
|
|
54
54
|
active_hours_end: Type.Number(),
|
|
55
55
|
max_idle_seconds: Type.Number(),
|
|
56
|
+
log_path: Type.String(),
|
|
56
57
|
}));
|
|
57
58
|
// ---------------------------------------------------------------------------
|
|
58
59
|
// loadConfig
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,IAAI,EAAe,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAGhD,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD,GAAG,EAAE,mCAAmC;IACxC,OAAO,EAAE,kCAAkC;IAC3C,SAAS,EAAE,8BAA8B;IACzC,QAAQ,EAAE,qCAAqC;IAC/C,UAAU,EAAE,qCAAqC;IACjD,GAAG,EAAE,iBAAiB;IACtB,MAAM,EAAE,kCAAkC;IAC1C,QAAQ,EAAE,iDAAiD;IAC3D,WAAW,EAAE,0BAA0B;IACvC,aAAa,EAAE,qCAAqC;CACrD,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAClC,EAAE,CAAC,OAAO,EAAE,EACZ,KAAK,EACL,qBAAqB,EACrB,aAAa,CACd,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAW;IACpC,oBAAoB,EAAE,CAAC;IACvB,2BAA2B,EAAE,EAAE;IAC/B,cAAc,EAAE,GAAG;IACnB,aAAa,EAAE,EAAE;IACjB,mBAAmB,EAAE,IAAI;IACzB,KAAK,EAAE,kBAAkB;IACzB,eAAe,EAAE,GAAG;IACpB,kBAAkB,EAAE,CAAC;IACrB,gBAAgB,EAAE,EAAE;IACpB,gBAAgB,EAAE,IAAI;CACvB,CAAC;AAEF,8EAA8E;AAC9E,mEAAmE;AACnE,8EAA8E;AAE9E,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CACtC,IAAI,CAAC,MAAM,CAAC;IACV,oBAAoB,EAAE,IAAI,CAAC,MAAM,EAAE;IACnC,2BAA2B,EAAE,IAAI,CAAC,MAAM,EAAE;IAC1C,cAAc,EAAE,IAAI,CAAC,MAAM,EAAE;IAC7B,aAAa,EAAE,IAAI,CAAC,MAAM,EAAE;IAC5B,mBAAmB,EAAE,IAAI,CAAC,MAAM,EAAE;IAClC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE;IACpB,eAAe,EAAE,IAAI,CAAC,MAAM,EAAE;IAC9B,kBAAkB,EAAE,IAAI,CAAC,MAAM,EAAE;IACjC,gBAAgB,EAAE,IAAI,CAAC,MAAM,EAAE;IAC/B,gBAAgB,EAAE,IAAI,CAAC,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,MAAM,gBAAgB,GACxB,YAAY,GACZ,eAAe,GACf,aAAa,GACb,WAAW,GACX,YAAY,GACZ,UAAU,GACV,WAAW,GACX,iBAAiB,GACjB,cAAc,CAAC;AAEnB,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAMD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC;AACjD,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,WAAW,CAAC;AAEtD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAMD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,MAAM;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,2BAA2B,EAAE,MAAM,CAAC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,MAAM,gBAAgB,GACxB,YAAY,GACZ,eAAe,GACf,aAAa,GACb,WAAW,GACX,YAAY,GACZ,UAAU,GACV,WAAW,GACX,iBAAiB,GACjB,cAAc,CAAC;AAEnB,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAMD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC;AACjD,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,WAAW,CAAC;AAEtD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAMD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,MAAM;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,2BAA2B,EAAE,MAAM,CAAC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logging for the background analyzer CLI.
|
|
3
|
+
* Writes to a configurable log file (default: ~/.pi/continuous-learning/analyzer.log).
|
|
4
|
+
* Each line is a JSON object for easy parsing and grep-ability.
|
|
5
|
+
*
|
|
6
|
+
* Log levels: info, warn, error
|
|
7
|
+
* Never throws - all I/O failures fall back to stderr.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { appendFileSync, mkdirSync, renameSync, statSync } from "node:fs";
|
|
11
|
+
import { dirname } from "node:path";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { getBaseDir } from "../storage.js";
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Constants
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
const DEFAULT_LOG_FILENAME = "analyzer.log";
|
|
20
|
+
const MAX_LOG_SIZE_BYTES = 10 * 1024 * 1024; // 10 MB - rotate beyond this
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Types
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
type LogLevel = "info" | "warn" | "error";
|
|
27
|
+
|
|
28
|
+
interface LogEntry {
|
|
29
|
+
readonly timestamp: string;
|
|
30
|
+
readonly level: LogLevel;
|
|
31
|
+
readonly message: string;
|
|
32
|
+
readonly [key: string]: unknown;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ProjectRunStats {
|
|
36
|
+
readonly project_id: string;
|
|
37
|
+
readonly project_name: string;
|
|
38
|
+
readonly duration_ms: number;
|
|
39
|
+
readonly observations_processed: number;
|
|
40
|
+
readonly observations_total: number;
|
|
41
|
+
readonly instincts_created: number;
|
|
42
|
+
readonly instincts_updated: number;
|
|
43
|
+
readonly instincts_deleted: number;
|
|
44
|
+
readonly tokens_input: number;
|
|
45
|
+
readonly tokens_output: number;
|
|
46
|
+
readonly tokens_cache_read: number;
|
|
47
|
+
readonly tokens_cache_write: number;
|
|
48
|
+
readonly tokens_total: number;
|
|
49
|
+
readonly cost_usd: number;
|
|
50
|
+
readonly model: string;
|
|
51
|
+
readonly skipped_reason?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface RunSummary {
|
|
55
|
+
readonly total_duration_ms: number;
|
|
56
|
+
readonly projects_processed: number;
|
|
57
|
+
readonly projects_skipped: number;
|
|
58
|
+
readonly projects_errored: number;
|
|
59
|
+
readonly projects_total: number;
|
|
60
|
+
readonly total_tokens: number;
|
|
61
|
+
readonly total_cost_usd: number;
|
|
62
|
+
readonly total_instincts_created: number;
|
|
63
|
+
readonly total_instincts_updated: number;
|
|
64
|
+
readonly total_instincts_deleted: number;
|
|
65
|
+
readonly project_stats: readonly ProjectRunStats[];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// Logger
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
export class AnalyzeLogger {
|
|
73
|
+
private readonly logPath: string;
|
|
74
|
+
|
|
75
|
+
constructor(logPath?: string) {
|
|
76
|
+
this.logPath = logPath ?? join(getBaseDir(), DEFAULT_LOG_FILENAME);
|
|
77
|
+
this.ensureLogDir();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getLogPath(): string {
|
|
81
|
+
return this.logPath;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
info(message: string, data?: Record<string, unknown>): void {
|
|
85
|
+
this.write("info", message, data);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
warn(message: string, data?: Record<string, unknown>): void {
|
|
89
|
+
this.write("warn", message, data);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
error(message: string, error?: unknown, data?: Record<string, unknown>): void {
|
|
93
|
+
const errorData: Record<string, unknown> = { ...data };
|
|
94
|
+
if (error instanceof Error) {
|
|
95
|
+
errorData.error_message = error.message;
|
|
96
|
+
errorData.error_stack = error.stack;
|
|
97
|
+
} else if (error !== undefined) {
|
|
98
|
+
errorData.error_message = String(error);
|
|
99
|
+
}
|
|
100
|
+
this.write("error", message, errorData);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Log the start of a full analyzer run */
|
|
104
|
+
runStart(projectCount: number): void {
|
|
105
|
+
this.info("Analyzer run started", {
|
|
106
|
+
event: "run_start",
|
|
107
|
+
project_count: projectCount,
|
|
108
|
+
pid: process.pid,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Log that a project was skipped (with reason) */
|
|
113
|
+
projectSkipped(projectId: string, projectName: string, reason: string): void {
|
|
114
|
+
this.info(`Skipped ${projectName}`, {
|
|
115
|
+
event: "project_skipped",
|
|
116
|
+
project_id: projectId,
|
|
117
|
+
project_name: projectName,
|
|
118
|
+
reason,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Log the start of a project analysis */
|
|
123
|
+
projectStart(projectId: string, projectName: string, newObservations: number, totalObservations: number): void {
|
|
124
|
+
this.info(`Processing ${projectName}`, {
|
|
125
|
+
event: "project_start",
|
|
126
|
+
project_id: projectId,
|
|
127
|
+
project_name: projectName,
|
|
128
|
+
new_observations: newObservations,
|
|
129
|
+
total_observations: totalObservations,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Log per-project results after analysis completes */
|
|
134
|
+
projectComplete(stats: ProjectRunStats): void {
|
|
135
|
+
const durationSec = (stats.duration_ms / 1000).toFixed(1);
|
|
136
|
+
const costFormatted = stats.cost_usd.toFixed(4);
|
|
137
|
+
this.info(
|
|
138
|
+
`Completed ${stats.project_name} in ${durationSec}s - ` +
|
|
139
|
+
`tokens: ${stats.tokens_total}, cost: $${costFormatted}, ` +
|
|
140
|
+
`instincts: +${stats.instincts_created} ~${stats.instincts_updated} -${stats.instincts_deleted}`,
|
|
141
|
+
{ event: "project_complete", ...stats }
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Log a project that errored during analysis */
|
|
146
|
+
projectError(projectId: string, projectName: string, error: unknown): void {
|
|
147
|
+
this.error(`Error processing ${projectName}`, error, {
|
|
148
|
+
event: "project_error",
|
|
149
|
+
project_id: projectId,
|
|
150
|
+
project_name: projectName,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Log the full run summary */
|
|
155
|
+
runComplete(summary: RunSummary): void {
|
|
156
|
+
const durationSec = (summary.total_duration_ms / 1000).toFixed(1);
|
|
157
|
+
const costFormatted = summary.total_cost_usd.toFixed(4);
|
|
158
|
+
this.info(
|
|
159
|
+
`Run complete in ${durationSec}s - ` +
|
|
160
|
+
`${summary.projects_processed}/${summary.projects_total} projects processed, ` +
|
|
161
|
+
`${summary.projects_skipped} skipped, ${summary.projects_errored} errored - ` +
|
|
162
|
+
`tokens: ${summary.total_tokens}, cost: $${costFormatted}, ` +
|
|
163
|
+
`instincts: +${summary.total_instincts_created} ~${summary.total_instincts_updated} -${summary.total_instincts_deleted}`,
|
|
164
|
+
{ event: "run_complete", ...summary }
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// -------------------------------------------------------------------------
|
|
169
|
+
// Internal
|
|
170
|
+
// -------------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
private ensureLogDir(): void {
|
|
173
|
+
try {
|
|
174
|
+
mkdirSync(dirname(this.logPath), { recursive: true });
|
|
175
|
+
} catch {
|
|
176
|
+
// Best effort
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private write(level: LogLevel, message: string, data?: Record<string, unknown>): void {
|
|
181
|
+
const entry: LogEntry = {
|
|
182
|
+
timestamp: new Date().toISOString(),
|
|
183
|
+
level,
|
|
184
|
+
message,
|
|
185
|
+
...data,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const line = JSON.stringify(entry) + "\n";
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
this.rotateIfNeeded();
|
|
192
|
+
appendFileSync(this.logPath, line, "utf-8");
|
|
193
|
+
} catch {
|
|
194
|
+
// Fall back to stderr - never lose log entries entirely
|
|
195
|
+
process.stderr.write(`[analyze] ${line}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private rotateIfNeeded(): void {
|
|
200
|
+
try {
|
|
201
|
+
const stat = statSync(this.logPath);
|
|
202
|
+
if (stat.size > MAX_LOG_SIZE_BYTES) {
|
|
203
|
+
renameSync(this.logPath, this.logPath + ".old");
|
|
204
|
+
}
|
|
205
|
+
} catch {
|
|
206
|
+
// File doesn't exist yet or stat failed - fine
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
package/src/cli/analyze.ts
CHANGED
|
@@ -37,13 +37,14 @@ import {
|
|
|
37
37
|
import { readAgentsMd } from "../agents-md.js";
|
|
38
38
|
import { homedir } from "node:os";
|
|
39
39
|
import type { InstalledSkill } from "../types.js";
|
|
40
|
+
import { AnalyzeLogger, type ProjectRunStats, type RunSummary } from "./analyze-logger.js";
|
|
40
41
|
|
|
41
42
|
// ---------------------------------------------------------------------------
|
|
42
|
-
// Lockfile guard
|
|
43
|
+
// Lockfile guard - ensures only one instance runs at a time
|
|
43
44
|
// ---------------------------------------------------------------------------
|
|
44
45
|
|
|
45
46
|
const LOCKFILE_NAME = "analyze.lock";
|
|
46
|
-
const LOCK_STALE_MS = 10 * 60 * 1000; // 10 minutes
|
|
47
|
+
const LOCK_STALE_MS = 10 * 60 * 1000; // 10 minutes - stale lock threshold
|
|
47
48
|
|
|
48
49
|
function getLockfilePath(baseDir: string): string {
|
|
49
50
|
return join(baseDir, LOCKFILE_NAME);
|
|
@@ -64,12 +65,12 @@ function acquireLock(baseDir: string): boolean {
|
|
|
64
65
|
if (age < LOCK_STALE_MS) {
|
|
65
66
|
return false; // Process alive and lock is fresh
|
|
66
67
|
}
|
|
67
|
-
// Process alive but lock is stale
|
|
68
|
+
// Process alive but lock is stale - treat as abandoned
|
|
68
69
|
} catch {
|
|
69
|
-
// Process is dead
|
|
70
|
+
// Process is dead - lock is orphaned, safe to take over
|
|
70
71
|
}
|
|
71
72
|
} catch {
|
|
72
|
-
// Malformed lockfile
|
|
73
|
+
// Malformed lockfile - remove and proceed
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -86,7 +87,7 @@ function releaseLock(baseDir: string): void {
|
|
|
86
87
|
try {
|
|
87
88
|
if (existsSync(lockPath)) unlinkSync(lockPath);
|
|
88
89
|
} catch {
|
|
89
|
-
// Best effort
|
|
90
|
+
// Best effort - don't crash on cleanup
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
|
|
@@ -96,13 +97,79 @@ function releaseLock(baseDir: string): void {
|
|
|
96
97
|
|
|
97
98
|
const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes total
|
|
98
99
|
|
|
99
|
-
function startGlobalTimeout(timeoutMs: number): void {
|
|
100
|
+
function startGlobalTimeout(timeoutMs: number, logger: AnalyzeLogger): void {
|
|
100
101
|
setTimeout(() => {
|
|
101
|
-
|
|
102
|
+
logger.error("Global timeout reached, forcing exit");
|
|
102
103
|
process.exit(2);
|
|
103
104
|
}, timeoutMs).unref();
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// Instinct operation tracking
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
interface InstinctOpCounts {
|
|
112
|
+
created: number;
|
|
113
|
+
updated: number;
|
|
114
|
+
deleted: number;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Wraps instinct tools to count create/update/delete operations.
|
|
119
|
+
* Returns new tool instances that increment the provided counts.
|
|
120
|
+
*/
|
|
121
|
+
function wrapInstinctToolsWithTracking(
|
|
122
|
+
projectId: string,
|
|
123
|
+
projectName: string,
|
|
124
|
+
baseDir: string,
|
|
125
|
+
counts: InstinctOpCounts
|
|
126
|
+
) {
|
|
127
|
+
const writeTool = createInstinctWriteTool(projectId, projectName, baseDir);
|
|
128
|
+
const deleteTool = createInstinctDeleteTool(projectId, baseDir);
|
|
129
|
+
|
|
130
|
+
const trackedWrite = {
|
|
131
|
+
...writeTool,
|
|
132
|
+
async execute(
|
|
133
|
+
toolCallId: string,
|
|
134
|
+
params: Parameters<typeof writeTool.execute>[1],
|
|
135
|
+
signal: AbortSignal | undefined,
|
|
136
|
+
onUpdate: unknown,
|
|
137
|
+
ctx: unknown
|
|
138
|
+
) {
|
|
139
|
+
const result = await writeTool.execute(toolCallId, params, signal, onUpdate, ctx);
|
|
140
|
+
const details = result.details as { action?: string } | undefined;
|
|
141
|
+
if (details?.action === "created") {
|
|
142
|
+
counts.created++;
|
|
143
|
+
} else {
|
|
144
|
+
counts.updated++;
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const trackedDelete = {
|
|
151
|
+
...deleteTool,
|
|
152
|
+
async execute(
|
|
153
|
+
toolCallId: string,
|
|
154
|
+
params: Parameters<typeof deleteTool.execute>[1],
|
|
155
|
+
signal: AbortSignal | undefined,
|
|
156
|
+
onUpdate: unknown,
|
|
157
|
+
ctx: unknown
|
|
158
|
+
) {
|
|
159
|
+
const result = await deleteTool.execute(toolCallId, params, signal, onUpdate, ctx);
|
|
160
|
+
counts.deleted++;
|
|
161
|
+
return result;
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
listTool: createInstinctListTool(projectId, baseDir),
|
|
167
|
+
readTool: createInstinctReadTool(projectId, baseDir),
|
|
168
|
+
writeTool: trackedWrite,
|
|
169
|
+
deleteTool: trackedDelete,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
106
173
|
// ---------------------------------------------------------------------------
|
|
107
174
|
// Per-project analysis
|
|
108
175
|
// ---------------------------------------------------------------------------
|
|
@@ -150,27 +217,39 @@ function hasNewObservations(projectId: string, meta: ProjectMeta, baseDir: strin
|
|
|
150
217
|
return true;
|
|
151
218
|
}
|
|
152
219
|
|
|
220
|
+
interface AnalyzeResult {
|
|
221
|
+
readonly ran: boolean;
|
|
222
|
+
readonly stats?: ProjectRunStats;
|
|
223
|
+
readonly skippedReason?: string;
|
|
224
|
+
}
|
|
225
|
+
|
|
153
226
|
async function analyzeProject(
|
|
154
227
|
project: ProjectEntry,
|
|
155
228
|
config: ReturnType<typeof loadConfig>,
|
|
156
|
-
baseDir: string
|
|
157
|
-
|
|
229
|
+
baseDir: string,
|
|
230
|
+
logger: AnalyzeLogger
|
|
231
|
+
): Promise<AnalyzeResult> {
|
|
158
232
|
const meta = loadProjectMeta(project.id, baseDir);
|
|
159
233
|
|
|
160
|
-
if (!hasNewObservations(project.id, meta, baseDir))
|
|
234
|
+
if (!hasNewObservations(project.id, meta, baseDir)) {
|
|
235
|
+
return { ran: false, skippedReason: "no new observations" };
|
|
236
|
+
}
|
|
161
237
|
|
|
162
238
|
const obsPath = getObservationsPath(project.id, baseDir);
|
|
163
239
|
const sinceLineCount = meta.last_observation_line_count ?? 0;
|
|
164
240
|
const { lines: newObsLines, totalLineCount } = tailObservationsSince(obsPath, sinceLineCount);
|
|
165
241
|
|
|
166
|
-
if (newObsLines.length === 0)
|
|
242
|
+
if (newObsLines.length === 0) {
|
|
243
|
+
return { ran: false, skippedReason: "no new observation lines" };
|
|
244
|
+
}
|
|
167
245
|
|
|
168
246
|
const obsCount = countObservations(project.id, baseDir);
|
|
169
|
-
if (obsCount < config.min_observations_to_analyze)
|
|
247
|
+
if (obsCount < config.min_observations_to_analyze) {
|
|
248
|
+
return { ran: false, skippedReason: `below threshold (${obsCount}/${config.min_observations_to_analyze})` };
|
|
249
|
+
}
|
|
170
250
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
);
|
|
251
|
+
const startTime = Date.now();
|
|
252
|
+
logger.projectStart(project.id, project.name, newObsLines.length, obsCount);
|
|
174
253
|
|
|
175
254
|
runDecayPass(project.id, baseDir);
|
|
176
255
|
|
|
@@ -188,7 +267,7 @@ async function analyzeProject(
|
|
|
188
267
|
description: s.description,
|
|
189
268
|
}));
|
|
190
269
|
} catch {
|
|
191
|
-
// Skills loading is best-effort
|
|
270
|
+
// Skills loading is best-effort - continue without them
|
|
192
271
|
}
|
|
193
272
|
|
|
194
273
|
const userPrompt = buildAnalyzerUserPrompt(obsPath, instinctsDir, project, {
|
|
@@ -203,11 +282,15 @@ async function analyzeProject(
|
|
|
203
282
|
const modelId = (config.model || DEFAULT_CONFIG.model) as Parameters<typeof getModel>[1];
|
|
204
283
|
const model = getModel("anthropic", modelId);
|
|
205
284
|
|
|
285
|
+
// Track instinct operations
|
|
286
|
+
const instinctCounts: InstinctOpCounts = { created: 0, updated: 0, deleted: 0 };
|
|
287
|
+
const trackedTools = wrapInstinctToolsWithTracking(project.id, project.name, baseDir, instinctCounts);
|
|
288
|
+
|
|
206
289
|
const customTools = [
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
290
|
+
trackedTools.listTool,
|
|
291
|
+
trackedTools.readTool,
|
|
292
|
+
trackedTools.writeTool,
|
|
293
|
+
trackedTools.deleteTool,
|
|
211
294
|
];
|
|
212
295
|
|
|
213
296
|
const loader = new DefaultResourceLoader({
|
|
@@ -230,13 +313,37 @@ async function analyzeProject(
|
|
|
230
313
|
session.dispose();
|
|
231
314
|
}
|
|
232
315
|
|
|
316
|
+
// Collect stats after session completes
|
|
317
|
+
const sessionStats = session.getSessionStats();
|
|
318
|
+
const durationMs = Date.now() - startTime;
|
|
319
|
+
|
|
320
|
+
const stats: ProjectRunStats = {
|
|
321
|
+
project_id: project.id,
|
|
322
|
+
project_name: project.name,
|
|
323
|
+
duration_ms: durationMs,
|
|
324
|
+
observations_processed: newObsLines.length,
|
|
325
|
+
observations_total: obsCount,
|
|
326
|
+
instincts_created: instinctCounts.created,
|
|
327
|
+
instincts_updated: instinctCounts.updated,
|
|
328
|
+
instincts_deleted: instinctCounts.deleted,
|
|
329
|
+
tokens_input: sessionStats.tokens.input,
|
|
330
|
+
tokens_output: sessionStats.tokens.output,
|
|
331
|
+
tokens_cache_read: sessionStats.tokens.cacheRead,
|
|
332
|
+
tokens_cache_write: sessionStats.tokens.cacheWrite,
|
|
333
|
+
tokens_total: sessionStats.tokens.total,
|
|
334
|
+
cost_usd: sessionStats.cost,
|
|
335
|
+
model: modelId,
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
logger.projectComplete(stats);
|
|
339
|
+
|
|
233
340
|
saveProjectMeta(
|
|
234
341
|
project.id,
|
|
235
342
|
{ ...meta, last_analyzed_at: new Date().toISOString(), last_observation_line_count: totalLineCount },
|
|
236
343
|
baseDir
|
|
237
344
|
);
|
|
238
|
-
|
|
239
|
-
return true;
|
|
345
|
+
|
|
346
|
+
return { ran: true, stats };
|
|
240
347
|
}
|
|
241
348
|
|
|
242
349
|
// ---------------------------------------------------------------------------
|
|
@@ -245,35 +352,67 @@ async function analyzeProject(
|
|
|
245
352
|
|
|
246
353
|
async function main(): Promise<void> {
|
|
247
354
|
const baseDir = getBaseDir();
|
|
355
|
+
const config = loadConfig();
|
|
356
|
+
const logger = new AnalyzeLogger(config.log_path);
|
|
248
357
|
|
|
249
358
|
if (!acquireLock(baseDir)) {
|
|
250
|
-
|
|
359
|
+
logger.info("Another instance is already running, exiting");
|
|
251
360
|
process.exit(0);
|
|
252
361
|
}
|
|
253
362
|
|
|
254
|
-
startGlobalTimeout(DEFAULT_TIMEOUT_MS);
|
|
363
|
+
startGlobalTimeout(DEFAULT_TIMEOUT_MS, logger);
|
|
364
|
+
|
|
365
|
+
const runStart = Date.now();
|
|
255
366
|
|
|
256
367
|
try {
|
|
257
|
-
const config = loadConfig();
|
|
258
368
|
const registry = loadProjectsRegistry(baseDir);
|
|
259
369
|
const projects = Object.values(registry);
|
|
260
370
|
|
|
261
371
|
if (projects.length === 0) {
|
|
262
|
-
|
|
372
|
+
logger.info("No projects registered");
|
|
263
373
|
return;
|
|
264
374
|
}
|
|
265
375
|
|
|
376
|
+
logger.runStart(projects.length);
|
|
377
|
+
|
|
266
378
|
let processed = 0;
|
|
379
|
+
let skipped = 0;
|
|
380
|
+
let errored = 0;
|
|
381
|
+
const allProjectStats: ProjectRunStats[] = [];
|
|
382
|
+
|
|
267
383
|
for (const project of projects) {
|
|
268
384
|
try {
|
|
269
|
-
const
|
|
270
|
-
if (
|
|
385
|
+
const result = await analyzeProject(project, config, baseDir, logger);
|
|
386
|
+
if (result.ran && result.stats) {
|
|
387
|
+
processed++;
|
|
388
|
+
allProjectStats.push(result.stats);
|
|
389
|
+
} else {
|
|
390
|
+
skipped++;
|
|
391
|
+
if (result.skippedReason) {
|
|
392
|
+
logger.projectSkipped(project.id, project.name, result.skippedReason);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
271
395
|
} catch (err) {
|
|
272
|
-
|
|
396
|
+
errored++;
|
|
397
|
+
logger.projectError(project.id, project.name, err);
|
|
273
398
|
}
|
|
274
399
|
}
|
|
275
400
|
|
|
276
|
-
|
|
401
|
+
const summary: RunSummary = {
|
|
402
|
+
total_duration_ms: Date.now() - runStart,
|
|
403
|
+
projects_processed: processed,
|
|
404
|
+
projects_skipped: skipped,
|
|
405
|
+
projects_errored: errored,
|
|
406
|
+
projects_total: projects.length,
|
|
407
|
+
total_tokens: allProjectStats.reduce((sum, s) => sum + s.tokens_total, 0),
|
|
408
|
+
total_cost_usd: allProjectStats.reduce((sum, s) => sum + s.cost_usd, 0),
|
|
409
|
+
total_instincts_created: allProjectStats.reduce((sum, s) => sum + s.instincts_created, 0),
|
|
410
|
+
total_instincts_updated: allProjectStats.reduce((sum, s) => sum + s.instincts_updated, 0),
|
|
411
|
+
total_instincts_deleted: allProjectStats.reduce((sum, s) => sum + s.instincts_deleted, 0),
|
|
412
|
+
project_stats: allProjectStats,
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
logger.runComplete(summary);
|
|
277
416
|
} finally {
|
|
278
417
|
releaseLock(baseDir);
|
|
279
418
|
}
|
|
@@ -281,6 +420,8 @@ async function main(): Promise<void> {
|
|
|
281
420
|
|
|
282
421
|
main().catch((err) => {
|
|
283
422
|
releaseLock(getBaseDir());
|
|
284
|
-
|
|
423
|
+
// Last-resort logging - config may not have loaded
|
|
424
|
+
const logger = new AnalyzeLogger();
|
|
425
|
+
logger.error("Fatal error", err);
|
|
285
426
|
process.exit(1);
|
|
286
427
|
});
|
package/src/config.ts
CHANGED
package/src/types.ts
CHANGED