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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,14 @@ listed here. A document PyYAML cannot read is reported as one problem.
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`, `witness_file` (glob), `partition`
`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.
Expand Down
14 changes: 14 additions & 0 deletions projects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
# sync_cli: <path> # the project's sync CLI, relative to local_path
# sync_verbs: [a, b, c] # the verbs that CLI has — a flow list of bare words, the only list
# ledger: <path> # the project's own commentary ledger, relative to local_path
# assistant: <name | none> # 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
# witness_file: <glob> # where a run's witness lands, relative to the mirror
# partition: gpu | ral | both # which SLURM partition(s) the project runs on
# status: active | dormant | planned | retired # `cortex.py retire` writes the last
Expand Down Expand Up @@ -50,6 +53,7 @@ inference_programme:
sync_cli: hpc/sync
sync_verbs: [pull, logs, status, submit, jobs, sacct, cancel, tail, du, check]
ledger: results/notes/inference/PROGRAMME.md
assistant: none
witness_file: results/searches/**/*.json
partition: both
status: retired
Expand All @@ -63,6 +67,7 @@ subhalo_validation:
sync_cli: hpc/sync
sync_verbs: [push, pull, logs, sync, push-data-init, pull-full, status, submit, push-submit, jobs, sacct, cancel, wait-and-pull, tail, du, check, clear-logs]
ledger: wiki/project/state.md
assistant: autolens_assistant
witness_file: results/**/*.json
partition: ral
status: active
Expand All @@ -76,6 +81,7 @@ euclid:
sync_cli: hpc/sync
sync_verbs: [push, pull, sync, status]
ledger: CLAUDE.md
assistant: none
witness_file: catalogue/**/*.csv
partition: both
status: dormant
Expand All @@ -89,6 +95,7 @@ euclid_dr1_prelim:
sync_cli: hpc/sync
sync_verbs: [push, pull, sync, status]
ledger: wiki/project/state.md
assistant: autolens_assistant
witness_file: results/**/*.json
partition: both
status: active
Expand All @@ -108,6 +115,7 @@ profiling:
sync_cli: hpc/sync
sync_verbs: [pull]
ledger: README.md
assistant: none
witness_file: results/**/*.json
partition: both
status: dormant
Expand All @@ -121,6 +129,7 @@ cowls_diana:
sync_cli: hpc/sync
sync_verbs: [pull]
ledger: README.md
assistant: none
witness_file: results/**/*.json
partition: both
status: dormant
Expand All @@ -134,6 +143,7 @@ subhalo_simulations:
sync_cli: hpc/sync
sync_verbs: [pull]
ledger: README.md
assistant: none
witness_file: results/**/*.json
partition: both
status: dormant
Expand All @@ -147,6 +157,7 @@ slope_hierarchy:
sync_cli: hpc/sync
sync_verbs: [pull]
ledger: README.md
assistant: none
witness_file: results/**/*.json
partition: both
status: dormant
Expand All @@ -160,6 +171,7 @@ pj011646:
sync_cli: hpc/sync
sync_verbs: [pull]
ledger: README.md
assistant: none
witness_file: results/**/*.json
partition: both
status: dormant
Expand All @@ -173,6 +185,7 @@ concr:
sync_cli: hpc/sync
sync_verbs: [pull]
ledger: README.md
assistant: none
witness_file: results/**/*.json
partition: both
status: dormant
Expand All @@ -186,6 +199,7 @@ ic50_workspace:
sync_cli: hpc/sync
sync_verbs: [pull]
ledger: README.md
assistant: none
witness_file: results/**/*.json
partition: both
status: dormant
Expand Down
7 changes: 6 additions & 1 deletion scripts/cortex.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@
RULING_SECTIONS = ("Ruling", "Evidence")

PROJECT_FIELDS = ("remote", "local_path", "ral_root", "mirror", "sync_cli",
"sync_verbs", "ledger", "witness_file", "partition", "status")
"sync_verbs", "ledger", "assistant", "witness_file", "partition",
"status")
#: the one optional field — free text about the row (why a remote is `none`,
#: what a verb does). A row may omit it; an empty `note:` is still drift, and
#: any field outside these two tuples is still an error.
Expand Down Expand Up @@ -367,6 +368,10 @@ def _finish_row(key: str, row: dict, problems: "list[str]") -> None:
problems.append(f"projects.yaml: {key}.{f} must be an absolute path")
if row.get("mirror") and row["mirror"] != "none" and not row["mirror"].startswith("/"):
problems.append(f"projects.yaml: {key}.mirror must be an absolute path or none")
assistant = row.get("assistant")
if assistant and assistant != "none" and not re.match(r"^[A-Za-z0-9_.-]+$", assistant):
problems.append(f"projects.yaml: {key}.assistant must be 'none' or a bare "
f"workspace-relative directory name (got {assistant!r})")


def load_projects(root: Path) -> "tuple[dict[str, dict], list[str]]":
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/skeleton/projects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ example:
sync_cli: hpc/sync
sync_verbs: [pull, submit, jobs, tail]
ledger: wiki/project/state.md
assistant: none
witness_file: output/**/checkpoint.hdf5
partition: gpu
status: active
25 changes: 25 additions & 0 deletions tests/test_cortex.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ def test_the_live_body_map_parses_clean():
assert rows["euclid_dr1_prelim"]["status"] == "active"
assert rows["euclid"]["remote"] == "none"
assert "PyAutoLabs remote" in rows["euclid"]["note"]
assert rows["subhalo_validation"]["assistant"] == "autolens_assistant"
assert rows["inference_programme"]["assistant"] == "none"


def test_a_block_list_and_a_quoted_scalar_are_ordinary_yaml(tmp_path):
Expand Down Expand Up @@ -279,6 +281,29 @@ def test_note_is_optional_but_never_empty_and_the_field_set_still_closes(tmp_pat
_assert_drift(root, "example.note is empty")


def test_assistant_is_required_and_names_a_bare_workspace_directory(tmp_path):
"""`assistant` is required like every field but `note`. Its value is
exactly `none` or a bare workspace-relative directory name — the Cortex
names the assistant, it never reads it, so no path and no stat."""
root = _copy(tmp_path)
assert _problems(root) == [], "the fixture carries `assistant: none`"
_edit(root, "projects.yaml", " assistant: none\n",
" assistant: autolens_assistant\n")
assert _problems(root) == []
rows, problems = cortex.parse_projects((root / "projects.yaml").read_text())
assert problems == [] and rows["example"]["assistant"] == "autolens_assistant"
_edit(root, "projects.yaml", " assistant: autolens_assistant\n",
" assistant:\n")
_assert_drift(root, "example.assistant is empty")
_edit(root, "projects.yaml", " assistant:\n", "")
_assert_drift(root, "example is missing assistant")
for bad in ("../autolens_assistant", "/home/jammy/Code/PyAutoLabs/autolens_assistant"):
root = _copy(tmp_path / bad.replace("/", "_"))
_edit(root, "projects.yaml", " assistant: none\n", f" assistant: {bad}\n")
_assert_drift(root, "example.assistant must be 'none' or a bare "
"workspace-relative directory name")


# --------------------------------------------------------------------------- #
# retire
# --------------------------------------------------------------------------- #
Expand Down
Loading