Skip to content

janus doc — Sovereign Documentation

Janus treats documentation as structured, queryable ASTDB data — not opaque text blobs. Every doc comment becomes a columnar row in the semantic database, linked to its target declaration by content ID. Documentation cannot drift from the code it describes because the compiler extracts capabilities, effects, and type signatures directly.

This system is inspired by Elixir’s @doc / ExDoc approach, but goes further:

PropertyTraditional (ExDoc, rustdoc)Janus Sovereign
StorageString blobs attached to ASTASTDB columnar rows
IdentityName-based (breaks on rename)CID-based (survives renames)
CapabilitiesNot trackedAuto-extracted from compiler EffectsInfo
DoctestsRegex-extracted from textFirst-class AST nodes, compiled and type-checked
Machine-readablePartial (ad hoc JSON)Native UTCP + query predicates
IncrementalFull rebuildCID-invalidated (unchanged docs skipped)

janus doc is the command that reads the ASTDB and generates output in four formats: Markdown, HTML, JSON, and UTCP.


Documentation uses /// line comments placed immediately before a declaration. The compiler captures these as doc_comment trivia tokens during lexing, then a dedicated extraction pass transforms them into structured DocEntry rows in ASTDB.

/// Open a file at the given path.
///
/// @param path Filesystem path to open
/// @param mode Access mode (read, write, read_write)
/// @param cap Capability token for filesystem access
/// @returns File handle bound to the caller's arena
/// @error FsError.NotFound Path does not exist
/// @error FsError.PermissionDenied Capability insufficient
/// @capability CapFsRead Required for read mode
/// @since 0.3.0
/// @see close_file
/// @safety Caller must ensure the capability token outlives the handle.
/// @complexity O(1) amortized
///
/// ## Examples
/// ```janus
/// let f = open_file("/data/config.kdl", .read, ctx.cap_fs)
/// ```
func open_file(path: String, mode: Mode, cap: CapFsRead) -> File ! FsError do
// ...
end
TagSyntaxPurpose
@param@param name DescriptionDocument a parameter
@returns@returns DescriptionDocument return value
@error@error ErrorType DescriptionDocument error variant
@capability@capability CapName DescriptionRequired capability (supplementary)
@since@since versionVersion introduced
@see@see identifierCross-reference to another declaration
@deprecated@deprecated ReasonMark as deprecated with migration guidance
@safety@safety ExplanationSafety invariants the caller must uphold
@complexity@complexity O(...)Algorithmic complexity

Note on @capability: This tag is supplementary. The compiler auto-extracts required capabilities from the function’s EffectsInfo during semantic analysis. Manual @capability tags add human-readable context only. If a manual tag contradicts the compiler’s analysis, a warning is emitted during janus doc --check.


Terminal window
janus doc --format=md --output=docs/

Generates .md files per module with full Mermaid diagram support:

  • Module dependency graphs auto-generated as Mermaid diagrams
  • Capability flow diagrams showing token threading
  • Compatible with any Markdown renderer (GitHub, GitLab, mdBook, Obsidian)
  • Embedded doctest source with pass/fail status annotations

This is the canonical human-readable format. Suitable for version control and rendering alongside source code.


Terminal window
janus doc --format=html --output=site/

Generates a static HTML site styled with PicoCSS (classless, ~10KB CSS):

FeatureDescription
Module navigationHierarchical sidebar mirroring the module tree
Mermaid diagramsRendered client-side via Mermaid.js
Capability badgesPer-function badges showing required capabilities
Effect markersPer-function markers showing tracked effects
Symbolic markersCompiler-derived safety indicators (see Symbolic Markers)
Doctest indicatorsEmbedded source with pass/fail status
Cross-referencesClickable links from @see tags

This is the beautiful browsable format. Intended for hosting on project documentation sites.


Terminal window
janus doc --format=json --output=api.json

Produces Canonical JSON (RFC 8785) — deterministic key ordering, no trailing whitespace, signable. Suitable for CI tooling, machine consumption, and registry integration.

This format follows the Law of Representation: KDL is for human intent, JSON is for machine state.


Terminal window
janus doc --format=utcp --output=manuals/

Generates structured JSON formatted for AI agent consumption. Each public declaration gets a UTCP entry containing:

  • Function signature with full type annotations
  • Parameter descriptions
  • Return type and error variants
  • Required capabilities and tracked effects
  • Embedded examples

This replaces hand-written utcpManual() functions. The compiler generates them from the same ASTDB data.


Terminal window
janus doc --check

Reports documentation quality issues without generating output:

CheckDescription
Undocumented public itemspub declarations missing /// comments
Missing @param tagsParameters not documented
Capability contradictions@capability tags that disagree with compiler analysis
Stale @see referencesCross-references pointing to renamed or removed items
Deprecated without reason@deprecated tags missing migration guidance

Gate-able in CI: Returns exit code 1 if any issues are found. Combine with HINGE_CI=1 for strict enforcement.


Test blocks placed immediately after a function are linked as that function’s doctest. They are first-class AST nodes — compiled, type-checked, and CID-tracked.

/// Clamp a value to a range.
func clamp(val: i32, lo: i32, hi: i32) -> i32 do
if val < lo do return lo end
if val > hi do return hi end
return val
end
test "clamp basics" do
assert(clamp(5, 0, 10) == 5)
assert(clamp(-1, 0, 10) == 0)
assert(clamp(99, 0, 10) == 10)
end

