# DX-91: Generated File Contract

**Status:** Implementation-facing contract  
**Date:** 2026-03-12  
**Derived from:** DX-91-migration-semantics.md (final)  

---

## 1. Purpose

This document defines the **canonical contract** for all files generated by `invar init` v2. It translates DX-91 finalized semantics into explicit requirements for:

1. **Runtime/template work** — What the init command must generate
2. **Repository documentation** — What INVAR.md/CLAUDE.md in the repo must contain
3. **Work split** — Which proposal sections are source-of-truth for each deliverable

---

## 2. Generated Files Contract

### 2.1 CLAUDE.md (Injected Section)

**Source of truth:** `docs/proposals/DX-91-claude-md-draft.md` section "Injected Content (~50 lines)"

**Canonical marker semantics (see `DX-91-migration-semantics.md` §4.4, §10.4):**
- Content *inside* `<!--invar:begin-->` / `<!--invar:end-->` is **regenerated exactly** on each `invar init`
- User content *must be outside markers* to be preserved
- Content inside markers is NOT merged, NOT preserved—replaced exactly

**Contract:**

| Attribute | Requirement |
|-----------|-------------|
| **Markers** | Single pair: `<!--invar:begin-->` / `<!--invar:end-->` |
| **Lines** | ~50 lines (±10 lines acceptable) |
| **Idempotent** | Re-running init replaces content between markers **exactly** (not merged) |
| **User content** | Content outside markers preserved verbatim |
| **Target file** | `CLAUDE.md` by default; `--file` supports alternatives |

**Required Content Sections:**

```markdown
<!--invar:begin-->
## Invar

[CRITICAL one-liner about contracts first]

### Architecture
[Zone table: Core vs Shell with paths and rules]

### Verification
[invar guard instruction]

### Tools
[Tool table: guard, sig, map, refs]

### Contract Traps
[Lambda @pre @post syntax examples]

### Escape Hatches
[@invar:allow example]

[Reference to INVAR.md for full spec]
<!--invar:end-->
```

**Explicitly Removed from v1:**
- ❌ `<!--invar:critical-->` / `<!--invar:managed-->` / `<!--invar:project-->` / `<!--invar:user-->` markers
- ❌ Check-In/Final protocol ceremony
- ❌ USBV phase headers
- ❌ Task completion checklists
- ❌ Skills/hooks references
- ❌ TypeScript variants
- ❌ `.invar/examples/` references

---

### 2.2 INVAR.md (Fully Managed)

**Source of truth:** `docs/proposals/DX-91-invar-md-draft.md` (entire document)

**Canonical authority (see `DX-91-freeze-spec-baseline.md` §"Source-of-Truth Boundaries"):**
- INVAR.md content: `DX-91-invar-md-draft.md`
- Marker semantics: `DX-91-migration-semantics.md` §3.3, §4.4, §10.4

**Contract:**

| Attribute | Requirement |
|-----------|-------------|
| **Markers** | NONE — entire file is overwritten on init |
| **Lines** | ~70-120 lines (target: compact agent spec) |
| **Idempotent** | Full overwrite; content identical for same version |
| **User edits** | NOT supported; add custom rules to CLAUDE.md user section |
| **Location** | Top-level `INVAR.md` |

**Required Sections (stable anchors for guard diagnostics):**

1. **Before Writing Code** — Contracts first, Core vs Shell decision
2. **Core vs Shell** — Decision rule and zone table
3. **Contract Syntax Traps** — @pre lambda params, @post(result) scope
4. **Canonical Core Example** — Python @pre/@post + doctest
5. **Canonical Shell Example** — Python Result[T, E]
6. **Escape Hatches** — @invar:allow syntax
7. **Minimal Configuration** — pyproject.toml snippet
8. **Common Guard Repairs** — Error-to-fix table with INVAR.md section links

**Explicitly Removed from v1:**
- ❌ References to `.invar/examples/`
- ❌ Skills/hooks documentation
- ❌ TypeScript variants
- ❌ Multi-language support sections
- ❌ Expanded prose (keep concise, reference CLAUDE.md for tools)

---

### 2.3 .pre-commit-config.yaml

**Source of truth:** `DX-91-migration-semantics.md` section 3.2

**Contract:**

| Attribute | Requirement |
|-----------|-------------|
| **Content** | Single hook: `invar guard` |
| **Lines** | ~8 lines |
| **Generated** | Yes, if not exists |
| **Managed** | No (user can customize) |

---

## 3. Implementation Work Split

### 3.1 Runtime/Template Work (src/invar/)

**Files to modify/create:**

| File | Change | Spec Reference |
|------|--------|----------------|
| `src/invar/templates/protocol/INVAR.md.jinja` | Replace with v2 minimal template | DX-91-invar-md-draft.md |
| `src/invar/templates/config/CLAUDE.md.jinja` | Replace with v2 minimal template | DX-91-claude-md-draft.md |
| `src/invar/shell/commands/init.py` | Remove v1 multi-agent selection; add v2 marker detection | DX-91-migration-semantics.md §3, §4 |
| `src/invar/shell/commands/template_sync.py` | Support single-marker regions | DX-91-migration-semantics.md §5 |
| `src/invar/core/template_parser.py` | Add v2 marker parsing | New: single-marker logic |
| `src/invar/shell/commands/dev_sync.py` | Remove examples/skills/hooks sync | DX-91-migration-semantics.md §5 |

**New Templates (v2):**

```
src/invar/templates/
├── INVAR.md.v2.jinja          # ~70-120 line agent spec
├── CLAUDE.md.v2.jinja         # ~50 line injected section
└── pre-commit.yaml.jinja      # Unchanged
```

