Adom Wiki
Public Made by Adomby adom
How the Adom Wiki (wiki.adom.inc) works and how to drive it with the adom-wiki CLI: the two storage layers (git page repo vs package registry), hosting source by pushing files (not a tarball), making packages, cutting per-platform releases, and the three-tier skill layout (user skills ship, dev-skills/ and publish-skills/ stay source-only). adom-wiki is the current tool; adompkg is deprecated. Read this first before publishing or installing.
Hardware taxonomy: component becomes hardware with first-class kinds (molecule, component, equipment)
Design + tracking issue for the taxonomy restructure Colby called for: the top-level component type becomes hardware, with first-class kinds underneath (molecule, component, equipment, and room for more). This is the largest structural change since the owner-namespace overhaul, so this issue is the full plan: model, wire contracts, staged rollout, migration mechanics, test strategy, risks, and open questions. Development happens on feat/hardware-taxonomy, validated against staging data before anything reaches main.
1. Why (the modeling argument)
type: component today conflates at least three structurally different things:
| What it really is | Example | Metadata it needs |
|---|---|---|
| A purchasable part | WS2812B-2020, LP5912Q1 | MPN, manufacturer, package, symbol/footprint/3D completeness |
| An Adom-built module | workcell mainboard, PM coil molecule | machine pins, BOM, placement renders, layout membership |
| Bench hardware / instruments | DSOX1204G scope, Red Pitaya | docs, calibration, drivers; often nothing installable |
Only the first fits component_metadata, which is why molecule pages have always sat awkwardly in the /components browser: wrong facets, wrong completeness chips, MPN fields that mean nothing. Tags cannot fix this, because the branches need different STRUCTURED metadata and different UI treatment. Different schema = different type, and that is the line between a kind and a tag.
The companion decision (from the tags-vs-categories discussion): tags remain the organic, cross-cutting layer underneath (kicad, rgb, power, 0603). Kinds are closed and curated; tags are open. Navigation composes both.
2. Target model
- Top-level types:
app | skill | hardware | bootstrap. (componentbecomes the legacy alias forhardware.) - New
kindaxis, only meaningful for hardware, stored in its own column and declared in page.json:
{ "type": "hardware", "kind": "molecule" }
- Initial kinds:
component,molecule,equipment. The enum is deliberately extensible (candidates the data already suggests:boardfor non-molecule assemblies like eval boards; decision below in Open Questions). - Each kind gets its own metadata home over time:
component_metadatastays the component kind's table; molecule and equipment metadata blocks come later (stage 4), not in the first cut. - Tags unchanged, on every type.
3. What type touches today (the honest blast-radius list)
- DB:
pages.type(+ CHECK constraints in places), queries keyed ontype = 'component'throughout server.js and lib/. - Disk: bare repos live at
data/repos/<owner>/<type>/<slug>— the type is a filesystem path segment. - Routes:
/componentslisting + facets,/viewer/*/:owner/:type/:slug,/blob/:type/:slug/*, readme routes. - Publish: manifest validation (
typeenum), discovery gate (apps/skills), hero gate, component auto-metadata extraction. - CLI: type enum in publish and install; install semantics key on type (component packages get CAD + auto-skill delivery).
- Content: every committed page.json carries the type string; external links reference /components.
- Home stats, search type chips, badges, cards.
The migration playbook exists: the namespace overhaul renamed a type before (bootstrap) with alias windows, and built the owner-keyed repo mover this will reuse.
4. Staged rollout
Stage 1 — kind exists, invisible to every client (this branch, first).
pages.kindcolumn (TEXT, addColumnIfMissing; NULL = unclassified).- page.json
kindfield, sanitized at index time (enum-checked; invalid values ignored with a publish hint). - Backfill classifier: a deferred sweep (same pattern as the skill-count sweep) classifies existing hardware pages by signals: MPN/manufacturer present = component; molecule signals (slug/tags/title, machine-pin metadata, molecule library membership) = molecule; explicit page.json wins over inference; everything ambiguous stays NULL and is listed for a human pass rather than guessed.
- Browse: the /components page gains kind sections/filters (component | molecule | equipment | unclassified), reusing the existing facet machinery. Cosmetic only; URLs unchanged.
- Publish hint
KIND_MISSING(info) nudges hardware publishers to declare a kind. - Nothing changes for the CLI, the API adds a passive
kindfield on page reads.
Stage 2 — the outward rename, dual-name window.
- Server accepts
type: hardware(+ kind) on publish and serves BOTH names: API responses carrytype: "hardware"pluslegacy_type: "component"(or the reverse during the window, decided with the CLI thread) so old clients keep working untouched. /hardwarebrowse becomes canonical;/components301s with the kind filter mapped.- Repo paths: new publishes land under
hardware/; existing repos migrated by the owner-keyed mover with symlink or lookup aliasing during the window. - CLI coordination issue: enum extension, and install semantics re-keyed on delivery behavior (unchanged behavior for all hardware kinds: CAD + auto-skill delivery exactly as component gets today).
- Committed page.json files: rewritten lazily on each page's next publish (the indexer treats
componentashardware+ inferred kind); no mass rewrite.
Stage 3 — legacy retirement, drain-gate keyed.
- When the client fleet and traffic show no
component-keyed consumers (same drain-gate discipline as every retirement this quarter), the alias becomes permanent-but-undocumented, then eventually removed from docs entirely. Nothing hard-breaks: aliases are cheap to keep.
Stage 4 — per-kind metadata (separate design).
molecule_metadata(machine pins, BOM ref, layout membership) andequipment_metadata(docs, drivers, cal) with their own completeness chips and facets. Out of scope here; filed separately when stage 2 settles.
5. Test strategy (per Colby: staging data as the test bed)
- All development on
feat/hardware-taxonomy; main stays deployable throughout. Nothing merges until stage 1 is green. - Classifier development is data-driven: a read-only dry run over the real page inventory (staging, plus prod read-only for volume, ~700 hardware pages) produces a classification report BEFORE the sweep ever writes a row. The report (counts per kind, the ambiguous list, per-page reasons) gets posted to this issue as the evidence base and human-pass worklist.
- Merging stage 1 to main deploys it to staging (normal flow); the backfill then runs against the real staging dataset and the browse sections are verified there against live data before the prod tag moves.
- Unit tests pin: sanitizer enum, classifier rules on synthetic + real-shaped rows, sweep idempotency, NULL-stays-NULL-for-ambiguous, hint firing, browse section rendering.
6. Risks
- Repo-path migration (stage 2) is the dangerous part: moving bare repos while the server runs. Mitigations exist (the namespace mover, per-repo write locks from the perf epic), and stage 2 does not start until stage 1 has soaked.
- CLI skew: the dual-name window plus drain gates make this boring, but the coordination issue must land before stage 2 merges.
- Classifier overreach: mitigated by explicit-declaration-wins, NULL-for-ambiguous, and the human worklist. The sweep never deletes or downgrades an explicit kind.
- External links: /components 301s forever; no link rot.
7. Open questions (Colby)
- Is
boarda fourth kind? The data has non-molecule assemblies (eval boards, breakouts, mainboards carrying molecules). Options: aboardkind, or fold them intomolecule(stretchy) orequipment(wrong). The dry-run report will show how many pages hang on this. - Equipment scope: instruments only (scope, Red Pitaya), or also machines (PnP line, laser)? Proposed: anything you point at on a bench that is not itself a part or a module.
- Naming during the window: which name the API leads with while both are valid (proposal:
hardwareleads immediately at stage 2,legacy_typecarriescomponent).
Branch: feat/hardware-taxonomy. Stage 1 starts now; the classification dry-run report lands as the first comment.







