refactor: drop dev-cycle-profile.yml for conventions + CLAUDE.md facts

The profile was never parsed — it was prose the skill bodies told the model to read, so most slots were dead, constant across every project, or fiction (the whole pipeline block, including the "tdd is opt-in" claim, was enforced by nothing).

Split it in two: constants become fixed conventions named directly by the skills (new docs/conventions.md), and the few genuinely per-project facts move to each project's CLAUDE.md under '## Skills plugin: project facts'. tdd/fieldtest/docwriter are now always available; the only behavioural toggle left is spec auto-sign.

Delete docs/profile-schema.md and templates/project-profile.yml; add docs/conventions.md and a project-facts section to templates/CLAUDE.md.fragment; rewrite all SKILL/agent prose and the pipeline/design/migration/README/INSTALL docs accordingly.
This commit is contained in:
2026-06-13 16:30:02 +02:00
parent 268ee705f4
commit 26e9630496
40 changed files with 752 additions and 894 deletions
+50 -43
View File
@@ -1,20 +1,28 @@
# Design
## Why split plugin from profile
## Why split plugin from project
The skills system originally evolved inside the AILang project,
where it grew organically against AILang's specific paths,
build commands, vocabulary, and contracts. Lifting it into a
plugin requires a clean separation between what is universal
(belongs in the plugin) and what is project-specific (belongs
in a per-project profile).
in the project's `CLAUDE.md`).
The litmus test: would a sentence in a SKILL or agent body
still make sense in a Python web project, a Rust CLI, and a
TypeScript library? If yes, plugin. If it mentions `cargo`,
`crates/`, `docs/design/INDEX.md`, `Form A`, or any project-specific
identifier, it goes to the profile (as a slot) or to the
project's `CLAUDE.md` (as sittenkodex).
identifier, it goes to the project's `CLAUDE.md` — either as a
project fact (the few mechanical facts the skills consume) or as
sittenkodex (domain contracts, anti-patterns).
There is no separate profile file. An earlier design had a
per-project `dev-cycle-profile.yml`, but it was never parsed — it
was prose the skill bodies told the model to read, and almost every
slot was constant across projects, dead, or derivable. So the
constant parts became fixed conventions (`conventions.md`) and the
genuinely-varying parts moved into each project's `CLAUDE.md`.
## Plugin layer (universal)
@@ -54,44 +62,42 @@ The plugin owns:
- **Output budget discipline** — agents have word budgets on
their reports.
## Profile layer (project-specific)
## Fixed conventions (universal)
The profile fills slots that the plugin's prose references
generically. Concretely:
The constants that used to be configurable but were the same in
every project are now plugin conventions, named directly in skill
and agent bodies and documented once in `conventions.md`:
spec dir `docs/specs`, plan dir `docs/plans`, 4-digit per-directory
naming, the vocabulary cycle / iteration / milestone / contract,
standing reading (`CLAUDE.md` + `git log -10`), git discipline
(only-orchestrator commits, main sacrosanct), Gitea + `closes #N`,
and the whole pipeline graph (see `pipeline.md`).
- **Paths**: `spec_dir`, `plan_dir`, `design_ledger`,
`design_contracts`, `design_models`, `code_roots`, `bench_dir`.
- **Commands**: `build`, `test`, `lint`, `regression` (list).
- **Vocabulary**: `cycle`, `subcycle`, `ledger_entry`.
- **Naming**: `counter_dirs`, `policy` (`stable_per_directory_4digit`
or `date_prefix` or `flat`).
- **Standing reading**: `always` (a list), `by_role` (a map
from role to list).
- **Git**: `main_sacrosanct` (bool, default true),
`only_orchestrator_commits` (bool, default true),
`issue_tracker.kind` (`gitea` / `github` / `linear` / `none`),
`issue_tracker.close_marker` (e.g. `"closes #N"`).
- **Pipeline customisations**: per-phase `mandatory_before`,
`mandatory_at`, `boss_only`, `when` (a condition tag).
## Project facts (project-specific)
The full schema lives in `profile-schema.md`. The functional
starting template is `../templates/project-profile.yml`.
The handful of facts that genuinely vary per project live in the
project's `CLAUDE.md` under `## Skills plugin: project facts`:
code roots, build / test / lint / doc-build commands, regression
scripts, architect sweeps, design-ledger / glossary / contracts /
models / bench / public-interface / fieldtest-examples paths,
spec-validation parsers, by-role standing reading, the issue-tracker
repo slug and commands, and spec auto-sign. The template is in
`../templates/CLAUDE.md.fragment`; the per-fact reference is the
table in `conventions.md`.
## Resolution model
The plugin uses **profile-driven prompts**, not template
rendering. Each SKILL.md and agent file is generic prose that
references the profile prosaically:
The plugin uses **convention-and-fact prompts**, not template
rendering and not a config parser. Each SKILL.md and agent file is
generic prose that either names a fixed convention directly or
points at a project fact:
> Write the spec to the directory configured under `paths.spec_dir`
> in the project profile. Use the naming policy configured under
> `naming.policy`.
> Write the spec to `docs/specs`. Use the project's build command
> (its CLAUDE.md project facts).
When Claude Code loads the skill, the project profile is in
context (the skill body explicitly instructs the model to read
it first). The model performs the substitution at read-time.
This avoids a build step and keeps a single source of truth in
the repo.
The project's `CLAUDE.md` is always in context (it is standing
reading #1), so the model resolves the facts at read-time. This
avoids a build step and keeps a single source of truth in the repo.
## Sittenkodex split
@@ -104,18 +110,19 @@ which are conditions for the plugin's own correctness.
The relationship:
- **Plugin** (this repo): mechanics, universal discipline
- **Profile** (per project): slots — paths, commands,
vocabulary, naming, git conventions, pipeline customisations
- **Project CLAUDE.md**: sittenkodex — domain-specific anti-
patterns and acceptance criteria
- **Plugin** (this repo): mechanics, universal discipline, fixed
conventions
- **Project CLAUDE.md**: project facts — the few mechanical facts
the skills consume (code roots, build/test, tracker slug, …) —
plus sittenkodex (domain-specific anti-patterns and acceptance
criteria)
## What's out of scope for this plugin
- **Issue-tracker integration**: the plugin can read the
profile's `issue_tracker.kind`, `issue_tracker.list_cmd`, and
`issue_tracker.show_cmd` and invoke the configured listing /
single-issue commands, and `specify` may post a reconciliation
- **Issue-tracker integration**: the plugin reads the project's
issue-tracker commands (the repo slug, list command, and
single-issue-with-comments command, all in its CLAUDE.md project
facts) and invokes them, and `specify` may post a reconciliation
comment via the tracker's comment command — but the plugin does
not directly call Gitea / GitHub / Linear APIs. Every read and
write goes through the configured shell command, so the plugin