diff --git a/.github/workflows/cortex_check.yml b/.github/workflows/cortex_check.yml index 3d49597..27422f3 100644 --- a/.github/workflows/cortex_check.yml +++ b/.github/workflows/cortex_check.yml @@ -13,9 +13,8 @@ on: push: branches: [main] paths: - - "tasks/**" - - "rulings/**" - - "batches/**" + - "projects/**" + - "archive/**" - "projects.yaml" - "checkin.yaml" - "dashboard.md" @@ -25,9 +24,8 @@ on: - ".github/workflows/cortex_check.yml" pull_request: paths: - - "tasks/**" - - "rulings/**" - - "batches/**" + - "projects/**" + - "archive/**" - "projects.yaml" - "checkin.yaml" - "dashboard.md" diff --git a/.github/workflows/dashboard_refresh.yml b/.github/workflows/dashboard_refresh.yml index 340278a..004d06e 100644 --- a/.github/workflows/dashboard_refresh.yml +++ b/.github/workflows/dashboard_refresh.yml @@ -2,10 +2,9 @@ name: Dashboard Refresh # Keeps the generated Cortex pages (`dashboard.md`, linked from the README, and # `dashboard.html`, the Pages index) in step with the registry they describe. -# The pages are rendered by PyAutoBrain's cortex conductor from `tasks/`, -# `rulings/`, `batches/`, `projects.yaml` and `checkin.yaml`, so any push that -# files a task, moves it, records a run, lands a ruling or stamps a check-in -# makes them stale. +# The pages are rendered by PyAutoBrain's cortex conductor from `projects/`, +# `projects.yaml` and `checkin.yaml`, so any push that records a run, logs an +# entry, rewrites a `## Now` or stamps a check-in makes them stale. # # Same shape as the Mind's dashboard_refresh.yml, and for the same reason: on # pull requests a stale page is an error the author fixes on the branch; on @@ -30,18 +29,16 @@ on: push: branches: [main] paths: - - "tasks/**" - - "rulings/**" - - "batches/**" + - "projects/**" + - "archive/**" - "projects.yaml" - "checkin.yaml" - "dashboard.md" - "dashboard.html" pull_request: paths: - - "tasks/**" - - "rulings/**" - - "batches/**" + - "projects/**" + - "archive/**" - "projects.yaml" - "checkin.yaml" - "dashboard.md" @@ -80,6 +77,19 @@ jobs: with: repository: PyAutoLabs/PyAutoBrain path: PyAutoBrain + # A Cortex branch that changes the schema alongside its Brain conductor + # is rendered by the PyAutoBrain branch of the SAME NAME when one exists + # (the two land as a pair), and by Brain main otherwise. + - name: Prefer the same-named PyAutoBrain branch, if any + working-directory: PyAutoBrain + env: + BR: ${{ github.head_ref || github.ref_name }} + run: | + if [ "$BR" != "main" ] && git fetch --depth 1 origin "$BR" 2>/dev/null; then + git checkout -q FETCH_HEAD && echo "PyAutoBrain @ $BR" + else + echo "PyAutoBrain @ main" + fi # No setup-python: the runner's python3 is the interpreter the laptop # render is compared to. PyYAML is `cortex.py`'s one dependency (it reads # `projects.yaml`), and the conductor imports that script at runtime. diff --git a/.github/workflows/ledger_merge.yml b/.github/workflows/ledger_merge.yml index 0a50911..034bd6b 100644 --- a/.github/workflows/ledger_merge.yml +++ b/.github/workflows/ledger_merge.yml @@ -3,7 +3,7 @@ name: Cortex Ledger Merge # Lands PyAutoCortex's own ledger work without anyone having to ask for it. # # THE PROBLEM. A branch-scoped session — the phone, claude.ai/code, any -# `claude/**` flow — pushes a task move, a ruling, a batch record to a feature +# `claude/**` flow — pushes a run recorded, an entry logged, a check-in to a feature # branch and it stops there: nothing downstream looks at a `claude/**` push. # The Mind learned this first (mind_ledger_merge.yml); the Cortex is born with # the answer. @@ -15,21 +15,20 @@ name: Cortex Ledger Merge # pushed it ever comes back. # # WHAT IT WILL AND WILL NOT MERGE. Only a branch whose whole diff is *ledger*: -# `tasks/`, `rulings/`, `batches/`, `checkin.yaml`. The line is drawn by +# `projects/`, `checkin.yaml`, the two generated pages. The line is drawn by # scripts/ledger_merge.py — a script, so it is testable and a session can # predict the verdict — and it is DEFAULT DENY: anything under `scripts/`, # `tests/`, `.github/`, `policy/`, `docs/`, `projects.yaml`, the prose pages, # or any path nobody has classified, stops the merge and leaves the branch for -# a human. So does a MODIFIED or DELETED file under `rulings/` — the ledger of -# record is append-only, and the classifier reads `git diff --name-status` to -# hold that line. This workflow's own file is on the code side, which is the +# a human. So does ANY change under `archive/` — the frozen 2026-08/09 task, +# ruling and batch ledgers, which nothing writes any more. This workflow's own file is on the code side, which is the # intended self-consistency: it cannot merge a change to itself. # # THE TRIAL-MERGE CHECK. `cortex.py check` is run on the branch tip (so audit # mode reports something) and AGAIN on the merged tree, after `git merge # --no-ff` and before `git push`. That second run is what catches the -# ruling-id race: two branches that both assign `R--03` each pass alone -# and fail merged. A failing check resets the trial merge and leaves the +# same-ledger race: two branches that each edit one project's ledger pass +# alone and can fail merged. A failing check resets the trial merge and leaves the # branch for a human. on: @@ -148,14 +147,14 @@ jobs: if [ "$RC" -ne 0 ]; then echo "verdict=code" >> "$GITHUB_OUTPUT" echo "" >> "$GITHUB_STEP_SUMMARY" - echo "**Left for a human** — this branch changes code, or edits a ruling, not just the ledger." >> "$GITHUB_STEP_SUMMARY" + echo "**Left for a human** — this branch changes code, or touches the archive, not just the ledger." >> "$GITHUB_STEP_SUMMARY" else echo "verdict=ledger" >> "$GITHUB_OUTPUT" fi - # Structural drift on the branch tip BLOCKS. A task in a state its - # header contradicts, a dangling Supersedes:, a run line that does not - # parse — nothing heals that automatically, and merging it would put the + # Structural drift on the branch tip BLOCKS. A run line that does not + # parse, a log that is not newest-first, an active project with no + # ledger — nothing heals that automatically, and merging it would put the # contradiction on main. Also the only check audit mode gets to report. # `cortex.py` reads `projects.yaml` with PyYAML — its one dependency. - name: dependencies @@ -205,12 +204,12 @@ jobs: exit 1 fi # THE TRIAL-MERGE CHECK. The branch passed alone; does it pass - # merged? This is where two branches that both assigned the same - # ruling id, or both moved the same task, are caught. + # merged? This is where two branches that both wrote the same + # project's ledger are caught. if ! python3 scripts/cortex.py check; then git reset --hard origin/main echo "::error::'$BRANCH' merges cleanly but 'cortex.py check' fails on the merged tree — left for a human" - echo "**Blocked** — \`$BRANCH\` fails \`cortex.py check\` once merged with main (a ruling-id or task-state race?); left for a human." >> "$GITHUB_STEP_SUMMARY" + echo "**Blocked** — \`$BRANCH\` fails \`cortex.py check\` once merged with main (two branches wrote the same ledger?); left for a human." >> "$GITHUB_STEP_SUMMARY" exit 1 fi if [ -n "$PR" ]; then diff --git a/.github/workflows/pages_dashboard.yml b/.github/workflows/pages_dashboard.yml index 6a05ef4..a79fd77 100644 --- a/.github/workflows/pages_dashboard.yml +++ b/.github/workflows/pages_dashboard.yml @@ -15,7 +15,7 @@ name: Pages Dashboard # `dashboard.md` (one census, two pages) and kept fresh by the same self-heal in # `dashboard_refresh.yml`; this workflow only publishes it. # Only the uploaded files reach Pages — nothing else in the repo, and in -# particular not `tasks/`, `rulings/` or `projects.yaml`, whose absolute laptop +# particular not `projects/` or `projects.yaml`, whose absolute laptop # paths are not for a public site. on: diff --git a/AGENTS.md b/AGENTS.md index 3d14104..7f1f8fc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ This file is for AI coding agents (Claude Code, Codex, Cursor, etc.) and humans discovering this repository. PyAutoCortex is the **Cortex** organ of the PyAuto -organism — where the organism learns what is true. +organism — where the organism keeps track of what is true. **You are one organ of the PyAuto organism** — an agentic ecosystem for @@ -15,7 +15,7 @@ Canonical boundaries live in `PyAutoBrain/ORGANISM.md`; the full body map |-------|------|------| | **Brain** | PyAutoBrain | Reasoning/orchestration layer; how work is decomposed and routed; the specialist agents. | | **Mind** | PyAutoMind | Intent, goals, priorities, workflow state; every task starts as a markdown prompt here. | -| **Cortex** | PyAutoCortex | The Cortex — where the organism learns what is true: the science body map (`projects.yaml`) and the rulings of record for every science run; the science mirror of the Mind (runs and rulings, not prompts and PRs). | +| **Cortex** | PyAutoCortex | The Cortex — where the organism keeps track of what is true: the science body map (`projects.yaml`) and one ledger per science project (what was run, what came back, what was learned, where to pick up); the science mirror of the Mind (runs and a dated log, not prompts and PRs). | | **Memory** | PyAutoMemory | Long-term scientific/software/project knowledge (see science pointer below). | | **Heart** | PyAutoHeart | Health/readiness — the authoritative "is it safe to release?" verdict. | | **Hands** | PyAutoHands | Packaging, tagging, notebook generation, PyPI release execution. | @@ -26,48 +26,36 @@ Call chain (always this order): **Brain → Heart (gate) → Build (execute)**. Generated from `PyAutoMind/repos.yaml` + `PyAutoBrain/ORGANISM.md`; edit there, then run `python3 PyAutoMind/scripts/repos_sync.py --write`. - ## What this repo is **The Mind decides what to build, the Brain routes the work and executes -nothing, the Cortex learns what is true.** The Cortex is a **run-and-ruling -registry**: `project → task → runs → rulings`. It owns two pieces of state no +nothing, the Cortex keeps track of what is true.** The Cortex is a +**project ledger**: `project → runs → log`. It owns two pieces of state no other organ holds — the **science body map** (`projects.yaml`: every science project, where it lives on the laptop and on RAL, how it syncs, where its own -commentary ledger is) and the **rulings ledger of record** (`rulings/`: every -verdict a human has passed on a science run, append-only). - -It is **not a second PyAutoMind.** The Mind is PR-shaped all the way down — -prompts, issues, branches, completion records, "delivered = a PR with a diff -and checks". The Cortex's unit is a **task** of a **project**, which spawns -**runs** (SLURM job ids) and ends in a **ruling**. Development work a science -task waits on stays in the Mind and is named here only as **gates** — GitHub -issue/PR refs in a task's `Gates:` header, one grammar, one direction. The -Mind learns nothing about the Cortex beyond a render-time badge. - -**Tasks, not phases** (2026-09-07). A project holds *unordered* tasks — ideas -the human runs in whatever order the results and the priorities dictate — so -there is no number and no sequence. A task's identity is its **slug**, unique -per project by the path itself, and every task carries a required `Summary:` -of at most ten words: the *question* it answers, which is the one line the -board shows. Mind **epics** are still numbered phases; that is development -work, and it really is sequential. - -The schemas — task files, the run-line grammar, rulings, batches, the -restricted `projects.yaml` subset — and the `scripts/cortex.py` verbs are in -[REFERENCE.md](REFERENCE.md). Every choice the birth epic did not fix is dated -in [docs/schema_decisions.md](docs/schema_decisions.md); read decisions there, -do not re-derive them. - -## The ruling of record - -**A verdict recorded only outside the Cortex does not exist.** `rulings/` is -canonical. A project's own ledger (`DECISIONS.md`, `state.md`, `RESULTS.md`) -remains as scientific commentary — evidence, reasoning, consequences — and -cites the ruling id. Rulings are **append-only**: a wrong ruling is superseded -by a new one (`Supersedes: R-…`) and never edited; `scripts/ledger_merge.py` -treats any modification or deletion under `rulings/` as code, which is a -human's turn. Full rules in [rulings/AGENTS.md](rulings/AGENTS.md). +commentary ledger is) and **one ledger per project** (`projects/.md`: +where the human is with it, what is on the cluster, and a dated history of +what they set off, saw and learned). + +It is **not a second PyAutoMind**, and it is **not a task tracker** +(2026-09-12, schema decision 60). Science is not worked as a queue of +pre-registered questions that get done and retired: the human does runs, looks +at results, thinks, and organically decides where to go next. So a ledger +holds no state machine, no witness, no verdict — it holds a **Now**, the +**Runs** on the cluster, and a **Log** that only ever gets longer. The board is +a live view of what has been going through the human's head on each project, +and the thing that makes a project easy to pick up after time away. + +**Nothing in a ledger is inferred from results.** A run's submission, start +and end are cluster facts and the script records them. A `result` or a +`lesson` is the human's own words, written on their ask. An agent that reads a +results file tells the human what it sees; the human says what to log. + +The schema — the ledger file, the run and log line grammars, the +`projects.yaml` subset — and the `scripts/cortex.py` verbs are in +[REFERENCE.md](REFERENCE.md). Every choice is dated in +[docs/schema_decisions.md](docs/schema_decisions.md); read decisions there, do +not re-derive them. ## Layout (operational) @@ -75,50 +63,49 @@ human's turn. Full rules in [rulings/AGENTS.md](rulings/AGENTS.md). code, not ledger**: `sync_cli` and `local_path` are paths a conductor will execute under, so a change to it is always a human's turn. `cortex.py` reads it with PyYAML and validates the fields (REFERENCE.md "projects.yaml"). -- **`tasks//.md`** — one file per task, with the Mind's light - header (`Key: value` lines, no YAML frontmatter — `Project:`, `Summary:`, - `State:`, …) and a `## Runs` body in the SLURM run-line grammar. There is no - `Phase:` number: the slug is the identity, and `check` names `Phase:` as a - retired key. `State:` is one of `planned | gated | ready | - submitted | running | pulled | awaiting-ruling | accepted | rerun | dropped`. - `legacy` and `legacy_wrong` are states of a **run**, never of a task. -- **`rulings///R--.md`** — the ledger of record. -- **`batches/`** — closed history. Three 2026-08/09 batch records and the - human's verbatim reviews under `reviews/`, kept because 13 rulings cite them - and append-only for the merge gate: never modified, only added. Nothing - writes new ones (the review-slot apparatus was retired 2026-09-03). +- **`projects/.md`** — one ledger per project (REFERENCE.md "The + ledger file"). Title `# — `; header `Project:` and + `Issue:` (`Repo#N`, an issue URL, or `none`); then exactly three sections: + `## Now`, `## Runs` (`open | running`), `## Log` (newest first, kind + `run | result | lesson | note`). Every `status: active` row must have one. + `projects/AGENTS.md` is the doctrine for the folder. +- **`archive/`** — frozen: the 2026-08/09 task, ruling and batch ledgers, + kept because the science repos cite their ids. Nothing writes there; any + change under it is code for the merge gate. - **`checkin.yaml`** — one key, `refreshed: `: when the science state was last actually checked in, written by `pyauto-brain cortex checkin --apply` and read back by the board. It means *last check-in*, never last - render, so a doc-only push cannot fake freshness; the HTML board reddens it - on the reader's own clock once it is more than an hour old. -- **`scripts/cortex.py`** — the one lifecycle script (stdlib only): + render; the HTML board reddens it on the reader's own clock once it is more + than an hour old. +- **`scripts/cortex.py`** — the one lifecycle script (PyYAML + stdlib): - `check` — every structural rule, hermetic; `cortex check: OK` or `DRIFT` with one ` - …` line per finding, exit 1. - - `gates` — read-only and offline: every gated task, its refs and their - URLs. Nothing polls GitHub and nothing flips a state; a human reads the - listing, opens the refs and types `move ready`. - - `rule --body …` — assigns the next ruling id, writes - the ruling file(s), updates the task's `Ruling:` and `State:`. The only - door to `accepted`, `rerun`, `dropped` and `leave-to-finish`. - - `move …` — every other transition, per the table in - REFERENCE.md; refuses the ruling edges. - - `new --summary "<≤10 words>" …` — writes a task file - from the template; `--summary` is required and capped, as `check` is. + - `new --summary "" [--issue Repo#N]` — opens a ledger + for a row of `projects.yaml`. + - `run "" [--partition P]` — records a submission: + the run goes under `## Runs` as `open` and the log gets a `run` entry. + - `running ` / `done [--failed] [--wall + H:MM] [--note …]` — what the cluster said; `done` moves the run into the + log. + - `log "" [--kind note|result|lesson]` — the human's words, + dated today, at the head of the log. + - `now ""` — rewrites `## Now`. + - `issue ` — prints the concise block that sits at the top of the + project's GitHub issue (Now, Runs, the last five entries) between two + markers; the Brain's `cortex issue --apply` writes it there. + - `link ` — sets the ledger's `Issue:`. - `retire --why ""` — the only verb that writes - `projects.yaml`: the row's `status:` becomes `retired` and its - `note:` records `retired : `. The row, its tasks and its - rulings all stay; it refuses while any task of that project is - outside `accepted | rerun | dropped | planned`. + `projects.yaml`: the row's `status:` becomes `retired`, its `note:` + records why, and the ledger logs it. It refuses while the ledger still + lists a run. - **`dashboard.md` / `dashboard.html`** — GENERATED, never hand-edited: the - board, rendered by the Brain's cortex conductor and self-healed on `main` - (see "Driving the Cortex" below). They are ledger for the merge gate. + board, rendered by the Brain's cortex conductor and self-healed on `main`. + They are ledger for the merge gate. - **`scripts/ledger_merge.py`** — the default-deny classifier behind `.github/workflows/ledger_merge.yml`: a `claude/**` push whose whole diff is - ledger (`tasks/`, `rulings/`, `batches/`, `checkin.yaml`, the two generated - dashboards) lands on `main` by itself; anything else waits for a human — and - that "anything else" includes an `AGENTS.md` or `TEMPLATE.md` *inside* a - ledger dir, which is doctrine, not an entry. `python3 + ledger (`projects/`, `checkin.yaml`, the two generated dashboards) lands on + `main` by itself; anything else waits for a human — `projects/AGENTS.md` + included (doctrine, not an entry), and anything under `archive/`. `python3 scripts/ledger_merge.py classify --base origin/main` predicts the verdict. ## Driving the Cortex @@ -126,33 +113,29 @@ human's turn. Full rules in [rulings/AGENTS.md](rulings/AGENTS.md). The Cortex holds state and checks itself; it does not reason. The reasoning lives in the Brain's **cortex conductor** — `pyauto-brain cortex `, or `python3 PyAutoBrain/agents/conductors/cortex/_cortex.py --cortex -` with no Brain install. It is read-mostly: it renders, it plans and -it scores. The only bytes it writes of its own are the two generated pages; -every change to a *task* goes through `scripts/cortex.py`, which owns the -state table. +` with no Brain install. It is read-mostly: it pulls, it shows, it +renders. The only bytes it writes of its own are the two generated pages and +`checkin.yaml`; every change to a *ledger* goes through `scripts/cortex.py`. | Verb | What it does | |------|--------------| -| `checkin [--dry-run \| --apply] [--push \| --no-push] [--project KEY] [--skip-pull]` | **the check-in** — the one door: pull every active project through its own `sync_cli`, score every live task, move what came back, re-render the board, push the ledger where the rule allows, and summarise **by project**. `--dry-run` is the default and reaches nothing | -| `census [--json]` | what the Cortex is holding, by state — the one-screen answer | +| `checkin [--dry-run \| --apply] [--push \| --no-push] [--project KEY] [--skip-pull]` | **the check-in** — the one door: pull every active project through its own `sync_cli`, run its `jobs` verb where it has one and show the output verbatim, re-render the board, push the ledger where the rule allows, and summarise **by project** (Now, runs, the last five entries, the commands you are likely to type next). `--dry-run` is the default and reaches nothing | +| `census [--json]` | what the Cortex is holding, by project — the one-screen answer | | `dashboard --check` \| `--apply` | render `dashboard.md` + `dashboard.html`; `--check` exits **1 on drift**, **2 on bad args**, anything else = the renderer could not run | -| `gates` | every gated task, its refs and their URLs — read-only, offline | -| `collect [--task REL] [--pull] [--refreshed ISO] [--apply]` | score what came back; with no `--task` it scopes to **every** `submitted \| running` task, and `--pull` runs the *project's own* sync CLI | +| `issue [--project KEY] [--apply]` | the concise ledger block for each project's GitHub issue; `--apply` writes it into the issue body between the markers (needs `gh`) | **`--apply` here, `--write` there.** The conductor's verbs spell the writing -flag `--apply` (the Brain's house spelling, as intake does); `scripts/cortex.py` -spells it `--write`. +flag `--apply` (the Brain's house spelling); `scripts/cortex.py` verbs write +directly and take `--today` for tests. **Nothing here submits a job by itself.** A submission is made only on the -human's ask — by the human, or by the agent in the session — with the project's -own `sync_cli submit` line, followed at once by `cortex.py move -submitted --run ` (ruled 2026-09-05; before that the human typed the -submit). -`checkin` and `collect --pull` are the only legs that shell out, and only to -the project's own CLI — the conductor adds no SSH of its own. Each project -`checkin` pulls gets a `/.cortex/pull.json` manifest -(REFERENCE.md "Check-in"), merged into whatever that project's CLI already -wrote there. +human's ask — by the human, or by the agent in the session — with the +project's own `sync_cli submit` line, followed at once by `cortex.py run + ""`. `running` and `done` may be typed by the agent +from what `jobs` printed, because those are cluster facts; `log --kind result` +and `--kind lesson` are typed only for words the human said. `checkin` is the +only leg that shells out, and only to the project's own CLI — the conductor +adds no SSH of its own. ### What runs by itself @@ -160,20 +143,14 @@ Three workflows, and only these may write: | Workflow | Trigger | May write | |---|---|---| -| `cortex_check.yml` | push/PR on ledger, scripts, tests, the dashboards | **nothing** — `cortex.py check` + pytest | +| `cortex_check.yml` | push/PR on the ledger, scripts, tests, the dashboards | **nothing** — `cortex.py check` + pytest | | `dashboard_refresh.yml` | push to main, PR, nightly 03:35 UTC, dispatch | `dashboard.md`, `dashboard.html` (self-heal on main; a PR run errors instead of healing) | | `pages_dashboard.yml` | push to `dashboard.html`, dispatch | nothing in the repo — it publishes to Pages | | `ledger_merge.yml` | push to `claude/**`, dispatch | merges a ledger-only branch to main | -**No scheduled job mutates the ledger.** A daily gate-grading cron did, until -gate grading was retired on 2026-09-03 (2 gated refs, 0 flips in its -lifetime); the only self-healing writer left renders the two generated pages. - -The main-writers share `concurrency: group: cortex-main-writers`, so two -bots never race for the tip of main. And because a `GITHUB_TOKEN` push triggers -no workflow at all, each of them re-dispatches by name what its push should have -woken (`pages_dashboard.yml` after a heal; `cortex_check.yml` + -`dashboard_refresh.yml` after a grading commit). +**No scheduled job mutates the ledger.** The main-writers share `concurrency: +group: cortex-main-writers`, so two bots never race for the tip of main, and +each re-dispatches by name what its `GITHUB_TOKEN` push cannot wake. The board is published at **** — `dashboard.html` as the index. @@ -185,50 +162,43 @@ exception, and it is confined to `projects.yaml`: a project's `local_path` and `mirror` are absolute laptop paths **outside** the workspace (the Science folder under `/mnt/c/…`), because that is where the datasets, the `output/` trees and the pulled results live and the review happens at the laptop. The -exception is stated in the file's header and here, and nowhere else — a task -file or a ruling points into a project through its `projects.yaml` row, never -with a bare absolute path of its own. +exception is stated in the file's header and here, and nowhere else — a ledger +points into a project through its `projects.yaml` row, never with a bare +absolute path of its own. ## What is out of scope, and why Quoted verbatim from `PyAutoMind/complete/archive/shelved/batch_science_lane.md` so nobody re-derives these: -> ## What is now out of scope, and why -> > - **RAL as canonical home for the science project.** Refused above. The datasets > and `output/` stay under `/mnt/c/…/Science/`. > - **A git-courier cron on the RAL login node.** Its value collapses once the > laptop is canonical: the laptop has to be on to hold and push the data anyway, -> so a courier saves almost nothing. It was the right answer to a question no -> longer being asked. +> so a courier saves almost nothing. > - **Globus Compute endpoint / self-hosted GitHub runner on the login node.** > Same reasoning, plus both are persistent login-node processes needing an -> operator conversation. Not worth it for a lane the human is happy to drive. +> operator conversation. > - Recorded so nobody re-derives them: SSH from a Claude container is a > non-starter in every variant (HTTPS-only proxied egress, no keys); Open > OnDemand is an admin-installed inbound portal; Cirun cannot reach someone -> else's SLURM. And phases 4, 6a and 6b of `euclid-dr1-prep` say in their own -> prompts that they are human-driven and supervised with a judged verdict as the -> deliverable — **no transport was ever going to make those unattended.** +> else's SLURM. -Every Cortex task therefore runs on the laptop. That was once written into -each task file as `Lane: local-dev` — 32 of 32 said the same thing, so the -header was deleted on 2026-09-03 and the fact lives here instead. (The quote -above is the Mind's, verbatim: the "phases 4, 6a and 6b" it names are phases of -the `euclid-dr1-prep` **Mind epic**, which is development work and genuinely -sequential — not Cortex tasks.) +Every Cortex project therefore runs from the laptop. ## Hard rules 1. **Never rewrite history on any branch with a remote** (block below). 2. **Pull before edit.** `git fetch && git status` first, every time. -3. **Never edit a ruling.** Supersede it. `ledger_merge.py` refuses to - auto-merge a modified or deleted file under `rulings/`. -4. **Run `python3 scripts/cortex.py check` before you push** a task, ruling - or batch change (it is what refuses a missing or over-long `Summary:`); `ledger_merge.yml` runs it on the trial-merge tree and a +3. **Never write a result or a lesson the human did not say.** Cluster facts + (`run`, `running`, `done`) are the script's to record; meaning is the + human's. +4. **Never edit a ledger by hand in a session.** Every write is a + `scripts/cortex.py` verb, and `python3 scripts/cortex.py check` runs + before you push; `ledger_merge.yml` runs it on the trial-merge tree and a failing check leaves the branch for a human. -5. **No hand-written HTML.** `dashboard.html` is rendered by the cortex +5. **Never touch `archive/`.** It is frozen; the merge gate refuses it. +6. **No hand-written HTML.** `dashboard.html` is rendered by the cortex conductor; a hand edit is drift that `dashboard_refresh.yml` will overwrite on the next push to `main`. @@ -278,11 +248,11 @@ several, which is exactly the session no hook fires in. *parent*, so a bare `skills/…` reads as a missing file rather than a missing repo prefix. - ## When in doubt Read [README.md](README.md) and [REFERENCE.md](REFERENCE.md). The birth epic's -ledger is `PyAutoMind/complete/archive/epics/cortex_birth_epic.md`. +ledger is `PyAutoMind/complete/archive/epics/cortex_birth_epic.md`; the +2026-09-12 redesign is schema decision 60. ## Never rewrite history @@ -292,7 +262,6 @@ tracked repo, no force-push to `main`, no fresh-start "Initial commit", no `filter-repo` / `filter-branch` / `rebase -i` on pushed branches. To get a clean tree: `git fetch origin && git reset --hard origin/main && git clean -fd`. - ## Sessions end at their deliverable diff --git a/README.md b/README.md index bb35e4b..70acfbd 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,60 @@ # PyAutoCortex -**PyAutoCortex is the Cortex of the PyAutoScientist** — where the organism -learns what is true. The Mind decides what to build, the Brain routes the work -and executes nothing, the Cortex learns what is true: it holds the **science -body map** (every science project, where it lives, how it syncs) and the -**rulings of record** — every verdict a human has passed on a science run, -append-only, superseded but never edited. +[![PyAutoScientist GitHub](https://img.shields.io/badge/%F0%9F%94%AD%20PyAutoScientist-GitHub-181717?style=flat-square)](https://github.com/PyAutoLabs/PyAutoScientist) [![PyAutoScientist ReadTheDocs](https://img.shields.io/badge/%F0%9F%93%96%20PyAutoScientist-ReadTheDocs-8CA1AF?style=flat-square)](https://pyautoscientist.readthedocs.io) -**The board** — every task the Cortex is holding, on one page, with the next -command a tap away: (markdown twin: -[dashboard.md](dashboard.md)). Both pages are generated by the Brain's cortex -conductor and refreshed on every push; never hand-edit them. +**PyAutoCortex is the Cortex of the PyAutoScientist** — where the organism +keeps track of what is true. It holds the **science body map** (every science +project, where it lives, how it syncs) and one **ledger per project**: what was +set off and when, what came back, what you learned, and where you meant to go +next — a history of how each project unfolds, written in your own words, never +a queue of things to finish. + +See the **[PyAutoCortex Dashboard](https://pyautolabs.github.io/PyAutoCortex/)** +for how this is used in practice: every active project on one page — where you +are with it, what is on the cluster right now, and the last five things you did +or learned — so a project you have been away from for a while is picked up +where you left it. The markdown twin is [dashboard.md](dashboard.md); both are +generated and never hand-edited. ## How PyAutoCortex works -The unit is a **task** of a **project**, which spawns **runs** (SLURM job ids) -and ends in a **ruling**: - -1. **Declare the task.** A markdown file under `tasks//` states the - question, the pre-registered witness, the wall budget and the GitHub issues - it waits on (`Gates:`). It starts `planned` or `gated`. -2. **Run it.** When the gates clear the task is `ready`; a submission makes - it `submitted` and then `running`, with every job id recorded in the file's - `## Runs` block in SLURM notation. -3. **Pull and review.** When the results are pulled to the laptop the task - becomes `pulled` and then `awaiting-ruling` — it is waiting on the human's - eyes, and on nothing else. -4. **Rule.** The human's verdict — `accept`, `rerun`, `drop` or - `leave-to-finish` — is written into `rulings/` with a permanent id. *A - verdict recorded only outside the Cortex does not exist.* - -In full those four steps are ten states — `planned`, `gated`, `ready`, -`submitted`, `running`, `pulled`, `awaiting-ruling`, then `accepted`, `rerun` -or `dropped` — of which only the last three are reachable, and only through -`scripts/cortex.py rule` (`legacy` and `legacy_wrong` are states of a *run*, -never of a task). Checking in is one command from the Brain's cortex -conductor — **`pyauto-brain cortex checkin --apply`** (see `--dry-run` first) -pulls every active project through its own sync CLI, scores every submitted or -running task against its pre-registered witness, moves what came back to -`awaiting-ruling`, re-renders the board, pushes the ledger where it is allowed -to, and prints a summary **by project** with the next prompt for each task. `batches/` is closed history: the three 2026-08/09 batch -records and the human's verbatim reviews stay readable because 13 rulings cite -them, and nothing writes new ones. - -The Cortex is **not a second PyAutoMind**: development tasks stay in the Mind -and are named here only as gates. Its one script, `scripts/cortex.py`, checks -the tree and moves tasks between states; the ledger folders auto-merge from -any surface that can push. +A project's ledger is one markdown file, `projects/.md`, with three +sections and nothing else: + +1. **Now.** Two or three lines, rewritten whenever you touch the project: what + is running, and what you meant to do next. +2. **Runs.** The jobs on the cluster right now, each `open` (submitted) or + `running`, with its date and one line saying what it is. A finished run + leaves this list and becomes a log entry. +3. **Log.** Dated entries, newest first — a run set off or finished, a + `result` you read off, a `lesson` you want kept, a `note`. Nothing here is + ever done; it only gets older. The board shows the last five. + +Every write goes through `scripts/cortex.py`: `run` records a submission, +`running` and `done` record what the cluster says, `log` and `now` record what +*you* say. Nothing in a ledger is inferred from results — a result or a lesson +is written only when you state it. Checking in is one command from the Brain's +cortex conductor, **`pyauto-brain cortex checkin --apply`** (`/cortex` in +Claude Code): it pulls every active project through that project's own sync +CLI, shows where each run stands, re-renders the board, pushes the ledger where +it is allowed to, and reads the projects back to you one by one. + +Each project links to a GitHub issue (`Issue:` in its header) that carries the +detailed run-through; the top of that issue is the same concise ledger the +board shows, regenerated from the project file with `pyauto-brain cortex issue`. + +The Cortex is **not a second PyAutoMind**: development work stays in the Mind. +The retired task-and-ruling ledgers of 2026-08/09 are frozen under +[`archive/`](archive/) because the science repos cite their ids. `scripts/cortex.py` needs Python 3.10+ and **PyYAML** (`python3 -m pip install pyyaml`), which is how it reads `projects.yaml`; the tests additionally need `pytest`. Nothing else. -The schemas — task files, the run-line grammar, rulings, the `projects.yaml` -fields — are in [REFERENCE.md](REFERENCE.md); how agents should -operate this repo is in [AGENTS.md](AGENTS.md); every design choice the birth -epic did not fix is dated in [docs/schema_decisions.md](docs/schema_decisions.md). -The organism this repo is the Cortex of is described once in +The schema — the ledger file, the run and log line grammars, the `projects.yaml` +fields, how the ledger auto-merges — is in [REFERENCE.md](REFERENCE.md); how +agents should operate this repo is in [AGENTS.md](AGENTS.md); every design +choice is dated in [docs/schema_decisions.md](docs/schema_decisions.md). The +organism this repo is the Cortex of is described once in [PyAutoBrain/ORGANISM.md](https://github.com/PyAutoLabs/PyAutoBrain/blob/main/ORGANISM.md) and documented in full at . diff --git a/REFERENCE.md b/REFERENCE.md index 16daf7b..8e2911c 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -1,754 +1,206 @@ -# PyAutoCortex reference +# PyAutoCortex — Reference -The schemas, grammars and conventions for this repo — the file `scripts/cortex.py` -implements and `scripts/cortex.py check` enforces. Agent docs that point at a -schema ("the transition table", "the run-line grammar", "the ruling schema") -resolve here, one link from [AGENTS.md](AGENTS.md). +The schema of the Cortex, in full. Everything `scripts/cortex.py check` +enforces is written here; nothing it enforces is not. Design choices are dated +in [docs/schema_decisions.md](docs/schema_decisions.md). ---- +## The ledger file -## What a task looks like +One file per project, `projects/.md`, where `` is a row of +`projects.yaml` (`^[a-z][a-z0-9_]*$`). Every `status: active` row must have +one; a `dormant`, `planned` or `retired` row may. -Here is a task file — `tasks/example/05_running_array.md` from the test -fixture — of a project whose GPU array is most of the way through: +```markdown +# — -````markdown -# Example — the nine-lens array +Project: +Issue: //issues/N | none> -Project: example -Summary: Does Delaunay reach the same theta_E basin on ten lenses -State: running -Gates: PyAutoArray#431 -Witness: nine of ten array tasks write a sane checkpoint.hdf5 within 8:00 wall -Budget: 8:00 -Runs: 342091, 342102 -Ruling: R-20260901-03 -Review-minutes: 8 -Epic: example-programme -Filed: 2026-08-29 +## Now -## Question +Two or three lines, rewritten whenever the project is touched: what is on the +cluster and what the human meant to do next. May not be empty on an active +project. -Does the Delaunay pipeline reach the same theta_E basin on all ten lenses? +## Runs -## Witness +- — — — — + an optional continuation line, indented two spaces -`output/task_05/*/checkpoint.hdf5` present for nine lenses, `.err` clean. +## Log -## Where to look +- — — + an optional continuation line, indented two spaces +``` -- `/mnt/c/Users/Jammy/Science/example/output/task_05/` +The header holds exactly `Project:` and `Issue:`; `Project:` must equal the +key. The three sections appear in that order and no other section exists. +` -- ` is read as ` — ` everywhere (phone keyboards). -## Runs +### Run lines (`## Runs`) -- 342091_[0-8,10]: done — gpu — submitted 2026-08-30 — wall 6:12 - pulled_to: /mnt/c/Users/Jammy/Science/example/output/task_05 -- 342091_9: failed — gpu — submitted 2026-08-30 — wall 0:00 — OOM before the first step -- 342102: running — gpu — submitted 2026-09-01 — wall 0:00 — task 9 resubmitted alone - after: 342091_9 - -## Ruling - -R-20260901-03 — leave-to-finish -```` - -The header is the Mind's **light header**: line 1 is `# `; `Key: value` -lines within the first 30 lines — the block starts at the first `Key: value` -line after the title and ends at the next blank line; the first occurrence of a -key wins; a list-valued key is a bare `Key:` line followed by `- item` lines; a -key with no value (`Gates:`, `Runs:`, `Ruling:`) may be left empty or omitted. -No YAML frontmatter. The body -sections are fixed: `## Question`, `## Witness`, `## Where to look`, `## Runs`, -`## Ruling`. - -**`## Where to look` is rendered, not just parsed.** Its `- ` bullets are the -answer to *which folder do I open* — the dashboard's `## By project` view and -`pyauto-brain cortex checkin` print them verbatim under the task, and -`collect` resolves the ones that are absolute paths inside the project's roots -to the artefacts it scores. `new` seeds the section with the placeholder -`- (the output path, once there is one)`, which is honest on a `planned` task -and a hole on any other, so **`check` requires a task whose `State:` is past -`planned` to carry at least one bullet that is not that placeholder**. A -bullet is free text: a path, a project-row-relative location, a Mind prompt, a -GitHub ref — whatever a human would open. - -A task has **no number**. Its identity is its **slug** — the file name, unique -per project by the path itself — because a science project is a set of ideas -run in whatever order the results dictate, not a sequence (decision, 2026-09-07). - -### Task header keys - -| Key | Value | Notes | +| Field | Grammar | Meaning | |---|---|---| -| `Project:` | project key | must equal the directory name **and** a `projects.yaml` key | -| `Summary:` | at most ten words | **required** — the QUESTION the task answers, not its method or its run ids; the board's one line per task. No project name, no number | -| `State:` | `planned \| gated \| ready \| submitted \| running \| pulled \| awaiting-ruling \| accepted \| rerun \| dropped` | | -| `Gates:` | comma-separated GitHub refs | `Repo#N` (owner `PyAutoLabs`) or an issue/PR URL; **no `owner/Repo#N`** form | -| `Reset:` | reason | written by `move ready --reason "<reason>"` when a `submitted \| running` task goes back to `ready` | -| `Witness:` | free text | **mandatory before `submitted`** — the pre-registered checkable claim | -| `Budget:` | `H+:MM` | wall budget per run | -| `Runs:` | comma-separated job **stems** | the index of the `## Runs` body; equal to the set of body stems | -| `Ruling:` | ruling id | the chain head (see "Rulings") | -| `Review-minutes:` | integer | a seed, not a measurement | -| `Epic:` | slug | OPTIONAL join key to a **Mind** epic; the Cortex keeps no epics file of its own | -| `Filed:` | `YYYY-MM-DD` | | -| `Migrated-from:` | source path or ledger anchor | the Mind prompt, review file or project-ledger entry this task was transcribed from (phase 4 of the birth epic) | - -Gate refs are matched by `GATE_REF_RE`, copied verbatim from -`PyAutoMind/scripts/lifecycle.py`: - -```python -GATE_REF_RE = re.compile( - r"https://github\.com/([\w.-]+)/([\w.-]+)/(?:issues|pull)/(\d+)" - r"|(?<![\w/])([A-Za-z_][\w.]*)#(\d+)\b" -) -DEFAULT_GATE_OWNER = "PyAutoLabs" -``` +| jobid | `342301`, `342301_3`, `342301_[0-9]`, `342301_[0,2,4-9]` | the SLURM id, array task or task set | +| state | `open` \| `running` | `open` = submitted and not yet seen running. There is no third state: a run that has finished is removed by `done` and becomes a log entry | +| partition | a bare word (`ral`, `gpu`) | must agree with the row's `partition:` unless that is `both` | +| date | `YYYY-MM-DD` | the submission date | +| what | free text, one line | what the run is — the human's description at submission | -The lookbehind `(?<![\w/])` is what rejects `owner/Repo#N`: the shorthand is -`Repo#N` with the default owner, and any other owner is spelled as a URL. +A job id appears once per file. A retired project lists no runs. ---- - -## How a task flows - -``` - planned ──(Gates: non-empty)──► gated ──(move ready: the human judged the refs)──► ready - │ │ - └──────(Gates: empty)───────────────────────────────────────────────────────────────┤ - ▼ - ready ──(Witness: + --run)──► submitted ──► running ──(no live run)──► pulled ──► awaiting-ruling - ▲ │ │ │ - │ (no live run, ≥1 failed|timeout|void, --reason) │ rule - └──────────────────────────────┴──────────────┘ ▼ - accepted │ rerun ──► ready │ dropped - │ rule --supersedes - └──► rerun | dropped -``` +### Log lines (`## Log`) -`cortex.py move` owns every edge except the ruling edges, which `cortex.py rule` -owns. The full table: +Newest first — `check` refuses a date that is later than the entry above it. +Four kinds: -| from | to | condition | +| Kind | Written by | What it is | |---|---|---| -| planned | gated / ready | `Gates:` non-empty / empty | -| gated | ready | `move <task> ready` — a human read `gates`, opened the refs and judged them cleared. No flag, and nothing written but `State:` | -| ready | gated | not an edge: re-gating a `ready` task is a judgement, so it is a hand edit of the header | -| ready | submitted | `Witness:` non-empty AND `--run <id>` supplied | -| ready | pulled | legacy-born task: every run line is `legacy\|legacy_wrong` (`new --legacy-run` / `move pulled`); `Witness:` still mandatory; every `legacy` run gets a `pulled_to:` (`--pulled-to`, else its own `where:`); refused when no run is `legacy` (nothing to review — `rule drop`) | -| submitted / running | same | `--run <id>` appends a wave, a chained job or a checkpoint resubmit (`resumes:`); state unchanged | -| submitted | running | — | -| submitted / running | ready | no run line in `submitted\|running` AND ≥1 `failed\|timeout\|void`; `--reason` required (→ writes `Reset:`) | -| running | pulled | no run line live; or `--partial` (a partial array), which `check` expects closed by a `leave-to-finish` ruling; `--pulled-to <path>` writes `pulled_to:` on every `done` run lacking one, and the move is refused when no `done` run would carry one | -| pulled | awaiting-ruling | — (the task joins the rolling board) | -| awaiting-ruling | accepted / rerun / dropped | **`rule` only** | -| running / pulled / awaiting-ruling | same | `rule leave-to-finish` (state unchanged) | -| accepted | rerun / dropped | `rule --supersedes <current Ruling:>` only (the REWIND case) | -| rerun | ready | — (the witness may be re-registered; run history is kept) | -| any non-terminal | dropped | `rule drop` only | -| dropped | — | terminal (revival = a new slug) | - -`accepted` is **not** terminal: a later ruling may supersede the acceptance -(2026-08-31's REWIND superseded accepted gates). `dropped` is. - -Offline invariants `check` enforces on top of the table: - -- `State ∈ submitted..accepted` (and `rerun`) ⇒ `Witness:` non-empty. -- `State ∈ accepted | rerun | dropped` ⇒ `Ruling:` present (those states are - reachable only through `rule`). -- `State = pulled` AND any run line `submitted | running` ⇒ `Ruling:` present - and its head verb is `leave-to-finish` (the `--partial` case). -- `State = gated` ⇒ `Gates:` non-empty (a gate that does not exist cannot - clear). -- A header key outside the table is drift (`Gate:` must not pass as a silent - typo for `Gates:`); the five body sections are present; `Summary:` is - present, non-empty and at most ten words; `Review-minutes:` is an integer, - `Budget:` is `H+:MM` and `Filed:` is `YYYY-MM-DD`. A key with an empty value - is read as absent. `Phase:` is named as a **retired** key rather than passing - as a generic unknown one — the number went on 2026-09-07. - ---- +| `run` | `cortex.py run` / `done` | `<jobid> submitted: <what>` · `<jobid> finished — wall H:MM: <what>` · `<jobid> failed: <what>` | +| `result` | `cortex.py log --kind result` | what the human read off the results, in their words | +| `lesson` | `cortex.py log --kind lesson` | something the human wants kept — a trap, a rule, a fact about the setup | +| `note` | `cortex.py log` (default), `new`, `retire` | anything else: a thought, a plan, `ledger opened`, `retired: <why>` | -## Repository layout - -``` -PyAutoCortex/ -├── README.md ← short front page -├── AGENTS.md ← agent guidance (generated blocks: organism map, remote sessions, history) -├── CLAUDE.md ← GENERATED pointer (@AGENTS.md) — repos_sync --write -├── REFERENCE.md ← this file (schemas + grammars) -├── LICENSE .gitignore -│ -├── projects.yaml ← the science body map — CODE, not ledger (read with PyYAML) -├── checkin.yaml ← `refreshed: <UTC ISO>` — the last check-in stamp; LEDGER -├── dashboard.md ← GENERATED board — cortex conductor (`dashboard --apply`); LEDGER -├── dashboard.html ← GENERATED board, the Pages index; LEDGER -│ -├── tasks/<project>/<slug>.md ← one file per task (LEDGER) -├── rulings/AGENTS.md ← the append-only rule -├── rulings/<YYYY>/<MM>/R-<YYYYMMDD>-<nn>.md ← the ledger of record (LEDGER, append-only) -├── batches/AGENTS.md ← "closed history: never modified, only added" -├── batches/<YYYY-MM-DD>-<slot>.md ← the 2026-08/09 records (LEDGER, append-only) -├── batches/reviews/{AGENTS.md,<slot>.md} ← the human's verbatim reviews (LEDGER, append-only) -│ -├── docs/schema_decisions.md ← every dated choice the epic did not fix -├── policy/never_rewrite_history.md policy/remote_sessions.md ← copies of the Mind's; spliced into AGENTS.md -│ -├── scripts/cortex.py ← check · gates · rule · move · new · retire (stdlib + PyYAML) -├── scripts/ledger_merge.py ← the default-deny ledger classifier (+ append-only on rulings/, batches/) -├── tests/test_cortex.py tests/test_ledger_merge.py -├── tests/fixtures/skeleton/ ← one project, one task per state, five rulings — the witness -├── tests/fixtures/empty/ ← an empty map passes `check` -│ -├── .github/workflows/cortex_check.yml ← check + pytest on push/PR -├── .github/workflows/ledger_merge.yml ← lands ledger-only `claude/**` branches -├── .github/workflows/dashboard_refresh.yml ← renders the board; self-heals main -├── .github/workflows/pages_dashboard.yml ← publishes dashboard.html to Pages -└── .claude/hooks/session-start.sh .claude/settings.json ← GENERATED — repos_sync --write -``` +The board and the issue block show the newest `LOG_WINDOW = 5` entries; the +file keeps them all. An entry is never edited or removed: a wrong entry is +answered by a newer one. -No `skills/` — the Cortex exposes no commands of its own; the conductor that -drives it lives in the Brain (`pyauto-brain cortex …`, AGENTS.md "Driving the -Cortex"), and the workflows above are the only things that run it unattended. +### The issue block ---- - -## Run lines (`## Runs`) - -SLURM notation, strict grammar. One line per job or per task set of an array; -structured facts on **indented continuation lines**, never in the note. +`cortex.py issue <project> [-n 5]` prints the concise ledger that sits at the +top of the project's GitHub issue: the title line and status, `**Now**`, the +runs on the cluster, and the last `n` entries, fenced by ``` -- <stem>[_<task>|_[<a>-<b>,<c>]]: <run-state> — <partition> — submitted <YYYY-MM-DD> — wall <H+:MM>[ — <note>] - pulled_to: <path> | after: <run> | resumes: <run> | where: <path> | ruled: <id> -``` - -- `<stem>` — the SLURM job id, digits. `_<task>` — one array task. - `_[<set>]` — an array task set: comma-separated integers and `a-b` ranges, - ascending, no spaces (`342091_[0-8,10]`). -- `<run-state>` ∈ `submitted | running | done | failed | timeout | void | - legacy | legacy_wrong`. `void` = cancelled or never produced a step. - `legacy` / `legacy_wrong` = quarantine (reusable / not) — **a run state, - never a task state**. -- `<partition>` — the SLURM partition the job went to, a bare word - (`^[a-z][a-z0-9_-]*$`, e.g. `gpu`). The project's `partition:` row says - which it may use. -- `submitted <YYYY-MM-DD>` — the submission date. `wall <H+:MM>` — wall time - used so far (`0:00` for a job that never ran). -- `<note>` — free text after a fourth ` — `; never carries a structured fact. -- Continuation lines — exactly four spaces then `<key>: <value>`, keys: - `pulled_to:` (laptop path the results were pulled to), `after:` (SLURM - `afterok` dependency), `resumes:` (a checkpoint resubmit of that run), - `where:` (the quarantine path of a `legacy*` run), `ruled:` (a ruling id - naming this run). -- The em dash `—` is canonical; `--` is accepted for it (phone keyboards). - `check` reads both as the same separator; the writing verbs emit `—`. - -The regex, as `check` applies it (after `--` → `—` normalisation): - -```python -RUN_LINE_RE = re.compile( - r"^- (?P<stem>\d+)" - r"(?:_(?P<task>\d+)|_\[(?P<tasks>\d+(?:-\d+)?(?:,\d+(?:-\d+)?)*)\])?" - r": (?P<state>submitted|running|done|failed|timeout|void|legacy|legacy_wrong)" - r" — (?P<partition>[a-z][a-z0-9_-]*)" - r" — submitted (?P<date>\d{4}-\d{2}-\d{2})" - r" — wall (?P<wall>\d+:\d{2})" - r"(?: — (?P<note>.+))?$" -) -RUN_CONT_RE = re.compile( - r"^ (?P<key>pulled_to|after|resumes|where|ruled): (?P<value>\S.*)$" -) +<!-- cortex:ledger begin — regenerated from projects/<key>.md; edit there --> +… +<!-- cortex:ledger end --> ``` -`check` enforces: +The Brain's `cortex issue --apply` replaces exactly that span in the issue +body (or prepends it when the markers are absent) and leaves everything under +it — the detailed, agent-friendly run-through — untouched. The Cortex never +creates an issue; `Issue:` is set with `new --issue` or `link`. -- every non-blank line under `## Runs` matches `RUN_LINE_RE` or `RUN_CONT_RE`; - a continuation line follows a run line; -- task sets on one stem are **disjoint within a task** (job ids are unique - per task, not globally — one array may feed two tasks); -- the `Runs:` header equals the set of body stems (both empty when the task - has no runs); -- `State: pulled` ⇒ at least one `done | legacy` run carries `pulled_to:`; -- a `legacy | legacy_wrong` run carries `where:`; -- an `after:` / `resumes:` target is the identifier (the text before the - colon — `342091`, `342091_9` or `342091_[0-8,10]`) of another run line of - the **same task**; -- a `ruled:` value resolves to a ruling file. - ---- - -## Rulings - -`rulings/<YYYY>/<MM>/R-<YYYYMMDD>-<nn>.md`. The id is `R-YYYYMMDD-nn` — a -two-digit per-day sequence, global across projects; `rule` assigns it; the -filename equals the id and so does the title line (`# <id>` or -`# <id> — <one-line summary>`); `rule` generates -`# <id> — <verb> <project> <slug>`. - -````markdown -# R-20260901-02 — re-accept example 08_accepted with the corrected evidence pointer - -Project: example -Task: tasks/example/08_accepted.md -Runs: 342050 -Ruling: accept -Supersedes: R-20260901-01 -Batch: 2026-09-01-pm -Reviewed-at: 2026-09-01T17:20Z -Review-minutes-actual: 6 -Follow-ups: PyAutoLens#901 - -## Ruling - -The human's words, verbatim. - -## Evidence - -- pointers into the pulled results, the project ledger, figures -```` +## `scripts/cortex.py` — the verb reference -| Key | Value | Notes | +| Verb | Writes | Refuses when | |---|---|---| -| `Project:` | project key | | -| `Task:` | one task path | repo-relative, `tasks/<project>/<slug>.md` | -| `Runs:` | comma-separated stems, or empty | ⊆ the task's `Runs:` | -| `Ruling:` | `accept \| rerun \| drop \| leave-to-finish` | the verb | -| `Supersedes:` | one ruling id | optional; see the chain rules | -| `Batch:` | `<YYYY-MM-DD>-<slot>` | optional-**historical**; the 2026-08/09 rulings' join, nothing writes new ones | -| `Reviewed-at:` | timestamp | | -| `Review-minutes-actual:` | integer | | -| `Follow-ups:` | comma-separated GitHub refs | `GATE_REF_RE`; **the issue is created before `rule` runs** | -| `Migrated-from:` | source path or ledger anchor | the review file or project-ledger entry a backfilled ruling was transcribed from | - -Body: `## Ruling` — the human's words verbatim; `## Evidence` — pointers. - -**One ruling file per task.** A multi-task ruling (a REWIND) is N `rule` -invocations with the same body — one per task. - -**Chain rules** (`check`): - -- the id is unique, equals the filename stem and the title, and its date is - the file's `<YYYY>/<MM>` directory; the body has `## Ruling` and - `## Evidence`; -- `Supersedes:` resolves to an existing ruling, is not the ruling itself, is - lexically smaller (earlier), and names the same project **and** task; -- **at most one successor per ruling** — a chain, not a tree: supersede the - head; -- the task's `Ruling:` is a chain head (no ruling supersedes it) whose - `Task:` is that task; -- the head's verb matches the task's state: `accept ⇒ accepted`, - `drop ⇒ dropped`, `rerun ⇒ rerun | ready | submitted | running | pulled | - awaiting-ruling` (the task has moved on), `leave-to-finish ⇒ any - non-terminal state`; -- the ruling's `Runs:` ⊆ the task's runs; -- `Batch:`, when present, names an existing `batches/<slot>.md`. - -A task may hold rulings that are not chained to each other — a -`leave-to-finish` followed by an `accept` is two chains of one. `Supersedes:` -is for replacing a verdict, not for sequencing. - -The rest of the rule — append-only, supersede-never-edit, *a verdict recorded -only outside the Cortex does not exist* — is [rulings/AGENTS.md](rulings/AGENTS.md). - ---- - -## Batches — closed history - -`batches/<YYYY-MM-DD>-<slot>.md` and the human's verbatim reviews under -`batches/reviews/` are read-only history: three records from 2026-08/09, cited -by 13 rulings, kept because *a verdict recorded only outside the Cortex does -not exist*. They are **append-only** for the merge gate — never modified, only -added — and `check` no longer has a schema for them: the review-slot apparatus -that produced them (the packet page, the scored members, the review-minute -budget, the `-r<N>` sittings) was retired on 2026-09-03, and nothing writes a -new record. - -A ruling's `Batch:` field is therefore **optional-historical**: where present -it must still name an existing `batches/<slot>.md`, and nothing writes a new -one. - ---- +| `check` | nothing | — (exit 1 on any finding) | +| `new <project> --summary "…" [--issue REF] [--now "…"]` | a fresh `projects/<key>.md` from the template, with one `note — ledger opened` | the key is not a row; the file exists; the summary is over 15 words; the ref is malformed | +| `run <project> <jobid> "<what>" [--partition P]` | a run line (`open`) + a `run` entry | the id is not SLURM-shaped; it is already listed; the row is `both` and no `--partition` | +| `running <project> <jobid>` | the run line's state | the id is not under `## Runs` | +| `done <project> <jobid> [--failed] [--wall H:MM] [--note "…"]` | removes the run line, prepends a `run` entry | the id is not under `## Runs`; `--wall` is not `H:MM` | +| `log <project> "<text>" [--kind KIND]` | one entry at the head of the log | empty text; a `--today` earlier than the head entry | +| `now <project> "<text>"` | the body of `## Now` | empty text | +| `issue <project> [-n N]` | nothing (prints) | — | +| `link <project> <ref>` | the `Issue:` header line | the ref is not `Repo#N`, an issue URL or `none` | +| `retire <project> --why "…"` | `projects.yaml` (`status: retired`, `note:`), one `note` entry | the row is already retired; the ledger still lists a run; `--why` holds `"` | + +Every verb takes `--root <dir>` (default: this checkout) and every dated verb +`--today YYYY-MM-DD`, so the tests run against a copy of the fixture with a +fixed clock. A verb that would leave a file `check` cannot read refuses and +writes nothing. ## `projects.yaml` -Ordinary YAML, read with `yaml.safe_load` (PyYAML is `cortex.py`'s one -dependency; the hand-rolled restricted-subset parser it replaced was retired -on 2026-09-03, its own parity test having proved it equivalent). The document -is a mapping of project key → field mapping: +The science body map. **Code, not ledger** — `sync_cli` and `local_path` are +paths a conductor executes under. Real YAML read with `yaml.safe_load`; the +shape is validated by `cortex.py`: -```yaml -<key>: # ^[a-z][a-z0-9_]*$ - <field>: <scalar> # fixed field set, unknown field = error - sync_verbs: [pull, push] # a list of bare words - note: "free text" # the one optional field -``` - -What `check` validates is the **fields**, not the syntax: the document is a -mapping of rows, every key matches the key grammar, every field is in the set -below, `sync_verbs` is a list of bare words, and each value passes the rules -listed here. A document PyYAML cannot read is reported as one problem. - -- Fields (required): `remote` (`owner/repo` | `none` — PyAutoLabs for active - projects; a personal remote is recorded as a fact with a `note:`), - `local_path` (absolute laptop path — the Cortex-only exception to the - workspace-paths rule), `ral_root`, `mirror` (path | `none`), `sync_cli`, - `sync_verbs`, `ledger`, `assistant`, `witness_file` (glob), `partition` - (`gpu | ral | both`), `status` - (`active | dormant | planned | retired`). -- `assistant` is the domain assistant this project's work enters through — a - workspace-relative repo name such as `autolens_assistant`, or `none`; the - Cortex names it, never reads it. `check` accepts `none` or a bare directory - name (`^[A-Za-z0-9_.-]+$`: no `/`, never absolute) and stats nothing, so the - render does not need an assistant checkout. -- `note` (free text) is the **one optional field**: a row may omit it, an - empty `note:` is drift, and any other field is still an unknown-field - error. A note holding `:` or `#` is quoted like any other scalar. -- **Retiring a project.** `cortex.py retire <key> --why "<one line>"` is - the one verb that writes this file: it flips the row's `status:` to - `retired` and rewrites (or appends) its `note:` as - `"retired <today>: <why>"`. The **row stays** — it is the only record of - where that project's data lives — and no task or ruling is touched; - `rulings/` is append-only and a change of status is not a rewrite of - history. It refuses while the project holds a task in any state - outside `accepted | rerun | dropped | planned`, naming each one, so the - live questions are ruled or dropped first; `planned` tasks are unasked - questions and may stay. The edit is exactly those two lines — every - other byte of the file is preserved — and the result is re-parsed - before it is kept, the original bytes restored if it does not read - back clean. -- Science repos are **not** added to `PyAutoMind/repos.yaml` — that map is the - workspace, this one is the science. -- A file with no rows parses to an empty map (`{}`); PyYAML returns `None` - for a comment-only document, so the `yaml.safe_load(text) == parse(text)` - parity test runs on the fixture, which has a row. - ---- - -## How the ledger lands (`ledger_merge.yml`) +| Field | Value | Notes | +|---|---|---| +| `remote` | `owner/repo` or `none` | PyAutoLabs for active projects; a personal remote is a fact with a `note:` | +| `local_path` | absolute path | the laptop checkout — the workspace-paths exception (AGENTS.md) | +| `ral_root` | absolute path | the project root on RAL | +| `mirror` | absolute path or `none` | the laptop pull root the sync CLI fills | +| `sync_cli` | path relative to `local_path` | the project's own sync CLI — the only thing that reaches a cluster | +| `sync_verbs` | flow list of bare words | the verbs that CLI has; `pull` is what `checkin` runs, `jobs` what it shows | +| `ledger` | path relative to `local_path` | the project's own commentary ledger (a `wiki/project/state.md`, a `NOTES.md`) | +| `assistant` | a workspace-relative repo name or `none` | the domain assistant the project's work enters through; named, never read | +| `witness_file` | glob relative to the mirror | kept for the projects' own tooling; the Cortex no longer scores it | +| `partition` | `gpu` \| `ral` \| `both` | which SLURM partition(s) the project runs on; `run` needs `--partition` on `both` | +| `status` | `active` \| `dormant` \| `planned` \| `retired` | `retire` writes the last | +| `note` | free text, **optional** | the only optional field; an empty `note:` is drift | -A push to a `claude/**` branch whose whole diff is **ledger** is merged into -`main` by `.github/workflows/ledger_merge.yml` and the branch deleted — no PR, -no session step. The line is drawn by `scripts/ledger_merge.py`, **default -deny**: - -| Ledger — merged automatically | Code — always a human | -|---|---| -| `tasks/**`, `rulings/**`, `batches/**` | `scripts/`, `tests/`, `.github/`, `policy/`, `docs/` | -| `checkin.yaml` | `projects.yaml`, `README.md`, `AGENTS.md`, `REFERENCE.md`, … | -| `dashboard.md`, `dashboard.html` (generated) | **`AGENTS.md` / `TEMPLATE.md` inside a ledger dir** | -| | anything unclassified — a new root file, a new top-level folder | -| | **any modification or deletion under `rulings/` or `batches/`** (append-only) | - -Three exceptions inside the ledger dirs. Two are the Mind's: a **dot-path** -anywhere, and a file pytest would **collect** (`conftest.py`, `test_*.py`, -`*_test.py`). The third is the Cortex's own **doctrine carve-out** — -`rulings/AGENTS.md`, `batches/AGENTS.md` and `batches/reviews/AGENTS.md` are -ledger by location but instructional by content: they say what an entry may be and what -every future entry is stamped from, so a change to one is a change to -behaviour. Auto-merging a rewrite of `rulings/AGENTS.md` would let a branch -edit the rule that governs its own merge. - -Pulling the other way, the two **generated** board pages are ledger: a branch -that moves a task re-renders them in the same push, and -`dashboard_refresh.yml`'s self-heal commit has to land without a human. - -And a fourth Cortex rule on *kind* rather than path: `ledger_merge.py` -classifies via `git diff --name-status`, and an `M`, `D` or `R` entry under -`rulings/**` or `batches/**` is code. `rulings/` because a ruling is -superseded, never edited; `batches/` since 2026-09-03, when the review-slot -apparatus was retired and its records became history — never modified, only -added. - -The blocking check is `python3 scripts/cortex.py check` run on the **trial-merge -tree** — after `git merge --no-ff`, before `git push` — which is what catches -the ruling-id race (two branches both assign `R-…-03`: each passes alone, the -merge fails). A failing check resets the trial merge and leaves the branch for -a human. Predict the verdict before you push: +## Repository layout -```bash -python3 scripts/ledger_merge.py classify --base origin/main # exit 0 = will auto-merge -python3 scripts/cortex.py check # exit 0 = will not block +``` +projects.yaml the body map (code) +projects/<key>.md one ledger per project (ledger) +projects/AGENTS.md doctrine for the folder (code) +checkin.yaml the last-check-in stamp (ledger) +dashboard.md, .html generated board (ledger; never hand-edited) +archive/ frozen 2026-08/09 tasks, rulings, batches (code) +scripts/cortex.py the lifecycle script +scripts/ledger_merge.py the auto-merge classifier +tests/ pytest; fixtures/skeleton and fixtures/empty +docs/schema_decisions.md every dated choice ``` ---- - -## `scripts/cortex.py` — the verb reference +## How the ledger lands (`ledger_merge.yml`) -Stdlib only; `main(argv)`; no import-time side effects; every verb takes -`--root <dir>` (default: the repo root the script lives in). Every leg of -`check` takes `root: Path`, so tests run it against a `tmp_path` copy. - -- **`check`** — every rule in this file: task headers and states, the witness - invariant, `## Where to look` naming somewhere past `planned`, run lines, - ruling ids and chains, the verb↔state agreement, every project named by a - task path is a `projects.yaml` key, and `projects.yaml`'s own fields. Hermetic (no network, no git). Output in `lifecycle.py`'s shape — - `cortex check: OK` or `cortex check: DRIFT` followed by one ` - …` line per - finding; exit 1 on drift. -- **`gates`** — read-only and offline: every `gated` task, its refs and the - URL each ref resolves to (`GATE_REF_RE` → `gate_url`). Nothing polls GitHub - and nothing flips a state. Grading was retired on 2026-09-03 — in its whole - life it saw 2 gated refs and flipped 0, while schema decision 54 routes - sequencing through prose `Ready when:` lines. A human reads the listing, - opens the refs and types `move <task> ready`. -- **`rule <task> <verb> --body <file> [--supersedes <id>] [--batch <slot>] - [--minutes n] [--follow-up <ref>]...`** — assigns the next id for today, - writes the ruling file, updates the task's `Ruling:` and `State:` per the - table (and appends `<id> — <verb>` to the task's - `## Ruling`); the ruling's `Runs:` is the task's, its `## Evidence` is the - task's `## Where to look`; refuses to touch an existing ruling; refuses a - verb the table does not allow from the task's state; validates everything - before writing anything. -- **`move <task> <state> [--run <id>] [--reason ..] - [--partial] [--pulled-to <path>] [--partition ..] [--after <run>] - [--resumes <run>] [--note ..]`** — the table; refuses every ruling edge - with a message naming `rule`. `--run` on `submitted`/`running` appends a - run line and keeps the state; the appended line is - `- <id>: submitted — <partition> — submitted <today> — wall 0:00[ — <note>]` - with `after:` / `resumes:` continuations from the flags, and its - partition is the project's `partition:` row unless that is `both`, when - `--partition` is required. Every edit is an in-place header edit or an - appended run line; every other byte of the file is preserved. -- **`new <project> <slug> --summary "<≤10 words>" [--gates ..] [--epic ..] - [--legacy-run <id>]... [--legacy-wrong <id>]... [--where <path>] - [--partition ..] [--witness ..] [--budget ..] [--minutes n] [--title ..]`** - — writes `tasks/<project>/<slug>.md` from the template in `planned` (or - `ready` when `--legacy-run` / `--legacy-wrong` is given and every run is - legacy); each legacy run line is written with today's date, `wall 0:00` - and the note `pre-Cortex run, migrated` — the human corrects the date and - wall by hand — and `--where` (required) as its `where:`; a legacy-born - task refuses `--gates`. `--summary` is required and held to the same ten - words `check` holds it to. Refuses an existing file (the slug is the - identity — there is nothing else to collide on) or an unknown project. -- **`retire <project> --why "<one line>"`** — the only verb that writes - `projects.yaml`: `status: retired` plus a `note:` reading - `"retired <today>: <why>"`, two lines edited in place and every other - byte preserved. Refuses an unknown key, an already-retired row, and any - project still holding a task outside `accepted | rerun | dropped | - planned` (the message names each `<task> — <state>`). The row, its - tasks and its rulings all stay; see `projects.yaml` above. - ---- +A push to `claude/**` whose whole diff is ledger — `projects/*.md` (not +`AGENTS.md` / `TEMPLATE.md`), `checkin.yaml`, `dashboard.md`, +`dashboard.html` — is merged into `main` with `--no-ff` and the branch +deleted. Anything else waits for a human: `scripts/`, `tests/`, `.github/`, +`policy/`, `docs/`, `projects.yaml`, the prose pages, anything under +`archive/`, and anything unclassified (default deny). `cortex.py check` runs +on the branch tip and again on the trial-merge tree, so two branches that +each edited the same ledger are caught before either lands. `python3 +scripts/ledger_merge.py classify --base origin/main` predicts the verdict +(exit 0 ledger · 1 code · 2 could not classify). ## Check-in -**One command.** `pyauto-brain cortex checkin` is the door the human types when -they want to know where their science is: +`pyauto-brain cortex checkin` (the Brain's cortex conductor) is the one door: ```bash -pyauto-brain cortex checkin --dry-run # what it would pull and score -pyauto-brain cortex checkin --apply # pull, score, move, render, push -pyauto-brain cortex checkin --apply --no-push # ... without the push +pyauto-brain cortex checkin --dry-run # what it would pull; reaches nothing +pyauto-brain cortex checkin --apply # pull, show jobs, render, push +pyauto-brain cortex checkin --apply --no-push pyauto-brain cortex checkin --apply --project subhalo_validation -pyauto-brain cortex checkin --apply --skip-pull # re-score what is already here +pyauto-brain cortex checkin --apply --skip-pull ``` -It sweeps every `status: active` row of `projects.yaml`, plus any project that -owns a task in `submitted | running`, and runs **that project's own** -`<local_path>/<sync_cli> pull` — the verb all seven implement. Nothing else -reaches a cluster; the conductor adds no SSH. A pull that exits non-zero is -recorded against its project and the sweep continues. Then it scores every live -task (the six legs below), moves `running → pulled → awaiting-ruling`, -re-renders `dashboard.md` + `dashboard.html`, and prints a summary keyed **by -project** — the last thing on screen, so a chat sees it first. - -### `checkin.yaml` — the last-check-in stamp +It sweeps every `status: active` row plus any project whose ledger lists a +run, runs **that project's own** `<local_path>/<sync_cli> pull` (a failing +pull is recorded against its project and the sweep continues), runs its `jobs` +verb where the row has one and prints the output verbatim, writes +`checkin.yaml`, re-renders the two pages, pushes the ledger on +`claude/checkin-<date>` when `gh` is logged in and the checkout is clean on +`main`, and prints last a summary keyed by project: Now, the runs, the last +five entries, and the `cortex.py` lines the human is likely to type next. It +flips no state and writes no entry of its own — the jobs output is read by +the human or the agent in the session and recorded with `running` / `done`. -One key, one line, committed and pushed with the ledger: +### `checkin.yaml` ```yaml -refreshed: 2026-09-04T14:03:00Z +refreshed: 2026-09-10T19:41Z ``` -It records the last **check-in**, not the last render: `checkin --apply` (and -`collect --apply`) writes it from the same stamp it scored against, before the -pages are rendered, so a doc-only push that re-renders the board cannot fake -freshness. The board reads it back as "Last check-in"; the HTML twin computes -the age on the *viewer's* clock and reddens it past sixty minutes, because a -static page cannot know when it is being read. Absent, the board says "never -checked in". The file is stable between renders, so `dashboard --check` needs -no rule for it. - -### The by-project view - -The summary is a tree, and it is the same tree in three places: the -`## By project` section of `dashboard.md` / `dashboard.html`, the text -`pyauto-brain cortex census --by-project` prints from the checkout alone, and -the closing summary of a real `checkin` (which is the only one of the three -carrying pull results and six-leg health). One builder, three renderings — a -prompt added to a state appears in all of them. - -Per project: the three folders it lives in (`local_path`, `mirror` when it has -one, `ral_root`), what came of its pull, its task counts by state, then every -task that is still **open** — awaiting a ruling, still out there, ready to -submit, gated, planned — each with its state and health, its `## Where to look` -bullets verbatim, and a copy chip per prompt its state carries. `accepted`, -`rerun` and `dropped` tasks are history and appear only in the counts. A -project gets a block when its `projects.yaml` row is `status: active`, or when -it still holds an open task; every other project folds into one line. - -On the board `## By project` is the **first** section, above the state lists: -those are cross-project, so every row has to be read to find out whose it is, -while this one answers "where is everything" a screen per project. The counts -table sits above it and keeps the urgency sections one tap away; the counts -strip itself is unchanged (the Brain board reads it). - -### The five starting prompts - -Every task row hands the reader a command rather than a decision. Which -prompts a task carries is its **state**, and nothing else: - -| Prompt | States | What it says | -|---|---|---| -| rule on it | `pulled`, `awaiting-ruling` | read the witness and the pulled evidence, draft the ruling body, `rule <task> <verb> --body <file>` | -| the results are good — accept and open the next task | `pulled`, `awaiting-ruling` | `rule <task> accept --body <file>`, then open the next task (below) | -| run it again | `pulled`, `awaiting-ruling`, `running` | `rule <task> rerun --body <file>`, `move <task> ready`, the project's own submit, `move <task> submitted --run <jobid>` | -| where the jobs stand | `submitted`, `running` | the project's own `<sync_cli> jobs` | -| submit it | `ready` | the task, the project's own submit verb, `move <task> submitted --run <jobid>` | - -(`gated` and `planned` tasks carry the one-line `gates` / `move … ready` -command they always had.) - -**Accept and open the next task** is two commands in one prompt because they -are one decision: an accept that opens nothing leaves the programme where it -was. With the number gone there is no "N+1" to prefill — the tasks a project -holds are unordered ideas, so the second half offers the project's `planned` -and `gated` tasks to open (`move … ready` + the launch) and otherwise a `new` -line for a task the human names with a slug and a `Summary:`. The `new` line -carries the task's own `Epic:` and spells out the title rule: **`new` writes -`# <Project> — ` in front of `--title` itself**, so `--title` takes the tail -alone. - -**Run it again** is a ruling first: `rerun` is the only verb that puts a task -back on the board, so the verdict on what came back is what makes the next -submission a rerun rather than a repeat. Its `move … submitted --run` line -carries the reminder that it is one run per call (`--after <run>` chains the -next). - -The payloads are short on purpose. They are pasted into a fresh chat, not run -as scripts: every one of them ends in a human's own reading, and the `<file>`, -`<script>`, `<slug>` and `<jobid>` placeholders are where that reading lands. - -### `.cortex/pull.json` — the pull manifest - -After a successful pull the door writes the manifest at the top of that -project's pull root (its `mirror` if it has one, else its `local_path`) — -the same file `collect`'s checkpoint leg reads: - -| Key | Written by | Meaning | -|---|---|---| -| `project` | the check-in | the `projects.yaml` key this tree belongs to | -| `pulled_at` | the check-in | UTC `YYYY-MM-DDTHH:MMZ` of the pull that just finished | -| `cmd` | the check-in | the pull as a human would type it (`cd <local_path> && <sync_cli> pull`) | -| `rc` | the check-in | that pull's exit code — `0`, or the manifest is not written | -| `tasks_live` | the check-in | the task paths that were `submitted \| running` when it ran | -| `schema` | a project's own CLI | `1` where the CLI writes the richer shape; absent = the older `runs`-only one | -| `checkpoints` | a project's own CLI | `{"<run dir, relative to the pull root>": {"bytes": N, "mtime": ISO}}` | -| `runs` | a project's own CLI | `{"<jobid|jobid_task>": {"checkpoint_bytes": N, "checkpoint_mtime": ISO}}` | - -**Merged, never clobbered.** `autolens_profiling`'s own `hpc/sync` already -writes `checkpoints` / `runs` here — the only window onto the RAL-only -`search_internal/checkpoint.hdf5`, which no pull mirrors. The check-in adds its -five keys and leaves every other key exactly as it found it, so the richer -manifest keeps making the checkpoint leg scorable. Without a manifest that leg -is `UNOBSERVABLE`, not `FAIL`. - -The manifests live **outside** this repository, in the science trees, so -`cortex.py check` says nothing about them; the check-in's own note line -(`<project>: pulled → <path>`) is the record that one was written. - -### The push - -`--push` is allowed only when **`gh auth status` succeeds** *and* **this -checkout is clean on `main`** — checked before anything is written, since -"clean" stops being true the moment the tasks move. That is the cloud/laptop -split and it is also the default: a laptop pushes without asking, a cloud -session cannot and says so. The push cuts `claude/checkin-<YYYY-MM-DD>` from a -fresh `origin/main`, commits the changed paths explicitly and pushes; -`ledger_merge.yml` then merges it into `main` and deletes the branch (below). -`scripts/ledger_merge.py classify` is asked **first** and a code-classified -diff — `projects.yaml`, `scripts/`, the prose pages — is refused before the -branch is cut. Never `main` directly, never `--force`. - -## Driving the Cortex — the conductor and the workflows - -The Cortex is state plus `cortex.py`. The reasoning over it — the board and the -check-in — is the Brain's **cortex conductor**: - -```bash -pyauto-brain cortex checkin [--dry-run|--apply] [--push|--no-push] [--project KEY] [--skip-pull] [--refreshed ISO] -pyauto-brain cortex census [--json] # what is held, by state -pyauto-brain cortex census --by-project # ... by project: folders, open tasks, prompts -pyauto-brain cortex dashboard --check | --apply # render the two pages -pyauto-brain cortex gates # the gated tasks and their refs -pyauto-brain cortex collect [--task REL] [--pull] [--refreshed ISO] [--apply] [--out F] -``` - -`checkin` composes the others (above). `collect` with no `--task` scopes to -**every** task in `submitted | running` — the scorer on its own. +Written by `checkin --apply` before the pages are rendered, so a doc-only +push that re-renders the board cannot fake freshness. The HTML board reddens +the stamp on the viewer's clock once it is an hour old. -With no Brain install, or from a workflow: +## The board -```bash -python3 ../PyAutoBrain/agents/conductors/cortex/_cortex.py dashboard --cortex . --check -``` - -`--cortex` is a flag of the **subcommand**, not a global one: it follows the -verb. (`--cortex . dashboard --check` exits 2.) The root is resolved -`--cortex` → `$PYAUTO_CORTEX` → `PyAutoCortex` beside the Brain checkout. - -**Two spellings of the same flag.** The conductor writes with `--apply` (the -Brain's house spelling); `scripts/cortex.py` writes with `--write`. Every edit -to a task is `cortex.py`'s either way. - -**The `--check` exit-code contract** (`dashboard_refresh.yml` depends on it): - -| Code | Meaning | What the caller does | -|---|---|---| -| 0 | the committed pages match a fresh render | nothing | -| 1 | **drift** — and nothing else | error on a PR, self-heal on main | -| 2 | bad args — this Brain has no such verb/flag | report a renderer failure | -| other | the renderer could not run (a Brain/Cortex skew) | report a renderer failure | - -Treating 2 as drift sends whoever reads the log to fix `dashboard.md` when the -broken thing is the Brain: `dashboard_refresh.yml` wraps the call in `check()` -for exactly that reason. - -### What each workflow may write - -| Workflow | Trigger | Writes | -|---|---|---| -| `cortex_check.yml` | push/PR on `tasks/ rulings/ batches/ projects.yaml checkin.yaml dashboard.* scripts/ tests/` | nothing (`cortex.py check` + pytest) | -| `dashboard_refresh.yml` | push to main + PR on the ledger paths and the two pages, nightly **03:35 UTC**, dispatch | `dashboard.md`, `dashboard.html` on main (3-attempt fetch/reset/render/commit/push); a PR run errors instead of healing | -| `pages_dashboard.yml` | push to `dashboard.html`, dispatch | nothing in git — publishes `dashboard.html` as the Pages index | -| `ledger_merge.yml` | push to `claude/**`, dispatch | merges a ledger-only branch into main | - -**No scheduled job mutates the ledger.** A daily gate-grading cron did until -2026-09-03; retiring gate grading retired it with no replacement. - -Every workflow that can push to main shares `concurrency: group: -cortex-main-writers, cancel-in-progress: false` — `dashboard_refresh.yml` and -`ledger_merge.yml` — so two bot writers never race for the tip. -`pages_dashboard.yml` keeps its own `group: pages`. - -A push made with `GITHUB_TOKEN` triggers **no** workflow, so each writer -re-dispatches by name what its push should have woken: `dashboard_refresh.yml` -asks for `pages_dashboard.yml` (on both paths — fresh *and* healed; folding the -fresh one away is the bug that stranded the Mind's published board), and -`ledger_merge.yml` asks for `cortex_check.yml`. - -The board is published at **<https://pyautolabs.github.io/PyAutoCortex/>**. - ---- +`dashboard.md` and `dashboard.html`, rendered by the conductor: a counts table +(**Running**, **Open**, **Projects** — the Brain board reads these three +rows), the check-in chip and stamp, a four-column **Summary** (`Project · +Running · Open · Last update` — deliberately no free text, so it fits a +phone), then one card per project with a ledger: the facts line, **Now**, the +**Runs**, the **Last 5** entries, and a single 📋 **resume** chip for an active +project — the paste that has an agent read the ledger and the project's own +state file and say where you left off. Retired projects fold into one line +each; dormant rows with no ledger are a small table. No chip on the page +submits, scores or decides anything. ## Bootstrap ```bash -cd ~/Code/PyAutoLabs -git clone https://github.com/PyAutoLabs/PyAutoCortex.git -python3 PyAutoMind/scripts/repos_sync.py --write # CLAUDE.md, .claude/, the AGENTS.md blocks -python3 PyAutoCortex/scripts/cortex.py check # OK on an empty tree +python3 -m pip install pyyaml pytest +python3 scripts/cortex.py check +python3 -m pytest -q ``` - -The checkout directory must be named `PyAutoCortex`; the organism's sync and -drift scripts address it by that name. diff --git a/archive/AGENTS.md b/archive/AGENTS.md new file mode 100644 index 0000000..701d212 --- /dev/null +++ b/archive/AGENTS.md @@ -0,0 +1,17 @@ +# archive/ — frozen + +The task, ruling and batch ledgers the Cortex kept between 2026-08-31 and +2026-09-11, retired on 2026-09-12 (schema decision 60) when the Cortex became +one ledger per project. Nothing writes here any more, nothing reads it at +render time, and `scripts/ledger_merge.py` classifies **any** change under +this directory — an addition included — as code, which is a human's turn. + +It stays because the science repos' own ledgers cite these files by id +(`R-20260910-04`, `tasks/euclid_dr1_prelim/ordered_rerun_catalogue_parity.md`). +Every entry that mattered was carried into `projects/<key>.md` on the day of +the migration, in the words already on file, with a `[archive/tasks/…]` link +back to the question it came from. + +- `tasks/<project>/<slug>.md` — the pre-registered questions and their run lines +- `rulings/<YYYY>/<MM>/R-<YYYYMMDD>-<nn>.md` — the 37 verdicts, the human's words verbatim +- `batches/` — the three 2026-08/09 review-slot records and their reviews diff --git a/batches/2026-08-31-am.md b/archive/batches/2026-08-31-am.md similarity index 100% rename from batches/2026-08-31-am.md rename to archive/batches/2026-08-31-am.md diff --git a/batches/2026-08-31-pm.md b/archive/batches/2026-08-31-pm.md similarity index 100% rename from batches/2026-08-31-pm.md rename to archive/batches/2026-08-31-pm.md diff --git a/batches/2026-09-02-pm.md b/archive/batches/2026-09-02-pm.md similarity index 100% rename from batches/2026-09-02-pm.md rename to archive/batches/2026-09-02-pm.md diff --git a/batches/AGENTS.md b/archive/batches/AGENTS.md similarity index 75% rename from batches/AGENTS.md rename to archive/batches/AGENTS.md index dd6699f..b121b4a 100644 --- a/batches/AGENTS.md +++ b/archive/batches/AGENTS.md @@ -1,3 +1,5 @@ +> **Frozen 2026-09-12** — this folder is history under `archive/` (schema decision 60). Nothing writes here any more; the rules below describe how it was kept. + # Batch records — closed history Read-only history: never modified, only added. Three 2026-08/09 batch records diff --git a/batches/reviews/2026-08-31-am.md b/archive/batches/reviews/2026-08-31-am.md similarity index 100% rename from batches/reviews/2026-08-31-am.md rename to archive/batches/reviews/2026-08-31-am.md diff --git a/batches/reviews/2026-08-31-pm.md b/archive/batches/reviews/2026-08-31-pm.md similarity index 100% rename from batches/reviews/2026-08-31-pm.md rename to archive/batches/reviews/2026-08-31-pm.md diff --git a/batches/reviews/2026-09-02-pm.md b/archive/batches/reviews/2026-09-02-pm.md similarity index 100% rename from batches/reviews/2026-09-02-pm.md rename to archive/batches/reviews/2026-09-02-pm.md diff --git a/batches/reviews/AGENTS.md b/archive/batches/reviews/AGENTS.md similarity index 79% rename from batches/reviews/AGENTS.md rename to archive/batches/reviews/AGENTS.md index 9f4ef4e..f7336bd 100644 --- a/batches/reviews/AGENTS.md +++ b/archive/batches/reviews/AGENTS.md @@ -1,3 +1,5 @@ +> **Frozen 2026-09-12** — this folder is history under `archive/` (schema decision 60). Nothing writes here any more; the rules below describe how it was kept. + # Batch reviews — what the human ruled, verbatim Read-only history, kept for the same reason the records beside them are: 13 diff --git a/rulings/2026/08/R-20260831-01.md b/archive/rulings/2026/08/R-20260831-01.md similarity index 100% rename from rulings/2026/08/R-20260831-01.md rename to archive/rulings/2026/08/R-20260831-01.md diff --git a/rulings/2026/08/R-20260831-02.md b/archive/rulings/2026/08/R-20260831-02.md similarity index 100% rename from rulings/2026/08/R-20260831-02.md rename to archive/rulings/2026/08/R-20260831-02.md diff --git a/rulings/2026/08/R-20260831-03.md b/archive/rulings/2026/08/R-20260831-03.md similarity index 100% rename from rulings/2026/08/R-20260831-03.md rename to archive/rulings/2026/08/R-20260831-03.md diff --git a/rulings/2026/08/R-20260831-04.md b/archive/rulings/2026/08/R-20260831-04.md similarity index 100% rename from rulings/2026/08/R-20260831-04.md rename to archive/rulings/2026/08/R-20260831-04.md diff --git a/rulings/2026/08/R-20260831-05.md b/archive/rulings/2026/08/R-20260831-05.md similarity index 100% rename from rulings/2026/08/R-20260831-05.md rename to archive/rulings/2026/08/R-20260831-05.md diff --git a/rulings/2026/08/R-20260831-06.md b/archive/rulings/2026/08/R-20260831-06.md similarity index 100% rename from rulings/2026/08/R-20260831-06.md rename to archive/rulings/2026/08/R-20260831-06.md diff --git a/rulings/2026/08/R-20260831-07.md b/archive/rulings/2026/08/R-20260831-07.md similarity index 100% rename from rulings/2026/08/R-20260831-07.md rename to archive/rulings/2026/08/R-20260831-07.md diff --git a/rulings/2026/08/R-20260831-08.md b/archive/rulings/2026/08/R-20260831-08.md similarity index 100% rename from rulings/2026/08/R-20260831-08.md rename to archive/rulings/2026/08/R-20260831-08.md diff --git a/rulings/2026/09/R-20260901-01.md b/archive/rulings/2026/09/R-20260901-01.md similarity index 100% rename from rulings/2026/09/R-20260901-01.md rename to archive/rulings/2026/09/R-20260901-01.md diff --git a/rulings/2026/09/R-20260901-02.md b/archive/rulings/2026/09/R-20260901-02.md similarity index 100% rename from rulings/2026/09/R-20260901-02.md rename to archive/rulings/2026/09/R-20260901-02.md diff --git a/rulings/2026/09/R-20260901-03.md b/archive/rulings/2026/09/R-20260901-03.md similarity index 100% rename from rulings/2026/09/R-20260901-03.md rename to archive/rulings/2026/09/R-20260901-03.md diff --git a/rulings/2026/09/R-20260901-04.md b/archive/rulings/2026/09/R-20260901-04.md similarity index 100% rename from rulings/2026/09/R-20260901-04.md rename to archive/rulings/2026/09/R-20260901-04.md diff --git a/rulings/2026/09/R-20260902-01.md b/archive/rulings/2026/09/R-20260902-01.md similarity index 100% rename from rulings/2026/09/R-20260902-01.md rename to archive/rulings/2026/09/R-20260902-01.md diff --git a/rulings/2026/09/R-20260902-02.md b/archive/rulings/2026/09/R-20260902-02.md similarity index 100% rename from rulings/2026/09/R-20260902-02.md rename to archive/rulings/2026/09/R-20260902-02.md diff --git a/rulings/2026/09/R-20260902-03.md b/archive/rulings/2026/09/R-20260902-03.md similarity index 100% rename from rulings/2026/09/R-20260902-03.md rename to archive/rulings/2026/09/R-20260902-03.md diff --git a/rulings/2026/09/R-20260902-04.md b/archive/rulings/2026/09/R-20260902-04.md similarity index 100% rename from rulings/2026/09/R-20260902-04.md rename to archive/rulings/2026/09/R-20260902-04.md diff --git a/rulings/2026/09/R-20260902-05.md b/archive/rulings/2026/09/R-20260902-05.md similarity index 100% rename from rulings/2026/09/R-20260902-05.md rename to archive/rulings/2026/09/R-20260902-05.md diff --git a/rulings/2026/09/R-20260902-06.md b/archive/rulings/2026/09/R-20260902-06.md similarity index 100% rename from rulings/2026/09/R-20260902-06.md rename to archive/rulings/2026/09/R-20260902-06.md diff --git a/rulings/2026/09/R-20260902-07.md b/archive/rulings/2026/09/R-20260902-07.md similarity index 100% rename from rulings/2026/09/R-20260902-07.md rename to archive/rulings/2026/09/R-20260902-07.md diff --git a/rulings/2026/09/R-20260902-08.md b/archive/rulings/2026/09/R-20260902-08.md similarity index 100% rename from rulings/2026/09/R-20260902-08.md rename to archive/rulings/2026/09/R-20260902-08.md diff --git a/rulings/2026/09/R-20260902-09.md b/archive/rulings/2026/09/R-20260902-09.md similarity index 100% rename from rulings/2026/09/R-20260902-09.md rename to archive/rulings/2026/09/R-20260902-09.md diff --git a/rulings/2026/09/R-20260902-10.md b/archive/rulings/2026/09/R-20260902-10.md similarity index 100% rename from rulings/2026/09/R-20260902-10.md rename to archive/rulings/2026/09/R-20260902-10.md diff --git a/rulings/2026/09/R-20260904-01.md b/archive/rulings/2026/09/R-20260904-01.md similarity index 100% rename from rulings/2026/09/R-20260904-01.md rename to archive/rulings/2026/09/R-20260904-01.md diff --git a/rulings/2026/09/R-20260904-02.md b/archive/rulings/2026/09/R-20260904-02.md similarity index 100% rename from rulings/2026/09/R-20260904-02.md rename to archive/rulings/2026/09/R-20260904-02.md diff --git a/rulings/2026/09/R-20260904-03.md b/archive/rulings/2026/09/R-20260904-03.md similarity index 100% rename from rulings/2026/09/R-20260904-03.md rename to archive/rulings/2026/09/R-20260904-03.md diff --git a/rulings/2026/09/R-20260904-04.md b/archive/rulings/2026/09/R-20260904-04.md similarity index 100% rename from rulings/2026/09/R-20260904-04.md rename to archive/rulings/2026/09/R-20260904-04.md diff --git a/rulings/2026/09/R-20260904-05.md b/archive/rulings/2026/09/R-20260904-05.md similarity index 100% rename from rulings/2026/09/R-20260904-05.md rename to archive/rulings/2026/09/R-20260904-05.md diff --git a/rulings/2026/09/R-20260907-01.md b/archive/rulings/2026/09/R-20260907-01.md similarity index 100% rename from rulings/2026/09/R-20260907-01.md rename to archive/rulings/2026/09/R-20260907-01.md diff --git a/rulings/2026/09/R-20260907-02.md b/archive/rulings/2026/09/R-20260907-02.md similarity index 100% rename from rulings/2026/09/R-20260907-02.md rename to archive/rulings/2026/09/R-20260907-02.md diff --git a/rulings/2026/09/R-20260907-03.md b/archive/rulings/2026/09/R-20260907-03.md similarity index 100% rename from rulings/2026/09/R-20260907-03.md rename to archive/rulings/2026/09/R-20260907-03.md diff --git a/rulings/2026/09/R-20260907-04.md b/archive/rulings/2026/09/R-20260907-04.md similarity index 100% rename from rulings/2026/09/R-20260907-04.md rename to archive/rulings/2026/09/R-20260907-04.md diff --git a/rulings/2026/09/R-20260907-05.md b/archive/rulings/2026/09/R-20260907-05.md similarity index 100% rename from rulings/2026/09/R-20260907-05.md rename to archive/rulings/2026/09/R-20260907-05.md diff --git a/rulings/2026/09/R-20260907-06.md b/archive/rulings/2026/09/R-20260907-06.md similarity index 100% rename from rulings/2026/09/R-20260907-06.md rename to archive/rulings/2026/09/R-20260907-06.md diff --git a/rulings/2026/09/R-20260910-01.md b/archive/rulings/2026/09/R-20260910-01.md similarity index 100% rename from rulings/2026/09/R-20260910-01.md rename to archive/rulings/2026/09/R-20260910-01.md diff --git a/rulings/2026/09/R-20260910-02.md b/archive/rulings/2026/09/R-20260910-02.md similarity index 100% rename from rulings/2026/09/R-20260910-02.md rename to archive/rulings/2026/09/R-20260910-02.md diff --git a/rulings/2026/09/R-20260910-03.md b/archive/rulings/2026/09/R-20260910-03.md similarity index 100% rename from rulings/2026/09/R-20260910-03.md rename to archive/rulings/2026/09/R-20260910-03.md diff --git a/rulings/2026/09/R-20260910-04.md b/archive/rulings/2026/09/R-20260910-04.md similarity index 100% rename from rulings/2026/09/R-20260910-04.md rename to archive/rulings/2026/09/R-20260910-04.md diff --git a/rulings/AGENTS.md b/archive/rulings/AGENTS.md similarity index 93% rename from rulings/AGENTS.md rename to archive/rulings/AGENTS.md index a89dfaa..ad7abee 100644 --- a/rulings/AGENTS.md +++ b/archive/rulings/AGENTS.md @@ -1,3 +1,5 @@ +> **Frozen 2026-09-12** — this folder is history under `archive/` (schema decision 60). Nothing writes here any more; the rules below describe how it was kept. + # Rulings — the ledger of record `rulings/<YYYY>/<MM>/R-<YYYYMMDD>-<nn>.md`, one file per verdict per task. diff --git a/tasks/analytic_gaussian/ensemble_parity.md b/archive/tasks/analytic_gaussian/ensemble_parity.md similarity index 100% rename from tasks/analytic_gaussian/ensemble_parity.md rename to archive/tasks/analytic_gaussian/ensemble_parity.md diff --git a/tasks/analytic_gaussian/minimal_ep_legb_mu_threshold.md b/archive/tasks/analytic_gaussian/minimal_ep_legb_mu_threshold.md similarity index 100% rename from tasks/analytic_gaussian/minimal_ep_legb_mu_threshold.md rename to archive/tasks/analytic_gaussian/minimal_ep_legb_mu_threshold.md diff --git a/tasks/autolens_inference/slam_hst_base.md b/archive/tasks/autolens_inference/slam_hst_base.md similarity index 100% rename from tasks/autolens_inference/slam_hst_base.md rename to archive/tasks/autolens_inference/slam_hst_base.md diff --git a/tasks/ep_toy_gaussian/nuts_vs_ep_x3_n50.md b/archive/tasks/ep_toy_gaussian/nuts_vs_ep_x3_n50.md similarity index 100% rename from tasks/ep_toy_gaussian/nuts_vs_ep_x3_n50.md rename to archive/tasks/ep_toy_gaussian/nuts_vs_ep_x3_n50.md diff --git a/tasks/euclid/magnification_robustness.md b/archive/tasks/euclid/magnification_robustness.md similarity index 100% rename from tasks/euclid/magnification_robustness.md rename to archive/tasks/euclid/magnification_robustness.md diff --git a/tasks/euclid/resimulate_fitted_lens_simulator.md b/archive/tasks/euclid/resimulate_fitted_lens_simulator.md similarity index 100% rename from tasks/euclid/resimulate_fitted_lens_simulator.md rename to archive/tasks/euclid/resimulate_fitted_lens_simulator.md diff --git a/tasks/euclid/sersic_index_recovery.md b/archive/tasks/euclid/sersic_index_recovery.md similarity index 100% rename from tasks/euclid/sersic_index_recovery.md rename to archive/tasks/euclid/sersic_index_recovery.md diff --git a/tasks/euclid_dr1_prelim/dr1_prelim_10_lens_science_run.md b/archive/tasks/euclid_dr1_prelim/dr1_prelim_10_lens_science_run.md similarity index 100% rename from tasks/euclid_dr1_prelim/dr1_prelim_10_lens_science_run.md rename to archive/tasks/euclid_dr1_prelim/dr1_prelim_10_lens_science_run.md diff --git a/tasks/euclid_dr1_prelim/ordered_mge_control_unordered_102005065.md b/archive/tasks/euclid_dr1_prelim/ordered_mge_control_unordered_102005065.md similarity index 100% rename from tasks/euclid_dr1_prelim/ordered_mge_control_unordered_102005065.md rename to archive/tasks/euclid_dr1_prelim/ordered_mge_control_unordered_102005065.md diff --git a/tasks/euclid_dr1_prelim/ordered_mge_witness_102005065.md b/archive/tasks/euclid_dr1_prelim/ordered_mge_witness_102005065.md similarity index 100% rename from tasks/euclid_dr1_prelim/ordered_mge_witness_102005065.md rename to archive/tasks/euclid_dr1_prelim/ordered_mge_witness_102005065.md diff --git a/tasks/euclid_dr1_prelim/ordered_rerun_catalogue_parity.md b/archive/tasks/euclid_dr1_prelim/ordered_rerun_catalogue_parity.md similarity index 100% rename from tasks/euclid_dr1_prelim/ordered_rerun_catalogue_parity.md rename to archive/tasks/euclid_dr1_prelim/ordered_rerun_catalogue_parity.md diff --git a/tasks/ic50_workspace/ep_scale_up.md b/archive/tasks/ic50_workspace/ep_scale_up.md similarity index 100% rename from tasks/ic50_workspace/ep_scale_up.md rename to archive/tasks/ic50_workspace/ep_scale_up.md diff --git a/tasks/inference_programme/cluster_extended_source_inference.md b/archive/tasks/inference_programme/cluster_extended_source_inference.md similarity index 100% rename from tasks/inference_programme/cluster_extended_source_inference.md rename to archive/tasks/inference_programme/cluster_extended_source_inference.md diff --git a/tasks/inference_programme/cluster_gradient_search_benchmark.md b/archive/tasks/inference_programme/cluster_gradient_search_benchmark.md similarity index 100% rename from tasks/inference_programme/cluster_gradient_search_benchmark.md rename to archive/tasks/inference_programme/cluster_gradient_search_benchmark.md diff --git a/tasks/inference_programme/delaunay_fp64_retro_baseline.md b/archive/tasks/inference_programme/delaunay_fp64_retro_baseline.md similarity index 100% rename from tasks/inference_programme/delaunay_fp64_retro_baseline.md rename to archive/tasks/inference_programme/delaunay_fp64_retro_baseline.md diff --git a/tasks/inference_programme/failed_submissions_342008_10.md b/archive/tasks/inference_programme/failed_submissions_342008_10.md similarity index 100% rename from tasks/inference_programme/failed_submissions_342008_10.md rename to archive/tasks/inference_programme/failed_submissions_342008_10.md diff --git a/tasks/inference_programme/inference_refs_v1_redo.md b/archive/tasks/inference_programme/inference_refs_v1_redo.md similarity index 100% rename from tasks/inference_programme/inference_refs_v1_redo.md rename to archive/tasks/inference_programme/inference_refs_v1_redo.md diff --git a/tasks/inference_programme/knn_rerun_342016_7.md b/archive/tasks/inference_programme/knn_rerun_342016_7.md similarity index 100% rename from tasks/inference_programme/knn_rerun_342016_7.md rename to archive/tasks/inference_programme/knn_rerun_342016_7.md diff --git a/tasks/inference_programme/legacy_point_output_sweep.md b/archive/tasks/inference_programme/legacy_point_output_sweep.md similarity index 100% rename from tasks/inference_programme/legacy_point_output_sweep.md rename to archive/tasks/inference_programme/legacy_point_output_sweep.md diff --git a/tasks/inference_programme/likelihood_term_levers.md b/archive/tasks/inference_programme/likelihood_term_levers.md similarity index 100% rename from tasks/inference_programme/likelihood_term_levers.md rename to archive/tasks/inference_programme/likelihood_term_levers.md diff --git a/tasks/inference_programme/mass_pix_gradient_cost_probe.md b/archive/tasks/inference_programme/mass_pix_gradient_cost_probe.md similarity index 100% rename from tasks/inference_programme/mass_pix_gradient_cost_probe.md rename to archive/tasks/inference_programme/mass_pix_gradient_cost_probe.md diff --git a/tasks/inference_programme/mge_fp64_retro_baseline.md b/archive/tasks/inference_programme/mge_fp64_retro_baseline.md similarity index 100% rename from tasks/inference_programme/mge_fp64_retro_baseline.md rename to archive/tasks/inference_programme/mge_fp64_retro_baseline.md diff --git a/tasks/inference_programme/mge_pos_ref_reuse.md b/archive/tasks/inference_programme/mge_pos_ref_reuse.md similarity index 100% rename from tasks/inference_programme/mge_pos_ref_reuse.md rename to archive/tasks/inference_programme/mge_pos_ref_reuse.md diff --git a/tasks/inference_programme/multiband_compile_census_completion.md b/archive/tasks/inference_programme/multiband_compile_census_completion.md similarity index 100% rename from tasks/inference_programme/multiband_compile_census_completion.md rename to archive/tasks/inference_programme/multiband_compile_census_completion.md diff --git a/tasks/inference_programme/nautilus_mass_pix_baseline.md b/archive/tasks/inference_programme/nautilus_mass_pix_baseline.md similarity index 100% rename from tasks/inference_programme/nautilus_mass_pix_baseline.md rename to archive/tasks/inference_programme/nautilus_mass_pix_baseline.md diff --git a/tasks/inference_programme/phase2_nss_mainline_gate_a_reuse.md b/archive/tasks/inference_programme/phase2_nss_mainline_gate_a_reuse.md similarity index 100% rename from tasks/inference_programme/phase2_nss_mainline_gate_a_reuse.md rename to archive/tasks/inference_programme/phase2_nss_mainline_gate_a_reuse.md diff --git a/tasks/inference_programme/phase3_prodigy_reliability_gate_b1_reuse.md b/archive/tasks/inference_programme/phase3_prodigy_reliability_gate_b1_reuse.md similarity index 100% rename from tasks/inference_programme/phase3_prodigy_reliability_gate_b1_reuse.md rename to archive/tasks/inference_programme/phase3_prodigy_reliability_gate_b1_reuse.md diff --git a/tasks/inference_programme/phase4_positions_gate_b2_reuse.md b/archive/tasks/inference_programme/phase4_positions_gate_b2_reuse.md similarity index 100% rename from tasks/inference_programme/phase4_positions_gate_b2_reuse.md rename to archive/tasks/inference_programme/phase4_positions_gate_b2_reuse.md diff --git a/tasks/inference_programme/phase5_mesh_gradient_positions_on.md b/archive/tasks/inference_programme/phase5_mesh_gradient_positions_on.md similarity index 100% rename from tasks/inference_programme/phase5_mesh_gradient_positions_on.md rename to archive/tasks/inference_programme/phase5_mesh_gradient_positions_on.md diff --git a/tasks/inference_programme/prodigy_mass_pix.md b/archive/tasks/inference_programme/prodigy_mass_pix.md similarity index 100% rename from tasks/inference_programme/prodigy_mass_pix.md rename to archive/tasks/inference_programme/prodigy_mass_pix.md diff --git a/tasks/inference_programme/refs_5_6_342016_56.md b/archive/tasks/inference_programme/refs_5_6_342016_56.md similarity index 100% rename from tasks/inference_programme/refs_5_6_342016_56.md rename to archive/tasks/inference_programme/refs_5_6_342016_56.md diff --git a/tasks/inference_programme/refs_v1_positions_on_completion.md b/archive/tasks/inference_programme/refs_v1_positions_on_completion.md similarity index 100% rename from tasks/inference_programme/refs_v1_positions_on_completion.md rename to archive/tasks/inference_programme/refs_v1_positions_on_completion.md diff --git a/tasks/inference_programme/rewind_2026_08_31.md b/archive/tasks/inference_programme/rewind_2026_08_31.md similarity index 100% rename from tasks/inference_programme/rewind_2026_08_31.md rename to archive/tasks/inference_programme/rewind_2026_08_31.md diff --git a/tasks/inference_programme/slogdet_ab_342017.md b/archive/tasks/inference_programme/slogdet_ab_342017.md similarity index 100% rename from tasks/inference_programme/slogdet_ab_342017.md rename to archive/tasks/inference_programme/slogdet_ab_342017.md diff --git a/tasks/inference_programme/smc_probe_342018.md b/archive/tasks/inference_programme/smc_probe_342018.md similarity index 100% rename from tasks/inference_programme/smc_probe_342018.md rename to archive/tasks/inference_programme/smc_probe_342018.md diff --git a/tasks/slope_hierarchy/methods_writeup.md b/archive/tasks/slope_hierarchy/methods_writeup.md similarity index 100% rename from tasks/slope_hierarchy/methods_writeup.md rename to archive/tasks/slope_hierarchy/methods_writeup.md diff --git a/tasks/slope_hierarchy_scale/n25_scale_up.md b/archive/tasks/slope_hierarchy_scale/n25_scale_up.md similarity index 100% rename from tasks/slope_hierarchy_scale/n25_scale_up.md rename to archive/tasks/slope_hierarchy_scale/n25_scale_up.md diff --git a/tasks/subhalo_validation/delaunay_adapt_split_pl_eff_0.md b/archive/tasks/subhalo_validation/delaunay_adapt_split_pl_eff_0.md similarity index 100% rename from tasks/subhalo_validation/delaunay_adapt_split_pl_eff_0.md rename to archive/tasks/subhalo_validation/delaunay_adapt_split_pl_eff_0.md diff --git a/tasks/subhalo_validation/delaunay_adapt_split_pl_eff_1_outer.md b/archive/tasks/subhalo_validation/delaunay_adapt_split_pl_eff_1_outer.md similarity index 100% rename from tasks/subhalo_validation/delaunay_adapt_split_pl_eff_1_outer.md rename to archive/tasks/subhalo_validation/delaunay_adapt_split_pl_eff_1_outer.md diff --git a/tasks/subhalo_validation/delaunay_adapt_split_pl_sersic_0.md b/archive/tasks/subhalo_validation/delaunay_adapt_split_pl_sersic_0.md similarity index 100% rename from tasks/subhalo_validation/delaunay_adapt_split_pl_sersic_0.md rename to archive/tasks/subhalo_validation/delaunay_adapt_split_pl_sersic_0.md diff --git a/tasks/subhalo_validation/rectangular_adapt_pl_eff_0.md b/archive/tasks/subhalo_validation/rectangular_adapt_pl_eff_0.md similarity index 100% rename from tasks/subhalo_validation/rectangular_adapt_pl_eff_0.md rename to archive/tasks/subhalo_validation/rectangular_adapt_pl_eff_0.md diff --git a/tasks/subhalo_validation/rectangular_adapt_pl_eff_1_outer.md b/archive/tasks/subhalo_validation/rectangular_adapt_pl_eff_1_outer.md similarity index 100% rename from tasks/subhalo_validation/rectangular_adapt_pl_eff_1_outer.md rename to archive/tasks/subhalo_validation/rectangular_adapt_pl_eff_1_outer.md diff --git a/tasks/subhalo_validation/rectangular_adapt_pl_sersic_0.md b/archive/tasks/subhalo_validation/rectangular_adapt_pl_sersic_0.md similarity index 100% rename from tasks/subhalo_validation/rectangular_adapt_pl_sersic_0.md rename to archive/tasks/subhalo_validation/rectangular_adapt_pl_sersic_0.md diff --git a/dashboard.html b/dashboard.html index 3be4411..1f51b16 100644 --- a/dashboard.html +++ b/dashboard.html @@ -4,7 +4,7 @@ <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>PyAutoCortex Dashboard - + +.fresh{padding:.1rem .9rem;margin:1.2rem 0;background:var(--tint)}.fresh p{margin:.5rem 0}table.map{width:100%;border-collapse:collapse;font-size:.95em}table.map th{text-align:left;color:var(--muted);font-weight:600}table.map td,table.map th{border-bottom:1px solid var(--line);padding:.4rem .5rem .4rem 0;vertical-align:top}.checkin{display:flex;gap:.9rem;align-items:center;padding:.9rem 1.2rem;border:2px solid var(--line);border-radius:.6rem;margin:.2rem 0 1.4rem}.checkin .mark{font-size:2rem;line-height:1}.checkin .label{display:block;font-size:.75rem;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}.checkin time{font-size:1.6rem;font-weight:700;font-variant-numeric:tabular-nums;display:block}.checkin .note{font-size:.85rem;color:var(--muted)}.checkin.fresh-ok{border-color:var(--ok);background:color-mix(in srgb,var(--ok) 12%,transparent)}.checkin.fresh-ok .mark{color:var(--ok)}.checkin.fresh-bad{border-color:var(--bad);background:color-mix(in srgb,var(--bad) 12%,transparent)}.checkin.fresh-bad .mark{color:var(--bad)}.project h3{font-size:1.35rem;font-weight:700;padding-bottom:.2rem;border-bottom:2px solid var(--accent);letter-spacing:.01em;margin-top:1.6rem}.pathchip{display:inline-block;background:var(--accent);color:#fff;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.88em;padding:.12em .5em;border-radius:.3rem;overflow-wrap:anywhere}@media(prefers-color-scheme:dark){.pathchip{background:color-mix(in srgb,var(--accent) 55%,#000)}}.stale{color:var(--bad);font-weight:600} -

