stata-code 0.8.1__tar.gz → 0.9.1__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.
- {stata_code-0.8.1 → stata_code-0.9.1}/.gitignore +2 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/CHANGELOG.md +217 -7
- {stata_code-0.8.1 → stata_code-0.9.1}/PKG-INFO +17 -6
- {stata_code-0.8.1 → stata_code-0.9.1}/PUBLISHING.md +16 -7
- {stata_code-0.8.1 → stata_code-0.9.1}/README.md +16 -5
- {stata_code-0.8.1 → stata_code-0.9.1}/SCHEMA.md +104 -21
- stata_code-0.9.1/docs/competitive-landscape.md +163 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/docs/industry-leader-roadmap.md +15 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/pyproject.toml +1 -1
- {stata_code-0.8.1 → stata_code-0.9.1}/schema/run_result.schema.json +284 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/__init__.py +41 -2
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/cli.py +12 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/core/__init__.py +40 -1
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/core/_pool.py +345 -103
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/core/_runtime.py +13 -2
- stata_code-0.9.1/stata_code/core/errors.py +802 -0
- stata_code-0.9.1/stata_code/core/estimation.py +377 -0
- stata_code-0.9.1/stata_code/core/handoff.py +96 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/core/log_artifacts.py +3 -1
- stata_code-0.9.1/stata_code/core/provenance.py +250 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/core/runner.py +88 -55
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/core/schema.py +96 -14
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/doctor.py +170 -13
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/kernel/kernel.py +6 -3
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/mcp/server.py +5 -2
- stata_code-0.9.1/tests/test_bugfix_regressions.py +556 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_doctor.py +99 -4
- stata_code-0.9.1/tests/test_errors.py +462 -0
- stata_code-0.9.1/tests/test_estimation.py +273 -0
- stata_code-0.9.1/tests/test_handoff.py +85 -0
- stata_code-0.9.1/tests/test_mcp_kernel_extra.py +1087 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_pool.py +22 -1
- stata_code-0.9.1/tests/test_pool_refs_extra.py +993 -0
- stata_code-0.9.1/tests/test_provenance.py +193 -0
- stata_code-0.9.1/tests/test_real_stata.py +221 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_runner.py +16 -0
- stata_code-0.9.1/tests/test_runner_helpers.py +1121 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_schema.py +39 -2
- stata_code-0.8.1/stata_code/core/errors.py +0 -456
- stata_code-0.8.1/tests/test_errors.py +0 -231
- {stata_code-0.8.1 → stata_code-0.9.1}/LICENSE +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/LICENSE-POLICY.md +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/docs/design/hard_timeout.md +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/examples/01-basic-regression.md +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/examples/02-did-card-krueger.md +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/examples/03-graphs.md +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/examples/04-multi-session.md +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/examples/05-large-matrix.md +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/examples/06-cross-stack-parity-audit.md +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/examples/07-data-mcp-handoff.md +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/examples/README.md +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/scripts/build_skill_zip.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/scripts/check_github_actions.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/scripts/check_versions.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/scripts/export_schema.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/__main__.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/core/_refs.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/core/notebook.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/core/run_index.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/kernel/__init__.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/kernel/__main__.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/kernel/assets/logo-32x32.png +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/kernel/assets/logo-64x64.png +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/kernel/assets/logo-svg.svg +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/mcp/__init__.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/stata_code/mcp/__main__.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/__init__.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/conftest.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/fixtures/.gitkeep +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_cancel.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_github_actions.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_kernel.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_log_artifacts.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_mcp.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_mcp_stdio.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_method_prompts.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_new_tools.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_notebook.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_notebook_phase2.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_public_api.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_release_versions.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_run_index.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_runtime_discovery.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_schema_artifact.py +0 -0
- {stata_code-0.8.1 → stata_code-0.9.1}/tests/test_skill_package.py +0 -0
|
@@ -4,6 +4,218 @@ All notable changes to `stata-code` are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); the project adheres
|
|
5
5
|
to semver-major.minor for the result schema (see `SCHEMA.md` §6).
|
|
6
6
|
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## 0.9.1 — 2026-07-22
|
|
10
|
+
|
|
11
|
+
Quality-hardening pass: correctness fixes from an adversarial code review,
|
|
12
|
+
a large offline test expansion, and a documentation accuracy audit. No new
|
|
13
|
+
features, no API or schema changes.
|
|
14
|
+
|
|
15
|
+
A second review round found that three of the first round's fixes were
|
|
16
|
+
incomplete or had introduced a regression of their own; those are the first
|
|
17
|
+
four entries below. The common failure was testing a fix in isolation while
|
|
18
|
+
the real call path stayed uncovered — the new tests go through `SessionPool`
|
|
19
|
+
rather than `WorkerProcess` wherever the pool is what carries the bug, and
|
|
20
|
+
each was confirmed to fail against the pre-fix source.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **A read-only status query no longer kills a healthy mid-run worker.**
|
|
25
|
+
Once `send_simple_op` learned to bail out rather than block on the worker
|
|
26
|
+
lock, that bail-out surfaced as a `_WorkerTimeout` — and
|
|
27
|
+
`SessionPool.stata_info` treated "busy" and "dead" identically: it
|
|
28
|
+
SIGTERMed the worker and dropped it from the pool. Calling the
|
|
29
|
+
`stata_info` tool during a long `bootstrap`/`reghdfe` therefore returned
|
|
30
|
+
the user's run as `adapter_crash` and wiped the session's loaded data, and
|
|
31
|
+
because the MCP layer swallows the exception the kill was invisible in the
|
|
32
|
+
tool response. Busy is now a distinct `_WorkerBusy` signal (a
|
|
33
|
+
`_WorkerTimeout` subclass, so warn-only callers are unaffected) that never
|
|
34
|
+
kills.
|
|
35
|
+
- **A timed-out read no longer steals the next request's response.** Each
|
|
36
|
+
request spawned its own `readline()` thread and abandoned it on deadline
|
|
37
|
+
overrun; the orphan stayed blocked on the pipe and consumed the *following*
|
|
38
|
+
response. The next `execute()` then burned its entire timeout (default
|
|
39
|
+
600 s) waiting for a reply that had already been eaten, after which the
|
|
40
|
+
pool killed a perfectly healthy worker. Reads now come off one long-lived
|
|
41
|
+
pump thread per worker, which cannot orphan, and responses carrying a
|
|
42
|
+
stale request id are discarded rather than mis-matched.
|
|
43
|
+
- **`send_simple_op` honors its full timeout budget.** The read deadline was
|
|
44
|
+
computed *after* acquiring the worker lock, so a call that spent most of
|
|
45
|
+
its budget waiting for the lock got a second full budget for the read —
|
|
46
|
+
worst case 2x `timeout_ms`, and `list_session_info_detailed` iterates
|
|
47
|
+
workers serially, so N busy workers stalled the status tool for
|
|
48
|
+
`2 * timeout * N`. The deadline is now fixed up front.
|
|
49
|
+
- **Repeated identical notes are no longer double-counted.** The previous
|
|
50
|
+
de-dup short-circuited before recording the matched span, so the second and
|
|
51
|
+
later copies of an identical `note:` line went unclaimed and were picked up
|
|
52
|
+
again by the generic-note pass — the exact double-count the fix was meant
|
|
53
|
+
to remove, reachable from any `foreach` loop re-running the same
|
|
54
|
+
regression.
|
|
55
|
+
- **`stata_info`'s worker eviction is identity-checked.** It popped the
|
|
56
|
+
session's worker unconditionally, so a concurrent `execute()` that had
|
|
57
|
+
already noticed the death and registered a replacement got *its* worker
|
|
58
|
+
evicted — leaking a live pystata subprocess that `request_cancel` /
|
|
59
|
+
`kill_session` / `shutdown` could no longer reach.
|
|
60
|
+
- **`kill()`'s already-dead fast path is identity-checked** too, matching its
|
|
61
|
+
own slow path: it could otherwise clear a handle a concurrent `execute()`
|
|
62
|
+
had just respawned into, stranding a live subprocess mid-request.
|
|
63
|
+
- **`TypeError` is no longer blanket-classified as a caller error.** The
|
|
64
|
+
guard wrapped the whole `execute()` call, not just argument binding, so a
|
|
65
|
+
`TypeError` raised deep inside result collection told the agent its
|
|
66
|
+
arguments were wrong when nothing was — and routed the failure out of the
|
|
67
|
+
`adapter_crash` path that would have recycled the wedged worker. Malformed
|
|
68
|
+
options are now caught by signature binding before the call; deeper
|
|
69
|
+
`TypeError`s stay in the `worker_error` bucket.
|
|
70
|
+
- **Session ids longer than Stata's 32-character name cap are mapped.** They
|
|
71
|
+
were passed through verbatim as a frame name, so `frame create` failed with
|
|
72
|
+
rc 198; they now route through the hashed mapped-frame path.
|
|
73
|
+
|
|
74
|
+
- **Worker stderr pipe is now drained continuously.** The subprocess pool
|
|
75
|
+
only read a worker's stderr after death, so a worker whose cumulative
|
|
76
|
+
stderr output (pystata banners, Stata C-side messages, warnings) exceeded
|
|
77
|
+
the ~64 KB OS pipe buffer blocked mid-write and never responded — the
|
|
78
|
+
parent then misreported the healthy worker as a `timeout` and killed it
|
|
79
|
+
(or hung forever with `timeout_ms=None`). A per-worker daemon thread now
|
|
80
|
+
drains stderr into a bounded tail buffer, which also enriches crash
|
|
81
|
+
messages.
|
|
82
|
+
- **A worker-reported failure no longer destroys the session.** A live
|
|
83
|
+
worker answering `{ok:false, error_kind:"worker_error"}` was handled like
|
|
84
|
+
a dead process: killed and dropped from the pool, wiping the session's
|
|
85
|
+
loaded dataset and `r()`/`e()` state — reachable from a mere argument
|
|
86
|
+
type typo. Such failures now surface as structured errors while the
|
|
87
|
+
worker (and the session's data) survives; the worker also classifies
|
|
88
|
+
`TypeError` as `invalid_request`.
|
|
89
|
+
- **LRU eviction skips busy workers.** `last_used` is stale for a mid-run
|
|
90
|
+
worker, so capacity pressure from an unrelated new session preferred the
|
|
91
|
+
longest-running request as its eviction victim (SIGTERM mid-run →
|
|
92
|
+
`adapter_crash`, session data lost). Eviction now skips in-flight
|
|
93
|
+
workers, bumps `last_used` at request start, and kills victims outside
|
|
94
|
+
the pool lock; timeout/error cleanup no longer removes a newer worker
|
|
95
|
+
handle registered in the interim.
|
|
96
|
+
- **Status queries no longer hang behind a long run.** `send_simple_op`
|
|
97
|
+
blocked unboundedly on the worker lock held by an in-flight `execute()`;
|
|
98
|
+
lock acquisition now counts against the same timeout budget and surfaces
|
|
99
|
+
as a per-session "busy" warning.
|
|
100
|
+
- **`rc` is taken from the last `r(NNN);` in a failure transcript.** An
|
|
101
|
+
earlier successful command echoing a literal `r(NNN);` (display string,
|
|
102
|
+
help output) previously hijacked the return code — and therefore the
|
|
103
|
+
`ErrorKind` classification, suggestions, and recovery contract.
|
|
104
|
+
- **Indented notes are no longer double-counted as warnings.** An indented
|
|
105
|
+
`note: … omitted because of collinearity` line produced both an
|
|
106
|
+
`omitted_collinear` and a generic `note` warning.
|
|
107
|
+
- **A session literally named `"default"` no longer aliases `"main"`.** In
|
|
108
|
+
in-process mode it silently shared `main`'s Stata frame (one dataset for
|
|
109
|
+
two nominally distinct sessions); it now routes through the private
|
|
110
|
+
mapped-frame path.
|
|
111
|
+
- **Matrices with missing sfi row/col names are no longer dropped.**
|
|
112
|
+
Positional names (`r1…`/`c1…`) are synthesized instead of letting the
|
|
113
|
+
shape validator silently discard successfully read values.
|
|
114
|
+
- **`get_graph(format=…)` is no longer a silent no-op.** Requesting a
|
|
115
|
+
format different from the stored one now returns `invalid_request`
|
|
116
|
+
instead of returning mismatched bytes.
|
|
117
|
+
- **Post-run file snapshots survive escaping symlinks.** A symlink inside
|
|
118
|
+
the working dir pointing outside it crashed `changed_output_files` with
|
|
119
|
+
an uncaught `ValueError`; it is now skipped.
|
|
120
|
+
|
|
121
|
+
### Added
|
|
122
|
+
|
|
123
|
+
- **≈300 new offline tests** (467 → 724 passing without Stata); coverage
|
|
124
|
+
73% → 90% overall (`mcp/server` 74→99%, `kernel` 73→98%, `_pool` 68→96%,
|
|
125
|
+
`_refs` 68→100%, `log_artifacts` 76→96%, `runner` 29→72%). The package is
|
|
126
|
+
now fully mypy-clean, including the previously unchecked top-level
|
|
127
|
+
modules.
|
|
128
|
+
- **Community health files**: `CONTRIBUTING.md` (dev setup + the exact CI
|
|
129
|
+
gates), `CODE_OF_CONDUCT.md` (Contributor Covenant 2.1), `SECURITY.md`,
|
|
130
|
+
and GitHub issue templates that ask for `stata-code doctor` output.
|
|
131
|
+
- **Second-round regression tests** for the eight fixes listed above, each
|
|
132
|
+
verified to fail against the pre-fix source (823 passing locally with
|
|
133
|
+
Stata). They drive real subprocess workers through `SessionPool` — a
|
|
134
|
+
status query racing a live run, a worker that drops its first request, a
|
|
135
|
+
worker that releases the lock partway — rather than asserting on a mocked
|
|
136
|
+
seam, which is what let the first round's regressions through.
|
|
137
|
+
|
|
138
|
+
### Docs
|
|
139
|
+
|
|
140
|
+
- Regenerated the skill's `rc → kind` reference from `errors.py` — it still
|
|
141
|
+
documented the pre-0.9.0 mappings the taxonomy audit had corrected; fixed
|
|
142
|
+
the "32 kinds" claims (the enum has 31).
|
|
143
|
+
- `plugin.json` install verify no longer uses `stata-code-mcp --help`
|
|
144
|
+
(which hangs); it runs `stata-code doctor --no-stata-probe`.
|
|
145
|
+
- PUBLISHING.md / AGENTS.md version-bump lists now cover all eight version
|
|
146
|
+
literals the release gate checks; removed the stale claim that a built
|
|
147
|
+
`.vsix` ships in the repo.
|
|
148
|
+
- SCHEMA.md documents `EstimationResult.command_family` and `.diagnostics`;
|
|
149
|
+
status lines updated v0.8 → v0.9; README.zh.md re-synced with the English
|
|
150
|
+
README (plugin-marketplace install, per-client MCP config table, Open VSX
|
|
151
|
+
and first-activation notes, cell/section conventions).
|
|
152
|
+
|
|
153
|
+
## 0.9.0 — 2026-06-23
|
|
154
|
+
|
|
155
|
+
### Fixed
|
|
156
|
+
|
|
157
|
+
- **Error-taxonomy correctness.** Audited the `_rc` → `ErrorKind` table against
|
|
158
|
+
StataCorp's `[P] error` manual (Stata 19) and corrected several
|
|
159
|
+
misclassifications: `not_sorted` is now `r(5)` (was the unrelated `r(119)`
|
|
160
|
+
"statement out of context" / `r(459)` "data is not…"); numlist errors
|
|
161
|
+
`r(122)`/`r(123)` are now `syntax` (were `invalid_name`); `r(322)` and
|
|
162
|
+
`r(1400)` map to `estimation_failure` (was `file_not_found` /
|
|
163
|
+
`estimation_sample_empty`); `r(480)` maps to `infeasible` (was
|
|
164
|
+
`out_of_memory`); local I/O `r(691)`–`r(693)` map to `file_io` (were
|
|
165
|
+
`network`). Misleading mappings for `r(9)`/`r(604)`/`r(615)`/`r(616)` were
|
|
166
|
+
removed (they fall through to `unknown` rather than assert a wrong kind).
|
|
167
|
+
- **Command "did you mean?" now fires.** The `command_not_found` (rc 199) name
|
|
168
|
+
extractor expected `"<X> unrecognized command"`, but Stata's actual message is
|
|
169
|
+
`"command <X> is unrecognized"` — so the fuzzy suggestion never matched in
|
|
170
|
+
practice (synthetic unit tests passed the name in directly and hid it). Fixed
|
|
171
|
+
the regex and added a real-Stata integration test so a typo like `regresss`
|
|
172
|
+
now surfaces "Did you mean `regress`?".
|
|
173
|
+
|
|
174
|
+
### Added
|
|
175
|
+
|
|
176
|
+
- **Typed estimation contract.** `RunResult.results.estimation` now exposes a
|
|
177
|
+
frontend-neutral coefficient table derived from verified `r(table)` when
|
|
178
|
+
possible, or from inline `e(b)` / `e(V)` as a clearly marked fallback. New
|
|
179
|
+
public helpers `build_estimation_result()` and
|
|
180
|
+
`build_estimation_from_returns()` keep the contract unit-testable without
|
|
181
|
+
Stata. The contract also carries a coarse `command_family`
|
|
182
|
+
(ols/iv/gmm/panel/count/did/…) and command-aware `diagnostics` — identification
|
|
183
|
+
and specification tests surfaced from `e()` for the commands economists must
|
|
184
|
+
report (`ivreg2`/`ivreghdfe` weak-ID F and Hansen J, `xtabond2` AR(2)/Hansen,
|
|
185
|
+
`reghdfe` within-R²/absorbed FE, `xtreg` rho). Only scalars actually present in
|
|
186
|
+
`e()` are surfaced — never fabricated.
|
|
187
|
+
- **Machine-readable recovery contract.** `error.recovery` now classifies each
|
|
188
|
+
`ErrorKind` by failure domain and tells agents whether an unchanged retry,
|
|
189
|
+
code edit, or user/out-of-band action is likely needed. Synthetic timeout,
|
|
190
|
+
cancellation, and adapter-crash errors carry the same recovery metadata as
|
|
191
|
+
ordinary Stata errors.
|
|
192
|
+
- **Reproducibility provenance helpers.** New `Provenance`,
|
|
193
|
+
`build_provenance()`, and `build_reproducible_do()` helpers turn a completed
|
|
194
|
+
`RunResult` plus original code into a runtime provenance envelope and a
|
|
195
|
+
re-runnable `.do` script preamble with Stata `version`, `set more off`, and an
|
|
196
|
+
optional `set seed`. Provenance now also records **per-package dependencies**
|
|
197
|
+
parsed from the script (`extract_package_installs()` →
|
|
198
|
+
`Provenance.packages`: `ssc`/`net install` name, source, and `from()` URL),
|
|
199
|
+
and `build_submission_package()` assembles a self-contained
|
|
200
|
+
replication/journal-submission bundle (`analysis.do` + `PROVENANCE.json` +
|
|
201
|
+
a `README.md` manifest listing runtime, seed, and required community packages).
|
|
202
|
+
- **Data-MCP handoff verifier.** New `verify_dataset()` and `DatasetCheck`
|
|
203
|
+
helpers validate imported datasets against provider metadata such as expected
|
|
204
|
+
row count, variable count, observation bounds, and required variables.
|
|
205
|
+
- **`error.rc_label` is now populated for real Stata errors.** New
|
|
206
|
+
`RC_LABEL` table and `label_for_rc()` (public API) supply Stata's canonical
|
|
207
|
+
short message (e.g. `r(111)` → "variable not found") so agents have a stable,
|
|
208
|
+
transcript-independent descriptor to branch and group on. Unverified codes
|
|
209
|
+
yield an empty label rather than a guess.
|
|
210
|
+
- **More return codes classified** (shrinking `unknown`): real network codes
|
|
211
|
+
`r(2)`/`r(631)`/`r(672)`/`r(677)` → `network`; `r(688)` → `file_corrupt`;
|
|
212
|
+
`r(907)` → `stata_limit`; `r(950)` → `out_of_memory`; numlist `r(124)`–`r(127)`
|
|
213
|
+
→ `syntax`.
|
|
214
|
+
- **Remediation suggestions for more error kinds.** `suggestions_for()` now
|
|
215
|
+
emits actionable hints for `network`, `infeasible`, `type_mismatch`,
|
|
216
|
+
`file_io`, `file_corrupt`, `permission`, `estimation_failure`, and
|
|
217
|
+
`matrix_missing`, so nearly every common failure ships a recovery hint.
|
|
218
|
+
|
|
7
219
|
## 0.8.1 — 2026-06-20
|
|
8
220
|
|
|
9
221
|
### Changed
|
|
@@ -160,8 +372,8 @@ to semver-major.minor for the result schema (see `SCHEMA.md` §6).
|
|
|
160
372
|
|
|
161
373
|
### Added
|
|
162
374
|
|
|
163
|
-
- **Claude Code plugin marketplace manifest.** `.claude-plugin/marketplace.json`
|
|
164
|
-
|
|
375
|
+
- **Claude Code plugin marketplace manifest.** `.claude-plugin/marketplace.json` +
|
|
376
|
+
`.claude-plugin/plugin.json` expose the repo as a single-plugin
|
|
165
377
|
marketplace, so users can install everything (MCP server config + agent
|
|
166
378
|
skill) with `claude plugin marketplace add brycewang-stanford/stata-code`
|
|
167
379
|
followed by `claude plugin install stata-code`.
|
|
@@ -602,6 +814,9 @@ Aggregated from the prior `Unreleased` section; covers 0.6.1 and 0.6.2.
|
|
|
602
814
|
`vscode/package.json`, and the VSCode MCP-client handshake all
|
|
603
815
|
declare `0.3.0`.
|
|
604
816
|
|
|
817
|
+
- **MCP server tool count is now 8** (added `get_matrix`,
|
|
818
|
+
`cancel_session`).
|
|
819
|
+
|
|
605
820
|
### Added
|
|
606
821
|
|
|
607
822
|
- **VSCode extension v0.3 — full UI surface** (`vscode/`). Beyond the
|
|
@@ -684,11 +899,6 @@ Aggregated from the prior `Unreleased` section; covers 0.6.1 and 0.6.2.
|
|
|
684
899
|
in-process and has no clean cancel primitive). Hard interruption
|
|
685
900
|
remains deferred to the subprocess-based runtime planned for v0.3+.
|
|
686
901
|
|
|
687
|
-
### Changed
|
|
688
|
-
|
|
689
|
-
- **MCP server tool count is now 8** (added `get_matrix`,
|
|
690
|
-
`cancel_session`).
|
|
691
|
-
|
|
692
902
|
## [0.2.0] — 2026-05-07
|
|
693
903
|
|
|
694
904
|
The first release that actually ships an end-to-end Stata pipeline. The v1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stata-code
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: Agent-native Stata bridge — one core, multiple frontends (MCP, Jupyter, VSCode)
|
|
5
5
|
Project-URL: Homepage, https://github.com/brycewang-stanford/stata-code
|
|
6
6
|
Project-URL: Repository, https://github.com/brycewang-stanford/stata-code
|
|
@@ -118,7 +118,7 @@ Then just ask:
|
|
|
118
118
|
└─────────────┘ └────────────┘ └─────────────────┘
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
**Status: v0.
|
|
121
|
+
**Status: v0.9 (June 2026)** — the core, MCP server, Jupyter kernel, and VS Code extension work end-to-end against Stata 18 MP. The test suite covers schema, runner, MCP, kernel, notebook, run-index, subprocess-pool, and VS Code modules; CI also checks linting, type safety, schema generation, package metadata, and VSIX packaging. License: **MIT**.
|
|
122
122
|
|
|
123
123
|
Three workflows the current tree explicitly supports for end users and agents:
|
|
124
124
|
|
|
@@ -184,12 +184,14 @@ Verify the local setup with the read-only doctor:
|
|
|
184
184
|
stata-code doctor
|
|
185
185
|
stata-code doctor --json # machine-readable output
|
|
186
186
|
stata-code doctor --no-stata-probe # skip live Stata initialization
|
|
187
|
+
stata-code doctor --workspace /path/to/project --no-user-config-scan
|
|
187
188
|
```
|
|
188
189
|
|
|
189
190
|
The doctor reports the package/Python version, MCP and Jupyter extras, `pystata`
|
|
190
|
-
discovery, console scripts on `PATH`,
|
|
191
|
-
|
|
192
|
-
VS Code
|
|
191
|
+
discovery, console scripts on `PATH`, common project/user MCP client config
|
|
192
|
+
files, client/VS Code configuration hints, and a best-effort Stata
|
|
193
|
+
version/edition probe. It never edits shell, Stata, Claude, Cursor, or VS Code
|
|
194
|
+
config.
|
|
193
195
|
|
|
194
196
|
---
|
|
195
197
|
|
|
@@ -418,7 +420,9 @@ If the extension or an MCP client cannot find the server, run
|
|
|
418
420
|
`stata-code doctor --no-stata-probe` in the same Python environment. It reports
|
|
419
421
|
whether `stata-code-mcp` is on `PATH` and suggests absolute-path or
|
|
420
422
|
`python -m stata_code.mcp` fallbacks for GUI clients whose `PATH` differs from
|
|
421
|
-
your shell.
|
|
423
|
+
your shell. It also reads common MCP config files in the current workspace and
|
|
424
|
+
user config directories so you can see whether a client is already wired to
|
|
425
|
+
`stata-code`.
|
|
422
426
|
|
|
423
427
|
#### Cell and section conventions
|
|
424
428
|
|
|
@@ -561,10 +565,17 @@ The `stata_required` marker tags the real-Stata integration tests. CI uses `pyte
|
|
|
561
565
|
|
|
562
566
|
## Contributing
|
|
563
567
|
|
|
568
|
+
Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the
|
|
569
|
+
development setup, the checks CI runs, and PR guidelines. In short:
|
|
570
|
+
|
|
564
571
|
- Read [LICENSE-POLICY.md](LICENSE-POLICY.md) before opening a PR.
|
|
565
572
|
- Add a one-line acknowledgement to your first PR description; the template is in the policy file.
|
|
566
573
|
- Tests are required for any new schema field or runner behavior.
|
|
567
574
|
|
|
575
|
+
Bug reports and support questions go through
|
|
576
|
+
[GitHub issues](https://github.com/brycewang-stanford/stata-code/issues);
|
|
577
|
+
security reports go through [SECURITY.md](SECURITY.md).
|
|
578
|
+
|
|
568
579
|
---
|
|
569
580
|
|
|
570
581
|
## License
|
|
@@ -20,12 +20,12 @@ Trusted Publishing has two modes:
|
|
|
20
20
|
- **Pending publisher** (preferred for the first release of a brand-new
|
|
21
21
|
project): you configure the trusted publisher *before* the project exists
|
|
22
22
|
on PyPI, and the first successful publish creates it. Go to
|
|
23
|
-
https://pypi.org/manage/account/publishing
|
|
23
|
+
<https://pypi.org/manage/account/publishing/> and add a "pending publisher"
|
|
24
24
|
with the values listed in step 2.
|
|
25
25
|
- **Existing project**: if you already pushed an initial release manually
|
|
26
26
|
(e.g. via `twine upload` with a one-off API token), configure trusted
|
|
27
27
|
publishing on the project page at
|
|
28
|
-
https://pypi.org/manage/project/stata-code/settings/publishing
|
|
28
|
+
<https://pypi.org/manage/project/stata-code/settings/publishing/>.
|
|
29
29
|
|
|
30
30
|
Either path lands you in the same place after the first run.
|
|
31
31
|
|
|
@@ -76,30 +76,39 @@ The environment doesn't need any secrets — Trusted Publishing handles auth.
|
|
|
76
76
|
|
|
77
77
|
Once the one-time setup above is done, every release is just:
|
|
78
78
|
|
|
79
|
-
1. **Bump the version everywhere
|
|
79
|
+
1. **Bump the version everywhere** (eight literals across six files —
|
|
80
|
+
`scripts/check_versions.py` gates the release build on all of them):
|
|
80
81
|
- `pyproject.toml` → `[project] version`
|
|
81
82
|
- `stata_code/__init__.py` → `__version__`
|
|
82
83
|
- `stata_code/mcp/server.py` → `__version__`
|
|
83
84
|
- `vscode/package.json` → `version`
|
|
84
|
-
- `vscode/package-lock.json` →
|
|
85
|
+
- `vscode/package-lock.json` → top-level `version` **and** `packages[""].version`
|
|
86
|
+
- `.claude-plugin/plugin.json` → `version`
|
|
87
|
+
- `.claude-plugin/marketplace.json` → `metadata.version` **and** each `plugins[*].version`
|
|
85
88
|
2. **Run the version guard** before tagging:
|
|
89
|
+
|
|
86
90
|
```bash
|
|
87
91
|
python scripts/check_versions.py
|
|
88
92
|
```
|
|
93
|
+
|
|
89
94
|
3. **Update `CHANGELOG.md`**: move the `[Unreleased]` entries under a new
|
|
90
95
|
`## [X.Y.Z] - YYYY-MM-DD` heading, leaving an empty `[Unreleased]` shell
|
|
91
96
|
on top.
|
|
92
97
|
4. **Commit** the bump:
|
|
98
|
+
|
|
93
99
|
```bash
|
|
94
100
|
git add pyproject.toml stata_code/__init__.py stata_code/mcp/server.py vscode/package.json vscode/package-lock.json CHANGELOG.md
|
|
95
101
|
git commit -m "release: vX.Y.Z"
|
|
96
102
|
```
|
|
103
|
+
|
|
97
104
|
5. **Tag and push**:
|
|
105
|
+
|
|
98
106
|
```bash
|
|
99
107
|
git tag vX.Y.Z
|
|
100
108
|
git push origin main
|
|
101
109
|
git push origin vX.Y.Z
|
|
102
110
|
```
|
|
111
|
+
|
|
103
112
|
6. Watch the **`release` workflow** under the Actions tab. It will:
|
|
104
113
|
- build the sdist + wheel
|
|
105
114
|
- run `twine check` on the artifacts
|
|
@@ -127,14 +136,14 @@ version if a publish has already succeeded under that number.
|
|
|
127
136
|
|
|
128
137
|
## Manual / emergency publish
|
|
129
138
|
|
|
130
|
-
`release.yml` also accepts `workflow_dispatch`, so you can trigger a build
|
|
131
|
-
|
|
139
|
+
`release.yml` also accepts `workflow_dispatch`, so you can trigger a build +
|
|
140
|
+
publish from the Actions UI without pushing a tag. The `github-release`
|
|
132
141
|
job will fail in that mode (no tag to attach to) — that's fine; the PyPI
|
|
133
142
|
publish itself will have already happened in `publish-pypi`.
|
|
134
143
|
|
|
135
144
|
If Trusted Publishing is broken for some reason and you need an emergency
|
|
136
145
|
release, generate a short-lived API token at
|
|
137
|
-
https://pypi.org/manage/account/token
|
|
146
|
+
<https://pypi.org/manage/account/token/> and run locally:
|
|
138
147
|
|
|
139
148
|
```bash
|
|
140
149
|
python -m build
|
|
@@ -79,7 +79,7 @@ Then just ask:
|
|
|
79
79
|
└─────────────┘ └────────────┘ └─────────────────┘
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
**Status: v0.
|
|
82
|
+
**Status: v0.9 (June 2026)** — the core, MCP server, Jupyter kernel, and VS Code extension work end-to-end against Stata 18 MP. The test suite covers schema, runner, MCP, kernel, notebook, run-index, subprocess-pool, and VS Code modules; CI also checks linting, type safety, schema generation, package metadata, and VSIX packaging. License: **MIT**.
|
|
83
83
|
|
|
84
84
|
Three workflows the current tree explicitly supports for end users and agents:
|
|
85
85
|
|
|
@@ -145,12 +145,14 @@ Verify the local setup with the read-only doctor:
|
|
|
145
145
|
stata-code doctor
|
|
146
146
|
stata-code doctor --json # machine-readable output
|
|
147
147
|
stata-code doctor --no-stata-probe # skip live Stata initialization
|
|
148
|
+
stata-code doctor --workspace /path/to/project --no-user-config-scan
|
|
148
149
|
```
|
|
149
150
|
|
|
150
151
|
The doctor reports the package/Python version, MCP and Jupyter extras, `pystata`
|
|
151
|
-
discovery, console scripts on `PATH`,
|
|
152
|
-
|
|
153
|
-
VS Code
|
|
152
|
+
discovery, console scripts on `PATH`, common project/user MCP client config
|
|
153
|
+
files, client/VS Code configuration hints, and a best-effort Stata
|
|
154
|
+
version/edition probe. It never edits shell, Stata, Claude, Cursor, or VS Code
|
|
155
|
+
config.
|
|
154
156
|
|
|
155
157
|
---
|
|
156
158
|
|
|
@@ -379,7 +381,9 @@ If the extension or an MCP client cannot find the server, run
|
|
|
379
381
|
`stata-code doctor --no-stata-probe` in the same Python environment. It reports
|
|
380
382
|
whether `stata-code-mcp` is on `PATH` and suggests absolute-path or
|
|
381
383
|
`python -m stata_code.mcp` fallbacks for GUI clients whose `PATH` differs from
|
|
382
|
-
your shell.
|
|
384
|
+
your shell. It also reads common MCP config files in the current workspace and
|
|
385
|
+
user config directories so you can see whether a client is already wired to
|
|
386
|
+
`stata-code`.
|
|
383
387
|
|
|
384
388
|
#### Cell and section conventions
|
|
385
389
|
|
|
@@ -522,10 +526,17 @@ The `stata_required` marker tags the real-Stata integration tests. CI uses `pyte
|
|
|
522
526
|
|
|
523
527
|
## Contributing
|
|
524
528
|
|
|
529
|
+
Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the
|
|
530
|
+
development setup, the checks CI runs, and PR guidelines. In short:
|
|
531
|
+
|
|
525
532
|
- Read [LICENSE-POLICY.md](LICENSE-POLICY.md) before opening a PR.
|
|
526
533
|
- Add a one-line acknowledgement to your first PR description; the template is in the policy file.
|
|
527
534
|
- Tests are required for any new schema field or runner behavior.
|
|
528
535
|
|
|
536
|
+
Bug reports and support questions go through
|
|
537
|
+
[GitHub issues](https://github.com/brycewang-stanford/stata-code/issues);
|
|
538
|
+
security reports go through [SECURITY.md](SECURITY.md).
|
|
539
|
+
|
|
529
540
|
---
|
|
530
541
|
|
|
531
542
|
## License
|
|
@@ -77,7 +77,38 @@ Every successful or failed Stata execution returns one result object:
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
|
-
"last_estimation_cmd": "regress"
|
|
80
|
+
"last_estimation_cmd": "regress",
|
|
81
|
+
"estimation": {
|
|
82
|
+
"command": "regress",
|
|
83
|
+
"depvar": "mpg",
|
|
84
|
+
"n_obs": 74,
|
|
85
|
+
"df_model": 1,
|
|
86
|
+
"df_resid": null,
|
|
87
|
+
"statistic_kind": "z",
|
|
88
|
+
"source": "e_b_v",
|
|
89
|
+
"ci_level": 95.0,
|
|
90
|
+
"coefficients": [
|
|
91
|
+
{
|
|
92
|
+
"term": "weight",
|
|
93
|
+
"b": -0.006,
|
|
94
|
+
"se": null,
|
|
95
|
+
"statistic": null,
|
|
96
|
+
"p_value": null,
|
|
97
|
+
"ci_low": null,
|
|
98
|
+
"ci_high": null
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"term": "_cons",
|
|
102
|
+
"b": 39.44,
|
|
103
|
+
"se": null,
|
|
104
|
+
"statistic": null,
|
|
105
|
+
"p_value": null,
|
|
106
|
+
"ci_low": null,
|
|
107
|
+
"ci_high": null
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
"model_stats": {"N": 74, "df_m": 1, "r2": 0.219}
|
|
111
|
+
}
|
|
81
112
|
},
|
|
82
113
|
|
|
83
114
|
"dataset": {
|
|
@@ -140,7 +171,8 @@ A failed execution sets `ok: false`, `rc != 0`, and populates `error`:
|
|
|
140
171
|
|
|
141
172
|
"results": { "r": {"scalars": {}, "macros": {}, "matrices": {}},
|
|
142
173
|
"e": {"scalars": {}, "macros": {}, "matrices": {}},
|
|
143
|
-
"last_estimation_cmd": null
|
|
174
|
+
"last_estimation_cmd": null,
|
|
175
|
+
"estimation": null },
|
|
144
176
|
|
|
145
177
|
"dataset": { "frame": "default", "n_obs": 74, "n_vars": 12, "changed": false,
|
|
146
178
|
"filename": "auto.dta", "variables": null },
|
|
@@ -167,7 +199,13 @@ A failed execution sets `ok: false`, `rc != 0`, and populates `error`:
|
|
|
167
199
|
"suggestions": [
|
|
168
200
|
{"action": "Check the variable name. Did you mean `mpg`?",
|
|
169
201
|
"command": "describe"}
|
|
170
|
-
]
|
|
202
|
+
],
|
|
203
|
+
"recovery": {
|
|
204
|
+
"category": "user_code",
|
|
205
|
+
"retriable": false,
|
|
206
|
+
"needs_code_change": true,
|
|
207
|
+
"needs_user_input": false
|
|
208
|
+
}
|
|
171
209
|
},
|
|
172
210
|
|
|
173
211
|
"schema_version": "1.0",
|
|
@@ -315,6 +353,36 @@ Stata's `r()` and `e()` return dictionaries, structurally separated. Each follow
|
|
|
315
353
|
| Field | Type | Notes |
|
|
316
354
|
| --- | --- | --- |
|
|
317
355
|
| `last_estimation_cmd` | `string \| null` | Mirrors `e(cmd)` for callers who don't want to dig into `e.macros`. After multi-command code, this reflects the *last* command that wrote to `e()`. `null` if no estimation has been performed. |
|
|
356
|
+
| `estimation` | `EstimationResult \| null` | Typed coefficient table derived from `r(table)` or `e(b)` / `e(V)`. `null` when no inline `e(b)` is available. |
|
|
357
|
+
|
|
358
|
+
**`EstimationResult` shape:**
|
|
359
|
+
|
|
360
|
+
| Field | Type | Notes |
|
|
361
|
+
| --- | --- | --- |
|
|
362
|
+
| `command` | `string \| null` | Mirrors `e(cmd)` when available; falls back to `last_estimation_cmd`. |
|
|
363
|
+
| `command_family` | `string \| null` | Coarse estimator family derived from the command name (`ols` / `iv` / `gmm` / `panel` / `count` / `did` / …); `null` when the command is unrecognized. |
|
|
364
|
+
| `depvar` | `string \| null` | Mirrors `e(depvar)`. |
|
|
365
|
+
| `n_obs` | `int \| null` | Integer form of `e(N)` when available. |
|
|
366
|
+
| `df_model` | `number \| null` | Mirrors `e(df_m)`. |
|
|
367
|
+
| `df_resid` | `number \| null` | Mirrors `e(df_r)`. |
|
|
368
|
+
| `statistic_kind` | `"t" \| "z"` | Which statistic fills each coefficient's `statistic` field. |
|
|
369
|
+
| `source` | `"r_table" \| "e_b_v"` | `r_table` means values were copied from Stata's displayed `r(table)` after verifying its columns and `b` row match `e(b)`; `e_b_v` means point estimates come from `e(b)` and inference, when present, is computed from `e(V)` with a normal approximation. |
|
|
370
|
+
| `ci_level` | `number` | Confidence level used for `ci_low` / `ci_high`; currently `95.0`. |
|
|
371
|
+
| `coefficients` | `array<Coefficient>` | One row per term in `e(b)`. |
|
|
372
|
+
| `model_stats` | `dict<str, number \| null>` | High-signal subset of `e()` scalars such as `N`, `df_m`, `df_r`, `r2`, `F`, `chi2`, `ll`, and `rmse`. Full scalars remain under `results.e.scalars`. |
|
|
373
|
+
| `diagnostics` | `dict<str, number \| null>` | Command-aware identification/specification statistics surfaced from `e()` (e.g. weak-ID F and Hansen J for `ivreg2`/`ivreghdfe`, AR(2)/Hansen for `xtabond2`, within-R² for `reghdfe`, `rho` for `xtreg`). Only scalars actually present in `e()` appear — never fabricated. |
|
|
374
|
+
|
|
375
|
+
**`Coefficient` shape:**
|
|
376
|
+
|
|
377
|
+
| Field | Type | Notes |
|
|
378
|
+
| --- | --- | --- |
|
|
379
|
+
| `term` | `string` | Term / coefficient column name. |
|
|
380
|
+
| `b` | `number \| null` | Point estimate. |
|
|
381
|
+
| `se` | `number \| null` | Standard error when available. |
|
|
382
|
+
| `statistic` | `number \| null` | `t` or `z`, per `EstimationResult.statistic_kind`. |
|
|
383
|
+
| `p_value` | `number \| null` | Two-sided p-value when available. |
|
|
384
|
+
| `ci_low` | `number \| null` | Lower confidence interval bound when available. |
|
|
385
|
+
| `ci_high` | `number \| null` | Upper confidence interval bound when available. |
|
|
318
386
|
|
|
319
387
|
**Empty is empty.** Sub-dicts are `{}` when Stata returned nothing — never absent, never `null`.
|
|
320
388
|
|
|
@@ -377,6 +445,7 @@ Populated iff `ok: false`. The schema's most important contribution to agent UX:
|
|
|
377
445
|
| `varname` | `string \| null` | For `varname_not_found` and related, the variable name at issue. |
|
|
378
446
|
| `name` | `string \| null` | For `name_conflict` and `invalid_name`, the conflicting/invalid name. |
|
|
379
447
|
| `suggestions` | `array<Suggestion>` | Producer-supplied remediation hints. Empty when none apply. See below. |
|
|
448
|
+
| `recovery` | `Recovery \| null` | Machine-readable recovery contract for agents. Present on current producers; old or third-party producers may omit it, so consumers should handle `null`. |
|
|
380
449
|
|
|
381
450
|
**`context` shape:**
|
|
382
451
|
|
|
@@ -399,36 +468,47 @@ Populated iff `ok: false`. The schema's most important contribution to agent UX:
|
|
|
399
468
|
|
|
400
469
|
Suggestions are best-effort; agents should treat them as hints, not directives. A suggestion is not consent to mutate source files or silently retry changed code; consumers should apply fixes automatically only in workflows where the user requested repair or approved iteration. The `kind` enum below documents what suggestions are typically populated.
|
|
401
470
|
|
|
471
|
+
**`Recovery` shape:**
|
|
472
|
+
|
|
473
|
+
| Field | Type | Notes |
|
|
474
|
+
| --- | --- | --- |
|
|
475
|
+
| `category` | `"user_code" \| "data" \| "model" \| "resource" \| "environment" \| "internal" \| "unknown"` | Broad failure domain for routing. |
|
|
476
|
+
| `retriable` | `bool` | Whether re-running the exact same code may succeed. True mainly for transient environment or producer-side failures. |
|
|
477
|
+
| `needs_code_change` | `bool` | Whether the submitted Stata code must change to succeed. |
|
|
478
|
+
| `needs_user_input` | `bool` | Whether resolution likely requires a human or out-of-band action such as permissions, license/edition limits, or re-acquiring a corrupt file. |
|
|
479
|
+
|
|
402
480
|
**`kind` enum (v1.0):**
|
|
403
481
|
|
|
482
|
+
rc(s) below cite StataCorp `[P] error` (Stata 19, 2025). The code is authoritative; this table is a readable mirror.
|
|
483
|
+
|
|
404
484
|
| `kind` | Typical rc(s) | Notes / suggestion seed |
|
|
405
485
|
| --- | --- | --- |
|
|
406
|
-
| `syntax` |
|
|
486
|
+
| `syntax` | 100, 101, 102, 103, 121–127, 130, 132, 197, 198 | Generic parser failure (incl. numlist errors 121–127). No automatic suggestion. |
|
|
407
487
|
| `command_not_found` | 199 | Often resolved by `ssc install` or `net install`; suggestions populated when Stata reports a likely package name. |
|
|
408
488
|
| `varname_not_found` | 111 | `varname` populated. Suggestions may include similar varnames from `dataset.variables`. |
|
|
409
|
-
| `invalid_name` |
|
|
410
|
-
| `type_mismatch` | 109, 408 | |
|
|
489
|
+
| `invalid_name` | (no dedicated rc) | Stata folds "invalid name" into r(198). `name` populated when constructed by a producer. |
|
|
490
|
+
| `type_mismatch` | 109, 408 | Suggestion: `destring`/`tostring`. |
|
|
411
491
|
| `name_conflict` | 110 | `name` populated. Suggestion typically: `replace`. |
|
|
412
|
-
| `not_sorted` |
|
|
492
|
+
| `not_sorted` | 5 | Suggestion: `sort <varlist>`. |
|
|
413
493
|
| `convergence` | 430 | |
|
|
414
|
-
| `infeasible` | 491 | Distinct from convergence: starting values not feasible. |
|
|
415
|
-
| `estimation_sample_empty` |
|
|
416
|
-
| `estimation_failure` | 1401, 1402 | |
|
|
494
|
+
| `infeasible` | 480, 491 | Distinct from convergence: starting values not feasible (e.g. `nl`, `ml`). |
|
|
495
|
+
| `estimation_sample_empty` | (no dedicated rc) | Empty estimation samples surface as r(2000); producer-set otherwise. |
|
|
496
|
+
| `estimation_failure` | 322, 1400, 1401, 1402 | Postestimation/prefix saw an unexpected result, or numerical overflow. |
|
|
417
497
|
| `no_estimation_results` | 301 | Common when calling `predict`/`margins` without prior estimation. |
|
|
418
498
|
| `no_observations` | 2000, 2001 | |
|
|
419
499
|
| `data_in_memory` | 4 | Suggestion: `clear`. |
|
|
420
500
|
| `matrix_singular` | 506, 508 | Matrix not positive definite / not invertible. |
|
|
421
|
-
| `matrix_conformability` | 503, 507 | Dimension mismatch. |
|
|
501
|
+
| `matrix_conformability` | 503, 507 | Dimension mismatch; 507 is a `matrix post` row/col name conflict kept in the matrix bucket. |
|
|
422
502
|
| `matrix_missing` | 504 | Matrix has missing values. |
|
|
423
|
-
| `file_not_found` |
|
|
503
|
+
| `file_not_found` | 601 | `path` populated. |
|
|
424
504
|
| `file_exists` | 602 | `path` populated. Suggestion: pass `replace` option. |
|
|
425
|
-
| `file_corrupt` |
|
|
426
|
-
| `file_io` | 603, 691
|
|
427
|
-
| `network` |
|
|
428
|
-
| `permission` | 608 | `path` populated.
|
|
429
|
-
| `encoding` |
|
|
430
|
-
| `stata_limit` | 901, 902, 903 | Edition /
|
|
431
|
-
| `out_of_memory` |
|
|
505
|
+
| `file_corrupt` | 610, 688 | `path` populated. "Not a Stata file" (610) or genuinely corrupt (688). |
|
|
506
|
+
| `file_io` | 603, 691, 692, 693 | `path` populated. Catch-all for open/read/write failures (691–693 are local filesystem I/O). |
|
|
507
|
+
| `network` | 2, 631, 672, 677 | Connection timed out / host not found / server refused / remote connection failed. |
|
|
508
|
+
| `permission` | 608 | `path` populated. File is read-only / not writable. |
|
|
509
|
+
| `encoding` | (no dedicated rc) | Unicode / encoding-conversion failures; producer-set. |
|
|
510
|
+
| `stata_limit` | 901, 902, 903, 907 | Edition / maxvar / width caps. Distinct from OS OOM. Suggestion: `set maxvar` or upgrade edition. |
|
|
511
|
+
| `out_of_memory` | 909, 950 | OS-level memory exhaustion. Suggestion: `compress`. |
|
|
432
512
|
| `interrupt` | 1 | User Break / Ctrl-C from a frontend. |
|
|
433
513
|
| `cancelled` | (synthetic `rc: -3`) | Cancellation was requested. Subprocess-backed producers may terminate an in-flight worker; the direct in-process runner only short-circuits before Stata receives code. |
|
|
434
514
|
| `timeout` | (synthetic `rc: -2`) | Adapter-imposed time limit exceeded. |
|
|
@@ -607,17 +687,20 @@ This section tracks how much of the schema is wired up in code. Not normative
|
|
|
607
687
|
emit a `matrix://<request_id>/<r|e>/<name>` ref instead, retrievable
|
|
608
688
|
via `get_matrix(ref)`.
|
|
609
689
|
- `results.last_estimation_cmd` (mirrors `e(cmd)`).
|
|
690
|
+
- `results.estimation` typed coefficient table, copied from verified
|
|
691
|
+
`r(table)` when possible and otherwise derived from inline `e(b)` / `e(V)`.
|
|
610
692
|
- `dataset` block — `n_obs`, `n_vars`, `frame`, `changed`, `filename`,
|
|
611
693
|
and `variables` (capped at 200 entries).
|
|
612
694
|
- `graphs[]` with `ref` + on-disk capture pipeline; format restricted to
|
|
613
695
|
`png` / `svg` / `pdf`; PNG `width` / `height` parsed from IHDR;
|
|
614
696
|
best-effort `source_command` / `source_line` attribution from the
|
|
615
697
|
submitted code. `inline` populated when `include_graphs="inline"`.
|
|
616
|
-
- Structured `error` —
|
|
698
|
+
- Structured `error` — 31-kind enum, `varname` / `path` / `name`
|
|
617
699
|
extracted from Stata's English error text by regex, structured
|
|
618
700
|
`context` (`{before, failing, after}`), `commands_executed` parsed
|
|
619
701
|
from pystata's multi-line transcript, `suggestions` generated by
|
|
620
|
-
`core.errors.suggestions_for
|
|
702
|
+
`core.errors.suggestions_for`, and `recovery` generated by
|
|
703
|
+
`core.errors.recovery_for`.
|
|
621
704
|
- `request_id` (uuid4 hex), `started_at` (ISO 8601 UTC ms),
|
|
622
705
|
`stata_elapsed_ms`, `capabilities`.
|
|
623
706
|
- Multi-session via Stata frames — `session_id="main"` ↔ `default`
|