aimx 0.3.2__tar.gz → 0.3.3__tar.gz

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 (115) hide show
  1. aimx-0.3.3/.agents/skills/aimx/SKILL.md +281 -0
  2. aimx-0.3.3/.agents/skills/aimx/references/aimx-cli.md +642 -0
  3. {aimx-0.3.2 → aimx-0.3.3}/.gitignore +2 -0
  4. {aimx-0.3.2 → aimx-0.3.3}/AGENTS.md +2 -0
  5. {aimx-0.3.2 → aimx-0.3.3}/PKG-INFO +26 -1
  6. {aimx-0.3.2 → aimx-0.3.3}/README.md +25 -0
  7. {aimx-0.3.2 → aimx-0.3.3}/pyproject.toml +1 -1
  8. aimx-0.3.3/specs/005-distribution-trace-visual/checklists/requirements.md +36 -0
  9. aimx-0.3.3/specs/005-distribution-trace-visual/contracts/cli-output.md +141 -0
  10. aimx-0.3.3/specs/005-distribution-trace-visual/data-model.md +184 -0
  11. aimx-0.3.3/specs/005-distribution-trace-visual/plan.md +161 -0
  12. aimx-0.3.3/specs/005-distribution-trace-visual/quickstart.md +155 -0
  13. aimx-0.3.3/specs/005-distribution-trace-visual/research.md +121 -0
  14. aimx-0.3.3/specs/005-distribution-trace-visual/spec.md +119 -0
  15. aimx-0.3.3/specs/005-distribution-trace-visual/tasks.md +241 -0
  16. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/__init__.py +1 -1
  17. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/aim_bridge/metric_stats.py +154 -0
  18. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/commands/help.py +6 -1
  19. aimx-0.3.3/src/aimx/commands/trace.py +320 -0
  20. aimx-0.3.3/src/aimx/rendering/trace_views.py +512 -0
  21. aimx-0.3.3/static/distributions.png +0 -0
  22. aimx-0.3.3/tests/contract/test_trace_contract.py +228 -0
  23. aimx-0.3.3/tests/integration/test_trace_command.py +334 -0
  24. {aimx-0.3.2 → aimx-0.3.3}/tests/unit/test_metric_stats.py +52 -0
  25. aimx-0.3.3/tests/unit/test_trace_distribution_views.py +244 -0
  26. aimx-0.3.3/tests/unit/test_trace_helpers.py +291 -0
  27. {aimx-0.3.2 → aimx-0.3.3}/uv.lock +1 -1
  28. aimx-0.3.2/.agents/skills/aimx/SKILL.md +0 -123
  29. aimx-0.3.2/.agents/skills/aimx/references/aimx-cli.md +0 -233
  30. aimx-0.3.2/src/aimx/commands/trace.py +0 -203
  31. aimx-0.3.2/src/aimx/rendering/trace_views.py +0 -168
  32. aimx-0.3.2/tests/contract/test_trace_contract.py +0 -77
  33. aimx-0.3.2/tests/integration/test_trace_command.py +0 -106
  34. aimx-0.3.2/tests/unit/test_trace_helpers.py +0 -111
  35. {aimx-0.3.2 → aimx-0.3.3}/.agents/skills/aimx/agents/openai.yaml +0 -0
  36. {aimx-0.3.2 → aimx-0.3.3}/.agents/skills/aimx/scripts/collect_experiment_snapshot.py +0 -0
  37. {aimx-0.3.2 → aimx-0.3.3}/.codex/hooks.json +0 -0
  38. {aimx-0.3.2 → aimx-0.3.3}/.github/workflows/CI.yaml +0 -0
  39. {aimx-0.3.2 → aimx-0.3.3}/.github/workflows/publish.yaml +0 -0
  40. {aimx-0.3.2 → aimx-0.3.3}/.python-version +0 -0
  41. {aimx-0.3.2 → aimx-0.3.3}/CLAUDE.md +0 -0
  42. {aimx-0.3.2 → aimx-0.3.3}/CONSTITUTION.md +0 -0
  43. {aimx-0.3.2 → aimx-0.3.3}/LICENSE +0 -0
  44. {aimx-0.3.2 → aimx-0.3.3}/TODO.md +0 -0
  45. {aimx-0.3.2 → aimx-0.3.3}/specs/001-aim-command-passthrough/checklists/requirements.md +0 -0
  46. {aimx-0.3.2 → aimx-0.3.3}/specs/001-aim-command-passthrough/contracts/cli-contract.md +0 -0
  47. {aimx-0.3.2 → aimx-0.3.3}/specs/001-aim-command-passthrough/data-model.md +0 -0
  48. {aimx-0.3.2 → aimx-0.3.3}/specs/001-aim-command-passthrough/plan.md +0 -0
  49. {aimx-0.3.2 → aimx-0.3.3}/specs/001-aim-command-passthrough/quickstart.md +0 -0
  50. {aimx-0.3.2 → aimx-0.3.3}/specs/001-aim-command-passthrough/research.md +0 -0
  51. {aimx-0.3.2 → aimx-0.3.3}/specs/001-aim-command-passthrough/spec.md +0 -0
  52. {aimx-0.3.2 → aimx-0.3.3}/specs/001-aim-command-passthrough/tasks.md +0 -0
  53. {aimx-0.3.2 → aimx-0.3.3}/specs/002-aim-query-command/checklists/requirements.md +0 -0
  54. {aimx-0.3.2 → aimx-0.3.3}/specs/002-aim-query-command/contracts/query-command.md +0 -0
  55. {aimx-0.3.2 → aimx-0.3.3}/specs/002-aim-query-command/data-model.md +0 -0
  56. {aimx-0.3.2 → aimx-0.3.3}/specs/002-aim-query-command/plan.md +0 -0
  57. {aimx-0.3.2 → aimx-0.3.3}/specs/002-aim-query-command/quickstart.md +0 -0
  58. {aimx-0.3.2 → aimx-0.3.3}/specs/002-aim-query-command/research.md +0 -0
  59. {aimx-0.3.2 → aimx-0.3.3}/specs/002-aim-query-command/spec.md +0 -0
  60. {aimx-0.3.2 → aimx-0.3.3}/specs/002-aim-query-command/tasks.md +0 -0
  61. {aimx-0.3.2 → aimx-0.3.3}/specs/003-query-images-terminal-render/checklists/requirements.md +0 -0
  62. {aimx-0.3.2 → aimx-0.3.3}/specs/003-query-images-terminal-render/contracts/cli-output.md +0 -0
  63. {aimx-0.3.2 → aimx-0.3.3}/specs/003-query-images-terminal-render/data-model.md +0 -0
  64. {aimx-0.3.2 → aimx-0.3.3}/specs/003-query-images-terminal-render/plan.md +0 -0
  65. {aimx-0.3.2 → aimx-0.3.3}/specs/003-query-images-terminal-render/quickstart.md +0 -0
  66. {aimx-0.3.2 → aimx-0.3.3}/specs/003-query-images-terminal-render/research.md +0 -0
  67. {aimx-0.3.2 → aimx-0.3.3}/specs/003-query-images-terminal-render/spec.md +0 -0
  68. {aimx-0.3.2 → aimx-0.3.3}/specs/003-query-images-terminal-render/tasks.md +0 -0
  69. {aimx-0.3.2 → aimx-0.3.3}/specs/004-run-params-query/checklists/requirements.md +0 -0
  70. {aimx-0.3.2 → aimx-0.3.3}/specs/004-run-params-query/contracts/cli-output.md +0 -0
  71. {aimx-0.3.2 → aimx-0.3.3}/specs/004-run-params-query/data-model.md +0 -0
  72. {aimx-0.3.2 → aimx-0.3.3}/specs/004-run-params-query/plan.md +0 -0
  73. {aimx-0.3.2 → aimx-0.3.3}/specs/004-run-params-query/quickstart.md +0 -0
  74. {aimx-0.3.2 → aimx-0.3.3}/specs/004-run-params-query/research.md +0 -0
  75. {aimx-0.3.2 → aimx-0.3.3}/specs/004-run-params-query/spec.md +0 -0
  76. {aimx-0.3.2 → aimx-0.3.3}/specs/004-run-params-query/tasks.md +0 -0
  77. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/__main__.py +0 -0
  78. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/aim_bridge/__init__.py +0 -0
  79. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/aim_bridge/hash_resolver.py +0 -0
  80. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/aim_bridge/run_params.py +0 -0
  81. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/cli.py +0 -0
  82. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/commands/__init__.py +0 -0
  83. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/commands/doctor.py +0 -0
  84. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/commands/query.py +0 -0
  85. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/commands/version.py +0 -0
  86. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/native_aim/__init__.py +0 -0
  87. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/native_aim/locator.py +0 -0
  88. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/native_aim/passthrough.py +0 -0
  89. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/rendering/__init__.py +0 -0
  90. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/rendering/colors.py +0 -0
  91. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/rendering/image_render.py +0 -0
  92. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/rendering/params_views.py +0 -0
  93. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/rendering/query_views.py +0 -0
  94. {aimx-0.3.2 → aimx-0.3.3}/src/aimx/router.py +0 -0
  95. {aimx-0.3.2 → aimx-0.3.3}/static/images.png +0 -0
  96. {aimx-0.3.2 → aimx-0.3.3}/static/metrics.png +0 -0
  97. {aimx-0.3.2 → aimx-0.3.3}/static/params.png +0 -0
  98. {aimx-0.3.2 → aimx-0.3.3}/static/trace.png +0 -0
  99. {aimx-0.3.2 → aimx-0.3.3}/tests/conftest.py +0 -0
  100. {aimx-0.3.2 → aimx-0.3.3}/tests/contract/test_cli_contract.py +0 -0
  101. {aimx-0.3.2 → aimx-0.3.3}/tests/contract/test_query_contract.py +0 -0
  102. {aimx-0.3.2 → aimx-0.3.3}/tests/integration/conftest.py +0 -0
  103. {aimx-0.3.2 → aimx-0.3.3}/tests/integration/test_missing_native_aim.py +0 -0
  104. {aimx-0.3.2 → aimx-0.3.3}/tests/integration/test_missing_python_aim_package.py +0 -0
  105. {aimx-0.3.2 → aimx-0.3.3}/tests/integration/test_passthrough_behavior.py +0 -0
  106. {aimx-0.3.2 → aimx-0.3.3}/tests/integration/test_query_command.py +0 -0
  107. {aimx-0.3.2 → aimx-0.3.3}/tests/integration/test_short_hash_and_steps.py +0 -0
  108. {aimx-0.3.2 → aimx-0.3.3}/tests/unit/test_hash_resolver.py +0 -0
  109. {aimx-0.3.2 → aimx-0.3.3}/tests/unit/test_image_render.py +0 -0
  110. {aimx-0.3.2 → aimx-0.3.3}/tests/unit/test_locator.py +0 -0
  111. {aimx-0.3.2 → aimx-0.3.3}/tests/unit/test_owned_commands.py +0 -0
  112. {aimx-0.3.2 → aimx-0.3.3}/tests/unit/test_query_helpers.py +0 -0
  113. {aimx-0.3.2 → aimx-0.3.3}/tests/unit/test_router.py +0 -0
  114. {aimx-0.3.2 → aimx-0.3.3}/tests/unit/test_run_params.py +0 -0
  115. {aimx-0.3.2 → aimx-0.3.3}/tests/unit/test_step_filter.py +0 -0
