devrites 5.3.0 → 5.5.0
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/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/docs/command-map.md +2 -2
- package/docs/engine/state-schema.md +12 -0
- package/docs/flow.md +4 -0
- package/docs/orchestration.md +5 -2
- package/engine/commands.go +2 -2
- package/engine/internal/devritespaths/paths.go +15 -0
- package/engine/internal/gate/gate.go +78 -0
- package/engine/internal/gate/gate_test.go +118 -0
- package/engine/internal/lib/candidate.go +7 -3
- package/engine/internal/lib/manifest_union.go +326 -0
- package/engine/internal/lib/manifest_union_test.go +214 -0
- package/engine/internal/lib/observe_budgets.go +73 -0
- package/engine/internal/lib/observe_budgets_test.go +142 -0
- package/engine/internal/lib/observe_summary.go +74 -13
- package/engine/internal/lib/workspace_read.go +11 -6
- package/engine/internal/state/budgets.go +163 -0
- package/engine/internal/state/budgets_test.go +42 -0
- package/engine/internal/state/cursor.go +16 -10
- package/engine/internal/state/observation.go +50 -4
- package/engine/internal/state/status.go +38 -26
- package/engine/internal/state/taskgraph.go +23 -0
- package/engine/main.go +32 -13
- package/engine/root_routing_test.go +3 -1
- package/pack/.claude/agents/devrites-code-reviewer.md +9 -6
- package/pack/.claude/agents/devrites-doubt-reviewer.md +6 -0
- package/pack/.claude/agents/devrites-plan-reviewer.md +7 -1
- package/pack/.claude/agents/devrites-slice-wright.md +42 -46
- package/pack/.claude/agents/devrites-test-analyst.md +9 -4
- package/pack/.claude/agents/devrites-upgrade-planner.md +9 -1
- package/pack/.claude/settings.json +17 -0
- package/pack/.claude/skills/devrites-api-interface/SKILL.md +2 -2
- package/pack/.claude/skills/devrites-doubt/SKILL.md +9 -17
- package/pack/.claude/skills/devrites-lib/reference/candidate-integrity.md +34 -35
- package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +11 -12
- package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +104 -51
- package/pack/.claude/skills/devrites-lib/reference/standards/agents.md +1 -0
- package/pack/.claude/skills/devrites-lib/reference/standards/context-hygiene.md +45 -25
- package/pack/.claude/skills/devrites-lib/reference/standards/core.md +1 -1
- package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +80 -41
- package/pack/.claude/skills/rite-autocomplete/SKILL.md +19 -8
- package/pack/.claude/skills/rite-autocomplete/reference/loop.md +33 -1
- package/pack/.claude/skills/rite-build/SKILL.md +26 -17
- package/pack/.claude/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/.claude/skills/rite-build/reference/parallel-batch.md +101 -39
- package/pack/.claude/skills/rite-build/reference/phase-contract.md +79 -59
- package/pack/.claude/skills/rite-build/reference/spec-drift-guard.md +14 -15
- package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +8 -8
- package/pack/.claude/skills/rite-define/SKILL.md +4 -1
- package/pack/.claude/skills/rite-plan/SKILL.md +4 -1
- package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +21 -0
- package/pack/.claude/skills/rite-plan/reference/slicing.md +117 -15
- package/pack/.claude/skills/rite-prove/SKILL.md +20 -22
- package/pack/.claude/skills/rite-review/SKILL.md +23 -16
- package/pack/.claude/skills/rite-seal/SKILL.md +8 -8
- package/pack/.claude/skills/rite-seal/reference/final-evidence.md +6 -5
- package/pack/.claude/skills/rite-seal/reference/phase-contract.md +13 -13
- package/pack/.claude/skills/rite-ship/SKILL.md +3 -0
- package/pack/.claude/skills/rite-ship/reference/close-out.md +16 -2
- package/pack/.claude/skills/rite-ship/reference/git-ship.md +14 -5
- package/pack/.claude/skills/rite-spec/SKILL.md +6 -0
- package/pack/.claude/skills/rite-spec/reference/state-workspace.md +6 -0
- package/pack/.claude/skills/rite-status/SKILL.md +4 -1
- package/pack/.claude/skills/rite-temper/SKILL.md +14 -11
- package/pack/.claude/skills/rite-temper/reference/anti-patterns.md +14 -13
- package/pack/.claude/skills/rite-temper/reference/review-dimensions.md +3 -4
- package/pack/.claude/skills/rite-upgrade/SKILL.md +11 -2
- package/pack/.claude/skills/rite-vet/SKILL.md +22 -15
- package/pack/.claude/skills/rite-vet/reference/anti-patterns.md +11 -9
- package/pack/.claude/skills/rite-vet/reference/depth.md +6 -7
- package/pack/.claude/skills/rite-vet/reference/review-axes.md +39 -14
- package/pack/generated/claude/agents/devrites-code-reviewer.md +9 -6
- package/pack/generated/claude/agents/devrites-doubt-reviewer.md +6 -0
- package/pack/generated/claude/agents/devrites-plan-reviewer.md +7 -1
- package/pack/generated/claude/agents/devrites-slice-wright.md +42 -46
- package/pack/generated/claude/agents/devrites-test-analyst.md +9 -4
- package/pack/generated/claude/agents/devrites-upgrade-planner.md +9 -1
- package/pack/generated/claude/settings.json +17 -0
- package/pack/generated/claude/skills/devrites-api-interface/SKILL.md +2 -2
- package/pack/generated/claude/skills/devrites-doubt/SKILL.md +9 -17
- package/pack/generated/claude/skills/devrites-lib/reference/candidate-integrity.md +34 -35
- package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +11 -12
- package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +104 -51
- package/pack/generated/claude/skills/devrites-lib/reference/standards/agents.md +1 -0
- package/pack/generated/claude/skills/devrites-lib/reference/standards/context-hygiene.md +45 -25
- package/pack/generated/claude/skills/devrites-lib/reference/standards/core.md +1 -1
- package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +80 -41
- package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +19 -8
- package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +33 -1
- package/pack/generated/claude/skills/rite-build/SKILL.md +26 -17
- package/pack/generated/claude/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/claude/skills/rite-build/reference/parallel-batch.md +101 -39
- package/pack/generated/claude/skills/rite-build/reference/phase-contract.md +79 -59
- package/pack/generated/claude/skills/rite-build/reference/spec-drift-guard.md +14 -15
- package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +8 -8
- package/pack/generated/claude/skills/rite-define/SKILL.md +4 -1
- package/pack/generated/claude/skills/rite-plan/SKILL.md +4 -1
- package/pack/generated/claude/skills/rite-plan/reference/replan-and-repair.md +21 -0
- package/pack/generated/claude/skills/rite-plan/reference/slicing.md +117 -15
- package/pack/generated/claude/skills/rite-prove/SKILL.md +20 -22
- package/pack/generated/claude/skills/rite-review/SKILL.md +23 -16
- package/pack/generated/claude/skills/rite-seal/SKILL.md +8 -8
- package/pack/generated/claude/skills/rite-seal/reference/final-evidence.md +6 -5
- package/pack/generated/claude/skills/rite-seal/reference/phase-contract.md +13 -13
- package/pack/generated/claude/skills/rite-ship/SKILL.md +3 -0
- package/pack/generated/claude/skills/rite-ship/reference/close-out.md +16 -2
- package/pack/generated/claude/skills/rite-ship/reference/git-ship.md +14 -5
- package/pack/generated/claude/skills/rite-spec/SKILL.md +6 -0
- package/pack/generated/claude/skills/rite-spec/reference/state-workspace.md +6 -0
- package/pack/generated/claude/skills/rite-status/SKILL.md +4 -1
- package/pack/generated/claude/skills/rite-temper/SKILL.md +14 -11
- package/pack/generated/claude/skills/rite-temper/reference/anti-patterns.md +14 -13
- package/pack/generated/claude/skills/rite-temper/reference/review-dimensions.md +3 -4
- package/pack/generated/claude/skills/rite-upgrade/SKILL.md +11 -2
- package/pack/generated/claude/skills/rite-vet/SKILL.md +22 -15
- package/pack/generated/claude/skills/rite-vet/reference/anti-patterns.md +11 -9
- package/pack/generated/claude/skills/rite-vet/reference/depth.md +6 -7
- package/pack/generated/claude/skills/rite-vet/reference/review-axes.md +39 -14
- package/pack/generated/codex/agents/devrites-code-reviewer.toml +9 -6
- package/pack/generated/codex/agents/devrites-doubt-reviewer.toml +6 -0
- package/pack/generated/codex/agents/devrites-plan-reviewer.toml +7 -1
- package/pack/generated/codex/agents/devrites-slice-wright.toml +42 -46
- package/pack/generated/codex/agents/devrites-test-analyst.toml +9 -4
- package/pack/generated/codex/agents/devrites-upgrade-planner.toml +9 -1
- package/pack/generated/codex/skills/devrites-api-interface/SKILL.md +2 -2
- package/pack/generated/codex/skills/devrites-doubt/SKILL.md +9 -17
- package/pack/generated/codex/skills/devrites-lib/reference/candidate-integrity.md +34 -35
- package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +11 -12
- package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +104 -51
- package/pack/generated/codex/skills/devrites-lib/reference/standards/agents.md +1 -0
- package/pack/generated/codex/skills/devrites-lib/reference/standards/context-hygiene.md +45 -25
- package/pack/generated/codex/skills/devrites-lib/reference/standards/core.md +1 -1
- package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +80 -41
- package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +19 -8
- package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +33 -1
- package/pack/generated/codex/skills/rite-build/SKILL.md +26 -17
- package/pack/generated/codex/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/codex/skills/rite-build/reference/parallel-batch.md +101 -39
- package/pack/generated/codex/skills/rite-build/reference/phase-contract.md +79 -59
- package/pack/generated/codex/skills/rite-build/reference/spec-drift-guard.md +14 -15
- package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +8 -8
- package/pack/generated/codex/skills/rite-define/SKILL.md +4 -1
- package/pack/generated/codex/skills/rite-plan/SKILL.md +4 -1
- package/pack/generated/codex/skills/rite-plan/reference/replan-and-repair.md +21 -0
- package/pack/generated/codex/skills/rite-plan/reference/slicing.md +117 -15
- package/pack/generated/codex/skills/rite-prove/SKILL.md +20 -22
- package/pack/generated/codex/skills/rite-review/SKILL.md +23 -16
- package/pack/generated/codex/skills/rite-seal/SKILL.md +8 -8
- package/pack/generated/codex/skills/rite-seal/reference/final-evidence.md +6 -5
- package/pack/generated/codex/skills/rite-seal/reference/phase-contract.md +13 -13
- package/pack/generated/codex/skills/rite-ship/SKILL.md +3 -0
- package/pack/generated/codex/skills/rite-ship/reference/close-out.md +16 -2
- package/pack/generated/codex/skills/rite-ship/reference/git-ship.md +14 -5
- package/pack/generated/codex/skills/rite-spec/SKILL.md +6 -0
- package/pack/generated/codex/skills/rite-spec/reference/state-workspace.md +6 -0
- package/pack/generated/codex/skills/rite-status/SKILL.md +4 -1
- package/pack/generated/codex/skills/rite-temper/SKILL.md +14 -11
- package/pack/generated/codex/skills/rite-temper/reference/anti-patterns.md +14 -13
- package/pack/generated/codex/skills/rite-temper/reference/review-dimensions.md +3 -4
- package/pack/generated/codex/skills/rite-upgrade/SKILL.md +11 -2
- package/pack/generated/codex/skills/rite-vet/SKILL.md +22 -15
- package/pack/generated/codex/skills/rite-vet/reference/anti-patterns.md +11 -9
- package/pack/generated/codex/skills/rite-vet/reference/depth.md +6 -7
- package/pack/generated/codex/skills/rite-vet/reference/review-axes.md +39 -14
- package/pack/generated/omp/agents/devrites-code-reviewer.md +9 -6
- package/pack/generated/omp/agents/devrites-doubt-reviewer.md +6 -0
- package/pack/generated/omp/agents/devrites-plan-reviewer.md +7 -1
- package/pack/generated/omp/agents/devrites-slice-wright.md +42 -46
- package/pack/generated/omp/agents/devrites-test-analyst.md +9 -4
- package/pack/generated/omp/agents/devrites-upgrade-planner.md +9 -1
- package/pack/generated/omp/skills/devrites-api-interface/SKILL.md +2 -2
- package/pack/generated/omp/skills/devrites-doubt/SKILL.md +9 -17
- package/pack/generated/omp/skills/devrites-lib/reference/candidate-integrity.md +34 -35
- package/pack/generated/omp/skills/devrites-lib/reference/parallel-dispatch.md +11 -12
- package/pack/generated/omp/skills/devrites-lib/reference/standards/afk-hitl.md +104 -51
- package/pack/generated/omp/skills/devrites-lib/reference/standards/agents.md +1 -0
- package/pack/generated/omp/skills/devrites-lib/reference/standards/context-hygiene.md +45 -25
- package/pack/generated/omp/skills/devrites-lib/reference/standards/core.md +1 -1
- package/pack/generated/omp/skills/devrites-lib/reference/workspace-artifact-schema.md +80 -41
- package/pack/generated/omp/skills/rite-autocomplete/SKILL.md +19 -8
- package/pack/generated/omp/skills/rite-autocomplete/reference/loop.md +33 -1
- package/pack/generated/omp/skills/rite-build/SKILL.md +26 -17
- package/pack/generated/omp/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/omp/skills/rite-build/reference/parallel-batch.md +101 -39
- package/pack/generated/omp/skills/rite-build/reference/phase-contract.md +79 -59
- package/pack/generated/omp/skills/rite-build/reference/spec-drift-guard.md +14 -15
- package/pack/generated/omp/skills/rite-build/reference/wright-dispatch.md +8 -8
- package/pack/generated/omp/skills/rite-define/SKILL.md +4 -1
- package/pack/generated/omp/skills/rite-plan/SKILL.md +4 -1
- package/pack/generated/omp/skills/rite-plan/reference/replan-and-repair.md +21 -0
- package/pack/generated/omp/skills/rite-plan/reference/slicing.md +117 -15
- package/pack/generated/omp/skills/rite-prove/SKILL.md +20 -22
- package/pack/generated/omp/skills/rite-review/SKILL.md +23 -16
- package/pack/generated/omp/skills/rite-seal/SKILL.md +8 -8
- package/pack/generated/omp/skills/rite-seal/reference/final-evidence.md +6 -5
- package/pack/generated/omp/skills/rite-seal/reference/phase-contract.md +13 -13
- package/pack/generated/omp/skills/rite-ship/SKILL.md +3 -0
- package/pack/generated/omp/skills/rite-ship/reference/close-out.md +16 -2
- package/pack/generated/omp/skills/rite-ship/reference/git-ship.md +14 -5
- package/pack/generated/omp/skills/rite-spec/SKILL.md +6 -0
- package/pack/generated/omp/skills/rite-spec/reference/state-workspace.md +6 -0
- package/pack/generated/omp/skills/rite-status/SKILL.md +4 -1
- package/pack/generated/omp/skills/rite-temper/SKILL.md +14 -11
- package/pack/generated/omp/skills/rite-temper/reference/anti-patterns.md +14 -13
- package/pack/generated/omp/skills/rite-temper/reference/review-dimensions.md +3 -4
- package/pack/generated/omp/skills/rite-upgrade/SKILL.md +11 -2
- package/pack/generated/omp/skills/rite-vet/SKILL.md +22 -15
- package/pack/generated/omp/skills/rite-vet/reference/anti-patterns.md +11 -9
- package/pack/generated/omp/skills/rite-vet/reference/depth.md +6 -7
- package/pack/generated/omp/skills/rite-vet/reference/review-axes.md +39 -14
- package/package.json +1 -1
- package/scripts/codex-generate.sh +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to DevRites are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and DevRites adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Releases are generated automatically by [semantic-release](https://semantic-release.gitbook.io/) from Conventional Commits on `main`.
|
|
4
4
|
|
|
5
|
+
## [5.5.0](https://github.com/ViktorsBaikers/DevRites/compare/v5.4.0...v5.5.0) (2026-09-13)
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
* **rite:** cap parallel batch width and chain deferred ship ([#68](https://github.com/ViktorsBaikers/DevRites/issues/68)) ([d023dfa](https://github.com/ViktorsBaikers/DevRites/commit/d023dfa742d5b6f5a9775c21308cd4731d6858f9))
|
|
10
|
+
|
|
11
|
+
## [5.4.0](https://github.com/ViktorsBaikers/DevRites/compare/v5.3.0...v5.4.0) (2026-09-13)
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
* **rite:** auto re-batch on frozen-lease scope defect ([#67](https://github.com/ViktorsBaikers/DevRites/issues/67)) ([6728385](https://github.com/ViktorsBaikers/DevRites/commit/6728385b522a5b34bebacb89a5855e81d54c0f68))
|
|
16
|
+
|
|
5
17
|
## [5.3.0](https://github.com/ViktorsBaikers/DevRites/compare/v5.2.4...v5.3.0) (2026-09-13)
|
|
6
18
|
|
|
7
19
|
### Added
|
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ project-conventional push, tag, or PR action, and archive the workspace.
|
|
|
33
33
|
Unattended runs may create local WIP checkpoint commits along the way, but they
|
|
34
34
|
remain local unless Ship's disclosed plan includes an approved remote action.
|
|
35
35
|
|
|
36
|
-
**Status:** [`v5.
|
|
36
|
+
**Status:** [`v5.5.0`](https://github.com/ViktorsBaikers/DevRites/releases/tag/v5.5.0): see [`CHANGELOG.md`](CHANGELOG.md) for release notes.
|
|
37
37
|
|
|
38
38
|
This is the latest published release; `main` may contain unreleased work.
|
|
39
39
|
|
package/docs/command-map.md
CHANGED
|
@@ -41,8 +41,8 @@ The Go surface is intentionally closed and deterministic:
|
|
|
41
41
|
| Lane | Commands | Owner |
|
|
42
42
|
|---|---|---|
|
|
43
43
|
| Candidate and deterministic checks | `check candidate`, `check readiness [--emit-binding]`, `check seal`, `check task-graph`, `check path-disjoint`, `check skill-trust`, `check indexes` | Candidate validates/hashes the strict project manifest; readiness checks phase files, the required `tasks.md` slice graph, or emits the vetted Build-input binding; seal checks final files/open gates, that graph and binding, then exact candidate bindings. `check indexes` reports install manifest and optional code-index directory presence as JSON. |
|
|
44
|
-
| Workspace observation | `observe summary`, `orient` | JSON workspace snapshot for agents; `orient` is an alias for `observe summary`. |
|
|
45
|
-
| Atomic workspace state | `state resolve`, `state close`, `migrate [--dry-run] [--answer id=choice]` | Go owns answer/drop/batch resolution, transactional close, and fail-closed v5 schema normalization. |
|
|
44
|
+
| Workspace observation | `observe summary`, `orient`, `observe slice <slug> <SLICE-ID>` | JSON workspace snapshot for agents (cursor, task graph, `artifact_budgets`, `bulk_files`); `orient` is an alias for `observe summary`. `observe slice` prints one `SLICE-###` section of `tasks.md` so Build reads a slice, not the file. |
|
|
45
|
+
| Atomic workspace state | `state resolve`, `state merge-manifest`, `state close`, `migrate [--dry-run] [--answer id=choice]` | Go owns answer/drop/batch resolution, the recorded predecessor-chain manifest union for a release milestone, transactional close, and fail-closed v5 schema normalization. |
|
|
46
46
|
| Security | `secret-scan` | `/rite-ship`, safe hooks, or an operator scans staged blobs, stdin, or touched files. |
|
|
47
47
|
| Install/operator | `install`, `update`, `uninstall`, `version` | Direct update acquires latest; npm/bootstrap may supply local candidates; the engine performs manifest-owned local changes. |
|
|
48
48
|
| Native policy | no engine command | Skills/root own spec grammar re-read, qid allocation, Clarify cursor edits, AFK/recovery accounting, and read-only `/rite-doctor`. |
|
|
@@ -147,6 +147,18 @@ There is no recovery-counter artifact. The caller and recovery loop count at
|
|
|
147
147
|
most three failed attempts per causal fingerprint from current context and the
|
|
148
148
|
recorded `## Dead ends` / `evidence.md`, then stop before a fourth.
|
|
149
149
|
|
|
150
|
+
For a deferred-ship continuation chain (`.devrites/AFK` `continue_sequence`),
|
|
151
|
+
three optional cursor fields carry the chain: `sequence_parent` (the immediately
|
|
152
|
+
preceding workspace slug), `sequence_position` (1-based ordinal), and
|
|
153
|
+
`sequence_workspaces_remaining` (slots the chain may still open). The controlling
|
|
154
|
+
root seeds them once per continuation workspace from the recorded parent and the
|
|
155
|
+
parent's counter; values only decrease, malformed values fail closed, and a
|
|
156
|
+
workspace without a recorded parent/position is not a sequence member. The
|
|
157
|
+
release milestone additionally carries `sequence_role: release`, which makes
|
|
158
|
+
`check candidate` and `check seal` require its manifest to cover the whole
|
|
159
|
+
recorded chain (built by `state merge-manifest`).
|
|
160
|
+
`observe summary`/`orient` surface them under `sequence`.
|
|
161
|
+
|
|
150
162
|
<!-- authority:state-tracking:start -->
|
|
151
163
|
Git-tracked shared state: `.devrites/specs/`. Per-clone runtime state: `.devrites/work/`, `.devrites/archive/`, `.devrites/ACTIVE`.
|
|
152
164
|
<!-- authority:state-tracking:end -->
|
package/docs/flow.md
CHANGED
|
@@ -351,6 +351,10 @@ erDiagram
|
|
|
351
351
|
string status "running | awaiting_human | blocked | done"
|
|
352
352
|
string active_slice "N: name"
|
|
353
353
|
int afk_slices_remaining "root-owned; never negative; one charge per green built slice"
|
|
354
|
+
string sequence_parent "deferred-ship chain: preceding workspace slug"
|
|
355
|
+
int sequence_position "1-based ordinal in the recorded continuation chain"
|
|
356
|
+
int sequence_workspaces_remaining "chain slots still open after this workspace; never negative"
|
|
357
|
+
string sequence_role "release on the release milestone; gates then require the chain union"
|
|
354
358
|
string return_phase "durable later-phase clarify return"
|
|
355
359
|
string return_next_action "restored only after fresh CLEAR"
|
|
356
360
|
block awaiting_human "qid, gate, question, proposed, raised_at (only when paused)"
|
package/docs/orchestration.md
CHANGED
|
@@ -127,8 +127,11 @@ conflict, extra paths, moved base, or cleanup failure stops with worktree eviden
|
|
|
127
127
|
preserved. No ad hoc copy/cherry-pick/merge occurs from the read-only root.
|
|
128
128
|
|
|
129
129
|
Isolation does not authorize same-worktree throughput. Parallel writers are allowed
|
|
130
|
-
**only** under `/rite-build
|
|
131
|
-
and a control `parallel-lease.md` apply (
|
|
130
|
+
**only** under the `/rite-build` batch path when path-disjoint eligibility, abort-batch,
|
|
131
|
+
and a control `parallel-lease.md` apply. `--parallel N` (or the AFK sentinel
|
|
132
|
+
`max_parallel`, default cap 10 under `/rite-autocomplete`) is a **cap**: each round runs
|
|
133
|
+
the largest eligible set, recomputes after every integrate, and repeats until no pending
|
|
134
|
+
slice remains; fewer than two eligible slices fall back to the serial cycle (see
|
|
132
135
|
[`parallel-batch.md`](../pack/.claude/skills/rite-build/reference/parallel-batch.md)).
|
|
133
136
|
Same-worktree multi-writer and root-emulated worktrees remain forbidden; default
|
|
134
137
|
`/rite-build` stays one writer across linked worktrees.
|
package/engine/commands.go
CHANGED
|
@@ -31,7 +31,7 @@ func rootModeFor(command string, args []string) rootMode {
|
|
|
31
31
|
return rootLenient
|
|
32
32
|
case "state":
|
|
33
33
|
switch subcommand {
|
|
34
|
-
case "resolve", "close":
|
|
34
|
+
case "resolve", "merge-manifest", "close":
|
|
35
35
|
return rootStrict
|
|
36
36
|
}
|
|
37
37
|
return rootUnused
|
|
@@ -49,7 +49,7 @@ func rootModeFor(command string, args []string) rootMode {
|
|
|
49
49
|
return rootStrictUsage
|
|
50
50
|
case "observe":
|
|
51
51
|
switch subcommand {
|
|
52
|
-
case "summary":
|
|
52
|
+
case "summary", "slice":
|
|
53
53
|
return rootStrictUsage
|
|
54
54
|
}
|
|
55
55
|
return rootUnused
|
|
@@ -118,6 +118,21 @@ func ArchiveDirChecked(root string) (string, error) {
|
|
|
118
118
|
return checkedCanonicalDir(root, filepath.Join(root, "archive"), "archive", "")
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
// ExistingArchivedFeatureDirChecked resolves an archived feature directory that
|
|
122
|
+
// must already exist. A live workspace never satisfies this lookup; callers
|
|
123
|
+
// that accept either location try ExistingFeatureDirChecked first.
|
|
124
|
+
func ExistingArchivedFeatureDirChecked(root, slug string) (string, error) {
|
|
125
|
+
if !validSlug(slug) {
|
|
126
|
+
return "", fmt.Errorf("DRV-WORKSPACE-INVALID: %q is not a feature slug", slug)
|
|
127
|
+
}
|
|
128
|
+
candidate := filepath.Join(root, "archive", slug)
|
|
129
|
+
resolved, err := checkedCanonicalDir(root, candidate, filepath.Join("archive", slug), "")
|
|
130
|
+
if err != nil {
|
|
131
|
+
return "", err
|
|
132
|
+
}
|
|
133
|
+
return resolved, nil
|
|
134
|
+
}
|
|
135
|
+
|
|
121
136
|
func checkedCanonicalDir(root, candidate, parent, slug string) (string, error) {
|
|
122
137
|
resolvedRoot, err := safepath.ResolveExisting(root)
|
|
123
138
|
if err != nil {
|
|
@@ -51,9 +51,38 @@ func Check(kind Kind, root, slug string) (*Result, error) {
|
|
|
51
51
|
if err != nil {
|
|
52
52
|
return nil, fmt.Errorf("gate %s: %w", kind, err)
|
|
53
53
|
}
|
|
54
|
+
for _, problem := range unsanctionedRootFiles(observation) {
|
|
55
|
+
result.StateProblems = append(result.StateProblems, "placement: "+problem)
|
|
56
|
+
// Keep a more specific reason (readiness-stale) when the observation
|
|
57
|
+
// already blocked; only an otherwise-passing gate takes the generic one.
|
|
58
|
+
if !result.Blocked {
|
|
59
|
+
result.Blocked = true
|
|
60
|
+
result.ReasonID = ResultReasonID(kind, true)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
54
63
|
return result, nil
|
|
55
64
|
}
|
|
56
65
|
|
|
66
|
+
// unsanctionedRootFiles blocks a workspace-root file the schema does not place
|
|
67
|
+
// there and is over the packet ceiling. `packets/` owns by-reference dispatch
|
|
68
|
+
// packets and admitted accounts (<= 64 KiB each) and `history/` owns relocated
|
|
69
|
+
// narrative, so a large stray file in the root is misplaced payload — the shape
|
|
70
|
+
// that let a real workspace reach 71 MB, 83% of it reviewer packets and traces
|
|
71
|
+
// (see context-hygiene.md dispatch packets and its failing case).
|
|
72
|
+
func unsanctionedRootFiles(observation *state.WorkspaceObservation) []string {
|
|
73
|
+
var problems []string
|
|
74
|
+
for _, file := range observation.RootFiles() {
|
|
75
|
+
if state.SanctionedRootFile(file.Name) || file.Bytes <= state.PacketMaxBytes {
|
|
76
|
+
continue
|
|
77
|
+
}
|
|
78
|
+
problems = append(problems, fmt.Sprintf(
|
|
79
|
+
"%s is %d bytes in the workspace root; move dispatch packets and accounts to packets/ (<= %d bytes each), closed narrative to history/ via /rite-plan revise, and never persist transcripts anywhere in .devrites/",
|
|
80
|
+
file.Name, file.Bytes, state.PacketMaxBytes,
|
|
81
|
+
))
|
|
82
|
+
}
|
|
83
|
+
return problems
|
|
84
|
+
}
|
|
85
|
+
|
|
57
86
|
func checkObservation(kind Kind, observation *state.WorkspaceObservation) (*Result, error) {
|
|
58
87
|
phase, err := observation.DeclaredPhase()
|
|
59
88
|
if err != nil {
|
|
@@ -109,6 +138,28 @@ func checkObservation(kind Kind, observation *state.WorkspaceObservation) (*Resu
|
|
|
109
138
|
blocked = true
|
|
110
139
|
}
|
|
111
140
|
}
|
|
141
|
+
if len(missingFiles) == 0 {
|
|
142
|
+
for _, problem := range artifactBudgetProblems(observation, policy) {
|
|
143
|
+
stateProblems = append(stateProblems, "budget: "+problem)
|
|
144
|
+
blocked = true
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Deliberately not gated on missingFiles: a file over the read cap IS missing,
|
|
148
|
+
// so the budget comparison below can never reach it. Missing already blocks it;
|
|
149
|
+
// name the size remedies too so the signal is actionable rather than a bare cap.
|
|
150
|
+
for _, artifact := range policy.RequiredArtifacts {
|
|
151
|
+
fact, ok := observation.Fact(artifact)
|
|
152
|
+
if !ok {
|
|
153
|
+
continue
|
|
154
|
+
}
|
|
155
|
+
if diagnostic, has := fact.Diagnostic(); has && diagnostic.Code == state.DiagnosticFileTooLarge {
|
|
156
|
+
stateProblems = append(stateProblems, fmt.Sprintf(
|
|
157
|
+
"budget: %s exceeds the %d-byte artifact cap; relocate history (history/<file>-<YYYYMMDD>.md) or split the feature via /rite-plan revise|course-correct",
|
|
158
|
+
artifact, state.MaxArtifactBytes,
|
|
159
|
+
))
|
|
160
|
+
blocked = true
|
|
161
|
+
}
|
|
162
|
+
}
|
|
112
163
|
if len(missingFiles) == 0 && phaseRequiresReadinessBinding(policy) {
|
|
113
164
|
expected, bindingErr := verifyReadinessBinding(observation)
|
|
114
165
|
if bindingErr != nil {
|
|
@@ -142,6 +193,33 @@ func checkObservation(kind Kind, observation *state.WorkspaceObservation) (*Resu
|
|
|
142
193
|
return result, nil
|
|
143
194
|
}
|
|
144
195
|
|
|
196
|
+
// artifactBudgetProblems blocks a required artifact only on a material overshoot
|
|
197
|
+
// (>= state.BudgetBlockFactor of a line or byte budget) with no structural
|
|
198
|
+
// `Budget override:` line. Smaller overshoots stay advisory and are reported by
|
|
199
|
+
// `orient`.
|
|
200
|
+
func artifactBudgetProblems(observation *state.WorkspaceObservation, policy state.PhasePolicy) []string {
|
|
201
|
+
var problems []string
|
|
202
|
+
for _, artifact := range policy.RequiredArtifacts {
|
|
203
|
+
fact, ok := observation.Fact(artifact)
|
|
204
|
+
if !ok || fact.State() != state.ArtifactPresent {
|
|
205
|
+
continue
|
|
206
|
+
}
|
|
207
|
+
if !state.ArtifactBudgetGateApplies(string(artifact)) {
|
|
208
|
+
continue
|
|
209
|
+
}
|
|
210
|
+
status, ok := state.ArtifactBudget(string(artifact), fact.Bytes())
|
|
211
|
+
if !ok || !status.Material || status.Override {
|
|
212
|
+
continue
|
|
213
|
+
}
|
|
214
|
+
problems = append(problems, fmt.Sprintf(
|
|
215
|
+
"%s is %d lines/%d bytes, at or above %gx its %d-line/%d-byte budget; relocate history (history/<file>-<YYYYMMDD>.md) or split the feature via /rite-plan revise|course-correct, or record a structural `Budget override: <reason>` line",
|
|
216
|
+
status.File, status.Lines, status.Bytes, state.BudgetBlockFactor,
|
|
217
|
+
status.LineBudget, status.ByteBudget,
|
|
218
|
+
))
|
|
219
|
+
}
|
|
220
|
+
return problems
|
|
221
|
+
}
|
|
222
|
+
|
|
145
223
|
func acceptanceMapProblems(observation *state.WorkspaceObservation, policy state.PhasePolicy) []string {
|
|
146
224
|
requireTasks := phaseRequiresTasks(policy)
|
|
147
225
|
requireTestPlan := phaseRequiresTestPlan(policy)
|
|
@@ -636,3 +636,121 @@ func writeWorkFeature(t *testing.T, root, slug string, files map[string]string)
|
|
|
636
636
|
testutil.WriteFile(t, filepath.Join(root, "work", slug, name), content)
|
|
637
637
|
}
|
|
638
638
|
}
|
|
639
|
+
|
|
640
|
+
func TestCheckBlocksMaterialBudgetOvershootWithoutOverride(t *testing.T) {
|
|
641
|
+
root := t.TempDir()
|
|
642
|
+
writeCompleteGateFeature(t, root, "oversized", state.PhaseBuild, state.PhaseBuild, "none\n")
|
|
643
|
+
workspace := filepath.Join(root, "work", "oversized")
|
|
644
|
+
oversized := "# Tasks\n\n## SLICE-001 A\nDependencies: none\n\n" + strings.Repeat("long line of planning prose\n", 500)
|
|
645
|
+
testutil.WriteFile(t, filepath.Join(workspace, "tasks.md"), oversized)
|
|
646
|
+
binding := mustReadinessBinding(t, root, "oversized")
|
|
647
|
+
testutil.AppendFile(t, filepath.Join(workspace, "eng-review.md"), "\n"+binding+"\n")
|
|
648
|
+
|
|
649
|
+
res, err := Check(Readiness, root, "oversized")
|
|
650
|
+
if err != nil {
|
|
651
|
+
t.Fatal(err)
|
|
652
|
+
}
|
|
653
|
+
if !res.Blocked {
|
|
654
|
+
t.Fatalf("blocked=false, want true")
|
|
655
|
+
}
|
|
656
|
+
joined := strings.Join(res.StateProblems, "\n")
|
|
657
|
+
if !strings.Contains(joined, "budget: tasks.md is") || !strings.Contains(joined, "Budget override") {
|
|
658
|
+
t.Fatalf("StateProblems=%q", joined)
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
testutil.AppendFile(t, filepath.Join(workspace, "tasks.md"), "\nBudget override: vendored requirement matrix, relocation pending\n")
|
|
662
|
+
res, err = Check(Readiness, root, "oversized")
|
|
663
|
+
if err != nil {
|
|
664
|
+
t.Fatal(err)
|
|
665
|
+
}
|
|
666
|
+
if strings.Contains(strings.Join(res.StateProblems, "\n"), "budget: tasks.md") {
|
|
667
|
+
t.Fatalf("override did not clear the budget problem: %v", res.StateProblems)
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
func TestCheckKeepsNonMaterialOvershootAdvisory(t *testing.T) {
|
|
672
|
+
root := t.TempDir()
|
|
673
|
+
writeCompleteGateFeature(t, root, "slightly-over", state.PhaseBuild, state.PhaseBuild, "none\n")
|
|
674
|
+
workspace := filepath.Join(root, "work", "slightly-over")
|
|
675
|
+
// 300 lines against a 280-line budget: over, but below the material factor.
|
|
676
|
+
testutil.WriteFile(t, filepath.Join(workspace, "tasks.md"), testutil.CanonicalTasksMarkdown+"\n"+strings.Repeat("note\n", 200))
|
|
677
|
+
binding := mustReadinessBinding(t, root, "slightly-over")
|
|
678
|
+
testutil.AppendFile(t, filepath.Join(workspace, "eng-review.md"), "\n"+binding+"\n")
|
|
679
|
+
|
|
680
|
+
res, err := Check(Readiness, root, "slightly-over")
|
|
681
|
+
if err != nil {
|
|
682
|
+
t.Fatal(err)
|
|
683
|
+
}
|
|
684
|
+
if strings.Contains(strings.Join(res.StateProblems, "\n"), "budget:") {
|
|
685
|
+
t.Fatalf("non-material overshoot must stay advisory: %v", res.StateProblems)
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
func TestCheckBlocksOversizedPacketInWorkspaceRoot(t *testing.T) {
|
|
690
|
+
root := t.TempDir()
|
|
691
|
+
writeCompleteGateFeature(t, root, "stray", state.PhaseBuild, state.PhaseBuild, "none\n")
|
|
692
|
+
workspace := filepath.Join(root, "work", "stray")
|
|
693
|
+
binding := mustReadinessBinding(t, root, "stray")
|
|
694
|
+
testutil.AppendFile(t, filepath.Join(workspace, "eng-review.md"), "\n"+binding+"\n")
|
|
695
|
+
|
|
696
|
+
// Sanctioned conditional artifact over the ceiling: placement stays legal.
|
|
697
|
+
testutil.WriteFile(t, filepath.Join(workspace, "references.md"),
|
|
698
|
+
"# refs\n\n"+strings.Repeat("reference line\n", 6000))
|
|
699
|
+
// Unsanctioned root payload over the ceiling: blocked.
|
|
700
|
+
testutil.WriteFile(t, filepath.Join(workspace, "vet-review-input-031.json"),
|
|
701
|
+
strings.Repeat("x", state.PacketMaxBytes+1))
|
|
702
|
+
|
|
703
|
+
res, err := Check(Readiness, root, "stray")
|
|
704
|
+
if err != nil {
|
|
705
|
+
t.Fatal(err)
|
|
706
|
+
}
|
|
707
|
+
joined := strings.Join(res.StateProblems, "\n")
|
|
708
|
+
if !res.Blocked || !strings.Contains(joined, "placement: vet-review-input-031.json") {
|
|
709
|
+
t.Fatalf("blocked=%v StateProblems=%q", res.Blocked, joined)
|
|
710
|
+
}
|
|
711
|
+
if !strings.Contains(joined, "packets/") {
|
|
712
|
+
t.Fatalf("remediation must name packets/: %q", joined)
|
|
713
|
+
}
|
|
714
|
+
if strings.Contains(joined, "references.md") {
|
|
715
|
+
t.Fatalf("sanctioned root artifact must not be treated as misplaced: %q", joined)
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
func TestCheckNamesSizeRemediesForArtifactOverReadCap(t *testing.T) {
|
|
720
|
+
root := t.TempDir()
|
|
721
|
+
writeCompleteGateFeature(t, root, "huge", state.PhaseBuild, state.PhaseBuild, "none\n")
|
|
722
|
+
workspace := filepath.Join(root, "work", "huge")
|
|
723
|
+
// Over the read cap, so the artifact cannot be measured against its line budget.
|
|
724
|
+
// No binding: an over-cap file cannot be hashed into one, and this asserts the
|
|
725
|
+
// size signal alone rather than a passing gate.
|
|
726
|
+
testutil.WriteFile(t, filepath.Join(workspace, "tasks.md"),
|
|
727
|
+
"# Tasks\n\n"+strings.Repeat("n\n", state.MaxArtifactBytes/2+1))
|
|
728
|
+
|
|
729
|
+
res, err := Check(Readiness, root, "huge")
|
|
730
|
+
if err != nil {
|
|
731
|
+
t.Fatal(err)
|
|
732
|
+
}
|
|
733
|
+
joined := strings.Join(res.StateProblems, "\n")
|
|
734
|
+
if !res.Blocked || !strings.Contains(joined, "budget: tasks.md exceeds the") {
|
|
735
|
+
t.Fatalf("blocked=%v StateProblems=%q", res.Blocked, joined)
|
|
736
|
+
}
|
|
737
|
+
if !strings.Contains(joined, "history/") || !strings.Contains(joined, "/rite-plan") {
|
|
738
|
+
t.Fatalf("size remedies must be named: %q", joined)
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
func TestCheckLeavesProofLedgerOvershootAdvisory(t *testing.T) {
|
|
743
|
+
root := t.TempDir()
|
|
744
|
+
writeCompleteGateFeature(t, root, "big-ledger", state.PhaseProve, state.PhaseProve, "none\n")
|
|
745
|
+
workspace := filepath.Join(root, "work", "big-ledger")
|
|
746
|
+
testutil.WriteFile(t, filepath.Join(workspace, "evidence.md"), strings.Repeat("EVID-001 proof line\n", 800))
|
|
747
|
+
testutil.WriteFile(t, filepath.Join(workspace, "touched-files.md"), strings.Repeat("trail line\n", 600))
|
|
748
|
+
|
|
749
|
+
res, err := Check(Readiness, root, "big-ledger")
|
|
750
|
+
if err != nil {
|
|
751
|
+
t.Fatal(err)
|
|
752
|
+
}
|
|
753
|
+
if joined := strings.Join(res.StateProblems, "\n"); strings.Contains(joined, "budget:") {
|
|
754
|
+
t.Fatalf("proof ledgers must stay advisory: %v", res.StateProblems)
|
|
755
|
+
}
|
|
756
|
+
}
|
|
@@ -33,6 +33,8 @@ const (
|
|
|
33
33
|
type candidateRow struct {
|
|
34
34
|
state string
|
|
35
35
|
path string
|
|
36
|
+
slice string
|
|
37
|
+
reason string
|
|
36
38
|
executable bool
|
|
37
39
|
size int64
|
|
38
40
|
info os.FileInfo
|
|
@@ -203,10 +205,12 @@ func parseCandidateManifest(raw []byte) ([]candidateRow, error) {
|
|
|
203
205
|
if err != nil {
|
|
204
206
|
return nil, fmt.Errorf("row %d File: %w", i+1, err)
|
|
205
207
|
}
|
|
206
|
-
|
|
208
|
+
sliceCell := strings.TrimSpace(cells[3])
|
|
209
|
+
if sliceCell == "" {
|
|
207
210
|
return nil, fmt.Errorf("row %d Slice must be nonempty", i+1)
|
|
208
211
|
}
|
|
209
|
-
|
|
212
|
+
reasonCell := strings.TrimSpace(cells[4])
|
|
213
|
+
if reasonCell == "" {
|
|
210
214
|
return nil, fmt.Errorf("row %d Reason must be nonempty", i+1)
|
|
211
215
|
}
|
|
212
216
|
if _, ok := seen[normalized]; ok {
|
|
@@ -221,7 +225,7 @@ func parseCandidateManifest(raw []byte) ([]candidateRow, error) {
|
|
|
221
225
|
}
|
|
222
226
|
seen[normalized] = struct{}{}
|
|
223
227
|
seenFolded[folded] = normalized
|
|
224
|
-
rows = append(rows, candidateRow{state: state, path: normalized})
|
|
228
|
+
rows = append(rows, candidateRow{state: state, path: normalized, slice: sliceCell, reason: reasonCell})
|
|
225
229
|
if len(rows) > maxCandidateRows {
|
|
226
230
|
return nil, errors.New("manifest exceeds 4096 rows")
|
|
227
231
|
}
|