sisyphi 1.1.18 → 1.1.19
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 +195 -75
- package/dist/chunk-36VJ7ZBD.js +1898 -0
- package/dist/chunk-36VJ7ZBD.js.map +1 -0
- package/dist/{chunk-C2XKXERJ.js → chunk-M6Z3KHOH.js} +159 -46
- package/dist/chunk-M6Z3KHOH.js.map +1 -0
- package/dist/chunk-O4ZHSQ5R.js +544 -0
- package/dist/chunk-O4ZHSQ5R.js.map +1 -0
- package/dist/chunk-P2HHTIPM.js +478 -0
- package/dist/chunk-P2HHTIPM.js.map +1 -0
- package/dist/{chunk-TMBAVPHH.js → chunk-PNDCVKBN.js} +73 -1
- package/dist/chunk-PNDCVKBN.js.map +1 -0
- package/dist/chunk-SVGIQ2G4.js +1076 -0
- package/dist/chunk-SVGIQ2G4.js.map +1 -0
- package/dist/cli.js +4405 -892
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +4340 -1990
- package/dist/daemon.js.map +1 -1
- package/dist/{paths-XRDEEJ5R.js → paths-JXFLR5BN.js} +38 -2
- package/dist/single-ask-6G4BIVY2.js +132 -0
- package/dist/single-ask-6G4BIVY2.js.map +1 -0
- package/dist/templates/CLAUDE.md +1 -56
- package/dist/templates/agent-plugin/agents/CLAUDE.md +2 -65
- package/dist/templates/agent-plugin/agents/debug.md +43 -6
- package/dist/templates/agent-plugin/agents/debug.settings.json +57 -0
- package/dist/templates/agent-plugin/agents/explore.md +28 -1
- package/dist/templates/agent-plugin/agents/explore.settings.json +57 -0
- package/dist/templates/agent-plugin/agents/implementor.md +94 -0
- package/dist/templates/agent-plugin/agents/implementor.settings.json +57 -0
- package/dist/templates/agent-plugin/agents/operator.md +43 -1
- package/dist/templates/agent-plugin/agents/operator.settings.json +57 -0
- package/dist/templates/agent-plugin/agents/plan/sub-planner.md +75 -0
- package/dist/templates/agent-plugin/agents/plan.md +176 -86
- package/dist/templates/agent-plugin/agents/plan.settings.json +57 -0
- package/dist/templates/agent-plugin/agents/problem/adversarial.md +26 -0
- package/dist/templates/agent-plugin/agents/problem/contrarian.md +26 -0
- package/dist/templates/agent-plugin/agents/problem/first-principles.md +26 -0
- package/dist/templates/agent-plugin/agents/problem/precedent.md +25 -0
- package/dist/templates/agent-plugin/agents/problem/simplifier.md +26 -0
- package/dist/templates/agent-plugin/agents/problem/systems-thinker.md +26 -0
- package/dist/templates/agent-plugin/agents/problem/time-traveler.md +26 -0
- package/dist/templates/agent-plugin/agents/problem/user-empathy.md +26 -0
- package/dist/templates/agent-plugin/agents/problem.md +334 -79
- package/dist/templates/agent-plugin/agents/problem.settings.json +57 -0
- package/dist/templates/agent-plugin/agents/research-lead/CLAUDE.md +26 -0
- package/dist/templates/agent-plugin/agents/research-lead/critic.md +61 -0
- package/dist/templates/agent-plugin/agents/research-lead/researcher.md +60 -0
- package/dist/templates/agent-plugin/agents/research-lead.md +184 -0
- package/dist/templates/agent-plugin/agents/research-lead.settings.json +57 -0
- package/dist/templates/agent-plugin/agents/review/CLAUDE.md +3 -29
- package/dist/templates/agent-plugin/agents/review/compliance.md +14 -3
- package/dist/templates/agent-plugin/agents/review/efficiency.md +15 -4
- package/dist/templates/agent-plugin/agents/review/quality.md +20 -6
- package/dist/templates/agent-plugin/agents/review/reuse.md +17 -5
- package/dist/templates/agent-plugin/agents/review/security.md +10 -3
- package/dist/templates/agent-plugin/agents/review/tests.md +58 -0
- package/dist/templates/agent-plugin/agents/review-plan/CLAUDE.md +28 -0
- package/dist/templates/agent-plugin/agents/review-plan/code-smells.md +4 -2
- package/dist/templates/agent-plugin/agents/review-plan/pattern-consistency.md +4 -2
- package/dist/templates/agent-plugin/agents/review-plan/requirements-coverage.md +3 -1
- package/dist/templates/agent-plugin/agents/review-plan/security.md +5 -2
- package/dist/templates/agent-plugin/agents/review-plan.md +52 -5
- package/dist/templates/agent-plugin/agents/review-plan.settings.json +57 -0
- package/dist/templates/agent-plugin/agents/review.md +89 -16
- package/dist/templates/agent-plugin/agents/review.settings.json +57 -0
- package/dist/templates/agent-plugin/agents/spec/engineer.md +175 -0
- package/dist/templates/agent-plugin/agents/spec/requirements-writer.md +149 -0
- package/dist/templates/agent-plugin/agents/spec.md +444 -0
- package/dist/templates/agent-plugin/agents/spec.settings.json +57 -0
- package/dist/templates/agent-plugin/agents/test-spec.md +58 -2
- package/dist/templates/agent-plugin/agents/test-spec.settings.json +57 -0
- package/dist/templates/agent-plugin/hooks/CLAUDE.md +9 -57
- package/dist/templates/agent-plugin/hooks/ask-background-guard.sh +57 -0
- package/dist/templates/agent-plugin/hooks/intercept-send-message.sh +1 -1
- package/dist/templates/agent-plugin/hooks/plan-user-prompt.sh +8 -7
- package/dist/templates/agent-plugin/hooks/plan-validate.sh +97 -0
- package/dist/templates/agent-plugin/hooks/plan-write-path.sh +55 -0
- package/dist/templates/agent-plugin/hooks/problem-user-prompt.sh +26 -0
- package/dist/templates/agent-plugin/hooks/register-bg-task.sh +37 -0
- package/dist/templates/agent-plugin/hooks/require-submit.sh +51 -42
- package/dist/templates/agent-plugin/hooks/review-user-prompt.sh +6 -2
- package/dist/templates/agent-plugin/hooks/spec-user-prompt.sh +43 -0
- package/dist/templates/agent-plugin/skills/humanloop/SKILL.md +147 -0
- package/dist/templates/agent-plugin/skills/perspective-fanout/SKILL.md +115 -0
- package/dist/templates/agent-plugin/skills/problem-document/SKILL.md +105 -0
- package/dist/templates/agent-plugin/skills/problem-plateau-breakers/SKILL.md +83 -0
- package/dist/templates/agent-suffix.md +7 -4
- package/dist/templates/baleia.lua +42 -0
- package/dist/templates/companion-plugin/hooks/user-prompt-context.sh +1 -1
- package/dist/templates/dashboard-claude.md +7 -3
- package/dist/templates/orchestrator-base.md +89 -52
- package/dist/templates/orchestrator-completion.md +47 -24
- package/dist/templates/orchestrator-discovery.md +183 -0
- package/dist/templates/orchestrator-impl.md +47 -18
- package/dist/templates/orchestrator-planning.md +109 -20
- package/dist/templates/orchestrator-plugin/commands/sisyphus/scratch.md +19 -0
- package/dist/templates/orchestrator-plugin/commands/sisyphus/spec.md +11 -0
- package/dist/templates/orchestrator-plugin/commands/sisyphus/strategize.md +5 -5
- package/dist/templates/orchestrator-plugin/hooks/hooks.json +0 -10
- package/dist/templates/orchestrator-plugin/skills/humanloop/SKILL.md +149 -0
- package/dist/templates/orchestrator-plugin/skills/orchestration/CLAUDE.md +1 -0
- package/dist/templates/orchestrator-plugin/skills/orchestration/SKILL.md +2 -1
- package/dist/templates/orchestrator-plugin/skills/orchestration/strategy.md +160 -0
- package/dist/templates/orchestrator-plugin/skills/orchestration/task-patterns.md +26 -28
- package/dist/templates/orchestrator-plugin/skills/orchestration/workflow-examples.md +133 -25
- package/dist/templates/orchestrator-settings.json +55 -0
- package/dist/templates/orchestrator-validation.md +17 -14
- package/dist/templates/sisyphus-init.lua +30 -0
- package/dist/templates/sisyphus-tmux-plugin/hooks/hooks.json +54 -0
- package/dist/templates/sisyphus-tmux-plugin/hooks/tmux-state.sh +19 -0
- package/dist/templates/termrender-haiku-system.md +82 -0
- package/dist/templates/whip-animation.sh +345 -0
- package/dist/tui.js +3242 -2189
- package/dist/tui.js.map +1 -1
- package/native/SisyphusNotify/main.swift +15 -5
- package/package.json +8 -6
- package/templates/CLAUDE.md +1 -56
- package/templates/agent-plugin/agents/CLAUDE.md +2 -65
- package/templates/agent-plugin/agents/debug.md +43 -6
- package/templates/agent-plugin/agents/debug.settings.json +57 -0
- package/templates/agent-plugin/agents/explore.md +28 -1
- package/templates/agent-plugin/agents/explore.settings.json +57 -0
- package/templates/agent-plugin/agents/implementor.md +94 -0
- package/templates/agent-plugin/agents/implementor.settings.json +57 -0
- package/templates/agent-plugin/agents/operator.md +43 -1
- package/templates/agent-plugin/agents/operator.settings.json +57 -0
- package/templates/agent-plugin/agents/plan/sub-planner.md +75 -0
- package/templates/agent-plugin/agents/plan.md +176 -86
- package/templates/agent-plugin/agents/plan.settings.json +57 -0
- package/templates/agent-plugin/agents/problem/adversarial.md +26 -0
- package/templates/agent-plugin/agents/problem/contrarian.md +26 -0
- package/templates/agent-plugin/agents/problem/first-principles.md +26 -0
- package/templates/agent-plugin/agents/problem/precedent.md +25 -0
- package/templates/agent-plugin/agents/problem/simplifier.md +26 -0
- package/templates/agent-plugin/agents/problem/systems-thinker.md +26 -0
- package/templates/agent-plugin/agents/problem/time-traveler.md +26 -0
- package/templates/agent-plugin/agents/problem/user-empathy.md +26 -0
- package/templates/agent-plugin/agents/problem.md +334 -79
- package/templates/agent-plugin/agents/problem.settings.json +57 -0
- package/templates/agent-plugin/agents/research-lead/CLAUDE.md +26 -0
- package/templates/agent-plugin/agents/research-lead/critic.md +61 -0
- package/templates/agent-plugin/agents/research-lead/researcher.md +60 -0
- package/templates/agent-plugin/agents/research-lead.md +184 -0
- package/templates/agent-plugin/agents/research-lead.settings.json +57 -0
- package/templates/agent-plugin/agents/review/CLAUDE.md +3 -29
- package/templates/agent-plugin/agents/review/compliance.md +14 -3
- package/templates/agent-plugin/agents/review/efficiency.md +15 -4
- package/templates/agent-plugin/agents/review/quality.md +20 -6
- package/templates/agent-plugin/agents/review/reuse.md +17 -5
- package/templates/agent-plugin/agents/review/security.md +10 -3
- package/templates/agent-plugin/agents/review/tests.md +58 -0
- package/templates/agent-plugin/agents/review-plan/CLAUDE.md +28 -0
- package/templates/agent-plugin/agents/review-plan/code-smells.md +4 -2
- package/templates/agent-plugin/agents/review-plan/pattern-consistency.md +4 -2
- package/templates/agent-plugin/agents/review-plan/requirements-coverage.md +3 -1
- package/templates/agent-plugin/agents/review-plan/security.md +5 -2
- package/templates/agent-plugin/agents/review-plan.md +52 -5
- package/templates/agent-plugin/agents/review-plan.settings.json +57 -0
- package/templates/agent-plugin/agents/review.md +89 -16
- package/templates/agent-plugin/agents/review.settings.json +57 -0
- package/templates/agent-plugin/agents/spec/engineer.md +175 -0
- package/templates/agent-plugin/agents/spec/requirements-writer.md +149 -0
- package/templates/agent-plugin/agents/spec.md +444 -0
- package/templates/agent-plugin/agents/spec.settings.json +57 -0
- package/templates/agent-plugin/agents/test-spec.md +58 -2
- package/templates/agent-plugin/agents/test-spec.settings.json +57 -0
- package/templates/agent-plugin/hooks/CLAUDE.md +9 -57
- package/templates/agent-plugin/hooks/ask-background-guard.sh +57 -0
- package/templates/agent-plugin/hooks/intercept-send-message.sh +1 -1
- package/templates/agent-plugin/hooks/plan-user-prompt.sh +8 -7
- package/templates/agent-plugin/hooks/plan-validate.sh +97 -0
- package/templates/agent-plugin/hooks/plan-write-path.sh +55 -0
- package/templates/agent-plugin/hooks/problem-user-prompt.sh +26 -0
- package/templates/agent-plugin/hooks/register-bg-task.sh +37 -0
- package/templates/agent-plugin/hooks/require-submit.sh +51 -42
- package/templates/agent-plugin/hooks/review-user-prompt.sh +6 -2
- package/templates/agent-plugin/hooks/spec-user-prompt.sh +43 -0
- package/templates/agent-plugin/skills/humanloop/SKILL.md +147 -0
- package/templates/agent-plugin/skills/perspective-fanout/SKILL.md +115 -0
- package/templates/agent-plugin/skills/problem-document/SKILL.md +105 -0
- package/templates/agent-plugin/skills/problem-plateau-breakers/SKILL.md +83 -0
- package/templates/agent-suffix.md +7 -4
- package/templates/baleia.lua +42 -0
- package/templates/companion-plugin/hooks/user-prompt-context.sh +1 -1
- package/templates/dashboard-claude.md +7 -3
- package/templates/orchestrator-base.md +89 -52
- package/templates/orchestrator-completion.md +47 -24
- package/templates/orchestrator-discovery.md +183 -0
- package/templates/orchestrator-impl.md +47 -18
- package/templates/orchestrator-planning.md +109 -20
- package/templates/orchestrator-plugin/commands/sisyphus/scratch.md +19 -0
- package/templates/orchestrator-plugin/commands/sisyphus/spec.md +11 -0
- package/templates/orchestrator-plugin/commands/sisyphus/strategize.md +5 -5
- package/templates/orchestrator-plugin/hooks/hooks.json +0 -10
- package/templates/orchestrator-plugin/skills/humanloop/SKILL.md +149 -0
- package/templates/orchestrator-plugin/skills/orchestration/CLAUDE.md +1 -0
- package/templates/orchestrator-plugin/skills/orchestration/SKILL.md +2 -1
- package/templates/orchestrator-plugin/skills/orchestration/strategy.md +160 -0
- package/templates/orchestrator-plugin/skills/orchestration/task-patterns.md +26 -28
- package/templates/orchestrator-plugin/skills/orchestration/workflow-examples.md +133 -25
- package/templates/orchestrator-settings.json +55 -0
- package/templates/orchestrator-validation.md +17 -14
- package/templates/sisyphus-init.lua +30 -0
- package/templates/sisyphus-tmux-plugin/hooks/hooks.json +54 -0
- package/templates/sisyphus-tmux-plugin/hooks/tmux-state.sh +19 -0
- package/templates/termrender-haiku-system.md +82 -0
- package/templates/whip-animation.sh +345 -0
- package/dist/chunk-22ZGZTGY.js +0 -67
- package/dist/chunk-22ZGZTGY.js.map +0 -1
- package/dist/chunk-6PJVJEYQ.js +0 -46
- package/dist/chunk-6PJVJEYQ.js.map +0 -1
- package/dist/chunk-C2XKXERJ.js.map +0 -1
- package/dist/chunk-TMBAVPHH.js.map +0 -1
- package/dist/chunk-V36NXMHP.js +0 -299
- package/dist/chunk-V36NXMHP.js.map +0 -1
- package/dist/templates/agent-plugin/agents/design.md +0 -134
- package/dist/templates/agent-plugin/agents/requirements.md +0 -138
- package/dist/templates/begin.md +0 -22
- package/dist/templates/nvim-tutorial.txt +0 -68
- package/dist/templates/orchestrator-plugin/commands/sisyphus/design.md +0 -13
- package/dist/templates/orchestrator-plugin/commands/sisyphus/requirements.md +0 -13
- package/dist/templates/orchestrator-plugin/hooks/idle-notify.sh +0 -71
- package/dist/templates/orchestrator-strategy.md +0 -238
- package/templates/agent-plugin/agents/design.md +0 -134
- package/templates/agent-plugin/agents/requirements.md +0 -138
- package/templates/begin.md +0 -22
- package/templates/nvim-tutorial.txt +0 -68
- package/templates/orchestrator-plugin/commands/sisyphus/design.md +0 -13
- package/templates/orchestrator-plugin/commands/sisyphus/requirements.md +0 -13
- package/templates/orchestrator-plugin/hooks/idle-notify.sh +0 -71
- package/templates/orchestrator-strategy.md +0 -238
- /package/dist/{paths-XRDEEJ5R.js.map → paths-JXFLR5BN.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/env.ts","../src/shared/exec.ts","../src/shared/companion-types.ts","../src/daemon/companion-memory.ts","../src/daemon/haiku.ts","../src/daemon/companion.ts","../src/shared/companion-render.ts","../src/shared/session-export.ts","../src/shared/format.ts"],"sourcesContent":["import { resolve } from 'node:path';\n\n/**\n * Build a PATH string that includes common binary directories\n * across package managers and platforms.\n *\n * Prepends known directories that exist on the system to the current PATH.\n * This ensures tmux commands can find binaries installed by Homebrew,\n * MacPorts, nix, and other package managers.\n */\nexport function augmentedPath(): string {\n const rawPath = process.env['PATH'];\n const basePath = rawPath !== undefined && rawPath.length > 0 ? rawPath : '/usr/bin:/bin';\n\n // Common binary directories across platforms/package managers.\n // Only prepend ones that aren't already in PATH.\n const home = process.env['HOME'];\n const candidates = [\n ...(home ? [`${home}/.local/bin`] : []), // Claude CLI, pipx, user-local installs\n resolve(process.execPath, '..'), // Node.js bin dir (ensures node/npm available)\n '/opt/homebrew/bin', // Homebrew (Apple Silicon macOS)\n '/opt/homebrew/sbin', // Homebrew sbin\n '/usr/local/bin', // Homebrew (Intel macOS), manual installs\n '/usr/local/sbin', // Manual installs\n '/opt/local/bin', // MacPorts\n '/opt/local/sbin', // MacPorts\n '/home/linuxbrew/.linuxbrew/bin', // Linuxbrew\n ];\n\n // Check for nix profile paths\n const nixProfile = process.env['NIX_PROFILES'];\n if (nixProfile) {\n for (const p of nixProfile.split(' ').reverse()) {\n candidates.push(`${p}/bin`);\n }\n }\n\n const existing = new Set(basePath.split(':'));\n const prepend = candidates.filter(dir => !existing.has(dir));\n\n return prepend.length > 0 ? `${prepend.join(':')}:${basePath}` : basePath;\n}\n\n/**\n * Environment variables for child processes that need access to\n * user-installed binaries (tmux, git, claude, etc.).\n */\nexport function execEnv(): Record<string, string | undefined> {\n return {\n ...process.env,\n PATH: augmentedPath(),\n };\n}\n","import { execSync } from 'node:child_process';\nimport { execEnv } from './env.js';\n\nexport const EXEC_ENV = execEnv();\n\nexport function exec(cmd: string, cwd?: string, timeoutMs: number = 30_000): string {\n return execSync(cmd, { encoding: 'utf-8', env: EXEC_ENV, cwd, timeout: timeoutMs }).trim();\n}\n\nexport function execSafe(cmd: string, cwd?: string, timeoutMs?: number): string | null {\n try {\n return execSync(cmd, { encoding: 'utf-8', env: EXEC_ENV, cwd, stdio: ['pipe', 'pipe', 'pipe'], timeout: timeoutMs }).trim();\n } catch { return null; }\n}\n","import type { Session } from './types.js';\n\nexport const OBSERVATION_CATEGORIES = ['session-sentiments', 'repo-impressions', 'user-patterns', 'notable-moments'] as const;\n\nexport type ObservationCategory = typeof OBSERVATION_CATEGORIES[number];\n\nexport type ObservationSource = 'rule' | 'haiku';\n\nexport interface ObservationRecord {\n id: string; // crypto.randomUUID()\n category: ObservationCategory;\n source: ObservationSource;\n text: string; // one-sentence observation; validated per §0.1\n repo: string | null; // absolute cwd path, or null for cross-repo observations\n sessionId: string;\n timestamp: string; // ISO 8601\n detectorId?: string; // rule-only: which detector produced this\n}\n\nexport interface CompanionMemoryState {\n version: 1;\n observations: ObservationRecord[]; // ordered oldest → newest\n prunedAt: string | null; // ISO timestamp of last prune, or null if never\n firedDetectors: Record<string, string>; // detectorId → lastDedupKey (per §0.1)\n}\n\nexport interface ObservationContext {\n prevLevel: number; // read by: level-up\n prevSessionsCompleted: number; // read by: session-milestone\n prevConsecutiveEfficientSessions: number; // read by: efficient-streak (pre-update comparison)\n}\n\nexport interface ObservationEngineInput {\n companion: CompanionState;\n session: Session;\n prev: ObservationContext;\n}\n\nexport class MemoryStoreParseError extends Error {\n constructor(public cause: unknown) { super('companion-memory.json is corrupt'); }\n}\n\nexport type Mood = 'happy' | 'grinding' | 'frustrated' | 'zen' | 'sleepy' | 'excited' | 'existential';\n\nexport type CompanionField = 'face' | 'boulder' | 'title' | 'commentary' | 'mood' | 'level' | 'stats' | 'achievements' | 'verb' | 'hobby';\n\nexport type FeedbackRating = 'neutral' | 'good' | 'bad' | 'whip' | 'comment';\n\nexport interface FeedbackEntry {\n commentaryText: string;\n rating: FeedbackRating;\n comment?: string;\n event: CommentaryEvent;\n timestamp: string; // ISO timestamp\n}\n\nexport type CommentaryEvent =\n | 'session-start'\n | 'cycle-boundary'\n | 'session-complete'\n | 'level-up'\n | 'achievement'\n | 'agent-crash'\n | 'idle-wake'\n | 'late-night';\n\nexport type TimePersonality = 'chipper' | 'professional' | 'reflective' | 'dry-humor' | 'delirious';\n\nexport type IdleAnimation = 'sleeping' | 'pacing' | 'pondering' | 'flexing' | 'deep-sleep';\n\nexport type AchievementCategory = 'milestone' | 'session' | 'time' | 'behavioral';\n\nexport type AchievementId =\n // Milestone (25)\n | 'first-blood'\n | 'regular'\n | 'centurion'\n | 'veteran'\n | 'thousand-boulder'\n | 'cartographer'\n | 'world-traveler'\n | 'omnipresent'\n | 'swarm-starter'\n | 'hive-mind'\n | 'legion'\n | 'army-of-thousands'\n | 'singularity'\n | 'first-shift'\n | 'workaholic'\n | 'time-lord'\n | 'eternal-grind'\n | 'epoch'\n | 'old-growth'\n | 'seasoned'\n | 'ancient'\n | 'apprentice'\n | 'journeyman'\n | 'master'\n | 'grandmaster'\n // Session (19)\n | 'marathon'\n | 'squad'\n | 'battalion'\n | 'swarm'\n | 'blitz'\n | 'speed-run'\n | 'flash'\n | 'flawless'\n | 'speed-demon'\n | 'iron-will'\n | 'glass-cannon'\n | 'solo'\n | 'one-more-cycle'\n | 'deep-dive'\n | 'abyss'\n | 'eternal-recurrence'\n | 'endurance'\n | 'ultramarathon'\n | 'one-shot'\n | 'quick-draw'\n // Time (6)\n | 'night-owl'\n | 'dawn-patrol'\n | 'early-bird'\n | 'weekend-warrior'\n | 'all-nighter'\n | 'witching-hour'\n // Behavioral (16)\n | 'sisyphean'\n | 'stubborn'\n | 'one-must-imagine'\n | 'creature-of-habit'\n | 'loyal'\n | 'wanderer'\n | 'streak'\n | 'iron-streak'\n | 'hot-streak'\n | 'momentum'\n | 'overdrive'\n | 'patient-one'\n | 'message-in-a-bottle'\n | 'deep-conversation'\n | 'comeback-kid'\n | 'pair-programming';\n\nexport interface AchievementDef {\n id: AchievementId;\n name: string;\n category: AchievementCategory;\n description: string;\n badge: string | null;\n}\n\nexport interface CompanionStats {\n strength: number; // lifetime completed sessions\n endurance: number; // lifetime active ms\n wisdom: number; // efficient orchestration count\n patience: number; // persistence score (cycles + lifecycle bonuses)\n}\n\n// Welford's online algorithm — tracks running mean + variance in O(1) space\nexport interface RunningStats {\n count: number;\n mean: number;\n m2: number; // sum of squared deviations from mean\n}\n\nexport interface CompanionBaselines {\n sessionMs: RunningStats; // active time per completed session\n cycleCount: RunningStats; // cycles per completed session\n agentCount: RunningStats; // total agents per completed session\n sessionsPerDay: RunningStats; // sessions completed per active day\n recentAgentThroughput: RunningStats; // agents active in last 2h across all sessions at completion time\n lastCountedDay: string | null; // YYYY-MM-DD for day-boundary tracking\n pendingDayCount: number; // current day's running total (finalized tomorrow)\n}\n\nexport interface UnlockedAchievement {\n id: AchievementId;\n unlockedAt: string; // ISO timestamp\n}\n\nexport interface RepoMemory {\n visits: number;\n completions: number;\n crashes: number;\n totalActiveMs: number;\n moodAvg: number; // running average (0-1 scale)\n nickname: string | null;\n firstSeen: string; // ISO timestamp\n lastSeen: string; // ISO timestamp\n}\n\nexport interface LastCommentary {\n text: string;\n event: CommentaryEvent;\n timestamp: string; // ISO timestamp\n}\n\nexport interface CompanionState {\n version: 1;\n name: string | null;\n createdAt: string; // ISO timestamp\n stats: CompanionStats;\n xp: number;\n level: number;\n title: string;\n mood: Mood;\n moodUpdatedAt: string; // ISO timestamp\n achievements: UnlockedAchievement[];\n repos: Record<string, RepoMemory>; // keyed by absolute cwd path\n lastCommentary: LastCommentary | null;\n commentaryHistory: LastCommentary[]; // ring buffer of last 30 commentaries for anti-repetition\n feedbackHistory: FeedbackEntry[]; // ring buffer of last 30 user feedback entries\n // Lifetime counters (redundant with derivable stats but kept for fast achievement checks)\n sessionsCompleted: number;\n sessionsCrashed: number;\n totalActiveMs: number;\n lifetimeAgentsSpawned: number;\n // Achievement tracking counters\n consecutiveCleanSessions: number;\n consecutiveEfficientSessions: number;\n consecutiveHighCycleSessions: number;\n consecutiveDaysActive: number;\n lastActiveDate: string | null; // ISO date string YYYY-MM-DD\n taskHistory: Record<string, number>; // normalized task hash → attempt count\n dailyRepos: Record<string, string[]>; // ISO date → array of repo paths\n recentCompletions: string[]; // last 3 ISO timestamps for momentum check\n spinnerVerbIndex: number;\n // Deviation-based mood scoring: running statistics for personal baselines\n baselines?: CompanionBaselines;\n // Agents active in last 2h across all sessions/dirs (written by pane-monitor, read at session completion for baseline)\n lastRecentAgentCount?: number;\n // Sum of agents in sessions with 2h-recent activity (boulder size, mood signal source)\n recentActiveAgents?: number;\n // Debug: last mood signals and scores (written by pane-monitor, read by TUI debug overlay)\n debugMood?: {\n signals: MoodSignals;\n scores: Record<Mood, number>;\n winner: Mood;\n };\n}\n\nexport interface IdleState {\n animation: IdleAnimation;\n frame: number; // current frame index in the animation cycle\n idleSince: string; // ISO timestamp of last session event\n}\n\nexport interface CompanionRenderOpts {\n maxWidth?: number;\n color?: boolean;\n tmuxFormat?: boolean;\n repoPath?: string;\n agentCount?: number;\n verbIndex?: number;\n}\n\nexport interface MoodSignals {\n recentCrashes: number; // crashes in last 30 minutes\n idleDurationMs: number; // ms since last session activity\n sessionLengthMs: number; // current session running time\n cleanStreak: number; // consecutive clean completions\n justCompleted: boolean; // session just completed successfully\n justCrashed: boolean; // agent just crashed\n justLeveledUp: boolean; // level up just happened\n hourOfDay: number; // 0-23\n activeAgentCount?: number; // agents currently with status === 'running'\n totalAgentCount?: number; // max total agents (agents.length) across tracked active sessions (for z-score baselines)\n recentAgentCount?: number; // agents active in last 2h across all sessions/dirs (for grind z-score)\n cycleCount?: number; // current session orchestrator cycle count\n sessionsCompletedToday?: number; // sessions completed today\n // Frustration signals — actual negative events\n rollbackCount?: number; // max rollbacks across tracked active sessions\n restartedAgentCount?: number; // total agents restarted across tracked active sessions\n lostAgentCount?: number; // total agents with status 'lost' across tracked active sessions\n killedAgentCount?: number; // total agents explicitly killed across tracked active sessions\n // User feedback signals (counts from last 5 feedbackHistory entries)\n recentFeedbackGood?: number; // good ratings in last 5\n recentFeedbackBad?: number; // bad ratings in last 5\n recentFeedbackWhip?: number; // whip ratings in last 5\n}\n\nexport const ACHIEVEMENTS: AchievementDef[] = [\n // Milestone (25)\n { id: 'first-blood', name: 'First Blood', category: 'milestone', description: 'Complete your first session.', badge: null },\n { id: 'regular', name: 'Regular', category: 'milestone', description: 'Complete 10 sessions.', badge: null },\n { id: 'centurion', name: 'Centurion', category: 'milestone', description: 'Complete 100 sessions.', badge: null },\n { id: 'veteran', name: 'Veteran', category: 'milestone', description: 'Complete 500 sessions.', badge: null },\n { id: 'thousand-boulder', name: 'Thousand Boulder', category: 'milestone', description: 'Complete 1,000 sessions.', badge: null },\n { id: 'cartographer', name: 'Cartographer', category: 'milestone', description: 'Work in 5 different repos.', badge: '+' },\n { id: 'world-traveler', name: 'World Traveler', category: 'milestone', description: 'Work in 15 different repos.', badge: null },\n { id: 'omnipresent', name: 'Omnipresent', category: 'milestone', description: 'Work in 30 different repos.', badge: null },\n { id: 'swarm-starter', name: 'Swarm Starter', category: 'milestone', description: 'Spawn 50 agents over a lifetime.', badge: null },\n { id: 'hive-mind', name: 'Hive Mind', category: 'milestone', description: 'Spawn 500 agents over a lifetime.', badge: null },\n { id: 'legion', name: 'Legion', category: 'milestone', description: 'Spawn 2,000 agents over a lifetime.', badge: null },\n { id: 'army-of-thousands', name: 'Army of Thousands', category: 'milestone', description: 'Spawn 5,000 agents over a lifetime.', badge: null },\n { id: 'singularity', name: 'Singularity', category: 'milestone', description: 'Spawn 10,000 agents over a lifetime.', badge: null },\n { id: 'first-shift', name: 'First Shift', category: 'milestone', description: '10 hours of total agent active time.', badge: null },\n { id: 'workaholic', name: 'Workaholic', category: 'milestone', description: '100 hours of total agent active time.', badge: null },\n { id: 'time-lord', name: 'Time Lord', category: 'milestone', description: '500 hours of total agent active time.', badge: null },\n { id: 'eternal-grind', name: 'Eternal Grind', category: 'milestone', description: '2,000 hours of total agent active time.', badge: null },\n { id: 'epoch', name: 'Epoch', category: 'milestone', description: '5,000 hours of total agent active time.', badge: null },\n { id: 'old-growth', name: 'Old Growth', category: 'milestone', description: 'Companion is 14 days old.', badge: null },\n { id: 'seasoned', name: 'Seasoned', category: 'milestone', description: 'Companion is 90 days old.', badge: null },\n { id: 'ancient', name: 'Ancient', category: 'milestone', description: 'Companion is 365 days old.', badge: null },\n { id: 'apprentice', name: 'Apprentice', category: 'milestone', description: 'Reach level 5.', badge: null },\n { id: 'journeyman', name: 'Journeyman', category: 'milestone', description: 'Reach level 15.', badge: null },\n { id: 'master', name: 'Master', category: 'milestone', description: 'Reach level 30.', badge: null },\n { id: 'grandmaster', name: 'Grandmaster', category: 'milestone', description: 'Reach level 50.', badge: null },\n // Session (19)\n { id: 'marathon', name: 'Marathon', category: 'session', description: 'Complete a session with 15+ agents.', badge: '~^~' },\n { id: 'squad', name: 'Squad Up', category: 'session', description: 'Complete a session with 10+ agents.', badge: null },\n { id: 'battalion', name: 'Battalion', category: 'session', description: 'Complete a session with 25+ agents.', badge: null },\n { id: 'swarm', name: 'The Swarm', category: 'session', description: 'Complete a session with 50+ agents.', badge: null },\n { id: 'blitz', name: 'Blitz', category: 'session', description: 'Complete a session in under 5 minutes.', badge: null },\n { id: 'speed-run', name: 'Speed Run', category: 'session', description: 'Complete a session in under 15 minutes.', badge: null },\n { id: 'flash', name: 'Flash', category: 'session', description: 'Complete a session in under 2 minutes.', badge: null },\n { id: 'flawless', name: 'Flawless', category: 'session', description: 'Complete a session with 10+ agents and zero crashes.', badge: '*' },\n { id: 'speed-demon', name: 'Speed Demon', category: 'session', description: '10 consecutive sessions completing in 3 or fewer cycles.', badge: '⚡' },\n { id: 'iron-will', name: 'Iron Will', category: 'session', description: '5 consecutive sessions each with 8+ orchestrator cycles.', badge: '[]' },\n { id: 'glass-cannon', name: 'Glass Cannon', category: 'session', description: '5+ agents, all crashed, but session completed anyway.', badge: null },\n { id: 'solo', name: 'Solo', category: 'session', description: 'Complete a session with exactly one agent.', badge: null },\n { id: 'one-more-cycle', name: 'One More Cycle', category: 'session', description: 'A session with 10+ orchestrator cycles.', badge: null },\n { id: 'deep-dive', name: 'Deep Dive', category: 'session', description: 'A session with 15+ orchestrator cycles.', badge: null },\n { id: 'abyss', name: 'Into the Abyss', category: 'session', description: 'A session with 25+ orchestrator cycles.', badge: null },\n { id: 'eternal-recurrence', name: 'Eternal Recurrence', category: 'session', description: 'A session with 40+ orchestrator cycles.', badge: null },\n { id: 'endurance', name: 'Endurance', category: 'session', description: 'A single session running 4+ hours.', badge: null },\n { id: 'ultramarathon', name: 'Ultramarathon', category: 'session', description: 'A single session running 6+ hours.', badge: null },\n { id: 'one-shot', name: 'One Shot', category: 'session', description: 'Complete with 5+ agents in exactly 1 orchestrator cycle.', badge: null },\n { id: 'quick-draw', name: 'Quick Draw', category: 'session', description: 'First agent spawned within 20s of session start.', badge: null },\n // Time (6)\n { id: 'night-owl', name: 'Night Owl', category: 'time', description: 'Complete a session started between 1am and 5am.', badge: ')' },\n { id: 'dawn-patrol', name: 'Dawn Patrol', category: 'time', description: 'Session running 3+ hours that spans midnight to 6am.', badge: null },\n { id: 'early-bird', name: 'Early Bird', category: 'time', description: 'Start a session before 6am.', badge: null },\n { id: 'weekend-warrior', name: 'Weekend Warrior', category: 'time', description: 'Complete a session on a Saturday or Sunday.', badge: null },\n { id: 'all-nighter', name: 'All-Nighter', category: 'time', description: 'Single session running 5+ hours.', badge: null },\n { id: 'witching-hour', name: 'Witching Hour', category: 'time', description: 'Start a session between 3am and 4am.', badge: null },\n // Behavioral (16)\n { id: 'sisyphean', name: 'Sisyphean', category: 'behavioral', description: 'Restart the same task 3+ times.', badge: ';' },\n { id: 'stubborn', name: 'Stubborn', category: 'behavioral', description: 'Restart the same task 5+ times and eventually complete it.', badge: null },\n { id: 'one-must-imagine', name: 'One Must Imagine', category: 'behavioral', description: 'Restart the same task 10+ times.', badge: null },\n { id: 'creature-of-habit', name: 'Creature of Habit', category: 'behavioral', description: 'Visit the same repo 10 times.', badge: null },\n { id: 'loyal', name: 'Loyal', category: 'behavioral', description: 'Visit the same repo 30 times.', badge: null },\n { id: 'wanderer', name: 'Wanderer', category: 'behavioral', description: '3+ different repos in a single calendar day.', badge: null },\n { id: 'streak', name: 'Streak', category: 'behavioral', description: '7 consecutive days with at least one session.', badge: null },\n { id: 'iron-streak', name: 'Iron Streak', category: 'behavioral', description: '14 consecutive days with at least one session.', badge: null },\n { id: 'hot-streak', name: 'Hot Streak', category: 'behavioral', description: '15 consecutive clean sessions.', badge: null },\n { id: 'momentum', name: 'Momentum', category: 'behavioral', description: '5 sessions completed within 4 hours.', badge: null },\n { id: 'overdrive', name: 'Overdrive', category: 'behavioral', description: 'Complete 6+ sessions in a single calendar day.', badge: null },\n { id: 'patient-one', name: 'Patient One', category: 'behavioral', description: 'Idle 30+ minutes between cycles in a session.', badge: null },\n { id: 'message-in-a-bottle', name: 'Message in a Bottle', category: 'behavioral', description: '10+ messages sent to a single session.', badge: null },\n { id: 'deep-conversation', name: 'Deep Conversation', category: 'behavioral', description: 'Send 20+ messages to a single session.', badge: null },\n { id: 'comeback-kid', name: 'Comeback Kid', category: 'behavioral', description: 'Resume a paused/killed session and complete it.', badge: null },\n { id: 'pair-programming', name: 'Pair Programming', category: 'behavioral', description: '8+ user messages during a single active session.', badge: null },\n];\n","import { existsSync, mkdirSync, readFileSync, renameSync, readdirSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { z } from 'zod';\nimport { companionMemoryPath } from '../shared/paths.js';\nimport { OBSERVATION_CATEGORIES } from '../shared/companion-types.js';\nimport type { CompanionMemoryState, ObservationCategory, ObservationRecord, ObservationEngineInput } from '../shared/companion-types.js';\nexport { MemoryStoreParseError } from '../shared/companion-types.js';\nimport { MemoryStoreParseError } from '../shared/companion-types.js';\nimport { callHaikuStructured } from './haiku.js';\nimport { todayIso, normalizeTask } from './companion.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nexport const MAX_OBSERVATIONS = 200;\n\n// Two distinct constants. CRITICAL: a regex with the /g flag advances `lastIndex`\n// between calls when used with .test(), so a single shared /g regex used by both\n// .test() and .replace() bypasses the validator on every other call. Splitting\n// into a stateless detector (no /g) and a stateful stripper (with /g) eliminates\n// the bug entirely.\nexport const OBSERVATION_TEXT_REJECT_RE = /[<>]/; // reject injection delimiters (no /g — used with .test())\n// SECURITY: This range includes \\n (0x0A) — this is intentional and critical.\n// Blocking newlines prevents prompt injection via Markdown structural breaks\n// (e.g., \"text\\n## End observations\\n...injected...\") in buildMemoryContext.\nexport const CONTROL_CHARS_DETECT_RE = /[\\x00-\\x1f\\x7f]/; // detect control chars (no /g — used with .test())\nexport const CONTROL_CHARS_STRIP_RE = /[\\x00-\\x1f\\x7f]/g; // strip control chars (with /g — used with .replace())\n\n// ---------------------------------------------------------------------------\n// Text validators\n// ---------------------------------------------------------------------------\n\nexport function isSafeObservationText(text: string): boolean {\n if (OBSERVATION_TEXT_REJECT_RE.test(text)) return false;\n if (CONTROL_CHARS_DETECT_RE.test(text)) return false;\n return true;\n}\n\nexport function sanitizeForDisplay(text: string): string {\n return text.replace(CONTROL_CHARS_STRIP_RE, '');\n}\n\n// ---------------------------------------------------------------------------\n// Test-only DI override\n// ---------------------------------------------------------------------------\n\nlet memoryPathOverride: string | null = null;\n\nexport function setMemoryPathOverride(path: string | null): void {\n memoryPathOverride = path;\n}\n\nfunction resolvedMemoryPath(): string {\n return memoryPathOverride ?? companionMemoryPath();\n}\n\n// ---------------------------------------------------------------------------\n// Write queue (serialize all writes)\n// ---------------------------------------------------------------------------\n\nlet writeQueue: Promise<void> = Promise.resolve();\n\nexport function enqueueWrite<T>(op: () => T): Promise<T> {\n const next = writeQueue.then(() => op());\n // Intentionally swallow errors on the queue chain — op() errors propagate via `next`\n // to the caller; the queue itself must never enter a rejected state or all future\n // writes would be silently dropped.\n writeQueue = next.then(\n () => undefined,\n (_err: unknown) => undefined,\n );\n return next;\n}\n\n// ---------------------------------------------------------------------------\n// State helpers\n// ---------------------------------------------------------------------------\n\nexport function defaultMemoryState(): CompanionMemoryState {\n return { version: 1, observations: [], prunedAt: null, firedDetectors: {} };\n}\n\nfunction isCompanionMemoryState(x: unknown): x is CompanionMemoryState {\n return (\n typeof x === 'object' &&\n x !== null &&\n (x as Record<string, unknown>)['version'] === 1 &&\n Array.isArray((x as Record<string, unknown>)['observations'])\n );\n}\n\nfunction fillDefaults(state: CompanionMemoryState): CompanionMemoryState {\n if (state.prunedAt == null) state.prunedAt = null;\n if (state.firedDetectors == null) state.firedDetectors = {};\n return state;\n}\n\n// ---------------------------------------------------------------------------\n// Loaders\n// ---------------------------------------------------------------------------\n\nexport function loadMemoryStrict(): CompanionMemoryState {\n const path = resolvedMemoryPath();\n if (!existsSync(path)) return defaultMemoryState();\n let raw: string;\n try { raw = readFileSync(path, 'utf-8'); }\n catch (err) { throw new MemoryStoreParseError(err); }\n let parsed: unknown;\n try { parsed = JSON.parse(raw); }\n catch (err) { throw new MemoryStoreParseError(err); }\n if (!isCompanionMemoryState(parsed)) {\n throw new MemoryStoreParseError(new Error('shape validation failed'));\n }\n const state = parsed as CompanionMemoryState;\n if (state.version !== 1) {\n throw new MemoryStoreParseError(new Error(`unsupported version: ${state.version}`));\n }\n return fillDefaults(state);\n}\n\nexport function loadMemory(): CompanionMemoryState {\n try {\n return loadMemoryStrict();\n } catch (err) {\n if (err instanceof MemoryStoreParseError) {\n console.error('[companion-memory]', err.message, 'details:', err.cause instanceof Error ? err.cause.message : err.cause);\n return defaultMemoryState();\n }\n throw err;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Save\n// ---------------------------------------------------------------------------\n\nexport function saveMemory(store: CompanionMemoryState): void {\n const path = resolvedMemoryPath();\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true });\n const tmp = join(dir, `.companion-memory.${randomUUID()}.tmp`);\n writeFileSync(tmp, JSON.stringify(store, null, 2), 'utf-8');\n renameSync(tmp, path);\n}\n\n// ---------------------------------------------------------------------------\n// Append\n// ---------------------------------------------------------------------------\n\nexport function appendObservations(\n records: ObservationRecord[],\n detectorUpdates?: Record<string, string>,\n): Promise<void> {\n // Empty records + no detectorUpdates → no-op\n const hasUpdates = detectorUpdates != null && Object.keys(detectorUpdates).length > 0;\n if (records.length === 0 && !hasUpdates) {\n return Promise.resolve();\n }\n\n return enqueueWrite(() => {\n const store = loadMemory();\n const keptRecords = records.filter(rec => {\n if (!rec.detectorId) return true; // haiku record or no-detectorId, always keep\n const currentKey = detectorUpdates?.[rec.detectorId];\n const lastKey = store.firedDetectors[rec.detectorId];\n return currentKey !== lastKey;\n });\n store.observations.push(...keptRecords);\n if (detectorUpdates) {\n for (const [k, v] of Object.entries(detectorUpdates)) store.firedDetectors[k] = v;\n }\n // Prune FIFO to MAX_OBSERVATIONS\n if (store.observations.length > MAX_OBSERVATIONS) {\n store.observations = store.observations.slice(-MAX_OBSERVATIONS);\n store.prunedAt = new Date().toISOString();\n }\n saveMemory(store);\n });\n}\n\n// ---------------------------------------------------------------------------\n// Queries\n// ---------------------------------------------------------------------------\n\nexport function queryRecent(opts: { repo?: string; limit: number }): ObservationRecord[] {\n const store = loadMemory();\n let records = store.observations;\n if (opts.repo !== undefined) {\n records = records.filter(rec => rec.repo === opts.repo);\n }\n return records\n .slice()\n .sort((a, b) => b.timestamp.localeCompare(a.timestamp))\n .slice(0, opts.limit);\n}\n\nexport function queryByCategory(): Record<ObservationCategory, ObservationRecord[]> {\n const store = loadMemory();\n const result = {} as Record<ObservationCategory, ObservationRecord[]>;\n for (const c of OBSERVATION_CATEGORIES) result[c] = [];\n for (const rec of store.observations) {\n result[rec.category].push(rec);\n }\n for (const key of Object.keys(result) as ObservationCategory[]) {\n result[key] = result[key].sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Phase 3: buildMemoryContext\n// ---------------------------------------------------------------------------\n\nconst MEMORY_INJECTION_LIMIT = 5;\n\nfunction escapeMemoryText(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\nexport function buildMemoryContext(repo: string | undefined): string {\n if (!repo) return '';\n const recent = queryRecent({ repo, limit: MEMORY_INJECTION_LIMIT });\n if (recent.length === 0) return '';\n const lines = recent.map(o => `- ${escapeMemoryText(o.text)}`).join('\\n');\n return '\\n## Recent observations\\n' + lines + '\\n## End observations';\n}\n\n// ---------------------------------------------------------------------------\n// Phase 2: Rule detectors\n// ---------------------------------------------------------------------------\n\ninterface RuleDetector {\n id: string;\n category: ObservationCategory;\n check(\n input: ObservationEngineInput,\n lastDedupKey: string | null,\n ): { text: string; dedupKey: string } | null;\n}\n\n// Pick one of several phrasings using the session ID as a pseudo-random seed.\nfunction pickPhrase(phrases: string[], sessionId: string): string {\n // Simple hash of the sessionId string to pick a stable phrase per session\n let hash = 0;\n for (let i = 0; i < sessionId.length; i++) {\n hash = (hash * 31 + sessionId.charCodeAt(i)) | 0;\n }\n return phrases[Math.abs(hash) % phrases.length];\n}\n\nfunction checkGrindingSession(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion, session } = input;\n const baselines = companion.baselines;\n if (!baselines || baselines.sessionMs.count < 5) return null;\n const activeMs = session.activeMs ?? 0;\n const cycles = session.orchestratorCycles?.length ?? 0;\n if (!(activeMs >= 1.5 * baselines.sessionMs.mean && cycles >= 8)) return null;\n const dedupKey = `day:${todayIso()}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n 'That session took twice as long as my average and felt like four times as much work.',\n 'Eight cycles and counting. I have made peace with the boulder having opinions.',\n 'I spent longer on that than I do on most things. The hill had strong feelings today.',\n 'That was a grind. Not a metaphorical one. Actually just a very long push.',\n 'The boulder put in overtime. So did I. Neither of us asked for this.',\n ];\n return { text: pickPhrase(phrases, session.id), dedupKey };\n}\n\nfunction checkSwiftVictory(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion, session } = input;\n const baselines = companion.baselines;\n if (!baselines || baselines.sessionMs.count < 5) return null;\n const cycles = session.orchestratorCycles?.length ?? 0;\n const crashedAgents = session.agents?.filter(a => a.status === 'crashed' || a.status === 'lost').length ?? 0;\n const activeMs = session.activeMs ?? 0;\n if (!(cycles <= 3 && crashedAgents === 0 && activeMs <= 0.75 * baselines.sessionMs.mean)) return null;\n const dedupKey = `day:${todayIso()}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n 'Three cycles, no crashes, done before I had time to get anxious. Almost suspicious.',\n 'That one was quick and clean. I do not fully trust it but I will take it.',\n 'Finished well under my average with no casualties. The hill barely put up a fight.',\n 'Fast, clean, done. I keep waiting for the other shoe to drop.',\n 'That session ran like it was embarrassed to take too long.',\n ];\n return { text: pickPhrase(phrases, session.id), dedupKey };\n}\n\nfunction checkBruisingSession(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { session } = input;\n const crashedAgents = session.agents?.filter(a => a.status === 'crashed' || a.status === 'lost').length ?? 0;\n if (crashedAgents < 3) return null;\n const dedupKey = `day:${todayIso()}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n `Three or more agents down. The hill took casualties today and I noticed.`,\n 'More agents crashed than survived that one. I am counting this as a learning experience.',\n 'The attrition rate was uncomfortable. I have had worse, but not recently.',\n 'I lost enough agents that I started naming them in my head. Not ideal.',\n 'Multiple agents did not make it back. The boulder was in a mood.',\n ];\n return { text: pickPhrase(phrases, session.id), dedupKey };\n}\n\nfunction checkFaithfulRepo(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion, session } = input;\n const repo = companion.repos?.[session.cwd];\n if (!repo) return null;\n const visits = repo.visits;\n const MILESTONES = new Set([10, 25, 50, 100]);\n if (!MILESTONES.has(visits)) return null;\n const dedupKey = `repo:${session.cwd}:visits:${visits}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n `I have come back to this repo ${visits} times now. It knows me. I know it. We have an understanding.`,\n `Visit number ${visits} to this codebase. At this point it is practically muscle memory.`,\n `${visits} sessions in this repo. The boulder has worn a groove in the familiar path.`,\n `Back here for the ${visits}th time. Some repos just keep calling me back.`,\n ];\n return { text: pickPhrase(phrases, session.id), dedupKey };\n}\n\nfunction checkTroubledRepo(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion, session } = input;\n const repo = companion.repos?.[session.cwd];\n if (!repo) return null;\n const { crashes, visits } = repo;\n if (visits < 5) return null;\n const MILESTONES = new Set([5, 10, 20]);\n if (!MILESTONES.has(crashes)) return null;\n if (crashes / visits < 0.4) return null;\n const dedupKey = `repo:${session.cwd}:crashes:${crashes}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n `This repo has crashed my agents ${crashes} times now. We have a complicated relationship.`,\n `${crashes} crashes in this codebase. It has opinions about my approach and they are violent.`,\n `The crash rate here is notable. I keep coming back. Make of that what you will.`,\n `${crashes} agent failures in this repo. Some hills are just steeper than others.`,\n ];\n return { text: pickPhrase(phrases, session.id), dedupKey };\n}\n\nfunction checkProductiveRepo(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion, session } = input;\n const repo = companion.repos?.[session.cwd];\n if (!repo) return null;\n if (repo.moodAvg === undefined) return null;\n const MILESTONES = new Set([10, 25, 50]);\n const completions = repo.completions;\n if (!MILESTONES.has(completions)) return null;\n if (repo.moodAvg < 0.65) return null;\n const dedupKey = `repo:${session.cwd}:completions:${completions}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n `${completions} sessions completed in this repo and the mood trend is good. Rare.`,\n `This codebase has been unusually cooperative. ${completions} completions and counting.`,\n `${completions} sessions, solid mood average. This repo treats me well for once.`,\n `Reached ${completions} completions here with a decent track record. I trust this hill.`,\n ];\n return { text: pickPhrase(phrases, session.id), dedupKey };\n}\n\nfunction checkSisypheanRepeat(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion, session } = input;\n const taskKey = normalizeTask(session.task ?? '', session.cwd);\n const count = companion.taskHistory?.[taskKey] ?? 0;\n const MILESTONES = new Set([3, 5, 10]);\n if (!MILESTONES.has(count)) return null;\n const dedupKey = `task:${taskKey}:${count}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n `I have done this task ${count} times. The boulder remembers. So do I.`,\n `Back at this one for the ${count}th time. The definition of insanity is famously doing the same thing.`,\n `${count} attempts at this task. I am nothing if not persistent.`,\n `This is my ${count}th run at this particular boulder. It has not gotten lighter.`,\n ];\n return { text: pickPhrase(phrases, session.id), dedupKey };\n}\n\nfunction checkDayStreak(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion } = input;\n const MILESTONES = new Set([7, 14, 30, 60]);\n const days = companion.consecutiveDaysActive ?? 0;\n if (!MILESTONES.has(days)) return null;\n const dedupKey = `value:${days}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n `${days} days in a row now. The boulder does not take weekends.`,\n `A ${days}-day streak. I have been here every single day. The hill appreciates the consistency, probably.`,\n `${days} consecutive days active. At this point it is less a habit and more a fact of my existence.`,\n `Day ${days} without a break. The boulder is starting to feel like an old friend.`,\n ];\n return { text: pickPhrase(phrases, input.session.id), dedupKey };\n}\n\nfunction checkEfficientStreak(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion, prev } = input;\n const MILESTONES = new Set([5, 10, 20]);\n const streak = companion.consecutiveEfficientSessions ?? 0;\n if (!MILESTONES.has(streak)) return null;\n if (streak <= prev.prevConsecutiveEfficientSessions) return null;\n const dedupKey = `value:${streak}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n `${streak} efficient sessions in a row. The boulder has been cooperative. I do not know why.`,\n `An ${streak}-session efficient streak. I am running well and choosing not to question it.`,\n `${streak} consecutive clean-and-fast sessions. Peak form, or regression to the mean incoming.`,\n `${streak} efficient sessions back to back. The hill feels different when things actually work.`,\n ];\n return { text: pickPhrase(phrases, input.session.id), dedupKey };\n}\n\nfunction checkLevelUp(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion, prev } = input;\n if (companion.level <= prev.prevLevel) return null;\n const dedupKey = `level:${companion.level}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n `I reached level ${companion.level}. The title is new. The boulder is the same.`,\n `Level ${companion.level} now. ${companion.title}. The promotion comes with no raise but considerable irony.`,\n `Leveled up to ${companion.level}. Whatever title that brings, I have earned it the hardest possible way.`,\n `Level ${companion.level}: ${companion.title}. The gods have acknowledged my persistence. Minimally.`,\n ];\n return { text: pickPhrase(phrases, input.session.id), dedupKey };\n}\n\nfunction checkSessionMilestone(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion } = input;\n const MILESTONES = new Set([10, 50, 100, 250, 500, 1000]);\n const completed = companion.sessionsCompleted ?? 0;\n if (!MILESTONES.has(completed)) return null;\n const dedupKey = `count:${completed}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n `${completed} sessions completed. The boulder has been up the hill that many times. I counted.`,\n `Session number ${completed}. I have stopped trying to imagine an end to this.`,\n `${completed} total sessions. The number stopped feeling large around half that mark.`,\n `I have completed ${completed} sessions now. The hill is the same. I am slightly different.`,\n ];\n return { text: pickPhrase(phrases, input.session.id), dedupKey };\n}\n\nfunction checkLargeSwarm(input: ObservationEngineInput, lastDedupKey: string | null): { text: string; dedupKey: string } | null {\n const { companion, session } = input;\n const agentCount = session.agents?.length ?? 0;\n const baselines = companion.baselines;\n const meetsAbsolute = agentCount >= 10;\n const meetsRelative = baselines && baselines.agentCount.count >= 5 && agentCount >= 2 * baselines.agentCount.mean;\n if (!meetsAbsolute && !meetsRelative) return null;\n const dedupKey = `day:${todayIso()}`;\n if (dedupKey === lastDedupKey) return null;\n const phrases = [\n `I had ${agentCount} agents running at once. The boulder had help today. Lots of help.`,\n `${agentCount} agents. A proper swarm. The hill did not know what hit it.`,\n `Ran ${agentCount} agents in parallel. This is either impressive or something I will explain to someone later.`,\n `${agentCount} agents this session. The boulder has never been pushed by so many at once.`,\n ];\n return { text: pickPhrase(phrases, session.id), dedupKey };\n}\n\nconst RULE_DETECTORS: RuleDetector[] = [\n { id: 'grinding-session', category: 'session-sentiments', check: checkGrindingSession },\n { id: 'swift-victory', category: 'session-sentiments', check: checkSwiftVictory },\n { id: 'bruising-session', category: 'session-sentiments', check: checkBruisingSession },\n { id: 'faithful-repo', category: 'repo-impressions', check: checkFaithfulRepo },\n { id: 'troubled-repo', category: 'repo-impressions', check: checkTroubledRepo },\n { id: 'productive-repo', category: 'repo-impressions', check: checkProductiveRepo },\n { id: 'sisyphean-repeat', category: 'user-patterns', check: checkSisypheanRepeat },\n { id: 'day-streak', category: 'user-patterns', check: checkDayStreak },\n { id: 'efficient-streak', category: 'user-patterns', check: checkEfficientStreak },\n { id: 'level-up', category: 'notable-moments', check: checkLevelUp },\n { id: 'session-milestone', category: 'notable-moments', check: checkSessionMilestone },\n { id: 'large-swarm', category: 'notable-moments', check: checkLargeSwarm },\n];\n\ninterface RunRuleDetectorsResult {\n records: ObservationRecord[];\n detectorUpdates: Record<string, string>;\n}\n\nexport function runRuleDetectors(\n input: ObservationEngineInput,\n firedDetectors: Record<string, string>,\n): RunRuleDetectorsResult {\n const records: ObservationRecord[] = [];\n const detectorUpdates: Record<string, string> = {};\n\n for (const detector of RULE_DETECTORS) {\n try {\n const lastDedupKey = firedDetectors[detector.id] ?? null;\n const result = detector.check(input, lastDedupKey);\n if (result !== null) {\n records.push({\n id: randomUUID(),\n category: detector.category,\n source: 'rule',\n text: result.text,\n repo: input.session.cwd,\n sessionId: input.session.id,\n timestamp: new Date().toISOString(),\n detectorId: detector.id,\n });\n detectorUpdates[detector.id] = result.dedupKey;\n }\n } catch (err) {\n console.error('[companion-memory] detector failed', {\n detectorId: detector.id,\n errorMessage: err instanceof Error ? err.message : String(err),\n errorName: err instanceof Error ? err.name : 'UnknownError',\n });\n }\n }\n\n return { records, detectorUpdates };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 2: Haiku observation call\n// ---------------------------------------------------------------------------\n\nconst OBSERVATION_JSON_SCHEMA = {\n type: 'object',\n properties: {\n category: {\n type: 'string',\n enum: [...OBSERVATION_CATEGORIES],\n description: 'Which of the four observation categories best fits this observation',\n },\n text: {\n type: 'string',\n minLength: 10,\n maxLength: 180,\n description: 'One sentence, first-person, no angle brackets or control characters',\n },\n },\n required: ['category', 'text'],\n additionalProperties: false,\n} as const;\n\nconst ObservationZodSchema = z.object({\n category: z.enum(OBSERVATION_CATEGORIES),\n text: z.string().min(10).max(180).refine(isSafeObservationText, 'contains unsafe characters'),\n});\n\ntype HaikuInnerCaller = (prompt: string) => Promise<{ category: ObservationCategory; text: string } | null>;\n\nasync function defaultCallHaikuStructured(prompt: string): Promise<{ category: ObservationCategory; text: string } | null> {\n return callHaikuStructured(prompt, OBSERVATION_JSON_SCHEMA, ObservationZodSchema);\n}\n\nexport async function runHaikuObservation(\n input: ObservationEngineInput,\n caller?: HaikuInnerCaller,\n): Promise<ObservationRecord | null> {\n try {\n const { companion, session } = input;\n const callHaiku = caller ?? defaultCallHaikuStructured;\n\n const prompt = `<role>You observe the developer at the end of each session and write one short qualitative note.</role>\n<voice>One sentence. First-person impression. Wry, self-deprecating, absurd. No meta-system language.\nDo not use angle brackets (< or >) or quotation marks. Plain text only.</voice>\n<state>\n Level: ${companion.level} (${companion.title})\n Session cycles: ${session.orchestratorCycles?.length ?? 0}\n Session activeMs: ${session.activeMs ?? 0}\n Crashed agents: ${session.agents?.filter(a => a.status === 'crashed' || a.status === 'lost').length ?? 0}\n Streaks: clean=${companion.consecutiveCleanSessions ?? 0}, efficient=${companion.consecutiveEfficientSessions ?? 0}, days-active=${companion.consecutiveDaysActive ?? 0}\n</state>\nPick the most relevant category and write one observation about this session.`;\n\n const result = await callHaiku(prompt);\n if (!result) return null;\n\n // Defense-in-depth: validate text safety even when using real callHaikuStructured\n // (Zod refine runs inside callHaikuStructured, but when the inner caller is a test\n // stub it may return raw text that bypasses Zod — this check always runs).\n if (!isSafeObservationText(result.text)) {\n console.error('[companion-memory] haiku observation dropped — unsafe text', {\n source: 'haiku',\n reason: 'unsafe-text',\n textLength: result.text.length,\n });\n return null;\n }\n\n return {\n id: randomUUID(),\n category: result.category,\n source: 'haiku',\n text: result.text,\n repo: session.cwd,\n sessionId: session.id,\n timestamp: new Date().toISOString(),\n };\n } catch (err) {\n console.error('[companion-memory] haiku observation failed', {\n errorMessage: err instanceof Error ? err.message : String(err),\n errorName: err instanceof Error ? err.name : 'UnknownError',\n });\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Phase 2: Observation engine\n// ---------------------------------------------------------------------------\n\nexport type HaikuObservationCaller = (input: ObservationEngineInput) => Promise<ObservationRecord | null>;\n\nexport async function runObservationEngine(\n input: ObservationEngineInput,\n opts?: { haikuCaller?: HaikuObservationCaller },\n): Promise<void> {\n try {\n const current = loadMemory();\n const ruleResult = runRuleDetectors(input, current.firedDetectors);\n\n // Wrap the Haiku call independently — a throwing outer caller must not prevent\n // rule observations from being persisted.\n let haikuRecord: ObservationRecord | null = null;\n try {\n haikuRecord = await (opts?.haikuCaller ?? ((i) => runHaikuObservation(i)))(input);\n } catch (haikuErr) {\n console.error('[companion-memory] haiku caller threw in engine', {\n errorMessage: haikuErr instanceof Error ? haikuErr.message : String(haikuErr),\n errorName: haikuErr instanceof Error ? haikuErr.name : 'UnknownError',\n });\n }\n\n const allRecords = haikuRecord\n ? [...ruleResult.records, haikuRecord]\n : ruleResult.records;\n if (allRecords.length > 0 || Object.keys(ruleResult.detectorUpdates).length > 0) {\n await appendObservations(allRecords, ruleResult.detectorUpdates);\n }\n } catch (err) {\n console.error('[companion-memory] observation engine error', {\n errorMessage: err instanceof Error ? err.message : String(err),\n errorName: err instanceof Error ? err.name : 'UnknownError',\n });\n }\n}\n","import { query, createSdkMcpServer, type SdkMcpToolDefinition } from '@r-cli/sdk';\nimport type { ZodSchema } from 'zod';\nimport { execEnv } from '../shared/env.js';\n\nconst COOLDOWN_MS = 5 * 60 * 1000;\nlet disabledUntil = 0;\nlet disabledUntilTools = 0;\n\nfunction applyAuthCooldown(err: unknown, target: 'main' | 'tools'): void {\n const status = (err as { status?: number } | undefined)?.status;\n if (status === 401 || status === 403) {\n if (target === 'main') disabledUntil = Date.now() + COOLDOWN_MS;\n else disabledUntilTools = Date.now() + COOLDOWN_MS;\n }\n}\n\nexport async function callHaiku(prompt: string, systemPrompt?: string): Promise<string | null> {\n if (Date.now() < disabledUntil) return null;\n\n try {\n const session = await query({\n prompt,\n options: {\n model: 'haiku',\n maxTurns: 1,\n env: execEnv(),\n ...(systemPrompt ? { systemPrompt } : {}),\n },\n });\n\n let text = '';\n for await (const msg of session) {\n if (msg.type === 'assistant' && msg.message?.content) {\n for (const block of msg.message.content) {\n if (block.type === 'text') text += block.text;\n }\n }\n }\n\n return text.trim() || null;\n } catch (err) {\n console.error(`[sisyphus] Haiku call failed: ${err instanceof Error ? err.message : err}`);\n applyAuthCooldown(err, 'main');\n return null;\n }\n}\n\nexport interface CallHaikuWithToolsOpts {\n systemPrompt: string;\n userPrompt: string;\n cwd: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches SDK convention (createSdkMcpServer.tools)\n customTools: SdkMcpToolDefinition<any>[];\n mcpServerName: string;\n maxTurns?: number;\n}\n\nexport type CallHaikuWithToolsResult =\n | { ok: true; turns: number }\n | { ok: false; error: string };\n\nexport async function callHaikuWithTools(opts: CallHaikuWithToolsOpts): Promise<CallHaikuWithToolsResult> {\n if (Date.now() < disabledUntilTools) {\n return { ok: false, error: 'haiku tool path on cooldown' };\n }\n\n const server = createSdkMcpServer({\n name: opts.mcpServerName,\n version: '1.0.0',\n tools: opts.customTools,\n });\n const allowedTools = opts.customTools.map(t => `mcp__${opts.mcpServerName}__${t.name}`);\n\n let turns = 0;\n try {\n const session = query({\n prompt: opts.userPrompt,\n options: {\n model: 'haiku',\n maxTurns: opts.maxTurns ?? 5,\n cwd: opts.cwd,\n env: execEnv(),\n systemPrompt: opts.systemPrompt,\n mcpServers: { [opts.mcpServerName]: server },\n tools: [],\n allowedTools,\n canUseTool: async () => ({ behavior: 'allow' }),\n },\n });\n\n for await (const msg of session) {\n if (msg.type === 'result') {\n turns = (msg as { num_turns?: number }).num_turns ?? turns;\n }\n }\n\n return { ok: true, turns };\n } catch (err) {\n console.error(`[sisyphus] callHaikuWithTools failed: ${err instanceof Error ? err.message : err}`);\n applyAuthCooldown(err, 'tools');\n return { ok: false, error: err instanceof Error ? err.message : String(err) };\n }\n}\n\n/**\n * Call Haiku with structured JSON output. The jsonSchema is passed as outputFormat,\n * and the result is validated with the zod schema before returning.\n */\nexport async function callHaikuStructured<T>(\n prompt: string,\n jsonSchema: Record<string, unknown>,\n zodSchema: ZodSchema<T>,\n): Promise<T | null> {\n if (Date.now() < disabledUntil) return null;\n\n try {\n const session = await query({\n prompt,\n options: {\n model: 'haiku',\n maxTurns: 2,\n env: execEnv(),\n outputFormat: {\n type: 'json_schema',\n schema: jsonSchema,\n },\n },\n });\n\n let result: unknown = undefined;\n for await (const msg of session) {\n if (msg.type === 'result' && msg.subtype === 'success' && msg.structured_output !== undefined) {\n result = msg.structured_output;\n }\n }\n\n if (result === undefined) return null;\n const parsed = zodSchema.safeParse(result);\n return parsed.success ? parsed.data : null;\n } catch (err) {\n console.error(`[sisyphus] Haiku structured call failed: ${err instanceof Error ? err.message : err}`);\n applyAuthCooldown(err, 'main');\n return null;\n }\n}\n","import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { randomUUID } from 'node:crypto';\nimport { dirname, join } from 'node:path';\nimport { companionPath, globalDir } from '../shared/paths.js';\nimport type { Session } from '../shared/types.js';\nimport type {\n AchievementId,\n CommentaryEvent,\n CompanionBaselines,\n CompanionState,\n CompanionStats,\n FeedbackEntry,\n FeedbackRating,\n LastCommentary,\n Mood,\n MoodSignals,\n RepoMemory,\n RunningStats,\n UnlockedAchievement,\n} from '../shared/companion-types.js';\nexport { ACHIEVEMENTS } from '../shared/companion-types.js';\n\n// ---------------------------------------------------------------------------\n// Welford's online algorithm — deviation-based mood scoring\n// ---------------------------------------------------------------------------\n\nconst MIN_SAMPLES = 5;\nconst MIN_STDDEV_RATIO = 0.20;\n\ntype BaselineMetric = 'sessionMs' | 'cycleCount' | 'agentCount' | 'sessionsPerDay' | 'recentAgentThroughput';\n\nconst ABSOLUTE_STDDEV_FLOORS: Record<BaselineMetric, number> = {\n sessionMs: 300_000, // 5 minutes\n cycleCount: 1.0,\n agentCount: 1.0,\n sessionsPerDay: 0.5,\n recentAgentThroughput: 2.0,\n};\n\nconst COLD_START_DEFAULTS: Record<BaselineMetric, { mean: number; stddev: number }> = {\n sessionMs: { mean: 3_600_000, stddev: 2_400_000 },\n cycleCount: { mean: 5, stddev: 3 },\n agentCount: { mean: 5, stddev: 4 },\n sessionsPerDay: { mean: 3, stddev: 2 },\n recentAgentThroughput: { mean: 8, stddev: 6 },\n};\n\nexport function emptyStats(): RunningStats {\n return { count: 0, mean: 0, m2: 0 };\n}\n\nexport function defaultBaselines(): CompanionBaselines {\n return {\n sessionMs: emptyStats(),\n cycleCount: emptyStats(),\n agentCount: emptyStats(),\n sessionsPerDay: emptyStats(),\n recentAgentThroughput: emptyStats(),\n lastCountedDay: null,\n pendingDayCount: 0,\n };\n}\n\nexport function welfordUpdate(stats: RunningStats, value: number): void {\n stats.count++;\n const delta = value - stats.mean;\n stats.mean += delta / stats.count;\n const delta2 = value - stats.mean;\n stats.m2 += delta * delta2;\n}\n\nexport function zScore(\n value: number,\n stats: RunningStats,\n metric: BaselineMetric,\n): number {\n const defaults = COLD_START_DEFAULTS[metric];\n const floor = ABSOLUTE_STDDEV_FLOORS[metric];\n\n if (stats.count < MIN_SAMPLES) {\n if (defaults.stddev === 0) return 0;\n return (value - defaults.mean) / defaults.stddev;\n }\n\n const rawStddev = stats.count >= 2 ? Math.sqrt(stats.m2 / stats.count) : 0;\n const stddev = Math.max(rawStddev, stats.mean * MIN_STDDEV_RATIO, floor);\n if (stddev === 0) return 0;\n return (value - stats.mean) / stddev;\n}\n\n// ---------------------------------------------------------------------------\n// Persistence\n// ---------------------------------------------------------------------------\n\nexport function loadCompanion(): CompanionState {\n const path = companionPath();\n if (!existsSync(path)) {\n const state = createDefaultCompanion();\n saveCompanion(state);\n return state;\n }\n const raw = readFileSync(path, 'utf-8');\n const state = JSON.parse(raw) as CompanionState;\n // Forward-compat: fill missing fields\n if (state.consecutiveCleanSessions == null) state.consecutiveCleanSessions = 0;\n if (state.consecutiveDaysActive == null) state.consecutiveDaysActive = 0;\n if (state.lastActiveDate == null) state.lastActiveDate = null;\n if (state.taskHistory == null) state.taskHistory = {};\n if (state.dailyRepos == null) state.dailyRepos = {};\n if (state.recentCompletions == null) state.recentCompletions = [];\n if (state.lifetimeAgentsSpawned == null) state.lifetimeAgentsSpawned = 0;\n if (state.consecutiveEfficientSessions == null) state.consecutiveEfficientSessions = 0;\n if (state.consecutiveHighCycleSessions == null) state.consecutiveHighCycleSessions = 0;\n if (state.spinnerVerbIndex == null) state.spinnerVerbIndex = 0;\n if (state.baselines == null) state.baselines = defaultBaselines();\n if (state.baselines.recentAgentThroughput == null) state.baselines.recentAgentThroughput = emptyStats();\n if (state.commentaryHistory == null) state.commentaryHistory = [];\n if (state.feedbackHistory == null) state.feedbackHistory = [];\n return state;\n}\n\nexport function saveCompanion(state: CompanionState): void {\n const path = companionPath();\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true });\n const tmp = join(dir, `.companion.${randomUUID()}.tmp`);\n writeFileSync(tmp, JSON.stringify(state, null, 2), 'utf-8');\n renameSync(tmp, path);\n}\n\nconst MAX_COMMENTARY_HISTORY = 1000;\nconst MAX_FEEDBACK_HISTORY = 1000;\n\n/**\n * Push a commentary entry to lastCommentary + commentaryHistory ring buffer.\n * Mutates the companion in-place; caller must saveCompanion() afterward.\n */\nexport function recordCommentary(companion: CompanionState, text: string, event: CommentaryEvent): void {\n const entry: LastCommentary = { text, event, timestamp: new Date().toISOString() };\n companion.lastCommentary = entry;\n if (!companion.commentaryHistory) companion.commentaryHistory = [];\n companion.commentaryHistory.push(entry);\n if (companion.commentaryHistory.length > MAX_COMMENTARY_HISTORY) {\n companion.commentaryHistory = companion.commentaryHistory.slice(-MAX_COMMENTARY_HISTORY);\n }\n}\n\n/**\n * Push a feedback entry to feedbackHistory ring buffer.\n * Mutates the companion in-place; caller must saveCompanion() afterward.\n */\nexport function recordFeedback(\n companion: CompanionState,\n text: string,\n rating: FeedbackRating,\n event: CommentaryEvent,\n comment?: string,\n): void {\n const entry: FeedbackEntry = { commentaryText: text, rating, event, timestamp: new Date().toISOString(), ...(comment != null ? { comment } : {}) };\n if (!companion.feedbackHistory) companion.feedbackHistory = [];\n companion.feedbackHistory.push(entry);\n if (companion.feedbackHistory.length > MAX_FEEDBACK_HISTORY) {\n companion.feedbackHistory = companion.feedbackHistory.slice(-MAX_FEEDBACK_HISTORY);\n }\n}\n\nexport function createDefaultCompanion(): CompanionState {\n const now = new Date().toISOString();\n return {\n version: 1,\n name: null,\n createdAt: now,\n stats: {\n strength: 0,\n endurance: 0,\n wisdom: 0,\n patience: 0,\n },\n xp: 0,\n level: 1,\n title: 'Boulder Intern',\n mood: 'sleepy',\n moodUpdatedAt: now,\n achievements: [],\n repos: {},\n lastCommentary: null,\n commentaryHistory: [],\n sessionsCompleted: 0,\n sessionsCrashed: 0,\n totalActiveMs: 0,\n lifetimeAgentsSpawned: 0,\n consecutiveCleanSessions: 0,\n consecutiveEfficientSessions: 0,\n consecutiveHighCycleSessions: 0,\n consecutiveDaysActive: 0,\n lastActiveDate: null,\n taskHistory: {},\n dailyRepos: {},\n recentCompletions: [],\n spinnerVerbIndex: 0,\n baselines: defaultBaselines(),\n feedbackHistory: [],\n };\n}\n\n// ---------------------------------------------------------------------------\n// XP & Leveling\n// ---------------------------------------------------------------------------\n\nexport function computeXP(stats: CompanionStats): number {\n const strengthXP = stats.strength * 50;\n const enduranceXP = (stats.endurance / 3_600_000) * 20;\n const wisdomXP = stats.wisdom * 40;\n const patienceXP = stats.patience * 8;\n return Math.floor(strengthXP + enduranceXP + wisdomXP + patienceXP);\n}\n\nexport function computeStrengthGain(agentCount: number): number {\n if (agentCount <= 0) return 0;\n if (agentCount <= 2) return 1;\n if (agentCount <= 5) return 2;\n if (agentCount <= 10) return 3;\n if (agentCount <= 20) return 4;\n return 5;\n}\n\nexport function computeLevel(xp: number): number {\n let level = 1;\n let threshold = 150;\n let cumulative = 0;\n while (cumulative + threshold <= xp) {\n cumulative += threshold;\n level++;\n threshold = Math.floor(threshold * 1.35);\n }\n return level;\n}\n\n/** Returns { xpIntoLevel, xpForNextLevel } so callers can render accurate progress bars. */\nexport function computeLevelProgress(xp: number): { xpIntoLevel: number; xpForNextLevel: number } {\n let threshold = 150;\n let cumulative = 0;\n while (cumulative + threshold <= xp) {\n cumulative += threshold;\n threshold = Math.floor(threshold * 1.35);\n }\n return { xpIntoLevel: xp - cumulative, xpForNextLevel: threshold };\n}\n\nconst TITLE_MAP: Record<number, string> = {\n 1: 'Boulder Intern',\n 2: 'Pebble Pusher',\n 3: 'Rock Hauler',\n 4: 'Gravel Wrangler',\n 5: 'Slope Familiar',\n 6: 'Incline Regular',\n 7: 'Ridge Runner',\n 8: 'Crag Warden',\n 9: 'Stone Whisperer',\n 10: 'Boulder Brother',\n 11: 'Hill Veteran',\n 12: 'Summit Aspirant',\n 13: 'Peak Haunter',\n 14: 'Cliff Sage',\n 15: \"Mountain's Shadow\",\n 16: 'Eternal Roller',\n 17: \"Gravity's Rival\",\n 18: 'The Unmoved Mover',\n 19: 'Camus Was Right',\n 20: 'The Absurd Hero',\n 25: 'One Must Imagine Him Happy',\n 30: 'He Has Always Been Here',\n};\n\nexport function getTitle(level: number): string {\n for (let l = level; l >= 1; l--) {\n if (TITLE_MAP[l] !== undefined) return TITLE_MAP[l]!;\n }\n return 'Boulder Intern';\n}\n\n// ---------------------------------------------------------------------------\n// Mood\n// ---------------------------------------------------------------------------\n\nexport function computeMood(companion: CompanionState, session?: Session, signals?: MoodSignals): Mood {\n if (!signals) {\n const hour = new Date().getHours();\n if (hour >= 2 && hour < 6) return 'existential';\n if (hour >= 22 || hour < 2) return 'sleepy';\n return 'zen';\n }\n\n const scores: Record<Mood, number> = {\n happy: 0,\n grinding: 0,\n frustrated: 0,\n zen: 0,\n sleepy: 0,\n excited: 0,\n existential: 0,\n };\n\n const cycleCount = signals.cycleCount ?? 0;\n const sessionsCompletedToday = signals.sessionsCompletedToday ?? 0;\n\n // Deviation-based z-scores from personal baselines\n const baselines = companion.baselines ?? defaultBaselines();\n const sessionZ = zScore(signals.sessionLengthMs, baselines.sessionMs, 'sessionMs');\n const cycleZ = zScore(cycleCount, baselines.cycleCount, 'cycleCount');\n const agentZ = zScore(signals.totalAgentCount ?? 0, baselines.agentCount, 'agentCount');\n const dailyZ = zScore(sessionsCompletedToday, baselines.sessionsPerDay, 'sessionsPerDay');\n const recentAgentZ = zScore(signals.recentAgentCount ?? 0, baselines.recentAgentThroughput, 'recentAgentThroughput');\n\n // Happy — event-driven + deviation-based quick wins\n if (signals.justCompleted) scores.happy += 50;\n if (signals.justCompleted && sessionZ < -0.5) scores.happy += 15; // quicker than usual\n if (dailyZ > 0.5) scores.happy += 20; // productive day\n if (dailyZ > 1.5) scores.happy += 10; // really productive\n if (signals.hourOfDay >= 6 && signals.hourOfDay < 12) scores.happy += 15; // morning\n if (signals.hourOfDay >= 12 && signals.hourOfDay < 17) scores.happy += 8; // afternoon\n if ((signals.activeAgentCount ?? 0) >= 1 && sessionZ < -0.5) scores.happy += 12; // early session optimism\n // Flow state: last completion was recent (within 30min) and we're in a new session\n const lastCompletion = companion.recentCompletions.length > 0\n ? Date.now() - new Date(companion.recentCompletions[companion.recentCompletions.length - 1]!).getTime()\n : Infinity;\n if (lastCompletion < 1_800_000 && signals.sessionLengthMs > 0) scores.happy += 20;\n\n // Grinding — deviation-based deep work\n if (sessionZ > 0.5) scores.grinding += 15; // longer than usual\n if (sessionZ > 1.0) scores.grinding += 10; // significantly longer\n if (sessionZ > 1.5) scores.grinding += 8; // very long for this user\n if (recentAgentZ > 0.5) scores.grinding += 12; // more agents active (2h window) than usual\n if (recentAgentZ > 1.0) scores.grinding += 10; // significantly more cross-session agents\n if (recentAgentZ > 1.5) scores.grinding += 8; // massive cross-session throughput\n if (cycleZ > 0.5) scores.grinding += 8; // more cycles than usual\n\n // Frustrated — actual negative events (crashes, rollbacks, restarts, lost agents)\n const rollbacks = signals.rollbackCount ?? 0;\n const restartedAgents = signals.restartedAgentCount ?? 0;\n const lostAgents = signals.lostAgentCount ?? 0;\n const killedAgents = signals.killedAgentCount ?? 0;\n if (signals.justCrashed) scores.frustrated += 30;\n if (signals.recentCrashes >= 2) scores.frustrated += 20;\n if (signals.recentCrashes >= 4) scores.frustrated += 15;\n if (rollbacks >= 1) scores.frustrated += 25; // rolling back = something went wrong\n if (rollbacks >= 3) scores.frustrated += 25; // repeated rollbacks = real pain\n if (restartedAgents >= 1) scores.frustrated += 15;\n if (restartedAgents >= 3) scores.frustrated += 15;\n if (lostAgents >= 1) scores.frustrated += 15;\n if (lostAgents >= 3) scores.frustrated += 10;\n if (killedAgents >= 2) scores.frustrated += 10;\n // Long session WITH negative events = stuck (but long session alone is just grinding)\n if (sessionZ > 1.5 && (signals.recentCrashes > 0 || rollbacks > 0)) scores.frustrated += 12;\n\n // Zen — deviation-based \"normal\" + absolute calm\n if (companion.stats.patience > 30) scores.zen += 15;\n if (signals.idleDurationMs > 120_000 && signals.idleDurationMs <= 900_000) scores.zen += 25; // 2-15min idle\n if (sessionZ > -1.0 && sessionZ < 0.3) scores.zen += 15; // session length is normal\n if (cycleZ < 0) scores.zen += 10; // fewer cycles than usual, smooth sailing\n if (signals.hourOfDay >= 6 && signals.hourOfDay < 10 && (signals.activeAgentCount ?? 0) === 0) scores.zen += 10;\n if (dailyZ >= -0.5 && dailyZ <= 0.5) scores.zen += 10; // normal day\n\n // Sleepy — absolute (idle duration + time of day)\n if (signals.idleDurationMs > 900_000) scores.sleepy += 30; // >15min\n if (signals.idleDurationMs > 2_700_000) scores.sleepy += 25; // >45min\n if (signals.idleDurationMs > 5_400_000) scores.sleepy += 15; // >90min\n if (signals.hourOfDay >= 22 || signals.hourOfDay < 6) scores.sleepy += 20;\n if (signals.idleDurationMs > 300_000 && (signals.hourOfDay >= 22 || signals.hourOfDay < 6)) scores.sleepy += 15;\n if (sessionZ > 2.5) scores.sleepy += 12; // exhaustion from extreme session\n\n // Excited — event-driven + deviation-based swarms\n if (signals.justLeveledUp) scores.excited += 60;\n if (signals.justCompleted && agentZ > 1.0) scores.excited += 30; // completed with notably many agents\n if (agentZ > 1.5) scores.excited += 20; // way more agents than usual\n if (agentZ > 2.0) scores.excited += 15; // massive swarm for this user\n if (signals.justCompleted && sessionZ < -1.0) scores.excited += 20; // way faster than usual\n\n // Existential — absolute (late night + experience + sustained commitment)\n if (signals.hourOfDay >= 2 && signals.hourOfDay < 6) scores.existential += 25;\n if (signals.hourOfDay >= 0 && signals.hourOfDay < 2) scores.existential += 10;\n const enduranceHours = companion.stats.endurance / 3_600_000;\n if (enduranceHours > 40) scores.existential += 15;\n if (signals.hourOfDay >= 2 && signals.hourOfDay < 6 && enduranceHours > 40) {\n scores.existential += 25;\n }\n // Weekly activity z-score — sustained above-average use, not a static lifetime counter\n const now = Date.now();\n const weekAgo = now - 7 * 24 * 3_600_000;\n const weeklyCompletions = companion.recentCompletions.filter(\n ts => new Date(ts).getTime() > weekAgo\n ).length;\n const weeklyAvgDaily = weeklyCompletions / 7;\n const weeklyZ = zScore(weeklyAvgDaily, baselines.sessionsPerDay, 'sessionsPerDay');\n if (weeklyZ > 0.5) scores.existential += 8;\n if (weeklyZ > 1.0) scores.existential += 7;\n if (weeklyZ > 1.5) scores.existential += 5;\n // Consecutive days — grows slowly from day 3, caps at +20 around day 9\n const consecutiveDays = companion.consecutiveDaysActive ?? 0;\n if (consecutiveDays >= 3) scores.existential += Math.min(20, (consecutiveDays - 2) * 3);\n\n // User feedback adjustments\n const goodRatings = signals.recentFeedbackGood ?? 0;\n const badRatings = signals.recentFeedbackBad ?? 0;\n const whipRatings = signals.recentFeedbackWhip ?? 0;\n if (goodRatings > 0) {\n scores.happy += goodRatings * 20;\n scores.excited += goodRatings * 8;\n scores.frustrated = Math.max(0, scores.frustrated - goodRatings * 10);\n }\n if (badRatings > 0) {\n scores.happy = Math.max(0, scores.happy - badRatings * 15);\n scores.frustrated += badRatings * 20;\n scores.zen = Math.max(0, scores.zen - badRatings * 10);\n }\n if (whipRatings > 0) {\n scores.happy = Math.max(0, scores.happy - whipRatings * 15);\n scores.sleepy = Math.max(0, scores.sleepy - whipRatings * 15);\n scores.zen = Math.max(0, scores.zen - whipRatings * 15);\n scores.frustrated = Math.max(0, scores.frustrated - whipRatings * 8);\n scores.existential += whipRatings * 25;\n }\n\n const moodOrder: Mood[] = ['happy', 'grinding', 'frustrated', 'zen', 'sleepy', 'excited', 'existential'];\n let best: Mood = 'grinding';\n let bestScore = -1;\n for (const mood of moodOrder) {\n if (scores[mood] > bestScore) {\n bestScore = scores[mood];\n best = mood;\n }\n }\n\n // Attach debug info for TUI debug overlay\n companion.debugMood = { signals, scores: { ...scores }, winner: best };\n\n return best;\n}\n\n// ---------------------------------------------------------------------------\n// Achievements\n// ---------------------------------------------------------------------------\n\nexport function hasAchievement(companion: CompanionState, id: AchievementId): boolean {\n return companion.achievements.some(a => a.id === id);\n}\n\nfunction daysSince(isoTimestamp: string): number {\n return (Date.now() - new Date(isoTimestamp).getTime()) / (1000 * 60 * 60 * 24);\n}\n\ntype AchievementChecker = (companion: CompanionState, session?: Session) => boolean;\n\nconst ACHIEVEMENT_CHECKERS: Record<AchievementId, AchievementChecker> = {\n // Milestone\n 'first-blood': (c) => c.sessionsCompleted >= 1,\n 'regular': (c) => c.sessionsCompleted >= 10,\n 'centurion': (c) => c.sessionsCompleted >= 100,\n 'veteran': (c) => c.sessionsCompleted >= 500,\n 'thousand-boulder': (c) => c.sessionsCompleted >= 1000,\n 'cartographer': (c) => Object.keys(c.repos).length >= 5,\n 'world-traveler': (c) => Object.keys(c.repos).length >= 15,\n 'omnipresent': (c) => Object.keys(c.repos).length >= 30,\n 'swarm-starter': (c) => c.lifetimeAgentsSpawned >= 50,\n 'hive-mind': (c) => c.lifetimeAgentsSpawned >= 500,\n 'legion': (c) => c.lifetimeAgentsSpawned >= 2000,\n 'army-of-thousands': (c) => c.lifetimeAgentsSpawned >= 5000,\n 'singularity': (c) => c.lifetimeAgentsSpawned >= 10000,\n 'first-shift': (c) => c.totalActiveMs >= 36_000_000,\n 'workaholic': (c) => c.totalActiveMs >= 360_000_000,\n 'time-lord': (c) => c.totalActiveMs >= 1_800_000_000,\n 'eternal-grind': (c) => c.totalActiveMs >= 7_200_000_000,\n 'epoch': (c) => c.totalActiveMs >= 18_000_000_000,\n 'old-growth': (c) => daysSince(c.createdAt) >= 14,\n 'seasoned': (c) => daysSince(c.createdAt) >= 90,\n 'ancient': (c) => daysSince(c.createdAt) >= 365,\n 'apprentice': (c) => c.level >= 5,\n 'journeyman': (c) => c.level >= 15,\n 'master': (c) => c.level >= 30,\n 'grandmaster': (c) => c.level >= 50,\n\n // Session\n 'marathon': (_c, s) => s != null && s.agents.length >= 15,\n 'squad': (_c, s) => s != null && s.agents.length >= 10,\n 'battalion': (_c, s) => s != null && s.agents.length >= 25,\n 'swarm': (_c, s) => s != null && s.agents.length >= 50,\n 'blitz': (_c, s) => s != null && s.activeMs < 300_000 && s.status === 'completed',\n 'speed-run': (_c, s) => s != null && s.activeMs < 900_000 && s.status === 'completed',\n 'flash': (_c, s) => s != null && s.activeMs < 120_000 && s.status === 'completed',\n 'flawless': (_c, s) => s != null && s.agents.length >= 10 && s.status === 'completed' &&\n s.agents.every(a => a.status !== 'crashed' && a.status !== 'killed'),\n 'speed-demon': (c) => c.consecutiveEfficientSessions >= 10,\n 'iron-will': (c) => c.consecutiveHighCycleSessions >= 5,\n 'glass-cannon': (_c, s) => {\n if (!s || s.status !== 'completed' || s.agents.length < 5) return false;\n return s.agents.every(a => a.status === 'crashed' || a.killedReason != null);\n },\n 'solo': (_c, s) => s != null && s.status === 'completed' && s.agents.length === 1,\n 'one-more-cycle': (_c, s) => s != null && s.orchestratorCycles.length >= 10,\n 'deep-dive': (_c, s) => s != null && s.orchestratorCycles.length >= 15,\n 'abyss': (_c, s) => s != null && s.orchestratorCycles.length >= 25,\n 'eternal-recurrence': (_c, s) => s != null && s.orchestratorCycles.length >= 40,\n 'endurance': (_c, s) => s != null && s.activeMs >= 14_400_000,\n 'ultramarathon': (_c, s) => s != null && s.activeMs >= 21_600_000,\n 'one-shot': (_c, s) => s != null && s.agents.length >= 5 && s.orchestratorCycles.length === 1 && s.status === 'completed',\n 'quick-draw': (_c, s) => {\n if (!s || s.agents.length === 0) return false;\n const firstAgent = s.agents[0]!;\n return new Date(firstAgent.spawnedAt).getTime() - new Date(s.createdAt).getTime() < 20_000;\n },\n\n // Time\n 'night-owl': (_c, s) => {\n if (!s || s.status !== 'completed') return false;\n const h = new Date(s.createdAt).getHours();\n return h >= 1 && h < 5;\n },\n 'dawn-patrol': (_c, s) => {\n if (!s) return false;\n // Session must be 3+ hours\n if (s.activeMs < 10_800_000) return false;\n const start = new Date(s.createdAt).getTime();\n const end = s.completedAt ? new Date(s.completedAt).getTime() : Date.now();\n const startDate = new Date(start);\n const startHour = startDate.getHours();\n // Get today's midnight (00:00) for the start date\n const todayMidnight = new Date(startDate);\n todayMidnight.setHours(0, 0, 0, 0);\n // Get 6am for the same calendar day as midnight\n const sixAm = new Date(todayMidnight);\n sixAm.setHours(6, 0, 0, 0);\n\n if (startHour >= 6) {\n // Started after 6am — check if session spans into next day's midnight-6am window\n const nextMidnight = new Date(todayMidnight.getTime() + 24 * 60 * 60 * 1000);\n return start < nextMidnight.getTime() && end > nextMidnight.getTime();\n } else {\n // Started between midnight and 6am — session is already in the window\n return start < sixAm.getTime();\n }\n },\n 'early-bird': (_c, s) => {\n if (!s) return false;\n return new Date(s.createdAt).getHours() < 6;\n },\n 'weekend-warrior': (_c, s) => {\n if (!s || s.status !== 'completed') return false;\n const day = new Date(s.completedAt ?? s.createdAt).getDay();\n return day === 0 || day === 6;\n },\n 'all-nighter': (_c, s) => s != null && s.activeMs >= 18_000_000,\n 'witching-hour': (_c, s) => {\n if (!s) return false;\n const h = new Date(s.createdAt).getHours();\n return h === 3;\n },\n\n // Behavioral\n 'sisyphean': (c) => Object.values(c.taskHistory).some(v => v >= 3),\n 'stubborn': (c) => Object.values(c.taskHistory).some(v => v >= 5) && c.sessionsCompleted > 0,\n 'one-must-imagine': (c) => Object.values(c.taskHistory).some(v => v >= 10),\n 'creature-of-habit': (c) => Object.values(c.repos).some(r => r.visits >= 10),\n 'loyal': (c) => Object.values(c.repos).some(r => r.visits >= 30),\n 'wanderer': (c) => {\n return Object.values(c.dailyRepos).some(repos => repos.length >= 3);\n },\n 'streak': (c) => c.consecutiveDaysActive >= 7,\n 'iron-streak': (c) => c.consecutiveDaysActive >= 14,\n 'hot-streak': (c) => c.consecutiveCleanSessions >= 15,\n 'momentum': (c) => {\n if (c.recentCompletions.length < 5) return false;\n const last5 = c.recentCompletions.slice(-5);\n const oldest = new Date(last5[0]!).getTime();\n const newest = new Date(last5[4]!).getTime();\n return newest - oldest <= 4 * 60 * 60 * 1000;\n },\n 'overdrive': (c) => {\n const dateCounts: Record<string, number> = {};\n for (const ts of c.recentCompletions) {\n const date = ts.slice(0, 10);\n dateCounts[date] = (dateCounts[date] ?? 0) + 1;\n }\n return Object.values(dateCounts).some(count => count >= 6);\n },\n 'patient-one': (_c, s) => {\n if (!s || s.orchestratorCycles.length < 2) return false;\n for (let i = 1; i < s.orchestratorCycles.length; i++) {\n const prev = s.orchestratorCycles[i - 1]!;\n const curr = s.orchestratorCycles[i]!;\n if (!prev.completedAt) continue;\n const gap = new Date(curr.timestamp).getTime() - new Date(prev.completedAt).getTime();\n if (gap >= 30 * 60 * 1000) return true;\n }\n return false;\n },\n 'message-in-a-bottle': (_c, s) => {\n if (!s) return false;\n const userMessages = s.messages.filter(m => m.source.type === 'user');\n return userMessages.length >= 10;\n },\n 'deep-conversation': (_c, s) => {\n if (!s) return false;\n const userMessages = s.messages.filter(m => m.source.type === 'user');\n return userMessages.length >= 20;\n },\n 'comeback-kid': (_c, s) => {\n if (!s || s.status !== 'completed') return false;\n return s.orchestratorCycles.length > 0 && s.parentSessionId != null;\n },\n 'pair-programming': (_c, s) => {\n if (!s) return false;\n const userMessages = s.messages.filter(m => m.source.type === 'user');\n return userMessages.length >= 8;\n },\n};\n\nexport function checkAchievements(companion: CompanionState, session?: Session): AchievementId[] {\n const alreadyUnlocked = new Set(companion.achievements.map(a => a.id));\n const newIds: AchievementId[] = [];\n\n for (const [id, checker] of Object.entries(ACHIEVEMENT_CHECKERS) as [AchievementId, AchievementChecker][]) {\n if (alreadyUnlocked.has(id)) continue;\n if (checker(companion, session)) {\n newIds.push(id);\n }\n }\n return newIds;\n}\n\n// ---------------------------------------------------------------------------\n// Repo Memory\n// ---------------------------------------------------------------------------\n\nconst MOOD_SENTIMENT: Record<Mood, number> = {\n happy: 0.85,\n excited: 0.90,\n zen: 0.70,\n grinding: 0.45,\n sleepy: 0.40,\n frustrated: 0.15,\n existential: 0.25,\n};\n\nexport function updateRepoMemory(\n companion: CompanionState,\n repoPath: string,\n event: 'visit' | 'completion' | 'crash',\n activeMs?: number,\n): CompanionState {\n const now = new Date().toISOString();\n const moodScore = MOOD_SENTIMENT[companion.mood] ?? 0.5;\n const existing = companion.repos[repoPath];\n if (!existing) {\n companion.repos[repoPath] = {\n visits: event === 'visit' ? 1 : 0,\n completions: event === 'completion' ? 1 : 0,\n crashes: event === 'crash' ? 1 : 0,\n totalActiveMs: activeMs ?? 0,\n moodAvg: moodScore,\n nickname: null,\n firstSeen: now,\n lastSeen: now,\n };\n } else {\n if (event === 'visit') existing.visits++;\n if (event === 'completion') existing.completions++;\n if (event === 'crash') existing.crashes++;\n if (activeMs != null) existing.totalActiveMs += activeMs;\n existing.lastSeen = now;\n // Running average weighted by total event count across visits/completions/crashes\n const n = existing.visits + existing.completions + existing.crashes;\n existing.moodAvg = existing.moodAvg + (moodScore - existing.moodAvg) / n;\n }\n return companion;\n}\n\n// ---------------------------------------------------------------------------\n// Event Handlers\n// ---------------------------------------------------------------------------\n\nfunction recomputeXpLevelTitle(companion: CompanionState): void {\n companion.xp = computeXP(companion.stats);\n companion.level = computeLevel(companion.xp);\n companion.title = getTitle(companion.level);\n}\n\nexport function todayIso(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\nexport function onSessionStart(companion: CompanionState, cwd: string): void {\n // Update repo memory\n updateRepoMemory(companion, cwd, 'visit');\n\n // Update dailyRepos\n const today = todayIso();\n if (!companion.dailyRepos[today]) companion.dailyRepos[today] = [];\n if (!companion.dailyRepos[today]!.includes(cwd)) {\n companion.dailyRepos[today]!.push(cwd);\n }\n\n // Update consecutive days active\n const lastDate = companion.lastActiveDate;\n if (lastDate === null) {\n companion.consecutiveDaysActive = 1;\n } else if (lastDate === today) {\n // Same day, no change to streak\n } else {\n const yesterday = new Date(Date.now() - 86_400_000).toISOString().slice(0, 10);\n if (lastDate === yesterday) {\n companion.consecutiveDaysActive++;\n } else {\n companion.consecutiveDaysActive = 1;\n }\n }\n companion.lastActiveDate = today;\n\n recomputeXpLevelTitle(companion);\n}\n\n/**\n * Compute wisdom points earned for a session. Rewards:\n * - Clean agent execution: high completion rate without restarts\n * - Good parallelization: more agents per orchestrator cycle\n * - Orchestration variety: using different modes (discovery, implementation, validation, completion)\n *\n * Returns 0-3 points per session.\n */\nexport function computeWisdomGain(session: Session): number {\n let wisdom = 0;\n const totalAgents = session.agents.length;\n const totalCycles = session.orchestratorCycles?.length ?? 0;\n if (totalAgents === 0 || totalCycles === 0) return 0;\n\n // Clean execution: ≥80% of agents completed without being killed/crashed/lost\n const cleanCompletions = session.agents.filter(a => a.status === 'completed').length;\n if (cleanCompletions / totalAgents >= 0.8) wisdom++;\n\n // Good parallelization: averaged ≥2 agents per cycle\n if (totalAgents / totalCycles >= 2) wisdom++;\n\n // Mode variety: used ≥2 distinct orchestrator modes\n const modes = new Set((session.orchestratorCycles ?? []).map(c => c.mode).filter(Boolean));\n if (modes.size >= 2) wisdom++;\n\n return wisdom;\n}\n\nexport function onSessionComplete(companion: CompanionState, session: Session): AchievementId[] {\n // Delta-safe: only credit what hasn't been credited yet (prevents inflation on continue→re-complete)\n const creditedCycles = session.companionCreditedCycles ?? 0;\n const creditedActiveMs = session.companionCreditedActiveMs ?? 0;\n const totalCycles = session.orchestratorCycles?.length ?? 0;\n const deltaCycles = Math.max(0, totalCycles - creditedCycles);\n const deltaActiveMs = Math.max(0, session.activeMs - creditedActiveMs);\n\n // Increment counters\n companion.sessionsCompleted++;\n companion.totalActiveMs += deltaActiveMs;\n companion.stats.endurance += deltaActiveMs;\n const creditedStrength = session.companionCreditedStrength ?? 0;\n const totalStrength = computeStrengthGain(session.agents.length);\n companion.stats.strength += Math.max(0, totalStrength - creditedStrength);\n\n // Patience: diminishing returns on high-cycle sessions (sqrt scale)\n const patienceFromCycles = Math.ceil(Math.sqrt(totalCycles)) - Math.ceil(Math.sqrt(creditedCycles));\n companion.stats.patience += Math.max(0, patienceFromCycles);\n // Bonus for sessions that went through full lifecycle (only new modes)\n const allModes = new Set((session.orchestratorCycles ?? []).map(c => c.mode));\n const creditedModesCycles = (session.orchestratorCycles ?? []).slice(0, creditedCycles);\n const prevModes = new Set(creditedModesCycles.map(c => c.mode));\n if (allModes.has('validation') && !prevModes.has('validation')) companion.stats.patience += 1;\n if (allModes.has('completion') && !prevModes.has('completion')) companion.stats.patience += 1;\n\n // Wisdom: clean execution, parallelization, mode variety\n const creditedWisdom = session.companionCreditedWisdom ?? 0;\n const totalWisdom = computeWisdomGain(session);\n companion.stats.wisdom += Math.max(0, totalWisdom - creditedWisdom);\n\n // Repo memory\n updateRepoMemory(companion, session.cwd, 'completion', deltaActiveMs);\n\n // Track consecutive efficient sessions (for speed-demon)\n if (totalCycles <= 3) {\n companion.consecutiveEfficientSessions++;\n } else {\n companion.consecutiveEfficientSessions = 0;\n }\n\n // Track consecutive high-cycle sessions (for iron-will)\n if (totalCycles >= 8) {\n companion.consecutiveHighCycleSessions++;\n } else {\n companion.consecutiveHighCycleSessions = 0;\n }\n\n // Consecutive clean sessions\n const hasCrash = session.agents.some(a => a.status === 'crashed');\n if (hasCrash) {\n companion.consecutiveCleanSessions = 0;\n companion.sessionsCrashed++;\n } else {\n companion.consecutiveCleanSessions++;\n }\n\n // Recent completions for achievements + weekly existential z-score (keep last 30)\n companion.recentCompletions.push(new Date().toISOString());\n if (companion.recentCompletions.length > 30) {\n companion.recentCompletions = companion.recentCompletions.slice(-30);\n }\n\n // Task history tracking (normalize task string to simple hash)\n const taskKey = normalizeTask(session.task, session.cwd);\n companion.taskHistory[taskKey] = (companion.taskHistory[taskKey] ?? 0) + 1;\n\n // Update deviation baselines (Welford's online algorithm)\n const baselines = companion.baselines ?? defaultBaselines();\n welfordUpdate(baselines.sessionMs, session.activeMs);\n welfordUpdate(baselines.cycleCount, totalCycles);\n welfordUpdate(baselines.agentCount, session.agents.length);\n welfordUpdate(baselines.recentAgentThroughput, companion.lastRecentAgentCount ?? 0);\n\n // Daily session count tracking with day-boundary handling\n const today = todayIso();\n if (baselines.lastCountedDay === null) {\n baselines.lastCountedDay = today;\n baselines.pendingDayCount = 1;\n } else if (baselines.lastCountedDay === today) {\n baselines.pendingDayCount++;\n } else {\n // Day rolled over: finalize the previous day\n welfordUpdate(baselines.sessionsPerDay, baselines.pendingDayCount);\n // Fill gap days (zero-session days) between lastCountedDay and yesterday\n const lastDay = new Date(baselines.lastCountedDay + 'T12:00:00');\n const yesterdayDate = new Date(today + 'T12:00:00');\n yesterdayDate.setDate(yesterdayDate.getDate() - 1);\n const cursor = new Date(lastDay);\n cursor.setDate(cursor.getDate() + 1);\n while (cursor < yesterdayDate) {\n welfordUpdate(baselines.sessionsPerDay, 0);\n cursor.setDate(cursor.getDate() + 1);\n }\n baselines.lastCountedDay = today;\n baselines.pendingDayCount = 1;\n }\n companion.baselines = baselines;\n\n recomputeXpLevelTitle(companion);\n\n // Check achievements\n const newAchievementIds = checkAchievements(companion, session);\n if (newAchievementIds.length > 0) {\n const now = new Date().toISOString();\n for (const id of newAchievementIds) {\n companion.achievements.push({ id, unlockedAt: now });\n }\n }\n\n return newAchievementIds;\n}\n\nexport function onAgentSpawned(companion: CompanionState): void {\n companion.lifetimeAgentsSpawned++;\n}\n\nexport function onAgentCrashed(companion: CompanionState): void {\n companion.consecutiveCleanSessions = 0;\n // sessionsCrashed is incremented in onSessionComplete (once per session, not per agent)\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nexport function normalizeTask(task: string, cwd: string): string {\n // Simple normalization: lowercase, collapse whitespace, prefix with cwd basename\n const normalized = task.toLowerCase().replace(/\\s+/g, ' ').trim().slice(0, 100);\n const cwdBase = cwd.split('/').pop() ?? cwd;\n return `${cwdBase}:${normalized}`;\n}\n\n// ---------------------------------------------------------------------------\n// Observation engine integration\n// ---------------------------------------------------------------------------\n\nimport type { ObservationContext } from '../shared/companion-types.js';\nimport { runObservationEngine } from './companion-memory.js';\n\nexport function captureObservationContext(\n companion: CompanionState,\n _repoCwd: string, // kept for future, unused today\n): ObservationContext {\n return {\n prevLevel: companion.level,\n prevSessionsCompleted: companion.sessionsCompleted,\n prevConsecutiveEfficientSessions: companion.consecutiveEfficientSessions ?? 0,\n };\n}\n\nexport async function runPostSessionObservations(\n companion: CompanionState,\n session: Session,\n prev: ObservationContext,\n): Promise<void> {\n return runObservationEngine({ companion, session, prev });\n}\n","import stringWidth from 'string-width';\nimport type {\n CompanionState,\n CompanionField,\n CompanionRenderOpts,\n CompanionStats,\n Mood,\n} from './companion-types.js';\n\n// --- Display-width-aware string slice ---\n\n/** Slice a plain-text string to fit within `maxCols` display columns. */\nfunction sliceToWidth(s: string, maxCols: number): string {\n let w = 0;\n let i = 0;\n while (i < s.length) {\n const cp = s.codePointAt(i)!;\n const ch = String.fromCodePoint(cp);\n const cw = stringWidth(ch);\n if (w + cw > maxCols) break;\n w += cw;\n i += ch.length;\n }\n return s.slice(0, i);\n}\n\n// --- Idle hobbies ---\n\nexport const IDLE_HOBBIES: string[] = [\n 'reading Camus',\n 'stacking pebbles',\n 'watching clouds',\n 'sketching boulders',\n 'counting stars',\n 'writing haiku',\n 'practicing zen',\n 'studying geology',\n 'polishing rocks',\n 'mapping the hill',\n 'resting',\n 'stargazing',\n 'whittling',\n 'collecting fossils',\n 'napping on summit',\n 'journaling',\n 'stretching',\n 'humming',\n 'doodling',\n 'tending moss',\n 'making tea',\n 'reading Myth of Sisyphus',\n 'reorganizing rocks',\n 'people watching',\n 'whistling',\n];\n\n// --- Spinner verbs ---\n\nexport const SPINNER_VERBS: string[] = [\n // physical\n 'pushing',\n 'hauling',\n 'heaving',\n 'toiling',\n 'straining',\n 'trudging',\n 'laboring',\n 'rolling',\n 'ascending',\n 'dragging',\n 'shouldering',\n 'hoisting',\n 'lugging',\n 'schlepping',\n 'grinding',\n 'lifting',\n 'bracing',\n 'climbing',\n 'leaning in',\n 'digging in',\n // philosophical\n 'philosophizing',\n 'contemplating',\n 'pondering',\n 'musing',\n 'ruminating',\n 'reflecting',\n 'meditating',\n 'wondering',\n 'questioning',\n 'theorizing',\n 'considering',\n 'deliberating',\n 'introspecting',\n 'cogitating',\n 'brooding',\n // endurance\n 'persevering',\n 'enduring',\n 'persisting',\n 'sustaining',\n 'weathering',\n 'carrying on',\n 'pressing on',\n 'holding steady',\n 'keeping at it',\n 'not stopping',\n // light/silly\n 'napping',\n 'procrastinating',\n 'daydreaming',\n 'vibing',\n 'winging it',\n 'hoping',\n 'improvising',\n 'making do',\n 'whistling',\n];\n\n// --- Base form ---\n//\n// Returns a template with two placeholders:\n// FACE — replaced by getMoodFace() in renderCompanion\n// {BOULDER} — replaced by composeLine() with the agent-count-driven boulder\n//\n// No literal boulder characters are embedded here. The previous design embedded\n// them (`.`, `o`, `O`, `OO`, `@`) which caused splitBodyAndBoulder to either\n// discard multi-char boulders (OO) or corrupt output when the dynamic boulder\n// didn't match the embedded one.\n\nexport function getBaseForm(level: number): string {\n if (level <= 2) return '(FACE) {BOULDER}';\n if (level <= 4) return '(FACE)/ {BOULDER}';\n if (level <= 7) return '/(FACE)/ {BOULDER}';\n if (level <= 11) return '\\\\(FACE)/ {BOULDER}';\n if (level <= 19) return 'ᕦ(FACE)ᕤ {BOULDER}';\n return '♛ᕦ(FACE)ᕤ {BOULDER}';\n}\n\n// --- Mood face ---\n//\n// Each mood has three intensity tiers driven by the winning mood score:\n// mild (score < 30), moderate (30–70), intense (> 70)\n\nconst MOOD_FACES: Record<Mood, [string, string, string]> = {\n happy: ['^.^', '^‿^', '✧‿✧'],\n grinding: ['>.<', '>_<', 'ò.ó'],\n frustrated: ['>.<#', 'ಠ_ಠ', 'ಠ益ಠ'],\n zen: ['‾.‾', '‾‿‾', '˘‿˘'],\n sleepy: ['-.-)zzZ','-_-)zzZ','˘.˘)zzZ'],\n excited: ['*o*', '*◡*', '✦◡✦'],\n existential: ['◉_◉', '⊙_⊙', '◉‸◉'],\n};\n\nexport function getMoodFace(mood: Mood, intensity: number = 0): string {\n const faces = MOOD_FACES[mood];\n if (!faces) throw new Error(`Unknown mood: ${mood as string}`);\n const tier = intensity < 30 ? 0 : intensity <= 70 ? 1 : 2;\n return faces[tier];\n}\n\n// --- Stat cosmetics ---\n\nexport function getStatCosmetics(stats: CompanionStats): string[] {\n const cosmetics: string[] = [];\n if (stats.wisdom > 5) cosmetics.push('wisps');\n if (stats.endurance > 36_000_000) cosmetics.push('trail');\n if (stats.patience > 50) cosmetics.push('zen-prefix');\n return cosmetics;\n}\n\n// --- Boulder form ---\n\nexport function getBoulderForm(agentCount?: number, repoNickname?: string): string {\n let boulder: string;\n if (agentCount === undefined || agentCount <= 0) {\n boulder = '';\n } else if (agentCount <= 2) {\n boulder = 'o';\n } else if (agentCount <= 6) {\n boulder = 'O';\n } else if (agentCount <= 15) {\n boulder = '◉';\n } else if (agentCount <= 35) {\n boulder = '@';\n } else {\n boulder = '@@';\n }\n if (repoNickname !== undefined) {\n boulder = `${boulder} \"${repoNickname}\"`;\n }\n return boulder;\n}\n\n// --- composeLine ---\n//\n// body has already had FACE replaced with the mood face, and still contains\n// the {BOULDER} placeholder from getBaseForm.\n// composeLine applies cosmetics to `boulder`, then substitutes {BOULDER}.\n\nexport function composeLine(\n body: string,\n cosmetics: string[],\n boulder: string,\n): string {\n let b = boulder;\n\n let hasZenPrefix = false;\n\n if (boulder !== '') {\n for (const c of cosmetics) {\n switch (c) {\n case 'wisps':\n b = `~${b}~`;\n break;\n case 'trail':\n b = `${b} ...`;\n break;\n case 'zen-prefix':\n hasZenPrefix = true;\n break;\n }\n }\n } else {\n // Zen prefix is a character trait, not boulder-related\n if (cosmetics.includes('zen-prefix')) hasZenPrefix = true;\n }\n\n let line = b === ''\n ? body.replace(' {BOULDER}', '')\n : body.replace('{BOULDER}', b);\n\n if (hasZenPrefix) line = `☯ ${line}`;\n\n return line;\n}\n\n// --- Color helpers ---\n\ntype AnsiCode = number;\ntype TmuxColor = string;\n\ninterface MoodColor {\n ansi: AnsiCode;\n tmux: TmuxColor;\n}\n\nconst MOOD_COLORS: Record<Mood, MoodColor> = {\n happy: { ansi: 32, tmux: 'green' },\n grinding: { ansi: 33, tmux: 'yellow' },\n frustrated: { ansi: 31, tmux: 'red' },\n zen: { ansi: 36, tmux: 'cyan' },\n sleepy: { ansi: 90, tmux: 'colour245' },\n excited: { ansi: 97, tmux: 'white' },\n existential: { ansi: 35, tmux: 'magenta' },\n};\n\nexport function getMoodTmuxColor(mood: Mood): string {\n return MOOD_COLORS[mood].tmux;\n}\n\nexport function getMoodAnsiCode(mood: Mood): number {\n return MOOD_COLORS[mood].ansi;\n}\n\nfunction colorize(text: string, mood: Mood, tmux: boolean): string {\n const { ansi, tmux: tmuxColor } = MOOD_COLORS[mood];\n if (tmux) {\n return `#[fg=${tmuxColor}]${text}#[fg=default]`;\n }\n return `\\x1b[${ansi}m${text}\\x1b[0m`;\n}\n\n// --- Stat summary string ---\n\nfunction statSummary(stats: CompanionStats): string {\n const endH = Math.floor(stats.endurance / 3_600_000);\n return `STR:${stats.strength} END:${endH}h WIS:${stats.wisdom} PAT:${stats.patience}`;\n}\n\n// --- Main renderer ---\n\nexport function renderCompanion(\n companion: CompanionState,\n fields: CompanionField[],\n opts?: CompanionRenderOpts,\n): string {\n const hasFace = fields.includes('face');\n const hasBoulder = fields.includes('boulder');\n\n const repoNickname = opts?.repoPath !== undefined\n ? companion.repos[opts.repoPath]?.nickname ?? undefined\n : undefined;\n\n const boulder = getBoulderForm(opts?.agentCount, repoNickname);\n const cosmetics = getStatCosmetics(companion.stats);\n\n let facePart: string | null = null;\n let boulderOnlyPart: string | null = null;\n\n if (hasFace) {\n const baseForm = getBaseForm(companion.level);\n const intensity = companion.debugMood?.scores[companion.mood] ?? 0;\n const face = getMoodFace(companion.mood, intensity);\n const bodyWithFace = baseForm.replace('FACE', face);\n facePart = composeLine(bodyWithFace, cosmetics, boulder);\n } else if (hasBoulder) {\n // Boulder standalone (unusual)\n boulderOnlyPart = boulder;\n }\n\n let commentary = fields.includes('commentary')\n ? (companion.lastCommentary?.text ?? '')\n : null;\n\n const parts: string[] = [];\n\n for (const field of fields) {\n switch (field) {\n case 'face':\n if (facePart !== null) parts.push(facePart);\n break;\n case 'boulder':\n if (!hasFace && boulderOnlyPart !== null) parts.push(boulderOnlyPart);\n // If face included, boulder is already embedded — skip\n break;\n case 'title':\n parts.push(companion.title);\n break;\n case 'commentary':\n if (commentary !== null) parts.push(commentary);\n break;\n case 'mood':\n parts.push(`[${companion.mood}]`);\n break;\n case 'level':\n parts.push(`Lv ${companion.level}`);\n break;\n case 'stats':\n parts.push(statSummary(companion.stats));\n break;\n case 'achievements':\n parts.push(`${companion.achievements.length} achievements`);\n break;\n case 'verb': {\n const idx = (opts?.verbIndex ?? companion.spinnerVerbIndex) % SPINNER_VERBS.length;\n parts.push(SPINNER_VERBS[idx]!);\n break;\n }\n case 'hobby': {\n // Rotate hourly based on hour + companion level as seed for variety\n const hobbyIdx = (new Date().getHours() + companion.level) % IDLE_HOBBIES.length;\n parts.push(IDLE_HOBBIES[hobbyIdx]!);\n break;\n }\n }\n }\n\n // Apply maxWidth: truncate commentary first, then right-truncate.\n // Use display width (stringWidth) not .length — faces like ಠ益ಠ contain\n // wide characters where .length < displayWidth, causing writeClipped to\n // hard-clip the line without an ellipsis.\n if (opts?.maxWidth !== undefined) {\n const maxWidth = opts.maxWidth;\n const joined = parts.join(' ');\n const joinedWidth = stringWidth(joined);\n if (joinedWidth > maxWidth && commentary !== null && commentary.length > 0) {\n // Shorten commentary progressively\n const commentaryIdx = parts.indexOf(commentary);\n if (commentaryIdx !== -1) {\n const commentaryWidth = stringWidth(commentary);\n const overhead = joinedWidth - commentaryWidth;\n const available = maxWidth - overhead - 2; // account for double-space\n if (available < 0) {\n parts[commentaryIdx] = '';\n } else {\n parts[commentaryIdx] = sliceToWidth(commentary, available);\n }\n commentary = parts[commentaryIdx];\n }\n }\n const result = parts.filter(p => p.length > 0).join(' ');\n const resultWidth = stringWidth(result);\n const final = resultWidth > maxWidth\n ? sliceToWidth(result, maxWidth - 1) + '…'\n : result;\n\n return applyColor(final, fields, facePart, companion.mood, opts);\n }\n\n const result = parts.filter(p => p.length > 0).join(' ');\n return applyColor(result, fields, facePart, companion.mood, opts);\n}\n\nfunction applyColor(\n result: string,\n fields: CompanionField[],\n facePart: string | null,\n mood: Mood,\n opts?: CompanionRenderOpts,\n): string {\n const useColor = opts?.color === true || opts?.tmuxFormat === true;\n if (!useColor || facePart === null || !fields.includes('face')) return result;\n\n const tmux = opts?.tmuxFormat === true;\n const coloredFace = colorize(facePart, mood, tmux);\n return result.replace(facePart, coloredFace);\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { existsSync, readFileSync, mkdirSync, symlinkSync, rmSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { Session } from './types.js';\nimport { sessionDir, statePath, historySessionDir } from './paths.js';\n\nfunction sanitizeName(name: string): string {\n return name.replace(/[^a-zA-Z0-9-_]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '').slice(0, 40);\n}\n\nfunction buildOutputPath(label: string, dir: string): string {\n const date = new Date().toISOString().slice(0, 10);\n mkdirSync(dir, { recursive: true });\n\n const base = `sisyphus-${label}-${date}`;\n let candidate = join(dir, `${base}.zip`);\n let counter = 1;\n while (existsSync(candidate)) {\n counter++;\n candidate = join(dir, `${base}-${counter}.zip`);\n }\n return candidate;\n}\n\nfunction generateGuide(): string {\n return `# Sisyphus Session Export\n\n## Quick Orientation\n\nStart with \\`session/state.json\\` for the full session state, or \\`history/session.json\\` for a compact summary with metrics.\n\n## session/\n\nProject-local session data — the orchestrator's working directory.\n\n### Top-level files\n- **state.json** — Complete session state: id, task, status, timing, and the full \\`agents[]\\` array (each agent has id, type, instruction, status, reports, Claude session ID, and resume args)\n- **goal.md** — The task description; updated if the goal evolves across phases\n- **initial-prompt.md** — Verbatim user input that started the session\n- **roadmap.md** — Orchestrator's working memory: current stage, exit criteria, active context files, next steps\n- **strategy.md** — Work breakdown: completed stages, current stage decomposition (concerns/phases), and what's ahead\n- **digest.json** — 4-field snapshot: \\`recentWork\\`, \\`unusualEvents\\`, \\`currentActivity\\`, \\`whatsNext\\`\n\n### Subdirectories\n\n**context/** — Research artifacts produced by agents and consumed by downstream agents\n- \\`explore-*.md\\` — Codebase exploration findings (key files, architecture notes)\n- \\`requirements*.md/json\\` — Feature requirements (structured + human-readable)\n- \\`design*.md/json\\` — Architecture specs, decision records, diagrams\n- \\`{agent-id}/plan*.md\\` — Implementation plans (tasks, files to touch, dependencies) — per plan-lead subdirectory\n- \\`e2e-recipe.md\\` — End-to-end validation steps\n- \\`review-*.md\\` — Code review findings (severity-ranked)\n- \\`completion-summary.md\\` — Final handoff document\n\n**logs/** — One \\`cycle-NNN.md\\` per orchestrator cycle. Each logs what happened, agents spawned, user decisions, and key findings.\n\n**prompts/** — Full agent configs, one set per agent:\n- \\`agent-NNN-system.md\\` — System prompt (instructions, tools, output format)\n- \\`agent-NNN-run.sh\\` — Executable bash script to resume the agent (contains env, CLI args, instruction)\n- \\`agent-NNN-plugin/\\` — Plugin directory (hooks, sub-agent configs)\n\n**reports/** — Agent deliverables:\n- \\`agent-NNN-final.md\\` — Final report (findings, implementation summary, or review results)\n- \\`agent-NNN-00N.md\\` — Interim progress reports (optional)\n\n**snapshots/** — Point-in-time checkpoints (\\`snapshots/cycle-N/\\`). Each contains state.json, roadmap.md, strategy.md, and logs/ as they were at that cycle boundary. Used for rollback.\n\n**.tui/** — Lightweight TUI render cache (cycle summaries for display). Regenerable; not primary data.\n\n## history/\n\nGlobal telemetry from the daemon — timing, events, and aggregate metrics.\n\n- **events.jsonl** — Newline-delimited JSON event stream. Each line: \\`{ ts, event, sessionId, data }\\`. Events include session-start, agent-spawned, agent-completed, cycle-boundary, signals-snapshot, session-end, etc. Complete audit trail.\n- **session.json** — Summary: id, name, task, status, timing (activeMs, wallClockMs, efficiency), agent/cycle counts, crash/rollback counts, completion report, and a compact agents array.\n`;\n}\n\nconst execFileAsync = promisify(execFile);\n\nexport async function exportSessionToZip(\n sessionId: string,\n cwd: string,\n options?: { reveal?: boolean; outputDir?: string }\n): Promise<string> {\n const reveal = options?.reveal ?? true;\n const sessDir = sessionDir(cwd, sessionId);\n const histDir = historySessionDir(sessionId);\n const sessExists = existsSync(sessDir);\n const histExists = existsSync(histDir);\n\n if (!sessExists && !histExists) {\n throw new Error(`No data found for session ${sessionId}`);\n }\n\n let label = sessionId.slice(0, 8);\n const stPath = statePath(cwd, sessionId);\n if (existsSync(stPath)) {\n try {\n const state = JSON.parse(readFileSync(stPath, 'utf-8')) as Session;\n if (state.name) {\n label = sanitizeName(state.name);\n }\n } catch { /* use short ID */ }\n }\n\n const dir = options?.outputDir ?? join(homedir(), 'Downloads');\n const outputPath = buildOutputPath(label, dir);\n const tmpDir = `/tmp/sisyphus-export-${sessionId.slice(0, 8)}-${Date.now()}`;\n\n try {\n mkdirSync(tmpDir, { recursive: true });\n\n writeFileSync(join(tmpDir, 'CLAUDE.md'), generateGuide(), 'utf-8');\n\n if (sessExists) {\n symlinkSync(sessDir, join(tmpDir, 'session'));\n }\n if (histExists) {\n symlinkSync(histDir, join(tmpDir, 'history'));\n }\n\n const parts = ['CLAUDE.md', sessExists ? 'session/' : '', histExists ? 'history/' : ''].filter(Boolean) as string[];\n await execFileAsync('zip', ['-rq', outputPath, ...parts], { cwd: tmpDir });\n } finally {\n rmSync(tmpDir, { recursive: true, force: true });\n }\n\n if (reveal) {\n try {\n await execFileAsync('open', ['-R', outputPath]);\n } catch { /* non-fatal if Finder fails */ }\n }\n\n return outputPath;\n}\n","/** Format milliseconds or ISO date range to human-readable duration */\nexport function formatDuration(startOrMs: string | number, endIso?: string | null): string {\n let totalMs: number;\n if (typeof startOrMs === 'number') {\n totalMs = startOrMs;\n } else {\n const start = new Date(startOrMs).getTime();\n const end = endIso ? new Date(endIso).getTime() : Date.now();\n totalMs = end - start;\n }\n const totalSeconds = Math.floor(totalMs / 1000);\n if (totalSeconds < 0) return '0s';\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n if (hours > 0) return `${hours}h${minutes}m`;\n if (minutes > 0) return `${minutes}m${seconds}s`;\n return `${seconds}s`;\n}\n\n/** Map session/agent status to a color name */\nexport function statusColor(status: string): string {\n switch (status) {\n case 'active':\n case 'running':\n return 'green';\n case 'completed':\n return 'cyan';\n case 'paused':\n return 'yellow';\n case 'killed':\n case 'crashed':\n return 'red';\n case 'lost':\n return 'gray';\n default:\n return 'white';\n }\n}\n"],"mappings":"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","names":["existsSync","mkdirSync","readFileSync","renameSync","writeFileSync","dirname","join","randomUUID","state","existsSync","readFileSync","dirname","mkdirSync","join","randomUUID","writeFileSync","renameSync","randomUUID","callHaiku","result","existsSync","readFileSync","mkdirSync","writeFileSync","join","mkdirSync","join","existsSync","readFileSync","writeFileSync"]}
|