Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Archkit Docs

Archkit docs home.

Use this book for two tracks:

  • AKS — language, grammar, examples, integration model
  • Archkit — CLI, project workflows, architecture, operations

Start here

Learn AKS

Use Archkit

Docs model

  • docs/src/ — mdBook entry pages, nav, wrappers
  • docs/AKS/ — authored AKS source docs
  • docs/guides/ — authored Archkit guides
  • docs/reference/ — curated reference docs
  • docs/architecture/ — ADRs, boundaries, system design
  • docs/operations/ — runbooks, CI, packaging, deploy

API docs

Use mdBook for product docs. Use rustdoc for crate API. See API Docs.

AKS: Architecture Knowledge Syntax

Welcome to the Architecture Knowledge Syntax (AKS) documentation. AKS is the native language for defining, modeling, and validating distributed system architectures in archkit.

What is AKS?

AKS is a domain-specific language (DSL) designed to model complex systems through:

  • Entities - System components (services, databases, external systems)
  • Shapes - Data structures and type definitions
  • Events - State changes and system communications
  • Relationships - Connections and dependencies between entities
  • Policies - Governance rules and constraints
  • Lattices - Domain-specific partial orders and refinements
  • Views - Projections for different stakeholders (dependency graphs, workflows, data flows)

Why AKS?

Modern distributed systems are complex. Traditional documentation and diagrams fall out of sync with code. AKS solves this by:

  • Single source of truth - One model drives all documentation, diagrams, and validation
  • Machine-readable - Parse and transform AKS into TypeScript, JSON Schema, Mermaid diagrams, and more
  • Type-safe - Shapes and events automatically generate type definitions for your code
  • Governance-first - Define policies and constraints that archkit can validate
  • Evidence-tracked - Know where every piece of architecture came from (code, documentation, or mirrored)

Quick Start

The 2-Minute Version

Create a file myapp.archkit.model.aks:

workspace "MyApp"
  module myapp@1.0.0

  shape User
    id: String
    email: String
    created_at: Timestamp
  end shape

  entity auth_service: User
    has role: orchestration
  end entity

  entity user_db database
  end entity

  entity frontend
    has role: presentation

    edge auth_service depends on
    end edge
  end entity
end workspace

Then ask archkit to validate it or generate types from it:

archkit parse -i myapp.archkit.model.aks
archkit generate code -i myapp.archkit.model.aks -t typescript.type -o generated/

Where to Go Next

I want to…

Core Concepts at a Glance

ConceptPurposeExample
WorkspaceRoot container for all architectureworkspace "MyApp" … end workspace
EntitySystem component (service, database, queue)entity user_db database … end entity
ShapeData structure or type definitionshape User … end shape
EventState change or messageevent UserCreated … end event
RelationshipDependency or connection between entitiesrelationship api calls db … end relationship
PolicyGovernance rule or constraintpolicy pii_encryption … end policy
LatticePartial order for domain-specific reasoninglattice Environment … end lattice
ViewProjection for specific audienceview revenue_overview … end view
EvidenceSource of truth (code, docs, mirror)derived from: "doc:checkout-design"

File Naming Convention

AKS files follow a predictable naming pattern:

<subject>.archkit.<kind>.<format>

Examples:
  workspace.archkit.model.aks              (authored model)
  tags.archkit.overlay.aks                 (overlay annotations)
  2026-06-30.cargo-workspace.archkit.mirror.aks  (timestamped mirror)
  • Subject: What the file describes (workspace, service, module)
  • Kind: model (authored), overlay (patches), mirror (auto-generated)
  • Format: Always aks for AKS files

Learning Path

Beginner

  1. Getting Started — Write your first model
  2. Examples: Systems Modeling — See progression from minimal to complex

Intermediate

  1. Core Concepts — Deep dive on each construct
  2. Grammar Reference — Detailed syntax rules
  3. Examples: Your Use Case — Type definition, governance, or data flow examples

Advanced

  1. Integration Docs — How archkit processes AKS
  2. Extension Framework — Custom validators, transformers
  3. Best Practices — Patterns for large models

Getting Help

Common Questions:

Need More?

FAQ

Q: Do I need AKS for every project? A: No. AKS is ideal for distributed systems with multiple components, complex dependencies, or governance needs. Simple microservices might not benefit.

Q: Can I use AKS with existing code? A: Yes. Archkit can mirror your Cargo workspace or Rustdoc and auto-generate an AKS model as a starting point.

Q: What if my system is too complex for AKS? A: Break it into modules. AKS supports multi-file models with imports.

Q: Can I generate code from AKS? A: Yes. Shapes and events automatically generate TypeScript, JSON Schema, and other type definitions. See Type Extraction.

Q: What formats does archkit export to? A: TypeScript, JSON Schema, Mermaid diagrams, Graphviz/DOT, and more. See Artifact Generation.


Ready? Start with Getting Started or jump to Examples.

Getting Started with AKS

Write your first AKS model in 15 minutes. We’ll build a simple e-commerce system step by step. Every snippet below parses with the real toolchain — the CI conformance test guarantees it.

Prerequisites

  • archkit CLI built (cargo build -p archkit-cli) or on your PATH
  • A text editor
  • 15 minutes

Step 1: Create Your First Model (2 min)

Create a file called ecommerce.archkit.model.aks:

workspace "Ecommerce"
end workspace

Two rules to notice immediately: the workspace name is a quoted string, and every block — including the workspace itself — closes with end <keyword>. Verify it:

archkit parse -i ecommerce.archkit.model.aks

Step 2: Add Your First Entities (2 min)

Entities are system components. Properties always take the has keyword:

workspace "Ecommerce"
  entity frontend
    has role: presentation
  end entity

  entity api
    has role: orchestration
  end entity
end workspace

Step 3: Define a Shape (2 min)

Shapes are typed data structures:

workspace "Ecommerce"
  shape Product
    id: String
    name: String
    price: Float
    in_stock: Bool
  end shape

  entity frontend
    has role: presentation
  end entity

  entity api
    has role: orchestration
  end entity
end workspace

Fields are name: Type. Add ? for optional (String?) and [] for lists (String[]).

Step 4: Add a Shape Reference (2 min)

An entity that owns/manages a data structure references it in the header:

entity api: Product
  has role: orchestration
end entity

Step 5: Add Dependencies (3 min)

Dependencies are edge blocks inside entities. depends on is one of the built-in edge phrases:

workspace "Ecommerce"
  shape Product
    id: String
    name: String
    price: Float
    in_stock: Bool
  end shape

  entity frontend
    has role: presentation

    edge api depends on
    end edge
  end entity

  entity api: Product
    has role: orchestration

    edge product_db depends on
    end edge
  end entity

  entity product_db database
  end entity
end workspace

Now we have a dependency chain: frontend → api → product_db. Note entity product_db databasedatabase is one of the built-in element kinds (database, queue, container, component, person, external system).

Step 6: Add an Event (2 min)

Events use the same field syntax as shapes and mark async messages:

event ProductPurchased
  product_id: String
  quantity: Int
  timestamp: Timestamp
end event

Add it inside the workspace alongside your shapes.

Step 7: Try archkit Commands (2 min)

Parse and validate:

archkit parse -i ecommerce.archkit.model.aks
# or the dedicated validator:
archkit-validate -i ecommerce.archkit.model.aks

Generate code from your shapes (TypeScript, JSON Schema, Python, Go, Protobuf, OpenAPI):

archkit generate code -i ecommerce.archkit.model.aks -t typescript.type -o generated/
archkit generate code -i ecommerce.archkit.model.aks -t json.schema -o generated/

Project a view:

archkit view file --help   # see projection options

Your First Complete Model

# Simple e-commerce system model
workspace "Ecommerce"
  module ecommerce@1.0.0

  shape Product
    id: String
    name: String
    price: Float
    in_stock: Bool
  end shape

  event ProductPurchased
    product_id: String
    quantity: Int
    timestamp: Timestamp
  end event

  entity frontend
    has role: presentation
    has description: "User-facing web application"

    edge api depends on
    end edge
  end entity

  entity api: Product
    has role: orchestration
    has description: "Backend API server"

    edge product_db depends on
    end edge
  end entity

  entity product_db database
    has description: "Data persistence layer"
  end entity
end workspace

Common Patterns

Modeling external systems

entity payment_gateway external system
  has description: "Stripe or similar"
end entity

Adding documentation

entity api
  has role: orchestration
  has description: "Main REST API. Implements GraphQL in v2.0"
end entity

Tagging for governance

entity api
  has tag critical
  has tag revenue_path
end entity

Troubleshooting

Parse error: “expected string, found Ident” — quote the workspace name: workspace "Ecommerce".

Parse error: “expected newline, found Ident” inside an entity — you wrote a bare key: value; entity properties need has key: value.

Parse error: “expected ‘end entity’” — every block needs its end <keyword> closer.

Parse error mentioning tabs — AKS indentation is spaces-only.

More in TROUBLESHOOTING.md.

Next Steps

Core Concepts

The mental model behind AKS: what each construct is for and how they compose. All snippets here are validated against the real parser in CI.

Workspaces

A workspace is the root container — one per file, quoted name, explicit end workspace:

workspace "Commerce"
  module commerce@1.0.0
end workspace

The optional module <name>@<version> line versions the model itself.

Entities

Entities are the nodes of your architecture graph: services, databases, queues, people, external systems.

entity checkout_api
  has role: orchestration
  has description: "Order checkout flow"
  has tag critical
end entity

Entity kinds

Structural classification uses the built-in kind vocabulary in the header:

entity payments_db database
end entity

entity events queue
end entity

entity stripe external system
end entity

Kinds: database, queue, container, component, person, external system. An entity without a kind is generic.

Entity properties and tags

  • has <key>: <value> — arbitrary properties (strings, numbers, booleans, identifiers, lists, objects)
  • has tag <name> — tags, the primary grouping mechanism for views and policies

The has keyword is required — bare key: value lines are a parse error in entity bodies.

Shapes (Data Structures)

Shapes define typed data structures — the input to type modeling and code generation.

Basic shape

shape User
  id: String
  email: String
  age: Int
end shape

Nested shapes

Reference other shapes by name:

shape Address
  street: String
  city: String
end shape

shape User
  id: String
  address: Address
end shape

Collections and optionals

shape Order
  id: String
  item_ids: String[]
  coupon: String?
  audit_trail: Json
end shape

T[] list, T? optional, suffixes stack (String?[]), Json for open key-value data. Map/tuple/union types and field constraints (@min etc.) are not part of the grammar — model invariants as policies.

Events (State Changes)

Events are shapes with async/message semantics — same field grammar, different keyword:

event OrderPlaced
  order_id: String
  user_id: String
  timestamp: Timestamp
end event

Events vs shapes: use event for records of things that happened (past-tense names), shape for commands, entities’ data, and value objects.

Relationships

Two ways to express edges in the graph:

Local edges (inside the entity)

entity checkout_api
  edge payments_db depends on
    has via: "SQL"
  end edge
end entity

Standalone relationships

relationship checkout_api calls payment_service
  has protocol: https
end relationship

Both use the same phrase vocabulary (calls, depends on, sends data to, publishes, subscribes, produces, consumes, … — see grammar §6). Unknown single words become custom phrases.

Shape conformance

An entity that owns/implements a data structure references the shape in its header:

entity user_service: User
  has role: orchestration
end entity

Multiple services may reference the same shape; an entity can reference at most one shape directly (model composites with edges or tags).

Provenance (Evidence)

Track where a claim about the architecture comes from:

entity checkout_api
  derived from: "doc:checkout-design"
  evidenced by: "trace:prod:checkout"
  verified by: "test:integration-suite"
end entity

Verbs: derived from, evidenced by, observed in, verified by, deprecated by. Provenance also attaches to edges and relationships. Values conventionally encode a source category prefix (doc:, trace:, test:, mirror:, code:).

Governance: Lattices and Policies

Lattices define ordered domains; policies state rules over the graph:

lattice Tier
  order best_effort < standard < critical
end lattice

policy critical_ownership
  applies to tag: critical
  must have owner
  requires tier at least standard
end policy

See grammar §8–9 and the governance examples.

Views and Projects

Views are filtered projections for diagrams; projects bundle entities with configuration:

view revenue_overview
  kind: system
  schema: c4
  include: tag: revenue_path
  focuses_on: checkout_api
end view

project checkout_system
  includes entity checkout_api
  has team: payments
end project

A Complete Workspace

workspace "Commerce"
  module commerce@1.0.0

  # Data structures
  shape Product
    id: String
    price: Float
  end shape

  # Events
  event ProductPurchased
    product_id: String
    timestamp: Timestamp
  end event

  # System components
  entity storefront
    has role: presentation

    edge catalog_api depends on
    end edge
  end entity

  entity catalog_api: Product
    has role: orchestration
    has tag critical
    has owner: catalog_team

    edge catalog_db depends on
    end edge
  end entity

  entity catalog_db database
  end entity

  # Governance
  policy critical_ownership
    applies to tag: critical
    must have owner
  end policy

  # Projection
  view overview
    kind: system
    schema: c4
    include: tag: critical
  end view
end workspace

Next

AKS Reference Index

Complete index to AKS documentation and resources.

Just starting?

Learning by example?

Need syntax?

Generating code?

Stuck?


Documentation Structure

docs/AKS/
├── README.md                        # Start here
├── GETTING_STARTED.md              # 15-minute introduction
├── CORE_CONCEPTS.md                # Detailed explanations
├── BEST_PRACTICES.md               # Patterns & recommendations
├── TROUBLESHOOTING.md              # Error solutions
├── MIGRATION.md                    # v1 → v2 upgrade
├── REFERENCE.md                    # This file
│
├── grammar/                        # Syntax reference (authoritative)
│   ├── README.md
│   ├── FULL_GRAMMAR.md            # Complete grammar + EBNF
│   └── LEXICAL_RULES.md           # Tokens & keywords
│
├── examples/                       # Runnable, CI-validated examples
│   ├── README.md                  # How to use examples
│   ├── PROGRESSION.md             # Learning path
│   ├── 01-systems-modeling/       # Model architecture
│   ├── 02-type-definition/        # Generate code
│   ├── 03-governance-policies/    # Add policies
│   └── 04-data-flow-events/       # Model events
│
└── integration/                    # How archkit works
    ├── README.md                  # Pipeline overview
    ├── HOW_ARCHKIT_USES_AKS.md    # Parse → workspace
    ├── ARTIFACT_GENERATION.md     # Output formats
    ├── TYPE_EXTRACTION.md         # Shapes → code
    ├── GRAPH_MODEL.md / GRAPH_EXAMPLES.md
    ├── EDGES_AND_PROVENANCE.md
    ├── LATTICE_DEEP_DIVE.md / POLICY_DEEP_DIVE.md
    ├── OPERATIONS_AND_PROJECTS.md
    └── EXTENSION_PIPELINE.md      # Custom extensions

By Use Case

I want to model a system

  1. Read README.md
  2. Try GETTING_STARTED.md
  3. Follow Systems Modeling Examples
  4. Reference Best Practices

I want to generate code

  1. Read Type Extraction
  2. Try Type Definition Examples
  3. Use archkit generate code -i model.aks -t typescript.type
  4. See Artifact Generation

I want to add governance

  1. Read CORE_CONCEPTS.md (policies section)
  2. Try Governance Examples
  3. Reference Grammar: Policies
  4. See Best Practices (policies section)

I want to model events

  1. Try Data Flow Examples
  2. Read CORE_CONCEPTS.md (events section)
  3. Reference Grammar: Shapes & Events

I want to understand archkit internals

  1. Read Integration README
  2. Study How Archkit Uses AKS
  3. Explore ARTIFACT_GENERATION.md
  4. See parser source: crates/archkit-frontend/src/aks/

I want to extend archkit

  1. Read Extension Pipeline
  2. See full guide: docs/guides/AKS_EXTENSION_FRAMEWORK.md
  3. Reference existing extensions in codebase

Command Reference

Parsing & Validation

archkit parse -i workspace.aks
# Parse and lower through the full frontend

archkit-validate -i workspace.aks
# Dedicated validator binary (same pipeline, JSON output options)

archkit check --help
# Project-level checks (schema, layout, policies)

Code Generation

archkit generate code -i workspace.aks -t typescript.type -o generated/
archkit generate code -i workspace.aks -t json.schema   -o generated/
archkit generate code -i workspace.aks -t python.type   -o generated/
# Targets: json.schema, typescript.type, python.type, go.type,
#          protobuf.type, openapi.schema

Views & Reports

archkit view file --help        # project a view from a single file
archkit report --help           # drift, health, compatibility reports

Help

archkit --help
archkit parse --help
archkit generate --help

Glossary

