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
10 changes: 10 additions & 0 deletions .github/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# AGENTS.md — `.github/`

- Keep action references pinned to full commit SHAs with the release in a
trailing comment. `dependabot.yml` owns upgrades.
- Keep the offline/live split. Do not add a job that pretends to run the Docker
or browser proofs; those stay local and explicit.
- The `gnn-conformance` job reads its tag and commit from
[`../gnn/upstream.json`](../gnn/upstream.json); do not duplicate the pin here.
- Keep `permissions` least-privilege and `timeout-minutes` bounded.
- Parent rules: [../AGENTS.md](../AGENTS.md).
13 changes: 13 additions & 0 deletions .github/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# `.github/` — repository automation

`dependabot.yml` declares the dependency-update policy. `workflows/gates.yml`
is the only workflow: it runs the offline gate set and the pinned-GNN
conformance job on pushes to `main`, pull requests and manual dispatch.

The live Docker + SkillTree + browser proofs are deliberately not simulated
here; see [`workflows/README.md`](workflows/README.md) and the project
[`../AGENTS.md`](../AGENTS.md) gate list.

Local check before editing a workflow: `uvx ruff check src scripts tests` and
`uv run pytest --cov=src --cov-fail-under=90` cover the same code paths the
offline job runs.
11 changes: 11 additions & 0 deletions .github/workflows/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# AGENTS.md — `.github/workflows/`

- `gates.yml` is the only workflow. Add a job only when it can run on a hosted
runner; live Docker and browser proofs stay local.
- Keep the `gnn conformance (pinned v5.0.3)` job name. It is the required-check
identity, and the pin must come from `gnn/upstream.json`.
- The conformance lane must fail, never skip, when the pinned fetch or parser
provisioning fails.
- Mirror local commands; the offline job should not invent a stricter command
that `AGENTS.md` does not document.
- Parent rules: [../AGENTS.md](../AGENTS.md).
14 changes: 14 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# `.github/workflows/` — CI jobs

`gates.yml` defines two jobs:

- `gates` — locked sync, Ruff check/format, mypy, curriculum and artifact
builds, the provenance/scholarship/manuscript validators, and the test suite
with the 90% coverage floor.
- `gnn conformance (pinned v5.0.3)` — fetches the commit in
[`../../gnn/upstream.json`](../../gnn/upstream.json), provisions its own
Python 3.12 environment, validates the specification, and runs
`tests/test_gnn_conformance.py`.

Live Docker, SkillTree and browser proofs are not run here. The job names are
the required checks; keep them stable when editing.
13 changes: 13 additions & 0 deletions gnn/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# AGENTS.md — `gnn/`

- `discrete_active_inference_agent.gnn.md` and
[`../src/kernels/active_inference.py`](../src/kernels/active_inference.py) are
one contract. Change them together, with
[`../src/gnn_conformance.py`](../src/gnn_conformance.py) and
[`../tests/test_gnn_conformance.py`](../tests/test_gnn_conformance.py).
- Read the pin from `upstream.json`; never read a GNN checkout's working tree.
The validator extracts the recorded commit with `git archive`.
- A pin change needs a fresh conformance run:
`uv run python scripts/validate_gnn_spec.py` and
`uv run pytest tests/test_gnn_conformance.py -q`.
- Parent rules: [../AGENTS.md](../AGENTS.md).
12 changes: 12 additions & 0 deletions gnn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# `gnn/` — pinned GNN specification

`discrete_active_inference_agent.gnn.md` is the Generalized Notation Notation
specification of the discrete-agent kernel's generative model.
`upstream.json` records the parser pin: repository
`ActiveInferenceInstitute/Generalized_Notation_Notation`, tag `v5.0.3`, commit
`8f293d9ba810e6eda5c09842d9c7ed9ffa5f92c1`.

`scripts/validate_gnn_spec.py` extracts that pinned commit with `git archive`
and validates the specification. `tests/test_gnn_conformance.py` checks the
specification against [`../src/kernels/active_inference.py`](../src/kernels/active_inference.py).
CI runs both in `gnn conformance (pinned v5.0.3)`.
10 changes: 10 additions & 0 deletions src/artifacts/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# AGENTS.md — `src/artifacts/`

