Axis / Axis design rules
Axis design rules
Domain boundaries
- Organize the public library around a small set of domain concepts: Artifact,
Build, Builder, Environment, Executor, Instance, Operation, Package, Recipe,
OS, Target and Toolchain. Their reusable packages live under
build/,
outside internal/.
- Use exactly the same vocabulary in the spec, package and primary type:
Toolchain ->
build/toolchain/ -> toolchain.Toolchain in toolchain.go; Executor ->
build/executor/ -> executor.Executor (an interface is appropriate). Do not replace
the domain name with Manager, Engine, Runtime or Runner, or satisfy this rule
with a type alias over an unchanged abstraction.
- The operating-system concept is OS:
build/os/, os.OS, os.go,
build/os/README.md, and CLI label os. Do not introduce System as a synonym.
- Each concept owns its meaning, properties, behavior, auxiliary types and
utilities. Its public API defines how other concepts interact with it. APIs
must be reusable by callers outside this repository, with caller-supplied
resources and policy, and without internal types in their signatures.
- Consolidate implementation mechanisms under their owner. A TAR file, cache
receipt, workspace directory or progress renderer is not a new domain concept
merely because it needs code. Do not create placeholder packages for future
features or wrappers that leave the real behavior elsewhere.
- Keep CLI presentation and distribution wiring outside this ontology. Domain
code must not import the root application, terminal UI, application assets or a language
runtime. Lua and Docker are adapters; domain APIs accept native values and
interfaces. Observation events describe execution, not terminal lanes.
- Keep private shared utilities small. Prefer an owner’s private functions over
another package, and avoid generic utility frameworks or speculative APIs.
Recursive source and specification layout
- The repository root is Axis:
README.md links to build/, axisd/ and
base-os/. Source, specs, future user documentation and directory structure
follow the same recursive ownership tree, subject to language conventions.
- Each concept directory owns one canonical
README.md specification beside
its implementation: build/artifact/artifact.go + build/artifact/README.md.
Do not repeat the directory name in the spec filename. The index defines the
concept, its API and relationships, and links to child concepts. Auxiliary
types may have their own colocated documents, such as build/plan.md.
Keep native Markdown, fenced Mermaid and relative links; do not introduce a
parallel HTML specification or docs/specs/ tree.
- The user supplies the Markdown viewer. Keep
style.css self-contained and
importable, using inline axis-* spans for subtle concept colors. Mermaid
rendering belongs to the viewer. Do not add an HTML viewer or web runtime.
- Go keeps
main.go at the root as the Axis application entry point,
internal/ for application utilities, axisd/main.go for axisd and
build/internal for private construction utilities. Examples belong under examples/, with
generated build outputs ignored there, never by ignoring the source build/.
Specification dependency direction
- Each spec defines its own concept and introduces only its immediate children.
The Axis root describes Build System, Base OS and axisd, not their internals.
- A spec must be understandable using its own definitions and its descendants.
Do not require sibling or ancestor specifications. Explain collaboration and
cross-concept policy once, at the nearest common parent. Concrete local API
fields may retain their source names without importing another spec’s definition.
- Public APIs and imports between sibling packages remain allowed. Their parent
owns the relationship; each package owns its behavior and local contract.
- Move misplaced rules to their owner; do not merely hide a dependency by deleting
its link or repeat another concept’s full definition. Keep source package comments
aligned with the independent concept and lifecycle ownership aligned with code.
- Every Markdown document starts with a linked breadcrumb from Axis through its
documented owners to itself. Use relative whole-document links separated by ` / `.
Breadcrumbs are navigation and may link ancestors; body definitions still obey
downward ownership. Skip technical directories without their own specification.
- Markdown links target whole documents. Do not add explicit anchors, element IDs
or URL fragments, including same-page links. Keep ordinary Markdown headings and
inline semantic-color spans without IDs.
Files and documentation
- Organize files by the type/concept they own.
plan.go defines Plan and all
its operations; build.go defines Build and its operations. Keep receiver
methods with their type. Avoid splitting an object’s contract among files such
as model.go, handlers.go, configure.go or phase.go.
- Keep the package comment immediately above the package declaration in its main
implementation file (for example,
toolchain.go). Do not create doc.go files.
- Auxiliary values and private helpers may share their owner’s file. A separate
helper file is appropriate for a distinct implementation responsibility, not
to scatter methods of the same object.
- Each concept’s spec explains its meaning, properties, defined behaviors and
relationships. The package comment describes the same concept. Document the
concrete contracts on public types, fields, functions, methods and interfaces,
including ownership, errors, lifetime and concurrency where relevant.
- Update the owning spec and API documentation together. Distinguish implemented
behavior from future normative requirements. Never present a transport detail
as an ontological peer or unsupported behavior as implemented.
Verification
- Run focused behavior tests,
go test -race ./... and go vet ./... after domain
refactors. Preserve source fidelity, artifact/cache identities and cancellation.
- Run
python3 tools/check-docs.py after moving or editing specifications.
- Validate external-library use independently of the CLI. Docker integration
tests and OS boot acceptance are different evidence; state what actually ran.
- CLI labels preserve the actual domain concept and its color. Activities such as
source acquisition are phases of their owning concept, not invented entity kinds
or color aliases (for example,
acquired source package: linux).
- CLI phase progress must reflect declared units, never estimated percentages
inferred from arbitrary compiler output. Preserve complete tool bytes in logs.