Abstract: Configuration files traditionally serve as "settings" or "tuning knobs" for software tools. This document argues for a more fundamental role: configuration as executable documentation of project semantics. We examine how Reveal's .reveal.yaml specification demonstrates this pattern, connecting to SIL's principles of explicit meaning, progressive disclosure, and tool behavior contracts.

Correction (2026-08-04): Sections 2, 3, and 4 originally presented a semantic:// adapter/custom_patterns config and an ast.entry_points config as part of Reveal's shipped .reveal.yaml specification. Neither was ever implemented, at the document's 2025-12-22 publication or since (checked against v0.113.0). semantic:// was explicitly evaluated and rejected — reveal's ROADMAP.md lists it under "Explicitly Not Planned" ("requires ML infrastructure; over-engineered"). entry_points was never built, though the underlying gap it addresses is real and now tracked as BACK-952. What is real and unchanged: architecture.layers (with paths/allow_imports/deny_imports, not the path/can_import/cannot_import field names used below) and ~/.reveal/rules/ custom-rule plugins (with the BaseRule API, not a Rule class). Examples below are corrected inline; §7's "Future Research" framing already correctly marked these as speculative and is left as-is.


1. The Problem with Traditional Configuration

1.1 Configuration Drift

Teams often declare architectural intentions ("we follow clean architecture") without enforcement mechanisms. Over time:

Result: Architecture documentation becomes archaeological artifact rather than living contract.

1.2 Binary Configuration Choices

Most tools force binary decisions:

Option A: Zero Configuration ("Convention over configuration")
- ✅ Simple to start
- ❌ No project-specific customization
- ❌ Generic rules don't match team reality
- Example: ESLint's default rules may not match your architecture

Option B: Configuration Everything ("Explicit over implicit")
- ✅ Full control
- ❌ Configuration complexity rivals codebase
- ❌ Barrier to entry (new devs overwhelmed)
- Example: Webpack configs that need configs

The gap: No middle path that scales complexity with project needs.

1.3 Configuration as Settings (Not Semantics)

Traditional configuration treats settings as opaque values:

# Traditional approach
max_line_length: 120
complexity_threshold: 10

These are tuning parameters, not semantic declarations. They answer "how much?" but not "what does this mean for our system?"


2. Configuration as Semantic Contract

2.1 Core Insight

Configuration should declare project semantics, not just tune behavior.

Instead of:

ignore_patterns: ["**/tests/**"]  # What does this mean?

