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:
+50
-43
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user