tmaudit 0.5.0__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.
- tmaudit-0.5.0/LICENSE +24 -0
- tmaudit-0.5.0/PKG-INFO +386 -0
- tmaudit-0.5.0/README.md +350 -0
- tmaudit-0.5.0/pyproject.toml +99 -0
- tmaudit-0.5.0/setup.cfg +4 -0
- tmaudit-0.5.0/src/tmaudit/__init__.py +68 -0
- tmaudit-0.5.0/src/tmaudit/__main__.py +5 -0
- tmaudit-0.5.0/src/tmaudit/cache.py +259 -0
- tmaudit-0.5.0/src/tmaudit/cli.py +479 -0
- tmaudit-0.5.0/src/tmaudit/configs/__init__.py +18 -0
- tmaudit-0.5.0/src/tmaudit/configs/compile_configs.py +296 -0
- tmaudit-0.5.0/src/tmaudit/configs/paper_configs.py +686 -0
- tmaudit-0.5.0/src/tmaudit/detector_config/__init__.py +21 -0
- tmaudit-0.5.0/src/tmaudit/detector_config/detector_min.py +113 -0
- tmaudit-0.5.0/src/tmaudit/forge.py +320 -0
- tmaudit-0.5.0/src/tmaudit/llm_fallback.py +328 -0
- tmaudit-0.5.0/src/tmaudit/plugins.py +464 -0
- tmaudit-0.5.0/src/tmaudit/report.py +353 -0
- tmaudit-0.5.0/src/tmaudit/templates/__init__.py +1 -0
- tmaudit-0.5.0/src/tmaudit/templates/compile_check_TEMPLATE.py +131 -0
- tmaudit-0.5.0/src/tmaudit/templates/fix_abstract_unicode_TEMPLATE.py +136 -0
- tmaudit-0.5.0/src/tmaudit/templates/verify_TEMPLATE.py +1719 -0
- tmaudit-0.5.0/src/tmaudit.egg-info/PKG-INFO +386 -0
- tmaudit-0.5.0/src/tmaudit.egg-info/SOURCES.txt +41 -0
- tmaudit-0.5.0/src/tmaudit.egg-info/dependency_links.txt +1 -0
- tmaudit-0.5.0/src/tmaudit.egg-info/entry_points.txt +2 -0
- tmaudit-0.5.0/src/tmaudit.egg-info/requires.txt +9 -0
- tmaudit-0.5.0/src/tmaudit.egg-info/top_level.txt +1 -0
- tmaudit-0.5.0/tests/test_bug5_unit.py +100 -0
- tmaudit-0.5.0/tests/test_c10_reproducibility.py +478 -0
- tmaudit-0.5.0/tests/test_c6_threshold.py +113 -0
- tmaudit-0.5.0/tests/test_c7_citation_context.py +447 -0
- tmaudit-0.5.0/tests/test_c8_statistical_power.py +511 -0
- tmaudit-0.5.0/tests/test_c9_figure_caption.py +495 -0
- tmaudit-0.5.0/tests/test_cache.py +371 -0
- tmaudit-0.5.0/tests/test_detector_config.py +169 -0
- tmaudit-0.5.0/tests/test_example_plugin.py +163 -0
- tmaudit-0.5.0/tests/test_forge.py +468 -0
- tmaudit-0.5.0/tests/test_forge_happy.py +217 -0
- tmaudit-0.5.0/tests/test_llm_fallback.py +408 -0
- tmaudit-0.5.0/tests/test_paper_configs.py +252 -0
- tmaudit-0.5.0/tests/test_plugin_api.py +682 -0
- tmaudit-0.5.0/tests/test_report.py +342 -0
tmaudit-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Liu Zewen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person
|
|
6
|
+
obtaining a copy of this software and associated documentation
|
|
7
|
+
files (the "Software"), to deal in the Software without
|
|
8
|
+
restriction, including without limitation the rights to use,
|
|
9
|
+
copy, modify, merge, publish, distribute, sublicense, and/or
|
|
10
|
+
sell copies of the Software, and to permit persons to whom the
|
|
11
|
+
Software is furnished to do so, subject to the following
|
|
12
|
+
conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be
|
|
15
|
+
included in all copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
19
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
21
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
22
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
23
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
24
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
tmaudit-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tmaudit
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Config-driven TMLR paper audit + LaTeX compile pipeline
|
|
5
|
+
Author-email: Liu Zewen <aidless@example.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/aidless/tmaudit
|
|
8
|
+
Project-URL: Issues, https://github.com/aidless/tmaudit/issues
|
|
9
|
+
Project-URL: Source, https://github.com/aidless/tmaudit
|
|
10
|
+
Project-URL: Changelog, https://github.com/aidless/tmaudit/blob/main/CHANGELOG.md
|
|
11
|
+
Project-URL: v0.4.0 release, https://github.com/aidless/tmaudit/releases/tag/v0.4.0
|
|
12
|
+
Keywords: tmaudit,tmlr,paper-audit,latex,compile,plugins,neurips,iclr,reviewer,audit
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering
|
|
22
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
23
|
+
Classifier: Topic :: Text Processing :: Markup :: LaTeX
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pyflakes>=3.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
30
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
31
|
+
Requires-Dist: build>=0.10; extra == "dev"
|
|
32
|
+
Requires-Dist: twine>=4; extra == "dev"
|
|
33
|
+
Requires-Dist: scipy>=1.10; extra == "dev"
|
|
34
|
+
Requires-Dist: PyYAML>=6.0; extra == "dev"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# tmaudit — Deploy & Quick Start
|
|
38
|
+
|
|
39
|
+
[](https://github.com/aidless/tmaudit/actions/workflows/ci.yml)
|
|
40
|
+

|
|
41
|
+

|
|
42
|
+

|
|
43
|
+

|
|
44
|
+

|
|
45
|
+

|
|
46
|
+

|
|
47
|
+

|
|
48
|
+

|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
This directory is a **deployable Python package** named `tmaudit`. It
|
|
52
|
+
ships three things in one place:
|
|
53
|
+
|
|
54
|
+
1. The **templates** for the three operational scripts that every
|
|
55
|
+
`PAPER<N>_CONSOLIDATED/` directory needs
|
|
56
|
+
(`verify_p<N>.py`, `_compile_check.py`,
|
|
57
|
+
`_fix_abstract_unicode.py`).
|
|
58
|
+
2. The **per-paper configurations** (C1..C10 audit rules: C1–C7
|
|
59
|
+
in v0.1.0–v0.2.0, plus C8 statistical power, C9 figure-caption,
|
|
60
|
+
and C10 reproducibility in v0.3.0; abstract Unicode
|
|
61
|
+
replacements) for Paper 1, 2, 3, 4, 5.
|
|
62
|
+
3. A **CLI** (`tmaudit`) that forks the templates into any paper
|
|
63
|
+
directory and (optionally) runs them.
|
|
64
|
+
|
|
65
|
+
## Three ways to use it
|
|
66
|
+
|
|
67
|
+
### (A) Run the single-file `tmaudit.pyz` (zero install)
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# on any machine with Python 3.9+
|
|
71
|
+
python tmaudit.pyz list
|
|
72
|
+
python tmaudit.pyz verify --paper 1
|
|
73
|
+
python tmaudit.pyz compile --paper 5
|
|
74
|
+
python tmaudit.pyz fix-unicode --paper 1
|
|
75
|
+
python tmaudit.pyz audit-all
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The `.pyz` is a self-extracting Python zip archive; the user does not
|
|
79
|
+
need to `pip install` anything. The file is `~46 KB` and contains all
|
|
80
|
+
five `PAPER_CONFIGS` and all three templates.
|
|
81
|
+
|
|
82
|
+
This is the **recommended distribution form** for handing the tool
|
|
83
|
+
to a co-author or to the TMLR reviewers.
|
|
84
|
+
|
|
85
|
+
### (B) `pip install --editable .` (development)
|
|
86
|
+
|
|
87
|
+
```powershell
|
|
88
|
+
cd <your tmaudit checkout>
|
|
89
|
+
python -m pip install --editable .
|
|
90
|
+
tmaudit list
|
|
91
|
+
tmaudit verify --paper 1
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Edits to `src/tmaudit/templates/*.py` or
|
|
95
|
+
`src/tmaudit/configs/*.py` are picked up immediately on the next
|
|
96
|
+
`tmaudit` invocation. This is the **recommended form for ongoing
|
|
97
|
+
development** of the templates themselves.
|
|
98
|
+
|
|
99
|
+
### (C) `pip install .` (deployment to a venv)
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python -m venv .venv
|
|
103
|
+
source .venv/bin/activate # or .venv\Scripts\activate on Windows
|
|
104
|
+
pip install .
|
|
105
|
+
tmaudit list
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
This produces a `tmaudit` console-script entry in the venv. The
|
|
109
|
+
template and config files are inside the wheel.
|
|
110
|
+
|
|
111
|
+
## v0.3.0 highlights
|
|
112
|
+
|
|
113
|
+
**Released: 2026-07-10.** This release adds 3 new audit categories
|
|
114
|
+
(C8, C9, C10) and brings the project to **10 categories, 176 unit
|
|
115
|
+
tests, 12/12 meta-test bugs caught, 5/5 papers auditable**.
|
|
116
|
+
|
|
117
|
+
| Category | What it checks | Severity | Always runs? |
|
|
118
|
+
|---|---|---|---|
|
|
119
|
+
| **C1** (v0.1.0) | Symbol inline definition | HIGH | Yes |
|
|
120
|
+
| **C2** (v0.1.0) | Bonferroni consistency | HIGH | Yes |
|
|
121
|
+
| **C3** (v0.1.0) | Formalization of key concept | MEDIUM | Yes |
|
|
122
|
+
| **C4** (v0.1.0) | Self-citation threshold | MEDIUM | Yes |
|
|
123
|
+
| **C5** (v0.1.0) | Test-name d | MEDIUM | Yes |
|
|
124
|
+
| **C6** (v0.1.1) | Blacklist word frequency | LOW | Yes |
|
|
125
|
+
| **C7** (v0.1.2) | Ceremonial citation detection | MEDIUM | Yes |
|
|
126
|
+
| **C8** (v0.3.0) | **Statistical power** (d-mismatch, post-hoc power) | HIGH/MED | No (opt-in) |
|
|
127
|
+
| **C9** (v0.3.0) | **Figure-caption consistency** (4 sub-checks) | HIGH/MED | Yes (sub-check 3 opt-in) |
|
|
128
|
+
| **C10** (v0.3.0) | **Reproducibility** (availability, metadata, consistency) | HIGH/MED/LOW | Yes (sub-check 2 opt-in) |
|
|
129
|
+
| **C7-LLM** (v0.2.0) | LLM fallback for C7 borderline cases (opt-in via `TMAUDIT_LLM_*` env) | MEDIUM | No |
|
|
130
|
+
|
|
131
|
+
**v0.2.0 added** (still shipping): `audit-all --output report.md`
|
|
132
|
+
generates a single Markdown report covering all papers; the report
|
|
133
|
+
is uploaded as a CI artefact.
|
|
134
|
+
|
|
135
|
+
**v0.2.0 added** (still shipping): per-paper config for Paper 2,
|
|
136
|
+
Paper 3, Paper 4 (was placeholder in v0.1.1). All 5 papers
|
|
137
|
+
(P1..P5) are now auditable.
|
|
138
|
+
|
|
139
|
+
**Per-paper config** for v0.3.0: `c8_claimed_effects` (statistical),
|
|
140
|
+
`c9_figure_keywords` (figure-caption), `c10_reproducibility_claims`
|
|
141
|
+
(reproducibility). Empty list = opt-out (with graceful degradation
|
|
142
|
+
in C9 and C10).
|
|
143
|
+
|
|
144
|
+
See [`RELEASE_NOTES_v0.3.0.md`](./RELEASE_NOTES_v0.3.0.md) for the
|
|
145
|
+
full release notes and [`engineering_notes_verify_template.md`](./engineering_notes_verify_template.md)
|
|
146
|
+
§12 (C8+C10) and §13 (C9) for the design rationale.
|
|
147
|
+
|
|
148
|
+
## CLI reference
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
tmaudit list # show all known paper configs
|
|
152
|
+
tmaudit verify --paper N [--dry-run] # fork verify_pN.py + run audit
|
|
153
|
+
tmaudit compile --paper N [--dry-run] # fork _compile_check.py + 4-pass build
|
|
154
|
+
tmaudit fix-unicode --paper N [--dry-run] # fork _fix_abstract_unicode.py
|
|
155
|
+
tmaudit audit-all [--start 1] [--end 5] # verify all papers in a range
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Every subcommand also accepts `--paper-dir PATH` to override the
|
|
159
|
+
default paper directory.
|
|
160
|
+
|
|
161
|
+
## The standard 3-step protocol for any new paper
|
|
162
|
+
|
|
163
|
+
```powershell
|
|
164
|
+
cd F:\Research\PAPER<N>_CONSOLIDATED
|
|
165
|
+
|
|
166
|
+
# 1. audit
|
|
167
|
+
tmaudit verify --paper N
|
|
168
|
+
|
|
169
|
+
# 2. fix abstract Unicode (if any finding)
|
|
170
|
+
tmaudit fix-unicode --paper N
|
|
171
|
+
tmaudit verify --paper N
|
|
172
|
+
|
|
173
|
+
# 3. compile
|
|
174
|
+
tmaudit compile --paper N
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Package layout
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
TEMPLATE/
|
|
181
|
+
├── pyproject.toml # build config
|
|
182
|
+
├── tmaudit.pyz # single-file distribution (46 KB)
|
|
183
|
+
├── README.md # this file
|
|
184
|
+
├── engineering_notes_verify_template.md # 6-bug engineering diary
|
|
185
|
+
├── _setup_pkg.py # one-time: copy templates into src/
|
|
186
|
+
├── _build_pyz.py # one-time: build tmaudit.pyz
|
|
187
|
+
├── _compile_appendix.py # LaTeX compile for the appendix
|
|
188
|
+
├── _regen_appendix.py # regenerate appendix_engineering.tex
|
|
189
|
+
├── _status.py # TEMPLATE/ state summary
|
|
190
|
+
└── src/
|
|
191
|
+
└── tmaudit/ # the actual package
|
|
192
|
+
├── __init__.py
|
|
193
|
+
├── __main__.py # `python -m tmaudit`
|
|
194
|
+
├── cli.py # argparse CLI
|
|
195
|
+
├── forge.py # template-substitution engine
|
|
196
|
+
├── templates/
|
|
197
|
+
│ ├── __init__.py
|
|
198
|
+
│ ├── verify_TEMPLATE.py # ≈ 22 KB, ~400 lines
|
|
199
|
+
│ ├── compile_check_TEMPLATE.py # ≈ 4.5 KB
|
|
200
|
+
│ └── fix_abstract_unicode_TEMPLATE.py # ≈ 5 KB
|
|
201
|
+
└── configs/
|
|
202
|
+
├── __init__.py # re-exports
|
|
203
|
+
├── paper_configs.py # VERIFY_CONFIGS for paper 1..5
|
|
204
|
+
└── compile_configs.py # COMPILE_CONFIGS for paper 1..5
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Adding a new paper (e.g., Paper 6)
|
|
208
|
+
|
|
209
|
+
Edit **two** files:
|
|
210
|
+
|
|
211
|
+
1. `src/tmaudit/configs/paper_configs.py` — add a new entry to
|
|
212
|
+
`PAPER_CONFIGS` (or `VERIFY_CONFIGS` after re-export). The fields
|
|
213
|
+
are documented in the docstring at the top of that file.
|
|
214
|
+
2. `src/tmaudit/configs/compile_configs.py` — add a matching entry
|
|
215
|
+
to `COMPILE_CONFIGS`. The fields are documented in the docstring
|
|
216
|
+
there.
|
|
217
|
+
|
|
218
|
+
Then:
|
|
219
|
+
|
|
220
|
+
```powershell
|
|
221
|
+
python -m pip install --editable . --break-system-packages
|
|
222
|
+
python _build_pyz.py
|
|
223
|
+
tmaudit list # confirm Paper 6 shows up
|
|
224
|
+
tmaudit verify --paper 6 # fork + run; will report any HIGH-severity
|
|
225
|
+
# issues caused by your config choices
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Verifying the .pyz is portable
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# On the source machine:
|
|
232
|
+
python _build_pyz.py
|
|
233
|
+
# -> tmaudit.pyz (46 KB)
|
|
234
|
+
|
|
235
|
+
# Copy tmaudit.pyz to a fresh machine with no Python packages installed
|
|
236
|
+
# (only a base Python 3.9+ interpreter):
|
|
237
|
+
scp tmaudit.pyz other-host:/tmp/
|
|
238
|
+
ssh other-host 'python /tmp/tmaudit.pyz list'
|
|
239
|
+
# -> should print the same 5-paper table
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
The `.pyz` has **no external dependencies** (only the Python standard
|
|
243
|
+
library). It works on Linux, macOS, and Windows alike.
|
|
244
|
+
|
|
245
|
+
## Bug history
|
|
246
|
+
|
|
247
|
+
The **twelve historical bugs** encountered while building this
|
|
248
|
+
package are documented in
|
|
249
|
+
[`engineering_notes_verify_template.md`](./engineering_notes_verify_template.md).
|
|
250
|
+
Each bug has a dedicated regression test in
|
|
251
|
+
`tests/test_forge_happy.py`, `tests/test_bug5_unit.py`,
|
|
252
|
+
`tests/test_c6_threshold.py`, `tests/test_c7_citation_context.py`,
|
|
253
|
+
`tests/test_cache.py`, `tests/test_c10_reproducibility.py`,
|
|
254
|
+
`tests/test_c8_statistical_power.py`, and
|
|
255
|
+
`tests/test_c9_figure_caption.py`. The meta-test
|
|
256
|
+
(`_check_all_regressions.py`) injects each bug in turn, asserts the
|
|
257
|
+
regression test catches it, and restores the source. **12/12 bugs
|
|
258
|
+
are caught.**
|
|
259
|
+
|
|
260
|
+
The fix patterns (raw-string regex literals, brace-counting state
|
|
261
|
+
machines, non-letter-class regex, second/third-pass audit logic,
|
|
262
|
+
sentinel-character sub-string extraction, etc.) are all implemented
|
|
263
|
+
in `src/tmaudit/forge.py` and
|
|
264
|
+
`src/tmaudit/templates/verify_TEMPLATE.py`.
|
|
265
|
+
|
|
266
|
+
## Continuous integration
|
|
267
|
+
|
|
268
|
+
### Workflow
|
|
269
|
+
|
|
270
|
+
`.github/workflows/ci.yml` runs on every push and pull request.
|
|
271
|
+
It consists of **five** jobs:
|
|
272
|
+
|
|
273
|
+
1. **pytest** (matrix: Python 3.9, 3.10, 3.11, 3.12 on `ubuntu-latest`)
|
|
274
|
+
— runs the **176-test** suite and uploads JUnit XML artifacts.
|
|
275
|
+
2. **meta-test** (Python 3.11) — runs `_check_all_regressions.py`
|
|
276
|
+
to verify that each of the **12 regression tests** actually catches
|
|
277
|
+
its target bug. Builds `tmaudit.pyz` and runs it as a smoke
|
|
278
|
+
test.
|
|
279
|
+
3. **validate-community-files** (Python 3.11) — runs
|
|
280
|
+
`_check_github_templates.py` to verify the `.github/`
|
|
281
|
+
directory structure (4 issue templates, PR template, CODEOWNERS,
|
|
282
|
+
dependabot.yml, CODE_OF_CONDUCT, SUPPORT, workflows).
|
|
283
|
+
4. **audit-all** (Python 3.11) — runs
|
|
284
|
+
`tmaudit audit-all --start 1 --end 5 --output audit-report.md
|
|
285
|
+
--no-cache` and uploads the Markdown report as a CI artefact.
|
|
286
|
+
5. **lint** (Python 3.11) — runs `pyflakes` on `src/tmaudit/`
|
|
287
|
+
and `tests/`.
|
|
288
|
+
|
|
289
|
+
### Local validation (before pushing)
|
|
290
|
+
|
|
291
|
+
To run the same checks locally before pushing:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
pip install -e . pytest pyflakes
|
|
295
|
+
pytest
|
|
296
|
+
python _check_all_regressions.py
|
|
297
|
+
python _build_pyz.py
|
|
298
|
+
python tmaudit.pyz list
|
|
299
|
+
python -m pyflakes src/tmaudit/ tests/
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Local CI simulation (`act` / `_act_*`)
|
|
303
|
+
|
|
304
|
+
The preferred tool for local CI simulation is
|
|
305
|
+
[nektos/act](https://github.com/nektos/act):
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
act -l # list jobs
|
|
309
|
+
act -j pytest # run the pytest job
|
|
310
|
+
act -j meta-test # run the meta-test job (after pytest)
|
|
311
|
+
act -j lint # run the lint job
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
`act` requires `act` installed **and** a working Docker daemon.
|
|
315
|
+
If either is unavailable (e.g., on a restricted sandbox machine),
|
|
316
|
+
this repo ships two **fallback** simulators:
|
|
317
|
+
|
|
318
|
+
| Script | `act` equivalent | What it does |
|
|
319
|
+
|---|---|---|
|
|
320
|
+
| `_act_dryrun.py` | `act -n` (dry-run) | Parses `ci.yml`, expands the matrix, prints what each step would do. **No commands are executed.** |
|
|
321
|
+
| `_act_simulate.py` | `act` (real run) | Same as dryrun, but actually runs the `run:` steps via `subprocess`. Implements stubs for `actions/checkout@v4`, `actions/setup-python@v5`, `actions/upload-artifact@v4`. |
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
python _act_dryrun.py # show what would be executed
|
|
325
|
+
python _act_dryrun.py --list # show jobs only
|
|
326
|
+
python _act_simulate.py --list # list jobs (act -l equivalent)
|
|
327
|
+
python _act_simulate.py --job pytest # run pytest job
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### CI simulation results
|
|
331
|
+
|
|
332
|
+
`_act_dryrun.py` was used to validate the workflow before
|
|
333
|
+
pushing. Results:
|
|
334
|
+
|
|
335
|
+
- ✅ `ci.yml` is valid YAML (parsed by PyYAML)
|
|
336
|
+
- ✅ **5 jobs**, 4 + 1 + 1 + 1 + 1 matrix rows, ~25 steps
|
|
337
|
+
- ✅ `meta-test` correctly depends on `pytest` (Kahn's algorithm topo sort)
|
|
338
|
+
- ✅ `matrix.python-version` substituted correctly into `${{ ... }}` expressions
|
|
339
|
+
- ✅ `if: always()` preserved on the upload-artifact step
|
|
340
|
+
- ✅ `with:` arguments (e.g., `cache: pip`, `cache-dependency-path: pyproject.toml`) preserved
|
|
341
|
+
|
|
342
|
+
The CI workflow's `run:` blocks are identical to commands
|
|
343
|
+
we have already executed successfully on the host:
|
|
344
|
+
|
|
345
|
+
| CI step | Local result |
|
|
346
|
+
|---|---|
|
|
347
|
+
| `python -m pip install -e .` | tmaudit installed ✅ |
|
|
348
|
+
| `python -m pip install pytest scipy` | deps installed ✅ |
|
|
349
|
+
| `python -m pytest -m "not slow"` | **223 passed, 1 skipped in ~4s** ✅ |
|
|
350
|
+
| `python _check_all_regressions.py` | **14/14 bugs caught** ✅ |
|
|
351
|
+
| `python _check_github_templates.py` | **44/44 OK** ✅ |
|
|
352
|
+
| `python -m src.tmaudit audit-all ...` | audit-report.md generated ✅ |
|
|
353
|
+
| `python -m src.tmaudit audit-all ...` | report uploaded as artefact ✅ |
|
|
354
|
+
| `python _build_pyz.py` | tmaudit.pyz built ✅ |
|
|
355
|
+
| `python tmaudit.pyz list` | 5 papers listed ✅ |
|
|
356
|
+
| `python -m pyflakes src/tmaudit/ tests/` | 0 errors ✅ |
|
|
357
|
+
|
|
358
|
+
### What `_act_*` cannot simulate
|
|
359
|
+
|
|
360
|
+
- `actions/setup-python@v5` cannot actually install a different
|
|
361
|
+
Python version (the host has only one Python; the matrix
|
|
362
|
+
includes 3.9/3.10/3.11/3.12). The simulator prints a
|
|
363
|
+
warning but does not fail.
|
|
364
|
+
- `actions/upload-artifact@v4` is simulated by copying files
|
|
365
|
+
to `_act_run/artifacts/<name>/`.
|
|
366
|
+
- The Docker isolation that real `act` provides is not present;
|
|
367
|
+
steps run on the host shell.
|
|
368
|
+
|
|
369
|
+
### Pre-push hook recommendation
|
|
370
|
+
|
|
371
|
+
To enforce CI validation before every push:
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
# .git/hooks/pre-push
|
|
375
|
+
python _check_yaml.py && python _act_dryrun.py
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
The `_check_yaml.py` script validates `ci.yml` is parseable
|
|
379
|
+
and has the expected structure (catches YAML syntax errors
|
|
380
|
+
before pushing).
|
|
381
|
+
|
|
382
|
+
### Full evidence
|
|
383
|
+
|
|
384
|
+
For the full simulation transcript (including the 5 sandbox
|
|
385
|
+
issues encountered and how they were worked around), see
|
|
386
|
+
[`act_summary.md`](./act_summary.md).
|