openwolf-enhanced 1.9.3

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.
Files changed (127) hide show
  1. package/CHANGELOG.md +386 -0
  2. package/LICENSE +663 -0
  3. package/NOTICE +48 -0
  4. package/README.md +283 -0
  5. package/dist/bin/openwolf.js +10 -0
  6. package/dist/bin/openwolf.js.map +1 -0
  7. package/dist/dashboard/assets/AISuggestions-DHXOgHMM.js +9 -0
  8. package/dist/dashboard/assets/ActivityTimeline-BXLwacZV.js +1 -0
  9. package/dist/dashboard/assets/AnatomyBrowser-CUyC8M2I.js +1 -0
  10. package/dist/dashboard/assets/BugLog-Bxvy1sPW.js +1 -0
  11. package/dist/dashboard/assets/CerebrumViewer-DCySVmzA.js +1 -0
  12. package/dist/dashboard/assets/CronStatus-BA4fmQX3.js +1 -0
  13. package/dist/dashboard/assets/DesignQC-BhNEKryS.js +1 -0
  14. package/dist/dashboard/assets/MemoryViewer-0y9lsDUO.js +1 -0
  15. package/dist/dashboard/assets/ProjectOverview-CC51rVRe.js +1 -0
  16. package/dist/dashboard/assets/StatusBadge-4NJI_F2G.js +1 -0
  17. package/dist/dashboard/assets/TokenUsage-7pCxlnCX.js +55 -0
  18. package/dist/dashboard/assets/index-4O5rk-qB.css +2 -0
  19. package/dist/dashboard/assets/index-jfgWxxsn.js +13 -0
  20. package/dist/dashboard/assets/utils-BqE_aDxV.js +1 -0
  21. package/dist/dashboard/index.html +16 -0
  22. package/dist/hooks/post-read.js +85 -0
  23. package/dist/hooks/post-write.js +520 -0
  24. package/dist/hooks/pre-read.js +107 -0
  25. package/dist/hooks/pre-write.js +120 -0
  26. package/dist/hooks/session-start.js +76 -0
  27. package/dist/hooks/shared.js +0 -0
  28. package/dist/hooks/stop.js +219 -0
  29. package/dist/src/buglog/bug-matcher.js +3 -0
  30. package/dist/src/buglog/bug-matcher.js.map +1 -0
  31. package/dist/src/buglog/bug-tracker.js +89 -0
  32. package/dist/src/buglog/bug-tracker.js.map +1 -0
  33. package/dist/src/cli/bug-cmd.js +31 -0
  34. package/dist/src/cli/bug-cmd.js.map +1 -0
  35. package/dist/src/cli/cron-cmd.js +107 -0
  36. package/dist/src/cli/cron-cmd.js.map +1 -0
  37. package/dist/src/cli/daemon-cmd.js +180 -0
  38. package/dist/src/cli/daemon-cmd.js.map +1 -0
  39. package/dist/src/cli/dashboard.js +88 -0
  40. package/dist/src/cli/dashboard.js.map +1 -0
  41. package/dist/src/cli/designqc-cmd.js +31 -0
  42. package/dist/src/cli/designqc-cmd.js.map +1 -0
  43. package/dist/src/cli/doctor-cmd.js +94 -0
  44. package/dist/src/cli/doctor-cmd.js.map +1 -0
  45. package/dist/src/cli/index.js +158 -0
  46. package/dist/src/cli/index.js.map +1 -0
  47. package/dist/src/cli/init.js +493 -0
  48. package/dist/src/cli/init.js.map +1 -0
  49. package/dist/src/cli/registry.js +93 -0
  50. package/dist/src/cli/registry.js.map +1 -0
  51. package/dist/src/cli/scan.js +39 -0
  52. package/dist/src/cli/scan.js.map +1 -0
  53. package/dist/src/cli/status.js +98 -0
  54. package/dist/src/cli/status.js.map +1 -0
  55. package/dist/src/cli/update.js +435 -0
  56. package/dist/src/cli/update.js.map +1 -0
  57. package/dist/src/daemon/cron-engine.js +321 -0
  58. package/dist/src/daemon/cron-engine.js.map +1 -0
  59. package/dist/src/daemon/file-watcher.js +64 -0
  60. package/dist/src/daemon/file-watcher.js.map +1 -0
  61. package/dist/src/daemon/health.js +23 -0
  62. package/dist/src/daemon/health.js.map +1 -0
  63. package/dist/src/daemon/wolf-daemon.js +440 -0
  64. package/dist/src/daemon/wolf-daemon.js.map +1 -0
  65. package/dist/src/designqc/designqc-capture.js +278 -0
  66. package/dist/src/designqc/designqc-capture.js.map +1 -0
  67. package/dist/src/designqc/designqc-engine.js +159 -0
  68. package/dist/src/designqc/designqc-engine.js.map +1 -0
  69. package/dist/src/designqc/designqc-types.js +5 -0
  70. package/dist/src/designqc/designqc-types.js.map +1 -0
  71. package/dist/src/hooks/post-read.js +86 -0
  72. package/dist/src/hooks/post-read.js.map +1 -0
  73. package/dist/src/hooks/post-write.js +521 -0
  74. package/dist/src/hooks/post-write.js.map +1 -0
  75. package/dist/src/hooks/pre-read.js +108 -0
  76. package/dist/src/hooks/pre-read.js.map +1 -0
  77. package/dist/src/hooks/pre-write.js +121 -0
  78. package/dist/src/hooks/pre-write.js.map +1 -0
  79. package/dist/src/hooks/session-start.js +77 -0
  80. package/dist/src/hooks/session-start.js.map +1 -0
  81. package/dist/src/hooks/shared.js +0 -0
  82. package/dist/src/hooks/shared.js.map +1 -0
  83. package/dist/src/hooks/stop.js +220 -0
  84. package/dist/src/hooks/stop.js.map +1 -0
  85. package/dist/src/scanner/anatomy-scanner.js +278 -0
  86. package/dist/src/scanner/anatomy-scanner.js.map +1 -0
  87. package/dist/src/scanner/description-extractor.js +1007 -0
  88. package/dist/src/scanner/description-extractor.js.map +1 -0
  89. package/dist/src/scanner/project-root.js +52 -0
  90. package/dist/src/scanner/project-root.js.map +1 -0
  91. package/dist/src/tracker/token-estimator.js +20 -0
  92. package/dist/src/tracker/token-estimator.js.map +1 -0
  93. package/dist/src/tracker/token-ledger.js +55 -0
  94. package/dist/src/tracker/token-ledger.js.map +1 -0
  95. package/dist/src/tracker/waste-detector.js +101 -0
  96. package/dist/src/tracker/waste-detector.js.map +1 -0
  97. package/dist/src/utils/dashboard-auth.js +50 -0
  98. package/dist/src/utils/dashboard-auth.js.map +1 -0
  99. package/dist/src/utils/fs-safe.js +135 -0
  100. package/dist/src/utils/fs-safe.js.map +1 -0
  101. package/dist/src/utils/hooks-deploy.js +70 -0
  102. package/dist/src/utils/hooks-deploy.js.map +1 -0
  103. package/dist/src/utils/logger.js +48 -0
  104. package/dist/src/utils/logger.js.map +1 -0
  105. package/dist/src/utils/maintenance.js +385 -0
  106. package/dist/src/utils/maintenance.js.map +1 -0
  107. package/dist/src/utils/paths.js +23 -0
  108. package/dist/src/utils/paths.js.map +1 -0
  109. package/dist/src/utils/platform.js +14 -0
  110. package/dist/src/utils/platform.js.map +1 -0
  111. package/dist/src/utils/seed.js +61 -0
  112. package/dist/src/utils/seed.js.map +1 -0
  113. package/package.json +82 -0
  114. package/src/templates/OPENWOLF.md +147 -0
  115. package/src/templates/STATUS.md +48 -0
  116. package/src/templates/anatomy.md +5 -0
  117. package/src/templates/buglog.json +4 -0
  118. package/src/templates/cerebrum.md +22 -0
  119. package/src/templates/claude-md-snippet.md +5 -0
  120. package/src/templates/claude-rules-openwolf.md +17 -0
  121. package/src/templates/config.json +83 -0
  122. package/src/templates/cron-manifest.json +97 -0
  123. package/src/templates/cron-state.json +7 -0
  124. package/src/templates/identity.md +9 -0
  125. package/src/templates/memory.md +4 -0
  126. package/src/templates/reframe-frameworks.md +597 -0
  127. package/src/templates/token-ledger.json +21 -0