PyAutoCortexDashboard

Question. Run. Rule.

Every science task the Cortex is holding, one line each under its project. Tap a task's 📋 and its next command is on your clipboard. The verdict is always yours — this page hands you the command, never the ruling.

-
  • 1Awaiting ruling
  • 37Recent rulings
-

Last updated 2026-09-11.

+

PyAutoCortexDashboard

Question. Run. Rule.

One ledger per science project: what is on the cluster right now, what the human said they would do next, and the last few things they wrote down. Nothing here is inferred from a result — the board hands you the check-in and the resume prompt; what a run meant is yours to log.

+
  • 1Running
  • 17Open
  • 7Projects
+

Last updated 2026-09-12.

markdown version · GitHub Page

-

check in since last time

+

check in since last time

Last check-in

Summary

-

One row per active project — the next thing, what it is holding, and when it last ruled.

- - - - - - - - + + + + + + + +
ProjectNext taskAwaitingRunningLast ruling
analytic_gaussianIs criterion 2's mu threshold or the minimal-EP control wrong002026-09-10
autolens_inferenceDo six backend legs agree on the HST SLaM posterior?00-
ep_toy_gaussianDo three EP fits agree with NUTS at N=5001-
euclid_dr1_prelimDo ordered Nautilus reruns reproduce the euclid catalogue values?102026-09-10
ic50_workspaceDoes EP match the graphical joint fit end to end01-
slope_hierarchy_scaleDoes hierarchical slope recovery hold at N=25 to 5001-
subhalo_validationDoes rectangular_adapt false-detect a subhalo on the clumpy source052026-09-07
ProjectRunningOpenLast update
subhalo_validation052026-09-07
euclid_dr1_prelim122026-09-11
analytic_gaussian002026-09-10
ep_toy_gaussian022026-09-10
slope_hierarchy_scale042026-09-09
ic50_workspace042026-09-09
autolens_inference002026-09-11
-