The compiler sees the test block as a child node of clamp in the ASTDB. Renaming clamp updates the link automatically via CID resolution.

Fenced janus code blocks inside doc comments are also treated as doctests:

/// Format a greeting.
///
/// ## Examples
/// ```janus
/// let msg = greet("Markus")
/// assert(msg == "Hello, Markus!")
/// ```
func greet(name: String) -> String do
return "Hello, " ++ name ++ "!"
end

Unlike regex-extracted doctests in other languages, these are parsed into AST nodes during the doc extraction pass. They participate in type checking and capability analysis.

Terminal window
janus test --doc # Run all doctests
janus test --doc --check # Verify they compile without executing

CID-based caching ensures unchanged doctests are skipped on subsequent runs. Only modified functions or their transitive dependents trigger re-execution.


Use janus query --doc to find declarations based on documentation state. This runs a lightweight predicate evaluator against the ASTDB’s DocStore and Decl arrays — no separate index is built.

Terminal window
janus query --doc "func and not has_doc" file.jan # Undocumented functions
janus query --doc "is_deprecated" file.jan # All deprecated items
janus query --doc "func and has_doctest" file.jan # Functions with doctests
janus query --doc "func and not has_param_doc" file.jan # Missing @param docs
janus query --doc "has_doc and not has_return_doc" file.jan # Missing @returns
PredicateMeaning
has_docDeclaration has a doc entry in DocStore
is_deprecatedHas @deprecated tag
has_doctestHas embedded or adjacent doctest
has_param_docHas at least one @param tag
has_return_docHas @returns tag
has_error_docHas @error tag
funcDeclaration is a function
structDeclaration is a struct/type
enumDeclaration is an enum
constDeclaration is a constant
traitDeclaration is a trait

Combine atoms with and, or, not, and parentheses. Precedence: or < and < not < atom.

Terminal window
janus query --doc "not has_doc" file.jan # All undocumented declarations
janus query --doc "func and has_doc and not has_param_doc" file.jan # Documented but missing @param
janus query --doc "func or struct" file.jan # All functions and structs
$ janus query --doc "is_deprecated" examples/doc_demo.jan
Doc Query: is_deprecated
File: examples/doc_demo.jan
line 39: func factorial — deprecated
1 match(es) in 5 declarations

These predicates operate on the same ASTDB rows that power the documentation output. Queries run against the compiler’s own semantic database.


The documentation output includes symbolic markers auto-inserted based on compiler analysis. These are not decorative — they reflect provable properties.

SymbolNameConditionMeaning
TurnstileAll doctests passProven — compiler verifies correctness
HazardCapabilities requiredEffectful — requires capability tokens
DeltaCompiler transforms appliedTransformed — desugared by compiler
BoxCrosses capability boundaryBoundary — context changes at this point

In HTML output, these appear as colored badges. In Markdown output, they appear inline. In JSON/UTCP output, they are structured fields.


The documentation system is a five-stage pipeline built on top of the existing compilation infrastructure:

  1. Lexer captures /// lines as doc_comment trivia tokens, preserving their source location and content.

  2. Doc extraction pass (post-parse, pre-semantic analysis) transforms trivia tokens into structured DocEntry rows in ASTDB. Each entry contains parsed tags, prose sections, and embedded code blocks.

  3. CID linking associates each DocEntry with its target declaration via content ID. This survives renames, file moves, and refactors — the link is semantic, not textual.

  4. Compiler enrichment populates capability requirements and effect tracking from the semantic analysis phase’s EffectsInfo. This data is authoritative — it comes from the compiler, not from human annotation.

  5. Output generators read the DocEntry table and produce the requested format (MD, HTML, JSON, UTCP). Each generator is a standalone module that reads ASTDB and writes files.


AspectExDoc (Elixir)rustdocJanus Sovereign
StorageString blobs on module attributesString blobs in ASTASTDB columnar rows
IdentityName-basedName-basedCID-based (rename-proof)
CapabilitiesNot trackedNot trackedAuto-extracted from compiler
DoctestsRegex-extracted from MarkdownRegex-extracted from MarkdownFirst-class AST nodes
Machine-readableJSON via mix docsPartial (unstable JSON)Native UTCP + query predicates
IncrementalFull rebuildFull rebuildCID-invalidated
LintingBasic coverage checkmissing_docs lintSemantic checks including capability contradictions
Effect trackingNoneNoneCompiler-verified effect annotations

PhaseDescriptionStatus
Phase 1DocEntry/DocTag/DocTest structs in ASTDBComplete
Phase 2Doc extraction pass (trivia + decl population)Complete
Phase 3janus doc / janus doc --check (MdRenderer + DocChecker)Complete
Phase 4janus query --doc predicate evaluatorComplete
Phase 5Output generators (HTML, JSON, UTCP)Planned
Phase 6Doctest execution, auto-extraction, LSP enrichmentPlanned

RFC-025 is complete through Phase 4 (v2026.3.11). The full ASTDB-integrated pipeline is operational: Parser populates trivia and decls, DocExtractor builds DocStore, MdRenderer generates structured Markdown, DocChecker validates coverage, and query predicates search declarations by documentation state.