0xray 4.0.12 → 4.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.grok-plugin/plugin.json +1 -1
  2. package/.xray/features.json +1 -1
  3. package/.xray/features.schema.json +1 -1
  4. package/AGENTS-consumer.md +4 -2
  5. package/AGENTS.md +8 -1
  6. package/README.md +1 -1
  7. package/SKILLS.md +1 -1
  8. package/dist/AGENTS.md +8 -1
  9. package/dist/CHANGELOG.md +25 -1
  10. package/dist/README.md +1 -1
  11. package/dist/SKILLS.md +1 -1
  12. package/dist/integrations/cursor/README.md +61 -0
  13. package/dist/integrations/cursor/hooks/after-file-edit.js +38 -0
  14. package/dist/integrations/cursor/hooks/cursor-hook-utils.js +170 -0
  15. package/dist/integrations/cursor/hooks/cursor-usage-receipt.js +298 -0
  16. package/dist/integrations/cursor/hooks/hooks.json +20 -0
  17. package/dist/integrations/cursor/hooks/pre-compact.js +88 -0
  18. package/dist/integrations/cursor/hooks/pre-tool-use.js +105 -0
  19. package/dist/integrations/hooks/station-hook-runtime.cjs +89 -1
  20. package/dist/integrations/hooks/station-hook-runtime.mjs +2 -0
  21. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  22. package/dist/nucleus/suit-temperament.d.ts +2 -2
  23. package/dist/nucleus/suit-temperament.js +3 -1
  24. package/llms.txt +6 -4
  25. package/package.json +4 -2
  26. package/scripts/foundry/CHANGELOG.md +37 -1
  27. package/scripts/foundry/README.md +13 -1
  28. package/scripts/foundry/assert-packed-dist-cli.mjs +97 -0
  29. package/scripts/foundry/blip-render.cjs +1237 -0
  30. package/scripts/foundry/blip-rippel.cjs +1963 -0
  31. package/scripts/foundry/blip.mjs +109 -0
  32. package/scripts/foundry/cli.mjs +8 -4
  33. package/scripts/foundry/inspect.mjs +117 -7
  34. package/scripts/foundry/mint-suit.cjs +215 -14
  35. package/scripts/foundry/package.json +7 -1
  36. package/scripts/foundry/plant/agents/blip-inspect.yml +5 -0
  37. package/scripts/foundry/plant/agents/blip.yml +5 -0
  38. package/scripts/foundry/plant/agents/inspect.yml +1 -1
  39. package/scripts/foundry/plant/agents/mill.yml +1 -1
  40. package/scripts/foundry/plant/agents/sound-inspect.yml +5 -0
  41. package/scripts/foundry/plant/agents/sound.yml +5 -0
  42. package/scripts/foundry/plant/motions/MOTION-REGISTRY.md +35 -0
  43. package/scripts/foundry/plant/motions/registry.json +81 -0
  44. package/scripts/foundry/plant/skills/blip/SKILL.md +39 -0
  45. package/scripts/foundry/plant/skills/blip-inspect/SKILL.md +32 -0
  46. package/scripts/foundry/plant/skills/inspect/SKILL.md +2 -2
  47. package/scripts/foundry/plant/skills/sound/SKILL.md +29 -0
  48. package/scripts/foundry/plant/skills/sound-inspect/SKILL.md +28 -0
  49. package/scripts/foundry/release-gate.mjs +18 -10
  50. package/scripts/foundry/release.mjs +3 -0
  51. package/scripts/foundry/sound-bed.cjs +454 -0
  52. package/scripts/foundry/sound-rippel.cjs +1434 -0
  53. package/scripts/foundry/sound.mjs +93 -0
  54. package/scripts/node/assert-packed-dist-cli.mjs +4 -0
  55. package/scripts/node/consumer-install-smoke.mjs +20 -1
  56. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  57. package/xray/features.json +1 -1
  58. package/xray/features.schema.json +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xray/foundry",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "0xRay mill: mint their suit params, stamp, gate, publish, CI report, git hooks. Not the worn exo.",