Nothing open

- - - - - - - - -
ProjectStatusTasksRetire
concrdormantnone
cowls_dianadormantnone
eucliddormantplanned 3
pj011646dormantnone
profilingdormantnone
subhalo_simulationsdormantnone
-
2 retired
    -
  • inference_programme — retired 2026-09-07: restarting from scratch: the project setup was unsatisfactory and it informed how the Cortex manages projects; RAL outputs stashed at /mnt/ral/jnightin/inference_programme_retired_2026-09-07
  • -
  • slope_hierarchy — retired 2026-09-08: wrapped up 2026-07-22 at N=5; succeeded by slope_hierarchy_scale; tree vaulted under z_projects_complete/
  • -
-

Projects markdown version

+

Projects

-

analytic_gaussian

-

Local /mnt/c/Users/Jammy/Science/analytic_gaussian

-

RAL /mnt/ral/jnightin/analytic_gaussian

-

active · ral partition · tasks: accepted 1 · planned 1

- -

tasks/analytic_gaussian/

+

subhalo_validation — Do the SLaM subhalo pipelines false-detect on lenses with no subhalo

+

active · ral · subhalo_validation#2 · projects/subhalo_validation.md · local /mnt/c/Users/Jammy/Science/subhalo_validation · RAL /mnt/ral/jnightin/subhalo_validation

