Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# SPDX-License-Identifier: MPL-2.0
# Review-only. No AI-authored finishing-touch commits.
# Canonical language policy:
# https://github.com/metadatastician/standards/blob/main/3-practice/LANGUAGE-POLICY.adoc
reviews:
auto_review:
enabled: true
drafts: false
path_instructions:
- path: "**/*"
instructions: >-
Estate policy prohibits NEW Python files, scripts, test code,
dependencies, and Python package manifests with no exceptions.
Do not recommend Python or generate Python fixes. The existing
upstream React and TypeScript frontend is temporarily permitted until
Marid is ready. Scientific code is Julia and R with pinned toolchains.
Flag additions of Python as a policy violation. Do not rewrite
unrelated upstream code for cosmetic compliance. Validate any
replacement through scientific result parity and tests.
finishing_touches:
docstrings:
enabled: false
unit_tests:
enabled: false
simplify:
enabled: false
autofix:
enabled: false
fix_ci:
enabled: false
resolve_merge_conflict:
enabled: false
43 changes: 43 additions & 0 deletions .github/workflows/language-policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# SPDX-License-Identifier: MPL-2.0
name: Language policy (no new Python)
on:
pull_request:
branches: [main]
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
jobs:
no-new-python:
name: No new Python
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Refuse Python additions and edits (allow deletion)
env:
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PUSH_BEFORE_SHA: ${{ github.event.before }}
EVENT_KIND: ${{ github.event_name }}
run: |
set -euo pipefail
if [[ "$EVENT_KIND" == pull_request ]]; then
base=$PR_BASE_SHA
elif [[ "$EVENT_KIND" == push ]]; then
base=$PUSH_BEFORE_SHA
if [[ "$base" == 0000000000000000000000000000000000000000 ]]; then
echo 'No push base available: refusing ambiguous evidence' >&2
exit 2
fi
else
echo 'Manual probe covers HEAD^..HEAD, not PR merge-base scope'
base=$(git rev-parse HEAD^)
fi
bash scripts/check-no-new-python.sh "$base"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Run the policy check from trusted code

For pull requests, the workflow checks out the contributor-controlled head SHA and then executes both policy scripts from that checkout. A PR can therefore add Python while modifying scripts/check-no-new-python.sh and its self-test to return success, making the required No new Python check green; the enforcement logic should come from a trusted base revision or otherwise be protected from changes in the PR being evaluated.

Useful? React with 👍 / 👎.

- name: Planted-negative and positive controls
run: bash scripts/tests/test-no-new-python.sh
34 changes: 34 additions & 0 deletions scripts/check-no-new-python.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: MPL-2.0
# Refuse newly added/modified Python source and manifests. Untouched inherited
# debt is not a blanket authorisation to add more. Deletion is allowed.
set -euo pipefail
if [[ $# -ne 1 || ! "$1" =~ ^[0-9a-fA-F]{40}$ ]]; then
printf 'Usage: %s <base-commit-sha>\n' "$0" >&2
exit 2
fi
base=$1
if ! git cat-file -e "${base}^{commit}"; then
echo 'Base commit unavailable; no language-policy evidence' >&2
exit 2
fi
changed=$(mktemp)
trap 'rm -f "$changed"' EXIT
if ! git diff --name-only --diff-filter=ACMR -z "${base}...HEAD" -- > "$changed"; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include type changes in the checked diff

The ACMR filter omits Git status T, so converting an inherited .py file between a regular file and a symlink is reported as a type change and the gate prints PASS without examining it. This contradicts the promised ban on edits to inherited Python paths; include T (or exclude only deletions) so these modifications are checked.

Useful? React with 👍 / 👎.

echo 'Cannot determine changed files; refusing a false green' >&2
exit 2
fi
bad=0
while IFS= read -r -d '' file; do
case "${file##*/}" in

Check failure on line 23 in scripts/check-no-new-python.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a default case (*) to handle unexpected values.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_MetaManifold-WebUI&issues=AaGPAkY2oYbKsR1GVvdE&open=AaGPAkY2oYbKsR1GVvdE&pullRequest=307
*.py|*.pyi|pyproject.toml|Pipfile|Pipfile.lock|poetry.lock|uv.lock|.python-version|setup.cfg|tox.ini|pytest.ini|requirements*.txt|requirements*.in)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Detect extensionless Python scripts

The gate classifies files only by a small filename allowlist, so an executable such as bin/report containing #!/usr/bin/env python3 passes even though it is new Python code; .pyw and other valid Python script names also pass. Because the stated policy bans Python scripts rather than only .py paths, inspect added/modified file contents for Python shebangs and cover the remaining Python source forms.

Useful? React with 👍 / 👎.

printf 'BANNED Python contribution: %q\n' "$file" >&2
bad=1 ;;
esac
done < "$changed"
if (( bad )); then
echo 'Python is banned for new work; migrate to approved languages. Removal-only cleanup is allowed.' >&2
echo 'Canon: metadatastician/standards/3-practice/LANGUAGE-POLICY.adoc section 3' >&2
exit 1
fi
echo 'Language policy PASS: no new or modified Python files/manifests in this diff; legacy untouched files are not certified.'
46 changes: 46 additions & 0 deletions scripts/tests/test-no-new-python.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: MPL-2.0
# Both pass and planted-fail controls for the diff-based ban.
set -euo pipefail
script=$(cd "$(dirname "$0")/.." && pwd)/check-no-new-python.sh
scratch=$(mktemp -d)
trap 'rm -rf "$scratch"' EXIT
cd "$scratch"
git init -q
git config user.name 'Language Gate Test'
git config user.email 'language-gate@example.invalid'
mkdir -p bench scripts
printf 'print("legacy")\n' > scripts/legacy.py
git add . && git commit -qm 'Pre-existing Python debt'
base=$(git rev-parse HEAD)
expect_failure() {
if bash "$script" "$base" > "$scratch/output.log" 2>&1; then
echo 'ERROR: planted Python violation passed' >&2; exit 1
fi
grep -q 'BANNED Python contribution:' "$scratch/output.log" || { cat "$scratch/output.log" >&2; exit 1; }
}
expect_pass() { bash "$script" "$base" > /dev/null; }
printf 'cat("R allowed")\n' > bench/check.R
git add . && git commit -qm 'Add R'
expect_pass
printf 'print("new")\n' > bench/new.py
git add . && git commit -qm 'Add Python'
expect_failure
git rm -q bench/new.py && git commit -qm 'Remove Python'
expect_pass
printf 'print("changed")\n' >> scripts/legacy.py
git add . && git commit -qm 'Edit legacy Python'
expect_failure
git restore --source="$base" scripts/legacy.py
git add . && git commit -qm 'Restore legacy'
expect_pass
printf '[project]\nname = "wrong"\n' > pyproject.toml
git add . && git commit -qm 'Add Python manifest'
expect_failure
git rm -q pyproject.toml && git commit -qm 'Remove manifest'
expect_pass
git rm -q scripts/legacy.py && git commit -qm 'Retire Python'
expect_pass
if bash "$script" not-a-sha >/dev/null 2>&1; then echo 'Malformed base passed' >&2; exit 1; fi
if bash "$script" 0000000000000000000000000000000000000000 >/dev/null 2>&1; then echo 'Missing base passed' >&2; exit 1; fi
echo 'no-new-python gate: planted-positive and planted-negative fixtures PASS'
Loading