@printpractical/cruze 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +7 -6
  2. package/dist/app/use_cases/new_work_item.js +1 -1
  3. package/dist/app/use_cases/run_review.js +1 -1
  4. package/dist/domain/journal.js +8 -3
  5. package/dist/domain/status/next_step.js +2 -2
  6. package/dist/domain/validation/element_rules.js +1 -1
  7. package/package.json +1 -1
  8. package/skills/architect/SKILL.md +2 -2
  9. package/skills/architect/feature.md +2 -0
  10. package/skills/architect/project.md +1 -1
  11. package/skills/architect/walkthrough.md +22 -19
  12. package/skills/build/SKILL.md +6 -5
  13. package/skills/formats/reference/architecture.md +1 -1
  14. package/skills/formats/reference/config.md +1 -1
  15. package/skills/formats/templates/architecture.md +2 -2
  16. package/skills/formats/templates/change.md +1 -1
  17. package/skills/formats/templates/feature.md +1 -1
  18. package/skills/formats/templates/standalone-change.md +1 -1
  19. package/skills/hexagonal-design/SKILL.md +9 -3
  20. package/skills/hexagonal-design/languages/rust.md +1 -1
  21. package/skills/hexagonal-design/languages/swift.md +46 -0
  22. package/skills/hexagonal-design/shapes.md +49 -0
  23. package/skills/improve/SKILL.md +51 -0
  24. package/skills/land/SKILL.md +1 -1
  25. package/skills/next/SKILL.md +1 -1
  26. package/skills/plan/SKILL.md +1 -1
  27. package/skills/plan/tasks.md +2 -1
  28. package/skills/realign/notes/0.0.6.md +44 -0
  29. package/skills/realign/notes/0.0.7.md +11 -0
  30. package/skills/realign/notes.md +2 -0
  31. package/skills/research/SKILL.md +7 -1
  32. package/skills/rethink/SKILL.md +1 -1
  33. package/skills/rethink/levels.md +1 -1
  34. package/skills/roles/SKILL.md +8 -5
  35. package/skills/roles/design-reviewer.md +6 -3
  36. package/skills/roles/surveyor.md +40 -0
  37. package/skills/roles/verifier.md +3 -2
  38. package/skills/verify/SKILL.md +10 -6
  39. package/src/app/use_cases/new_work_item.ts +1 -1
  40. package/src/app/use_cases/run_review.ts +1 -1
  41. package/src/domain/journal.ts +8 -3
  42. package/src/domain/status/next_step.ts +2 -2
  43. package/src/domain/validation/element_rules.ts +1 -1
