@printpractical/cruze 0.0.13 → 0.0.15
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.
- package/README.md +61 -118
- package/dist/adapters/inbound/cli/cli_context.js +0 -27
- package/dist/adapters/inbound/cli/commands/code.js +5 -18
- package/dist/adapters/inbound/cli/commands/documents.js +11 -37
- package/dist/adapters/inbound/cli/commands/init.js +1 -1
- package/dist/adapters/inbound/cli/commands/install.js +1 -0
- package/dist/adapters/inbound/cli/commands/review.js +2 -9
- package/dist/adapters/inbound/cli/commands/status.js +16 -63
- package/dist/adapters/inbound/cli/commands.js +10 -37
- package/dist/adapters/inbound/cli/parse_command.js +0 -54
- package/dist/adapters/outbound/git_repository.js +2 -71
- package/dist/app/ports/repository.js +0 -12
- package/dist/app/project_context.js +15 -25
- package/dist/app/use_cases/approve_document.js +29 -0
- package/dist/app/use_cases/check_code.js +21 -56
- package/dist/app/use_cases/install_skills.js +7 -1
- package/dist/app/use_cases/new_document.js +25 -0
- package/dist/app/use_cases/project_status.js +43 -67
- package/dist/app/use_cases/run_review.js +11 -30
- package/dist/app/use_cases/validate_project.js +8 -5
- package/dist/domain/approvals.js +51 -0
- package/dist/domain/check/check_source.js +3 -32
- package/dist/domain/check/imports.js +3 -3
- package/dist/domain/check/rust_imports.js +25 -3
- package/dist/domain/config.js +8 -84
- package/dist/domain/hashing.js +16 -30
- package/dist/domain/ids.js +13 -27
- package/dist/domain/next_step.js +41 -0
- package/dist/domain/project/features.js +71 -0
- package/dist/domain/project/layout.js +11 -27
- package/dist/domain/project/project_docs.js +48 -0
- package/dist/domain/project/release.js +30 -0
- package/dist/domain/scaffold.js +0 -1
- package/dist/domain/skill_budget.js +4 -4
- package/dist/domain/trace.js +8 -25
- package/dist/domain/validation/document_rules.js +65 -0
- package/dist/domain/validation/release_rules.js +45 -0
- package/dist/domain/validation/review_rules.js +21 -0
- package/dist/domain/validation/validate_project.js +20 -27
- package/dist/domain/versions/cruze_version.js +3 -9
- package/dist/main.js +1 -1
- package/package.json +1 -1
- package/skills/asking/SKILL.md +51 -0
- package/skills/behavioural-testing/SKILL.md +14 -16
- package/skills/behavioural-testing/examples.md +1 -2
- package/skills/behavioural-testing/fakes.md +2 -2
- package/skills/build/SKILL.md +34 -38
- package/skills/dependency-approval/SKILL.md +34 -31
- package/skills/envision/SKILL.md +23 -18
- package/skills/envision/architecture.md +16 -0
- package/skills/envision/breakdown.md +14 -0
- package/skills/envision/possibilities.md +6 -7
- package/skills/fix/SKILL.md +34 -0
- package/skills/formats/SKILL.md +39 -87
- package/skills/formats/config.md +47 -0
- package/skills/formats/templates/architecture.md +18 -74
- package/skills/formats/templates/feature.md +18 -34
- package/skills/formats/templates/vision.md +15 -27
- package/skills/hexagonal-design/SKILL.md +11 -11
- package/skills/hexagonal-design/contracts.md +3 -3
- package/skills/hexagonal-design/fundamentals.md +1 -1
- package/skills/hexagonal-design/languages/cpp.md +1 -1
- package/skills/hexagonal-design/languages/rust.md +1 -1
- package/skills/hexagonal-design/languages/swift.md +2 -2
- package/skills/hexagonal-design/runtime.md +2 -2
- package/skills/research/SKILL.md +4 -4
- package/skills/research/evaluation.md +1 -1
- package/skills/review/SKILL.md +27 -0
- package/skills/roles/SKILL.md +8 -59
- package/skills/roles/code-reviewer.md +22 -32
- package/skills/roles/researcher.md +3 -3
- package/skills/shape/SKILL.md +37 -0
- package/skills/shape/self-check.md +12 -0
- package/src/adapters/inbound/cli/cli_context.ts +0 -27
- package/src/adapters/inbound/cli/commands/code.ts +5 -18
- package/src/adapters/inbound/cli/commands/documents.ts +11 -37
- package/src/adapters/inbound/cli/commands/init.ts +1 -1
- package/src/adapters/inbound/cli/commands/install.ts +1 -0
- package/src/adapters/inbound/cli/commands/review.ts +2 -9
- package/src/adapters/inbound/cli/commands/status.ts +16 -63
- package/src/adapters/inbound/cli/commands.ts +10 -37
- package/src/adapters/inbound/cli/parse_command.ts +0 -54
- package/src/adapters/outbound/git_repository.ts +2 -71
- package/src/app/ports/repository.ts +0 -12
- package/src/app/project_context.ts +15 -25
- package/src/app/use_cases/approve_document.ts +29 -0
- package/src/app/use_cases/check_code.ts +21 -56
- package/src/app/use_cases/install_skills.ts +7 -1
- package/src/app/use_cases/new_document.ts +25 -0
- package/src/app/use_cases/project_status.ts +49 -73
- package/src/app/use_cases/run_review.ts +11 -30
- package/src/app/use_cases/validate_project.ts +8 -5
- package/src/domain/approvals.ts +51 -0
- package/src/domain/check/check_source.ts +3 -32
- package/src/domain/check/imports.ts +3 -3
- package/src/domain/check/rust_imports.ts +25 -3
- package/src/domain/config.ts +9 -85
- package/src/domain/hashing.ts +16 -30
- package/src/domain/ids.ts +13 -27
- package/src/domain/next_step.ts +41 -0
- package/src/domain/project/features.ts +71 -0
- package/src/domain/project/layout.ts +11 -27
- package/src/domain/project/project_docs.ts +48 -0
- package/src/domain/project/release.ts +30 -0
- package/src/domain/scaffold.ts +0 -1
- package/src/domain/skill_budget.ts +4 -4
- package/src/domain/trace.ts +8 -25
- package/src/domain/validation/document_rules.ts +65 -0
- package/src/domain/validation/release_rules.ts +45 -0
- package/src/domain/validation/review_rules.ts +21 -0
- package/src/domain/validation/validate_project.ts +21 -28
- package/src/domain/versions/cruze_version.ts +3 -9
- package/src/main.ts +1 -1
- package/templates/init/AGENTS.md +4 -12
- package/templates/init/ci.yml +3 -3
- package/templates/init/config.yaml +8 -17
- package/templates/init/review/claude.yaml +2 -2
- package/dist/adapters/inbound/cli/argument_files.js +0 -29
- package/dist/adapters/inbound/cli/commands/diff.js +0 -23
- package/dist/adapters/inbound/cli/commands/journal.js +0 -32
- package/dist/adapters/inbound/cli/commands/progress.js +0 -55
- package/dist/adapters/inbound/cli/commands/realign.js +0 -28
- package/dist/adapters/inbound/cli/commands/show.js +0 -96
- package/dist/app/use_cases/abandon_work.js +0 -42
- package/dist/app/use_cases/approve_artifact.js +0 -197
- package/dist/app/use_cases/journal_events.js +0 -64
- package/dist/app/use_cases/land_change.js +0 -134
- package/dist/app/use_cases/new_project_doc.js +0 -48
- package/dist/app/use_cases/new_work_item.js +0 -75
- package/dist/app/use_cases/realign_done.js +0 -45
- package/dist/app/use_cases/realign_status.js +0 -106
- package/dist/app/use_cases/record_progress.js +0 -118
- package/dist/app/use_cases/show_elements.js +0 -18
- package/dist/app/use_cases/show_notes.js +0 -11
- package/dist/app/use_cases/show_scope.js +0 -51
- package/dist/app/use_cases/upstream_diff.js +0 -55
- package/dist/domain/approvals/agent_approval.js +0 -68
- package/dist/domain/approvals/evaluate.js +0 -36
- package/dist/domain/approvals/fingerprint.js +0 -52
- package/dist/domain/approvals/rebase.js +0 -39
- package/dist/domain/approvals/records.js +0 -50
- package/dist/domain/approvals/upstream_text.js +0 -36
- package/dist/domain/architecture_sections.js +0 -23
- package/dist/domain/check/decision_comments.js +0 -38
- package/dist/domain/decision_citations.js +0 -62
- package/dist/domain/edits/agents_file.js +0 -58
- package/dist/domain/edits/managed_tables.js +0 -60
- package/dist/domain/edits/progress_block.js +0 -33
- package/dist/domain/edits/status_lines.js +0 -52
- package/dist/domain/elements.js +0 -126
- package/dist/domain/journal.js +0 -109
- package/dist/domain/land/bookkeeping.js +0 -54
- package/dist/domain/land/merge_plan.js +0 -137
- package/dist/domain/land/text_ops.js +0 -66
- package/dist/domain/line_diff.js +0 -56
- package/dist/domain/project/artifact_ref.js +0 -42
- package/dist/domain/project/deltas.js +0 -49
- package/dist/domain/project/element_lookup.js +0 -124
- package/dist/domain/project/living_model.js +0 -55
- package/dist/domain/project/new_items.js +0 -48
- package/dist/domain/project/notes.js +0 -74
- package/dist/domain/project/plan_parts.js +0 -111
- package/dist/domain/project/progress.js +0 -43
- package/dist/domain/project/project_view.js +0 -72
- package/dist/domain/project/roadmap.js +0 -43
- package/dist/domain/project/scope_view.js +0 -134
- package/dist/domain/project/work_items.js +0 -68
- package/dist/domain/status/next_step.js +0 -181
- package/dist/domain/status/pending_rethink.js +0 -22
- package/dist/domain/status/verification.js +0 -29
- package/dist/domain/status/work_status.js +0 -125
- package/dist/domain/validation/decision_rules.js +0 -76
- package/dist/domain/validation/delta_rules.js +0 -81
- package/dist/domain/validation/element_rules.js +0 -104
- package/dist/domain/validation/future_rules.js +0 -40
- package/dist/domain/validation/living_rules.js +0 -99
- package/dist/domain/validation/plan_rules.js +0 -124
- package/dist/domain/validation/project_rules.js +0 -115
- package/dist/domain/validation/size_rules.js +0 -45
- package/dist/domain/validation/vision_rules.js +0 -41
- package/dist/domain/validation/work_item_rules.js +0 -175
- package/dist/domain/versions/realign_notes.js +0 -72
- package/dist/domain/versions/rule_versions.js +0 -29
- package/dist/domain/versions/scheduled_exceptions.js +0 -41
- package/skills/about/SKILL.md +0 -21
- package/skills/architect/SKILL.md +0 -49
- package/skills/architect/feature.md +0 -40
- package/skills/architect/project.md +0 -71
- package/skills/architect/tweak.md +0 -22
- package/skills/architect/walkthrough.md +0 -35
- package/skills/domain-language/SKILL.md +0 -37
- package/skills/envision/feature.md +0 -25
- package/skills/envision/intake.md +0 -28
- package/skills/envision/project.md +0 -24
- package/skills/explore/SKILL.md +0 -39
- package/skills/formats/reference/architecture.md +0 -84
- package/skills/formats/reference/config.md +0 -80
- package/skills/formats/reference/durable-docs.md +0 -74
- package/skills/formats/reference/specs.md +0 -65
- package/skills/formats/reference/work-items.md +0 -100
- package/skills/formats/templates/adr.md +0 -7
- package/skills/formats/templates/change.md +0 -29
- package/skills/formats/templates/glossary.md +0 -8
- package/skills/formats/templates/roadmap.md +0 -32
- package/skills/formats/templates/spec.md +0 -11
- package/skills/formats/templates/standalone-change.md +0 -46
- package/skills/grilling/SKILL.md +0 -90
- package/skills/grilling/illustrating.md +0 -38
- package/skills/improve/SKILL.md +0 -51
- package/skills/land/SKILL.md +0 -48
- package/skills/next/SKILL.md +0 -31
- package/skills/plan/SKILL.md +0 -62
- package/skills/plan/tasks.md +0 -35
- package/skills/plan/test-plan.md +0 -14
- package/skills/realign/SKILL.md +0 -37
- package/skills/realign/notes/0.0.10.md +0 -131
- package/skills/realign/notes/0.0.11.md +0 -15
- package/skills/realign/notes/0.0.12.md +0 -31
- package/skills/realign/notes/0.0.13.md +0 -11
- package/skills/realign/notes/0.0.2.md +0 -69
- package/skills/realign/notes/0.0.3.md +0 -11
- package/skills/realign/notes/0.0.4.md +0 -27
- package/skills/realign/notes/0.0.5.md +0 -38
- package/skills/realign/notes/0.0.6.md +0 -44
- package/skills/realign/notes/0.0.7.md +0 -11
- package/skills/realign/notes/0.0.8.md +0 -97
- package/skills/realign/notes/0.0.9.md +0 -59
- package/skills/realign/notes.md +0 -40
- package/skills/rethink/SKILL.md +0 -62
- package/skills/rethink/levels.md +0 -54
- package/skills/roadmap/SKILL.md +0 -54
- package/skills/roles/auditor.md +0 -35
- package/skills/roles/design-reviewer.md +0 -43
- package/skills/roles/design-rubric.md +0 -41
- package/skills/roles/plan-rubric.md +0 -11
- package/skills/roles/surveyor.md +0 -41
- package/skills/roles/verifier.md +0 -42
- package/skills/triage/SKILL.md +0 -37
- package/skills/verify/SKILL.md +0 -45
- package/skills/verify/manual-test.md +0 -23
- package/src/adapters/inbound/cli/argument_files.ts +0 -29
- package/src/adapters/inbound/cli/commands/diff.ts +0 -23
- package/src/adapters/inbound/cli/commands/journal.ts +0 -32
- package/src/adapters/inbound/cli/commands/progress.ts +0 -55
- package/src/adapters/inbound/cli/commands/realign.ts +0 -28
- package/src/adapters/inbound/cli/commands/show.ts +0 -96
- package/src/app/use_cases/abandon_work.ts +0 -42
- package/src/app/use_cases/approve_artifact.ts +0 -197
- package/src/app/use_cases/journal_events.ts +0 -64
- package/src/app/use_cases/land_change.ts +0 -134
- package/src/app/use_cases/new_project_doc.ts +0 -48
- package/src/app/use_cases/new_work_item.ts +0 -75
- package/src/app/use_cases/realign_done.ts +0 -45
- package/src/app/use_cases/realign_status.ts +0 -106
- package/src/app/use_cases/record_progress.ts +0 -118
- package/src/app/use_cases/show_elements.ts +0 -18
- package/src/app/use_cases/show_notes.ts +0 -11
- package/src/app/use_cases/show_scope.ts +0 -51
- package/src/app/use_cases/upstream_diff.ts +0 -55
- package/src/domain/approvals/agent_approval.ts +0 -68
- package/src/domain/approvals/evaluate.ts +0 -36
- package/src/domain/approvals/fingerprint.ts +0 -52
- package/src/domain/approvals/rebase.ts +0 -39
- package/src/domain/approvals/records.ts +0 -50
- package/src/domain/approvals/upstream_text.ts +0 -36
- package/src/domain/architecture_sections.ts +0 -23
- package/src/domain/check/decision_comments.ts +0 -38
- package/src/domain/decision_citations.ts +0 -62
- package/src/domain/edits/agents_file.ts +0 -58
- package/src/domain/edits/managed_tables.ts +0 -60
- package/src/domain/edits/progress_block.ts +0 -33
- package/src/domain/edits/status_lines.ts +0 -52
- package/src/domain/elements.ts +0 -126
- package/src/domain/journal.ts +0 -109
- package/src/domain/land/bookkeeping.ts +0 -54
- package/src/domain/land/merge_plan.ts +0 -137
- package/src/domain/land/text_ops.ts +0 -66
- package/src/domain/line_diff.ts +0 -56
- package/src/domain/project/artifact_ref.ts +0 -42
- package/src/domain/project/deltas.ts +0 -49
- package/src/domain/project/element_lookup.ts +0 -124
- package/src/domain/project/living_model.ts +0 -55
- package/src/domain/project/new_items.ts +0 -48
- package/src/domain/project/notes.ts +0 -74
- package/src/domain/project/plan_parts.ts +0 -111
- package/src/domain/project/progress.ts +0 -43
- package/src/domain/project/project_view.ts +0 -72
- package/src/domain/project/roadmap.ts +0 -43
- package/src/domain/project/scope_view.ts +0 -134
- package/src/domain/project/work_items.ts +0 -68
- package/src/domain/status/next_step.ts +0 -181
- package/src/domain/status/pending_rethink.ts +0 -22
- package/src/domain/status/verification.ts +0 -29
- package/src/domain/status/work_status.ts +0 -125
- package/src/domain/validation/decision_rules.ts +0 -76
- package/src/domain/validation/delta_rules.ts +0 -81
- package/src/domain/validation/element_rules.ts +0 -104
- package/src/domain/validation/future_rules.ts +0 -40
- package/src/domain/validation/living_rules.ts +0 -99
- package/src/domain/validation/plan_rules.ts +0 -124
- package/src/domain/validation/project_rules.ts +0 -115
- package/src/domain/validation/size_rules.ts +0 -45
- package/src/domain/validation/vision_rules.ts +0 -41
- package/src/domain/validation/work_item_rules.ts +0 -175
- package/src/domain/versions/realign_notes.ts +0 -72
- package/src/domain/versions/rule_versions.ts +0 -29
- package/src/domain/versions/scheduled_exceptions.ts +0 -41
- package/templates/init/gitattributes +0 -2
package/README.md
CHANGED
|
@@ -4,25 +4,38 @@
|
|
|
4
4
|
<img src="docs/assets/cruze-logo.jpg" alt="Cruze" width="720">
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
-
Cruze is a spec-driven
|
|
7
|
+
Cruze is a lightweight spec-driven workflow for coding agents. You and the agent put the product's vision and future features on paper, break the release into features, and agree on an architecture map. Then, one feature at a time, you agree on what it does and what its public API looks like, and the agent builds it test-first with ports and adapters, reviews it in a fresh context, and opens a pull request.
|
|
8
8
|
|
|
9
|
-
It works with any agent that supports the [Agent Skills](https://agentskills.io) format. It ships as one npm package: a `cruze` CLI
|
|
9
|
+
It works with any agent that supports the [Agent Skills](https://agentskills.io) format. It ships as one npm package: a small `cruze` CLI for the deterministic parts (approvals, the next step, scenario-to-test tracing, layer rules) and a set of skills that guide the agent.
|
|
10
10
|
|
|
11
11
|
## Status
|
|
12
12
|
|
|
13
|
-
Version 0.0.
|
|
13
|
+
Version 0.0.14 was a rewrite. The earlier previews ran thirteen steps with design reviews, plans, verifiers, journals and merged living specs. Measured across nine projects, they took about twice the time of a plain design doc and plan for code of the same quality, and asked the user so many questions that most answers were a bare "agree". It kept what paid off and dropped the rest. Nothing is compatible with 0.0.13 projects. Claude Code is the agent tested so far.
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## The flow
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
```
|
|
18
|
+
envision ──► shape ──► build ──► review ──► pull request
|
|
19
|
+
(project start or a major shift)
|
|
20
|
+
|
|
21
|
+
fix: reproduce ──► failing test ──► fix ──► review ──► pull request
|
|
22
|
+
```
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
+
| Step | Who | What comes out | Your part |
|
|
25
|
+
| --- | --- | --- | --- |
|
|
26
|
+
| `envision` | you and the agent | `docs/vision.md`: the problem, users, the release's features and what each needs, future features and what must stay possible. `docs/architecture.md`: ports, adapters, runtime, technology, layers | Answer one round of questions, approve both documents |
|
|
27
|
+
| `shape` | you and the agent | `docs/features/<slug>.md`: behaviour as scenarios, the public API as code, a sketch of how it crosses the stack, the decisions the agent took | Approve it, or say what to change |
|
|
28
|
+
| `build` | the agent | Code built test-first, one scenario at a time; the first feature also sets up CI with a coverage gate | Nothing, unless a scenario or the public API has to change; then you see the change and approve again |
|
|
29
|
+
| `review` | a fresh-context reviewer | Fixes for what it finds, a note on how to try the feature, a pull request | Decide only findings that would change what you approved |
|
|
30
|
+
| `fix` | the agent | A failing test that reproduces the bug, the fix, a review, a pull request | Nothing, unless the right behaviour is your call |
|
|
24
31
|
|
|
25
|
-
|
|
32
|
+
What it holds to:
|
|
33
|
+
|
|
34
|
+
- **You decide behaviour and public APIs; the agent decides the rest.** The agent asks at most one round of questions per step, and lists the choices it made in the document you approve, so nothing about the stack surprises you at the end.
|
|
35
|
+
- **The architecture is designed for what's coming.** Future features shape the boundaries, such as where a port goes, but nothing is built for them until they join a release.
|
|
36
|
+
- **Ports and adapters.** `cruze check` enforces the layer rules in CI.
|
|
37
|
+
- **Behavioural tests.** Every scenario has a test carrying its ID, and `cruze trace` fails CI when one is missing.
|
|
38
|
+
- **Approvals follow the text.** An approved feature edited later shows as edited until you approve it again.
|
|
26
39
|
|
|
27
40
|
## Quick start
|
|
28
41
|
|
|
@@ -32,10 +45,10 @@ Requires Node.js 22.18 or later, and git.
|
|
|
32
45
|
|
|
33
46
|
The skills run `cruze` commands, so the agent needs `cruze` on its path. Install it globally, in one of three ways. `cruze --version` confirms which version you have.
|
|
34
47
|
|
|
35
|
-
From a GitHub Release, without npm
|
|
48
|
+
From a GitHub Release, without npm:
|
|
36
49
|
|
|
37
50
|
```sh
|
|
38
|
-
npm install -g https://github.com/PrintPractical/cruze/releases/download/v0.0.
|
|
51
|
+
npm install -g https://github.com/PrintPractical/cruze/releases/download/v0.0.15/printpractical-cruze-0.0.15.tgz
|
|
39
52
|
```
|
|
40
53
|
|
|
41
54
|
From npm, once a version is published there:
|
|
@@ -44,10 +57,10 @@ From npm, once a version is published there:
|
|
|
44
57
|
npm install -g @printpractical/cruze
|
|
45
58
|
```
|
|
46
59
|
|
|
47
|
-
From the git repository, at a tag or `#main`.
|
|
60
|
+
From the git repository, at a tag or `#main`. npm 11 needs `--install-links` for a global git install, and the first `cruze` command builds the CLI:
|
|
48
61
|
|
|
49
62
|
```sh
|
|
50
|
-
npm install -g --install-links github:PrintPractical/cruze#v0.0.
|
|
63
|
+
npm install -g --install-links github:PrintPractical/cruze#v0.0.15
|
|
51
64
|
```
|
|
52
65
|
|
|
53
66
|
### 2. Set up a repository
|
|
@@ -58,129 +71,59 @@ In the root of the repository:
|
|
|
58
71
|
cruze init
|
|
59
72
|
```
|
|
60
73
|
|
|
61
|
-
When you didn't install from npm, tell `init` where Cruze came from, so the CI it writes runs the same source
|
|
74
|
+
When you didn't install from npm, tell `init` where Cruze came from, so the CI it writes runs the same source:
|
|
62
75
|
|
|
63
76
|
```sh
|
|
64
|
-
cruze init --package https://github.com/PrintPractical/cruze/releases/download/v0.0.
|
|
77
|
+
cruze init --package https://github.com/PrintPractical/cruze/releases/download/v0.0.15/printpractical-cruze-0.0.15.tgz
|
|
65
78
|
```
|
|
66
79
|
|
|
67
|
-
`init` asks for the project name
|
|
68
|
-
|
|
69
|
-
| Path | Purpose |
|
|
70
|
-
| --- | --- |
|
|
71
|
-
| `README.md` | Titled with the project name |
|
|
72
|
-
| `CHANGELOG.md` | In [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format |
|
|
73
|
-
| `AGENTS.md` | Agent instructions; Cruze keeps its managed sections current |
|
|
74
|
-
| `CLAUDE.md` | For Claude Code only: a link to `AGENTS.md` |
|
|
75
|
-
| `.cruze/config.yaml` | Project configuration, including the Cruze version whose skills the project uses, and for Claude Code the command `cruze review` runs |
|
|
76
|
-
| `.github/workflows/ci.yml` | CI that runs `cruze validate`, `check` and `trace`; the foundation change adds the language's build and test steps |
|
|
77
|
-
| `.gitattributes` | Merges Cruze's journals line by line, so parallel branches don't conflict on them |
|
|
78
|
-
| `.agents/skills/cruze-*` | The Cruze skills, also linked into `.claude/skills/` for Claude Code |
|
|
80
|
+
`init` asks for the project name and your coding agent: `claude` for Claude Code, or `other` for any agent that reads `AGENTS.md` and `.agents/skills/`. It creates `README.md`, `CHANGELOG.md`, `AGENTS.md` (and `CLAUDE.md` for Claude Code), `.cruze/config.yaml`, a CI workflow that runs `cruze validate`, `check` and `trace`, and the skills in `.agents/skills/`, linked into `.claude/skills/` for Claude Code. It never overwrites an existing file.
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
### 3. Start
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
Ask your agent to envision the project, and give it whatever you have: a sentence, a design document, a conversation. From then on, `cruze next` says what comes next.
|
|
83
85
|
|
|
84
86
|
## Upgrading
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
1. **Upgrade the CLI** the same way you installed it, naming the new version, then check it with `cruze --version`:
|
|
91
|
-
|
|
92
|
-
```sh
|
|
93
|
-
npm install -g https://github.com/PrintPractical/cruze/releases/download/v<version>/printpractical-cruze-<version>.tgz
|
|
94
|
-
npm install -g @printpractical/cruze@<version>
|
|
95
|
-
npm install -g --install-links github:PrintPractical/cruze#v<version>
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
2. **Update each repository.** In its root, run:
|
|
88
|
+
1. Upgrade the CLI the same way you installed it, naming the new version.
|
|
89
|
+
2. In each repository, run `cruze install`. It replaces the Cruze skills (those named `cruze-*`) and leaves your own alone, records the version in `.cruze/config.yaml`, and moves the CI workflow to the new version when CI runs a published package, a release tarball or a release tag.
|
|
90
|
+
3. Commit the skills, the config and the CI workflow together.
|
|
99
91
|
|
|
100
|
-
|
|
101
|
-
cruze install
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
`install` does three things:
|
|
105
|
-
- It replaces the Cruze skills (those named `cruze-*`) and leaves your own skills alone. Pass `--agent claude` to link them for Claude Code in a repository without `CLAUDE.md` or `.claude/`.
|
|
106
|
-
- It records the new version in `.cruze/config.yaml`.
|
|
107
|
-
- It moves `.github/workflows/ci.yml` to the new version when CI runs the npm package, a release tarball or a release tag. It names any other source, such as a branch, for you to update by hand.
|
|
108
|
-
|
|
109
|
-
3. **Commit** the skills, the config and the CI workflow together, with a message such as `chore: upgrade Cruze to <version>`, so CI runs the version the skills were written for.
|
|
110
|
-
|
|
111
|
-
4. **Realign the code** when it suits you, with the `realign` skill. `cruze realign status` lists what each release since `standards:` expects of existing code: what its CLI rules find, and the questions a fresh-context auditor answers. You decide each finding: fix it in a prefactor change, waive it for good, or defer it. `cruze realign done` then moves `standards:` up. Findings still waiting for their prefactor are listed under `check.exceptions` until it lands, so CI stays green. Add `--full` to audit against every release, such as for a project that adopted Cruze partway. `cruze next` suggests realigning when nothing else is due.
|
|
112
|
-
|
|
113
|
-
An older CLI refuses to install over a repository that already moved to a newer version, so a stale CLI on another machine can't roll it back. To go back on purpose, set `cruze:` in `.cruze/config.yaml` to the older version first, then run that version's `cruze install`.
|
|
92
|
+
When the CLI you run differs from the version the project records, every command notes it on stderr, and `cruze validate` warns.
|
|
114
93
|
|
|
115
94
|
## Commands
|
|
116
95
|
|
|
117
|
-
Skills call these at fixed points, and CI runs `check` and `trace` on every push. Run `cruze help` for every option.
|
|
118
|
-
|
|
119
96
|
| Command | What it does |
|
|
120
97
|
| --- | --- |
|
|
121
|
-
| `cruze
|
|
122
|
-
| `cruze
|
|
123
|
-
| `cruze
|
|
124
|
-
| `cruze
|
|
125
|
-
| `cruze
|
|
126
|
-
| `cruze
|
|
127
|
-
| `cruze
|
|
128
|
-
| `cruze
|
|
129
|
-
| `cruze
|
|
130
|
-
| `cruze
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
| `cruze task done <T#>` | Ticks a task with its commit; `cruze task reopen` unticks one a rethink changed, and `cruze task deviation` records a small departure from the plan |
|
|
134
|
-
| `cruze features <add\|update\|drop>` | Edits the feature map: adds or drops a future feature, or corrects a summary |
|
|
135
|
-
| `cruze roadmap prune` | Clears landed items from the roadmap's status when a release closes |
|
|
136
|
-
| `cruze trace` | Fails when a delivered scenario has no test carrying its ID; `--all` checks every built scenario |
|
|
137
|
-
| `cruze check` | Enforces the layer rules and the file budgets, and warns on decision numbers in code comments; `--ci` also fails on warnings |
|
|
138
|
-
| `cruze review <role>` | Runs a role (design reviewer, code reviewer, verifier, researcher or auditor) in a fresh agent context, through the command in `.cruze/config.yaml`. When no command is set, or its program isn't installed, it prints the role's prompt for the agent to run in a helper of its own |
|
|
139
|
-
| `cruze land` | Merges a verified change into the living docs, re-stamps the approvals the merge would make stale, fills the Commands and Layout sections of `AGENTS.md`, and archives finished work |
|
|
140
|
-
| `cruze realign status` | Lists what the installed Cruze expects of existing code since its `standards:` version, with what the CLI rules find now; `--full` covers every release |
|
|
141
|
-
| `cruze realign done` | Moves `standards:` up once every finding is fixed, waived or scheduled in a change named with `--change` |
|
|
142
|
-
| `cruze abandon <ref>` | Archives a feature or standalone change that stops for good, with its reason, and puts a feature back on the future list |
|
|
143
|
-
| `cruze journal add <event>` | Records a rethink, review round, disposition, verification, override, bug or lesson; `cruze journal list` reads the work in flight's entries, or landed work's too with `--all`; `cruze feedback export` bundles the journal for improving Cruze itself |
|
|
144
|
-
|
|
145
|
-
Stepping back is editing: change an upstream document and every approval that cites a changed element shows as stale, with the element named. Re-approving is the rewind; there are no phases to reset.
|
|
98
|
+
| `cruze init` | Sets up the repository and installs the skills |
|
|
99
|
+
| `cruze install` | Installs or updates the skills |
|
|
100
|
+
| `cruze new vision\|architecture\|feature <slug>` | Starts a document from its template |
|
|
101
|
+
| `cruze validate` | Checks the documents: required sections, scenario IDs, the release's features and needs, leftover template text |
|
|
102
|
+
| `cruze approve <vision\|architecture\|slug>` | Records that you approved a document as it reads now |
|
|
103
|
+
| `cruze status` | Each document's approval and each feature's progress, in release order, and the next step |
|
|
104
|
+
| `cruze next` | The step to run next, and why |
|
|
105
|
+
| `cruze trace [<slug>]` | Fails when a built feature's scenario has no test carrying its ID, or a test names a scenario no feature defines |
|
|
106
|
+
| `cruze check [<file>...] [--ci]` | Enforces the layer rules, and warns on file budgets (fails on them with `--ci`) |
|
|
107
|
+
| `cruze review code-reviewer --feature <slug> --base <commit>` | Runs the code reviewer in a fresh agent context, through the command in `.cruze/config.yaml` |
|
|
108
|
+
|
|
109
|
+
Every command prints JSON when stdout isn't a terminal, and text on a terminal; `--json` and `--text` choose. Errors and notes go to stderr.
|
|
146
110
|
|
|
147
111
|
## Skills
|
|
148
112
|
|
|
149
|
-
`cruze init` and `cruze install` put these into `.agents/skills/`. Agents load them when a situation calls for them, and the workflow skills will load them by path at the step that needs them.
|
|
150
|
-
|
|
151
113
|
| Skill | What it holds |
|
|
152
114
|
| --- | --- |
|
|
153
|
-
| `cruze-
|
|
154
|
-
| `cruze-
|
|
155
|
-
| `cruze-
|
|
156
|
-
| `cruze-
|
|
157
|
-
| `cruze-
|
|
158
|
-
| `cruze-
|
|
159
|
-
| `cruze-
|
|
160
|
-
| `cruze-
|
|
161
|
-
| `cruze-
|
|
162
|
-
| `cruze-
|
|
163
|
-
| `cruze-
|
|
164
|
-
| `cruze-
|
|
165
|
-
| `cruze-next` | Says which step to run next and why |
|
|
166
|
-
| `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 |
|
|
167
|
-
| `cruze-formats` | The format of every Cruze document, with templates |
|
|
168
|
-
| `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++ |
|
|
169
|
-
| `cruze-behavioural-testing` | Which tests to write and at which seam, fakes instead of mocks, and protecting approved scenarios' tests |
|
|
170
|
-
| `cruze-grilling` | Interviewing the user in rounds until decisions settle, and challenging once before deferring |
|
|
171
|
-
| `cruze-domain-language` | Building the glossary and using its words in documents, IDs and code |
|
|
172
|
-
| `cruze-dependency-approval` | No new dependency without your explicit approval, and where approvals are recorded |
|
|
173
|
-
| `cruze-research` | Adopting a mature library before building, and answering questions from primary sources at the right version |
|
|
174
|
-
|
|
175
|
-
## Reporting back
|
|
176
|
-
|
|
177
|
-
Cruze improves from what goes wrong in real projects. Every rethink, review finding, bug and override is recorded in the project's journal, along with each repeated lesson about Cruze's own steps. To send them back, with the `## Known pitfalls` of `AGENTS.md`:
|
|
178
|
-
|
|
179
|
-
```sh
|
|
180
|
-
cruze feedback export --out cruze-feedback.json
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
The export replaces the project name, and the name of whoever approved or recorded each entry, with placeholders. Read it before sharing: summaries can still mention your domain or people. Attach it to an issue at https://github.com/PrintPractical/cruze/issues. Maintainers turn it into changes with the `cruze-retro` skill in this repository.
|
|
115
|
+
| `cruze-envision` | The vision with future features, the release broken into features with their needs, and the architecture map |
|
|
116
|
+
| `cruze-shape` | One feature's behaviour, public API and stack sketch, self-checked and approved by you |
|
|
117
|
+
| `cruze-build` | Building an approved feature test-first, scenario by scenario, and the foundation's CI |
|
|
118
|
+
| `cruze-review` | The fresh-context code review, fixes, and the pull request |
|
|
119
|
+
| `cruze-fix` | A bug from report to reviewed fix |
|
|
120
|
+
| `cruze-asking` | When to ask you and when to decide, and how to show a question with code and diagrams |
|
|
121
|
+
| `cruze-formats` | The format of each document, with templates |
|
|
122
|
+
| `cruze-hexagonal-design` | Ports and adapters with domain-driven design, contracts, runtime ownership, layouts by kind of system, and notes for Rust, Swift and C++ |
|
|
123
|
+
| `cruze-behavioural-testing` | Which tests to write and at which seam, and fakes instead of mocks |
|
|
124
|
+
| `cruze-dependency-approval` | Adopt libraries freely; ask only for significant ones |
|
|
125
|
+
| `cruze-research` | Adopting a mature library before building, and answering questions from primary sources |
|
|
126
|
+
| `cruze-roles` | The fresh-context code reviewer and researcher, and how to run them |
|
|
184
127
|
|
|
185
128
|
## Development
|
|
186
129
|
|
|
@@ -1,32 +1,19 @@
|
|
|
1
1
|
import { posix } from "node:path";
|
|
2
2
|
import { checkCode, traceTests } from "../../../../app/use_cases/check_code.js";
|
|
3
|
-
import { landChange } from "../../../../app/use_cases/land_change.js";
|
|
4
3
|
|
|
5
4
|
|
|
6
5
|
export async function runCheck(context , args , options ) {
|
|
7
|
-
const files =
|
|
6
|
+
const files = args.map((file) => posix.normalize(posix.join(context.workingDirectory, file)));
|
|
8
7
|
const report = await checkCode(context, { ci: options.ci, ...(files.length === 0 ? {} : { files }) });
|
|
9
|
-
const lines = report.findings.map((f) => `${f.severity} ${f.path}${f.line === undefined ? "" : `:${f.line}`} ${f.message} [${f.rule}]
|
|
8
|
+
const lines = report.findings.map((f) => `${f.severity} ${f.path}${f.line === undefined ? "" : `:${f.line}`} ${f.message} [${f.rule}]`);
|
|
10
9
|
lines.push(`Checked ${report.checked} file(s): ${report.passed ? "passed" : "failed"}.`);
|
|
11
10
|
return { json: report, human: lines.join("\n"), failed: !report.passed };
|
|
12
11
|
}
|
|
13
12
|
|
|
14
|
-
export async function runTrace(context ,
|
|
15
|
-
const report = await traceTests(context,
|
|
13
|
+
export async function runTrace(context , args ) {
|
|
14
|
+
const report = await traceTests(context, args[0]);
|
|
16
15
|
const lines = report.missing.map((id) => `missing test for ${id}`);
|
|
17
|
-
lines.push(...report.unknown.map((u) => `${u.path}:${u.line} cites ${u.id}, which no
|
|
16
|
+
lines.push(...report.unknown.map((u) => `${u.path}:${u.line} cites ${u.id}, which no feature defines`));
|
|
18
17
|
lines.push(`Traced ${report.scenarios.length} scenario(s) for ${report.scope}: ${report.passed ? "passed" : "failed"}.`);
|
|
19
18
|
return { json: report, human: lines.join("\n"), failed: !report.passed };
|
|
20
19
|
}
|
|
21
|
-
|
|
22
|
-
export async function runLand(context , args , options ) {
|
|
23
|
-
const report = await landChange(context, args[0], options.override === undefined ? {} : { override: options.override });
|
|
24
|
-
const lines = [`Landed ${report.change}.`];
|
|
25
|
-
if (report.merged.length > 0) lines.push(`Merged into the living docs: ${report.merged.join(", ")}`);
|
|
26
|
-
if (report.built.length > 0) lines.push(`Now built: ${report.built.join(", ")}`);
|
|
27
|
-
if (report.removed.length > 0) lines.push(`Removed: ${report.removed.join(", ")}`);
|
|
28
|
-
if (report.restamped.length > 0) lines.push(`Re-stamped approvals: ${report.restamped.join(", ")}`);
|
|
29
|
-
if (report.unexcepted.length > 0) lines.push(`CI checks these again, now that the change realign scheduled them in has landed: ${report.unexcepted.join(", ")}`);
|
|
30
|
-
if (report.archivedTo !== undefined) lines.push(`Finished; archived to ${report.archivedTo}.`);
|
|
31
|
-
return { json: report, human: lines.join("\n") };
|
|
32
|
-
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { createWorkItem, } from "../../../../app/use_cases/new_work_item.js";
|
|
1
|
+
import { approveDocument } from "../../../../app/use_cases/approve_document.js";
|
|
2
|
+
import { DOCUMENT_KINDS, createDocument, } from "../../../../app/use_cases/new_document.js";
|
|
4
3
|
import { validate } from "../../../../app/use_cases/validate_project.js";
|
|
5
4
|
|
|
6
|
-
import { UsageError, requireArgs,
|
|
5
|
+
import { UsageError, requireArgs, } from "../cli_context.js";
|
|
7
6
|
|
|
8
7
|
export async function runValidate(context ) {
|
|
9
8
|
const report = await validate(context);
|
|
@@ -11,44 +10,19 @@ export async function runValidate(context ) {
|
|
|
11
10
|
return { json: report, human: [...report.problems.map(formatProblem), summary].join("\n"), failed: !report.valid };
|
|
12
11
|
}
|
|
13
12
|
|
|
14
|
-
export async function runApprove(context , args
|
|
13
|
+
export async function runApprove(context , args ) {
|
|
15
14
|
requireArgs(args, ["document"]);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const report = await approveArtifact(context, args[0] ?? "", { replan: options.replan, rebase: options.rebase, ...(agent === undefined ? {} : { agent }) });
|
|
19
|
-
const lines = [`Approved ${report.artifact} (${report.hash.slice(0, 19)}), pinned to ${report.upstream.length} upstream element(s).`];
|
|
20
|
-
if (report.basis === "plan-review") lines.push("Approved for the user: its plan review closed with no blocker open.");
|
|
21
|
-
if (report.restamped !== undefined) lines.push(`Re-stamped for the user: its own design is unchanged, and only ${report.restamped.join(", ")} changed.`);
|
|
22
|
-
if (report.stamped.length > 0) lines.push(`Marked ${report.stamped.length} element(s) planned.`);
|
|
23
|
-
if (report.bound !== undefined) lines.push(`Bound the change to branch ${report.bound}.`);
|
|
24
|
-
if (report.replanned.length > 0) lines.push(`Set back to planned: ${report.replanned.join(", ")}.`);
|
|
25
|
-
if (report.rebased.length > 0) lines.push(`Accepted the current living text of: ${report.rebased.join(", ")}.`);
|
|
26
|
-
return { json: report, human: lines.join("\n") };
|
|
15
|
+
const record = await approveDocument(context, args[0] ?? "");
|
|
16
|
+
return { json: record, human: `Approved ${record.path} (${record.hash.slice(0, 19)}).` };
|
|
27
17
|
}
|
|
28
18
|
|
|
29
19
|
export async function runNew(context , args , options ) {
|
|
30
20
|
requireArgs(args, ["kind"]);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (args[0] === "note") {
|
|
37
|
-
const report = await createNote(context, args[1] ?? "", requireOption(options.title, "--title"), requireOption(options.kind, "--kind"), requireOption(options.about, "--about"));
|
|
38
|
-
return { json: report, human: `Created ${report.path}` };
|
|
39
|
-
}
|
|
40
|
-
const kind = args[0] ;
|
|
41
|
-
if (!["feature", "change", "adr"].includes(kind)) {
|
|
42
|
-
throw new UsageError(`cruze new takes ${PROJECT_DOC_KINDS.join(", ")}, feature, change, adr or note, not "${args[0]}"`);
|
|
43
|
-
}
|
|
44
|
-
const report = await createWorkItem(context, {
|
|
45
|
-
kind,
|
|
46
|
-
slug: args[1] ?? "",
|
|
47
|
-
title: requireOption(options.title, "--title"),
|
|
48
|
-
...(options.feature === undefined ? {} : { feature: options.feature }),
|
|
49
|
-
...(options.roadmap === undefined ? {} : { roadmap: options.roadmap }),
|
|
50
|
-
});
|
|
51
|
-
return { json: report, human: `Created ${report.kind} ${report.ref} at ${report.path}` };
|
|
21
|
+
const kind = args[0] ;
|
|
22
|
+
if (!DOCUMENT_KINDS.includes(kind)) throw new UsageError(`cruze new takes ${DOCUMENT_KINDS.join(", ")}, not "${args[0]}"`);
|
|
23
|
+
if (kind === "feature") requireArgs(args, ["kind", "slug"]);
|
|
24
|
+
const report = await createDocument(context, kind, args[1], options.title);
|
|
25
|
+
return { json: report, human: `Created ${report.path}` };
|
|
52
26
|
}
|
|
53
27
|
|
|
54
28
|
export function formatProblem(problem ) {
|
|
@@ -18,6 +18,6 @@ export async function runInit(context , _args , options
|
|
|
18
18
|
if (report.created.length > 0) lines.push(`Created: ${report.created.join(", ")}`);
|
|
19
19
|
if (report.skipped.length > 0) lines.push(`Left untouched (already present): ${report.skipped.join(", ")}`);
|
|
20
20
|
lines.push(...describeSkillInstall(report.skills));
|
|
21
|
-
lines.push("Next: open your coding agent in this repository and ask it
|
|
21
|
+
lines.push("Next: open your coding agent in this repository and ask it to envision the project, with whatever you have: a sentence, a design document, notes.");
|
|
22
22
|
return { json: report, human: lines.join("\n") };
|
|
23
23
|
}
|
|
@@ -15,5 +15,6 @@ export function describeSkillInstall(report ) {
|
|
|
15
15
|
if (from !== to) lines.push(`Recorded Cruze ${to} in .cruze/config.yaml${from === undefined ? "" : `, up from ${from}`}`);
|
|
16
16
|
if (ci.repinned.length > 0) lines.push(`CI runs ${ci.repinned.join(", ")}`);
|
|
17
17
|
for (const spec of ci.unrecognised) lines.push(`CI runs ${spec}, which Cruze can't move to ${to}; update .github/workflows/ci.yml yourself`);
|
|
18
|
+
for (const note of report.notes) lines.push(`Note: ${note}`);
|
|
18
19
|
return lines;
|
|
19
20
|
}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
import { runReview } from "../../../../app/use_cases/run_review.js";
|
|
2
|
-
import {
|
|
3
|
-
import { UsageError, requireArgs, } from "../cli_context.js";
|
|
2
|
+
import { requireArgs, } from "../cli_context.js";
|
|
4
3
|
|
|
5
4
|
export async function runReviewCommand(context , args , options ) {
|
|
6
5
|
requireArgs(args, ["role"]);
|
|
7
|
-
const round = options.round === undefined ? undefined : Number(options.round);
|
|
8
|
-
if (round !== undefined && round !== 1 && round !== 2) throw new UsageError("--round is 1 or 2");
|
|
9
|
-
if (options.blockers !== undefined && round !== 2) throw new UsageError("--blockers goes with --round 2");
|
|
10
|
-
const blockers = options.blockers === undefined ? undefined : await readArgumentFile(options.blockers);
|
|
11
6
|
const report = await runReview(context, {
|
|
12
7
|
role: args[0] ?? "",
|
|
13
|
-
...(options.
|
|
14
|
-
...(round === undefined ? {} : { round }),
|
|
15
|
-
...(blockers === undefined ? {} : { blockers }),
|
|
8
|
+
...(options.feature === undefined ? {} : { item: options.feature }),
|
|
16
9
|
...(options.base === undefined ? {} : { base: options.base }),
|
|
17
10
|
});
|
|
18
11
|
return { json: report, human: report.status === "reported" ? report.report : `${report.instruction}\n\n${report.prompt}` };
|
|
@@ -1,71 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { showStatus, suggestNext } from "../../../../app/use_cases/project_status.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
4
|
|
|
5
|
-
export async function runStatus(context
|
|
6
|
-
if (options.override !== undefined && options.gate === undefined) throw new UsageError("--override goes with --gate build");
|
|
7
|
-
if (options.change !== undefined && !options.overlap) throw new UsageError("--change goes with --overlap");
|
|
8
|
-
if (options.gate !== undefined && options.overlap) throw new UsageError("--gate and --overlap are alternatives");
|
|
9
|
-
if (options.gate !== undefined) {
|
|
10
|
-
if (options.gate !== "build") throw new UsageError(`unknown gate "${options.gate}"; the only gate is build`);
|
|
11
|
-
const report = await checkBuildGate(context, options.override);
|
|
12
|
-
const human = report.passed
|
|
13
|
-
? report.overridden ? `Build gate overridden and journaled:\n ${report.reasons.join("\n ")}` : "Build gate passed."
|
|
14
|
-
: `Build gate blocked:\n ${report.reasons.join("\n ")}`;
|
|
15
|
-
return { json: report, human, failed: !report.passed };
|
|
16
|
-
}
|
|
17
|
-
if (options.overlap) {
|
|
18
|
-
const report = await findOverlaps(context, options.change);
|
|
19
|
-
const human = report.overlaps.length === 0
|
|
20
|
-
? `No other branch touches what ${report.change} touches.`
|
|
21
|
-
: report.overlaps.map((o) => `${o.branch}: ${o.item} also touches ${o.shared.join(", ")}`).join("\n");
|
|
22
|
-
return { json: report, human };
|
|
23
|
-
}
|
|
5
|
+
export async function runStatus(context ) {
|
|
24
6
|
const report = await showStatus(context);
|
|
25
|
-
const lines =
|
|
26
|
-
for (const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const name = change.ref.split("/")[1] ?? change.ref;
|
|
31
|
-
lines.push(change.landed !== undefined ? ` ${name}: landed ${change.landed}` : ` ${describe(name, change.approval)}, tasks ${change.tasksDone}/${change.tasksTotal}${pendingNote(change.rethinkPending)}`);
|
|
32
|
-
}
|
|
7
|
+
const lines = report.documents.map((d) => `${d.path}: ${d.state}`);
|
|
8
|
+
for (const f of report.features) {
|
|
9
|
+
const needs = f.needs.length === 0 ? "" : `, needs ${f.needs.join(", ")}`;
|
|
10
|
+
const approval = f.approval === "missing" ? "" : `, ${f.approval}`;
|
|
11
|
+
lines.push(`${f.slug}: ${f.status}${approval}${f.scenarios === 0 ? "" : `, ${f.scenarios} scenario(s)`}${needs}${f.inRelease ? "" : " (not in the release)"}`);
|
|
33
12
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
...report,
|
|
37
|
-
documents: report.documents.map(compact),
|
|
38
|
-
features: report.features.map((f) => ({ ...f, approval: compact(f.approval), changes: f.changes.map((c) => ({ ...c, approval: compact(c.approval) })) })),
|
|
39
|
-
standalone: report.standalone.map((c) => ({ ...c, approval: compact(c.approval) })),
|
|
40
|
-
};
|
|
41
|
-
return { json, human: lines.join("\n") };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** The state without the record's hashes: an agent reads status often, and the hashes were a third of each read. */
|
|
45
|
-
function compact(status ) {
|
|
46
|
-
const { record, ...rest } = status;
|
|
47
|
-
if (record === undefined) return rest;
|
|
48
|
-
return { ...rest, approvedAt: record.approvedAt, by: record.by, ...(record.basis === undefined ? {} : { basis: record.basis }) };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function pendingNote(findings ) {
|
|
52
|
-
return findings === undefined ? "" : `, ${findings.length} finding(s) waiting on a rethink`;
|
|
13
|
+
lines.push(`Next: ${describe(report.next)}`);
|
|
14
|
+
return { json: report, human: lines.join("\n") };
|
|
53
15
|
}
|
|
54
16
|
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
const BASIS = { "plan-review": " (by the agent, after its plan review)", rethink: " (re-stamped by the agent after a rethink)" };
|
|
59
|
-
|
|
60
|
-
function describe(label , status ) {
|
|
61
|
-
const byAgent = status.state === "approved" ? BASIS[status.record?.basis ?? ""] ?? "" : "";
|
|
62
|
-
const detail = status.changed.length > 0 ? ` (${status.changed.join(", ")})` : status.unjournaled === true ? " (no journal entry)" : byAgent;
|
|
63
|
-
return `${label}: ${status.state}${detail}`;
|
|
17
|
+
export async function runNext(context ) {
|
|
18
|
+
const next = await suggestNext(context);
|
|
19
|
+
return { json: next, human: `Next: ${describe(next)}` };
|
|
64
20
|
}
|
|
65
21
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const describe = (s ) => `${s.step}${s.target === undefined ? "" : ` ${s.target}`}: ${s.reason}`;
|
|
69
|
-
const lines = [`Next: ${describe(report.next)}`, ...report.also.map((s) => `Also: ${describe(s)}`), FRESH_SESSION];
|
|
70
|
-
return { json: { ...report, session: FRESH_SESSION }, human: lines.join("\n") };
|
|
22
|
+
function describe(step ) {
|
|
23
|
+
return `${step.step}${step.target === undefined ? "" : ` ${step.target}`}: ${step.reason}`;
|
|
71
24
|
}
|