Zum Inhalt springen

The Two-Layer Model

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

Most project documentation lives in a single flat namespace. READMEs, design docs, task descriptions, meeting notes, and coding standards all sit in the same directory or wiki, distinguished only by naming conventions or folder structure. This works well enough for human readers who can infer from context whether a document is a permanent specification or a temporary task description.

AI agents cannot make this inference reliably. When an agent loads project documentation, it needs to know: is this a durable rule that always applies, or a transient note tied to a specific piece of work? Should this information shape every future interaction, or only the current task? Is this document still active, or has the work it describes been completed?

Contextia answers these questions structurally, by organizing all project knowledge into two distinct layers:

  • System layer — durable knowledge that persists across tasks, sessions, and contributors
  • Operational layer — transient state that has a lifecycle tied to specific work items

This separation is not just organizational. It is a semantic distinction that affects how context is assembled, how artifacts are maintained, and how knowledge flows through a project.

The system layer contains everything an agent needs to know about the project regardless of what task it is currently working on. This knowledge is durable: it was true yesterday, it is true today, and it will remain true until someone explicitly changes it.

Every project has exactly one identity file at .contextia/system/identity.md. It is the project’s self-description — the first thing loaded into any agent’s context.

---
project: acme-billing
version: "3.0"
languages: [python, typescript]
frameworks: [fastapi, react]
---
# Acme Billing
A subscription billing platform that handles plan management,
usage metering, invoice generation, and payment processing.
## Architecture
Python backend (FastAPI) with a React frontend.
PostgreSQL for transactional data, Redis for caching,
Stripe for payment processing.

The identity file is deliberately concise. Its purpose is orientation, not exhaustive documentation. An agent reading it should know the project’s domain, tech stack, and high-level architecture in under 200 tokens.

Specifications are behavioral contracts. Each spec describes what a component, feature, or subsystem does — its responsibilities, its interfaces, its constraints. Specs answer the question: what should this thing do?