package/README.md CHANGED
@@ -10,7 +10,7 @@ It works with any agent that supports the [Agent Skills](https://agentskills.io)
10
10
 
11
11
  ## Status
12
12
 
13
- Version 0.0.5 is the fifth preview. It cuts the ceremony per change: reviews bring you only the findings that are yours to decide, plans are approved once their review closes, a rethink re-stamps the work it didn't change, and changes are sized to be worth their review and verify. Early development. The CLI is complete for the V1 lifecycle. The document formats ship as the `cruze-formats` skill, the standards an agent designs and codes to ship as knowledge skills, and the whole workflow, from explore to land, ships as workflow skills. Claude Code is the agent tested so far.
13
+ Version 0.0.7 is the seventh preview. It fits the structure to the kind of system: layers are roles rather than folders, a context starts as one core module with its adapters, architect starts from the layout that is normal for a library, a daemon, an app or a CLI, and the new `improve` skill restructures existing code to those standards when you choose. Early development. The CLI is complete for the V1 lifecycle. The document formats ship as the `cruze-formats` skill, the standards an agent designs and codes to ship as knowledge skills, and the whole workflow, from explore to land, ships as workflow skills. Claude Code is the agent tested so far.
14
14
 
15
15
  ## Why
16
16
 
@@ -35,7 +35,7 @@ The skills run `cruze` commands, so the agent needs `cruze` on its path. Install
35
35
  From a GitHub Release, without npm. Each release attaches the packed package:
36
36
 
37
37
  ```sh
38
- npm install -g https://github.com/PrintPractical/cruze/releases/download/v0.0.5/printpractical-cruze-0.0.5.tgz
38
+ npm install -g https://github.com/PrintPractical/cruze/releases/download/v0.0.7/printpractical-cruze-0.0.7.tgz
39
39
  ```
40
40
 
41
41
  From npm, once a version is published there:
@@ -47,7 +47,7 @@ npm install -g @printpractical/cruze
47
47
  From the git repository, at a tag or `#main`. This needs git and access to the repository. npm 11 needs `--install-links` for a global git install, and the first `cruze` command builds the CLI, which takes a moment:
48
48
 
49
49
  ```sh
50
- npm install -g --install-links github:PrintPractical/cruze#v0.0.5
50
+ npm install -g --install-links github:PrintPractical/cruze#v0.0.7
51
51
  ```
52
52
 
53
53
  ### 2. Set up a repository
@@ -61,7 +61,7 @@ cruze init
61
61
  When you didn't install from npm, tell `init` where Cruze came from, so the CI it writes runs the same source instead of the npm package:
62
62
 
63
63
  ```sh
64
- cruze init --package https://github.com/PrintPractical/cruze/releases/download/v0.0.5/printpractical-cruze-0.0.5.tgz
64
+ cruze init --package https://github.com/PrintPractical/cruze/releases/download/v0.0.7/printpractical-cruze-0.0.7.tgz
65
65
  ```
66
66
 
67
67
  `init` asks for the project name, and which coding agent you use: `claude` for Claude Code, or `other` for any agent that reads `AGENTS.md` and `.agents/skills/`, such as Codex or OpenCode. It doesn't ask when you pass `--agent claude` or `--agent other`, or when the repository already has `CLAUDE.md` or `.claude/`. With `--yes`, or without a terminal, it sets up Claude Code. Then it creates:
@@ -156,10 +156,11 @@ Stepping back is editing: change an upstream document and every approval that ci
156
156
  | `cruze-triage` | Reproduces a bug, finds its root cause against the living docs, and fixes it test-first or routes it to architect or rethink |
157
157
  | `cruze-rethink` | Steps back to the level a discovery touches, keeps completed work, re-approves what went stale and records why |
158
158
  | `cruze-realign` | Brings existing code up to what a new Cruze expects: audits it against each release's notes, decides every finding with you, and schedules the fixes as prefactor changes |
159
+ | `cruze-improve` | Restructures existing code to meet today's standards: surveys it for structure that departs from them or keeps causing friction, lets you pick any or all of the candidates, and schedules the moves as prefactor changes |
159
160
  | `cruze-next` | Says which step to run next and why |
160
- | `cruze-roles` | The fresh-context design reviewer, code reviewer, verifier, researcher and auditor, and how a review runs to a disposition for every finding |
161
+ | `cruze-roles` | The fresh-context design reviewer, code reviewer, verifier, researcher, auditor and surveyor, and how a review runs to a disposition for every finding |
161
162
  | `cruze-formats` | The format of every Cruze document, with templates |
162
- | `cruze-hexagonal-design` | Ports and adapters with domain-driven design: who owns each rule, dependency direction, many small modules, contracts, runtime ownership, and notes for Rust and C++ |
163
+ | `cruze-hexagonal-design` | Ports and adapters with domain-driven design: who owns each rule, dependency direction, many small modules, contracts, runtime ownership, layouts by kind of system, and notes for Rust, Swift and C++ |
163
164
  | `cruze-behavioural-testing` | Which tests to write and at which seam, fakes instead of mocks, and protecting approved scenarios' tests |
164
165
  | `cruze-grilling` | Interviewing the user in rounds until decisions settle, and challenging once before deferring |
165
166
  | `cruze-domain-language` | Building the glossary and using its words in documents, IDs and code |
@@ -28,7 +28,7 @@ import { appendJournal, loadView, } from "../project_context.js
28
28
  export async function createWorkItem(deps , request ) {
29
29
  const view = await loadView(deps.files);
30
30
  const date = deps.clock.today();
31
- const values = { id: "", title: request.title, date, project_name: "" };
31
+ const values = { id: "", title: request.title, title_quoted: JSON.stringify(request.title), date, project_name: "" };
32
32
  if (request.title.trim() === "") throw new CruzeError("missing-title", "a title is required");
33
33
 
34
34
  if (request.kind === "adr") {
@@ -4,7 +4,7 @@ import { featureOf } from "../../domain/project/work_items.js";
4
4
 
5
5
  import { loadView, } from "../project_context.js";
6
6
 
7
- export const ROLES = ["design-reviewer", "code-reviewer", "verifier", "researcher", "auditor"] ;
7
+ export const ROLES = ["design-reviewer", "code-reviewer", "verifier", "researcher", "auditor", "surveyor"] ;
8
8
 
9
9
 
10
10
 
@@ -15,25 +15,27 @@ export const RECORDED_EVENTS = {
15
15
  override: ["gate", "reason"],
16
16
  bug: ["summary", "cause"],
17
17
  verification: ["result", "summary"],
18
+ checks: ["commit"],
18
19
  };
19
20
 
20
21
  /** Fields an event may carry beyond its required ones, checked when present. A defect rethink must say which step missed it. */
21
22
  const OPTIONAL_FIELDS = {
22
23
  rethink: ["missed_by"],
23
- review: ["nits"],
24
+ review: ["nits", "checked_by"],
24
25
  disposition: ["decided"],
25
26
  };
26
27
 
27
28
  /** The workflow steps and checks that find or miss a problem, so a retro can count them. */
28
- export const STEPS = ["envision", "architect", "research", "design-review", "walkthrough", "plan", "plan-review", "build", "code-review", "verify", "land", "realign", "validate", "check", "user"];
29
+ export const STEPS = ["envision", "architect", "research", "design-review", "walkthrough", "plan", "plan-review", "build", "code-review", "verify", "land", "realign", "improve", "validate", "check", "user"];
29
30
 
30
31
  export const FIELD_VALUES = {
31
32
  level: ["task", "change", "feature", "architecture", "vision"],
32
33
  kind: ["defect", "discovery"],
33
34
  disposition: ["fixed", "waived", "deferred", "rejected"],
34
35
  decided: ["agent", "user"],
35
- review: ["design", "plan", "code", "realign"],
36
+ review: ["design", "plan", "code", "realign", "improve"],
36
37
  result: ["accepted", "sent-back"],
38
+ checked_by: ["agent", "reviewer"],
37
39
  found_by: STEPS,
38
40
  missed_by: STEPS,
39
41
  };
@@ -79,6 +81,9 @@ export function recordedEventProblems(event , fields
79
81
  if (allowed !== undefined && !allowed.includes(value)) problems.push(`${field} must be one of ${allowed.join(", ")}`);
80
82
  if (COUNT_FIELDS.includes(field) && !/^\d+$/.test(value)) problems.push(`${field} must be a whole number`);
81
83
  }
84
+ if (event === "checks" && fields["commit"] !== undefined && !/^[0-9a-f]{7,40}$/.test(fields["commit"])) {
85
+ problems.push("commit must be a commit hash, such as the output of git rev-parse --short HEAD");
86
+ }
82
87
  if (event === "disposition" && fields["decided"] === "agent" && fields["disposition"] !== "fixed") {
83
88
  problems.push("the agent decides only fixes; the user waives, defers or rejects a finding (decided=user)");
84
89
  }
@@ -66,7 +66,7 @@ function projectStep(view ) {
66
66
  {
67
67
  path: PATHS.architecture,
68
68
  missing: { step: "architect", reason: "the project has no architecture yet" },
69
- unapproved: { step: "architect", reason: "finish the architecture, walk through it and approve it" },
69
+ unapproved: { step: "architect", reason: "finish the architecture, review it and approve it" },
70
70
  changed: { step: "rethink", target: "architecture", reason: "the architecture changed since its approval" },
71
71
  },
72
72
  {
@@ -89,7 +89,7 @@ function itemSteps(view , item , branch )
89
89
  if (item.kind === "standalone") return [changeStep(view, item, branch)];
90
90
  const state = evaluateApproval(view, item.path);
91
91
  if (readChangesTable(item.doc).length === 0) return [{ step: "architect", target: item.ref, reason: "the feature has no design or changes yet" }];
92
- if (state.state === "unapproved") return [{ step: "architect", target: item.ref, reason: "review the feature's design, walk through it and approve it" }];
92
+ if (state.state === "unapproved") return [{ step: "architect", target: item.ref, reason: "review the feature's design and approve it" }];
93
93
  if (state.state !== "approved") return [{ step: "rethink", target: item.ref, reason: `the feature changed since its approval${state.changed.length > 0 ? ` (${state.changed.join(", ")})` : ""}` }];
94
94
  const changes = changesOf(view.items, item);
95
95
  const landed = new Set(changes.filter((c) => readProgress(c.doc).landed !== undefined).map((c) => c.folderName));
@@ -18,7 +18,7 @@ const REQUIRED_FACTS = {
18
18
  const ALLOWED_VALUES = {
19
19
  Kind: { kinds: ["ENT"], values: ["aggregate", "entity", "value", "service", "policy", "event"] },
20
20
  Direction: { kinds: ["PORT"], values: ["driven", "driving"] },
21
- Layer: { kinds: ["MOD"], values: ["domain", "application", "adapter", "composition"] },
21
+ Layer: { kinds: ["MOD"], values: ["core", "domain", "application", "adapter", "composition"] },
22
22
  };
23
23
 
24
24
  export function elementProblems(path , doc , element ) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@printpractical/cruze",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Spec-driven development for coding agents: one living model of the system, small deltas, convergent review.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Chris Buchter",
@@ -5,7 +5,7 @@ description: Decides how to build and how big, at project scope (domain model, c
5
5
 
6
6
  # Architect
7
7
 
8
- Architect decides the how and the how big. It designs the domain, the ports and adapters, and where every element lives in the source tree, before any code exists. It ends with the one heavy human gate, the design walkthrough, where the user sees the entities, their interactions, the ports and the files, and approves the design.
8
+ Architect decides the how and the how big. It designs the domain, the ports and adapters, and where every element lives in the source tree, before any code exists. It ends with the one heavy human gate, the design walkthrough: a short overview in plain terms, after which the user reads the design documents in full and approves or comments.
9
9
 
10
10
  ## Steps
11
11
 
@@ -25,7 +25,7 @@ Architect decides the how and the how big. It designs the domain, the ports and
25
25
  - `.agents/skills/cruze-formats/reference/architecture.md`
26
26
  5. **Design.** Follow the scope's procedure: [project.md](project.md), [feature.md](feature.md) or [tweak.md](tweak.md). Tweak scope ends there and hands off to `plan`.
27
27
  6. **Review the design.** Run the design review in `.agents/skills/cruze-roles/SKILL.md`, with the design reviewer role. Done when every finding has a journaled disposition and no blocker is open without the user's decision.
28
- 7. **Walk the user through it.** Follow [walkthrough.md](walkthrough.md). Apply what the user changes, run `cruze validate` again, and repeat the parts of the walkthrough those changes affect.
28
+ 7. **Hand the design to the user.** Follow [walkthrough.md](walkthrough.md): one overview message, then the documents to read in full. Apply what the user changes, run `cruze validate` again, and say what changed.
29
29
  8. **Record the approval.** Only after the user says they approve, run the scope's `cruze approve` command and quote its result, then commit. At project scope, the roadmap follows as its own approval, described in [project.md](project.md).
30
30
 
31
31
  ## Rules
@@ -33,4 +33,6 @@ The result is a `feature.md` with a complete architecture delta and an ordered l
33
33
 
34
34
  The thresholds are the defaults under `changes:` in `.cruze/config.yaml`; a project can tune them.
35
35
 
36
+ Done when `cruze validate` reports no `change-too-small`, `change-too-large` or `feature-size` warning, or the user has accepted one and a `D<n>` line under the feature's `## Decisions` records why. After approval, only a rethink can split a change.
37
+
36
38
  Then continue with the review and walkthrough steps of the skill. When the user approves, run `cruze approve <feature>` and quote its result. The command takes the feature's full ID, such as `2026-09-25-open-console`, or its slug when no other active item shares it.
@@ -16,7 +16,7 @@ The result has four parts, reviewed together and shown at one walkthrough:
16
16
  5. **Ports (`PORT`).** Define every capability the use cases need from outside, named by capability. Write each operation's contract, following `.agents/skills/cruze-hexagonal-design/contracts.md`. Add driving ports only where the hexagonal-design skill calls for them.
17
17
  6. **Adapters (`ADP`).** Name the technology behind each driven port and each inbound adapter that drives use cases. Run the researcher role on every adapter's technology first, and record the result in the adapter's `Adopts` fact. Take every new dependency to the user.
18
18
  7. **Flows (`FLOW`).** Write a `sequenceDiagram` for each of the 2 to 5 most important interactions, including their failure paths. Leave out `Serves` until scenarios exist.
19
- 8. **Modules (`MOD`).** Give each context its hexagonal modules, and give the shared CLI shell and the composition root the `system` scope. Add a `system` module in the `composition` layer for the build and CI files, such as the package manifest and `.github/workflows/`, so the tasks that write them have an owner. Every source file must fall inside some module's `Path`, including namespace files that join a context's modules, such as `src/inventory/mod.rs` or `index.ts`; list them in a `composition` module's `Path` when no other module fits. Every module gets a `Path` and a `Layer`, and every element above gets its `Module` and `File`.
19
+ 8. **Modules (`MOD`).** Name the kind of system in the Overview, and choose the layout that is normal for that kind and the language, following `.agents/skills/cruze-hexagonal-design/shapes.md` and the language file. Give each context the fewest modules that keep its layer rules, usually one `core` module and its adapters, and give the shared CLI shell and the composition root the `system` scope. Add a `system` module in the `composition` layer for the build and CI files, such as the package manifest and `.github/workflows/`, so the tasks that write them have an owner. Every source file must fall inside some module's `Path`, including namespace files that join a context's modules, such as `src/inventory/mod.rs` or `index.ts`; list them in a `composition` module's `Path` when no other module fits. Every module gets a `Path` and a `Layer`, and every element above gets its `Module` and `File`.
20
20
  9. **Dependency rules (`RULE`).** State what may import what, in one or two sentences each.
21
21
  10. **Cross-cutting concerns (`XC`).** Cover errors, configuration, logging, concurrency and security, plus build and delivery (CI, formatting, linting). Read `.agents/skills/cruze-hexagonal-design/runtime.md` for concurrency.
22
22
  11. **Decisions.** Write an ADR, with `cruze new adr <slug> --title "<title>"`, for each decision that passes the ADR test. Record the other project decisions as `D<n>` lines under `## Decisions`.
@@ -1,29 +1,32 @@
1
1
  # The design walkthrough
2
2
 
3
- The walkthrough is where the user comes to understand the design well enough to explain it without you. It is the one heavy gate before code. Show the design as it stands in the files, one part at a time, in the order below. Pause after each part for questions.
3
+ The walkthrough hands the design to the user in one message: a short overview in plain terms, then the documents to review in full. The documents are the design, and the user reads them faster than you can retell them, so present the whole design at once and wait for one answer: approval, or comments.
4
4
 
5
- At feature scope, show only what the feature adds, changes or removes, next to the current elements it touches. At project scope, show the whole architecture.
5
+ At feature scope, cover only what the feature adds, changes or removes. At project scope, cover the whole architecture, the layer rules, the roadmap and the walking skeleton.
6
6
 
7
- ## Order
7
+ ## The overview
8
8
 
9
- 1. **What it does.** The intent in two sentences, then each requirement with its scenarios' titles.
10
- 2. **Where it sits.** The `VIEW-context` diagram, or at feature scope, the contexts the feature touches.
11
- 3. **The domain.** The domain-model class diagram, then each new or changed entity: its invariants, its states and who owns it.
12
- 4. **How it runs.** For each key flow, show its `sequenceDiagram` and walk one scenario through it step by step, including one failure path. This is the part the user must be able to retell.
13
- 5. **The seams.** Each new or changed port with its operations and their contracts, then the adapter behind each one and the library it adopts.
14
- 6. **Dependencies.** Every new dependency, named out loud with its purpose and the approval behind it. Also the components you chose to build yourself, with the reason.
15
- 7. **Where the code goes.** Each new element next to its module, file path and layer, and the layer rules those files must obey. At project scope, also the `layers:` in `.cruze/config.yaml`.
16
- 8. **The slices.** The changes in order, with what each delivers and builds, and why the first is first. At project scope, the roadmap's phases and the walking skeleton instead.
17
- 9. **Decisions and review.** The settled decisions and ADRs, each review finding with its disposition, and the points where a fresh implementer could still build something different.
9
+ Write it in the glossary's terms, as what callers can do and what happens when they do, not as a list of elements. Keep it to what the user can read in a minute.
18
10
 
19
- ## Showing diagrams
11
+ 1. **What it does.** The intent in two sentences. Then one line per use case, or at feature scope per requirement: who asks for what, what they get, and the main way it fails.
12
+ 2. **What it touches.** Each new external system, and each new dependency named with its purpose and the approval behind it. Also each component you chose to build yourself, with the reason.
13
+ 3. **The slices.** The changes in order, one line each, saying what each delivers and why the first is first. At project scope, the roadmap's phases and the walking skeleton instead.
14
+ 4. **What is yours to decide.** The review findings the roles skill brings to the user, any `cruze validate` warning still standing, such as a change over its size limit, any point where a fresh implementer could still build something different, and any rule you challenged that the user overrode.
20
15
 
21
- Mermaid diagrams live in the documents, so point to the file and line of each one, and paste its source into the conversation. When the user can render Mermaid (an editor preview, or GitHub), say where to open it. Keep each diagram under 15 nodes; split a bigger picture instead of shrinking it.
16
+ ## The documents
17
+
18
+ List each file the user should read in full, with the sections that changed:
19
+
20
+ - Feature scope: the feature's `feature.md`, and the ADRs it adds.
21
+ - Project scope: `docs/architecture.md`, the `layers:` in `.cruze/config.yaml`, `docs/roadmap.md`, the walking-skeleton `change.md`, and the ADRs in `docs/adr/`.
22
+
23
+ The diagrams are Mermaid inside those files. Say where the user can render them, such as an editor preview or GitHub, rather than pasting them.
24
+
25
+ End the message with: "Read these in full, then tell me what to change, or approve. Do you approve this design?"
22
26
 
23
27
  ## Ending
24
28
 
25
- 1. Ask the user to explain one flow back in their own words, or to name what they would still find surprising in the code. Treat their answer as the check that the walkthrough worked, and go back over any part they can't retell.
26
- 2. Ask for approval in these words: "Do you approve this design?"
27
- 3. A request for changes is not an approval. Apply the changes and run `cruze validate`. When they touch placement, dependency direction, adopt-or-build decisions, port contracts or flows, run a new design review on the diff alone. Then walk through only the parts that changed, and ask again.
28
- 4. When the user rejects the design outright, don't approve anything. Ask what is wrong. When the problem is what to build, go back to `envision`; when it is the whole approach, restart this step's design; when the user wants to stop, leave the work unapproved and say how to resume.
29
- 5. Done when the user says they approve.
29
+ 1. Answer a question from the documents, pointing to the file and section, and answer only what was asked.
30
+ 2. A request for changes is not an approval. Apply the changes and run `cruze validate`. When the user edited the documents themselves, read their diff and run `cruze validate` on it. When the changes touch placement, dependency direction, adopt-or-build decisions, port contracts or flows, run a new design review on the diff alone. Then say in a few lines what changed and where, and ask again.
31
+ 3. When the user rejects the design outright, don't approve anything. Ask what is wrong. When the problem is what to build, go back to `envision`; when it is the whole approach, restart this step's design; when the user wants to stop, leave the work unapproved and say how to resume.
32
+ 4. Done when the user says they approve.
@@ -19,10 +19,11 @@ Build turns an approved plan into code, one task at a time. Each task starts wit
19
19
  3. **Read the plan and the design.** Read the change's `change.md` and its feature's `feature.md`. Read the full body of every element the change builds, and every scenario it delivers. Read `commands:` in `.cruze/config.yaml`.
20
20
  4. **Build each open task in order,** following the task loop below. Skip the tasks already ticked in `## Progress`.
21
21
  5. **Finish.** When every task is ticked:
22
- - Run the full test suite, the formatter and the linter, using the project's commands.
22
+ - Run the format, lint and build commands and the full suite, as `.agents/skills/cruze-formats/reference/config.md` defines it under `commands`.
23
23
  - Run `cruze check` and `cruze trace`, and quote their results.
24
+ - When all of them pass, record the commit they ran at with `cruze journal add checks --set commit=<commit> --item <ref>`, where the commit is the output of `git rev-parse --short HEAD`. Verify quotes this instead of running the suite again.
24
25
  - Commit the progress record with a message such as `chore: record progress on <change>`.
25
- - Done when all of them pass.
26
+ - Done when all of them pass and the checks are recorded.
26
27
 
27
28
  ## The task loop
28
29
 
@@ -31,7 +32,7 @@ For task `T<n>`:
31
32
  1. **Read it.** Note its owner, its files, the IDs it proves, and the test plan rows for those IDs.
32
33
  2. **Red.** Write the tests for the IDs it proves, at the seams the test plan names, carrying the IDs. Run them, and see them fail for the reason you expect.
33
34
  3. **Green.** Write the least code that makes them pass, in the task's files. Code that belongs to another task, or another change, waits for it, even when the next change will need it.
34
- 4. **Check.** Run `cruze check <the task's files>`, the formatter and the linter, and fix what they report. Run the tests the task touched, and the rest of the suite when they are quick.
35
+ 4. **Check.** Run `cruze check <the task's files>`, the formatter and the linter, and fix what they report. Run the tests the task touched. When `commands:` has a `test_full`, run `test` too, since it is the fast tier. Otherwise run the rest of the suite only when it is quick.
35
36
  5. **Commit** with a Conventional Commit message naming the task, such as `feat(access): console session state machine (T2)`.
36
37
  6. **Tick it.** Run `cruze task done T<n>`, which records the commit. Its progress edit rides along in the next commit.
37
38
 
@@ -43,10 +44,10 @@ Done for a task when its tests pass, `cruze check` passes for its files, the com
43
44
 
44
45
  The plan is design. Within a task you decide only what is local and reversible.
45
46
 
46
- - **Record it and carry on** for a task-level choice: a private helper in another file of the same module, a private type, or two tasks' commits swapped for a reason. Run `cruze task deviation T<n> "<what you did and why>"`.
47
+ - **Record it and carry on** for a task-level choice: a private helper in another file of the same module, a private type, a fixture or harness added to the test support module that the task's tests need, or two tasks' commits swapped for a reason. The test support module is in every test-writing task's scope, so extend it rather than writing a private helper in a test file. Run `cruze task deviation T<n> "<what you did and why>"`.
47
48
  - **Stop and offer `rethink`** when the code needs any of these:
48
49
  - a new element, port operation or scenario;
49
- - a file outside the owner's module;
50
+ - a file outside the owner's module, other than the test support module;
50
51
  - a change to an approved scenario's behaviour, or to its test;
51
52
  - a dependency the design doesn't name.
52
53
 
@@ -35,7 +35,7 @@ Facts are `- Key: value` items. Keys marked required must be present; the others
35
35
  | `PORT` | `Direction` (`driven` or `driving`), `Operations`, `Module`, `File` | `Implemented by`, `Future` |
36
36
  | `ADP` | `Implements` (a driven port) or `Drives` (use cases), `Technology`, `Module`, `File` | `Adopts` (library and adopt-or-build reason), `Format` (the stored or wire format it owns, or where its schema lives) |
37
37
  | `FLOW` | `Elements`, a Mermaid `sequenceDiagram` | `Serves` (SCN IDs, once they exist), `Failure paths` |
38
- | `MOD` | `Path`, `Layer` (`domain`, `application`, `adapter` or `composition`) | |
38
+ | `MOD` | `Path`, `Layer` (`core`, `domain`, `application`, `adapter` or `composition`) | |
39
39
  | `RULE` | one or two sentences of rule | `Enforced by` (config layer names) |
40
40
  | `XC` | prose | |
41
41
 
@@ -56,7 +56,7 @@ layers:
56
56
  | `check.max_types` | Budget of top-level types per source file. |
57
57
  | `check.exceptions` | Files allowed past a budget, or Rust test files allowed under `src/` (`test-placement`), each with a `path` and a `reason`. `realign` adds entries whose reason ends `scheduled in <ref>`, and landing that change removes them. |
58
58
  | `layers` | Each layer has a `name`, the `paths` it covers, and `may_import`, the layers it may depend on. |
59
- | `commands` | The project's commands by name, such as `test` or `run`. The walking-skeleton change fills them in, and `cruze land` copies them into the Commands section of `AGENTS.md`. |
59
+ | `commands` | The project's commands by name, such as `test` or `run`. The walking-skeleton change fills them in, and `cruze land` copies them into the Commands section of `AGENTS.md`. When the suite has a slow tier, such as UI, device or end-to-end tests, `test` runs only the fast tier and `test_full` runs everything. The full suite is `test_full` when it is set, and `test` otherwise. |
60
60
  | `review.command` | The program and arguments `cruze review` runs to start an agent in a fresh context, with the prompt on standard input. Optional. `cruze init` sets it for Claude Code to run in print mode, allowed to read the project and run `git diff`, `git log`, `git show` and `cruze`. The verifier runs the system, so add the project's build and run commands. When it is unset, or its program isn't installed, `cruze review` hands the role's prompt back to the calling agent to run in a helper. |
61
61
  | `review.decide` | Which review findings the user decides. `exceptions`, the default: only findings whose fix changes behaviour, a designed port or contract, or another decision the user owns, and any the agent wouldn't simply fix as proposed. The agent fixes the rest and lists them. `all`: the user decides every finding. |
62
62
  | `changes.min_builds` | A feature's change that builds fewer elements than this gets a `change-too-small` warning: merge it into the change it continues. Default `3`. |
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- <One paragraph: what the system is, how it is used, and the architectural style.>
5
+ <One paragraph: what the system is and what kind (a library, a daemon or service, a mobile or desktop app, a CLI, or several deliverables), how it is used, and the architectural style.>
6
6
 
7
7
  ### VIEW-context: System context
8
8
 
@@ -81,7 +81,7 @@ sequenceDiagram
81
81
 
82
82
  ### MOD-<context>.<name>: <Module title>
83
83
  - Path: `<directory or file>`
84
- - Layer: <domain | application | adapter | composition>
84
+ - Layer: <core | domain | application | adapter | composition>
85
85
 
86
86
  ## Dependency rules
87
87
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: {{id}}
3
- title: {{title}}
3
+ title: {{title_quoted}}
4
4
  ---
5
5
 
6
6
  # Change: {{title}}
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: {{id}}
3
- title: {{title}}
3
+ title: {{title_quoted}}
4
4
  roadmap: <roadmap item slug>
5
5
  ---
6
6
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: {{id}}
3
- title: {{title}}
3
+ title: {{title_quoted}}
4
4
  roadmap: <roadmap item slug, when the change is on the roadmap>
5
5
  ---
6
6
 
@@ -37,6 +37,7 @@ When two rules pull apart, the earlier one wins. Prefer the simplest design that
37
37
 
38
38
  | Layer | Owns | May depend on |
39
39
  | --- | --- | --- |
40
+ | `core` | A context's concepts, use cases and ports together (`ENT`, `UC`, `PORT`), when its domain needs no boundary of its own | The standard library, and approved libraries with no infrastructure in them |
40
41
  | `domain` | Concepts, state, rules, invariants and domain errors (`ENT`) | Domain code, the standard library, and approved libraries with no infrastructure in them, such as an error-derive crate |
41
42
  | `application` | Use cases (`UC`) and the ports they define (`PORT`) | The domain |
42
43
  | `adapter` | Inbound adapters that drive use cases, and outbound adapters that implement driven ports (`ADP`) | Application, domain and third-party libraries |
@@ -44,6 +45,10 @@ When two rules pull apart, the earlier one wins. Prefer the simplest design that
44
45
 
45
46
  `cruze check` enforces imports between the project's own layers. It allows every third-party import, so review checks that infrastructure libraries appear only in adapters.
46
47
 
48
+ Use the fewest layers that keep the rules. A context starts with `core`, its adapters and the composition root. The boundary that matters most is between the core and infrastructure, because it is what lets tests fake the outside world. Split a context's core into `domain` and `application` when its domain has rules and invariants that several use cases share and a workflow could break, and record the split as a `D<n>` decision. A `core` module follows the domain and the application rules below together.
49
+
50
+ Layers are roles, not folders. Choose the layout that is normal for the kind of system and its language, following [shapes.md](shapes.md), and give each module the layer of what it holds.
51
+
47
52
  Layers are dependency boundaries, not runtime hops. A port can be a plain function call. Add a task, thread, channel or process only for a concrete ownership, concurrency, isolation or backpressure need, and read [runtime.md](runtime.md) first.
48
53
 
49
54
  ### Domain
@@ -83,13 +88,13 @@ Layers are dependency boundaries, not runtime hops. A port can be a plain functi
83
88
 
84
89
  ## Many small modules
85
90
 
86
- - Give each responsibility its own module, grouped by domain concept, with the hexagonal roles inside. A file may hold a few closely related types.
91
+ - Give each responsibility its own module, grouped by domain concept, with the hexagonal roles inside. A context's core is usually one module, with each port beside the use cases that define it, and grows submodules by concept, not by layer. A file may hold a few closely related types.
87
92
  - When a file passes its budget (`check:` in `.cruze/config.yaml`, enforced by `cruze check`) or gains a second responsibility, split it into a submodule named for what it owns.
88
93
  - Entry-point and namespace files, such as `main`, `lib.rs`, `mod.rs` and `index.ts`, hold only wiring and declarations.
89
94
  - Don't create generic modules such as `utils`, `helpers`, `common`, `services`, `models`, `types` or `manager`. Shared behaviour belongs with the concept that owns it.
90
95
  - Duplication is semantic. Two implementations of one rule are duplication even when the text differs, so consolidate them in the owner, not in a helper.
91
- - Structure follows the module map, never a per-language template. Write idiomatic code for the language and use its standard tooling. [languages/rust.md](languages/rust.md) and [languages/cpp.md](languages/cpp.md) add rules for those languages.
92
- - In an existing codebase, its established layout and naming win over these structure rules. Ownership and dependency direction still apply.
96
+ - Structure follows the module map, never a per-language template. Write idiomatic code for the language and use its standard tooling. [languages/rust.md](languages/rust.md), [languages/swift.md](languages/swift.md) and [languages/cpp.md](languages/cpp.md) add rules for those languages.
97
+ - In an existing codebase, its established layout and naming win over these structure rules until the user restructures it with the improve skill. Ownership and dependency direction still apply.
93
98
 
94
99
  ## Representations and errors
95
100
 
@@ -119,6 +124,7 @@ These are review signals, not automatic failures. When one could be checked mech
119
124
 
120
125
  ## Further reading
121
126
 
127
+ - [shapes.md](shapes.md): choosing the layout for a library, a daemon or service, a mobile or desktop app, or a CLI.
122
128
  - [contracts.md](contracts.md): writing a port's `Operations`, a public API, an IPC protocol or a stored format.
123
129
  - [runtime.md](runtime.md): concurrency, long-lived resources (connections, sessions, devices, subprocesses), state machines, cancellation or a hot path.
124
130
  - [fundamentals.md](fundamentals.md): choosing a data structure, a state representation or an abstraction mechanism; defining equality or ordering; bounding loops, retries and fan-out.
@@ -6,7 +6,7 @@ These add to the hexagonal design rules for Rust projects. The module map decide
6
6
 
7
7
  - `main.rs` is the composition root and stays thin. `lib.rs` and every `mod.rs` hold only module declarations, visibility and deliberate re-exports, and `lib.rs` exposes the use cases, ports and domain types that tests drive.
8
8
  - Name modules for the concept they own. Don't put domain definitions in a `mod.rs`, and don't create `domain.rs`, `services.rs`, `models.rs` or `utils.rs` catch-alls.
9
- - Where the layer rules need a hard boundary, a Cargo workspace with one crate per layer makes the compiler enforce it. The walking-skeleton change decides this.
9
+ - Split crates by deliverable, such as the library, a client, a daemon and a CLI, in a Cargo workspace when there is more than one. Inside a crate, modules carry the concepts and the layers, and `cruze check` enforces the layer rules between them. A crate per layer is unusual in Rust and puts a public API between the layers: use one only when the user wants the compiler to enforce a boundary, and record it as a decision.
10
10
 
11
11
  ## Modelling
12
12
 
@@ -0,0 +1,46 @@
1
+ # Swift
2
+
3
+ These add to the hexagonal design rules for Swift projects, such as iOS and macOS apps and Swift packages. The module map decides the layout; this file never does.
4
+
5
+ ## Packages and targets
6
+
7
+ - Every target is a Swift module, and anything another target uses must be `public`. Each target boundary costs access-control boilerplate and build time, so use few:
8
+ - one core target for the app's contexts, with a folder per feature or concept;
9
+ - adapter targets only where a framework or package must stay out of the core, or one adapters target for all of them;
10
+ - the app target, holding the screens, their models and the composition root, or a feature target per feature once the app is large enough to build and preview features alone;
11
+ - one test-support target with the fakes and fixtures every test target shares.
12
+ - Keep `internal`, the default, for everything used inside its target. Use `package` for what the package's own targets share, and `public` only for what the app target or another package needs.
13
+ - A target can import only the targets and packages it declares in `Package.swift`, so declared dependencies enforce those boundaries. They don't stop a target importing a platform framework, such as `CoreLocation` or `SwiftUI`, which any target can import. Review checks framework imports against the layer rules, or a short CI script lists them per target.
14
+ - Keep the core free of UIKit, SwiftUI and other platform frameworks. Its tests then build and run without the app, and with a macOS platform in `Package.swift`, without a simulator.
15
+
16
+ ## Modelling
17
+
18
+ - Use structs for values and entities, enums for closed alternatives and states, and classes only where identity needs reference semantics. Wrap primitives with meaning, such as `struct OfficeName { let value: String }`, with a failable or throwing initializer that enforces the invariant.
19
+ - Use concrete types for single-strategy behaviour. Use protocols for ports and for strategies that really vary.
20
+
21
+ ## Ports and injection
22
+
23
+ - Ports are protocols owned by the core, named for the capability. Platform types, such as `CLLocation` or `UNNotificationRequest`, never appear in their signatures.
24
+ - Inject through initializers. The composition root at the app's entry point builds the adapters and the use cases, and hands each screen's model what it calls.
25
+
26
+ ## Screens
27
+
28
+ - A SwiftUI view and its `@Observable` model are the screen's inbound adapter. The model calls use cases and maps their results to what the view shows. Domain rules stay out of both.
29
+ - Test the model with fakes behind its use cases' ports. Keep UI tests for what only the running screen can show.
30
+
31
+ ## Errors and logging
32
+
33
+ - Throw a typed error, `throws(OfficeChangeError)`, where callers handle its cases differently, and use plain `throws` elsewhere. Never `try!` or `fatalError` for a condition that can happen in production. Tests may use them.
34
+ - Log with `os.Logger` in adapters, use cases and screen models. The domain doesn't log.
35
+
36
+ ## Concurrency
37
+
38
+ - Use the Swift 6 language mode. Domain values are `Sendable` structs and enums. A use case is a struct, or an actor when it owns mutable state that several callers reach.
39
+ - `@MainActor` belongs on views and their models, not on the core.
40
+ - Don't mark a type `@unchecked Sendable` without a comment giving the reason.
41
+
42
+ ## Tooling and tests
43
+
44
+ - Format with `swift format format --in-place --recursive`, and lint with `swift format lint --strict --recursive`.
45
+ - Package tests live in `Tests/<Target>Tests/`. They import the target with `@testable import`, which makes its `internal` declarations visible, so nothing is made `public` only for tests. UI tests live in the app's UI test target.
46
+ - Put the package's tests in the `test` command and the app's UI tests in `test_full`, as `.agents/skills/cruze-formats/reference/config.md` describes, since UI tests run through the simulator and are by far the slowest.
@@ -0,0 +1,49 @@
1
+ # Shapes by kind of system
2
+
3
+ Start from the layout that is normal for the kind of system and its language, then place each owner in it. The hexagonal rules decide what depends on what. They don't decide the folders: a reader who knows the ecosystem should find the code where they expect it.
4
+
5
+ Name the kind in the architecture's Overview. A system can be more than one kind, such as a daemon that ships a client library and a CLI. Each is then its own deliverable, with its own entry point, and in a language with packages, its own package.
6
+
7
+ ## Library
8
+
9
+ A crate, package or SDK that other code calls.
10
+
11
+ - The public API is the inbound adapter. Callers drive the use cases through it, so keep it small and treat it as a contract: read [contracts.md](contracts.md).
12
+ - A pure library, with no I/O, has a core only: no ports and no application layer.
13
+ - A client library that talks to a server keeps the transport and the wire format behind driven ports, so its tests run against a fake server. Group its modules by what callers do with it, such as `connection`, `consumer` and `provider`, with the wire format and the transport as adapters.
14
+
15
+ ## Daemon or service
16
+
17
+ A process that runs until it is stopped, serving requests or reconciling state.
18
+
19
+ - `main` is the composition root and stays thin: configuration, construction, signals and shutdown.
20
+ - One inbound adapter per interface it offers, such as HTTP, IPC, a message consumer or a signal handler. Each decodes, calls one use case and encodes.
21
+ - One outbound adapter per technology it uses, such as storage, the OS, a subprocess or another service.
22
+ - Each context's core is one module, by concept. Long-lived tasks and their shutdown follow [runtime.md](runtime.md).
23
+
24
+ ## Mobile or desktop app
25
+
26
+ An app with screens, on a platform that hosts it.
27
+
28
+ - Group modules by feature, such as `Offices` or `Dashboard`, each with its core and its screens.
29
+ - A screen's view and its model form the inbound adapter: the model maps what the person does to use cases, and use-case results to what the view shows. Neither holds a domain rule.
30
+ - Platform frameworks, such as location, notifications, maps and storage, are outbound adapters behind ports named for the capability, such as `ZoneMonitor` rather than `CoreLocationClient`.
31
+ - The app's entry point is the composition root.
32
+ - Most tests drive the core and the screen models with fakes. UI tests prove only what needs the screen itself, one or two per flow, because they are the slowest tests the project has.
33
+
34
+ ## CLI tool
35
+
36
+ A program a person or a script runs and that exits.
37
+
38
+ - The commands are the inbound adapter, one module per command or command group. Argument parsing and output formatting stay there, and each command calls one use case.
39
+ - The filesystem, the network, the terminal and the clock are outbound adapters behind ports, like any other technology, so tests run the commands against fakes.
40
+
41
+ ## Splitting further
42
+
43
+ Split a deliverable into more packages, crates or targets only for a concrete need, and record it as a `D<n>` decision:
44
+
45
+ - a second deliverable that shares the code, such as a client library, a CLI or an app extension;
46
+ - a dependency boundary the build should enforce, such as keeping a platform framework out of the core's tests;
47
+ - build time, when one package has grown too slow to build and test alone.
48
+
49
+ A package per layer, or per layer per context, is rarely normal in any ecosystem. Each boundary costs a public API between the layers and slows the build, and `cruze check` enforces the layer rules inside a package where it reads the language's imports.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: cruze-improve
3
+ description: Improves the structure of existing code to meet Cruze's current standards, by surveying it for structure that departs from them or keeps causing friction, letting you pick any or all of the candidates, designing the target through an architecture rethink, and scheduling the moves as prefactor changes.
4
+ ---
5
+
6
+ # Improve
7
+
8
+ Improve restructures code that already works, so it meets the standards Cruze holds new work to, such as a layout that is normal for the kind of system, or so it stops causing the same friction. It is design work with one approval gate, and it never changes behaviour: the behaviour tests are the safety net, and they pass unchanged at every step.
9
+
10
+ Realign is different. It applies what each release's notes expect of existing code, and moves `standards:`. Improve runs whenever the user asks, whatever the version, and can take on structure that realign leaves alone, such as a layout the notes mark as new work only.
11
+
12
+ ## Steps
13
+
14
+ 1. **Check what it builds on.** Run `cruze status`. `docs/architecture.md` must be approved and current; when it isn't, stop and name `rethink`. Note the features and changes in flight, which step 8 schedules around. When the user names an area, such as a context or a module, keep to it.
15
+ 2. **Check the safety net.** Run `cruze trace --all`, and the full suite as `.agents/skills/cruze-formats/reference/config.md` defines it under `commands`. Done when both pass, and you have listed each module whose scenarios have no test. Moving such a module first needs tests that record what it does today.
16
+ 3. **Load the standards.** Read these, and follow them for the rest of this skill:
17
+ - `.agents/skills/cruze-hexagonal-design/SKILL.md`, `.agents/skills/cruze-hexagonal-design/shapes.md`, and the language file when one exists for the project's language
18
+ - `.agents/skills/cruze-behavioural-testing/SKILL.md`
19
+ - `.agents/skills/cruze-formats/reference/architecture.md`
20
+ - `.agents/skills/cruze-grilling/SKILL.md`
21
+ 4. **Survey.** Run the surveyor role from `.agents/skills/cruze-roles/SKILL.md` once for the system's layout, then once for each module in the module map, or in the user's area, giving it the module's `Path`. Run them in parallel where the agent can. Check each candidate's evidence against the files and the journal before you use it. Done when the layout and every module in scope have a report.
22
+ 5. **List the candidates** in one message, numbered, merging candidates that share a cause across modules. For each, give:
23
+ - the problem in one sentence, and its evidence;
24
+ - the standard it departs from, or the friction it causes;
25
+ - the target shape;
26
+ - its size in prefactor changes, and its risk.
27
+
28
+ Recommend which to take and why, then ask the user to pick any or all of them.
29
+ 6. **Record each decision:** `cruze journal add disposition --set review=improve --set finding="<module or area>: <summary>" --set disposition=<fixed|waived|deferred> --set reason="<reason>" --set decided=user`. A picked candidate is `fixed`. The rest are `waived`, with the user's reason, or `deferred`. A recorded waiver is never raised again.
30
+ 7. **Design the target** for every picked candidate together, as a rethink at architecture level, following `.agents/skills/cruze-rethink/SKILL.md` with `kind=discovery` and `found_by=improve`:
31
+ - Amend `docs/architecture.md`: the module map and layers, the moved elements' `Module` and `File` facts, the `layers:` in `.cruze/config.yaml`, and a `D<n>` or an ADR for each structural decision. Change no requirement, scenario or port contract unless the user decided that in step 5.
32
+ - When a candidate changes an interface, such as a port or a module's public API, sketch two or three shapes, compare them, and recommend one before writing it.
33
+ - Before the rethink's walkthrough, run the design review from the roles skill on the diff, with `review=design`.
34
+ - Approve it as the rethink's architecture level says, with `--replan` for each built element that moves.
35
+ 8. **Schedule the moves.** Group the replanned elements into prefactor changes, as "A prefactor" in `.agents/skills/cruze-architect/tweak.md` describes, each sized as step 12 of `.agents/skills/cruze-architect/feature.md` says.
36
+ - Order them so each lands on its own and the code builds after every one: first the tests that record behaviour a module lacks, then one context or feature at a time.
37
+ - Put each on the roadmap, following `.agents/skills/cruze-roadmap/SKILL.md`. Run `cruze status --overlap --change <ref>`, and block it on every in-flight item it overlaps.
38
+ - Commit, with a message such as `docs: plan the <area> restructure`.
39
+
40
+ Done when every candidate has a journaled disposition, the target architecture is approved, and every move is a prefactor change on the roadmap.
41
+
42
+ ## Rules
43
+
44
+ - **Behaviour stays.** Wire formats, stored formats, messages, exit codes, and every approved scenario and its test stay as they are, unless the user decided otherwise in step 5.
45
+ - **Small files stay.** Many small modules are the standard, so a candidate never merges files only to make a module deeper. Merging is a candidate when two modules own one responsibility, or one only forwards calls to another.
46
+ - **Ports and adapters stay.** A restructure moves where the core, the ports and the adapters live, never whether a technology sits behind a port.
47
+ - **The existing layout wins** until the user picks a candidate that changes it. Improve never restructures code the user didn't pick.
48
+
49
+ ## Next step
50
+
51
+ `plan` for the first prefactor change. When the user picked nothing, `next`.
@@ -13,7 +13,7 @@ Land makes finished work part of the living model. `cruze land` merges the chang
13
13
  2. **Bring in main.** Merge or rebase the branch onto an up-to-date main, and resolve conflicts.
14
14
  - `journal.jsonl` files merge by keeping every line; `cruze init` sets that up in `.gitattributes`. When that file lacks the rule, keep both sides' lines.
15
15
  - When an `approvals.json` conflicts, take main's version of it. Then run `cruze status`, and re-approve what it shows stale, as step 3 describes.
16
- - Resolve code conflicts as usual, then run the tests.
16
+ - Resolve code conflicts as usual, then run the full suite. When main came in without code conflicts, leave the full suite to CI.
17
17
  3. **Run `cruze status`.** When the change or its feature shows `upstream changed`, another branch landed changes to elements it cites. Then:
18
18
  - Show the user the diff of each changed element, and check that the change's code and tests still hold against it.
19
19
  - When they still hold, re-approve the stale documents: the feature first, then the change. The change's verification carries over when its own design didn't change.
@@ -28,4 +28,4 @@ Next reads the project's state and says what to do now. The CLI works it out fro
28
28
  | `realign` | `realign`: the installed Cruze expects more of existing code than it meets |
29
29
  | `switch-branch` | Switch to the named branch, where that change is built |
30
30
 
31
- When the user asks about something `cruze next` didn't name, such as a bug or an idea, point them to `triage` or `explore`.
31
+ When the user asks about something `cruze next` didn't name, point them to `triage` for a bug, `explore` for an idea, or `improve` for existing code whose structure they want to change.
@@ -44,7 +44,7 @@ Say what is missing and why, then send the change to `rethink` at feature level.
44
44
 
45
45
  The walking-skeleton change also makes CI and the project's tooling real. Its plan adds:
46
46
 
47
- - `commands:` in `.cruze/config.yaml`: the format, lint, build, test and run commands, as the language's standard tooling runs them.
47
+ - `commands:` in `.cruze/config.yaml`: the format, lint, build, test and run commands, as the language's standard tooling runs them. When some tests are much slower than the rest, such as UI or device tests, `test` runs the fast tier and `test_full` the whole suite, so build can run `test` after every task.
48
48
  - A task that adds the language's format, lint, build and test steps to CI (`.github/workflows/ci.yml`), before the Cruze steps `cruze init` put there. The task proves the flow its smoke test runs.
49
49
 
50
50
  ## Next step
@@ -9,6 +9,7 @@ A task is one owner, the files it writes, and the IDs it proves. Build does them
9
9
  - The composition root comes last.
10
10
  - Put fakes just before the first task whose test needs them.
11
11
  - Each task's test can fail first and then pass, using only what earlier tasks built.
12
+ - A test that expects a default or empty result, such as no prompt, an empty list, `nil` or `0`, passes against a stub that returns it. Name in the task the break it is first seen failing against, such as "fails against a model that always shows the prompt".
12
13
  - When the project's lint rejects unused code, such as `cargo clippy -- -D warnings`, put each new item in the task of its first user, or in a task whose own test uses it. Each task then commits green on its own.
13
14
  3. **Write one line per task:**
14
15
 
@@ -17,7 +18,7 @@ A task is one owner, the files it writes, and the IDs it proves. Build does them
17
18
  - T7: `OpenConsole` in `src/access/app/open_console.rs`, proves UC-access.open-console, SCN-access.direct-serial
18
19
  ```
19
20
 
20
- - Owner and paths in backticks. Every path is a file the architecture assigns to that owner, or a test or support file.
21
+ - Owner and paths in backticks. Every path is a file the architecture assigns to that owner, or a test or support file. List the test support files the task extends, such as a shared harness or fixture, so its tests reuse them.
21
22
  - A task proves the elements it builds, and each scenario whose test goes green in it.
22
23
  - A task that only sets up tooling proves the flow or scenario its checks run.
23
24
  4. **Find the callers.** For each signature, default or setting a task changes, search the code for every use of it, including tests that start the real binary or read the setting. Add each file that must change to the task. Done when no task will need a file it doesn't list.
@@ -0,0 +1,44 @@
1
+ # Realign notes: 0.0.6
2
+
3
+ ## New work only
4
+
5
+ ### suite-once-per-commit: The full test suite runs once per commit, and verify quotes build's result
6
+ - Applies to: new work only
7
+ - Rule: `.agents/skills/cruze-verify/SKILL.md`, "Steps", step 2
8
+
9
+ ### test-tiers: A project with slow tests can split them into test and test_full
10
+ - Applies to: new work only
11
+ - Rule: `.agents/skills/cruze-formats/reference/config.md`
12
+ - Fix: when the full suite takes more than a few minutes, move it to `test_full` under `commands:` and make `test` the fast tier
13
+
14
+ ### test-support-in-scope: Build extends the test support module without a rethink
15
+ - Applies to: new work only
16
+ - Rule: `.agents/skills/cruze-build/SKILL.md`, "Deviations"
17
+
18
+ ### name-the-break: Plan names the break for a test that passes against a stub
19
+ - Applies to: new work only
20
+ - Rule: `.agents/skills/cruze-plan/tasks.md`, step 2
21
+
22
+ ### round-2-by-agent: The agent checks round 2 when every blocker was fixed as proposed
23
+ - Applies to: new work only
24
+ - Rule: `.agents/skills/cruze-roles/SKILL.md`, "Running a review", round 2
25
+
26
+ ### size-before-approval: Size warnings are cleared or accepted before a feature is approved
27
+ - Applies to: new work only
28
+ - Rule: `.agents/skills/cruze-architect/feature.md`, step 12
29
+
30
+ ### verify-every-claim: Research checks claims about the language, platform and external systems
31
+ - Applies to: new work only
32
+ - Rule: `.agents/skills/cruze-research/SKILL.md`, "Adopt or build", step 7
33
+
34
+ ### cross-section-consistency: The design reviewer checks cross-cutting rules, interleavings and stale prose
35
+ - Applies to: new work only
36
+ - Rule: `.agents/skills/cruze-roles/design-reviewer.md`, "Rubric", item 8
37
+
38
+ ### one-message-walkthrough: The design walkthrough is one overview, then the documents in full
39
+ - Applies to: new work only
40
+ - Rule: `.agents/skills/cruze-architect/walkthrough.md`
41
+
42
+ ### quoted-titles: New features and changes quote their title in the header
43
+ - Applies to: new work only
44
+ - Rule: `.agents/skills/cruze-formats/templates/change.md`
@@ -0,0 +1,11 @@
1
+ # Realign notes: 0.0.7
2
+
3
+ ## New work only
4
+
5
+ ### improve-skill: Existing code can be restructured to today's standards with the improve skill
6
+ - Applies to: new work only
7
+ - Rule: `.agents/skills/cruze-improve/SKILL.md`
8
+
9
+ ### layout-by-kind: The layout is the one normal for the kind of system and its language, with the fewest layers that keep the rules
10
+ - Applies to: new work only
11
+ - Rule: `.agents/skills/cruze-hexagonal-design/SKILL.md`, "Layers"
@@ -8,6 +8,8 @@ Each release that changes what Cruze expects of a project ships a notes file, `n
8
8
  - [0.0.3](notes/0.0.3.md)
9
9
  - [0.0.4](notes/0.0.4.md)
10
10
  - [0.0.5](notes/0.0.5.md)
11
+ - [0.0.6](notes/0.0.6.md)
12
+ - [0.0.7](notes/0.0.7.md)
11
13
 
12
14
  ## Format
13
15
 
@@ -17,7 +17,13 @@ Run these steps for each component in a design that isn't domain logic. Domain l
17
17
  4. Recommend one. Adopt a library, or build with a concrete reason: the behaviour is specific to this product, no candidate meets a stated constraint, every candidate brings disproportionate risk or complexity, or the capability is the product itself. Avoiding a dependency is not a reason on its own.
18
18
  5. Record the result as a row in the `## Adopt or build` table of the feature or standalone change, as Component, Decision, Choice and Reason. At project scope, record it as the adapter's `Adopts` fact, and put rows for anything no adapter owns in the walking-skeleton change's `## Adopt or build`. When the evidence runs longer than the reason, write it to `.cruze/notes/<date>-<slug>.md` and cite that note in the reason.
19
19
  6. Take the recommendation to the user. Adopting means a new dependency, which follows `.agents/skills/cruze-dependency-approval/SKILL.md`. Building commodity functionality is the user's call as well.
20
- 7. Verify what the design will rely on. List each claim the design makes about an adopted library or tool: the features or flags it needs, and each command the design spells out, such as a CI step. Once the user has approved the dependency, check each claim by running it: build a scratch project outside the repository with exactly the declared features, and run each command there or with `--help`. When a claim can't be run, check it in that version's source. Write the features into the `Adopts` fact or the row's Choice.
20
+ 7. Verify what the design will rely on. List each claim the design or its testing approach makes about anything it doesn't build:
21
+ - an adopted library or tool: the features or flags it needs, and each command the design spells out, such as a CI step;
22
+ - the language or runtime, such as whether a trait with async methods can be used as a trait object;
23
+ - the platform's test environment, such as which permissions a test process gets;
24
+ - an external system the product talks to, such as what a broker logs or how it answers.
25
+
26
+ Once the user has approved any dependency involved, check each claim by running it: build a scratch project outside the repository with exactly the declared features, and run each command there or with `--help`, or run the external system and watch it. When a claim can't be run, check it in that version's source, and say so. Write the features into the `Adopts` fact or the row's Choice.
21
27
 
22
28
  Done when every non-domain component in the design has a row with a decision and a reason, and every claim the design relies on is verified, with how.
23
29
 
@@ -32,7 +32,7 @@ Finding a design flaw mid-build is information, not failure. Rethink amends the
32
32
  --set agent="<the agent you run in>" [--item <ref>]
33
33
  ```
34
34
 
35
- `found_by` is the step that found it. A defect also needs `missed_by`, the earliest step whose job was to catch it. Both take one of `envision`, `architect`, `research`, `design-review`, `walkthrough`, `plan`, `plan-review`, `build`, `code-review`, `verify`, `land`, `validate`, `check` or `user`.
35
+ `found_by` is the step that found it. A defect also needs `missed_by`, the earliest step whose job was to catch it. Both take one of `envision`, `architect`, `research`, `design-review`, `walkthrough`, `plan`, `plan-review`, `build`, `code-review`, `verify`, `land`, `improve`, `validate`, `check` or `user`.
36
36
 
37
37
  Done when `cruze status` shows every document approved and current, or names only work the user chose to leave for later.
38
38
 
@@ -11,7 +11,7 @@
11
11
 
12
12
  1. Edit the feature's `## Spec delta`, `## Architecture delta` or `## Changes`. For a standalone change, edit its own deltas and scope. Write complete bodies, as `architect` does, and keep the scope rules.
13
13
  2. Run `cruze validate`. Done when it reports no errors for the feature or its changes.
14
- 3. Run the design review from the roles skill on the diff alone, with `review=design`. Walk the user through the changed parts, following `.agents/skills/cruze-architect/walkthrough.md`.
14
+ 3. Run the design review from the roles skill on the diff alone, with `review=design`. Run the walkthrough of the changed parts, following `.agents/skills/cruze-architect/walkthrough.md`.
15
15
  4. Re-approve the feature. For each of its changes that shows as stale, check it against the diff. When the amendment touches the change's scope, test plan or tasks, update them to match, reopen touched tasks, run the plan review on the diff, and re-approve it with `cruze approve <change> --by-agent`. When it doesn't, re-stamp the change as the skill's step 6 describes.
16
16
  5. When a change hasn't been created yet, only the feature's Changes row changes; `plan` picks it up.
17
17
 
@@ -14,12 +14,13 @@ A role is a prompt with fixed inputs and a report as its only output. It runs in
14
14
  | Verifier | [verifier.md](verifier.md) | verify, to run the system |
15
15
  | Researcher | [researcher.md](researcher.md) | architect, for adopt-or-build decisions |
16
16
  | Auditor | [auditor.md](auditor.md) | realign, to compare existing code with what a release now expects |
17
+ | Surveyor | [surveyor.md](surveyor.md) | improve, to find structure that departs from the standards or keeps causing friction |
17
18
 
18
19
  ## Running a role
19
20
 
20
21
  1. Read the role file and gather exactly the inputs it lists. Done when you have every input path, plus any command output the role asks for.
21
22
  2. Start a fresh context: a helper agent with no conversation history, where the agent can start one. Give it the role file's full text and the inputs the role lists, including draft documents it names, and nothing else. Your own opinions, the conversation and your reasons for the design stay out.
22
- 3. If the agent can't start a helper, run `cruze review <role> --item <ref>`, where the role is `design-reviewer`, `code-reviewer`, `verifier`, `researcher` or `auditor`. Add `--base <commit>` for the code under review. It starts the agent configured under `review:` in `.cruze/config.yaml` in a fresh context and prints the role's report. When no agent is configured, or it isn't installed, it reports `status: run-in-helper` with the role's full prompt instead: start a helper, such as a subagent, and give it exactly that prompt. If no fresh context can run, the reviewers, the verifier and the auditor must still run fresh: tell the user, and have them run the role in a new session. The researcher may run in your own context, since its evidence is checkable; say that you did.
23
+ 3. If the agent can't start a helper, run `cruze review <role> --item <ref>`, where the role is `design-reviewer`, `code-reviewer`, `verifier`, `researcher`, `auditor` or `surveyor`. Add `--base <commit>` for the code under review. It starts the agent configured under `review:` in `.cruze/config.yaml` in a fresh context and prints the role's report. When no agent is configured, or it isn't installed, it reports `status: run-in-helper` with the role's full prompt instead: start a helper, such as a subagent, and give it exactly that prompt. If no fresh context can run, the reviewers, the verifier and the auditor must still run fresh: tell the user, and have them run the role in a new session. The researcher may run in your own context, since its evidence is checkable; say that you did.
23
24
  4. Take the report as it comes back. Check its evidence against the files before you act on any finding.
24
25
 
25
26
  ## Running a review
@@ -53,11 +54,13 @@ A review has at most two rounds. Only blockers can force the second one.
53
54
 
54
55
  ### Round 2
55
56
 
56
- Run round 2 only when a round-1 blocker was fixed.
57
+ Run round 2 only when a round-1 blocker was fixed. It checks only whether those blockers are fixed, and raises nothing new.
57
58
 
58
- 1. Run the reviewer again with its usual inputs, plus the round-1 blockers and the diff of their fixes. It may be the round-1 reviewer resumed, since that context never saw the conversation that produced the work (with `cruze review`: `--round 2 --blockers <file> --base <round-1 commit>`). It checks only whether those blockers are fixed, and raises nothing new.
59
- 2. Record the round with `round=2`.
60
- 3. Take any blocker still open to the user, who fixes it now, waives it or starts a rethink. There is no round 3.
59
+ 1. **Choose who checks.** When every blocker was fixed exactly as the reviewer proposed, check the fixes yourself: a fresh reviewer re-reading a fix it proposed finds nothing new. When any blocker was fixed differently from the proposal, or its fix reaches past what the finding names, run the reviewer.
60
+ 2. **Check them yourself:** read each blocker's finding against the diff of its fix, and run `cruze validate`. A blocker is fixed when the diff does what the proposal says and validate reports no new errors.
61
+ 3. **Or run the reviewer** again with its usual inputs, plus the round-1 blockers and the diff of their fixes. It may be the round-1 reviewer resumed, since that context never saw the conversation that produced the work (with `cruze review`: `--round 2 --blockers <file> --base <round-1 commit>`).
62
+ 4. Record the round with `round=2`, the blockers still open, `concerns=0`, and `checked_by=agent` or `checked_by=reviewer`.
63
+ 5. Take any blocker still open to the user, who fixes it now, waives it or starts a rethink. There is no round 3.
61
64
 
62
65
  Done when every finding has a journaled disposition, and every exception, and every blocker left open in round 2, has the user's decision.
63
66
 
@@ -20,7 +20,7 @@ Review against these items and nothing else. Each finding names one.
20
20
 
21
21
  1. **Behaviour.** Every requirement has at least one scenario. Every scenario has concrete values, one WHEN, and a THEN a person could check. Failure behaviour the user will meet has its own scenario.
22
22
  2. **Seams.** Every scenario can be driven through a use case, or through an inbound adapter when the outcome is what that adapter shows. Every driven port the use case needs can be faked.
23
- 3. **Placement.** Every new or changed element with code has a `Module` whose `Layer` fits its role and a `File` with a real path. No generic modules, and no file is likely to hold two responsibilities. Every element, fact and value serves a requirement in scope or a `Future` fact the feature map calls for. Anything reserved for a need nobody stated is a finding.
23
+ 3. **Placement.** Every new or changed element with code has a `Module` whose `Layer` fits its role and a `File` with a real path. No generic modules, and no file is likely to hold two responsibilities. The layout is the one normal for the kind of system and the language, and every layer, module, package or target split beyond a context's `core` and its adapters has a recorded reason. Every element, fact and value serves a requirement in scope or a `Future` fact the feature map calls for. Anything reserved for a need nobody stated is a finding.
24
24
  4. **Direction.** Every dependency points inward and is allowed by the `RULE` elements and the `layers:` in `.cruze/config.yaml`.
25
25
  5. **Adopt or build.** Every component that isn't domain logic has an adopt-or-build decision with a reason, and every new dependency is named with the features the design uses. Every command the design spells out, such as a CI step, is spelled as that version's `--help` or source shows it. A claim the design relies on that the research left unverified is a blocker.
26
26
  6. **Contracts.** Every new or changed port's `Operations` state what each operation guarantees, how it fails, and who owns cleanup.
@@ -28,8 +28,11 @@ Review against these items and nothing else. Each finding names one.
28
28
  8. **Consistency.** The design agrees with `docs/architecture.md`, the accepted ADRs and what earlier changes landed, or changes them explicitly through a `MODIFIED` operation or a new ADR. Its own elements agree with each other. Check every pair, not a sample:
29
29
  - each use case's `Output` and `Errors` against the `FLOW`s that serve it and the `XC` rules that apply to it;
30
30
  - each adapter's duties against the port it implements and the `XC` rules it follows;
31
- - each guarantee, such as "always fits" or "never returns", against the limits and failures that bound it.
32
- 9. **Slicing.** Each change is a vertical slice that delivers scenarios end to end and can land on its own. The order respects `Depends on`, and the first change proves the design end to end. Each change carries enough work to be worth its own plan review, code review and verify: changes that build one or two elements each on the same adapters or screens, in a chain, are one change split too fine. A change that one verifier run can't hold is split too coarse. A change `Builds` an element only when its delivered scenarios prove the whole body; an element whose duties arrive in several changes is split into elements that each arrive whole. `Depends on` names every earlier change that builds something this change's scenarios need. At project scope, the roadmap starts with the walking skeleton, and every goal in the release is covered.
31
+ - each guarantee, such as "always fits" or "never returns", against the limits and failures that bound it;
32
+ - each `XC` rule against the other `XC` rules, the `RULE` elements and the `layers:` in `.cruze/config.yaml`, such as a logging rule that every module logs against a build rule that forbids the logging import;
33
+ - each pair of use cases that change the same state, for an interleaving that leaves it wrong, against the concurrency rule in `XC`;
34
+ - at feature scope, the prose in `docs/architecture.md` the delta makes untrue, such as an Overview sentence or a `D<n>` line describing an element the delta splits or replaces.
35
+ 9. **Slicing.** Each change is a vertical slice that delivers scenarios end to end and can land on its own. The order respects `Depends on`, and the first change proves the design end to end. Each change carries enough work to be worth its own plan review, code review and verify: changes that build one or two elements each on the same adapters or screens, in a chain, are one change split too fine. A change that one verifier run can't hold is split too coarse. A `change-too-small`, `change-too-large` or `feature-size` warning from `cruze validate` is a finding, unless a decision records the user accepting it. A change `Builds` an element only when its delivered scenarios prove the whole body; an element whose duties arrive in several changes is split into elements that each arrive whole. `Depends on` names every earlier change that builds something this change's scenarios need. At project scope, the roadmap starts with the walking skeleton, and every goal in the release is covered.
33
36
  10. **Ambiguity.** Name each point where a fresh implementer could reasonably build something different from what the user expects.
34
37
 
35
38
  ## Plan rubric
@@ -0,0 +1,40 @@
1
+ # Surveyor
2
+
3
+ You survey existing code for structure that departs from Cruze's current standards, or that keeps causing friction, and say what it should become. You report candidates, and you edit nothing.
4
+
5
+ ## Inputs
6
+
7
+ - What to survey: the system's layout, or one module, named with its `Path`.
8
+ - The standards: `.agents/skills/cruze-hexagonal-design/SKILL.md`, `.agents/skills/cruze-hexagonal-design/shapes.md`, the language file for the project's language when one exists, and `.agents/skills/cruze-behavioural-testing/SKILL.md`.
9
+ - `docs/architecture.md`, for the module map and the elements the code implements, and `.cruze/config.yaml`.
10
+ - The files in scope: for the layout, the build manifests, such as `Cargo.toml` or `Package.swift`, and each module's `Path`; for a module, every source and test file under its `Path`.
11
+ - The journal: the output of `cruze journal list --event deviation`, `cruze journal list --event rethink` and `cruze journal list --event disposition`.
12
+ - The settled ledger, as `.agents/skills/cruze-roles/SKILL.md` defines it, and the earlier `improve` and `realign` dispositions. Never raise a candidate they waived.
13
+
14
+ ## Work
15
+
16
+ 1. **The layout.** Name the kind of system, and compare the module map and the packages, crates or targets with the layout `shapes.md` and the language file describe. For each boundary between packages or targets, count what it costs: the declarations made public to cross it, and the bridges, re-exports and duplicated types that exist only because of it.
17
+ 2. **The module's code.** Read every file in scope, not a sample. Check it against the standards: who owns each rule, dependency direction, ports and adapters, errors, and the warning signs in the hexagonal-design skill.
18
+ 3. **The journal.** Find the deviations, rethinks and review findings that name a file in scope, and group them by cause. A cause that recurs is friction.
19
+ 4. **The history.** Run `git log --format=%h --name-only -n 300 -- <Path>`. Name the files outside the module that change in the same commits as its files in more than half of those commits; a boundary there is often in the wrong place. Name the files that change most.
20
+ 5. **One operation.** Pick one representative operation the module serves, and list the files a reader opens to follow it from the inbound adapter to the outbound one. Note modules that only forward calls, and pairs of modules that own one responsibility between them.
21
+ 6. **Shape each candidate.** Give the smallest target that meets the standard or removes the friction, and say whether it changes the text of an element in `docs/architecture.md`. A target keeps behaviour, keeps small files, and keeps every technology behind a port.
22
+
23
+ Done when every file in scope was read, and every candidate has evidence.
24
+
25
+ ## Report
26
+
27
+ One block per candidate:
28
+
29
+ ```markdown
30
+ ### <n>. <one-line summary>
31
+ - Kind: standard | friction
32
+ - Evidence: <path:line quoting the code, journal entries with their timestamps, or commit counts>
33
+ - Cost: <the rule text it departs from, or what the friction cost, such as five deviations>
34
+ - Target: <the specific shape it should take>
35
+ - Size: <prefactor changes, and tasks in each>
36
+ - Risk: <what could break, and which tests cover it>
37
+ - Design change: <the elements in docs/architecture.md whose text must change, or `no`>
38
+ ```
39
+
40
+ Report every candidate that has evidence, and none that doesn't. End with one line: `Candidates: <n>. Standard: <n>. Friction: <n>.`
@@ -6,11 +6,12 @@ You check that a change actually works when someone uses it. The tests passing i
6
6
 
7
7
  - The change's `change.md`, and its `feature.md` when it belongs to a feature. The scenarios it delivers are listed under `Delivers` in its scope, and written out in the spec delta.
8
8
  - The project's commands, from `commands:` in `.cruze/config.yaml`, and from `README.md` when they aren't there.
9
+ - The mechanical checks' results, with the commit they ran at.
9
10
  - The flows in `docs/architecture.md` that serve those scenarios.
10
11
 
11
12
  ## Work
12
13
 
13
- 1. **Build.** Build the system and run the full test suite with the project's commands. Record each command and whether it passed.
14
+ 1. **Build.** Build the system with the project's build command, and record whether it passed. The test suite already ran at the commit in your inputs, and CI runs it again before the merge, so don't run it. Run a single test only when it is how a scenario reaches its real front door, such as a UI test that drives the app.
14
15
  2. **Trace.** Run `cruze trace --change <ref>` and record its result.
15
16
  3. **Run each scenario.** For every scenario the change delivers:
16
17
  - Set up its GIVEN with real things where you can: configuration files, directories, a local test server, a pseudo-terminal. Put them in a temporary directory outside the project.
@@ -35,4 +36,4 @@ One block per scenario:
35
36
  - Notes: <surprises from probing, or what a person needs to run it>
36
37
  ```
37
38
 
38
- Before the blocks, list the build, test and trace commands with their results. End with one line: `Pass: <n>. Fail: <n>. Could not run: <n>.`
39
+ Before the blocks, list the build and trace commands with their results, and the commit the mechanical checks ran at. End with one line: `Pass: <n>. Fail: <n>. Could not run: <n>.`
@@ -10,18 +10,22 @@ Verify answers one question: does this change work when someone uses it? Green t
10
10
  ## Steps
11
11
 
12
12
  1. **Check it is ready.** Run `cruze next`. It must name `verify` for this change, on this branch. Find the base commit the change branched from with `git merge-base main HEAD`.
13
- 2. **Run the mechanical checks.** Run the project's format, lint, build and test commands from `commands:` in `.cruze/config.yaml`, then `cruze validate`, `cruze check --ci` and `cruze trace --change <ref>`. Quote each result. When one fails, fix the code in a commit and run them again. When a fix needs design, stop and offer `rethink`.
13
+ 2. **Run the mechanical checks.** Run `cruze validate`, `cruze check --ci` and `cruze trace --change <ref>`, and quote each result.
14
+ - Run `cruze journal list --event checks --item <ref>`. When its last entry's commit has no code changes since, that is when `git diff --quiet <commit> HEAD -- . ':(exclude)docs' ':(exclude).cruze'` succeeds, quote that entry for the format, lint, build and test commands instead of running them again.
15
+ - Otherwise run the format, lint and build commands and the full suite, as `.agents/skills/cruze-formats/reference/config.md` defines it under `commands`. When they pass, record them with `cruze journal add checks --set commit=<commit> --item <ref>`, where the commit is the output of `git rev-parse --short HEAD`.
16
+ - When one fails, fix the code in a commit and run them again. When a fix needs design, stop and offer `rethink`.
14
17
  3. **Check the dependencies.** Follow "Checking" in `.agents/skills/cruze-dependency-approval/SKILL.md` against the base commit. An unrecorded dependency is a blocker.
15
- 4. **Run the verifier.** Run the verifier role from `.agents/skills/cruze-roles/SKILL.md` for the change. It must be able to build and run the system. When it runs through `cruze review`, check that `review.command` in `.cruze/config.yaml` allows the project's build and run commands, and add them with the user's agreement. Done when you have its report, with a result for every delivered scenario.
16
- 5. **Review the code.** Run the review in the roles skill with the code reviewer, `review=code`, `--item <ref>` and the base commit. Fix each finding whose disposition is `fixed` in a commit, then check the fixes in round 2.
18
+ 4. **Run the verifier.** Run the verifier role from `.agents/skills/cruze-roles/SKILL.md` for the change, with the mechanical checks' results and the commit they ran at. It must be able to build and run the system. When it runs through `cruze review`, check that `review.command` in `.cruze/config.yaml` allows the project's build and run commands, and add them with the user's agreement. Done when you have its report, with a result for every delivered scenario.
19
+ 5. **Review the code.** Run the review in the roles skill with the code reviewer, `review=code`, `--item <ref>` and the base commit. Fix each finding whose disposition is `fixed` in a commit, running the tests each fix touches, and `test` when `commands:` has a `test_full`. Then check the fixes in round 2.
17
20
  6. **Write the manual test script** as `manual-test.md` in the change folder, following [manual-test.md](manual-test.md). Commit it.
18
- 7. **Report.** Show the user four things:
21
+ 7. **Check the fixes once.** When code changed since the last `checks` entry, run the format, lint and build commands and the full suite once more, and record them as in step 2. Done when the last `checks` entry is at a commit with no code changes since.
22
+ 8. **Report.** Show the user four things:
19
23
  - The mechanical checks, one line each.
20
24
  - The verifier's result for every scenario.
21
25
  - The review's outcome, with each finding's disposition.
22
26
  - The path to `manual-test.md`, with a recommendation to run it before accepting.
23
- 8. **Ask for the decision:** "Do you accept this change, or send it back?"
24
- 9. **Record it** with `cruze journal add verification --set result=accepted --set summary="<one line>" --item <ref>`, or `result=sent-back`. On sent-back, say what goes back:
27
+ 9. **Ask for the decision:** "Do you accept this change, or send it back?"
28
+ 10. **Record it** with `cruze journal add verification --set result=accepted --set summary="<one line>" --item <ref>`, or `result=sent-back`. On sent-back, say what goes back:
25
29
  - A defect in code a task already built: `cruze task reopen T<n> "<reason>"`, then `build`.
26
30
  - A design that can't deliver the scenario: `rethink`.
27
31
 
@@ -28,7 +28,7 @@ export interface NewReport {
28
28
  export async function createWorkItem(deps: ProjectDeps, request: NewRequest): Promise<NewReport> {
29
29
  const view = await loadView(deps.files);
30
30
  const date = deps.clock.today();
31
- const values = { id: "", title: request.title, date, project_name: "" };
31
+ const values = { id: "", title: request.title, title_quoted: JSON.stringify(request.title), date, project_name: "" };
32
32
  if (request.title.trim() === "") throw new CruzeError("missing-title", "a title is required");
33
33
 
34
34
  if (request.kind === "adr") {
@@ -4,7 +4,7 @@ import { featureOf } from "../../domain/project/work_items.ts";
4
4
  import type { AgentRunner } from "../ports/agent_runner.ts";
5
5
  import { loadView, type ProjectDeps } from "../project_context.ts";
6
6
 
7
- export const ROLES = ["design-reviewer", "code-reviewer", "verifier", "researcher", "auditor"] as const;
7
+ export const ROLES = ["design-reviewer", "code-reviewer", "verifier", "researcher", "auditor", "surveyor"] as const;
8
8
  export type Role = (typeof ROLES)[number];
9
9
 
10
10
  export interface ReviewRequest {
@@ -15,25 +15,27 @@ export const RECORDED_EVENTS: Record<string, string[]> = {
15
15
  override: ["gate", "reason"],
16
16
  bug: ["summary", "cause"],
17
17
  verification: ["result", "summary"],
18
+ checks: ["commit"],
18
19
  };
19
20
 
20
21
  /** Fields an event may carry beyond its required ones, checked when present. A defect rethink must say which step missed it. */
21
22
  const OPTIONAL_FIELDS: Record<string, string[]> = {
22
23
  rethink: ["missed_by"],
23
- review: ["nits"],
24
+ review: ["nits", "checked_by"],
24
25
  disposition: ["decided"],
25
26
  };
26
27
 
27
28
  /** The workflow steps and checks that find or miss a problem, so a retro can count them. */
28
- export const STEPS = ["envision", "architect", "research", "design-review", "walkthrough", "plan", "plan-review", "build", "code-review", "verify", "land", "realign", "validate", "check", "user"];
29
+ export const STEPS = ["envision", "architect", "research", "design-review", "walkthrough", "plan", "plan-review", "build", "code-review", "verify", "land", "realign", "improve", "validate", "check", "user"];
29
30
 
30
31
  export const FIELD_VALUES: Record<string, string[]> = {
31
32
  level: ["task", "change", "feature", "architecture", "vision"],
32
33
  kind: ["defect", "discovery"],
33
34
  disposition: ["fixed", "waived", "deferred", "rejected"],
34
35
  decided: ["agent", "user"],
35
- review: ["design", "plan", "code", "realign"],
36
+ review: ["design", "plan", "code", "realign", "improve"],
36
37
  result: ["accepted", "sent-back"],
38
+ checked_by: ["agent", "reviewer"],
37
39
  found_by: STEPS,
38
40
  missed_by: STEPS,
39
41
  };
@@ -79,6 +81,9 @@ export function recordedEventProblems(event: string, fields: Record<string, stri
79
81
  if (allowed !== undefined && !allowed.includes(value)) problems.push(`${field} must be one of ${allowed.join(", ")}`);
80
82
  if (COUNT_FIELDS.includes(field) && !/^\d+$/.test(value)) problems.push(`${field} must be a whole number`);
81
83
  }
84
+ if (event === "checks" && fields["commit"] !== undefined && !/^[0-9a-f]{7,40}$/.test(fields["commit"])) {
85
+ problems.push("commit must be a commit hash, such as the output of git rev-parse --short HEAD");
86
+ }
82
87
  if (event === "disposition" && fields["decided"] === "agent" && fields["disposition"] !== "fixed") {
83
88
  problems.push("the agent decides only fixes; the user waives, defers or rejects a finding (decided=user)");
84
89
  }
@@ -66,7 +66,7 @@ function projectStep(view: ProjectView): NextStep | null {
66
66
  {
67
67
  path: PATHS.architecture,
68
68
  missing: { step: "architect", reason: "the project has no architecture yet" },
69
- unapproved: { step: "architect", reason: "finish the architecture, walk through it and approve it" },
69
+ unapproved: { step: "architect", reason: "finish the architecture, review it and approve it" },
70
70
  changed: { step: "rethink", target: "architecture", reason: "the architecture changed since its approval" },
71
71
  },
72
72
  {
@@ -89,7 +89,7 @@ function itemSteps(view: ProjectView, item: WorkItem, branch: string | null): Ne
89
89
  if (item.kind === "standalone") return [changeStep(view, item, branch)];
90
90
  const state = evaluateApproval(view, item.path);
91
91
  if (readChangesTable(item.doc).length === 0) return [{ step: "architect", target: item.ref, reason: "the feature has no design or changes yet" }];
92
- if (state.state === "unapproved") return [{ step: "architect", target: item.ref, reason: "review the feature's design, walk through it and approve it" }];
92
+ if (state.state === "unapproved") return [{ step: "architect", target: item.ref, reason: "review the feature's design and approve it" }];
93
93
  if (state.state !== "approved") return [{ step: "rethink", target: item.ref, reason: `the feature changed since its approval${state.changed.length > 0 ? ` (${state.changed.join(", ")})` : ""}` }];
94
94
  const changes = changesOf(view.items, item);
95
95
  const landed = new Set(changes.filter((c) => readProgress(c.doc).landed !== undefined).map((c) => c.folderName));
@@ -18,7 +18,7 @@ const REQUIRED_FACTS: Partial<Record<Kind, string[]>> = {
18
18
  const ALLOWED_VALUES: Record<string, { kinds: Kind[]; values: string[] }> = {
19
19
  Kind: { kinds: ["ENT"], values: ["aggregate", "entity", "value", "service", "policy", "event"] },
20
20
  Direction: { kinds: ["PORT"], values: ["driven", "driving"] },
21
- Layer: { kinds: ["MOD"], values: ["domain", "application", "adapter", "composition"] },
21
+ Layer: { kinds: ["MOD"], values: ["core", "domain", "application", "adapter", "composition"] },
22
22
  };
23
23
 
24
24
  export function elementProblems(path: string, doc: MarkdownDoc, element: Element): Problem[] {