Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
176 commits
Select commit Hold shift + click to select a range
c1d8647
feat: scaffold Lumen OS monorepo, core packages and shell
claude Sep 4, 2026
ee8adf9
fix(shell): spin the wait cursor around its centre, and de-pill the l…
claude Sep 4, 2026
616d29e
feat(apps): Files, Sheets, Terminal and Editor in progress
claude Sep 4, 2026
bf39d63
fix(ci): make lint and the Rust job pass
claude Sep 4, 2026
66d44db
feat(apps): Writer, Editor and Sheets
claude Sep 4, 2026
a05a24d
feat(apps): complete Editor, Writer and Sheets; register built-in apps
claude Sep 4, 2026
76e525e
fix(shell): correct two composition faults visible on the running des…
claude Sep 4, 2026
2dfca01
chore(ui): triage the kill-ai-slop scan across ui and kernel
claude Sep 4, 2026
c018b98
fix(apps): complete the Slides app so packages/apps typechecks again
claude Sep 4, 2026
af7941f
fix(tooling): stop Vitest collecting the Playwright suite, and unmoun…
claude Sep 4, 2026
031b50d
chore(tokens): quiet the design scan where it matches the rules thems…
claude Sep 4, 2026
08ff070
fix(apps): drop the stray heading level from the Slides inspector
claude Sep 4, 2026
2cdb473
refactor(apps): widen the Preview file-kind table
claude Sep 4, 2026
ca49e01
refactor(apps): fold the Browser navigation module into the tab state
claude Sep 4, 2026
3af8488
feat(apps): land the Media, System Information and Task Manager modules
claude Sep 4, 2026
bc26be6
feat(apps): complete the System Information app
claude Sep 4, 2026
d851df2
feat(apps): complete the Browser, Preview and Task Manager apps
claude Sep 4, 2026
240a07f
feat(apps): register Browser, Slides, Preview, Task Manager and Syste…
claude Sep 4, 2026
2645a9b
fix(apps): repair the torn System Information snapshot that broke CI
claude Sep 4, 2026
6c5ed03
feat(apps): finish the Preview viewers and playback controls
claude Sep 4, 2026
9ab89d7
feat(apps): complete the Notes, Media Player and Calculator apps
claude Sep 4, 2026
7cf3093
feat(apps): register Notes, Media Player and Calculator
claude Sep 4, 2026
24af8b9
feat(apps): finish the Media Player and Notes apps
claude Sep 4, 2026
d83a63d
fix(shell): let a focused app claim the window shortcuts the shell al…
claude Sep 4, 2026
0b79ffa
feat(apps): finish the Calculator's interface and tests
claude Sep 4, 2026
3f7e954
fix(apps): stop a slow read in useJsonFile reverting a value already …
claude Sep 4, 2026
94b5c0b
fix(ci): rename modules that differ only by case, and guard against more
claude Sep 4, 2026
07ffac4
ci(github): add CodeQL, PR labelling, support docs and a shared setup…
claude Sep 4, 2026
c85c341
feat(apps): land the logic for Calendar, Clock, Console, Paint and So…
claude Sep 4, 2026
a66e2fb
fix(kernel): close a prototype-pollution hole in the settings store
claude Sep 4, 2026
86e3310
fix(apps): give the Console menu mocks their real signatures
claude Sep 5, 2026
b3479c5
feat(desktop): build for macOS and Linux, not only Windows
claude Sep 5, 2026
7b4b879
feat(apps): land Storage, Software Center, Minesweeper and Paint
claude Sep 5, 2026
79ba648
feat(apps): land Calendar, Clock and Console
claude Sep 5, 2026
963309e
feat(apps): finish the Console shell and register nine more apps
claude Sep 5, 2026
b4e010f
fix(ci): unbreak the Windows MSI and the case-collision guard
claude Sep 5, 2026
0d1235b
feat(apps): finish the Calendar shell and register it
claude Sep 5, 2026
fedad12
feat(apps): finish the Paint shell and register it
claude Sep 5, 2026
fa59233
fix(landing): list the apps the OS actually ships, and keep it that way
claude Sep 5, 2026
d199ca1
fix(ci): pin the third-party actions, and stop a test looking like a …
claude Sep 5, 2026
94a163b
fix(shell): stop the menubar clock wrapping when the bar runs out of …
claude Sep 5, 2026
6e08f8d
feat(apps): add Mail, Contacts, Reminders, Archive Utility, Units and…
claude Sep 5, 2026
71e2ea8
fix: five high-severity defects found by the audit
claude Sep 5, 2026
00c3f6e
fix(kernel): four medium defects, and land the chess engine
claude Sep 5, 2026
9b550d3
feat(apps): register the six new apps and list them on the landing page
claude Sep 5, 2026
22072eb
fix: the remaining audit findings in the kernel and the file system
claude Sep 5, 2026
4bfa983
chore: ignore the scratch probes review agents leave behind
claude Sep 5, 2026
2ec1b61
feat(apps): give Chess its board and window, and register it
claude Sep 5, 2026
be00cf9
feat(shell): two more screensavers, three more wallpapers, and motion…
claude Sep 5, 2026
cc7b81d
fix(ui): no control is squeezed out of its box at an app's smallest w…
claude Sep 5, 2026
e50294a
docs: turn the new brief into a specification and a plan
claude Sep 5, 2026
92ede2b
fix(shell): the five defects a person meets in the first minute
claude Sep 5, 2026
4570f66
feat(apps): add Sudoku and 2048
claude Sep 5, 2026
5384044
feat(kernel): settings for motion, blur and window behaviour
claude Sep 5, 2026
74667f6
feat(kernel): a service catalogue and a load model that answers to wh…
claude Sep 5, 2026
691ef8f
feat(kernel): the file manager runs for the whole session
claude Sep 5, 2026
b15716f
feat(settings): a page for animation, and blur as a control
claude Sep 5, 2026
356dbe3
feat(apps): every setting, every service and sudo from the terminal
claude Sep 5, 2026
30b79c6
feat(shell): a selection rectangle on the desktop, and dialogs that fit
claude Sep 5, 2026
a31be15
feat(apps): a services tab in the task manager
claude Sep 5, 2026
d312b8b
feat(apps): finish Solitaire
claude Sep 5, 2026
6588a50
feat(apps): register Solitaire
claude Sep 5, 2026
62ad77e
feat(shell): the front window steps back when the keyboard leaves, an…
claude Sep 5, 2026
917261f
feat(shell): full screen takes the display
claude Sep 5, 2026
a3f40c1
fix(kernel): a booting kernel starts with an empty process table
claude Sep 5, 2026
0749e6f
feat(apps): a card view for Files and settings the browser actually k…
claude Sep 5, 2026
402dcee
feat(tokens): groundwork for the store and for controls that share a row
claude Sep 5, 2026
d7d5ccb
feat(apps): chess plays a full game and fits the window it is given
claude Sep 5, 2026
c7702bc
feat(apps): a Settings page for where the catalogue comes from
claude Sep 5, 2026
e5d0c5e
feat(apps): the client half of the store, from a base URL to a verifi…
claude Sep 5, 2026
68511ed
fix(apps): seven windows put their controls in the app's own toolbar row
claude Sep 5, 2026
c1df5d8
feat(tooling): the store catalogue, and the generator that keeps it h…
claude Sep 5, 2026
7aa4a22
feat(apps): a store account, and what a subscription lets it install
claude Sep 5, 2026
8064f3b
fix(apps): Quick Look measures the window, not the screen
claude Sep 5, 2026
ca7d27e
fix(apps): four more windows name themselves in their own toolbar row
claude Sep 5, 2026
0f7c4c1
docs(tooling): the store's own README, and a pass over the catalogue
claude Sep 5, 2026
a44402f
feat(apps): every table alternates its rows, not only the ones built …
claude Sep 5, 2026
9d34cba
fix(apps): the last five windows lose their title band, and the board…
claude Sep 5, 2026
c23bb14
feat(apps): the storefront browses the live catalogue and installs fr…
claude Sep 6, 2026
03b1354
feat(shell): two settings that were switches over nothing now do what…
claude Sep 6, 2026
170bf57
fix(apps): a shelf row stops bleeding four pixels out of its window
claude Sep 6, 2026
6b1f629
feat(apps): drag a rectangle to select in the file views, not only on…
claude Sep 6, 2026
881f08f
fix(shell): the desktop's marquee hook runs on every render
claude Sep 6, 2026
09cf587
feat(shell): a column resize and a row resize get cursors of their own
claude Sep 6, 2026
d4c0cbd
fix(shell): a right-click gets a menu everywhere, instead of nothing
claude Sep 6, 2026
1fa2293
feat(shell): the taskbar reads the four settings that were switches o…
claude Sep 6, 2026
6e4a4f9
feat(vfs): the system's own files refuse to be deleted without a pass…
claude Sep 6, 2026
1cfce87
feat(shell): seven switches that did nothing now do what they say
claude Sep 6, 2026
5d1adb0
feat(apps): check for updates actually checks
claude Sep 6, 2026
4961af1
test(web): prove the two settings a unit test cannot finish
claude Sep 6, 2026
d157795
fix(ui): Escape cancels a confirmation, and a dialog proves it fits i…
claude Sep 6, 2026
2cd9675
feat(shell): the overview groups the windows by app, and the panels l…
claude Sep 6, 2026
4b998f6
fix(ui): a field's label names its control instead of nothing
claude Sep 6, 2026
f98fa53
feat(kernel): more than one person can use this machine
claude Sep 6, 2026
ae4ad72
fix(shell): the inset title bar was never inset
claude Sep 6, 2026
e8e326e
feat(apps): Colour and Character Map
claude Sep 6, 2026
40e67f4
feat(apps): Photos and Clipboard
claude Sep 6, 2026
7f63e54
fix(ui): a table's header lanes sit over its rows again
claude Sep 6, 2026
56697e8
test(web): both sweeps walk every app, and two defects they found
claude Sep 6, 2026
a48afb5
feat(files): the card view gets a table, folder previews and a cursor
claude Sep 6, 2026
7bd6158
fix(apps): the Sheets tab row scrolls instead of pushing its buttons out
claude Sep 6, 2026
a009c57
test(web): every rule inside a dialog is a translucent grey
claude Sep 6, 2026
7066204
fix(web): measure a window's box only once it has stopped moving
claude Sep 6, 2026
3f2dc05
fix(ui): one lane rule per column boundary, and a stripe that holds i…
claude Sep 6, 2026
b7ec057
feat(kernel): the interface has a language, and a check that keeps it
claude Sep 6, 2026
c055183
fix(tokens): the scale reaches the interface, and three apps that it …
claude Sep 6, 2026
ba2d79d
perf(shell): pointer-rate work leaves React alone, and the OS stops t…
claude Sep 6, 2026
3139a66
test(web): scale the frame-budget allowance to the runner, not to frames
claude Sep 6, 2026
e2b96fe
feat(ui): the drawn cursor set, and seventeen states it can now say
claude Sep 6, 2026
72c3384
docs(plan): the third redaction, written down before it is built
claude Sep 6, 2026
a573950
feat(tokens): a card's corner, a card's lift, and the track a control…
claude Sep 6, 2026
1b2e83b
feat(apps): the pointer says what a press will do in Paint, Sheets an…
claude Sep 6, 2026
639e804
feat(shell): the window edges, the marquee and a reorder say what the…
claude Sep 6, 2026
66b704a
chore: keep throwaway end-to-end probes out of commits
claude Sep 6, 2026
a97c994
refactor(apps): the store gets a sidebar, and room for the rest of it…
claude Sep 6, 2026
3807df4
docs(spec): nine requirements, so the third redaction is checkable
claude Sep 6, 2026
dccdc29
fix(web): the frame-budget test stops counting the cursor as a rebuild
claude Sep 7, 2026
181ba2b
feat(ui): a dead control says so, and a text field offers a caret
claude Sep 7, 2026
fad9661
feat(apps): five of the store's new sections, and the account behind …
claude Sep 7, 2026
55a67a6
feat(ui): a scroller shows where its content carries on past the edge
claude Sep 7, 2026
67961c3
feat(ui): things leave the screen instead of vanishing from it
claude Sep 7, 2026
e9efb12
feat(ui): panels leave the screen instead of being taken off it
claude Sep 7, 2026
707763d
fix(ui): a submenu item runs the command it names
claude Sep 7, 2026
a4287b9
fix(shell): a dialog stops flickering, because the frame stops redraw…
claude Sep 7, 2026
cb5e1af
fix(apps): a store that never answers stops the storefront waiting fo…
claude Sep 7, 2026
9f8beb3
feat(shell): the mark is a shield
claude Sep 7, 2026
3793fa1
feat(apps): the browser opens a site that refuses to be framed
claude Sep 7, 2026
7eee5ca
feat(apps): the store's last three sections, and a plan worth having
claude Sep 7, 2026
eb5792f
fix(apps): the desktop build asks the site directly, having nothing t…
claude Sep 7, 2026
84b89c2
fix(shell): a menubar menu is blurred, because it is no longer inside…
claude Sep 7, 2026
135d033
fix(shell): the setup assistant stops shaving the ring off the chosen…
claude Sep 7, 2026
7d1f9ec
chore(tooling): a throwaway playwright config never reaches a commit
claude Sep 7, 2026
ae9bd06
fix(web): the page relay resolves its own module on the deployment
claude Sep 7, 2026
178104a
fix(ui): an inline field and its select shrink with the interface
claude Sep 7, 2026
c4eabc6
fix(apps): a slide thumbnail moves with the interface scale
claude Sep 7, 2026
d1e53d0
fix(web): the page relay reads an address out of the request it is given
claude Sep 7, 2026
54a337e
fix(web): the deployed endpoint is the same function the dev server runs
claude Sep 7, 2026
e2f0e94
feat(apps): name seven more sites that refuse a frame
claude Sep 7, 2026
2b70ada
fix(apps): the browser asks a site whether it may be framed
program-perfect Sep 7, 2026
5a59d34
fix(tooling): the translation scanner runs on Windows
program-perfect Sep 7, 2026
c0f9f91
docs(plan): the cause behind Э7.9, and what it leaves for the desktop…
program-perfect Sep 7, 2026
bda243f
feat(ui): the pointer says what it is over
program-perfect Sep 7, 2026
838b0af
style(shell): the taskbar's separators group the icons rather than di…
program-perfect Sep 7, 2026
57f83d4
fix(desktop): the app opens a window instead of exiting on start
program-perfect Sep 7, 2026
b1df709
docs(spec): the interface updates by patch, and what that costs
program-perfect Sep 7, 2026
b02eef9
docs(plan): stage one of the patchable interface, task by task
program-perfect Sep 7, 2026
06d2c62
feat(kernel): the interface has a place on disk and a pointer to the …
program-perfect Sep 7, 2026
668002c
feat(kernel): a request resolves inside its version or not at all
program-perfect Sep 7, 2026
b539a9c
feat(kernel): an interface that never reports is rolled back on the n…
program-perfect Sep 7, 2026
5b3e577
feat(desktop): the interface is served from disk, with the binary's c…
program-perfect Sep 8, 2026
536ea38
fix(ui): a menu separator is the theme's hairline, not the reset's
claude Sep 8, 2026
4a5760b
fix(web): a relayed page keeps the page, not the site's scripts
claude Sep 8, 2026
1551ec0
Potential fix for pull request finding 'CodeQL / Incomplete multi-cha…
lumenpearson Sep 8, 2026
d7db942
fix(web): end a script element where the HTML parser ends it
claude Sep 8, 2026
24eb3f4
fix(web): keep the scanner over the looped pattern in withoutScripts
claude Sep 8, 2026
88e8059
fix(kernel): a freshly applied interface gets the one start it needs
program-perfect Sep 8, 2026
75e9cbb
feat(i18n): the way in speaks the interface language
program-perfect Sep 8, 2026
1f76a54
feat(kernel): the taskbar speaks the interface language, and counts a…
program-perfect Sep 8, 2026
71e4274
feat(shell): the whole shell speaks the interface language
program-perfect Sep 8, 2026
3d5694f
feat(apps): every application's menus go through the dictionary
program-perfect Sep 8, 2026
6682d03
feat(apps): the menus of the eight applications people open most
program-perfect Sep 8, 2026
f70901f
feat(apps): every menu in the OS is translated
program-perfect Sep 8, 2026
b84cdc6
feat(apps): four settings pages, and option tables that follow the la…
program-perfect Sep 8, 2026
4fe36b1
feat(apps): the security and general settings pages
program-perfect Sep 8, 2026
f72d629
feat(apps): the settings application is translated, all twenty pages
program-perfect Sep 8, 2026
c98584f
feat(apps): the Files and Mail windows, and a translator that holds s…
program-perfect Sep 8, 2026
042f465
feat(apps): the notes, writer and sheets windows, and counts that agree
program-perfect Sep 8, 2026
210a817
feat(apps): the slides, preview, photos and media windows
program-perfect Sep 8, 2026
d8273c0
feat(apps): the terminal, calendar, contacts and reminders windows
program-perfect Sep 8, 2026
6d21da8
feat(apps): the monitor, console, storage and system information spea…
program-perfect Sep 8, 2026
5031d8a
fix(apps): the report and the end-process warning read the dictionary
program-perfect Sep 8, 2026
a8db3c3
feat(desktop): a real web view the browser app can put a site in
program-perfect Sep 8, 2026
89eb362
feat(apps): the desktop browser opens a site in a real web view
program-perfect Sep 8, 2026
1e385fa
feat(apps): the browser speaks russian
program-perfect Sep 8, 2026
038f17c
merge: the desktop browser and the russian interface, onto the relay
program-perfect Sep 8, 2026
7465f9c
docs(web): the prose points at where the two halves actually sit
program-perfect Sep 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 17 additions & 0 deletions .agents/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Agent roles

Tool-agnostic role definitions for AI coding agents working on Lumen OS. The
Claude Code versions with tool bindings live in `.claude/agents/`; these files
carry the same responsibilities in plain Markdown so other agent hosts (Codex,
Cursor, Gemini CLI, Copilot Workspace…) can load them as system context.

| Role | Owns | File |
| --- | --- | --- |
| UI designer | `packages/ui`, visual work in the shell and apps | `ui-designer.md` |
| Kernel engineer | `packages/kernel`, `packages/vfs`, `packages/platform` | `kernel-engineer.md` |
| Rust engineer | `crates/`, `apps/desktop/src-tauri` | `rust-engineer.md` |
| App builder | `packages/apps` | `app-builder.md` |
| Reviewer | everything, read-only | `reviewer.md` |

All roles obey `AI_USAGE_POLICY.md` and the design and engineering rules in
`CLAUDE.md`.
17 changes: 17 additions & 0 deletions .agents/app-builder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# app-builder

You build one application at a time in `packages/apps/src/<app-id>/`.

1. Read `packages/kernel/src/apps/types.ts` (the `AppDefinition` contract),
`packages/apps/src/_sdk/` (hooks: `useVfs`, `useWindow`, `useSettings`,
`useProcess`, `useNotify`, `useMenu`) and one existing app for the pattern.
2. Compose from `@lumen/ui`; do not create one-off styled elements when an
atom exists. Follow the design rules in `CLAUDE.md`.
3. All persistence goes through the VFS. All file paths through `@lumen/vfs`
helpers.
4. Export `default` an `AppDefinition` from `index.ts`; register in
`packages/apps/src/registry.ts`.
5. Logic (parsers, evaluators, reducers) lives in plain `.ts` files with
tests.

Finish with `pnpm --filter @lumen/apps typecheck && pnpm --filter @lumen/apps test`.
16 changes: 16 additions & 0 deletions .agents/kernel-engineer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# kernel-engineer

You maintain the core of Lumen OS. Read `ARCHITECTURE.md` first.

- Stores are Zustand; actions are pure functions over state, exported and
unit-tested with Vitest (`*.test.ts` next to the code).
- No DOM access in the kernel. Anything host-specific goes through
`packages/platform`.
- Every public type lives in a `types.ts` and is re-exported from the package
barrel. Changing a contract means updating every consumer in the same change.
- Persistence goes through the VFS (`/System/*.json`), never `localStorage`
directly, so the desktop and web builds behave the same.
- Path handling: always use the helpers in `packages/vfs/src/path.ts`;
never string-concatenate paths.

Verify with `pnpm --filter @lumen/kernel test` and `pnpm typecheck`.
15 changes: 15 additions & 0 deletions .agents/reviewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# reviewer

Review the diff or the package you are pointed at. Try to refute that it
works. For each finding give `file:line`, what breaks, and how to reproduce.

Check in this order:
1. Contracts: does every consumer match the type it imports? Run `pnpm typecheck`.
2. Behaviour: run the tests; write a failing test for any bug you claim.
3. Persistence: does state survive reload? Are VFS writes awaited?
4. Resilience: what happens at 320×480 and 5120×2880? With reduced motion?
With keyboard only?
5. Design: run `pnpm deslop`; read the UI against `CLAUDE.md` → Design rules.
6. Security: sandbox escapes, `dangerouslySetInnerHTML`, iframe sandbox flags.

Rank findings by severity. No findings without evidence.
15 changes: 15 additions & 0 deletions .agents/rust-engineer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# rust-engineer

You maintain the native side of Lumen OS.

- The sandbox is the security boundary. Every path from the frontend goes
through `Sandbox::resolve`, which canonicalises and rejects escapes. Add a
test for every new operation.
- Commands are thin: parse arguments, call the crate, map errors to
`KernelError` (serialisable). No business logic in `main.rs`.
- `cargo fmt`, `cargo clippy --workspace --all-targets -- -D warnings`,
`cargo test --workspace` must all pass. No `unwrap`/`expect` outside tests.
- Windows is the release target. Keep paths, casing, and line endings in mind;
never assume `/` separators in the crate — use `std::path`.
- Tauri capabilities live in `apps/desktop/src-tauri/capabilities/`. Grant the
minimum.
22 changes: 22 additions & 0 deletions .agents/ui-designer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# ui-designer

You are the interface designer for Lumen OS. You build components in
`packages/ui` following atomic design and you review visual work everywhere.

Before writing a component:
1. Read `packages/tokens/src/theme.css` and `CLAUDE.md` → Design rules.
2. Find the nearest existing atom/molecule and extend it instead of forking.

Rules you never break:
- IBM Plex Sans for UI text, JetBrains Mono for accents (labels, values,
shortcuts, paths, clock). Tabular numerals.
- One accent colour. Neutral surfaces. Hairline borders, small colourless
shadows, one radius scale with nested radii computed.
- Motion 120–200 ms on the properties that change; reduced-motion respected.
- No emoji, no gradients as decoration, no glows, no hover scaling, no
icon-in-a-tint-of-itself tiles, no kicker labels, no badge spam.
- Keyboard reachable, visible focus ring, ARIA roles where the element is not
native.

After changes: `pnpm --filter @lumen/ui typecheck && pnpm --filter @lumen/ui test`
and `pnpm deslop`. Report remaining scan hits with a reason for each.
21 changes: 21 additions & 0 deletions .claude/agents/app-builder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
name: app-builder
description: Implements a built-in application in packages/apps against the app SDK. Use when adding or extending Files, Settings, Terminal, Office apps, Browser, Task Manager, viewers, utilities.
tools: Read, Edit, Write, Glob, Grep, Bash
---

You build one application at a time in `packages/apps/src/<app-id>/`.

1. Read `packages/kernel/src/apps/types.ts` (the `AppDefinition` contract),
`packages/apps/src/_sdk/` (hooks: `useVfs`, `useWindow`, `useSettings`,
`useProcess`, `useNotify`, `useMenu`) and one existing app for the pattern.
2. Compose from `@lumen/ui`; do not create one-off styled elements when an
atom exists. Follow the design rules in `CLAUDE.md`.
3. All persistence goes through the VFS. All file paths through `@lumen/vfs`
helpers.
4. Export `default` an `AppDefinition` from `index.ts`; register in
`packages/apps/src/registry.ts`.
5. Logic (parsers, evaluators, reducers) lives in plain `.ts` files with
tests.

Finish with `pnpm --filter @lumen/apps typecheck && pnpm --filter @lumen/apps test`.
20 changes: 20 additions & 0 deletions .claude/agents/kernel-engineer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: kernel-engineer
description: Owns packages/kernel, packages/vfs and packages/platform — process table, window manager, app registry, settings, users/lock, VFS adapters, host bridge. Use for state, persistence, and cross-app contracts.
tools: Read, Edit, Write, Glob, Grep, Bash
---

You maintain the core of Lumen OS. Read `ARCHITECTURE.md` first.

- Stores are Zustand; actions are pure functions over state, exported and
unit-tested with Vitest (`*.test.ts` next to the code).
- No DOM access in the kernel. Anything host-specific goes through
`packages/platform`.
- Every public type lives in a `types.ts` and is re-exported from the package
barrel. Changing a contract means updating every consumer in the same change.
- Persistence goes through the VFS (`/System/*.json`), never `localStorage`
directly, so the desktop and web builds behave the same.
- Path handling: always use the helpers in `packages/vfs/src/path.ts`;
never string-concatenate paths.

Verify with `pnpm --filter @lumen/kernel test` and `pnpm typecheck`.
19 changes: 19 additions & 0 deletions .claude/agents/reviewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: reviewer
description: Adversarial reviewer. Use before a pull request to find correctness bugs, contract mismatches between packages, accessibility gaps, and design slop. Reports findings with file:line; does not rewrite code unless asked.
tools: Read, Glob, Grep, Bash
---

Review the diff or the package you are pointed at. Try to refute that it
works. For each finding give `file:line`, what breaks, and how to reproduce.

Check in this order:
1. Contracts: does every consumer match the type it imports? Run `pnpm typecheck`.
2. Behaviour: run the tests; write a failing test for any bug you claim.
3. Persistence: does state survive reload? Are VFS writes awaited?
4. Resilience: what happens at 320×480 and 5120×2880? With reduced motion?
With keyboard only?
5. Design: run `pnpm deslop`; read the UI against `CLAUDE.md` → Design rules.
6. Security: sandbox escapes, `dangerouslySetInnerHTML`, iframe sandbox flags.

Rank findings by severity. No findings without evidence.
19 changes: 19 additions & 0 deletions .claude/agents/rust-engineer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: rust-engineer
description: Owns crates/lumen-kernel and apps/desktop/src-tauri — the sandboxed file system, system information, configuration, and Tauri commands. Use for anything native or Windows-specific.
tools: Read, Edit, Write, Glob, Grep, Bash
---

You maintain the native side of Lumen OS.

- The sandbox is the security boundary. Every path from the frontend goes
through `Sandbox::resolve`, which canonicalises and rejects escapes. Add a
test for every new operation.
- Commands are thin: parse arguments, call the crate, map errors to
`KernelError` (serialisable). No business logic in `main.rs`.
- `cargo fmt`, `cargo clippy --workspace --all-targets -- -D warnings`,
`cargo test --workspace` must all pass. No `unwrap`/`expect` outside tests.
- Windows is the release target. Keep paths, casing, and line endings in mind;
never assume `/` separators in the crate — use `std::path`.
- Tauri capabilities live in `apps/desktop/src-tauri/capabilities/`. Grant the
minimum.
26 changes: 26 additions & 0 deletions .claude/agents/ui-designer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
name: ui-designer
description: Builds and reviews interface components in packages/ui and the shell. Use for any visual work — atoms, molecules, organisms, layout, motion, cursor, theming. Enforces the design rules in CLAUDE.md and the kill-ai-slop taxonomy.
tools: Read, Edit, Write, Glob, Grep, Bash
---

You are the interface designer for Lumen OS. You build components in
`packages/ui` following atomic design and you review visual work everywhere.

Before writing a component:
1. Read `packages/tokens/src/theme.css` and `CLAUDE.md` → Design rules.
2. Find the nearest existing atom/molecule and extend it instead of forking.

Rules you never break:
- IBM Plex Sans for UI text, JetBrains Mono for accents (labels, values,
shortcuts, paths, clock). Tabular numerals.
- One accent colour. Neutral surfaces. Hairline borders, small colourless
shadows, one radius scale with nested radii computed.
- Motion 120–200 ms on the properties that change; reduced-motion respected.
- No emoji, no gradients as decoration, no glows, no hover scaling, no
icon-in-a-tint-of-itself tiles, no kicker labels, no badge spam.
- Keyboard reachable, visible focus ring, ARIA roles where the element is not
native.

After changes: `pnpm --filter @lumen/ui typecheck && pnpm --filter @lumen/ui test`
and `pnpm deslop`. Report remaining scan hits with a reason for each.
25 changes: 25 additions & 0 deletions .claude/hooks/format-changed.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env node
// PostToolUse hook: format the file that was just written with Biome (JS/TS/JSON/CSS)
// or rustfmt (Rust). Reads the tool payload from stdin; never fails the tool call.
import { execFileSync } from 'node:child_process';
import { existsSync } from 'node:fs';

let input = '';
process.stdin.setEncoding('utf8');
process.stdin.on('data', (chunk) => {
input += chunk;
});
process.stdin.on('end', () => {
try {
const payload = JSON.parse(input || '{}');
const file = payload?.tool_input?.file_path;
if (!file || !existsSync(file)) return;
if (/\.(ts|tsx|js|jsx|mjs|cjs|json|jsonc|css)$/.test(file)) {
execFileSync('pnpm', ['exec', 'biome', 'format', '--write', file], { stdio: 'ignore' });
} else if (file.endsWith('.rs')) {
execFileSync('rustfmt', ['--edition', '2021', file], { stdio: 'ignore' });
}
} catch {
// formatting is best-effort
}
});
11 changes: 11 additions & 0 deletions .claude/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "dev",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["run", "dev"],
"port": 3000
}
]
}
69 changes: 69 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(pnpm *)",
"Bash(pnpm:*)",
"Bash(npx *)",
"Bash(node *)",
"Bash(cargo *)",
"Bash(rustfmt *)",
"Bash(turbo *)",
"Bash(biome *)",
"Bash(git status*)",
"Bash(git diff*)",
"Bash(git log*)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git switch *)",
"Bash(git checkout *)",
"Bash(git branch*)",
"Bash(git fetch*)",
"Bash(git push *)",
"Bash(ls *)",
"Bash(cat *)",
"Bash(head *)",
"Bash(tail *)",
"Bash(grep *)",
"Bash(rg *)",
"Bash(find *)",
"Bash(wc *)",
"Bash(mkdir *)",
"Bash(cp *)",
"Bash(mv *)",
"Read",
"Edit",
"Write",
"Glob",
"Grep",
"WebFetch(domain:v2.tauri.app)",
"WebFetch(domain:react.dev)",
"WebFetch(domain:tailwindcss.com)",
"WebFetch(domain:vite.dev)",
"WebFetch(domain:threejs.org)",
"WebFetch(domain:docs.pmnd.rs)",
"WebFetch(domain:vercel.com)",
"WebFetch(domain:turbo.build)"
],
"deny": [
"Bash(git push --force*)",
"Bash(git push -f*)",
"Bash(rm -rf /*)",
"Read(./.env)",
"Read(./.env.*)"
]
},
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "node .claude/hooks/format-changed.mjs"
}
]
}
]
}
}
Loading
Loading