release: v0.3.0 \u2014 P0 hardening + full test suite + CI#3
Merged
Conversation
Introduces the formal audit artifacts that drive the rest of this change set: 16 findings across security, license, code quality, packaging, and compliance, prioritized P0-P3. The follow-up commits on this branch close every P0 item. Also adds scripts/create_issues.sh for pushing the backlog into GitHub Issues, and updates .gitignore to exclude pytest/coverage artifacts and local Claude Code config. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the two placeholders that made the previous LICENSE legally non-functional: - "Copyright (c) 2025 [Your Name]" -> "Copyright (c) 2025 Bishwas Jha" - "[MIT terms continued...]" -> full MIT grant + warranty disclaimer Closes AUDIT_REPORT.md finding LIC-001 (CRITICAL): until now the project had no enforceable license and could not legally be used or redistributed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces naive str.replace() with a two-pass algorithm that splits
input into (string-literal, code) regions and only applies keyword
substitution to code regions, using custom lookbehind/lookahead for
the Devanagari block so keywords embedded in longer identifiers are
not matched.
Fixes two data-corrupting bugs proven in AUDIT_REPORT.md finding
CQ-001 (CRITICAL):
- छपाउ("यह में है") no longer becomes print("यह in है")
(the word में inside the string literal is preserved)
- नवयुग = ५ no longer becomes __init__युग = 5
(नव -> __init__ only fires at word boundaries)
The pre-compiled pattern cache keeps the hot path fast despite the
regex overhead.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two false-positive fixes that blocked idiomatic Maithili code from
linting cleanly:
1. Comparison operators (==, !=, <=, >=) were being parsed as
assignments by the naive .split("=") logic, producing spurious
"invalid variable name" errors on any conditional. Now detects
the operator context before treating an = as an assignment.
2. नव (mapped to __init__) was flagged as an unused function
because it is never called by name — Python invokes it
implicitly on class instantiation. Skipped from the unused-
function post-scan.
Also ignores attribute assignments (e.g., स्वयं.नाम = ...) which
are never new-variable declarations.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes AUDIT_REPORT.md finding SEC-001 (CRITICAL): previously any
.dmai file could do "आयात os" (which transpiled to "import os")
and then perform arbitrary filesystem or process operations with
the full authority of the CLI user.
The new execution model:
- exec_globals no longer inherits the CLI's globals(); it gets a
fresh {"__builtins__": safe_builtins} dict.
- safe_builtins excludes __import__, exec, eval, compile, open,
and breakpoint. __import__ is replaced with a whitelist-only
variant that only permits modules in MAITHILI_MODULES values.
- translate_imports() now returns the set of modules it actually
translated so raw Python "import os" lines injected post-
transpile (never surfaced from a Maithili import) are rejected.
- _validate_imports() catches the rejected imports BEFORE exec
runs, since Python's import statement does not always route
through __import__.
Belt-and-suspenders: both layers (static validator + runtime
__import__ hook) must pass for a module to load, so bypassing one
still leaves the other in place.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…n -m entry
Wraps several packaging and CLI-ergonomics improvements that the
audit and tests both depend on:
- Adds pyproject.toml (PEP 517/518) as the canonical metadata source,
with pytest + coverage configuration co-located (closes PKG-001).
- setup.py kept as legacy shim; reads version via regex (not import)
so it works in isolated build envs. Bumps python_requires from
>=3.6 (EOL) to >=3.9, aligning with the CI matrix.
- maithili_dsl/__init__.py now exposes __version__ = "0.3.0" and
__all__ (closes PKG-002, PKG-003). Single source of truth.
- Adds maithili_dsl/__main__.py so `python -m maithili_dsl <file>`
works without relying on the installed console script.
- cli.main() now returns an integer exit code, accepts argv for
testability, and supports --version / -V. run_dmai_file() uses
named EXIT_* constants (NOT_FOUND, LINT_ERROR, IMPORT_BLOCKED,
RUNTIME_ERROR, USAGE) so CI and smoke tests can assert on
specific failure paths instead of just "non-zero".
- requirements-dev.txt pins pytest + pytest-cov + pytest-timeout
with compatible-range bounds.
- .gitignore ignores .venv/ (in addition to the previously added
pytest/coverage/claude entries).
No runtime dependencies added — the package still has zero runtime
deps.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tiers
Closes AUDIT_REPORT.md finding CQ-002 (HIGH): the project had zero
automated tests. This commit adds 142 tests across 6 files:
- tests/test_numeral.py — every Devanagari digit + mixed text
- tests/test_transpile.py — every keyword in DEVNAGIRI_KEYWORD_MAP
parametrized + explicit CQ-001 regression cases (string literals
and word boundaries) + "transpiled output is valid Python"
- tests/test_linter.py — clean-code pass, == not flagged,
नव constructor not flagged as unused, unbalanced paren/quote,
line length, snake_case toggle, all known exception translations
- tests/test_security.py — _validate_imports rejects raw
Python imports; _make_safe_import only permits whitelist;
exec/eval/open/compile/breakpoint absent from safe_builtins;
end-to-end attacks (import os, exec(), eval(), open()) rejected
by run_dmai_file with correct exit codes
- tests/test_cli.py — every EXIT_* code is reachable by
a test; subprocess invocation via `python -m maithili_dsl`
works for --version, usage, and file execution
- tests/test_smoke.py — every example in examples/ runs
end-to-end (parametrized); error.dmai is expected to be
rejected by the linter, not executed
Coverage (measured locally with pytest-cov):
maithili_dsl/__init__.py 100%
maithili_dsl/cli.py 98%
maithili_dsl/transpiler/__init__.py 100%
maithili_dsl/transpiler/linter.py 90%
maithili_dsl/transpiler/mappings.py 100%
maithili_dsl/transpiler/numeral.py 100%
maithili_dsl/transpiler/transpile.py 98%
TOTAL 95%
Critical modules (cli, transpile, linter) all at or above the
90% gate set in the implementation plan.
Run with: pytest -v --cov=maithili_dsl --cov-report=term-missing
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes AUDIT_REPORT.md finding #6 (P1): the project had no CI/CD
gate — code could merge without any automated verification.
The workflow runs on every push and PR to main and development:
- Matrix: 4 Python versions x 2 operating systems = 8 jobs.
- Installs the package editable + dev deps with pip caching keyed
on requirements-dev.txt + pyproject.toml.
- Verifies both CLI entry points (`python -m maithili_dsl` and the
`python_maithili` console script) respond to --version.
- Runs the full pytest suite with coverage.
- Runs a bash smoke loop over every .dmai in examples/, treating
error.dmai as expected-to-fail so a regression that starts
executing it would be caught immediately.
- Uploads coverage.xml as an artifact from the ubuntu + 3.12 job.
Also adds .github/PULL_REQUEST_TEMPLATE.md to enforce test evidence
and audit-reference fields on future PRs — so the thing that's in
the root of this branch (a PR body tied to specific BACKLOG items)
becomes the default for everyone.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… CONTRIBUTING
Closes four compliance / docs findings from AUDIT_REPORT.md:
- SEC-003 / compliance "SECURITY.md MISSING": adds SECURITY.md with
a responsible-disclosure contact, supported-version table, an
explicit threat model pinned to the sandbox's enforcement layers,
and an SLA for acknowledgement / triage / patch.
- DOCS P3 "README references `youruser`": clone URL now points at
alphacrack/python-maithili-dsl. Also adds a Security section
linking to SECURITY.md, a Testing section documenting the
pytest + coverage-gate workflow, and moves "Unit testing + CI/CD"
out of Future Goals (it ships in this release). Replaces the
future-goals list with still-open items (while / try-except /
mypy).
- DOCS P2 "CONTRIBUTING.md has duplicated README content": the
entire README was pasted above the actual contributing section.
Rewrites CONTRIBUTING.md from scratch with real dev setup
(venv + editable install + requirements-dev), a test-tier table,
the coverage gate, and a security-change policy requiring a new
test + a "Security Considerations" PR section.
- Adds CHANGELOG.md in Keep-a-Changelog format. The 0.3.0 section
documents every Added / Fixed / Changed item on this branch,
cross-referenced to the AUDIT_REPORT.md finding IDs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release PR consolidating
developmentintomain. This unfreezesmain, which has been stuck at the initial commit. After this lands,mainreflects the 0.3.0 release.Contains 13 commits ahead of
main:What's in 0.3.0
See CHANGELOG.md for the complete entry. Highlights:
Security
exec()with safe-builtins map (noexec/eval/open/compile/breakpoint) and import whitelist driven fromMAITHILI_MODULES. Closes audit finding SEC-001 (CRITICAL)._validate_imports+ runtime__import__wrapper.SECURITY.mdwith threat model and responsible-disclosure process.Correctness (data-loss bugs fixed)
छपाउ("यह में है")stays intact instead of becomingprint("यह in है").नवयुगstays intact instead of becoming__init__युग.==comparisons as assignments.नव(constructor) as unused.Infrastructure
pyproject.toml(PEP 517/518) with pytest + coverage config.python -m maithili_dslentry point;--versionflag; named exit codes.Compliance
[Your Name]/[MIT terms continued...]placeholders). Closes LIC-001 (CRITICAL).CHANGELOG.mdin Keep-a-Changelog format.youruser→alphacrack); CONTRIBUTING rewritten with real dev/test workflow.Test Evidence
PR #2 shipped with all 8 CI jobs green (Python 3.9/3.10/3.11/3.12 × Ubuntu/macOS). CI will re-run on this PR against
main— expected to pass identically.Local verification before the PR #2 merge:
Breaking Changes
python_requiresto>=3.9. Users still on 3.6–3.8 must pinpython_maithili<0.3.cli.run_dmai_fileandcli.mainnow return an integer exit code (previously implicitNone). Callers treating any return as "success" should now check for0.No other API changes.
Post-merge cleanup
After this merges:
origin/fix/issue-with-linterwill be deleted (it's already fully contained indevelopmentvia PR added more example and fixed issue with linting #1, verified bygit log origin/fix/issue-with-linter --not origin/developmentreturning empty).Checklist
developmentdevelopmentHEAD (all 8 matrix jobs)0.3.0set consistently inmaithili_dsl/__init__.pyand propagated viasetup.py+pyproject.toml🤖 Generated with Claude Code