sneakoscope 0.9.13 → 0.9.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 (88) hide show
  1. package/README.md +30 -39
  2. package/crates/sks-core/Cargo.lock +99 -1
  3. package/crates/sks-core/Cargo.toml +2 -1
  4. package/crates/sks-core/src/main.rs +77 -43
  5. package/package.json +8 -5
  6. package/src/cli/command-registry.mjs +73 -114
  7. package/src/cli/feature-commands.mjs +44 -5
  8. package/src/cli/install-helpers.mjs +2 -2
  9. package/src/cli/router.mjs +2 -3
  10. package/src/commands/aliases.mjs +2 -0
  11. package/src/commands/auto-review.mjs +5 -0
  12. package/src/commands/autoresearch.mjs +5 -0
  13. package/src/commands/bootstrap.mjs +2 -0
  14. package/src/commands/code-structure.mjs +5 -0
  15. package/src/commands/codex-lb.mjs +61 -3
  16. package/src/commands/commands.mjs +5 -0
  17. package/src/commands/commit-and-push.mjs +5 -0
  18. package/src/commands/commit.mjs +5 -0
  19. package/src/commands/computer-use.mjs +31 -0
  20. package/src/commands/conflicts.mjs +13 -0
  21. package/src/commands/context7.mjs +5 -0
  22. package/src/commands/db.mjs +1 -1
  23. package/src/commands/deps.mjs +5 -0
  24. package/src/commands/dfix.mjs +2 -0
  25. package/src/commands/doctor.mjs +2 -2
  26. package/src/commands/dollar-commands.mjs +2 -0
  27. package/src/commands/eval.mjs +5 -0
  28. package/src/commands/fix-path.mjs +2 -0
  29. package/src/commands/gc.mjs +2 -0
  30. package/src/commands/goal.mjs +5 -0
  31. package/src/commands/guard.mjs +10 -0
  32. package/src/commands/gx.mjs +5 -0
  33. package/src/commands/harness.mjs +5 -0
  34. package/src/commands/help.mjs +3 -74
  35. package/src/commands/hook.mjs +8 -0
  36. package/src/commands/hproof.mjs +5 -0
  37. package/src/commands/image-ux-review.mjs +38 -0
  38. package/src/commands/init.mjs +2 -0
  39. package/src/commands/mad-sks.mjs +14 -0
  40. package/src/commands/memory.mjs +5 -0
  41. package/src/commands/openclaw.mjs +2 -0
  42. package/src/commands/perf.mjs +2 -2
  43. package/src/commands/pipeline.mjs +25 -0
  44. package/src/commands/postinstall.mjs +2 -0
  45. package/src/commands/ppt.mjs +44 -0
  46. package/src/commands/profile.mjs +5 -0
  47. package/src/commands/proof-field.mjs +5 -0
  48. package/src/commands/proof.mjs +22 -1
  49. package/src/commands/qa-loop.mjs +5 -0
  50. package/src/commands/quickstart.mjs +2 -0
  51. package/src/commands/reasoning.mjs +2 -0
  52. package/src/commands/recallpulse.mjs +5 -0
  53. package/src/commands/research.mjs +5 -0
  54. package/src/commands/selftest.mjs +2 -0
  55. package/src/commands/setup.mjs +2 -0
  56. package/src/commands/skill-dream.mjs +5 -0
  57. package/src/commands/stats.mjs +2 -0
  58. package/src/commands/team.mjs +2 -0
  59. package/src/commands/tmux.mjs +5 -0
  60. package/src/commands/update-check.mjs +2 -0
  61. package/src/commands/usage.mjs +2 -0
  62. package/src/commands/validate-artifacts.mjs +2 -0
  63. package/src/commands/versioning.mjs +16 -0
  64. package/src/commands/wiki.mjs +2 -2
  65. package/src/core/codex-lb-circuit.mjs +18 -0
  66. package/src/core/commands/basic-cli.mjs +315 -0
  67. package/src/{cli/maintenance-commands.mjs → core/commands/route-cli.mjs} +37 -37
  68. package/src/core/feature-fixture-runner.mjs +109 -0
  69. package/src/core/feature-fixtures.mjs +1 -1
  70. package/src/core/feature-registry.mjs +19 -7
  71. package/src/core/fsx.mjs +1 -1
  72. package/src/core/git-simple.mjs +118 -0
  73. package/src/core/pipeline.mjs +1 -1
  74. package/src/core/proof/route-finalizer-fixtures.mjs +21 -0
  75. package/src/core/proof/route-finalizer-policy.mjs +13 -0
  76. package/src/core/proof/route-finalizer.mjs +82 -0
  77. package/src/core/proof-field.mjs +2 -2
  78. package/src/core/routes.mjs +31 -1
  79. package/src/core/rust-accelerator.mjs +8 -3
  80. package/src/core/version.mjs +1 -1
  81. package/src/core/wiki-image/before-after-relation.mjs +1 -0
  82. package/src/core/wiki-image/computer-use-evidence.mjs +1 -0
  83. package/src/core/wiki-image/generated-review-parser.mjs +1 -0
  84. package/src/core/wiki-image/image-ux-evidence.mjs +1 -0
  85. package/src/core/wiki-image/image-voxel-ledger.mjs +10 -3
  86. package/src/core/wiki-image/ppt-image-evidence.mjs +1 -0
  87. package/src/core/wiki-image/route-image-evidence.mjs +107 -0
  88. package/src/cli/legacy-main.mjs +0 -4147
package/README.md CHANGED
@@ -1,8 +1,27 @@
1
1
  # Sneakoscope Codex
2
2
 
3
- Fast proof-first Codex trust layer with image-based Voxel TriWiki.
3
+ Fast legacy-free proof-first Codex trust layer with image-based Voxel TriWiki.
4
4
 