+

Now

+

Five chains on RAL under the corrected adapt settings: rectangular_adapt on pl_eff_0 / pl_eff_1_outer (job A done, job B 342311 submitted) and the delaunay_adapt_split reruns plus rectangular_adapt on pl_sersic_0. pl_sersic_0 on delaunay_adapt_split is accepted (no false detection, +2.557).
Next: pull when the numba chains land and read the evidence_increase of each; no more 1000-pixel runs.

+

Runs

+
    +
  • 342299_1 — open — ral — 2026-09-07 — delaunay_adapt_split_pl_eff_0: job B, numba chain at the standard 1250-pixel Delaunay mesh (8c / 96gb / 48 h); reloads job A 342231_1; the 09-07 ruling: run al…
  • +
  • 342299_2 — open — ral — 2026-09-07 — delaunay_adapt_split_pl_eff_1_outer: job B, numba chain at the standard 1250-pixel Delaunay mesh (8c / 96gb / 48 h); reloads job A 342231_2; the 09-07 ruling:…
  • +
  • 342311_1 — open — ral — 2026-09-07 — rectangular_adapt_pl_eff_0: job B, numba chain (8c / 96gb / 48 h) at the standard 1250-pixel mesh under PIPELINE=rectangular_adapt; reloads job A 342237_1; the…
  • +
  • 342311_2 — open — ral — 2026-09-07 — rectangular_adapt_pl_eff_1_outer: job B, numba chain (8c / 96gb / 48 h) at the standard 1250-pixel mesh under PIPELINE=rectangular_adapt; reloads job A 342237_…
  • +
  • 342311_0 — open — ral — 2026-09-07 — rectangular_adapt_pl_sersic_0: job B, numba chain (8c / 96gb / 48 h) at the standard 1250-pixel mesh under PIPELINE=rectangular_adapt; reloads job A 342237_0;…
  • +
+

Last 5

+
    +
  • 2026-09-07 — result — accepted delaunay_adapt_split_pl_sersic_0 (R-20260907-01): Accepted. The numba delaunay_adapt_split chain on pl_sersic_0 (job 342273_0, 22 h 08 m, 1250 Hilbert / 1310 Delaunay pixels) lands evidence_increase +2.557 (< 5): no false detectio…
  • +
  • 2026-09-07 — run — 342311_0 submitted: rectangular_adapt_pl_sersic_0 — job B, numba chain (8c / 96gb / 48 h) at the standard 1250-pixel mesh under PIPELINE=rectangular_adapt; reloads job A 342237_0; the 09-07 ask: submit the rectangular runs too
  • +
  • 2026-09-07 — run — 342311_2 submitted: rectangular_adapt_pl_eff_1_outer — job B, numba chain (8c / 96gb / 48 h) at the standard 1250-pixel mesh under PIPELINE=rectangular_adapt; reloads job A 342237_2; the 09-07 ask: submit the rectangular runs too
  • +
  • 2026-09-07 — run — 342311_1 submitted: rectangular_adapt_pl_eff_0 — job B, numba chain (8c / 96gb / 48 h) at the standard 1250-pixel mesh under PIPELINE=rectangular_adapt; reloads job A 342237_1; the 09-07 ask: submit the rectangular runs too
  • +
  • 2026-09-07 — run — 342299_2 submitted: delaunay_adapt_split_pl_eff_1_outer — job B, numba chain at the standard 1250-pixel Delaunay mesh (8c / 96gb / 48 h); reloads job A 342231_2; the 09-07 ruling: run all datasets at 1250, no more pix1000
  • +