- Write atomically, through `json_io.write_json_artifact`; do not scatter
`json.dump` calls through producers.
- Keep output deterministic: sorted keys, stable separators, no wall-clock
timestamps or machine paths unless the payload schema explicitly owns them.
- Add or change a stable payload in `contracts.py` first, then update every
reader. Consumers type their inputs with these `TypedDict` shapes.
- A malformed payload fails at the write boundary, not when a figure renders.
- Parent rules: [../AGENTS.md](../AGENTS.md).
11 changes: 11 additions & 0 deletions src/artifacts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# `src/artifacts/` — deterministic JSON artifacts

`json_io.py` provides read/write helpers for JSON objects and arrays, including
`write_json_artifact`. `contracts.py` declares the `TypedDict` payload shapes
shared by figure and dashboard consumers.

Artifacts are the boundary between producers (validators, figure renderers) and
readers (figures, dashboard, manuscript variables). Writers sort keys and omit
timestamps by default so rebuilds are byte-identical.

Parent guide: [`../AGENTS.md`](../AGENTS.md).
13 changes: 13 additions & 0 deletions src/curriculum/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# AGENTS.md — `src/curriculum/`

- Keep the graph acyclic and fully connected foundations→applications. Roots
stay in `MATH_FOUNDATIONS` and `PROBABILITY`; ids stay unique and
prerequisites must resolve.
- Add skills as data in `catalog_data/` or an `_ext_*.py` module, not in
`graph.py`. Use the `_s`/`_q` shorthands from `authoring.py`.
- Any learner-facing number is a `{{claim:NAME}}` token. Author input values
inside `$...$` math; the bare-number linter must stay green.
- Imports are `src.*` only. A bare `curriculum.` import creates a second module
identity and breaks the DAG types.
- Run `uv run python scripts/build_curriculum.py` after edits, plus the
curriculum tests. Parent rules: [../AGENTS.md](../AGENTS.md).
18 changes: 18 additions & 0 deletions src/curriculum/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# `src/curriculum/` — the validated prerequisite DAG

`model.py` defines the frozen `Stratum`, `Subject`, `Skill` and
`AssessmentQuestion` types. `graph.py` owns `CurriculumGraph` validation,
topological order, levels and the foundations→applications connectivity check.
`catalog.py` is the entry point: `build_curriculum()` assembles the subjects and
runs `quality.py`.

Subject content lives in [`catalog_data/`](catalog_data/); the many `_ext_*.py`
modules are curriculum extensions aggregated by
`catalog_data/subjects_extensions_*.py`. `normalize.py` and
`assessment_normalize.py` harden authored data; `diagnostics.py`,
`recommendations.py`, `alignment.py` and `vfe_efe_bridge.py` derive read-only
views.

Build: `uv run python scripts/build_curriculum.py`.
Parent guide: [`../AGENTS.md`](../AGENTS.md). Architecture:
[`../../docs/architecture.md`](../../docs/architecture.md).
13 changes: 13 additions & 0 deletions src/curriculum/catalog_data/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# AGENTS.md — `src/curriculum/catalog_data/`

- Append skills with `_s(...)`/`_q(...)`. Give each a unique `skill_id`, a
stratum, an objective, and prerequisites that already exist.
- Every description number is a claim token. No literal result values.
- Keep `assembly.py` thin; subject construction belongs in the `subjects_*`
modules and their aggregated `_ext_*` sources.
- Do not add graph rules here. Validation belongs in `../graph.py` and
`../quality.py`.
- Rebuild and test after edits:
`uv run python scripts/build_curriculum.py` then
`uv run pytest tests/test_curriculum_catalog.py -q`.
- Parent rules: [../AGENTS.md](../AGENTS.md).
13 changes: 13 additions & 0 deletions src/curriculum/catalog_data/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# `src/curriculum/catalog_data/` — authored curriculum data

`assembly.py` exposes the thin `build_subject_list()`. `core_strata.py` holds
the inline stratum tuples; `subjects_canopy.py` shapes the subject tree. The
`subjects_extensions_*.py` modules aggregate the `_ext_*.py` extension modules
that sit one level up in [`..`](..).

