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
37 changes: 33 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
# Full history: check_metrics_fresh.py verifies that METRICS.yaml's
# ``generator_git_sha`` is an ancestor of HEAD; a shallow checkout
# (default depth 1) cannot walk ancestry on the PR merge ref, so the
# gate fails with "not an ancestor of HEAD" even when METRICS is in
# sync.
uses: actions/checkout@v5
with:
fetch-depth: 0

- name: Set up uv
uses: astral-sh/setup-uv@v8.1.0
Expand Down Expand Up @@ -111,8 +118,12 @@ jobs:
- name: Synthetic-surface classification gate
# Every retained fallback/mock/placeholder/stub occurrence in tracked
# project-owned files must be classified as degraded output, template
# variable, type stub, negative control, or UI empty state.
run: cd .. && uv run --directory cogant python ../tools/audit_synthetic_surfaces.py --strict
# variable, type stub, negative control, or UI empty state. --strict
# additionally validates generated public artifacts (output/manuscript,
# figure sidecars), which only exist after a pipeline run — that lane
# belongs to tools/release_gate.py on a rendered worktree, not a clean
# CI checkout, so CI enforces the classification layer only.
run: cd .. && uv run --directory cogant python ../tools/audit_synthetic_surfaces.py

- name: Manuscript figure-renderer provenance gate
# Registered manuscript figures must point to importable renderers and
Expand Down Expand Up @@ -148,7 +159,12 @@ jobs:
run: MYPYPATH=py uv run mypy --package cogant --strict --no-warn-unused-configs

test:
name: Test (py${{ matrix.python-version }})
# No explicit ``name:``: matrix context in ``jobs.<job_id>.name`` only
# expands for jobs that actually RUN — while the job is skipped (e.g.
# ``needs: lint`` failing) GitHub renders the raw ``${{ matrix.* }}``
# expression literally in the UI. Dropping the name lets GitHub apply
# its default matrix naming (``test (3.11)`` …), which renders the
# expanded python version in both skipped and executed states.
runs-on: ubuntu-latest
needs: lint
strategy:
Expand Down Expand Up @@ -232,6 +248,15 @@ jobs:
- name: Checkout
uses: actions/checkout@v5

# audit_release_integrity --check-wheel-reproducibility rebuilds the
# wheel via ``uv build``; without this step the job dies with
# FileNotFoundError: 'uv' (latent defect: the job is ``needs: lint``
# and lint never reached green until now).
- name: Set up uv
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true

- name: Set up Python
uses: actions/setup-python@v6
with:
Expand Down Expand Up @@ -270,8 +295,12 @@ jobs:
PY

- name: Release integrity and wheel reproducibility
# PYTHONPATH points at the clean target install so the OpenAPI
# contract check imports cogant from the wheel under test; without
# it the audit failed with "No module named 'cogant'" (latent
# defect: this job is needs: lint and lint never reached green).
run: |
python ../tools/audit_release_integrity.py \
PYTHONPATH=/tmp/cogant-wheel-install python ../tools/audit_release_integrity.py \
--wheel /tmp/cogant-wheelhouse/cogant-*.whl \
--require-wheel \
--check-wheel-reproducibility
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
| [`scripts/`](scripts/) | Thin orchestrators (`z_generate_manuscript_variables.py`, which also refreshes `output/figures/`). |
| [`src/`](src/), [`tests/`](tests/), [`pyproject.toml`](pyproject.toml) | Tiny parent-template compatibility shell so `docxology/template` project discovery sees top-level source/tests when linked under `projects/working/cogant/`. The real package remains nested under `cogant/`. |
| [`run_all.py`](run_all.py), [`run_all.sh`](run_all.sh), [`run_all.example.json`](run_all.example.json) | Configurable batch run: `translate` + GNN exports + `render` + `viz` + `validate` per target. Targets are either `path` (under inner `cogant/`) or `git_url` (shallow clone to `<output_root>/<target_id>/_git_source/`). If `run_all.json` is absent, built-in defaults cover the three `examples/control_positive/*` fixtures plus two small Pallets repos; the shipped `run_all.json` is the larger corpus config. The shipped and built-in configs set `output_root: "cogant/output"`; `run_all.example.json` uses `output`. Each target writes under `<output_root>/<target_id>/` (with `data/`, `figures/`, `site/`, `reports/`, `gnn_package/`, `analysis/`, `exports/`, `roundtrip/`). Stderr + optional `--log`: per-target banner, per-step wall time / exit status, batch `summary` in `<output_root>/run_manifest.json`, cross-target `summary.md`/`summary.json`, and `<output_root>/dashboard/` when `steps.batch_dashboard` is enabled. |
| [`output/`](output/) | Generated manuscript outputs — `data/manuscript_variables.json`, `output/manuscript/` injected copy, and copied figures (all disposable and regeneratable). Batch runs write per-target directories under the configured `<output_root>/<target_id>/`; the shipped `run_all.json` uses `cogant/output`, while `run_all.example.json` uses project-root `output`. |
| `output/` | Generated manuscript outputs — `data/manuscript_variables.json`, `output/manuscript/` injected copy, and copied figures (all disposable and regeneratable). Batch runs write per-target directories under the configured `<output_root>/<target_id>/`; the shipped `run_all.json` uses `cogant/output`, while `run_all.example.json` uses project-root `output`. |
| [`PROMOTION.md`](PROMOTION.md) | Checklist for exposing this working sidecar tree to the parent template render location. |