TermDefinition
WorkspaceRoot container for all architecture
EntitySystem component (service, database, queue)
ShapeData structure or type definition
EventImmutable record of something happening
RelationshipConnection between entities (dependency, conformance)
ConformanceEntity conforms to / implements a shape
DependencyEntity requires/depends on another entity
LatticePartial order for domain-specific reasoning
PolicyGovernance rule or constraint
EvidenceSource of truth (code, mirror, authored, observation)
ViewProjection for specific stakeholder
ModuleSub-workspace for organization
OverlayAdditional annotations/properties
MirrorAuto-generated snapshot from code

File Naming

<subject>.archkit.<kind>.<format>

Examples:
  workspace.archkit.model.aks
  security.archkit.overlay.aks
  2026-06-30.cargo-workspace.archkit.mirror.aks

Kinds: model, overlay, mirror
Format: Always 'aks'

Quick Syntax

Basic Structure

workspace "MyApp"
  module myapp@1.0.0

  shape User
    id: String
    email: String
  end shape

  entity user_service: User
    has role: orchestration

    edge user_db depends on
    end edge
  end entity

  entity user_db database
  end entity
end workspace

Common Keywords

KeywordPurpose
workspaceRoot container (quoted name, end workspace)
moduleModel version (module name@version)
shapeData structure
eventAsync message/state change
entitySystem component (node)
edgeLocal relationship inside an entity
relationshipStandalone edge between entities
hasProperty/tag prefix in entity bodies
policyGovernance rule
latticeOrdered domain (chains)
derived from / verified by / …Provenance verbs

Element Kinds and Roles

Structural kinds go in the entity header; roles are a has property convention:

  • Kinds: database, queue, container, component, person, external system
  • Role convention (has role: …): presentation, orchestration, storage, messaging, external, observability

Common Types

  • String, Int, Float, Bool, Timestamp — named types (conventions; names are not validated at parse time)
  • Json — untyped JSON (the only special-cased name)
  • Type? — optional (suffix)
  • Type[] — list (suffix)

There are no map, tuple, or union type literals — use Json.


Tips & Tricks

Validate

archkit parse -i workspace.aks
archkit-validate -i workspace.aks --json-out validation.json

Generate Code from Shapes

for target in typescript.type json.schema python.type go.type; do
  archkit generate code -i workspace.aks -t $target -o generated/
done

Project Checks (drift, layout, health)

archkit check --help
archkit report --help

Debug Issues

archkit parse -i workspace.aks -v 2>&1 | head -50

External Resources

Project System

Archkit API

  • Public API: crates/archkit/src/lib.rs
  • Type System: crates/archkit-type-model/src/lib.rs
  • Extensions: crates/archkit-extensions/src/lib.rs

Common Tasks

TaskReference
Write first modelGETTING_STARTED.md
Learn conceptsCORE_CONCEPTS.md
Find syntaxGrammar
Model systemSystems Examples
Generate typesType Extraction
Add policyGovernance Examples
Model eventsData Flow Examples
Fix errorTroubleshooting
Migrate v1MIGRATION.md
Extend archkitExtension Pipeline

Getting Help

Documentation Flow

1. Start with README.md
   ↓ (What is AKS?)
2. Try GETTING_STARTED.md
   ↓ (15-minute intro)
3. Pick your path:
   ├─ Examples (learn by doing)
   ├─ Core Concepts (deep dive)
   ├─ Grammar (syntax reference)
   └─ Integration (understand internals)
4. When stuck: Troubleshooting
   ↓ (solve specific errors)
5. Advanced: Best Practices
   ↓ (patterns at scale)

Support Checklist


Site Map

Main Entry Points:

Learning:

Reference:

Integration:

Support:


Ready to start? → Go to README.md or GETTING_STARTED.md

Have an error? → See TROUBLESHOOTING.md

Want to learn? → Try Examples or CORE_CONCEPTS.md

Need syntax? → Go to Grammar

Best Practices

Patterns and recommendations for effective AKS modeling. All ```aks snippets are CI-validated against the real parser.

File Organization

Single-File Models

For small systems (< 20 entities):

workspace/
├── workspace.archkit.model.aks     (main model)
└── README.md                       (documentation)

Project-System Layout

For larger systems, use the archkit project system (archkit project init) and its directory ownership rules:

project/
├── authored/     *.archkit.model.aks     (hand-written models)
├── overlays/     *.archkit.overlay.aks   (annotations; separate dialect)
├── mirror/       YYYY-MM-DD.*.archkit.mirror.aks  (auto-generated)
├── generated/    (schemas, types — auto-generated, do not edit)
└── reports/      (drift, health — auto-generated)

See docs/guides/PROJECT_SYSTEM.md for the full ownership table.

File Naming

  • Model files: *.archkit.model.aks
  • Overlay files: *.archkit.overlay.aks
  • Mirror files: YYYY-MM-DD.source.archkit.mirror.aks

Naming

Entities: snake_case ids

entity user_service
end entity

entity product_db database
end entity

entity event_bus queue
end entity

Entity ids are graph node ids — keep them short, lowercase, and stable; they appear in edges, views, and policies.

Shapes and events: PascalCase, singular

shape User
  id: String
end shape

event UserCreated
  user_id: String
end event

Shapes are singular (User, not Users); events are past-tense (UserCreated, not CreateUser — that’s a command shape).

Fields: snake_case

shape User
  user_id: String
  created_at: Timestamp
end shape

Modeling Patterns

Layered architecture

Dependencies point downward: presentation → orchestration → storage.

entity web_frontend
  has role: presentation

  edge api_gateway depends on
  end edge
end entity

entity api_gateway
  has role: orchestration

  edge user_service depends on
  end edge
end entity

entity user_service
  has role: orchestration

  edge user_db depends on
  end edge
end entity

entity user_db database
end entity

Data ownership

One service owns the authoritative copy — express it with a shape reference; consumers depend on the owner, not the shape:

shape User
  id: String
  email: String
end shape

entity user_service: User
  has role: orchestration
end entity

entity order_service
  edge user_service depends on
  end edge
end entity

Event-driven communication

Prefer pub/sub through a bus over direct coupling:

entity user_service
  edge event_bus publishes
    has emits: UserCreated
  end edge
end entity

entity notification_service
  edge event_bus subscribes
    has listens_for: UserCreated
  end edge
end entity

entity event_bus queue
end entity

Governance with tags

Tags are the selector mechanism for policies and views — tag consistently:

entity checkout_api
  has tag critical
  has tag revenue_path
  has owner: payments_team
end entity

policy critical_ownership
  applies to tag: critical
  must have owner
end policy

Documentation

Descriptions and properties

entity user_service
  has role: orchestration
  has description: "Manages user authentication and profiles"
  has owner: platform_team
end entity

Provenance

Track where every claim comes from with the built-in verbs:

entity user_service
  has role: orchestration
  derived from: "code:src/services/user_service.rs"
  verified by: "test:integration-suite"
end entity

Prefix values by source category: code:, doc:, trace:, test:, mirror:, authored:.

Comments

# This dependency exists for legacy compatibility (v1.x);
# remove when decommissioning the old API.
entity old_api
  edge legacy_service depends on
  end edge
end entity

Avoid Anti-Patterns

❌ Circular dependencies

If a → b → c → a, break the cycle with an event bus or an intermediary:

entity a
  edge event_bus publishes
  end edge
end entity

entity b
  edge event_bus subscribes
  end edge
end entity

entity event_bus queue
end entity

❌ Everything depending on everything

Introduce an aggregator so consumers have a single dependency:

entity api_gateway
  has role: orchestration

  edge user_service depends on
  end edge
  edge order_service depends on
  end edge
end entity

entity frontend
  edge api_gateway depends on
  end edge
end entity

❌ Overly generic shapes

value: Json everywhere defeats type modeling. Create specific shapes:

shape User
  id: String
  email: String
  name: String
end shape

Reserve Json for genuinely open data (metadata, config).

❌ Untagged, roleless entities

Policies and views select on tags and properties — an entity with neither is invisible to governance:

entity user_service
  has role: orchestration
  has tag service
end entity

Validation

Validate on every change; wire it into CI:

archkit parse -i workspace.archkit.model.aks
archkit-validate -i workspace.archkit.model.aks

# Project-level checks (drift, layout, health):
archkit check --help
archkit report --help

Versioning

Version the model with the module line and bump it like semver:

workspace "MyApp"
  module myapp@1.2.3
end workspace
  • MAJOR — breaking architecture changes
  • MINOR — new services/shapes
  • PATCH — fixes, refinements

Troubleshooting

Real error messages from the AKS parser and how to fix them. Errors include line:column positions. Validate any file with:

archkit-validate -i workspace.aks
# or
archkit parse -i workspace.aks

Parse Errors

expected string, found Ident("...") (at 1:11)

Cause: unquoted workspace name.

workspace Ecommerce        # WRONG

Fix:

workspace "Ecommerce"
end workspace

expected newline, found Ident("...") in an entity body

Cause: bare key: value property — entity properties require has.

entity api
  role: orchestration      # WRONG
end entity

Fix:

entity api
  has role: orchestration
end entity

expected 'end <kind>' / unexpected token in declarations

Cause: a block was never closed, or closed with the wrong keyword. Every block needs its own end:

workspace "Demo"
  shape User
    id: String
  end shape

  entity api
  end entity
end workspace

Also raised when an end at the wrong indentation level makes the parser see a mismatched block boundary — the end <kind> must sit at the opener’s indentation, not the body’s.

tabs not allowed in indentation (use spaces only)

Cause: a tab character anywhere in leading whitespace. Convert to spaces; AKS never accepts tabs.

expected type, found LBracket / expected type, found Question

Cause: prefix type syntax from other languages. AKS types use suffixes:

items: [OrderItem]     # WRONG   (prefix list)
phone: ?string         # WRONG   (prefix optional)

Fix:

shape Order
  items: OrderItem[]
  phone: String?
end shape

expected newline, found At

Cause: field constraint annotations (@min(0), @pattern(...)) — these are not part of the grammar. Remove them; express invariants as policies.

unknown element kind '...'

Cause: a word after the entity id that isn’t a kind. Only database, queue, container, component, person, external system are valid there:

entity payments_db database
end entity

If you meant a shape reference, use a colon: entity api: Service.

unexpected keyword in view: ...

Cause: unsupported view body keyword. Views accept exactly kind:, schema:, include:, exclude:, focuses_on: (note the spelling — not focus_on), and layout (bare keyword, no colon):

view overview
  kind: system
  schema: c4
  include: tag: critical
  focuses_on: checkout_api
  layout
    rankdir: LR
end view

unknown selector type: ...

Cause: view selectors are limited to entity:, tag:, and relationship:. There is no tier: or other custom selector — put the property on a tag and select the tag.

unsupported lattice syntax 'level' (also covers, join, meet)

Cause: partial-order lattice syntax is reserved but not implemented. Only chains work:

lattice Env
  order dev < staging < prod
  bottom dev
  top prod
end lattice

expected identifier, found <Keyword>

Cause: using a reserved word (event, view, order, top, …) as an entity id or property key. Rename it (has emits: instead of has event:). Full reserved list: grammar §17.

unexpected character '*' (or =, +, ->)

Cause: characters outside the AKS token set — often inside expands to blocks, whose bodies must still lex as AKS tokens.

expected newline, found LBrace

Cause: brace-block syntax (entity Foo { ... }) from other modeling languages. AKS uses indentation + end markers, never braces — except as property values (has config: {timeout: 30}), which are fine.

Lowering Errors (Parse Succeeds, Validation Fails)

expression: unexpected end in operation

Known limitation: <> op operation trees in the expression sub-language parse but do not lower yet — only variable/constant forms (o quantity) survive the full pipeline.

Lattice bottom/top mismatch

bottom must name the first element of the chain and top the last; anything else fails during lowering with an explicit message.

Overlay Files Fail to Parse

*.overlay.aks files containing annotate <id> { ... } blocks are a separate dialect processed by the project system (archkit-project), not the workspace grammar. Do not feed overlay files to archkit parse; they are applied through project operations (archkit project ...).

Still Stuck?

Migration Guide: Legacy Dialects → Current AKS

Two legacy dialects appear in old documents and models:

  1. v1 (brace-based)app MyApp { ... }, data, relates_to
  2. Terse draft (indentation, no end markers)workspace MyApp, bare role: properties, depends_on: / conforms_to: lines

Neither parses with the current toolchain. This guide maps both onto the implemented grammar. Old-dialect snippets below are tagged as plain text because they are intentionally not valid AKS; every ```aks snippet is CI-validated.

Quick Mapping Table

LegacyCurrent AKS
app MyApp {} / workspace MyAppworkspace "MyApp" … end workspace
version 1.0.0module myapp@1.0.0
data User { … }shape User … end shape
role: storage (bare)has role: storage
conforms_to: Userentity <id>: User (shape ref in header)
depends_on: X / relates_to:edge x depends on … end edge
produces: E / subscribes_to: Xedge E produces / edge x subscribes
evidence: "src"provenance verbs: derived from:, verified by:, …
[Type]Type[]
?typeType?
{string: Type}Json
@min(0) constraintsnot supported — model as policies
policy: "prose"named policy <id> … end policy blocks
lattice X + a < blattice X + order a < b
role: externalentity <id> external system

Side-by-Side

Workspace

Legacy:

app MyApp {
  version: "1.0.0"
}

workspace MyApp
  version 1.0.0

Current:

workspace "MyApp"
  module myapp@1.0.0
end workspace

Entities and dependencies

Legacy:

entity UserService {
  role: "orchestration"
  depends_on: ["UserDB"]
}

entity UserService
  role: orchestration
  depends_on: UserDB

Current:

entity user_service
  has role: orchestration

  edge user_db depends on
  end edge
end entity

entity user_db database
end entity

Shapes

Legacy:

data User {
  fields: {
    id: "string"
    email: "string"
  }
}

shape User
  id: string
  email: string

Current:

shape User
  id: String
  email: String
  created_at: Timestamp
end shape

Conformance

Legacy:

entity UserService
  conforms_to: User

Current — the shape reference lives in the entity header:

entity user_service: User
  has role: orchestration
end entity

Events and messaging

Legacy:

entity EventBus
  role: messaging
  produces: UserCreated

entity NotificationService
  subscribes_to: EventBus
    listens_for: UserCreated

Current:

entity event_bus queue
  edge UserCreated produces
  end edge
end entity

entity notification_service
  edge event_bus subscribes
    has listens_for: UserCreated
  end edge
end entity

Policies

Legacy:

policy: "PII data must be encrypted"
  applies_to: Sensitivity.pii

Current:

policy pii_encryption
  applies to tag: pii_handler
  when sensitivity at least pii
  requires encryption: enabled
end policy

Evidence

Legacy:

entity Service
  evidence: "code:src/main.rs line 42"

Current — use the closed provenance verbs:

entity service
  derived from: "code:src/main.rs line 42"
  verified by: "test:integration-suite"
end entity

Migration Steps

  1. Quote the workspace name and add end workspace.
  2. Close every block with end <keyword> (end shape, end entity, …).
  3. Prefix entity properties with has; convert conforms_to: into a header shape reference; convert role external into the external system kind.
  4. Convert relationship properties to edges (edge <target> <phrase> with end edge), or standalone relationship <from> <phrase> <to> blocks.
  5. Fix types: [T]T[], ?TT?, maps → Json, drop @ constraints.
  6. Rewrite policies as named blocks with applies to selectors.
  7. Validate: archkit parse -i model.aks — errors include line:column; see TROUBLESHOOTING.md for each message.

Reference

  • Current grammar: grammar/FULL_GRAMMAR.md
  • Validated examples of every construct: examples/
  • Historical record of the v1 dialect: docs/reference/aks-syntax-migration.md (archived analysis)

AKS Examples

This section contains runnable AKS examples organized by use case, each with progressive complexity.

Choose Your Path

Pick the use case that matches your needs:

1. Systems Modeling

Learn: How to define system architecture, entities, dependencies, and layers.

Good if:

  • You’re designing a new microservices system
  • You need to document existing architecture
  • You want dependency validation

Progression:

  • 01-minimal/ - One entity, one shape (5 lines)
  • 02-microservices/ - Multi-service system with layers (50 lines)
  • 03-distributed-system/ - Complex system with overlays and evidence (200+ lines)

2. Type Definition

Learn: How to model data structures and generate TypeScript/JSON Schema.

Good if:

  • You need to generate types for your code
  • You want a single source of truth for data models
  • You’re building type-safe APIs

Progression:

  • 01-basic-shapes/ - Simple shapes → TypeScript (20 lines)
  • 02-event-sourcing/ - Events and event types (50 lines)
  • 03-complex-types/ - Nested shapes, generics, constraints (100+ lines)

3. Governance & Policy

