diff --git a/.agents/factory/bin/_fsm.py b/.agents/factory/bin/_fsm.py new file mode 100644 index 00000000..1a10faca --- /dev/null +++ b/.agents/factory/bin/_fsm.py @@ -0,0 +1,209 @@ +"""Shared helpers for the RCAC-Docs documentation-factory FSM scripts. + +The finite-state machine for a documentation job (a `feature`/`fix`/`refactor`) +lives in the YAML frontmatter of its ``spec//TECH.md`` roadmap. These +helpers read, validate, mutate, and re-serialize that frontmatter so the +*scripts* (not the model) own the fragile YAML arithmetic — model in-context +YAML editing is the primary FSM-corruption risk (see +``.agents/factory/methodology.md``). + +Requires PyYAML, which is a declared project dependency (``requirements.txt``) +and lives in the project virtual environment — NOT the system interpreter. Run +these scripts with the project env active, e.g. from the repo root:: + + source .venv/bin/activate # or: conda activate rcac-docs + python3 .agents/factory/bin/ + + + + + +
+
+ RCAC docs · factory + +
+
+ +
+
+

RCAC Docs · Agentic Authoring · Getting Started

+

From chatbots to a documentation factory

+

A guide to agentic documentation authoring for the RCAC docs team — what an + agent really is, how a harness turns context into action, and how a lightweight, + auditable methodology (the .agents/factory) makes authoring and maintaining this + site repeatable, reviewable, and safe.

+
+ ~20 min read + Executive orientation ~5 min + Audience: contributors & leadership + Self-contained · works offline +
+
+
+ +
+
+ + +
+

Executive orientation

+

Why this, why now #

+

For a decade our tools have answered questions. In the last two years they + began to do work. That is the whole story — and it changes how technical documentation + gets written and maintained.

+ +

A chatbot produces text. An agent is given a goal, a set of tools, and the + latitude to use them in a loop: it reads the existing pages, builds the site, checks that links + resolve and pages render, edits Markdown, and inspects the result — narrating and course-correcting + as it goes. The thing that made this leap possible is not a bigger model alone; it is the + harness — the software (Claude Code and peers) that assembles a critical mass + of context and grants the model the ability to act. Context plus action, in a + loop, is where the wellspring of productivity comes from.

+ +

That power needs a channel. Left unstructured, an agent will happily write the wrong page quickly, + or the right page in a way you cannot review — or, worse for a user guide, document a + #SBATCH flag that does not exist. The discipline that channels it is + method — and the good parts of agile practice (especially 37signals' + Shape Up) map cleanly onto agent work. This site packages that method as a small, + transparent toolkit in .agents/: five skills and a set of reference + documents that carry a change from a shaped goal, through a researched plan, through authoring, + through an adversarial review, to a pull request — with a durable, committed record at every step.

+ +

What changes for the docs team #

+

The level of abstraction rises. People spend less time on boilerplate scaffolding, nav wiring, and + consistency chores, and more time doing the things only people can do well: shaping + what is worth documenting, judging whether what came back is accurate and clear, + and owning the result. The agent executes; the human sets direction and holds the + bar — and for HPC instructions people run on real clusters, that bar is high.

+ +
+
+

What the factory is

+
    +
  • A repeatable lifecycle: shape → plan → draft → review → ship.
  • +
  • Plain Markdown + git + skills — no new platform, no lock-in.
  • +
  • An auditable trail: intent, design, and content, committed together.
  • +
  • Human judgement at every gate that matters — and review before production.
  • +
+
+
+

What it is not

+
    +
  • Not "the AI writes everything and we hope." Every step is reviewable.
  • +
  • Not a replacement for writers or RSEs — it raises what they work on.
  • +
  • Not a heavyweight process forced onto a typo fix (it scales down).
  • +
  • Not a frozen spec: the plan is a living artifact, the goal is the contract.
  • +
+
+
+ +

For institutional leadership, at a glance #

+

The four questions leaders ask most, answered in one line each — with a fuller treatment in + Notes for institutional leadership.

+
+
+
Governance & guardrails
+

Human sign-off gates, high-impact-file controls, and an independent adversarial review step are + engineered into the lifecycle — critical because a merge to main deploys straight + to production.

+
+
+
Cost & effort economics
+

Ceremony scales to the size of the change (an appetite), so a typo fix does not pay + for a new user guide's process. You spend rigor where it earns its keep.

+
+
+
Reproducibility & auditability
+

Every job leaves a committed record — goal, design, and content, traceable requirement → + commit. A paper trail for why a page says what it says.

+
+
+
Workforce
+

This augments the docs team. Humans shape, judge, and own; agents execute. The scarce skill + becomes good judgement about accuracy and clarity, which your people already have.

+
+
+ + +
+ + +
+

Practitioner guide · 1

+

Agents, not chatbots #

+

A chatbot is a function from prompt to text. You ask; it answers; the transaction ends. Useful, + but it does nothing — you still paste the Markdown, build the site, find the broken link, + and come back.

+ +

An agent closes that loop itself. Given a goal and a set of tools, it + runs a cycle:

+ +
+
01
Perceive
read pages, build the site, inspect state
+
+
02
Reason
decide the next concrete action
+
+
03
Act
edit Markdown, update nav, run mkdocs
+
+
04
Observe
read the result, then loop
+
+ +

The difference is not eloquence; it is agency. Because it observes the outcome of + each action, an agent can recover from a broken build, chase down a bad link, or notice that the + page it just wrote never made it into the nav. This is why "it drafted some text" (2022) and "it + shipped a reviewed page" (2026) are different eras.

+ +
+
+

Chatbot

+
# one shot, no hands
+you   ❯ write a Running Jobs page
+bot   ❯ here's some Markdown…
+you   ❯ # you paste it, the build
+        # warns, the link 404s…
+
+
+

Agent

+
agent ❯ read userguides/gautschi/run_jobs
+agent ❯ edit: add a #SBATCH example
+agent ❯ run: mkdocs build --strict
+agent# warn → fix link → clean → commit
+
+
+ +
+
The catch
+

Agency cuts both ways. An agent can write the wrong thing, or an inaccurate thing, just as fast + as the right thing well. Everything after this section is about channelling that agency — + giving it the right context, the right method, and the right gates.

+
+
+ + +
+

Practitioner guide · 2

+

The harness: where context becomes action #

+

The model is the engine; the harness is the vehicle. A coding/authoring harness + (Claude Code and peers) does two jobs at once, and their combination is the productivity + unlock:

+ +
+
+ Context in +

A critical mass of context

+

The harness feeds the model far more than your prompt:

+
    +
  • The repository — every page, read on demand, searched, navigated.
  • +
  • Project memory — an AGENTS.md + that states the conventions and invariants of this site.
  • +
  • Tools — the shell, mkdocs, git, the web.
  • +
  • Skills — packaged procedures the agent can invoke by name.
  • +
+
+
+ Action out +

The ability to act

+

And it lets the model do things, under permission control:

+
    +
  • Edit and create pages across the site; wire up the nav.
  • +
  • Run commands — build the site, check links, regenerate breadcrumbs.
  • +
  • Use git; open pull requests.
  • +
  • Spawn sub-agents to research in parallel.
  • +
+
+
+ +

Put a loop around those two and you have the whole machine: gather context → decide → act → + observe → repeat. The art — "context engineering" — is getting the right context in + front of the model at the right moment, because a model's attention is finite and its session + memory is not durable across restarts.

+ +
+
The load-bearing idea
+

Because a fresh session starts blank, durable state must live in files and git, not in + the chat. That single fact is why the factory writes everything down — the goal, the + plan, the roadmap, the review — and reads it back fresh each time. It is what lets a draft resume + next week on another machine, and lets a reviewer start with no memory of how the page was + written.

+
+ +

Skills: procedures the agent can run #

+

A skill is a Markdown file (SKILL.md) with a little front-matter and + a body of instructions. When you type its name as a slash command — say /docs-draft — + the harness loads those instructions, injects live facts (the current branch, the git status), and + the agent follows the procedure. Skills are how you capture "the way we author here" once, so nobody + re-explains it every time. The five skills in this guide are exactly that: the RCAC-Docs way to take + a change from idea to merge.

+
+ + +
+

Practitioner guide · 3

+

Method: Shape Up meets agents #

+

Give a capable agent no method and you get motion without direction. The good news: much of what + teams already learned about directing work applies — you just keep the thinking tools and + drop the calendar rituals.

+ +

The sharpest fit is Shape Up (Ryan Singer / 37signals). Its core ideas translate + almost directly to a solo-author-plus-agent pipeline:

+ +
+ + + + + + + + + + + + + + + + +
Shape Up ideaIn the factory
Appetite — fix the time, vary the scope.An appetite: small|big field sizes how much research and how many phases a job gets. The plan fits the appetite, not the reverse.
Shaping — rough, solved, and bounded, at the right altitude.The GOAL.md is shaped: concrete enough to de-risk, abstract enough to leave design freedom.
No-gos — say what you will not do.An explicit non-goals list keeps scope from creeping ("not documenting cluster X").
Rabbit holes — name the scary unknowns and settle them first.Each research brief investigates one unknown — often an HPC spec to verify against an authoritative source.
Hill — uphill (figuring out) vs downhill (just writing).Each phase carries a hill signal; a phase stuck "uphill" is a raised hand.
Circuit breaker — don't extend indefinitely; stop and re-shape.Draft iterations and review bounce-backs are capped; on trip, stop and re-plan.
+
+ +

What we deliberately discard: the betting table, six-week cycles, cool-down, and + separate shaper/builder/QA roles — those exist to synchronize a human team and dissolve + for a serial solo-plus-agent flow.

+ +
+
One place Shape Up must not be followed
+

Shape Up assumes scope is always cuttable and most defects can wait. That is + false for documentation people run on real clusters: a wrong #SBATCH + flag, a partition that doesn't exist, an inaccessible table, or a broken link that silently ships + to production is not a deferrable defect. The factory marks HPC technical accuracy, WCAG + accessibility, and build integrity as hammerable: false — the reviewer may never trim + them to "fit the appetite."

+
+ +

The broader movement this belongs to — committing a specification alongside + the content and letting the spec drive the work — is often called spec-driven + development. Tools like GitHub Spec Kit and AWS Kiro converge on the same + what/why → how → ordered-work spine the factory uses. Our version is deliberately + lightweight: Markdown, git, and skills, anchored on the site's own AGENTS.md.

+
+ + +
+

Practitioner guide · 4

+

The .agents/factory lifecycle #

+

One documentation job flows through five skills, on its own git branch, leaving a committed trail + under spec/<slug>/. The whole pipeline:

+ +
+
/docs-feature
Shape
GOAL.md — what & why
+
+
/docs-plan
Design
research → PLAN → TECH
+
+
/docs-draft
Author
one phase at a time ⟲
+
+
/docs-review
Judge
blind QA ⟲
+
+
/docs-publish
Ship
PR → main
+
+

The ⟲ steps loop: review sends confirmed + problems back to draft until the change is clean, then publish opens the pull request. Merging to + main auto-deploys to production within ~5 minutes.

+ +

The artifact spine #

+

Each stage reads the previous stage's committed files and writes its own. This is the durable + substrate from §2 in practice:

+
+ + + + + + + + + + + + + + +
FileWritten byWhat it is
GOAL.md/docs-featureThe locked contract: problem, appetite, non-goals, and testable + acceptance criteria with stable IDs (R1, R2…).
PLAN.md/docs-planThe authoritative design: archetype, page structure, nav placement, + macros/snippets, mapped back to each requirement ID.
research/*.md/docs-planBriefs from parallel read-only sub-agents — one per rabbit hole (big appetite only).
TECH.md/docs-planThe phased roadmap — a small state machine (see below) the draft resumes from.
REVIEW.md/docs-reviewSeverity-ranked findings + a requirement→evidence matrix.
+
+ +

TECH.md is a finite-state machine #

+

The roadmap's YAML front-matter is the resume point. It lists phases (publishable units of + work — a page or a coherent section), each with the requirements it satisfies, a verify command, and + honesty signals. The draft skill reads it fresh every time, does the next actionable phase, and + writes the state back — so authoring is fully resumable and git history becomes the checkpoint log.

+
spec/<slug>/TECH.md — front-matter (excerpt)
+
appetite: big              # small|big → caps phases & iterations
+status: in_progress
+current_phase: P2
+phases:
+  - id: P1
+    name: "Scaffold: index + overview"
+    satisfies: [R1]             # traces back to GOAL requirement IDs
+    hammerable: false          # HPC accuracy — review may not cut this
+    hill: downhill            # uphill=figuring out · downhill=writing
+    status: done
+    verify: ".venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py"
+

A pair of small helper scripts (next_phase.py / + set_phase.py) read and update this block, so the agent + never hand-edits fragile YAML.

+ +
+
Why --strict
+

Production CI builds with mkdocs build --verbose, so a broken internal link or a + page missing from the nav ships silently. The factory's verify gate runs + mkdocs build --strict and blocks only on warnings not already in + strict-baseline.txt — catching regressions before + they reach readers.

+
+ +

Build in the open #

+

All of this — the skills, the reference docs, the per-job spec/ folders — is committed + to the repository. The methodology is not a hidden prompt; it is version-controlled, reviewable, and + improvable like any other part of the site. The full rationale lives in + methodology.md.

+
+ + +
+

Practitioner guide · 5

+

Hands-on: the five skills #

+

Each is a slash command you invoke deliberately (none fire on their own). They guard their own + preconditions — a wrong branch or a dirty tree stops them cold — so the process is hard to run out + of order.

+ +
+
/docs-feature — shape the goal
+

From a clean main, creates a feature/<slug>, + fix/<slug>, or refactor/<slug> branch and refines your idea + (or a hand-written GOAL) into a shaped GOAL.md: appetite, non-goals, and testable + criteria. Shaping only — no research, no drafting. Asks you when something is ambiguous rather + than guessing.

+
reads your prompt / an untracked GOAL.md · writes spec/<slug>/GOAL.md · + skill docs-feature/SKILL.md
+
+ +
+
/docs-plan — research & design
+

Checks the idea against the site's invariants, fans out read-only research sub-agents (scaled to + appetite; existing-site-first), then writes the PLAN.md design and the + TECH.md phased roadmap. A small fix can skip the research entirely.

+
reads GOAL.md, AGENTS.md, the site · writes research/, PLAN.md, TECH.md · + skill docs-plan/SKILL.md
+
+ +
+
/docs-draft — author the roadmap
+

The resume-and-write driver. Reads the FSM, authors the next phase, runs that phase's verify + command (it proves the work by building and rendering the site, not by ticking a box), + and makes one atomic commit of content + state. It may revise the plan as reality demands, but a + contradiction with the locked GOAL stops it for you.

+
reads TECH.md, PLAN.md, the pages · writes docs/, nav, TECH.md state · + skill docs-draft/SKILL.md
+
+ +
+
/docs-review — adversarial QA
+

Independent quality assurance. It delegates to a fresh reviewer with no memory of how the + page was written, who sees only the goal, the diff, and the invariants — not the + author's own plan. It verifies by building and rendering the site, and separates what it can prove + by command (broken links, nav, front-matter) from what needs a human (HPC accuracy, prose + accessibility). Confirmed issues loop back to draft; high-impact files always require a human + sign-off.

+
reads GOAL.md + diff + invariants (blind to PLAN/TECH) · writes REVIEW.md, findings · + skill docs-review/SKILL.md
+
+ +
+
/docs-publish — ship it
+

Opens a pull request to main with a rich, artifact-linked description (or does a + local squash-merge). This is the one irreversible, outward step — a merge deploys to production — + so it always confirms with you first and never targets dev.

+
reads all artifacts + git log · writes a PR (or a local merge) · + skill docs-publish/SKILL.md
+
+ +

A day in the life #

+
a new user-guide page, start to finish
+
/docs-feature add a Python examples page to the Gautschi user guide
+# → branch feature/gautschi-python, spec/gautschi-python/GOAL.md — you review it
+
+/docs-plan
+# → research/, PLAN.md, TECH.md — you approve the design (archetype, nav spot, macros)
+
+/docs-draft          # phase P1: scaffold + nav … commit
+/docs-draft          # phase P2: draft the page … commit  (repeat until done)
+
+/docs-review         # fresh, blind QA → REVIEW.md (approved / changes-requested)
+
+/docs-publish        # opens the PR to main, links every artifact
+
+
Scales down
+

A typo fix or a one-line correction does not need all of this. Set appetite: small + (the default for fix/ branches) and /docs-plan collapses to a lean plan + with no research fan-out. A truly trivial change can skip the lifecycle altogether. Rigor is a + dial, not a toll.

+
+
+ + +
+

For institutional leadership

+

Notes for institutional leadership #

+

The at-a-glance panel above, expanded. These are the concerns that decide whether the + docs team can adopt agentic authoring responsibly.

+ +

Governance & guardrails #

+

Autonomy is bounded by design, not by hope:

+
    +
  • Human gates at the decisions that matter. A human approves the goal before + the planning, the design before pages are written, and the review before anything ships.
  • +
  • Independent review. The QA step runs in a fresh context, blind to the author's + reasoning, and verifies by building and rendering the site — a direct countermeasure to a model + rubber-stamping its own work. Because there is no staging environment, this review is the last + line of defense before production.
  • +
  • High-impact-file controls. Any confirmed problem touching a shared surface + (mkdocs.yml, the macros in main.py, the catalog generators, the theme + overrides, CI) forces a mandatory human sign-off.
  • +
  • Encoded invariants. The site's non-negotiable rules — branch/deploy model, + the generated-content firewall, HPC accuracy, WCAG accessibility — live in + invariants.md and are checked at both planning and + review; violating one is an automatic top-severity finding.
  • +
+ +

Cost & effort economics #

+

Agent work consumes tokens (and therefore money and time), most of all during broad research + fan-out. The factory treats spend as a dial:

+
    +
  • Appetite scaling. Small changes skip research and collapse the paperwork; only + genuinely large jobs (a new cluster guide, a tutorial series) pay for parallel investigation.
  • +
  • Parallel where it pays, serial where it must. Research fans out (large, + well-understood gains); authoring stays single-threaded (parallel authors make conflicting + decisions about voice, structure, and nav).
  • +
  • Circuit breakers. A stuck phase or a review that keeps bouncing trips a stop, + rather than burning budget in a loop — a spend ceiling with a human off-ramp.
  • +
+ +

Reproducibility & auditability #

+

Every job leaves a committed, dated record:

+
    +
  • A traceable chain from requirement ID → design element → implementing commit → + review evidence. You can answer "why does this page say this, and who decided?" from the + repository alone.
  • +
  • An ADR-style trail. The spec/<slug>/ folder is retained on + merge as a point-in-time record of intent and design — not a living doc to maintain forever.
  • +
  • The site remains ground truth. Specs record intent; the rendered site and + AGENTS.md are authoritative. This avoids the classic trap of stale documentation + pretending to be the source of truth.
  • +
+ +

Workforce #

+

The honest framing: this raises the level of abstraction at which the docs team + works. The routine scaffolding is increasingly automated; the durable, human contributions become + more valuable, not less:

+
    +
  • Shaping — deciding what is worth documenting and bounding it well.
  • +
  • Judgement — knowing whether a page is accurate, clear, and accessible.
  • +
  • Ownership — standing behind what ships to users.
  • +
+

These are exactly the skills experienced writers and RSEs already have. The change is that they + spend more of their day exercising them and less on boilerplate. It is a force multiplier for a + small docs team, not a substitute for one.

+
+ + +
+

Practitioner guide · 6

+

Reference: every material, linked #

+

Everything the factory is made of, with what it is and how it is used. All paths are relative to + .agents/factory/ (this file's home).

+ +

The constitution #

+
+ + + + + + +
MaterialWhat it is / how it's used
AGENTS.md (repo root)The site's operating manual and the factory's constitution: architecture, + content conventions, the branch/deploy model, the invariants. Skills reference it; they + never duplicate it. (CLAUDE.md is a symlink to it.)
+
+ +

The five skills #

+
+ + + + + + + + + +
SkillRole
docs-featureShape a goal on a fresh branch.
docs-planResearch, design, and lay out the phased roadmap.
docs-draftAuthor the roadmap, one verified phase at a time.
docs-reviewIndependent, blind, evidence-based QA.
docs-publishOpen the pull request to main (or merge locally).
+
+ +

Reference documents #

+
+ + + + + + + + + + + + + + +
DocumentWhat it is / how it's used
methodology.mdThe full lifecycle rationale — the "why" behind the skills, and the Shape Up mapping. + Read this to understand the flow.
invariants.mdThe curated checklist of load-bearing rules, drawn from AGENTS.md. Used as + the planning gate and the review footgun list.
ears.mdTemplates for writing testable acceptance criteria (the EARS convention), recast for + documentation outcomes. Used by /docs-feature.
style-guide.mdThe house style and per-archetype conventions (front-matter, macros/snippets, admonitions, + links, assets, nav). Used by /docs-plan and /docs-draft.
review-rubric.mdThe reviewer's operating manual — what it may see, severity levels, the CONFIRMED vs + PLAUSIBLE split, and when a human must sign off.
+
+ +

Templates & state scripts #

+
+ + + + + + + + + + + + + +
FileWhat it is / how it's used
templates/GOAL.mdSkeleton for the shaped goal.
templates/PLAN.mdSkeleton for the design.
templates/TECH.mdSkeleton for the phased FSM roadmap (with the field reference).
templates/REVIEW.mdSkeleton for the review report.
bin/next_phase.pyReads & validates a TECH.md; prints the next actionable phase as JSON.
bin/set_phase.pyAdvances FSM state by regenerating the front-matter (no fragile hand-edits).
bin/strict_check.pyGates a mkdocs --strict log against the warning baseline (fails only on regressions).
bin/_fsm.pyShared parse / validate / serialize helpers for the scripts above.
strict-baseline.txtThe known pre-existing --strict warnings the build gate ignores.
+
+ +

Further reading #

+ +
+ +
+
+ + + + + + diff --git a/.agents/factory/invariants.md b/.agents/factory/invariants.md new file mode 100644 index 00000000..9c3bd982 --- /dev/null +++ b/.agents/factory/invariants.md @@ -0,0 +1,134 @@ +# Documentation invariants — the footgun checklist + +A curated, explicitly-enumerated subset of the load-bearing rules from `AGENTS.md`, kept +**in lockstep with it**. `AGENTS.md` is ground truth; if this file drifts, fix it. Two +consumers: + +- **`docs-plan` (gate):** before research and again after the design is drafted, walk the + sections this change touches and confirm the design honors each; record any deliberate + bend in PLAN's deviation-justification table. +- **`docs-review` (footgun list):** any violation here is **auto-CRITICAL**; if it touches + a high-impact file (below), it forces a **human sign-off gate** before publish. + +Rule: only invoke the sections relevant to the change. Do not manufacture findings against +untouched parts of the site. + +**High-impact files** (any CONFIRMED review finding touching these → mandatory human gate): +`mkdocs.yml` · `main.py` · `docs/snippets/**` · `overrides/**` · `docs/stylesheets/**` · +`docs/assets/js/**` · `requirements.txt` · `Dockerfile.geddes-prod` · `k8s/**` · +`.github/workflows/**` · `tools/**` + `modulefiles/**` · any hand-edit of a generated +output file · any dev-only accessibility-layer path edited on `main` (see §2). + +--- + +## §1 — Branch & deploy model + +`main` is the trunk **and the only production branch**. A merge to `main` auto-deploys to +the Geddes Kubernetes cluster within ~5 minutes; **there is no staging environment**, so +review is the last line of defense before users see it. Do all work on a short-lived +`feature/`, `fix/`, or `refactor/` branch and open a PR into `main`. + +`dev` is a **long-lived WCAG 2.1 accessibility-remediation branch**, not a staging or +integration branch. Data flows **main → dev** (via `sync_main_to_dev.yml`); **`dev → main` +PRs are hard-blocked by CI** (`block_dev_to_main.yml`). Never cherry-pick, rebase, or PR +from `dev` into `main` without an explicit human request tied to the a11y rollout. + +## §2 — The dev-only accessibility layer is untouchable on `main` + +The `sync_main_to_dev.yml` workflow force-preserves a hardcoded set of dev-only files; +edits made to them on `main` can be **clobbered** on the next sync. Never modify these on +`main`: `docs/stylesheets/extra.css`, `overrides/partials/{toc,header,logo,nav,nav-item,palette,search}.html`, +`overrides/base.html`, `docs/assets/js/a11y.js`, `dev.md`, `Dockerfile.geddes`, +`k8s/geddes-dev/`, `deploy_to_geddes_dev.yml`, `wcag_audit/`. Theme-level accessibility is +a `dev` concern; on `main` you own **content-level** a11y only (§9). + +## §3 — Generated-content firewall + +Never hand-edit generated files — your changes are lost on the next regeneration. They +carry a `` marker. This includes: +`docs/software/apps_md/**`, `docs/software/*_catalog.md`, `docs/software/index.md`, +`docs/software/ngc_md/**`, `docs/software/rocm_md/**`, `docs/datasets/dataset_catalog.md`, +and `docs/assets/data/breadcrumbs.json`. To change them, edit the source +(`modulefiles/`, `tools/*.json`, or the generator scripts) and regenerate: +`cd tools && make` for the software/dataset catalogs, `python tools/generate_breadcrumbs.py` +for breadcrumbs. + +## §4 — Navigation is manual + +Every new page **must** be added to `nav:` in `mkdocs.yml`, or it is orphaned (unreachable +except by search/direct URL) and `mkdocs build --strict` warns "not included in nav". +Section hubs use an `index.md` (the `navigation.indexes` feature). After a `nav:` change, +breadcrumbs regenerate (`python tools/generate_breadcrumbs.py`; CI also does this on +`mkdocs.yml` change). Preserve per-cluster nav parallelism (§10). + +## §5 — Links relative, assets absolute + +Page-to-page markdown links are **relative** to the current file +(`[Overview](overview.md)`, `[Back](../index.md)`) so `mkdocs build --strict` can validate +them and they survive moves. Static assets (images, PDFs, JS/CSS) use **absolute** +site-root paths (`/assets/images/userguides/foo.png`). Getting `../` depth wrong is the +single most common broken-link bug here (see `strict-baseline.txt` for live examples). + +## §6 — Front-matter per archetype + +Match the archetype's front-matter contract (full detail in `style-guide.md`): + +- **Userguide page:** `tags: []`, `authors: []`, `resource: ` + (only if the body uses `{{ resource }}`), `search: { boost: 2 }`. +- **Blog post:** `date: { created: YYYY-MM-DD }`, `categories:` from the allowed set + (`Announcements, Anvil, Gautschi, Software, Slurm, Workflows, Life Sciences`), `title`, + `slug`, `authors:` (∈ `docs/blog/.authors.yml`), and a `` excerpt marker. +- **Catalog / landing:** `hide: [footer]` (and often `toc`); generated catalogs also carry + `search: { exclude: true }`. + +## §7 — Macros, snippets, and Jinja escaping + +Cluster-variable content is produced by macros in `main.py` (`{{ ssh_keys_snippet(resource) }}`, +inline `{{ resource }}`) — don't hardcode what a macro supplies. File includes use +`--8<-- "docs/snippets/…"` (repo-root-relative); `snippets/` is `exclude_docs` — snippets +are includes, not linkable pages. The macros plugin evaluates Jinja: any **literal** +`{{` or `{%` in prose or a code block (e.g. a Slurm array `${SLURM_...}` is fine, but +`{{ … }}` templating shown as an example) must be wrapped in `{% raw %}…{% endraw %}` or +the build breaks. + +## §8 — Build integrity (hammerable: false) + +`mkdocs build --strict` must introduce **no new warnings** versus `strict-baseline.txt`. +CI builds with `--verbose`, not `--strict`, so broken links and nav orphans would +otherwise ship silently. Gate with: +`.venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py`. +This is a correctness gate, not a nicety — do not scope-hammer it. + +## §9 — Content-level accessibility, WCAG 2.1 (hammerable: false) + +Every image needs meaningful `alt` text (empty `alt=""` only for decorative images); +headings descend without skipping levels (one `#` H1 per page); link text is descriptive +(not "click here"); tables use header rows; meaning is never conveyed by color alone. +This is *content* a11y, which you own on `main`; *theme* a11y lives on `dev` (§2) — the +reviewer must not demand theme fixes on `main`. + +## §10 — Per-cluster parallelism + +Cluster user guides share a consistent chapter set and order (Overview, Biography, +Accounts, Software, Running Jobs, File Storage and Transfer, Gateway/Open OnDemand, +Compiling Source Code, FAQs). A new cluster guide mirrors this structure; a new chapter +type is either added across clusters or intentionally scoped in `GOAL.md` non-goals. + +## §11 — HPC technical accuracy (hammerable: false) + +Slurm directives, partition and sub-cluster names, `module load` commands, filesystem +paths and quotas, node/GPU specs, and gateway URLs must be **correct and +cluster-appropriate**. Verify against authoritative sources or existing gold-standard +pages (e.g. `docs/userguides/gautschi/`) — never invent a flag or a path. When unsure, +emit `[NEEDS CLARIFICATION]` rather than guess. Note: technical accuracy is often not +machine-checkable, so review classifies it PLAUSIBLE (human triage), not +CONFIRMED-by-command (see `review-rubric.md`). + +## §12 — Commit & PR conventions + +Target `main`; open a squash PR. Commit subjects are `[category] Imperative summary` +(category ∈ `feature`, `fix`, `refactor`, `docs`, `content`, `catalog`, `ci`, `harness` — +not closed). **No `Co-Authored-By` trailer** (a deliberate clean-log convention; end PR +*bodies* with the generation line instead). Use `Closes #NN` to auto-close an issue — +here it works, because `main` is the default branch. Commit only when asked; never commit +straight to `main` (always via a branch + PR) and never to `dev` outside an a11y rollout. diff --git a/.agents/factory/methodology.md b/.agents/factory/methodology.md new file mode 100644 index 00000000..f0c5c128 --- /dev/null +++ b/.agents/factory/methodology.md @@ -0,0 +1,156 @@ +# The documentation factory — methodology + +This document explains the *why* behind the spec-driven authoring lifecycle that the +`docs-*` skills implement. The skills themselves are thin; this is the rationale a +contributor (human or agent) reads once to understand the flow. For a gentler, +narrative introduction see `getting-started.html`. + +**Precedence.** When something here disagrees with a skill, the skill body is the +operating procedure — fix this file. When something here disagrees with `AGENTS.md`, +`AGENTS.md` (the constitution) wins. The rendered site and the source tree are ground +truth; the `spec/{slug}/` records are a point-in-time account of intent, not a living +source of truth to maintain forever. + +## What we are adapting, and why + +This is the HyperShell "software factory" (spec-driven development for a Python engine) +generalized to **documentation and training authoring**. The lifecycle is conserved; +only the domain changes. A software feature becomes a new user guide, tutorial, or blog +post; a bug fix becomes a correction or enhancement; "drive the CLI to prove it works" +becomes **"render the site and inspect it."** The invariants stop being about task +databases and TLS and become about navigation, front-matter, generated-content, HPC +technical accuracy, and accessibility. + +We do this because documentation deserves the same rigor code gets: shaped intent, +a reviewable design, an auditable trail, and an independent quality gate — so an agent +can *author* material, not just edit it, and a human can trust what shipped. + +## The lifecycle + +One job (a `feature`, `fix`, or `refactor`) flows through five skills, on its own git +branch, with every artifact committed under `spec/{slug}/`: + +``` +main ──/docs-feature──▶ feature|fix|refactor/{slug} GOAL.md (shape: what & why, locked) + ├──────────/docs-plan──────────▶ research/ PLAN.md TECH.md (design + phased FSM) + ├──────────/docs-draft─────────▶ docs/ + mkdocs.yml nav (author one phase/loop) + │ ▲ │ + │ └────────┘ (loop until TECH.md is done) + ├──────────/docs-review────────▶ REVIEW.md (blind QA: build, render, links, a11y) + │ │ + │ changes-requested ──▶ back to /docs-draft ; approved ──▶ + └──────────/docs-publish───────▶ PR → main (auto-deploys to production) +``` + +1. **`/docs-feature`** → `GOAL.md`: the shaped, *locked* contract — problem, appetite, + non-goals, and testable acceptance criteria with stable `R#` IDs. Shaping only; no + deep research, no drafting. +2. **`/docs-plan`** → `research/`, `PLAN.md`, `TECH.md`: the design (page structure, + archetype, nav placement, macros/snippets, assets, cross-links, a11y strategy) and a + phased YAML-FSM (`TECH.md`) the drafting step resumes from. +3. **`/docs-draft`** → the actual pages + `mkdocs.yml` nav: executes one phase, runs that + phase's `verify:` gate, makes one atomic content+state commit. Loops until done. +4. **`/docs-review`** → `REVIEW.md`: blind, adversarial QA in a clean context — a fresh + reviewer that sees the GOAL, the diff, and the invariants but *not* the author's plan. +5. **`/docs-publish`** → a squash PR to `main`. On merge, the site auto-deploys to + production (Geddes) within ~5 minutes — there is no staging gate, so review is the + last line of defense. + +Renamed from HyperShell: `build` → **`draft`**, because `/docs-build` collides with +`mkdocs build`, and "draft" better connotes revisable prose. + +## The artifact spine + +`GOAL.md → PLAN.md → TECH.md → REVIEW.md`, all anchored by stable requirement IDs +(`R1`, `R2`, …). This is the industry-standard spec-driven skeleton (cf. GitHub Spec Kit +`spec → plan → tasks`; AWS Kiro `requirements → design → tasks`). The `R#` is the +connective tissue: GOAL defines them → PLAN maps each to a design element → TECH's phases +declare which they `satisfies` → REVIEW verifies each against the rendered diff. The +committed `spec/{slug}/` folder is an immutable, dated design record ("build in the +open"), retained on merge like an ADR — not a doc to keep updating. + +## Load-bearing principles + +1. **`AGENTS.md` is the constitution.** Skills reference it and the curated + `invariants.md` (a strict subset, kept in lockstep). There is no invented + `constitution.md`. +2. **Files and git are the durable substrate.** Lifecycle state lives only in committed + `TECH.md` frontmatter, re-read fresh each invocation via `next_phase.py`. Never rely + on conversation memory to carry state — `docs-review` runs in a separate context, and + `docs-draft` may resume next week on another machine. +3. **Parallelize research, never authoring.** `docs-plan` may fan out read-only research + subagents (surveying existing pages, reference sites, HPC specifics). `docs-draft` is + strictly single-threaded and linear — parallel authors make conflicting implicit + decisions about voice, structure, and nav. (This factory itself was *researched* in + parallel and *written* serially, for exactly this reason.) +4. **Blind, externally-verified review beats self-review.** The reviewer is denied the + author's PLAN/TECH rationale and must cite evidence — a `mkdocs build --strict` run, a + rendered page, a resolved link — not an assertion. Enforced by spawning a fresh + subagent, not by trusting a human to `/clear`. +5. **Ceremony scales to appetite.** The worst anti-pattern is a uniform heavyweight + process — 16 acceptance criteria for a one-line typo fix. `appetite: small` (default + for `fix/`) skips research fan-out and collapses to a single phase; a one-sentence + change may skip the lifecycle entirely. Rigor is a dial, not a toll. +6. **Never guess.** Ambiguity gets a literal `[NEEDS CLARIFICATION: …]` marker in + `GOAL.md` and a question to a human — never a silent assumption. Wrong HPC + instructions harm users. + +## Shape Up, adapted + +We take Shape Up's cognitive tools and drop its team rituals. + +**Adopt:** *appetite* (fixed budget, variable scope — expressed as a phase/iteration cap, +since calendar weeks are meaningless at machine tempo); *shaping* (`GOAL.md` is rough, +solved, and bounded); *no-gos* (explicit exclusions); *rabbit holes* (each +`research/NN-topic.md` investigates one scary unknown); *hill* (`uphill|crest|downhill` +per phase — a stuck-uphill phase is a raised hand); *scope hammering* (nice-to-haves are +cuttable; review scope-checks against appetite); *circuit breaker* (cap draft iterations +and review bounce-backs; on trip, stop and re-shape). + +**Discard:** the betting table, six-week cycles, cool-down, separate shaper/builder/QA +roles — those synchronize a human *team* and dissolve for a serial solo-plus-agent flow. + +**The one place Shape Up must NOT be followed — quality is not negotiable.** Shape Up +assumes scope is always cuttable and most defects can wait. That is *false* for +documentation that people run on real clusters: a wrong `#SBATCH` flag, a partition that +doesn't exist, an inaccessible table, or a broken link that silently ships to production +is not a deferrable defect. Three concerns are marked `hammerable: false` and the reviewer +may never trim them to "fit the appetite": + +- **HPC technical accuracy** — commands, flags, partition/sub-cluster names, paths, specs. +- **WCAG 2.1 content-level accessibility** — alt text, heading order, link text, tables. +- **Build integrity** — `mkdocs build --strict` introduces no new warnings (see below). + +## Verify by rendering, not asserting + +CI builds with `mkdocs build --verbose`, **not** `--strict` — so broken internal links and +nav orphans deploy silently today. The factory closes that gap: every phase's `verify:` +runs `mkdocs build --strict` piped through `.agents/factory/bin/strict_check.py`, which +blocks only on warnings not already in `strict-baseline.txt`. Beyond the build, verify by +*looking*: render the page (`mkdocs serve`), confirm it appears in the nav, check that +links resolve, that front-matter matches the archetype, and that images have alt text. + +## Where things live + +``` +.agents/ + skills/docs-{feature,plan,draft,review,publish}/SKILL.md # the five lifecycle skills + factory/ + methodology.md invariants.md ears.md style-guide.md review-rubric.md + getting-started.html # human onboarding + strict-baseline.txt # known pre-existing --strict warnings + templates/ # GOAL.md PLAN.md TECH.md REVIEW.md skeletons + bin/ # next_phase.py, set_phase.py, strict_check.py, _fsm.py +spec/{slug}/ # per-job artifacts (committed, retained on merge) +AGENTS.md # the constitution (CLAUDE.md is a symlink to it) +``` + +`.claude` is a symlink to `.agents` so Claude Code discovers the skills and settings. + +## Traceability chain + +`GOAL.md` R-IDs → `PLAN.md` requirement→design map → `TECH.md` phase `satisfies:` → +commits → `REVIEW.md` requirement→evidence matrix → PR body. Because a merged PR squashes +per-commit history, the committed `spec/{slug}/` folder *is* the retained trace. +Provenance lives in that chain and in the commit/PR — **never** embed feature-scoped +`R#`/`P#` IDs in page content (they restart per job and collide across branches). diff --git a/.agents/factory/review-rubric.md b/.agents/factory/review-rubric.md new file mode 100644 index 00000000..c60e6038 --- /dev/null +++ b/.agents/factory/review-rubric.md @@ -0,0 +1,109 @@ +# Review rubric — the `docs-review` operating manual + +The operating manual for the `docs-review` adversarial QA pass. The correctness review runs +in an **isolated context (a fresh subagent)** and grades the branch diff against **`GOAL.md` ++ the invariants + the style guide only**. It is **denied `PLAN.md`/`TECH.md`/`research/`** — +showing the author's own rationale triggers grading-its-own-homework and plan-sycophancy. + +**Verification is by rendering the site and reading the diff — never by assertion.** Where a +claim can be checked by a command (build, link, nav, front-matter) it must be; where it +cannot (technical accuracy, prose accessibility) it is surfaced for a human, not asserted. + +## What the reviewer sees / doesn't see + +- ✅ `GOAL.md` (the locked contract — the `R#` IDs) +- ✅ the branch diff (`git diff main...HEAD`) + `git log --oneline main..HEAD` + the full + runnable repo (can `mkdocs build`/`serve`) +- ✅ `invariants.md`, `style-guide.md`, `ears.md`, `strict-baseline.txt` +- ❌ **NOT** `PLAN.md`, `TECH.md`, or `research/` (for the correctness pass) +- A separate, later **completeness sub-pass** *may* read `TECH.md` to ask "did every planned + phase ship? did scope balloon?" — kept isolated so the plan never contaminates the + correctness verdict. + +## Scope — flag ONLY these + +1. **Content defects** — wrong or broken rendered output: a broken internal link, a nav + orphan, a `--strict` regression, malformed front-matter, an unescaped `{{`/`{%` that + breaks the build, a table that doesn't render, a missing/empty `alt`. +2. **HPC technical inaccuracy** — a wrong `#SBATCH` flag, a non-existent partition/module, + an incorrect path/quota/spec, a stale gateway URL. +3. **GOAL-requirement gaps** — an `R#` with no implementing change, or implemented wrong. +4. **Invariant violations** (`invariants.md`) — auto-CRITICAL. +5. **Scope creep** — changes that map to no `R#` (report; don't necessarily block). + +**Do NOT report:** style nitpicks the style guide doesn't mandate, speculative +"you could also add…", rephrasing for taste, or theme-level a11y (that lives on `dev`). +A gap-hunting reviewer manufactures gaps, which drives over-authoring. **Silence on a +clean diff is a valid, valuable result.** + +## Refutation protocol — try to disprove each finding first + +1. **Reproduce it.** Run the command or render the page that would reveal it: + - build/nav/link/front-matter/`--strict` → + `.venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py` + and inspect the log for the specific file; + - rendering/a11y-structure → `mkdocs serve` and view the page (or inspect the built + HTML under `site/`); + - requirement coverage → read the diff for the `R#`'s implementing change. +2. Classify the outcome (below). +3. If it dissolves under scrutiny → **drop it silently.** Default to dropping when uncertain. + +## CONFIRMED vs PLAUSIBLE — the documentation split + +Not every documentation defect is machine-checkable. Classify honestly: + +- **CONFIRMED** — reproduced by an executed command or a direct read of the rendered + output/diff. Examples: `strict_check.py` reports a new warning; a page is absent from + nav; front-matter is missing a required key; an image has no `alt`; an `R#` has no diff. + Only CONFIRMED findings auto-loop back to `docs-draft`. +- **PLAUSIBLE** — a real risk you *cannot* prove by command: **HPC technical accuracy** + (is `--gpus-per-node=2` right for this partition?), **prose/semantic accessibility** + (is this `alt` text actually meaningful? is the heading order logical for a screen + reader?), factual claims about hardware/policy. These go to a **human for triage** — do + **not** auto-loop and do **not** assert them as fact. Cite the specific concern and the + authoritative source you'd check. + +This split is essential: without it the reviewer either rubber-stamps accuracy or +hallucinates accuracy findings. Build/link/nav/front-matter/structural-a11y are objective; +accuracy and prose-a11y are judgment calls that belong to a person. + +## Severity + +| Severity | Meaning | +|---|---| +| **CRITICAL** | Any `invariants.md` violation (§1–§11); a wrong HPC command/path that would misdirect a user; content that breaks the build or ships a broken link to production. | +| **HIGH** | A GOAL `R#` unmet or implemented wrong; a real defect on a common page. | +| **MEDIUM** | A defect on an edge/rarely-hit page; a partial requirement. | +| **LOW** | Minor content risk; a missing-but-non-blocking cross-link or tag. | + +A §12 (commit/PR-convention) violation is **HIGH**, not auto-CRITICAL. + +## Verdict & loop + +- Emit findings via **`ReportFindings`** (most-severe first, each with its CONFIRMED/PLAUSIBLE + verdict) **and** write `spec/{slug}/REVIEW.md`. +- **CONFIRMED** findings → `set_phase.py --top-status blocked --verdict changes-requested + --reviewed-commit --blocked-reason "" --touch` → loop back to `docs-draft`. +- **PLAUSIBLE** findings → surface to the human for triage; do **not** auto-loop. +- **Clean pass** → `set_phase.py --verdict approved --reviewed-commit --touch` → + proceed to `docs-publish`. +- **Bounded loop:** at most **2–3 review↔draft cycles**. On non-convergence, STOP and + escalate to a human — self-correction does not reliably converge. + +## Mandatory human sign-off gate + +A human must approve before `docs-publish` whenever **any** CONFIRMED finding touches a +**high-impact file** (`invariants.md` header list: `mkdocs.yml`, `main.py`, +`docs/snippets/**`, `overrides/**`, `tools/**`+`modulefiles/**`, CI, k8s, a generated +output, or the dev-only a11y layer). And remember the standing reality: **a merge to `main` +auto-deploys to production within ~5 minutes with no staging gate** — so when a +CONFIRMED-or-PLAUSIBLE **HPC-accuracy** concern remains on a high-traffic page, prefer human +sign-off even if no high-impact *file* is touched. + +## Optional variants + +- **`debate`** (high-risk diffs, e.g. touching `main.py`/`mkdocs.yml`/many pages): run two + independent fresh reviewers — one arguing "ship", one "block" — and reconcile. Independent + instances beat single-model introspection. Reserve for genuinely high-risk changes (cost). +- **`completeness`**: a separate fresh reviewer that *may* read `TECH.md` — did every + planned phase ship? did scope balloon past appetite? Appends to `REVIEW.md`. diff --git a/.agents/factory/strict-baseline.txt b/.agents/factory/strict-baseline.txt new file mode 100644 index 00000000..34d5155e --- /dev/null +++ b/.agents/factory/strict-baseline.txt @@ -0,0 +1,31 @@ +# mkdocs --strict warning baseline for the RCAC-Docs documentation factory. +# +# WHAT THIS IS +# `mkdocs build --strict` promotes build WARNINGs (broken internal links, +# missing targets, nav orphans) to hard errors. CI builds with `--verbose`, +# NOT `--strict`, so these warnings currently ship to production silently. +# The factory's build-integrity gate runs `--strict` and blocks only on +# warnings that are NOT already in this baseline — i.e. regressions your +# change introduced. Pre-existing warnings (below) are known debt. +# +# HOW IT IS USED +# .venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py +# Exit 0 = you introduced no new warnings (PASS). +# Exit 1 = new warning(s) attributable to your change (STOP; fix or justify). +# Lines starting with '#' and blank lines are ignored by the checker. +# +# MAINTENANCE +# These are real, pre-existing broken links (a great first `fix/` job for the +# factory). Entries #1-2 live in tool-generated catalog files +# (software/ngc_catalog.md, software/rocm_catalog.md) and must be fixed at the +# generator (tools/), not by hand. When a baseline warning is genuinely fixed, +# delete its line here in the same change so the debt count only shrinks. +# Last captured: 2026-07-14 (mkdocs 1.6.1, mkdocs-material 9.6.16). +# +Doc file 'software/ngc_catalog.md' contains a link '../../assets/images/nvidia_logo.png', but the target '../assets/images/nvidia_logo.png' is not found among documentation files. Did you mean '../assets/images/nvidia_logo.png'? +Doc file 'software/rocm_catalog.md' contains a link '../../assets/images/rocm_logo.png', but the target '../assets/images/rocm_logo.png' is not found among documentation files. Did you mean '../assets/images/rocm_logo.png'? +Doc file 'userguides/gilbreth/run_jobs/learning/customml.md' contains a link 'index.md', but the target 'userguides/gilbreth/run_jobs/learning/index.md' is not found among documentation files. +Doc file 'userguides/gilbreth/run_jobs/learning/ml_batch.md' contains a link 'index.md', but the target 'userguides/gilbreth/run_jobs/learning/index.md' is not found among documentation files. +Doc file 'userguides/negishi/run_jobs/biocontainers.md' contains a link '../../../../assets/images/userguides/examples/biocontainers.png', but the target '../assets/images/userguides/examples/biocontainers.png' is not found among documentation files. Did you mean '../../../assets/images/userguides/examples/biocontainers.png'? +Doc file 'userguides/negishi/run_jobs/windows/launcher.md' contains a link '../../../../../assets/images/userguides/examples/windows.png', but the target '../assets/images/userguides/examples/windows.png' is not found among documentation files. Did you mean '../../../../assets/images/userguides/examples/windows.png'? +Doc file 'userguides/scholar/run_jobs/r_example.md' contains a link '../../userguides/gautschi/run_jobs/examples/example_r_profile_setup.md', but the target 'userguides/userguides/gautschi/run_jobs/examples/example_r_profile_setup.md' is not found among documentation files. diff --git a/.agents/factory/style-guide.md b/.agents/factory/style-guide.md new file mode 100644 index 00000000..3399f46e --- /dev/null +++ b/.agents/factory/style-guide.md @@ -0,0 +1,161 @@ +# RCAC-Docs authoring style guide + +The house style and per-archetype conventions for authoring pages. `docs-plan` chooses the +archetype and cites this file; `docs-draft` follows it; `docs-review` checks against it. +This is descriptive of the *current* site — when it disagrees with a gold-standard page +(`docs/userguides/gautschi/`, `docs/blog/posts/`, `docs/templates.md`), the rendered site +wins; fix this file. `docs/templates.md` is the live "kitchen-sink" of every extension. + +## Content archetypes + +Pick one; each has a distinct front-matter contract and skeleton. + +### A. Cluster user-guide article — `docs/userguides//**` + +Front-matter: +```yaml +--- +tags: + - Gautschi # the cluster name +authors: + - jin456 # RCAC staff handle(s) +resource: Gautschi # title-case; ONLY if the body uses {{ resource }} +search: + boost: 2 # user guides rank higher in search +--- +``` +Skeleton: one `#` H1 tied to the cluster ("Gautschi User Guide", "Running Jobs"), then +`##`/`###` sections mixing prose, spec tables, `bash` blocks, `!!!` admonitions, macro/ +snippet includes, and a closing back-link. Many pages are thin wrappers that just set the +`resource` var and `--8<--`/macro-include shared content. Keep the chapter set consistent +across clusters (see invariants §10). + +### B. Catalog entry — `docs/software/apps_md/.md`, `docs/datasets//.md` + +**Usually generated — do not hand-author** (invariants §3). If you must add one manually, +match the fixed skeleton: software app = `# ` → back-link → `## Description` → +`## Homepage` → `## Available Versions on RCAC Clusters` (per-cluster table, `(D)` = +default) → `## Module` (`module load` block) → closing `!!! note` about `module spider`. +Dataset entry = `# ` → back-link → a single vertical Field/Value table. + +### C. Blog post — `docs/blog/posts/*.md` + +Front-matter: +```yaml +--- +date: + created: 2026-04-20 +categories: + - Announcements # MUST be from the allowed set (below) +title: Introducing the New RCAC Docs +slug: rcac-docs-intro # controls the URL +authors: + - jin456 # must exist in docs/blog/.authors.yml +tags: [Documentation, Search] +pin: true # optional +--- +``` +Allowed `categories`: **Announcements, Anvil, Gautschi, Software, Slurm, Workflows, +Life Sciences**. Body: intro paragraph, then a `` marker (required — it +delimits the index excerpt), then the post. Warmer, announcement-style voice is fine here. + +### D. Tutorial / workshop lesson — `docs/workshops/**`, `docs/lifesciences/{guides,tutorials}/**` + +Organized as a **series** with an `index.md` hub linking ordered lessons. Lesson +front-matter is light (`title`, optional `tags`/`authors`/`search.boost:1`). Pedagogical, +progressive voice ("Let's start by…"); Introduction → Setup → step sections; copious +screenshots with detailed alt text; `[Back to index](index.md){ .md-button }` / +prev-next nav buttons. + +### E. Reference / hub / landing — `docs/index.md`, section `index.md`s, `faqs.md`, `contact.md` + +Front-matter uses `hide: [footer]` (and often `toc`); minimal prose; grid-card or bulleted +navigation. FAQ pages use `??? question` collapsibles with anchor deep-links. + +## Markdown patterns (extensions enabled in `mkdocs.yml`) + +**Admonitions** (`admonition` + `pymdownx.details`): +```markdown +!!! important + Do NOT run heavy jobs on a login node. + +!!! note "Custom title" + ... + +??? info "Collapsible (starts closed)" + ... +``` +Types: `note, abstract, tip, info, success, failure, danger, warning, question, quote, +example, important`. + +**Content tabs** (`pymdownx.tabbed`) — the standard for OS/method/cluster variants: +```markdown +=== "macOS / Linux" + ```bash + ssh you@gautschi.rcac.purdue.edu + ``` +=== "Windows (PuTTY)" + ... +``` +Tabs nest inside admonitions (common for the dataset-request block). + +**Snippets & macros** (see invariants §7): `--8<-- "docs/snippets/home_directory.md"` for +static includes (named sections via `--8<-- "docs/snippets/app.md:python"`); +`{% set resource = "gautschi" %}` + `{{ ssh_keys_snippet(resource) }}` for cluster-variable +content. Available macros live in `main.py` (`ssh_keys_snippet`, `ssh_x11_snippet`, +`thinlinc_snippet`, `accounts_md_snippet`, `scp_snippet`, `globus_snippet`, +`scratch_space`, `compile_gpu_snippet`, `htar_snippet`, `hsi_snippet`, … — read `main.py` +for the current list and signatures). + +**Code blocks** — always tag the language; show interactive prompts with `$`. Extras: +` ```python title="test.py" `, line highlight ` ```py hl_lines="2 3" `, `linenums="1"`, +inline `` `#!python range()` ``. Job scripts conventionally open with `# FILENAME: myjob.sub`. + +**Grid cards** (Material) — the landing-page layout: +```markdown +
+ +- :material-server:{ .lg .middle } __Gautschi__ + + --- + + Purdue's community cluster — **192 cores/node · H100 GPUs** + + [:octicons-arrow-right-24: Gautschi User Guide](userguides/gautschi/index.md) + +
+``` + +**attr_list** — buttons `[text](url){ .md-button }`, icon sizing +`:material-account-plus:{ .lg .middle }`, image alignment +`{ align=right width="260" }`, arrow links `[:octicons-arrow-right-24: label](...)`. + +**Icons/emoji** — Material (`:material-*:`), FontAwesome (`:fontawesome-brands-github:`), +Simple Icons (`:simple-nvidia:`), octicons for arrows. + +## Links & assets + +- **Page-to-page links: relative** (`[Overview](overview.md)`, `[Back](../index.md)`) so + `--strict` validates them. Getting `../` depth wrong is the #1 broken-link bug — count + directory levels carefully. +- **Static assets: absolute** site-root (`![Cluster](/assets/images/userguides/gautschi/rack.png)`). + Add a title where useful: `![alt](/assets/…/plot.png "Sine and Cosine")`. +- Images live under `docs/assets/images/` mirroring the content tree + (`images/blog/`, `images/userguides//`, `images/workshops//`). +- Every content image needs meaningful `alt` text (invariants §9). + +## Naming & file layout + +- Lowercase `snake_case` filenames (`run_jobs/`, `gpu_jobs.md`, `home_directory.md`). + Dataset/generated entries may mirror the source's own casing (`COCO.md`, `climateModel.md`). +- Every section directory has an `index.md` hub (`navigation.indexes`). +- Blog URLs come from `slug:`, not the filename. +- `nav:` in `mkdocs.yml` is manual — add every new page (invariants §4). + +## Voice & tone + +Professional, instructional, second person ("you"); imperative for steps ("Submit the +job:", "Prepare a submission file…"). Safety/policy via `!!! important`/`!!! danger`. +First-time-user friendly where the audience is new (home page, HPC Exchange week 1, life +sciences), deeper for advanced topics (MPI/GPU tuning). Cross-link related pages and end +subpages with a back-link to their hub. diff --git a/.agents/factory/templates/GOAL.md b/.agents/factory/templates/GOAL.md new file mode 100644 index 00000000..4dd1ce2e --- /dev/null +++ b/.agents/factory/templates/GOAL.md @@ -0,0 +1,54 @@ +# GOAL — {Title} + +> **Origin spec.** The *what* and *why* — the locked contract `docs-review` grades against. +> The *how* lives in [`PLAN.md`](PLAN.md) and [`TECH.md`](TECH.md) (written by `docs-plan`). +> Keep this at the right altitude: solved and bounded, but not over-specified — leave design +> freedom for the plan. Edit requirements here; do **not** silently drift them during drafting. + +- **slug:** {slug} +- **kind:** feature | fix | refactor · *feature = new material · fix = correction/enhancement · refactor = restructure* +- **appetite:** small | big · *small caps research + phase count; a one-sentence change may skip + the lifecycle entirely.* + +## Problem + + + +## Outcome / vision + + + +## Acceptance criteria (the contract) + +Stable IDs (`R1`, `R2`, …) that survive squash-merge and anchor traceability. Prefer **EARS** +phrasing (see [`../../.agents/factory/ears.md`](../../.agents/factory/ears.md)) — it makes each line +directly testable — but plain, unambiguous prose is acceptable where EARS would be forced. State +reader-facing outcomes, not implementation (which macro/file is design → `PLAN.md`). + +- **R1** — WHEN , the SHALL . +- **R2** — The SHALL . +- **R3** — IF , THEN `mkdocs build --strict` SHALL . +- **R4** — WHERE , each image SHALL . + +## Non-goals (no-gos) + +Explicit exclusions that keep scope bounded to the appetite. Naming what we are **not** doing is as +important as what we are (e.g. "not documenting cluster X", "not touching the software catalog", +"not theme/CSS changes"). + +- + +## Clarifications + +Questions resolved with the human during shaping. Unresolved ones stay marked `[NEEDS +CLARIFICATION: …]` and **block** `docs-plan` — never guess (especially HPC specifics). + +- **Q:** — **A:** (resolved YYYY-MM-DD). + +## Related materials + +- Issue: +- diff --git a/.agents/factory/templates/PLAN.md b/.agents/factory/templates/PLAN.md new file mode 100644 index 00000000..b523ff1a --- /dev/null +++ b/.agents/factory/templates/PLAN.md @@ -0,0 +1,81 @@ +# PLAN — {Title} + +> **Status:** Draft for review · **Last updated:** {YYYY-MM-DD} +> **Authoritative design.** The *how*. Vision/contract is [`GOAL.md`](GOAL.md); the phased +> executable roadmap is [`TECH.md`](TECH.md). Backing detail is in [`research/`](research/) +> (when `appetite: big`). Every design element traces to a GOAL R-ID. + +## 1. Summary + +<2–4 sentences: the approach in a nutshell and why it fits the appetite.> + +## 2. Design + + + +- **Archetype** (see [`../../.agents/factory/style-guide.md`](../../.agents/factory/style-guide.md)): + userguide article · catalog entry · blog post · tutorial/workshop lesson · reference/hub. State + the front-matter contract it implies. +- **Page structure:** the file(s) to create/edit and their heading outline; which are new vs edited. +- **Navigation placement:** exactly where in `mkdocs.yml` `nav:` each page goes (and the section + `index.md` hub, if any). Note that breadcrumbs regenerate from nav. +- **Reuse:** which `main.py` macros and `docs/snippets/` includes to use (don't hardcode + cluster-variable content); which existing gold-standard page to mirror. +- **Assets:** images/PDFs to add under `docs/assets/…`, and their absolute reference paths. +- **Cross-links & tags:** related pages to link to/from; tags/categories to apply. +- **Accessibility plan:** alt text, heading hierarchy, table headers, link text. + +### Requirement → design map + +| R-ID | Design element(s) that satisfy it | +|------|-----------------------------------| +| R1 | | +| R2 | <…> | + +## 3. Invariant gate (constitution check) + +Checked against [`../../.agents/factory/invariants.md`](../../.agents/factory/invariants.md) +**before** research and **again** after this design was drafted. List every invariant this change +touches and confirm compliance (branch/deploy model, generated-content firewall, nav-is-manual, +links/assets, front-matter, macros/Jinja, build integrity, WCAG, per-cluster parallelism, HPC +accuracy). + +- . + +### Deviation justifications + +Any place this design bends an invariant or adds complexity — with the simpler alternative and why +it was rejected. Empty is the goal. + +| Deviation | Why needed | Simpler alternative rejected because | +|-----------|-----------|--------------------------------------| +| — | — | — | + +## 4. Rabbit holes (resolved) + +Scary unknowns that could have blown the appetite, and how research settled them (link the relevant +`research/NN-*.md`). For docs this is often HPC-accuracy verification (is this the right partition +name / Slurm flag / module?) or "how does the existing site handle X". + +- ([`research/NN-topic.md`](research/NN-topic.md)). + +## 5. Risks & open questions + +- . + +## 6. Verification strategy + +How we will *prove* the pages are correct — this seeds each phase's `verify:` in `TECH.md`: + +- **Build integrity:** `.venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py` + (no new warnings vs baseline). +- **Nav:** the new page(s) appear in `mkdocs.yml` and resolve (no "not in nav" warning). +- **Render:** `mkdocs serve` and view the page(s) — layout, tabs, admonitions, macros expand. +- **Front-matter:** matches the archetype (blog `` + allowed category + known author, etc.). +- **Accessibility:** images have alt text; headings descend logically. +- **HPC accuracy:** which authoritative source or gold-standard page each factual claim was checked against. + +--- + +*Backing research (if present): [`research/00-digest.md`](research/00-digest.md).* diff --git a/.agents/factory/templates/REVIEW.md b/.agents/factory/templates/REVIEW.md new file mode 100644 index 00000000..e5132fba --- /dev/null +++ b/.agents/factory/templates/REVIEW.md @@ -0,0 +1,62 @@ +# REVIEW — {Title} + +> Adversarial QA by `docs-review`, run in an isolated/clean context. The correctness pass grades the +> branch diff against [`GOAL.md`](GOAL.md) + the invariants + the style guide **only** — it does not +> see `PLAN.md`/`TECH.md` (avoids grading-its-own-homework / plan-sycophancy). Every finding cites +> **evidence** — a build/render/link result or a direct read of the diff — not an assertion. + +- **Reviewed commit:** {sha} · **Base:** main · **Date:** {YYYY-MM-DD} +- **Verdict:** approved | changes-requested +- **Cycle:** {n} of ≤3 (escalate to human on non-convergence) + +## Verification run + +Commands actually executed / pages actually rendered, and their outcomes (the spine of the review): + +- `.venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py` → +- `mkdocs serve` + viewed +- nav check: +- front-matter / a11y spot-check → + +## Requirement → evidence matrix + +Bidirectional traceability. Flag requirements with no implementing change **and** changes that map +to no requirement (scope creep). + +| R-ID | Implemented by (file/commit) | Verified how | Status | +|------|------------------------------|--------------|--------| +| R1 | <…> | | ✅ / ❌ | + +Unmapped changes (possible scope creep): . + +## Findings + +Severity: **CRITICAL** (any invariant violation, or a wrong HPC command/path, is auto-CRITICAL) · +**HIGH** · **MEDIUM** · **LOW**. Verdict: **CONFIRMED** (reproduced by command/render or direct diff +read) vs **PLAUSIBLE** (a real risk that is not machine-checkable — HPC accuracy, prose/semantic +a11y — needs human triage). Only CONFIRMED findings auto-loop to `docs-draft`; PLAUSIBLE findings go +to a human. + +### [CRITICAL/CONFIRMED] +- **Where:** `file:line` +- **Failure scenario:** +- **Evidence:** +- **Touches invariant / requirement:** + +### [HIGH/PLAUSIBLE] +- **Where:** `file:line` +- **Concern:** +- **Authoritative source to check:** + +## Human-gate triggers + +Set if any CONFIRMED finding touches a **high-impact file** (`mkdocs.yml`, `main.py`, +`docs/snippets/**`, `overrides/**`, `tools/**`+`modulefiles/**`, CI, k8s, a generated output, or the +dev-only a11y layer), **or** an unresolved HPC-accuracy concern remains on a high-traffic page. +Remember: merging to `main` auto-deploys to production within ~5 minutes — there is no staging gate. + +- + +## Optional completeness sub-pass (separate reviewer; may see TECH.md) + +- Was every planned phase actually shipped? Did scope balloon beyond the appetite? diff --git a/.agents/factory/templates/TECH.md b/.agents/factory/templates/TECH.md new file mode 100644 index 00000000..e7d0e374 --- /dev/null +++ b/.agents/factory/templates/TECH.md @@ -0,0 +1,118 @@ +--- +slug: example-slug +title: "One-line human title for this documentation job" +kind: feature +appetite: big +status: in_progress +branch: feature/example-slug +base: main +current_phase: P1 +last_updated: "2026-01-01" +phases: + - id: P1 + name: "Scaffold: index + overview (sets nav anchor and resource var)" + status: pending + satisfies: [R1] + depends_on: [] + parallel: false + hammerable: false + hill: uphill + verify: ".venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py" + - id: P2 + name: "Draft the Running Jobs article" + status: pending + satisfies: [R2, R3] + depends_on: [P1] + parallel: true + hammerable: false + hill: uphill + verify: ".venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py && grep -q 'run_jobs' mkdocs.yml" +review: + last_reviewed_commit: "" + verdict: none + blocked_reason: "" +--- + +# TECH.md — {title} + +The **context engine and finite-state machine** for authoring this job. The YAML frontmatter +above is the resume ground-truth (read it with +`python3 .agents/factory/bin/next_phase.py spec/{slug}/TECH.md`); the per-phase checklists +below are the work. `docs-draft` executes the next actionable phase, runs its `verify:` +command, updates state via `python3 .agents/factory/bin/set_phase.py …`, and makes one atomic +content+state commit. Run from the repo root with the project env active. + +- **Vision / requirements (locked):** [`GOAL.md`](GOAL.md) — R-IDs are the contract. +- **Authoritative design:** [`PLAN.md`](PLAN.md). +- **Backing research:** [`research/00-digest.md`](research/00-digest.md) + briefs (if `appetite: big`). + +## Frontmatter field reference + +- `base`: the branch this merges into — **`main`** (trunk and production). +- `status` (top): `planned | in_progress | blocked | in_review | done` +- `appetite`: `small | big` — caps phase count and draft-iteration budget (circuit breaker). +- phase `status`: `pending | in_progress | done | blocked` +- `satisfies`: GOAL R-IDs this phase delivers (traceability anchor for `docs-review`). +- `depends_on`: phase ids that must be `done` first (a phase is actionable only when met). +- `parallel`: `true` for genuinely independent content pages (e.g. two sibling userguide + articles a research fan-out *could* draft separately). Anything that edits shared surface — + `mkdocs.yml` nav, `main.py` macros, `docs/snippets/**`, an `index.md` hub — is always `false`. + (Note: `docs-draft` itself still authors one phase at a time; `parallel` documents which + phases have no ordering coupling.) +- `hammerable`: `false` marks a phase whose content accuracy or build integrity scope-hammering + must **never** cut (HPC-accuracy pages, a11y, the build gate). +- `hill`: `uphill` (still figuring it out) → `crest` (unknowns resolved) → `downhill` (just + writing). A phase stuck `uphill` across drafts is a raised hand → escalate to the human. +- `verify`: the exact command that proves the phase — prefer the `--strict` gate plus a nav/ + front-matter check; add a `mkdocs serve` render check in the phase steps when layout matters. + +## Conventions (apply to every phase) + +- Voice, archetype conventions, and load-bearing rules come from + [`../../AGENTS.md`](../../AGENTS.md) (the constitution), + [`../../.agents/factory/style-guide.md`](../../.agents/factory/style-guide.md), and the curated + [`../../.agents/factory/invariants.md`](../../.agents/factory/invariants.md). +- One phase per `docs-draft` invocation by default; one atomic commit containing **both** the + content and the `TECH.md` state change. Commit subjects follow `[{category}] Draft {slug} P: …` + (no `WIP:` prefix) — squashed into the single PR-title commit at `docs-publish`. +- **No `Co-Authored-By` trailer** (repo convention; overrides any default). +- **Adding or moving a page updates `mkdocs.yml` `nav:` in the same commit** (else it is orphaned); + when nav changes, regenerate breadcrumbs: `python tools/generate_breadcrumbs.py` (CI also does + this, but keep the PR self-consistent). +- Never hand-edit generated files (catalogs, breadcrumbs) — regenerate via `tools/`. + +--- + +## Phase P1 — Scaffold: index + overview +**Satisfies:** R1 · **Depends on:** — +**Goal:** . + +- [ ] Create `docs/userguides//index.md` and `overview.md` from the userguide archetype. +- [ ] Add the section + pages to `mkdocs.yml` `nav:`. +- [ ] `python tools/generate_breadcrumbs.py`. +- **Verify:** `.venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py` +- **Touches:** `docs/userguides//index.md`, `overview.md`, `mkdocs.yml`. + +## Phase P2 — Draft the Running Jobs article +**Satisfies:** R2, R3 · **Depends on:** P1 +**Goal:** . + +- [ ] Write `run_jobs/index.md` (prose + `bash` batch example + admonitions + macros/snippets). +- [ ] Add it to `nav:`; add cross-links and a back-link to the hub. +- [ ] `mkdocs serve` and eyeball the rendered page (tabs, admonitions, macro expansion). +- **Verify:** `.venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py && grep -q 'run_jobs' mkdocs.yml` +- **Touches:** `docs/userguides//run_jobs/index.md`, `mkdocs.yml`. + +--- + +## How `docs-draft` drives this + +1. `next_phase.py` prints the next actionable phase (statuses are authoritative; the + `current_phase` pointer is reconciled against them). +2. Pre-flight: clean tree, on `branch`, `base` (`main`) reachable, project env active + (`python3 -c "import yaml, mkdocs"`). +3. Execute every `[ ]` in the phase (consult `PLAN.md` / `research/` / `style-guide.md` for detail). +4. Run the phase's `verify:` command — never advance on a checkbox alone. +5. Amend this file freely if reality diverges (regenerate frontmatter with `set_phase.py`; note the + amendment in the commit body). STOP and escalate only on a **`GOAL.md` contradiction**. +6. Mark the phase `done`, advance `current_phase`, `--touch`; one `[{category}]` commit; stop and report. diff --git a/.agents/settings.json b/.agents/settings.json new file mode 100644 index 00000000..182186b6 --- /dev/null +++ b/.agents/settings.json @@ -0,0 +1,19 @@ +{ + "$comment": "Shared, version-controlled permission allowlist for the RCAC-Docs documentation factory. These are safe, read-only-or-idempotent commands the docs-* skills run repeatedly; pre-approving them reduces interactive prompts. Personal overrides go in .agents/settings.local.json (gitignored). Keep this least-privilege — do not add broad wildcards.", + "permissions": { + "allow": [ + "Bash(mkdocs build:*)", + "Bash(.venv/bin/mkdocs build:*)", + "Bash(python3 .agents/factory/bin/next_phase.py:*)", + "Bash(python3 .agents/factory/bin/strict_check.py:*)", + "Bash(python3 -c \"import yaml, mkdocs\":*)", + "Bash(python tools/generate_breadcrumbs.py:*)", + "Bash(git status:*)", + "Bash(git diff:*)", + "Bash(git log:*)", + "Bash(git branch:*)", + "Bash(git rev-parse:*)", + "Bash(grep:*)" + ] + } +} diff --git a/.agents/skills/docs-draft/SKILL.md b/.agents/skills/docs-draft/SKILL.md new file mode 100644 index 00000000..c97dcb26 --- /dev/null +++ b/.agents/skills/docs-draft/SKILL.md @@ -0,0 +1,84 @@ +--- +name: docs-draft +description: >- + Resume and execute a documentation job's phased roadmap. Discovers spec/{slug}/TECH.md from the + current feature/fix/refactor branch, reads the FSM via next_phase.py, authors the next phase + (default one at a time), runs that phase's verify command (mkdocs --strict + nav/render checks), + updates state via set_phase.py, and makes one atomic content+state commit. May amend TECH.md freely + as reality dictates; only a GOAL.md contradiction forces a stop. The resume-and-write driver of the + documentation factory (see .agents/factory/methodology.md). +disable-model-invocation: true +argument-hint: "[status | dry run | phase P3 | through P5 | next 2 | skip review]" +allowed-tools: Read, Write, Edit, Grep, Glob, Bash(git status *), Bash(git branch *), Bash(git rev-parse *), Bash(git log *), Bash(git diff *), Bash(git add *), Bash(git commit *), Bash(python3 .agents/factory/bin/*), Bash(python3 -c *), Bash(.venv/bin/mkdocs *), Bash(mkdocs *), Bash(python tools/generate_breadcrumbs.py), Bash(grep *) +--- + +# docs-draft — execute the roadmap + +Resume the FSM in `spec/{slug}/TECH.md` and author the next phase. The frontmatter is the +ground-truth; you never hand-edit its YAML — `next_phase.py` reads it and `set_phase.py` mutates it. + +## Step 0 — status / dry-run (when requested) + +Print the FSM state (`next_phase.py`) and what the next phase would do. No edits, no commits. + +## Step 1 — Pre-flight + +- Clean tree on a `feature/`|`fix/`|`refactor/` branch; resolve `{slug}`. +- Assert the environment: `python3 -c "import yaml, mkdocs"` (activate `.venv`/conda if it fails). +- `python3 .agents/factory/bin/next_phase.py spec/{slug}/TECH.md`. If it warns of pointer drift, + reconcile with `set_phase.py --current ` before acting. +- **Remediation mode:** if `top_status: blocked` or `review.verdict: changes-requested`, read + `spec/{slug}/REVIEW.md`, reopen the phase(s) covering the failing R-IDs with + `set_phase.py --phase P --phase-status in_progress` and `--top-status in_progress`. + +## Step 2 — Identify the target phase & load context + +Target = the `next_phase` output (or the arg-selected phase). Confirm its `depends_on` are all +`done`. Read `PLAN.md`, the relevant `research/`, `.agents/factory/style-guide.md`, and the actual +files/pages you will touch (and a gold-standard page to mirror). + +## Step 3 — Author the phase + +Execute every `[ ]` step to the archetype conventions (`style-guide.md`) and the invariants: + +- Correct front-matter for the archetype; **relative** page links, **absolute** asset paths. +- Reuse `main.py` macros / `docs/snippets/` includes for cluster-variable content; escape literal + `{{`/`{%` with `{% raw %}`. +- **Add every new page to `mkdocs.yml` `nav:` in this same phase** (else it is orphaned), and when + nav changes run `python tools/generate_breadcrumbs.py`. +- Never hand-edit generated files (catalogs, breadcrumbs beyond the generator) — regenerate via `tools/`. +- Content images need meaningful `alt`; verify HPC specifics against an authoritative source. + +## Step 4 — Verify gate + +Run the phase's `verify:` command — at minimum +`.venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py` +plus any nav/front-matter check. When layout matters, also `mkdocs serve` and eyeball the rendered +page. **A non-zero verify (a new `--strict` warning, a failed check) is a STOP condition — do not +advance the phase.** + +## Step 5 — Update the FSM + +Check off the `[ ]` items in the body; advance state via +`set_phase.py spec/{slug}/TECH.md --phase {id} --phase-status done --current {next_id_or_done} --touch` +(regenerate — never hand-edit YAML). Update `--hill` when the honesty signal changes. When all phases +are done, also `--top-status in_review`. + +## Step 6 — Commit (atomic content + state) + +`git add -A` → `git commit -m "[{kind}] Draft {slug} {id}: {phase name}"` (no `WIP:` prefix, no +`Co-Authored-By` trailer; body only for non-obvious decisions or a TECH.md amendment). + +## Step 7 — Continue or stop + +Default: one phase, then stop and report. Loop for `through P` / `next N`. Amend `TECH.md` freely +if reality diverges from the plan (regenerate via `set_phase.py`; note it in the commit body) — but a +contradiction with the **locked `GOAL.md`** stops you for the human. + +**Circuit breaker.** If a phase fails its verify gate across repeated attempts, do not thrash — +STOP and recommend re-shaping via `/docs-plan`. + +## Final report + +State the phase(s) completed, verify results, and remaining phases. When the FSM is fully done +(`status: in_review`), recommend a clean-session `/docs-review`. diff --git a/.agents/skills/docs-feature/SKILL.md b/.agents/skills/docs-feature/SKILL.md new file mode 100644 index 00000000..ff226b66 --- /dev/null +++ b/.agents/skills/docs-feature/SKILL.md @@ -0,0 +1,73 @@ +--- +name: docs-feature +description: >- + Start a new RCAC-Docs documentation job (feature/fix/refactor) from a clean main branch. + Safety-checks the tree, derives a {slug}, creates feature/{slug} | fix/{slug} | refactor/{slug}, + ingests an inline prompt or an untracked GOAL.md, and refines it into spec/{slug}/GOAL.md — + appetite, non-goals, EARS acceptance criteria with stable R-IDs, resolved clarifications. + Shaping only: no deep research, no drafting of pages. The first step of the documentation + factory lifecycle (see .agents/factory/methodology.md). +disable-model-invocation: true +argument-hint: " | spec//GOAL.md [fix|refactor] [appetite small|big]" +allowed-tools: Read, Write, Edit, Grep, Glob, AskUserQuestion, Bash(git status *), Bash(git branch *), Bash(git switch *), Bash(git checkout *), Bash(git rev-parse *), Bash(git fetch *), Bash(git add *), Bash(git commit *), Bash(git log *) +--- + +# docs-feature — shape the goal + +Shape a documentation job into a locked `spec/{slug}/GOAL.md` on a fresh branch. This is the +first step of the factory (see `.agents/factory/methodology.md`). Produce exactly one artifact +and stop for the human's sign-off before the more expensive `/docs-plan`. + +**Never guess.** Where intent is ambiguous — which cluster, which audience, an HPC spec you can't +confirm — emit a literal `[NEEDS CLARIFICATION: …]` marker and ask (`AskUserQuestion`). Wrong or +invented documentation harms real users. + +## Step 1 — Pre-flight + +- Confirm you are on `main` with an otherwise-clean tree. The only permitted pending change is an + untracked `spec/{slug}/GOAL.md` you are about to adopt. If not on `main`, STOP and tell the human. +- `git fetch origin || true` (best-effort freshness). + +## Step 2 — Resolve slug / kind / appetite + +- **kind:** `feature` (new material), `fix` (correction/enhancement), or `refactor` (restructure). + Default `feature` unless the prompt/argument says otherwise. +- **appetite:** `small` or `big`. Default `small` for `fix`, `big` for a new user guide / tutorial + series. `small` skips research fan-out and usually collapses to a single phase. +- **slug:** a short kebab-case name (≤ ~5 words), or take it from a given `spec//GOAL.md` path. +- **branch:** `{kind}/{slug}` (e.g. `feature/gautschi-python-guide`). +- **Collision check:** `git rev-parse --verify {branch}` must fail (branch absent) and + `spec/{slug}/` must not already be tracked. If either exists, pick a new slug or STOP. + +## Step 3 — Create the branch + +`git switch -c {branch} main` + +## Step 4 — Write / refine GOAL.md + +From `.agents/factory/templates/GOAL.md`, write `spec/{slug}/GOAL.md`: + +- Record `slug`, `kind`, `appetite` in the header bullets. +- **Problem** and **Outcome / vision** in plain language (what's missing/wrong, for which readers). +- **Acceptance criteria** as stable `R1`, `R2`, … nudged toward EARS + (`.agents/factory/ears.md`) — reader-facing, observable outcomes, not implementation. +- **Non-goals** — explicit exclusions bounding scope to the appetite. +- **Clarifications** — dated Q/A; any unresolved item stays `[NEEDS CLARIFICATION: …]`. +- **Related materials** — issue link, gold-standard pages to mirror, reference sites, source specs. + +If adopting a hand-written untracked `GOAL.md`, refine it in place rather than overwriting intent. + +## Step 5 — Coherence self-check + +Bounded to the appetite · no unresolved `[NEEDS CLARIFICATION]` left silently · every criterion is +testable (renderable/checkable) · the archetype is implied or stated. + +## Step 6 — Commit + +`git add spec/{slug}/GOAL.md` → `git commit -m "[{kind}] Shape {slug} goal"` +(no `Co-Authored-By` trailer). + +## Step 7 — Report & hand off + +Summarize the slug, kind, appetite, and the R-IDs; note any `[NEEDS CLARIFICATION]` awaiting the +human. Recommend `/docs-plan` once the GOAL is approved. diff --git a/.agents/skills/docs-plan/SKILL.md b/.agents/skills/docs-plan/SKILL.md new file mode 100644 index 00000000..2449538d --- /dev/null +++ b/.agents/skills/docs-plan/SKILL.md @@ -0,0 +1,79 @@ +--- +name: docs-plan +description: >- + Turn a shaped spec/{slug}/GOAL.md into a design and a phased roadmap. Runs an invariant gate + against AGENTS.md, fans out read-only research subagents (scaled to appetite; existing-site-first), + synthesizes spec/{slug}/PLAN.md, re-checks invariants, and generates spec/{slug}/TECH.md — the + phased YAML-FSM driven by /docs-draft. Second step of the documentation factory + (see .agents/factory/methodology.md). +disable-model-invocation: true +argument-hint: "[appetite small|big] [skip research] [status]" +allowed-tools: Read, Write, Edit, Grep, Glob, Agent, AskUserQuestion, WebSearch, WebFetch, Bash(git status *), Bash(git branch *), Bash(git rev-parse *), Bash(git log *), Bash(git add *), Bash(git commit *), Bash(python3 .agents/factory/bin/*), Bash(python3 -c *) +--- + +# docs-plan — research → PLAN → TECH + +Design the change and generate the phased FSM the drafting step resumes from. Two invariant gates +bracket the design so it can't drift from the constitution. + +## Step 1 — Pre-flight & load + +- Confirm a `feature/`|`fix/`|`refactor/` branch with a clean tree; resolve `{slug}` from the branch. +- Assert the environment: `python3 -c "import yaml, mkdocs"` (activate `.venv`/conda if it fails). +- Read `spec/{slug}/GOAL.md`, `.agents/factory/invariants.md`, `.agents/factory/style-guide.md`, + and `AGENTS.md`. GOAL.md must be committed with **no unresolved `[NEEDS CLARIFICATION]`** — if any + remain, STOP and return to `/docs-feature`. + +## Step 2 — Invariant gate #1 (pre-research) + +List the invariant sections this change touches (branch/deploy, generated-content firewall, +nav-is-manual, links/assets, front-matter, macros/Jinja, build integrity, WCAG, per-cluster +parallelism, HPC accuracy). Confirm the intent is sane; STOP/escalate on a fundamental conflict. + +## Step 3 — Research fan-out (appetite-scaled) + +- `small` / `fix` / `skip research` → skip the fan-out; do a couple of targeted reads (the + gold-standard page to mirror, the relevant macros in `main.py`, the nav neighborhood). +- `big` → launch parallel **read-only** `Agent` subagents, one per rabbit-hole topic, each writing + `spec/{slug}/research/NN-topic.md` (numbered to avoid write conflicts). **Existing-site-first:** + survey how the current docs handle this (archetype, macros, snippets, nav) before the web; reserve + `WebSearch`/`WebFetch` for external unknowns (HPC vendor specs, reference sites). Then synthesize + `spec/{slug}/research/00-digest.md`. + +Research is the one place we parallelize; drafting never is. + +## Step 4 — Write PLAN.md + +From `.agents/factory/templates/PLAN.md`: summary; design at the right altitude (archetype, page +structure/outline, exact `nav:` placement, macros/snippets to reuse, assets, cross-links, a11y +plan); a **requirement → design map** covering every R-ID; rabbit holes resolved; risks/open +questions; and a **verification strategy** that seeds each phase's `verify:` (the `--strict` gate +plus nav/front-matter/render checks). + +## Step 5 — Invariant gate #2 (post-design) + +Re-walk the touched invariants against the drafted design; fill PLAN's **deviation-justification +table** (empty is the goal). STOP on an unavoidable CRITICAL conflict. + +## Step 6 — Generate TECH.md (the FSM) + +From `.agents/factory/templates/TECH.md`, author phases as **publishable units** (a page or coherent +section that builds clean, is wired into nav, and passes structural a11y), ordered scaffold-first +(the `index.md`/hub that sets nav anchors and the `resource` var), then dependent pages, then a final +integration phase (cross-links, breadcrumbs). Per phase set `id`, `name`, `satisfies` (R-IDs), +`depends_on`, `parallel` (`false` for anything editing `mkdocs.yml`/`main.py`/shared snippets/hubs), +`hammerable` (`false` for HPC-accuracy/a11y/build phases), `hill: uphill`, and a real `verify:`. +Set top `status: in_progress`, `current_phase` = first phase, `base: main`, `last_updated` today. + +**Validate:** `python3 .agents/factory/bin/next_phase.py spec/{slug}/TECH.md` must exit 0 and report +the first phase. If it reports invalid, fix it before committing. + +## Step 7 — Commit + +`git add spec/{slug}/research spec/{slug}/PLAN.md spec/{slug}/TECH.md` → +`git commit -m "[{kind}] Plan {slug}: design + phased roadmap"` (no `Co-Authored-By` trailer). + +## Step 8 — Report & hand off + +Summarize the design, the phase list, and any risks/open questions for the human. Recommend +`/docs-draft` to begin executing the roadmap. diff --git a/.agents/skills/docs-publish/SKILL.md b/.agents/skills/docs-publish/SKILL.md new file mode 100644 index 00000000..b18b0d30 --- /dev/null +++ b/.agents/skills/docs-publish/SKILL.md @@ -0,0 +1,63 @@ +--- +name: docs-publish +description: >- + Land an approved documentation branch on main. Default: push the branch and open a squash PR to + main with a rich, artifact-linked body (Summary/Goal/Design/Research/Phases/Verification). + Alternative (local): squash-merge into main locally. Confirms before any irreversible/outward step; + never targets dev. NOTE: merging to main auto-deploys to production (Geddes) within ~5 minutes — + this is the one irreversible, outward step. Final step of the documentation factory. +disable-model-invocation: true +argument-hint: "[pr (default) | local] [merge]" +allowed-tools: Read, Grep, Glob, AskUserQuestion, Bash(git status *), Bash(git branch *), Bash(git log *), Bash(git diff *), Bash(git rev-parse *), Bash(git fetch *), Bash(git push *), Bash(git switch *), Bash(git checkout *), Bash(git merge *), Bash(git add *), Bash(git commit *), Bash(gh pr *), Bash(gh repo *) +--- + +# docs-publish — ship the branch to main + +Open a squash PR to `main` (default) or squash-merge locally. **Merging to `main` deploys to +production within ~5 minutes — there is no staging gate.** Always confirm before the irreversible step, +and never target `dev` (CI blocks `dev → main` anyway; `dev` is the a11y branch). + +## Step 0 — status (when requested) + +Report the review verdict, commits vs `main`, and any existing PR (`gh pr status`). No action. + +## Step 1 — Pre-flight + +- On the `feature/`|`fix/`|`refactor/` branch, clean tree; resolve `{slug}`. +- Read `kind` and `review.verdict` from `TECH.md` — **STOP if the verdict is not `approved`** + (unless the human explicitly overrides). If review flagged a human gate, confirm sign-off happened. +- `git fetch origin`; flag if the branch is behind `main`. + +## Step 2 — Compose PR title + body + +- **Title:** `[{kind}] {imperative summary}` synthesized from `GOAL.md` (never Conventional Commits + like `feat:`/`docs:`). +- **Body** (link artifacts via SHA-pinned permalinks using `git rev-parse HEAD`; link, don't quote): + - **Summary** — what changed and why (from GOAL). + - **Goal** → `spec/{slug}/GOAL.md` + - **Design** → `spec/{slug}/PLAN.md` + - **Research** → `spec/{slug}/research/*.md` (if present) + - **Phases completed** → from the `TECH.md` FSM (id · name · satisfies R-IDs) + - **Verification** → from `spec/{slug}/REVIEW.md` (build/render/link/nav/a11y results, verdict) + - `Closes #NN` (this auto-closes the issue — `main` is the default branch) + - trailing line: `🤖 Generated with [Claude Code](https://claude.com/claude-code)` + +## Step 3 — Confirm with the human (mandatory) + +`AskUserQuestion`: mode (PR vs local), title, and body. This is the last gate before production. + +## Step 4a — PR (default) + +`git push -u origin {branch}` → `gh pr create --base main --head {branch} --title "…" --body-file …`. +If `merge` is confirmed: `gh pr merge {N} --squash --subject "{title}" --body "…" --delete-branch`. + +## Step 4b — local + +`git switch main && git pull --ff-only` → `git merge --squash {branch}` → +`git commit -m "{title}"` → `git branch -D {branch}`. Do not push `main` unless explicitly asked +(a push to `main` triggers the production deploy). + +## Step 5 — Report + +PR URL / merge result, the squash subject, and the retained `spec/{slug}/` artifacts. Remind the +human that a merge to `main` rolls out to `docs.rcac.purdue.edu` within ~5 minutes. diff --git a/.agents/skills/docs-review/SKILL.md b/.agents/skills/docs-review/SKILL.md new file mode 100644 index 00000000..1c6d8a11 --- /dev/null +++ b/.agents/skills/docs-review/SKILL.md @@ -0,0 +1,74 @@ +--- +name: docs-review +description: >- + Adversarial QA of a completed documentation branch. Delegates the correctness pass to a FRESH + reviewer subagent that sees only GOAL.md + the branch diff + the invariants + the style guide + the + runnable repo — NOT PLAN.md/TECH.md (avoids grading-its-own-homework). The reviewer verifies by + building (mkdocs --strict), rendering, and checking links/nav/front-matter/a11y; classifies each + finding CONFIRMED (machine-checked) or PLAUSIBLE (HPC accuracy / prose a11y → human). CONFIRMED + findings loop back to /docs-draft; high-impact files force a human gate. Fourth step of the + documentation factory (see .agents/factory/review-rubric.md). +disable-model-invocation: true +argument-hint: "[debate] [completeness] [status]" +allowed-tools: Read, Grep, Glob, Write, Agent, ReportFindings, AskUserQuestion, Bash(git status *), Bash(git branch *), Bash(git log *), Bash(git diff *), Bash(git rev-parse *), Bash(git add *), Bash(git commit *), Bash(python3 .agents/factory/bin/set_phase.py *) +--- + +# docs-review — blind adversarial QA + +Grade the branch against the locked `GOAL.md` and the invariants, in a clean context, by rendering +the site — not by assertion. Full operating manual: `.agents/factory/review-rubric.md`. + +## Step 1 — Pre-flight + +- On the `feature/`|`fix/`|`refactor/` branch; resolve `{slug}`; read `base` (`main`) and `kind` + from `TECH.md` (metadata only — do **not** feed PLAN/TECH content to the reviewer). +- Capture the head SHA: `git rev-parse HEAD`. +- If `TECH.md` `status` is not `in_review`/`done`, ask whether to proceed anyway. + +## Step 2 — Delegate the correctness pass (blind) + +Spawn a fresh `Agent` (general-purpose) given **inline, ONLY**: + +- the full text of `spec/{slug}/GOAL.md` (the R-IDs); +- the diff command to run: `git diff main...HEAD` (+ `git log --oneline main..HEAD`); +- the full text of `.agents/factory/invariants.md`, `.agents/factory/review-rubric.md`, + `.agents/factory/style-guide.md`, and `.agents/factory/strict-baseline.txt`; +- instructions to work in the runnable repo (project env active) and **verify by executing**: + `.venv/bin/mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py`, `mkdocs serve` + + view changed pages, nav/front-matter/a11y checks; +- an explicit instruction to **NOT read `PLAN.md`, `TECH.md`, or `research/`**. + +Required return: structured findings — each with severity, **CONFIRMED** (reproduced by +command/render/diff) vs **PLAUSIBLE** (HPC accuracy or prose a11y that isn't machine-checkable → +human triage), `file:line`, failure scenario/concern, executed evidence — plus a requirement→evidence +matrix and any unmapped (scope-creep) changes. + +`debate` → spawn two independent reviewers (one arguing "ship", one "block") and reconcile. + +## Step 3 — Collect, sanity-check, report + +Write `spec/{slug}/REVIEW.md` from the template. Call `ReportFindings` (most-severe first, each +carrying its CONFIRMED/PLAUSIBLE verdict). Silence on a clean diff is a valid result — do not +manufacture findings. + +## Step 4 — Set verdict & route + +- **Clean pass:** `set_phase.py spec/{slug}/TECH.md --verdict approved --reviewed-commit {sha} --touch` + → recommend `/docs-publish`. +- **CONFIRMED findings:** `set_phase.py … --top-status blocked --verdict changes-requested + --reviewed-commit {sha} --blocked-reason "" --touch` → recommend `/docs-draft`. If any + CONFIRMED finding touches a **high-impact file** (see review-rubric) → STOP and require human sign-off. +- **PLAUSIBLE only:** surface to the human for triage; do not auto-block. +- Then commit the review: `git commit -m "[{kind}] Review {slug}: cycle {n} — {verdict}"` + (no `Co-Authored-By` trailer). + +## Step 5 — Optional completeness sub-pass (`completeness`) + +A separate fresh subagent that *may* read `TECH.md`: did every planned phase ship? did scope balloon +past appetite? Append its notes to `REVIEW.md`. + +## Final report + +Verdict, finding counts (CONFIRMED vs PLAUSIBLE), human-gate status, R-ID coverage, and the next +step. Bounded loop: escalate to the human on the 2nd–3rd non-converging cycle. Remember a merge to +`main` auto-deploys to production within ~5 minutes — review is the last line of defense. diff --git a/.claude b/.claude new file mode 120000 index 00000000..c0ca4685 --- /dev/null +++ b/.claude @@ -0,0 +1 @@ +.agents \ No newline at end of file diff --git a/.github/workflows/deploy_to_geddes_prod.yml b/.github/workflows/deploy_to_geddes_prod.yml index 0820cb16..f0010842 100644 --- a/.github/workflows/deploy_to_geddes_prod.yml +++ b/.github/workflows/deploy_to_geddes_prod.yml @@ -8,6 +8,11 @@ on: - 'modulefiles/**' - 'tools/**' - 'wcag_audit/**' + # Documentation-factory bookkeeping never affects the built site (all outside docs/). + - 'spec/**' + - '.agents/**' + - 'AGENTS.md' + - 'CLAUDE.md' workflow_dispatch: permissions: diff --git a/.gitignore b/.gitignore index eb621ad3..d37e4447 100644 --- a/.gitignore +++ b/.gitignore @@ -46,7 +46,9 @@ htmlcov/ .env.local # Assistant / tooling scratch -.claude/ +# `.claude` is a tracked symlink -> `.agents` (the documentation factory), so it is NOT +# ignored. Only genuinely personal Claude Code settings are ignored: +.agents/settings.local.json .warp/ # Project-local drafts not for publication diff --git a/AGENTS.md b/AGENTS.md index 6a530daa..857ac888 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,244 +1,202 @@ -# RCAC Documentation Website -## Project Overview -This is the MkDocs-based documentation website for the **Rosen Center for Advanced Computing (RCAC)** at Purdue University. It provides comprehensive user guides, tutorials, reference material, software catalogs, datasets, blog articles, and workshop materials for RCAC's HPC systems (Anvil and Gautschi). - -**Primary URL**: https://docs.rcac.purdue.edu (served from the Geddes Kubernetes cluster) -**Source Repository**: https://github.com/PurdueRCAC/RCAC-Docs -### Reference Sites -The following HPC documentation sites use a similar MkDocs Material framework and serve as design/content references: -- https://docs.tacc.utexas.edu/ -- https://docs.alcf.anl.gov/ -- https://docs.ncsa.illinois.edu/en/latest/ -- https://docs.jetstream-cloud.org/ -- https://docs.hpc.ucdavis.edu/ -## Repository Structure -``` -RCAC-Docs/ -├── .github/ -│ ├── ISSUE_TEMPLATE/ # Bug/feature request templates -│ └── workflows/ # GitHub Actions automation -├── docs/ # Main documentation content -│ ├── assets/ # Images, CSS, JS, fonts, data files -│ ├── blog/ # Blog posts -│ ├── datasets/ # Dataset documentation -│ ├── snippets/ # Reusable content snippets -│ ├── software/ # Software catalog pages (auto-generated) -│ ├── stylesheets/ # extra.css and theme overrides -│ ├── userguides/ # User guides (Anvil, Gautschi) -│ ├── workshops/ # Workshop materials (HPC Exchange, Matplotlib, etc.) -│ ├── contact.md # Contact page -│ ├── faq.md # FAQ page -│ ├── index.md # Homepage -│ ├── tags.md # Tag index page -│ └── templates.md # Template examples -├── hooks/ # MkDocs hooks (e.g., social media) -├── k8s/geddes-prod/ # Kubernetes manifests for production deployment -├── modulefiles/ # HPC module files (software installations) -├── overrides/ # Material theme customizations (main.html, partials) -├── tools/ # Automation scripts for software catalog -├── .gitignore -├── .readthedocs.yaml # Read the Docs configuration (legacy/secondary) -├── Dockerfile.geddes-prod # Image built and pushed to GHCR for Geddes -├── main.py # MkDocs macros plugin definitions -├── mkdocs.yml # MkDocs configuration -├── README.md -└── requirements.txt # Python dependencies -``` -## Technology Stack -### Core Technologies -- **MkDocs**: Static site generator (v1.6.1) -- **Material for MkDocs**: Theme (v9.6.16) -- **Python 3.x**: Runtime environment (Dockerfile uses `python:3.11-slim`) -- **GitHub Actions**: CI/CD automation -- **Docker / GHCR**: Production image at `ghcr.io/purduercac/rcac-docs-prod:latest` (served by `nginx:alpine`) -- **Kubernetes (Geddes)**: Production hosting in the `rcac-docs` namespace -### Key MkDocs Plugins -- `mkdocs-material`: Material Design theme -- `mkdocs-material-extensions` -- `material/blog` (built-in blog plugin): Blog functionality with categories and pagination -- `material/tags` (built-in tags plugin): Content tagging -- `mkdocs-git-revision-date-localized-plugin`: Git-based timestamps -- `mkdocs-macros-plugin`: Dynamic content macros (see `main.py`) -- `search`: Built-in search -### Markdown Extensions -- `pymdownx` (details, blocks.caption, emoji, snippets, highlight, inlinehilite, superfences, tabbed) -- `admonition`: Callout boxes -- `tables`: Table support -- `attr_list` and `md_in_html`: HTML attributes / inline HTML in markdown -- `toc`: Table of contents with permalinks -## Content Organization -### Major Sections -1. **HPC User Guides**: Comprehensive guides for Anvil and Gautschi clusters (plus external links to Bell, Negishi, Gilbreth, Scholar) -2. **Storage User Guides**: External links to Data Depot, Fortress, Scratch, Home, Box -3. **Blog**: News and updates categorized by system/topic (Anvil, Gautschi, Software, Slurm, Workflows) -4. **Software Catalog**: Auto-generated catalog of available software -5. **Datasets**: AI, Hydrological, Meteorological, Geospatial, Covariates, GeoAI, Igenomes -6. **Workshops**: HPC Exchange (weeks 1–4), Anvil Kubernetes, Scientific Visualization with Matplotlib -7. **FAQs** and **Contact** pages -### Software Catalog System -The software catalog is **automatically generated** from HPC module files: -**Process Flow**: -1. `modulefiles/` → Module files for installed software -2. `tools/update_apps_inventory.sh` → Extracts app names, versions, clusters → `rcac_apps_inventory.json` -3. `tools/generate_apps_topics.py` → Categorizes apps by topic → `apps_topics.json` -4. `tools/gen_apps_descriptions.py` and `tools/update_apps_descriptions_from_inventory.sh` → Fetches descriptions from Spack / Wikipedia / PyPI → `apps_descriptions.json` -5. `tools/generate_md.sh` → Creates individual markdown files under `docs/software/apps_md/` -6. `tools/update_apps_catalog.sh` → Updates catalog index page `docs/software/app_catalog.md` -**Topics**: MPI, Compilers, Audio/Visual, Climate, Chemistry, Fluid Dynamics, Geoscience, Library, Material Science, Math/Stat, Engineering, Programming, Utilities, Workflow, Misc. -## Automation & Workflows -### Branches -> **Heads-up for agents and new contributors**: despite its name, `dev` is **not** a generic development/integration branch. Do **not** treat it the way you would a `dev` branch in a conventional dev→main flow. Read the section below before pushing, merging, or opening PRs involving `dev`. - -- `main`: **trunk and the only production branch.** All normal content and feature work targets `main` directly via PR. `main` is what deploys to https://docs.rcac.purdue.edu. -- `dev`: a **long-lived, permanently-divergent WCAG 2.1 accessibility remediation branch.** It carries an experimental Material theme override layer (ARIA labels, dedup'd form labels, contrast fixes) that is **not yet ready for production**. It is served separately from its own Geddes environment (`k8s/geddes-dev/`, `Dockerfile.geddes`, `deploy_to_geddes_dev.yml`) for WAVE re-audits. See `dev.md` on the `dev` branch for the remediation plan and phase history. -- Data flow is **main → dev**, not the other way around. `sync_main_to_dev.yml` forward-merges `main` into `dev` on every push so the a11y preview stays current with content, while preserving the dev-only framework layer. -- Direct PRs from `dev` into `main` are **blocked** by CI (`block_dev_to_main.yml`). When the a11y work is complete and accepted, the expected endgame is a deliberate, curated PR of the theme layer into `main` — not an automatic merge. - -#### Guidance for agents -- Default working branch for any content, nav, workflow, infra, or macro change is **`main`** (usually via a short-lived feature/`wip` branch PR'd into `main`). -- Do **not** cherry-pick, rebase, or PR from `dev` into `main` without an explicit human request tied to the a11y rollout. -- When editing files in the dev-only a11y layer (`docs/stylesheets/extra.css`, `overrides/partials/toc.html`, `docs/assets/js/a11y.js`, the `a11y.js` entry in `mkdocs.yml`, `overrides/base.html`, `overrides/partials/{header,logo,nav,nav-item,palette,search}.html`, `dev.md`, `Dockerfile.geddes`, `k8s/geddes-dev/`, `deploy_to_geddes_dev.yml`, `wcag_audit/`), work on `dev` — changes made on `main` to these files can be overwritten or clobbered by the sync workflow's "preserve dev" logic. -- The sync workflow's list of preserved paths is **hardcoded** in `sync_main_to_dev.yml`; if a11y work expands to new files, that workflow must be updated or those files will be overwritten on the next sync. -### GitHub Actions -#### 1. `deploy_to_geddes_prod.yml` — **primary production deployment** -- **Triggers**: Push to `main` (excluding `modulefiles/**`, `tools/**`, `wcag_audit/**`); also manual `workflow_dispatch` -- **Process**: - 1. Logs into GHCR with `GITHUB_TOKEN` - 2. Builds `Dockerfile.geddes-prod` (multi-stage: `python:3.11-slim` → `mkdocs build` → `nginx:alpine`) - 3. Pushes `ghcr.io/purduercac/rcac-docs-prod:latest` -- **Rollout**: The in-cluster `rcac-docs-prod-restart` CronJob (every 5 minutes) runs `kubectl rollout restart deployment/rcac-docs-prod -n rcac-docs`, which re-pulls `:latest` (because `imagePullPolicy: Always`) -#### 2. `publish_to_s3.yml` — secondary/legacy S3 publish -- **Triggers**: Completion of the catalog rebuild workflow, push to `main`/`auto_publish` (excluding `modulefiles/**` and `tools/**`), or `workflow_dispatch` -- **Process**: Builds the site and syncs to the Ceph S3 bucket `s3://rcac-docs/` at `https://s3.rcac.purdue.edu` -- **Status**: No longer the canonical production target; retained for mirror/backup purposes -#### 3. `rebuild_on_module_tools_change.yml` -- **Triggers**: Push to `main` or `dev` when `modulefiles/**` or `tools/**` change -- **Purpose**: Automatically regenerate the software catalog -- **Process**: - 1. Runs `make` in `tools/` - 2. Stages/rebases/commits updated catalog files (`docs/software/apps_md/`, `app_catalog.md`, `index.md`) - 3. Pushes using GitHub App token (`purduercac-docs-bot`) -#### 4. `update_breadcrumbs.yml` -- **Triggers**: Push to `main` or `dev` when `mkdocs.yml` changes -- **Purpose**: Regenerate navigation breadcrumbs -- **Process**: Runs `tools/generate_breadcrumbs.py`, updates `docs/assets/data/breadcrumbs.json`, commits via App token -- **Logic**: Only includes parent titles if parent has an `index.md`; root `/` is excluded -#### 5. `sync_main_to_dev.yml` -- **Triggers**: Push to `main`; manual `workflow_dispatch` -- **Purpose**: Forward-merge `main` into the a11y remediation branch `dev` so it stays current with production content, while **hardcoded-preserving** the dev-only a11y framework layer: `docs/stylesheets/`, `overrides/partials/toc.html`, and the `a11y.js` entry in `mkdocs.yml` (re-added via `sed` if absent). -- **Caveat**: the preserved-paths list is hardcoded. If the a11y work adds or moves files outside that list, this workflow must be updated or those files will be clobbered on the next sync. -#### 6. `block_dev_to_main.yml` -- **Triggers**: Pull requests targeting `main` -- **Purpose**: Fail CI if the PR source branch is `dev`. This is a guardrail against accidentally shipping the experimental a11y theme layer to production — **not** a statement that the workflow is inverted. See the **Branches** section above for the intended model. -### Kubernetes Deployment (Geddes) -Manifests live in `k8s/geddes-prod/` and are applied to the `rcac-docs` namespace on the Geddes cluster: -- `deployment.yaml`: `rcac-docs-prod` Deployment, 1 replica, image `ghcr.io/purduercac/rcac-docs-prod:latest`, `imagePullPolicy: Always`, `imagePullSecrets: ghcr-secret`, modest CPU/memory limits -- `service.yaml`: `ClusterIP` Service exposing port 80 -- `ingress.yaml`: `ingressClassName: public`, TLS host `docs.rcac.purdue.edu` (secret `rcac-docs-prod-tls`) -- `cronjob.yaml`: `rcac-docs-prod-restart` CronJob running every 5 minutes; uses `bitnami/kubectl` (from `geddes-registry.rcac.purdue.edu/docker-hub-cache/`) with a mounted `kubeconfig-secret` to `kubectl rollout restart` the deployment so new `:latest` images are pulled -### GitHub App Bot -- **Name**: `purduercac-docs-bot` -- **Purpose**: Automated commits that push to `main`/`dev` without triggering recursive workflows -- **Configuration**: `PURDUERCAC_DOCS_BOT_APP_ID` and `PURDUERCAC_DOCS_BOT_PRIVATE_KEY` in repository secrets; commits authored as `purduercac-docs-bot@users.noreply.github.com` -### Read the Docs Integration -- `.readthedocs.yaml` is still present (Ubuntu 24.04, Python 3, `pip install -r requirements.txt`) but is **no longer the primary deployment path**. The Geddes/Kubernetes pipeline above serves `docs.rcac.purdue.edu`. -## Development Workflow -### Local Development Setup -```bash -# Clone repository -git clone git@github.com:PurdueRCAC/RCAC-Docs.git -cd RCAC-Docs +# AGENTS.md -# Create Python environment (conda or venv) -conda create -n rcac-docs python -conda activate rcac-docs +Guidance for agents (Claude Code and others) working in this repository. `CLAUDE.md` is a +symlink to this file — edit `AGENTS.md`, never a separate copy. (`.claude` is likewise a +symlink to `.agents`, so Claude Code discovers the documentation-factory skills and settings +through it.) -# Install dependencies -python -m pip install -r requirements.txt +This document is the operating manual and **constitution**: the architecture, the +load-bearing invariants, and the process rules an agent needs to make correct, safe changes +to this documentation site without rediscovering them each session. **When something here +disagrees with the rendered site or the source tree, the site is ground truth — fix this +file.** The curated `.agents/factory/invariants.md` is a strict subset of this file, kept in +lockstep; if it drifts, this file wins. + +--- + +## Project + +This is the MkDocs Material documentation website for the **Rosen Center for Advanced +Computing (RCAC)** at Purdue University — user guides, references, software/dataset catalogs, +blog articles, and workshop/training material for RCAC's HPC clusters and storage services. + +- **Production URL:** (served from the Geddes Kubernetes cluster). +- **Source repo:** . +- **Design/content reference sites** (same MkDocs-Material lineage): docs.tacc.utexas.edu, + docs.alcf.anl.gov, docs.ncsa.illinois.edu, docs.jetstream-cloud.org, docs.hpc.ucdavis.edu. + +## Environment & working rules + +- **Setup:** create a Python environment and install pinned deps. + ```bash + python -m venv .venv && source .venv/bin/activate # or: conda create -n rcac-docs python && conda activate rcac-docs + python -m pip install -r requirements.txt + ``` + (The local `.venv` may be uv-created and lacks `pip`; `uv pip install -r requirements.txt` + syncs it. The project itself is pip/`requirements.txt`-managed — there is no `pyproject.toml` + and no `uv.lock`.) +- **Always run tooling from the repo root.** The macros module (`main.py`) and the factory + scripts resolve paths relative to the current directory. +- **Commit only when explicitly asked.** When you do: branch off **`main`** (never commit + straight to `main`; never touch `dev` outside an a11y rollout — see Branch & deploy model). + Commit subjects follow `[category] Imperative summary` — categories include `feature`, `fix`, + `refactor`, `docs`, `content`, `catalog`, `ci`, `harness` (the `.agents/` factory); the set is + not closed. +- **No `Co-Authored-By` trailer** on commits — a deliberate clean-log convention. End PR + **bodies** with the generation line instead. (Automated commits are authored as the GitHub + App bot `purduercac-docs-bot`.) +- **Use `Closes #NN`** to auto-close an issue — it works here because `main` is the default branch. + +## Commands -# Start local server -mkdocs serve # Default: http://localhost:8000 -mkdocs serve -a localhost:8080 # Custom port -``` -### Local Production-Image Build (optional) -```bash -docker build -f Dockerfile.geddes-prod -t rcac-docs-prod:local . -docker run --rm -p 8080:80 rcac-docs-prod:local -``` -### Making Changes -#### Content Changes -1. Edit markdown files in `docs/` -2. Test locally with `mkdocs serve` -3. Open a PR into `main` from a short-lived feature or `wip` branch. Do **not** PR from `dev` into `main` — it is blocked by CI, and `dev` is the a11y remediation branch, not a staging branch for content. -4. On merge to `main`, `deploy_to_geddes_prod.yml` builds and pushes the image; the Geddes CronJob rolls the deployment within ~5 minutes. `sync_main_to_dev.yml` separately forwards the merge onto `dev` for the a11y preview. -#### Software Catalog Updates -1. Add/modify module files in `modulefiles/` -2. Push/merge to `main` (or `dev`) -3. `rebuild_on_module_tools_change.yml` runs `make` and bot-commits the regenerated catalog -#### Navigation Changes -1. Edit `nav:` in `mkdocs.yml` -2. Push/merge to `main` (or `dev`) -3. `update_breadcrumbs.yml` regenerates `docs/assets/data/breadcrumbs.json` -### Manual Catalog Generation ```bash -cd tools -make # Runs all steps in correct order - -# Or run individually: -./update_apps_inventory.sh -v -./generate_apps_topics.py -./update_apps_descriptions_from_inventory.sh -./generate_md.sh -./update_apps_catalog.sh +mkdocs serve # local preview at http://localhost:8000 +mkdocs serve -a localhost:8080 # custom port +mkdocs build # build the static site into ./site (gitignored) +mkdocs build --strict # promote link/nav warnings to errors — USE THIS to verify (CI does not) + +cd tools && make # regenerate the software & dataset catalogs (see Automation) +python tools/generate_breadcrumbs.py # regenerate docs/assets/data/breadcrumbs.json after a nav change + +# Optional: build the production image locally +docker build -f Dockerfile.geddes-prod -t rcac-docs-prod:local . && docker run --rm -p 8080:80 rcac-docs-prod:local ``` -## Special Features -### MkDocs Macros (`main.py`) -Reusable content snippets defined as Python functions (via `mkdocs-macros-plugin`): -- `login_snippet(host, cluster)`: SSH login instructions -- `account_snippet(host, cluster)`: Account creation info -- `ssh_keys_snippet(resource)`: SSH key setup guide (macOS/Linux/Windows/PuTTY) -- `ssh_x11_snippet(resource)`: X11 forwarding setup -- `thinlinc_snippet(resource)`: ThinLinc client instructions -### MkDocs Hooks -- `hooks/socialmedia.py`: Social-media share button support (currently commented out in `mkdocs.yml`) -### Theme Customizations -- **Logo/Favicon**: Purdue branding (`docs/assets/purdue.png`, `docs/assets/purdue_favicon.png`) -- **Color Schemes**: Auto / light / dark (Material palette toggles) -- **Fonts**: Roboto (text), Consolas (code) -- **Custom CSS**: `docs/stylesheets/extra.css` -- **Custom JS**: `docs/assets/js/` — `tablefilter.js`, `init-tablefilter.js`, `breadcrumbs.js`, `external-links.js` (plus `a11y.js` on `dev`) -- **Theme overrides**: `overrides/main.html` and `overrides/partials/` -### Analytics & Feedback -- Google Analytics (property: `G-3D80JBWGP0`) -- Page feedback widget (thumbs up/down) with link to a feedback issue template -## Best Practices -### Content -- Use admonitions for important notes/warnings -- Include code blocks with proper syntax highlighting -- Link to related pages within user guides -- Tag blog posts with appropriate categories (Anvil, Gautschi, Software, Slurm, Workflows) -### Version Control -- Land all content/feature/workflow changes on `main` via PR; `sync_main_to_dev.yml` will forward them to the a11y `dev` branch automatically -- Touch `dev` directly **only** for WCAG/a11y remediation work on the override layer; never backport `dev` to `main` outside of an explicit, curated a11y rollout -- Oz-assisted commits include trailer: `Co-Authored-By: Oz ` -- Bot commits are authored as: `purduercac-docs-bot@users.noreply.github.com` -### Testing -- Always test locally with `mkdocs serve` before pushing -- Optionally validate the production image with `docker build -f Dockerfile.geddes-prod` -- Verify breadcrumbs render correctly after `mkdocs.yml` changes -- Verify software catalog after module file changes -## Key Files Reference -- `mkdocs.yml`: Main configuration, navigation, plugins, markdown extensions -- `requirements.txt`: Python dependencies (pinned) -- `main.py`: MkDocs macros -- `hooks/socialmedia.py`: Optional social-share hook -- `tools/Makefile` and `tools/README.md`: Software catalog build automation -- `Dockerfile.geddes-prod`: Production image for Geddes (builder + nginx serve stage) -- `k8s/geddes-prod/*.yaml`: Kubernetes Deployment, Service, Ingress, CronJob -- `.github/workflows/`: CI/CD automation (deploy to Geddes, S3 mirror, catalog, breadcrumbs, branch sync/guards) -- `.readthedocs.yaml`: Read the Docs build config (secondary) + +**Stack:** MkDocs 1.6.1 · Material for MkDocs 9.6.16 (custom_dir `overrides`) · Python 3.11 in +the prod image · pinned in `requirements.txt`. Plugins: `search`, `blog`, `tags`, +`git-revision-date-localized`, `rss`, `macros` (see `main.py`). Markdown extensions: `toc` +(permalink), `tables`, `attr_list`, `md_in_html`, `admonition`, and `pymdownx.*` (`details`, +`blocks.caption`, `emoji`, `snippets`, `highlight`, `inlinehilite`, `superfences`, `tabbed`). + +## Repository map + +| Path | Responsibility | +|------|----------------| +| `docs/` | All published content (the only directory MkDocs builds). | +| `docs/userguides//` | Per-cluster/storage guides (anvil, bell, gautschi, gilbreth, negishi, scholar, geddes, hammer; storage: depot, fortress, boxfolder, reedfolder). Consistent chapter set across clusters. | +| `docs/blog/posts/` | Blog posts (Material blog plugin); authors in `docs/blog/.authors.yml`. | +| `docs/software/`, `docs/datasets/` | **Auto-generated** catalog pages (see Automation) — do not hand-edit. | +| `docs/workshops/`, `docs/lifesciences/` | Training material, organized as series with an `index.md` hub. | +| `docs/snippets/` | Reusable includes (`--8<--`); `exclude_docs` — not pages. | +| `docs/assets/` | Images, JS, CSS, data (`assets/data/breadcrumbs.json` is generated), PDFs, fonts. | +| `mkdocs.yml` | Config, theme, plugins, markdown extensions, and the **manually curated `nav:`**. | +| `main.py` | `mkdocs-macros` module — the `{{ … }}` macros/snippets (SSH, accounts, Slurm, storage, containers, …). | +| `overrides/`, `docs/stylesheets/` | Material theme overrides + custom CSS (much of it dev-only a11y layer — see below). | +| `tools/` | Catalog generators (`Makefile`, `generate_*`/`update_*`) and `generate_breadcrumbs.py`. | +| `modulefiles/` | HPC module files that seed the software-catalog generator. | +| `hooks/` | MkDocs hooks (`socialmedia.py`, currently disabled in `mkdocs.yml`). | +| `Dockerfile.geddes-prod`, `k8s/geddes-prod/` | Production image (builder → nginx) and Kubernetes manifests. | +| `.github/workflows/` | CI/CD (deploy, catalog rebuild, breadcrumbs, branch sync/guard). | +| **`.agents/`** | The spec-driven **documentation factory** (`docs-*` skills + `factory/` methodology, invariants, style guide, EARS, review rubric, templates, and `bin/` FSM scripts). `.claude` symlinks here. | +| **`spec/{slug}/`** | The committed, dated per-job design records (`GOAL/PLAN/TECH/REVIEW.md`) the factory produces and retains on merge. Outside `docs/`, so not published. | + +## Content conventions & archetypes + +Full detail in `.agents/factory/style-guide.md`; `docs/templates.md` is the live extension +reference. In brief: + +- **Archetypes:** cluster user-guide article · catalog entry (mostly generated) · blog post · + tutorial/workshop lesson · reference/hub/landing. Each has a distinct front-matter contract. +- **Front-matter:** user guides carry `tags`/`authors`/`resource`/`search.boost:2`; blog posts + carry `date.created`/`categories` (from the allowed set)/`slug`/`authors` + a `` + excerpt marker; landing/catalog pages use `hide: [footer(, toc)]`. +- **Links relative, assets absolute:** page-to-page markdown links are relative + (`[Overview](overview.md)`); images/PDFs/JS/CSS use absolute site-root paths (`/assets/…`). +- **Reuse over duplication:** cluster-variable content comes from `main.py` macros + (`{{ ssh_keys_snippet(resource) }}`, inline `{{ resource }}`) and `--8<--` snippet includes — + don't hardcode what a macro supplies. Escape literal `{{`/`{%` in prose with `{% raw %}`. +- **Voice:** professional, instructional, second person; imperative for steps; admonitions for + notes/warnings; one `#` H1 per page; cross-link and end subpages with a back-link. + +## Invariants (load-bearing) + +The curated footgun checklist is `.agents/factory/invariants.md` (used by the plan gate and the +review). The headlines: + +1. **Branch & deploy model** — `main` is trunk *and* production; merging auto-deploys. `dev` is + the a11y branch; `dev → main` is CI-blocked. +2. **The dev-only a11y layer is untouchable on `main`** (the sync workflow clobbers it). +3. **Generated-content firewall** — never hand-edit catalogs or `breadcrumbs.json`; regenerate. +4. **Nav is manual** — add every new page to `mkdocs.yml` `nav:` or it is orphaned. +5. **Links relative, assets absolute.** +6. **Front-matter per archetype** (blog `categories` from the allowed set; ``). +7. **Macros/snippets + Jinja escaping.** +8. **Build integrity** — `mkdocs build --strict` introduces no new warnings vs the baseline + (`hammerable: false`). +9. **Content-level WCAG 2.1 accessibility** (`hammerable: false`). +10. **Per-cluster parallelism** — keep the shared chapter set/order. +11. **HPC technical accuracy** — commands, flags, partitions, paths, specs must be correct + (`hammerable: false`). +12. **Commit/PR conventions** (this file's "Environment & working rules"). + +## Branch & deploy model + +- **`main`** — trunk and the **only production branch**. All content/feature/nav/infra work + targets `main` via a PR from a short-lived `feature/`|`fix/`|`refactor/` branch. **A merge to + `main` auto-deploys to production within ~5 minutes — there is no staging gate.** +- **`dev`** — a long-lived, permanently-divergent **WCAG 2.1 accessibility-remediation** branch + carrying an experimental theme/override layer not yet ready for production. Served from its own + Geddes environment for WAVE re-audits. +- **Data flow is main → dev.** `sync_main_to_dev.yml` forward-merges `main` into `dev` on every + push, force-preserving a hardcoded list of dev-only files (`docs/stylesheets/`, + `overrides/partials/toc.html`, the `a11y.js` nav entry, …). Editing those files on `main` risks + being clobbered — do that work on `dev`. +- **`dev → main` PRs are hard-blocked** by `block_dev_to_main.yml`. When the a11y work is + accepted, the endgame is a deliberate, curated PR of the theme layer — never an automatic merge. + +**Deploy chain:** push/merge to `main` → `deploy_to_geddes_prod.yml` builds `Dockerfile.geddes-prod` +(`python:3.11-slim` → `mkdocs build --verbose` → `nginx:alpine`) and pushes +`ghcr.io/purduercac/rcac-docs-prod:latest` → the in-cluster `rcac-docs-prod-restart` CronJob +(every 5 min) rolls the deployment (`imagePullPolicy: Always`). Manifests live in `k8s/geddes-prod/` +(`deployment/service/ingress/cronjob/nginx.conf`). + +## Automation & generated content + +- **Software/dataset catalogs** are generated from `modulefiles/` + `tools/*.json` by + `tools/Makefile` (`make` runs `update_apps_inventory.sh` → `generate_apps_topics.py` → + `update_apps_descriptions_from_inventory.sh` → `generate_md.sh` → `update_apps_catalog.sh`, plus + the NGC/ROCm steps). Output lands in `docs/software/**` and `docs/datasets/dataset_catalog.md` + with a `` marker. `rebuild_on_module_tools_change.yml` + regenerates and bot-commits these when `modulefiles/**` or `tools/**` change. +- **Breadcrumbs** — `python tools/generate_breadcrumbs.py` writes `docs/assets/data/breadcrumbs.json` + from the nav; `update_breadcrumbs.yml` regenerates and bot-commits it when `mkdocs.yml` changes. +- **CI is not `--strict`.** The prod build uses `mkdocs build --verbose`, so broken internal links + and nav orphans deploy silently. The factory's verify gate runs `--strict` to catch them; see + `.agents/factory/strict-baseline.txt` for the known pre-existing warnings. + +## Special features + +- **Macros (`main.py`):** `mkdocs-macros` functions for reusable, cluster-variable content — + SSH/keys/X11/ThinLinc, accounts, Slurm overviews, storage/scratch/quota, transfers + (scp/sftp/globus/htar/hsi), containers (apptainer/biocontainers/rocm), compile, recovery, etc. + Read `main.py` for the current list and signatures before hardcoding anything. +- **Theme:** Purdue branding, light/dark/auto palette, custom CSS in `docs/stylesheets/extra.css`, + custom JS in `docs/assets/js/` (tablefilter, breadcrumbs, external-links, outage-widget). +- **Analytics & feedback:** Google Analytics; a thumbs up/down page-feedback widget. + +## Working on this repo as an agent — the documentation factory + +- **Use the factory for non-trivial work.** A documentation job (`feature`/`fix`/`refactor`) flows + through the `.agents/` spec-driven lifecycle — `/docs-feature` (shape `GOAL.md`) → `/docs-plan` + (research + `PLAN.md`/`TECH.md`) → `/docs-draft` (execute phases) → `/docs-review` (blind, + externally-verified QA) → `/docs-publish` (squash PR to `main`), each on a + `feature/`|`fix/`|`refactor/` branch with artifacts committed under `spec/{slug}/`. + `.agents/factory/methodology.md` is the *why*; `getting-started.html` is the onboarding. + **Ceremony scales to appetite** — a one-sentence fix may skip the lifecycle entirely. +- **Verify by rendering, not asserting.** After a change, run + `mkdocs build --strict 2>&1 | python3 .agents/factory/bin/strict_check.py` (no new warnings), + confirm the page is in `nav:`, and `mkdocs serve` to eyeball the render — the concurrency and + link/nav behavior are where documentation bugs hide. +- **Put content where it belongs:** new pages under `docs/…` + a `nav:` entry; cluster-variable + content via `main.py` macros (extend the macro, don't fork the prose); generated catalogs via + `tools/`, never by hand. +- **Never guess HPC specifics.** A wrong `#SBATCH` flag, partition, module, or path misdirects real + users. Verify against a gold-standard page or an authoritative source, or emit + `[NEEDS CLARIFICATION]`. +- **This file is the map, but it drifts.** For a deep change, re-verify the specific invariant + against the site/source before relying on it, and update this file when things move. + ## Contact -- **Organization**: Rosen Center for Advanced Computing -- **Email**: rcac-help@purdue.edu -- **GitHub**: https://github.com/PurdueRCAC -- **Discord**: https://discord.gg/RmtKZmaQW9 + +- **Org:** Rosen Center for Advanced Computing · **Email:** rcac-help@purdue.edu +- **GitHub:** · **Discord:** diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 00000000..47dc3e3d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/spec/README.md b/spec/README.md new file mode 100644 index 00000000..46e7a45c --- /dev/null +++ b/spec/README.md @@ -0,0 +1,22 @@ +# `spec/` — documentation-factory design records + +Each documentation job run through the factory (see [`../.agents/factory/methodology.md`](../.agents/factory/methodology.md)) +gets a `spec/{slug}/` directory holding its committed, dated design record: + +``` +spec/{slug}/ + GOAL.md # what & why — the locked contract (stable R-IDs), by /docs-feature + PLAN.md # the design (archetype, structure, nav, macros, a11y), by /docs-plan + TECH.md # the phased YAML-FSM the draft step resumes from, by /docs-plan + REVIEW.md # blind adversarial QA findings + verdict, by /docs-review + research/ # read-only research briefs (big appetite only), by /docs-plan +``` + +These are an **immutable, point-in-time record of intent** ("build in the open"), retained on +merge like an architecture decision record — not living documents to maintain forever. The +rendered site and the source tree remain ground truth; `AGENTS.md` is the constitution. + +This directory sits **outside `docs/`**, so MkDocs does not build or publish it. + +The `{slug}` matches the job's branch (`feature/{slug}`, `fix/{slug}`, or `refactor/{slug}`). +Start a new job with `/docs-feature`.