## Location matrix
Expand Down
15 changes: 9 additions & 6 deletions cogant/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@ repos:
# CI ratchet (.github/workflows/ci.yml :: Lint (ruff)). Auxiliary
# scripts under tools/, scripts/, manuscript/, etc. are intentionally
# not policed by pre-commit yet — see CONTRIBUTING.md "Lint scope".
# NOTE: pre-commit is invoked from the repo root by both
# ``pre-commit run --config cogant/.pre-commit-config.yaml`` (CI) and
# ``pre-commit install`` from inside ``cogant/`` (local), so we
# accept either prefix.
# NOTE: pre-commit always matches ``files`` against paths relative to
# the git repo root (COGANT/), regardless of the cwd the command was
# invoked from, so the ``cogant/`` prefix is required. A bare
# ``tests/`` alternative would also sweep the repo-root ``tests/``
# tree (tools audit tests) which is NOT covered by the CI ruff
# ratchet and formats under a different ruff config — on CI that made
# this hook rewrite 24 files and fail every run.
- id: ruff
args: [--fix]
files: ^(cogant/)?(py/cogant/|tests/)
files: ^cogant/(py/cogant|tests)/
- id: ruff-format
files: ^(cogant/)?(py/cogant/|tests/)
files: ^cogant/(py/cogant|tests)/

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
Expand Down
1 change: 0 additions & 1 deletion cogant/benchmarks/results/suite_20260818.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,3 @@
- `OBSERVATION`: 2

**GNN shapes:** A=[2 x 3], B=[3 x 3 x 11], C=[2], D=[3]

6 changes: 3 additions & 3 deletions cogant/evaluation/METRICS.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# DO NOT EDIT BY HAND. Run: cd cogant && uv run python ../tools/regenerate_metrics.py

schema_version: '1.0'
generated_at: '2026-09-08T22:48:12.814800Z'
generator_git_sha: c14e1d9887cff323702329b5b9d2995d015346e5
generated_at: '2026-09-10T17:46:31.510967Z'
generator_git_sha: f78e364d753b3899ef7975955c9e384b724ea4bc
cogant_version: 0.6.0
package:
name: cogant
Expand Down Expand Up @@ -517,7 +517,7 @@ literature:
source: cogant/docs/evaluation/LITERATURE.md
bibliography_entries: 104
benchmark:
suite_runtime_s: 608.32
suite_runtime_s: 871.82
shipped_fixture_count: 12
benchmark_suite_file: suite_20260818.md
benchmark_python_version: 3.12.13
Expand Down
5 changes: 1 addition & 4 deletions cogant/tests/property/test_correctness_laws.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,7 @@ def test_law6_transition_normalization(
A=[[1.0]],
D=[1.0],
B=[
[
[1.0 if row == col else 0.0 for _ in range(n_actions)]
for col in range(n_states)
]
[[1.0 if row == col else 0.0 for _ in range(n_actions)] for col in range(n_states)]
for row in range(n_states)
],
)
Expand Down
1 change: 1 addition & 0 deletions scripts/code_quality/batch_cogsec_improve.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import re
from pathlib import Path


def improve_file(path: Path) -> dict:
source = path.read_text()
lines = source.splitlines(keepends=True)
Expand Down
1 change: 0 additions & 1 deletion scripts/z_generate_manuscript_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ def get_logger(name: str) -> logging.Logger:
substitute_text,
)


logger = get_logger(__name__)

MANUSCRIPT_DIR = COGANT_STAGING_ROOT / "manuscript"
Expand Down
1 change: 1 addition & 0 deletions tests/test_manuscript_figures.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def test_copy_manuscript_figures_writes_template_figure_registry(tmp_path: Path)
"role": "test",
"sha256": registry["figures"][0]["sha256"],
"source_artifact": "",
"alt_text": "",
}
]

Expand Down
2 changes: 1 addition & 1 deletion tools/audit_synthetic_surfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def format(self) -> str:
justification="maximum-entropy priors and structural defaults are documented degraded-output values",
),
AllowRule(
path=r"(^\.github/workflows/.*\.ya?ml$|^README\.md$|^TODO\.md$|^cogant/(\.gitignore|AGENTS\.md|CHANGELOG\.md|CONTRIBUTING\.md|Makefile|README\.md|pyproject\.toml)$|^cogant/docs/|^cogant/evaluation/|^cogant/examples/|^cogant/parsers/|^cogant/specs/|^cogant/rust/|^manuscript/|^scripts/|^tools/)",
path=r"(^\.github/workflows/.*\.ya?ml$|^README\.md$|^TODO\.md$|^ISA\.md$|^REVIEW_LOG_[0-9-]+\.md$|^cogant/(\.gitignore|AGENTS\.md|CHANGELOG\.md|CONTRIBUTING\.md|Makefile|README\.md|pyproject\.toml)$|^cogant/docs/|^cogant/evaluation/|^cogant/examples/|^cogant/parsers/|^cogant/specs/|^cogant/rust/|^manuscript/|^scripts/|^tools/)",
terms=("fallback", "mock", "stub"),
category="degraded_output",
justification="project documentation, examples, and release notes describe audited degradation or compatibility behavior",
Expand Down
4 changes: 4 additions & 0 deletions tools/figures/copier.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,10 @@ def _write_template_figure_registry(
"generated_by": record.get("renderer", ""),
"source_artifact": record.get("source_artifact", ""),
"sha256": record.get("sha256", ""),
# The template HTML renderer refuses figures without
# accessibility alt text (``require_record_alt``), so
# every registry record carries the registered alt text.
"alt_text": record.get("alt_text", ""),
}
)
registry = {
Expand Down