sign-off-axi 0.3.4 → 0.3.6
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 +7 -3
- package/dist/cli.js +211 -65
- package/dist/contract.js +81 -4
- package/dist/store.js +17 -5
- package/fixtures/contract/README.md +3 -3
- package/fixtures/contract/evidence.v1/invalid-about-missing.json +1 -1
- package/fixtures/contract/evidence.v1/invalid-commit-short.json +1 -1
- package/fixtures/contract/evidence.v1/invalid-detail-unknown.json +1 -1
- package/fixtures/contract/evidence.v1/valid-run.json +1 -1
- package/fixtures/contract/report.v2/invalid-about-missing.json +1 -0
- package/fixtures/contract/report.v2/invalid-filed-not-utc.json +1 -0
- package/fixtures/contract/report.v2/invalid-group-too-long.json +1 -0
- package/fixtures/contract/report.v2/invalid-link-control-character.json +1 -0
- package/fixtures/contract/report.v2/invalid-options-empty.json +1 -0
- package/fixtures/contract/report.v2/invalid-schema-1-text-only.json +1 -0
- package/fixtures/contract/report.v2/invalid-view-missing.json +1 -0
- package/fixtures/contract/report.v2/page/index.html +152 -0
- package/fixtures/contract/report.v2/page/preview.svg +16 -0
- package/fixtures/contract/report.v2/valid-full.json +1 -0
- package/fixtures/contract/report.v2/valid-minimal.json +11 -0
- package/package.json +1 -1
- package/web/index.html +162 -121
- package/web/report-preview.svg +19 -0
- package/web/report.html +154 -0
- package/fixtures/contract/report.v1/invalid-about-missing.json +0 -1
- package/fixtures/contract/report.v1/invalid-filed-not-utc.json +0 -1
- package/fixtures/contract/report.v1/invalid-group-too-long.json +0 -1
- package/fixtures/contract/report.v1/invalid-link-control-character.json +0 -1
- package/fixtures/contract/report.v1/invalid-options-empty.json +0 -1
- package/fixtures/contract/report.v1/valid-full.json +0 -1
- package/fixtures/contract/report.v1/valid-minimal.json +0 -9
package/README.md
CHANGED
|
@@ -128,6 +128,9 @@ sign-off-axi post --type diagram|interactive --title "<question>" --view <path>
|
|
|
128
128
|
ask with a diagram image, or a sandboxed interactive .html page
|
|
129
129
|
sign-off-axi post --type explainer --title "<question>" --media <video> [--about <summary>] [--chapter <m:ss>=<title>]...
|
|
130
130
|
ask with a narrated video the agent made with free local tools
|
|
131
|
+
sign-off-axi report init <folder> write a report page to fill: the answer and a picture, a diagram, steps to tap, the detail folded
|
|
132
|
+
sign-off-axi post --type report --title "<the answer>" --about "<why it matters>" --view <page.html> --preview <picture>
|
|
133
|
+
post that page as a report: a card with its picture that opens full screen; text alone is refused
|
|
131
134
|
sign-off-axi init [dir] [--agent auto|<name>] write the repo setup under <dir>/.sign-off/ (config, board, mocks/ and evidence/ folders)
|
|
132
135
|
and install the skill for each chosen coding agent (auto: each one on PATH)
|
|
133
136
|
sign-off-axi doctor [dir] check that setup and each agent's skill; every failure names its fix
|
|
@@ -145,9 +148,10 @@ sign-off-axi export [--out <file.html>] write a frozen read-only copy o
|
|
|
145
148
|
|
|
146
149
|
- The board is the one you name right after the command (`sign-off-axi answers ./decisions.json`). With none, it is the nearest `.sign-off/` board that `init` set up, found by the walk described in [Test runs never touch your board](#test-runs-never-touch-your-board); otherwise the default board there (`~/.sign-off/decisions.json`, or under `SIGN_OFF_HOME`). Answers are saved next to it.
|
|
147
150
|
- Next-step commands in the output name paths under the working folder relative to it, and say `npx -y sign-off-axi` when sign-off-axi runs through `npx`.
|
|
148
|
-
- `post --type design` asks for a pick between up to 6 mock options, each with an optional `--mock <value>=<path>` file (`.html`, `.svg`, `.png`, `.jpg`, `.jpeg`, `.webp
|
|
151
|
+
- `post --type design` asks for a pick between up to 6 mock options, each with an optional `--mock <value>=<path>` file (`.html`, `.svg`, `.png`, `.jpg`, `.jpeg`, `.webp`, 5 MB or less) shown as a tall phone frame above its button (the recommended one first; on a phone the frames swipe sideways, the next one peeking in, and a tap opens one full size), plus a `--tradeoff` line and a `--recommend` badge. Mock paths are relative to the board file's folder and never escape it. One `.html` page can hold every variant: `--mock a=mocks/<key>/index.html?variant=a` loads the page with `?variant=a`. An `.html` mock or view loads the css, scripts, images and fonts beside it by relative name (`style.css`, `img/dot.png`), from its own folder only, never anything above it. The board adds a small pointing script to each `.html` mock: once the board turns it on for that frame, a tap on a part of the mock is kept from the mock and named back to the board as a path to that element, its tag and its words; it passes only text and gives the mock no reach into the board. With **Comment on the mocks** on, a tap opens a comment on that element: one per element, listed under the mocks with Edit and Delete (words typed but not yet saved stay with their element while the page is open, so tapping another element and back keeps them; a reload drops them), kept on the board and shown, until it is sent, only on the exact mock file it was made on. The comments go to the agent with the next answer on that card (a pick, Other answer or **Another round**, which may then have no note), each with its element, in `wait` and `answers` (`comments`); once sent they are listed as sent and can no longer change. An option with no mock, or whose file is gone, says "No mock for this option". `post --type decision` (the default) is exactly `raise`, and `raise` stays as its alias.
|
|
149
152
|
- `post --type evidence` posts the next numbered update (`update-1`, `update-2`, ...) with 1 to 12 screenshots or recordings (`.png`, `.jpg`, `.jpeg`, `.webp`, `.mp4`, `.webm`, up to 50 MB each), a short note and an optional commit or PR link. The files are copied into `evidence/<number>/` next to the board, so the board is the store: no hosted service. The page shows the updates newest first; each file is served only while its size and SHA-256 still match what was posted, and recordings play inline on a phone. The person gives a verdict, **Pass**, **Fail** or **Needs work**, with an optional note, read back with `answers` or `wait --key update-<number>`.
|
|
150
153
|
- `post --type diagram` and `post --type interactive` show a question with a picture: `--view <path>` names one board-relative file, an image (`.svg`, `.png`, `.jpg`, `.jpeg`, `.webp`) drawn at card width for a diagram, or one self-contained `.html` page that runs in a sandboxed frame for interactive. Every mock and view is served under a Content-Security-Policy with no `fetch`, no remote files and no access to the dashboard or its tab. They answer like a decision.
|
|
154
|
+
- `post --type report` posts an explainer page the user reads, with no answer: something they asked to have explained, or a concept, design or trade-off they must understand. `sign-off-axi report init <folder>` writes the page to fill, one self-contained `.html` file, phone first, light and dark: the answer in one plain sentence with a picture and an as-of line naming the date the facts were true, then a diagram, then steps the reader taps through, then the detail folded. Reports and explainers lists each one as a card with its picture; a tap opens the page over the whole board, on a phone and a desk alike, with **‹ Reports** (or Escape) to go back. A report of text only is refused with the command that makes the page; one stored before reports had pages still loads, folded under **Notes**. Proof that something works is evidence, and a merge or a status note is neither.
|
|
151
155
|
- `post --type explainer` shows a question with a narrated video the agent made itself (stills plus speech from a free local engine such as piper or espeak-ng, joined with ffmpeg; the skill has the recipe). `--media` names one `.mp4` or `.webm`, copied into `evidence/<number>/` and served hash-checked like evidence media; it plays on the card with its own controls, at phone width too. `--about` is a short summary and each `--chapter m:ss=<title>` is a button that plays the video from there. sign-off itself never makes the video: it calls no speech engine, no ffmpeg and no network service.
|
|
152
156
|
- The person can also tap **Another round** inside **Other answer** (with the typed note), which wakes a waiting agent the same way an answer does; the agent reads it back in `answers --json` under `rounds`, with any comments on mock elements it carried.
|
|
153
157
|
- **Dismiss** (the × on an item in a list, **Dismiss** under Needs you first and beside **Skip for now** in Triage, or **Clear all done** on Answered) hides items from the board, Today included; **Undo** in the toast brings them back, and so does **Restore** under **Dismissed (N)** at the end of Needs you first and Triage. `list` counts a dismissed item as neither waiting nor answered, as the board does (`list --full` says `dismissed` for an unanswered one and still its answer for an answered one), and `answers` does not count it as waiting; the agent is not told, so an ask it waits on keeps waiting, and `answers` still returns a dismissed answer. The storage is in [docs/file-formats.md](docs/file-formats.md).
|
|
@@ -161,7 +165,7 @@ sign-off-axi export [--out <file.html>] write a frozen read-only copy o
|
|
|
161
165
|
- `open` is a no-op when the same board is already open on the same address, and fails with `CONFLICT` when it runs on another one. `--evidence-root` is the folder holding `.done-done/`, for decisions that link run evidence.
|
|
162
166
|
- `--filer <id>` on `post` and `raise` saves who filed the item (an agent session id or any 1-128 of `A-Z a-z 0-9 . _ -`; `SIGN_OFF_FILER` sets it for every command, and a post with neither saves `CLAUDE_CODE_SESSION_ID` when it is set). `wait --filer <id>` then returns only answers to that filer's items it has not taken yet (with `--key`, that key's answer even if taken), marks each taken (`decisions.seen.jsonl`) and the card shows **Seen by agent**; it fails with `NOT_FOUND` when none of that filer's items still needs an answer. The page never shows the filer id.
|
|
163
167
|
- `on_answer: <command> [args]` in the `config.yaml` beside the board runs that command for every saved answer, read when the board starts. It runs with no shell, in the board's folder, and gets the answer as one JSON line on stdin (`{"event":"answer","contract":1,"kind","schema","key","answer","label","close","at","note"?,"title"?,"filer"?,"comments"?}`, where `kind` and `schema` are the item's contract kind, or `ask` and 1 for a board-format item, and `comments`, present when the answer carried comments on mock elements, lists each as `id`, `mock`, `hash`, `ref`, `tag`, `words` and `text`); the answer is never put into its arguments, so a typed note cannot inject a command. A failure is logged and never blocks the answer. With no shell, `|`, `>` and `&&` are passed as plain arguments, so put a pipeline in a script and name the script; a relative path such as `./hook.sh` is found from the board's folder. `doctor` checks that the command can run.
|
|
164
|
-
- `post --from <file> --replace --filer <id>` lets several programs feed one board: it replaces only that filer's items (and items with no filer that the file names by key), keeps every other item, the board's other top-level fields and all answers, and an empty items list removes that filer's items.
|
|
168
|
+
- `post --from <file> --replace --filer <id>` lets several programs feed one board: it replaces only that filer's items (and items with no filer that the file names by key), keeps every other item, the board's other top-level fields and all answers, and an empty items list removes that filer's items. A contract message that changed is checked against its kind's rules again, so one that no longer matches is refused with the board left as it was; an answered contract key the feed dropped cannot come back, so post it under a new key (a design, diagram, interactive or explainer item that comes back keeps its answer).
|
|
165
169
|
- `wait` replaces a polling loop. With `--key` it returns at once if that decision is already answered, and waits for a key that is not raised yet; without it, it waits for the next answer to any decision that still needs an answer and fails with `NOT_FOUND` when nothing needs one. It wakes on each save, gives up after `--timeout` seconds (600, ten minutes, by default) with code `TIMEOUT` and exit 1, and takes `--full` and `--json` like `answers`. Ctrl-C stops it without changing anything.
|
|
166
170
|
- `open` records the board's pid, port and address next to the board file (`decisions.board.pid`). `status` and `stop` read it and only act on a pid that really serves that board, so no one has to guess a pid to kill. `open` on a board already served by `serve` records that server, so `stop` can close it too.
|
|
167
171
|
|
|
@@ -215,4 +219,4 @@ tmp=$(mktemp -d)
|
|
|
215
219
|
(cd "$tmp" && SIGN_OFF_HOME="$tmp" sign-off-axi raise --title "Probe?") # lands in $tmp/.sign-off/decisions.json
|
|
216
220
|
```
|
|
217
221
|
|
|
218
|
-
|
|
222
|
+
Proof lives in [`.done-done.yaml`](.done-done.yaml): the `install`, `test` and `skill` journeys re-run every check the CI gate enforces, and CI calls them through `done-done run`.
|