Skip to content

Commit 528722d

Browse files
committed
update
1 parent 749bbd3 commit 528722d

9 files changed

Lines changed: 413 additions & 15 deletions

File tree

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# ============================================================
2+
# .github/workflows/verify-regimes.yml (Verify Regime Compatibility)
3+
# ============================================================
4+
# Updated: 2026-04-27 (REPO-SPECIFIC)
5+
# PURPOSE: Verify that this mapping repository can be evaluated against
6+
# SE regime behavior and generate the regime coverage matrix.
7+
8+
name: Verify Regime Compatibility
9+
10+
on:
11+
push:
12+
pull_request:
13+
workflow_dispatch: # WHY: Manual trigger - always available
14+
workflow_call: # WHY: Allow this workflow to be called by other workflows if needed
15+
inputs:
16+
cases_path:
17+
required: false
18+
type: string
19+
default: "cases/"
20+
report_path:
21+
required: false
22+
type: string
23+
default: "reports/stress_report.md"
24+
25+
permissions:
26+
contents: read
27+
28+
env:
29+
PYTHONUNBUFFERED: "1" # WHY: Real-time log output in CI.
30+
PYTHONIOENCODING: "utf-8" # WHY: Consistent encoding across platforms.
31+
PYTHON_VERSION: "3.15"
32+
UV_PYTHON: "3.15"
33+
34+
jobs:
35+
verify_regime_compatibility:
36+
runs-on: ubuntu-latest
37+
38+
steps:
39+
# ============================================================
40+
# A) ASSEMBLE: Checkout code and set up environment
41+
# ============================================================
42+
43+
- name: A1) Checkout repository code
44+
uses: actions/checkout@v6
45+
# WHY: Required so all subsequent steps can access repo files.
46+
47+
- name: A2) Install uv (with caching)
48+
uses: astral-sh/setup-uv@v7
49+
with:
50+
enable-cache: true
51+
# WHY: Cache the uv tool itself for faster subsequent runs.
52+
cache-dependency-glob: "uv.lock"
53+
# WHY: Invalidate cache only when locked dependencies change.
54+
55+
- name: A3) Install Python ${{ env.PYTHON_VERSION }}
56+
run: uv python install ${{ env.PYTHON_VERSION }}
57+
# WHY: Ensures the pinned Python version is available in CI.
58+
# OBS: Does not modify the repo; uv manages the interpreter locally.
59+
60+
- name: A4) Install all dependencies
61+
run: uv sync --extra dev --extra docs --upgrade
62+
# WHY: Install dev and docs extras so all check and build tools are available.
63+
# OBS: --upgrade ensures CI catches dependency drift early.
64+
65+
- name: A5) Show tool versions
66+
run: |
67+
uv --version
68+
uv run python --version
69+
uv run python -m ruff --version
70+
uv run python -m pyright --version
71+
if [ -f "zensical.toml" ]; then
72+
uv run python -m zensical --version
73+
fi
74+
# WHY: Version output helps debug when tools change.
75+
76+
# ============================================================
77+
# B) BASELINE CHECKS: Verify regime compatibility
78+
# ============================================================
79+
- name: B1) Verify regime compatibility
80+
run: |
81+
uv run python -m se_mapping_education_math_g8 verify-regimes \
82+
--cases "${{ inputs.cases_path || 'cases/' }}" \
83+
--report "${{ inputs.report_path || 'reports/stress_report.md' }}"
84+
85+
- name: B2) Upload stress report
86+
uses: actions/upload-artifact@v4
87+
with:
88+
name: stress-report
89+
path: "${{ inputs.report_path || 'reports/stress_report.md' }}"

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ uvx pre-commit run --all-files
114114
uv run python -m se_mapping_education_math_g8 sort
115115
uv run python -m se_mapping_education_math_g8 validate
116116
uv run python -m se_mapping_education_math_g8 matrix
117+
uv run python -m se_mapping_education_math_g8 verify-regimes
117118

118119
# do chores
119120
npx markdownlint-cli "**/*.md" --fix

