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:
+13
-10
@@ -23,8 +23,10 @@ to prevent>
|
||||
|
||||
## Standing reading list
|
||||
|
||||
<list of always-binding documents — derived from the project
|
||||
profile's `standing_reading.always` plus `standing_reading.by_role.<this-role>`>
|
||||
<list of always-binding documents — the fixed always list (`CLAUDE.md`
|
||||
plus `git log -10 --format=full`), the per-role standing reading the
|
||||
project lists in its CLAUDE.md project facts, and the project's glossary
|
||||
if it has one>
|
||||
|
||||
## Carrier contract
|
||||
|
||||
@@ -119,15 +121,16 @@ forcefully than "this role helps with X".
|
||||
|
||||
### Standing reading list
|
||||
|
||||
The plugin's skill body computes this from the project profile
|
||||
(`standing_reading.always` + `standing_reading.by_role.<role>`)
|
||||
and passes the resolved list to the agent via the carrier. The
|
||||
agent's body says, prosaically: "Read everything in the standing
|
||||
reading list before doing anything else."
|
||||
The plugin's skill body composes this list and passes it to the agent
|
||||
via the carrier. It is built from a fixed always list — `CLAUDE.md`
|
||||
plus `git log -10 --format=full`, binding on every role — extended by
|
||||
the per-role standing reading the project lists in its CLAUDE.md project
|
||||
facts. The agent's body says, prosaically: "Read everything in the
|
||||
standing reading list before doing anything else."
|
||||
|
||||
A set `paths.glossary` is implicitly part of `always`, so every role
|
||||
reads the project glossary without a per-role entry (see
|
||||
`profile-schema.md` § `paths`).
|
||||
When the project's CLAUDE.md project facts name a glossary path, that
|
||||
glossary is implicitly part of the always list, so every role reads the
|
||||
project glossary without a per-role entry.
|
||||
|
||||
The agent file itself does not hardcode file paths.
|
||||
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
# Conventions
|
||||
|
||||
The skills plugin used to read a per-project `dev-cycle-profile.yml`.
|
||||
It no longer does. There was never a parser — the profile was prose
|
||||
the skill bodies told the model to read, and almost every slot was
|
||||
either dead, constant across all projects, or derivable. So the
|
||||
plugin now splits cleanly in two:
|
||||
|
||||
- **Fixed conventions** (this file) — the things that were constant
|
||||
across every project. They are not configurable; the skill and agent
|
||||
bodies name them directly.
|
||||
- **Per-project facts** — the handful of things that genuinely vary
|
||||
per project (where the code lives, how to build and test it, the
|
||||
tracker slug, …). These live as prose in each project's own
|
||||
`CLAUDE.md` under a `## Skills plugin: project facts` heading. See
|
||||
`../templates/CLAUDE.md.fragment` for the template, and the section
|
||||
list at the bottom of this file.
|
||||
|
||||
## File layout
|
||||
|
||||
| Artefact | Location |
|
||||
|----------|----------|
|
||||
| Specs (from `specify`) | `docs/specs/` |
|
||||
| Plans (from `planner`) | `docs/plans/` |
|
||||
|
||||
These directories are fixed. A project that keeps specs and plans
|
||||
elsewhere is the rare exception and states the override in its
|
||||
`CLAUDE.md` project facts.
|
||||
|
||||
## Naming
|
||||
|
||||
Counter-prefixed, per directory: `NNNN-slug.md`, 4-digit
|
||||
zero-padded. The counter is per directory, assigned in creation
|
||||
order, and stable for the life of the file. New files take the
|
||||
next-higher number; deleted files retire their number (numbers are
|
||||
not recycled). `brainstorm` / `specify` / `planner` scan the target
|
||||
directory for the next free number before writing.
|
||||
|
||||
The slug separator is `-`.
|
||||
|
||||
## Vocabulary
|
||||
|
||||
The pipeline's nouns are fixed:
|
||||
|
||||
| Term | Meaning |
|
||||
|------|---------|
|
||||
| **cycle** | One round in the pipeline graph (`brainstorm → specify → planner → implement → audit → [fieldtest]`). NOT the top-level container. |
|
||||
| **iteration** | A sub-unit of a cycle. |
|
||||
| **milestone** | Tracker container spanning many cycles; closes only when complete AND functional (see `pipeline.md` § Milestone-close gate). |
|
||||
| **contract** | A single design-ledger entry. |
|
||||
|
||||
When a project declares a glossary (in its CLAUDE.md project facts),
|
||||
that glossary is the source of truth for domain nomenclature and
|
||||
overrides these names where they collide (see `glossary-convention.md`).
|
||||
|
||||
## Standing reading
|
||||
|
||||
Every agent reads, at the start of every dispatch:
|
||||
|
||||
- the project's `CLAUDE.md`
|
||||
- `git log -10 --format=full`
|
||||
|
||||
A project may add more — globally or per role — in its CLAUDE.md
|
||||
project facts (`standing reading`). If the project declares a
|
||||
glossary, that file is implicitly standing reading for every role
|
||||
too.
|
||||
|
||||
## Git discipline
|
||||
|
||||
- **Only the orchestrator commits.** No skill agent runs `git commit`.
|
||||
Agents write into the working tree as unstaged changes; the
|
||||
orchestrator inspects, decides commit shape, and commits.
|
||||
- **main HEAD is sacrosanct.** Nobody runs `git reset` / `git revert`
|
||||
on main (or any other protected branch). main moves forward only via
|
||||
orchestrator commits; a wrong agent diff is discarded with
|
||||
`git checkout -- <paths>` / `git stash`, never by rewinding main.
|
||||
|
||||
These also appear in the universal-discipline fragment
|
||||
(`../templates/CLAUDE.md.fragment`) that each project's CLAUDE.md
|
||||
imports.
|
||||
|
||||
## Issue tracker
|
||||
|
||||
The tracker is **Gitea** and the commit close-marker is `closes #N`
|
||||
(`refs #N` for non-closing work). The per-project repo slug and the
|
||||
list/show commands live in the project's CLAUDE.md project facts
|
||||
(see below) — the `boss` skill reads the forward queue from there,
|
||||
and the `spec-skeptic` `scope-fork` juror reads single issues with
|
||||
their comment threads from there.
|
||||
|
||||
## Pipeline
|
||||
|
||||
The phase set, the gates, and the conditional dispatch are **fixed**
|
||||
and documented once in `pipeline.md`. There is no per-project pipeline
|
||||
configuration. In particular: `brainstorm`, `specify`, `planner`,
|
||||
`implement`, `audit`, `debug`, `tdd`, `fieldtest`, and `docwriter` are
|
||||
always available. `tdd` is a standard entry path for test-specifiable
|
||||
work — not an opt-in. `audit` is mandatory at cycle close.
|
||||
`fieldtest` / `docwriter` are orchestrator-dispatched. The single
|
||||
behavioural toggle is spec auto-sign under `/boss`, declared (when a
|
||||
project wants it) in that project's CLAUDE.md project facts.
|
||||
|
||||
## Per-project facts (in each project's CLAUDE.md)
|
||||
|
||||
Under `## Skills plugin: project facts`, where applicable:
|
||||
|
||||
| Fact | Used by | Notes |
|
||||
|------|---------|-------|
|
||||
| **code roots** | architect, quality-reviewer, fieldtester | Directories reviewers walk. Required. |
|
||||
| **build / test command** | implement, audit | Required. Exit 0 = success. |
|
||||
| **lint command** | (quality) | Optional. |
|
||||
| **doc-build command** | docwriter | Optional; prints warnings on stderr. |
|
||||
| **regression scripts** | audit (bencher) | Optional list; non-zero exit = regress. |
|
||||
| **architect sweeps** | audit (architect) | Optional list; non-zero exit = drift suspicion. |
|
||||
| **spec-validation parsers** | specify, grounding-check | Optional; fence-label → `{ext, cmd}` table. `cmd` MUST contain `{file}`. Absent label → documented skip, never silent pass. |
|
||||
| **design ledger** | architect, most agents | Optional path (e.g. `design/INDEX.md`). |
|
||||
| **glossary** | every role | Optional path; implicitly standing reading. |
|
||||
| **design contracts / models** | docwriter, specify | Optional dirs. Aspirational-source frontmatter marker recommended (see below). |
|
||||
| **bench dir** | fieldtest, bencher | Optional path. |
|
||||
| **public interface** | fieldtester | Optional list — the only surface the fieldtester may read; everything else (code roots, bench) is forbidden to it. |
|
||||
| **fieldtest examples** | fieldtester | Optional path where fixtures are written. |
|
||||
| **by-role standing reading** | named agent | Optional; extra files/commands a specific role reads. |
|
||||
| **issue tracker** | boss, spec-skeptic | Repo slug + list command + show command (the latter MUST render an issue WITH its comments). |
|
||||
| **spec auto-sign** | boss, specify | Optional; `enabled` lets `/boss` sign a spec in the user's place through the auto-sign gate (default: human signature). |
|
||||
|
||||
### Aspirational-source marker (recommendation)
|
||||
|
||||
Files under a project's design-models / RFCs / proposals directory
|
||||
commonly carry aspirational code — constructs written before the
|
||||
surface that parses them exists. To let a later `specify` tell
|
||||
aspirational content from validated contract, give each such file a
|
||||
frontmatter marker:
|
||||
|
||||
```yaml
|
||||
---
|
||||
status: aspirational
|
||||
validated-against: <commit-sha | "no validation">
|
||||
---
|
||||
```
|
||||
|
||||
When the marker is absent the signal is simply absent — `specify`
|
||||
degrades to treating the content as unmarked, never hard-failing.
|
||||
Content lifted from an aspirational source is flagged and must clear
|
||||
the parse-every-block gate before it ships in a spec.
|
||||
+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
|
||||
|
||||
@@ -9,18 +9,17 @@ this convention.
|
||||
|
||||
## Where it lives
|
||||
|
||||
A project opts in by setting `paths.glossary` in its
|
||||
`.claude/dev-cycle-profile.yml` (see `profile-schema.md` § `paths`).
|
||||
When the slot is set, the file it names is standing reading for every
|
||||
role — no separate `standing_reading.always` entry is required. When
|
||||
the slot is unset, the whole feature is a documented no-op.
|
||||
A project opts in by naming a glossary path in its CLAUDE.md project
|
||||
facts (see `conventions.md`). When it is named, the file it points to
|
||||
is standing reading for every role — no separate standing-reading entry
|
||||
is required. When the project names none, the whole feature is a
|
||||
documented no-op.
|
||||
|
||||
A set glossary is the source of truth for the project's nomenclature.
|
||||
A glossary is the source of truth for the project's nomenclature.
|
||||
Where any other document names a concept differently — including the
|
||||
example renamings in `profile-schema.md` § `vocabulary` — the
|
||||
glossary's canonical entry, and its **Avoid** list, win. A
|
||||
`vocabulary.*` slot only sets which term the glossary then pins as
|
||||
canonical; it does not override the glossary.
|
||||
fixed vocabulary in `conventions.md` (cycle / iteration / milestone /
|
||||
contract) — the glossary's canonical entry, and its **Avoid** list,
|
||||
win.
|
||||
|
||||
## Format
|
||||
|
||||
|
||||
+9
-4
@@ -36,9 +36,12 @@ the structural binding.
|
||||
`docs/design/INDEX.md`, `crates/`, `bench/`).
|
||||
2. Strip project-specific commands (`cargo build`,
|
||||
`bench/check.py`).
|
||||
3. Replace literals with profile-slot references in prose.
|
||||
3. Replace literals with fixed conventions named directly (see
|
||||
`conventions.md`) or, where they vary per project, a reference to
|
||||
the project's `CLAUDE.md` project facts.
|
||||
4. Strip project vocabulary (`AILang`, `Form A`, `.ail.json`,
|
||||
`Boss`); use the profile's vocabulary slots.
|
||||
`Boss`); use the fixed vocabulary (cycle / iteration / milestone /
|
||||
contract).
|
||||
5. Strip project-specific contracts (honesty-rule,
|
||||
feature-acceptance). These belong in the project's own
|
||||
`CLAUDE.md`, not the plugin.
|
||||
@@ -51,8 +54,10 @@ the structural binding.
|
||||
1. Drop the `ailang-` prefix from the `name:` frontmatter
|
||||
field. The skill path is the disambiguator.
|
||||
2. Replace hardcoded standing-reading paths
|
||||
(`docs/design/INDEX.md`, etc.) with a reference to the profile's
|
||||
`standing_reading` section.
|
||||
(`docs/design/INDEX.md`, etc.) with the fixed standing reading
|
||||
(`CLAUDE.md` + `git log -10`) plus, for role-specific files, a
|
||||
reference to the per-role standing reading in the project's
|
||||
`CLAUDE.md` project facts.
|
||||
3. Replace project-specific Iron Law clauses with the universal
|
||||
discipline constants; project-specific clauses go to the
|
||||
project's own `CLAUDE.md`.
|
||||
|
||||
+21
-19
@@ -98,15 +98,16 @@ Hard-gate before plan — the spec-production core and the carrier of the
|
||||
"no plan without an approved spec" invariant. Takes a settled design
|
||||
(directly from sources, or a ratified design handed over by
|
||||
`brainstorm`), applies the feature-acceptance criterion, writes the
|
||||
spec to the configured `spec_dir`, runs the parse-every-block and
|
||||
spec to `docs/specs`, runs the parse-every-block and
|
||||
`grounding-check` gates, and takes user sign-off — with review but no
|
||||
interview. Bounces to `brainstorm` the moment the sources do not
|
||||
resolve a load-bearing design decision. A core node, not opt-in
|
||||
(unlike `tdd`).
|
||||
resolve a load-bearing design decision. A core node — the
|
||||
spec-production gate before `planner` on every design path.
|
||||
|
||||
The sign-off is the user's by default, including under `/boss`. The
|
||||
one exception is the opt-in `pipeline.boss.spec_auto_sign` slot: with
|
||||
it on, a `/boss` run may sign a spec in the user's place — but only
|
||||
one exception is spec auto-sign (a project that enables it in its
|
||||
CLAUDE.md project facts): with it on, a `/boss` run may sign a spec in
|
||||
the user's place — but only
|
||||
when every objective gate is green AND a unanimous five-lens
|
||||
`spec-skeptic` panel passes; the orchestrator's own confidence never
|
||||
signs. A `BLOCK` is never signed over: an editorial one (`criterion` /
|
||||
@@ -123,7 +124,7 @@ resolution instead of blocking on the stale body. See
|
||||
### planner
|
||||
|
||||
Hard-gate before implement. Produces a placeholder-free,
|
||||
bite-sized implementation plan in the configured `plan_dir`
|
||||
bite-sized implementation plan in `docs/plans`
|
||||
that the implement skill can execute task-by-task. Dispatches
|
||||
the plan-recon agent for read-only file-structure mapping.
|
||||
|
||||
@@ -150,7 +151,7 @@ the GREEN side to the implement skill in mini mode.
|
||||
|
||||
### tdd
|
||||
|
||||
Opt-in alternative to the `brainstorm → specify → planner` design entry,
|
||||
A standard alternative entry, alongside `brainstorm → specify → planner`,
|
||||
for work whose desired behaviour is test-specifiable — expressible
|
||||
as one failing test. RED-first: the `tdd-author` agent turns a
|
||||
description or issue into a single minimal, autonomous RED
|
||||
@@ -213,9 +214,9 @@ documents what the skill skips and under what conditions:
|
||||
- `implement` is the iteration body; not skippable.
|
||||
- `audit` is mandatory at cycle close.
|
||||
- `debug` is mandatory RED-first for any observable bug.
|
||||
- `tdd` is an opt-in alternative entry to `brainstorm` for
|
||||
- `tdd` is a standard alternative entry to `brainstorm` for
|
||||
test-specifiable work; it bounces back to `brainstorm` on a
|
||||
design fork. A profile that omits the `tdd` phase disables it.
|
||||
design fork. Always available — not opt-in.
|
||||
- `fieldtest` and `docwriter` are optional and orchestrator-
|
||||
dispatched.
|
||||
|
||||
@@ -225,14 +226,15 @@ commit body — never as undocumented practice.
|
||||
|
||||
## Pipeline configuration
|
||||
|
||||
The phase set, gating, and conditional dispatch are configured
|
||||
in the project profile under `pipeline:`. A project that does
|
||||
not want `fieldtest` simply omits the key. A project that wants
|
||||
a different gate set (e.g. `planner` without a `brainstorm`
|
||||
gate, for trivial bug-fix iterations) configures it there.
|
||||
There is none. The phase set, the gates, and the conditional
|
||||
dispatch shown above are fixed — the same for every project. All
|
||||
phases (`brainstorm`, `specify`, `planner`, `implement`, `audit`,
|
||||
`debug`, `tdd`, `fieldtest`, `docwriter`) are always available; which
|
||||
ones run on a given iteration is the orchestrator's judgement per the
|
||||
skip rules above, not a per-project setting. The only behavioural
|
||||
toggle is spec auto-sign under `/boss`, declared in a project's
|
||||
CLAUDE.md project facts. See `conventions.md`.
|
||||
|
||||
See `profile-schema.md` for the syntax.
|
||||
|
||||
If the profile sets `paths.glossary`, that file is standing reading
|
||||
for every role — the canonical-nomenclature source every skill and
|
||||
agent consults (see `glossary-convention.md`). Unset, it is a no-op.
|
||||
If a project declares a glossary in its CLAUDE.md project facts, that
|
||||
file is standing reading for every role — the canonical-nomenclature
|
||||
source every skill and agent consults (see `glossary-convention.md`).
|
||||
|
||||
@@ -1,290 +0,0 @@
|
||||
# Profile schema
|
||||
|
||||
Location: `<project-root>/.claude/dev-cycle-profile.yml`
|
||||
|
||||
Encoding: YAML. Each top-level key is a section. Keys are
|
||||
lowercase snake_case. Lists are YAML sequences.
|
||||
|
||||
## `paths`
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|---------------------|--------|------------------------|-------------|
|
||||
| `spec_dir` | string | `docs/specs` | Where the specify skill writes specs. |
|
||||
| `plan_dir` | string | `docs/plans` | Where the planner skill writes plans. |
|
||||
| `glossary` | string | (unset) | Canonical-nomenclature file (optional). If set, it is standing reading for every role — no separate `standing_reading.always` entry is needed; unset is a documented no-op. See `glossary-convention.md`. |
|
||||
| `design_ledger` | string | `docs/design/INDEX.md` | Canonical specification index (optional — projects without a design ledger can omit). |
|
||||
| `design_contracts` | string | `design/contracts` | Directory of prose-authoritative contracts (optional). |
|
||||
| `design_models` | string | `design/models` | Directory of onboarding whitepapers (optional). |
|
||||
| `code_roots` | list | `[src]` | Code directories the architect / quality reviewer walk. |
|
||||
| `bench_dir` | string | `bench` | Where regression harnesses live (optional). |
|
||||
| `public_interface` | list | `[README.md, docs]` | Directories and files the `fieldtester` may read — the project's outward-facing surface (READMEs, design ledger, examples, public API docs). Everything else (especially `code_roots` and `bench_dir`) is forbidden to the fieldtester. |
|
||||
| `fieldtest_examples`| string | `examples/fieldtest` | Where the `fieldtester` agent writes its fixtures. |
|
||||
|
||||
Omitted optional keys signal that the feature is unused in this
|
||||
project; skills that depend on them either short-circuit or
|
||||
skip the corresponding step.
|
||||
|
||||
### Aspirational-source marker (recommendation)
|
||||
|
||||
Files under `design_models` (or an equivalent `RFCs` /
|
||||
`proposals` directory) commonly carry aspirational code —
|
||||
constructs written before the surface that would parse them
|
||||
exists. To let a later specify tell aspirational content from
|
||||
validated contract, projects are encouraged (not required) to
|
||||
give each such file a frontmatter marker:
|
||||
|
||||
```yaml
|
||||
---
|
||||
status: aspirational
|
||||
validated-against: <commit-sha | "no validation">
|
||||
---
|
||||
```
|
||||
|
||||
`status: aspirational` says "the code here is a target, not a
|
||||
verified fact"; `validated-against` records the last commit at
|
||||
which someone actually ran the code through the live tool (or
|
||||
`"no validation"`). A design ledger (`design_ledger`) is likewise
|
||||
encouraged to distinguish "model" rows from "contract" rows so a
|
||||
reading agent can mechanically tell which carry verified
|
||||
behaviour.
|
||||
|
||||
When a file lacks the marker the signal is simply absent — the
|
||||
specify skill degrades to treating its content as unmarked, never
|
||||
hard-failing. The marker is consumed by the specify skill (see
|
||||
its Step 1 and Step 4): content lifted from an aspirational source
|
||||
is flagged and must clear the Step-4 parse-every-block gate before
|
||||
it ships in a spec.
|
||||
|
||||
## `naming`
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|--------------------|--------|----------------------------------|-------------|
|
||||
| `counter_dirs` | list | `[docs/specs, docs/plans, design/contracts, design/models]` | Directories that use the counter-prefix policy. |
|
||||
| `policy` | enum | `stable_per_directory_4digit` | One of `stable_per_directory_4digit`, `date_prefix`, `flat`. |
|
||||
| `slug_separator` | string | `-` | Separator inside the slug. |
|
||||
|
||||
`stable_per_directory_4digit` means each listed directory has a
|
||||
per-directory counter, 4-digit zero-padded, assigned in
|
||||
creation order, stable for the life of the file. New files
|
||||
take the next-higher number; deleted files retire their number.
|
||||
|
||||
`date_prefix` uses `YYYY-MM-DD-slug.md`.
|
||||
|
||||
`flat` uses `slug.md`.
|
||||
|
||||
## `commands`
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|----------------|--------|----------------|-------------|
|
||||
| `build` | string | (required) | Build command — exit 0 means success. |
|
||||
| `test` | string | (required) | Test command — exit 0 means success. |
|
||||
| `lint` | string | (optional) | Lint command — exit 0 means success. |
|
||||
| `doc_build` | string | (optional) | Documentation-build command used by the `docwriter` skill. Should print warnings on stderr so the agent can enumerate them (e.g. `cargo doc --no-deps 2>&1`). Omit if the project has no API docs. |
|
||||
| `regression` | list | `[]` | Regression scripts run by the audit skill. Each entry is a shell command; non-zero exit is a regress. |
|
||||
| `architect_sweeps` | list | `[]` | Project-specific architect sweep commands run by the `architect` agent in addition to its universal checks. Each entry is a shell command; non-zero exit means at least one sweep matched and the matches are drift-suspicions to verify. Optional. |
|
||||
|
||||
## `spec_validation`
|
||||
|
||||
Optional. A registry mapping each markdown fence label to the tool
|
||||
that validates a spec code block of that kind. The specify
|
||||
parse-gate and the grounding-check code-block pass run these
|
||||
parsers so that spec code blocks are treated as hypotheses to
|
||||
verify, not as authoritative truth.
|
||||
|
||||
```yaml
|
||||
spec_validation:
|
||||
parsers:
|
||||
ail:
|
||||
ext: ".ail"
|
||||
cmd: "ail parse {file}"
|
||||
ail-json:
|
||||
ext: ".ail.json"
|
||||
cmd: "ail check {file}"
|
||||
ll:
|
||||
ext: ".ll"
|
||||
cmd: "llvm-as {file} -o /dev/null"
|
||||
```
|
||||
|
||||
The key of each `parsers` entry is the fence info-string of a spec
|
||||
code block (the token immediately after the opening ` ``` `). Only
|
||||
blocks whose label has an entry are validated; a block whose label
|
||||
is absent from the map is skipped and the skip is documented ("no
|
||||
parser for fence label X") — never a silent pass.
|
||||
|
||||
| Key | Type | Description |
|
||||
|-------|--------|-------------|
|
||||
| `ext` | string | Extension (including the leading dot) the harness gives the temp file it writes the block into, so tools that key off extension — `.ail` vs `.ail.json` — see the right one. |
|
||||
| `cmd` | string | Validation command. MUST contain the `{file}` placeholder, which is substituted with the temp file's path. Exit 0 means a clean parse; any non-zero exit is a parse failure the consuming skill turns into a BLOCK. |
|
||||
|
||||
A malformed entry — `cmd` missing the `{file}` placeholder, or
|
||||
either `ext` or `cmd` absent — is a profile error the consuming
|
||||
skill surfaces, not a silent skip; the gate fails closed.
|
||||
|
||||
Omitting the whole `spec_validation` section disables the
|
||||
block-validation gates: the consuming skills short-circuit, exactly
|
||||
as with other omitted optional features.
|
||||
|
||||
## `vocabulary`
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|----------------|--------|----------------|-------------|
|
||||
| `cycle` | string | `cycle` | One round in the pipeline graph (NOT the top-level container). Examples: `cycle`, `release`, `epic`. |
|
||||
| `subcycle` | string | `iteration` | A sub-unit of a cycle. Examples: `iteration`, `sprint`, `story`. |
|
||||
| `milestone` | string | `milestone` | Tracker container spanning many cycles; closes only when complete AND functional (see `pipeline.md` § Milestone-close gate). Examples: `milestone`, `epic`, `release`. |
|
||||
| `ledger_entry` | string | `contract` | What a single design-ledger entry is called. Examples: `contract`, `RFC`, `ADR`. |
|
||||
|
||||
Skills use these names in their generated artefacts and prose.
|
||||
Picking accurate vocabulary keeps prose readable; the underlying
|
||||
mechanics are identical regardless of name.
|
||||
|
||||
The renamings shown as examples above illustrate the slot only; they
|
||||
are not nomenclature for any particular project. When a project sets
|
||||
`paths.glossary`, that glossary is the source of truth for its
|
||||
nomenclature and overrides these examples where they collide — a word
|
||||
offered here may sit under **Avoid** in a given project's glossary
|
||||
(see `glossary-convention.md`).
|
||||
|
||||
## `standing_reading`
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|----------------|--------|----------------|-------------|
|
||||
| `always` | list | `[CLAUDE.md]` | Files every agent reads at start of every dispatch. |
|
||||
| `by_role` | map | `{}` | Map from role name to list of additional files. |
|
||||
|
||||
Role names match agent slugs: `architect`, `bencher`, `debugger`,
|
||||
`implementer`, `tester`, `fieldtester`, `docwriter`,
|
||||
`grounding-check`, `plan-recon`, `spec-reviewer`, `quality-reviewer`.
|
||||
|
||||
Entries may be shell commands as well as file paths — they are
|
||||
read as opaque strings the agent should fetch / execute, e.g.
|
||||
`"git log -10 --format=full"`.
|
||||
|
||||
A set `paths.glossary` is implicitly appended to every role's
|
||||
`always` list — it does not need its own entry here. The slot's
|
||||
authoritative semantics live at the `paths` row above.
|
||||
|
||||
## `git`
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|------------------------------|------|---------|-------------|
|
||||
| `main_sacrosanct` | bool | `true` | If true, no actor may reset or revert main. |
|
||||
| `only_orchestrator_commits` | bool | `true` | If true, no agent commits; the orchestrator commits. |
|
||||
| `issue_tracker.kind` | enum | `none` | One of `gitea`, `github`, `linear`, `none`. |
|
||||
| `issue_tracker.close_marker` | string | `"closes #N"` | Marker the orchestrator includes in commit bodies to auto-close issues. |
|
||||
| `issue_tracker.url` | string | (empty) | Human-browsable URL of the issue list — surfaced in notifications and cross-references. |
|
||||
| `issue_tracker.list_cmd` | string | (empty) | Shell command that lists open issues. Used by the `boss` skill to read the forward queue. Examples: `tea issues ls --repo X/Y --state open`, `gh issue list --repo X/Y --state open`. |
|
||||
| `issue_tracker.show_cmd` | string | (empty) | Shell command that renders **one** issue **with its comment thread**; the orchestrator and the `spec-skeptic` `scope-fork` juror append the issue index as the final argument (e.g. `tea issues --comments` → `tea issues --comments 55`). MUST include comments — a `specify` reconciliation comment (see `specify/SKILL.md` Step 1.5) is invisible to the juror otherwise. Examples: `tea issues --comments`, `gh issue view --comments`. If empty, the juror reads only the issue body and a fork resolved in-context but not echoed into the body cannot be ratified — auto-sign falls back to the human sign-off. |
|
||||
| `protected_branches` | list | `[main]` | Branches that are sacrosanct in the same sense as main. |
|
||||
|
||||
## `notifications`
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----------|--------|---------|-------------|
|
||||
| `command` | string | (empty) | Shell command the `boss` skill invokes on done-state and bounce-back. Receives the message text as a single argument. Example: `"~/.claude/notify.sh"`. If empty, the orchestrator falls back to printing the notification in chat. |
|
||||
|
||||
## `pipeline`
|
||||
|
||||
Per-phase configuration. Each phase has its own sub-map.
|
||||
|
||||
```yaml
|
||||
pipeline:
|
||||
brainstorm: {} # optional discovery front-end; no hard gate of its own
|
||||
specify:
|
||||
gates: [planner] # core node — planner cannot start until the spec is approved
|
||||
planner:
|
||||
gates: [implement]
|
||||
implement: {} # standard
|
||||
audit:
|
||||
mandatory_at: cycle_close # auto-fires at end of each cycle
|
||||
fieldtest:
|
||||
boss_only: true # only orchestrator dispatches
|
||||
when: surface_touch # condition tag (orchestrator judgement)
|
||||
milestone_fieldtest:
|
||||
boss_only: true
|
||||
when: surface_touch # end-to-end proof of the milestone's promise
|
||||
gates_close: milestone # its green roll-up is the functional leg of the milestone-close gate
|
||||
docwriter:
|
||||
boss_only: true
|
||||
when: api_stable_across_n_cycles
|
||||
debug:
|
||||
trigger: bug # observable misbehaviour
|
||||
red_first: true # RED test before any fix
|
||||
# specify above is a CORE node (always present); tdd below is opt-in.
|
||||
tdd: # opt-in: omit the key to disable the entry path
|
||||
trigger: test_specifiable_feature # behaviour expressible as one failing test
|
||||
red_first: true # RED executable-spec before any implementation
|
||||
alt_to: brainstorm # alternative design entry; bounces back on a design fork
|
||||
boss:
|
||||
user_invoked: true # autonomous-orchestrator mode, /boss
|
||||
spec_auto_sign: false # opt-in: let /boss sign a spec in the user's place (default off)
|
||||
```
|
||||
|
||||
Phases not listed are disabled for the project. A project that
|
||||
does not want a `fieldtest` phase simply omits the key. `tdd` is
|
||||
opt-in the same way.
|
||||
|
||||
`boss.spec_auto_sign` is an opt-in slot, default off (a missing key
|
||||
reads as `false`). With it off — the conservative default — a
|
||||
`specify` dispatch in a `/boss` session always pauses at its Step-6
|
||||
user-review gate for the user's signature, exactly as before. With it
|
||||
**on**, the orchestrator may sign a spec in the user's place, but only
|
||||
through `specify`'s auto-sign gate: every objective gate green
|
||||
(precondition, parse, a `grounding-check` `PASS` with no human
|
||||
override) AND a unanimous five-lens `spec-skeptic` panel. A `BLOCK` is
|
||||
never signed over: an *editorial* one (`criterion` / `ambiguity` /
|
||||
`plan-readiness`) the orchestrator repairs in a bounded loop (≤ 2
|
||||
rounds, re-running the objective gates and re-dispatching all five
|
||||
lenses each round), while a *design* one (`scope-fork` / `grounding`),
|
||||
an `INFRA_ERROR`, any objective gate not green, or an exhausted budget
|
||||
falls back to the human sign-off pause. Model self-confidence alone
|
||||
never signs — the gate is built specifically not to rely on it. On a
|
||||
clean sign the
|
||||
orchestrator commits the spec (subject carries `(boss-signed)`), sends
|
||||
the mandatory informational-with-veto notify, and continues to
|
||||
`planner` without stopping. See `../specify/SKILL.md` Step 6 (gate
|
||||
owner), `../specify/agents/spec-skeptic.md` (the juror), and
|
||||
`../boss/SKILL.md` §"Spec auto-sign" (notify + veto contract). `specify`, by contrast, is a **core** node — it
|
||||
is the spec-production gate before `planner` on every design path,
|
||||
reachable directly from settled sources or via the optional
|
||||
`brainstorm` discovery stage. `tdd` opt-in only adds the
|
||||
test-specifiable bypass; with `tdd` omitted, the design entry paths
|
||||
are `brainstorm → specify → planner` and `specify → planner`.
|
||||
|
||||
## Example: minimal profile
|
||||
|
||||
```yaml
|
||||
paths:
|
||||
spec_dir: docs/specs
|
||||
plan_dir: docs/plans
|
||||
code_roots: [src]
|
||||
|
||||
commands:
|
||||
build: cargo build
|
||||
test: cargo test
|
||||
|
||||
vocabulary:
|
||||
cycle: cycle
|
||||
subcycle: iteration
|
||||
|
||||
standing_reading:
|
||||
always:
|
||||
- CLAUDE.md
|
||||
- "git log -10 --format=full"
|
||||
|
||||
git:
|
||||
issue_tracker:
|
||||
kind: github
|
||||
close_marker: "closes #N"
|
||||
|
||||
pipeline:
|
||||
brainstorm: {} # optional discovery; no hard gate
|
||||
specify: { gates: [planner] }
|
||||
planner: { gates: [implement] }
|
||||
implement: {}
|
||||
audit: { mandatory_at: cycle_close }
|
||||
debug: { trigger: bug, red_first: true }
|
||||
```
|
||||
|
||||
This minimal profile enables five phases, no fieldtest, no
|
||||
docwriter, no design-ledger. Good starting point for a small
|
||||
project.
|
||||
Reference in New Issue
Block a user