@titan-design/brain 0.3.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.
@@ -0,0 +1,352 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # PM Diagnostic Automation — Orchestrator
5
+ # Usage: ./scripts/diagnostic/run.sh <version> [options]
6
+ # --skip-setup Skip reset/build/onboarding (re-run tests only)
7
+ # --phase <name> Run only: test-bench, audits, assemble, observations
8
+ # --concurrency <n> Parallel test agents (default: 6)
9
+
10
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
+ PROJECT_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
12
+ cd "$PROJECT_DIR"
13
+ WORKSPACE_DIR="${HOME}/Documents/projects/voltras-workspace"
14
+
15
+ VERSION="${1:?Usage: run.sh <version> [--skip-setup] [--phase <name>] [--concurrency <n>]}"
16
+ shift
17
+
18
+ SKIP_SETUP=false
19
+ SKIP_QUALITY_GATE=false
20
+ PHASE="all"
21
+ CONCURRENCY=6
22
+
23
+ while [[ $# -gt 0 ]]; do
24
+ case "$1" in
25
+ --skip-setup) SKIP_SETUP=true; shift ;;
26
+ --skip-quality-gate) SKIP_QUALITY_GATE=true; shift ;;
27
+ --phase) PHASE="$2"; shift 2 ;;
28
+ --concurrency) CONCURRENCY="$2"; shift 2 ;;
29
+ *) echo "Unknown option: $1"; exit 1 ;;
30
+ esac
31
+ done
32
+
33
+ RESULTS_DIR="docs/pm-module/diagnostic/${VERSION}"
34
+ PROMPTS_DIR="docs/pm-module/diagnostic/prompts"
35
+ SCHEMA_FILE="scripts/diagnostic/schema.json"
36
+
37
+ # Compute previous version for delta comparison
38
+ VERSION_NUM="${VERSION#v}"
39
+ PREV_NUM=$((VERSION_NUM - 1))
40
+ PREVIOUS_VERSION="v${PREV_NUM}"
41
+
42
+ SETUP_SESSION_LOG=""
43
+
44
+ mkdir -p "${RESULTS_DIR}/test-bench"
45
+
46
+ echo "═══════════════════════════════════════════════"
47
+ echo " PM Diagnostic — ${VERSION}"
48
+ echo " Phase: ${PHASE}"
49
+ echo " Skip setup: ${SKIP_SETUP}"
50
+ echo " Concurrency: ${CONCURRENCY}"
51
+ echo " Results: ${RESULTS_DIR}/"
52
+ echo "═══════════════════════════════════════════════"
53
+
54
+ apply_template() {
55
+ local file="$1"
56
+ sed \
57
+ -e "s|{{VERSION}}|${VERSION}|g" \
58
+ -e "s|{{RESULTS_DIR}}|${RESULTS_DIR}|g" \
59
+ -e "s|{{PREVIOUS_VERSION}}|${PREVIOUS_VERSION}|g" \
60
+ "$file"
61
+ }
62
+
63
+ run_agent() {
64
+ local prompt_file="$1"
65
+ local output_file="${2:-}"
66
+ local model="${3:-sonnet}"
67
+ local extra_flags="${4:-}"
68
+
69
+ local prompt
70
+ prompt="$(apply_template "$prompt_file")"
71
+
72
+ local cmd=(
73
+ env -u CLAUDECODE -u CLAUDE_CODE_ENTRYPOINT
74
+ -u CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY
75
+ -u CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
76
+ -u CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
77
+ claude -p
78
+ --model "$model"
79
+ --permission-mode bypassPermissions
80
+ --no-session-persistence
81
+ --setting-sources user
82
+ )
83
+
84
+ if [[ -n "$extra_flags" ]]; then
85
+ # shellcheck disable=SC2206
86
+ cmd+=($extra_flags)
87
+ fi
88
+
89
+ if [[ -n "$output_file" ]]; then
90
+ "${cmd[@]}" "$prompt" > "$output_file"
91
+ else
92
+ "${cmd[@]}" "$prompt"
93
+ fi
94
+ }
95
+
96
+ # ── Phase 0: Reset & Build ──────────────────────────
97
+
98
+ run_setup() {
99
+ echo ""
100
+ echo "── Phase 0: Reset & Build ──────────────────────"
101
+
102
+ echo "Building..."
103
+ npm run build --silent
104
+
105
+ echo "Resetting brain..."
106
+ (cd /tmp && npx tsx "$PROJECT_DIR/src/cli.ts" reset --confirm)
107
+
108
+ echo "Linking..."
109
+ npm link --silent
110
+
111
+ echo "Initializing brain..."
112
+ # Run from /tmp to avoid local .brain/ instance resolution
113
+ (cd /tmp && brain init --notes-dir ~/brain --embedder local)
114
+
115
+ echo "Ingesting command reference docs..."
116
+ for doc in docs/pm-module/commands/*.md; do
117
+ (cd /tmp && brain add "$PROJECT_DIR/$doc" --type guide --tier fast 2>/dev/null) || true
118
+ done
119
+
120
+ echo "Spawning setup agent (with session persistence)..."
121
+ local prompt
122
+ prompt="$(apply_template "${PROMPTS_DIR}/setup.md")"
123
+
124
+ (cd "$WORKSPACE_DIR" && env -u CLAUDECODE -u CLAUDE_CODE_ENTRYPOINT \
125
+ -u CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY \
126
+ -u CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC \
127
+ -u CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS \
128
+ claude -p \
129
+ --model sonnet \
130
+ --permission-mode bypassPermissions \
131
+ --no-session-persistence \
132
+ --setting-sources user \
133
+ "$prompt")
134
+
135
+ # Find the session log written by the setup agent
136
+ local project_hash_dir
137
+ project_hash_dir=$(ls -dt ~/.claude/projects/*/ 2>/dev/null | head -1)
138
+ if [[ -n "$project_hash_dir" ]]; then
139
+ SETUP_SESSION_LOG=$(ls -t "${project_hash_dir}"*.jsonl 2>/dev/null | head -1)
140
+ if [[ -n "$SETUP_SESSION_LOG" ]]; then
141
+ echo " Setup session log: ${SETUP_SESSION_LOG}"
142
+ else
143
+ echo " WARNING: No session log found in ${project_hash_dir}"
144
+ fi
145
+ fi
146
+
147
+ echo "Setup complete."
148
+ }
149
+
150
+ # ── Phase 1-3: Audits ───────────────────────────────
151
+
152
+ run_audits() {
153
+ echo ""
154
+ echo "── Phase 1-3: Audits (parallel) ────────────────"
155
+
156
+ local pids=()
157
+ for audit in data-audit gap-analysis; do
158
+ echo " Spawning ${audit} agent..."
159
+ run_agent \
160
+ "${PROMPTS_DIR}/${audit}.md" \
161
+ "${RESULTS_DIR}/${audit}.md" \
162
+ sonnet &
163
+ pids+=($!)
164
+ done
165
+
166
+ # Session audit runs separately — needs setup session log path
167
+ if [[ -n "${SETUP_SESSION_LOG:-}" ]]; then
168
+ echo " Spawning session-audit agent..."
169
+ local prompt
170
+ prompt="$(apply_template "${PROMPTS_DIR}/session-audit.md")"
171
+ prompt="${prompt//\{\{SETUP_SESSION_LOG\}\}/${SETUP_SESSION_LOG}}"
172
+
173
+ local cmd=(
174
+ env -u CLAUDECODE -u CLAUDE_CODE_ENTRYPOINT
175
+ -u CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY
176
+ -u CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
177
+ -u CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
178
+ claude -p
179
+ --model sonnet
180
+ --permission-mode bypassPermissions
181
+ --no-session-persistence
182
+ --setting-sources user
183
+ )
184
+ "${cmd[@]}" "$prompt" > "${RESULTS_DIR}/session-audit.md" &
185
+ pids+=($!)
186
+ else
187
+ echo " SKIP: session-audit (no setup session log available)"
188
+ fi
189
+
190
+ echo " Waiting for ${#pids[@]} audit agents..."
191
+ local failed=0
192
+ for pid in "${pids[@]}"; do
193
+ if ! wait "$pid"; then
194
+ ((failed++))
195
+ fi
196
+ done
197
+
198
+ if [[ $failed -gt 0 ]]; then
199
+ echo " WARNING: ${failed} audit agent(s) failed"
200
+ else
201
+ echo " All audits complete."
202
+ fi
203
+ }
204
+
205
+ # ── Phase 4: Test Bench ─────────────────────────────
206
+
207
+ run_test_bench() {
208
+ echo ""
209
+ echo "── Phase 4: Test Bench (${CONCURRENCY} concurrent) ──────"
210
+
211
+ local total=0
212
+ local failed=0
213
+ local pids=()
214
+ local next_i=1
215
+
216
+ # Launch agents in waves of $CONCURRENCY
217
+ while [[ $next_i -le 30 ]]; do
218
+ local wave_pids=()
219
+ local wave_count=0
220
+
221
+ while [[ $next_i -le 30 && $wave_count -lt $CONCURRENCY ]]; do
222
+ local num
223
+ num=$(printf "%02d" "$next_i")
224
+ local prompt_file="${PROMPTS_DIR}/test-bench/P-${num}.md"
225
+ local output_file="${RESULTS_DIR}/test-bench/P-${num}.json"
226
+ ((next_i++))
227
+
228
+ if [[ ! -f "$prompt_file" ]]; then
229
+ echo " SKIP: ${prompt_file} not found"
230
+ continue
231
+ fi
232
+
233
+ run_agent "$prompt_file" "$output_file" sonnet "--output-format json" &
234
+ local pid=$!
235
+ echo " Started P-${num} (pid ${pid})"
236
+ wave_pids+=("$pid")
237
+ ((total++))
238
+ ((wave_count++))
239
+ done
240
+
241
+ # Wait for entire wave to finish
242
+ for pid in "${wave_pids[@]}"; do
243
+ if ! wait "$pid"; then
244
+ ((failed++))
245
+ fi
246
+ done
247
+ echo " Wave complete (${wave_count} agents)"
248
+ done
249
+
250
+ echo " Test bench complete: ${total} prompts, ${failed} failures"
251
+ }
252
+
253
+ # ── Phase 4b: Assemble ──────────────────────────────
254
+
255
+ run_assemble() {
256
+ echo ""
257
+ echo "── Phase 4b: Assemble Results ──────────────────"
258
+
259
+ npx tsx scripts/diagnostic/assemble.ts \
260
+ --version "$VERSION" \
261
+ --previous "$PREVIOUS_VERSION" \
262
+ --results-dir "$RESULTS_DIR"
263
+
264
+ echo " Wrote ${RESULTS_DIR}/test-bench-results.md"
265
+ }
266
+
267
+ # ── Phase 5a: Observations ──────────────────────────
268
+
269
+ run_observations() {
270
+ echo ""
271
+ echo "── Phase 5a: Extract Observations ──────────────"
272
+
273
+ run_agent \
274
+ "${PROMPTS_DIR}/observations.md" \
275
+ "${RESULTS_DIR}/observations.md" \
276
+ sonnet
277
+
278
+ echo " Wrote ${RESULTS_DIR}/observations.md"
279
+ }
280
+
281
+ # ── Phase 5b: Summary ───────────────────────────────
282
+
283
+ run_summary() {
284
+ echo ""
285
+ echo "── Phase 5b: Generate Summary ──────────────────"
286
+
287
+ run_agent \
288
+ "${PROMPTS_DIR}/summary.md" \
289
+ "${RESULTS_DIR}/summary.md" \
290
+ sonnet
291
+
292
+ echo " Wrote ${RESULTS_DIR}/summary.md"
293
+ }
294
+
295
+ # ── Execute ─────────────────────────────────────────
296
+
297
+ case "$PHASE" in
298
+ all)
299
+ if [[ "$SKIP_SETUP" == false ]]; then
300
+ run_setup
301
+ fi
302
+ echo ""
303
+ echo "── Quality Gate ─────────────────────────────────"
304
+ if [[ "$SKIP_QUALITY_GATE" == true ]]; then
305
+ bash "${SCRIPT_DIR}/quality-gate.sh" --skip
306
+ else
307
+ bash "${SCRIPT_DIR}/quality-gate.sh"
308
+ fi
309
+ run_audits
310
+ run_test_bench
311
+ run_assemble
312
+ echo ""
313
+ echo "── Phase 5: Observations + Summary (parallel) ──"
314
+ run_observations &
315
+ pid_obs=$!
316
+ run_summary &
317
+ pid_sum=$!
318
+ wait "$pid_obs" "$pid_sum"
319
+
320
+ echo ""
321
+ echo "── Ingesting diagnostic outputs ──────────────"
322
+ (cd /tmp && brain add "$PROJECT_DIR/${RESULTS_DIR}/summary.md" --type note --tier fast 2>/dev/null) || echo " SKIP: summary.md ingest failed"
323
+ (cd /tmp && brain add "$PROJECT_DIR/${RESULTS_DIR}/gap-analysis.md" --type note --tier fast 2>/dev/null) || echo " SKIP: gap-analysis.md ingest failed"
324
+ echo " Diagnostic outputs ingested for future reference."
325
+ ;;
326
+ test-bench)
327
+ run_test_bench
328
+ run_assemble
329
+ ;;
330
+ audits)
331
+ run_audits
332
+ ;;
333
+ assemble)
334
+ run_assemble
335
+ ;;
336
+ observations)
337
+ run_observations
338
+ run_summary
339
+ ;;
340
+ *)
341
+ echo "Unknown phase: ${PHASE}"
342
+ echo "Valid phases: all, test-bench, audits, assemble, observations"
343
+ exit 1
344
+ ;;
345
+ esac
346
+
347
+ echo ""
348
+ echo "═══════════════════════════════════════════════"
349
+ echo " Diagnostic ${VERSION} complete"
350
+ echo " Results: ${RESULTS_DIR}/"
351
+ echo " Review: ${RESULTS_DIR}/summary.md"
352
+ echo "═══════════════════════════════════════════════"
@@ -0,0 +1,54 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "required": ["id", "version", "category", "prompt", "commands", "metrics", "answer", "analysis"],
5
+ "properties": {
6
+ "id": { "type": "string", "pattern": "^P-\\d{2}$" },
7
+ "version": { "type": "string" },
8
+ "category": { "type": "string" },
9
+ "prompt": { "type": "string" },
10
+ "commands": {
11
+ "type": "array",
12
+ "items": { "type": "string" },
13
+ "description": "Every brain CLI command run, in order"
14
+ },
15
+ "metrics": {
16
+ "type": "object",
17
+ "required": ["total_calls", "brain_cli_calls", "non_brain_calls", "file_reads", "quality"],
18
+ "properties": {
19
+ "total_calls": { "type": "integer", "minimum": 0 },
20
+ "brain_cli_calls": { "type": "integer", "minimum": 0 },
21
+ "non_brain_calls": { "type": "integer", "minimum": 0 },
22
+ "file_reads": { "type": "integer", "minimum": 0 },
23
+ "quality": { "type": "integer", "minimum": 1, "maximum": 5 }
24
+ }
25
+ },
26
+ "answer": {
27
+ "type": "string",
28
+ "description": "The agent's complete answer to the prompt"
29
+ },
30
+ "analysis": {
31
+ "type": "object",
32
+ "required": ["what_worked", "friction_points", "known_gaps_hit", "new_issues"],
33
+ "properties": {
34
+ "what_worked": { "type": "string" },
35
+ "friction_points": { "type": "string" },
36
+ "known_gaps_hit": {
37
+ "type": "array",
38
+ "items": { "type": "string" }
39
+ },
40
+ "new_issues": {
41
+ "type": "array",
42
+ "items": {
43
+ "type": "object",
44
+ "required": ["description", "severity"],
45
+ "properties": {
46
+ "description": { "type": "string" },
47
+ "severity": { "type": "string", "enum": ["blocker", "friction", "suggestion", "docs", "observation"] }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }