austere-axi 0.7.1 → 0.8.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/README.md CHANGED
@@ -18,6 +18,8 @@ Review pages for coding agents.
18
18
 
19
19
  <sub>The real loop, about 30 s: [MP4](docs/demo.mp4) · [WebM](docs/demo.webm).</sub>
20
20
 
21
+ **[Website](https://mandalorianbatman.github.io/austere-axi/)** · **[Playground](https://mandalorianbatman.github.io/austere-axi/play/)** (no install) · **[Gallery](https://mandalorianbatman.github.io/austere-axi/gallery/)** · **[Benchmark](docs/benchmark.md)** · **[Writing a pack](docs/writing-a-pack.md)**
22
+
21
23
  ```
22
24
  root = Stack([intro, flow, options, decide], "column", "l")
23
25
  intro = Card([CardHeader("Session storage migration", "Redis → Postgres"), introText])
@@ -39,6 +41,18 @@ A full page (KPIs, diagram, table, chart, diff, decision form) is about 1,000 to
39
41
 
40
42
  **See it without installing:** the [gallery](https://mandalorianbatman.github.io/austere-axi/gallery/) shows example pages next to their source and token counts. The [playground](https://mandalorianbatman.github.io/austere-axi/play/) lets you edit OpenUI Lang and see the page live.
41
43
 
44
+ ## Quick start
45
+
46
+ Needs Node.js 22.18 or later. Your agent runs:
47
+
48
+ ```sh
49
+ npx -y austere-axi spec # component reference (read once per session)
50
+ npx -y austere-axi plan.html # validate and open the page for review
51
+ npx -y austere-axi poll plan.html # wait until the reviewer presses Send
52
+ ```
53
+
54
+ `--help` prints the file skeleton and the loop (about 900 tokens); `help all` adds the rarer commands and the environment. The agent does not look at the page itself: the reviewer judges how it looks, and render failures come back through `poll`. To have agents reach for it on their own, use the [skill, plugin or MCP server](#install).
55
+
42
56
  ## Why
43
57
 
44
58
  Same loop as [lavish-axi](https://github.com/kunchenguid/lavish-axi). The difference: the agent never writes HTML, CSS or layout.
@@ -99,10 +113,11 @@ In a session: `/plugin marketplace add MandalorianBatman/austere-axi`, then `/pl
99
113
 
100
114
  ### MCP
101
115
 
102
- `austere-axi mcp` is an MCP server on stdio. Tools: `spec`, `check`, `open`, `poll`, `reply`, `patch`, `end`. Each one runs the CLI command of the same name, so the loop is the same as on the command line.
116
+ `austere-axi mcp` is an MCP server on stdio. Tools: `spec`, `check`, `open`, `poll`, `reply`, `patch`, `end`, `components`. Each one runs the CLI command of the same name, so the loop is the same as on the command line.
103
117
 
104
118
  - `poll` returns `status: timeout` after 50 s by default, because many clients cancel longer calls. The agent polls again; nothing is lost. `timeout_ms: 0` waits until feedback arrives.
105
119
  - `poll` and `reply` take the `cursor` a poll returned, like `--cursor`.
120
+ - `components` takes `command` (`search`, `show`, `list` or `add`) and `args`; `show` also takes `pack`, like `--pack`. `add` takes only an npm package name, never a folder or `.tgz`, and has no `trust`: a third-party pack the user has not trusted is refused, and the agent asks the user to install it.
106
121
  - Pass absolute file paths. The server resolves relative paths against its own working directory, which depends on the client.
107
122
  - No screen? Set `AUSTERE_AXI_NO_OPEN=1` in the server's `env` so `open` prints the link instead. Other [environment variables](#environment) work the same way.
108
123
 
@@ -127,16 +142,6 @@ command = "npx"
127
142
  args = ["-y", "austere-axi", "mcp"]
128
143
  ```
129
144
 
130
- ## Quick start
131
-
132
- ```sh
133
- npx -y austere-axi spec # component reference (read once per session)
134
- npx -y austere-axi plan.html # validate and open the page for review
135
- npx -y austere-axi poll plan.html # wait until the reviewer presses Send
136
- ```
137
-
138
- `--help` prints the file skeleton and the loop (about 900 tokens); `help all` adds the rarer commands and the environment. The agent does not look at the page itself: the reviewer judges how it looks, and render failures come back through `poll`.
139
-
140
145
  ## How it works
141
146
 
142
147
  ```
@@ -149,8 +154,8 @@ agent patches changes ◄── austere-axi poll plan.html ◄─┘ (long-pol
149
154
  ```
150
155
 
151
156
  - **A page is a plain `.html` file:** one runtime `<script>` tag and one `<script type="text/openui">` block. Opened directly, it loads the runtime from the CDN. Under review, the server serves a local copy.
152
- - **Components:** 58 stock OpenUI components, plus `Architecture` (`Node`, `Edge`, `Group`), `Diff` and `FileTree`. `Mermaid` and nine shadcn-style components come as bundled [packs](#components-and-packs).
153
- - **Diagrams lay out automatically** ([dagre](https://github.com/dagrejs/dagre)); the agent never writes coordinates. Every node and edge is a click target. `lanes` puts each group in a column; `tone` colors a box or line to show risk. Use Mermaid for sequences, state machines, ER and gantt.
157
+ - **Components:** 58 stock OpenUI components, plus `Architecture` (`Node`, `Edge`, `Group`), `Diff` and `FileTree`. Nine shadcn-style components come as a bundled [pack](#components-and-packs).
158
+ - **Diagrams lay out automatically** ([dagre](https://github.com/dagrejs/dagre)); the agent never writes coordinates. Every node and edge is a click target. `lanes` puts each group in a column; `tone` colors a box or line to show risk.
154
159
  - **Notes** attach to the smallest named statement under the click, with detail where it exists: table row and column, `file:+line` in a diff, a diagram node, or selected text. The reviewer can move a note to a parent section.
155
160
  - **Changes flash** after each agent turn, and the bar shows `N changed`. Click it to keep the last turn's changes outlined until you click again.
156
161
  - **Buttons and forms send feedback.** `@ToAssistant("…")` sends a message with the form values. A button with no action sends its label.
@@ -174,6 +179,8 @@ austere-axi check <file> validate the program (no browser) [--fix] [-
174
179
  austere-axi patch <file> merge statements from stdin into the program (reports dropped unreferenced ones)
175
180
  austere-axi spec [group|pack...] component reference (~5.8k tokens; groups narrow it)
176
181
  austere-axi components ... list | search | show | add | remove | new | build
182
+ austere-axi trust list|add|remove packs your agent may add without --trust (see Trust)
183
+ austere-axi registry list|add|remove private npm registries for scopes (see Private registries)
177
184
  austere-axi export <file> one self-contained HTML file, works offline
178
185
  austere-axi hub on|off|status|list|notes|open home page with every page and note
179
186
  austere-axi share <file> --as "<name>" invite link for a teammate on your tailnet [--auto]
@@ -193,9 +200,10 @@ Output is compact YAML for agents. Each `poll` item has its statement and that s
193
200
  - **End is soft:** ending a review (the agent's `end`, or **End review** in the page) means the agent stopped. The reviewer can still send notes. The next `poll` returns every unacknowledged note, including ones sent before the end or released from hold after it, and reopens the review. A batch the reviewer sent together with end stays final.
194
201
  - **Close is hard:** only the owner's **close** (`close <file>`, or **Close review** in the page) locks the composer. `reopen <file>` or **Reopen review** unlocks it.
195
202
  - A review the user ended or closed opens again only with `--reopen`.
203
+ - An `Image` src that is a path relative to the page (png, jpg, gif, webp, svg, avif) loads under review for the owner and for invited reviewers, and `export` inlines it as a data URI. Both read only regular files in the page's own folder, never dotfiles or links that leave it; `export` skips an image over 10 MB. A file `export` cannot read stays as written, and the output names it in `notices`.
196
204
  - **Tabs closed:** `poll` returns `browser_disconnected` 10 s after the last review tab closes, or 5 min after a dropped connection (for example, a locked phone). The review stays open, so later notes reach the next `poll`.
197
205
  - `feedback <file>` returns notes no agent has answered, from any day. Reading them acknowledges them; `reply` marks them answered.
198
- - **Render failures reach the agent without a click:** bad Mermaid syntax, an unknown component or a component that throws. The owner's open review page sends them as a note from "Render check", once per page revision, and `poll` returns them as `render_error` items. With no review tab open, nothing renders, so nothing is sent. `check --render <file>` renders the page in headless Chrome (an installed Chrome, Chromium or Edge, or `CHROME_PATH`) at 1280 and 390 px and prints render errors and the statements that make the page scroll sideways, as text, with no screenshot. Agents run it only when the user asks for a check.
206
+ - **Render failures reach the agent without a click:** an unknown component or a component that throws. The owner's open review page sends them as a note from "Render check", once per page revision, and `poll` returns them as `render_error` items. With no review tab open, nothing renders, so nothing is sent. `check --render <file>` renders the page in headless Chrome (an installed Chrome, Chromium or Edge, or `CHROME_PATH`) at 1280 and 390 px, opens each tab in turn, and prints render errors and the statements that make the page scroll sideways, as text, with no screenshot. Agents run it only when the user asks for a check.
199
207
 
200
208
  ## Components and packs
201
209
 
@@ -203,8 +211,9 @@ Output is compact YAML for agents. Each `poll` item has its statement and that s
203
211
 
204
212
  ```sh
205
213
  austere-axi components # every component, by group
206
- austere-axi components search scatter # search by name, group, description
214
+ austere-axi components search scatter # search by name, group, description; also packs on npm
207
215
  austere-axi components show AreaChart # signature, notes, example
216
+ austere-axi components show Milestones --pack austere-pack-orbit # one pack's, when several share the name
208
217
  ```
209
218
 
210
219
  **Packs** add components. A pack is an npm package with `dist/pack.js` (the components, a few KB) and `dist/catalog.json` (signatures, examples, schema).
@@ -214,6 +223,8 @@ austere-axi components add austere-pack-gantt --trust # npm name, folder, or .
214
223
  austere-axi check --fix plan.html # adds the pack tag to the page
215
224
  ```
216
225
 
226
+ `components search` and `components show` also cover packs on npm that are not installed, meaning any package with the keyword `austere-axi-pack`. Search lists up to 8 core and installed components under `results`, then up to 3 from packs on npm under `npm`, so a pack on npm never pushes a core component out. A result names its pack, says `not installed`, and says whether the pack is first-party, `trusted` (on your trust list) or third-party; `show` cuts such a component's description, example and notes short. `show <Name>` returns the first component by that name, core and installed packs first; `--pack <pack>` looks only in that pack, and search names it for an npm result whose name another result or a local component shares. The CLI reads the pack's catalog from its tarball, checked against the registry's integrity hash, and runs none of its code. It caches the pack list for an hour, under `~/.austere-axi/npm-packs/`. It caches each pack version for good once it is read, fails the install checks, or the registry answers 404 or 410 for it; any other failure is tried again on the next search. For a third-party pack, the agent is told to ask you to review it and run `components add <pack> --trust`. With the registry unreachable, search shows local results, says so, and tries the registry again after 5 minutes. A pack the registry fails to serve is left out, and search says how many were.
227
+
217
228
  A page names its packs in the head, so it renders anywhere:
218
229
 
219
230
  ```html
@@ -223,7 +234,6 @@ A page names its packs in the head, so it renders anywhere:
223
234
  - Under review, the server serves an installed pack only while it matches its hash in `~/.austere-axi/packs.json`. Opened directly, the page loads packs from jsDelivr with Subresource Integrity. `export` inlines them.
224
235
  - A pack component with no pack tag is a `missing-pack` error. `check --fix` repairs it.
225
236
  - **Bundled packs** need no tag and load only when used:
226
- - `Mermaid`.
227
237
  - `shadcn`: `Progress`, `Avatar`, `AvatarGroup`, `Tooltip`, `HoverCard`, `Breadcrumb` (`BreadcrumbItem`), `Kbd`, `Skeleton`, `Calendar` and `Timeline` (`TimelineItem`). Read-only.
228
238
  ```
229
239
  rollout = Progress(64, "Rows migrated")
@@ -232,6 +242,38 @@ A page names its packs in the head, so it renders anywhere:
232
242
 
233
243
  **Trust.** Pack code runs inside your review pages, where notes and button presses also come from. Packs under `@austere-axi/` on npm install directly. Other npm packs and any `.tgz` need `--trust`, so read them first. A local folder counts as your own. A page with third-party packs shows a warning, and `poll` tells the agent.
234
244
 
245
+ Your trust list, `~/.austere-axi/trusted.json`, names npm packs your agent may install without `--trust`:
246
+
247
+ ```sh
248
+ austere-axi trust add austere-pack-gantt@1.2.0 # pins that version and the hash of its pack.js
249
+ austere-axi trust add @acme # every pack in a scope on the current registry, e.g. your company's
250
+ austere-axi trust list
251
+ austere-axi trust remove @acme
252
+ ```
253
+
254
+ - A pin trusts one exact version with the same `pack.js`. A later publish, or the same version with other code, still needs `--trust`. `components add <pack>` with no version installs the pinned one.
255
+ - A scope is bound to the registry it was added from: its private registry when the scope is mapped to one (see Private registries), else the default (`AUSTERE_AXI_NPM_REGISTRY`, else `npm_config_registry`, else npmjs). Pointed at another registry, packs in that scope are third-party again, since anyone may own the same scope name there.
256
+ - Search marks packs on the list `trusted` and tells the agent it may add them.
257
+ - `trust add` asks you to confirm at a terminal and refuses when stdin is not one, which is how agents run commands. That stops an agent adding a search hit to the list by accident. It does not stop an agent set on editing the file.
258
+ - Only this file in your home folder counts. A project cannot ship its own list.
259
+ - If the file is unreadable, search counts every npm pack third-party and says so, and `trust` refuses until you fix or delete it. `components add` refuses only the installs the list would decide: a third-party npm pack without `--trust`. First-party packs, local folders and `--trust` installs are unaffected.
260
+
261
+ **Private registries.** Packs your team publishes to Verdaccio, Artifactory or GitHub Packages are found and installed once you map their npm scope to that registry, in `~/.austere-axi/registries.json`:
262
+
263
+ ```sh
264
+ austere-axi registry add @acme https://npm.acme.dev/ --token-env ACME_NPM_TOKEN
265
+ austere-axi registry list
266
+ austere-axi registry remove @acme
267
+ ```
268
+
269
+ - `components search` and `show` query the default registry and each mapped one, with the same `austere-axi-pack` keyword search. A hit from a mapped registry names its host, e.g. `npm @acme/pack-flows@0.3.0 (npm.acme.dev), not installed, third-party`. If one registry does not answer, the others still do and the result says which one was unavailable.
270
+ - `components add @acme/<pack>` installs from @acme's registry. A mapped registry counts only for its own scope: packs it lists under other names are ignored, and the default registry's packs in that scope are left out.
271
+ - `--token-env` names an environment variable that holds a bearer token. The file stores the name, never the token. The token goes only to that registry's own origin, never to the default registry or to a tarball on another host.
272
+ - The URL must be https, or http on localhost. `@austere-axi` cannot be mapped.
273
+ - `registry add` runs only at a terminal, like `trust add`: a mapping decides which host receives the token, so an agent without a terminal is told to ask you. `registry remove` works anywhere.
274
+ - Mapping a scope grants no trust: its packs stay third-party until you trust the scope (`trust add @acme`, which records the mapped registry) or pin a pack.
275
+ - Only this file in your home folder counts. If it is unreadable, search covers the default registry only and says so, while `components add`, `trust add` and `registry` refuse until you fix it.
276
+
235
277
  **Write a pack:** [Writing a pack](docs/writing-a-pack.md) goes from scaffold to `npm publish`, with [austere-pack-gantt](https://github.com/MandalorianBatman/austere-pack-gantt) as the example. Short version:
236
278
 
237
279
  ```sh
@@ -322,7 +364,7 @@ jobs:
322
364
  runs-on: ubuntu-latest
323
365
  steps:
324
366
  - uses: actions/checkout@v7
325
- - uses: MandalorianBatman/austere-axi/action@main # pin a release tag or SHA once you settle
367
+ - uses: MandalorianBatman/austere-axi/action@v0.7.0
326
368
  with:
327
369
  pages: reviews/*.html
328
370
  ```
@@ -361,7 +403,7 @@ Outputs: `ok` (`true` when every page passed) and `artifact-url`.
361
403
  | `AUSTERE_AXI_DISCONNECT_GRACE_MS` | `300000` | how long a dropped connection can stay away before `poll` returns; `0` disables |
362
404
  | `AUSTERE_AXI_IDLE_TIMEOUT_MS` | `1800000` | idle shutdown; `0` disables |
363
405
  | `AUSTERE_AXI_PERSIST` | | `1`: never idle out, as `server --persist` |
364
- | `AUSTERE_AXI_NPM_REGISTRY` | `npm_config_registry`, else npmjs | where `components add` gets packs |
406
+ | `AUSTERE_AXI_NPM_REGISTRY` | `npm_config_registry`, else npmjs | where `components add` gets packs and `components search` finds them, except scopes mapped with `registry add` |
365
407
  | `CHROME_PATH` | an installed Chrome, Chromium or Edge | the browser `check --render` uses |
366
408
 
367
409
  ## Security
@@ -386,7 +428,7 @@ The server binds to loopback, plus the Tailscale IP when Tailscale is up. Never
386
428
 
387
429
  **Page sandbox.** The page runs in a sandboxed iframe with no same-origin access; packs run there too. Page files are also served with `Content-Security-Policy: sandbox`, so a page opened in a popup or its own tab stays sandboxed. In review, the review page opens new-window links only if they are external `http(s):` or `mailto:` links. A popup the frame opens any other way stays sandboxed.
388
430
 
389
- **Packs.** Third-party packs need `--trust`. Installed packs must match their lockfile hash; CDN loads use Subresource Integrity.
431
+ **Packs.** Third-party packs need `--trust` unless your trust list names them. Installed packs must match their lockfile hash; CDN loads use Subresource Integrity.
390
432
 
391
433
  **Telemetry.** OpenUI's Node side has PostHog telemetry; the CLI sets `OPENUI_TELEMETRY_DISABLED=1`. The browser runtime sends none.
392
434
 
@@ -401,7 +443,7 @@ The server binds to loopback, plus the Tailscale IP when Tailscale is up. Never
401
443
 
402
444
  ```sh
403
445
  npm install
404
- npm run build # dist/: runtime, packs, pack kit, Mermaid, spec, catalog, review UI, cli.mjs
446
+ npm run build # dist/: runtime, packs, pack kit, spec, catalog, review UI, cli.mjs
405
447
  npm test
406
448
  npm run typecheck # tsc over src/cli, src/shared and the pack types
407
449
  node dist/cli.mjs examples/session-migration.html
@@ -409,6 +451,10 @@ node dist/cli.mjs examples/session-migration.html
409
451
 
410
452
  Repo layout, website, playground, benchmark, CI and release: [CONTRIBUTING.md](CONTRIBUTING.md).
411
453
 
454
+ ## Contributing
455
+
456
+ Bug reports, examples, docs fixes and packs are welcome; [CONTRIBUTING.md](CONTRIBUTING.md) has setup and the rules. Issues labelled [`good first issue`](https://github.com/MandalorianBatman/austere-axi/labels/good%20first%20issue) are small and have a clear finish line. Security problems: [report privately](https://github.com/MandalorianBatman/austere-axi/security/advisories/new), not in an issue.
457
+
412
458
  ## License
413
459
 
414
460
  MIT. Builds on [OpenUI](https://github.com/thesysdev/openui) (MIT). The review loop design comes from [lavish-axi](https://github.com/kunchenguid/lavish-axi) (MIT).