This is the directory to edit when adding or changing a skill. `_s` and `_q`
come from [`../authoring.py`](../authoring.py); graph validation stays in
[`../graph.py`](../graph.py).

Build: `uv run python scripts/build_curriculum.py`.
Parent guide: [`../AGENTS.md`](../AGENTS.md).
10 changes: 10 additions & 0 deletions src/curriculum/materials/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# AGENTS.md — `src/curriculum/materials/`

- Every material row needs a resolvable source in
`data/course_material_sources.yaml`; do not invent a URL or a commit.
- Keep records read-only projections of the graph and source catalog. No learner
progress, ranking or completion state belongs here.
- Validation is fail-closed: an unaligned skill, quiz or material must fail
`scripts/validate_course_material_alignment.py`.
- Keep the JSON shape stable; the dashboard and manuscript variables read it.
- Parent rules: [../AGENTS.md](../AGENTS.md).
13 changes: 13 additions & 0 deletions src/curriculum/materials/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# `src/curriculum/materials/` — local Learn records

Builds the modular dashboard "Learn" records from the curriculum graph and
`data/course_material_sources.yaml`. `builders.py` assembles records,
`validation.py` checks them, `github_sources.py` resolves pinned GitHub
citations, and `models.py`/`helpers.py` hold the shared types.

The contract keeps material sources traceable to a real URL or commit while
leaving learner state to SkillTree. The validation entry point is
`write_course_material_artifacts`.

Check: `uv run python scripts/validate_course_material_alignment.py`.
Parent guide: [`../AGENTS.md`](../AGENTS.md).
12 changes: 12 additions & 0 deletions src/dashboard/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# AGENTS.md — `src/dashboard/`

- Keep payload shapes stable. `/api/status`, `/api/course-materials`, graph,
artifact and SkillTree-link responses have contract tests; change both sides
together.
- The CSP starts at `default-src 'none'` and must keep the SkillTree origin in
`frame-src` and its `ws://`/`wss://` origin in `connect-src`.
- `?defer_live=1` skips only the live parity round trip. Never let a deferred
block read as a passed check; validators use the default path.
- Bind loopback only. Do not add a remote host default or an app-owned login.
- Parent rules: [../AGENTS.md](../AGENTS.md). Design tokens:
[`../../DESIGN.md`](../../DESIGN.md).
14 changes: 14 additions & 0 deletions src/dashboard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# `src/dashboard/` — local learner dashboard

A read-only shell over generated artifacts and official SkillTree views.
`server.py` is the small HTTP server; `payload.py`, `status.py` and
`artifacts.py` build its JSON; `artifact_catalog.py` and `figure_metadata.py`
register the evidence surfaces; `graph_analysis.py` serves the additive graph
recommendation; `live_validation.py` runs the live parity check.

SkillTree owns progress, ranking, quizzes and learner records. The dashboard
must not become a second implementation or an app-owned authentication layer.
The static frontend lives in [`assets/`](assets/).

Run: `uv run python scripts/serve_learner_dashboard.py`.
Parent guide: [`../AGENTS.md`](../AGENTS.md).
11 changes: 11 additions & 0 deletions src/dashboard/assets/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# AGENTS.md — `src/dashboard/assets/`

- No frontend framework, bundler or npm dependency. Keep this surface vanilla and
directly servable.
- Read [`../../../DESIGN.md`](../../../DESIGN.md) before styling; use declared CSS
tokens, not raw colors.
- Do not rename payload keys or reshape a response from the browser side alone.
Update `src/dashboard/` and its tests in the same change.
- Treat `vendor/skills-client-js.esm.min.js` as third-party. Do not edit it by
hand; replace it only with a reviewed upstream build.
- Parent rules: [../AGENTS.md](../AGENTS.md).
11 changes: 11 additions & 0 deletions src/dashboard/assets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# `src/dashboard/assets/` — dashboard frontend

`index.html`, `app.js` and `styles.css` are the vanilla HTML/CSS/JS learner
dashboard. `vendor/skills-client-js.esm.min.js` is the pinned official
SkillTree client; it is vendored, not built.

The frontend renders the payloads from [`..`](..) and embeds the official
SkillTree display. It follows the root [`../../../DESIGN.md`](../../../DESIGN.md)
token contract and has no npm build step.

