@alecsibilia/luca 13.0.1 → 14.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +96 -24
  3. package/board/client/board-look.ts +292 -0
  4. package/board/client/board-panel.tsx +1355 -0
  5. package/board/client/engine-settings-screen.tsx +167 -0
  6. package/board/client/timeline-rows.tsx +402 -0
  7. package/board/index.client.tsx +109 -0
  8. package/board/index.server.ts +173 -0
  9. package/board/package.json +6 -0
  10. package/board/paseo-plugin.json +7 -0
  11. package/board/server/board-server.ts +988 -0
  12. package/board/server/board-vocabulary.ts +492 -0
  13. package/board/server/engine-launch.ts +193 -0
  14. package/board/server/engine-watch.ts +197 -0
  15. package/board/server/list-processes.ts +35 -0
  16. package/board/server/make-rows.ts +834 -0
  17. package/board/server/reduce-board.ts +1952 -0
  18. package/board/server/run-command.ts +54 -0
  19. package/board/server/run-journals.ts +120 -0
  20. package/board/server/run-registry.ts +171 -0
  21. package/board/server/spawn-detached.ts +45 -0
  22. package/board/server/usage-lines-file.ts +43 -0
  23. package/board/shared/board-rows.ts +127 -0
  24. package/board/shared/board-rpc.ts +131 -0
  25. package/board/shared/board-state.ts +683 -0
  26. package/board/shared/engine-settings.ts +36 -0
  27. package/engine/agents/agent-launcher.ts +188 -0
  28. package/engine/agents/claude-launcher.ts +781 -0
  29. package/engine/agents/claude-options.ts +239 -0
  30. package/engine/agents/message-tool.ts +124 -0
  31. package/engine/agents/role-instructions.ts +287 -0
  32. package/engine/agents/role-prompts.ts +207 -0
  33. package/engine/agents/role-results.ts +335 -0
  34. package/engine/agents/scripted-launcher.ts +227 -0
  35. package/engine/board/board-state-dir.ts +20 -0
  36. package/engine/board/board-sync.ts +145 -0
  37. package/engine/board/paseo-board-link.ts +125 -0
  38. package/engine/cli/board-in-paseo.ts +154 -0
  39. package/engine/cli/bunfig.toml +4 -0
  40. package/engine/cli/computer-adapters-real.ts +456 -0
  41. package/engine/cli/computer-adapters.ts +122 -0
  42. package/engine/cli/computer-checks.ts +404 -0
  43. package/engine/cli/doctor-checks.ts +171 -0
  44. package/engine/cli/doctor-command.ts +94 -0
  45. package/engine/cli/doctor.ts +369 -0
  46. package/engine/cli/going-runs.ts +130 -0
  47. package/engine/cli/init-command.ts +143 -0
  48. package/engine/cli/init.ts +346 -0
  49. package/engine/cli/luca-run.ts +189 -0
  50. package/engine/cli/luca.ts +62 -0
  51. package/engine/cli/muninn-entry.ts +87 -0
  52. package/engine/cli/repo-adapters-real.ts +70 -0
  53. package/engine/cli/run-args.ts +223 -0
  54. package/engine/cli/run-modes.ts +629 -0
  55. package/engine/cli/setup-command.ts +59 -0
  56. package/engine/cli/setup.ts +710 -0
  57. package/engine/cli/upgrade-command.ts +140 -0
  58. package/engine/cli/upgrade.ts +262 -0
  59. package/engine/cli/v13-leftovers.ts +694 -0
  60. package/engine/config/engine-config.ts +168 -0
  61. package/engine/config/luca-version.ts +47 -0
  62. package/engine/core/changeset.ts +140 -0
  63. package/engine/core/decide-build.ts +1318 -0
  64. package/engine/core/decide-crashes.ts +70 -0
  65. package/engine/core/decide-final-review.ts +416 -0
  66. package/engine/core/decide-memory.ts +667 -0
  67. package/engine/core/decide-plan.ts +87 -0
  68. package/engine/core/decide-run-budget.ts +76 -0
  69. package/engine/core/decide-stuck.ts +347 -0
  70. package/engine/core/decide-usage-line.ts +113 -0
  71. package/engine/core/decide-usage.ts +68 -0
  72. package/engine/core/decide.ts +200 -0
  73. package/engine/core/execute-build.ts +1121 -0
  74. package/engine/core/execute-changeset.ts +149 -0
  75. package/engine/core/execute-final-review.ts +324 -0
  76. package/engine/core/execute-memory.ts +475 -0
  77. package/engine/core/execute-stuck.ts +315 -0
  78. package/engine/core/execute.ts +1112 -0
  79. package/engine/core/final-review-text.ts +278 -0
  80. package/engine/core/fix-loop-text.ts +124 -0
  81. package/engine/core/learner-digest.ts +214 -0
  82. package/engine/core/loop-caps.ts +39 -0
  83. package/engine/core/memory-text.ts +132 -0
  84. package/engine/core/pull-request-text.ts +154 -0
  85. package/engine/core/review-text.ts +211 -0
  86. package/engine/core/session-close.ts +159 -0
  87. package/engine/core/stuck-text.ts +370 -0
  88. package/engine/doctor/v13-files.json +3948 -0
  89. package/engine/doctor/v13-manifest.ts +124 -0
  90. package/engine/gates/gate-runner.ts +103 -0
  91. package/engine/gates/gate-schemas.ts +63 -0
  92. package/engine/gates/leftover-scan.ts +110 -0
  93. package/engine/gates/lockfile-install.ts +109 -0
  94. package/engine/gates/red-check.ts +134 -0
  95. package/engine/gates/test-runner.ts +212 -0
  96. package/engine/git/git-adapter.ts +535 -0
  97. package/engine/guards/after-turn-check.ts +269 -0
  98. package/engine/guards/guard-hook.ts +63 -0
  99. package/engine/guards/role-rules.ts +704 -0
  100. package/engine/guards/sandbox-settings.ts +94 -0
  101. package/engine/guards/worktree-state.ts +959 -0
  102. package/engine/index.ts +297 -0
  103. package/engine/intake/intake-checks.ts +295 -0
  104. package/engine/intake/intake-schemas.ts +78 -0
  105. package/engine/jev/jev-client.ts +173 -0
  106. package/engine/jev/jev-jobs.ts +369 -0
  107. package/engine/jev/jev-schemas.ts +89 -0
  108. package/engine/jev/jev-shadow.ts +149 -0
  109. package/engine/journal/journal-record.ts +1324 -0
  110. package/engine/journal/journal.ts +115 -0
  111. package/engine/journal/replay.ts +2432 -0
  112. package/engine/journal/step-records.ts +142 -0
  113. package/engine/limits/limit-wait.ts +86 -0
  114. package/engine/limits/plan-signals.ts +122 -0
  115. package/engine/limits/plan-usage.ts +275 -0
  116. package/engine/limits/run-budget.ts +63 -0
  117. package/engine/limits/usage-line.ts +324 -0
  118. package/engine/memory/memory-client.ts +144 -0
  119. package/engine/memory/memory-recall.ts +62 -0
  120. package/engine/memory/memory-routing.ts +170 -0
  121. package/engine/memory/memory-schemas.ts +125 -0
  122. package/engine/memory/muninn-mcp-client.ts +390 -0
  123. package/engine/messages/agent-messages.ts +357 -0
  124. package/engine/messages/agent-messaging.ts +77 -0
  125. package/engine/shell/run-command.ts +86 -0
  126. package/engine/testing/build-fixtures.ts +912 -0
  127. package/engine/testing/fake-muninn.ts +219 -0
  128. package/engine/testing/final-review-fixtures.ts +223 -0
  129. package/engine/testing/intake-fixtures.ts +118 -0
  130. package/engine/testing/many-tickets.ts +739 -0
  131. package/engine/testing/memory-fixtures.ts +202 -0
  132. package/engine/testing/practice-repo.ts +475 -0
  133. package/engine/testing/practice-run.ts +182 -0
  134. package/engine/tracker/github-tracker.ts +262 -0
  135. package/engine/tracker/in-memory-tracker.ts +161 -0
  136. package/engine/tracker/post-comment-once.ts +69 -0
  137. package/engine/tracker/tracker.ts +119 -0
  138. package/package.json +57 -74
  139. package/bin/luca.js +0 -3
  140. package/dist/chunks/brain.mjs +0 -77
  141. package/dist/chunks/branch.mjs +0 -51
  142. package/dist/chunks/bun-runtime.mjs +0 -46
  143. package/dist/chunks/checks.mjs +0 -57
  144. package/dist/chunks/claim-verify.mjs +0 -70
  145. package/dist/chunks/classify.mjs +0 -105
  146. package/dist/chunks/confidence.mjs +0 -277
  147. package/dist/chunks/config-version-skew.mjs +0 -94
  148. package/dist/chunks/doctor.mjs +0 -174
  149. package/dist/chunks/hook.mjs +0 -850
  150. package/dist/chunks/init.mjs +0 -1015
  151. package/dist/chunks/legacy-claude-artifacts.mjs +0 -105
  152. package/dist/chunks/legacy-package.mjs +0 -47
  153. package/dist/chunks/luca-gitignore.mjs +0 -93
  154. package/dist/chunks/muninn-mcp.mjs +0 -81
  155. package/dist/chunks/muninndb-health.mjs +0 -66
  156. package/dist/chunks/phase.mjs +0 -64
  157. package/dist/chunks/plan.mjs +0 -51
  158. package/dist/chunks/pr-review.mjs +0 -128
  159. package/dist/chunks/preferences.mjs +0 -66
  160. package/dist/chunks/repair.mjs +0 -111
  161. package/dist/chunks/repo.mjs +0 -58
  162. package/dist/chunks/retro.mjs +0 -87
  163. package/dist/chunks/roadmap.mjs +0 -63
  164. package/dist/chunks/rules.mjs +0 -524
  165. package/dist/chunks/shared-tmp-payloads.mjs +0 -72
  166. package/dist/chunks/stale-global-symlinks.mjs +0 -78
  167. package/dist/chunks/stale-mcp-server.mjs +0 -90
  168. package/dist/chunks/state.mjs +0 -104
  169. package/dist/chunks/stray-local-install.mjs +0 -208
  170. package/dist/chunks/telemetry.mjs +0 -370
  171. package/dist/chunks/todo.mjs +0 -230
  172. package/dist/chunks/vault-config-location.mjs +0 -100
  173. package/dist/chunks/vault-init.mjs +0 -94
  174. package/dist/chunks/verification.mjs +0 -99
  175. package/dist/chunks/version.mjs +0 -70
  176. package/dist/chunks/workflow.mjs +0 -51
  177. package/dist/claude/.claude/agents/architect.md +0 -508
  178. package/dist/claude/.claude/agents/build.md +0 -117
  179. package/dist/claude/.claude/agents/debater.md +0 -95
  180. package/dist/claude/.claude/agents/discuss.md +0 -99
  181. package/dist/claude/.claude/agents/discussion.md +0 -143
  182. package/dist/claude/.claude/agents/execute.md +0 -450
  183. package/dist/claude/.claude/agents/executor.md +0 -187
  184. package/dist/claude/.claude/agents/fast.md +0 -90
  185. package/dist/claude/.claude/agents/finalize.md +0 -562
  186. package/dist/claude/.claude/agents/learner.md +0 -167
  187. package/dist/claude/.claude/agents/plan-reviewer.md +0 -137
  188. package/dist/claude/.claude/agents/plan.md +0 -102
  189. package/dist/claude/.claude/agents/research.md +0 -334
  190. package/dist/claude/.claude/agents/researcher.md +0 -81
  191. package/dist/claude/.claude/agents/review.md +0 -330
  192. package/dist/claude/.claude/agents/reviewer.md +0 -177
  193. package/dist/claude/.claude/agents/shadow-scanner.md +0 -261
  194. package/dist/claude/.claude/agents/test-writer.md +0 -96
  195. package/dist/claude/.claude/agents/triage.md +0 -230
  196. package/dist/claude/.claude/agents/verifier.md +0 -192
  197. package/dist/claude/.claude/commands/bug-diagnose.md +0 -12
  198. package/dist/claude/.claude/commands/gh-issue-triage.md +0 -14
  199. package/dist/claude/.claude/commands/gh-pr-address.md +0 -235
  200. package/dist/claude/.claude/commands/gh-prepare.md +0 -12
  201. package/dist/claude/.claude/commands/grill-me.md +0 -12
  202. package/dist/claude/.claude/commands/lu-review.md +0 -51
  203. package/dist/claude/.claude/commands/lu.md +0 -98
  204. package/dist/claude/.claude/commands/luca-init.md +0 -14
  205. package/dist/claude/.claude/commands/luca-telemetry-report.md +0 -12
  206. package/dist/claude/.claude/commands/memory-audit.md +0 -12
  207. package/dist/claude/.claude/commands/milestone-new.md +0 -122
  208. package/dist/claude/.claude/commands/phase-discuss.md +0 -45
  209. package/dist/claude/.claude/commands/phase-execute.md +0 -39
  210. package/dist/claude/.claude/commands/phase-plan.md +0 -57
  211. package/dist/claude/.claude/commands/repo-cleanup.md +0 -83
  212. package/dist/claude/.claude/commands/todo-add.md +0 -28
  213. package/dist/claude/.claude/commands/todo-check.md +0 -36
  214. package/dist/claude/.claude/hooks/context-refresher.ts +0 -14074
  215. package/dist/claude/.claude/hooks/continuation-messages.ts +0 -14049
  216. package/dist/claude/.claude/hooks/pipeline-guard.ts +0 -14036
  217. package/dist/claude/.claude/luca-statusline.ts +0 -159
  218. package/dist/claude/.claude/settings.json +0 -41
  219. package/dist/claude/skills/arch-audit/SKILL.md +0 -161
  220. package/dist/claude/skills/bug-diagnose/SKILL.md +0 -102
  221. package/dist/claude/skills/caveman/SKILL.md +0 -58
  222. package/dist/claude/skills/choose/SKILL.md +0 -124
  223. package/dist/claude/skills/gh-issue-triage/SKILL.md +0 -97
  224. package/dist/claude/skills/gh-pr-address/SKILL.md +0 -235
  225. package/dist/claude/skills/gh-prepare/SKILL.md +0 -209
  226. package/dist/claude/skills/grill-me/SKILL.md +0 -46
  227. package/dist/claude/skills/lu/SKILL.md +0 -262
  228. package/dist/claude/skills/lu-review/SKILL.md +0 -51
  229. package/dist/claude/skills/luca-init/SKILL.md +0 -91
  230. package/dist/claude/skills/luca-telemetry-report/SKILL.md +0 -210
  231. package/dist/claude/skills/luca-write-surface/SKILL.md +0 -229
  232. package/dist/claude/skills/memory-audit/SKILL.md +0 -217
  233. package/dist/claude/skills/milestone-audit/SKILL.md +0 -525
  234. package/dist/claude/skills/milestone-complete/SKILL.md +0 -179
  235. package/dist/claude/skills/milestone-gaps/SKILL.md +0 -60
  236. package/dist/claude/skills/milestone-new/SKILL.md +0 -125
  237. package/dist/claude/skills/note/SKILL.md +0 -162
  238. package/dist/claude/skills/phase-add/SKILL.md +0 -91
  239. package/dist/claude/skills/phase-assumptions/SKILL.md +0 -92
  240. package/dist/claude/skills/phase-discuss/SKILL.md +0 -175
  241. package/dist/claude/skills/phase-execute/SKILL.md +0 -1857
  242. package/dist/claude/skills/phase-insert/SKILL.md +0 -100
  243. package/dist/claude/skills/phase-plan/SKILL.md +0 -489
  244. package/dist/claude/skills/phase-remove/SKILL.md +0 -113
  245. package/dist/claude/skills/phase-research/SKILL.md +0 -88
  246. package/dist/claude/skills/post-init-tour/SKILL.md +0 -58
  247. package/dist/claude/skills/progress/SKILL.md +0 -271
  248. package/dist/claude/skills/project-new/SKILL.md +0 -564
  249. package/dist/claude/skills/quick/SKILL.md +0 -251
  250. package/dist/claude/skills/rename-audit/SKILL.md +0 -52
  251. package/dist/claude/skills/repo-audit/SKILL.md +0 -88
  252. package/dist/claude/skills/repo-cleanup/SKILL.md +0 -83
  253. package/dist/claude/skills/seed-memory/SKILL.md +0 -242
  254. package/dist/claude/skills/session-pause/SKILL.md +0 -126
  255. package/dist/claude/skills/session-plan/SKILL.md +0 -113
  256. package/dist/claude/skills/session-resume/SKILL.md +0 -111
  257. package/dist/claude/skills/todo-add/SKILL.md +0 -62
  258. package/dist/claude/skills/todo-check/SKILL.md +0 -81
  259. package/dist/claude/skills/workflow-save/SKILL.md +0 -277
  260. package/dist/index.d.mts +0 -33
  261. package/dist/index.d.ts +0 -33
  262. package/dist/index.mjs +0 -71
  263. package/dist/shared/luca.41dcdyd6.mjs +0 -197
  264. package/dist/shared/luca.BIOOhA-l.mjs +0 -249
  265. package/dist/shared/luca.BZc5veeE.mjs +0 -36
  266. package/dist/shared/luca.Bdq1J16r.mjs +0 -21
  267. package/dist/shared/luca.BfjhRHhj.mjs +0 -217
  268. package/dist/shared/luca.BpClq9Sj.mjs +0 -9
  269. package/dist/shared/luca.CIYP8N2e.mjs +0 -116
  270. package/dist/shared/luca.CQ3g1xrD.mjs +0 -19
  271. package/dist/shared/luca.CWvhdASW.mjs +0 -1369
  272. package/dist/shared/luca.DDb4WHV5.mjs +0 -102
  273. package/dist/shared/luca.DTomPq7I.mjs +0 -91
  274. package/dist/shared/luca.DdFkobL1.mjs +0 -10
  275. package/dist/shared/luca.Dqloj2-2.mjs +0 -201
  276. package/dist/shared/luca.E5xdUA-2.mjs +0 -2789
  277. package/dist/shared/luca.F3D90t11.mjs +0 -52
  278. package/dist/shared/luca.LXh1v8zr.mjs +0 -127
  279. package/dist/shared/luca.X1ymL7m1.mjs +0 -361
  280. package/dist/shared/luca.dM-MKlNE.mjs +0 -25
  281. package/dist/shared/luca.naWEcQ4B.mjs +0 -7
  282. package/dist/shared/luca.raYjreBY.mjs +0 -122
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @alecsibilia/luca
2
+
3
+ ## 14.0.0-alpha.0
4
+
5
+ ### Major Changes
6
+
7
+ - f732641: Luca v14: new Luca on npm
package/README.md CHANGED
@@ -1,47 +1,119 @@
1
1
  # @alecsibilia/luca