We declare (a proposed config shape — not implemented, see BACK-952 — shown here to illustrate the concept; reveal's actual --uncalled already recognizes pytest test functions via a hardcoded built-in list, just not a configurable one):

ast:
  entry_points:
    - pattern: "def test_"
      description: "Pytest test functions"
      languages: [python]

Difference:
- Traditional: "Ignore this path" (mechanism)
- Semantic: "These functions are entry points invoked by pytest" (meaning)

2.2 Executable Documentation

Configuration becomes executable documentation when:

  1. It declares intent (not just parameters)
  2. Tools enforce it (violations detected automatically)
  3. It's version-controlled (evolves with codebase)
  4. It's team-shared (everyone sees same rules)

Example from Reveal (real, working config — field names corrected: paths/deny_imports, not path/cannot_import):

architecture:
  layers:
    - name: routes
      paths: [app/routes/**]
      description: "HTTP route handlers"
      deny_imports:
        - repositories      # Routes must go through services

    - name: services
      paths: [app/services/**]
      description: "Business logic layer"
      deny_imports:
        - routes

This configuration IS the architecture. The tool enforces what the team means by "layered architecture."

2.3 Connection to SIL Principle #2: Meaning Must Be Explicit

From architectural-principles.md:

Principle #2: Meaning Must Be Explicit
Semantic infrastructure makes meaning first-class. All meaningful objects are typed, inspectable semantic structures—not implicit conventions or documentation promises.

How configuration embodies this:
- Layer boundaries are explicit typed structures (not implicit conventions)
- Entry points are declared patterns (not "developers should know")
- Custom semantics are named patterns (not "search the code for Stripe calls")

Traditional configuration: "Here are some settings"
Semantic configuration: "Here is what these structures mean in our system"


3. Reveal's YAML Specification: Case Study

3.1 Progressive Configuration Pattern

Reveal demonstrates progressive configuration matching the three-level progressive disclosure pattern:

Level 1: Zero Config (Intelligent Defaults)

reveal app.py                    # Works immediately
reveal app.py --check            # Quality checks with sensible rules

Level 2: Project Overrides (.reveal.yaml)

# .reveal.yaml - Project-specific semantics
architecture:
  layers:
    - name: routes
      paths: [app/routes/**]
      deny_imports: [repositories]

rules:
  C901:
    threshold: 15   # cyclomatic complexity

Level 3: Custom Extensions (~/.reveal/rules/)

# ~/.reveal/rules/stripe_usage.py
# Team-specific custom rule for tracking payment code

Key insight: Complexity cost is opt-in. Teams pay for what they need.

3.2 URI Schemes = Composable Queries (No Named Custom Patterns)

Reveal's URI adapter system (24 adapters — ast://, calls://, imports://, etc.) enables queryable domain knowledge without configuration:

reveal 'ast://app?complexity>10'
reveal 'calls://app/?target=charge_card'
reveal app/ --grep 'stripe\.'

Correction: the semantic: custom_patterns config and semantic:// adapter shown in the original version of this section (for saving a named pattern like uses_stripe_api as a queryable identifier) were never built. This was evaluated and explicitly rejected: reveal's ROADMAP.md lists "semantic:// embedding search" under "Explicitly Not Planned" — "requires ML infrastructure; over-engineered." Domain-specific queries today are ad hoc --grep/ast:// invocations, not named, saved, first-class semantics — "what code touches our payment provider?" still requires knowing (or writing down elsewhere) the right grep pattern, not a config-declared vocabulary. The USIR connection below remains aspirational, not something Reveal's config implements.

3.3 Entry Points and Dead-Code Detection

Modern frameworks use implicit invocation (decorators, dependency injection, event handlers). Dead code detection fails because tools don't understand "framework magic."

What Reveal actually does today: calls://?uncalled recognizes a fixed, built-in set — property/classmethod/staticmethod, pytest fixtures/test_*, unittest lifecycle methods, C#/Java test attributes (BACK-446) — but nothing for web/CLI framework routes (Flask/FastAPI/FastHTML @app.route, Click @click.command, Django views). Those still false-flag as dead code.

Proposed, not implemented (would extend the built-in list to be project-configurable — filed as BACK-952):

ast:
  entry_points:
    - pattern: "@app\\.(route|get|post)"
      description: "FastHTML route handlers"
      languages: [python]

    - pattern: "@click\\.command"
      description: "Click CLI commands"
      languages: [python]

Benefit (if built): Teaches tools about framework invocation patterns. What was "magic" becomes declared semantic contract.

Generalization: Any implicit invocation pattern can be declared:
- Event handlers (addEventListener, React hooks)
- Dependency injection (@Injectable, Spring beans)
- Plugin systems (Jupyter kernels, VSCode extensions)

3.4 Team-Shareable Architectural Rules

The free-form architecture.rules[].check: "<expression>" DSL shown below was never implemented — no arbitrary-expression rule engine exists in .reveal.yaml. What's real is per-built-in-rule threshold overrides (keyed by rule code, e.g. rules: {C901: {threshold: 15}}) plus the architecture.layers import-boundary mechanism from §2.2/§3.1. The example is left as illustrative of the idea, not a working config:

# NOT IMPLEMENTED — illustrative only
architecture:
  rules:
    - name: no-god-functions
      check: function_lines <= 100
      severity: error
      message: "Functions should be under 100 lines for maintainability"

    - name: models-import-restrictions
      pattern: "app/models/**/*.py"
      check: "only imports from [typing, pydantic, datetime, enum]"
      severity: error
      message: "Models should have no business logic dependencies"

Distinction from ESLint/Pylint:
- Global rules: Apply same rules everywhere
- Semantic rules: Different rules for different architectural layers

Example: Services can import repositories, but routes cannot. This is architecture-aware.


4. Theoretical Foundations

4.1 Configuration as Tool Behavior Contract (TBC)

From LAYER3_SUBLAYER_ARCHITECTURE.md, every tool should answer:

  1. How does it execute? (mode: sync/async/job/session)
  2. What channels does it use? (stdin, stdout, stderr, events)
  3. How do you track progress?
  4. What permissions does it need?
  5. How do I invoke and monitor you?

Configuration extends this:

The .reveal.yaml file documents how Reveal should behave for this project:

# Execution mode: How should unused imports be detected?
imports:
  ignore_unused: [...]           # Context-specific execution rules

# Permissions: What can different layers access?
architecture:
  layers:
    - name: routes
      paths: [app/routes/**]
      deny_imports: [repositories]       # Permission boundaries

Key insight: Configuration is metadata about tool behavior in project context.

4.2 Invariants Over Layers

From architectural-principles.md:

Principle #4: Invariants Define Correctness
Correctness in semantic infrastructure comes from preserved invariants, not intuition or guidelines.

How configuration encodes invariants:

architecture:
  layers:
    - name: models
      paths: [app/models/**]
      allow_imports: [typing, pydantic, datetime, enum]
      deny_imports: [services, routes, repositories]

This declares an invariant: "Models have no business logic dependencies"

Verification: Tool checks imports → violations break the build → invariant enforced

Traditional approach: Write this in documentation, hope developers remember, catch in code review (maybe).

Semantic approach: Declare the invariant, automate verification, make violation impossible to merge.

4.3 Multi-Agent Protocol Principles

From MULTI_AGENT_PROTOCOL_PRINCIPLES.md:

Principle 2: All communication must be typed
Input/output schemas prevent silent failures

How configuration would support this, if the semantic: config existed (it doesn't — see §3.2 correction):

# NOT IMPLEMENTED — rejected per ROADMAP.md, "Explicitly Not Planned"
semantic:
  custom_patterns:
    - name: uses_email
      description: "Functions that send email"
      languages: [python]
      patterns: ["send.*email", "EmailMessage"]

Result (hypothetical): Agents could query "what functions send email?" with typed responses. Today, an agent gets the same answer via reveal app/ --grep 'send.*email|EmailMessage', just without a saved name for the pattern.


5. Broader Implications

5.1 Pattern Applies Beyond Code Analysis

The "configuration as semantic contract" pattern generalizes:

Documentation Structure:

# docs.yaml
structure:
  - section: foundations
    audience: [newcomers, researchers]
    reading_time: 30min
    dependencies: []

  - section: systems
    audience: [developers]
    reading_time: 2hr
    dependencies: [foundations]

API Contracts:

# api.yaml
endpoints:
  - path: /api/users
    rate_limit: 1000/hour
    auth_required: true
    data_sensitivity: PII
    cannot_call: [/api/admin/**]    # Security boundary

Deployment Rules:

# deployment.yaml
environments:
  - name: production
    branch: main
    auto_deploy: false              # Invariant: prod requires approval
    required_checks: [tests, security_scan, architecture_validation]

Common pattern: Declare semantic constraints, enforce automatically, version-control the contract.

5.2 Configuration as Team Alignment Mechanism

Traditional alignment:
- Write architecture docs
- Explain in meetings
- Hope everyone remembers
- Catch drift in code reviews

Semantic configuration alignment:
- Declare architecture in .reveal.yaml
- Commit to version control
- Tool enforces on every commit
- Violations fail CI immediately

Result: Architecture cannot drift silently. The configuration is living documentation.

5.3 Enabling Progressive Complexity

The problem with "zero config" tools:
- Great for simple projects
- Break down as complexity scales
- Force users to eject entirely (React's eject pattern)

The problem with "configure everything" tools:
- Overwhelming for simple projects
- Barrier to entry too high
- Configuration becomes second codebase

Progressive configuration solves this:
- Start with intelligent defaults
- Add project overrides as needed
- Extend with custom rules when domain-specific
- Complexity scales with actual project needs


6. Connection to SIL Research Themes

6.1 Progressive Disclosure (Theme: Information Architecture)

Configuration follows three-level progressive disclosure:

Level 1: Tool works with zero config (intelligent defaults)
Level 2: Project declares overrides (.reveal.yaml)
Level 3: Team extends with custom semantics (~/.reveal/rules/)

See: PROGRESSIVE_DISCLOSURE_GUIDE.md

6.2 Agent-Help Standard (Theme: Agent Infrastructure)

Configuration becomes machine-readable tool contract:

reveal --agent-help                    # General usage
reveal architecture src/               # Architectural brief for a directory (entry points, risks, next commands)

The configuration documents project-specific semantics that agents can query.

See: AGENT_HELP_STANDARD.md

6.3 Tool Behavior Contracts (Theme: Agent Infrastructure)

Configuration answers the TBC questions for project context:

See: LAYER3_SUBLAYER_ARCHITECTURE.md

6.4 Structure Before Heuristics (Theme: Architectural Principles)

Traditional linters: Heuristics for "code smells"
Semantic configuration: Explicit structural rules

# Not: "Complexity seems high" (heuristic)
# Instead: "Functions in services/ must be under 100 lines" (structure)
architecture:
  rules:
    - pattern: "app/services/**"
      check: function_lines <= 100

See: architectural-principles.md


7. Future Research Directions

7.1 Configuration as Trust Assertion

Could configuration declare capability requirements?

# Hypothetical: Trust Assertion Protocol integration
trust:
  capabilities:
    - name: network_access
      required_for: [semantic://app?makes_http_call]
      justification: "External API calls for data enrichment"

Vision: Configuration declares what capabilities code needs, TAP verifies at runtime.

See: TRUST_ASSERTION_PROTOCOL.md

7.2 Multi-Agent Configuration Contracts

Could teams declare agent behavior contracts in configuration?

# Hypothetical: Agent Ether integration
agents:
  code_reviewer:
    can_read: [src/**, tests/**]
    can_write: [tests/**]
    cannot_write: [src/**]              # Read-only for source
    required_approval: [human]          # Must get human approval

  test_generator:
    can_read: [src/**]
    can_write: [tests/**]
    auto_commit: true                   # Can commit directly

Vision: Configuration as multi-agent protocol contract (not just single-tool settings).

7.3 Cross-Project Semantic Standards

Could projects declare semantic compatibility?

# Hypothetical: USIR compatibility declaration
semantics:
  compatible_with:
    - usir: v1.0
    - domain: code-understanding
  exports:
    - type: ArchitectureGraph
      version: 1.0
      schema: ./schemas/architecture.yaml

Vision: Projects declare semantic exports, other tools can depend on them.


8. Practical Guidelines

8.1 When to Use Semantic Configuration

Use semantic configuration when:

Team alignment matters (architecture rules, conventions)
Domain knowledge is valuable (custom patterns, project-specific semantics)
Enforcement prevents drift (layer boundaries, invariants)
Configuration is shared (version-controlled, team-wide)

Don't use semantic configuration for:

Personal preferences (tabs vs spaces, editor settings)
Purely aesthetic rules (no semantic meaning)
Rules that can't be verified (vague guidelines)

8.2 Design Principles for Semantic Config

1. Declare meaning, not mechanism

# ❌ Mechanism-focused
ignore_paths: ["tests/"]

# ✅ Meaning-focused
ast:
  entry_points:
    - pattern: "def test_"
      description: "Test functions invoked by pytest"

2. Make contracts explicit

# ❌ Implicit
max_imports: 10

# ✅ Explicit contract
architecture:
  rules:
    - name: minimize-coupling
      check: import_count <= 10
      message: "High import count suggests tight coupling"

3. Enable progressive adoption
- Level 1: Zero config (intelligent defaults)
- Level 2: Project overrides (common needs)
- Level 3: Custom extensions (domain-specific)

4. Version control and share
- Commit .reveal.yaml to repository
- Document why rules exist (not just what they check)
- Review config changes like code changes


9. Conclusion

Configuration as semantic contract transforms configuration from "settings file" to "executable documentation of project semantics."

Key insights:

  1. Configuration should declare meaning (not just tune parameters)
  2. Tools should enforce contracts (violations detected automatically)
  3. Progressive complexity (opt-in, scales with project needs)
  4. Team alignment (shared, version-controlled, living documentation)

Reveal's .reveal.yaml specification demonstrates:
- Progressive disclosure applied to configuration
- URI schemes + custom patterns = composable semantics
- Entry points as first-class framework integration concept
- Architecture-aware rules (not just global linting)

Connection to SIL:
- Embodies Principle #2 (Meaning Must Be Explicit)
- Extends Tool Behavior Contracts to project context
- Demonstrates Structure Before Heuristics
- Supports Agent-Help Standard with machine-readable contracts

Future potential:
- Integration with Trust Assertion Protocol (capability declarations)
- Multi-agent configuration contracts (Agent Ether)
- Cross-project semantic compatibility (USIR exports)

Bottom line: When configuration declares project semantics rather than just tuning behavior, it becomes infrastructure for maintaining architectural integrity—exactly the kind of semantic infrastructure SIL builds.


10. References

SIL Documents:
- Architectural Principles - Structure Before Heuristics, Meaning Must Be Explicit
- Progressive Disclosure Guide - Three-level pattern
- Agent-Help Standard - Machine-readable tool contracts
- Layer 3 Architecture - Tool Behavior Contracts
- Multi-Agent Protocol Principles - Typed communication

External References:
- Reveal .reveal.yaml (real, current example): /home/scottsen/src/projects/reveal/external-git/.reveal.yaml
- Reveal layer-config implementation: reveal/analyzers/imports/layers.py
- Reveal v0.113.0: current version at time of correction (2026-08-04); a REVEAL_YAML_CONFIG_SPEC.md referenced in an earlier draft of this document does not exist in the repo

Related Research:
- Configuration as code (infrastructure as code patterns)
- Design by contract (Bertrand Meyer)
- Type-driven development (dependent types, refinement types)
- Architecture decision records (ADRs)


Status: Published
Date: 2025-12-22 (corrected 2026-08-04)
Version: 1.1 — fabricated/unimplemented features (semantic://, ast.entry_points) corrected against actual v0.113.0 codebase; see note at top
Author: Semantic Infrastructure Lab
Maintainer: SIL Research Team