@@ -38,6 +38,10 @@
38
38
  "./mill-root": "./mill-root.mjs",
39
39
  "./mint-suit": "./mint-suit.cjs",
40
40
  "./inspect": "./inspect.mjs",
41
+ "./sound": "./sound.mjs",
42
+ "./sound-bed": "./sound-bed.cjs",
43
+ "./blip": "./blip.mjs",
44
+ "./blip-render": "./blip-render.cjs",
41
45
  "./ci-monitor": "./ci-monitor.mjs",
42
46
  "./hooks": "./hooks.mjs",
43
47
  "./docs-build": "./docs-build.mjs"
@@ -49,6 +53,8 @@
49
53
  "0xray",
50
54
  "foundry",
51
55
  "mill",
56
+ "sound",
57
+ "blip",
52
58
  "release",
53
59
  "changelog"
54
60
  ]
@@ -0,0 +1,5 @@
1
+ name: blip-inspect
2
+ skill: blip-inspect
3
+ description: "Inspect the last factory-blip: 4.44s duration, mode, file present. Fail-closed."
4
+ version: "0.1.10"
5
+ mode: subagent
@@ -0,0 +1,5 @@
1
+ name: blip
2
+ skill: blip
3
+ description: "Factory-blip plant. Brief → seed → still|motion:<id> → 4.44s mp4 → inspect gate."
4
+ version: "0.1.10"
5
+ mode: subagent
@@ -1,5 +1,5 @@
1
1
  name: inspect
2
2
  skill: inspect
3
3
  description: "Inspect AI work: diffs, traces, mill receipts, CI. Fastened mill plant."
4
- version: "0.1.9"
4
+ version: "0.1.10"
5
5
  mode: subagent
@@ -1,5 +1,5 @@
1
1
  name: mill
2
2
  skill: mill
3
3
  description: "Fasten their plant as the suit. Factory Repertoire. Inspect is the mill discipline."
4
- version: "0.1.9"
4
+ version: "0.1.10"
5
5
  mode: subagent