@@ -0,0 +1,281 @@
1
+ ---
2
+ name: aimx
3
+ description: Use when autoresearch, log_experiment, experiment analysis, or automatic iteration workflows need to inspect local Aim repositories with aimx, collect run params, metric summaries, traces, image evidence, compare training runs, or summarize model results without mutating Aim data.
4
+ ---
5
+
6
+ # Aimx
7
+
8
+ ## Overview
9
+
10
+ Use `aimx` as a read-only evidence collector for `autoresearch` `log_experiment`
11
+ steps. Prefer JSON output so downstream agents can compare runs, explain model
12
+ effects, and propose the next experiment from concrete Aim data.
13
+
14
+ ## Fast Recipes
15
+
16
+ Use these first for common analysis tasks. Keep `--repo` explicit and prefer
17
+ `--json` for machine-readable output.
18
+
19
+ ### Discover run scope and available params
20
+
21
+ ```bash
22
+ aimx query params "run.hash != ''" --repo <repo> --json
23
+ ```
24
+
25
+ ### Inspect one run quickly
26
+
27
+ ```bash
28
+ aimx query params "run.hash == '<run-hash>'" --repo <repo> --json
29
+ aimx query metrics "(run.hash == '<run-hash>') and metric.name != ''" --repo <repo> --json
30
+ ```
31
+
32
+ ### Rank runs by an objective metric
33
+
34
+ ```bash
35
+ aimx query metrics "(<run-scope>) and metric.name == '<metric>'" --repo <repo> --json > metrics.json
36
+ python - <<'PY'
37
+ from __future__ import annotations
38
+ import json
39
+ from pathlib import Path
40
+
41
+ payload = json.loads(Path("metrics.json").read_text())
42
+ rows = []
43
+ for run in payload.get("runs", []):
44
+ for metric in run.get("metrics", []):
45
+ value = metric.get("min", {}).get("value")
46
+ if value is not None:
47
+ rows.append((value, run.get("hash"), run.get("name"), metric.get("context", {})))
48
+ for value, run_hash, run_name, context in sorted(rows)[:5]:
49
+ print(f"{value:.6f}\t{run_hash}\t{run_name}\t{context}")
50
+ PY
51
+ ```
52
+
53
+ ### Compare two runs side by side
54
+
55
+ ```bash
56
+ aimx query params "run.hash == '<baseline-hash>' or run.hash == '<candidate-hash>'" --repo <repo> --json
57
+ aimx query metrics "((run.hash == '<baseline-hash>') or (run.hash == '<candidate-hash>')) and metric.name == '<metric>'" --repo <repo> --json
58
+ ```
59
+
60
+ ### Check curve health with bounded trace evidence
61
+
62
+ ```bash
63
+ aimx trace "(<run-scope>) and metric.name == '<metric>'" --repo <repo> --json --tail 200 > trace.json
64
+ ```
65
+
66
+ Then reduce `trace.json` with the `curve_summary` snippet from
67
+ `references/aimx-cli.md` instead of pasting raw series.
68
+
69
+ ### Sanity-check distribution traces
70
+
71
+ ```bash
72
+ aimx trace distribution "<distribution-expr>" --repo <repo> --json --tail 5
73
+ aimx trace distribution "distribution.name != ''" --repo <repo> --step 12300
74
+ ```
75
+
76
+ ### Capture one snapshot bundle for logs
77
+
78
+ ```bash
79
+ uv run python skills/aimx/scripts/collect_experiment_snapshot.py \
80
+ --repo data \
81
+ --base-expr "run.hash != ''" \
82
+ --metric loss \
83
+ --trace-metric loss \
84
+ --pretty
85
+ ```
86
+
87
+ ## When to use what
88
+
89
+ | Need | Use |
90
+ | --- | --- |
91
+ | Discover runs and key hyperparameters | `aimx query params "<run-scope>" --repo <repo> --json` |
92
+ | Rank runs cheaply by objective | `aimx query metrics "<metric-expr>" --repo <repo> --json` and compare `min.value` or `max.value` |
93
+ | Inspect curve shape and late stability | `aimx trace "<metric-expr>" --repo <repo> --json --tail N` |
94
+ | Focus on a step or epoch window | `--steps a:b` or `--epochs a:b` on query/trace commands |
95
+ | Analyze weight or gradient histograms | `aimx trace distribution "<distribution-expr>" --repo <repo> --json` |
96
+ | Collect qualitative image evidence | `aimx query images "<image-expr>" --repo <repo> --json --head N` |
97
+ | Check native Aim passthrough readiness | `aimx doctor` |
98
+
99
+ ## Requirements
100
+
101
+ - Require `aimx` in the Python environment that runs `log_experiment`.
102
+ Verify with `aimx --help` or `python -m aimx --help` before collecting data.
103
+ - When `aimx` is missing, first identify and follow the user's current
104
+ dependency-management workflow from project files and instructions
105
+ (`pyproject.toml`, lockfiles, README, AGENTS/CLAUDE/GEMINI notes, CI config).
106
+ Use that manager to add or install `aimx`. In this repository, prefer
107
+ `uv sync`, `uv run ...`, and `uv add aimx` because repo policy requires `uv`.
108
+ - If there is no project environment to modify and the user only needs a
109
+ standalone CLI, install `aimx` as a tool using the user's preferred tool
110
+ manager. Use `uv tool install aimx` only when `uv` is already the chosen or
111
+ accepted tool workflow.
112
+ - Require read access to a local Aim repository path. Pass `--repo` explicitly
113
+ and keep collection commands read-only.
114
+ - If native Aim availability matters for passthrough checks, run `aimx doctor`;
115
+ do not initialize, repair, migrate, or rewrite Aim repositories from this
116
+ skill.
117
+
118
+ ## Workflow
119
+
120
+ For common tasks, start from **Fast Recipes** and only switch to this full
121
+ workflow when the scope is unclear or the question is complex.
122
+
123
+ 1. Locate the Aim repository. Pass `--repo <repo-root-or-.aim>` explicitly; in
124
+ this repository, use `--repo data` or `--repo data/.aim` for local checks.
125
+ 2. Define the run scope as an AimQL expression. Start broad with
126
+ `run.hash != ''`, then narrow by `run.hash`, `run.experiment`, or `run.name`.
127
+ 3. Collect run parameters:
128
+
129
+ ```bash
130
+ aimx query params "<run-scope>" --repo <repo> --json
131
+ aimx query params "<run-scope>" --repo <repo> --json --param hparam.lr --param model
132
+ ```
133
+
134
+ 4. Collect metric summaries for candidate objective metrics:
135
+
136
+ ```bash
137
+ aimx query metrics "(<run-scope>) and metric.name == 'loss'" --repo <repo> --json
138
+ aimx query metrics "(<run-scope>) and metric.name != ''" --repo <repo> --json
139
+ ```
140
+
141
+ 5. Collect traces only for decisive metrics or suspected anomalies:
142
+
143
+ ```bash
144
+ aimx trace "(<run-scope>) and metric.name == 'loss'" --repo <repo> --json --tail 50
145
+ ```
146
+
147
+ 6. Inspect distribution traces when weight, activation, or gradient histograms
148
+ matter. Prefer JSON/CSV for automation; use the default visual output for
149
+ human terminal inspection.
150
+
151
+ ```bash
152
+ aimx trace distribution "<distribution-expr>" --repo <repo> --json --tail 5
153
+ aimx trace distribution "distribution.name != ''" --repo <repo> --step 12300
154
+ ```
155
+
156
+ 7. Collect image metadata when qualitative outputs matter:
157
+
158
+ ```bash
159
+ aimx query images "images" --repo <repo> --json --head 20
160
+ ```
161
+
162
+ 8. Emit a compact `log_experiment` record containing:
163
+
164
+ ```json
165
+ {
166
+ "repo": "<repo>",
167
+ "run_scope": "<AimQL>",
168
+ "params": {},
169
+ "metric_summary": {},
170
+ "trace_evidence": {},
171
+ "distribution_evidence": {},
172
+ "image_evidence": {},
173
+ "interpretation": {
174
+ "best_runs": [],
175
+ "regressions": [],
176
+ "confidence": "low|medium|high",
177
+ "next_experiments": []
178
+ }
179
+ }
180
+ ```
181
+
182
+ ## Analysis Workflow
183
+
184
+ Use the same discipline as large experiment trackers: inspect structure first,
185
+ query only the fields needed for the question, then reduce evidence into compact
186
+ statistics before writing conclusions.
187
+
188
+ 1. Start with params and metric summaries to discover candidate runs, objective
189
+ metrics, contexts, and missing fields. Avoid dumping full JSON payloads into
190
+ conversation context.
191
+ 2. Choose the objective direction explicitly. Rank cheaply from summaries first:
192
+ `min.value` for loss/error, `max.value` for accuracy/F1/AUC/IoU, and
193
+ `last.value` only when the final checkpoint is the real objective.
194
+ 3. Pull bounded traces only for the baseline, top candidates, and suspicious
195
+ runs. Prefer `--tail`, `--steps`, `--epochs`, and `--every` before collecting
196
+ full curves.
197
+ 4. Compute local stats before interpreting: best step, final-window mean/std,
198
+ train-vs-val gap, NaN/Inf counts, sustained increases, spikes, and plateaus.
199
+ 5. Compare runs side by side with selected params plus selected metrics. Do not
200
+ iterate every param or every metric unless discovery is the goal.
201
+ 6. Escalate evidence by modality: use distribution traces for weights,
202
+ activations, or gradients; use image metadata for qualitative regressions.
203
+ 7. Keep the final analysis small: state objective, run scope, top runs, curve
204
+ health, anomalies, confidence, and the next experiment suggested by evidence.
205
+
206
+ ## Critical Rules
207
+
208
+ - Discover scope first with `aimx query params "<run-scope>" --repo <repo> --json`.
209
+ Do not assume metric or param names.
210
+ - Treat `aimx` output as data: parse JSON and report aggregates, not raw payloads.
211
+ - Slice traces aggressively with `--tail`, `--head`, `--steps`, `--epochs`, or
212
+ `--every` before computing local statistics.
213
+ - Always pass `--repo` explicitly to avoid reading an unintended repository.
214
+ - For automation, use `aimx trace distribution` with `--json`, `--csv`, or
215
+ `--table`. Unflagged mode is terminal visualization for human inspection.
216
+ - Always finish with a compact conclusion: objective, top runs, curve health,
217
+ anomalies, confidence, and next experiment.
218
+
219
+ ## Interpretation Rules
220
+
221
+ - Prefer validation, test, or held-out contexts over training contexts when
222
+ ranking runs.
223
+ - Treat `aimx query metrics` as summary data: `last`, `min`, `max`, and step
224
+ counts. Use `aimx trace --json` when shape, stability, divergence, or late
225
+ improvement matters.
226
+ - Use `aimx trace distribution --json` or `--csv` for automated histogram
227
+ evidence. The unflagged distribution command is a non-interactive terminal
228
+ visual that lists matched distributions, selects the first non-empty series,
229
+ and renders a current-step histogram plus step-by-bin heatmap. `--step N`
230
+ affects only this visual mode and falls back to the nearest tracked step.
231
+ - For minimization metrics such as loss or error, compare `min.value` and the
232
+ corresponding step. For maximization metrics such as accuracy, F1, AUC, or
233
+ IoU, compare `max.value`.
234
+ - Separate incomplete or failed runs from strong results before drawing
235
+ conclusions. Very low step counts, missing params, or missing validation
236
+ metrics should reduce confidence.
237
+ - Preserve read-only behavior. Do not run commands that initialize, repair,
238
+ migrate, delete, or rewrite Aim repositories during `log_experiment`.
239
+
240
+ ## Gotchas
241
+
242
+ | Gotcha | Wrong | Right |
243
+ | --- | --- | --- |
244
+ | Missing `aimx` in environment | Assume `aimx` is available | Verify with `aimx --help` or `python -m aimx --help`, then follow project install workflow |
245
+ | Repository targeting | Rely on current directory | Pass `--repo <repo>` explicitly on every collection command |
246
+ | Summary vs curve confusion | Treat `query metrics` output as full history | Use `query metrics` for summary (`last/min/max`) and `trace --json` for curve shape |
247
+ | Raw payload dumping | Paste full JSON into conversation | Parse and compute compact aggregates before reporting |
248
+ | AimQL string quoting | `metric.name == "loss"` | `metric.name == 'loss'` |
249
+ | Short hash assumptions | Assume short hash is canonical identity | Let `aimx` expand it, but compare/store full run hash |
250
+ | Distribution output mode | Use default distribution mode in scripts | Use `--json`, `--csv`, or `--table` for automation |
251
+ | `--step` expectation | Expect `--step` to filter JSON/CSV/table exports | Use `--step` only for visual histogram mode |
252
+ | Empty trace handling | Treat non-JSON message as fatal parsing error | Treat it as no trace evidence and continue analysis |
253
+ | Full trace collection | Pull all runs and all points first | Rank by summary, then trace only baseline, top candidates, and suspicious runs |
254
+
255
+ ## Helper Script
256
+
257
+ Use `scripts/collect_experiment_snapshot.py` when an agent needs one structured
258
+ JSON bundle instead of several manual commands.
259
+
260
+ ```bash
261
+ uv run python skills/aimx/scripts/collect_experiment_snapshot.py \
262
+ --repo data \
263
+ --base-expr "run.experiment == 'cloud-segmentation'" \
264
+ --metric loss \
265
+ --trace-metric loss \
266
+ --param hparam.lr \
267
+ --param model \
268
+ --pretty
269
+ ```
270
+
271
+ The script uses the current Python interpreter as `python -m aimx` by default.
272
+ Pass `--aimx "aimx"` or `--aimx "uv run aimx"` when a different launcher is
273
+ needed. It writes only to stdout.
274
+
275
+ ## Reference
276
+
277
+ Read `references/aimx-cli.md` for command details, JSON envelope shapes, and
278
+ suggested `log_experiment` evidence fields. For deeper experiment analysis
279
+ patterns, see "Analysis Patterns", "Find best run by objective", "Spike /
280
+ divergence / plateau / NaN detection", "Overfitting detection", and "Sweep
281
+ ranking".