Parent guide: [`../AGENTS.md`](../AGENTS.md).
11 changes: 11 additions & 0 deletions src/figures/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# AGENTS.md — `src/figures/`

- Keep rendering deterministic and headless. Set `MPLBACKEND=Agg`; do not open a
window or read the clock for a label.
- Numeric inputs come from the graph or a validated audit payload. No hardcoded
results in a renderer.
- A new figure needs a registry row, filename, caption, alt text and semantic
metadata; the manuscript audit cross-checks them.
- Keep `figure_registry.json` and the dashboard artifact catalog in step; both
name the same files.
- Parent rules: [../AGENTS.md](../AGENTS.md).
13 changes: 13 additions & 0 deletions src/figures/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# `src/figures/` — figure registry and renderers

`registry.py` loads the typed figure registry and its chart contract;
`registry_manifest.py` holds the canonical rows and semantic overrides;
`table_companions.py` emits the table companions. The renderers live in
[`plots/`](plots/).

`plots.render_all()` writes the PNGs and `figure_registry.json`. Numeric inputs
come from the curriculum graph and the validated audit payloads, never from
literals in a renderer. Rendering is headless (`Agg`).

Check: `uv run pytest tests/test_figures.py -q`.
Parent guide: [`../AGENTS.md`](../AGENTS.md).
11 changes: 11 additions & 0 deletions src/figures/plots/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# AGENTS.md — `src/figures/plots/`

- One renderer per registered figure. Register it in `registry.py`; do not add a
second filename or caption rule here.
- Use `style.py` tokens and the headless backend. No random, date or
environment-dependent labels.
- Read inputs through `FigureRenderContext`; do not reach into another package's
private state.
- A renderer change that moves a label, filename or caption must update the
manuscript declaration and dashboard artifact in the same change.
- Parent rules: [../AGENTS.md](../AGENTS.md).
11 changes: 11 additions & 0 deletions src/figures/plots/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# `src/figures/plots/` — figure renderers

One module per figure family: `curriculum.py`, `kernels.py`,
`scholarship_coverage.py`, `scholarship_source_map.py`,
`scholarship_source_health.py`, `front_matter_cover.py`,
`front_matter_atlas.py`, `graph_diagnostics.py`, `roadmap.py` and
`validation.py`. `registry_io.py` owns `FigureRenderContext` and `render_all()`;
`style.py` holds the shared palette; `registry_helpers.py` and
`validation_data.py`/`validation_intent.py` support the registry and its checks.

Parent guide: [`../AGENTS.md`](../AGENTS.md).
12 changes: 12 additions & 0 deletions src/integration/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# AGENTS.md — `src/integration/`

- This is a live proof, not a unit test. Do not make a green offline run imply
that Docker or the browser proof ran.
- Bind local services to loopback. Never add a public host default, a remote
URL or a deployment helper here.
- Restart a stale browser session at most once, as
`ensure_browser_session_responsive` does; then fail with the named harness
cause.
- Do not duplicate dashboard, SkillTree or curriculum logic. Call the owning
package and assert on its real output.
- Parent rules: [../AGENTS.md](../AGENTS.md).
13 changes: 13 additions & 0 deletions src/integration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# `src/integration/` — live-stack orchestration

`full_app_stack.py` brings up and checks the live proof: Docker services,
SkillTree and the local learner dashboard. It owns orchestration only; the
dashboard payload, SkillTree client and curriculum logic stay in their packages.

`ensure_browser_session_responsive` probes the browser automation daemon and
restarts it once before a browser proof, so a stale session is reported as a
harness problem rather than an application failure.

Driver: `scripts/validate_full_app_stack.py`. Parent guide:
[`../AGENTS.md`](../AGENTS.md). This proof needs a Docker daemon and a browser;
CI does not run it.
12 changes: 12 additions & 0 deletions src/kernels/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# AGENTS.md — `src/kernels/`

