TNL — Typed Natural Language
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
AI coding agents make design decisions silently, drift from what was planned, and lose context at session end. TNL (Typed Natural Language) is the fix: a per-feature English contract with a fixed schema — proposed by the agent, approved by you, implemented against, saved on disk, and read by every future session. If you've used plan mode in Claude Code, this is the same discipline made compact, persistent, and machine-checkable.
The schema
The schema is seven fields:
- id / title — what this feature is
- scope — feature or repo-wide
- paths — which files the change is allowed to touch
- surfaces — named external surfaces (CLI commands, routes, MCP tools)
- behaviors — numbered MUST / SHOULD / MAY clauses; the contract proper
- non-goals — what's explicitly out of scope
- rationale — the why, for future readers
You approve this *once*, before any code runs. The agent implements against each MUST clause and self-attests at the end — for every MUST, naming the file or test that satisfies it.
**No new tool, no new agent, no new workflow.** TNL slots into whatever agent you already use. Claude Code, Codex, Gemini, and Cursor get first-class tnl init with stanza + hooks + MCP. Any agent that reads a Markdown instruction file adopts with a two-step manual copy — the minimum product is a stanza in your instruction file plus a tnl/ directory. tnl verify, the PreToolUse hook that re-surfaces the contract mid-edit, and the MCP server are optional layers on top.
A TNL file looks like this
Three zones: **machine** (id, paths, surfaces), **contract** (behaviors with RFC 2119 keywords and [semantic] / [test: …] prefixes), **human** (intent, non-goals, rationale).
---
The workflow
Every feature request — new or modification — runs through 7 steps:
1. **Scope** — agent scans tnl/ for files whose paths: overlap the request. If one exists, the output is an *edit*; if not, a *new* TNL.
2. **Clarify** — ambiguous request? Agent asks questions before proposing anything.
3. **Propose** — agent outputs the full TNL content inline in chat. Nothing on disk yet.
4. **Wait for approval** — you review, push back, approve. Nothing is written until you say go.
5. **Save** — agent writes the approved TNL to tnl/ .tnl.
6. **Implement** — agent writes code + tests against the contract. paths: bounds the change.
7. **Self-attest** — agent lists every MUST clause and where it was satisfied. Silent omission counts as a miss.
For follow-up work, step 1 returns "edit the existing TNL" — and the next session reads the already-approved contract as context, rather than rediscovering design decisions from the code.
---
What you get over plan mode
- **Structure.** Seven fixed fields. Reviewers scan the same things every time. Agents produce the same shape every session.
- **Persistence.** Plan mode's output is a chat message — gone when the session ends. A TNL is a file on disk alongside your code. The next session reads the contract instead of re-analysing source.
- **Enforcement.** Every MUST clause maps to a file or test at self-attestation time. tnl verify checks paths exist and test bindings resolve. The PreToolUse hook re-injects the contract on every Edit/Write so the agent can't drift silently.
- **Incremental adoption.** No bulk migration. Your next feature gets a TNL; the rest of the repo stays as-is. The knowledge base accumulates as the work accumulates.
---
Does it actually work?
We ran a controlled A/B. Baseline condition: four working principles — think before coding, simplicity first, surgical edits, goal-driven — written as prose in the project's CLAUDE.md / AGENTS.md. TNL condition: the same four plus two more (match existing conventions; exhaustive end-of-task self-attestation) encoded as tnl/workflow.tnl, plus a per-feature TNL. Same agent, same project context; only the contract step differs.