cases/.gitkeep

Whitespace-only changes.

cases/education/math/g8/cases.toml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# ============================================================
2+
# cases/education/math/g8/cases.toml
3+
# Regime stress-test cases grounded in se-mapping-education-math-g8 artifacts.
4+
# Domain: education.math.g8
5+
# Source repo: se-mapping-education-math-g8
6+
# ============================================================
7+
8+
# --- ENR SPLIT: branching ---
9+
# NAEP.Math.G8.Algebra.LinearEquations is the standard identifier.
10+
# It can be expressed in multiple notational forms (short code, full name,
11+
# URI) while referring to the same assessment locus.
12+
13+
[[case]]
14+
id = "edu-math-g8-enr-l-001"
15+
domain = "education.math.g8"
16+
source = "se-mapping-education-math-g8:NAEP.Math.G8.Algebra.LinearEquations"
17+
description = """
18+
NAEP.Math.G8.Algebra.LinearEquations expressed as a short code vs a full
19+
descriptive label refers to the same assessment standard locus.
20+
"""
21+
candidate_regime = "ENR-L"
22+
transformations = ["BF"]
23+
notes = "Locus identity survives branching: same standard, different notational artifacts."
24+
[[case.expected]]
25+
after = "BF"
26+
regime = "ENR-L"
27+
outcome = "PRS"
28+
29+
[[case]]
30+
id = "edu-math-g8-enr-i-001"
31+
domain = "education.math.g8"
32+
source = "se-mapping-education-math-g8:NAEP.Math.G8.Algebra.LinearEquations"
33+
description = """
34+
The specific artifact 'NAEP.Math.G8.Algebra.LinearEquations' (short code form)
35+
does not survive branching into a URI-form artifact — distinct objects are produced.
36+
"""
37+
candidate_regime = "ENR-I"
38+
transformations = ["BF"]
39+
notes = "Artifact identity breaks under branching: distinct constructed objects."
40+
[[case.expected]]
41+
after = "BF"
42+
regime = "ENR-I"
43+
outcome = "BRK"
44+
45+
# --- CTX SPLIT: decomposition ---
46+
# ctx.naep.math.g8 is defined as the full NAEP Grade 8 assessment framework.
47+
# It can be decomposed into sub-contexts (Algebra, Data/Statistics, Geometry)
48+
# while applying to the same student population.
49+
50+
[[case]]
51+
id = "edu-math-g8-ctx-e-001"
52+
domain = "education.math.g8"
53+
source = "se-mapping-education-math-g8:ctx.naep.math.g8"
54+
description = """
55+
ctx.naep.math.g8 decomposed into Algebra + Data/Statistics + Geometry
56+
sub-contexts still applies to the same Grade 8 student population.
57+
"""
58+
candidate_regime = "CTX-E"
59+
transformations = ["decomposition"]
60+
notes = "Extensional identity survives decomposition: same student case set."
61+
[[case.expected]]
62+
after = "decomposition"
63+
regime = "CTX-E"
64+
outcome = "PRS"
65+
66+
[[case]]
67+
id = "edu-math-g8-ctx-s-001"
68+
domain = "education.math.g8"
69+
source = "se-mapping-education-math-g8:ctx.naep.math.g8"
70+
description = """
71+
ctx.naep.math.g8 decomposed into sub-contexts is no longer the same
72+
structural organization as the unified framework.
73+
"""
74+
candidate_regime = "CTX-S"
75+
transformations = ["decomposition"]
76+
notes = "Structural identity breaks under decomposition: organization changed."
77+
[[case.expected]]
78+
after = "decomposition"
79+
regime = "CTX-S"
80+
outcome = "BRK"
81+
82+
# --- NOR SPLIT: normative reorganization ---
83+
# nor.math.g8.solve_linear_eq_one_var is a normative structure for solving
84+
# one-variable linear equations. It can be reorganized into sub-objectives
85+
# (isolate variable, apply inverse operations, verify solution) while
86+
# preserving what proficiency requires.
87+
88+
[[case]]
89+
id = "edu-math-g8-nor-c-001"
90+
domain = "education.math.g8"
91+
source = "se-mapping-education-math-g8:nor.math.g8.solve_linear_eq_one_var"
92+
description = """
93+
nor.math.g8.solve_linear_eq_one_var reorganized into sub-objectives
94+
(isolate variable, apply inverse operations, verify) preserves
95+
what the standard requires of students.
96+
"""
97+
candidate_regime = "NOR-C"
98+
transformations = ["nor_reorg"]
99+
notes = "Content identity survives reorganization: same normative requirements."
100+
[[case.expected]]
101+
after = "nor_reorg"
102+
regime = "NOR-C"
103+
outcome = "PRS"
104+
105+
[[case]]
106+
id = "edu-math-g8-nor-s-001"
107+
domain = "education.math.g8"
108+
source = "se-mapping-education-math-g8:nor.math.g8.solve_linear_eq_one_var"
109+
description = """
110+
nor.math.g8.solve_linear_eq_one_var reorganized into sub-objectives
111+
is no longer the same structural form as the original single standard.
112+
"""
113+
candidate_regime = "NOR-S"
114+
transformations = ["nor_reorg"]
115+
notes = "Structural identity breaks under reorganization: organization changed."
116+
[[case.expected]]
117+
after = "nor_reorg"
118+
regime = "NOR-S"
119+
outcome = "BRK"
120+
121+
# --- Additional NOR case: two-sides equation ---
122+
# nor.math.g8.solve_linear_eq_two_sides overlaps with LinearEquations
123+
# via the alignment mapping. Tests that the same regime behavior holds
124+
# for a second normative artifact in the same alignment cluster.
125+
126+
[[case]]
127+
id = "edu-math-g8-nor-c-002"
128+
domain = "education.math.g8"
129+
source = "se-mapping-education-math-g8:nor.math.g8.solve_linear_eq_two_sides"
130+
description = """
131+
nor.math.g8.solve_linear_eq_two_sides reorganized to make the
132+
two-sides constraint explicit preserves what the standard requires.
133+
"""
134+
candidate_regime = "NOR-C"
135+
transformations = ["nor_reorg"]
136+
notes = "Second NOR-C case from the LinearEquations alignment cluster."
137+
[[case.expected]]
138+
after = "nor_reorg"
139+
regime = "NOR-C"
140+
outcome = "PRS"

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ dynamic = ["version"] # WHY: Version is computed from git tags at build time (se
1919
dependencies = [
2020
"se-mapping-education",
2121
"se-mapping-education-math",
22+
"se-regimes",
2223
"tomli-w",
2324
]
2425