5
- Sneakoscope Codex (`sks`) is a Codex CLI/App harness for repeatable workflows. It adds terminal commands, Codex App `$` commands, tmux workspaces, Team/QA/Research routes, pipeline plans, Computer Use, imagegen UI/UX review, Goal, Context7, DB safety, Voxel TriWiki, design-system routing, skill dreaming, completion proof, and Honest Mode.
5
+ Sneakoscope Codex (`sks`) is a Codex CLI/App harness that makes repeatable Codex work auditable. `0.9.14` runs through split command modules, automatically seals serious routes with Completion Proof, binds visual/UI claims to Image Voxel TriWiki anchors and relations, and release-gates hooks, codex-lb, executable fixtures, Rust parity, and DB safety evidence.
6
+
7
+ ## 0.9.14 Current Release
8
+
9
+ `0.9.14` turns SKS into a legacy-free proof-first trust layer for Codex work:
10
+
11
+ - Command registry entries load independent command modules without runtime fallback to archived 0.9.13 CLI bundles.
12
+ - Serious routes write Completion Proof through the central route finalizer before completion is claimed.
13
+ - Visual/UI routes require Image Voxel TriWiki anchors, with before/after relations for visual fix claims.
14
+ - Executable feature fixtures validate expected artifact existence and schema contracts.
15
+ - Hook replay strictly matches decision, reason, gate, issues, continuation, and redaction policy.
16
+ - codex-lb launch failures feed both global and active-project circuit health; stateless `previous_response_not_found` stays a warning.
17
+ - Rust `image-hash` and semantic `voxel-validate` commands match JS fallback behavior.
18
+ - `$Commit` and `$Commit-And-Push` provide a simple git-only route for staging, committing, and optionally pushing without the full SKS pipeline.
19
+
20
+ Learn more:
21
+ - Completion Proof: [docs/completion-proof.md](docs/completion-proof.md)
22
+ - Image Voxel TriWiki: [docs/image-voxel-ledger.md](docs/image-voxel-ledger.md)
23
+ - Codex App Hooks/PAT: [docs/hooks-pat.md](docs/hooks-pat.md)
24
+ - codex-lb: [docs/codex-lb.md](docs/codex-lb.md)
6
25
 
7
26
  ## 60-second start
8
27
 
@@ -16,28 +35,20 @@ sks selftest --mock
16
35
 
17
36
  ## Three core promises
18
37
 
19
- 1. Image-based Voxel TriWiki memory
20
- 2. Codex App / codex-lb operational readiness
21
- 3. Completion proof for every serious route
38
+ 1. Completion Proof for every serious route
39
+ 2. Image Voxel TriWiki anchors and relations for every visual route
40
+ 3. Codex App, codex-lb, hooks, Rust, DB, and fixtures verified by release gates
22
41
 
23
- ## Quick Start
42
+ ## Install Options
24
43
 
25
44
  Install globally, then run `sks` from either a project or any global shell location:
26
45
 
27
46
  ```sh
28
47
  npm i -g sneakoscope
29
48
  sks root
30
- sks
49
+ sks doctor
31
50
  ```
32
51
 
33
- `0.9.13` connects serious routes to Completion Proof, visual routes to image voxel anchors, hook replay to shared runtime policy, codex-lb launch failures to circuit health, and Rust accelerator commands to JS fallback parity. Rust accelerator source is included in the npm package; until prebuilt binaries ship, SKS uses JS fallbacks unless `SKS_RS_BIN` or a source-checkout `sks-rs` binary is available.
34
-
35
- Learn more:
36
- - Completion Proof: [docs/completion-proof.md](docs/completion-proof.md)
37
- - Image Voxel TriWiki: [docs/image-voxel-ledger.md](docs/image-voxel-ledger.md)
38
- - Codex App Hooks/PAT: [docs/hooks-pat.md](docs/hooks-pat.md)
39
- - codex-lb: [docs/codex-lb.md](docs/codex-lb.md)
40
-
41
52
  `npm i -g sneakoscope` automatically refreshes the `sks` command shim, global Codex App `$` skills, and SKS bootstrap surface. When the install is run from a project, postinstall bootstraps that project. When it is run outside a repo/project marker, postinstall bootstraps the per-user global runtime root instead of writing `.sneakoscope` into a random current directory. `sks root` tells you which root SKS will use.
42
53
 
43
54
  If you only want a one-shot run without keeping `sks` installed globally:
@@ -59,6 +70,7 @@ Check that the install is usable:
59
70
  sks deps check
60
71
  sks codex-app check
61
72
  sks dollar-commands
73
+ sks commit --json
62
74
  sks selftest --mock
63
75
  ```
64
76
 
@@ -66,32 +78,11 @@ sks selftest --mock
66
78
 
67
79
  `sks` adds a tmux Codex CLI runtime, Codex App `$` commands, Team/QA/PPT/Research/DB/GX/Wiki routes, OpenClaw skill generation, Context7-gated current docs, TriWiki context packs, DB safety, design SSOT policy, skill dreaming, release checks, and Honest Mode.
68
80
 
69
- ## 0.8.0 Massive Upgrade
70
-
71
- Sneakoscope 0.8.0 introduces the RecallPulse planning spine: a report-only active-recall layer that records what the pipeline should remember before a stage proceeds. RecallPulse maps TriWiki into L1/L2/L3 cache behavior, writes durable status ledgers instead of relying on ephemeral hook text, suppresses duplicate reminder loops, and emits RouteProofCapsule plus EvidenceEnvelope artifacts for later gate comparison. These artifacts are evidence surfaces first; speed or accuracy gains remain benchmark-gated until scored evals prove them.
72
-
73
- Inspect the new report-only artifacts with:
74
-
75
- ```sh
76
- sks recallpulse run latest
77
- sks recallpulse status latest --json
78
- sks recallpulse eval latest --json
79
- sks recallpulse governance latest --json
80
- sks recallpulse checklist latest --json
81
- sks recallpulse checklist latest --task T001 --apply --evidence src/core/recallpulse.mjs
82
- ```
83
-
84
- Research scouts now use named persona-inspired cognitive lenses: Einstein Scout, Feynman Scout, Turing Scout, von Neumann Scout, and Skeptic Scout. They are not impersonations; each scout ledger row must carry `display_name`, `persona`, `persona_boundary`, `reasoning_effort=xhigh`, a literal `Eureka!` idea, falsifiers, cheap probes, and debate participation evidence.
85
-
86
- For existing 0.7.x users, the visible change is new report-only evidence, not a route personality rewrite. Team still feels like Team, DFix stays ultralight, DB remains conservative, QA-LOOP still dogfoods, PPT stays information-first, imagegen still requires real raster evidence, and Honest Mode remains the final truth pass. The original strong reminder idea became neutral RecallPulse so user-facing prompts stay short, professional, and non-repetitive; hook messages can point at status, but `mission-status-ledger.json` is the durable source when app-visible text disappears. The planning source is `docs/RECALLPULSE_0_8_0_TASKS.md`, and implementation is designed to land in safe task-sized slices before any enforcement promotion.
87
-
88
- ## 0.9.0 Report-Only Decision Lattice
89
-
90
- Sneakoscope 0.9.0 adds a report-only Decision Lattice planner that uses A* over proof-debt signals to explain which route or verification path the pipeline would prefer. It is an evidence and planning surface, not a runtime shortcut: SKS must not claim speedup, fast-lane accuracy, or reduced verification cost from the lattice until replay or scored eval evidence demonstrates those outcomes.
81
+ ## Report-Only Planning Surfaces
91
82
 
92
- The lattice integrates with the existing proof-field and `sks pipeline plan` surfaces. Its reports are expected to show the explored frontier, the selected path, and rejected paths with their proof-debt reasons, so reviewers can audit why a route stayed on the full Team/Honest path or why a smaller verification plan was only proposed. Like RecallPulse, this is designed to land as report-only evidence first; route enforcement and performance claims remain gated by later validation.
83
+ Decision Lattice and RecallPulse remain report-only planning and evidence surfaces. They can explain route choices and proof-debt signals, but SKS does not claim speedup, fast-lane accuracy, or reduced verification cost from them until scored evals prove those outcomes.
93
84
 
94
- Quick checks:
85
+ Useful checks:
95
86
 
96
87
  ```bash
