PROJECT: action-code-style — deterministic black formatting for Python in MyST/markdown
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 38/100
Research direction
Start by reviewing the .github/actions/code-style-checker/ implementation and test suite referenced in closed PR #240, then compare the architecture questions with issues #268 and #266. Establish the standalone repository and its relationship to myst-lint before implementation. Done means the documented extraction, black formatting, check/fix modes, configuration, and listed tests work in a pilot repository.
Written by the indexing model from the issue text.
Description
Summary
Build a standalone GitHub Action that runs black over Python code embedded in MyST {code-cell} directives and standard markdown fenced code blocks, keeping lecture code PEP8-compliant and consistently formatted. The tool is deterministic (no AI), cheap, and safe to run automatically.
This issue captures the essence of the closed Copilot PR #240 and the original request in #221, plus the architecture decision reached in discussion (a separate repo, not folded into action-style-guide), so the feature can be cleanly re-implemented once it has a home.
Background
- #221 requested automatic
blackstyle checks on Python contained in MySTcode-celldirectives and standard fenced markdown code blocks. - #240 (Copilot) implemented a
code-style-checkeraction insidemeta(.github/actions/code-style-checker/), comment-triggered via@quantecon-code-style. It was never reviewed/merged and is structured the old (in-meta) way, contrary to the migration of actions into individual repos (#244). It has been closed in favour of this documented project. - This is a real, still-unmet need: no current QuantEcon repo provides deterministic
blackformatting of code embedded in markdown.action-style-guideis adjacent but fundamentally different (see below).
Architecture decision: separate action-code-style, not part of action-style-guide
The two share the phrase "code style" but differ on every axis that matters for packaging:
| Axis | black formatting (this project) |
action-style-guide |
|---|---|---|
| Mechanism | Deterministic, fixed rules | AI (Claude), non-deterministic, confidence-scored |
| Dependencies | black only — no API key, free |
LLM API key, cost per run |
| Auto-run | Safe on every PR / push | Comment-triggered only (cost + noise) |
| Cadence | Tiny, stable utility | Large, evolving (prompt versioning, rules DB) |
| Audience | Any MyST/Jupyter Book project | QuantEcon-opinionated |
Decisive points:
- Invocation policy differs —
blackwants to be cheap and always-on (a normal CI check); the AI style guide must stay comment-triggered to avoid being intrusive/expensive. One repo cannot cleanly serve both runtime profiles. - Coupling a stable formatter to a fast-moving AI tool creates release friction — every prompt/rule change would churn a repo that also houses a formatter that rarely changes.
- Small, single-purpose repos match the #244 grain (
action-link-checker,action-check-warnings, …).
The one genuine overlap is the MyST/markdown code-extraction parser (both need to pull Python out of {code-cell} and fenced blocks). If duplication becomes annoying, factor that into a small shared helper rather than merging two tools with opposite runtime profiles.
➡️ Home: a new standalone QuantEcon/action-code-style repo. (The standalone-vs-centralised question is being worked through more broadly in #266 — the final home should be consistent with whatever that lands on.)
Relationship to myst-lint (#268)
#268 proposes myst-lint, a deterministic MyST quality tool (wraps markdownlint + MyST rules: directive/role validation, math-delimiter matching, code-block delimiters, code-cell validation). It shares this project's exact design philosophy (deterministic, no API cost, fast, CI/pre-commit) but a different concern:
myst-lint(#268) validates markdown structure (headings, delimiters, math, directives) — it checks, doesn't reformat code.action-code-style(this, #320) reformats Python code inside blocks withblack(PEP8).
Open question to resolve before building: one tool or two? They could ship as separate siblings, or black-formatting could be a module/rule-set within myst-lint (one deterministic "MyST quality" tool with both a structure-lint pass and a code-format pass). Decide this jointly with #268 rather than in isolation.
Scope / requirements
(capturing the essence of #221 + #240)
- Parse
mdfiles and extract Python from both MyST{code-cell}directives and standard fenced```pythonblocks - Only format blocks tagged
python,python3,ipython,ipython3; skip others (e.g.julia) with an informative log line - Run
blackover each extracted block and write the formatted code back into the file, preserving the surrounding markdown/directive structure exactly - Configurable inputs:
-
files— explicit list and/or glob patterns (e.g.lecture/**/*.md) - toggle MyST
code-cellscanning (default on) - toggle standard markdown block scanning (default on)
-
python-languages(defaultpython,python3,ipython,ipython3) -
black-args(e.g.--line-length=88)
-
- Design intent: deterministic and cheap → support always-on / push-triggered CI usage, in addition to an optional comment trigger (
@quantecon-code-style) - Check mode (non-mutating): report diffs / fail CI without committing, so it can run as a status check
- Fix mode: commit formatted results, per-file, with a message like
[{filename}] applying black changes to code(per #221) - Tests: unformatted MyST+markdown, already-formatted (no-op), non-python (skip), glob expansion
Reference implementation
#240 (closed) is a usable starting point — it already had a working line-by-line MyST/markdown parser, language detection, glob handling, and a test suite. Re-implement cleanly in the new repo rather than porting the Copilot bulk wholesale.
Related
- #221 — original feature request (closed, superseded by this project)
- #240 — closed Copilot PR; reference implementation
- #244 — migration of actions into individual repos (the grain this follows)
- #268 —
myst-lint, sibling deterministic MyST quality tool; resolve "one tool or two?" jointly - #266 — mono-repo vs centralised actions vs hybrid (informs the home decision)
- QuantEcon/action-style-guide — adjacent AI style tool; intentionally kept separate
- QuantEcon/actions — build/preview/publish actions monorepo
Suggested next steps
- Create
QuantEcon/action-code-style(+ atest-action-code-stylefixture repo, matching theaction-style-guidepattern) - Port/clean the parser +
blackrunner from #240 - Implement both check mode (always-on CI) and fix mode (comment trigger / commit)
- Pilot on one lecture repo, then roll out
- Dominant language
- No language data
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from QuantEcon/meta
-
test-jax-install.py does not assert the GPU — a silent CPU fallback passes CI in all five repos Openbug testing
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
GitHub MCP server drops tag-shaped content from issue-body reads — decide whether to report upstream Open
Difficulty 5/5 Over a week Newbie friendliness 35/100
-
enhancement project
Difficulty 5/5 Over a week Newbie friendliness 35/100
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 35/100
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 35/100
Similar issues
-
kind/bug Ubuntu 24
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
kubernetes-sigs/kubespray#13532 ·
-
Needs Design Priority: Wishlist
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
elementary/flatpak-platform#253 ·
-
tagbot-manual
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100