package/NOTICE ADDED
@@ -0,0 +1,48 @@
1
+ OpenWolf Enhanced
2
+ =================
3
+
4
+ This project is a fork of OpenWolf, a token-conscious context manager for
5
+ Claude Code projects.
6
+
7
+ Original work:
8
+ OpenWolf
9
+ Copyright (c) 2026 Cytostack Pvt Ltd
10
+ https://github.com/cytostack/openwolf
11
+ Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
12
+
13
+ This fork:
14
+ OpenWolf Enhanced
15
+ Copyright (c) 2026 Krynex Labs
16
+ https://github.com/bassprofressor-lab/openwolf-enhanced
17
+ Also licensed under the GNU Affero General Public License v3.0 (AGPL-3.0),
18
+ as required by the license of the original work.
19
+
20
+ The full license text is in the LICENSE file. Per the AGPL, the copyright and
21
+ license of the original work are preserved, and this NOTICE documents the
22
+ modifications made in this fork.
23
+
24
+ Summary of modifications relative to the upstream 1.0.4 baseline
25
+ ----------------------------------------------------------------
26
+ - Bounded storage growth: token-ledger.json (sessions and per-session I/O),
27
+ buglog.json, cron dead-letter queue, and waste_flags are all capped.
28
+ - Tamed auto bug-detection: removed the noisy "significant diff" catch-all,
29
+ widened the de-duplication window, and made buglog IDs collision-free.
30
+ - anatomy.md is no longer rewritten when a file's entry is unchanged, and the
31
+ edited file is read only once per write.
32
+ - Daemon no longer re-reads/broadcasts large files on every change; large
33
+ files are trimmed for dashboard delivery.
34
+ - New `openwolf doctor` command: daemon-independent .wolf/ health report and
35
+ compaction (ledger, memory consolidation, buglog de-dup, backup pruning,
36
+ log rotation, tmp cleanup).
37
+ - New `.wolfignore` support: gitignore-style scoping for anatomy scanning and
38
+ hook tracking.
39
+ - New `openwolf.retention` config block: all limits are user-tunable.
40
+ - `openwolf update` now deep-merges config.json instead of overwriting it, so
41
+ user settings survive updates.
42
+ - `openwolf status` now reports the .wolf/ footprint and size warnings.
43
+ - Stop hook opportunistically consolidates memory.md when it grows too large,
44
+ so maintenance works even when the daemon is not running.
45
+ - Legacy bare-array buglog.json files are read tolerantly and migrated to the
46
+ { version, bugs } schema without data loss.
47
+
48
+ See CHANGELOG.md for details.
package/README.md ADDED
@@ -0,0 +1,283 @@
1
+ <p align="center">
2
+ <img src="openwolf-icon.png" alt="OpenWolf Enhanced" width="120" />
3
+ </p>
4
+
5
+ <h1 align="center">OpenWolf Enhanced</h1>
6
+
7
+ <p align="center">
8
+ <strong>A second brain for Claude Code — now with bounded storage and self-maintenance.</strong><br />
9
+ Project intelligence, token tracking, and invisible enforcement through 6 hook scripts. Zero workflow changes.
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-AGPL--3.0-blue.svg" alt="License: AGPL-3.0" /></a>
14
+ <a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-20%2B-green.svg" alt="Node.js" /></a>
15
+ <a href="https://github.com/cytostack/openwolf"><img src="https://img.shields.io/badge/fork%20of-cytostack%2Fopenwolf-lightgrey.svg" alt="Fork of cytostack/openwolf" /></a>
16
+ <a href="https://www.krynexlabs.de/en/openwolf-enhanced"><img src="https://img.shields.io/badge/by-Krynex%20Labs-6D28D9.svg" alt="by Krynex Labs" /></a>
17
+ </p>
18
+
19
+ ---
20
+
21
+ > **This is an enhanced fork of [OpenWolf](https://github.com/cytostack/openwolf)** by Cytostack Pvt Ltd.
22
+ > The original is a great idea; in long-lived projects its `.wolf/` directory could grow
23
+ > without bound (multi-megabyte token ledgers, an ever-growing bug log, full-file rewrites
24
+ > on every edit). This fork keeps everything the original does and makes storage **bounded,
25
+ > self-maintaining, and scopeable**. The CLI is still `openwolf`, so it's a drop-in replacement.
26
+ > See [what's enhanced](#whats-enhanced) and the [CHANGELOG](CHANGELOG.md).
27
+
28
+ ## Why OpenWolf Exists
29
+
30
+ Claude Code is powerful but it works blind. It doesn't know what a file contains until it opens it. It can't tell a 50-token config from a 2,000-token module. It reads the same file multiple times in one session without noticing. It has no index of your project, no memory of your corrections, and no awareness of what it already tried.
31
+
32
+ OpenWolf gives Claude a second brain: a file index so it knows what files contain before reading them, a learning memory that accumulates your preferences and past mistakes, and a token ledger that tracks everything. All through 6 invisible hook scripts that fire on every Claude action.
33
+
34
+ ## What's Enhanced
35
+
36
+ Everything from upstream still works. On top of that:
37
+
38
+ | Area | Enhancement |
39
+ |------|-------------|
40
+ | 🩺 **Self-maintenance** | New `openwolf doctor` — a daemon-independent command that reports the `.wolf/` footprint and compacts everything (ledger, memory, bug log, backups, logs, tmp), and flags cross-project registry issues (dead entries, dashboard-port collisions). `--dry-run` to preview. |
41
+ | 📊 **Dashboard upgrades** | A daemon-down banner (no more empty panels that look like an empty project), a Design QC thumbnail grid + lightbox (was filenames only), and theme-aware chart tooltips. |
42
+ | 📦 **Bounded storage** | `token-ledger.json`, `buglog.json`, cron dead-letter queue and waste flags are all capped. No more runaway multi-MB files. |
43
+ | 🎯 **`.wolfignore`** | gitignore-style scoping for anatomy scanning **and** hook tracking. Stop indexing `vendor/`, generated code, or `*.log`. |
44
+ | ⚙️ **Tunable retention** | New `openwolf.retention` config block — every limit is user-adjustable. |
45
+ | 🔁 **Non-destructive updates** | `openwolf update` now **deep-merges** `config.json` instead of overwriting it, so your settings survive. |
46
+ | 🧹 **Less churn** | `anatomy.md` isn't rewritten when nothing changed; the daemon no longer re-broadcasts large files on every write; auto bug-detection no longer flags ordinary refactors. |
47
+ | 📏 **Visibility** | `openwolf status` now shows the `.wolf/` footprint and size warnings. |
48
+
49
+ ### Security & correctness hardening (1.2.0)
50
+
51
+ This fork also adopts security and bug fixes that were reported/proposed upstream but never
52
+ merged (the upstream repo has been inactive since March 2026):
53
+
54
+ - 🔒 **Dashboard is no longer network-exposed** — binds to `127.0.0.1` (was `0.0.0.0`) and
55
+ requires a per-project token on every API request and WebSocket connection, closing an
56
+ unauthenticated path to trigger cron tasks. *(upstream #30, #34)*
57
+ - 🔒 **No command injection** — shell command strings replaced with argument arrays
58
+ (`execFileSync`); the PM2 process name is sanitized. *(upstream #34)*
59
+ - 🔒 **No path traversal** — cron AI tasks can't read files outside the project root. *(upstream #34)*
60
+ - 🛡 **No secret leakage** — private keys, certs and keystores (`.pem`, `.key`, `.p8`,
61
+ `.keystore`, `id_rsa`, `credentials`…) are excluded from the brain, not just `.env`. *(upstream #54)*
62
+ - 🐛 **CRLF no longer wipes `anatomy.md`** — the entry parser tolerates `\r\n`, so Windows /
63
+ `git autocrlf` repos don't get their file map truncated. *(upstream #50)*
64
+ - 🐛 **`bug search` won't crash** on entries with missing fields or a `files[]` array. *(upstream #44)*
65
+ - 🐛 **Re-reads after edits aren't flagged** — a file that changed during the session can be
66
+ re-read without a "already read" warning. *(upstream #41)*
67
+ - 🐛 **No off-project tracking** — files outside the project root never enter anatomy/memory. *(upstream #56)*
68
+ - 🐛 **Saner auto bug-detection** — the noisy "any big diff is a bug" heuristic was removed. *(upstream #28)*
69
+ - 🐛 **`.gitignore` is respected** — anatomy scanning and hook tracking honor `.gitignore` (not just `.wolfignore`), so ignored/build files aren't indexed. *(upstream #15)*
70
+ - 🐛 **`init` won't scaffold `$HOME`** — `findProjectRoot` stops at the home directory, and multi-project port collisions are avoided. *(upstream #20)*
71
+
72
+ ### Adopted upstream PRs (1.3.x)
73
+
74
+ Useful upstream pull requests that were never merged, adapted to this fork:
75
+
76
+ - 💬 **End-of-turn reminders actually reach Claude** — the stop hook's reminders (unlogged bug
77
+ fixes, stale `cerebrum.md`, missing session summary) were written to stderr, which the model
78
+ never sees; they now use the `additionalContext` stdout channel, and each fires **at most
79
+ once per session** instead of nagging every turn. *(upstream #55)*
80
+ - 🖥 **Works on WSL2 / EFS** — file copies use a read+write shim, fixing `EPERM` on WSL2 mounts
81
+ under EFS-encrypted directories. *(upstream #33)*
82
+ - 🏷 **Cleaner hook management** — `.claude/settings.json` entries are tagged `_managedBy:
83
+ "openwolf"`, so `init`/`update` can replace/remove only their own hooks. *(upstream #32)*
84
+ - 🎯 **Dart support** — `.dart` files are recognized for token estimation. *(upstream #10)*
85
+
86
+ ### Reliability, dependencies & dashboard (1.6–1.9)
87
+
88
+ Ongoing hardening and modernization beyond the upstream backlog:
89
+
90
+ - 🔒 **Zero known vulnerabilities** — a self-audit fixed 11 transitive advisories; `pnpm audit --prod` is clean, kept current with a dependency pass (all dev **and** runtime majors upgraded: TypeScript 7, Vite 8, recharts 3, chokidar 5, commander 15, node-cron 4…). *(1.6.1, 1.8.0)*
91
+ - 🔐 **Safe concurrent sessions** — the token-ledger read-modify-write is wrapped in a best-effort file lock, so two sessions ending at once (or a session plus the cron report) can't clobber each other. It never blocks a hook for long. *(1.7.0)*
92
+ - 🧪 **Test suite** — `pnpm test` covers the core logic (retention/ledger caps, buglog migration, ignore matcher, secret detection, CRLF parsing). *(1.7.0)*
93
+ - 🔒 **`/api/switch` is allow-listed** — the daemon only switches to projects in the registry, not arbitrary directories. *(1.7.0)*
94
+ - 🐛 **File-watcher exclusions actually fire** — a latent bug (glob strings silently stopped matching under chokidar 4+) meant the daemon was re-reading and broadcasting `token-ledger.json`/`buglog.json` on every write; fixed with a predicate matcher. *(1.8.0)*
95
+ - 📊 **Dashboard quick wins** — daemon-down banner with retry, Design QC thumbnails + lightbox (new path-safe token-gated image route), theme-aware tooltips. *(1.9.0)*
96
+ - 💾 **Backups stay small** — `update` no longer snapshots the regenerable `token-ledger.json` into every backup, and `createBackup()` now enforces `retention.backups_keep` on the write path instead of only when `doctor` happened to run. One project went from 41 MB to 9 MB of `.wolf/` with no loss of restorable state. *(1.9.1)*
97
+ - 🌱 **`update` seeds files a project never received** — user-data files are never overwritten, but that was implemented as *never touched*, so a project initialised before a file existed never got one. `STATUS.md` was the casualty. Missing files are now created from the templates; existing ones are still left alone. *(1.9.2)*
98
+ - 🪝 **The hooks we test are the hooks we ship** — hook deployment and the test suite pointed at two different `tsc` outputs of the same sources, free to diverge. One artifact now, deployed from one shared `hooks-deploy` module. *(1.9.2)*
99
+
100
+ Full details in the [CHANGELOG](CHANGELOG.md) and [NOTICE](NOTICE).
101
+
102
+ ## Quick Start
103
+
104
+ ```bash
105
+ npm install -g openwolf-enhanced
106
+ ```
107
+
108
+ > **Note:** this is the maintained fork. `npm install -g openwolf` installs the
109
+ > original `openwolf` (last released 1.0.4, March 2026, unmaintained) — a different
110
+ > package. Install `openwolf-enhanced` for the bounded-storage, self-maintenance and
111
+ > security work described above. Both provide the same `openwolf` command.
112
+
113
+ <details>
114
+ <summary>Install from source instead</summary>
115
+
116
+ ```bash
117
+ git clone https://github.com/bassprofressor-lab/openwolf-enhanced.git
118
+ cd openwolf-enhanced
119
+ pnpm install
120
+ pnpm build # builds CLI, hooks, and dashboard
121
+ npm install -g . # installs the `openwolf` command globally
122
+ ```
123
+ </details>
124
+
125
+ Then, in any project:
126
+
127
+ ```bash
128
+ cd your-project
129
+ openwolf init
130
+ ```
131
+
132
+ That's it. Use `claude` normally. OpenWolf is watching.
133
+
134
+ ### Rebuilding an installed copy
135
+
136
+ Two things to know before you re-run `pnpm build` on a copy you have already installed globally:
137
+
138
+ - **`prebuild` deletes `dist/` before compiling**, and the global `openwolf` command is a symlink
139
+ into `dist/bin/openwolf.js`. If the build then fails, the CLI is gone until you build again. Back
140
+ `dist/` up first if you are mid-change, or build in a clean checkout.
141
+ - **A rebuild does not deploy anything.** The hooks that actually run are per-project copies under
142
+ `<project>/.wolf/hooks/`, invoked by `.claude/settings.json` — not the installed package. Run
143
+ `openwolf update` afterwards to push new hooks into your projects (it touches *every* registered
144
+ project; scope it with `--project <name>`).
145
+
146
+ > **Upgrading the tool?** The hooks that actually run are **per-project copies** in
147
+ > `<project>/.wolf/hooks/`, not the global package. After rebuilding/reinstalling, run
148
+ > `openwolf update` (or `openwolf update --project <name>`) to copy the new hooks into your
149
+ > projects — a global reinstall alone does not update them. `openwolf update` with no
150
+ > `--project` updates **all** registered projects.
151
+
152
+ ## What It Creates
153
+
154
+ `openwolf init` creates a `.wolf/` directory in your project:
155
+
156
+ | File | Purpose |
157
+ |------|---------|
158
+ | `anatomy.md` | Project file map with descriptions and token estimates |
159
+ | `cerebrum.md` | Learned preferences, corrections, Do-Not-Repeat list |
160
+ | `memory.md` | Chronological action log with token estimates |
161
+ | `buglog.json` | Bug fix memory, searchable, prevents re-discovery |
162
+ | `token-ledger.json` | Lifetime token tracking and session history |
163
+ | `hooks/` | 6 Claude Code lifecycle hooks (pure Node.js) |
164
+ | `config.json` | Configuration with sensible defaults (incl. `retention`) |
165
+ | `identity.md` | Agent persona for this project |
166
+ | `OPENWOLF.md` | Instructions Claude follows every session |
167
+
168
+ ## How It Works
169
+
170
+ Before Claude reads a file, OpenWolf tells it what the file contains and how large it is. If Claude already read that file this session, OpenWolf warns it. Before Claude writes code, OpenWolf checks your `cerebrum.md` for known mistakes. After every write, it auto-updates the project map and logs token usage. You see none of this. It just happens.
171
+
172
+ ```
173
+ You type a message
174
+
175
+ Claude decides to read a file
176
+
177
+ OpenWolf: "anatomy.md says this file is ~380 tokens. Description: Main entry point."
178
+
179
+ Claude reads the file → OpenWolf logs the read, checks for repeated reads
180
+
181
+ Claude writes code → OpenWolf checks cerebrum.md for known mistakes
182
+
183
+ Claude finishes → OpenWolf updates anatomy.md, appends to memory.md, updates the ledger
184
+ ```
185
+
186
+ ## Keeping `.wolf/` Healthy
187
+
188
+ The `.wolf/` directory is designed to stay small, but on very active projects you can compact it any time — no daemon required:
189
+
190
+ ```bash
191
+ openwolf doctor --dry-run # report footprint + warnings, change nothing
192
+ openwolf doctor # compact ledger, consolidate memory, dedup buglog,
193
+ # prune backups, rotate logs, clear tmp
194
+ ```
195
+
196
+ `openwolf status` shows the current footprint and warns before anything gets large.
197
+
198
+ ### Tuning limits
199
+
200
+ Edit the `openwolf.retention` block in `.wolf/config.json` (defaults shown):
201
+
202
+ ```json
203
+ {
204
+ "openwolf": {
205
+ "retention": {
206
+ "token_ledger_max_sessions": 200,
207
+ "session_io_max": 100,
208
+ "buglog_max_entries": 200,
209
+ "backups_keep": 10,
210
+ "memory_consolidate_after_days": 7,
211
+ "memory_max_bytes": 262144,
212
+ "daemon_log_max_bytes": 524288
213
+ }
214
+ }
215
+ }
216
+ ```
217
+
218
+ These survive `openwolf update` (config is deep-merged, not overwritten).
219
+
220
+ ### Scoping with `.wolfignore`
221
+
222
+ Create a `.wolfignore` at your project root to exclude paths from anatomy scanning and hook tracking (gitignore-style):
223
+
224
+ ```
225
+ vendor/
226
+ dist/
227
+ **/*.generated.ts
228
+ *.log
229
+ ```
230
+
231
+ ## Commands
232
+
233
+ ```
234
+ openwolf init Initialize .wolf/ and register hooks
235
+ openwolf status Show health, stats, .wolf/ footprint, size warnings
236
+ openwolf doctor Report + compact .wolf/ (daemon-independent) [--dry-run]
237
+ openwolf scan Refresh the project structure map
238
+ openwolf scan --check Verify anatomy matches filesystem (exits 1 if stale)
239
+ openwolf dashboard Open the real-time web dashboard
240
+ openwolf daemon start Start background task scheduler
241
+ openwolf daemon stop Stop the scheduler
242
+ openwolf daemon restart Restart the scheduler
243
+ openwolf daemon logs View scheduler logs
244
+ openwolf cron list Show all scheduled tasks
245
+ openwolf cron run <id> Trigger a task manually
246
+ openwolf cron retry <id> Retry a dead-lettered task
247
+ openwolf designqc Capture full-page screenshots for design evaluation
248
+ openwolf bug search <term> Search bug memory for known fixes
249
+ openwolf update Update registered projects (deep-merges config)
250
+ openwolf restore [backup] Restore .wolf/ from a timestamped backup
251
+ ```
252
+
253
+ ## Design QC
254
+
255
+ Capture full-page screenshots of your running app and let Claude evaluate the design.
256
+
257
+ ```bash
258
+ openwolf designqc
259
+ ```
260
+
261
+ Auto-detects your dev server, captures viewport-height JPEG sections of every route, and saves them to `.wolf/designqc-captures/`. Then tell Claude to read the screenshots and evaluate. Requires `puppeteer-core`.
262
+
263
+ ## Requirements
264
+
265
+ - Node.js 20+
266
+ - Claude Code CLI
267
+ - Windows, macOS, or Linux
268
+ - Optional: PM2 for persistent background tasks
269
+ - Optional: `puppeteer-core` for Design QC screenshots
270
+
271
+ ## Limitations
272
+
273
+ - Claude Code hooks are a relatively new feature. OpenWolf falls back to `CLAUDE.md` instructions when hooks don't fire.
274
+ - Token tracking is estimation-based (character-to-token ratio), not exact API counts. Accurate to within ~15%.
275
+ - `cerebrum.md` depends on Claude following instructions to update it after corrections. Compliance is ~85–90%, not 100%.
276
+
277
+ ## Credits
278
+
279
+ OpenWolf was created by [Cytostack Pvt Ltd](https://github.com/cytostack/openwolf) (Farhan Palathinkal Afsal). This enhanced fork is maintained by **[Krynex Labs](https://krynexlabs.de)** — AI engineering & automation. Huge thanks to the original authors for the design and the idea.
280
+
281
+ ## License
282
+
283
+ **AGPL-3.0** — same as the original. See [LICENSE](LICENSE) and [NOTICE](NOTICE). As a derivative work under the AGPL, this fork preserves the original copyright and remains AGPL-3.0; if you run a modified version as a network service, you must make your source available to its users.
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ const major = parseInt(process.versions.node.split(".")[0], 10);
3
+ if (major < 20) {
4
+ console.error(`OpenWolf requires Node.js 20 or higher. You are running ${process.version}.`);
5
+ process.exit(1);
6
+ }
7
+ import { createProgram } from "../src/cli/index.js";
8
+ const program = createProgram();
9
+ program.parse(process.argv);
10
+ //# sourceMappingURL=openwolf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openwolf.js","sourceRoot":"","sources":["../../bin/openwolf.ts"],"names":[],"mappings":";AAEA,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChE,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;IACf,OAAO,CAAC,KAAK,CAAC,2DAA2D,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC;IAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAChC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import{a as e,c as t,r as n}from"./index-jfgWxxsn.js";import{i as r}from"./utils-BqE_aDxV.js";var i=t(e(),1),a=n(),o=[{key:`achievements`,title:`Achievements`,icon:`🏆`,color:`#059669`},{key:`improvements`,title:`Improvements`,icon:`✨`,color:`#3b82f6`},{key:`next_tasks`,title:`Next Tasks`,icon:`📋`,color:`#d97706`},{key:`risks`,title:`Risks & Tech Debt`,icon:`🛡`,color:`#dc2626`}],s=`Analyze this project and write a JSON file to .wolf/suggestions.json with this exact structure:
2
+ {
3
+ "generated_at": "<ISO timestamp>",
4
+ "achievements": ["..."],
5
+ "improvements": ["..."],
6
+ "next_tasks": ["..."],
7
+ "risks": ["..."]
8
+ }
9
+ Base it on the recent memory, anatomy, and current project state. Be specific and actionable.`;function c({data:e}){let{suggestions:t}=e,[n,c]=(0,i.useState)(!1),l=()=>{navigator.clipboard.writeText(s).then(()=>{c(!0),setTimeout(()=>c(!1),2e3)})};return t?(0,a.jsxs)(`div`,{children:[(0,a.jsxs)(`div`,{className:`flex items-center justify-between mb-6`,children:[(0,a.jsxs)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:[`Generated: `,t.generated_at?r(t.generated_at):`unknown`]}),(0,a.jsx)(`button`,{onClick:l,className:`px-3 py-1.5 text-xs rounded-lg transition-colors`,style:{background:`var(--bg-surface-hover)`,border:`1px solid var(--border-subtle)`,color:n?`var(--accent)`:`var(--text-secondary)`},children:n?`Copied!`:`Regenerate via Claude`})]}),(0,a.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:o.map(({key:e,title:n,icon:r,color:i})=>{let o=t[e]||[];return(0,a.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`${i}08`,border:`1px solid ${i}33`},children:[(0,a.jsxs)(`div`,{className:`flex items-center gap-2 mb-3`,children:[(0,a.jsx)(`span`,{className:`text-lg`,children:r}),(0,a.jsx)(`h3`,{className:`font-medium`,style:{color:i},children:n})]}),o.length===0?(0,a.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`None reported.`}):(0,a.jsx)(`ul`,{className:`space-y-2`,children:o.map((e,t)=>(0,a.jsxs)(`li`,{className:`text-sm flex items-start gap-2`,style:{color:`var(--text-secondary)`},children:[(0,a.jsx)(`span`,{className:`mt-1 shrink-0`,style:{color:`var(--text-faint)`},children:`•`}),(0,a.jsx)(`span`,{children:e})]},t))})]},e)})})]}):(0,a.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-12 text-center`,children:[(0,a.jsx)(`div`,{className:`text-4xl mb-3`,children:`✦`}),(0,a.jsx)(`h3`,{className:`font-medium mb-2`,style:{color:`var(--text-secondary)`},children:`No AI suggestions yet`}),(0,a.jsx)(`p`,{className:`text-sm max-w-sm mb-6`,style:{color:`var(--text-muted)`},children:`Suggestions are generated by Claude during your sessions. Paste this prompt into your next Claude Code conversation:`}),(0,a.jsxs)(`div`,{className:`w-full max-w-lg text-left rounded-xl overflow-hidden`,style:{border:`1px solid var(--border-subtle)`},children:[(0,a.jsxs)(`div`,{className:`flex items-center justify-between px-4 py-2`,style:{background:`var(--bg-surface-hover)`,borderBottom:`1px solid var(--border-subtle)`},children:[(0,a.jsx)(`span`,{className:`text-xs font-medium`,style:{color:`var(--text-muted)`},children:`Prompt for Claude`}),(0,a.jsx)(`button`,{onClick:l,className:`text-xs px-3 py-1 rounded-md transition-colors`,style:{background:n?`var(--accent-subtle)`:`var(--bg-surface)`,border:`1px solid var(--border-subtle)`,color:n?`var(--accent)`:`var(--text-secondary)`},children:n?`Copied!`:`Copy`})]}),(0,a.jsx)(`pre`,{className:`text-xs px-4 py-3 whitespace-pre-wrap`,style:{background:`var(--bg-code)`,color:`var(--text-secondary)`},children:s})]}),(0,a.jsx)(`p`,{className:`text-xs mt-4`,style:{color:`var(--text-faint)`},children:`Claude will write the results here automatically. They update live.`})]})}export{c as AISuggestions};
@@ -0,0 +1 @@
1
+ import{a as e,c as t,r as n}from"./index-jfgWxxsn.js";var r=t(e(),1),i=n();function a({data:e}){let{memory:t}=e,[n,a]=(0,r.useState)(`all`),[o,s]=(0,r.useState)(``),[c,l]=(0,r.useState)(!0),u=(0,r.useMemo)(()=>{let e=t;if(n===`today`){let t=new Date().toISOString().slice(0,10);e=e.filter(e=>e.date===t)}else if(n===`week`){let t=new Date(Date.now()-7*864e5).toISOString().slice(0,10);e=e.filter(e=>e.date>=t)}if(o){let t=o.toLowerCase();e=e.map(e=>({...e,entries:e.entries.filter(e=>e.action.toLowerCase().includes(t)||e.files.toLowerCase().includes(t))})).filter(e=>e.entries.length>0)}return e},[t,n,o]);return(0,i.jsxs)(`div`,{children:[(0,i.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 mb-4`,children:[(0,i.jsx)(`div`,{className:`flex gap-1 rounded-lg p-1`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[`all`,`today`,`week`].map(e=>(0,i.jsx)(`button`,{onClick:()=>a(e),className:`px-3 py-1 text-xs rounded-md transition-colors`,style:{background:n===e?`var(--bg-surface-hover)`:`transparent`,color:n===e?`var(--text-primary)`:`var(--text-muted)`},children:e===`all`?`All`:e===`today`?`Today`:`This Week`},e))}),(0,i.jsx)(`input`,{type:`text`,placeholder:`Search actions...`,value:o,onChange:e=>s(e.target.value),className:`rounded-lg px-3 py-1.5 text-sm flex-1 min-w-[200px] focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}}),(0,i.jsx)(`button`,{onClick:()=>l(!c),className:`px-3 py-1.5 text-xs rounded-lg`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-muted)`},children:c?`Flat view`:`Group by session`})]}),u.length===0?(0,i.jsx)(`div`,{className:`text-center py-12`,style:{color:`var(--text-muted)`},children:`No activity found.`}):c?u.map((e,t)=>(0,i.jsxs)(`div`,{className:`mb-4`,children:[(0,i.jsxs)(`div`,{className:`text-sm font-medium mb-2`,style:{color:`var(--text-muted)`},children:[e.date,` `,e.time,` — `,e.entries.length,` actions`]}),(0,i.jsx)(`div`,{className:`rounded-xl`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:e.entries.map((t,n)=>(0,i.jsxs)(`div`,{className:`flex items-center gap-4 px-4 py-3`,style:{borderBottom:n<e.entries.length-1?`1px solid var(--border)`:`none`},children:[(0,i.jsx)(`span`,{className:`text-xs font-mono w-12 shrink-0`,style:{color:`var(--text-faint)`},children:t.time}),(0,i.jsx)(`span`,{className:`w-2 h-2 rounded-full shrink-0 ${t.action.includes(`Created`)?`bg-emerald-500`:t.action.includes(`Edited`)?`bg-blue-500`:``}`,style:{background:!t.action.includes(`Created`)&&!t.action.includes(`Edited`)?`var(--text-faint)`:void 0}}),(0,i.jsx)(`span`,{className:`text-sm flex-1`,style:{color:`var(--text-secondary)`},children:t.action}),(0,i.jsx)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:t.tokens})]},n))})]},t)):(0,i.jsx)(`div`,{className:`rounded-xl`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:u.flatMap(e=>e.entries.map((t,n)=>(0,i.jsxs)(`div`,{className:`flex items-center gap-4 px-4 py-3`,style:{borderBottom:`1px solid var(--border)`},children:[(0,i.jsx)(`span`,{className:`text-xs font-mono w-20 shrink-0`,style:{color:`var(--text-faint)`},children:e.date}),(0,i.jsx)(`span`,{className:`text-xs font-mono w-12 shrink-0`,style:{color:`var(--text-faint)`},children:t.time}),(0,i.jsx)(`span`,{className:`text-sm flex-1`,style:{color:`var(--text-secondary)`},children:t.action}),(0,i.jsx)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:t.tokens})]},`${e.date}-${n}`)))})]})}export{a as ActivityTimeline};
@@ -0,0 +1 @@
1
+ import{a as e,c as t,r as n}from"./index-jfgWxxsn.js";import{r,t as i}from"./utils-BqE_aDxV.js";var a=t(e(),1),o=n();function s({tokens:e,className:t}){return(0,o.jsxs)(`span`,{className:i(`font-mono text-xs`,e<200?`text-emerald-400`:e<1e3?`text-amber-400`:`text-red-400`,t),children:[`~`,r(e),` tok`]})}function c(e){let t={name:`.`,path:`.`,children:[],files:[]},n=new Map;n.set(`./`,t);for(let r of e){let e=r.section;if(!n.has(e)){let r=e.replace(/\/$/,``).split(`/`),i=t,a=``;for(let e of r){a=a?`${a}/${e}`:e;let t=`${a}/`;if(!n.has(t)){let r={name:e,path:t,children:[],files:[]};i.children.push(r),n.set(t,r)}i=n.get(t)}}n.get(e).files.push({file:r.file,description:r.description,tokens:r.tokens})}return t}function l({node:e,search:t,depth:n=0}){let[r,i]=(0,a.useState)(n<2),c=t.toLowerCase(),f=e.files.filter(e=>!t||e.file.toLowerCase().includes(c)||e.description.toLowerCase().includes(c)),p=e.children.some(e=>d(e,c));return t&&f.length===0&&!p?null:(0,o.jsxs)(`div`,{className:`ml-3`,children:[e.name!==`.`&&(0,o.jsxs)(`button`,{onClick:()=>i(!r),className:`flex items-center gap-1.5 py-1 text-sm transition-colors`,style:{color:`var(--text-secondary)`},children:[(0,o.jsx)(`span`,{className:`w-4 text-center`,style:{color:`var(--text-faint)`},children:r?`▼`:`▶`}),(0,o.jsx)(`span`,{className:`text-amber-400`,children:`📁`}),(0,o.jsxs)(`span`,{children:[e.name,`/`]}),(0,o.jsxs)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[u(e),` files`]})]}),(r||e.name===`.`)&&(0,o.jsxs)(`div`,{className:e.name===`.`?``:`ml-4`,children:[f.sort((e,t)=>e.file.localeCompare(t.file)).map(e=>(0,o.jsxs)(`div`,{className:`flex items-center gap-2 py-1 pl-5`,children:[(0,o.jsx)(`span`,{style:{color:`var(--text-faint)`},children:`📄`}),(0,o.jsx)(`span`,{className:`text-sm font-mono`,style:{color:`var(--text-primary)`},children:e.file}),e.description&&(0,o.jsxs)(`span`,{className:`text-xs truncate max-w-xs`,style:{color:`var(--text-faint)`},children:[`— `,e.description]}),(0,o.jsx)(s,{tokens:e.tokens,className:`ml-auto shrink-0`})]},e.file)),e.children.sort((e,t)=>e.name.localeCompare(t.name)).map(e=>(0,o.jsx)(l,{node:e,search:t,depth:n+1},e.path))]})]})}function u(e){return e.files.length+e.children.reduce((e,t)=>e+u(t),0)}function d(e,t){return e.files.some(e=>e.file.toLowerCase().includes(t)||e.description.toLowerCase().includes(t))?!0:e.children.some(e=>d(e,t))}function f({data:e}){let{anatomy:t}=e,[n,r]=(0,a.useState)(``),[i,s]=(0,a.useState)(!1),u=(0,a.useMemo)(()=>c(t.entries),[t.entries]),d=(0,a.useMemo)(()=>{let e=t.entries.map(e=>e.tokens);return{total:t.entries.length,avg:e.length>0?Math.round(e.reduce((e,t)=>e+t,0)/e.length):0,largest:e.length>0?Math.max(...e):0}},[t.entries]);return(0,o.jsxs)(`div`,{children:[(0,o.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 mb-4`,children:[(0,o.jsx)(`input`,{type:`text`,placeholder:`Search files...`,value:n,onChange:e=>r(e.target.value),className:`flex-1 min-w-[200px] rounded-lg px-3 py-2 text-sm focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}}),(0,o.jsx)(`button`,{onClick:()=>s(!i),className:`px-3 py-2 text-xs rounded-lg`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-muted)`},children:i?`Sort: Size`:`Sort: A-Z`})]}),(0,o.jsxs)(`div`,{className:`flex gap-4 mb-4 text-sm`,style:{color:`var(--text-muted)`},children:[(0,o.jsxs)(`span`,{children:[d.total,` files tracked`]}),(0,o.jsxs)(`span`,{children:[`Avg: `,d.avg,` tok/file`]}),(0,o.jsxs)(`span`,{children:[`Largest: `,d.largest,` tok`]})]}),(0,o.jsx)(`div`,{className:`rounded-xl p-4`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:t.entries.length===0?(0,o.jsxs)(`div`,{className:`text-center py-12`,style:{color:`var(--text-muted)`},children:[(0,o.jsx)(`p`,{className:`text-2xl mb-2`,children:`📂`}),(0,o.jsxs)(`p`,{children:[`No anatomy data. Run `,(0,o.jsx)(`code`,{style:{color:`var(--text-secondary)`},children:`openwolf scan`}),` to index your project.`]})]}):(0,o.jsx)(l,{node:u,search:n})})]})}export{f as AnatomyBrowser};
@@ -0,0 +1 @@
1
+ import{a as e,c as t,r as n}from"./index-jfgWxxsn.js";var r=t(e(),1),i=n();function a({data:e}){let{buglog:t}=e,[n,a]=(0,r.useState)(``),[o,s]=(0,r.useState)(null),c=n?t.bugs.filter(e=>e.error_message.toLowerCase().includes(n.toLowerCase())||e.root_cause.toLowerCase().includes(n.toLowerCase())||e.fix.toLowerCase().includes(n.toLowerCase())||e.tags.some(e=>e.toLowerCase().includes(n.toLowerCase()))):t.bugs;if(t.bugs.length===0)return(0,i.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-16 text-center`,children:[(0,i.jsx)(`div`,{className:`text-4xl mb-3`,children:`🐛`}),(0,i.jsx)(`h3`,{className:`font-medium mb-1`,style:{color:`var(--text-secondary)`},children:`No bugs logged yet`}),(0,i.jsx)(`p`,{className:`text-sm max-w-sm`,style:{color:`var(--text-muted)`},children:`When you encounter and fix bugs, they'll appear here for future reference.`})]});let l=t.bugs.flatMap(e=>e.tags),u=new Map;for(let e of l)u.set(e,(u.get(e)||0)+1);let d=[...u.entries()].sort((e,t)=>t[1]-e[1]).slice(0,5);return(0,i.jsxs)(`div`,{children:[(0,i.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4 mb-4`,children:[(0,i.jsx)(`input`,{type:`text`,placeholder:`Search bugs...`,value:n,onChange:e=>a(e.target.value),className:`flex-1 min-w-[200px] rounded-lg px-3 py-2 text-sm focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}}),(0,i.jsxs)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:[t.bugs.length,` bugs logged`]})]}),d.length>0&&(0,i.jsx)(`div`,{className:`flex flex-wrap gap-2 mb-4`,children:d.map(([e,t])=>(0,i.jsxs)(`button`,{onClick:()=>a(e),className:`px-2 py-1 text-xs rounded-full`,style:{background:`var(--bg-surface-hover)`,border:`1px solid var(--border-subtle)`,color:`var(--text-muted)`},children:[e,` (`,t,`)`]},e))}),(0,i.jsx)(`div`,{className:`space-y-3`,children:c.map(e=>{let t=o===e.id;return(0,i.jsxs)(`div`,{className:`rounded-xl overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsxs)(`button`,{onClick:()=>s(t?null:e.id),className:`w-full flex items-start gap-3 px-5 py-3 transition-colors text-left`,onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsx)(`span`,{className:`text-sm mt-0.5`,style:{color:`var(--text-faint)`},children:t?`▼`:`▶`}),(0,i.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,i.jsx)(`p`,{className:`text-sm truncate`,style:{color:`var(--text-primary)`},children:e.error_message}),(0,i.jsxs)(`div`,{className:`flex items-center gap-3 mt-1`,children:[(0,i.jsx)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:e.file}),(0,i.jsx)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:e.timestamp?.slice(0,10)})]})]}),e.occurrences>1&&(0,i.jsxs)(`span`,{className:`shrink-0 px-2 py-0.5 rounded-full text-xs`,style:{background:`var(--warning-subtle)`,color:`var(--warning)`},children:[`Seen `,e.occurrences,`x`]})]}),t&&(0,i.jsxs)(`div`,{className:`px-5 py-4 space-y-3`,style:{borderTop:`1px solid var(--border)`},children:[(0,i.jsxs)(`div`,{children:[(0,i.jsx)(`p`,{className:`text-xs uppercase mb-1`,style:{color:`var(--text-faint)`},children:`Error Message`}),(0,i.jsx)(`pre`,{className:`text-sm rounded-lg p-3 overflow-x-auto font-mono`,style:{color:`var(--danger)`,background:`var(--danger-subtle)`},children:e.error_message})]}),(0,i.jsxs)(`div`,{children:[(0,i.jsx)(`p`,{className:`text-xs uppercase mb-1`,style:{color:`var(--text-faint)`},children:`Root Cause`}),(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-secondary)`},children:e.root_cause})]}),(0,i.jsxs)(`div`,{children:[(0,i.jsx)(`p`,{className:`text-xs uppercase mb-1`,style:{color:`var(--text-faint)`},children:`Fix`}),(0,i.jsx)(`pre`,{className:`text-sm rounded-lg p-3 overflow-x-auto font-mono`,style:{color:`var(--accent)`,background:`var(--accent-subtle)`},children:e.fix})]}),(0,i.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:e.tags.map(e=>(0,i.jsx)(`span`,{className:`px-2 py-0.5 text-xs rounded-full`,style:{background:`var(--bg-surface-hover)`,border:`1px solid var(--border-subtle)`,color:`var(--text-muted)`},children:e},e))})]})]},e.id)})})]})}export{a as BugLog};
@@ -0,0 +1 @@
1
+ import{a as e,c as t,r as n}from"./index-jfgWxxsn.js";var r=t(e(),1),i=n();function a({data:e}){let{cerebrum:t}=e,[n,a]=(0,r.useState)(``),[o,s]=(0,r.useState)({preferences:!0,learnings:!0,doNotRepeat:!0,decisions:!1}),c=e=>s(t=>({...t,[e]:!t[e]})),l=e=>!n||e.toLowerCase().includes(n.toLowerCase());return(0,i.jsxs)(`div`,{children:[(0,i.jsx)(`div`,{className:`flex items-center justify-between mb-4`,children:(0,i.jsxs)(`div`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:[`Last updated: `,t.lastUpdated||`—`,` ·`,t.preferences.length+t.learnings.length+t.doNotRepeat.length+t.decisions.length,` entries`]})}),(0,i.jsx)(`input`,{type:`text`,placeholder:`Search cerebrum...`,value:n,onChange:e=>a(e.target.value),className:`w-full rounded-lg px-3 py-2 text-sm mb-4 focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}}),(0,i.jsxs)(`div`,{className:`rounded-xl mb-4 overflow-hidden`,style:{background:`var(--danger-subtle)`,border:`1px solid rgba(220, 38, 38, 0.2)`},children:[(0,i.jsxs)(`button`,{onClick:()=>c(`doNotRepeat`),className:`w-full flex items-center justify-between px-5 py-3 transition-colors`,onMouseEnter:e=>e.currentTarget.style.background=`rgba(220, 38, 38, 0.08)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,i.jsx)(`span`,{style:{color:`var(--danger)`},children:`⊘`}),(0,i.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--danger)`},children:`Do-Not-Repeat`}),(0,i.jsx)(`span`,{className:`text-xs px-2 py-0.5 rounded-full`,style:{background:`rgba(220, 38, 38, 0.1)`,color:`var(--danger)`},children:t.doNotRepeat.length})]}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:o.doNotRepeat?`▼`:`▶`})]}),o.doNotRepeat&&(0,i.jsxs)(`div`,{className:`px-5 pb-4 space-y-2`,children:[t.doNotRepeat.filter(e=>l(e.text)).map((e,t)=>(0,i.jsxs)(`div`,{className:`rounded-lg p-3`,style:{background:`rgba(220, 38, 38, 0.05)`,border:`1px solid rgba(220, 38, 38, 0.1)`},children:[e.date&&(0,i.jsxs)(`span`,{className:`text-xs font-mono mr-2`,style:{color:`rgba(220, 38, 38, 0.6)`},children:[`[`,e.date,`]`]}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-secondary)`},children:e.text})]},t)),t.doNotRepeat.length===0&&(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No entries yet.`})]})]}),(0,i.jsxs)(`div`,{className:`rounded-xl mb-4 overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsxs)(`button`,{onClick:()=>c(`preferences`),className:`w-full flex items-center justify-between px-5 py-3 transition-colors`,onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,i.jsx)(`span`,{className:`text-blue-400`,children:`◈`}),(0,i.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`User Preferences`}),(0,i.jsx)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:t.preferences.length})]}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:o.preferences?`▼`:`▶`})]}),o.preferences&&(0,i.jsxs)(`div`,{className:`px-5 pb-4`,children:[t.preferences.filter(l).map((e,t)=>(0,i.jsxs)(`div`,{className:`flex items-start gap-2 py-1.5`,children:[(0,i.jsx)(`span`,{className:`mt-1`,style:{color:`var(--text-faint)`},children:`•`}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-secondary)`},children:e})]},t)),t.preferences.length===0&&(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No preferences recorded yet.`})]})]}),(0,i.jsxs)(`div`,{className:`rounded-xl mb-4 overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsxs)(`button`,{onClick:()=>c(`learnings`),className:`w-full flex items-center justify-between px-5 py-3 transition-colors`,onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,i.jsx)(`span`,{style:{color:`var(--accent)`},children:`◎`}),(0,i.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Key Learnings`}),(0,i.jsx)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:t.learnings.length})]}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:o.learnings?`▼`:`▶`})]}),o.learnings&&(0,i.jsxs)(`div`,{className:`px-5 pb-4 space-y-2`,children:[t.learnings.filter(l).map((e,t)=>(0,i.jsx)(`div`,{className:`rounded-lg p-3 text-sm`,style:{background:`var(--bg-surface-hover)`,color:`var(--text-secondary)`},children:e},t)),t.learnings.length===0&&(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No learnings recorded yet.`})]})]}),(0,i.jsxs)(`div`,{className:`rounded-xl overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsxs)(`button`,{onClick:()=>c(`decisions`),className:`w-full flex items-center justify-between px-5 py-3 transition-colors`,onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,i.jsx)(`span`,{className:`text-amber-400`,children:`⚖`}),(0,i.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Decision Log`}),(0,i.jsx)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:t.decisions.length})]}),(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:o.decisions?`▼`:`▶`})]}),o.decisions&&(0,i.jsxs)(`div`,{className:`px-5 pb-4 space-y-2`,children:[t.decisions.filter(l).map((e,t)=>(0,i.jsx)(`div`,{className:`rounded-lg p-3 text-sm`,style:{background:`var(--bg-surface-hover)`,color:`var(--text-secondary)`},children:e},t)),t.decisions.length===0&&(0,i.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No decisions logged yet.`})]})]})]})}export{a as CerebrumViewer};
@@ -0,0 +1 @@
1
+ import{a as e,c as t,r as n,t as r}from"./index-jfgWxxsn.js";import{i,n as a}from"./utils-BqE_aDxV.js";import{t as o}from"./StatusBadge-4NJI_F2G.js";var s=t(e(),1),c=n();function l({data:e}){let{cronManifest:t,cronState:n,client:l}=e,[u,d]=(0,s.useState)(!0),[f,p]=(0,s.useState)(!1),[m,h]=(0,s.useState)({}),g=e=>n.dead_letter_queue.some(t=>t.task_id===e)?`failed`:n.execution_log.filter(t=>t.task_id===e).sort((e,t)=>t.timestamp.localeCompare(e.timestamp))[0]?.status||`ok`,_=e=>{let t=n.execution_log.filter(t=>t.task_id===e).sort((e,t)=>t.timestamp.localeCompare(e.timestamp))[0];return t?i(t.timestamp):`never`},v=e=>{h(t=>({...t,[e]:`running`})),r(`/api/cron/run/${encodeURIComponent(e)}`,{method:`POST`}).then(t=>{h(n=>({...n,[e]:t.ok?`ok`:`error`})),setTimeout(()=>h(t=>{let n={...t};return delete n[e],n}),3e3)}).catch(()=>{h(t=>({...t,[e]:`error`})),setTimeout(()=>h(t=>{let n={...t};return delete n[e],n}),3e3)})},y=e=>{l?.send({type:`retry_dead_letter`,task_id:e})};return(0,c.jsxs)(`div`,{children:[(0,c.jsx)(`div`,{className:`rounded-xl overflow-hidden mb-6`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:(0,c.jsxs)(`table`,{className:`w-full`,children:[(0,c.jsx)(`thead`,{children:(0,c.jsxs)(`tr`,{style:{borderBottom:`1px solid var(--border)`},children:[(0,c.jsx)(`th`,{className:`text-left px-4 py-3 text-xs font-medium uppercase`,style:{color:`var(--text-faint)`},children:`Status`}),(0,c.jsx)(`th`,{className:`text-left px-4 py-3 text-xs font-medium uppercase`,style:{color:`var(--text-faint)`},children:`Task`}),(0,c.jsx)(`th`,{className:`text-left px-4 py-3 text-xs font-medium uppercase hidden md:table-cell`,style:{color:`var(--text-faint)`},children:`Schedule`}),(0,c.jsx)(`th`,{className:`text-left px-4 py-3 text-xs font-medium uppercase hidden md:table-cell`,style:{color:`var(--text-faint)`},children:`Last Run`}),(0,c.jsx)(`th`,{className:`text-right px-4 py-3 text-xs font-medium uppercase`,style:{color:`var(--text-faint)`},children:`Actions`})]})}),(0,c.jsx)(`tbody`,{children:t.tasks.map(e=>(0,c.jsxs)(`tr`,{className:`transition-colors`,style:{borderBottom:`1px solid var(--border)`},onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,c.jsx)(`td`,{className:`px-4 py-3`,children:(0,c.jsx)(o,{status:e.enabled?g(e.id):`disabled`})}),(0,c.jsxs)(`td`,{className:`px-4 py-3`,children:[(0,c.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-primary)`},children:e.name}),(0,c.jsx)(`p`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:e.description})]}),(0,c.jsx)(`td`,{className:`px-4 py-3 hidden md:table-cell text-sm`,style:{color:`var(--text-muted)`},children:a(e.schedule)}),(0,c.jsx)(`td`,{className:`px-4 py-3 hidden md:table-cell text-sm`,style:{color:`var(--text-faint)`},children:_(e.id)}),(0,c.jsx)(`td`,{className:`px-4 py-3 text-right`,children:(()=>{let t=m[e.id];return(0,c.jsx)(`button`,{onClick:()=>v(e.id),disabled:t===`running`,className:`px-3 py-1 text-xs rounded-md transition-colors`,style:{background:`var(--bg-surface-hover)`,border:`1px solid var(--border-subtle)`,color:t===`ok`?`var(--accent)`:t===`error`?`var(--danger)`:`var(--text-secondary)`,opacity:t===`running`?.6:1},children:t===`running`?`Running…`:t===`ok`?`Triggered ✓`:t===`error`?`Failed ✗`:`Run Now`})})()})]},e.id))})]})}),(0,c.jsxs)(`div`,{className:`rounded-xl p-5 mb-6`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,c.jsxs)(`button`,{onClick:()=>d(!u),className:`flex items-center gap-2 w-full text-left`,children:[(0,c.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:u?`▼`:`▶`}),(0,c.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Dead Letter Queue`}),(0,c.jsxs)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[`(`,n.dead_letter_queue.length,`)`]})]}),u&&(n.dead_letter_queue.length===0?(0,c.jsx)(`div`,{className:`text-center py-6 text-sm mt-2`,style:{color:`var(--text-muted)`},children:`No dead letters — all systems healthy`}):(0,c.jsx)(`div`,{className:`space-y-3 mt-3`,children:n.dead_letter_queue.map((e,t)=>(0,c.jsx)(`div`,{className:`rounded-lg p-4`,style:{background:`var(--danger-subtle)`,border:`1px solid rgba(220, 38, 38, 0.2)`},children:(0,c.jsxs)(`div`,{className:`flex items-start justify-between`,children:[(0,c.jsxs)(`div`,{children:[(0,c.jsx)(`p`,{className:`text-sm font-medium`,style:{color:`var(--danger)`},children:e.task_id}),(0,c.jsx)(`p`,{className:`text-xs mt-1`,style:{color:`var(--text-muted)`},children:e.error}),(0,c.jsxs)(`p`,{className:`text-xs mt-1`,style:{color:`var(--text-faint)`},children:[i(e.timestamp),` · `,e.attempts,` attempts`]})]}),(0,c.jsx)(`button`,{onClick:()=>y(e.task_id),className:`px-3 py-1 text-xs rounded-md`,style:{background:`var(--bg-surface-hover)`,border:`1px solid var(--border-subtle)`,color:`var(--text-secondary)`},children:`Retry`})]})},t))}))]}),(0,c.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,c.jsxs)(`button`,{onClick:()=>p(!f),className:`flex items-center gap-2 w-full text-left`,children:[(0,c.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:f?`▼`:`▶`}),(0,c.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Execution History`})]}),f&&(0,c.jsxs)(`div`,{className:`mt-3`,children:[n.execution_log.slice(-30).reverse().map((e,t)=>(0,c.jsxs)(`div`,{className:`flex items-center gap-4 py-2`,style:{borderBottom:`1px solid var(--border)`},children:[(0,c.jsx)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:e.timestamp?.slice(11,16)}),(0,c.jsx)(`span`,{className:`text-sm flex-1`,style:{color:`var(--text-secondary)`},children:e.task_id}),(0,c.jsxs)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:[e.duration_ms,`ms`]}),(0,c.jsx)(o,{status:e.status})]},t)),n.execution_log.length===0&&(0,c.jsx)(`p`,{className:`text-sm py-4 text-center`,style:{color:`var(--text-muted)`},children:`No executions yet.`})]})]})]})}export{l as CronStatus};
@@ -0,0 +1 @@
1
+ import{a as e,c as t,n,r,t as i}from"./index-jfgWxxsn.js";var a=t(e(),1),o=r(),s=e=>n(`/api/designqc/capture/${encodeURIComponent(e)}`);function c({data:e}){let{designqcReport:t,project:n}=e,[r,c]=(0,a.useState)(`idle`),[l,u]=(0,a.useState)(null),[d,f]=(0,a.useState)(null),p=t&&t.captures&&t.captures.length>0;return(0,o.jsxs)(`div`,{children:[(0,o.jsxs)(`div`,{className:`rounded-xl px-4 py-3 mb-6 flex items-start gap-3`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,o.jsx)(`span`,{style:{color:`var(--text-faint)`,marginTop:1},children:`ℹ`}),(0,o.jsxs)(`div`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:[`Works with `,(0,o.jsx)(`span`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`any accessible URL`}),` — local or deployed. The URL is auto-detected from `,(0,o.jsx)(`code`,{className:`px-1 rounded text-xs`,style:{background:`var(--bg-base)`},children:`package.json`}),` homepage, env files, or a running dev server.`,n?.root&&(0,o.jsxs)(`span`,{children:[` Scanning `,(0,o.jsx)(`code`,{className:`px-1 rounded text-xs`,style:{background:`var(--bg-base)`},children:n.root}),`.`]})]})]}),(0,o.jsxs)(`div`,{className:`rounded-xl p-5 mb-6`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,o.jsxs)(`div`,{className:`flex items-center justify-between mb-3`,children:[(0,o.jsx)(`h3`,{className:`font-medium`,style:{color:`var(--text-secondary)`},children:`Capture Screenshots`}),(0,o.jsx)(`button`,{onClick:()=>{c(`running`),u(null),i(`/api/designqc/run`,{method:`POST`,headers:{"Content-Type":`application/json`},body:`{}`}).then(async e=>{if(!e.ok){let t=await e.json().catch(()=>({error:e.statusText}));throw Error(t.error||e.statusText)}c(`idle`)}).catch(e=>{c(`error`),u(e.message)})},disabled:r===`running`,className:`px-4 py-1.5 text-sm rounded-lg transition-colors`,style:{background:r===`error`?`var(--danger-subtle)`:`var(--accent-subtle)`,border:`1px solid ${r===`error`?`rgba(220,38,38,0.3)`:`var(--accent)`}`,color:r===`error`?`var(--danger)`:`var(--accent)`,opacity:r===`running`?.6:1},children:r===`running`?`Capturing…`:r===`error`?`Retry Capture`:`Run Capture`})]}),r===`running`&&(0,o.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`Auto-detecting URL, launching browser, capturing screenshots… this takes ~15–30s.`}),r===`error`&&l&&(0,o.jsx)(`p`,{className:`text-sm`,style:{color:`var(--danger)`},children:l}),r===`idle`&&(0,o.jsxs)(`div`,{className:`space-y-1.5 text-sm`,style:{color:`var(--text-muted)`},children:[(0,o.jsxs)(`p`,{children:[`Detects your URL automatically from `,(0,o.jsx)(`code`,{className:`px-1 rounded text-xs`,style:{background:`var(--bg-base)`},children:`package.json`}),`, env files, or a running dev server.`]}),(0,o.jsxs)(`p`,{children:[`After capture, ask Claude: `,(0,o.jsx)(`span`,{className:`italic`,children:`"Read .wolf/designqc-captures/ and evaluate the design"`})]})]})]}),(0,o.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,o.jsx)(`h3`,{className:`font-medium mb-3`,style:{color:`var(--text-secondary)`},children:`Last Capture`}),p?(0,o.jsxs)(`div`,{children:[(0,o.jsxs)(`div`,{className:`flex gap-4 text-sm mb-4`,children:[(0,o.jsxs)(`span`,{style:{color:`var(--text-faint)`},children:[`Captured: `,t.captured_at||`—`]}),(0,o.jsxs)(`span`,{style:{color:`var(--text-faint)`},children:[`Size: `,t.total_size_kb||0,`KB`]}),(0,o.jsxs)(`span`,{style:{color:`var(--text-faint)`},children:[`Est. tokens: ~`,t.estimated_tokens||0]})]}),(0,o.jsx)(`div`,{className:`grid grid-cols-2 md:grid-cols-3 gap-4`,children:t.captures.map((e,t)=>(0,o.jsxs)(`button`,{onClick:()=>f(e.file),className:`text-left rounded-lg overflow-hidden transition-transform hover:-translate-y-0.5`,style:{background:`var(--bg-base)`,border:`1px solid var(--border)`},title:`Klicken zum Vergrößern`,children:[(0,o.jsx)(`img`,{src:s(e.file),alt:`${e.viewport} · ${e.route}`,loading:`lazy`,className:`w-full block`,style:{maxHeight:200,objectFit:`cover`,objectPosition:`top`,background:`var(--bg-surface)`}}),(0,o.jsxs)(`div`,{className:`px-3 py-2`,children:[(0,o.jsx)(`div`,{className:`text-sm truncate`,style:{color:`var(--text-primary)`},children:e.file}),(0,o.jsxs)(`div`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[e.viewport,` · `,e.route]})]})]},t))})]}):(0,o.jsx)(`div`,{className:`text-center py-8`,children:(0,o.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No screenshots captured yet.`})})]}),d&&(0,o.jsxs)(`div`,{onClick:()=>f(null),className:`fixed inset-0 z-50 flex items-center justify-center p-6`,style:{background:`rgba(0,0,0,0.8)`},children:[(0,o.jsx)(`div`,{className:`relative max-w-6xl max-h-[90vh] overflow-auto rounded-lg`,onClick:e=>e.stopPropagation(),children:(0,o.jsx)(`img`,{src:s(d),alt:d,className:`block`,style:{maxWidth:`100%`}})}),(0,o.jsx)(`button`,{onClick:()=>f(null),className:`absolute top-4 right-4 w-9 h-9 rounded-full flex items-center justify-center text-lg`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`},"aria-label":`Schließen`,children:`✕`})]})]})}export{c as DesignQC};
@@ -0,0 +1 @@
1
+ import{a as e,c as t,r as n}from"./index-jfgWxxsn.js";var r=t(e(),1),i=n();function a({data:e}){let{memory:t}=e,[n,a]=(0,r.useState)(0),[o,s]=(0,r.useState)(``),c=o?t.filter(e=>e.entries.some(e=>e.action.toLowerCase().includes(o.toLowerCase())||e.files.toLowerCase().includes(o.toLowerCase()))):t;return(0,i.jsxs)(`div`,{children:[(0,i.jsx)(`div`,{className:`flex items-center gap-3 mb-4`,children:(0,i.jsx)(`input`,{type:`text`,placeholder:`Search memory...`,value:o,onChange:e=>s(e.target.value),className:`flex-1 rounded-lg px-3 py-2 text-sm focus:outline-none`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`,color:`var(--text-primary)`}})}),c.length===0?(0,i.jsx)(`div`,{className:`text-center py-12`,style:{color:`var(--text-muted)`},children:`No sessions found.`}):(0,i.jsx)(`div`,{className:`space-y-3`,children:c.map((e,t)=>{let r=n===t,o=e.entries.reduce((e,t)=>e+(parseInt(t.tokens.replace(/[^0-9]/g,``))||0),0);return(0,i.jsxs)(`div`,{className:`rounded-xl overflow-hidden`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,i.jsxs)(`button`,{onClick:()=>a(r?-1:t),className:`w-full flex items-center justify-between px-5 py-3 transition-colors`,onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,i.jsx)(`span`,{className:`text-sm`,style:{color:`var(--text-faint)`},children:r?`▼`:`▶`}),(0,i.jsxs)(`span`,{className:`text-sm font-medium`,style:{color:`var(--text-primary)`},children:[e.date,` `,e.time]}),(0,i.jsxs)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[e.entries.length,` actions`]})]}),o>0&&(0,i.jsxs)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:[`~`,o,` tok`]})]}),r&&e.entries.length>0&&(0,i.jsx)(`div`,{style:{borderTop:`1px solid var(--border)`},children:(0,i.jsxs)(`table`,{className:`w-full`,children:[(0,i.jsx)(`thead`,{children:(0,i.jsxs)(`tr`,{className:`text-xs uppercase`,style:{color:`var(--text-faint)`},children:[(0,i.jsx)(`th`,{className:`text-left px-4 py-2 w-16`,children:`Time`}),(0,i.jsx)(`th`,{className:`text-left px-4 py-2`,children:`Action`}),(0,i.jsx)(`th`,{className:`text-left px-4 py-2 hidden md:table-cell`,children:`Files`}),(0,i.jsx)(`th`,{className:`text-left px-4 py-2 hidden md:table-cell`,children:`Outcome`}),(0,i.jsx)(`th`,{className:`text-right px-4 py-2 w-20`,children:`Tokens`})]})}),(0,i.jsx)(`tbody`,{children:e.entries.map((e,t)=>(0,i.jsxs)(`tr`,{style:{borderBottom:`1px solid var(--border)`},onMouseEnter:e=>e.currentTarget.style.background=`var(--bg-surface-hover)`,onMouseLeave:e=>e.currentTarget.style.background=`transparent`,children:[(0,i.jsx)(`td`,{className:`px-4 py-2 text-xs font-mono`,style:{color:`var(--text-faint)`},children:e.time}),(0,i.jsx)(`td`,{className:`px-4 py-2 text-sm`,style:{color:`var(--text-secondary)`},children:e.action}),(0,i.jsx)(`td`,{className:`px-4 py-2 text-sm hidden md:table-cell`,style:{color:`var(--text-muted)`},children:e.files}),(0,i.jsx)(`td`,{className:`px-4 py-2 text-sm hidden md:table-cell`,style:{color:`var(--text-muted)`},children:e.outcome}),(0,i.jsx)(`td`,{className:`px-4 py-2 text-xs font-mono text-right`,style:{color:`var(--text-faint)`},children:e.tokens})]},t))})]})})]},t)})})]})}export{a as MemoryViewer};
@@ -0,0 +1 @@
1
+ import{a as e,r as t}from"./index-jfgWxxsn.js";import{i as n,r}from"./utils-BqE_aDxV.js";import{t as i}from"./StatusBadge-4NJI_F2G.js";e();var a=t();function o({data:e}){let{identity:t,health:o,cronState:s,tokenLedger:c,anatomy:l,memory:u,project:d}=e,f=c.lifetime,p=d.name||t.name,m=d.description||``;return(0,a.jsxs)(`div`,{children:[(0,a.jsxs)(`div`,{className:`rounded-xl p-6 mb-6`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,a.jsx)(`h2`,{className:`text-3xl font-bold`,style:{color:`var(--text-primary)`},children:p}),m&&(0,a.jsx)(`p`,{className:`mt-1`,style:{color:`var(--text-muted)`},children:m}),(0,a.jsxs)(`div`,{className:`flex items-center gap-4 mt-3`,children:[(0,a.jsx)(i,{status:s.engine_status}),o.uptime_seconds>0&&(0,a.jsxs)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[`Uptime: `,Math.floor(o.uptime_seconds/3600),`h `,Math.floor(o.uptime_seconds%3600/60),`m`]}),s.last_heartbeat&&(0,a.jsxs)(`span`,{className:`text-xs`,style:{color:`var(--text-faint)`},children:[`Last heartbeat: `,n(s.last_heartbeat)]})]})]}),(0,a.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-3 gap-4 mb-6`,children:[(0,a.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,a.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`Files Tracked`}),(0,a.jsx)(`p`,{className:`text-2xl font-bold mt-1`,style:{color:`var(--text-primary)`},children:l.metadata.files})]}),(0,a.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,a.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`Sessions`}),(0,a.jsx)(`p`,{className:`text-2xl font-bold mt-1`,style:{color:`var(--text-primary)`},children:f.total_sessions})]}),(0,a.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,a.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`Tokens Saved`}),(0,a.jsxs)(`p`,{className:`text-2xl font-bold mt-1`,style:{color:`var(--accent)`},children:[`~`,r(f.estimated_savings_vs_bare_cli)]}),f.total_tokens_estimated>0&&(0,a.jsxs)(`p`,{className:`text-xs mt-1`,style:{color:`var(--text-faint)`},children:[Math.round(f.estimated_savings_vs_bare_cli/(f.total_tokens_estimated+f.estimated_savings_vs_bare_cli)*100),`% savings`]})]})]}),(0,a.jsxs)(`div`,{className:`rounded-xl p-5`,style:{background:`var(--bg-surface)`,border:`1px solid var(--border)`},children:[(0,a.jsx)(`h3`,{className:`font-medium mb-3`,style:{color:`var(--text-secondary)`},children:`Recent Activity`}),u.length===0?(0,a.jsx)(`p`,{className:`text-sm`,style:{color:`var(--text-muted)`},children:`No activity yet. Start a Claude Code session to see activity here.`}):(0,a.jsx)(`div`,{className:`space-y-2`,children:u.slice(0,3).flatMap(e=>e.entries.slice(0,5).map((t,n)=>(0,a.jsxs)(`div`,{className:`flex items-center gap-3 py-2`,style:{borderBottom:`1px solid var(--border)`},children:[(0,a.jsx)(`span`,{className:`text-xs font-mono w-12`,style:{color:`var(--text-faint)`},children:t.time}),(0,a.jsx)(`span`,{className:`text-sm flex-1`,style:{color:`var(--text-secondary)`},children:t.action}),(0,a.jsx)(`span`,{className:`text-xs font-mono`,style:{color:`var(--text-faint)`},children:t.tokens})]},`${e.date}-${n}`))).slice(0,5)})]})]})}export{o as ProjectOverview};
@@ -0,0 +1 @@
1
+ import{a as e,r as t}from"./index-jfgWxxsn.js";import{t as n}from"./utils-BqE_aDxV.js";e();var r=t(),i={healthy:`bg-emerald-500/20 text-emerald-400 border-emerald-500/30`,running:`bg-emerald-500/20 text-emerald-400 border-emerald-500/30`,success:`bg-emerald-500/20 text-emerald-400 border-emerald-500/30`,ok:`bg-emerald-500/20 text-emerald-400 border-emerald-500/30`,enabled:`bg-emerald-500/20 text-emerald-400 border-emerald-500/30`,warning:`bg-amber-500/20 text-amber-400 border-amber-500/30`,retrying:`bg-amber-500/20 text-amber-400 border-amber-500/30`,degraded:`bg-amber-500/20 text-amber-400 border-amber-500/30`,error:`bg-red-500/20 text-red-400 border-red-500/30`,failed:`bg-red-500/20 text-red-400 border-red-500/30`,stopped:`bg-red-500/20 text-red-400 border-red-500/30`,disabled:`bg-zinc-500/20 text-zinc-400 border-zinc-500/30`,unknown:`bg-zinc-500/20 text-zinc-400 border-zinc-500/30`,initialized:`bg-blue-500/20 text-blue-400 border-blue-500/30`};function a({status:e,className:t}){return(0,r.jsxs)(`span`,{className:n(`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium border`,i[e.toLowerCase()]||i.unknown,t),children:[e===`running`||e===`healthy`?(0,r.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-emerald-400 mr-1.5 pulse-green`}):null,e.charAt(0).toUpperCase()+e.slice(1)]})}export{a as t};