97
88
  sks proof-field scan --json --intent "small CLI change"
@@ -2,6 +2,104 @@
2
2
  # It is not intended for manual editing.
3
3
  version = 4
4
4
 
5
+ [[package]]
6
+ name = "itoa"
7
+ version = "1.0.18"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
10
+
11
+ [[package]]
12
+ name = "memchr"
13
+ version = "2.8.0"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
16
+
17
+ [[package]]
18
+ name = "proc-macro2"
19
+ version = "1.0.106"
20
+ source = "registry+https://github.com/rust-lang/crates.io-index"
21
+ checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
22
+ dependencies = [
23
+ "unicode-ident",
24
+ ]
25
+
26
+ [[package]]
27
+ name = "quote"
28
+ version = "1.0.45"
29
+ source = "registry+https://github.com/rust-lang/crates.io-index"
30
+ checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
31
+ dependencies = [
32
+ "proc-macro2",
33
+ ]
34
+
35
+ [[package]]
36
+ name = "serde"
37
+ version = "1.0.228"
38
+ source = "registry+https://github.com/rust-lang/crates.io-index"
39
+ checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
40
+ dependencies = [
41
+ "serde_core",
42
+ ]
43
+
44
+ [[package]]
45
+ name = "serde_core"
46
+ version = "1.0.228"
47
+ source = "registry+https://github.com/rust-lang/crates.io-index"
48
+ checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
49
+ dependencies = [
50
+ "serde_derive",
51
+ ]
52
+
53
+ [[package]]
54
+ name = "serde_derive"
55
+ version = "1.0.228"
56
+ source = "registry+https://github.com/rust-lang/crates.io-index"
57
+ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
58
+ dependencies = [
59
+ "proc-macro2",
60
+ "quote",
61
+ "syn",
62
+ ]
63
+
64
+ [[package]]
65
+ name = "serde_json"
66
+ version = "1.0.149"
67
+ source = "registry+https://github.com/rust-lang/crates.io-index"
68
+ checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
69
+ dependencies = [
70
+ "itoa",
71
+ "memchr",
72
+ "serde",
73
+ "serde_core",
74
+ "zmij",
75
+ ]
76
+
5
77
  [[package]]
6
78
  name = "sks-core"
7
- version = "0.9.13"
79
+ version = "0.9.14"
80
+ dependencies = [
81
+ "serde_json",
82
+ ]
83
+
84
+ [[package]]
85
+ name = "syn"
86
+ version = "2.0.117"
87
+ source = "registry+https://github.com/rust-lang/crates.io-index"
88
+ checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
89
+ dependencies = [
90
+ "proc-macro2",
91
+ "quote",
92
+ "unicode-ident",
93
+ ]
94
+
95
+ [[package]]
96
+ name = "unicode-ident"
97
+ version = "1.0.24"
98
+ source = "registry+https://github.com/rust-lang/crates.io-index"
99
+ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
100
+
101
+ [[package]]
102
+ name = "zmij"
103
+ version = "1.0.21"
104
+ source = "registry+https://github.com/rust-lang/crates.io-index"
105
+ checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
@@ -1,9 +1,10 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "0.9.13"
3
+ version = "0.9.14"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
7
+ serde_json = "1"
7
8
 
8
9
  [[bin]]
9
10
  name = "sks-rs"
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
4
4
  fn main() {
5
5
  let mut args = std::env::args().skip(1);
6
6
  match args.next().as_deref() {
7
- Some("--version") => println!("sks-rs 0.9.13"),
7
+ Some("--version") => println!("sks-rs 0.9.14"),
8
8
  Some("compact-info") => {
9
9
  let mut input = String::new();
10
10
  let _ = io::stdin().read_to_string(&mut input);
@@ -40,9 +40,15 @@ fn main() {
40
40
  }
41
41
  Some("voxel-validate") => {
42
42
  let path = args.next().unwrap_or_default();
43
+ let mut require_anchors = false;
44
+ let mut require_relations = false;
45
+ while let Some(arg) = args.next() {
46
+ if arg == "--require-anchors" { require_anchors = true; }
47
+ if arg == "--require-relations" { require_relations = true; }
48
+ }
43
49
  match std::fs::read_to_string(&path) {
44
50
  Ok(text) => {
45
- let report = voxel_validate(&text);
51
+ let report = voxel_validate(&text, require_anchors, require_relations);
46
52
  println!("{}", report);
47
53
  if report.contains("\"ok\":false") { std::process::exit(1); }
48
54
  }
@@ -139,52 +145,80 @@ fn sha256_hex(data: &[u8]) -> String {
139
145
  h.iter().map(|x| format!("{:08x}", x)).collect::<String>()
140
146
  }
141
147
 
142
- fn voxel_validate(text: &str) -> String {
143
- let mut issues: Vec<&str> = Vec::new();
144
- if !text.contains("\"schema\"") || !text.contains("sks.image-voxel-ledger.v1") { issues.push("schema"); }
145
- if !text.contains("\"images\"") { issues.push("missing_images"); }
146
- if !text.contains("\"anchors\"") { issues.push("missing_anchors"); }
147
- let image_count = count_object_entries(text, "images");
148
- let anchor_count = count_object_entries(text, "anchors");
149
- if image_count == 0 { issues.push("missing_images"); }
150
- if anchor_count == 0 { issues.push("missing_anchors"); }
151
- issues.sort();
152
- issues.dedup();
153
- let ok = issues.is_empty();
154
- let issue_json = issues.iter().map(|x| format!("\"{}\"", json_escape(x))).collect::<Vec<_>>().join(",");
155
- format!("{{\"ok\":{},\"engine\":\"rust\",\"schema\":\"sks.image-voxel-ledger.v1\",\"images\":{},\"anchors\":{},\"issues\":[{}]}}", if ok { "true" } else { "false" }, image_count, anchor_count, issue_json)
156
- }
157
-
158
- fn count_object_entries(text: &str, key: &str) -> usize {
159
- let marker = format!("\"{}\"", key);
160
- let Some(start) = text.find(&marker) else { return 0; };
161
- let Some(open) = text[start..].find('[').map(|i| start + i) else { return 0; };
162
- let mut depth = 0i32;
163
- let mut entries = 0usize;
164
- let mut in_string = false;
165
- let mut escape = false;
166
- for ch in text[open..].chars() {
167
- if escape {
168
- escape = false;
169
- continue;
148
+ fn voxel_validate(text: &str, require_anchors: bool, require_relations: bool) -> String {
149
+ let parsed: serde_json::Value = match serde_json::from_str(text) {
150
+ Ok(value) => value,
151
+ Err(err) => {
152
+ return format!("{{\"ok\":false,\"engine\":\"rust\",\"schema\":\"sks.image-voxel-ledger.v1\",\"images\":0,\"anchors\":0,\"relations\":0,\"issues\":[\"json_parse\"],\"error\":\"{}\"}}", json_escape(&err.to_string()));
170
153
  }
171
- if ch == '\\' && in_string {
172
- escape = true;
173
- continue;
154
+ };
155
+ let mut issues: Vec<String> = Vec::new();
156
+ if parsed.get("schema").and_then(|v| v.as_str()) != Some("sks.image-voxel-ledger.v1") { issues.push("schema".to_string()); }
157
+ let images = parsed.get("images").and_then(|v| v.as_array()).cloned().unwrap_or_default();
158
+ let anchors = parsed.get("anchors").and_then(|v| v.as_array()).cloned().unwrap_or_default();
159
+ let relations = parsed.get("relations").and_then(|v| v.as_array()).cloned().unwrap_or_default();
160
+ if !parsed.get("images").map(|v| v.is_array()).unwrap_or(false) { issues.push("missing_images".to_string()); }
161
+ if !parsed.get("anchors").map(|v| v.is_array()).unwrap_or(false) { issues.push("missing_anchors".to_string()); }
162
+ if require_anchors && anchors.is_empty() { issues.push("missing_anchors:visual-route".to_string()); }
163
+ if require_relations && relations.is_empty() { issues.push("missing_relations:visual-route".to_string()); }
164
+ let mut image_ids: Vec<String> = Vec::new();
165
+ let mut anchor_ids: Vec<String> = Vec::new();
166
+ for image in &images {
167
+ let id = image.get("id").and_then(|v| v.as_str()).unwrap_or("");
168
+ if id.is_empty() { issues.push("image_id".to_string()); }
169
+ if !id.is_empty() && image_ids.iter().any(|x| x == id) { issues.push(format!("duplicate_image:{}", id)); }
170
+ if !id.is_empty() { image_ids.push(id.to_string()); }
171
+ if image.get("path").and_then(|v| v.as_str()).unwrap_or("").is_empty() { issues.push(format!("image_path:{}", if id.is_empty() { "unknown" } else { id })); }
172
+ if image.get("sha256").and_then(|v| v.as_str()).unwrap_or("").is_empty() { issues.push(format!("image_sha256:{}", if id.is_empty() { "unknown" } else { id })); }
173
+ let w = image.get("width").and_then(|v| v.as_f64());
174
+ let h = image.get("height").and_then(|v| v.as_f64());
175
+ if !w.map(|n| n.is_finite()).unwrap_or(false) || !h.map(|n| n.is_finite()).unwrap_or(false) {
176
+ issues.push(format!("image_dimensions:{}", if id.is_empty() { "unknown" } else { id }));
174
177
  }
175
- if ch == '"' {
176
- in_string = !in_string;
177
- continue;
178
+ }
179
+ for anchor in &anchors {
180
+ let id = anchor.get("id").and_then(|v| v.as_str()).unwrap_or("");
181
+ if id.is_empty() { issues.push("anchor_id".to_string()); }
182
+ if !id.is_empty() && anchor_ids.iter().any(|x| x == id) { issues.push(format!("duplicate_anchor:{}", id)); }
183
+ if !id.is_empty() { anchor_ids.push(id.to_string()); }
184
+ let image_id = anchor.get("image_id").and_then(|v| v.as_str()).unwrap_or("");
185
+ if image_id.is_empty() || !image_ids.iter().any(|x| x == image_id) { issues.push(format!("anchor_image_ref:{}", if id.is_empty() { "unknown" } else { id })); }
186
+ let image = images.iter().find(|img| img.get("id").and_then(|v| v.as_str()) == Some(image_id));
187
+ let w = image.and_then(|img| img.get("width")).and_then(|v| v.as_f64()).unwrap_or(f64::NAN);
188
+ let h = image.and_then(|img| img.get("height")).and_then(|v| v.as_f64()).unwrap_or(f64::NAN);
189
+ match anchor.get("bbox").and_then(|v| v.as_array()) {
190
+ Some(bbox) if bbox.len() == 4 => {
191
+ let vals: Vec<f64> = bbox.iter().map(|v| v.as_f64().unwrap_or(f64::NAN)).collect();
192
+ if vals.iter().any(|n| !n.is_finite()) { issues.push(format!("bbox_number:{}", if id.is_empty() { "unknown" } else { id })); }
193
+ if vals[2] <= 0.0 || vals[3] <= 0.0 { issues.push(format!("bbox_positive:{}", if id.is_empty() { "unknown" } else { id })); }
194
+ if w.is_finite() && vals[0] + vals[2] > w {
195
+ issues.push(format!("bbox_width_out_of_bounds:{}", if id.is_empty() { "unknown" } else { id }));
196
+ }
197
+ if h.is_finite() && vals[1] + vals[3] > h {
198
+ issues.push(format!("bbox_height_out_of_bounds:{}", if id.is_empty() { "unknown" } else { id }));
199
+ }
200
+ }
201
+ Some(_) => issues.push(format!("bbox_shape:{}", if id.is_empty() { "unknown" } else { id })),
202
+ None => issues.push(format!("anchor_bbox:{}", if id.is_empty() { "unknown" } else { id })),
203
+ }
204
+ }
205
+ for relation in &relations {
206
+ if let Some(before) = relation.get("before_image_id").and_then(|v| v.as_str()) {
207
+ if !image_ids.iter().any(|x| x == before) { issues.push(format!("relation_before:{}", before)); }
208
+ }
209
+ if let Some(after) = relation.get("after_image_id").and_then(|v| v.as_str()) {
210
+ if !image_ids.iter().any(|x| x == after) { issues.push(format!("relation_after:{}", after)); }
178
211
  }
179
- if in_string { continue; }
180
- if ch == '[' { depth += 1; }
181
- else if ch == ']' {
182
- depth -= 1;
183
- if depth == 0 { break; }
212
+ let changed = relation.get("changed_anchor_ids").or_else(|| relation.get("anchors")).and_then(|v| v.as_array()).cloned().unwrap_or_default();
213
+ for anchor_id in changed.iter().filter_map(|v| v.as_str()) {
214
+ if !anchor_ids.iter().any(|x| x == anchor_id) { issues.push(format!("relation_anchor:{}", anchor_id)); }
184
215
  }
185
- else if ch == '{' && depth == 1 { entries += 1; }
186
216
  }
187
- entries
217
+ issues.sort();
218
+ issues.dedup();
219
+ let ok = issues.is_empty();
220
+ let issue_json = issues.iter().map(|x| format!("\"{}\"", json_escape(x))).collect::<Vec<_>>().join(",");
221
+ format!("{{\"ok\":{},\"engine\":\"rust\",\"schema\":\"sks.image-voxel-ledger.v1\",\"images\":{},\"anchors\":{},\"relations\":{},\"issues\":[{}]}}", if ok { "true" } else { "false" }, images.len(), anchors.len(), relations.len(), issue_json)
188
222
  }
189
223
 
190
224
  fn json_escape(value: &str) -> String {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "0.9.13",
4
+ "version": "0.9.14",
5
5
  "description": "Sneakoscope Codex: fast proof-first Codex trust layer with image-based Voxel TriWiki.",
6
6
  "type": "module",
7
7
  "homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
@@ -37,22 +37,25 @@
37
37
  "postinstall": "node ./bin/sks.mjs postinstall",
38
38
  "selftest": "node ./bin/sks.mjs selftest --mock",
39
39
  "doctor": "node ./bin/sks.mjs doctor",
40
- "packcheck": "find bin src scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check",
40
+ "packcheck": "find bin src scripts test -name '*.mjs' -print0 | xargs -0 -n1 node --check",
41
41
  "changelog:check": "node ./scripts/changelog-check.mjs",
42
42
  "cli-entrypoint:check": "node ./scripts/check-cli-entrypoint.mjs",
43
- "legacy-budget:check": "node ./scripts/check-legacy-budget.mjs",
43
+ "legacy-free:check": "node ./scripts/check-legacy-free.mjs",
44
44
  "sizecheck": "node ./scripts/sizecheck.mjs",
45
45
  "registry:check": "node ./scripts/release-registry-check.mjs",
46
46
  "feature:check": "node ./bin/sks.mjs features check --json",
47
47
  "all-features:selftest": "node ./bin/sks.mjs all-features selftest --mock --json",
48
- "all-features:execute-fixtures": "node ./bin/sks.mjs all-features selftest --mock --execute-fixtures --json",
48
+ "all-features:execute-fixtures": "node ./bin/sks.mjs all-features selftest --mock --execute-fixtures --strict-artifacts --json",
49
49
  "perf:cold-start": "node ./bin/sks.mjs perf cold-start --json",
50
50
  "perf:gate": "node ./scripts/perf-gate.mjs",
51
51
  "test": "node --test \"test/**/*.test.mjs\"",
52
52
  "test:unit": "node --test \"test/unit/**/*.test.mjs\"",
53
53
  "test:integration:mock": "node --test \"test/integration/**/*.test.mjs\"",
54
+ "test:e2e:mock": "node --test \"test/e2e/**/*.test.mjs\"",
55
+ "rust:check": "cargo check --manifest-path crates/sks-core/Cargo.toml",
56
+ "rust:smoke": "node ./scripts/rust-smoke.mjs",
54
57
  "coverage": "node --experimental-test-coverage --test \"test/**/*.test.mjs\"",
55
- "release:check": "npm run repo-audit && npm run changelog:check && npm run cli-entrypoint:check && npm run legacy-budget:check && npm run packcheck && npm run feature:check && npm run all-features:selftest && npm run all-features:execute-fixtures && npm run selftest && npm run test:unit && npm run test:integration:mock && npm run perf:gate && npm run sizecheck && npm run registry:check",
58
+ "release:check": "npm run repo-audit && npm run changelog:check && npm run cli-entrypoint:check && npm run legacy-free:check && npm run packcheck && npm run feature:check && npm run all-features:selftest && npm run all-features:execute-fixtures && npm run selftest && npm run test:unit && npm run test:integration:mock && npm run test:e2e:mock && npm run rust:check && npm run rust:smoke && npm run perf:gate && npm run sizecheck && npm run registry:check",
56
59
  "publish:dry": "npm run release:check && npm --cache /tmp/sks-npm-cache publish --dry-run --registry https://registry.npmjs.org/ --access public",
57
60
  "publish:npm": "npm --cache /tmp/sks-npm-cache publish --registry https://registry.npmjs.org/ --access public",
58
61
  "prepublishOnly": "npm run release:check && node ./scripts/release-registry-check.mjs --require-unpublished"
@@ -1,126 +1,85 @@
1
- const legacy = () => import('./legacy-main.mjs');
2
-
3
1
  export const COMMANDS = {
4
- help: {
5
- maturity: 'stable',
6
- summary: 'Show SKS help',
7
- lazy: () => import('../commands/help.mjs')
8
- },
9
- version: {
10
- maturity: 'stable',
11
- summary: 'Show SKS version',
12
- lazy: () => import('../commands/version.mjs')
13
- },
14
- commands: {
15
- maturity: 'stable',
16
- summary: 'List SKS commands',
17
- lazy: () => import('../commands/help.mjs')
18
- },
19
- root: {
20
- maturity: 'stable',
21
- summary: 'Show active SKS root',
22
- lazy: () => import('../commands/root.mjs')
23
- },
24
- features: {
25
- maturity: 'beta',
26
- summary: 'Validate feature registry',
27
- lazy: () => import('../commands/features.mjs')
28
- },
29
- 'all-features': {
30
- maturity: 'beta',
31
- summary: 'Run all-features selftest',
32
- lazy: () => import('../commands/all-features.mjs')
33
- },
34
- hooks: {
35
- maturity: 'beta',
36
- summary: 'Explain and inspect Codex hooks',
37
- lazy: () => import('../commands/hooks.mjs')
38
- },
39
- proof: {
40
- maturity: 'beta',
41
- summary: 'Show and validate completion proof',
42
- lazy: () => import('../commands/proof.mjs')
43
- },
44
- wiki: {
45
- maturity: 'beta',
46
- summary: 'Manage TriWiki and image voxel ledgers',
47
- lazy: () => import('../commands/wiki.mjs')
48
- },
49
- perf: {
50
- maturity: 'beta',
51
- summary: 'Run performance checks',
52
- lazy: () => import('../commands/perf.mjs')
53
- },
54
- 'codex-lb': {
55
- maturity: 'beta',
56
- summary: 'Inspect codex-lb status and circuit health',
57
- lazy: () => import('../commands/codex-lb.mjs')
58
- },
59
- auth: {
60
- maturity: 'beta',
61
- summary: 'Alias for codex-lb auth commands',
62
- lazy: () => import('../commands/codex-lb.mjs')
63
- },
64
- postinstall: { maturity: 'stable', summary: 'Run postinstall bootstrap', lazy: legacy },
65
- wizard: { maturity: 'stable', summary: 'Open setup wizard', lazy: legacy },
66
- ui: { maturity: 'stable', summary: 'Open setup UI', lazy: legacy },
67
- 'update-check': { maturity: 'stable', summary: 'Check npm package freshness', lazy: legacy },
68
- usage: { maturity: 'stable', summary: 'Show focused usage topic', lazy: legacy },
69
- quickstart: { maturity: 'stable', summary: 'Show quickstart flow', lazy: legacy },
70
- 'codex-app': { maturity: 'beta', summary: 'Check Codex App readiness', lazy: () => import('../commands/codex-app.mjs') },
71
- openclaw: { maturity: 'labs', summary: 'Create OpenClaw skill package', lazy: legacy },
72
- bootstrap: { maturity: 'stable', summary: 'Initialize SKS project files', lazy: legacy },
73
- deps: { maturity: 'stable', summary: 'Check or install local dependencies', lazy: legacy },
74
- 'qa-loop': { maturity: 'beta', summary: 'Run QA loop missions', lazy: legacy },
75
- ppt: { maturity: 'labs', summary: 'Inspect/build PPT artifacts', lazy: legacy },
76
- 'image-ux-review': { maturity: 'labs', summary: 'Inspect image UX artifacts', lazy: legacy },
77
- 'ux-review': { maturity: 'labs', summary: 'Alias for image UX review', lazy: legacy },
78
- 'visual-review': { maturity: 'labs', summary: 'Alias for image UX review', lazy: legacy },
79
- 'ui-ux-review': { maturity: 'labs', summary: 'Alias for image UX review', lazy: legacy },
80
- context7: { maturity: 'beta', summary: 'Context7 checks and docs', lazy: legacy },
81
- recallpulse: { maturity: 'labs', summary: 'RecallPulse evidence route', lazy: legacy },
82
- pipeline: { maturity: 'beta', summary: 'Inspect pipeline missions', lazy: legacy },
83
- guard: { maturity: 'beta', summary: 'Check harness guard', lazy: legacy },
84
- conflicts: { maturity: 'beta', summary: 'Check harness conflicts', lazy: legacy },
85
- versioning: { maturity: 'stable', summary: 'Manage release version metadata', lazy: legacy },
86
- reasoning: { maturity: 'labs', summary: 'Show reasoning route', lazy: legacy },
87
- aliases: { maturity: 'stable', summary: 'Show command aliases', lazy: legacy },
88
- setup: { maturity: 'stable', summary: 'Initialize SKS state', lazy: legacy },
89
- 'fix-path': { maturity: 'stable', summary: 'Repair hook command paths', lazy: legacy },
2
+ help: { maturity: 'stable', summary: 'Show SKS help', lazy: () => import('../commands/help.mjs') },
3
+ version: { maturity: 'stable', summary: 'Show SKS version', lazy: () => import('../commands/version.mjs') },
4
+ commands: { maturity: 'stable', summary: 'List SKS commands', lazy: () => import('../commands/commands.mjs') },
5
+ root: { maturity: 'stable', summary: 'Show active SKS root', lazy: () => import('../commands/root.mjs') },
6
+ 'update-check': { maturity: 'stable', summary: 'Check npm package freshness', lazy: () => import('../commands/update-check.mjs') },
7
+ wizard: { maturity: 'stable', summary: 'Open setup wizard help', lazy: () => import('../commands/quickstart.mjs') },
8
+ usage: { maturity: 'stable', summary: 'Show focused usage topic', lazy: () => import('../commands/usage.mjs') },
9
+ quickstart: { maturity: 'stable', summary: 'Show quickstart flow', lazy: () => import('../commands/quickstart.mjs') },
10
+ setup: { maturity: 'stable', summary: 'Initialize SKS state', lazy: () => import('../commands/setup.mjs') },
11
+ bootstrap: { maturity: 'stable', summary: 'Initialize SKS project files', lazy: () => import('../commands/bootstrap.mjs') },
12
+ init: { maturity: 'stable', summary: 'Initialize local control surface', lazy: () => import('../commands/init.mjs') },
13
+ deps: { maturity: 'stable', summary: 'Check local dependencies', lazy: () => import('../commands/deps.mjs') },
14
+ 'fix-path': { maturity: 'stable', summary: 'Repair hook command paths', lazy: () => import('../commands/fix-path.mjs') },
90
15
  doctor: { maturity: 'stable', summary: 'Check and repair SKS install', lazy: () => import('../commands/doctor.mjs') },
91
- init: { maturity: 'stable', summary: 'Initialize local control surface', lazy: legacy },
92
- selftest: { maturity: 'stable', summary: 'Run local mock selftest', lazy: legacy },
93
- goal: { maturity: 'beta', summary: 'Manage Goal bridge workflow', lazy: legacy },
94
- research: { maturity: 'labs', summary: 'Run research missions', lazy: legacy },
95
- hook: { maturity: 'beta', summary: 'Codex hook entrypoint', lazy: legacy },
96
- profile: { maturity: 'labs', summary: 'Inspect/set profile', lazy: legacy },
97
- hproof: { maturity: 'beta', summary: 'Evaluate H-Proof gate', lazy: legacy },
98
- 'validate-artifacts': { maturity: 'beta', summary: 'Validate mission artifacts', lazy: legacy },
99
- 'proof-field': { maturity: 'beta', summary: 'Scan proof field', lazy: legacy },
100
- 'skill-dream': { maturity: 'labs', summary: 'Track skill dream counters', lazy: legacy },
101
- 'code-structure': { maturity: 'labs', summary: 'Scan source structure', lazy: legacy },
102
- memory: { maturity: 'labs', summary: 'Run retention checks', lazy: legacy },
103
- gx: { maturity: 'labs', summary: 'Render/validate GX cartridges', lazy: legacy },
104
- team: { maturity: 'beta', summary: 'Create and observe Team missions', lazy: legacy },
16
+ postinstall: { maturity: 'stable', summary: 'Run postinstall bootstrap', lazy: () => import('../commands/postinstall.mjs') },
17
+ 'codex-app': { maturity: 'beta', summary: 'Check Codex App readiness', lazy: () => import('../commands/codex-app.mjs') },
18
+ 'codex-lb': { maturity: 'beta', summary: 'Inspect codex-lb status and circuit health', lazy: () => import('../commands/codex-lb.mjs') },
19
+ auth: { maturity: 'beta', summary: 'Alias for codex-lb auth commands', lazy: () => import('../commands/codex-lb.mjs') },
20
+ hooks: { maturity: 'beta', summary: 'Explain and inspect Codex hooks', lazy: () => import('../commands/hooks.mjs') },
21
+ openclaw: { maturity: 'labs', summary: 'Create OpenClaw skill package', lazy: () => import('../commands/openclaw.mjs') },
22
+ tmux: { maturity: 'beta', summary: 'Open/check SKS tmux UI', lazy: () => import('../commands/tmux.mjs') },
23
+ mad: { maturity: 'beta', summary: 'MAD-SKS tmux permission launcher', lazy: () => import('../commands/mad-sks.mjs') },
24
+ 'mad-sks': { maturity: 'beta', summary: 'MAD-SKS scoped permission modifier', lazy: () => import('../commands/mad-sks.mjs') },
25
+ 'auto-review': { maturity: 'beta', summary: 'Manage auto-review profile', lazy: () => import('../commands/auto-review.mjs') },
26
+ autoreview: { maturity: 'beta', summary: 'Alias for auto-review', lazy: () => import('../commands/auto-review.mjs') },
27
+ 'dollar-commands': { maturity: 'stable', summary: 'List Codex App dollar commands', lazy: () => import('../commands/dollar-commands.mjs') },
28
+ dollars: { maturity: 'stable', summary: 'Alias for dollar-commands', lazy: () => import('../commands/dollar-commands.mjs') },
29
+ '$': { maturity: 'stable', summary: 'Alias for dollar-commands', lazy: () => import('../commands/dollar-commands.mjs') },
30
+ commit: { maturity: 'stable', summary: 'Create a simple git commit', lazy: () => import('../commands/commit.mjs') },
31
+ 'commit-and-push': { maturity: 'stable', summary: 'Create a simple git commit and push', lazy: () => import('../commands/commit-and-push.mjs') },
32
+ dfix: { maturity: 'stable', summary: 'Explain DFix route', lazy: () => import('../commands/dfix.mjs') },
33
+ team: { maturity: 'beta', summary: 'Create and observe Team missions', lazy: () => import('../commands/team.mjs') },
34
+ 'qa-loop': { maturity: 'beta', summary: 'Run QA loop missions', lazy: () => import('../commands/qa-loop.mjs') },
35
+ research: { maturity: 'labs', summary: 'Run research missions', lazy: () => import('../commands/research.mjs') },
36
+ autoresearch: { maturity: 'labs', summary: 'Alias for research/autoresearch route', lazy: () => import('../commands/autoresearch.mjs') },
37
+ ppt: { maturity: 'labs', summary: 'Inspect/build PPT artifacts', lazy: () => import('../commands/ppt.mjs') },
38
+ 'image-ux-review': { maturity: 'labs', summary: 'Inspect image UX artifacts', lazy: () => import('../commands/image-ux-review.mjs') },
39
+ 'ux-review': { maturity: 'labs', summary: 'Alias for image UX review', lazy: () => import('../commands/image-ux-review.mjs') },
40
+ 'visual-review': { maturity: 'labs', summary: 'Alias for image UX review', lazy: () => import('../commands/image-ux-review.mjs') },
41
+ 'ui-ux-review': { maturity: 'labs', summary: 'Alias for image UX review', lazy: () => import('../commands/image-ux-review.mjs') },
42
+ 'computer-use': { maturity: 'beta', summary: 'Record Computer Use visual evidence', lazy: () => import('../commands/computer-use.mjs') },
43
+ cu: { maturity: 'beta', summary: 'Alias for Computer Use', lazy: () => import('../commands/computer-use.mjs') },
44
+ context7: { maturity: 'beta', summary: 'Context7 checks and docs', lazy: () => import('../commands/context7.mjs') },
45
+ recallpulse: { maturity: 'labs', summary: 'RecallPulse evidence route', lazy: () => import('../commands/recallpulse.mjs') },
46
+ pipeline: { maturity: 'beta', summary: 'Inspect pipeline missions', lazy: () => import('../commands/pipeline.mjs') },
47
+ guard: { maturity: 'beta', summary: 'Check harness guard', lazy: () => import('../commands/guard.mjs') },
48
+ conflicts: { maturity: 'beta', summary: 'Check harness conflicts', lazy: () => import('../commands/conflicts.mjs') },
49
+ versioning: { maturity: 'stable', summary: 'Manage release version metadata', lazy: () => import('../commands/versioning.mjs') },
50
+ reasoning: { maturity: 'labs', summary: 'Show reasoning route', lazy: () => import('../commands/reasoning.mjs') },
51
+ aliases: { maturity: 'stable', summary: 'Show command aliases', lazy: () => import('../commands/aliases.mjs') },
52
+ selftest: { maturity: 'stable', summary: 'Run local mock selftest', lazy: () => import('../commands/selftest.mjs') },
53
+ goal: { maturity: 'beta', summary: 'Manage Goal bridge workflow', lazy: () => import('../commands/goal.mjs') },
54
+ hook: { maturity: 'beta', summary: 'Codex hook entrypoint', lazy: () => import('../commands/hook.mjs') },
55
+ profile: { maturity: 'labs', summary: 'Inspect/set profile', lazy: () => import('../commands/profile.mjs') },
56
+ hproof: { maturity: 'beta', summary: 'Evaluate H-Proof gate', lazy: () => import('../commands/hproof.mjs') },
57
+ 'validate-artifacts': { maturity: 'beta', summary: 'Validate mission artifacts', lazy: () => import('../commands/validate-artifacts.mjs') },
58
+ proof: { maturity: 'beta', summary: 'Show and validate completion proof', lazy: () => import('../commands/proof.mjs') },
59
+ 'proof-field': { maturity: 'beta', summary: 'Scan proof field', lazy: () => import('../commands/proof-field.mjs') },
60
+ 'skill-dream': { maturity: 'labs', summary: 'Track skill dream counters', lazy: () => import('../commands/skill-dream.mjs') },
61
+ 'code-structure': { maturity: 'labs', summary: 'Scan source structure', lazy: () => import('../commands/code-structure.mjs') },
62
+ memory: { maturity: 'labs', summary: 'Run retention checks', lazy: () => import('../commands/memory.mjs') },
63
+ gx: { maturity: 'labs', summary: 'Render/validate GX cartridges', lazy: () => import('../commands/gx.mjs') },
105
64
  db: { maturity: 'beta', summary: 'Inspect DB safety policy', lazy: () => import('../commands/db.mjs') },
106
- eval: { maturity: 'labs', summary: 'Run eval reports', lazy: legacy },
107
- harness: { maturity: 'labs', summary: 'Run harness fixtures', lazy: legacy },
108
- gc: { maturity: 'labs', summary: 'Compact/prune runtime state', lazy: legacy },
109
- stats: { maturity: 'labs', summary: 'Show storage stats', lazy: legacy },
110
- tmux: { maturity: 'beta', summary: 'Open/check SKS tmux UI', lazy: legacy },
111
- 'auto-review': { maturity: 'beta', summary: 'Manage auto-review profile', lazy: legacy },
112
- autoreview: { maturity: 'beta', summary: 'Alias for auto-review', lazy: legacy },
113
- 'dollar-commands': { maturity: 'stable', summary: 'List Codex App dollar commands', lazy: legacy },
114
- dollars: { maturity: 'stable', summary: 'Alias for dollar-commands', lazy: legacy },
115
- '$': { maturity: 'stable', summary: 'Alias for dollar-commands', lazy: legacy },
116
- dfix: { maturity: 'stable', summary: 'Explain DFix route', lazy: legacy }
65
+ eval: { maturity: 'labs', summary: 'Run eval reports', lazy: () => import('../commands/eval.mjs') },
66
+ harness: { maturity: 'labs', summary: 'Run harness fixtures', lazy: () => import('../commands/harness.mjs') },
67
+ wiki: { maturity: 'beta', summary: 'Manage TriWiki and image voxel ledgers', lazy: () => import('../commands/wiki.mjs') },
68
+ gc: { maturity: 'labs', summary: 'Compact/prune runtime state', lazy: () => import('../commands/gc.mjs') },
69
+ stats: { maturity: 'labs', summary: 'Show storage stats', lazy: () => import('../commands/stats.mjs') },
70
+ features: { maturity: 'beta', summary: 'Validate feature registry', lazy: () => import('../commands/features.mjs') },
71
+ 'all-features': { maturity: 'beta', summary: 'Run all-features selftest', lazy: () => import('../commands/all-features.mjs') },
72
+ perf: { maturity: 'beta', summary: 'Run performance checks', lazy: () => import('../commands/perf.mjs') }
117
73
  };
118
74
 
119
75
  export const COMMAND_ALIASES = {
120
76
  '--help': 'help',
121
77
  '-h': 'help',
122
78
  '--version': 'version',
123
- '-v': 'version'
79
+ '-v': 'version',
80
+ '--mad': 'mad',
81
+ '--MAD': 'mad',
82
+ '--mad-sks': 'mad-sks'
124
83
  };
125
84
 
126
85
  export function commandNames() {