---
type: spec
id: SPEC-BILLING-001
title: Invoice Generation
status: current
links:
decisions: [DEC-BILLING-001, DEC-BILLING-003]
norms: [NORM-ERROR-001, NORM-ASYNC-001]
paths:
- src/billing/invoice/**
- src/billing/templates/invoice*
tags: [billing, invoicing, pdf]
---
# Invoice Generation
The invoice generation subsystem creates PDF invoices from
subscription and usage data at the end of each billing cycle.
## Responsibilities
- Aggregate line items from usage records and plan charges
- Apply discounts, proration, and tax calculations
- Render invoices to PDF using the configured template
- Store generated invoices in S3 with a 7-year retention policy
- Send invoice notifications via the notification subsystem

Specs are the most important artifact type in Contextia. They are what link tasks to code, decisions to implementation, and norms to enforcement. A well-written spec tells an agent everything it needs to implement or modify a feature correctly.

Norms are coding standards and conventions that apply across the codebase. Unlike specs, which describe what individual components do, norms describe how code should be written regardless of which component it belongs to.

---
type: norm
id: NORM-ERROR-001
title: Error Handling Conventions
status: current
tags: [errors, exceptions, logging]
---
# Error Handling Conventions
## Rules
1. All public functions must declare their error types explicitly
2. Use domain-specific exception classes, never bare Exception
3. Log errors at the boundary where they are caught, not where raised
4. Include correlation IDs in all error log messages
5. HTTP endpoints return structured error responses (RFC 7807)

Norms are referenced by specs via links.norms. When an agent loads context for a task, the relevant norms are included automatically. This ensures that code generated by an agent follows project conventions without the developer having to remind it in every prompt.

Rationale documents (also called decisions or ADRs) record why the project is built the way it is. They capture the constraints, alternatives considered, and reasoning behind architectural choices.

---
type: decision
id: DEC-BILLING-001
title: PDF Generation Library Selection
status: accepted
date: 2025-08-14
links:
specs: [SPEC-BILLING-001]
tags: [billing, pdf, infrastructure]
---
# PDF Generation Library Selection
## Context
Invoice generation requires rendering dynamic PDF documents
from structured data. We evaluated three options.
## Options considered
1. **WeasyPrint** — HTML/CSS to PDF, Python-native
2. **ReportLab** — Low-level PDF generation, mature
3. **Puppeteer** — Headless Chrome rendering, Node.js
## Decision
WeasyPrint. It uses HTML/CSS templates (familiar to the team),
runs in-process (no Node.js dependency), and handles Unicode
and RTL text natively (needed for international invoices).
## Consequences
- Template authors need CSS knowledge, not a custom DSL
- PDF output is limited by CSS print media support
- WeasyPrint has native dependencies (cairo, pango) that
must be available in the Docker image

Rationale documents are crucial for AI agents because they prevent the agent from re-litigating decisions that have already been made. When an agent sees that PostgreSQL was chosen over MongoDB for specific, documented reasons, it will not suggest switching databases or using patterns that assume a document store.

The operational layer contains everything tied to specific work items. This knowledge is transient — it is created when work begins and has a defined lifecycle that ends when the work completes.

Tasks are work orders. Each task describes what needs to be done and links to the system-layer artifacts that govern the work.

---
type: task
id: TASK-042
title: Add multi-currency support to invoice generation
status: in_progress
links:
specs: [SPEC-BILLING-001, SPEC-CURRENCY-001]
decisions: [DEC-BILLING-001]
norms: [NORM-ERROR-001]
priority: high
created: 2026-02-28
---
# Add multi-currency support to invoice generation
## Objective
Extend the invoice generation subsystem to support
multiple currencies per customer account.
## Acceptance criteria
- Invoices render amounts in the customer's configured currency
- Exchange rates are fetched from the configured provider
- Tax calculations respect currency-specific rounding rules

The links field in a task is the starting point for context assembly. When an agent calls contextia context TASK-042, the system reads these links and recursively loads the referenced specs, decisions, and norms.

Active work directories (work/active/{task}/)

Section titled “Active work directories (work/active/{task}/)”

When a task is actively being worked on, it gets a directory under work/active/ that holds all transient artifacts:

work/active/TASK-042/
├── plan.md # Step-by-step implementation plan
├── logs/ # Session logs
│ ├── 2026-02-28.md # What happened in this session
│ └── 2026-03-01.md
├── proposals/ # Proposed spec changes
│ └── SPEC-BILLING-001-v2.md
└── scratch/ # Temporary working notes
└── exchange-rate-research.md

Plans break a task into ordered steps. An agent can generate a plan, have it reviewed, then execute it step by step with checkpoints.

Session logs record what happened during each working session — what was attempted, what succeeded, what failed, what remains. They provide continuity across sessions, allowing an agent to resume work without re-discovering the project state.

Proposals are the staging area for spec changes. When an agent determines that a spec needs updating, it does not edit the spec directly. Instead, it writes a proposal that a human reviews. This is a safety mechanism: specs are durable system knowledge, and changes should be deliberate.

Scratch is for anything temporary — research notes, API response examples, debug output. It is explicitly disposable and is cleaned up when the task completes.

When TASK-042 is completed, the task file is marked status: done and eventually archived. But SPEC-BILLING-001 remains in the system layer, now updated with multi-currency support. The specification outlives the work that produced it.

If specs lived in the operational layer alongside tasks, completing a task would risk losing the specifications it produced. By keeping them separate, the system layer accumulates knowledge over time while the operational layer stays clean.

DEC-BILLING-001 (choosing WeasyPrint) was made during an early task that has long since been completed. But the decision remains relevant every time invoice generation is modified. New tasks reference the same decision, and the agent understands the constraints without the original task being present.

Because system and operational artifacts are in separate directories with different structures, context assembly can be targeted. Loading a task’s context follows links into the system layer — it does not need to scan through other tasks, archived plans, or old session logs.

System-layer artifacts have a status lifecycle (draft / current / deprecated) that is independent of any task. A spec can be deprecated without any task being active. A norm can be updated as part of routine maintenance.

Operational-layer artifacts have a work lifecycle (open / in_progress / done / archived) tied to the task they belong to. When the task is done, its active directory can be cleaned up.

System layer lifecycle: draft → current → deprecated
Operational layer lifecycle: open → in_progress → done → archived

These lifecycles are independent. A task can be done while the specs it implemented are current. A spec can be deprecated while a task to replace it is in_progress.

Knowledge flows in both directions between layers, but through controlled channels:

When a task results in a new specification, the spec is drafted as a proposal in the operational layer (work/active/{task}/proposals/), reviewed by a human, and then promoted to the system layer (system/specs/). The promotion is an explicit command:

Terminal window
contextia spec promote work/active/TASK-042/proposals/SPEC-CURRENCY-001.md

This ensures that durable knowledge enters the system layer through a review gate, not automatically.

When a new task is created, it links to existing specs, decisions, and norms in the system layer. These links determine what context the agent receives when it starts working.

system/specs/SPEC-BILLING-001.md ←──── task references spec
system/rationale/DEC-BILLING-001.md ←── task references decision
system/norms/NORM-ERROR-001.md ←────── spec references norm
└─── pulled into agent context when task is loaded
┌──────────────────────────────────────────────┐
│ System Layer │
│ specs ← decisions ← norms ← identity │
│ ↑ │
│ │ promote │
│ │ │
│ ┌──┴────────────────────────────────────┐ │
│ │ Operational Layer │ │
│ │ tasks → plans → logs → proposals ─────┘ │
│ └────────────────────────────────────────┘ │
└──────────────────────────────────────────────┘

Tasks consume system knowledge. Work produces new knowledge. That knowledge is reviewed and promoted into the system layer, where it is available for future tasks. This cycle is how a project accumulates institutional knowledge over time — not in wikis that nobody reads, but in structured artifacts that agents load automatically.

.contextia/
├── system/ # Durable knowledge
│ ├── identity.md # Project orientation
│ ├── specs/ # Behavioral contracts
│ │ ├── SPEC-AUTH-001.md
│ │ └── SPEC-BILLING-001.md
│ ├── norms/ # Coding standards
│ │ ├── NORM-ERROR-001.md
│ │ └── NORM-LOG-001.md
│ └── rationale/ # Architectural decisions
│ ├── DEC-AUTH-001.md
│ └── DEC-BILLING-001.md
├── work/ # Transient state
│ ├── tasks/ # Work orders
│ │ ├── TASK-042.md
│ │ └── TASK-043.md
│ └── active/ # Work-in-progress artifacts
│ └── TASK-042/
│ ├── plan.md
│ ├── logs/
│ ├── proposals/
│ └── scratch/
└── config.yaml # Project configuration

Every file in this structure is Markdown with YAML frontmatter. Every link between files is an explicit ID reference in frontmatter. Every artifact has a type and a status. This structure is what makes deterministic context assembly possible — the agent does not search, it navigates.