# ChadKit - Project Information Model

**Version:** post-0.6.0, latest dev build 81483a0 2026-09-27 (60 commits after v0.6.0)  
**Applies to:** projects using Git, Markdown, deterministic tools, and AI agents.  

> This is a **model, not a framework**. Adapt it to the project. Do not create artifacts,
> directories, metadata, or process merely to comply with this document.

## Contents

### I. Orientation
1. [Why ChadKit exists and when to use it](#why-chadkit-exists-and-when-to-use-it)
2. [Quick start for an existing project](#quick-start-for-an-existing-project)
3. [Two operating modes](#two-operating-modes)
4. [Authority and adaptation](#authority-and-adaptation)
5. [Default directives](#default-directives)

### II. The model
6. [Minimal information model](#minimal-information-model)
7. [Format, container, and addressing](#format-container-and-addressing)
8. [The project config](#the-project-config)

### III. Project truth
9. [Goals](#goals)
10. [Tasks](#tasks)
11. [Log](#log)
12. [Decisions](#decisions)
13. [Ubiquitous Language](#ubiquitous-language)
14. [Thoughts, optional](#thoughts-optional)
15. [Promotion](#promotion)

### IV. Procedure and practice
16. [Deterministic tools](#deterministic-tools)
17. [Workflows](#workflows)
18. [Agent adapters, skills, and context loading](#agent-adapters-skills-and-context-loading)
19. [Git diff discipline](#git-diff-discipline)
20. [Double-loop review](#double-loop-review)

### V. Adoption and evolution
21. [Bootstrapping and migrating an existing project](#bootstrapping-and-migrating-an-existing-project)
22. [When to deviate](#when-to-deviate)
23. [ChadKit versioning while experimental](#chadkit-versioning-while-experimental)
24. [Design provenance and evolution](#design-provenance-and-evolution)


## Why ChadKit exists and when to use it

ChadKit exists for projects where important project knowledge and state should live in Git alongside
the work, be usable by humans and AI agents, and remain reviewable through small deterministic
changes.

It is meant as much for **cleaning up an existing repository as for starting a new one**. Most
projects that need ChadKit already have the material - decisions argued in pull requests, feedback in
a chat log, conventions living in one person's head - scattered where neither a human nor an agent
can find it. Adoption is largely an act of consolidation, and the model is shaped around that: nothing
is scaffolded ahead of need, existing artifacts are adopted in place rather than migrated, and dated
records carry the date the project learned a thing rather than the date somebody got around to
writing it down.

Its focus is **durable project truth and agent-safe project state**: goals, tasks, evidence,
terminology, decisions, and reusable workflows. It does not require that every feature begin with a
formal specification or that projects adopt one prescribed development lifecycle.

ChadKit is intentionally composable. A project may use it alongside a specification system, coding
methodology, Agent Skill library, issue tracker, or documentation framework. If another maintained
system solves a ChadKit concern better with equal or lower complexity, prefer adopting, integrating,
or delegating to that system over maintaining a parallel invention.

### When ChadKit is a good fit

Use ChadKit when several of these are true:

- Git should be authoritative for durable project state and knowledge.
- Humans need to review AI-made project-state changes through normal diffs.
- AI agents need stable terminology and targeted context.
- Existing/brownfield projects must be improved incrementally rather than rebuilt around a process.
- The project needs lightweight goals/tasks/evidence/decisions without a full PM platform.
- Deterministic tools should own repetitive state mutations.
- You want AI workflows to evolve experimentally rather than follow one fixed methodology.

ChadKit may be unnecessary when the project has almost no durable non-code state, or when another
system is intentionally authoritative and duplicating it in Git would create more problems than it
solves.

### Related systems

| System | Primary concern | Prefer/use it when | Relationship to ChadKit |
|---|---|---|---|
| **ChadKit** | Git-native durable project truth and agent-safe state | You need lightweight goals, tasks, evidence, terminology, decisions, and workflows across human/AI work | Base information layer |
| **GitHub Spec Kit** | Extensible intent/spec-driven process harness | You want structured specification, planning, task generation, implementation workflows, presets, extensions, or broader SDLC automation | Major upstream idea source; can coexist with ChadKit |
| **OpenSpec** | Lightweight behavior/change specification for AI coding | The main problem is agreeing on what to build before implementation, including brownfield change work | Complementary specification/change layer |
| **Superpowers** | Composable agent software-development methodology/skills | You want strong reusable coding workflows such as planning, debugging, TDD, verification, and review | Reuse skills/workflows rather than copying them into ChadKit |
| **BMAD Method** | Broad AI-driven development lifecycle with specialized agents and workflows | You want a more comprehensive, opinionated methodology | Usually heavier than ChadKit; mine useful ideas selectively |
| **Agent Skills / Claude Skills** | Portable packaging of reusable agent instructions, scripts, references, and assets | You need a reusable agent capability | Mechanism ChadKit should use, not replace |
| **MADR** | Architectural and other consequential decision records | You need durable rationale for a choice among alternatives | ChadKit's decision-record foundation |
| **Diátaxis** | User-facing documentation organization | You need to organize tutorials, how-to guides, reference, and explanation | Useful documentation lens, not ChadKit's project-state taxonomy |

The existence of overlap is intentional. ChadKit should own only the concerns for which a lightweight
Git-native information layer provides distinct value.


## Quick start for an existing project

Two paths, depending on which of the [two operating modes](#two-operating-modes) applies. Either
way the goal is a working minimum, not a complete directory.

**Tooled.** Install the CLI, then from the project root:

```bash
chadkit init                 # writes the config, README.md, and thoughts.md - nothing else
chadkit init --full          # ...or also language.md, one adoption spike task, and a known-installs entry
chadkit task add "First real task"                        # creates tasks.md
chadkit log add --type t_lesson --summary "Why X works this way"   # creates log.md if it does not exist
chadkit validate
```

**Doc-only.** Put this document wherever the project keeps reference material and create
`chadkit/config.yaml` if paths or overrides differ from the defaults. Write the first task, log
record, or term into its artifact when you actually have one.

Either way, no artifact exists until something is written to it. That is deliberate: read
[Bootstrapping and migrating an existing project](#bootstrapping-and-migrating-an-existing-project) before adding anything, and
the useful work turns out to be deciding what the project already has, not producing files.


## Two operating modes

This document works with or without tooling. Know which mode you are in.

| Mode | Condition | Behavior |
|---|---|---|
| **Tooled** | `chadkit` CLI installed and `chadkit/config.yaml` exists | Defaults come from ChadKit; deviations and project overrides come from the config. Structured mutations go through the tool. `doctor` may report drift. |
| **Doc-only** | This file was handed to an agent in a project with no CLI installed | Conventions only. Follow the formats below, make surgical edits by hand, skip command references. A config is optional but recommended when paths or overrides differ from the defaults. |

Doc-only is a first-class mode, not a degraded fallback - it is how this model reaches projects
that will never install anything. Nothing below may depend on the tool existing.


## Authority and adaptation

When instructions conflict, use this precedence:

1. Current explicit human instruction.
2. Project-specific instructions and overrides, including `chadkit/config.yaml` when present.
3. Accepted project decision records and established project constraints.
4. This document.
5. Agent/tool conventions and general best practices.

Do not silently override a higher-authority rule with a lower-authority one.

If a project already has a good equivalent for an artifact described here, **reuse it rather
than creating a duplicate**, and declare it in the config. Prefer migration by accretion:
improve the project as work touches it instead of reorganizing the repository.


## Default directives

Preserve the intent even when adapting the structure.

- Directive 1. **Git is the system of record.** Durable project state should be reviewable through Git.
- Directive 2. **Markdown is the default human/AI knowledge format.** Use structured metadata only where it
   materially improves deterministic processing.
- Directive 3. **Keep the model lightweight.** Create the minimum artifacts needed for the current project.
- Directive 4. **Optimize for small, reviewable diffs.** Do not rewrite, reorder, normalize, or regenerate
   whole files when a surgical edit or append will do.
- Directive 5. **Prefer deterministic mutations.** Where project state has repeatable structure, use a tool
   rather than letting agents freely rewrite Markdown.
- Directive 6. **Do not turn Markdown into an uncontrolled database.** Stable IDs, bounded formats,
   validation, and deterministic writes protect state that agents modify frequently.
- Directive 7. **Separate truth from procedure.** Project facts belong in artifacts; repeatable procedures
   in workflows; deterministic operations in tools; vendor agent files are thin adapters.
- Directive 8. **Keep AI-specific adapters thin.** `CLAUDE.md` and equivalents point to project truth; they
   never duplicate it.
- Directive 9. **One owner per fact; everywhere else references it.** Any fact that can change - a version,
   a path, a term's meaning, a decision's rationale - has exactly one place that states it. Other
   places link to it or derive from it; they do not restate it. A restated fact is not duplicated
   information, it is a *second* fact that will disagree with the first, and the disagreement
   surfaces long after the change that caused it. Prefer making duplication impossible over
   promising to keep copies aligned: derive the copy, or when it genuinely must be written twice,
   add a check that fails when the two differ. This generalises the thin-adapter rule above - an
   adapter is only the most common thing tempted to restate truth.
- Directive 10. **Use Ubiquitous Language by default.** Even small projects benefit when AI might use different
   words for the same concept or similar words for different concepts. Keep the mechanism lightweight
   when the domain is simple.
- Directive 11. **Treat workflows as hypotheses, not doctrine.** Adapt the workflow when AI or automation
    demonstrably does the work better.
- Directive 12. **Support exploration.** Goals may be directional. Do not force premature success metrics.
- Directive 13. **Persist only durable information.** No session narration, repeated summaries, or
    speculative notes that will not affect future work.
- Directive 14. **Promote information when its importance grows.** A log record may become a task, workflow,
    domain term, or decision. Do not make every observation a standalone artifact.
- Directive 15. **Preserve provenance.** Records retain what happened and why; they are not silently rewritten.
- Directive 16. **Existing projects win over idealized structure.** No large migration unless the expected
    value justifies the review cost.
- Directive 17. **Question the goals, not only the execution.** Single-loop learning improves execution
    against current goals and assumptions; double-loop review questions whether those goals and
    assumptions are themselves right. The review mechanism is optional and should fit the project -
    see [Double-loop review](#double-loop-review).
- Directive 18. **Make structure earn its existence.** Before adding a rule, artifact, field, workflow, or tool,
    ask: *does this prevent a failure we have seen or strongly anticipate, or is it infrastructure for
    a hypothetical future system?* Prefer omission in the latter case.


## Minimal information model

Keep ChadKit-owned project state together rather than scattering kit files through the repository root.

ChadKit state lives in a single `chadkit/` directory at the project root. In prose this is written
`<project-root>/chadkit/`, where the project root is the repository root, or the root of the subtree
a project owns inside a larger repository. Paths elsewhere in this document are relative to it.

```text
README.md                         # normal project entry point; not ChadKit-owned
CLAUDE.md                         # optional agent adapter; not project truth

chadkit/
├── README.md                     # what this directory holds; no rules, no project truth
├── config.yaml                 # required in tooled mode; optional in doc-only
├── goals.md
├── tasks.md
├── tasks-archive.md              # create only when first needed
├── log.md
├── language.md
├── thoughts.md                   # human-only scratch; created by init
├── decisions/                    # create only when needed
└── workflows/                    # create only for repeatable procedures
```

The `chadkit` CLI may be installed externally or implemented locally. Its executable location is not
part of the project information model.

Do **not** create empty directories or placeholder documents merely because they appear above. The
one exception is `thoughts.md`, which `init` creates: it is hand-edited only, so no command would ever
materialise it, and an existing scratch file is what invites the first jotted idea. `init --full` also
writes `language.md`'s bootstrap rows and one adoption task; those carry content the project uses at
once, so they are records, not placeholders.

Only the artifacts below are ChadKit-owned. The project's root `README.md` and any agent adapter are
outside that boundary: ChadKit neither creates nor edits them.

| Artifact | Purpose | Default shape |
|---|---|---|
| `chadkit/README.md` | Orientation for the directory: version, one line per artifact, who writes what, link to this model | Short; states where things are, never what the rules are |
| `chadkit/config.yaml` | ChadKit version plus project-specific deviations/overrides | Required in tooled mode; optional in doc-only |
| `chadkit/goals.md` | Direction and outcomes worth pursuing | One file |
| `chadkit/tasks.md` | Current actionable project work | One file until sharding is justified |
| `chadkit/tasks-archive.md` | Completed project tasks removed from the active container | Create only when archiving is first needed |
| `chadkit/log.md` | Typed chronological evidence | Append-oriented |
| `chadkit/language.md` | Ubiquitous Language | One file; may be very small |
| `chadkit/thoughts.md` | Unstructured human scratch | One file, hand-edited only; created by `init` |
| `chadkit/decisions/` | Consequential choices | One record per decision |
| `chadkit/workflows/` | Repeatable procedures | One file per workflow |

### Who writes what

Not every file is tool-owned. The boundary is **structured record mutation**, not file ownership:

- **Through `chadkit` when installed:** allocating a `PT-` or `PLR-` ID, completing a task, changing
  a task's bracket fields, appending a log record. These need ID allocation and validation, and are
  the operations agents repeat.
- **Edited normally by humans and agents:** goals, terminology, decision records, workflows, task
  and goal prose, `README.md`. These are prose. [Git diff discipline](#git-diff-discipline) applies; the tool does not.
- **Never edited by tooling or agents:** `thoughts.md` - `init` only seeds it; see
  [Thoughts, optional](#thoughts-optional).

In doc-only mode the first category is hand-edited too, under the same discipline.

`README.md` remains uppercase because that filename is a widely recognized repository convention.
ChadKit-owned files use lowercase consistently; `thoughts.md` has no special ecosystem convention that
justifies all-caps naming.


## Format, container, and addressing

### Core ChadKit IDs

```text
PG-001                  Project Goal
PT-001                  Project Task
PLR-20260827-01         Project Log Record
PD-001                  Project Decision (MADR-based, project-local)
```

All four prefixes are self-describing and grep-safe. Decision records use MADR 4.0 as their content
model but not its bare `0007` numbering, because a decision ID is referenced from task lines, log
records, and prose where the containing path is not present to supply the namespace - and `grep 0007`
matches dates, versions, and hashes. A container that already uses a different convention keeps it;
see [Decisions](#decisions).

**Every record value is a single line.** A task line is one line; a log record is a heading plus one
line per field. No value may contain a newline or a control character, because the line break is what
separates one record from the next: a newline inside a value does not corrupt its own line, it
fabricates the ones after it. Values written into brackets additionally may not contain `[`, `]`, or
`,`, which delimit the fields. Tools reject such values; a human writing by hand should not produce
them. Long context belongs in a linked artifact, not inside a record.

Three separable layers allow projects to adapt without needless churn or breaking common tooling.

| Layer | Project rule |
|---|---|
| **Record format** - base shape and semantics of a task line or log record | **Shared base is stable; projects may extend it but should not remove or reinterpret shared semantics** |
| **Container layout** - how many files, their names, how records group | **May vary freely**, declared in the config when one exists |
| **Addressing** - how a record is referenced | **Stable and unambiguous**; IDs remain project-global where defined that way |

Project-specific extensions are legitimate:

```markdown
- [ ] PT-017 [PG-002] [#auth] [owner:client] Resolve callback failure.
```

Here `[owner:client]` is the extension; `[PG-002]` and `[#auth]` are shared base fields defined under [Tasks](#tasks).

Reinterpreting shared syntax is not:

```text
[x] means "blocked" in this project
```

If a project genuinely requires incompatible semantics, declare that artifact nonstandard in the
config rather than silently changing the contract.

A larger project may shard `tasks.md` into:

```text
chadkit/tasks/
├── auth.md
└── billing.md
```

This is a container change, not an identity change. **Project task IDs remain project-global.**
`PT-017` stays `PT-017` if it moves from `auth.md` to `billing.md`.

Before sharding, try tags such as `[F1]` or `[#auth]`. Do not encode the task's current feature,
container, or file location into its stable identity (`F1T-017`), because classification can change
while identity should not.


## The project config

`chadkit/config.yaml` is the project-local discovery point for ChadKit. Its fixed location
lets tooling and agents find project-specific deviations without scattering configuration through
agent-specific files.

In **tooled mode**, the config is required. In **doc-only mode**, it is optional when the project
uses ChadKit defaults, but recommended whenever artifact paths or important overrides differ.

**Do not edit this model per project.** Project-specific deviations belong in the config or in
higher-authority project instructions.

**Do not vendor this model into the project.** A copied `CHADKIT-MODEL.md` goes stale, produces large
diffs on every ChadKit change, and invites the per-project editing forbidden above. In tooled mode the
config's `chadkit-version` is the reference and `chadkit model` names where to read the matching text; in
doc-only mode the document is present because a human put it there deliberately.

The config should declare **deviations, not restate every default**:

```yaml
# chadkit/config.yaml

chadkit-version: 0.6.0   # written by init; matches the installed CLI

# Omit paths that use ChadKit defaults.
paths:
  tasks: BACKLOG.md
  task_archive: archive/completed-project-tasks.md

# Only when more than one decision container exists; see the Decisions section.
decisions:
  - path: docs/adr/
    schema: docs/adr/README.md
    scope: architecture
    prefix: ADR
  - path: chadkit/decisions/

review:
  trigger: "after each full pipeline pass"   # optional; only when useful

workflows:                                   # settings by workflow name; see below
  qa-gate:
    checks: scripts/gate-checks.sh
    paths:
      - src/parser.py
    since: main

overrides:
  - Existing BACKLOG.md remains authoritative for project tasks.
  - Domain term is Customer, not Member.
```

Default paths are:

```text
goals:        chadkit/goals.md
tasks:        chadkit/tasks.md
task_archive: chadkit/tasks-archive.md
log:          chadkit/log.md
language:     chadkit/language.md
decisions:    chadkit/decisions/        # shorthand; see Decisions for several
workflows:    chadkit/workflows/
thoughts:     chadkit/thoughts.md       # human scratch; created by init
```

`workflows` holds settings by workflow name and is an extension namespace: any workflow may keep
keys under its own name, and the CLI checks only the entries it knows. It knows `qa-gate` (see
[Workflows](#workflows)): `checks` names the script the gate runs after a review, `paths` the paths
whose commits the gate must clear, and `since` where the audit starts, a date, a commit, or a
branch name, which audits only the commits not yet merged there and so suits a squash-merge
workflow. What `doctor` checks against these is under [Deterministic tools](#deterministic-tools).

Omitting an optional artifact such as `workflows/` is legitimate. Ubiquitous Language is a default
invariant: keep `language.md` unless an explicit project override explains why terminology governance
provides no useful value.

In doc-only mode, existing project instructions and current human direction serve as project-specific
overrides. Do not create a config merely to repeat defaults. Do create one when non-default paths
would otherwise be ambiguous to humans or agents.

### One file name at two levels

The same name and grammar serve the project and the user, following the usual configuration
convention:

| Level | Path | Holds |
|---|---|---|
| Project | `chadkit/config.yaml` | Declarations: version, paths, containers, review trigger, overrides, workflow settings |
| User | `$XDG_CONFIG_HOME/chadkit/config.yaml`, default `~/.config/chadkit/config.yaml` | `init` (what a bare `chadkit init` does: `minimal` or `full`) and `known-installs`, the projects this user works in, each with how much of it a cross-repo sweep may read (`chadkit` or `all`) |

Precedence is not a merge: the project file declares, and the user file only supplies defaults for
what a project has not declared. A user file can never override a project declaration.
A machine level, if one is ever needed, takes the same name and the same rule.
`chadkit config` owns the user file (`init`, `show`, `add-install`, `remove-install`). Before 0.6
the project file was
`chadkit/manifest.yaml`; that name is still read for one minor release and `chadkit upgrade`
renames it.


## Goals

Goals may be **directional**, **outcome-oriented**, or **exploratory**. A goal does not need a
fake metric to look rigorous.

```markdown
# Goals

## PG-001 - Make AI a first-class project collaborator

Explore where AI improves speed, quality, consistency, or breadth, and adapt workflows when
evidence supports it.

## Review

Optional project-specific questions worth revisiting:

1. Is the fixed output schema producing cross-project insight, or fighting the domains?
```

- Stable project-goal IDs use `PG-NNN` (`PG-001`, …). Keep the active set small.
- `PG-` distinguishes project goals from generic `G-` identifiers and makes cross-references and grep safer.
- A goal describes direction; tasks describe work; decisions commit.
- Mark obsolete goals inactive or superseded; do not erase why they existed.
- An optional `## Review` section may keep project-specific double-loop questions near the goals they interrogate; omit it when it adds no value.


## Tasks

All ChadKit project-task IDs use the `PT-NNN` form.

```markdown
# Tasks

- [ ] PT-001 [PG-001] Add terminology validation to ChadKit tooling.
- [ ] PT-002 [PG-002] [#onboarding] Investigate failure reported in PLR-20260827-02.
- [x] PT-003 [PG-001] Prototype agent-driven QA. Completed: 2026-08-27
- [ ] PT-004 [PG-001,PG-003] [#auth,#billing] [needs:PT-002,PT-003] Resolve callback failure.
- [-] PT-005 [PG-002] Build combined exporter. Resolved: 2026-08-30 no longer relevant per-format exporters cover it
- [?] PT-006 [PG-002] Add the exporter CLI. Confirm the flag names in chadkit/work/PT-006.md?
```

The mark is the task's state, one of five:

| Mark | State | Written by |
|---|---|---|
| `[ ]` | Open, untouched | `task add` |
| `[?]` | Waiting on a human: the task cannot proceed until someone answers. The question lives in the task's work file, optionally in the task text | `task wait`; `task resume` returns it to `[ ]` |
| `[/]` | In progress | Hand-written; reserved, no verb yet |
| `[x]` | Completed, with a `Completed:` trailer | `task complete` |
| `[-]` | Resolved, with a `Resolved:` trailer | `task resolve` |

The first three are the open marks: a waiting or in-progress task still takes dependencies, is
still scanned by `language check`, and completes or resolves directly without passing through
`[ ]`. `[?]` and `[/]` follow the Minimal checklist convention; GitHub renders both as literal
text rather than a checkbox. A `[?]` task is the one to review first on returning to a project:
`chadkit task list --waiting` lists them (`doctor` too; see [Deterministic tools](#deterministic-tools)).

The shared base fields follow the task ID, in this order, each optional:

| Field | Form | Meaning |
|---|---|---|
| Goals | `[PG-001,PG-003]` | Goals this task serves |
| Tags | `[#auth,#billing]` | Free classification; the `#` sigil is repeated on every tag. Recording each tag in [Ubiquitous Language](#ubiquitous-language) is recommended |
| Dependencies | `[needs:PT-002,PT-003]` | Tasks that must complete first |
| Priority | `[priority:high]` | Optional `low`/`med`/`high`; an absent bracket means `med`, and tools write only the deviations. `high` is reserved for important features or work an important feature needs |

The field order above is canonical for a line written whole. It is **not** a validity condition, and
nothing may reorder the fields of an existing line to achieve it - the search recipes in the retrieval
contract are position-independent by design, so reordering costs diff size and buys nothing.

A reader treats repeated same-kind brackets (`[PG-001] [PG-002]`) as the comma-joined union in file
order: non-canonical, but unambiguous, and hand-writing them is natural in doc-only mode. Tools never
write that shape, and a mutation that touches such a field may collapse it into a single bracket -
that collapse is the minimal lossless way to express the change, not gratuitous normalisation.

Multi-valued fields are comma-separated inside one bracket, never repeated as separate brackets.
The `#` sigil repeats so that a bare search for `#billing` matches in any position. The retrieval
contract under [Agent adapters, skills, and context loading](#agent-adapters-skills-and-context-loading)
holds the matching search recipes, which must be used instead of `grep '\[PG-003\]'` - that pattern
silently returns nothing when the goal is not the only value.

- IDs are stable, project-global, and never reused.
- `PT-` distinguishes project tasks from other identifiers and makes repository-wide grep safer than
  a generic `T-` prefix.
- One concise line per task. Link a goal when meaningful; not every maintenance task needs one.
- `needs` expresses ordering between existing tasks. It must reference real task IDs and must not
  form a cycle; both are validation targets. A task with unmet dependencies is not thereby blocked
  from being worked, and completion does not cascade.
- Completion changes only the task line. Do not reorder, reformat, or relocate completed tasks merely
  for tidiness.
- A task that ends without completing is **resolved**: the mark becomes `[-]` and the line gains
  `Resolved: YYYY-MM-DD` plus why - `split into PT-...`, `duplicate of PT-NNN`, or `no longer
  relevant` with optional prose. The text keeps saying what was intended; rewriting it to match what
  happened falsifies the record, and successor tasks carry the remainder.
- A resolved task never completes, so a `needs` pointing at one is stale: repoint it at the named
  successors or the duplicate's target - a validation target. A resolution of `no longer relevant`
  names nothing to repoint at, so a dependent needs a human decision; that is health reporting, not
  validation.
- Archiving treats resolved tasks like completed ones.
- Substantial design context goes in a focused artifact such as `chadkit/work/PT-017.md`, linked
  from the task rather than inlined: hand-edited prose that evolves with the task, and where a
  human looks first. Record the why - rejected options, gates, reasons - not only the what.
- A feature is an umbrella task: members in `needs:`, the feature's priority in its priority
  bracket, and everything that evolves - scope, notes, why the priority is what it is - in its
  work file. A log record only for a turning point worth a dated, append-only trail.
- Archive completed tasks only when the active container has become materially harder to use.
- The default archive destination is `chadkit/tasks-archive.md`. Create it only when the first archive occurs.
- If a project needs another destination, declare `paths.task_archive` in the config.
- Archiving preserves the original task ID and text; it must not renumber or reinterpret completed work.
- When tasks are sharded by feature or domain, IDs remain `PT-NNN`; use file location and tags for
  classification rather than identity.

`tasks.md` is the actionable backlog. **The log is not a second backlog.**


## Log

One append-oriented log holding evidence and history. Records are never rewritten.

Project log record IDs use `PLR-YYYYMMDD-NN`; the `PLR-` namespace is intentionally explicit
and grep-safe, matching the self-describing `PG-` and `PT-` namespaces.

**`Date` is when the project learned it**, not when the thing happened. For most record types these
coincide - a `t_qa` observation, a `t_lesson`, a `t_experiment`'s result and a `t_review` are all
learned as they occur. Where they differ, the knowledge date is the one worth recording; the reason is
under *Why insertion order is worth preserving* below.

Three dates can be in play, and conflating them is what makes a log misleading:

| Date | Where it lives |
|---|---|
| When the project learned it | `Date` - the required field, and the date the ID stamps |
| When it was written down | `Recorded`, optional, present only when it differs from `Date` |
| When the underlying thing happened | The summary prose, when it is significant at all |

A client mentioning something a fortnight ago that reaches you today is dated today: today is when the
project could first act on it, so a report written last week cannot fairly be faulted for missing it.
Put "Shanna said this on the 15th" in the summary if the timing matters.

Fields are written in one order: `Date`, then the type's required fields as listed below, then
whichever optional fields apply. A record's body is its field lines: any top-level `- Word: value`
line under a heading is a field claim and is validated as one; prose belongs in field values, not
free bullets. A record is readable either way, but a fixed order keeps generated
and hand-written records from differing for no reason.

| Type | Meaning | Required fields | Optional |
|---|---|---|---|
| `t_feedback` | Input from a client, user, or stakeholder | Date, Source, Summary | Related, Action |
| `t_qa` | Observed behavior, test result, defect evidence | Date, Summary | Related, Action, Severity |
| `t_lesson` | Durable knowledge learned while working | Date, Summary | Related |
| `t_experiment` | A bounded trial, especially of AI/tool/workflow behavior | Date, Hypothesis, Result | Related, Follow-up |
| `t_review` | Optional double-loop reassessment - see [Double-loop review](#double-loop-review) | Date, Summary | Trigger, Outcomes, Goals, Shape, Cost, Decision, Related |
| `t_release` | A release of this project was cut; the note says what changed | Date, Version, Summary | Related |
| `t_other` | An observation worth dating that fits no other type; promote it or leave it. The agent-writable counterpart of `thoughts.md`, which agents never write to | Date, Summary | Related |

The `t_` sigil is part of the type's name, on the same reasoning as the `#` on tags: `t_release` is
grep-distinct from a `#release` tag and from the word "release" in prose, where the bare word is
useless as a search key.

Every type also accepts an optional `Recorded` field: the date the record was written, when that is
later than `Date`. Omit it when they match, which is the normal case. It exists for the two cases
where they genuinely differ - adopting ChadKit into a project with existing history, and writing up
something learned a while ago - and it must never be earlier than `Date`, since nothing is written
before it is known.

Every type likewise accepts an optional `Tags` field: free classification, comma-separated with the
`#` sigil repeated (`- Tags: #cli,#regression`), under the same recommendation to record each tag in
[Ubiquitous Language](#ubiquitous-language). Tags on a record classify the observation; tags on a
task classify work.

Add types only for a real need (`t_risk`); `t_other` exists so that need is felt before a type is
invented, and a `t_other` that keeps recurring with one shape is the case for a new type.

The heading line is `### PLR-YYYYMMDD-NN t_type [IDs] Title`, so one grep hit on an ID carries the
record's id, type, links, and title, and the delimiter recipes of the retrieval contract work on the
log too. The bracket is **derived, never hand-maintained**: it holds the union of ID-shaped tokens
appearing in the record's field values - IDs stay in prose where they belong, and a bare ID in
`Related` adds a link with no prose.
An id in backticks is quoted verbatim - a foreign project's id, an example - and is neither linked
nor reference-checked.
Declared decision container prefixes join the link grammar
(`ADR-0006`, `PD-004`), resolved against the container's files; path-qualified decision references
stay prose. A bracket that does not equal that union is a validation
failure, since the tool cannot produce one; omit the bracket when no field names an ID, except that
a title itself beginning with `[` is preceded by an explicit empty bracket (`[]`) so it cannot read
as the links.

```markdown
### PLR-20260827-01 t_feedback [PG-002,PT-014] Onboarding terminology is confusing

- Date: 2026-08-27
- Source: client
- Summary: Client read "workspace" as an organization rather than a project container.
- Related: PG-002
- Action: PT-014
```

- IDs stable: `PLR-YYYYMMDD-NN`. `NN` is two digits, so one date addresses at most 99 records.
  Reaching that is a signal the log is being used as something else; tools refuse rather than
  widen the field, because the width is part of the shared format.
- Append; never rewrite. Correct a material error with a new record that references the old one.
  Append-only protects what a record *meant*, not its spelling: a human may fix a wording mistake
  - wrong when written - in place, while a term correct when written is history and stays, and
  quoted third-party wording is never the project's to fix. No tool tells these apart; the git
  diff review is the guard.
- `log.md` ends with one blank line, so every append is a pure tail-addition.
- **File order is insertion order, not date order.** A backdated record is appended like any other,
  so it lands last even though its ID sorts earliest. Sort by ID when chronological order is what
  you want; do not reorder the file to get it.
- A log entry is evidence, not work. If action is required, create a task and link it.
- If an observation becomes a durable rule, update the appropriate truth document.
- If an experiment establishes a repeatable procedure, promote it to a workflow or a tool.
- Rotate (`chadkit/log/2026.md`) only when the file becomes genuinely unwieldy, and declare the
  new path in the config. Do not split preemptively.

**Why insertion order is worth preserving.** It records what was knowable when. A review that judges
last quarter's work against today's log is committing hindsight bias - faulting people for missing
information the project did not yet have. Because `Date` is the knowledge date, the log answers that
directly: everything above a record was known before it.

Because `Date` is the knowledge date, ID order and file order normally agree, and a record whose ID
precedes its neighbours is the exception rather than the norm. When one appears it means the project
learned something and wrote it down later - bulk adoption of existing history, most often - and its
`Recorded` field says so explicitly rather than leaving a reader to infer it from position.

**Experiments vs decisions.** An experiment is a bounded trial with no commitment attached. A
decision commits. An experiment whose result changes what you do gets promoted to a decision
record - it does not stay in the log as the authority.

Do not split types into separate files merely because their semantics differ. Split only when
lifecycle diverges materially - for example, QA acquires status, severity, ownership, and
closure workflows, or a single-loop calibration record accumulates enough volume to warrant its own
file. When that happens, keep the shared record format unless the changed lifecycle creates a real need to extend or replace it.


## Decisions

Use **MADR 4.0 as the base model** for consequential technical and non-technical choices. A project
may use an established customized MADR template, but the depth of a record should be proportional to
the consequence and uncertainty of the decision.

Create a decision record when a future reader is likely to ask: *why this instead of the plausible
alternatives?* Do not create one merely because a choice occurred.

In a container ChadKit creates, records are `PD-NNN`, one per file, named `PD-001-short-title.md`.
This diverges from MADR's `0001-short-title.md` filenames deliberately, for the addressing reason
given under [Format, container, and addressing](#format-container-and-addressing).

A container that already exists keeps its own filenames and its own `id` field. Nothing is renamed.

### Lightweight decision rule

For routine-but-consequential decisions, the useful minimum is:

- Status
- Context / problem
- Considered options
- Decision
- Consequences

Use additional fields from the project's customized MADR schema - such as reversibility, validation,
review date, outcome grading, source drift, or claim validation - only when they materially improve
the decision or its later review. Empty ceremony is worse than an omitted field.

`status` and `date` go in YAML frontmatter, as MADR 4.0 places them. The retrieval contract greps
for `status: accepted` across a container, so a status buried in prose is invisible to it:

```markdown
---
status: accepted
date: 2026-08-28
---

# PD-002 - Multi-valued task fields are comma-separated

Related: PG-001

## Context and problem
...
```

Status values follow MADR: `proposed`, `accepted`, `rejected`, `deprecated`, `superseded by <id>`.

If a container declares a decision schema - by default `chadkit/decisions/README.md` - that schema is
authoritative for records in that container. ChadKit uses MADR 4.0 as the common basis and permits
established project extensions. Extensions may add useful fields; they should not redefine the meaning
of the shared lightweight fields.

- Do not create records for routine implementation details, temporary experiments, or observations
  that belong in the log.
- A log entry may identify a decision candidate; promote it once the choice becomes consequential.
- Reference the goal a decision serves (`Related: PG-001`) when one applies.
- Decision IDs are project-local and are not globally unique across repositories.

### More than one decision container

A project may already keep architecture decisions somewhere else, often under a heavier customized
MADR template scoped to architecture alone. Keep it. Do not migrate those records into `chadkit/`
(directive 16 under [Default directives](#default-directives)), and do not force lightweight
decisions into an architecture-scoped schema.

Declare each container in the config, with its schema and what it is scoped to:

```yaml
decisions:
  - path: docs/adr/               # files stay 0001-use-madr-with-source-drift-tracking.md
    schema: docs/adr/README.md
    scope: architecture
    prefix: ADR                   # reference form only: ADR-0001
  - path: chadkit/decisions/      # everything the existing container is not scoped to
```

`prefix` governs **how a decision is referenced, not what its file is called.** Declaring
`prefix: ADR` above means a task line or log record cites `ADR-0001`; the file remains
`docs/adr/0001-use-madr-with-source-drift-tracking.md` and its `id: 0001` field is untouched.
Renaming existing records to carry a prefix is a migration, and migrations need the justification
described under [Bootstrapping and migrating an existing project](#bootstrapping-and-migrating-an-existing-project).

The `decisions:` list supersedes `paths.decisions` when present; use the shorthand for the ordinary
single-container case. Rules when more than one container exists:

- **Scopes must not overlap.** If a decision could plausibly land in either container, the scopes are
  wrong. Fix the declared scopes rather than deciding case by case.
- **References must be unambiguous.** Numbering is per-container, so a reference carries its
  container's `prefix` - `ADR-0001` for the adopted container, `PD-001` for ChadKit's. Where no
  prefix is declared, references must be path-qualified (`docs/adr/0001`). Bare `0001` is
  never a valid cross-container reference.
- **One container may be external.** If an intentionally authoritative external system owns a class of
  decisions, declare it in `overrides` and do not mirror its records into Git - see [When to deviate](#when-to-deviate).


## Ubiquitous Language

Use Ubiquitous Language in every project, even small ones, because AI agents are especially prone to
terminology drift: using multiple words for the same concept, or reusing similar words for concepts
that are actually different.

The implementation may be tiny. `chadkit/language.md` can begin with only the terms that have already
shown ambiguity or are central to the project.

Scope values are themselves project vocabulary: give each a row with `Scope: scope`, so the column's
possible values are listed in the one file a human edits. Only `tag` is interpreted by tooling; every
other scope value is the project's to define.

**Tags belong here too**, as rows with `Scope: tag` - task tags and log record tags are one
namespace. Recording a tag when you invent it is
recommended, not required - nothing rejects an undefined tag, because a tag has to stay cheap enough
that trying one out costs nothing. But an undefined tag is how a project ends up with `#migration`,
`#adoption`, and `#brownfield` splitting one category three ways, and the moment that risk is highest
is the moment the tag is created, not later. Writing one line then is the whole safeguard.

```markdown
| Term | Meaning | Allowed aliases | Avoid | Scope |
|------|---------|-----------------|-------|-------|
| Member | Registered person using the product | - | customer, account-holder | domain |
| Single-loop learning | Improve execution while current goals and assumptions remain fixed | - | fast-loop | project-management |
| Double-loop review | Reassess the goals, assumptions, constraints, or shape of the work itself | - | slow-loop, direction review | project-management |
| `domain` | Terms of the project's own subject matter | - | - | scope |
| `project-management` | General methodology terms the project has adopted | - | - | scope |
| `scope` | Values of the Scope column itself; each value used gets a row like these | - | - | scope |
```

Rules:

- One canonical term per concept unless there is a deliberate reason for aliases.
- If two similar terms represent different concepts, define the distinction explicitly.
- Record synonyms to avoid, not only preferred words.
- External/library vocabulary may legitimately differ. Do not rename third-party API concepts.
- New recurring ambiguity is a signal to add or clarify a term.
- Consequential terminology changes may warrant a decision record.

Enforcement is warnings: `language check` never fails, and `validate` does not check terminology use.
A hard failure would need a check with near-zero false positives, which none has earned yet.

The checker distinguishes **project-authored terminology** from **literal or externally owned text**.
Do not require terminology rewrites inside:

- verbatim client/user quotations or transcripts;
- third-party API, protocol, library, product, or schema names;
- glossary rows that intentionally list aliases or discouraged terms;
- examples explicitly marked as externally sourced or intentionally literal.

Markdown syntax alone is **not** a blanket exemption in principle, but the current checker skips
fenced and inline code: code is where third-party literals live, and checking project-owned
identifiers inside code is deliberately deferred until observed drift demands it. Blockquotes are
exempt only when they are actually preserving quoted/external wording.

The checker reports the discouraged or ambiguous term, canonical term or conflict, file, and location.
It does not automatically rewrite semantic terminology unless the change is unambiguous.


## Thoughts, optional

`init` creates `chadkit/thoughts.md` for thoughts, half-baked ideas, and anything with nowhere else
to go yet. It is the top of the chain described under [Promotion](#promotion), and the only artifact
with no structure.

**Rules - these are exemptions, and they are binding:**

- **Zero format.** No IDs, no required fields, no dates unless the human wants them.
- **Exempt from everything.** Not covered by `validate`, `language check`, diff discipline, or
  promotion pressure. Nothing may report on its contents.
- **Hand-edited only.** There is deliberately no `chadkit thoughts` command.
- **Agents never write to it**, never reorder or tidy it, and do not read it by default. An
  agent may read it when explicitly pointed at it, and may *propose* promoting an item.
- Entries that never leave are fine. This is not a backlog and does not need draining.

Keeping `thoughts.md` out of default context loading also prevents an agent treating a discarded
half-idea as a plan. Projects that do not need a human scratch file may delete it; `init` never
recreates it.


## Promotion

Use the lightest artifact that preserves useful information.
Everything starts in the transient layer; promotion routes it by what the information is:

```text
From thoughts.md / conversation / transient note:

  actionable work               -> task
  durable evidence or learning  -> typed log record
  changed direction             -> goal edit
  repeated procedure            -> workflow or tool
  consequential choice          -> decision record
  canonical meaning             -> language.md / other truth document

And onward between artifacts as information hardens:

  log record -> task              when the evidence becomes actionable
  task       -> decision record   when a consequential choice surfaces
  t_review   -> goal edit         when the reassessment moves direction
  anything   -> language.md       when a term needs pinning
```

Possible transitions, not a mandatory lifecycle.

A **spike** is promotion done as scheduled work: a task, tagged `#spike` by convention, whose
deliverable is knowledge or direction rather than a change to materials. While open, its work file
holds options, evidence, and the direction stakeholders gave; it closes by promoting - tasks for
what became actionable, a log record for what was learned or decided (`t_feedback` when the yield
is mostly the direction given), a decision record for a consequential choice, a goal edit if
direction moved. No time-box and no required output shape: an exploration that yields only a
lesson closed well.


## Deterministic tools

Once agents repeatedly mutate structured state, prefer a tool. In tooled mode, artifact paths come
from `chadkit/config.yaml`; do not hardcode movable artifact paths.

```text
chadkit init [--full|--minimal] # config, orientation README, thoughts.md; --full adds language.md, an adoption spike, a known-installs entry
chadkit task add "<text>" [--goal PG-001] [--tag auth] [--needs PT-002]
chadkit task complete PT-017 [--date YYYY-MM-DD]
chadkit task mod PT-004 --add-tag billing --remove-goal PG-001
chadkit task resolve PT-005 --split-into PT-006,PT-007    # or --duplicate-of PT-002, --not-relevant [--reason "..."]
chadkit task wait PT-006                                  # [?]: cannot proceed until a human answers; no date
chadkit task resume PT-006                                # [?] back to [ ]
chadkit task list [--all | --waiting] [--priority high] [--sort-by state,priority] [--width 80]
chadkit task info PT-006 [--history]      # the task's part of a gate brief; --history: the timeline alone
chadkit task stats                                        # counts per state, high priority alone, most recently updated
chadkit log add --type t_feedback [--date YYYY-MM-DD]   # the bare type is accepted and normalised
chadkit log add --type t_review
chadkit language init                       # language.md from the template: the scope rows plus #spike and #migration
chadkit language check [paths...] [--all]   # Avoid-column warnings; never fails; defaults scan chadkit artifacts only
chadkit language check --fix [paths...]     # rewrite confident matches for git-diff review; never combines with --all
chadkit validate
chadkit doctor [--all]          # health/drift reporting; --all sweeps every known install in one report
chadkit goals | chadkit tags    # one line per goal or tag with its meaning; also shown in --goal and --tag help
chadkit goals qa                # every goal in full with the gate's standing question, what the judge reads
chadkit model                   # where CHADKIT-MODEL.md is: the checkout's copy, this version's URL, latest
chadkit help --all              # every command and subcommand's help in one dump, for adapters to point at
chadkit upgrade                 # config chadkit-version -> installed CLI; prints how to refresh the CLI
chadkit config init | show      # the user-level config.yaml; add-install [path] [--read all], remove-install [path]
```

Later: `goal add`, `task archive`, `decision new`, `log rotate`.

`chadkit init` writes `chadkit/config.yaml`, `chadkit/README.md`, and `chadkit/thoughts.md` - the
last being the placeholder rule's one exception - and stops. A re-run on an initialised project
refuses; `--force` rewrites the config alone, and a deleted README or `thoughts.md` stays deleted.
Every other artifact is created by the first command that writes a record into it - `task add` creates
`tasks.md`, `log add` creates `log.md` - in a new or existing repository alike. Scaffolding a full
directory would contradict both the placeholder rule under
[Minimal information model](#minimal-information-model) and the inspect-first sequence under
[Bootstrapping and migrating an existing project](#bootstrapping-and-migrating-an-existing-project), and it would guess at
answers that only inspecting the project can give. A missing artifact is a valid state, not a
finding: `validate` must not report one.

Multi-valued options accept either repetition or a comma list (`--goal PG-001 --goal PG-003`,
`--goal PG-001,PG-003`) and always write the canonical single-bracket form defined under [Tasks](#tasks).

`--date` exists for adoption and migration: a task completed before today, or an imported log record
whose `PLR-YYYYMMDD-NN` ID must reflect when the evidence arrived rather than when it was recorded.

`chadkit task mod` changes only the bracket fields on a task line, using explicit `--add-*` and
`--remove-*` verbs so a bulk pass cannot silently drop a field. It does not rewrite task text;
that is a human edit, and requirement 6 below applies.

`chadkit task archive` writes to `chadkit/tasks-archive.md` by default (or the config
override) and makes only the minimum necessary source/archive edits.

**Requirements:**

1. Make the smallest practical textual change.
2. Never reserialize or reformat a whole file to change one record.
3. Preserve comments, ordering, and human formatting outside the targeted region.
4. Refuse ambiguous mutations instead of guessing.
5. Validate IDs and references before writing.
6. Never overwrite an existing record.
7. Emit concise machine-readable output when useful to agents.
8. Test mutation behavior once the tool matters.
9. Prefer idempotent operations.
10. Keep diff size proportional to the semantic change.

Until a tool exists, agents edit directly under the same discipline. When the same structured
edit recurs, add the command rather than repeatedly teaching agents to edit Markdown.

**`validate`** grows in response to real failure modes: duplicate or malformed IDs, references to
nonexistent IDs, `needs` dependency cycles, invalid log record types, fields that are
missing or that do not apply for a record's type, malformed `language.md`, config-declared
invariants. Do not build a schema
system before the project needs one. Discouraged terminology is `language check`'s job, and it
warns rather than fails.

**`doctor`** reports project health rather than correctness. Keep it lightweight and add checks
only for failure modes the project actually cares about - for example ChadKit version drift, overdue
decision reviews, pending unverified claims, or a configured review trigger that appears to have been
skipped. Two checks earn their place from the start. Because artifacts are created lazily, `doctor`
reports a project that has accumulated real work with no `language.md`, so that the Ubiquitous
Language invariant is dropped by explicit override rather than by never getting around to it. And
because recording a tag is recommended rather than required, `doctor` reports tags in use with no row
in `language.md` - a note, never a failure, which is the right weight for a recommendation.
Where a project declares a QA gate, `doctor` reports a check script that is missing or not
executable, and names commits touching a gate path with no `QA-Gate:` trailer since the declared
start (up to ten, then a count), so a skipped gate is noticed rather than remembered. Where a task
is waiting on a human, `doctor` lists it, as it does an open task that cites no goal, since
validation has nothing to judge it against. If a project has no review trigger, gate, or enhanced
decision fields, `doctor` should not invent them.


## Workflows

A workflow is a repeatable way of doing work, not project state. Create one when the procedure
repeats, a missed step has caused problems, an agent benefits materially from explicit
sequencing, tools must be called in order, or the process should improve over time. Do not
document one-off activities.

Assume workflows can improve. When an agent or tool demonstrates a better procedure: run a
bounded experiment if evidence is uncertain, record the result as a `t_experiment` or `t_lesson`,
update the workflow if evidence supports it, move mechanical steps into tools, remove obsolete
human-only steps rather than preserving ceremony, and keep human review gates where judgment,
risk, or accountability warrant them.

The goal is not to make AI imitate the human process. It is the most effective reliable process
using humans, agents, and deterministic software for the parts each does best.

### The QA gate, a worked example

The QA gate is one project's workflow, the ChadKit repository's own, offered as the shape a gate
can take: an independent adversarial examination a body of work takes before it lands, and the
record it leaves.

- **Roles.** A requester names the scope and the focus. A manager, the session doing the work,
  dispatches the reviewer, verifies every finding against the real tree, applies each or declines
  it with a reason, runs the checks, writes the record, and stamps the commit. A reviewer is an
  independent agent biased toward recall, given the diff, the task and the goals it cites, and the
  focus, and never the session's history, so it can say whether the right thing was built as well
  as whether it was built right; which reviewer, and on which model, is the project's choice and
  lives in its workflow.
- **Checks.** The script declared under `workflows.qa-gate.checks` in the project config, so the gate runs
  one command rather than a list it is trusted to remember.
- **Record.** A run that confirmed at least one finding appends one `t_qa` record tagged
  `#qa-gate`, related to the task, with the confirmed, refuted, and declined findings and why,
  appended before the commit so the record lands in the commit it stamps. A clean run appends
  nothing.
- **Stamp.** The commit that lands carries a trailer, `QA-Gate: PLR-YYYYMMDD-NN` naming that
  record or `QA-Gate: clean`; `doctor` audits it (see [Deterministic tools](#deterministic-tools)).
- **Improve.** A finding class confirmed for the second time becomes a `#qa-gate` task that
  makes it deterministic: a test, a `validate` rule, a script.

A project adopts the gate by writing its own `chadkit/workflows/qa-gate.md` with these parts and
its specifics, declaring `workflows.qa-gate` in [the project config](#the-project-config), and adding the
`QA gate` term and `#qa-gate` tag rows to its `language.md`. Which commits must take it is the
project's rule, stated in its workflow.


## Agent adapters, skills, and context loading

`CLAUDE.md`, Claude Skills, Codex instructions, and equivalents are adapters. They point at project
truth; they do not copy it.

```markdown
When asked to review, QA, or gate a change:

1. Follow `chadkit/workflows/qa-gate.md`.
2. Record a run that confirmed a finding: `chadkit log add --type t_qa --tag qa-gate --related PT-NNN --summary "..."`.
3. Follow terminology in `chadkit/language.md`.
4. Do not duplicate project truth in this file.
```

An adapter names commands, not their surface: `chadkit help --all` is the whole surface in one
dump, `chadkit task list`, `chadkit goals`, and `chadkit tags` are the state a session needs on
arrival, `chadkit model` is where the model is, and each stays current without an edit to the
adapter.

### Artifact consultation triggers

Adapters and skill descriptions must state **when to consult an artifact**, not merely where the file
lives. Passive references are easy for agents to under-trigger on. When missing an artifact could
materially reduce correctness, prefer explicit and somewhat assertive trigger language.

At minimum:

- Consult `language.md` whenever naming or renaming domain concepts, project-owned APIs, data fields,
  goals, tasks, user-facing concepts, or other terminology with semantic meaning.
- Consult relevant decisions before changing architecture, dependencies, established conventions,
  significant workflows, or behavior that may already have a recorded rationale.
- Search the log when investigating defects, prior feedback, QA findings, experiments, lessons, or
  why current behavior exists.
- Consult goals when prioritizing, planning scope, proposing work, or choosing among approaches whose
  value depends on project direction.
- Consult the relevant workflow before performing a repeated procedure that the project has chosen to
  standardize.

Descriptions should optimize for reliable triggering, not elegance. A short adapter that clearly says
*when* to load project truth is better than a passive catalog of paths.

### Reuse skills before inventing them

Before creating a ChadKit-specific skill or workflow for a common development activity, check whether
an existing maintained Agent Skill already solves the problem adequately. Prefer composition and
integration over copying a generic methodology into ChadKit.

Relevant overlap includes:

- **Agent Skills / Claude Skills** - the packaging mechanism for reusable instructions, scripts,
  references, and assets. ChadKit should use this mechanism rather than invent a competing skill
  format.
- **Anthropic `skill-creator`** - use it to create, evaluate, and improve Claude Skills rather than
  inventing a separate ChadKit skill-development methodology.
- **Anthropic `claude-md-management`** - useful for maintaining thin `CLAUDE.md` adapters, but durable
  project knowledge should still be promoted into ChadKit truth instead of accumulating in
  `CLAUDE.md`.
- **Anthropic `project-artifact`** - useful as a presentation/status output layer. It may summarize
  ChadKit truth; it should not become a competing source of truth.
- **Superpowers and similar skill libraries** - candidates for common coding workflows such as
  brainstorming, planning, debugging, TDD, verification, and review. Reference or compose them when
  they fit rather than duplicating their procedures.

A ChadKit workflow should add project-specific orchestration around reusable skills, terminology,
truth, and deterministic state mutations.

### Retrieval contract

Agents do not load every document. Default order:

1. current request;
2. `chadkit/config.yaml` when present (especially for non-default paths or overrides);
3. relevant goals and tasks;
4. relevant terminology;
5. linked decisions, workflows, and log records as needed.

Targeted retrieval is grep-shaped:

```bash
grep '^- \[[ ?/]\] PT-' chadkit/tasks.md    # open tasks, any open mark
grep '^- \[?\] PT-' chadkit/tasks.md        # waiting on a human
grep '^- \[ \] PT-' chadkit/tasks.md        # not started
grep -A12 'PLR-20260827-01' chadkit/log.md
grep -l 'status: accepted' chadkit/decisions/*.md
```

Task fields are comma-separated lists (see [Tasks](#tasks)), so match on the delimiters rather than
the whole bracket.
These patterns are exact at any position in the list and need no word-boundary escape, which is not
portable across `grep` implementations:

```bash
grep -E '[[,]PG-003[],]' chadkit/tasks.md    # tasks serving a goal
grep -E '[[,]#auth[],]'  chadkit/tasks.md    # tasks carrying a tag
grep -E '[:,]PT-002[],]' chadkit/tasks.md    # tasks blocked on a dependency
```

`grep '\[PG-003\]'` is wrong: it silently returns nothing whenever the goal is not the only value.

Never ingest the whole log or every decision record by default. Never read
`chadkit/thoughts.md` by default.


## Git diff discipline

Large diffs are a project-quality problem, not merely a review inconvenience. Before finishing,
inspect the diff and ask: did I change only what actually changed; did I rewrite or reformat
unrelated documentation; did I duplicate information authoritative elsewhere; did I create a
durable record for transient session context; could a tool make this mutation smaller next time?

Avoid: automatic session-summary dumps; repeated project descriptions across files; generated
timestamps on untouched records; sorting or reflowing whole files; updating related documents
"just in case"; copying workflow or policy text into agent adapters; storing raw AI reasoning or
implementation narration.


## Double-loop review

*An optional mechanism, but an important concept - a project may skip the record and still owe itself
the question.*

**Single-loop learning** improves execution while the current goals and assumptions remain fixed:
workflows adapt, tools improve, and `t_experiment` and `t_lesson` records accumulate.

**Double-loop review** asks a different question: **are the goals, assumptions, constraints, and
shape of the work themselves still right?** Without that question, a project can become highly
efficient at pursuing the wrong target. The terminology derives from Argyris and Schön.

A project may record a double-loop review as a `t_review` log record when doing so adds value. There is
no mandatory cadence, trigger, or checklist.

Useful questions include:

- Did the work produce what it was for, judged on what was known at the time? The log's insertion
  order exists for this question (see [Log](#log)).
- Are the goals still right, or should any be dropped, added, or reweighted?
- Has the shape of the work become over- or under-built?
- Is cost still favorable relative to value?
- Are important constraints or assumptions still earning their keep?
- Has AI experimentation revealed a better division of labor or workflow?

If the project has a natural review trigger, it may declare one in the config. If not, omit it.
A review that changes a goal edits the goal; a review that changes a consequential commitment may
produce a decision record. The review record itself is evidence of the reassessment, not a second
source of truth.

Use the terms **single-loop learning** and **double-loop review** rather than `fast-loop` and
`slow-loop`; terminology consistency here is itself an example of the Ubiquitous Language rule.


## Bootstrapping and migrating an existing project

1. Inspect current docs, agent files, scripts, and conventions.
2. Identify existing equivalents before creating anything.
3. In tooled mode, create `chadkit/config.yaml`; in doc-only mode, create it only when
   non-default paths or overrides would otherwise be ambiguous.
4. Create only the minimum missing artifacts needed now.
5. Do not migrate historical notes unless they remain useful.
6. Start tooling at the current pain point - usually task mutation, typed log append, terminology
   validation, or project validation.
7. Keep existing agent files working; shorten them only for clear benefit.
8. Improve incrementally as normal work exposes weaknesses.

Adoption starts at the config alone. After a little real use, a project may have grown only this
far, and that is a complete and valid state:

```text
chadkit/
├── config.yaml    # required tooled; optional doc-only
├── README.md
├── tasks.md         # appeared when the first task was recorded
├── log.md           # appeared when the first record was appended
└── language.md      # appeared when the first term needed pinning down
```

Goals, decisions, and workflows appear the same way - when they provide value or map to a useful
existing project artifact, never in advance of one. `thoughts.md` is the exception: `init` seeds it
so the first jotted idea has somewhere to go, and a project that does not want it deletes it.

Migration here means consolidating a project's existing history into ChadKit records - what the
`--date` and `Recorded` mechanics exist for. Migrating records between ChadKit **versions** is the
other sense: see [ChadKit versioning while experimental](#chadkit-versioning-while-experimental),
where `chadkit upgrade` moves the config and `validate` names each record still in an old format.


## When to deviate

Deviation is expected when it improves the project. Good reasons: the repo has a clear
equivalent; the project is too small for an artifact; an artifact's lifecycle warrants splitting;
an external system is intentionally authoritative; a different structure produces smaller diffs
or better agent reliability; experiments show a better approach.

Bad reasons: an agent prefers its habitual layout; a template says a file "should" exist; extra
structure makes the repo look complete; duplication is convenient for one prompt.

Record recurring deviations in the config `overrides` or as a decision record. Prefer extending
shared formats to redefining them; if incompatibility is necessary, make it explicit.


## ChadKit versioning while experimental

For now, use **one ChadKit version** for the shared contract: the information model, shared record
semantics, and tooling expected to operate on them. Do not separately version `MODEL.md`, the CLI,
and schemas until a real release-management need requires that separation.

ChadKit's first released version was **0.1.0**, cut when it was placed in its own repository and
applied to the first real project. Projects in tooled mode declare the version they follow in the
config (see [The project config](#the-project-config)); `doctor` reports when the installed CLI
has moved past it, and `chadkit upgrade` brings the config up to the installed version. The
reverse - a config ahead of the installed CLI - fails `validate`, because a checker older than
the records it is judging passes blind. Refreshing
the CLI itself is the user's action; `upgrade` reads how the CLI was installed (PEP 610
`direct_url.json`) and names the reinstall command rather than running it - or says none is
needed, for an editable install that runs live from its checkout.

ChadKit remains intentionally **pre-1.0**. We want permission to change our minds cheaply while real
projects reveal which ideas work.

Guidelines:

- Change shared record semantics sparingly because common tooling depends on them.
- Projects may extend shared formats but should not remove or reinterpret their base semantics.
- Add optional capabilities without forcing existing projects to adopt them.
- Prefer backwards-compatible interpretation when practical.
- Do not preserve a bad design merely to avoid a version bump.
- Before 1.0, learning from real project use is more important than compatibility ceremony.
- If CLI/tool release cadence eventually needs to diverge from the information-model contract,
  introduce separate component/schema versions then - not before.

Changes to ChadKit should be justified by observed or strongly anticipated failure modes, not by a
desire to complete a hypothetical platform.


## Design provenance and evolution

ChadKit borrows from existing work rather than claiming these ideas as novel.

### Current influences

- **GitHub Spec Kit** - separation of project-owned artifacts from tooling/integration assets;
  aggregated task artifacts; live policy truth rather than copied downstream instructions;
  deterministic scripts with bounded writes; progressive context loading; explicit support for
  existing projects; extensible workflows, presets, and other composable process assets.
- **MADR 4.0** - decision records and the principle that consequential choices should preserve the
  context, alternatives, decision, and consequences.
- **Domain-Driven Design / Ubiquitous Language** - canonical terminology shared across people,
  software, documentation, and agents.
- **Argyris and Schön** - single-loop learning versus double-loop questioning of underlying goals
  and assumptions.
- **Agent Skills / Claude Skills** - reusable capability packaging with progressive disclosure and
  deterministic scripts/resources.
- **Diátaxis** - useful distinctions for documentation types, without adopting its categories as the
  top-level project information model.
- **OpenSpec, Superpowers, BMAD, and similar agent-development systems** - external experiments in
  specification, workflow design, context management, and human/agent division of labor.

### Evolution rule: prefer adoption over invention

Maintained external systems are ongoing sources of research and proven patterns. When GitHub Spec Kit,
OpenSpec, Agent Skills, Superpowers, MADR, DDD practice, or another relevant model introduces an idea
that could improve ChadKit, treat it as a candidate rather than assuming ChadKit's current design is
superior.

Adopt, integrate, delegate to, or replace existing ChadKit behavior when an alternative solves the
same problem more effectively without violating ChadKit's core constraints. Do not add an idea merely
because another framework has it.

Evaluate candidate changes with these questions:

1. **Does this prevent a failure we have seen or strongly anticipate, or is it infrastructure for a
   hypothetical future system?**
2. Does it reduce or add ceremony?
3. Does it preserve small, reviewable diffs?
4. Does it work well for existing/brownfield projects?
5. Can project truth remain vendor-neutral?
6. Does an existing maintained tool or skill already solve the problem well enough?
7. Is the benefit worth the new concept, artifact, rule, or dependency?

If a substantially better model emerges, ChadKit should be willing to shrink, integrate with it,
replace part of itself, or stop owning a concern entirely.

### References to monitor

- GitHub Spec Kit: https://github.com/github/spec-kit
- OpenSpec: https://github.com/Fission-AI/OpenSpec
- Agent Skills specification: https://agentskills.io/specification
- Anthropic Skills: https://github.com/anthropics/skills
- Anthropic Claude plugins: https://github.com/anthropics/claude-plugins-official
- Superpowers: https://github.com/obra/superpowers
- BMAD Method: https://github.com/bmad-code-org/BMAD-METHOD
- MADR: https://adr.github.io/madr/
- Diátaxis: https://diataxis.fr/