2
2
 
3
- Luca — spec-driven agentic development workflow for [Claude Code](https://claude.com/claude-code).
3
+ Luca turns a spec on GitHub Issues into a reviewed pull request. A run takes the spec's tickets through the engine, plain code that picks every next step, while Claude agents write the tests and the code and a fresh reviewer checks each ticket. The board shows the run live in Paseo.
4
4
 
5
- The `luca` CLI bootstraps [MuninnDB](https://github.com/asibilia/muninn) for long-term memory, installs the Luca skill/command/agent set into your global Claude home, and writes the per-project `.luca/` skeleton that drives the autonomous pipeline.
5
+ This is Luca v14, in alpha. Old Luca (v13) is still on npm; see [Coming from v13](#coming-from-v13).
6
6
 
7
- ## What's in the box
7
+ ## What you need
8
8
 
9
- This package is an umbrella: at build time it inlines three private workspace packages into a single self-contained tarball.
9
+ - macOS
10
+ - the Paseo desktop app, 0.9.1 or newer
11
+ - Claude Code 2.1.280 or newer, signed in with a Claude **Pro or Max** plan (not the Free plan, and not an API key)
12
+ - [Bun](https://bun.sh)
13
+ - git
14
+ - the GitHub CLI, `gh`, signed in (`gh auth login`)
15
+ - GitHub Issues as your repo's tracker
10
16
 
11
- | Sub-package | Role |
12
- |---|---|
13
- | `@alecsibilia/luca-cli` | The `luca` command surface (init, doctor, state, phase, todo, telemetry, …) |
14
- | `@alecsibilia/luca-core` | Deterministic logic — state machine, `.luca/` contract, telemetry, complexity routing, verification, confidence journal |
15
- | `@alecsibilia/luca-tools` | Artifact definitions (agents, skills, commands, rules, hooks) + the compiler that emits them to the Claude Code shape |
17
+ ## First run
16
18
 
17
- You do not depend on those names. Just `@alecsibilia/luca`.
19
+ 1. Install Luca:
18
20
 
19
- ## Installation
21
+ ```bash
22
+ bun add -g @alecsibilia/luca
23
+ ```
24
+
25
+ While v14 is in alpha, npm's `latest` is still v13, so install `@alecsibilia/luca@alpha` for now.
26
+
27
+ 2. Set up this computer, once:
28
+
29
+ ```bash
30
+ luca init
31
+ ```
32
+
33
+ 3. Set up your repo, once, from inside it:
34
+
35
+ ```bash
36
+ luca setup
37
+ ```
38
+
39
+ 4. In Claude Code, in your repo, run `/setup-matt-pocock-skills` so the planning skills know your repo.
40
+ 5. Write a spec with `/to-spec`, then split it into tickets with `/to-tickets`.
41
+ 6. In a Paseo chat, type `/luca-run <spec number>`. The board shows the run in the side panel, and the run ends in one pull request.
42
+
43
+ ## Commands
44
+
45
+ | Command | What it does |
46
+ | ------- | ------------ |
47
+ | `luca init` | Sets up this computer, once (safe to run again): MuninnDB and its Claude Code entry, the board in Paseo with its engine and Bun paths, and the planning skills (`to-spec`, `to-tickets`, `setup-matt-pocock-skills`, `grilling`, `domain-modeling`). It asks before turning on Paseo's plugins, and leaves skills you already have alone. `--skip-skills` skips the skills. |
48
+ | `luca setup` | Gets the repo in this folder ready: the labels a run needs (and the `release:*` labels when the repo uses changesets), `.luca/config.json`, and a check of GitHub sub-issues and dependencies. `--base <branch>` names the base branch. |
49
+ | `luca doctor` | Checks this computer, this repo when you're in one, and what v13 left behind. Each problem comes with its exact fix. `luca doctor --fix` fixes what's safe without asking: it never deletes (v13 files go to a dated backup folder) and never commits, and it lists the repo files to commit. |
50
+ | `luca upgrade` | Moves to the newest Luca on your channel: `alpha` stays on `alpha`, and it never goes back to v13. It refuses while any run is going (stuck runs and limit waits count) and lists them. Then it reloads the board and says when to run `/reload-skills`. |
51
+ | `luca upgrade --to <version>` | Installs that exact version, an older one too, to go back when a version breaks. |
52
+
53
+ `init`, `setup`, and `upgrade` end with their part of `luca doctor`'s checks.
54
+
55
+ ## Memory
56
+
57
+ Luca's runs remember what they learn with MuninnDB. `luca init` installs and starts it, adds it to Claude Code as the user-scope `muninn` server, and adds a login item that starts it again after a reboot.
58
+
59
+ If you run MuninnDB your own way, or want no memory, skip that step:
20
60
 
21
61
  ```bash
22
- bun add -g @alecsibilia/luca
23
- # or
24
- npm install -g @alecsibilia/luca
62
+ luca init --skip-muninndb
25
63
  ```
26
64
 
27
- ## Quickstart
65
+ A run with no `muninn` server in Claude Code has memory off, and `luca doctor` warns "memory off" rather than failing.
66
+
67
+ ## Coming from v13
68
+
69
+ v14 is a new Luca: `/lu`, `/luca-init`, v13's skills, agents, commands, hooks, and status line are gone. Matt Pocock's skills do the planning, and `/luca-run` does the building. Run `luca doctor --fix` to move what v13 left behind to a backup folder. See the [migration guide](https://github.com/asibilia/luca-framework/blob/main/docs/migrating-to-v14.md).
70
+
71
+ To stay on v13, don't install v14: v13 stays on npm. One computer holds one global `luca`.
72
+
73
+ ## For maintainers
74
+
75
+ ### Releasing
76
+
77
+ This package is released with changesets and the [`release.yml`](https://github.com/asibilia/luca-framework/blob/main/.github/workflows/release.yml) workflow. The repo is in changesets' pre mode `alpha`, so only `14.0.0-alpha.N` versions go out, under npm's `alpha` tag, and `latest` stays on `13.0.1`.
78
+
79
+ 1. Merge a PR with a changeset (`bunx changeset`). On the push to `main`, the workflow opens or updates the Version PR, "chore(release): version packages (...)". This package, `@luca/engine`, and `@luca/board` are one `fixed` group in `.changeset/config.json`: this package ships the engine's and board's files without depending on them, so a changeset that names only the private engine or board (as the engine's own changesets on its runs' PRs do) still bumps this package.
80
+ 2. The Version PR is opened by the bot, so its checks don't start on their own: on the PR, click **Approve workflows to run**.
81
+ 3. Merge the Version PR. The workflow sees no pending changesets and a version that isn't on npm yet, so it publishes: the PR checks, `bun pm pack`, an install of the tarball with `luca-run --demo`, a guard that fails unless the version is `-alpha.N`, `npm publish --tag alpha` over npm trusted publishing (no token), and a GitHub release marked as a prerelease.
82
+
83
+ Switch on `latest` later, after a real `tmnb` run works, with one reviewed PR that runs `changeset pre exit` and changes the `-alpha.N` guard (and the `--tag alpha`) in `release.yml` together.
84
+
85
+ ### What's in the package
86
+
87
+ This is the one package that goes to npm. It's TypeScript source with no build and no bundle, because the engine only runs on Bun. It has two commands: `luca`, for people, and `luca-run`, the engine, which the board starts. At pack time it copies in:
88
+
89
+ | Folder | What it is |
90
+ | ------ | ---------- |
91
+ | `engine/` | The engine's source, from [`packages/engine/src`](../engine/src). Both bins point into it. |
92
+ | `board/` | The board plugin's folder, from [`packages/board`](../board): `paseo-plugin.json`, its entry points, its client, server, and shared code, and its own `package.json`, so Paseo can install it as a folder source. |
93
+ | `LICENSE` | The repo's license. |
94
+
95
+ Test files and test helpers stay out. The engine and the board stay private workspace packages, and this package lists every package they import at runtime as its own dependency.
96
+
97
+ ### Pack it
98
+
99
+ Pack it with Bun, from this folder:
28
100
 
29
101
  ```bash
30
- luca init # Bootstrap MuninnDB + install Claude skills/commands/agents globally
31
- luca vault:init # Configure the per-project MuninnDB vault
32
- luca doctor # Environment diagnostics
102
+ bun pm pack
33
103
  ```
34
104
 
35
- Then, inside Claude Code, run the `/lu` slash command to drive the autonomous pipeline.
105
+ `bun pm pack` runs the `prepack` script ([`scripts/copy-sources.ts`](scripts/copy-sources.ts)), which copies the engine and the board in, then packs, then runs `postpack`, which removes the copies again.
36
106
 
37
- ## CLI reference
107
+ `bun pm pack` leaves out every `bunfig.toml` by default, even one named in `files`. The engine needs its own `cli/bunfig.toml`, because the board starts it with `--config` pointing there. So the script writes an `.npmignore` into `engine/` that puts it back.
38
108
 
39
- Use `luca --help` for the full surface, and `luca <command> --help` per noun group.
109
+ It must be packed with Bun. The manifest uses the workspace's `catalog:` and `workspace:` versions, and `bun pm pack` turns them into real versions in the packed `package.json`. A plain `npm pack` ships them unchanged, and an install from that tarball fails. Publish the tarball Bun made:
40
110
 
41
- Lifecycle: `init`, `vault:init`, `doctor`, `retro`, `claim-verify`, `telemetry`, `rules`, `classify`, `hook`, `repair`, `version`.
111
+ ```bash
112
+ npm publish <tarball> --tag alpha
113
+ ```
42
114
 
43
- Write surface (structured mutations of `.luca/`): `state`, `phase`, `roadmap`, `preferences`, `todo`, `pr-review`, `repo`, `checks`, `branch`, `workflow`, `confidence`, `verification`.
115
+ npm does the publishing because Bun can't publish over npm's trusted publishing (OIDC) yet.
44
116
 
45
117
  ## License
46
118
 
47
- MIT — see [LICENSE](./LICENSE).
119
+ Apache License 2.0. See [LICENSE](https://github.com/asibilia/luca-framework/blob/main/LICENSE).
@@ -0,0 +1,292 @@
1
+ import { useEffect, useState } from 'react'
2
+
3
+ import type { PluginTheme } from '@getpaseo/plugin'
4
+ import { Platform } from 'react-native'
5
+
6
+ import type { Tone } from '../shared/board-rows'
7
+ import type {
8
+ LensState,
9
+ RunStatus,
10
+ TicketStage,
11
+ UsageLevel,
12
+ } from '../shared/board-state'
13
+
14
+ /**
15
+ * Colors and words shared by the side panel and the chat rows, so both views
16
+ * match. Every color comes from the host theme.
17
+ */
18
+
19
+ export const MONO = Platform.select({ ios: 'Menlo', default: 'monospace' })
20
+
21
+ /** How often a running step's time counts up. */
22
+ const TICK_MS = 1000
23
+
24
+ /**
25
+ * The clock, ticking every second, so a running step's time counts up
26
+ * even when no new record redraws the view.
27
+ *
28
+ * @example
29
+ * const now = useNow()
30
+ * currentStepText({ step, now })
31
+ */
32
+ export const useNow = (): number => {
33
+ const [now, setNow] = useState(() => Date.now())
34
+ useEffect(() => {
35
+ const timer = setInterval(() => setNow(Date.now()), TICK_MS)
36
+ return () => clearInterval(timer)
37
+ }, [])
38
+ return now
39
+ }
40
+
41
+ /** Opacity for dimmed parts: empty stages, the final review before it starts. */
42
+ export const DIMMED = 0.45
43
+
44
+ /**
45
+ * Plan usage color: green below 60%, yellow 60–85%, red above 85%, muted
46
+ * with no reading.
47
+ */
48
+ export const usageColor = ({
49
+ level,
50
+ theme,
51
+ }: {
52
+ level: UsageLevel | null
53
+ theme: PluginTheme
54
+ }): string => {
55
+ if (level === null) return theme.colors.foregroundMuted
56
+ switch (level) {
57
+ case 'ok':
58
+ return theme.colors.statusSuccess
59
+ case 'warn':
60
+ return theme.colors.statusWarning
61
+ case 'high':
62
+ return theme.colors.statusDanger
63
+ }
64
+ }
65
+
66
+ export const stageColor = ({
67
+ stage,
68
+ theme,
69
+ }: {
70
+ stage: TicketStage
71
+ theme: PluginTheme
72
+ }): string => {
73
+ switch (stage) {
74
+ case 'building':
75
+ case 'reviewing':
76
+ return theme.colors.accent
77
+ case 'stuck':
78
+ return theme.colors.statusDanger
79
+ case 'done':
80
+ return theme.colors.statusSuccess
81
+ case 'blocked':
82
+ case 'skipped':
83
+ return theme.colors.foregroundMuted
84
+ }
85
+ }
86
+
87
+ export const lensColor = ({
88
+ state,
89
+ theme,
90
+ }: {
91
+ state: LensState
92
+ theme: PluginTheme
93
+ }): string => {
94
+ switch (state) {
95
+ case 'waiting':
96
+ return theme.colors.foregroundMuted
97
+ case 'reviewing':
98
+ return theme.colors.accent
99
+ case 'fixing':
100
+ return theme.colors.statusWarning
101
+ case 'clean':
102
+ return theme.colors.statusSuccess
103
+ }
104
+ }
105
+
106
+ export const toneColor = ({
107
+ tone,
108
+ theme,
109
+ }: {
110
+ tone: Tone
111
+ theme: PluginTheme
112
+ }): string => {
113
+ switch (tone) {
114
+ case 'info':
115
+ return theme.colors.accent
116
+ case 'success':
117
+ return theme.colors.statusSuccess
118
+ case 'warning':
119
+ return theme.colors.statusWarning
120
+ case 'danger':
121
+ return theme.colors.statusDanger
122
+ }
123
+ }
124
+
125
+ export const statusColor = ({
126
+ status,
127
+ theme,
128
+ }: {
129
+ status: RunStatus
130
+ theme: PluginTheme
131
+ }): string => {
132
+ switch (status) {
133
+ case 'done':
134
+ return theme.colors.statusSuccess
135
+ case 'stuck':
136
+ case 'stopped':
137
+ case 'refused':
138
+ case 'ended_with_error':
139
+ return theme.colors.statusDanger
140
+ case 'limit_wait':
141
+ case 'usage_line_wait':
142
+ return theme.colors.statusWarning
143
+ case 'starting':
144
+ case 'intake':
145
+ case 'building':
146
+ case 'final_review':
147
+ return theme.colors.accent
148
+ case 'nothing_to_do':
149
+ return theme.colors.foregroundMuted
150
+ }
151
+ }
152
+
153
+ /** A run status in words. */
154
+ export const statusText = ({ status }: { status: RunStatus }): string => {
155
+ switch (status) {
156
+ case 'starting':
157
+ return 'starting'
158
+ case 'intake':
159
+ return 'intake'
160
+ case 'building':
161
+ return 'building'
162
+ case 'final_review':
163
+ return 'final review'
164
+ case 'limit_wait':
165
+ return 'limit wait'
166
+ case 'usage_line_wait':
167
+ return 'paused at the usage line'
168
+ case 'done':
169
+ return 'done'
170
+ case 'refused':
171
+ return 'refused'
172
+ case 'nothing_to_do':
173
+ return 'nothing to do'
174
+ case 'stuck':
175
+ return 'stuck'
176
+ case 'stopped':
177
+ return 'run stopped'
178
+ case 'ended_with_error':
179
+ return 'engine stopped'
180
+ }
181
+ }
182
+
183
+ /** A usage percent, or "–" for a window with no reading yet. */
184
+ export const percentText = ({ percent }: { percent: number | null }): string =>
185
+ percent === null ? '–' : `${percent}%`
186
+
187
+ /** 1234 → "1.2k"; 9000000 → "9.0M". */
188
+ export const tokensText = ({ tokens }: { tokens: number }): string => {
189
+ if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}M`
190
+ return tokens >= 1000 ? `${(tokens / 1000).toFixed(1)}k` : String(tokens)
191
+ }
192
+
193
+ const two = ({ value }: { value: number }) => String(value).padStart(2, '0')
194
+
195
+ /** An ISO time as local "hh:mm", or the text itself when it isn't a time. */
196
+ export const clockText = ({ iso }: { iso: string }): string => {
197
+ const date = new Date(iso)
198
+ if (Number.isNaN(date.getTime())) return iso
199
+ return `${two({ value: date.getHours() })}:${two({ value: date.getMinutes() })}`
200
+ }
201
+
202
+ /** When a limit resets, e.g. "17:00 (in 1h 20m)". */
203
+ export const resetsText = ({
204
+ resets_at,
205
+ now,
206
+ }: {
207
+ resets_at: string | null
208
+ now: number
209
+ }): string => {
210
+ if (!resets_at) return 'unknown'
211
+ const at = new Date(resets_at).getTime()
212
+ if (Number.isNaN(at)) return resets_at
213
+ const minutes = Math.max(0, Math.round((at - now) / 60_000))
214
+ const left =
215
+ minutes >= 60
216
+ ? `${Math.floor(minutes / 60)}h ${minutes % 60}m`
217
+ : `${minutes}m`
218
+ return `${clockText({ iso: resets_at })} (in ${left})`
219
+ }
220
+
221
+ /**
222
+ * A limit wait's headline, e.g. "Plan limit hit (five-hour window)". `window`
223
+ * is already in words; without one it's just "Plan limit hit".
224
+ */
225
+ export const limitHitText = ({ window }: { window: string | null }): string =>
226
+ window === null ? 'Plan limit hit' : `Plan limit hit (${window} window)`
227
+
228
+ /** "The run waits until 17:00 (in 1h 20m) and then carries on by itself." */
229
+ export const limitUntilText = ({
230
+ resets_at,
231
+ now,
232
+ }: {
233
+ resets_at: string | null
234
+ now: number
235
+ }): string =>
236
+ `The run waits until ${resetsText({ resets_at, now })} and then carries on by itself.`
237
+
238
+ /**
239
+ * What a limit wait means, e.g. "Plan limit hit (weekly window). The run
240
+ * waits until 17:00 (in 1h 20m) and then carries on by itself."
241
+ */
242
+ export const limitWaitText = ({
243
+ window,
244
+ resets_at,
245
+ now,
246
+ }: {
247
+ window: string | null
248
+ resets_at: string | null
249
+ now: number
250
+ }): string =>
251
+ `${limitHitText({ window })}. ${limitUntilText({ resets_at, now })}`
252
+
253
+ /**
254
+ * What a pause at the usage line means, e.g. "Paused at the weekly usage
255
+ * line: the account's weekly window is at 82% (line 80%). The run waits
256
+ * until 11:00 (in 3h 5m), or until the line is raised, and then carries on
257
+ * by itself."
258
+ */
259
+ export const usageLineWaitText = ({
260
+ window,
261
+ line,
262
+ percent,
263
+ resets_at,
264
+ now,
265
+ }: {
266
+ window: string
267
+ line: number
268
+ percent: number
269
+ resets_at: string
270
+ now: number
271
+ }): string =>
272
+ `Paused at the ${window} usage line: the account's ${window} window is at ${percent}% (line ${line}%). ` +
273
+ `The run waits until ${resetsText({ resets_at, now })}, or until the line is raised, and then carries on by itself.`
274
+
275
+ /** "Spec #10 · Add CSV export", or "Demo run" before the engine names one. */
276
+ export const runTitle = ({
277
+ spec_number,
278
+ spec_title,
279
+ demo,
280
+ }: {
281
+ spec_number: number | null
282
+ spec_title: string | null
283
+ demo: boolean
284
+ }): string => {
285
+ const spec =
286
+ spec_number === null
287
+ ? demo
288
+ ? 'Demo run'
289
+ : 'Run'
290
+ : `${demo ? 'Demo · ' : ''}Spec #${spec_number}`
291
+ return spec_title ? `${spec} · ${spec_title}` : spec
292
+ }