01_cleanup_simplification

galaxy-architecture: cleanup & simplification audit

Repo: ~/projects/repositories/galaxy-architecture (last commit 01fd94c, 2026-05-20). Audited 2026-09-26, read-only.

TL;DR

Inventory

PathPurposeStatusRationale
topics/*/content.yamlSlide/prose/agent-context blockscollapseThe real content. 514 inline blocks. The YAML wrapper adds indentation noise around markdown. Convert to topic.md.
topics/*/metadata.yamlTraining/sphinx/xref/agentic-op metadatacollapseBecomes front-matter. Drop the unused fields (see model section).
topics/*/.claude/CLAUDE.mdPer-topic agent contextkeep → fold15 topics (missing for file-sources). Could become an agent-context section of the topic md.
topics/{file-sources,markdown}/notes/ (39+48 files), */plan/, tests/plan.md/research-topic + /plan-a-topic outputscutWorking scratch. PR diffs and summaries are stale. Move to galaxy-brain vault if wanted.
topics/*/suggestions/, tests/harmonize//generate-agentic-op + /harmonize side-outputscutFeedback scratch. validate.py even warns when suggestions/ is missing (drop that check).
topics/files/fragments/*.yaml (12)Output of generate_files_prose.pycutReferenced by nothing. files/content.yaml has only 9 image slides.
PLAN.md (347 lines)Strategic plancut”Current state: all done.” Its content model description is inaccurate (it shows file: fragments/...). Fold the 5-line vision into the README.
LAYOUT_PLAN.md (235)Plan for layout_namecutImplemented, and then misused (template: key).
SPHINX_PLAN.md (406)Sphinx implementation phasescutSays “COMPLETE” as of 2025-11-11.
MIGRATED.md (327)GTN→repo migration recordcutHistorical. Covers 13 topics, now 16.
IMAGE_HANDLING.md (415)GTN image path patternscutOnly relevant to GTN round-trip. References a nonexistent BACK_TO_TRAINING_PLAN.md.
docs/MIGRATION.md (258)Plan for moving into GalaxyrewriteSuperseded by this vault project. Replace with a real migration plan.
docs/OUTPUTS.md, docs/SCHEMA.md (auto-gen), docs/CONTRIBUTING.mdMeta-docscollapseMerge into one short CONTRIBUTING. Generate SCHEMA only if the model survives.
docs/GITHUB_PAGES_{QUICKSTART,SETUP}.md (346)Pages setupcut at migrationGalaxy has its own doc hosting.
docs/SLIDE_GUIDE.md, docs/DIAGRAM_GUIDE.md, images/MERMAID.md, images/README.mdAuthoring guideskeep, mergeThe real value. Merge MERMAID.md + images/README into DIAGRAM_GUIDE.
scripts/models.py (564)Pydantic models + loaderscollapseLarge for its job: 3 content sources, 2 render configs, class/slides.class_ alias, a no-op validator (validate_slide_heading), inline import yaml, and extra='ignore'. Should be about 100 LOC.
scripts/validate.py (226)Validate topics + tutorial chainkeep, shrinkCore. Drop the suggestions/CLAUDE.md nag warnings.
scripts/generate_schema_docs.py (270)SCHEMA.md generatorcut270 LOC to document about 20 fields. Docstrings/README suffice.
scripts/migrate_topic.py (615)One-shot GTN→YAML importcutMigration done. Hardcodes ~/workspace/training-material.
scripts/plantuml_to_mindmap_yaml.py (228)One-shot PlantUML→mindmap YAMLcutThe conversion is done. The reverse images/mindmap_yaml_to_plantuml.py is what the build uses.
scripts/validate_images.py (202)Find/copy missing images from GTNcutMigration-era. Hardcoded path. Overlaps with sphinx_image_linter.py.
scripts/generate_files_prose.py (163)Mindmap → GitHub-link prose, verified against Galaxy checkoutcut or reworkOutput is orphaned. Once in the Galaxy repo, “verify file exists” becomes a trivial in-repo test.
scripts/sync_to_training_material.py (236), sync_images.py (243), compare_slides.py (248), validate_sync.py (150)GTN round-tripdecide (Q1)Only needed if GTN remains a published target. Otherwise cut all 877 LOC plus 3 Make targets.
scripts/sphinx_image_linter.py (314)Broken-image check on HTMLkeep, shrinkUseful. Exits 0 when doc/build/html is missing, so it passes falsely. Sphinx’s -W plus nitpicky mode may replace it.
outputs/training-slides/build.py (354) + template.html, html_wrapper_template.html, assets/GTN slides + standalone Remark HTMLkeep, cleanSee the duplication section.
outputs/sphinx-docs/build.py (523)Topic → MyST markdown + toctreekeep, cleanSame. At migration this should become a Sphinx extension or pre-build step in galaxy/doc.
outputs/*/generated/Build outputokAlready gitignored.
doc/source/architecture/*.md (17, tracked)Generated MyST copied into the Sphinx projectcut from gitDuplicate generated output. build-sphinx overwrites it. Currently byte-identical to fresh output.
doc/source/_images → ../../images symlink, assets/GTNLogo1000.png (also in images/)Image plumbingcollapseDuplicate logo. The symlink plus the Makefile cp images/* into html is two mechanisms for one thing.
images/*.plantuml.txt (~60), *.mindmap.yml (16), *.mermaid.txt (3), png/svgDiagram sources + static artkeepContent.
images/MakefilePlantUML/Mermaid buildkeep, fixEvery PlantUML output depends on all inputs, so any edit rebuilds everything. It downloads the jar at build time.
images/build.shAlternate PlantUML build (plantuml CLI/docker)cutUnused by Make/CI. Wrong glob (*.txt also picks up mermaid).
images/plantuml.jarLocal jar (gitignored)okCI installs both apt plantuml and the jar; one of those is unused.
package.json (untracked), package-lock.json (gitignored!), node_modules/mermaid-cli for 3 diagramsdecide (Q3)Lock file is gitignored, package.json never committed, CI never runs npm install. So Mermaid SVGs are never built in CI (probable cause of Deploy failures). Either commit package.json + lock and install in CI, or render Mermaid client-side (sphinxcontrib-mermaid; Remark can use mermaid.js).
generated_agentic_operations/commands/ (3)Generated review commandskeepThe useful agentic artifact (di, controllers/services/managers, async-sync).
review/ (Makefile, sync_generated.py, generated_commands{,.yaml}, static_commands/ (8), galaxy-plugins submodule)Packaging for the claude-galaxy-plugins marketplacesplit outA different concern from architecture docs. generated_commands/ holds stale duplicates (review-di.md + gx-review-di.md). The legacy Make target points at a nonexistent gx-arch-review/. Uses bare python. The static commands belong in the plugins repo.
.claude/commands/ (10)Authoring workflowstrimSee the slash-commands section.
tests/test_validate.py (92, 6 tests, pass)Validation testskeep, extendNothing tests either builder. That is where the bugs are (template:, speaker-notes split).
pyproject.tomldeps: PyYAML, Jinja2, pydantic; extras dev/docskeepFine. Jinja2 is used only for 2 templates. The comment “Scripts are run directly… for now” plus sys.path.insert hacks everywhere means the package is not installable.
.github/workflows/{deploy-docs,validate}.ymlCIfixNode-20 action pins (checkout@v4, setup-uv@v3, setup-python@v5, setup-java@v4, cache@v4). No npm step. Duplicate PlantUML install.
.DS_Store (root, untracked but present)—ignoreAlready in .gitignore.

Metadata fields: who consumes what

Consumers checked: scripts/, both builders, templates, .claude/commands, review/.

FieldConsumed byVerdict
topic_id, titleboth builderskeep
training.tutorial_numberslides title (Architecture NN - ...), sync/compare, validatekeep; use it as the ordering key
training.subtitle, questions, objectives, key_points, time_estimationslides template; sphinx uses questions/objectives/key_pointskeep (GTN front-matter)
contributorsslides templatekeep
training.previous_to / continues_tosphinx toctree ordering, validate chain, sync footnotescut: redundant with tutorial_number (a linked list to maintain by hand)
training.prerequisitesnothing (validated only)cut. Values are inconsistent anyway (architecture-frameworks vs project-management).
sphinx.section / subsectionnothing (only migrate_topic writes it)cut
sphinx.level, toc_depth, hub.*, claude.*nothing; not in the model, silently droppedcut, then set extra='forbid'
related_topicsvalidated onlykeep only if the builder renders “See also” links; otherwise cut
related_code_paths, related_pull_requestsslash commands (research-*, generate-agentic-op, harmonize)keep; this is the agentic value. In Galaxy, paths can be CI-checked for existence.
agentic_operationsgenerate-agentic-op, harmonize, validatekeep, but type: claude-skill is never used (all are slash commands)

Content-block fields:

FieldUsage
typeslide 394, prose 116, agent-context 4
class286 uses; keep
doc.render: false2 uses
slides:/doc: render: true3 redundant uses (defaults)
heading_levelnever read by anything
slides.rendernever read: the slides builder filters on type only
slides.layout_name0 uses (19 blocks wrongly use template: instead)

Proposed simplified content model

One file per topic, topics/<id>.md (or doc/source/architecture/<id>.md once in Galaxy):

---
id: dependency-injection
title: Dependency Injection
order: 6                      # replaces tutorial_number + previous_to/continues_to
subtitle: ...
contributors: [jmchilton]
time_estimation: 30m
questions: [...]
objectives: [...]
key_points: [...]
code_paths: [{path: lib/galaxy/app.py, note: ...}]
pull_requests: [{url: ..., note: ...}]
agentic_operations: [{name: review-di, prompt: ...}]
---

## The Problem
<!-- slide class="reduce90" layout="left-aligned" -->
...markdown...
???
speaker notes

---

<!-- docs-only -->
Longer prose only for Sphinx.

<!-- agent-only -->
Anti-patterns for review commands.

What the current structure buys:

What it costs:

The GTN slide format is already “markdown split on --- with class: lines”. The native Remark format is this format, so the slides builder mostly becomes: strip docs-only sections, prepend GTN front-matter. Conversion is mechanical: a one-shot script over the 16 content.yaml files, verifying rendered output is byte-identical before and after (except the template: fix).

Alternative if the YAML structure is kept: set extra='forbid', and delete file/fragments/separator, doc/slides sub-objects (replace with type + optional class/layout), heading_level, sphinx, and prerequisites. That is roughly 60% of models.py.

Build-script duplication and dead code

CLI arguments / Makefile (“cleaning up the arguments”)

Slash commands and agentic bits

CommandVerdict
research-topic, research-find-code-paths, plan-a-topickeep one merged “research → plan” command. The 3-step chain plus 2-agent plan merge produced the notes/plan dirs, which are now scratch.
research-prose-plan-with-code-pathsmerge into the above
generate-agentic-opkeep. This is the core docs → agent value.
harmonizekeep (docs ↔ existing-command feedback loop), maybe merge with generate
migrate-topiccut (migration done; wraps migrate_topic.py)
add-project-slidecut or make generic (“add slide to topic”). It’s ecosystem-specific.
annotate-topic-slides, resize-topic-contentkeep as authoring aids. They’re cheap. resize needs Playwright MCP.

Block type agent-context is used only 4 times (frameworks 1, tests 3). It’s cheap and on-mission, so keep it. generated_agentic_operations/ should be a build output that’s committed, or it should move straight into the plugin repo. The review/ copy-with-rename step (generated_commands.yaml) is an extra hop.

Concrete cleanup PRs (ordered, each small)

  1. Fix CI. Bump actions to Node-24 versions. Add npm ci plus a committed package.json/lock, or drop Mermaid CLI. Remove the duplicate PlantUML install. Make sphinx_image_linter.py exit non-zero when HTML is missing. Goal: green Deploy.
  2. Fix silent key drops. Add model_config = ConfigDict(extra='forbid') to all models. Rename the 19 template: keys to a real field. Delete hub:/claude:/sphinx.level/toc_depth. Add a builder test asserting layout: left-aligned appears.
  3. Delete planning cruft. PLAN.md, LAYOUT_PLAN.md, SPHINX_PLAN.md, MIGRATED.md, IMAGE_HANDLING.md, docs/OUTPUTS.md. Fold the vision into the README. Update .claude/CLAUDE.md (it still says “Current Topics: dependency-injection” and “Follow the PLAN.md phases”).
  4. Delete one-shot scripts. migrate_topic.py, plantuml_to_mindmap_yaml.py, validate_images.py, images/build.sh, and the migrate-topic command.
  5. Delete scratch dirs. topics/*/{notes,plan,suggestions,harmonize}, tests/plan.md, topics/files/fragments/, and generate_files_prose.py plus the validate-files target. Move anything worth keeping to galaxy-brain. Drop the suggestions/ warning in validate.py.
  6. Untrack generated files. Remove doc/source/architecture/*.md from git (gitignore it; build-sphinx regenerates it). Dedupe assets/GTNLogo1000.png.
  7. Trim the schema. Drop file/fragments/separator, doc/slides render sub-objects, heading_level, sphinx, prerequisites, and previous_to/continues_to (order by tutorial_number). Delete generate_schema_docs.py and docs/SCHEMA.md, or regenerate them.
  8. Clean up the builders.
    • Extract a shared topic_loader for resolving content and filtering blocks, used by both.
    • Keep one image-path rewrite function per target.
    • Delete the dead functions and move imports to the top.
    • Make the slides builder accept multiple topics / all; the Makefile loop goes away.
    • Add builder unit tests (speaker notes, pull directives, layout).
  9. Unify the CLI. Make the package installable (entry points, no sys.path.insert). Use consistent --topic/all semantics and env-var external roots. Simplify the Makefile.
  10. GTN decision (Q1). Either delete the 4 sync scripts (877 LOC) and 3 Make targets, or keep them behind gxarch sync-gtn.
  11. Split review/ into the claude-galaxy-plugins repo. Keep only generated_agentic_operations/ here.
  12. Convert content to markdown + front-matter (optional, biggest). Use a one-shot converter with a byte-identical-output check, then delete the YAML loaders.
  13. Consolidate docs. Merge DIAGRAM_GUIDE + MERMAID.md + images/README, and SLIDE_GUIDE + CONTRIBUTING, into ≤2 authoring guides ready for galaxy/doc/source/dev/.

Build health today (2026-09-26)

Open questions

  1. Does GTN stay a published target after migration (keep sync scripts), or does Galaxy Sphinx become the only output, with the GTN slides pointing to it?
  2. Is it OK to convert content.yaml to markdown + front-matter before migration, or migrate the YAML as-is?
  3. Mermaid: commit package.json/lock and install in CI, render client-side, or convert the 3 Mermaid diagrams to PlantUML?
  4. Where should review/ and the static commands live? Is claude-galaxy-plugins the owner?
  5. Keep related_topics (and render “See also”), or cut it?
  6. Keep the notes/ and plan/ research output anywhere (galaxy-brain), or discard it?
  7. Deploy failure root cause: re-run the workflow with fresh logs before PR 1?
  8. Should the “cleaning up the arguments” ask mean the CLI/Makefile args above, or something else (the rationale/“argument” for the POC)?