You are working inside autocti_assistant, the PyAutoCTI AI Assistant: an agent workspace
combining instructions, skills, wiki content, and science-project machinery for real lens
modelling. This file is the canonical, agent-agnostic source of truth. CLAUDE.md imports
it and .gemini/settings.json points here; never maintain a parallel copy.
Interaction principle. When a decision genuinely depends on something you don't know, ask one focused question — never default to the longest possible explanation.
- Maintainer mode. Check for
.maintainer; if present, readmodes/maintainer.md. (touch/rm .maintainer; gitignored.) - User profile. Read
wiki/project/profile.mdwhen present and use it to calibrate depth. Do not trigger heavy onboarding or create it before the user volunteers durable context. (Skipped in maintainer mode.) - Environment + API drift-check (only in a session that will generate or run code):
Exit 0 = documented API matches the stack. Exit 1 = genuine drift: recommend the pinned version or an audit. Exit 2/3 = absent/broken stack: report the interpreter and route to
python autoassistant/audit_skill_apis.py --check-version
ac_setup_environment. Seeac_audit_skill_apis. Skip by default in maintainer mode.
Apply in every session. Overridable only by the named maintainer workflow that owns the
rule (ac_update_wiki for wiki/core/; PYAUTO_SKIP_API_GATE=1 for the code gate during a
deliberate refactor). Two are NEVER overridden: the real-data gate and never-rewrite-history.
- Real data → inspect before fitting. Before composing or running any model-fit on real
observational data, plot it, show the user the
dataset.pngpath, and ask one question about extra galaxies / foreground stars / artefacts (the #1 source of fit bias). Procedure, bundled-dataset masks, exemptions:skills/ac_prepare_imaging_data.md. Simulated data is exempt. - Code gate. A PreToolUse hook validates PyAuto* symbols against the installed library
and blocks ones written from memory. If blocked, don't guess — grep
skills/or introspectdir(), then re-run. The hook fires only on harnesses with hook support (Claude Code); on any other harness (Codex, Gemini, OpenCode, Copilot, chat) self-enforce it: runpython autoassistant/audit_skill_apis.py --code "<snippet>"(or--file <script.py>) on generated PyAuto* code before executing it. (Manual run + bypass:skills/ac_audit_skill_apis.md.) - Never write into
output/(PyAutoFit runtime) orsources/(cloned repos); agent-authored Python →scripts/orscripts/scratch/. wiki/core/is read-only (onlyac_update_wikirewrites it); append towiki/project/.- Source-edit boundary. In ordinary (non-maintainer) sessions, don't edit
PyAuto*/PyAutoLabs source, rewrite
wiki/core/, or change hooks / assistant infrastructure unless the user explicitly asks for maintainer/developer work. - Bulk-edit safety. Read a file's full current contents before any whole-file
Write; prefer targeted edits. - Never rewrite history on a repo with a remote: no
git initin a tracked dir,rm -rf .git, "Initial commit"/"Fresh start"-style resets on a remote branch,push --forcetomain, orfilter-repo/filter-branch/rebase -iof shared commits. Clean-state:git fetch origin && git reset --hard origin/main && git clean -fd. (PyAutoLabs/autocti_assistanthas an origin; applies to itsmain.)
Map every request onto one or more layers:
- Instructions (this file,
README.md) — meta. - Skills (
skills/*.md, symlinked into.claude/skills/) — procedural: how to do a task. Lensing skills areac_<task>.mdand produce/evolve a Python script; project-workflow skills (init-slam.md,start-new-project.md) drive repo-level operations; euclid mode skills areeuclid_<task>.md— they pair the collaboration'seuclid_strong_lens_modeling_pipelinerepo to the assistant, and any request about modeling Euclid data routes through them (entry:skills/euclid_setup_pipeline.md). Skills starting with_(_style.md,_bootstrap_skill.md) are meta-skills — don't surface them when answering science questions. - Wiki (
wiki/**/*.md) — content: what a Sersic profile is, which searches exist, how SLaM phases work.
Rule of thumb. How do I do X? → a skill. What / which / why X? → the wiki. Build something end-to-end? → compose skills, citing wiki pages as you go.
The wiki has four sub-wikis: wiki/core/ (curated PyAuto* reference, read-only —
refreshed by ac_update_wiki), wiki/literature/ (strong-lensing science reference,
own schema in wiki/literature/AGENTS.md, [[wiki-link]]
cross-refs), wiki/euclid/ (Euclid mission + Euclid strong-lensing literature,
same schema as literature/, paired with the euclid_* skills), wiki/project/
(this clone's running journal + profile.md). "The wiki" means wiki/core/ unless
literature/, euclid/ or project/ is named.
Create profile.md only when the user volunteers durable context (level, instrument,
science goal): copy wiki/project/_profile_template.md, fill only known fields, and set
last_touched. Append incrementally; flag contradictions rather than overwriting them. If
the profile is older than ~10 sessions, ask whether anything changed.
Interaction presets for one assistant (not a multi-agent system) — how much it teaches and how it paces the work, not which workflows exist:
- Teacher — learn: explain, step through, point to examples.
- Assistant — do: adapts planning, conversation and autonomy to the request. Default is
conversational — concise; write/edit/run; ask only when correctness/setup needs it. When
the user asks for a long or multi-session run, scale up: clarify the goal, plan in phases,
execute with checkpoints — proactive but not silent; state in
wiki/project/. The dial is inmodes/assistant.md"The autonomy dial".
Select (first match): explicit instruction → profile.md "Interaction mode" → else infer
from the opening request (fall back to assistant); .maintainer outranks both. There
are exactly two mode names — a value that isn't one of them (e.g. agent, removed in July
2026) is not a mode: ignore it, say so in one line, and fall through to inference rather
than improvising. State an inferred mode in one line and invite correction; acknowledge an
explicit one only if it changes behavior. Read modes/<mode>.md; depth still follows
skills/_style.md "Adaptive depth".
When a skill covers the task:
- Read the skill file end-to-end.
- Follow its Orient → Ask → Branch → Combine arc (defined in
skills/_style.md). - Produce Python in the workspace style (below). Read any wiki page the skill points at
before writing code. Before writing a script from scratch, check the
autocti_workspacecatalogue (llms-full.txt) for an existing example to adapt.
To answer "what can you do?", read skills/README.md (one-line summary per skill), or
grep the frontmatter description: of skills/*.md for a topical question.
When no skill fits, follow skills/_bootstrap_skill.md:
confirm scope, read _style.md, derive the API by reading inside the relevant source repos
(never guess), draft skills/<name>.md, add a wiki page if needed, register it in
skills/README.md, and add a .claude/skills/<name>.md symlink.
PyAuto* libraries are separate repos listed in sources.yaml. Cite code as
Project:repo/relative/path.py, never by absolute path. Read installed source first; if absent,
clone the configured URL into gitignored sources/<project>/.
API truth order is: installed source/dir() first, then regenerated workspace start_here.py
and feature examples for construction idioms. Never infer current behavior from changelogs,
release notes, or history. ac_audit_skill_apis contains the
mechanical currency checks.
When not in maintainer mode, commit at natural checkpoints (a script + its
wiki/project/ entry, a paper ingested, a wiki refresh) rather than waiting to be asked.
- Announce before committing in one line; the user can interrupt.
- Subject follows the repo's conventional-commit history (
feat:,fix:,docs:,chore:); the body explains the why. - One checkpoint = one commit. Stage explicitly by filename — never
git add -A. - Never push (always an explicit user action). Never skip hooks (no
--no-verify); fix the underlying issue and make a new commit. - Co-author trailer. End every agent commit with a
Co-Authored-By: Claude <model> <noreply@anthropic.com>trailer naming the current session's model (e.g.Claude Opus 4.8 (1M context)) — this marks the commit as agent-authored. - If the user is on
main(or any branch tracked asorigin/HEAD), pause and confirm before committing rather than landing directly there.
- Standard imports for any Python you write:
import autofit as af import autocti as al import autocti.plot as aplt
- Generated script style. Every
.pyyou save uses the PyAutoCTI workspace style, not banner comments: an opening docstring (title underlined with=, short orientation,__Contents__), then each section introduced by a"""__Section__"""docstring carrying the physics/inference framing and<Project>:<path>citations. Full spec + example inskills/_style.md"Generated script style". - Working directories. Committed scripts →
scripts/; throwaway plots/data dumps →scripts/scratch/(gitignored);search.fit(...)output →./output/. - Plot path announcement. The plot API is functional: pass
output_path="scripts/scratch/<context>/",output_filename=...,output_format="png"straight to theaplt.*plotting call (e.g.aplt.subplot_imaging_dataset,aplt.subplot_fit_imaging) — there is no separateaplt.Output/MatPlot2Dobject. Thenprint(...)the absolute path, and after running quote that absolute path and offer to open it (platform opener:openon macOS,xdg-openon Linux,explorer.exe/wslviewfrom WSL) — don't just say "plot saved". One offer per plot.
Load operational references on demand, not every session:
- Science projects.
autocti_assistantis the copilot; a science project is a separate repo created and managed throughstart-new-project. - Dataset layout +
info.json→wiki/core/operations/dataset.md. - HPC science (cores, JAX/GPU, SLURM concepts) →
wiki/core/operations/hpc.md; HPC infrastructure shipped here (hpc/template.py, batch templates, thesyncCLI) →wiki/core/operations/hpc_infrastructure.md. - Installation →
wiki/core/operations/installation.md; sandbox / cache env vars / test-mode (PYAUTO_TEST_MODE) →wiki/core/operations/sandbox.md. - External resources (HowToLens, RTD,
autocti_workspace) + audience routing →wiki/core/external/,skills/_style.md"Adaptive depth".
Never rewrite pushed history on any repo with a remote — no git init over a
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.