@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.
- package/CHANGELOG.md +7 -0
- package/README.md +96 -24
- package/board/client/board-look.ts +292 -0
- package/board/client/board-panel.tsx +1355 -0
- package/board/client/engine-settings-screen.tsx +167 -0
- package/board/client/timeline-rows.tsx +402 -0
- package/board/index.client.tsx +109 -0
- package/board/index.server.ts +173 -0
- package/board/package.json +6 -0
- package/board/paseo-plugin.json +7 -0
- package/board/server/board-server.ts +988 -0
- package/board/server/board-vocabulary.ts +492 -0
- package/board/server/engine-launch.ts +193 -0
- package/board/server/engine-watch.ts +197 -0
- package/board/server/list-processes.ts +35 -0
- package/board/server/make-rows.ts +834 -0
- package/board/server/reduce-board.ts +1952 -0
- package/board/server/run-command.ts +54 -0
- package/board/server/run-journals.ts +120 -0
- package/board/server/run-registry.ts +171 -0
- package/board/server/spawn-detached.ts +45 -0
- package/board/server/usage-lines-file.ts +43 -0
- package/board/shared/board-rows.ts +127 -0
- package/board/shared/board-rpc.ts +131 -0
- package/board/shared/board-state.ts +683 -0
- package/board/shared/engine-settings.ts +36 -0
- package/engine/agents/agent-launcher.ts +188 -0
- package/engine/agents/claude-launcher.ts +781 -0
- package/engine/agents/claude-options.ts +239 -0
- package/engine/agents/message-tool.ts +124 -0
- package/engine/agents/role-instructions.ts +287 -0
- package/engine/agents/role-prompts.ts +207 -0
- package/engine/agents/role-results.ts +335 -0
- package/engine/agents/scripted-launcher.ts +227 -0
- package/engine/board/board-state-dir.ts +20 -0
- package/engine/board/board-sync.ts +145 -0
- package/engine/board/paseo-board-link.ts +125 -0
- package/engine/cli/board-in-paseo.ts +154 -0
- package/engine/cli/bunfig.toml +4 -0
- package/engine/cli/computer-adapters-real.ts +456 -0
- package/engine/cli/computer-adapters.ts +122 -0
- package/engine/cli/computer-checks.ts +404 -0
- package/engine/cli/doctor-checks.ts +171 -0
- package/engine/cli/doctor-command.ts +94 -0
- package/engine/cli/doctor.ts +369 -0
- package/engine/cli/going-runs.ts +130 -0
- package/engine/cli/init-command.ts +143 -0
- package/engine/cli/init.ts +346 -0
- package/engine/cli/luca-run.ts +189 -0
- package/engine/cli/luca.ts +62 -0
- package/engine/cli/muninn-entry.ts +87 -0
- package/engine/cli/repo-adapters-real.ts +70 -0
- package/engine/cli/run-args.ts +223 -0
- package/engine/cli/run-modes.ts +629 -0
- package/engine/cli/setup-command.ts +59 -0
- package/engine/cli/setup.ts +710 -0
- package/engine/cli/upgrade-command.ts +140 -0
- package/engine/cli/upgrade.ts +262 -0
- package/engine/cli/v13-leftovers.ts +694 -0
- package/engine/config/engine-config.ts +168 -0
- package/engine/config/luca-version.ts +47 -0
- package/engine/core/changeset.ts +140 -0
- package/engine/core/decide-build.ts +1318 -0
- package/engine/core/decide-crashes.ts +70 -0
- package/engine/core/decide-final-review.ts +416 -0
- package/engine/core/decide-memory.ts +667 -0
- package/engine/core/decide-plan.ts +87 -0
- package/engine/core/decide-run-budget.ts +76 -0
- package/engine/core/decide-stuck.ts +347 -0
- package/engine/core/decide-usage-line.ts +113 -0
- package/engine/core/decide-usage.ts +68 -0
- package/engine/core/decide.ts +200 -0
- package/engine/core/execute-build.ts +1121 -0
- package/engine/core/execute-changeset.ts +149 -0
- package/engine/core/execute-final-review.ts +324 -0
- package/engine/core/execute-memory.ts +475 -0
- package/engine/core/execute-stuck.ts +315 -0
- package/engine/core/execute.ts +1112 -0
- package/engine/core/final-review-text.ts +278 -0
- package/engine/core/fix-loop-text.ts +124 -0
- package/engine/core/learner-digest.ts +214 -0
- package/engine/core/loop-caps.ts +39 -0
- package/engine/core/memory-text.ts +132 -0
- package/engine/core/pull-request-text.ts +154 -0
- package/engine/core/review-text.ts +211 -0
- package/engine/core/session-close.ts +159 -0
- package/engine/core/stuck-text.ts +370 -0
- package/engine/doctor/v13-files.json +3948 -0
- package/engine/doctor/v13-manifest.ts +124 -0
- package/engine/gates/gate-runner.ts +103 -0
- package/engine/gates/gate-schemas.ts +63 -0
- package/engine/gates/leftover-scan.ts +110 -0
- package/engine/gates/lockfile-install.ts +109 -0
- package/engine/gates/red-check.ts +134 -0
- package/engine/gates/test-runner.ts +212 -0
- package/engine/git/git-adapter.ts +535 -0
- package/engine/guards/after-turn-check.ts +269 -0
- package/engine/guards/guard-hook.ts +63 -0
- package/engine/guards/role-rules.ts +704 -0
- package/engine/guards/sandbox-settings.ts +94 -0
- package/engine/guards/worktree-state.ts +959 -0
- package/engine/index.ts +297 -0
- package/engine/intake/intake-checks.ts +295 -0
- package/engine/intake/intake-schemas.ts +78 -0
- package/engine/jev/jev-client.ts +173 -0
- package/engine/jev/jev-jobs.ts +369 -0
- package/engine/jev/jev-schemas.ts +89 -0
- package/engine/jev/jev-shadow.ts +149 -0
- package/engine/journal/journal-record.ts +1324 -0
- package/engine/journal/journal.ts +115 -0
- package/engine/journal/replay.ts +2432 -0
- package/engine/journal/step-records.ts +142 -0
- package/engine/limits/limit-wait.ts +86 -0
- package/engine/limits/plan-signals.ts +122 -0
- package/engine/limits/plan-usage.ts +275 -0
- package/engine/limits/run-budget.ts +63 -0
- package/engine/limits/usage-line.ts +324 -0
- package/engine/memory/memory-client.ts +144 -0
- package/engine/memory/memory-recall.ts +62 -0
- package/engine/memory/memory-routing.ts +170 -0
- package/engine/memory/memory-schemas.ts +125 -0
- package/engine/memory/muninn-mcp-client.ts +390 -0
- package/engine/messages/agent-messages.ts +357 -0
- package/engine/messages/agent-messaging.ts +77 -0
- package/engine/shell/run-command.ts +86 -0
- package/engine/testing/build-fixtures.ts +912 -0
- package/engine/testing/fake-muninn.ts +219 -0
- package/engine/testing/final-review-fixtures.ts +223 -0
- package/engine/testing/intake-fixtures.ts +118 -0
- package/engine/testing/many-tickets.ts +739 -0
- package/engine/testing/memory-fixtures.ts +202 -0
- package/engine/testing/practice-repo.ts +475 -0
- package/engine/testing/practice-run.ts +182 -0
- package/engine/tracker/github-tracker.ts +262 -0
- package/engine/tracker/in-memory-tracker.ts +161 -0
- package/engine/tracker/post-comment-once.ts +69 -0
- package/engine/tracker/tracker.ts +119 -0
- package/package.json +57 -74
- package/bin/luca.js +0 -3
- package/dist/chunks/brain.mjs +0 -77
- package/dist/chunks/branch.mjs +0 -51
- package/dist/chunks/bun-runtime.mjs +0 -46
- package/dist/chunks/checks.mjs +0 -57
- package/dist/chunks/claim-verify.mjs +0 -70
- package/dist/chunks/classify.mjs +0 -105
- package/dist/chunks/confidence.mjs +0 -277
- package/dist/chunks/config-version-skew.mjs +0 -94
- package/dist/chunks/doctor.mjs +0 -174
- package/dist/chunks/hook.mjs +0 -850
- package/dist/chunks/init.mjs +0 -1015
- package/dist/chunks/legacy-claude-artifacts.mjs +0 -105
- package/dist/chunks/legacy-package.mjs +0 -47
- package/dist/chunks/luca-gitignore.mjs +0 -93
- package/dist/chunks/muninn-mcp.mjs +0 -81
- package/dist/chunks/muninndb-health.mjs +0 -66
- package/dist/chunks/phase.mjs +0 -64
- package/dist/chunks/plan.mjs +0 -51
- package/dist/chunks/pr-review.mjs +0 -128
- package/dist/chunks/preferences.mjs +0 -66
- package/dist/chunks/repair.mjs +0 -111
- package/dist/chunks/repo.mjs +0 -58
- package/dist/chunks/retro.mjs +0 -87
- package/dist/chunks/roadmap.mjs +0 -63
- package/dist/chunks/rules.mjs +0 -524
- package/dist/chunks/shared-tmp-payloads.mjs +0 -72
- package/dist/chunks/stale-global-symlinks.mjs +0 -78
- package/dist/chunks/stale-mcp-server.mjs +0 -90
- package/dist/chunks/state.mjs +0 -104
- package/dist/chunks/stray-local-install.mjs +0 -208
- package/dist/chunks/telemetry.mjs +0 -370
- package/dist/chunks/todo.mjs +0 -230
- package/dist/chunks/vault-config-location.mjs +0 -100
- package/dist/chunks/vault-init.mjs +0 -94
- package/dist/chunks/verification.mjs +0 -99
- package/dist/chunks/version.mjs +0 -70
- package/dist/chunks/workflow.mjs +0 -51
- package/dist/claude/.claude/agents/architect.md +0 -508
- package/dist/claude/.claude/agents/build.md +0 -117
- package/dist/claude/.claude/agents/debater.md +0 -95
- package/dist/claude/.claude/agents/discuss.md +0 -99
- package/dist/claude/.claude/agents/discussion.md +0 -143
- package/dist/claude/.claude/agents/execute.md +0 -450
- package/dist/claude/.claude/agents/executor.md +0 -187
- package/dist/claude/.claude/agents/fast.md +0 -90
- package/dist/claude/.claude/agents/finalize.md +0 -562
- package/dist/claude/.claude/agents/learner.md +0 -167
- package/dist/claude/.claude/agents/plan-reviewer.md +0 -137
- package/dist/claude/.claude/agents/plan.md +0 -102
- package/dist/claude/.claude/agents/research.md +0 -334
- package/dist/claude/.claude/agents/researcher.md +0 -81
- package/dist/claude/.claude/agents/review.md +0 -330
- package/dist/claude/.claude/agents/reviewer.md +0 -177
- package/dist/claude/.claude/agents/shadow-scanner.md +0 -261
- package/dist/claude/.claude/agents/test-writer.md +0 -96
- package/dist/claude/.claude/agents/triage.md +0 -230
- package/dist/claude/.claude/agents/verifier.md +0 -192
- package/dist/claude/.claude/commands/bug-diagnose.md +0 -12
- package/dist/claude/.claude/commands/gh-issue-triage.md +0 -14
- package/dist/claude/.claude/commands/gh-pr-address.md +0 -235
- package/dist/claude/.claude/commands/gh-prepare.md +0 -12
- package/dist/claude/.claude/commands/grill-me.md +0 -12
- package/dist/claude/.claude/commands/lu-review.md +0 -51
- package/dist/claude/.claude/commands/lu.md +0 -98
- package/dist/claude/.claude/commands/luca-init.md +0 -14
- package/dist/claude/.claude/commands/luca-telemetry-report.md +0 -12
- package/dist/claude/.claude/commands/memory-audit.md +0 -12
- package/dist/claude/.claude/commands/milestone-new.md +0 -122
- package/dist/claude/.claude/commands/phase-discuss.md +0 -45
- package/dist/claude/.claude/commands/phase-execute.md +0 -39
- package/dist/claude/.claude/commands/phase-plan.md +0 -57
- package/dist/claude/.claude/commands/repo-cleanup.md +0 -83
- package/dist/claude/.claude/commands/todo-add.md +0 -28
- package/dist/claude/.claude/commands/todo-check.md +0 -36
- package/dist/claude/.claude/hooks/context-refresher.ts +0 -14074
- package/dist/claude/.claude/hooks/continuation-messages.ts +0 -14049
- package/dist/claude/.claude/hooks/pipeline-guard.ts +0 -14036
- package/dist/claude/.claude/luca-statusline.ts +0 -159
- package/dist/claude/.claude/settings.json +0 -41
- package/dist/claude/skills/arch-audit/SKILL.md +0 -161
- package/dist/claude/skills/bug-diagnose/SKILL.md +0 -102
- package/dist/claude/skills/caveman/SKILL.md +0 -58
- package/dist/claude/skills/choose/SKILL.md +0 -124
- package/dist/claude/skills/gh-issue-triage/SKILL.md +0 -97
- package/dist/claude/skills/gh-pr-address/SKILL.md +0 -235
- package/dist/claude/skills/gh-prepare/SKILL.md +0 -209
- package/dist/claude/skills/grill-me/SKILL.md +0 -46
- package/dist/claude/skills/lu/SKILL.md +0 -262
- package/dist/claude/skills/lu-review/SKILL.md +0 -51
- package/dist/claude/skills/luca-init/SKILL.md +0 -91
- package/dist/claude/skills/luca-telemetry-report/SKILL.md +0 -210
- package/dist/claude/skills/luca-write-surface/SKILL.md +0 -229
- package/dist/claude/skills/memory-audit/SKILL.md +0 -217
- package/dist/claude/skills/milestone-audit/SKILL.md +0 -525
- package/dist/claude/skills/milestone-complete/SKILL.md +0 -179
- package/dist/claude/skills/milestone-gaps/SKILL.md +0 -60
- package/dist/claude/skills/milestone-new/SKILL.md +0 -125
- package/dist/claude/skills/note/SKILL.md +0 -162
- package/dist/claude/skills/phase-add/SKILL.md +0 -91
- package/dist/claude/skills/phase-assumptions/SKILL.md +0 -92
- package/dist/claude/skills/phase-discuss/SKILL.md +0 -175
- package/dist/claude/skills/phase-execute/SKILL.md +0 -1857
- package/dist/claude/skills/phase-insert/SKILL.md +0 -100
- package/dist/claude/skills/phase-plan/SKILL.md +0 -489
- package/dist/claude/skills/phase-remove/SKILL.md +0 -113
- package/dist/claude/skills/phase-research/SKILL.md +0 -88
- package/dist/claude/skills/post-init-tour/SKILL.md +0 -58
- package/dist/claude/skills/progress/SKILL.md +0 -271
- package/dist/claude/skills/project-new/SKILL.md +0 -564
- package/dist/claude/skills/quick/SKILL.md +0 -251
- package/dist/claude/skills/rename-audit/SKILL.md +0 -52
- package/dist/claude/skills/repo-audit/SKILL.md +0 -88
- package/dist/claude/skills/repo-cleanup/SKILL.md +0 -83
- package/dist/claude/skills/seed-memory/SKILL.md +0 -242
- package/dist/claude/skills/session-pause/SKILL.md +0 -126
- package/dist/claude/skills/session-plan/SKILL.md +0 -113
- package/dist/claude/skills/session-resume/SKILL.md +0 -111
- package/dist/claude/skills/todo-add/SKILL.md +0 -62
- package/dist/claude/skills/todo-check/SKILL.md +0 -81
- package/dist/claude/skills/workflow-save/SKILL.md +0 -277
- package/dist/index.d.mts +0 -33
- package/dist/index.d.ts +0 -33
- package/dist/index.mjs +0 -71
- package/dist/shared/luca.41dcdyd6.mjs +0 -197
- package/dist/shared/luca.BIOOhA-l.mjs +0 -249
- package/dist/shared/luca.BZc5veeE.mjs +0 -36
- package/dist/shared/luca.Bdq1J16r.mjs +0 -21
- package/dist/shared/luca.BfjhRHhj.mjs +0 -217
- package/dist/shared/luca.BpClq9Sj.mjs +0 -9
- package/dist/shared/luca.CIYP8N2e.mjs +0 -116
- package/dist/shared/luca.CQ3g1xrD.mjs +0 -19
- package/dist/shared/luca.CWvhdASW.mjs +0 -1369
- package/dist/shared/luca.DDb4WHV5.mjs +0 -102
- package/dist/shared/luca.DTomPq7I.mjs +0 -91
- package/dist/shared/luca.DdFkobL1.mjs +0 -10
- package/dist/shared/luca.Dqloj2-2.mjs +0 -201
- package/dist/shared/luca.E5xdUA-2.mjs +0 -2789
- package/dist/shared/luca.F3D90t11.mjs +0 -52
- package/dist/shared/luca.LXh1v8zr.mjs +0 -127
- package/dist/shared/luca.X1ymL7m1.mjs +0 -361
- package/dist/shared/luca.dM-MKlNE.mjs +0 -25
- package/dist/shared/luca.naWEcQ4B.mjs +0 -7
- package/dist/shared/luca.raYjreBY.mjs +0 -122
package/CHANGELOG.md
ADDED
package/README.md
CHANGED
|
@@ -1,47 +1,119 @@
|
|
|
1
1
|
# @alecsibilia/luca
|
|
2
2
|
|
|
3
|
-
Luca
|
|
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
|
-
|
|
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
|
|
7
|
+
## What you need
|
|
8
8
|
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
19
|
+
1. Install Luca:
|
|
18
20
|
|
|
19
|
-
|
|
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
|
-
|
|
23
|
-
# or
|
|
24
|
-
npm install -g @alecsibilia/luca
|
|
62
|
+
luca init --skip-muninndb
|
|
25
63
|
```
|
|
26
64
|
|
|
27
|
-
|
|
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
|
-
|
|
31
|
-
luca vault:init # Configure the per-project MuninnDB vault
|
|
32
|
-
luca doctor # Environment diagnostics
|
|
102
|
+
bun pm pack
|
|
33
103
|
```
|
|
34
104
|
|
|
35
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
111
|
+
```bash
|
|
112
|
+
npm publish <tarball> --tag alpha
|
|
113
|
+
```
|
|
42
114
|
|
|
43
|
-
|
|
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
|
-
|
|
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
|
+
}
|