@@ -140,6 +141,7 @@ convention = "google" # ALT: "numpy" — choose one, never mix.
140141
[tool.uv.sources]
141142
se-mapping-education = { git = "https://github.com/structural-explainability/se-mapping-education", branch = "main" }
142143
se-mapping-education-math = { git = "https://github.com/structural-explainability/se-mapping-education-math", branch = "main" }
144+
se-regimes = { git = "https://github.com/structural-explainability/se-regimes" }
143145

144146
# ============================================================
145147
# SECTION 3: BUILD SYSTEM (boilerplate; CUSTOM src/ agreement)

reports/stress_report.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# se-regimes stress report
2+
3+
**Regimes:** 9 **Families:** 3 **Cases:** 7 **Passed:** 7 **Failed:** 0
4+
5+
## Rule matrix
6+
7+
_Declared responses from the regime registry (se-regimes): theory-level assertions, not empirically validated._
8+
_Populated from registry regardless of case coverage._
9+
10+
| regime | BF | decomposition | nor_reorg |
11+
| ------- | --- | ------------- | --------- |
12+
| `OBL` | INH | INH | INH |
13+
| `OCC` | INH | INH | INH |
14+
| `REC` | INH | INH | INH |
15+
| `ENR-L` | PRS | INH | INH |
16+
| `ENR-I` | BRK | INH | INH |
17+
| `CTX-E` | INH | PRS | INH |
18+
| `CTX-S` | INH | BRK | INH |
19+
| `NOR-C` | INH | INH | PRS |
20+
| `NOR-S` | INH | INH | BRK |
21+
22+
Legend for rule matrix:
23+
24+
- PRS = Preserves identity. The transformation does not change identity under the regime.
25+
- BRK = Breaks identity. The transformation produces a distinct identity under the regime.
26+
- INH = Inherits identity.
27+
The transformation does not operate on the identity criteria tracked by the regime;
28+
identity is carried forward without a PRS/BRK determination at this layer.
29+
30+
## Case coverage matrix
31+
32+
_Which regime x family pairs have at least one stress-test case._
33+
34+
| regime | BF | decomposition | nor_reorg |
35+
| ------- | --- | ------------- | --------- |
36+
| `OBL` | - | - | - |
37+
| `OCC` | - | - | - |
38+
| `REC` | - | - | - |
39+
| `ENR-L` || - | - |
40+
| `ENR-I` || - | - |
41+
| `CTX-E` | - || - |
42+
| `CTX-S` | - || - |
43+
| `NOR-C` | - | - ||
44+
| `NOR-S` | - | - ||
45+
46+
## All cases
47+
48+
| id | domain | regime | expected | source | result |
49+
| ----------------------- | ------------------- | ------- | ------------------- | -------------------------------------------------------------------- | ------ |
50+
| `edu-math-g8-enr-l-001` | `education.math.g8` | `ENR-L` | `BF:PRS` | `se-mapping-education-math-g8:NAEP.Math.G8.Algebra.LinearEquations` ||
51+
| `edu-math-g8-enr-i-001` | `education.math.g8` | `ENR-I` | `BF:BRK` | `se-mapping-education-math-g8:NAEP.Math.G8.Algebra.LinearEquations` ||
52+
| `edu-math-g8-ctx-e-001` | `education.math.g8` | `CTX-E` | `decomposition:PRS` | `se-mapping-education-math-g8:ctx.naep.math.g8` ||
53+
| `edu-math-g8-ctx-s-001` | `education.math.g8` | `CTX-S` | `decomposition:BRK` | `se-mapping-education-math-g8:ctx.naep.math.g8` ||
54+
| `edu-math-g8-nor-c-001` | `education.math.g8` | `NOR-C` | `nor_reorg:PRS` | `se-mapping-education-math-g8:nor.math.g8.solve_linear_eq_one_var` ||
55+
| `edu-math-g8-nor-s-001` | `education.math.g8` | `NOR-S` | `nor_reorg:BRK` | `se-mapping-education-math-g8:nor.math.g8.solve_linear_eq_one_var` ||
56+
| `edu-math-g8-nor-c-002` | `education.math.g8` | `NOR-C` | `nor_reorg:PRS` | `se-mapping-education-math-g8:nor.math.g8.solve_linear_eq_two_sides` ||

src/se_mapping_education_math_g8/cli.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from se_mapping_education.sort import run_sort
77
from se_mapping_education.validate import run_validate
88

9+
from se_mapping_education_math_g8.verify_regimes import main as run_verify_regimes
10+
911

1012
def main(argv: list[str] | None = None) -> int:
1113
"""Entry point for CLI commands."""
@@ -14,7 +16,7 @@ def main(argv: list[str] | None = None) -> int:
1416

1517
if not argv:
1618
print("Usage: python -m se_mapping_education_math_g8 <command>")
17-
print("Commands: validate, matrix, sort")
19+
print("Commands: validate, matrix, sort, verify-regimes")
1820
return 1
1921

2022
command = argv[0]
@@ -28,5 +30,8 @@ def main(argv: list[str] | None = None) -> int:
2830
if command == "matrix":
2931
return run_matrix()
3032

33+
if command == "verify-regimes":
34+
return run_verify_regimes(argv[1:])
35+
3136
print(f"Unknown command: {command}")
3237
return 1

0 commit comments

Comments
 (0)