- Keep every function pure: inputs in, values out, no file, network or global
state. Rendering and writes belong in `figures/` and `scripts/`.
- Units are nats. Keep the existing guards against negative, unnormalized and
non-finite inputs; a new guard needs a test that rejects the bad input.
- No bare `kernels.` imports. Use `from src.kernels.<module> import ...`.
- Every learner-facing number comes from `examples.build_claim_registry()`,
referenced as `{{claim:NAME}}`; never hardcode a result in a skill.
- Kernel changes land with a real-value test asserting an analytic identity,
not a smoke call. Seed any RNG with `numpy.random.default_rng`.
- Parent rules: [../AGENTS.md](../AGENTS.md).
14 changes: 14 additions & 0 deletions src/kernels/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# `src/kernels/` — pure Active Inference math

Deterministic NumPy/SciPy functions in nats. This package is the only source of
quantitative values used in learner-facing content.

- `information.py` — entropy, KL divergence, cross-entropy, mutual information, surprise.
- `distributions.py` — softmax, normalize, stable logs, Dirichlet expectations.
- `inference.py` — Bayes posterior, variational free energy, log evidence, ELBO.
- `active_inference.py` — expected free energy, policy posterior, `DiscreteActiveInferenceAgent`.
- `predictive_coding.py` — precision-weighted descent to the analytic minimum.
- `examples.py` — fixed-input worked examples and `build_claim_registry()`.

Check: `uv run pytest tests/test_kernels_*.py -q`.
Parent guide: [`../AGENTS.md`](../AGENTS.md). GNN specification: [`../../gnn/README.md`](../../gnn/README.md).
10 changes: 10 additions & 0 deletions src/manuscript/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# AGENTS.md — `src/manuscript/`

- Keep every audit fail-closed. Do not add an allowlist or a warning-only path to
turn a real manuscript defect green.
- Numbers in prose are tokens, never literals. A changed count is regenerated,
not hand-edited.
- A new figure needs its registry row, caption, alt text, semantic metadata and
manuscript declaration; the audit checks all of them.
- Keep the prose American English; the validator is intentional.
- Parent rules: [../AGENTS.md](../AGENTS.md).
17 changes: 17 additions & 0 deletions src/manuscript/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# `src/manuscript/` — manuscript surface validation

- `audit.py` — validates `figure_registry.json` against manuscript figure
declarations, `[@fig:...]` references, readable PNGs, caption/alt text,
semantic metadata and dashboard artifacts; writes `manuscript_artifacts.json`.
- `claim_support.py` — validates `claim-support` anchors against evidence
classes, citations, variables, claim tokens, figures and limitations.
- `variables.py` — keeps generated counts bound to tokens, not prose literals.
- `american_english.py` — rejects British spelling variants in authored prose.
- `web_math.py` — checks rendered HTML that carries math loads MathJax.

Drivers: `scripts/validate_manuscript_artifacts.py`,
`scripts/validate_claim_support.py`, `scripts/validate_manuscript_variables.py`,
`scripts/validate_american_english.py`.

Parent guide: [`../AGENTS.md`](../AGENTS.md). Writing rules:
[`../../docs/agent_instructions.md`](../../docs/agent_instructions.md).
10 changes: 10 additions & 0 deletions src/pilot/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# AGENTS.md — `src/pilot/`

- Keep the contract protocol-only. Do not add learner records, identifiers,
storage or an outcome claim.
- Validation stays fail-closed: missing privacy, feasibility or missing-data
fields raise `PilotContractError`.
- Read-only SkillTree exports only. No writes, no live calls from validation.
- Change the schema and [`../../docs/pilot/`](../../docs/pilot/) together, with
a test for both the accepted and rejected shape.
- Parent rules: [../AGENTS.md](../AGENTS.md).
12 changes: 12 additions & 0 deletions src/pilot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# `src/pilot/` — learner-pilot protocol contract

`contract.py` validates the protocol-only learner-pilot contract:
`load_pilot_contract()` reads a JSON object and `validate_pilot_contract()`
checks that the protocol is measurable, privacy-bounded and non-causal. Failures
raise `PilotContractError`.

The package stores no learner state and makes no efficacy claim. The schema and
privacy boundary are documented in [`../../docs/pilot/`](../../docs/pilot/).

Check: `uv run python scripts/validate_learner_pilot_contract.py`.
Parent guide: [`../AGENTS.md`](../AGENTS.md).
Loading
Loading