Learn: How to define policies, constraints, and domain rules.

Good if:

  • You need to enforce architecture decisions
  • You’re modeling compliance or governance
  • You want to define domain-specific rules

Progression:

  • 01-simple-constraints/ - Basic policy rules (20 lines)
  • 02-domain-lattices/ - Partial orders and refinement rules (50 lines)
  • 03-governance-framework/ - Complex compliance framework (150+ lines)

4. Data Flow & Events

Learn: How to model events, event streams, and data transformations.

Good if:

  • You’re building event-driven systems
  • You need to track data flow through your system
  • You want to validate event causality

Progression:

  • 01-basic-events/ - Simple event definitions (20 lines)
  • 02-event-streams/ - Stores and event producers (60 lines)
  • 03-event-sourcing-pipeline/ - Full CQRS/ES system (150+ lines)

How to Use These Examples

Each example has:

  1. workspace.aks - The actual AKS model
  2. EXPLANATION.md - Detailed walkthrough of concepts
  3. Generated outputs (where applicable):
    • *.ts - Generated TypeScript types
    • *.json - Generated JSON Schema
    • *.mmd - Mermaid diagrams

Running an Example

Navigate to any example and try:

cd examples/01-systems-modeling/01-minimal

# Parse and validate
archkit parse workspace.aks

# Generate diagram
archkit view file -i workspace.aks --output diagram.mmd

# Generate TypeScript types
archkit generate code -i workspace.aks -t typescript.type -o generated/

# Generate JSON Schema
archkit generate code -i workspace.aks -t json.schema -o generated/

Reading an Example

  1. Start with the first file in each progression (e.g., 01-minimal/)
  2. Skim the workspace.aks file (notice the syntax)
  3. Read EXPLANATION.md for detailed commentary
  4. Try running the commands above
  5. Move to the next complexity level

Learning Paths

Path 1: Beginner (30 min)

Path 2: Type Generation (45 min)

Path 3: Governance (45 min)

Path 4: Complete Walkthrough (2 hours)

  • Follow all progressions in order (1→2→3→4)
  • Read EXPLANATION.md for each
  • Try generating outputs for each

Quick Reference

Each example folder contains:

examples/
  01-systems-modeling/
    README.md                          (use case intro + progression)
    01-minimal/
      workspace.aks                    (the model)
      EXPLANATION.md                   (detailed walkthrough)
    02-microservices/
      workspace.aks
      entities.txt                     (entity reference)
      EXPLANATION.md
    03-distributed-system/
      workspace.aks
      overlays/
        tags.aks
        policies.aks
      EXPLANATION.md

Progression Complexity Matrix

LevelExampleLOCConstructsConcepts
Beginnersystems 01-minimal10entity, shapeBasics
type 01-basic-shapes20shapeType definition
Intermediatesystems 02-microservices50entity, depends_on, shapeLayers, dependencies
type 02-event-sourcing50event, shape, conforms_toEvents
governance 02-lattices50lattice, policyDomain rules
Advancedsystems 03-distributed200+overlays, evidence, modulesComplexity at scale
type 03-complex-types100+nested shapes, constraintsType sophistication
governance 03-framework150+complex policies, evidenceCompliance

Tips

Debugging an example:

  • Check indentation (AKS uses off-side rule)
  • Verify all strings are quoted
  • Run archkit parse to validate
  • See Troubleshooting for common errors

Modifying an example:

  • Copy the .aks file to your project
  • Edit entities and shapes to match your system
  • Run archkit generate code to generate output
  • See Best Practices for patterns

Want more?


Pick a use case above and dive in!

AKS Grammar Reference

Authoritative syntax specification for the Architecture Knowledge Syntax language, derived from and validated against the real parser in crates/archkit-frontend/src/aks/.

Contents

  • FULL_GRAMMAR.md — every construct with rules, verified examples, and an EBNF summary. Start here.
  • LEXICAL_RULES.md — tokens, keywords, indentation, closed phrase tables, string/number rules

Guarantees

Every ```aks fenced example in these documents (and everywhere else under docs/) is parsed and lowered by the real frontend in CI: crates/archkit-frontend/tests/docs_aks_conformance.rs. If a snippet stops matching the implementation, the test suite fails.

Examples that intentionally show invalid syntax use ```text fences.

Quick Navigation

Validating Your Own Files

cargo run -p archkit-cli --bin archkit-validate -- -i workspace.aks
# or through the main CLI:
archkit parse --input workspace.aks
  • Working examples (also CI-validated): ../examples/
  • How AKS lowers into the workspace/substrate model: ../integration/HOW_ARCHKIT_USES_AKS.md
  • Overlay files (annotate blocks in overlays/) are a separate dialect handled by archkit-project, not this grammar
  • Parser source: crates/archkit-frontend/src/aks/parser/
  • Lexer source: crates/archkit-frontend/src/aks/lexer/

AKS Full Grammar Reference

