Idxs as Mappings, Not Decoration#

An idx looks like text: 1.2, a.i., +, or `1.a.`. Its useful identity is not that text, however. It is a mapping between a visible document site and a place in a hierarchy. Rendering is only one representation of that relation.

This is why arch.idx stores zero-based ordinals separately from style. The first child is place zero whether it renders as 1, a, i, or .. A style can change without changing what the idx addresses, and matches() therefore compares places while render() owns notation.

1 Policy is not mechanism#

Four layers have separate responsibilities:

  1. The domain model parses, renders, builds, and compares idxs.

  2. Document adapters expose structural sites and free comment occurrences.

  3. YAML configuration independently chooses participation, index notation, and header presentation.

  4. The engine derives diagnostics and edits, then applies a content-hash-guarded plan.

The CLI and TUI are projections of layer four. Neither is allowed to invent its own mutation semantics. This makes JSON, a unified diff, and a highlighted terminal pane mutually checkable views of one object.

2 Two idx domains, one clear boundary#

arch.Quad is the preferred name for the original architectonic address. arch.Idx remains its compatibility name. A Quad has at most four concrete places, may be the empty root, and can name an abstract a or b half between its concrete branches. It is also a persisted SQL model value. arch.idx.Idx is instead a non-empty, arbitrary-depth sequence of zero-based document ordinals whose numeral styles, separators, markers, and wrappers are presentation policy.

They therefore must not be joined by a subtype relationship. Subtyping would promise shared construction, ancestry, emptiness, and persistence invariants that neither model actually has. An explicit adapter can be introduced later for a concrete use case. Today, imports name the domain directly, which is the safer and more legible boundary.

3 Positive enrollment precedes observation#

Indexing a document is an authorship decision: it changes the document’s conceptual model, often on every heading. A numeral already present in a file is not evidence of consent. It may be prose, a fixture, foreign numbering, or residue from an earlier tool run. Repository discovery therefore requires a positive indexing.paths rule before it creates a plan. An explicit --spec override or direct Python planner call is also an explicit selection. Diagnostic callers can pass enrolled=False.

Observation only narrows an authorized operation:

  • observed inserts at structural depths already represented in the enrolled file;

  • never validates existing addresses without insertion;

  • all covers the entire intended hierarchy, but is legal only on an explicit path rule or command override.

This is deliberately stricter than “the tool can infer a tree.” Capability does not constitute permission, and an incompatible numeric-looking token is reported without being rewritten.

4 Selection authorities stay independent#

Participation, address notation, and visible header formatting answer different questions. The configuration assigns each authority separately:

  • indexing.paths selects a named IdxSpec.

  • header_paths selects a named HeaderProfile.

  • Document-family defaults choose safe presentation without enrolling indexing.

The internal configuration model exposes both resolutions separately, and arch config show --path FILE reports each authority and its source. A shared name cannot accidentally couple the decisions.

Markdown and source are also separate structural families. The Markdown default is non-case-changing, leaves H1 unindexed, and displays H2+ addresses as dotted backtick tags. Source retains its established code-header dialect. Typst, reStructuredText, and unknown suffixes fail closed until they have dedicated adapters.

5 Comments are real document surfaces#

Source comments carry headings, doctrine, runbooks, and local tables of contents. Ignoring them would make an idx linter language-biased. Treating every comment as a heading would be worse: ordinary prose would become hierarchy.

The adapters therefore separate structural sites from free occurrences. A decorated comment heading can generate an expected hierarchical address. A plain comment idx is still parsed, validated, canonicalized, and removable, but it does not acquire children or reorder its neighbors.

6 Plans make change legible#

A mutation is represented by:

  • the original content digest;

  • decoded text facts such as BOM and newline style;

  • occurrences and structured diagnostics;

  • non-overlapping source spans and replacements.

Application is intentionally boring. It rechecks the digest, applies spans in reverse order, encodes with the original UTF-8 mode, flushes a same-directory temporary file, preserves permissions, and atomically replaces the target. Once replacement succeeds, an unavailable parent directory sync cannot turn that completed write into a reported failure. Refusal is a first-class outcome, not a recovery path hidden behind retries.

Configured depth is also a semantic boundary, not a formatting hint. A structural site beyond max_depth receives an explicit diagnostic and no proposed address. Truncating it would silently map two different sites onto the same visible place.

7 Frontier#

  • Keystone: semantic adapters beyond line syntax

    • Tree-sitter-backed comment recognition could distinguish comments from string literals.

    • Language-specific heading conventions could be configured without weakening generic safety.

    • A measured corpus should establish whether those gains justify the dependency and complexity.

  • Alternative plans

    • The TUI could offer per-occurrence alternatives rather than only per-file systematic modes.

    • Saved plan manifests could support reviewed, later application across agent handoffs.

  • Wider notation

    • Tagged and bespoke wrappers from historical subl/headers projects can be added as explicit specs if real files demonstrate demand.

    • Unicode symbol alphabets need width and normalization tests before adoption.

  • Terminus

    • No daemon, language server, or automatic whole-repository rewrite is implied.

    • The current terminus is a local, inspectable, run-to-completion linter with an optional terminal skin.