devrites 5.4.0 → 5.6.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 +8 -6
- 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 +18 -0
- package/engine/internal/gate/gate.go +78 -0
- package/engine/internal/gate/gate_test.go +118 -0
- package/engine/internal/hostpack/hostpack.go +45 -6
- package/engine/internal/hostpack/hostpack_test.go +29 -13
- package/engine/internal/install/apply.go +14 -5
- package/engine/internal/install/install.go +8 -2
- package/engine/internal/install/install_test.go +12 -5
- package/engine/internal/install/merge.go +5 -0
- package/engine/internal/install/preflight.go +20 -2
- package/engine/internal/install/uninstall.go +5 -0
- package/engine/internal/install/update.go +1 -1
- 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/install.sh +4 -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 -19
- package/pack/.claude/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/.claude/skills/rite-build/reference/parallel-batch.md +90 -40
- 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/README.md +5 -1
- 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 -19
- package/pack/generated/claude/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/claude/skills/rite-build/reference/parallel-batch.md +90 -40
- 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 -19
- package/pack/generated/codex/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/codex/skills/rite-build/reference/parallel-batch.md +90 -40
- 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 -19
- package/pack/generated/omp/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/omp/skills/rite-build/reference/parallel-batch.md +90 -40
- 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/pack/generated/pi/AGENTS.md +22 -0
- package/pack/generated/pi/agents/devrites-code-reviewer.md +142 -0
- package/pack/generated/pi/agents/devrites-devex-reviewer.md +124 -0
- package/pack/generated/pi/agents/devrites-doubt-reviewer.md +88 -0
- package/pack/generated/pi/agents/devrites-evidence-scout.md +72 -0
- package/pack/generated/pi/agents/devrites-frontend-reviewer.md +116 -0
- package/pack/generated/pi/agents/devrites-performance-reviewer.md +115 -0
- package/pack/generated/pi/agents/devrites-plan-drafter.md +99 -0
- package/pack/generated/pi/agents/devrites-plan-reviewer.md +142 -0
- package/pack/generated/pi/agents/devrites-proof-runner.md +74 -0
- package/pack/generated/pi/agents/devrites-retrospector.md +61 -0
- package/pack/generated/pi/agents/devrites-security-auditor.md +109 -0
- package/pack/generated/pi/agents/devrites-simplifier-reviewer.md +94 -0
- package/pack/generated/pi/agents/devrites-slice-wright.md +204 -0
- package/pack/generated/pi/agents/devrites-spec-reviewer.md +96 -0
- package/pack/generated/pi/agents/devrites-strategy-reviewer.md +100 -0
- package/pack/generated/pi/agents/devrites-test-analyst.md +94 -0
- package/pack/generated/pi/agents/devrites-upgrade-planner.md +89 -0
- package/pack/generated/pi/prompts/rite-adopt.md +5 -0
- package/pack/generated/pi/prompts/rite-autocomplete.md +5 -0
- package/pack/generated/pi/prompts/rite-build.md +5 -0
- package/pack/generated/pi/prompts/rite-clarify.md +5 -0
- package/pack/generated/pi/prompts/rite-converge.md +5 -0
- package/pack/generated/pi/prompts/rite-customize.md +5 -0
- package/pack/generated/pi/prompts/rite-define.md +5 -0
- package/pack/generated/pi/prompts/rite-doctor.md +5 -0
- package/pack/generated/pi/prompts/rite-dogfood.md +5 -0
- package/pack/generated/pi/prompts/rite-explain.md +5 -0
- package/pack/generated/pi/prompts/rite-frame.md +5 -0
- package/pack/generated/pi/prompts/rite-handoff.md +5 -0
- package/pack/generated/pi/prompts/rite-learn.md +5 -0
- package/pack/generated/pi/prompts/rite-plan.md +5 -0
- package/pack/generated/pi/prompts/rite-polish.md +5 -0
- package/pack/generated/pi/prompts/rite-pov.md +5 -0
- package/pack/generated/pi/prompts/rite-pr-feedback.md +5 -0
- package/pack/generated/pi/prompts/rite-pressure-test.md +5 -0
- package/pack/generated/pi/prompts/rite-prototype.md +5 -0
- package/pack/generated/pi/prompts/rite-prove.md +5 -0
- package/pack/generated/pi/prompts/rite-quick.md +5 -0
- package/pack/generated/pi/prompts/rite-resolve.md +5 -0
- package/pack/generated/pi/prompts/rite-review.md +5 -0
- package/pack/generated/pi/prompts/rite-seal.md +5 -0
- package/pack/generated/pi/prompts/rite-ship.md +5 -0
- package/pack/generated/pi/prompts/rite-spec.md +5 -0
- package/pack/generated/pi/prompts/rite-status.md +5 -0
- package/pack/generated/pi/prompts/rite-temper.md +5 -0
- package/pack/generated/pi/prompts/rite-upgrade.md +5 -0
- package/pack/generated/pi/prompts/rite-vet.md +5 -0
- package/pack/generated/pi/prompts/rite-watch-pr.md +5 -0
- package/pack/generated/pi/prompts/rite-zoom-out.md +5 -0
- package/pack/generated/pi/prompts/rite.md +5 -0
- package/pack/generated/pi/skills/devrites-api-interface/SKILL.md +63 -0
- package/pack/generated/pi/skills/devrites-audit/SKILL.md +50 -0
- package/pack/generated/pi/skills/devrites-browser-proof/SKILL.md +76 -0
- package/pack/generated/pi/skills/devrites-browser-proof/reference/browser-performance.md +15 -0
- package/pack/generated/pi/skills/devrites-browser-proof/reference/visual-verdict.md +34 -0
- package/pack/generated/pi/skills/devrites-debug-recovery/SKILL.md +96 -0
- package/pack/generated/pi/skills/devrites-debug-recovery/reference/build-the-loop.md +58 -0
- package/pack/generated/pi/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +34 -0
- package/pack/generated/pi/skills/devrites-debug-recovery/reference/hypotheses.md +17 -0
- package/pack/generated/pi/skills/devrites-debug-recovery/reference/instrumentation.md +21 -0
- package/pack/generated/pi/skills/devrites-debug-recovery/reference/regression-test.md +30 -0
- package/pack/generated/pi/skills/devrites-debug-recovery/reference/trace.md +25 -0
- package/pack/generated/pi/skills/devrites-doubt/SKILL.md +79 -0
- package/pack/generated/pi/skills/devrites-frontend-craft/SKILL.md +86 -0
- package/pack/generated/pi/skills/devrites-frontend-craft/reference/craft.md +63 -0
- package/pack/generated/pi/skills/devrites-frontend-craft/reference/design-references.md +116 -0
- package/pack/generated/pi/skills/devrites-frontend-craft/reference/fullstack.md +46 -0
- package/pack/generated/pi/skills/devrites-frontend-craft/reference/quality-standards.md +294 -0
- package/pack/generated/pi/skills/devrites-frontend-craft/reference/reuse-first.md +53 -0
- package/pack/generated/pi/skills/devrites-frontend-craft/reference/shape.md +56 -0
- package/pack/generated/pi/skills/devrites-interview/SKILL.md +102 -0
- package/pack/generated/pi/skills/devrites-lib/SKILL.md +58 -0
- package/pack/generated/pi/skills/devrites-lib/reference/candidate-integrity.md +42 -0
- package/pack/generated/pi/skills/devrites-lib/reference/intent-map.md +64 -0
- package/pack/generated/pi/skills/devrites-lib/reference/orchestration-profiles.md +27 -0
- package/pack/generated/pi/skills/devrites-lib/reference/parallel-dispatch.md +73 -0
- package/pack/generated/pi/skills/devrites-lib/reference/reply-contract.md +88 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/README.md +60 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/acceptance-preserving-reslice.md +30 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/afk-hitl.md +398 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/agents.md +99 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/anti-patterns.md +48 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/browser-proof-checklist.md +24 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/ci-cd.md +50 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/code-navigation.md +43 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/code-review.md +108 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/coding-style.md +48 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/context-hygiene.md +109 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/core.md +167 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/data-integrity.md +118 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/debug-recovery.md +28 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/definition-of-done.md +19 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/deprecation.md +31 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/developer-experience.md +119 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/development-workflow.md +29 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/documentation.md +43 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/edge-case-trace.md +92 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/elicitation.md +85 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/error-handling.md +47 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/git-workflow.md +49 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/hooks.md +25 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/integration-reliability.md +102 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/loop-operations.md +85 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/observability.md +88 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/one-shot-actions.md +97 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/patterns.md +68 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/performance.md +51 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/principles.md +42 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/prose-style.md +123 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/release/ship-checklist.md +8 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/repository-topology.md +80 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/review-checklist.md +12 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/security-checklist.md +25 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/security.md +202 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/skill-authoring.md +209 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/spec-grammar.md +197 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/test-proof-checklist.md +13 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/testing.md +212 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/tooling.md +92 -0
- package/pack/generated/pi/skills/devrites-lib/reference/standards/workflow-artifacts.md +427 -0
- package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/code.md +44 -0
- package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/comparison.md +42 -0
- package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/diagram.md +51 -0
- package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/index.md +66 -0
- package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/input.md +46 -0
- package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/outline-template.md +106 -0
- package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/plan.md +48 -0
- package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/slides.md +40 -0
- package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/table.md +42 -0
- package/pack/generated/pi/skills/devrites-lib/reference/workspace-artifact-schema.md +267 -0
- package/pack/generated/pi/skills/devrites-prose-craft/SKILL.md +73 -0
- package/pack/generated/pi/skills/devrites-prose-craft/reference/banned-phrases.md +132 -0
- package/pack/generated/pi/skills/devrites-prose-craft/reference/examples.md +131 -0
- package/pack/generated/pi/skills/devrites-prose-craft/reference/structures.md +196 -0
- package/pack/generated/pi/skills/devrites-source-driven/SKILL.md +52 -0
- package/pack/generated/pi/skills/devrites-ux-shape/SKILL.md +134 -0
- package/pack/generated/pi/skills/devrites-ux-shape/reference/brief-template.md +108 -0
- package/pack/generated/pi/skills/devrites-ux-shape/reference/visual-direction-probe.md +48 -0
- package/pack/generated/pi/skills/rite/SKILL.md +148 -0
- package/pack/generated/pi/skills/rite/reference/menu.md +48 -0
- package/pack/generated/pi/skills/rite-adopt/SKILL.md +52 -0
- package/pack/generated/pi/skills/rite-adopt/reference/adoption.md +19 -0
- package/pack/generated/pi/skills/rite-adopt/reference/anti-patterns.md +19 -0
- package/pack/generated/pi/skills/rite-autocomplete/SKILL.md +132 -0
- package/pack/generated/pi/skills/rite-autocomplete/reference/decision-policy.md +41 -0
- package/pack/generated/pi/skills/rite-autocomplete/reference/loop.md +148 -0
- package/pack/generated/pi/skills/rite-autocomplete/reference/stop-conditions.md +92 -0
- package/pack/generated/pi/skills/rite-build/SKILL.md +96 -0
- package/pack/generated/pi/skills/rite-build/reference/afk-discipline.md +145 -0
- package/pack/generated/pi/skills/rite-build/reference/anti-patterns.md +23 -0
- package/pack/generated/pi/skills/rite-build/reference/checkpoint-protocol.md +120 -0
- package/pack/generated/pi/skills/rite-build/reference/checkpoint.md +44 -0
- package/pack/generated/pi/skills/rite-build/reference/frontend-trigger.md +39 -0
- package/pack/generated/pi/skills/rite-build/reference/one-slice-cycle.md +50 -0
- package/pack/generated/pi/skills/rite-build/reference/output.md +33 -0
- package/pack/generated/pi/skills/rite-build/reference/parallel-batch.md +205 -0
- package/pack/generated/pi/skills/rite-build/reference/phase-contract.md +87 -0
- package/pack/generated/pi/skills/rite-build/reference/spec-drift-guard.md +84 -0
- package/pack/generated/pi/skills/rite-build/reference/tdd.md +27 -0
- package/pack/generated/pi/skills/rite-build/reference/wright-dispatch.md +89 -0
- package/pack/generated/pi/skills/rite-clarify/SKILL.md +99 -0
- package/pack/generated/pi/skills/rite-clarify/reference/anti-patterns.md +24 -0
- package/pack/generated/pi/skills/rite-clarify/reference/decision-coverage.md +55 -0
- package/pack/generated/pi/skills/rite-converge/SKILL.md +145 -0
- package/pack/generated/pi/skills/rite-converge/reference/anti-patterns.md +35 -0
- package/pack/generated/pi/skills/rite-converge/reference/convergence-assessment.md +65 -0
- package/pack/generated/pi/skills/rite-customize/SKILL.md +60 -0
- package/pack/generated/pi/skills/rite-define/SKILL.md +169 -0
- package/pack/generated/pi/skills/rite-define/reference/anti-patterns.md +26 -0
- package/pack/generated/pi/skills/rite-define/reference/gates.md +154 -0
- package/pack/generated/pi/skills/rite-define/reference/plan-template.md +149 -0
- package/pack/generated/pi/skills/rite-doctor/SKILL.md +69 -0
- package/pack/generated/pi/skills/rite-dogfood/SKILL.md +55 -0
- package/pack/generated/pi/skills/rite-explain/SKILL.md +152 -0
- package/pack/generated/pi/skills/rite-explain/reference/intake.md +89 -0
- package/pack/generated/pi/skills/rite-frame/SKILL.md +115 -0
- package/pack/generated/pi/skills/rite-frame/reference/failure-modes.md +66 -0
- package/pack/generated/pi/skills/rite-handoff/SKILL.md +97 -0
- package/pack/generated/pi/skills/rite-handoff/reference/handoff-template.md +44 -0
- package/pack/generated/pi/skills/rite-learn/SKILL.md +72 -0
- package/pack/generated/pi/skills/rite-plan/SKILL.md +186 -0
- package/pack/generated/pi/skills/rite-plan/reference/anti-patterns.md +34 -0
- package/pack/generated/pi/skills/rite-plan/reference/dependency-graph.md +48 -0
- package/pack/generated/pi/skills/rite-plan/reference/replan-and-repair.md +105 -0
- package/pack/generated/pi/skills/rite-plan/reference/slicing.md +167 -0
- package/pack/generated/pi/skills/rite-plan/reference/task-breakdown.md +42 -0
- package/pack/generated/pi/skills/rite-polish/SKILL.md +104 -0
- package/pack/generated/pi/skills/rite-polish/reference/adr-promotion.md +11 -0
- package/pack/generated/pi/skills/rite-polish/reference/anti-ai-slop.md +187 -0
- package/pack/generated/pi/skills/rite-polish/reference/anti-patterns.md +30 -0
- package/pack/generated/pi/skills/rite-polish/reference/backend-polish.md +80 -0
- package/pack/generated/pi/skills/rite-polish/reference/browser-polish-evidence.md +33 -0
- package/pack/generated/pi/skills/rite-polish/reference/code.md +82 -0
- package/pack/generated/pi/skills/rite-polish/reference/design-memory.md +117 -0
- package/pack/generated/pi/skills/rite-polish/reference/design-system-discovery.md +8 -0
- package/pack/generated/pi/skills/rite-polish/reference/harden-checklist.md +109 -0
- package/pack/generated/pi/skills/rite-polish/reference/ledger.md +65 -0
- package/pack/generated/pi/skills/rite-polish/reference/ui.md +137 -0
- package/pack/generated/pi/skills/rite-pov/SKILL.md +58 -0
- package/pack/generated/pi/skills/rite-pr-feedback/SKILL.md +54 -0
- package/pack/generated/pi/skills/rite-pressure-test/SKILL.md +67 -0
- package/pack/generated/pi/skills/rite-prototype/SKILL.md +104 -0
- package/pack/generated/pi/skills/rite-prove/SKILL.md +120 -0
- package/pack/generated/pi/skills/rite-prove/reference/acceptance-proof.md +88 -0
- package/pack/generated/pi/skills/rite-prove/reference/anti-patterns.md +25 -0
- package/pack/generated/pi/skills/rite-prove/reference/browser-proof.md +51 -0
- package/pack/generated/pi/skills/rite-prove/reference/failure-triage.md +43 -0
- package/pack/generated/pi/skills/rite-prove/reference/proof-ladder.md +28 -0
- package/pack/generated/pi/skills/rite-prove/reference/test-command-discovery.md +30 -0
- package/pack/generated/pi/skills/rite-quick/SKILL.md +82 -0
- package/pack/generated/pi/skills/rite-resolve/SKILL.md +95 -0
- package/pack/generated/pi/skills/rite-resolve/reference/answer-protocol.md +118 -0
- package/pack/generated/pi/skills/rite-review/SKILL.md +170 -0
- package/pack/generated/pi/skills/rite-review/reference/anti-patterns.md +32 -0
- package/pack/generated/pi/skills/rite-review/reference/cognitive-load.md +90 -0
- package/pack/generated/pi/skills/rite-review/reference/feature-scoped-review.md +26 -0
- package/pack/generated/pi/skills/rite-review/reference/five-axis-review.md +66 -0
- package/pack/generated/pi/skills/rite-review/reference/nielsen-heuristics.md +126 -0
- package/pack/generated/pi/skills/rite-review/reference/performance-checklist.md +80 -0
- package/pack/generated/pi/skills/rite-review/reference/performance-review.md +14 -0
- package/pack/generated/pi/skills/rite-review/reference/security-review.md +42 -0
- package/pack/generated/pi/skills/rite-seal/SKILL.md +75 -0
- package/pack/generated/pi/skills/rite-seal/reference/anti-patterns.md +29 -0
- package/pack/generated/pi/skills/rite-seal/reference/final-evidence.md +41 -0
- package/pack/generated/pi/skills/rite-seal/reference/go-no-go.md +29 -0
- package/pack/generated/pi/skills/rite-seal/reference/output.md +5 -0
- package/pack/generated/pi/skills/rite-seal/reference/phase-contract.md +47 -0
- package/pack/generated/pi/skills/rite-seal/reference/risk-and-rollback.md +56 -0
- package/pack/generated/pi/skills/rite-seal/reference/seal-template.md +27 -0
- package/pack/generated/pi/skills/rite-ship/SKILL.md +88 -0
- package/pack/generated/pi/skills/rite-ship/reference/anti-patterns.md +28 -0
- package/pack/generated/pi/skills/rite-ship/reference/close-out.md +68 -0
- package/pack/generated/pi/skills/rite-ship/reference/git-ship.md +120 -0
- package/pack/generated/pi/skills/rite-ship/reference/rollout.md +62 -0
- package/pack/generated/pi/skills/rite-ship/reference/ship-template.md +39 -0
- package/pack/generated/pi/skills/rite-spec/SKILL.md +150 -0
- package/pack/generated/pi/skills/rite-spec/reference/acceptance-criteria.md +31 -0
- package/pack/generated/pi/skills/rite-spec/reference/ai-spec-template.md +40 -0
- package/pack/generated/pi/skills/rite-spec/reference/anti-patterns.md +27 -0
- package/pack/generated/pi/skills/rite-spec/reference/interview-patterns.md +56 -0
- package/pack/generated/pi/skills/rite-spec/reference/investigation.md +83 -0
- package/pack/generated/pi/skills/rite-spec/reference/question-protocol.md +36 -0
- package/pack/generated/pi/skills/rite-spec/reference/references-intake.md +62 -0
- package/pack/generated/pi/skills/rite-spec/reference/spec-checklists.md +89 -0
- package/pack/generated/pi/skills/rite-spec/reference/spec-template.md +154 -0
- package/pack/generated/pi/skills/rite-spec/reference/state-workspace.md +227 -0
- package/pack/generated/pi/skills/rite-status/SKILL.md +57 -0
- package/pack/generated/pi/skills/rite-temper/SKILL.md +130 -0
- package/pack/generated/pi/skills/rite-temper/reference/anti-patterns.md +30 -0
- package/pack/generated/pi/skills/rite-temper/reference/review-dimensions.md +66 -0
- package/pack/generated/pi/skills/rite-temper/reference/scope-modes.md +53 -0
- package/pack/generated/pi/skills/rite-temper/reference/significance.md +46 -0
- package/pack/generated/pi/skills/rite-temper/reference/strategy-template.md +90 -0
- package/pack/generated/pi/skills/rite-upgrade/SKILL.md +121 -0
- package/pack/generated/pi/skills/rite-vet/SKILL.md +193 -0
- package/pack/generated/pi/skills/rite-vet/reference/anti-patterns.md +43 -0
- package/pack/generated/pi/skills/rite-vet/reference/artifacts.md +202 -0
- package/pack/generated/pi/skills/rite-vet/reference/cross-model.md +19 -0
- package/pack/generated/pi/skills/rite-vet/reference/depth.md +59 -0
- package/pack/generated/pi/skills/rite-vet/reference/eng-lenses.md +48 -0
- package/pack/generated/pi/skills/rite-vet/reference/review-axes.md +201 -0
- package/pack/generated/pi/skills/rite-watch-pr/SKILL.md +85 -0
- package/pack/generated/pi/skills/rite-zoom-out/SKILL.md +69 -0
- package/package.json +3 -2
- package/scripts/build-host-artifacts.sh +54 -4
- package/scripts/codex-generate.sh +6 -0
- package/scripts/pi-generate.sh +198 -0
|
@@ -24,6 +24,7 @@ func (r *runner) install() error {
|
|
|
24
24
|
fmt.Fprintf(r.opts.Stdout, " agents : %s\n", yesno(r.opts.WithAgents))
|
|
25
25
|
fmt.Fprintf(r.opts.Stdout, " codex : %s\n", yesno(r.opts.WithCodex))
|
|
26
26
|
fmt.Fprintf(r.opts.Stdout, " omp : %s\n", yesno(r.opts.WithOmp))
|
|
27
|
+
fmt.Fprintf(r.opts.Stdout, " pi : %s\n", yesno(r.opts.WithPi))
|
|
27
28
|
fmt.Fprintf(r.opts.Stdout, " aliases: %s\n", r.opts.AliasMode)
|
|
28
29
|
if r.opts.DryRun {
|
|
29
30
|
fmt.Fprintln(r.opts.Stdout, " (dry run - no changes will be made)")
|
|
@@ -38,7 +39,7 @@ func (r *runner) install() error {
|
|
|
38
39
|
return err
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
for _, tree := range hostpack.InstallTrees(r.opts.WithSkills, r.opts.WithAgents, r.opts.WithCodex, r.opts.WithOmp) {
|
|
42
|
+
for _, tree := range hostpack.InstallTrees(r.opts.WithSkills, r.opts.WithAgents, r.opts.WithCodex, r.opts.WithOmp, r.opts.WithPi) {
|
|
42
43
|
if err := r.installTree(tree.PayloadPrefix, tree.TargetPrefix); err != nil {
|
|
43
44
|
return fmt.Errorf("install tree %s: %w", tree.TargetPrefix, err)
|
|
44
45
|
}
|
|
@@ -49,7 +50,7 @@ func (r *runner) install() error {
|
|
|
49
50
|
if err != nil {
|
|
50
51
|
return fmt.Errorf("render alias skill %s: %w", alias.Name, err)
|
|
51
52
|
}
|
|
52
|
-
for _, rel := range hostpack.AliasTargets(alias, r.opts.WithCodex, r.opts.WithOmp) {
|
|
53
|
+
for _, rel := range hostpack.AliasTargets(alias, r.opts.WithCodex, r.opts.WithOmp, r.opts.WithPi) {
|
|
53
54
|
if err := r.installData(data, rel); err != nil {
|
|
54
55
|
return fmt.Errorf("install alias: %w", err)
|
|
55
56
|
}
|
|
@@ -64,6 +65,11 @@ func (r *runner) install() error {
|
|
|
64
65
|
return fmt.Errorf("merge %s: %w", hostpack.CodexConfigMerge.TargetRel, err)
|
|
65
66
|
}
|
|
66
67
|
}
|
|
68
|
+
if r.opts.WithSkills && r.opts.WithPi {
|
|
69
|
+
if err := r.mergeMarkerFile(hostpack.PiAgentsMerge); err != nil {
|
|
70
|
+
return fmt.Errorf("merge %s: %w", hostpack.PiAgentsMerge.TargetRel, err)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
67
73
|
if r.opts.WithSkills {
|
|
68
74
|
if err := r.seedClaudeSettings(); err != nil {
|
|
69
75
|
return fmt.Errorf("seed claude settings: %w", err)
|
|
@@ -93,11 +99,11 @@ func (r *runner) install() error {
|
|
|
93
99
|
fmt.Fprintf(r.opts.Stdout, " installed: %d overwritten: %d skipped(conflict): %d pruned: %d\n", r.stats.installed, r.stats.overwrote, r.stats.skipped, r.stats.pruned)
|
|
94
100
|
if !r.opts.DryRun && r.opts.WithSkills {
|
|
95
101
|
switch {
|
|
96
|
-
case r.opts.WithCodex && r.opts.WithOmp:
|
|
97
|
-
fmt.Fprintln(r.opts.Stdout, "Next: reopen the project, then run /rite (Claude) or $rite (Codex) or /skill:rite.")
|
|
102
|
+
case r.opts.WithCodex && (r.opts.WithOmp || r.opts.WithPi):
|
|
103
|
+
fmt.Fprintln(r.opts.Stdout, "Next: reopen the project, then run /rite (Claude) or $rite (Codex) or /skill:rite (omp/pi).")
|
|
98
104
|
case r.opts.WithCodex:
|
|
99
105
|
fmt.Fprintln(r.opts.Stdout, "Next: reopen the project, then run /rite (Claude) or $rite (Codex).")
|
|
100
|
-
case r.opts.WithOmp:
|
|
106
|
+
case r.opts.WithOmp || r.opts.WithPi:
|
|
101
107
|
fmt.Fprintln(r.opts.Stdout, "Next: reopen the project, then run /rite or /skill:rite.")
|
|
102
108
|
default:
|
|
103
109
|
fmt.Fprintln(r.opts.Stdout, "Next: reopen the project, then run /rite.")
|
|
@@ -311,6 +317,9 @@ func (r *runner) flagsString() string {
|
|
|
311
317
|
if !r.opts.WithOmp {
|
|
312
318
|
flags = append(flags, "--no-omp")
|
|
313
319
|
}
|
|
320
|
+
if !r.opts.WithPi {
|
|
321
|
+
flags = append(flags, "--no-pi")
|
|
322
|
+
}
|
|
314
323
|
if !r.opts.WithBinary {
|
|
315
324
|
flags = append(flags, "--no-binary")
|
|
316
325
|
}
|
|
@@ -35,6 +35,7 @@ type Options struct {
|
|
|
35
35
|
WithAgents bool
|
|
36
36
|
WithCodex bool
|
|
37
37
|
WithOmp bool
|
|
38
|
+
WithPi bool
|
|
38
39
|
WithBinary bool
|
|
39
40
|
KeepBinary bool
|
|
40
41
|
AliasMode string
|
|
@@ -84,6 +85,7 @@ func DefaultOptions(mode Mode) Options {
|
|
|
84
85
|
WithAgents: true,
|
|
85
86
|
WithCodex: true,
|
|
86
87
|
WithOmp: true,
|
|
88
|
+
WithPi: true,
|
|
87
89
|
WithBinary: true,
|
|
88
90
|
AliasMode: "safe",
|
|
89
91
|
Stdout: io.Discard,
|
|
@@ -135,6 +137,7 @@ func parseArgs(args []string, opts *Options) error {
|
|
|
135
137
|
force := flags.Bool("force", opts.Force, "")
|
|
136
138
|
noCodex := flags.Bool("no-codex", !opts.WithCodex, "")
|
|
137
139
|
noOmp := flags.Bool("no-omp", !opts.WithOmp, "")
|
|
140
|
+
noPi := flags.Bool("no-pi", !opts.WithPi, "")
|
|
138
141
|
noAgents := flags.Bool("no-agents", !opts.WithAgents, "")
|
|
139
142
|
noSkills := flags.Bool("no-skills", !opts.WithSkills, "")
|
|
140
143
|
noBinary := flags.Bool("no-binary", !opts.WithBinary, "")
|
|
@@ -162,6 +165,7 @@ func parseArgs(args []string, opts *Options) error {
|
|
|
162
165
|
opts.Force = *force
|
|
163
166
|
opts.WithCodex = !*noCodex
|
|
164
167
|
opts.WithOmp = !*noOmp
|
|
168
|
+
opts.WithPi = !*noPi
|
|
165
169
|
opts.WithAgents = !*noAgents
|
|
166
170
|
opts.WithSkills = !*noSkills
|
|
167
171
|
opts.WithBinary = !*noBinary
|
|
@@ -208,7 +212,7 @@ func usage(mode Mode) string {
|
|
|
208
212
|
case ModeUpdate:
|
|
209
213
|
return "usage: devrites-engine update [--target DIR] [--dry-run] [--force] [--check] [install flags] [--source-dir DIR --payload-dir DIR]\n"
|
|
210
214
|
default:
|
|
211
|
-
return "usage: devrites-engine install [--target DIR] [--dry-run] [--force] [--no-codex] [--no-omp] [--no-agents] [--no-skills] [--no-binary] [--short-aliases=all]\n"
|
|
215
|
+
return "usage: devrites-engine install [--target DIR] [--dry-run] [--force] [--no-codex] [--no-omp] [--no-pi] [--no-agents] [--no-skills] [--no-binary] [--short-aliases=all]\n"
|
|
212
216
|
}
|
|
213
217
|
}
|
|
214
218
|
|
|
@@ -333,7 +337,7 @@ func (r *runner) validatePayload() error {
|
|
|
333
337
|
if r.payload == "" {
|
|
334
338
|
return fmt.Errorf("generated install payload not found; pass --payload-dir or run scripts/build-host-artifacts.sh")
|
|
335
339
|
}
|
|
336
|
-
if err := hostpack.ValidatePayload(r.payloadFS, r.opts.WithCodex, r.opts.WithOmp); err != nil {
|
|
340
|
+
if err := hostpack.ValidatePayload(r.payloadFS, r.opts.WithCodex, r.opts.WithOmp, r.opts.WithPi); err != nil {
|
|
337
341
|
return fmt.Errorf("generated install payload under %s: %w", r.payload, err)
|
|
338
342
|
}
|
|
339
343
|
return nil
|
|
@@ -349,6 +353,8 @@ func isGlobalTarget(target string) bool {
|
|
|
349
353
|
filepath.Join(home, ".codex"),
|
|
350
354
|
filepath.Join(home, ".omp"),
|
|
351
355
|
filepath.Join(home, ".omp", "agent"),
|
|
356
|
+
filepath.Join(home, ".pi"),
|
|
357
|
+
filepath.Join(home, ".pi", "agent"),
|
|
352
358
|
} {
|
|
353
359
|
if target == global || strings.HasPrefix(target, global+string(os.PathSeparator)) {
|
|
354
360
|
return true
|
|
@@ -53,12 +53,14 @@ func TestInstallPrintsFirstMoveForInstalledHosts(t *testing.T) {
|
|
|
53
53
|
name string
|
|
54
54
|
withCodex bool
|
|
55
55
|
withOmp bool
|
|
56
|
+
withPi bool
|
|
56
57
|
want string
|
|
57
58
|
}{
|
|
58
|
-
{name: "Claude, Codex, and OMP", withCodex: true, withOmp: true, want: "Next: reopen the project, then run /rite (Claude) or $rite (Codex) or /skill:rite."},
|
|
59
|
-
{name: "Claude and Codex", withCodex: true, withOmp: false, want: "Next: reopen the project, then run /rite (Claude) or $rite (Codex)."},
|
|
60
|
-
{name: "Claude and OMP", withCodex: false, withOmp: true, want: "Next: reopen the project, then run /rite or /skill:rite."},
|
|
61
|
-
{name: "Claude
|
|
59
|
+
{name: "Claude, Codex, and OMP", withCodex: true, withOmp: true, want: "Next: reopen the project, then run /rite (Claude) or $rite (Codex) or /skill:rite (omp/pi)."},
|
|
60
|
+
{name: "Claude and Codex", withCodex: true, withOmp: false, withPi: false, want: "Next: reopen the project, then run /rite (Claude) or $rite (Codex)."},
|
|
61
|
+
{name: "Claude and OMP", withCodex: false, withOmp: true, withPi: false, want: "Next: reopen the project, then run /rite or /skill:rite."},
|
|
62
|
+
{name: "Claude and pi", withCodex: false, withOmp: false, withPi: true, want: "Next: reopen the project, then run /rite or /skill:rite."},
|
|
63
|
+
{name: "Claude only", withCodex: false, withOmp: false, withPi: false, want: "Next: reopen the project, then run /rite."},
|
|
62
64
|
} {
|
|
63
65
|
t.Run(tc.name, func(t *testing.T) {
|
|
64
66
|
var out bytes.Buffer
|
|
@@ -67,6 +69,7 @@ func TestInstallPrintsFirstMoveForInstalledHosts(t *testing.T) {
|
|
|
67
69
|
opts.PayloadDir = testPayload(t)
|
|
68
70
|
opts.WithCodex = tc.withCodex
|
|
69
71
|
opts.WithOmp = tc.withOmp
|
|
72
|
+
opts.WithPi = tc.withPi
|
|
70
73
|
opts.Stdout = &out
|
|
71
74
|
opts.Stderr = &bytes.Buffer{}
|
|
72
75
|
|
|
@@ -758,7 +761,7 @@ func TestLegacyCodexHooksMergeIsCleanupOnly(t *testing.T) {
|
|
|
758
761
|
if !ok || merge != legacy {
|
|
759
762
|
t.Fatalf("legacy marker lookup = %#v, %t", merge, ok)
|
|
760
763
|
}
|
|
761
|
-
if slices.Contains(hostpack.RequiredPayload(true, true), "codex/hooks.json") {
|
|
764
|
+
if slices.Contains(hostpack.RequiredPayload(true, true, true), "codex/hooks.json") {
|
|
762
765
|
t.Fatal("legacy Codex hooks entered the required payload")
|
|
763
766
|
}
|
|
764
767
|
r := runner{opts: DefaultOptions(ModeInstall), payloadFS: os.DirFS(testPayload(t))}
|
|
@@ -1247,6 +1250,10 @@ extends = ":workspace"
|
|
|
1247
1250
|
testutil.WriteFile(t, filepath.Join(root, "omp", "skills", "rite", "SKILL.md"), "omp rite\n")
|
|
1248
1251
|
testutil.WriteFile(t, filepath.Join(root, "omp", "agents", "devrites-code-reviewer.md"), "omp agent\n")
|
|
1249
1252
|
testutil.WriteFile(t, filepath.Join(root, "omp", ".omp-plugin", "plugin.json"), "{}\n")
|
|
1253
|
+
testutil.WriteFile(t, filepath.Join(root, "pi", "skills", "rite", "SKILL.md"), "pi rite\n")
|
|
1254
|
+
testutil.WriteFile(t, filepath.Join(root, "pi", "agents", "devrites-code-reviewer.md"), "pi agent\n")
|
|
1255
|
+
testutil.WriteFile(t, filepath.Join(root, "pi", "prompts", "rite.md"), "pi prompt\n")
|
|
1256
|
+
testutil.WriteFile(t, filepath.Join(root, "pi", "AGENTS.md"), "<!-- BEGIN DEVRITES PI -->\nDevRites\n<!-- END DEVRITES PI -->\n")
|
|
1250
1257
|
}
|
|
1251
1258
|
|
|
1252
1259
|
func testSource(t *testing.T, version string) string {
|
|
@@ -63,6 +63,11 @@ func (r *runner) mergeMarkerFile(merge hostpack.MarkerMerge) error {
|
|
|
63
63
|
if err := fsutil.WriteFileAtomic(dest, next, 0o644); err != nil {
|
|
64
64
|
return fmt.Errorf("cannot write %s: %w", merge.TargetRel, err)
|
|
65
65
|
}
|
|
66
|
+
// Multiple marker blocks can share one target (AGENTS.md carries both
|
|
67
|
+
// the Codex and pi blocks).
|
|
68
|
+
if err := r.refreshPreflight(merge.TargetRel); err != nil {
|
|
69
|
+
return err
|
|
70
|
+
}
|
|
66
71
|
}
|
|
67
72
|
return r.installMarker(merge.MarkerRel, merge.MarkerText)
|
|
68
73
|
}
|
|
@@ -93,7 +93,7 @@ func (r *runner) preflightUninstall(entries []string) error {
|
|
|
93
93
|
|
|
94
94
|
func (r *runner) desiredInstallPaths() (map[string]bool, error) {
|
|
95
95
|
out := map[string]bool{".devrites/README.md": true}
|
|
96
|
-
for _, tree := range hostpack.InstallTrees(r.opts.WithSkills, r.opts.WithAgents, r.opts.WithCodex, r.opts.WithOmp) {
|
|
96
|
+
for _, tree := range hostpack.InstallTrees(r.opts.WithSkills, r.opts.WithAgents, r.opts.WithCodex, r.opts.WithOmp, r.opts.WithPi) {
|
|
97
97
|
err := fs.WalkDir(r.payloadFS, tree.PayloadPrefix, func(path string, d fs.DirEntry, err error) error {
|
|
98
98
|
if err != nil {
|
|
99
99
|
return err
|
|
@@ -114,7 +114,7 @@ func (r *runner) desiredInstallPaths() (map[string]bool, error) {
|
|
|
114
114
|
}
|
|
115
115
|
if r.opts.WithSkills && r.opts.AliasMode == "all" {
|
|
116
116
|
for _, alias := range hostpack.Aliases {
|
|
117
|
-
for _, rel := range hostpack.AliasTargets(alias, r.opts.WithCodex, r.opts.WithOmp) {
|
|
117
|
+
for _, rel := range hostpack.AliasTargets(alias, r.opts.WithCodex, r.opts.WithOmp, r.opts.WithPi) {
|
|
118
118
|
out[rel] = true
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -123,6 +123,9 @@ func (r *runner) desiredInstallPaths() (map[string]bool, error) {
|
|
|
123
123
|
out[hostpack.CodexAgentsMerge.MarkerRel] = true
|
|
124
124
|
out[hostpack.CodexConfigMerge.MarkerRel] = true
|
|
125
125
|
}
|
|
126
|
+
if r.opts.WithSkills && r.opts.WithPi {
|
|
127
|
+
out[hostpack.PiAgentsMerge.MarkerRel] = true
|
|
128
|
+
}
|
|
126
129
|
if r.opts.WithSkills {
|
|
127
130
|
out[hostpack.ClaudeSettingsMerge.MarkerRel] = true
|
|
128
131
|
}
|
|
@@ -136,6 +139,9 @@ func (r *runner) installMergeTargets() []string {
|
|
|
136
139
|
if r.opts.WithCodex {
|
|
137
140
|
out = append(out, hostpack.CodexAgentsMerge.TargetRel, hostpack.CodexConfigMerge.TargetRel)
|
|
138
141
|
}
|
|
142
|
+
if r.opts.WithPi {
|
|
143
|
+
out = append(out, hostpack.PiAgentsMerge.TargetRel)
|
|
144
|
+
}
|
|
139
145
|
}
|
|
140
146
|
return out
|
|
141
147
|
}
|
|
@@ -153,6 +159,18 @@ func (r *runner) rememberPath(rel string) (pathSnapshot, error) {
|
|
|
153
159
|
return snapshot, nil
|
|
154
160
|
}
|
|
155
161
|
|
|
162
|
+
// refreshPreflight replaces a recorded snapshot after the runner's own
|
|
163
|
+
// verified write (marker merge, strip). Needed when several managed merges
|
|
164
|
+
// share one target such as AGENTS.md.
|
|
165
|
+
func (r *runner) refreshPreflight(rel string) error {
|
|
166
|
+
snap, err := inspectManagedPath(r.target, rel)
|
|
167
|
+
if err != nil {
|
|
168
|
+
return err
|
|
169
|
+
}
|
|
170
|
+
r.preflight[filepath.ToSlash(rel)] = snap
|
|
171
|
+
return nil
|
|
172
|
+
}
|
|
173
|
+
|
|
156
174
|
func (r *runner) recheckPath(rel string) error {
|
|
157
175
|
rel = filepath.ToSlash(rel)
|
|
158
176
|
before, ok := r.preflight[rel]
|
|
@@ -58,6 +58,11 @@ func (r *runner) uninstall() error {
|
|
|
58
58
|
if err := stripMarkerPath(filepath.Join(r.target, filepath.FromSlash(merge.TargetRel)), merge.Begin, merge.End); err != nil {
|
|
59
59
|
return fmt.Errorf("strip marker block from %s: %w", merge.TargetRel, err)
|
|
60
60
|
}
|
|
61
|
+
// The Codex and pi AGENTS.md blocks share one target; record the strip
|
|
62
|
+
// so the next merge's recheckPath sees our own write, not a race.
|
|
63
|
+
if err := r.refreshPreflight(merge.TargetRel); err != nil {
|
|
64
|
+
return err
|
|
65
|
+
}
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
var dirs []string
|
|
@@ -65,7 +65,7 @@ func runUpdate(opts Options) error {
|
|
|
65
65
|
if err != nil {
|
|
66
66
|
return fmt.Errorf("resolve payload %s: %w", opts.PayloadDir, err)
|
|
67
67
|
}
|
|
68
|
-
if err := hostpack.ValidatePayload(os.DirFS(payload), true, true); err != nil {
|
|
68
|
+
if err := hostpack.ValidatePayload(os.DirFS(payload), true, true, true); err != nil {
|
|
69
69
|
return fmt.Errorf("local update payload under %s is invalid: %w", payload, err)
|
|
70
70
|
}
|
|
71
71
|
installFlags := manifestHeader(mf, "devrites-flags")
|
|
@@ -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
|
}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
package lib
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"errors"
|
|
5
|
+
"fmt"
|
|
6
|
+
"io"
|
|
7
|
+
"os"
|
|
8
|
+
"path/filepath"
|
|
9
|
+
"sort"
|
|
10
|
+
"strings"
|
|
11
|
+
|
|
12
|
+
"github.com/devrites/devrites/internal/devritespaths"
|
|
13
|
+
"github.com/devrites/devrites/internal/state"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// maxSequenceChain bounds the sequence_parent walk so a malformed cycle cannot
|
|
17
|
+
// loop forever; real chains are far smaller.
|
|
18
|
+
const maxSequenceChain = 64
|
|
19
|
+
|
|
20
|
+
// RunMergeManifest folds predecessor candidate manifests into the release
|
|
21
|
+
// workspace's `## Candidate manifest` so a release milestone's prove/review/seal
|
|
22
|
+
// binds the union surface instead of only its own slices. On a path collision
|
|
23
|
+
// the later sequence position's row wins (it records the most recent touch).
|
|
24
|
+
// Everything outside the manifest section of the release workspace's
|
|
25
|
+
// touched-files.md is preserved.
|
|
26
|
+
//
|
|
27
|
+
// args is `<slug>` to walk the recorded `sequence_parent` chain, or
|
|
28
|
+
// `<slug> <predecessor> [<predecessor>...]` for an explicit ordered list —
|
|
29
|
+
// required for chains recorded before the sequence cursor fields existed.
|
|
30
|
+
// Exit codes:
|
|
31
|
+
//
|
|
32
|
+
// 0 merged and written
|
|
33
|
+
// 2 usage error
|
|
34
|
+
// 3 blocked: a workspace, manifest, or chain check failed
|
|
35
|
+
// 1 internal/IO error
|
|
36
|
+
func RunMergeManifest(root string, args []string, stdout, stderr io.Writer) int {
|
|
37
|
+
if len(args) < 1 {
|
|
38
|
+
fmt.Fprintln(stderr, "usage: devrites-engine state merge-manifest <slug> [<predecessor>...]")
|
|
39
|
+
return 2
|
|
40
|
+
}
|
|
41
|
+
slug := args[0]
|
|
42
|
+
workspace, err := devritespaths.ExistingFeatureDirChecked(root, slug)
|
|
43
|
+
if err != nil {
|
|
44
|
+
fmt.Fprintf(stderr, "merge-manifest: BLOCKED: workspace for %s: %v\n", slug, err)
|
|
45
|
+
return 3
|
|
46
|
+
}
|
|
47
|
+
if err := state.RequireWorkspaceSchema(root, slug); err != nil {
|
|
48
|
+
fmt.Fprintf(stderr, "merge-manifest: BLOCKED: %v\n", err)
|
|
49
|
+
return 3
|
|
50
|
+
}
|
|
51
|
+
manifestPath := filepath.Join(workspace, "touched-files.md")
|
|
52
|
+
releaseRaw, err := readBoundedRegularFile(manifestPath, maxCandidateManifestBytes)
|
|
53
|
+
if err != nil {
|
|
54
|
+
fmt.Fprintf(stderr, "merge-manifest: BLOCKED: candidate manifest %s: %v\n", manifestPath, err)
|
|
55
|
+
return 3
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
var manifests [][]candidateRow
|
|
59
|
+
if len(args) > 1 {
|
|
60
|
+
manifests, err = explicitManifests(root, slug, args[1:])
|
|
61
|
+
} else {
|
|
62
|
+
// The walked chain is validated inside walkSequenceChain; only its
|
|
63
|
+
// manifests feed the union.
|
|
64
|
+
_, manifests, err = walkSequenceChain(root, slug, workspace)
|
|
65
|
+
}
|
|
66
|
+
if err != nil {
|
|
67
|
+
fmt.Fprintf(stderr, "merge-manifest: BLOCKED: %v\n", err)
|
|
68
|
+
return 3
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
merged := make(map[string]candidateRow)
|
|
72
|
+
collisions := 0
|
|
73
|
+
fold := func(rows []candidateRow) {
|
|
74
|
+
for _, row := range rows {
|
|
75
|
+
if _, dup := merged[row.path]; dup {
|
|
76
|
+
collisions++
|
|
77
|
+
}
|
|
78
|
+
merged[row.path] = row
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
for _, rows := range manifests {
|
|
82
|
+
fold(rows)
|
|
83
|
+
}
|
|
84
|
+
releaseRows, err := parseCandidateManifest(releaseRaw)
|
|
85
|
+
if err != nil {
|
|
86
|
+
fmt.Fprintf(stderr, "merge-manifest: BLOCKED: candidate manifest %s: %v\n", manifestPath, err)
|
|
87
|
+
return 3
|
|
88
|
+
}
|
|
89
|
+
fold(releaseRows)
|
|
90
|
+
|
|
91
|
+
paths := make([]string, 0, len(merged))
|
|
92
|
+
for path := range merged {
|
|
93
|
+
paths = append(paths, path)
|
|
94
|
+
}
|
|
95
|
+
sort.Strings(paths)
|
|
96
|
+
body := make([]string, 0, len(paths)+2)
|
|
97
|
+
if len(paths) == 0 {
|
|
98
|
+
body = append(body, "No project files.")
|
|
99
|
+
} else {
|
|
100
|
+
body = append(body, "| State | File | Slice | Reason |", "| --- | --- | --- | --- |")
|
|
101
|
+
for _, path := range paths {
|
|
102
|
+
row := merged[path]
|
|
103
|
+
body = append(body, fmt.Sprintf("| %s | `%s` | %s | %s |", row.state, row.path, row.slice, row.reason))
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
updated, err := replaceManifestSectionBody(releaseRaw, body)
|
|
107
|
+
if err != nil {
|
|
108
|
+
fmt.Fprintf(stderr, "merge-manifest: BLOCKED: candidate manifest %s: %v\n", manifestPath, err)
|
|
109
|
+
return 3
|
|
110
|
+
}
|
|
111
|
+
if err := state.AtomicWrite(manifestPath, updated, 0o644); err != nil {
|
|
112
|
+
fmt.Fprintf(stderr, "merge-manifest: cannot write %s: %v\n", manifestPath, err)
|
|
113
|
+
return 1
|
|
114
|
+
}
|
|
115
|
+
fmt.Fprintf(stdout, "merge-manifest: merged %d manifest(s) into %d row(s)", len(manifests)+1, len(paths))
|
|
116
|
+
if collisions > 0 {
|
|
117
|
+
fmt.Fprintf(stdout, " (%d path collision(s), later position kept)", collisions)
|
|
118
|
+
}
|
|
119
|
+
fmt.Fprintln(stdout)
|
|
120
|
+
return 0
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// explicitManifests parses the caller-ordered predecessor list. When the
|
|
124
|
+
// workspace carries a sequence_parent cursor, the last predecessor must be the
|
|
125
|
+
// recorded parent; a mismatch means the list does not describe this chain.
|
|
126
|
+
func explicitManifests(root, slug string, predecessors []string) ([][]candidateRow, error) {
|
|
127
|
+
seen := make(map[string]struct{}, len(predecessors))
|
|
128
|
+
for _, pred := range predecessors {
|
|
129
|
+
if pred == slug {
|
|
130
|
+
return nil, fmt.Errorf("predecessor %q names the target workspace", pred)
|
|
131
|
+
}
|
|
132
|
+
if _, dup := seen[pred]; dup {
|
|
133
|
+
return nil, fmt.Errorf("duplicate predecessor %q", pred)
|
|
134
|
+
}
|
|
135
|
+
seen[pred] = struct{}{}
|
|
136
|
+
}
|
|
137
|
+
if parent := sequenceParent(root, slug); parent != "" && parent != predecessors[len(predecessors)-1] {
|
|
138
|
+
return nil, fmt.Errorf("%s records sequence_parent %q; pass the full ordered predecessor list ending with it (or no list to walk the recorded chain)", slug, parent)
|
|
139
|
+
}
|
|
140
|
+
manifests := make([][]candidateRow, 0, len(predecessors))
|
|
141
|
+
for _, pred := range predecessors {
|
|
142
|
+
rows, err := predecessorManifestRows(root, pred)
|
|
143
|
+
if err != nil {
|
|
144
|
+
return nil, fmt.Errorf("predecessor %s: %w", pred, err)
|
|
145
|
+
}
|
|
146
|
+
manifests = append(manifests, rows)
|
|
147
|
+
}
|
|
148
|
+
return manifests, nil
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// walkSequenceChain follows the target workspace's sequence_parent links to the
|
|
152
|
+
// chain head, returning predecessors oldest-first with their manifests. Every
|
|
153
|
+
// link must resolve to a live or archived workspace carrying the cursor field;
|
|
154
|
+
// a broken link refuses the merge rather than producing a partial union.
|
|
155
|
+
func walkSequenceChain(root, slug, workspace string) ([]string, [][]candidateRow, error) {
|
|
156
|
+
visited := map[string]struct{}{slug: {}}
|
|
157
|
+
chain := []string{}
|
|
158
|
+
manifests := [][]candidateRow{}
|
|
159
|
+
dir := workspace
|
|
160
|
+
for len(chain) < maxSequenceChain {
|
|
161
|
+
raw, err := readBoundedRegularFile(filepath.Join(dir, "state.md"), maxCandidateManifestBytes)
|
|
162
|
+
if err != nil {
|
|
163
|
+
return nil, nil, fmt.Errorf("%s state.md: %w", filepath.Base(dir), err)
|
|
164
|
+
}
|
|
165
|
+
parent, _ := state.CursorField(strings.Split(string(raw), "\n"), state.CursorSequenceParent)
|
|
166
|
+
if parent == "" {
|
|
167
|
+
break
|
|
168
|
+
}
|
|
169
|
+
if _, dup := visited[parent]; dup {
|
|
170
|
+
return nil, nil, fmt.Errorf("sequence_parent cycle at %q", parent)
|
|
171
|
+
}
|
|
172
|
+
visited[parent] = struct{}{}
|
|
173
|
+
rows, err := predecessorManifestRows(root, parent)
|
|
174
|
+
if err != nil {
|
|
175
|
+
return nil, nil, fmt.Errorf("sequence_parent %s: %w", parent, err)
|
|
176
|
+
}
|
|
177
|
+
dir, err = devritespaths.ExistingFeatureDirChecked(root, parent)
|
|
178
|
+
if errors.Is(err, os.ErrNotExist) {
|
|
179
|
+
dir, err = devritespaths.ExistingArchivedFeatureDirChecked(root, parent)
|
|
180
|
+
}
|
|
181
|
+
if err != nil {
|
|
182
|
+
return nil, nil, fmt.Errorf("sequence_parent %s: %w", parent, err)
|
|
183
|
+
}
|
|
184
|
+
chain = append(chain, parent)
|
|
185
|
+
manifests = append(manifests, rows)
|
|
186
|
+
}
|
|
187
|
+
if len(chain) == 0 {
|
|
188
|
+
return nil, nil, fmt.Errorf("%s has no sequence_parent; pass an explicit ordered predecessor list", slug)
|
|
189
|
+
}
|
|
190
|
+
for i, j := 0, len(chain)-1; i < j; i, j = i+1, j-1 {
|
|
191
|
+
chain[i], chain[j] = chain[j], chain[i]
|
|
192
|
+
manifests[i], manifests[j] = manifests[j], manifests[i]
|
|
193
|
+
}
|
|
194
|
+
return chain, manifests, nil
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
func sequenceParent(root, slug string) string {
|
|
198
|
+
dir, err := devritespaths.ExistingFeatureDirChecked(root, slug)
|
|
199
|
+
if err != nil {
|
|
200
|
+
return ""
|
|
201
|
+
}
|
|
202
|
+
raw, err := readBoundedRegularFile(filepath.Join(dir, "state.md"), maxCandidateManifestBytes)
|
|
203
|
+
if err != nil {
|
|
204
|
+
return ""
|
|
205
|
+
}
|
|
206
|
+
parent, _ := state.CursorField(strings.Split(string(raw), "\n"), state.CursorSequenceParent)
|
|
207
|
+
return parent
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// VerifyReleaseUnion enforces the release-milestone contract at the candidate
|
|
211
|
+
// and seal gates: a workspace whose cursor declares `sequence_role: release`
|
|
212
|
+
// must carry a candidate manifest covering every predecessor in its recorded
|
|
213
|
+
// `sequence_parent` chain. Workspaces without the role are unaffected.
|
|
214
|
+
func VerifyReleaseUnion(root, slug string) error {
|
|
215
|
+
dir, err := devritespaths.ExistingFeatureDirChecked(root, slug)
|
|
216
|
+
if err != nil {
|
|
217
|
+
return fmt.Errorf("workspace for %s: %w", slug, err)
|
|
218
|
+
}
|
|
219
|
+
raw, err := readBoundedRegularFile(filepath.Join(dir, "state.md"), maxCandidateManifestBytes)
|
|
220
|
+
if errors.Is(err, os.ErrNotExist) {
|
|
221
|
+
return nil // no state.md: nothing declares the release role
|
|
222
|
+
}
|
|
223
|
+
if err != nil {
|
|
224
|
+
return fmt.Errorf("%s state.md: %w", slug, err)
|
|
225
|
+
}
|
|
226
|
+
role, _ := state.CursorField(strings.Split(string(raw), "\n"), state.CursorSequenceRole)
|
|
227
|
+
if role != "release" {
|
|
228
|
+
return nil
|
|
229
|
+
}
|
|
230
|
+
_, manifests, err := walkSequenceChain(root, slug, dir)
|
|
231
|
+
if err != nil {
|
|
232
|
+
return err
|
|
233
|
+
}
|
|
234
|
+
manifestRaw, err := readBoundedRegularFile(filepath.Join(dir, "touched-files.md"), maxCandidateManifestBytes)
|
|
235
|
+
if err != nil {
|
|
236
|
+
return fmt.Errorf("candidate manifest: %w", err)
|
|
237
|
+
}
|
|
238
|
+
rows, err := parseCandidateManifest(manifestRaw)
|
|
239
|
+
if err != nil {
|
|
240
|
+
return fmt.Errorf("candidate manifest: %w", err)
|
|
241
|
+
}
|
|
242
|
+
declared := make(map[string]struct{}, len(rows))
|
|
243
|
+
for _, row := range rows {
|
|
244
|
+
declared[row.path] = struct{}{}
|
|
245
|
+
}
|
|
246
|
+
var missing []string
|
|
247
|
+
for _, ancestor := range manifests {
|
|
248
|
+
for _, row := range ancestor {
|
|
249
|
+
if _, ok := declared[row.path]; !ok {
|
|
250
|
+
missing = append(missing, row.path)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if len(missing) > 0 {
|
|
255
|
+
sort.Strings(missing)
|
|
256
|
+
const show = 8
|
|
257
|
+
list := missing
|
|
258
|
+
if len(list) > show {
|
|
259
|
+
list = append(append([]string(nil), missing[:show]...), fmt.Sprintf("…and %d more", len(missing)-show))
|
|
260
|
+
}
|
|
261
|
+
return fmt.Errorf("release manifest does not cover the recorded sequence chain; run `devrites-engine state merge-manifest %s`. Missing: %s", slug, strings.Join(list, ", "))
|
|
262
|
+
}
|
|
263
|
+
return nil
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// predecessorManifestRows loads the candidate manifest of a sealed or archived
|
|
267
|
+
// predecessor workspace. Live workspaces win over archive entries so an
|
|
268
|
+
// unshipped sequence member is always found first.
|
|
269
|
+
func predecessorManifestRows(root, slug string) ([]candidateRow, error) {
|
|
270
|
+
dir, err := devritespaths.ExistingFeatureDirChecked(root, slug)
|
|
271
|
+
if errors.Is(err, os.ErrNotExist) {
|
|
272
|
+
dir, err = devritespaths.ExistingArchivedFeatureDirChecked(root, slug)
|
|
273
|
+
}
|
|
274
|
+
if err != nil {
|
|
275
|
+
return nil, fmt.Errorf("no live or archived workspace: %w", err)
|
|
276
|
+
}
|
|
277
|
+
raw, err := readBoundedRegularFile(filepath.Join(dir, "touched-files.md"), maxCandidateManifestBytes)
|
|
278
|
+
if err != nil {
|
|
279
|
+
return nil, fmt.Errorf("candidate manifest: %w", err)
|
|
280
|
+
}
|
|
281
|
+
rows, err := parseCandidateManifest(raw)
|
|
282
|
+
if err != nil {
|
|
283
|
+
return nil, fmt.Errorf("candidate manifest: %w", err)
|
|
284
|
+
}
|
|
285
|
+
return rows, nil
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// replaceManifestSectionBody rewrites the body of the single
|
|
289
|
+
// `## Candidate manifest` section, keeping every other byte of the file —
|
|
290
|
+
// headings, `## Touched files` narrative, and `## Review trail` — intact.
|
|
291
|
+
func replaceManifestSectionBody(raw []byte, body []string) ([]byte, error) {
|
|
292
|
+
text := string(raw)
|
|
293
|
+
crlf := strings.Contains(text, "\r\n")
|
|
294
|
+
lines := strings.Split(text, "\n")
|
|
295
|
+
start, count := -1, 0
|
|
296
|
+
for i, line := range lines {
|
|
297
|
+
if strings.TrimSpace(line) == "## Candidate manifest" {
|
|
298
|
+
start = i + 1
|
|
299
|
+
count++
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if count != 1 {
|
|
303
|
+
return nil, errors.New("requires exactly one ## Candidate manifest section")
|
|
304
|
+
}
|
|
305
|
+
end := len(lines)
|
|
306
|
+
for i := start; i < len(lines); i++ {
|
|
307
|
+
if strings.HasPrefix(strings.TrimSpace(lines[i]), "## ") {
|
|
308
|
+
end = i
|
|
309
|
+
break
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
emitted := append([]string(nil), body...)
|
|
313
|
+
if crlf {
|
|
314
|
+
for i := range emitted {
|
|
315
|
+
emitted[i] += "\r"
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if end < len(lines) {
|
|
319
|
+
emitted = append(emitted, "")
|
|
320
|
+
if crlf {
|
|
321
|
+
emitted[len(emitted)-1] = "\r"
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
lines = append(lines[:start], append(emitted, lines[end:]...)...)
|
|
325
|
+
return []byte(strings.Join(lines, "\n")), nil
|
|
326
|
+
}
|