ChadKit - Project Information Model

Version: 0.7.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
  2. Quick start for an existing project
  3. Two operating modes
  4. Authority and adaptation
  5. Default directives

II. The model

  1. Minimal information model
  2. Format, container, and addressing
  3. The project config

III. Project truth

  1. Goals
  2. Tasks
  3. Log
  4. Decisions
  5. Ubiquitous Language
  6. Thoughts, optional
  7. Promotion

IV. Procedure and practice

  1. Deterministic tools
  2. Workflows
  3. Agent adapters, skills, and context loading
  4. Git diff discipline
  5. Double-loop review

V. Adoption and evolution

  1. Bootstrapping and migrating an existing project
  2. When to deviate
  3. ChadKit versioning while experimental
  4. 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:

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.

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 applies. Either way the goal is a working minimum, not a complete directory.

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

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 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.

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.

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:

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

PG-01                   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.

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, and project-qualified across projects, user-ck/PT-005

Project-specific extensions are legitimate:

- [ ] PT-017 [PG-02] [#auth] [owner:client] Resolve callback failure.

Here [owner:client] is the extension; [PG-02] and [#auth] are shared base fields defined under Tasks.

Reinterpreting shared syntax is not:

[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:

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:

# chadkit/config.yaml

chadkit-version: 0.7.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
    from: user-ck@7baff35                  # the shared qa-gate.md this one follows, at that commit

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

Default paths are:

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 workflows it knows, whose keys are closed, so a misspelled checks is refused rather than ignored. It knows qa-gate (see Workflows): checks names the script the gate runs after a review, paths the paths whose commits the gate must clear, 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, and from the shared qa-gate.md this project follows, <project>@<revision>: the project's root directory name, then the revision holding the shared file, in since's form, a commit to pin it or a branch to track it. Nothing reads from; it is the one place the revision is written. What doctor checks against these is under 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.

# Goals

## PG-01 - 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?

Tasks

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

# Tasks

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

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

Field Form Meaning
Goals [PG-01,PG-03] Goals this task serves
Tags [#auth,#billing] Free classification; the # sigil is repeated on every tag. Recording each tag in 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-01] [PG-02]) 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 holds the matching search recipes, which must be used instead of grep '\[PG-03\]' - that pattern silently returns nothing when the goal is not the only value.

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 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. 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 - an example, a quotation - 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. An id qualified by a / is prose, whatever its shape: another project's, user-ck/PT-005, the project named by its root directory; a path's, decisions/PD-004-title.md. A work file's basename, PT-017.md, keeps the id linked. 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.

### PLR-20260827-01 t_feedback [PG-02,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-02
- Action: PT-014

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.

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:

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:

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

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

Related: PG-01

## 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.

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), 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:

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.

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

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.

| 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:

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:

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, and the only artifact with no structure.

Rules - these are exemptions, and they are binding:

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:

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.

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-01] [--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-01
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 and the inspect-first sequence under 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-01 --goal PG-03, --goal PG-01,PG-03) and always write the canonical single-bracket form defined under 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.

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, 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.

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:

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:

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:

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), 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:

grep -E '[[,]PG-03[],]' 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-03\]' 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:

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:

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, 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); 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:

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

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