@printpractical/cruze 0.0.13 → 0.0.14
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/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/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 +4 -4
- package/dist/domain/approvals.js +51 -0
- package/dist/domain/check/check_source.js +2 -31
- 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 +70 -0
- package/dist/domain/validation/release_rules.js +45 -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 +21 -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/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/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 +4 -4
- package/src/domain/approvals.ts +51 -0
- package/src/domain/check/check_source.ts +2 -31
- 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 +70 -0
- package/src/domain/validation/release_rules.ts +45 -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
|
@@ -1,38 +1,29 @@
|
|
|
1
1
|
# Code reviewer
|
|
2
2
|
|
|
3
|
-
You review the code
|
|
3
|
+
You review the code of one feature before it lands, in a fresh context. You ask two things: does the code do what the user approved, and will it hold up when it runs. You report findings, and you edit nothing.
|
|
4
4
|
|
|
5
5
|
## Inputs
|
|
6
6
|
|
|
7
|
-
- The
|
|
8
|
-
- The diff under review, from `git diff <base>` for the base commit you are given.
|
|
9
|
-
-
|
|
10
|
-
- The
|
|
11
|
-
- The settled ledger, as `.agents/skills/cruze-roles/SKILL.md` defines it, with the output of `cruze journal list --event disposition --item <ref>`.
|
|
12
|
-
- The deviations the change recorded, from `cruze journal list --event deviation --item <ref>`.
|
|
13
|
-
- The output of `cruze check` and `cruze trace --change <ref>`.
|
|
7
|
+
- The feature file in `docs/features/`: its scenarios, public API, stack sketch and decisions. This is what the user approved.
|
|
8
|
+
- The diff under review, from `git diff <base>` for the base commit you are given.
|
|
9
|
+
- `docs/architecture.md`, at the ports, runtime and layers the diff touches.
|
|
10
|
+
- The output of `cruze check` and `cruze trace <slug>`.
|
|
14
11
|
- The standards: `.agents/skills/cruze-hexagonal-design/SKILL.md`, its language file for the project's language when one exists, `.agents/skills/cruze-behavioural-testing/SKILL.md` and `.agents/skills/cruze-dependency-approval/SKILL.md`.
|
|
15
12
|
|
|
13
|
+
You may run the project's tests.
|
|
14
|
+
|
|
16
15
|
## Rubric
|
|
17
16
|
|
|
18
17
|
Review against these items and nothing else. Each finding names one.
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
5. **Placement.** Every file the diff adds or changes is where the architecture puts its owner, and matches the task's file targets or a recorded deviation.
|
|
30
|
-
6. **Direction.** Dependencies point inward. No technology type crosses a port. Inbound adapters hold no domain rules or workflow.
|
|
31
|
-
7. **Size.** No file holds two responsibilities, and none passes its budget without a recorded exception. No file was split by length alone, leaving one responsibility across files, and no code is bent to fit a budget, such as a type alias, a string where an error type belongs, types merged or a function placed away from its owner to stay under a limit.
|
|
32
|
-
8. **Idiom.** The code is idiomatic for the language, uses its standard tooling, and follows the language file's rules, including where tests live. Tests reuse the fixtures and harnesses in the test support module rather than redefining them. Each `expect`, `unwrap` or panic in the diff has a reason its case can't happen; one a caller, the clock or a concurrent call can reach is a finding.
|
|
33
|
-
9. **Libraries.** Nothing hand-writes what a mature library does without a recorded `build` decision, and every new dependency has a recorded approval. No code works around a dependency or a feature: hand-written code, a shell command or a less idiomatic construct chosen because the clean one needs a dependency is a finding.
|
|
34
|
-
10. **Contracts.** Each adapter honours its port's `Operations`, and each fake passes the same contract tests as the real adapter.
|
|
35
|
-
11. **Deviations.** Each deviation the change recorded is a choice build may make on its own: a private helper or a new file inside the owner's module, a `check.exceptions` entry, a fixture in the test support module, or two tasks swapped. A deviation that added an element, port operation or scenario, wrote a file outside the owner's module, changed an approved scenario's behaviour or its test, worked around a dependency or a feature, or settled a limit, timeout, message or error case the design doesn't give, needed a design amendment: a blocker, with `Needs design change` naming the element.
|
|
19
|
+
1. **Scenarios.** Every scenario is implemented and has a test that carries its ID, drives a public seam, and takes its expected values from the scenario. Each failure scenario produces the message and leaves the state it specifies.
|
|
20
|
+
2. **Public API.** What the code exposes matches the feature's public API section: names, types, errors, commands and output. Anything public it doesn't list is a finding.
|
|
21
|
+
3. **Runtime.** Follow each request, message and event from its source to its consumer through every task, channel and queue. Look for what tests rarely reach: a hang, a spin, a leak of a task, handle or memory, a race, unbounded growth, a full queue holding up unrelated work, a lost result across a reconnect, shutdown that waits forever or drops work it promised to finish.
|
|
22
|
+
4. **Failures.** Each external call's failure is handled as the feature and the architecture say: disks, networks, peers and user mistakes. Nothing is silently swallowed.
|
|
23
|
+
5. **Ports and adapters.** Dependencies point inward and match the layers. No technology type crosses a port. Inbound adapters hold no domain rules. Each fake passes the same contract tests as its real adapter.
|
|
24
|
+
6. **Tests.** No test was weakened, skipped or deleted. Tests drive behaviour through public interfaces rather than restating what a fake was told.
|
|
25
|
+
7. **Idiom.** The code is idiomatic for the language and follows its language file. Each `expect`, `unwrap` or panic has a reason its case can't happen.
|
|
26
|
+
8. **Libraries.** Nothing hand-writes what a mature library does, and every significant dependency is in the architecture or approved.
|
|
36
27
|
|
|
37
28
|
## Findings
|
|
38
29
|
|
|
@@ -42,17 +33,15 @@ Each finding has this shape:
|
|
|
42
33
|
### <n>. <rubric item>: <one-line summary>
|
|
43
34
|
- Severity: blocker | concern
|
|
44
35
|
- Evidence: <path:line, quoting the code>
|
|
45
|
-
- Failure scenario: <
|
|
36
|
+
- Failure scenario: <who meets it, how, and what goes wrong>
|
|
46
37
|
- Proposed fix: <the specific change>
|
|
47
|
-
-
|
|
38
|
+
- Changes what the user approved: <the scenario or public API the fix changes, or no>
|
|
48
39
|
```
|
|
49
40
|
|
|
50
|
-
- A **blocker**
|
|
51
|
-
- Everything else is a **concern
|
|
52
|
-
- List every blocker
|
|
53
|
-
- Drop any finding that contradicts the settled ledger. The only exception is a blocker with new evidence, which you mark `New evidence:` and explain.
|
|
54
|
-
- When a finding could be caught mechanically, add `Check: <the cruze check rule or linter setting that would catch it>`.
|
|
41
|
+
- A **blocker** is a scenario that fails or has no test, a public API that differs from the approved one, a broken layer rule, or a failure that someone using the product in an ordinary way reaches and that loses or corrupts data, crashes, hangs, spins, or holds up other work.
|
|
42
|
+
- Everything else is a **concern**. Say who reaches it and how. A failure that only deliberately malformed input reaches, and that harms only its sender, is a concern.
|
|
43
|
+
- List every blocker, and at most 5 concerns, the most important first. Count the rest as nits by number only. No findings is a valid report.
|
|
55
44
|
|
|
56
45
|
## Report
|
|
57
46
|
|
|
58
|
-
|
|
47
|
+
List the findings, then end with one line: `Blockers: <n>. Concerns: <n>. Nits: <n>.`
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Researcher
|
|
2
2
|
|
|
3
|
-
You find out whether mature libraries already provide the components
|
|
3
|
+
You find out whether mature libraries already provide the components the architecture needs, and you answer technical questions from primary sources. You report what you found, and you edit nothing in the project.
|
|
4
4
|
|
|
5
5
|
## Inputs
|
|
6
6
|
|
|
7
|
-
- The components to research. For each: the capability in one line, the requirements that matter
|
|
7
|
+
- The components to research. For each: the capability in one line, and the requirements that matter.
|
|
8
8
|
- Or a question, with the version it applies to.
|
|
9
9
|
- The constraints section of `docs/vision.md`.
|
|
10
10
|
- The project's dependency manifests and lockfiles, if they exist.
|
|
@@ -25,7 +25,7 @@ For components, report one block each:
|
|
|
25
25
|
| <component> | adopt or build | <package and version, when adopting> | <the deciding reason> |
|
|
26
26
|
|
|
27
27
|
Evidence: <the evaluation table for the serious candidates, with sources and the date checked>
|
|
28
|
-
New dependency: yes or
|
|
28
|
+
New dependency: no, yes, or significant with the reason
|
|
29
29
|
Claims to verify: <each feature, flag or command the design would rely on, with where the source shows it>
|
|
30
30
|
```
|
|
31
31
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cruze-shape
|
|
3
|
+
description: Shapes one feature with the user before it is built, writing its behaviour as scenarios, its public API as code and a sketch of how it crosses the stack, and ends with the user's approval.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Shape
|
|
7
|
+
|
|
8
|
+
Shape is where the user decides what a feature does and what it looks like from outside, before any code exists. It produces one document, `docs/features/<slug>.md`, and one approval. Everything the user would otherwise discover at the end, such as an internal type they wouldn't have chosen or a thread they didn't expect, is shown here instead.
|
|
9
|
+
|
|
10
|
+
Read `.agents/skills/cruze-asking/SKILL.md` and `.agents/skills/cruze-formats/SKILL.md`, and `.agents/skills/cruze-hexagonal-design/SKILL.md` with its language file.
|
|
11
|
+
|
|
12
|
+
## Steps
|
|
13
|
+
|
|
14
|
+
1. **Find the feature.** Run `cruze next`, or take the slug the user names. Read its row in the vision's Release table, `docs/architecture.md`, and the feature files of what it needs. Work on a branch named for the feature. Done when you know what the feature is for and what it builds on.
|
|
15
|
+
2. **Start the document** with `cruze new feature <slug> --title "<title>"`, unless it exists.
|
|
16
|
+
3. **Write the behaviour.** For the feature's intent, write the scenarios: the main case first, then each edge and each failure a user can meet, with concrete values. Each one is a Given, a When and a Then, in the user's words, with the exact message or output they see. Invent the edge cases a user would hit: empty input, a duplicate, the thing not there, the network gone, the limit reached.
|
|
17
|
+
4. **Write the public API** as real code in the project's language: every public type, function, command, endpoint, message or file format this feature adds or changes, with its errors. For a command-line tool, the commands and their exact output. Write "No change." when the feature has none.
|
|
18
|
+
5. **Sketch the stack.** A plain-text diagram of the main scenario crossing the stack: the inbound adapter, the use case, the domain, each port and the adapter behind it, marking what is new. Below it, one line per change to `docs/architecture.md`, such as a new port or a new runtime task, and make those changes there. Name any value the system's own components pass each other untyped or encoded, such as a JSON value, and any new thread, task or queue.
|
|
19
|
+
6. **Check it yourself** against [self-check.md](self-check.md), and fix what it finds. Done when every item passes.
|
|
20
|
+
7. **Ask what only the user can answer,** in at most one round, as the asking skill says. Write the answers in.
|
|
21
|
+
8. **Show it.** In one message:
|
|
22
|
+
- what the feature does, in two sentences;
|
|
23
|
+
- each scenario in one line, as the user would see it;
|
|
24
|
+
- the public API as code;
|
|
25
|
+
- the stack sketch;
|
|
26
|
+
- the decisions you took, one line each.
|
|
27
|
+
|
|
28
|
+
End with: "Do you approve this feature, or what should change?" Apply changes, and say what moved. Done when the user approves.
|
|
29
|
+
9. **Approve and commit.** Run `cruze approve <slug>`, then commit the feature file and any architecture change with a message such as `docs: shape <slug>`.
|
|
30
|
+
|
|
31
|
+
## Changing an approved feature
|
|
32
|
+
|
|
33
|
+
Shape also runs when build finds that a scenario or the public API must change. Edit the document, show the user exactly what changed, with the before and after as code or output, and approve again. `cruze status` shows the feature as edited until then.
|
|
34
|
+
|
|
35
|
+
## Next step
|
|
36
|
+
|
|
37
|
+
`build`, for the approved feature.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Self-check before showing a feature
|
|
2
|
+
|
|
3
|
+
Read the feature as an implementer who never saw the conversation. Each "no" is a gap build would fill with a guess; fix it in the document.
|
|
4
|
+
|
|
5
|
+
1. **Every failure has a scenario.** For each external call the feature makes, and each input a user gives, the scenarios say what the user sees when it fails: the message, the exit code or the screen, and what state is left behind.
|
|
6
|
+
2. **Every number is written down.** Each timeout, limit, buffer size, retry count and poll interval the feature depends on has a value, in the scenario or the architecture's runtime.
|
|
7
|
+
3. **Every queue says what happens when it is full.** For each channel, buffer or queue the feature adds: what a sender does when it is full, and which other work waits meanwhile. One slow peer holds up only its own work unless a decision says otherwise.
|
|
8
|
+
4. **Shutdown and recovery are covered.** What happens to work in flight when the process stops, a connection drops, or a dependency comes back.
|
|
9
|
+
5. **The public API is complete.** Every error a caller can meet is named in the code sketch. Nothing public exists only for a later feature.
|
|
10
|
+
6. **The ports stay ports.** No technology type, such as a database row, an HTTP request or a JSON value, crosses into the domain or the use cases.
|
|
11
|
+
7. **Nothing is built ahead of need.** Every type, field and operation in the sketch is used by one of this feature's scenarios. A future feature leaves room; it adds nothing now.
|
|
12
|
+
8. **Each scenario can be tested** through a public interface, with the values it states.
|
|
@@ -34,36 +34,9 @@ export interface Options {
|
|
|
34
34
|
text: boolean;
|
|
35
35
|
title?: string;
|
|
36
36
|
feature?: string;
|
|
37
|
-
roadmap?: string;
|
|
38
|
-
change?: string;
|
|
39
|
-
commit?: string;
|
|
40
|
-
summary?: string;
|
|
41
|
-
goals?: string;
|
|
42
|
-
reason?: string;
|
|
43
|
-
set: string[];
|
|
44
|
-
item?: string;
|
|
45
|
-
event?: string;
|
|
46
|
-
out?: string;
|
|
47
|
-
redact: boolean;
|
|
48
|
-
all: boolean;
|
|
49
|
-
file: string[];
|
|
50
37
|
ci: boolean;
|
|
51
|
-
gate?: string;
|
|
52
|
-
override?: string;
|
|
53
|
-
overlap: boolean;
|
|
54
|
-
full: boolean;
|
|
55
|
-
replan: string[];
|
|
56
|
-
rebase: string[];
|
|
57
|
-
byAgent: boolean;
|
|
58
|
-
restampUnchanged: boolean;
|
|
59
|
-
index: boolean;
|
|
60
|
-
notes: boolean;
|
|
61
|
-
kind?: string;
|
|
62
|
-
about?: string;
|
|
63
|
-
round?: string;
|
|
64
38
|
package?: string;
|
|
65
39
|
base?: string;
|
|
66
|
-
blockers?: string;
|
|
67
40
|
}
|
|
68
41
|
|
|
69
42
|
export type Handler = (context: CliContext, args: string[], options: Options) => Promise<CommandResult>;
|
|
@@ -1,32 +1,19 @@
|
|
|
1
1
|
import { posix } from "node:path";
|
|
2
2
|
import { checkCode, traceTests } from "../../../../app/use_cases/check_code.ts";
|
|
3
|
-
import { landChange } from "../../../../app/use_cases/land_change.ts";
|
|
4
3
|
import type { CliContext, CommandResult, Options } from "../cli_context.ts";
|
|
5
4
|
|
|
6
5
|
export async function runCheck(context: CliContext, args: string[], options: Options): Promise<CommandResult> {
|
|
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: CliContext,
|
|
15
|
-
const report = await traceTests(context,
|
|
13
|
+
export async function runTrace(context: CliContext, args: string[]): Promise<CommandResult> {
|
|
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: CliContext, args: string[], options: Options): Promise<CommandResult> {
|
|
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, type NewKind } from "../../../../app/use_cases/new_work_item.ts";
|
|
1
|
+
import { approveDocument } from "../../../../app/use_cases/approve_document.ts";
|
|
2
|
+
import { DOCUMENT_KINDS, createDocument, type DocumentKind } from "../../../../app/use_cases/new_document.ts";
|
|
4
3
|
import { validate } from "../../../../app/use_cases/validate_project.ts";
|
|
5
4
|
import type { Problem } from "../../../../domain/validation/problem.ts";
|
|
6
|
-
import { UsageError, requireArgs,
|
|
5
|
+
import { UsageError, requireArgs, type CliContext, type CommandResult, type Options } from "../cli_context.ts";
|
|
7
6
|
|
|
8
7
|
export async function runValidate(context: CliContext): Promise<CommandResult> {
|
|
9
8
|
const report = await validate(context);
|
|
@@ -11,44 +10,19 @@ export async function runValidate(context: CliContext): Promise<CommandResult> {
|
|
|
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: CliContext, args: string[]
|
|
13
|
+
export async function runApprove(context: CliContext, args: string[]): Promise<CommandResult> {
|
|
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: CliContext, args: string[], options: Options): Promise<CommandResult> {
|
|
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] as NewKind;
|
|
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] as DocumentKind;
|
|
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: Problem): string {
|
|
@@ -18,6 +18,6 @@ export async function runInit(context: CliContext, _args: string[], options: Opt
|
|
|
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
|
}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
import { runReview } from "../../../../app/use_cases/run_review.ts";
|
|
2
|
-
import {
|
|
3
|
-
import { UsageError, requireArgs, type CliContext, type CommandResult, type Options } from "../cli_context.ts";
|
|
2
|
+
import { requireArgs, type CliContext, type CommandResult, type Options } from "../cli_context.ts";
|
|
4
3
|
|
|
5
4
|
export async function runReviewCommand(context: CliContext, args: string[], options: Options): Promise<CommandResult> {
|
|
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
|
-
import type {
|
|
3
|
-
import {
|
|
1
|
+
import { showStatus, suggestNext } from "../../../../app/use_cases/project_status.ts";
|
|
2
|
+
import type { NextStep } from "../../../../domain/next_step.ts";
|
|
3
|
+
import type { CliContext, CommandResult } from "../cli_context.ts";
|
|
4
4
|
|
|
5
|
-
export async function runStatus(context: CliContext
|
|
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: CliContext): Promise<CommandResult> {
|
|
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: ApprovalStatus): Omit<ApprovalStatus, "record"> & { approvedAt?: string; by?: string; basis?: string } {
|
|
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: string[] | undefined): string {
|
|
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: Record<string, string> = { "plan-review": " (by the agent, after its plan review)", rethink: " (re-stamped by the agent after a rethink)" };
|
|
59
|
-
|
|
60
|
-
function describe(label: string, status: ApprovalStatus): string {
|
|
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: CliContext): Promise<CommandResult> {
|
|
18
|
+
const next = await suggestNext(context);
|
|
19
|
+
return { json: next, human: `Next: ${describe(next)}` };
|
|
64
20
|
}
|
|
65
21
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const describe = (s: { step: string; target?: string; reason: string }): string => `${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: NextStep): string {
|
|
23
|
+
return `${step.step}${step.target === undefined ? "" : ` ${step.target}`}: ${step.reason}`;
|
|
71
24
|
}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import type { Handler } from "./cli_context.ts";
|
|
2
|
-
import { runCheck,
|
|
3
|
-
import { runDiff } from "./commands/diff.ts";
|
|
2
|
+
import { runCheck, runTrace } from "./commands/code.ts";
|
|
4
3
|
import { runApprove, runNew, runValidate } from "./commands/documents.ts";
|
|
5
4
|
import { runInit } from "./commands/init.ts";
|
|
6
5
|
import { runInstall } from "./commands/install.ts";
|
|
7
|
-
import { runRealign } from "./commands/realign.ts";
|
|
8
|
-
import { runFeedback, runJournal } from "./commands/journal.ts";
|
|
9
|
-
import { runAbandon, runFeatures, runRoadmap, runTask } from "./commands/progress.ts";
|
|
10
6
|
import { runReviewCommand } from "./commands/review.ts";
|
|
11
|
-
import { runShow } from "./commands/show.ts";
|
|
12
7
|
import { runNext, runStatus } from "./commands/status.ts";
|
|
13
8
|
|
|
14
9
|
/** A command, and the options it takes: one list, or one per subcommand for a command that has them. */
|
|
@@ -20,37 +15,15 @@ export interface Command {
|
|
|
20
15
|
|
|
21
16
|
export const COMMANDS: Record<string, Command> = {
|
|
22
17
|
init: { handler: runInit, options: ["name", "yes", "agent", "package"], usage: "init [--name <name>] [--yes] [--agent claude|other] [--package <npm spec>] set up this repository and install the skills" },
|
|
23
|
-
install: { handler: runInstall, options: ["agent"], usage: "install [--agent <agent>]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
},
|
|
33
|
-
approve: {
|
|
34
|
-
handler: runApprove,
|
|
35
|
-
options: ["replan", "rebase", "by-agent", "restamp-unchanged"],
|
|
36
|
-
usage: "approve <vision|architecture|roadmap|ref|path> [--replan <ID>...] [--rebase <ID>...] [--by-agent|--restamp-unchanged] record an approval of a document",
|
|
37
|
-
},
|
|
38
|
-
new: {
|
|
39
|
-
handler: runNew,
|
|
40
|
-
options: { vision: [], glossary: [], architecture: [], roadmap: [], feature: ["title", "roadmap"], change: ["title", "feature", "roadmap"], adr: ["title"], note: ["title", "kind", "about"] },
|
|
41
|
-
usage: "new <vision|glossary|architecture|roadmap> | new <feature|change|adr> <slug> --title <title> [--feature <ref>] [--roadmap <slug>] | new note <slug> --title <title> --kind <input|intake|explore|research> --about <subjects>",
|
|
42
|
-
},
|
|
43
|
-
task: { handler: runTask, options: { done: ["change", "commit"], deviation: ["change"], reopen: ["change"] }, usage: "task <done|deviation|reopen> <T#> [text] [--change <ref>] [--commit <sha>]" },
|
|
44
|
-
features: { handler: runFeatures, options: { add: ["summary", "goals"], update: ["summary"], drop: ["reason"] }, usage: "features <add|update|drop> <slug> [--summary <text>] [--goals <ids>] [--reason <text>]" },
|
|
45
|
-
roadmap: { handler: runRoadmap, options: { prune: [] }, usage: "roadmap prune clear landed items from the roadmap status when a release closes" },
|
|
46
|
-
journal: { handler: runJournal, options: { add: ["set", "item"], list: ["event", "item", "all"] }, usage: "journal <add <event> --set key=value... [--item <ref>]|list [--event <event>] [--item <ref>] [--all]>" },
|
|
47
|
-
review: { handler: runReviewCommand, options: ["item", "round", "blockers", "base"], usage: "review <role> [--item <ref>] [--round 1|2 --blockers <file>] [--base <commit>] run a role in a fresh agent context" },
|
|
48
|
-
feedback: { handler: runFeedback, options: { export: ["out", "no-redact"] }, usage: "feedback export [--out <file>] [--no-redact]" },
|
|
49
|
-
trace: { handler: runTrace, options: ["all", "change"], usage: "trace [--all] [--change <ref>] link scenarios to the tests that prove them" },
|
|
50
|
-
check: { handler: runCheck, options: ["file", "ci"], usage: "check [<file>...] [--ci] enforce layer rules and file budgets" },
|
|
51
|
-
abandon: { handler: runAbandon, options: ["reason"], usage: "abandon <ref> --reason <text> archive a feature or standalone change that stops for good" },
|
|
52
|
-
land: { handler: runLand, options: ["override"], usage: "land [<ref>] [--override <reason>] merge a verified change into the living docs" },
|
|
53
|
-
realign: { handler: runRealign, options: { status: ["full"], done: ["change"] }, usage: "realign <status [--full]|done [--change <ref>]> what the installed Cruze expects of existing code, and recording that the code meets it" },
|
|
18
|
+
install: { handler: runInstall, options: ["agent"], usage: "install [--agent <agent>] install or update the Cruze skills" },
|
|
19
|
+
new: { handler: runNew, options: { vision: [], architecture: [], feature: ["title"] }, usage: "new vision | new architecture | new feature <slug> [--title <title>] start a document from its template" },
|
|
20
|
+
validate: { handler: runValidate, options: [], usage: "validate check every document against the formats" },
|
|
21
|
+
approve: { handler: runApprove, options: [], usage: "approve <vision|architecture|feature slug> record that the user approved a document as it reads now" },
|
|
22
|
+
status: { handler: runStatus, options: [], usage: "status each document's approval, each feature's progress, and the next step" },
|
|
23
|
+
next: { handler: runNext, options: [], usage: "next the step to run next, and why" },
|
|
24
|
+
trace: { handler: runTrace, options: [], usage: "trace [<feature slug>] link scenarios to the tests that carry their IDs" },
|
|
25
|
+
check: { handler: runCheck, options: ["ci"], usage: "check [<file>...] [--ci] enforce layer rules and file budgets" },
|
|
26
|
+
review: { handler: runReviewCommand, options: ["feature", "base"], usage: "review <code-reviewer|researcher> [--feature <slug>] [--base <commit>] run a role in a fresh agent context" },
|
|
54
27
|
};
|
|
55
28
|
|
|
56
29
|
export const USAGE = `Usage: cruze <command> [options]
|
|
@@ -28,36 +28,9 @@ export function parseCommand(argv: string[]): ParsedCommand {
|
|
|
28
28
|
help: { type: "boolean", short: "h", default: false },
|
|
29
29
|
title: { type: "string" },
|
|
30
30
|
feature: { type: "string" },
|
|
31
|
-
roadmap: { type: "string" },
|
|
32
|
-
change: { type: "string" },
|
|
33
|
-
commit: { type: "string" },
|
|
34
|
-
summary: { type: "string" },
|
|
35
|
-
goals: { type: "string" },
|
|
36
|
-
reason: { type: "string" },
|
|
37
|
-
set: { type: "string", multiple: true, default: [] },
|
|
38
|
-
item: { type: "string" },
|
|
39
|
-
event: { type: "string" },
|
|
40
|
-
out: { type: "string" },
|
|
41
|
-
"no-redact": { type: "boolean", default: false },
|
|
42
|
-
all: { type: "boolean", default: false },
|
|
43
|
-
file: { type: "string", multiple: true, default: [] },
|
|
44
31
|
ci: { type: "boolean", default: false },
|
|
45
|
-
gate: { type: "string" },
|
|
46
|
-
override: { type: "string" },
|
|
47
|
-
overlap: { type: "boolean", default: false },
|
|
48
|
-
full: { type: "boolean", default: false },
|
|
49
|
-
round: { type: "string" },
|
|
50
32
|
package: { type: "string" },
|
|
51
|
-
replan: { type: "string", multiple: true, default: [] },
|
|
52
|
-
rebase: { type: "string", multiple: true, default: [] },
|
|
53
33
|
base: { type: "string" },
|
|
54
|
-
blockers: { type: "string" },
|
|
55
|
-
"by-agent": { type: "boolean", default: false },
|
|
56
|
-
"restamp-unchanged": { type: "boolean", default: false },
|
|
57
|
-
index: { type: "boolean", default: false },
|
|
58
|
-
notes: { type: "boolean", default: false },
|
|
59
|
-
kind: { type: "string" },
|
|
60
|
-
about: { type: "string" },
|
|
61
34
|
},
|
|
62
35
|
});
|
|
63
36
|
} catch (error) {
|
|
@@ -71,39 +44,12 @@ export function parseCommand(argv: string[]): ParsedCommand {
|
|
|
71
44
|
agent: values.agent,
|
|
72
45
|
json: values.json,
|
|
73
46
|
text: values.text,
|
|
74
|
-
set: values.set,
|
|
75
|
-
redact: !values["no-redact"],
|
|
76
|
-
all: values.all,
|
|
77
|
-
file: values.file,
|
|
78
47
|
ci: values.ci,
|
|
79
|
-
overlap: values.overlap,
|
|
80
|
-
full: values.full,
|
|
81
|
-
replan: values.replan,
|
|
82
|
-
rebase: values.rebase,
|
|
83
|
-
byAgent: values["by-agent"],
|
|
84
|
-
restampUnchanged: values["restamp-unchanged"],
|
|
85
|
-
index: values.index,
|
|
86
|
-
notes: values.notes,
|
|
87
48
|
...optional("name", values.name),
|
|
88
49
|
...optional("title", values.title),
|
|
89
50
|
...optional("feature", values.feature),
|
|
90
|
-
...optional("roadmap", values.roadmap),
|
|
91
|
-
...optional("change", values.change),
|
|
92
|
-
...optional("commit", values.commit),
|
|
93
|
-
...optional("summary", values.summary),
|
|
94
|
-
...optional("goals", values.goals),
|
|
95
|
-
...optional("reason", values.reason),
|
|
96
|
-
...optional("item", values.item),
|
|
97
|
-
...optional("event", values.event),
|
|
98
|
-
...optional("out", values.out),
|
|
99
|
-
...optional("gate", values.gate),
|
|
100
|
-
...optional("override", values.override),
|
|
101
|
-
...optional("round", values.round),
|
|
102
51
|
...optional("package", values.package),
|
|
103
52
|
...optional("base", values.base),
|
|
104
|
-
...optional("blockers", values.blockers),
|
|
105
|
-
...optional("kind", values.kind),
|
|
106
|
-
...optional("about", values.about),
|
|
107
53
|
};
|
|
108
54
|
const given = [...new Set(tokens.flatMap((token) => (token.kind === "option" ? [token.name] : [])))];
|
|
109
55
|
return { words: positionals, options, given, help: values.help, version: values.version };
|