@@ -0,0 +1,5 @@
1
+ name: sound-inspect
2
+ skill: sound-inspect
3
+ description: "Inspect the last factory-sound bed: chop, levels, peak, hum. Fail-closed."
4
+ version: "0.1.10"
5
+ mode: subagent
@@ -0,0 +1,5 @@
1
+ name: sound
2
+ skill: sound
3
+ description: "Factory-sound plant. Brief → seed → genre → headless wav → metrics gate."
4
+ version: "0.1.10"
5
+ mode: subagent
@@ -0,0 +1,35 @@
1
+ # Motion registry (factory-blip)
2
+
3
+ Law: motions are a dynamic registry (`id → renderer`). Rippel names are **imports**, not a frozen enum. Unknown id FAIL. `kapow` is a growth stub (`renderer: null`) until a renderer ships.
4
+
5
+ On-disk SSOT: `registry.json` next to this file.
6
+
7
+ ## v0 seed
8
+
9
+ `still` · `orb` · `swirl` · `snap` · `waves` · `spark`
10
+
11
+ ## Rippel v2 — converter + living motions (TICKET-BLIP-RENDERER-UPGRADE)
12
+
13
+ Default motion path is the Rippel converter spine, not ffmpeg geometry. Look is **sharp** (opaque body + crisp rim + short glow) on all five. Motion is a **4.44s blip**: fast abstract travel, soft gold tints — no hard strobe. LFOs share the crystal-mill genre tempo + `CircleConfig.frequency` with the audio bed.
14
+
15
+ - **SSOT** `htafolla/rippel-synapse-flow@e5014cd`
16
+ - `animationIcons.ts` → `ANIMATION_TO_VISUALIZATION`
17
+ - `types/index.ts` → `ChecksumResponse.visualConfig` (`CircleConfig[]`, `CanvasConfig`, `tlmCommand`)
18
+ - `SimplifiedVisualConverter.tsx` → Animation → viz id, canvas **1280×720** @ ~30fps
19
+ - `MiniAnimationViewer` / `FiveDimensionalVisualizer` → viz backends
20
+
21
+ | id | viz id | backend |
22
+ |----|--------|---------|
23
+ | `orb` | `canvas` | Orb Glow — dual rings, beat tick, frequency flash |
24
+ | `swirl` | `3d-sacred` | merkaba + hex plate, counter-spin, beat vertices |
25
+ | `snap` | `neural` | dual-ring lattice, hub, skip-links, traveling pulses |
26
+ | `waves` | `waveform` | Wave Flow — harmonic ribbons + beat envelope + gold needle |
27
+ | `spark` | `particles` | Spark Drift — beat bursts, orbital + radial motes |
28
+
29
+ Every mint wears a **sparse seed mesh** (12 families · 5 gaits) plus a **field** (stars · grids `floor`/`meridian`/`ticks` · gradients · blinkers). Uniqueness is the field, not more wire in the middle. Receipt `visualConfig.mesh` + `visualConfig.field` are the NFT fingerprints.
30
+
31
+ Motions encode **≥720p**. The old 320×180 ffmpeg wireframe is **`--engine wireframe` only**.
32
+
33
+ Every Blip muxes a **4.44s audio bed** (`--bed PATH` or auto sound mill). No audio stream = inspect FAIL.
34
+
35
+ `still` is the **Power Plant ident** — titlecard / corridor / rain / endcard dissolve over 4.44s at ≥720p. Not a frozen poster. Palette `#08090B` `#F5F7FA` `#3DE0E8` `#F5C518` `#4A7FD4`.
@@ -0,0 +1,81 @@
1
+ {
2
+ "version": 1,
3
+ "law": "Motions are a dynamic registry (id → renderer). Rippel names are imports. Kapow is a growth stub until a renderer ships.",
4
+ "v0": ["still", "orb", "swirl", "snap", "waves", "spark"],
5
+ "palette": {
6
+ "void": "#08090B",
7
+ "ink": "#F5F7FA",
8
+ "cyan": "#3DE0E8",
9
+ "gold": "#F5C518",
10
+ "blue": "#4A7FD4",
11
+ "plate": "power-plant-intro"
12
+ },
13
+ "motions": [
14
+ {
15
+ "id": "still",
16
+ "kind": "motion",
17
+ "source": "blips",
18
+ "renderer": "still",
19
+ "status": "v0",
20
+ "notes": "Power Plant ident — hard-cut titlecard/corridor/rain/endcard over 4.44s. Not a frozen still. ≥720p + bed."
21
+ },
22
+ {
23
+ "id": "orb",
24
+ "kind": "motion",
25
+ "source": "rippel",
26
+ "import": true,
27
+ "visualization": "canvas",
28
+ "renderer": "orb",
29
+ "status": "v0",
30
+ "notes": "Rippel v2 canvas — Orb Glow, sharp discs, dual rings + beat tick. ≥720p + 4.44s bed."
31
+ },
32
+ {
33
+ "id": "swirl",
34
+ "kind": "motion",
35
+ "source": "rippel",
36
+ "import": true,
37
+ "visualization": "3d-sacred",
38
+ "renderer": "swirl",
39
+ "status": "v0",
40
+ "notes": "Rippel v2 3d-sacred — merkaba + hex plate, counter-spin, beat vertices. ≥720p + 4.44s bed."
41
+ },
42
+ {
43
+ "id": "snap",
44
+ "kind": "motion",
45
+ "source": "rippel",
46
+ "import": true,
47
+ "visualization": "neural",
48
+ "renderer": "snap",
49
+ "status": "v0",
50
+ "notes": "Rippel v2 neural — dual-ring lattice, hub, skip-links, frequency + beat pulses. ≥720p + 4.44s bed."
51
+ },
52
+ {
53
+ "id": "waves",
54
+ "kind": "motion",
55
+ "source": "rippel",
56
+ "import": true,
57
+ "visualization": "waveform",
58
+ "renderer": "waves",
59
+ "status": "v0",
60
+ "notes": "Rippel v2 Wave Flow — harmonic ribbons + beat envelope + gold needle. ≥720p + 4.44s bed."
61
+ },
62
+ {
63
+ "id": "spark",
64
+ "kind": "motion",
65
+ "source": "rippel",
66
+ "import": true,
67
+ "visualization": "particles",
68
+ "renderer": "spark",
69
+ "status": "v0",
70
+ "notes": "Rippel v2 Spark Drift — beat bursts, orbital + radial motes, short trails. ≥720p + 4.44s bed."
71
+ },
72
+ {
73
+ "id": "kapow",
74
+ "kind": "motion",
75
+ "source": "blips",
76
+ "renderer": null,
77
+ "status": "growth",
78
+ "notes": "named growth slot — FAIL until a renderer ships"
79
+ }
80
+ ]
81
+ }
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: blip
3
+ description: Factory-blip plant. Brief → checksum seed → still|motion:<id> → 4.44s mp4 → inspect gate. Sibling to mill + sound. Not costume.
4
+ ---
5
+
6
+ # Blip
7
+
8
+ This **factory plant** fastens a tiny-video factory. 4.44 seconds of picture **with a mandatory audio bed**. Sibling to mill + sound — not a mill copy.
9
+
10
+ **Seat:** `foundry.json` `"plant": "blip"` turns mill off. `"plant": ["mill", "blip"]` wears both. Default stays mill+inspect.
11
+
12
+ **Motions** live in an on-disk registry (`plant/motions/registry.json`). v0 seed:
13
+
14
+ `still` · `orb` · `swirl` · `snap` · `waves` · `spark`
15
+
16
+ Rippel five are **imports**. Each mint is a **4.44s Short** — hook → turn → tag on one grid for picture and bed (continuous `hookEase`/`turnEase`/`tagEase`, not gear-shift flags). Seed-selected look (`focus` solid disc + satellites + field/mesh mass, or `cage` Wu hairline + field). Receipt `visualConfig.lookKind` + mesh + field are the fingerprints. `kapow` is a growth stub (FAIL until a renderer ships). Unknown id FAIL.
17
+
18
+ `still` is the **Power Plant ident** — titlecard / corridor / rain / endcard dissolve over 4.44s at ≥720p, not a frozen poster: void `#08090B` · ink `#F5F7FA` · cyan `#3DE0E8` · gold `#F5C518` · agent blue `#4A7FD4`. Motions use that palette as the Rippel `VisualConfig.circles` theme. The mill is the renderer — no LLM in the pixel/audio loop.
19
+
20
+ **Spine (headless, no browser):**
21
+
22
+ 1. **Brief** → checksum seed → Rippel `VisualConfig` (`CircleConfig[]`).
23
+ 2. **Mode** → `still` or `motion:<id>` from the registry.
24
+ 3. **Render** → 4.44s mp4. Motions are Rippel v2 viz at ≥720p (`--look focus|cage`, seed picks if omitted). `--engine wireframe` is emergency only.
25
+ 4. **Bed** → `--bed PATH` or auto sound mill. Auto bed **syncopates** to the motion grid (same seed + tempo + phase; downbeat kick / AND hat). Every mp4 muxes **stereo AAC**. Missing stream or inaudible bed = inspect FAIL.
26
+ 5. **Inspect gate** → file, duration 4.44s±tol, mode id, **audio stream**, motion ≥720p. Fail-closed.
27
+ 6. **Receipt** → `.xray/blip/receipt.json` (`PASS` / `FAIL` + pictureMode + motionId + visualConfig).
28
+
29
+ ```bash
30
+ npx @0xray/foundry mint --skip-live
31
+ npx @0xray/foundry blip render --brief "night alley still" --mode still
32
+ npx @0xray/foundry blip render --brief "warehouse floor · Power Plant" --mode motion:orb --look focus
33
+ npx @0xray/foundry blip inspect
34
+ npx @0xray/foundry inspect --skip-live
35
+ ```
36
+
37
+ Mint fastens `blip` + `blip-inspect`. Chat is not a receipt.
38
+
39
+ A friend would hear: Blips should look like Rippel living motions with sound, not a silent wireframe box.
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: blip-inspect
3
+ description: Inspect the last factory-blip — duration 4.44s, registry mode id, file present. Fail-closed. Not costume.
4
+ ---
5
+
6
+ # Blip inspect
7
+
8
+ This is the **factory-blip** inspect, not mill inspect. Open the receipt. Quote the numbers. Do not invent a pass.
9
+
10
+ `npx @0xray/foundry inspect` reports blip plant present, live registry ids, plus last blip `PASS`/`FAIL`. `npx @0xray/foundry blip inspect` is the same check.
11
+
12
+ ## Gates (fail-closed)
13
+
14
+ Missing mp4, unreadable mp4, or a thrown probe is **FAIL**. Never pass on a missing file.
15
+
16
+ 1. **File.** `.xray/blip/blip.mp4` (or receipt `mp4`) exists.
17
+ 2. **Duration.** 4.44s ± 0.12s.
18
+ 3. **Mode.** Receipt records a registry id (`still` or `motion:<id>`). Unknown id is FAIL.
19
+ 4. **Video.** Stream present.
20
+ 5. **Audio.** Stream present. Silent mp4 = FAIL. `--bed` or auto sound mill.
21
+ 6. **Resolution.** Every live blip ≥720p (`1280×720`), including the Power Plant ident (`still`).
22
+
23
+ v0 ids: `still` · `orb` · `swirl` · `snap` · `waves` · `spark`. `kapow` is a growth stub (FAIL until a renderer ships). Unknown id FAIL. Receipt records the Power Plant palette.
24
+
25
+ Receipt: `.xray/blip/receipt.json`. Mp4 default: `.xray/blip/blip.mp4`.
26
+
27
+ ```bash
28
+ npx @0xray/foundry blip render --brief "warm basement swirl" --mode motion:swirl --bed bed.wav
29
+ npx @0xray/foundry blip inspect
30
+ ```
31
+
32
+ Plant-vs-worn allowlists `blip` + `blip-inspect` when `"plant": "blip"`. They are not a costume dump. Mill may be off on this seat.
@@ -12,8 +12,8 @@ Mill **does** these checks (`npx @0xray/foundry inspect`). Mint fails on a costu
12
12
  ## What mill inspects