This is the authoritative grammar specification for AKS (Architecture Knowledge Syntax). Every ```aks example in this document is validated against the real parser by crates/archkit-frontend/tests/docs_aks_conformance.rs — if it’s written here, it parses.

Grammar style: off-side rule (indentation-sensitive) with explicit end <keyword> block closers. Parser: hand-written lexer + recursive-descent parser in crates/archkit-frontend/src/aks/.


1. High-Level Structure

Every AKS file contains exactly one workspace block. The workspace name must be a quoted string. Nine kinds of declaration may appear inside, in any order.

workspace "Commerce"
  module commerce@v1

  shape Service
    id: String
  end shape

  entity checkout_api: Service
    has tag critical
  end entity
end workspace

Rules:

  • Must start with workspace "name" (quoted string, not a bare identifier)
  • Optional module <name>@<version> immediately after the header
  • Declarations: shape, event, entity, relationship, lattice, policy, operation, project, view
  • Every block closes with end <keyword>, including end workspace
  • Indentation is significant: spaces only, one level per block

2. Module Declaration (Optional)

workspace "Demo"
  module archkit_core@v2.0
end workspace

Rules:

  • Optional; appears immediately after the workspace header
  • Syntax: module <identifier>@<version> — the version is free text to end of line (v1, 2.0, 1.2.3-beta all work) and must be non-empty
  • end module is optional

3. Shapes (Data Structures)

shape Account
  id: String
  email: String
  balance: Float?
  tags: String[]
  fallbacks: String?[]
  metadata: Json
end shape

shape EmptyShape
end shape

Rules:

  • shape <identifier> followed by newline
  • Fields are name: TypeExpr, one per line, indented
  • end shape required; empty shapes allowed

Type expressions (implemented):

SyntaxMeaning
Namenamed type (String, Int, Float, Bool, or any shape name — names are not validated at parse time)
Jsonuntyped JSON (the only special-cased type name)
T?optional
T[]list
suffix stackingString?[] = list of optionals

Not implemented (do not use): [T] prefix lists, {k: T} map types, (T1, T2) tuples, T1 | T2 unions. The AST reserves nodes for map/tuple/union, but no surface syntax produces them.


4. Events

Events use identical field syntax to shapes; the keyword marks async message/event semantics.

event OrderPlaced
  order_id: String
  customer_id: String
  amount: Float
end event

5. Entities (Instances / Nodes)

Header forms

entity plain_node
end entity

entity account1: Account
end entity

entity payments_db database
end entity

entity stripe external system
end entity
  • entity <id> — generic kind
  • entity <id>: <ShapeName> — with shape reference
  • entity <id> <kind> — with element kind. Kind vocabulary: database, queue, container, component, person, and the two-word phrase external system. Any other word in kind position is a parse error.

Body

entity checkout_api: Service
  has tag critical
  has tag revenue_path
  has owner: payments_team
  has sla: "4 hour response"
  has config: {timeout: 30, retries: 3}
  has regions: ["us-east", "eu-central"]
  derived from: "service-catalog:checkout_api"
  verified by: "arch-review:AR-2026-041"

  edge payment_service calls
    has protocol: https
    verified by: "trace:prod:checkout/payment"
  end edge

  edge notification_queue sends data to
    has async: true
  end edge
end entity

Body items (all optional, repeatable):

  • has tag <identifier> — attach a tag
  • has <key>: <value> — attach a property (the has keyword is required; bare key: value lines are not valid in entity bodies)
  • provenance clauses (§7)
  • edge <target> <phrase> … end edge — local edges (§6 phrase vocabulary); edge bodies take has properties and provenance clauses
  • expands to <kind> … end <kind> — sub-language blocks (§12)

6. Relationships (Global Edges)

relationship user uses api
end relationship

relationship frontend calls backend
  has protocol: "JSON-RPC"
  has timeout_ms: 5000
end relationship

relationship db serves api
  evidenced by: "trace:prod:db-query"
  verified by: "test:integration"
end relationship

Rules:

  • relationship <from> <phrase> <to> followed by newline
  • Body (optional): has <key>: <value> properties and provenance clauses
  • end relationship required

Edge phrase vocabulary — these normalize to a closed EdgeKind set:

  • Multi-word (pre-tokenized by the lexer): depends on, sends data to, receives data from, reads from, writes to, connects to, owned by, contained by, extended by, implemented by, used by, provided by, served by, cached by, monitored by
  • Single-word: calls, publishes, subscribes, precedes, follows, triggers, owns, contains, extends, implements, uses, produces, consumes, exports, imports, serves, caches, monitors
  • Any other single word is accepted as a custom phrase (EdgeKind::Custom). Custom multi-word phrases are not possible.

7. Provenance (Evidence Tracking)

Provenance clauses may appear in entity, edge, and relationship bodies:

entity user_service
  derived from: "doc:requirements"
  evidenced by: "trace:prod:user-table"
  observed in: "runbook:user-mgmt"
  verified by: "test:user-factory"
  deprecated by: "doc:migration-2026"
end entity

Verbs (closed set, pre-tokenized): derived from, evidenced by, observed in, verified by, deprecated by.

Format: <verb>: <value> where value is a string or identifier; repeatable.

replaces is not a provenance verb. Express supersession as a property: has replaces: "old_notification_queue".


8. Lattices (Ordered Domains)

Only chain lattices are implemented:

lattice Criticality
  order low < medium < high
end lattice

lattice Severity
  order minor < moderate < major < critical
  bottom minor
  top critical
end lattice

Rules:

  • lattice <identifier> followed by newline
  • order a < b < c — a single ascending chain
  • Optional bottom <element> (must be the chain’s first element) and top <element> (must be the last)
  • end lattice required
  • Lowering computes the reflexive-transitive closure automatically

Explicitly rejected (reserved for future partial orders): level, covers, join, meet, incomparable — using them is a parse error, not a silent no-op.


9. Policies (Governance Rules)

policy revenue_reliability
  applies to tag: revenue_path
  when source.env: prod
  unless source.experimental: true
  requires monitoring.enabled
  must have owner
  forbids tier: best_effort
  requires reaches via depends on where target.owner: platform
end policy

Structure:

  • policy <identifier> followed by newline
  • Selector (required): applies to tag: <tag> | applies to entity: <id> | applies to shape: <name> | applies to relationship: <phrase>
  • Conditions (optional, repeatable): when <predicate>, unless <predicate>
  • Requirements (optional, repeatable): requires <predicate>, forbids <predicate>, must have <predicate> (alias of requires), must not <predicate> (alias of forbids)
  • end policy required

Predicates:

  • Free text to end of line (monitoring.enabled, source.owner: platform) — captured as a simple predicate and interpreted during evaluation
  • Lattice comparisons: <expr> at least <expr>, <expr> at most <expr>, <expr> above <expr>, <expr> below <expr>
  • Reachability: reaches via <edge-phrase> with optional where <predicate> (nestable). Reachability predicates currently lower as advisory (info) diagnostics — they parse and are preserved, but are not evaluated against the graph yet.

10. Operations (Behavior Property Bags)

operation DataSync
  action: "synchronize replicas"
  timeout_sec: 3600
  retry: 3
end operation

Rules: operation <identifier>, body is bare key: value lines (no has prefix here), schema is user-defined. end operation required.


11. Projects (Bundles)

project checkout_system
  includes entity user
  includes entity api
  has team: payments
  deployment: production
end project

Rules:

  • project <identifier> followed by newline
  • Body may contain, in any order:
    • includes <free text> — repeatable; stored as includes_<n> properties
    • has <key>: <value> or bare <key>: <value> — both accepted here
  • end project required

12. Views (Projections)

view revenue_overview
  kind: system
  schema: c4
  include: tag: revenue_path
  include: entity: payments_db
  exclude: tag: experimental
  focuses_on: checkout_api
  layout
    rankdir: LR
    fontsize: 12
end view

Body keywords:

  • kind: <identifier> — view type (defaults to system)
  • schema: <identifier> — rendering schema (defaults to c4)
  • include: <selector> / exclude: <selector> — repeatable
  • focuses_on: <entity> — highlight one entity (note the spelling: focuses_on, not focus_on)
  • layoutbare keyword, no colon, followed by an indented block of key: value pairs; the block ends at dedent (there is no end layout)
  • end view required

Selectors: entity: <name>, tag: <tag>, relationship: <phrase>. No other selector types exist.


13. Sub-Language Blocks (expands to)

Entities can embed domain-specific sub-language blocks:

entity pricing_rules
  expands to expression
    o quantity
  end expression
end entity

Rules:

  • expands to <kind> followed by newline and an indented block
  • The block body is captured as a raw token stream (it must still lex as AKS: tokens like *, =, + are rejected by the lexer)
  • Closed by end <kind> at the parent indentation

The expression sub-language:

  • o <name> — variable reference; o 42 / o "lit" — constants
  • <> <op> with left: / right: ports — operation trees. Known limitation: operation trees currently parse but fail lowering (“unexpected end in operation”); only variable/constant expressions survive the full pipeline today. Track before relying on <> forms.

14. Property Values

Values in has k: v, operation/project/layout bodies:

FormExample
string"4 hour response" (double quotes only; escapes \n \t \" \\)
integer5000 (no negative literals, no exponents)
float3.14
booleantrue, false
identifierhttps, payments_team (colon-joined idents like a:b also parse)
list["us-east", "eu-central"], [1, 2, 3]
object{timeout: 30, retries: 3, cache: true} (nestable)

15. EBNF Summary

workspace       = "workspace" STRING newline module? decl* "end" "workspace"
module          = "module" IDENT "@" line_text newline ("end" "module")?

decl            = shape | event | entity | relationship | lattice
                | policy | operation | project | view

shape           = "shape" IDENT newline (indent field* dedent)? "end" "shape"
event           = "event" IDENT newline (indent field* dedent)? "end" "event"
field           = IDENT ":" type_expr newline
type_expr       = ("Json" | IDENT) ("?" | "[" "]")*

entity          = "entity" IDENT ((":" IDENT) | kind_phrase)? newline
                  (indent entity_item* dedent)? "end" "entity"
kind_phrase     = "database" | "queue" | "container" | "component"
                | "person" | "external system"
entity_item     = "has" "tag" IDENT newline
                | "has" IDENT ":" value newline
                | provenance
                | edge
                | expands_to
edge            = "edge" IDENT edge_phrase newline
                  (indent (has_prop | provenance)* dedent)? "end" "edge"
expands_to      = "expands" "to" IDENT newline indent raw_tokens dedent "end" IDENT

relationship    = "relationship" IDENT edge_phrase IDENT newline
                  (indent (has_prop | provenance)* dedent)? "end" "relationship"
edge_phrase     = EDGE_PHRASE_TOKEN | IDENT          (* see §6 vocabulary *)
provenance      = PROVENANCE_VERB ":" line_text newline   (* see §7 verbs *)

lattice         = "lattice" IDENT newline indent
                  "order" IDENT ("<" IDENT)+ newline
                  ("bottom" IDENT newline)? ("top" IDENT newline)?
                  dedent "end" "lattice"

policy          = "policy" IDENT newline indent
                  ("applies" "to" selector newline)
                  (("when" | "unless") predicate newline)*
                  (("requires" | "forbids" | "must have" | "must not") predicate newline)*
                  dedent "end" "policy"
selector        = ("tag" | "entity" | "shape" | "relationship") ":" value

operation       = "operation" IDENT newline (indent kv* dedent)? "end" "operation"
project         = "project" IDENT newline
                  (indent ("includes" line_text | has_prop | kv)* dedent)? "end" "project"

view            = "view" IDENT newline (indent view_item* dedent)? "end" "view"
view_item       = ("kind" | "schema") ":" IDENT newline
                | ("include" | "exclude") ":" selector_type ":" IDENT newline
                | "focuses_on" ":" IDENT newline
                | "layout" newline indent kv* dedent
selector_type   = "entity" | "tag" | "relationship"

has_prop        = "has" IDENT ":" value newline
kv              = IDENT ":" value newline
value           = STRING | INT | FLOAT | BOOL | IDENT
                | "[" (value ("," value)*)? "]"
                | "{" (IDENT ":" value ("," IDENT ":" value)*)? "}"

16. Common Errors

Missing end marker — every block needs its closer:

entity user
  has tag actor
# error: expected 'end entity'

Mismatched end:

entity user
end shape        # error: expected 'end entity', found 'end shape'

Bare property in entity body (entity bodies require has):

entity user
  role: storage  # error: expected newline — write `has role: storage`
end entity

Unquoted workspace name:

workspace Ecommerce   # error: expected string — write workspace "Ecommerce"

Tabs in indentation — the lexer rejects tabs outright.


17. Reserved Words

Reserved (cannot be used as bare identifiers in most positions):

workspace module shape event entity relationship lattice policy
operation project view end edge has tag with includes excludes
focuses on renders shows hides groups orders by expands
when unless requires forbids above below
order level top bottom join meet covers incomparable

Notes:

  • with, renders, shows, hides, groups, orders, by, on, focuses, excludes are reserved but currently consumed by no grammar rule (reserved for future view syntax)
  • at least, at most, must have, must not, applies to, the edge phrases (§6), the provenance verbs (§7), and external system are pre-tokenized multi-word phrases

  • Lexical detail (tokens, indentation, phrase tables): LEXICAL_RULES.md
  • Working examples (validated in CI): ../examples/
  • Overlay files (annotate blocks) are a separate dialect handled by archkit-project, not this grammar — see docs/guides/PROJECT_SYSTEM.md
  • Parser source: crates/archkit-frontend/src/aks/parser/
  • Lexer source: crates/archkit-frontend/src/aks/lexer/
  • Conformance test: crates/archkit-frontend/tests/docs_aks_conformance.rs

Integration Guide

How archkit processes, extends, and generates artifacts from AKS models.

Overview

AKS Source File
     ↓
[Lexer] - Tokenization
     ↓
[Parser] - Syntax analysis
     ↓
[AST] - Abstract syntax tree
     ↓
[Lowering] - AKS → Workspace (internal representation)
     ↓
[Workspace] - Validated architecture model
     ↓
[Generators] - Output to target formats
     ├─ TypeScript generator
     ├─ JSON Schema generator
     ├─ Mermaid diagram generator
     ├─ Graphviz DOT generator
     └─ Other generators

Key Documents

HOW_ARCHKIT_USES_AKS.md

Deep dive: The complete pipeline from source to workspace.

Topics:

  • Lexer (tokenization with off-side rule)
  • Parser (recursive descent implementation)
  • AST data structures
  • Lowering process (AST → Workspace)
  • Evidence handling
  • Graph construction
  • Workspace validation

Read this if: You want to understand how archkit internally processes AKS.

Need source-verified precision instead? This guide is a conceptual tour and has known drift from current code (e.g. token/AST examples that don’t match today’s grammar). For claims traced to exact functions and file:line references — including which of the two AKS lowering pipelines is actually live — see ../internals/.

ARTIFACT_GENERATION.md

Output formats: How archkit generates TypeScript, JSON Schema, diagrams.

Topics:

  • TypeScript type generation
  • JSON Schema export
  • Mermaid diagram rendering
  • Graphviz DOT export
  • AKS roundtripping
  • Which constructs generate what

Read this if: You want to know what outputs archkit can generate and why.

TYPE_EXTRACTION.md

Code generation: How shapes and events become types.

Topics:

  • Shape → TypeScript interface mapping
  • Event → TypeScript class mapping
  • Constraint → validation rules
  • Codegen pipeline
  • Custom type mappings
  • Integration patterns

Read this if: You’re generating code from shapes and events.

GRAPH_MODEL.md

The Graph Model: How AKS becomes a queryable, traversable graph.

Topics:

  • Nodes and edges (entities, shapes, relationships)
  • Building graphs (AKS → graph factory)
  • Graph traversal (paths, reachability, cycles)
  • Conformance relationships
  • Event flow graphs
  • Views and projections
  • Rendering from graphs
  • Performance characteristics
  • Graph queries and analysis

Read this if: You want to understand how archkit models relationships, traverse dependencies, or implement custom graph operations.

GRAPH_EXAMPLES.md

Practical Examples: Concrete examples showing AKS → graph → analysis.

Topics:

  • 5 worked examples (simple to complex)
  • AKS syntax, graph visualization, query results
  • Common graph query patterns
  • Problem detection and fixing (cycles)
  • Complex analysis scenarios
  • Query performance benchmarks
  • Integration with validation

Read this if: You want to see concrete examples of graphs in action, query patterns, or how to analyze specific scenarios.

EXTENSION_PIPELINE.md

Extensibility: Writing custom validators, transformers, generators.

Topics:

  • Extension trait (AksExtension)
  • Preprocess/postprocess phases
  • Extension registry
  • Custom validators
  • Custom transformers
  • Custom generators
  • Extension examples

Read this if: You want to extend archkit with custom behavior.

Quick Start Paths

I want to generate TypeScript from my model

  1. Read ARTIFACT_GENERATION.md (5 min)
  2. Read TYPE_EXTRACTION.md (10 min)
  3. Try:
    archkit generate code -i workspace.aks -t typescript.type -o generated/ > types.ts
    

I want to understand how archkit works

  1. Read HOW_ARCHKIT_USES_AKS.md (20 min)
  2. Read ARTIFACT_GENERATION.md (10 min)
  3. Explore source in crates/archkit-core/src/schema/frontend/aks/

I want to extend archkit

  1. Read EXTENSION_PIPELINE.md (15 min)
  2. See full extension guide in docs/guides/AKS_EXTENSION_FRAMEWORK.md
  3. Try implementing a custom validator

I’m troubleshooting a parse error

  1. Read Troubleshooting
  2. Check LEXICAL_RULES.md
  3. Verify indentation and syntax

Architecture

Parser

Location: crates/archkit-core/src/schema/frontend/aks/parser/

Recursive descent parser that:

  • Accepts tokenized input from lexer
  • Builds abstract syntax tree (AST)
  • Reports syntax errors with line/column
  • Continues parsing after errors (best-effort)

Lowering

Location: crates/archkit-core/src/schema/frontend/aks/lowering/

Transforms AST to Workspace:

  • Validates references (shapes, entities, events)
  • Builds dependency graph
  • Tracks evidence and provenance
  • Handles computed values (expressions)
  • Applies lattice and policy constraints

Type System

Location: crates/archkit-core/src/schema/frontend/aks/type_system.rs

Extracts shapes and events to TypeSystemModel:

  • Maps shape fields to type properties
  • Captures constraints and validation rules
  • Builds type hierarchies
  • Feeds to code generators

Generators

Location: crates/archkit-core/src/schema/render/ and crates/archkit-core/src/schema/export/

Output renderers:

  • typescript.rs - TypeScript interface generation
  • json_schema.rs - JSON Schema export
  • mermaid.rs - Mermaid diagram syntax
  • graphviz.rs / dot.rs - Graphviz DOT
  • aks.rs - AKS roundtripping

Data Structures

AST (Abstract Syntax Tree)

Location: crates/archkit-core/src/schema/frontend/aks/ast/

Represents parsed AKS syntax:

#![allow(unused)]
fn main() {
pub enum Declaration {
    Shape { name, fields },
    Event { name, fields },
    Entity { name, attributes },
    Relationship { source, target, kind },
    // ...
}
}

Workspace

Location: crates/archkit-core/src/schema/workspace.rs

Validated internal representation:

#![allow(unused)]
fn main() {
pub struct Workspace {
    pub name: String,
    pub entities: Vec<Entity>,
    pub shapes: Vec<Shape>,
    pub relationships: Vec<Relationship>,
    // ...
}
}

TypeSystemModel

Location: crates/archkit-type-model/src/lib.rs

Type information extracted from workspace:

#![allow(unused)]
fn main() {
pub struct TypeSystemModel {
    pub records: Vec<Record>,    // From shapes
    pub events: Vec<Event>,      // From events
    pub constraints: Vec<Constraint>,
}
}

Processing Steps

1. Lexical Analysis

"entity UserService" → [KEYWORD(entity), IDENT(UserService), NEWLINE]

2. Parsing

[KEYWORD(entity), IDENT(UserService), ...] → AST(Entity)

3. Lowering

AST(Entity) → Workspace(Entity) + validate references

4. Type Extraction

Workspace(Shape User) → TypeSystemModel(Record User)

5. Code Generation

TypeSystemModel(Record User) → TypeScript(interface User)

Error Handling

Archkit reports errors with context:

$ archkit parse bad.aks
Error: undefined entity "Database"
  at bad.aks:5:15
  entity Service
    depends_on: Database  ← undefined

Error categories:

  • Syntax - Grammar violation
  • Reference - Undefined entity/shape
  • Validation - Constraint violation
  • Type - Type mismatch

See Troubleshooting for solutions.

Integration Patterns

With Your Build System

# Generate types during build
cargo build --pre-build "archkit generate code -i model.aks -t typescript.type -o generated/ > src/types.ts"

With CI/CD

# GitHub Actions example
- name: Validate AKS
  run: archkit verify workspace.aks --check-all

- name: Generate types
  run: archkit generate code -i workspace.aks -t typescript.type -o generated/ > types/generated.ts

- name: Generate diagrams
  run: archkit view file -i workspace.aks --output diagram.mmd > docs/architecture.mmd

With Custom Tools

Use archkit as a library:

#![allow(unused)]
fn main() {
use archkit::AksService;

let workspace = AksService::parse(source)?;
let types = TypeSystemModel::from_workspace(&workspace)?;
let ts_code = TypeScriptGenerator::generate(&types)?;
}

See crates/archkit/src/lib.rs for public API.

Performance

Typical performance (single-file models):

OperationTime
Parse< 10ms
Lowering< 5ms
Type extraction< 2ms
TypeScript generation< 5ms
Diagram generation< 20ms

For multi-file models (100+ files):

  • Parse: 100-500ms
  • Full pipeline: 200-1000ms

Next Steps


Pick a topic above or explore the source code!

Type Extraction

How shapes and events become code (TypeScript, JSON Schema, etc.).

The Type Extraction Pipeline

AKS Shapes & Events
      ↓
TypeSystemModel
  (canonical type representation)
      ↓
   ├─ TypeScript Generator
   ├─ JSON Schema Generator
   ├─ Python Generator
   ├─ Go Generator
   └─ Other Generators
      ↓
   Generated Code

TypeSystemModel

Location: crates/archkit-type-model/src/lib.rs

Intermediate representation of types extracted from shapes/events:

#![allow(unused)]
fn main() {
pub struct TypeSystemModel {
    pub records: Vec<Record>,       // From shapes
    pub events: Vec<Event>,         // From events
    pub enums: Vec<Enum>,          // Enumeration types
    pub constraints: Vec<Constraint>, // Validation rules
}

pub struct Record {
    pub id: RecordId,
    pub name: String,
    pub properties: Vec<Property>,
    pub required: Vec<String>,
}

pub struct Property {
    pub name: String,
    pub type_spec: TypeSpec,
    pub constraints: Vec<Constraint>,
    pub optional: bool,
}
}

Shape → Record Mapping

Basic Mapping

shape User
  id: String
  email: String
  age: Int
  created_at: Timestamp
end shape

Becomes:

#![allow(unused)]
fn main() {
Record {
  name: "User",
  properties: [
    Property { name: "id", type_spec: String, optional: false },
    Property { name: "email", type_spec: String, optional: false },
    Property { name: "age", type_spec: Int, optional: false },
    Property { name: "created_at", type_spec: Timestamp, optional: false },
  ],
  required: ["id", "email", "age", "created_at"],
}
}

Optional Fields

shape BlogPost
  title: String
  content: String
  published_at: Timestamp?
end shape

Becomes:

#![allow(unused)]
fn main() {
Record {
  properties: [
    Property { name: "published_at", optional: true, ... },
  ],
  required: ["title", "content"],  // published_at NOT required
}
}

Collections

shape Order
  items: OrderItem[]
  tags: String[]
  metadata: Json
end shape

Becomes:

#![allow(unused)]
fn main() {
Property { name: "items", type_spec: List(Record(OrderItem)) },
Property { name: "tags", type_spec: List(String) },
Property { name: "metadata", type_spec: Json },
}

Event → Event Mapping

event UserCreated
  user_id: String
  email: String
  timestamp: Timestamp
end event

Becomes:

#![allow(unused)]
fn main() {
Event {
  name: "UserCreated",
  properties: [
    Property { name: "user_id", type_spec: String },
    Property { name: "email", type_spec: String },
    Property { name: "timestamp", type_spec: Timestamp },
  ],
  required: ["user_id", "email", "timestamp"],
}
}

Difference from Record:

  • Events always have timestamp
  • Events are immutable/final
  • Events imply causality

Constraint Mapping (Not Implemented)

Inline field constraints were part of an early draft and are not in the grammar — annotations like these are parse errors today:

shape Product
  price: decimal @min(0.01)          # NOT valid AKS
  email: string @pattern("^[^@]+$")  # NOT valid AKS

Express invariants as policies on the entities that carry the data, or enforce them in the generated code’s validation layer.

Type Extraction Entry Points

Via CLI

archkit generate code -i workspace.aks -t typescript.type -o generated/ > types.ts
# Internally: parse → TypeSystemModel → TypeScriptGenerator

Via Rust API

#![allow(unused)]
fn main() {
use archkit::AksService;
use archkit_type_model::TypeSystemModel;

let workspace = AksService::parse(source)?;
let type_model = TypeSystemModel::from_workspace(&workspace)?;

// Use type_model for code generation
}

From File

#![allow(unused)]
fn main() {
let type_model = TypeSystemModel::from_file("workspace.aks")?;
}

Code Generators

TypeScript

Location: crates/archkit-codegen/src/generators/typescript.rs

Generates TypeScript interfaces:

// From shape User
interface User {
  id: string;
  email: string;
  age: number;
  created_at: Date;
}

// With constraints
export const UserValidator = z.object({
  email: z.string().email(),
  age: z.number().min(0).max(150),
});

JSON Schema

Location: crates/archkit-codegen/src/generators/json_schema.rs

Generates JSON Schema with validation:

{
  "User": {
    "type": "object",
    "properties": {
      "email": { "type": "string", "format": "email" },
      "age": { "type": "integer", "minimum": 0, "maximum": 150 }
    },
    "required": ["id", "email"]
  }
}

Python

Generates Python dataclasses:

from dataclasses import dataclass

@dataclass
class User:
    id: str
    email: str
    age: int
    created_at: datetime

Go

Generates Go structs:

type User struct {
    ID        string    `json:"id"`
    Email     string    `json:"email"`
    Age       int       `json:"age"`
    CreatedAt time.Time `json:"created_at"`
}

OpenAPI/Swagger

Generates OpenAPI schema:

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
          format: email
      required:
        - id
        - email

Type Mapping Reference

Primitive Types

AKSTypeScriptJSON SchemaPythonGo
stringstring{ “type”: “string” }strstring
intnumber{ “type”: “integer” }intint64
decimalnumber{ “type”: “number” }floatfloat64
boolboolean{ “type”: “boolean” }boolbool
timestampDate{ “type”: “string”, “format”: “date-time” }datetimetime.Time
bytesBuffer{ “type”: “string”, “format”: “byte” }bytes[]byte

Collection Types

AKSTypeScriptJSON SchemaPythonGo
[string]string[]{ “type”: “array”, “items”: {…} }List[str][]string
{str: str}Record<string, string>{ “type”: “object” }Dict[str, str]map[string]string

Optional

AKSTypeScriptJSON SchemaPythonGo
?stringstring | undefinednot in requiredOptional[str]*string

Constraint Mapping

AKSTypeScriptJSON SchemaValidation
@min(0)-minimum: 0Zod: .min(0)
@max(100)-maximum: 100Zod: .max(100)
@pattern(rx)-pattern: “rx”Zod: .regex(rx)
@format(url)-format: “url”Zod: .url()

Custom Type Mappings

Extend type extraction for custom needs:

#![allow(unused)]
fn main() {
pub struct CustomTypeMapper;

impl TypeMapper for CustomTypeMapper {
    fn map_property(&self, prop: &Property) -> CustomType {
        // Custom mapping logic
    }
}

let type_model = TypeSystemModel::from_workspace_with_mapper(
    &workspace,
    CustomTypeMapper,
)?;
}

Performance

Type extraction performance (single model):

StepTime
Parse AKS10ms
Build TypeSystemModel5ms
Generate TypeScript5ms
Total20ms

Multi-file (100 shapes):

  • Build TypeSystemModel: 50-100ms
  • Generate TypeScript: 50-100ms
  • Total: 100-200ms

Common Patterns

API Request/Response Types

shape CreateUserRequest
  email: String
  name: String
end shape

shape UserResponse
  id: String
  email: String
  created_at: Timestamp
end shape

entity user_api
  edge CreateUserRequest consumes
  end edge
  edge UserResponse produces
  end edge
end entity

Domain Models

shape Money
  amount: Float
  currency: String
end shape

shape Order
  id: String
  total: Money
  items: OrderItem[]
end shape

Event Models

event UserCreated
  user_id: String
  email: String
  timestamp: Timestamp
end event

event OrderPlaced
  order_id: String
  user_id: String
  timestamp: Timestamp
end event

Integration Examples

Express Validation

import { UserValidator } from './types';

app.post('/user', (req, res) => {
  const result = UserValidator.safeParse(req.body);
  if (!result.success) {
    return res.status(400).json(result.error);
  }
  // result.data is typed as User
});

OpenAPI Documentation

archkit generate code -i workspace.aks -t openapi.schema -o generated/
# Generate Swagger UI automatically

Database Schema

# JSON Schema → SQL schema generator
archkit generate code -i workspace.aks -t json.schema -o generated/ | json-schema-to-sql

Next Steps


Type extraction bridges AKS models and code generation!

How Archkit Uses AKS

Complete walkthrough of the AKS processing pipeline from source to workspace.

The Pipeline

AKS Source File
     ↓ [Input: String]
[Lexer]
  - Tokenizes source
  - Handles indentation (off-side rule)
  - Produces token stream
     ↓ [Token Stream]
[Parser]
  - Recursive descent parsing
  - Builds abstract syntax tree
  - Reports syntax errors
     ↓ [AST: Declaration Nodes]
[Lowering]
  - Validates references
  - Builds graph structures
  - Tracks provenance
  - Handles computed values
     ↓ [Validated Graph]
[Workspace]
  - Entities, shapes, relationships
  - Evidence tracking
  - Policy constraints
  - Ready for analysis/generation

1. Lexer (Tokenization)

File: crates/archkit-core/src/schema/frontend/aks/lexer/

The lexer converts source text into tokens:

Input:  "entity UserService\n  role: orchestration"

Output: [
  KEYWORD(entity),
  IDENT(UserService),
  NEWLINE,
  INDENT(2),
  KEYWORD(role),
  COLON,
  IDENT(orchestration),
  DEDENT,
  EOF
]

Key Features

  • Off-side rule: Tracks indentation levels
  • Error recovery: Continues after lexical errors
  • Line/column tracking: For error reporting
  • Context-aware: Keywords vs identifiers

2. Parser (Syntax Analysis)

File: crates/archkit-core/src/schema/frontend/aks/parser/

The parser builds an AST from tokens:

[KEYWORD(entity), IDENT(UserService), COLON, IDENT(orchestration)]
              ↓
          Parser
              ↓
ast::Declaration::Entity {
  name: "UserService",
  attributes: [
    ("role", "orchestration"),
  ]
}

Parsing Strategy

  • Recursive descent - Top-down parsing
  • Multi-pass - Separate passes for different constructs
  • Error recovery - Best-effort parsing

Grammar Hierarchy

program
  → workspace
      → shape | event | entity | ...
          → field: type | relationship: target | ...

3. Abstract Syntax Tree (AST)

File: crates/archkit-core/src/schema/frontend/aks/ast/

Represents parsed structure:

#![allow(unused)]
fn main() {
pub enum Declaration {
    Shape {
        name: String,
        fields: Vec<FieldDef>,
    },
    Event {
        name: String,
        fields: Vec<FieldDef>,
    },
    Entity {
        name: String,
        attributes: Vec<Attribute>,
    },
    Relationship {
        source: String,
        target: String,
        kind: RelationshipKind,
        phrases: Vec<(String, String)>,
    },
    // ... more variants
}

pub struct FieldDef {
    pub name: String,
    pub type_spec: TypeSpec,
    pub constraints: Vec<Constraint>,
}
}

4. Lowering (AST → Workspace)

File: crates/archkit-core/src/schema/frontend/aks/lowering/

Transforms AST to validated Workspace:

4a. Reference Resolution

All references are validated:

  • Entity dependencies → must reference defined entities
  • Shape conformance → must reference defined shapes
  • Event production → must reference defined events
Entity: "UserService depends_on: UserDB"
  ↓ [Validate UserDB exists]
  ↓ [Validate it's an entity]
  → Relationship created

4b. Graph Construction

Builds internal graph representation:

#![allow(unused)]
fn main() {
pub struct Workspace {
    pub entities: Vec<Entity>,
    pub shapes: Vec<Shape>,
    pub events: Vec<Event>,
    pub relationships: Vec<Relationship>,
    // ... more fields
}

pub struct Entity {
    pub id: EntityId,
    pub name: String,
    pub role: Role,
    pub conformances: Vec<ShapeId>,
    pub dependencies: Vec<Relationship>,
    // ...
}
}

4c. Provenance Handling

Tracks source of truth:

evidence: "code:src/service.rs line 42"
  ↓ [Parse source indicator]
  → Provenance { kind: Code, location: "src/service.rs", line: 42 }

Evidence categories:

  • code: - From source code
  • mirror: - Auto-generated observation
  • authored: - Manual documentation
  • observation: - External source

4d. Computed Values

Evaluates expressions:

entity Count
  current_entities: @count(entity)      # Computed via aggregation

5. Workspace (Internal Representation)

File: crates/archkit-core/src/schema/workspace.rs

Validated, normalized representation ready for:

  • Analysis (dependencies, cycles, coverage)
  • Validation (policies, constraints, evidence)
  • Generation (TypeScript, diagrams, etc.)

Structure

#![allow(unused)]
fn main() {
pub struct Workspace {
    pub name: String,
    pub version: Version,
    pub entities: Vec<Entity>,
    pub shapes: Vec<Shape>,
    pub events: Vec<Event>,
    pub relationships: Vec<Relationship>,
    pub policies: Vec<Policy>,
    pub lattices: Vec<Lattice>,
    pub evidence: ProvE nanceGraph,
}
}

Validation Steps

  1. Syntactic - Grammar compliance (lexer/parser)
  2. Referential - All references exist and are typed correctly
  3. Semantic - Domain-specific rules (policies, lattices)
  4. Consistency - No conflicts or contradictions

Entry Points

Parsing Only

#![allow(unused)]
fn main() {
use archkit::AksService;

let workspace = AksService::parse(source)?;
// Returns parsed, lowered, validated Workspace
}

With File Path

#![allow(unused)]
fn main() {
let workspace = AksService::parse_file("workspace.aks")?;
}

From String

#![allow(unused)]
fn main() {
let source = r#"
  workspace MyApp
    entity Service
      role: orchestration
"#;
let workspace = AksService::parse(source)?;
}

Error Handling

Errors include context:

#![allow(unused)]
fn main() {
pub struct ParseError {
    pub message: String,
    pub location: SourceLocation,  // line, column, file
    pub context: String,           // relevant code snippet
    pub suggestion: Option<String>, // helpful hint
}
}

Example output:

Error: undefined entity "Database"
  at workspace.aks:5:15
    entity Service
      depends_on: Database ← undefined
  
  Suggestion: define "Database" entity or check spelling

Type System Integration

Type Extraction

Workspace (shapes, events)
  ↓ [TypeSystemModel::from_workspace()]
  → TypeSystemModel (types, constraints, properties)
  ↓ [CodeGenerator::generate()]
  → TypeScript, JSON Schema, etc.

See TYPE_EXTRACTION.md for details.

Performance Characteristics

Single File

  • Lex: < 5ms
  • Parse: < 10ms
  • Lower: < 5ms
  • Total: < 20ms

Multi-File (100 files)

  • Lex all: 50-100ms
  • Parse all: 100-200ms
  • Lower all: 50-100ms
  • Total: 200-400ms

Implementation Files

FilePurpose
lexer/lexer_impl.rsTokenization
parser/parser_impl.rsParse workspace/modules
parser/entities.rsEntity parsing
parser/shapes.rsShape parsing
parser/relationships.rsRelationship parsing
lowering/substrate_impl.rsAST → Workspace
lowering/evidence.rsProvenance tracking
lowering/graph_factory.rsGraph construction
type_system.rsType extraction

Next Steps


Understanding the pipeline helps you use archkit more effectively and extend it for custom needs!

Extension Pipeline

Writing custom extensions to archkit.

Extension Trait

Location: crates/archkit-extensions/src/lib.rs

#![allow(unused)]
fn main() {
pub trait AksExtension: Send + Sync {
    /// Preprocess phase - modify AKS before lowering
    fn preprocess(&self, source: &str) -> Result<String>;
    
    /// Postprocess phase - modify workspace after lowering
    fn postprocess(&self, workspace: &mut Workspace) -> Result<()>;
    
    /// Extension metadata
    fn name(&self) -> &str;
    fn version(&self) -> &str;
}
}

Phases

Extensions hook into two phases:

1. Preprocess (Source → AST)

When: Before parsing

Can modify:

  • AKS source text
  • Add/remove/modify constructs
  • Expand macros

Use cases:

  • Validation rules (e.g., “all entities must have description”)
  • Transformations (e.g., “convert v1 to v2 syntax”)
  • Macro expansion
  • Templating

Example: Validate all entities have descriptions

#![allow(unused)]
fn main() {
pub struct DescriptionValidator;

impl AksExtension for DescriptionValidator {
    fn preprocess(&self, source: &str) -> Result<String> {
        // Parse and validate
        let lines: Vec<&str> = source.lines().collect();
        for (i, line) in lines.iter().enumerate() {
            if line.trim_start().starts_with("entity ") {
                // Check next line for description
                if i + 1 >= lines.len() || !lines[i + 1].contains("description:") {
                    return Err(format!(
                        "Entity at line {} missing description",
                        i + 1
                    ));
                }
            }
        }
        Ok(source.to_string())
    }
    
    fn postprocess(&self, _workspace: &mut Workspace) -> Result<()> {
        Ok(())
    }
    
    fn name(&self) -> &str { "description-validator" }
    fn version(&self) -> &str { "1.0.0" }
}
}

2. Postprocess (AST → Workspace)

When: After lowering to Workspace

Can modify:

  • Entities, shapes, relationships
  • Add computed properties
  • Validate constraints
  • Generate derived data

Use cases:

  • Adding computed entities (e.g., count, aggregates)
  • Validating policies
  • Computing metrics
  • Enriching with metadata

Example: Count entities

#![allow(unused)]
fn main() {
pub struct EntityCounter;

impl AksExtension for EntityCounter {
    fn preprocess(&self, source: &str) -> Result<String> {
        Ok(source.to_string())
    }
    
    fn postprocess(&self, workspace: &mut Workspace) -> Result<()> {
        let count = workspace.entities.len();
        // Log or use count
        println!("Workspace contains {} entities", count);
        Ok(())
    }
    
    fn name(&self) -> &str { "entity-counter" }
    fn version(&self) -> &str { "1.0.0" }
}
}

Extension Registry

Location: crates/archkit-extensions/src/registry.rs

#![allow(unused)]
fn main() {
pub struct ExtensionRegistry {
    extensions: Vec<Box<dyn AksExtension>>,
}

impl ExtensionRegistry {
    pub fn new() -> Self { ... }
    
    pub fn register(&mut self, ext: Box<dyn AksExtension>) -> Result<()> { ... }
    
    pub fn preprocess(&self, source: &str) -> Result<String> { ... }
    pub fn postprocess(&self, workspace: &mut Workspace) -> Result<()> { ... }
}
}

Using Extensions

In Rust Code

#![allow(unused)]
fn main() {
use archkit::AksService;
use archkit_extensions::{ExtensionRegistry, DescriptionValidator};

let mut registry = ExtensionRegistry::new();
registry.register(Box::new(DescriptionValidator))?;

let source = std::fs::read_to_string("workspace.aks")?;

// Preprocess with extensions
let preprocessed = registry.preprocess(&source)?;

// Parse and lower
let mut workspace = AksService::parse(&preprocessed)?;

// Postprocess with extensions
registry.postprocess(&mut workspace)?;

// Use workspace
}

Via CLI

# Register extensions in archkit.toml
[extensions]
validators = ["description-validator", "policy-enforcer"]

# archkit automatically loads and applies them
archkit parse workspace.aks

Common Extension Patterns

1. Validator

Checks properties and enforces rules:

#![allow(unused)]
fn main() {
pub struct PolicyValidator;

impl AksExtension for PolicyValidator {
    fn preprocess(&self, source: &str) -> Result<String> {
        // Check all policies are defined
        Ok(source.to_string())
    }
    
    fn postprocess(&self, workspace: &mut Workspace) -> Result<()> {
        for policy in &workspace.policies {
            if policy.description.is_empty() {
                return Err("Policy must have description".into());
            }
        }
        Ok(())
    }
    
    fn name(&self) -> &str { "policy-validator" }
    fn version(&self) -> &str { "1.0.0" }
}
}

2. Transformer

Modifies content programmatically:

#![allow(unused)]
fn main() {
pub struct VersionUpgrader;

impl AksExtension for VersionUpgrader {
    fn preprocess(&self, source: &str) -> Result<String> {
        // Convert v1 syntax to v2
        let updated = source
            .replace("entity_type: ", "role: ")
            .replace("relates_to: ", "depends_on: ");
        Ok(updated)
    }
    
    fn postprocess(&self, _workspace: &mut Workspace) -> Result<()> {
        Ok(())
    }
    
    fn name(&self) -> &str { "version-upgrader" }
    fn version(&self) -> &str { "1.0.0" }
}
}

3. Enricher

Adds computed or derived data:

#![allow(unused)]
fn main() {
pub struct MetricsEnricher;

impl AksExtension for MetricsEnricher {
    fn postprocess(&self, workspace: &mut Workspace) -> Result<()> {
        // Add computed metrics
        workspace.metrics.entity_count = workspace.entities.len();
        workspace.metrics.dependency_count = 
            workspace.relationships.iter()
                .filter(|r| r.kind == RelationshipKind::DependsOn)
                .count();
        Ok(())
    }
    
    fn preprocess(&self, source: &str) -> Result<String> {
        Ok(source.to_string())
    }
    
    fn name(&self) -> &str { "metrics-enricher" }
    fn version(&self) -> &str { "1.0.0" }
}
}

4. Generator

Generates additional content:

#![allow(unused)]
fn main() {
pub struct DiagramGenerator;

impl AksExtension for DiagramGenerator {
    fn postprocess(&self, workspace: &mut Workspace) -> Result<()> {
        // Generate diagrams as side effects
        let mermaid = generate_mermaid(workspace);
        std::fs::write("diagram.mmd", mermaid)?;
        Ok(())
    }
    
    fn preprocess(&self, source: &str) -> Result<String> {
        Ok(source.to_string())
    }
    
    fn name(&self) -> &str { "diagram-generator" }
    fn version(&self) -> &str { "1.0.0" }
}
}

Built-in Extensions

Archkit includes standard extensions:

NamePhasePurpose
syntax-validatorPreCheck grammar compliance
reference-validatorPostValidate all references exist
policy-enforcerPostEnforce governance policies
metrics-collectorPostCompute system metrics
diagram-generatorPostGenerate diagrams

Creating a Custom Extension

Step 1: Define Struct

#![allow(unused)]
fn main() {
pub struct MyExtension {
    config: MyConfig,
}

impl MyExtension {
    pub fn new(config: MyConfig) -> Self {
        MyExtension { config }
    }
}
}

Step 2: Implement Trait

#![allow(unused)]
fn main() {
impl AksExtension for MyExtension {
    fn preprocess(&self, source: &str) -> Result<String> {
        // Modify source or validate
        Ok(source.to_string())
    }
    
    fn postprocess(&self, workspace: &mut Workspace) -> Result<()> {
        // Modify workspace or validate
        Ok(())
    }
    
    fn name(&self) -> &str { "my-extension" }
    fn version(&self) -> &str { "1.0.0" }
}
}

Step 3: Register

#![allow(unused)]
fn main() {
registry.register(Box::new(MyExtension::new(config)))?;
}

Step 4: Use

archkit parse --with-extensions workspace.aks

Publishing Extensions

Create a package for distribution:

[package]
name = "archkit-ext-myext"
version = "1.0.0"

[dependencies]
archkit = "0.2"
archkit-extensions = "0.2"

Users can then import:

#![allow(unused)]
fn main() {
use archkit_ext_myext::MyExtension;
}

Error Handling

Extensions should report clear errors:

#![allow(unused)]
fn main() {
fn postprocess(&self, workspace: &mut Workspace) -> Result<()> {
    for entity in &workspace.entities {
        if entity.role.is_none() {
            return Err(format!(
                "Entity '{}' missing required 'role' property",
                entity.name
            ));
        }
    }
    Ok(())
}
}

Testing Extensions

#![allow(unused)]
fn main() {
#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_validator_rejects_missing_description() {
        let ext = DescriptionValidator;
        let source = r#"
            workspace Test
              entity Service
                role: orchestration
        "#;
        assert!(ext.preprocess(source).is_err());
    }
}
}

Performance

Extension overhead:

  • Preprocess string transformations: < 5ms (typical)
  • Postprocess workspace modifications: < 10ms (typical)
  • Total for all built-in extensions: < 50ms

Keep extensions fast—they run on every parse!

Full Example Extension

See docs/guides/AKS_EXTENSION_FRAMEWORK.md for complete working example.

Next Steps

  • Extension framework guidedocs/guides/AKS_EXTENSION_FRAMEWORK.md
  • See examplesExamples
  • IntegrationIntegration README

Extensions make archkit flexible and adaptable to your needs!

AKS Frontend Internals

Source-grounded, function-level documentation of how the AKS frontend (crates/archkit-core/src/schema/frontend/aks/) actually works today — as opposed to ../integration/, which is a higher-level, less precisely-sourced tour of the same territory.

Written 2026-07-02 as part of an audit that resolved two open questions about the frontend: which of two lowering pipelines is actually live, and why single-word entity-kind phrases (database, queue, …) weren’t raising the validation error they were supposed to. Both are answered here, and the answers are load-bearing for anything that touches ElementKindRef, lower_workspace, or lower_aks_to_substrate next.

Read pipeline-overview.md first. It’s the trunk everything else hangs off. The other files go deep on one stage:

  • lexer.md — off-side rule, closed-phrase tokenization, tab rejection
  • ast.mdAksDecl variants, ElementKindRef, sub-language capture
  • parser.md — module map, closed-vocabulary idiom, hard-error scope limits
  • lowering.mdlower_workspace trace, GraphRecordFactory, canonicalization
  • known-gaps.md — dated list of confirmed-but-unresolved issues

Staying accurate over time: every file here names real functions and file paths so claims can be re-checked against source. When you find a claim that’s drifted from the code, fix the doc in the same change that changes the code — don’t let it rot into the next audit’s problem.

Archkit

Archkit = architecture modeling, validation, projection, generation toolkit.

Core capabilities

  • author architecture in AKS
  • organize models in managed project layout
  • validate modeled system and project health
  • mirror external systems into AKS artifacts
  • detect drift between authored and observed state
  • promote reviewed changes into authored source
  • generate code, schemas, reports, diagrams

Main workflows

Docs split

  • mdBook — product docs, tutorials, language guide, ops
  • rustdoc — Rust crate API

Source docs

This section wraps existing authored docs under docs/guides/, docs/reference/, docs/architecture/, and docs/operations/.

Quickstart

Official packaging policy: docs/operations/packaging.md.

Audience and install path

  • End users and external adopters: install a pinned binary from GitHub Releases (primary path).
  • Rust-native fallback: cargo install archkit --locked --version <x.y.z>.
  • Contributors to this repo: use source workflow below (cargo make onboarding), with optional cargo install --path . for local install checks.

0) Install prerequisites

Rust toolchain is pinned by this repo to 1.94.1 via rust-toolchain.toml.

Required for onboarding:

  • rustc
  • cargo

Optional (warn-only in onboarding preflight):

  • dot (Graphviz render gate)
  • git (doc drift checks like cargo make autodoc-check; docgen-check is a compatibility alias)
  • nu (parity script)

Install cargo-make once:

cargo install cargo-make --version 0.37.24 --locked

1) One-command onboarding

Run the local onboarding flow:

cargo make onboarding

This runs a preflight, verifies formatting, builds the workspace, runs the production-like dogfood validate/project path, and regenerates docs artifacts.

Discoverability commands:

cargo make
cargo make help
cargo make --list-all-steps --output-format short-description

Use the canonical AKS path (Tier 1):

cargo make dev

This emits deterministic artifacts under generated/ephemeral/dogfood/main/, including canonical JSON, DOT, and Mermaid outputs.

3) Docs and artifacts

Generate docs and rustdoc artifacts:

cargo make docs-artifacts

4) Full local test suite

cargo make test-all

Recommended first 5-10 minutes after clone:

cargo make onboarding
cargo make dev
cargo make docs-artifacts
cargo make test-all

5) Optional Graphviz render gate

Requires Graphviz (dot -V):

cargo make render

5b) Canonical project architecture workflow

Run the canonical self-model for this repository:

cargo make architecture-self

Canonical source model: architecture/models/archkit_self.ncl.

6) Direct CLI flow (contributor/source workflow)

Enter the Nix dev shell:

nix develop -c bash

Validate a Nickel spec:

cargo run -p archkit-cli -- validate -i docs/dogfood/examples/workspace.ncl

Project a named view to DOT (+ Mermaid companion):

cargo run -p archkit-cli -- view -i docs/dogfood/examples/workspace.ncl --view-id container_main -o generated/ephemeral/run/container.dot

This also writes generated/ephemeral/run/container.document.json and generated/ephemeral/run/container.mmd.

6b) (Optional, experimental) Generate AKS from canonical JSON

cargo run -p archkit-cli -- export-aks -i generated/ephemeral/run/container.document.json -o generated/ephemeral/run/container.aks

6c) (Optional) Generate Nickel from canonical JSON

cargo run -p archkit-cli -- export-nickel -i generated/ephemeral/run/container.document.json -o generated/ephemeral/run/container.ncl

6d) Render DOT to SVG

cargo run -p archkit-cli -- render -i generated/ephemeral/run/container.dot -f svg -o generated/ephemeral/run/container.svg

This also writes generated/ephemeral/run/container.document.json, generated/ephemeral/run/container.dot, and generated/ephemeral/run/container.mmd (copied canonical JSON and Mermaid companion from projection artifacts).

7) Clean-room setup verification (sprint baseline)

Use this checklist to verify a new machine can run the documented CLI path without hidden assumptions.

  1. Build:
cargo build

Expected: build succeeds.

  1. Validate Nickel example:
cargo run -p archkit-cli -- validate -i docs/dogfood/examples/workspace.ncl

Expected: exit 0, workspace valid.

  1. View named diagram:
cargo run -p archkit-cli -- view -i docs/dogfood/examples/workspace.ncl --view-id container_main -o generated/ephemeral/run/container.dot

Expected: generated/ephemeral/run/container.dot, generated/ephemeral/run/container.mmd, and generated/ephemeral/run/container.document.json.

  1. Render when Graphviz is installed:
dot -V
cargo run -p archkit-cli -- render -i generated/ephemeral/run/container.dot -f svg -o generated/ephemeral/run/container.svg

Expected: exit 0, generated/ephemeral/run/container.svg plus render companions.

  1. Graphviz-absent behavior:
  • If dot -V fails, onboarding and validate/project checks are still valid baseline success.
  • render is expected to fail with error[render] and exit class 4 until Graphviz is installed.
  1. Feature-flag variants:
cargo test --no-default-features
cargo test --features dot-import

Expected: both commands pass; feature-disabled command paths report exit class 5 where applicable.

architecture/
  workspace.aks
generated/ephemeral/run/
  *.dot
  *.mmd
  *.document.json
  *.svg

Use validate and view in CI to keep architecture specs reviewable and deterministic.

AKS is Tier 1 canonical specification language. Nickel is Tier 2 complementary for contracts.

Dogfood target

The repository includes a realistic end-to-end target under dogfood/:

archkit validate -i dogfood/architecture/main.ncl
archkit view -i dogfood/architecture/main.ncl --view-id container_main -o generated/ephemeral/dogfood/main/container.dot

Archkit Project System Guide

Archkit project system organizes authored models, generated artifacts, reports, and inspection workflows under one deterministic project root.

Project shape

my-project/
├── archkit.project.toml
├── authored/
├── overlays/
├── mirror/
├── promoted/
├── generated/
├── reports/
│   └── generate/
│       ├── project-generate.archkit.plan.json
│       └── project-generate.archkit.report.json
└── .archkit/index/

Core commands

Initialize project:

nix develop -c cargo run -p archkit-cli -- project init --root ./my-project --name "My Project"

Validate layout and health:

nix develop -c cargo run -p archkit-cli -- project layout-check --root ./my-project
nix develop -c cargo run -p archkit-cli -- project dogfood --root ./my-project

Self-Hosting Assessment (M1-M9)

Assess self-hosting adoption readiness using the complete meta-model foundation:

# Text report (human-readable)
nix develop -c cargo run -p archkit-cli -- project self-hosting-assess --root ./my-project

# JSON report (machine-readable)
nix develop -c cargo run -p archkit-cli -- project self-hosting-assess --root ./my-project --format json

# Save to file
nix develop -c cargo run -p archkit-cli -- project self-hosting-assess --root ./my-project --out adoption-report.txt

The self-hosting assessment command:

  1. Loads your project manifest and structure
  2. Generates all 4 meta-models (GenerationPlan, Capability, Extension, Topology)
  3. Runs comprehensive validation across all models
  4. Reports adoption status: Ready, WarningsPending, or Failed
  5. Provides remediation guidance for any issues found

See: SELF_HOSTING_CLI_ASSESSMENT.md for complete guide including:

  • Detailed usage examples
  • Output format reference
  • Integration patterns (CI/CD, dashboards)
  • Remediation guide
  • Troubleshooting

Manifest-driven generation

Generation now comes from [[generate]] entries in archkit.project.toml.

Example:

[project]
name = "My Project"

[[generate]]
name = "schema"
model = "authored/domain.aks"
target = "json.schema"
output = "generated/domain.schema.json"

[[generate]]
name = "types"
model = "authored/domain.aks"
target = "typescript.type"
output = "generated/domain.types.ts"

[[generate]]
name = "summary"
model = "authored/domain.aks"
target = "json.schema"
output = "generated/domain.summary.md"
template = "artifact.summary.md"

Run configured generation set:

nix develop -c cargo run -p archkit-cli -- project generate --root ./my-project

Current built-in targets:

  • json.schema
  • typescript.type

Generation inspection flow

Write plan + artifacts + report

nix develop -c cargo run -p archkit-cli -- project generate --root ./my-project

Writes generated outputs plus persisted files:

  • reports/generate/project-generate.archkit.plan.json
  • reports/generate/project-generate.archkit.report.json

Show persisted plan

nix develop -c cargo run -p archkit-cli -- project generate --root ./my-project --plan

Use when reviewing planned artifact ids, targets, inputs, renderers, and output paths.

Check persisted plan drift

nix develop -c cargo run -p archkit-cli -- project generate --root ./my-project --check

Use when manifest or model changed and you need to know whether persisted plan stale. Check reads current manifest-derived plan and compares it to persisted reports/generate/project-generate.archkit.plan.json.

Explain all planned artifacts

nix develop -c cargo run -p archkit-cli -- project generate --root ./my-project --explain

Use when you need inventory of artifact ids, targets, renderers, templates, inputs, and output paths.

Explain one artifact by id

nix develop -c cargo run -p archkit-cli -- project generate --root ./my-project --explain --artifact-id json.schema:schema

Explain one artifact by output path

nix develop -c cargo run -p archkit-cli -- project generate --root ./my-project --explain --output-path generated/domain.schema.json

Template overrides

Template-backed generation supports:

  • explicit template_override = "..."
  • conventional project overrides in templates/codegen/
  • conventional shared overrides in templates/shared/codegen/
  • builtin fallback templates

Resolution order:

explicit override
-> templates/codegen/
-> templates/shared/codegen/
-> builtin template

Unused conventional override files do not fail generation. They emit warning diagnostics in generation report and persisted reports/generate/project-generate.archkit.report.json.

File ownership rules

DirectoryTypical contentsHuman-editable
authored/source AKS modelsyes
overlays/tags, notes, tracking overlaysyes
mirror/generated observationsusually no
promoted/proposal workflow filesmixed
generated/generated artifactsno
reports/generated reportsno
.archkit/index/generated indexesno

Practical workflow

  1. edit models under authored/
  2. adjust [[generate]] manifest entries if outputs change
  3. run project generate
  4. inspect with --plan, --check, or --explain when needed
  5. review generated outputs plus persisted project-generate.archkit.plan.json and project-generate.archkit.report.json
  6. run layout-check and dogfood for broader project health

Notes

  • output paths for [[generate]] entries must stay under generated/
  • generation plan stays deterministic and persisted under reports/generate/
  • artifact lookups use either stable artifact_id or relative output_path
  • use Nix-wrapped commands in this repo

Future Enhancements (Optional M7 Roadmap)

The generation-spec implementation is complete as of 2026-06-23. Optional enhancements are documented in the M7 enhancement roadmap:

See: docs/plans/archkit-codegen-m7-enhancement-roadmap.md

Planned future work includes:

  • Diff/Report Command: Rich visibility into generation plan changes with HTML diffing
  • Additional Targets: Python (dataclass/Pydantic), Go, Rust, GraphQL, OpenAPI, Protobuf
  • Richer UX: Enhanced explain output, interactive CLI explorer, HTML plan viewer, verbose reporting
  • Cross-Cutting: Metrics collection, config profiles, dry-run mode, plugin system

These enhancements are not blockers for the current generation-spec flow and can be implemented in phases.

Project System Example Walkthrough

This guide walks through creating and managing a real project using the Archkit project system.

Setup: Create a New Project

# Create project directory
mkdir my-ecommerce-arch
cd my-ecommerce-arch

# Initialize the project structure
archkit project init --root . --name "E-Commerce Architecture"

# Check that everything was created
ls -la

Output:

archkit.project.toml
authored/
overlays/
mirror/
promoted/
generated/
reports/
.archkit/

Step 1: Define Your Architecture Model

Edit authored/E-Commerce Architecture.archkit.model.aks:

workspace "E-Commerce Architecture"
  module ecommerce@v1.0

  entity customer
    has tag actor
  end entity

  entity admin
    has tag actor
  end entity

  entity ecommerce_platform
    has tag system
  end entity

  entity payment_gateway
    has tag external
  end entity

  entity email_service
    has tag external
  end entity

  entity api
    has tag backend
    has tech: "Node.js"
  end entity

  entity frontend
    has tag frontend
    has tech: "React"
  end entity

  entity database
    has tag datastore
    has tech: "PostgreSQL"
  end entity

  relationship customer uses frontend
  end relationship

  relationship admin uses frontend
  end relationship

  relationship frontend calls api
  end relationship

  relationship api writes to database
  end relationship

  relationship api calls payment_gateway
  end relationship

  relationship api calls email_service
  end relationship
end workspace

Step 2: Check Initial Layout

archkit project layout-check --root .

Expected output:

{"errors": 0, "warnings": 0, "diagnostics": []}

Step 3: Run Initial Health Check

archkit project dogfood --root . --json-out health-baseline.json
cat health-baseline.json

Output:

{
  "schema_version": 1,
  "status": "green",
  "project_name": "E-Commerce Architecture",
  "stages": [
    {"stage": "manifest_load", "status": "green", "message": "Manifest loaded successfully"},
    {"stage": "index_build", "status": "green", "message": "Index built: 2 entries"},
    {"stage": "layout_check", "status": "green", "message": "Layout check: 0 errors, 0 warnings"},
    {"stage": "frontend_parse", "status": "green", "message": "AKS models parse successfully"}
  ]
}

Step 4: Tag Key Components

Tag components as public API or critical for governance:

# Tag the API server as public-facing
archkit project tag --root . api public-api

# Tag the database as critical infrastructure
archkit project tag --root . database critical-infrastructure

# Tag the payment gateway integration
archkit project tag --root . payment_gateway pci-scope

# Mark components by stability
archkit project tag --root . frontend stable
archkit project tag --root . api stable
archkit project tag --root . database stable

Check the tags file:

cat overlays/tags.archkit.overlay.aks

Output (overlay file with annotations):

workspace "Tags"
  entity api
    has tag public-api
    has tag stable
  end entity

  entity database
    has tag critical-infrastructure
    has tag stable
  end entity

  entity payment_gateway
    has tag pci-scope
  end entity

  entity frontend
    has tag stable
  end entity
end workspace

Step 5: Document Decisions

Add decision notes for audit trails:

# Document API design decision
archkit project note --root . api "REST API following OpenAPI 3.0 spec. Decision made 2026-05-30 by Architecture Board."

# Document data storage decision
archkit project note --root . database "PostgreSQL chosen for ACID compliance and complex queries. Evaluated MySQL and MongoDB."

# Document security decision
archkit project note --root . payment_gateway "PCI DSS compliance required. Never stores credit card data, delegates to Stripe."

Check the notes file:

cat overlays/notes.archkit.overlay.aks

Step 6: Build the Project Index

Generate a complete index of all project files:

archkit project index --root . --json-out project-index.json
cat project-index.json

Output (abbreviated):

{
  "schema_version": 1,
  "project_name": "E-Commerce Architecture",
  "entries": [
    {
      "rel_path": "authored/E-Commerce Architecture.archkit.model.aks",
      "subject": "E-Commerce Architecture",
      "kind": "model",
      "format": "aks",
      "origin": "authored",
      "editable": true,
      "generated": false,
      "content_hash": "a1b2c3d4...",
      "size_bytes": 1024
    },
    {
      "rel_path": "overlays/tags.archkit.overlay.aks",
      "subject": "tags",
      "kind": "overlay",
      "format": "aks",
      "origin": "authored",
      "editable": true,
      "generated": false,
      "content_hash": "e5f6g7h8...",
      "size_bytes": 512
    }
  ],
  "unclassified": []
}

Step 7: Add More Models

Create additional models for different system aspects:

# Data model
cat > authored/data-model.archkit.model.aks << 'EOF'
workspace "Data Model"
  module data_model@v1.0

  shape Order
    id: String
    customer_id: String
    items: [OrderItem]
    total: Float
    status: String
    created_at: String
  end shape

  shape OrderItem
    product_id: String
    quantity: Int
    price: Float
  end shape

  entity current_order: Order
    has status: "pending"
  end entity
end workspace
EOF

Check layout:

archkit project layout-check --root .

Step 8: Run Full Health Check

archkit project dogfood --root . --json-out health-final.json --strict
echo "Exit code: $?"

This will exit with 0 (success) because all checks pass. Without --strict, it would also succeed on Yellow status.

Step 9: Review Health Report

cat health-final.json | jq '.stages[]'

Output:

{
  "stage": "manifest_load",
  "status": "green",
  "message": "Manifest loaded successfully"
}
{
  "stage": "index_build",
  "status": "green",
  "message": "Index built: 3 entries"
}
{
  "stage": "layout_check",
  "status": "green",
  "message": "Layout check: 0 errors, 0 warnings"
}
{
  "stage": "frontend_parse",
  "status": "green",
  "message": "AKS models parse successfully"
}

Step 10: Simulate an Error Condition

Intentionally place a file in the wrong directory to see error handling:

# Create a model in the wrong directory (generated instead of authored)
mkdir -p generated
cp authored/E-Commerce\ Architecture.archkit.model.aks generated/bad-placement.archkit.model.aks

# Run layout check
archkit project layout-check --root . --json-out bad-layout.json

Output:

{
  "errors": 1,
  "warnings": 0,
  "diagnostics": [
    {
      "severity": "error",
      "code": "misplaced_model",
      "rel_path": "generated/bad-placement.archkit.model.aks",
      "message": "model files should live in authored, found in generated",
      "expected_dir": "authored",
      "actual_dir": "generated"
    }
  ]
}

Dogfood will now report Red:

archkit project dogfood --root . --json-out health-error.json
cat health-error.json | jq '.status'

Output: "red"

Step 11: Fix the Error

rm generated/bad-placement.archkit.model.aks
archkit project layout-check --root .

CI/CD Integration

Add to your CI pipeline (e.g., GitHub Actions, GitLab CI):

#!/bin/bash
set -e

# Check layout rules are followed
archkit project layout-check --root . --json-out layout-report.json

# Run full health check (fail if not Green)
archkit project dogfood --root . --json-out dogfood-report.json --strict

# Generate updated index
archkit project index --root . --json-out project-index.json

# Upload reports as artifacts
echo "✅ All project checks passed"

Project Maintenance

Regular commands for project maintenance:

# Monthly: Review architecture health
archkit project dogfood --root . --json-out reports/monthly-health-$(date +%Y-%m).json

# After major changes: Update tags
archkit project tag --root . "New Component" "new" "pending-review"

# Quarterly: Audit project structure
archkit project index --root . --json-out reports/quarterly-index-$(date +%Y-Q%q).json

# Before release: Final validation
archkit project dogfood --root . --json-out reports/pre-release-health.json --strict

Self-Hosting Assessment (M1-M9)

Before finalizing your architecture, assess self-hosting readiness:

# Comprehensive adoption assessment
archkit project self-hosting-assess --root . --format text

# JSON format for dashboards
archkit project self-hosting-assess --root . --format json --out adoption-report.json

# Track over time
archkit project self-hosting-assess --root . --format json \
  --out reports/adoption-$(date +%Y-%m-%d).json

This generates a complete adoption report showing:

  • Status: Ready / WarningsPending / Failed
  • Statistics: Artifacts, capabilities, extensions, packages
  • Validation: Consistency, integrity, completeness checks
  • Findings: Specific errors, warnings, information
  • Recommendations: Actionable next steps

Example report:

ARCHKIT SELF-HOSTING ADOPTION REPORT
System: E-Commerce Architecture
Status: WarningsPending

STATISTICS
  Artifacts: 3
  Capabilities: 2
  Extensions: 1
  Packages: 8
  Workspace Elements: 12
  Issues: 1

VALIDATION RESULTS
  Consistency: ✓ Pass
  Referential Integrity: ✓ Pass
  Completeness: ✗ Fail (1 warning)
  Errors: 0
  Warnings: 1

FINDINGS
  1. [Warning] empty_extensions
  Remediation: Add extensions to enable extension-based workflows

RECOMMENDATIONS
  1. Address validation warnings to reach Ready status
  2. Define extensions for modeling updates
  3. Once Ready, ready for production adoption

See: SELF_HOSTING_CLI_ASSESSMENT.md for the complete assessment guide.

Summary

The project system provides:

  • ✅ Structured organization of architecture models
  • ✅ Metadata tracking via overlays (tags, notes, decisions)
  • ✅ Automated validation and health checks
  • ✅ Deterministic indexing for reproducibility
  • ✅ Self-hosting assessment for adoption readiness
  • ✅ CI/CD integration for governance
  • ✅ Audit trail of decisions and changes

Your project is now ready for collaboration, review, and evolution!

Dogfooding: Project Health Checks

Dogfooding is Archkit’s multi-stage project health check system. It validates your architecture models across seven dimensions, giving you a comprehensive view of model quality, completeness, and consistency.

Overview

The dogfood check runs automatically as part of the project dogfood command and provides deterministic status reporting: Green (all checks pass), Yellow (warnings present), or Red (errors found).

archkit project dogfood --root /path/to/project

The Seven Stages

Stage 1: Manifest Load

What it checks: Can your project manifest be parsed?

{
  "stage": "manifest_load",
  "status": "green",
  "message": "Manifest loaded successfully"
}

Status Rules:

  • 🟢 Green: archkit.project.toml exists and is valid TOML
  • 🔴 Red: Parse error or file missing

What it means: If this fails, none of the other stages can run. Fix the manifest TOML syntax and try again.


Stage 2: Index Build

What it checks: Can all files in your project be classified and indexed?

{
  "stage": "index_build",
  "status": "yellow",
  "message": "Index built: 14 entries, 2 unclassified"
}

Status Rules:

  • 🟢 Green: All files classified (follow <subject>.archkit.<kind>.<format> naming)
  • 🟡 Yellow: Some files couldn’t be classified
  • 🔴 Red: Index build failed (disk error, permissions, etc.)

What it means: Unclassified files are warnings, not errors. Review your file naming to ensure models follow the convention.

Example valid names:

  • workspace.archkit.model.aks - authored model
  • tags.archkit.overlay.aks - overlay annotations
  • cargo-workspace.archkit.mirror.aks - mirror observation
  • 2026-06-14.cargo-workspace.archkit.mirror.aks - timestamped mirror

Stage 3: Layout Check

What it checks: Do files live in the correct directories?

{
  "stage": "layout_check",
  "status": "green",
  "message": "Layout check: 0 errors, 0 warnings"
}

Status Rules:

  • 🟢 Green: All files in correct directories, 0 errors, 0 warnings
  • 🟡 Yellow: Layout warnings (e.g., unexpected files in authored/)
  • 🔴 Red: Layout errors (e.g., editable files in generated/, orphaned models)

Directory Rules:

DirectoryEditableAuto-GeneratedExpected Files
authored/.model.aks
overlays/.overlay.aks
mirror/.mirror.aks, .import.json
generated/schemas, types, diffs
promoted/⚠️⚠️proposals, accepted, rejected
reports/analysis reports
.archkit/index/project index

What it means: Layout violations can prevent other tools from finding your models. Fix directory ownership and try again.


Stage 4: Frontend Parse

What it checks: Do all AKS models parse without syntax errors?

{
  "stage": "frontend_parse",
  "status": "green",
  "message": "AKS models parse successfully"
}

Status Rules:

  • 🟢 Green: All .aks files parse successfully
  • 🔴 Red: One or more files have syntax errors
  • 🟡 Yellow: Parsing disabled (when frontend-aks feature is not enabled)

What it means: AKS files must follow the correct syntax. Use archkit parse --input model.aks to debug specific files.


Stage 5: Drift Check

What it checks: How well do your authored models match mirror observations (cargo workspace)?

{
  "stage": "drift_check",
  "status": "yellow",
  "message": "Drift check: 8 matched, 2 missing from authored, 0 missing from mirror"
}

Status Rules:

  • 🟢 Green: 100% of mirror entities have authored models
  • 🟡 Yellow: Some drift found (entities in mirror but not modeled, or vice versa)
  • 🔴 Red: Mirror data missing or drift detection failed

Metrics:

  • Matching entities: Crates/modules present in both mirror and authored models
  • Missing from authored: Mirror observations you haven’t modeled yet
  • Missing from mirror: Models you’ve authored but aren’t in the actual codebase

What it means: Drift indicates gaps between intent (your models) and reality (mirror observations). High drift often means your architecture models are out-of-sync with your codebase.

How to fix:

# See what's drifting
archkit project dogfood --root . --json-out report.json

# Look at the drift findings in reports/mirror/

# Create proposals to bridge the gap
archkit project promote plan --root . --kind cargo.workspace

# Review and apply them
archkit project promote apply --root . --proposal promoted/pending/<proposal>.aks

Stage 6: Quality Check

What it checks: How complete and consistent are your authored models?

{
  "stage": "quality_check",
  "status": "yellow",
  "message": "Quality check: 80% completeness (8/10), 0 orphans, 2 unmodeled deps"
}

Status Rules:

  • 🟢 Green: ≥90% completeness, 0 orphan entities, 0 unmodeled internal dependencies, 0 naming violations
  • 🟡 Yellow: ≥70% completeness, but may have warnings
  • 🔴 Red: <70% completeness or violations found

Metrics:

  • Completeness: % of actual crates/modules that have been modeled
  • Orphan entities: Entities in your models that don’t exist in the codebase
  • Unmodeled dependencies: Internal package-to-package dependencies you haven’t captured
  • Naming violations: Entities that don’t follow snake_case convention

What it means: Quality score tells you how much of your system you’ve documented. Aim for ≥90% Green.

How to improve:

  • Model missing crates: add more Crate entities to authored/ models
  • Fix orphans: remove modeled entities that no longer exist
  • Capture dependencies: add morph edges for internal package dependencies
  • Use consistent naming: ensure entity names follow naming conventions

Stage 7: Type Check

What it checks: Are all type references in your models valid and consistent?

{
  "stage": "type_check",
  "status": "green",
  "message": "Type check: 0 unresolved, 0 ambiguous, 0 union violations, 0 cross-model issues"
}

Status Rules:

  • 🟢 Green: 0 unresolved references, 0 ambiguous references, 0 union violations
  • 🟡 Yellow: Cross-model type issues (types defined in multiple models)
  • 🔴 Red: Unresolved or ambiguous type references found

Diagnostics:

  • Unresolved refs: Type references that don’t have matching definitions
  • Ambiguous refs: Type names that match multiple definitions
  • Union violations: Union types defined inconsistently across models
  • Cross-model issues: Same type defined in multiple models (potential incompatibility)

What it means: Type validation ensures your type system is well-formed. References should point to valid, uniquely-named types.

How to fix:

  • Add missing type definitions (shape, event, entity type)
  • Rename duplicate types to be unique within scope
  • Ensure union types have consistent members across models

Overall Status Rollup

The dogfood status is determined by the worst stage:

Red > Yellow > Green

If any stage is Red, the overall status is Red. If no Red stages exist but Yellow stages exist, the status is Yellow. Only if all stages are Green is the overall status Green.

Usage Examples

Run dogfood on a project

archkit project dogfood --root /path/to/my-project

Output:

{
  "schema_version": 1,
  "status": "yellow",
  "project_name": "my-project",
  "stages": [
    { "stage": "manifest_load", "status": "green", "message": "..." },
    { "stage": "index_build", "status": "green", "message": "..." },
    { "stage": "layout_check", "status": "green", "message": "..." },
    { "stage": "frontend_parse", "status": "green", "message": "..." },
    { "stage": "drift_check", "status": "yellow", "message": "..." },
    { "stage": "quality_check", "status": "green", "message": "..." },
    { "stage": "type_check", "status": "green", "message": "..." }
  ]
}

Get JSON output for scripting

archkit project dogfood --root . | jq '.status'
# Output: "yellow"

archkit project dogfood --root . | jq '.stages[] | select(.stage == "drift_check")'
# Output: { "stage": "drift_check", "status": "yellow", "message": "..." }
archkit project history --root . --limit 10

Shows Green/Yellow/Red status over time plus improvement rate percentage.

Integration with CI/CD

GitHub Actions Example

- name: Check architecture health
  run: |
    STATUS=$(archkit project dogfood --root . | jq -r '.status')
    if [ "$STATUS" = "red" ]; then
      echo "Architecture health check failed"
      exit 1
    fi

Exit codes

  • Green or Yellow: exit 0 (success)
  • Red: exit 1 (failure)

Feature Gates

The frontend_parse stage (Stage 4) requires the frontend-aks feature:

# With feature enabled (default)
cargo build --features frontend-aks

# Stage runs, validates AKS syntax
archkit project dogfood --root .

# Without feature
cargo build --no-default-features
# Stage is skipped, status defaults to Yellow
CommandPurpose
archkit project initCreate project skeleton with starter models
archkit project indexRebuild and view the project file index
archkit project layout-checkDetailed layout validation report
archkit project driftDeep dive into mirror vs. authored drift
archkit project qualityDetailed quality metrics and analysis
archkit project type-checkDetailed type validation report
archkit project verifyAggregate health check (includes dogfood + mirror-check)
archkit project promote planGenerate proposals from drift findings
archkit project promote applyApply proposals to authored models

Troubleshooting

“Drift check returned Red”

Cause: Mirror data not found or mirror-check failed

Fix: Generate mirror observations first

archkit mirror run --root . --kind cargo.workspace --write

“Quality check is Yellow”

Cause: <90% of crates are modeled

Fix: Add more Crate entities to your authored models

archkit project promote plan --root . --kind cargo.workspace
archkit project promote apply --root . --proposal promoted/pending/<generated>.aks

“Type check shows unresolved refs”

Cause: Type references without matching definitions

Fix: Either define the missing types or remove invalid references

# Add a shape definition
archkit parse --input my-model.aks  # to see errors
# Edit the file to fix type references

“Index build shows unclassified files”

Cause: Files don’t follow <subject>.archkit.<kind>.<format> naming

Fix: Rename files to match the convention

# Bad:  my-types.aks
# Good: my-types.archkit.model.aks

# Bad:  annotations.txt
# Good: annotations.archkit.overlay.aks

Best Practices

  1. Aim for Green on all stages. Yellow is acceptable for drift during active development, but work toward closure.

  2. Fix from top to bottom. Manifest → Index → Layout → Parse → Drift → Quality → Type. Earlier stages block later ones.

  3. Keep models in sync. Run archkit project promote plan regularly to identify drift early, before it accumulates.

  4. Use consistent naming. Follow snake_case for entity names (e.g., my_service, not myService).

  5. Version your models. Commit dogfood reports to see trends over time. Use archkit project history to track improvement.

  6. Integrate into CI. Make dogfood status part of your PR checks. Prevent Red from merging.

See Also

Promotion System Guide

This guide explains how to use Archkit’s promotion system to convert mirror observations (drift findings) into authored model updates.

Overview

The promotion system bridges the gap between automated observations (mirrors) and curated architectural intent (authored models). It allows you to:

  1. Discover what’s missing in your authored model vs. actual system (via mirrors)
  2. Review proposed changes (promotion proposals)
  3. Selectively choose which items to promote
  4. Apply changes to overlays or authored models
  5. Reject proposals you don’t want

Core Concepts

Mirror vs. Authored

  • Mirror: Auto-generated observation of actual system structure (read-only)
  • Authored: Human-written architectural intent (read-write)
  • Drift: Difference between the two
  • Promotion: Process of closing the gap by updating authored models

Promotion Workflow

1. Mirror       → Scan actual system (cargo, rustdoc, etc.)
   ↓
2. Drift        → Compare to authored model
   ↓
3. Plan         → Generate proposal with missing items
   ↓
4. Review       → Examine what would be promoted
   ↓
5. Apply/Reject → Merge into model or discard
   ↓
6. Health Check → Verify new model is valid

Targets

Overlays (Default, Non-Destructive):

  • Appends entities to overlays/promoted.archkit.overlay.aks
  • Preserves original authored model
  • Good for annotations and progressive updates

Authored (Direct Model Updates):

  • Inserts entities into authored/workspace.archkit.model.aks
  • Modifies authoritative model directly
  • Requires --allow-authored-write safety flag
  • Better for complete model migrations

Command Reference

Plan: Discover Missing Items

# Plan promotion to overlay (default)
archkit project promote plan \
  --root . \
  --kind cargo.workspace

# Plan promotion to authored model
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --to authored

# Plan with output file
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --json-out promoted/plans/workspace.json

Output: JSON report with:

  • Proposal file path
  • Entity count (what was found missing)
  • Dependency count
  • Status (green=found items, yellow=nothing to promote, red=drift error)

Selective Promotion: Choose What to Promote

By Entity

# Select single entity
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --select-entity archkit-core

# Select multiple entities
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --select-entity archkit-core \
  --select-entity archkit-project \
  --select-entity archkit-type-model

By Dependency

# Format: --select-dep FROM:TO

# Single dependency
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --select-dep archkit:archkit-core

# Multiple dependencies
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --select-dep archkit-app:archkit \
  --select-dep archkit-app:archkit-core

Combined Selection

# Entities AND dependencies
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --select-entity archkit-core \
  --select-entity archkit-project \
  --select-dep archkit:archkit-core \
  --select-dep archkit-app:archkit-project

Apply: Merge Proposal into Model

# Apply to overlay (default, safe)
archkit project promote apply \
  --root . \
  --proposal promoted/pending/cargo-workspace.archkit.proposal.aks

# Apply to authored model (requires safety flag)
archkit project promote apply \
  --root . \
  --proposal promoted/pending/cargo-workspace.archkit.proposal.aks \
  --allow-authored-write

# Apply with output file
archkit project promote apply \
  --root . \
  --proposal promoted/pending/cargo-workspace.archkit.proposal.aks \
  --json-out promoted/reports/apply.json

Safety:

  • --allow-authored-write is required for authored target
  • Missing flag → Error (safe by default)
  • Overlay target → No flag needed (non-destructive)
  • Destination root must be authored/ or overlays/
  • Proposal path must resolve under promoted/pending/
  • Absolute paths and parent traversal are rejected
  • Proposal header target must match command destination
  • Proposal finding codes must match expected codes when supplied
  • Proposal and destination hashes are rechecked immediately before mutation

See also: ../architecture/command-path-hardening-phase-2-1.md

Reject: Discard Proposal

# Reject proposal (moves to promoted/rejected/)
archkit project promote reject \
  --root . \
  --proposal promoted/pending/cargo-workspace.archkit.proposal.aks

Workflow Examples

Example 1: Full Workspace Promotion

Scenario: You have a new Rust project and want to model all crates at once.

# 1. Scan cargo workspace
archkit project mirror \
  --root . \
  --kind cargo.workspace \
  --source . \
  --write

# 2. Plan promotion
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --source . \
  --json-out /tmp/plan.json

# 3. Review proposal (examine /tmp/plan.json)
jq '.entities, .dependencies' /tmp/plan.json

# 4. Apply to authored model
archkit project promote apply \
  --root . \
  --proposal promoted/pending/cargo-workspace.archkit.proposal.aks \
  --allow-authored-write

# 5. Verify health
archkit project dogfood --root .

Example 2: Selective Promotion by Tier

Scenario: Large codebase, promote tier by tier.

# Tier 1: Core infrastructure
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --select-entity archkit-core \
  --select-entity archkit-substrate-model \
  --to authored

archkit project promote apply \
  --root . \
  --proposal promoted/pending/cargo-workspace.archkit.proposal.aks \
  --allow-authored-write

# Tier 2: Libraries
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --select-entity archkit-type-model \
  --select-entity archkit-project \
  --to authored

archkit project promote apply \
  --root . \
  --proposal promoted/pending/cargo-workspace.archkit.proposal.aks \
  --allow-authored-write

# Tier 3: Applications
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --select-entity archkit-app \
  --select-entity archkit-cli \
  --to authored

archkit project promote apply \
  --root . \
  --proposal promoted/pending/cargo-workspace.archkit.proposal.aks \
  --allow-authored-write

Example 3: Mixed Overlay and Authored

Scenario: Use overlays for temporary annotations, authored for permanent model updates.

# First pass: Add to overlay for review
archkit project promote apply \
  --root . \
  --proposal promoted/pending/cargo-workspace.archkit.proposal.aks

# Review the overlay annotations
cat overlays/promoted.archkit.overlay.aks

# Second pass: Promote selected items to authored
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --select-entity archkit-core \
  --to authored

archkit project promote apply \
  --root . \
  --proposal promoted/pending/cargo-workspace.archkit.proposal.aks \
  --allow-authored-write

Proposal Format

Generated proposals are valid AKS files with metadata headers:

# archkit:file kind=proposal origin=generated subject=cargo-workspace
# archkit:source reports/drift/cargo-workspace.archkit.drift.json
# archkit:target overlays/promoted.archkit.overlay.aks
# archkit:status pending
# archkit:entities 11
# archkit:dependencies 14

workspace "Cargo Workspace Promotion"
  module cargo_workspace_promotion@v0

  operation PromoteProposal
    kind: proposal
    subject: "cargo.workspace"
    target: "overlays/promoted.archkit.overlay.aks"
    entities: 11
    dependencies: 14
  end operation

  entity archkit: Crate
    has name: "archkit"
    has path: "crates/archkit"
    has manifest: "crates/archkit/Cargo.toml"
    has promoted_from: "cargo.workspace"
  end entity

  # ... more entities and relationships ...
end workspace

Best Practices

Command-Path Safety Model

promote_apply is first command-governed mutation sample in Archkit.

Validation invariants

Before mutation, command validation enforces:

  • proposal path under promoted/pending/
  • destination under authored/ or overlays/
  • workspace-relative paths only
  • no absolute paths
  • no .. traversal
  • proposal metadata target matches destination
  • authored writes require explicit opt-in

Pre-mutation recheck

Immediately before write/move, Archkit rechecks:

  • proposal still exists
  • proposal hash unchanged
  • destination hash or missing/present state unchanged
  • proposal target still matches destination
  • finding code expectations still match

If any recheck fails, apply aborts without writing target or moving proposal.

Event behavior

Command path emits:

  • command.accepted
  • command.started
  • project.promote.applied
  • command.completed
  • command.failed

Failure policy:

  • pre-mutation lifecycle emit failure → command fails closed
  • post-mutation fact emit failure → mutation remains, report marks audit_gap

1. Validate Before Applying

# Generate proposal first
archkit project promote plan \
  --root . \
  --kind cargo.workspace \
  --json-out /tmp/plan.json

# Review the report
jq . /tmp/plan.json | less

# Only then apply
archkit project promote apply --root . ...

2. Start with Overlay, Move to Authored

# Safe: Try in overlay first
archkit project promote apply --root .

# Review overlay annotations
cat overlays/promoted.archkit.overlay.aks

# When ready: Move to authored with selection
archkit project promote plan --root . --to authored --select-entity ...
archkit project promote apply --root . --allow-authored-write

3. Use Selective Promotion for Large Codebases

# Don't promote everything at once
# Break into manageable chunks
archkit project promote plan \
  --root . \
  --select-entity core-lib \
  --select-entity util-lib

4. Track Changes with History

# Before promoting
archkit project dogfood --root . > /tmp/before.json

# After promoting
archkit project dogfood --root . > /tmp/after.json

# Compare
diff /tmp/before.json /tmp/after.json

Directory Structure

After running promotion commands, your project will have:

project/
├── promoted/
│   ├── pending/                    # Awaiting apply/reject
│   │   └── cargo-workspace.archkit.proposal.aks
│   ├── accepted/                   # Applied proposals
│   │   └── cargo-workspace.archkit.proposal.aks
│   └── rejected/                   # Rejected proposals
│       └── old-workspace.archkit.proposal.aks
├── authored/
│   └── workspace.archkit.model.aks # Updated by apply
└── overlays/
    └── promoted.archkit.overlay.aks # Updated by apply

Troubleshooting

Proposal Shows 0 Entities

Cause: All items already in authored model
Solution: Update mirror if system changed, or review authored model

Error: “proposal targets authored model but –allow-authored-write was not provided”

Cause: Trying to apply to authored without safety flag
Solution: Add --allow-authored-write flag to apply command

Error: “proposal path must be under promoted/pending/”

Cause: Proposal file in wrong location
Solution: Only proposals in promoted/pending/ can be applied

Merge Conflict in Authored Model

Cause: Proposal tries to add duplicate entities
Solution: Use selective promotion to target only new items

See Also

CLI Commands (Curated Guide)

Canonical CLI help lives in generated reference:

  • apps/archkit-cli/generated/persistent/docs/cli-reference.md

Use this page for navigation + policy, not copied help text.

Ownership model

  • Generated command details: gen_docs output (cli-reference.md)
  • Curated/operator guidance: this page + adjacent reference docs
  • Drift rule: do not duplicate full --help blocks here

Common flows

  • Parse/validate/view: archkit parse, archkit validate, archkit view
  • Batch operations: archkit validate-all, archkit view-all, archkit index
  • Project management: archkit project <subcommand> (init, index, layout-check, tag, note, dogfood, check, mirror, drift, promote, verify)
  • Docs pipeline: archkit docgen
  • Type model workflows: archkit type-model <subcommand>
  • Snapshot lifecycle: archkit snapshot <subcommand>

Project Init Configuration

The archkit project init command is configurable via CLI flags:

archkit project init --root <dir> --name <name> \
  [--version <version>] \
  [--description <description>] \
  [--overlay <overlay>...]
  • --root - Project root directory (default: .)
  • --name - Project name (required if not inferring from –root)
  • --version - Semantic version for archkit.project.toml (default: v0)
  • --description - Optional project description
  • --overlay - Custom overlay file stems (repeatable; when provided, replaces defaults)

Configuration is persisted in archkit.project.toml under [init]. Re-running init on an existing project is idempotent and respects saved configuration as defaults.

Feature-gated commands

See generated matrix:

  • apps/archkit-cli/generated/persistent/docs/feature-command-matrix.md

Quick start

archkit --help
archkit <command> --help

For full command tree coverage, rely on generated cli-reference.md only.

Canonical Project Architecture

architecture/ is canonical authored source-of-truth for architecture-as-code in this repository.

This directory defines how archkit models itself and other first-class architecture artifacts.

Ownership and Policy

  • Canonical authored models live in architecture/models/*.aks.
  • AKS (.aks) is source-of-truth authoring format.
  • Nickel (.ncl) remains complementary for parity and contract workflows.
  • Generated outputs must go under generated/ephemeral/**.
  • Do not commit generated outputs from architecture workflows.

Directory Layout (v0)

  • architecture/models/
    • Canonical architecture specs.
    • architecture/models/modules/ stores reusable structure modules referenced by canonical specs.
  • architecture/views/
    • View intent map and review guidance.
  • architecture/contracts/
    • Modeling guardrails and evolution notes.
  • architecture/decisions/
    • ADRs for major architecture modeling decisions.
    • canonicalization-design.md — Design of SubstrateAksDocument fingerprinting and JCS canonicalization
  • command-path-hardening-phase-2-1.md
    • Hardening record for ProjectCommand::PromoteApply validation, path safety, TOCTOU checks, event policy, and build-state boundary.
  • ../guides/RUNTIME_WATCH.md
    • Runtime host architecture for foreground watch/live execution.
  • ../guides/TUI.md
    • Phase 7 terminal UI client/view architecture over runtime, event, build, command, and store surfaces.

Modeling Conventions

  • IDs use prefixes: person_*, sys_*, ctr_*, cmp_*.
  • Relationship labels are verb-first (parses, projects, renders, emits).
  • Every container/component includes properties.path when mapped to repo code.
  • architecture/models/archkit_self.aks is canonical entrypoint.
  • Start small (10-20 elements), then add detail only when view needs it.

Command Loop

Validate canonical model:

cargo run --bin archkit -- validate -i architecture/models/archkit_self.aks

Project selected review views (DOT + Mermaid sidecar + canonical JSON sidecar):

cargo run --bin archkit -- project -i architecture/models/archkit_self.aks --view-id ctx_archkit -o generated/ephemeral/architecture/archkit-self/ctx_archkit.dot
cargo run --bin archkit -- project -i architecture/models/archkit_self.aks --view-id ctr_archkit -o generated/ephemeral/architecture/archkit-self/ctr_archkit.dot
cargo run --bin archkit -- project -i architecture/models/archkit_self.aks --view-id wf_from_cli -o generated/ephemeral/architecture/archkit-self/wf_from_cli.dot
cargo run --bin archkit -- project -i architecture/models/archkit_self.aks --view-id dep_all -o generated/ephemeral/architecture/archkit-self/dep_all.dot
cargo run --bin archkit -- project -i architecture/models/archkit_self.aks --view-id cmp_cli -o generated/ephemeral/architecture/archkit-self/cmp_cli.dot
cargo run --bin archkit -- project -i architecture/models/archkit_self.aks --view-id cmp_frontends -o generated/ephemeral/architecture/archkit-self/cmp_frontends.dot
cargo run --bin archkit -- project -i architecture/models/archkit_self.aks --view-id cmp_render -o generated/ephemeral/architecture/archkit-self/cmp_render.dot
cargo run --bin archkit -- project -i architecture/models/archkit_self.aks --view-id int_external -o generated/ephemeral/architecture/archkit-self/int_external.dot

Optional render gate (requires Graphviz dot):

cargo run --bin archkit -- render -i generated/ephemeral/architecture/archkit-self/ctr_archkit.dot -f svg -o generated/ephemeral/architecture/archkit-self/ctr_archkit.svg

Cargo-Make Shortcut

Use:

cargo make architecture-self

This runs validate + deterministic projection for canonical self-model. All generated architecture artifacts must remain under generated/ephemeral/** and are not committed.

Operations

  • ci.md
  • packaging.md
  • release-process.md
  • release-checklist.md

Cloudflare Pages Deployment for mdBook

This repo can publish docs with mdBook to Cloudflare Pages.

Build output

  • mdBook config: docs/book.toml
  • source: docs/src/
  • build output: docs/book/

Local build

Use repo docs shell:

nix develop .#docs -c mdbook build docs

Serve locally:

nix develop .#docs -c mdbook serve docs --open

Recommended path: GitLab CI builds book, deploys to Cloudflare Pages. Reason: repo already has .gitlab-ci.yml; docs should publish from same CI system.

Required Cloudflare config

Create Pages project in Cloudflare dashboard.

Set GitLab CI/CD variables:

  • CLOUDFLARE_API_TOKEN
  • CLOUDFLARE_ACCOUNT_ID
  • CLOUDFLARE_PAGES_PROJECT_NAME

GitLab CI jobs

Pipeline file: .gitlab-ci.yml

Build job:

  • installs mdbook
  • runs mdbook build docs
  • stores docs/book/ as artifact

Deploy job:

  • runs in node:22-bullseye
  • installs wrangler
  • runs:
wrangler pages deploy docs/book \
  --project-name "$CLOUDFLARE_PAGES_PROJECT_NAME" \
  --branch "$CI_COMMIT_REF_SLUG"

Current rule: deploy on default branch only.

Native Cloudflare Pages build

Possible, but weaker fit. Reason: Cloudflare Pages build image does not use repo Nix shell by default.

If using native Pages build, configure:

  • Framework preset: None
  • Build command: install mdbook, then mdbook build docs
  • Build output directory: docs/book

Use native build only if you accept non-Nix tool bootstrap in build step.

Custom domain

After first deploy, attach custom domain in Pages project settings.

Notes

  • Do not commit docs/book/
  • Keep authored docs in docs/
  • Keep rustdoc separate from mdBook site
  • Local dev can still use Nix docs shell even if CI installs mdbook directly

API Docs

Use rustdoc for Rust API surface.

Local build

nix develop .#docs -c cargo doc --workspace --no-deps

Open output:

xdg-open target/doc/index.html

Publishing model

Recommended split:

  • mdBook / Cloudflare Pages — AKS + Archkit docs site
  • rustdoc — API reference artifact

Link from this book to hosted rustdoc once publish target exists. Until then, treat rustdoc as local or CI artifact.