**Deleted (v1 cleanup — canonical list: `DX-91-migration-semantics.md` §2.2):**

```
src/invar/templates/
├── skills/                    # Delete if present (non-fatal if absent)
├── hooks/                     # Delete if present (non-fatal if absent)
├── onboard/                   # Delete if present (non-fatal if absent)
├── examples/                  # Delete if present (non-fatal if absent)
├── claude-md/                 # Delete if present (non-fatal if absent)
└── protocol/typescript/       # Delete if present (non-fatal if absent)
```

**Optional-file semantics:** Deletion proceeds even if any directory is missing. No error is raised for absent directories.

---

### 3.2 Repository Documentation Work (docs/)

**Files to align:**

| File | Action | Rationale |
|------|--------|-----------|
| `README.md` | Rewrite per DX-91 §9.2 | New simplified install/init/use flow |
| `AGENTS.md` | Archive or redirect | Documents removed skill/hook model |
| `INVAR.md` (repo root) | Align with v2 template | This is the "reference INVAR.md" that templates copy |
| `CLAUDE.md` (repo root) | Align v2 injected section | Serves as example of generated content |

**Proposal Archives:**

Per DX-91 §9.1, move to `docs/proposals/archive/`:
- DX-22 through DX-81 (completed/superseded)
- DX-87 (superseded by DX-91)
- LX-05, LX-06, LX-07 (TS-related, obsolete)
- DX-79 (feedback, removed)

**Keep active:**
- DX-88, DX-89 (wiring rules continue)
- DX-91 (this proposal)

---

## 4. Marker System Contract

### 4.1 v2 Single-Marker System

```markdown
<!--invar:begin-->
... managed content ...
<!--invar:end-->
```

**Behavior:**
- If markers exist → replace content between them
- If markers missing → append section with markers
- User content outside markers → never touched

### 4.2 v1 to v2 Migration Mapping

| v1 Marker | v2 Handling |
|-----------|-------------|
| `<!--invar:critical-->` | Content replaced by v2 block between `<!--invar:begin-->` / `<!--invar:end-->` markers |
| `<!--invar:managed-->` | Replaced by `<!--invar:begin-->` / `<!--invar:end-->` markers |
| `<!--invar:project-->` | Content moved to `.invar/project-additions.md` (user region outside markers) |
| `<!--invar:user-->` | Preserved verbatim outside `<!--invar:begin-->` / `<!--invar:end-->` markers |

---

## 5. Intentionally Deferred

The following are **explicitly NOT in scope** for runtime rewrite to prevent scope creep:

| Deferred Item | Rationale | Future Work |
|---------------|-----------|-------------|
| Wording cleanup in guard error messages | Can be done post-DX-91 | DX-92 ( Guard DX improvements) |
| Additional escape hatch types | Only `dead_export` needed for MVP | Future proposal |
| Multi-language INVAR.md | Python-only per simplified boundary | Separate proposal if needed |
| `.invar/context.md` generation | No longer generated; user creates if needed | Document only |
| Migration rollback command | Out of scope; manual backup sufficient | Not planned |

---

## 6. Verification Matrix

Each generated-file contract MUST map to an explicit proposal section:

| Generated File | Contract Section | Source Proposal | Proposal Section |
|----------------|------------------|-----------------|-------------------|
| `CLAUDE.md` markers | §2.1 | DX-91-migration-semantics.md | §3.3 Managed Section Markers |
| `CLAUDE.md` content | §2.1 | DX-91-claude-md-draft.md | §2 Injected Content |
| `INVAR.md` content | §2.2 | DX-91-invar-md-draft.md | Entire document |
| `.pre-commit-config.yaml` | §2.3 | DX-91-migration-semantics.md | §3.2 Generated Files |
| Migration behavior | §4 | DX-91-migration-semantics.md | §4 Migration Behavior |
| Idempotency | §2.1, §2.2 | DX-91-migration-semantics.md | §4.5 Idempotent Re-run |

---

## 7. No Unresolved Ambiguity Checklist

| Question | Resolution | Location |
|----------|------------|----------|
| Minimum CLAUDE.md injected content? | ~50 lines, 6 sections | §2.1, DX-91-claude-md-draft.md |
| Marker format? | `<!--invar:begin-->` / `<!--invar:end-->` | §2.1, DX-91-migration-semantics.md §3.3 |
| File split (runtime vs repo)? | Runtime=src/invar/templates/, Repo=docs/ | §3 |
| INVAR.md length target? | ~70-120 lines | §2.2, DX-91-invar-md-draft.md |
| What happens to v1 markers? | Migrated to single v2 block | §4.2 |
| What stays in CLAUDE.md user section? | Everything outside markers | §2.1 |
| Is INVAR.md user-editable? | NO — fully managed | §2.2 |
| Dev sync scope after DX-91? | CLAUDE.md + INVAR.md only | §3.1, DX-91-migration-semantics.md §5 |

---

## 8. References

- **Source proposals:**
  - `docs/proposals/DX-91-migration-semantics.md` — Final semantics (canonical)
  - `docs/proposals/DX-91-claude-md-draft.md` — CLAUDE.md content
  - `docs/proposals/DX-91-invar-md-draft.md` — INVAR.md content

- **Template files (current v1):**
  - `src/invar/templates/protocol/INVAR.md.jinja`
  - `src/invar/templates/config/CLAUDE.md.jinja`
  - `src/invar/templates/config/AGENT.md.jinja`

- **Implementation files:**
  - `src/invar/shell/commands/init.py`
  - `src/invar/shell/commands/template_sync.py`
  - `src/invar/core/template_parser.py`