13
13
 
14
14
  1. **Diff.** `git status` / `git diff --stat` of the milled cwd. Ignore the agent's summary if the diff disagrees.
15
- 2. **Plant vs worn.** `src/skills`, `src/opencode/agents` vs `.opencode/skills`, `.opencode/agents`. Same name: plant wins. Shop plant (`shop-extract`, `shop-witness`, `shop-pin`, plus `foundry.json` `shopPlant`) is first-class with mill plant. Costume dump (worn names they did not plant, mill did not fasten, and shop plant did not name) fails mint unless `foundry.json` has `"costume": true`.
16
- 3. **Mill receipt.** `.xray/foundry-inventory.json` — mill name/version, `suit` (`fastened` / `overlay` / `costume`), `millPlant.skills` must include `mill` and `inspect`.
15
+ 2. **Plant vs worn.** `src/skills`, `src/opencode/agents` vs `.opencode/skills`, `.opencode/agents`. Same name: plant wins. Shop plant (`shop-extract`, `shop-witness`, `shop-pin`, plus `foundry.json` `shopPlant`) is first-class with mill plant. Sound plant (`sound`, `sound-inspect`) is first-class when `foundry.json` `"plant": "sound"` (mill may be off). Blip plant (`blip`, `blip-inspect`) is first-class when `foundry.json` `"plant": "blip"` (mill may be off). Costume dump (worn names they did not plant, mill did not fasten, sound did not fasten, blip did not fasten, and shop plant did not name) fails mint unless `foundry.json` has `"costume": true`.
16
+ 3. **Mill receipt.** `.xray/foundry-inventory.json` — mill name/version, `suit` (`fastened` / `overlay` / `costume`), `plant`. Mill seats: `millPlant.skills` must include `mill` and `inspect`. Sound seats: `soundPlant.skills` must include `sound` and `sound-inspect`; last bed receipt is a separate check. Blip seats: `blipPlant.skills` must include `blip` and `blip-inspect`; last blip receipt is a separate check.
17
17
  4. **CI.** GitHub mill CI report (`.opencode/logs/ci-cd-monitor-report.json`), not a green check in chat. No token is a skip, not a pass invented.