+

full log

+

resume subhalo_validation

-

autolens_inference

-

Local /home/jammy/Code/PyAutoLabs/autolens_inference

-

RAL /mnt/ral/jnightin/autolens_inference

-

active · both partition · tasks: ready 1

- -

tasks/autolens_inference/ · issues

+

euclid_dr1_prelim — Refit the ten DR1-prelim tiles and rebuild the catalogue on RAL

+

active · both · PyAutoCortex#35 · projects/euclid_dr1_prelim.md · local /mnt/c/Users/Jammy/Science/euclid_dr1_prelim · RAL /mnt/ral/jnightin/euclid_dr1_prelim

+

Now

+

342629 reran the ten tiles on refreshed libraries; eight finished and confirmed all four 09-10 defects fixed, tiles 1 and 3 are still in vis_lp. The SED chain ran on GPU for the eight (342648) and the CPU verification on tile 9 (342668_9) passed in 9:24, faster than the GPU — the CPU route is the one the main experiment uses.
Next: pull, bundle with output_sed, compare magnitudes (µJy fluxes) against the 20260623 catalogue; then tiles 1/3 SED on the CPU script. The parity clause needs restating: rerun scatter, not ordering, is what fails it.

+

Runs

+
    +
  • 342629_[0-9] — running — ral — 2026-09-10 — ordered_rerun_catalogue_parity: two-stage vis_lp(n_live=750)+vis_pix(n_live=300), array 0-9, ten dr1_prelim tiles; libraries refreshed BEFORE submit (PyAutoNer…
  • +
  • 342648_[0,2,4-9] — open — gpu — 2026-09-11 — ordered_rerun_catalogue_parity: SED chain `hpc/batch_gpu/submit_sersic_waveband_8tiles` (a copy of `submit_sersic_waveband` differing only in `--array=0,2,4-9`…
  • +
  • 342668_9 — open — ral — 2026-09-11 — ordered_rerun_catalogue_parity: CPU verification of the SED chain via hpc/batch_cpu/submit_sersic_waveband (pipeline PR #70, sbatch --array=9): tile 102008848,…
  • +
+

Last 5

+
    +
  • 2026-09-11 — note — **CPU verification PASSED and was faster than the GPU.** `342668_9` (ral, 8 CPU, JAX on the CPU backend) COMPLETED in **9:24** wall, exit 0, all eight `sersic_lens_model/{vis,nir_y,nir_j,nir_h,decam_g,decam_r,decam_i,decam_z}` searches wri…
  • +
  • 2026-09-11 — note — **342629 scored on the eight tiles that finished; all four 09-10 defects confirmed fixed; parity fails on rerun scatter, not ordering.** `sacct`: tasks 0,2,4,5,6,7,8,9 COMPLETED (walls 5:45–9:42, MaxRSS 7.6–10.9 GB); tasks 1 (`Tile10200729…
  • +
  • 2026-09-11 — run — 342668_9 submitted: ordered_rerun_catalogue_parity — CPU verification of the SED chain via hpc/batch_cpu/submit_sersic_waveband (pipeline PR #70, sbatch --array=9): tile 102008848, JAX on the CPU backend, 8 CPU; same seeded vis_lp zip as t…
  • +
  • 2026-09-11 — run — 342648_[0,2,4-9] submitted: ordered_rerun_catalogue_parity — SED chain `hpc/batch_gpu/submit_sersic_waveband_8tiles` (a copy of `submit_sersic_waveband` differing only in `--array=0,2,4-9`, because `hpc/sync submit` passes no sbatch argume…
  • +
  • 2026-09-10 — result — accepted dr1_prelim_10_lens_science_run (R-20260910-03): For euclid_dr1_prelim, I am content these 3 are success so wrap them up and then do the 4th task on the catalogue stuff
  • +
+

full log

+

resume euclid_dr1_prelim

-

ep_toy_gaussian

-

Local /mnt/c/Users/Jammy/Science/ep_toy_gaussian

-

RAL /mnt/ral/jnightin/ep_toy_gaussian

-

active · ral partition · tasks: submitted 1

-

Do three EP fits agree with NUTS at N=50submitted — runs 342639, 342640 · wall 0:00 of 24:00 (0%)

-

tasks/ep_toy_gaussian/ · issues

+

analytic_gaussian — Graphical and EP against a closed-form Gaussian posterior, at ensemble scale

+

active · ral · PyAutoCortex#34 · projects/analytic_gaussian.md · local /mnt/c/Users/Jammy/Science/analytic_gaussian · RAL /mnt/ral/jnightin/analytic_gaussian

+

Now

+

Wave 1 (342413, 200 seeds at N=5) is accepted as the baseline: autofit EP is exact on the Gaussian leg, leg B sigma misses as pre-registered (78/200), collapse rate 0/200. Follow-ups filed through /intake.
Next: settle whether criterion 2's mu threshold or the minimal-EP control is wrong before any rerun; the N=25 rung is written but not submitted.

+

Runs

+

nothing on the cluster

+

Last 5

+
    +
  • 2026-09-10 — result — accepted ensemble_parity (R-20260910-04): ok accept and intake the things to address. we can do another run down the line so also achieve the results in the analytic_gaussian project for future comparison
  • +
  • 2026-09-10 — note — question: Is criterion 2's mu threshold or the minimal-EP control wrong — planned, never run [archive/tasks/analytic_gaussian/minimal_ep_legb_mu_threshold.md]
  • +
  • 2026-09-09 — run — 342413_[0-199] submitted (done, wall 0:05): ensemble_parity — the N=5 seed ensemble, 200 seeds, 50 concurrent, `hpc/batch_cpu/submit_ensemble_n5`, sample `ens_n5`. RAL PyAuto mirror verified at PyAutoFit `66f9f8d5d` before submission, whic…
  • +
  • 2026-09-09 — note — question: Do graphical and EP recover closed-form means and errors [archive/tasks/analytic_gaussian/ensemble_parity.md]
  • +
+

full log

+

resume analytic_gaussian

-

euclid_dr1_prelim

-

Local /mnt/c/Users/Jammy/Science/euclid_dr1_prelim

-

RAL /mnt/ral/jnightin/euclid_dr1_prelim

-

active · both partition · tasks: accepted 3 · awaiting-ruling 1

- -

↳ the results are good — accept and open the next task

-

↳ run it again

-

tasks/euclid_dr1_prelim/

+

ep_toy_gaussian — NUTS versus three EP fits on the #1405 collapse toy at N=50

+

active · ral · ep_toy_gaussian#1 · projects/ep_toy_gaussian.md · local /mnt/c/Users/Jammy/Science/ep_toy_gaussian · RAL /mnt/ral/jnightin/ep_toy_gaussian

+

Now

+

n50_seed42 is on RAL: NUTS + one-by-one as 342639, EP x3 on identical data as 342640_[0-2]. The one-by-one leg finished (50/50 in 319 s); the EP repeats are turning per-factor Dynesty fits.
Next: pull and run scripts/compare.py --sample n50_seed42; settle first whether a prior factor with only NO_CHANGE rows counts as zero SUCCESS updates.

+

Runs

+
    +
  • 342639 — open — ral — 2026-09-10 — nuts_vs_ep_x3_n50: one_by_one + BlackJAX NUTS, partition ral
  • +
  • 342640 — open — ral — 2026-09-10 — nuts_vs_ep_x3_n50: EP x3 on identical data, array 0-2
  • +
+

Last 5

+
    +
  • 2026-09-10 — run — 342640 submitted: nuts_vs_ep_x3_n50 — EP x3 on identical data, array 0-2
  • +
  • 2026-09-10 — run — 342639 submitted: nuts_vs_ep_x3_n50 — one_by_one + BlackJAX NUTS, partition ral
  • +
  • 2026-09-10 — note — question: Do three EP fits agree with NUTS at N=50 [archive/tasks/ep_toy_gaussian/nuts_vs_ep_x3_n50.md]
  • +
+

full log

+

resume ep_toy_gaussian

-

ic50_workspace

-

Local /mnt/c/Users/Jammy/Science/ic50_workspace

-

RAL /mnt/ral/jnightin/ic50_workspace

-

active · ral partition · tasks: submitted 1

-

Does EP match the graphical joint fit end to endsubmitted — runs 342408, 342409, 342411, 342412 · wall 0:00 of 48:00 (0%)

-

tasks/ic50_workspace/ · issues

+

slope_hierarchy_scale — Hierarchical slope recovery with graphical and EP at N=25 to 50

+

active · both · slope_hierarchy_scale#2 · projects/slope_hierarchy_scale.md · local /mnt/c/Users/Jammy/Science/slope_hierarchy_scale · RAL /mnt/ral/jnightin/slope_hierarchy_scale

+

Now

+

The N=25 scale-up is running: graphical array 342348_[0-24], joint fits 342350_0 / 342351_0, and the EP rerun 342410 on the mirror that carries #1580.
Next: pull wave 1 and compare EP against the NUTS parent sigma; then decide whether to go to N=50.

+

Runs

+
    +
  • 342348_[0-24] — open — gpu — 2026-09-08 — n25_scale_up: one lens per array task, hpc/batch_gpu/submit_one_by_one, sample_n25_seed42
  • +
  • 342350_0 — open — gpu — 2026-09-08 — n25_scale_up: joint hierarchical NUTS fit, hpc/batch_gpu/submit_graphical
  • +
  • 342351_0 — open — ral — 2026-09-08 — n25_scale_up: EP arm on the CPU partition, hpc/batch_cpu/submit_ep, max_steps 12; RAL PyAutoFit mirror 68ff9bd57 predates PyAutoFit#1580, so this arm runs with…
  • +
  • 342410 — open — ral — 2026-09-09 — n25_scale_up: EP arm rerun on the JAX-on-CPU path (no multiprocessing pool); replaces 342351_0
  • +
+

Last 5

+
    +
  • 2026-09-09 — run — 342410 submitted: n25_scale_up — EP arm rerun on the JAX-on-CPU path (no multiprocessing pool); replaces 342351_0
  • +
  • 2026-09-08 — run — 342351_0 submitted: n25_scale_up — EP arm on the CPU partition, hpc/batch_cpu/submit_ep, max_steps 12; RAL PyAutoFit mirror 68ff9bd57 predates PyAutoFit#1580, so this arm runs without the stale-mask fixed-point fix
  • +
  • 2026-09-08 — run — 342350_0 submitted: n25_scale_up — joint hierarchical NUTS fit, hpc/batch_gpu/submit_graphical
  • +
  • 2026-09-08 — run — 342348_[0-24] submitted: n25_scale_up — one lens per array task, hpc/batch_gpu/submit_one_by_one, sample_n25_seed42
  • +
  • 2026-07-22 — note — question: Does hierarchical slope recovery hold at N=25 to 50 [archive/tasks/slope_hierarchy_scale/n25_scale_up.md]
  • +
+

full log

+

resume slope_hierarchy_scale

-

slope_hierarchy_scale

-

Local /mnt/c/Users/Jammy/Science/slope_hierarchy_scale

-

RAL /mnt/ral/jnightin/slope_hierarchy_scale

-

active · both partition · tasks: running 1

-

Does hierarchical slope recovery hold at N=25 to 50running — runs 342348_[0-24], 342350_0, 342351_0, 342410 · wall 0:00 of 48:00 (0%)

-

tasks/slope_hierarchy_scale/ · issues

+

ic50_workspace — EP against the graphical joint fit on IC50 dose-response data, scaling up

+

active · ral · PyAutoCortex#36 · projects/ic50_workspace.md · local /mnt/c/Users/Jammy/Science/ic50_workspace · RAL /mnt/ral/jnightin/ic50_workspace

+

Now

+

Parity at N=5 achieved on RAL (33/33 within 3σ for both methods, runs 342408 / 342409); the scale ladder runs 342411 and 342412 are submitted.
Next: pull the ladder and see where EP's cost and hill_coef width go as N grows; ep_lbfgs_jax is the scale lever.

+

Runs

+
    +
  • 342408 — open — ral — 2026-09-09 — ep_scale_up: EP sim, nlive 150, max_steps 12
  • +
  • 342409 — open — ral — 2026-09-09 — ep_scale_up: graphical sim joint Dynesty, nlive 150
  • +
  • 342411 — open — ral — 2026-09-09 — ep_scale_up: EP scale ladder, sim rungs 5/10/25/50, nlive 150 max_steps 12
  • +
  • 342412 — open — ral — 2026-09-09 — ep_scale_up: graphical scale ladder, sim rungs 5/10/25/50, nlive 150
  • +
+

Last 5

+
    +
  • 2026-09-09 — run — 342412 submitted: ep_scale_up — graphical scale ladder, sim rungs 5/10/25/50, nlive 150
  • +
  • 2026-09-09 — run — 342411 submitted: ep_scale_up — EP scale ladder, sim rungs 5/10/25/50, nlive 150 max_steps 12
  • +
  • 2026-09-09 — run — 342409 submitted: ep_scale_up — graphical sim joint Dynesty, nlive 150
  • +
  • 2026-09-09 — run — 342408 submitted: ep_scale_up — EP sim, nlive 150, max_steps 12
  • +
  • 2026-08-19 — note — question: Does EP match the graphical joint fit end to end [archive/tasks/ic50_workspace/ep_scale_up.md]
  • +
+

full log

+

resume ic50_workspace

-

subhalo_validation

-

Local /mnt/c/Users/Jammy/Science/subhalo_validation

-

RAL /mnt/ral/jnightin/subhalo_validation

-

active · ral partition · tasks: accepted 1 · running 2 · submitted 3

-

Does rectangular_adapt false-detect a subhalo on the clumpy sourcerunning — runs 342237_1, 342240_1, 342311_1 · wall 1:52 of 48:00 (4%) · ⚠️ failed runs: 342240_1

-

Does rectangular_adapt false-detect a subhalo on the outer-component lensrunning — runs 342237_2, 342240_2, 342311_2 · wall 1:52 of 48:00 (4%) · ⚠️ failed runs: 342240_2

-

Does delaunay_adapt_split false-detect a subhalo on the clumpy sourcesubmitted — runs 342027_1, 342231_1, 342234_1, 342299_1 · wall 45:10 of 48:00 (94%) · ⚠️ failed runs: 342234_1

-

Does delaunay_adapt_split false-detect on the outer-component lens and AdaptSplit fixsubmitted — runs 342027_2, 342093_0, 342231_2, 342234_2, 342299_2 · wall 47:05 of 48:00 (98%) · ⚠️ failed runs: 342234_2

-

Does rectangular_adapt behave like delaunay_adapt_split on the clean nullsubmitted — runs 342094_0, 342095_0, 342237_0, 342240_0, 342311_0 · wall 18:01 of 48:00 (38%) · ⚠️ failed runs: 342240_0

-

tasks/subhalo_validation/ · issues

+

autolens_inference — Do the PyAutoLens inference backends agree on the HST SLaM posterior

+

active · both · autolens_inference#4 · projects/autolens_inference.md · local /home/jammy/Code/PyAutoLabs/autolens_inference · RAL /mnt/ral/jnightin/autolens_inference

+

Now

+

Born 2026-09-10 as the from-scratch restart of inference_programme; slam_hst_base is the first question and is ready to submit — nothing has run yet.
Next: hpc/sync submit the six backend legs on the HST SLaM dataset and record the job ids here.

+

Runs

+

nothing on the cluster

+

Last 5

+
    +
  • 2026-09-11 — note — question: Do six backend legs agree on the HST SLaM posterior? — ready, never run [archive/tasks/autolens_inference/slam_hst_base.md]
  • +
+

full log

+

resume autolens_inference

-

Awaiting ruling markdown version

Results are in and nothing is running — the human's verdict is the only thing outstanding. Ordered failures first, then the tasks a ruling is required for, then the clean ones.

- -

↳ the results are good — accept and open the next task

-

↳ run it again

-

Recent rulings markdown version

The ledger of record, newest first. A verdict recorded only outside the Cortex does not exist.

+
+

euclid — The original Euclid DR1 grade-AB catalogue project, superseded by euclid_dr1_prelim

+

dormant · both · no issue yet · projects/euclid.md · local /mnt/c/Users/Jammy/Science/euclid · RAL /mnt/ral/jnightin/euclid_strong_lens_modeling_pipeline

+

Now

+

Dormant since 2026-09-07: superseded by euclid_dr1_prelim. Three questions were planned and never run (see the archive).

+

Runs

+

nothing on the cluster

+

Last 5

+
    +
  • 2026-08-28 — note — question: Do we recover Sersic indices or is prior pile-up artefact — planned, never run [archive/tasks/euclid/sersic_index_recovery.md]
  • +
  • 2026-08-28 — note — question: Can a fitted Euclid lens be resimulated and recovered — planned, never run [archive/tasks/euclid/resimulate_fitted_lens_simulator.md]
  • +
  • 2026-08-28 — note — question: How robust are magnification estimates under model match and mismatch — planned, never run [archive/tasks/euclid/magnification_robustness.md]
  • +
+

full log

+
+
2 retired
    +
  • inference_programme — The first inference programme, retired and restarted as autolens_inference — retired 2026-09-07: restarting from scratch: the project setup was unsatisfactory and it informed how the Cortex manages projects; RAL outputs stashed at /mnt/ral/jnightin/inference_programme_retired_2026-09-07
  • +
  • slope_hierarchy — Hierarchical slope recovery at N=5, wrapped up and succeeded by slope_hierarchy_scale — retired 2026-09-08: wrapped up 2026-07-22 at N=5; succeeded by slope_hierarchy_scale; tree vaulted under z_projects_complete/
  • +
+

No ledger

- - - - - - - - - - - - - + + + + + +
RulingVerbTaskBatch
R-20260910-04accepttasks/analytic_gaussian/ensemble_parity.md-
R-20260910-03accepttasks/euclid_dr1_prelim/dr1_prelim_10_lens_science_run.md-
R-20260910-02accepttasks/euclid_dr1_prelim/ordered_mge_control_unordered_102005065.md-
R-20260910-01accepttasks/euclid_dr1_prelim/ordered_mge_witness_102005065.md-
R-20260907-06droptasks/inference_programme/legacy_point_output_sweep.md-
R-20260907-05droptasks/inference_programme/cluster_extended_source_inference.md-
R-20260907-04droptasks/inference_programme/likelihood_term_levers.md-
R-20260907-03droptasks/inference_programme/prodigy_mass_pix.md-
R-20260907-02droptasks/inference_programme/nautilus_mass_pix_baseline.md-
R-20260907-01accepttasks/subhalo_validation/delaunay_adapt_split_pl_sersic_0.md-
R-20260904-05droptasks/inference_programme/multiband_compile_census_completion.md-
R-20260904-04droptasks/inference_programme/mass_pix_gradient_cost_probe.md-
ProjectStatusNote
profilingdormant2026-05 checkpointed sweep harness, PyAutoNSS venv; name collides with autolens_profiling; ral_root planned, sync_verbs unverified
cowls_dianadormantlocal git, no remote; ral_root planned, sync_verbs unverified
subhalo_simulationsdormantgit init, zero commits, 21 GB; ral_root planned, sync_verbs unverified
pj011646dormantpersonal remote, recorded as a fact — not a PyAutoLabs repo; ral_root planned, sync_verbs unverified
concrdormantpersonal remote Jammy2211/cosmology_and_cancer, recorded as a fact; ral_root planned, sync_verbs unverified