18
18
  5. **Live PUT.** HTTP 200 on the npm `.tgz`. Metadata without a tarball is not shipped.
19
19
  6. **Isolated HOME.** Last-mile dest is project `.grok/plugins/0xray`. Isolated HOME may wear `$HOME/.grok/plugins/0xray` and must not write machine `~/.grok/plugins/0xray`. Shared HOME (passwd `$HOME`) does not last-wins clobber the machine plugin. Mill compares `$HOME` to the passwd home (`os.userInfo().homedir`), not `os.homedir()` (which follows `$HOME`).
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: sound
3
+ description: Factory-sound plant. Brief → checksum seed → genre → headless wav → metrics gate. Not mill. Not costume.
4
+ ---
5
+
6
+ # Sound
7
+
8
+ This plant **fastens** a music/bed factory. Dist audio beds get a real plant like mill — not code-mill skills on a sound seat.
9
+
10
+ **Seat:** `foundry.json` `"plant": "sound"` turns mill off. `"plant": ["mill", "sound"]` wears both. Default stays mill+inspect.
11
+
12
+ **Spine (headless, no browser):**
13
+
14
+ 1. **Brief** → checksum seed (stable hash lineage).
15
+ 2. **Genre** → tempo + voice prefs: `ambient` | `techno` | `jazz` (`phonk` / `destination` are aliases).
16
+ 3. **Render** → wav via a crystal-clear mill of Rippel’s prototype chains (Membrane kick / Metal hat / Duo bass / mixer). Tone.Offline is blocked in Node (`OfflineAudioContext` missing); this is the lean headless port, not a 3-sine bed and not the Lovable volume-hack soup.
17
+ 4. **Metrics gate** → chop / levels / peak / hum. Fail-closed.
18
+ 5. **Receipt** → `.xray/sound-bed-receipt.json` (`PASS` / `FAIL` + numbers).
19
+
20
+ ```bash
21
+ npx @0xray/foundry mint --skip-live
22
+ npx @0xray/foundry sound render --brief "night alley rain" --genre ambient
23
+ npx @0xray/foundry sound inspect
24
+ npx @0xray/foundry inspect --skip-live
25
+ ```
26
+
27
+ Mint fastens `sound` + `sound-inspect`. It does not dump mill inspect onto a sound-only seat. Chat is not a bed receipt.
28
+
29
+ A friend would hear: the sound mill mills Dist beds like Rippel’s prototype grew up — kick membranes, metal hats, and a crystal-clear mixer, not a muddy toy and not a 3-sine pad.
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: sound-inspect
3
+ description: Inspect the last factory-sound bed — loudness/smoothness gates, not code-mill diffs. Not costume.
4
+ ---
5
+
6
+ # Sound inspect
7
+
8
+ This is the **bed** inspect, not mill inspect. Open the receipt. Quote the numbers. Do not invent a pass.
9
+
10
+ `npx @0xray/foundry inspect` reports sound plant present plus last bed `PASS`/`FAIL`. `npx @0xray/foundry sound inspect` is the same bed check.
11
+
12
+ ## Gates (fail-closed)
13
+
14
+ Missing wav, unreadable wav, or a thrown metric is **FAIL**. Never pass on silence.
15
+
16
+ 1. **Chop.** Mean |ΔRMS| over 0.25s windows ≪ 0.1 (strong ≤ 0.05).
17
+ 2. **Levels.** Body / intro mean RMS ratio ~1.5–3.0. Body min RMS ≥ 0.05 (exclude the final 1s fade).
18
+ 3. **Peak.** Max |sample| < 0.95.
19
+ 4. **Hum.** No continuous near-constant drone (dominant-bin share over the piece).
20
+
21
+ Receipt: `.xray/sound-bed-receipt.json`. Wav default: `.xray/sound/bed.wav`.
22
+
23
+ ```bash
24
+ npx @0xray/foundry sound render --brief "warm basement pad" --genre jazz
25
+ npx @0xray/foundry sound inspect
26
+ ```
27
+
28
+ Plant-vs-worn allowlists `sound` + `sound-inspect` when `"plant": "sound"`. They are not a costume dump. Mill may be off on this seat.
@@ -53,33 +53,41 @@ function main() {
53
53
  if (!isXrayExoRepo(rootDir)) {
54
54
  runLightGate();
55
55
  } else if (verifyOnly) {
56
- step("1/5 Git + reconcile", "node scripts/node/pre-publish-guard.js --verify-only");
56
+ step("1/6 Git + reconcile", "node scripts/node/pre-publish-guard.js --verify-only");
57
57
  if (!skipDocs) {
58
- step("2/5 Release docs", docsCheckCmd());
58
+ step("2/6 Release docs", docsCheckCmd());
59
59
  }
60
60
  step(
61
- "3/5 Plugin infrastructure",
61
+ "3/6 Plugin infrastructure",
62
62
  "node scripts/test/validate-plugins-e2e.cjs --structural-only",
63
63
  );
64
+ step(
65
+ "4/6 Packed dist/cli",
66
+ `${JSON.stringify(process.execPath)} ${JSON.stringify(millScript("assert-packed-dist-cli.mjs"))}`,
67
+ );
64
68
  if (!skipSmoke) {
65
- step("4/5 Consumer install smoke", "node scripts/node/consumer-install-smoke.mjs");
69
+ step("5/6 Consumer install smoke", "node scripts/node/consumer-install-smoke.mjs");
66
70
  }
67
71
  } else {
68
- step("1/7 Build", "npm run build");
69
- step("2/7 Tests", "npm run test:comprehensive");
72
+ step("1/8 Build", "npm run build");
73
+ step(
74
+ "2/8 Packed dist/cli",
75
+ `${JSON.stringify(process.execPath)} ${JSON.stringify(millScript("assert-packed-dist-cli.mjs"))}`,
76
+ );
77
+ step("3/8 Tests", "npm run test:comprehensive");
70
78
  if (!skipDocs) {
71
- step("3/7 Release docs", docsCheckCmd());
79
+ step("4/8 Release docs", docsCheckCmd());
72
80
  }
73
81
  step(
74
- "4/7 Consumer hook verifiers",
82
+ "5/8 Consumer hook verifiers",
75
83
  "npm run verify:pre-commit-diff && npm run verify:pre-push-diff && node scripts/mjs/verify-delegation-gate-core.mjs --host=grok && node scripts/mjs/verify-delegation-gate-core.mjs --host=hermes && node scripts/mjs/verify-delegation-gate-core.mjs --host=opencode && node scripts/mjs/verify-hermes-session-start.mjs && node scripts/mjs/verify-confer-core.mjs && npm run verify:user-aside && npm run build && node scripts/mjs/verify-pipeline-facets.mjs --package-only",
76
84
  );
77
85
  step(
78
- "5/7 Plugin infrastructure",
86
+ "6/8 Plugin infrastructure",
79
87
  "node scripts/test/validate-plugins-e2e.cjs --structural-only",
80
88
  );
81
89
  if (!skipSmoke) {
82
- step("6/7 Consumer install smoke (fresh + upgrade)", "node scripts/node/consumer-install-smoke.mjs");
90
+ step("7/8 Consumer install smoke (fresh + upgrade)", "node scripts/node/consumer-install-smoke.mjs");
83
91
  }
84
92
  }
85
93
 
@@ -112,6 +112,9 @@ function publishIdempotent(version) {
112
112
  console.log(`ℹ️ ${packageName()}@${version} already on npm — skipping publish`);
113
113
  return;
114
114
  }
115
+ if (isXrayExoRepo(rootDir)) {
116
+ runMill("assert-packed-dist-cli.mjs", [], "packed dist/cli");
117
+ }
115
118
  execSync(npmPublishCmd(), { cwd: rootDir, stdio: "inherit", encoding: "utf-8" });
116
119
  console.log(`✅ Published ${packageName()}@${version}`);
117
120
  }