devrites 5.14.3 → 6.0.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 +26 -0
- package/NOTICE.md +6 -4
- package/README.md +77 -16
- package/SECURITY.md +25 -11
- package/bin/devrites.mjs +49 -15
- package/docs/adr/0001-go-engine-as-control-plane.md +6 -3
- package/docs/adr/0029-v5-workspace-schema-and-native-migration.md +9 -0
- package/docs/adr/README.md +3 -2
- package/docs/agents/issue-tracker.md +1 -1
- package/docs/architecture.md +6 -3
- package/docs/cli.md +32 -9
- package/docs/command-map.md +5 -3
- package/docs/engine/state-schema.md +1 -1
- package/docs/flow.md +1 -1
- package/docs/harness-compliance.md +2 -2
- package/docs/release.md +15 -11
- package/docs/usage.md +1 -1
- package/engine/commands.go +1 -1
- package/engine/go.mod +1 -1
- package/engine/help.go +41 -15
- package/engine/help_test.go +134 -0
- package/engine/internal/acceptance/acceptance_test.go +298 -7
- package/engine/internal/acceptance/approve.go +7 -2
- package/engine/internal/acceptance/cli.go +3 -0
- package/engine/internal/acceptance/evidence.go +69 -5
- package/engine/internal/acceptance/lint.go +1 -1
- package/engine/internal/acceptance/run.go +5 -3
- package/engine/internal/acceptance/scaffold.go +5 -16
- package/engine/internal/devritespaths/paths.go +7 -6
- package/engine/internal/devritespaths/paths_test.go +18 -0
- package/engine/internal/fsutil/copy.go +83 -49
- package/engine/internal/fsutil/copy_test.go +70 -109
- package/engine/internal/gate/gate.go +89 -16
- package/engine/internal/gate/gate_test.go +101 -0
- package/engine/internal/hostpack/hostpack.go +52 -2
- package/engine/internal/hostpack/hostpack_test.go +83 -2
- package/engine/internal/install/apply.go +59 -16
- package/engine/internal/install/binary.go +10 -1
- package/engine/internal/install/install_test.go +428 -0
- package/engine/internal/install/merge.go +69 -38
- package/engine/internal/install/preflight.go +7 -0
- package/engine/internal/install/uninstall.go +43 -4
- package/engine/internal/lib/claims.go +25 -4
- package/engine/internal/lib/claims_test.go +57 -0
- package/engine/internal/lib/closeout.go +41 -3
- package/engine/internal/lib/closeout_test.go +144 -0
- package/engine/internal/lib/context.go +8 -4
- package/engine/internal/lib/context_next_test.go +100 -0
- package/engine/internal/lib/detect.go +1 -1
- package/engine/internal/lib/detect_test.go +13 -0
- package/engine/internal/lib/diffscope.go +19 -9
- package/engine/internal/lib/dispatch.go +7 -0
- package/engine/internal/lib/dup.go +40 -37
- package/engine/internal/lib/dup_test.go +178 -0
- package/engine/internal/lib/manifest_union.go +4 -1
- package/engine/internal/lib/manifest_union_test.go +37 -0
- package/engine/internal/lib/metrics.go +4 -0
- package/engine/internal/lib/metrics_test.go +28 -0
- package/engine/internal/lib/migrate_test.go +59 -0
- package/engine/internal/lib/observe_budgets.go +25 -9
- package/engine/internal/lib/observe_budgets_test.go +254 -0
- package/engine/internal/lib/observe_summary.go +23 -2
- package/engine/internal/lib/open_visual.go +4 -2
- package/engine/internal/lib/open_visual_test.go +11 -0
- package/engine/internal/lib/regression.go +62 -23
- package/engine/internal/lib/regression_test.go +103 -0
- package/engine/internal/lib/resolve.go +36 -17
- package/engine/internal/lib/resolve_remediation_test.go +132 -0
- package/engine/internal/lib/skilltrust.go +0 -11
- package/engine/internal/lib/slicecheck.go +7 -5
- package/engine/internal/lib/slicecheck_test.go +18 -0
- package/engine/internal/lib/triggers.go +9 -3
- package/engine/internal/lib/triggers_test.go +23 -0
- package/engine/internal/lib/util.go +17 -3
- package/engine/internal/lib/util_test.go +104 -0
- package/engine/internal/lib/visual_outline.go +7 -3
- package/engine/internal/lib/visual_outline_test.go +28 -0
- package/engine/internal/lib/windows.go +13 -9
- package/engine/internal/lib/windows_test.go +98 -0
- package/engine/internal/lib/workspace_read.go +2 -11
- package/engine/internal/lib/workspace_read_test.go +102 -0
- package/engine/internal/markdowntext/markdowntext.go +194 -11
- package/engine/internal/markdowntext/testdata/structural.json +250 -0
- package/engine/internal/notes/cli.go +30 -12
- package/engine/internal/notes/notes.go +242 -39
- package/engine/internal/notes/notes_test.go +372 -0
- package/engine/internal/overhaul/admit/packet.go +89 -0
- package/engine/internal/overhaul/admit/packet_test.go +223 -0
- package/engine/internal/overhaul/admit/run.go +4 -0
- package/engine/internal/overhaul/bench/run.go +6 -0
- package/engine/internal/overhaul/bench/run_test.go +46 -0
- package/engine/internal/overhaul/overhaul.go +6 -1
- package/engine/internal/overhaul/ovio/ovio.go +10 -3
- package/engine/internal/overhaul/ovio/ovio_test.go +75 -0
- package/engine/internal/overhaul/packet/packet.go +208 -0
- package/engine/internal/overhaul/packet/packet_test.go +263 -0
- package/engine/internal/overhaul/records/check.go +6 -0
- package/engine/internal/overhaul/records/init.go +16 -5
- package/engine/internal/overhaul/records/records_test.go +4 -0
- package/engine/internal/overhaul/records/run.go +66 -0
- package/engine/internal/overhaul/records/run_test.go +77 -0
- package/engine/internal/overhaul/render/run.go +15 -11
- package/engine/internal/overhaul/render/run_test.go +463 -1
- package/engine/internal/overhaul/render/visual.go +95 -33
- package/engine/internal/overhaul/score/run.go +20 -0
- package/engine/internal/overhaul/score/run_test.go +156 -1
- package/engine/internal/overhaul/snapshot/run.go +78 -21
- package/engine/internal/overhaul/snapshot/run_test.go +344 -8
- package/engine/internal/parallel/cli.go +33 -20
- package/engine/internal/parallel/cli_test.go +59 -0
- package/engine/internal/parallel/git.go +39 -1
- package/engine/internal/parallel/ops.go +101 -11
- package/engine/internal/parallel/ops_test.go +552 -69
- package/engine/internal/parallel/parallel_test.go +31 -1
- package/engine/internal/parallel/pathdisjoint.go +19 -1
- package/engine/internal/parallel/pathdisjoint_test.go +72 -0
- package/engine/internal/parallel/select.go +6 -2
- package/engine/internal/release/release.go +13 -3
- package/engine/internal/release/release_test.go +208 -3
- package/engine/internal/rootfacts/facts.go +9 -0
- package/engine/internal/rootfacts/facts_test.go +38 -0
- package/engine/internal/state/acceptance.go +7 -1
- package/engine/internal/state/budgets.go +11 -10
- package/engine/internal/state/budgets_test.go +93 -0
- package/engine/internal/state/cursor.go +19 -8
- package/engine/internal/state/cursor_test.go +120 -0
- package/engine/internal/state/lock_unix.go +7 -1
- package/engine/internal/state/lock_windows.go +7 -1
- package/engine/internal/state/state_test.go +49 -18
- package/engine/internal/state/taskgraph.go +18 -4
- package/engine/internal/state/taskgraph_test.go +43 -0
- package/engine/internal/state/workspaceschema.go +16 -2
- package/engine/internal/state/workspaceschema_test.go +34 -0
- package/engine/internal/state/write.go +67 -6
- package/engine/internal/state/write_test.go +136 -0
- package/engine/internal/version/version_test.go +2 -0
- package/engine/main.go +8 -1
- package/engine/observation_contract_test.go +1 -1
- package/engine/root_routing_test.go +23 -1
- package/install.sh +132 -12
- package/pack/.claude/agents/_shared/result-admission.md +3 -1
- package/pack/.claude/agents/devrites-code-reviewer.md +3 -2
- package/pack/.claude/agents/devrites-doubt-reviewer.md +4 -2
- package/pack/.claude/agents/devrites-spec-reviewer.md +5 -4
- package/pack/.claude/skills/devrites-browser-proof/SKILL.md +2 -2
- package/pack/.claude/skills/devrites-frontend-craft/reference/design-references.md +18 -18
- package/pack/.claude/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
- package/pack/.claude/skills/devrites-interview/SKILL.md +4 -4
- package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
- package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +11 -3
- package/pack/.claude/skills/devrites-lib/reference/standards/agents.md +3 -2
- package/pack/.claude/skills/devrites-lib/reference/standards/gates.md +6 -5
- package/pack/.claude/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
- package/pack/.claude/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
- package/pack/.claude/skills/devrites-lib/reference/standards/windows.md +3 -3
- package/pack/.claude/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
- package/pack/.claude/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
- package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
- package/pack/.claude/skills/devrites-ux-shape/SKILL.md +11 -12
- package/pack/.claude/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
- package/pack/.claude/skills/overhaul/SKILL.md +1 -1
- package/pack/.claude/skills/overhaul/references/orchestration.md +5 -3
- package/pack/.claude/skills/overhaul/references/records.md +39 -0
- package/pack/.claude/skills/overhaul/references/scoring.md +14 -4
- package/pack/.claude/skills/rite/reference/menu.md +1 -1
- package/pack/.claude/skills/rite-adopt/SKILL.md +8 -2
- package/pack/.claude/skills/rite-autocomplete/SKILL.md +12 -7
- package/pack/.claude/skills/rite-autocomplete/reference/decision-policy.md +3 -2
- package/pack/.claude/skills/rite-autocomplete/reference/loop.md +3 -3
- package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
- package/pack/.claude/skills/rite-build/SKILL.md +2 -1
- package/pack/.claude/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/.claude/skills/rite-build/reference/checkpoint-protocol.md +1 -1
- package/pack/.claude/skills/rite-build/reference/checkpoint.md +5 -0
- package/pack/.claude/skills/rite-build/reference/parallel-batch.md +2 -2
- package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +3 -2
- package/pack/.claude/skills/rite-clarify/SKILL.md +5 -4
- package/pack/.claude/skills/rite-clarify/reference/anti-patterns.md +2 -2
- package/pack/.claude/skills/rite-clarify/reference/decision-coverage.md +3 -2
- package/pack/.claude/skills/rite-converge/SKILL.md +2 -0
- package/pack/.claude/skills/rite-customize/SKILL.md +6 -4
- package/pack/.claude/skills/rite-define/SKILL.md +2 -0
- package/pack/.claude/skills/rite-define/reference/gates.md +8 -7
- package/pack/.claude/skills/rite-explain/SKILL.md +1 -1
- package/pack/.claude/skills/rite-explain/reference/intake.md +1 -1
- package/pack/.claude/skills/rite-fast/SKILL.md +1 -1
- package/pack/.claude/skills/rite-plan/SKILL.md +4 -3
- package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +4 -4
- package/pack/.claude/skills/rite-plan/reference/slicing.md +3 -3
- package/pack/.claude/skills/rite-polish/reference/anti-ai-slop.md +1 -1
- package/pack/.claude/skills/rite-prove/reference/browser-proof.md +5 -5
- package/pack/.claude/skills/rite-resolve/SKILL.md +3 -3
- package/pack/.claude/skills/rite-seal/SKILL.md +4 -3
- package/pack/.claude/skills/rite-seal/reference/phase-contract.md +3 -2
- package/pack/.claude/skills/rite-seal/reference/seal-template.md +2 -0
- package/pack/.claude/skills/rite-ship/SKILL.md +4 -2
- package/pack/.claude/skills/rite-ship/reference/git-ship.md +8 -2
- package/pack/.claude/skills/rite-ship/reference/ship-template.md +2 -1
- package/pack/.claude/skills/rite-spec/SKILL.md +2 -2
- package/pack/.claude/skills/rite-spec/reference/spec-checklists.md +1 -1
- package/pack/.claude/skills/rite-spec/reference/spec-template.md +7 -3
- package/pack/.claude/skills/rite-spec/reference/state-workspace.md +2 -0
- package/pack/.claude/skills/rite-temper/SKILL.md +14 -11
- package/pack/.claude/skills/rite-temper/reference/scope-modes.md +1 -1
- package/pack/.claude/skills/rite-temper/reference/significance.md +10 -3
- package/pack/.claude/skills/rite-temper/reference/strategy-template.md +13 -2
- package/pack/.claude/skills/rite-vet/SKILL.md +4 -3
- package/pack/.claude/skills/rite-vet/reference/artifacts.md +1 -1
- package/pack/.claude/workflows/devrites-readonly-review.js +5 -4
- package/pack/generated/claude/agents/devrites-code-reviewer.md +6 -3
- package/pack/generated/claude/agents/devrites-devex-reviewer.md +3 -1
- package/pack/generated/claude/agents/devrites-doubt-reviewer.md +7 -3
- package/pack/generated/claude/agents/devrites-evidence-scout.md +3 -1
- package/pack/generated/claude/agents/devrites-frontend-reviewer.md +3 -1
- package/pack/generated/claude/agents/devrites-performance-reviewer.md +3 -1
- package/pack/generated/claude/agents/devrites-plan-reviewer.md +3 -1
- package/pack/generated/claude/agents/devrites-proof-runner.md +3 -1
- package/pack/generated/claude/agents/devrites-retrospector.md +3 -1
- package/pack/generated/claude/agents/devrites-security-auditor.md +3 -1
- package/pack/generated/claude/agents/devrites-simplifier-reviewer.md +3 -1
- package/pack/generated/claude/agents/devrites-spec-reviewer.md +8 -5
- package/pack/generated/claude/agents/devrites-strategy-reviewer.md +3 -1
- package/pack/generated/claude/agents/devrites-test-analyst.md +3 -1
- package/pack/generated/claude/agents/devrites-upgrade-planner.md +3 -1
- package/pack/generated/claude/skills/devrites-browser-proof/SKILL.md +2 -2
- package/pack/generated/claude/skills/devrites-frontend-craft/reference/design-references.md +18 -18
- package/pack/generated/claude/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
- package/pack/generated/claude/skills/devrites-interview/SKILL.md +4 -4
- package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
- package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +11 -3
- package/pack/generated/claude/skills/devrites-lib/reference/standards/agents.md +3 -2
- package/pack/generated/claude/skills/devrites-lib/reference/standards/gates.md +6 -5
- package/pack/generated/claude/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
- package/pack/generated/claude/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
- package/pack/generated/claude/skills/devrites-lib/reference/standards/windows.md +3 -3
- package/pack/generated/claude/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
- package/pack/generated/claude/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
- package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
- package/pack/generated/claude/skills/devrites-ux-shape/SKILL.md +11 -12
- package/pack/generated/claude/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
- package/pack/generated/claude/skills/overhaul/SKILL.md +1 -1
- package/pack/generated/claude/skills/overhaul/references/orchestration.md +5 -3
- package/pack/generated/claude/skills/overhaul/references/records.md +39 -0
- package/pack/generated/claude/skills/overhaul/references/scoring.md +14 -4
- package/pack/generated/claude/skills/rite/reference/menu.md +1 -1
- package/pack/generated/claude/skills/rite-adopt/SKILL.md +8 -2
- package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +12 -7
- package/pack/generated/claude/skills/rite-autocomplete/reference/decision-policy.md +3 -2
- package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +3 -3
- package/pack/generated/claude/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
- package/pack/generated/claude/skills/rite-build/SKILL.md +2 -1
- package/pack/generated/claude/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/claude/skills/rite-build/reference/checkpoint-protocol.md +1 -1
- package/pack/generated/claude/skills/rite-build/reference/checkpoint.md +5 -0
- package/pack/generated/claude/skills/rite-build/reference/parallel-batch.md +2 -2
- package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +3 -2
- package/pack/generated/claude/skills/rite-clarify/SKILL.md +5 -4
- package/pack/generated/claude/skills/rite-clarify/reference/anti-patterns.md +2 -2
- package/pack/generated/claude/skills/rite-clarify/reference/decision-coverage.md +3 -2
- package/pack/generated/claude/skills/rite-converge/SKILL.md +2 -0
- package/pack/generated/claude/skills/rite-customize/SKILL.md +6 -4
- package/pack/generated/claude/skills/rite-define/SKILL.md +2 -0
- package/pack/generated/claude/skills/rite-define/reference/gates.md +8 -7
- package/pack/generated/claude/skills/rite-explain/SKILL.md +1 -1
- package/pack/generated/claude/skills/rite-explain/reference/intake.md +1 -1
- package/pack/generated/claude/skills/rite-fast/SKILL.md +1 -1
- package/pack/generated/claude/skills/rite-plan/SKILL.md +4 -3
- package/pack/generated/claude/skills/rite-plan/reference/replan-and-repair.md +4 -4
- package/pack/generated/claude/skills/rite-plan/reference/slicing.md +3 -3
- package/pack/generated/claude/skills/rite-polish/reference/anti-ai-slop.md +1 -1
- package/pack/generated/claude/skills/rite-prove/reference/browser-proof.md +5 -5
- package/pack/generated/claude/skills/rite-resolve/SKILL.md +3 -3
- package/pack/generated/claude/skills/rite-seal/SKILL.md +4 -3
- package/pack/generated/claude/skills/rite-seal/reference/phase-contract.md +3 -2
- package/pack/generated/claude/skills/rite-seal/reference/seal-template.md +2 -0
- package/pack/generated/claude/skills/rite-ship/SKILL.md +4 -2
- package/pack/generated/claude/skills/rite-ship/reference/git-ship.md +8 -2
- package/pack/generated/claude/skills/rite-ship/reference/ship-template.md +2 -1
- package/pack/generated/claude/skills/rite-spec/SKILL.md +2 -2
- package/pack/generated/claude/skills/rite-spec/reference/spec-checklists.md +1 -1
- package/pack/generated/claude/skills/rite-spec/reference/spec-template.md +7 -3
- package/pack/generated/claude/skills/rite-spec/reference/state-workspace.md +2 -0
- package/pack/generated/claude/skills/rite-temper/SKILL.md +14 -11
- package/pack/generated/claude/skills/rite-temper/reference/scope-modes.md +1 -1
- package/pack/generated/claude/skills/rite-temper/reference/significance.md +10 -3
- package/pack/generated/claude/skills/rite-temper/reference/strategy-template.md +13 -2
- package/pack/generated/claude/skills/rite-vet/SKILL.md +4 -3
- package/pack/generated/claude/skills/rite-vet/reference/artifacts.md +1 -1
- package/pack/generated/claude/workflows/devrites-readonly-review.js +5 -4
- package/pack/generated/codex/AGENTS.md +1 -1
- package/pack/generated/codex/agents/devrites-code-reviewer.toml +6 -3
- package/pack/generated/codex/agents/devrites-devex-reviewer.toml +3 -1
- package/pack/generated/codex/agents/devrites-doubt-reviewer.toml +7 -3
- package/pack/generated/codex/agents/devrites-evidence-scout.toml +3 -1
- package/pack/generated/codex/agents/devrites-frontend-reviewer.toml +3 -1
- package/pack/generated/codex/agents/devrites-performance-reviewer.toml +3 -1
- package/pack/generated/codex/agents/devrites-plan-reviewer.toml +3 -1
- package/pack/generated/codex/agents/devrites-proof-runner.toml +3 -1
- package/pack/generated/codex/agents/devrites-retrospector.toml +3 -1
- package/pack/generated/codex/agents/devrites-security-auditor.toml +3 -1
- package/pack/generated/codex/agents/devrites-simplifier-reviewer.toml +3 -1
- package/pack/generated/codex/agents/devrites-spec-reviewer.toml +8 -5
- package/pack/generated/codex/agents/devrites-strategy-reviewer.toml +3 -1
- package/pack/generated/codex/agents/devrites-test-analyst.toml +3 -1
- package/pack/generated/codex/agents/devrites-upgrade-planner.toml +3 -1
- package/pack/generated/codex/skills/devrites-browser-proof/SKILL.md +2 -2
- package/pack/generated/codex/skills/devrites-frontend-craft/reference/design-references.md +18 -18
- package/pack/generated/codex/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
- package/pack/generated/codex/skills/devrites-interview/SKILL.md +4 -4
- package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
- package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +11 -3
- package/pack/generated/codex/skills/devrites-lib/reference/standards/agents.md +3 -2
- package/pack/generated/codex/skills/devrites-lib/reference/standards/gates.md +6 -5
- package/pack/generated/codex/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
- package/pack/generated/codex/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
- package/pack/generated/codex/skills/devrites-lib/reference/standards/windows.md +3 -3
- package/pack/generated/codex/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
- package/pack/generated/codex/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
- package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
- package/pack/generated/codex/skills/devrites-ux-shape/SKILL.md +11 -12
- package/pack/generated/codex/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
- package/pack/generated/codex/skills/overhaul/SKILL.md +1 -1
- package/pack/generated/codex/skills/overhaul/references/orchestration.md +5 -3
- package/pack/generated/codex/skills/overhaul/references/records.md +39 -0
- package/pack/generated/codex/skills/overhaul/references/scoring.md +14 -4
- package/pack/generated/codex/skills/rite/reference/menu.md +1 -1
- package/pack/generated/codex/skills/rite-adopt/SKILL.md +8 -2
- package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +12 -7
- package/pack/generated/codex/skills/rite-autocomplete/reference/decision-policy.md +3 -2
- package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +3 -3
- package/pack/generated/codex/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
- package/pack/generated/codex/skills/rite-build/SKILL.md +2 -1
- package/pack/generated/codex/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/codex/skills/rite-build/reference/checkpoint-protocol.md +1 -1
- package/pack/generated/codex/skills/rite-build/reference/checkpoint.md +5 -0
- package/pack/generated/codex/skills/rite-build/reference/parallel-batch.md +2 -2
- package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +3 -2
- package/pack/generated/codex/skills/rite-clarify/SKILL.md +5 -4
- package/pack/generated/codex/skills/rite-clarify/reference/anti-patterns.md +2 -2
- package/pack/generated/codex/skills/rite-clarify/reference/decision-coverage.md +3 -2
- package/pack/generated/codex/skills/rite-converge/SKILL.md +2 -0
- package/pack/generated/codex/skills/rite-customize/SKILL.md +6 -4
- package/pack/generated/codex/skills/rite-define/SKILL.md +2 -0
- package/pack/generated/codex/skills/rite-define/reference/gates.md +8 -7
- package/pack/generated/codex/skills/rite-explain/SKILL.md +1 -1
- package/pack/generated/codex/skills/rite-explain/reference/intake.md +1 -1
- package/pack/generated/codex/skills/rite-fast/SKILL.md +1 -1
- package/pack/generated/codex/skills/rite-plan/SKILL.md +4 -3
- package/pack/generated/codex/skills/rite-plan/reference/replan-and-repair.md +4 -4
- package/pack/generated/codex/skills/rite-plan/reference/slicing.md +3 -3
- package/pack/generated/codex/skills/rite-polish/reference/anti-ai-slop.md +1 -1
- package/pack/generated/codex/skills/rite-prove/reference/browser-proof.md +5 -5
- package/pack/generated/codex/skills/rite-resolve/SKILL.md +3 -3
- package/pack/generated/codex/skills/rite-seal/SKILL.md +4 -3
- package/pack/generated/codex/skills/rite-seal/reference/phase-contract.md +3 -2
- package/pack/generated/codex/skills/rite-seal/reference/seal-template.md +2 -0
- package/pack/generated/codex/skills/rite-ship/SKILL.md +4 -2
- package/pack/generated/codex/skills/rite-ship/reference/git-ship.md +8 -2
- package/pack/generated/codex/skills/rite-ship/reference/ship-template.md +2 -1
- package/pack/generated/codex/skills/rite-spec/SKILL.md +2 -2
- package/pack/generated/codex/skills/rite-spec/reference/spec-checklists.md +1 -1
- package/pack/generated/codex/skills/rite-spec/reference/spec-template.md +7 -3
- package/pack/generated/codex/skills/rite-spec/reference/state-workspace.md +2 -0
- package/pack/generated/codex/skills/rite-temper/SKILL.md +14 -11
- package/pack/generated/codex/skills/rite-temper/reference/scope-modes.md +1 -1
- package/pack/generated/codex/skills/rite-temper/reference/significance.md +10 -3
- package/pack/generated/codex/skills/rite-temper/reference/strategy-template.md +13 -2
- package/pack/generated/codex/skills/rite-vet/SKILL.md +4 -3
- package/pack/generated/codex/skills/rite-vet/reference/artifacts.md +1 -1
- package/pack/generated/devin/AGENTS.md +1 -1
- package/pack/generated/devin/agents/devrites-code-reviewer.md +6 -3
- package/pack/generated/devin/agents/devrites-devex-reviewer.md +3 -1
- package/pack/generated/devin/agents/devrites-doubt-reviewer.md +7 -3
- package/pack/generated/devin/agents/devrites-evidence-scout.md +3 -1
- package/pack/generated/devin/agents/devrites-frontend-reviewer.md +3 -1
- package/pack/generated/devin/agents/devrites-performance-reviewer.md +3 -1
- package/pack/generated/devin/agents/devrites-plan-reviewer.md +3 -1
- package/pack/generated/devin/agents/devrites-proof-runner.md +3 -1
- package/pack/generated/devin/agents/devrites-retrospector.md +3 -1
- package/pack/generated/devin/agents/devrites-security-auditor.md +3 -1
- package/pack/generated/devin/agents/devrites-simplifier-reviewer.md +3 -1
- package/pack/generated/devin/agents/devrites-spec-reviewer.md +8 -5
- package/pack/generated/devin/agents/devrites-strategy-reviewer.md +3 -1
- package/pack/generated/devin/agents/devrites-test-analyst.md +3 -1
- package/pack/generated/devin/agents/devrites-upgrade-planner.md +3 -1
- package/pack/generated/devin/skills/devrites-browser-proof/SKILL.md +2 -2
- package/pack/generated/devin/skills/devrites-frontend-craft/reference/design-references.md +18 -18
- package/pack/generated/devin/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
- package/pack/generated/devin/skills/devrites-interview/SKILL.md +4 -4
- package/pack/generated/devin/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
- package/pack/generated/devin/skills/devrites-lib/reference/standards/afk-hitl.md +11 -3
- package/pack/generated/devin/skills/devrites-lib/reference/standards/agents.md +3 -2
- package/pack/generated/devin/skills/devrites-lib/reference/standards/gates.md +6 -5
- package/pack/generated/devin/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
- package/pack/generated/devin/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
- package/pack/generated/devin/skills/devrites-lib/reference/standards/windows.md +3 -3
- package/pack/generated/devin/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
- package/pack/generated/devin/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
- package/pack/generated/devin/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
- package/pack/generated/devin/skills/devrites-ux-shape/SKILL.md +11 -12
- package/pack/generated/devin/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
- package/pack/generated/devin/skills/overhaul/SKILL.md +1 -1
- package/pack/generated/devin/skills/overhaul/references/orchestration.md +5 -3
- package/pack/generated/devin/skills/overhaul/references/records.md +39 -0
- package/pack/generated/devin/skills/overhaul/references/scoring.md +14 -4
- package/pack/generated/devin/skills/rite/reference/menu.md +1 -1
- package/pack/generated/devin/skills/rite-adopt/SKILL.md +8 -2
- package/pack/generated/devin/skills/rite-autocomplete/SKILL.md +12 -7
- package/pack/generated/devin/skills/rite-autocomplete/reference/decision-policy.md +3 -2
- package/pack/generated/devin/skills/rite-autocomplete/reference/loop.md +3 -3
- package/pack/generated/devin/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
- package/pack/generated/devin/skills/rite-build/SKILL.md +2 -1
- package/pack/generated/devin/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/devin/skills/rite-build/reference/checkpoint-protocol.md +1 -1
- package/pack/generated/devin/skills/rite-build/reference/checkpoint.md +5 -0
- package/pack/generated/devin/skills/rite-build/reference/parallel-batch.md +2 -2
- package/pack/generated/devin/skills/rite-build/reference/wright-dispatch.md +3 -2
- package/pack/generated/devin/skills/rite-clarify/SKILL.md +5 -4
- package/pack/generated/devin/skills/rite-clarify/reference/anti-patterns.md +2 -2
- package/pack/generated/devin/skills/rite-clarify/reference/decision-coverage.md +3 -2
- package/pack/generated/devin/skills/rite-converge/SKILL.md +2 -0
- package/pack/generated/devin/skills/rite-customize/SKILL.md +6 -4
- package/pack/generated/devin/skills/rite-define/SKILL.md +2 -0
- package/pack/generated/devin/skills/rite-define/reference/gates.md +8 -7
- package/pack/generated/devin/skills/rite-explain/SKILL.md +1 -1
- package/pack/generated/devin/skills/rite-explain/reference/intake.md +1 -1
- package/pack/generated/devin/skills/rite-fast/SKILL.md +1 -1
- package/pack/generated/devin/skills/rite-plan/SKILL.md +4 -3
- package/pack/generated/devin/skills/rite-plan/reference/replan-and-repair.md +4 -4
- package/pack/generated/devin/skills/rite-plan/reference/slicing.md +3 -3
- package/pack/generated/devin/skills/rite-polish/reference/anti-ai-slop.md +1 -1
- package/pack/generated/devin/skills/rite-prove/reference/browser-proof.md +5 -5
- package/pack/generated/devin/skills/rite-resolve/SKILL.md +3 -3
- package/pack/generated/devin/skills/rite-seal/SKILL.md +4 -3
- package/pack/generated/devin/skills/rite-seal/reference/phase-contract.md +3 -2
- package/pack/generated/devin/skills/rite-seal/reference/seal-template.md +2 -0
- package/pack/generated/devin/skills/rite-ship/SKILL.md +4 -2
- package/pack/generated/devin/skills/rite-ship/reference/git-ship.md +8 -2
- package/pack/generated/devin/skills/rite-ship/reference/ship-template.md +2 -1
- package/pack/generated/devin/skills/rite-spec/SKILL.md +2 -2
- package/pack/generated/devin/skills/rite-spec/reference/spec-checklists.md +1 -1
- package/pack/generated/devin/skills/rite-spec/reference/spec-template.md +7 -3
- package/pack/generated/devin/skills/rite-spec/reference/state-workspace.md +2 -0
- package/pack/generated/devin/skills/rite-temper/SKILL.md +14 -11
- package/pack/generated/devin/skills/rite-temper/reference/scope-modes.md +1 -1
- package/pack/generated/devin/skills/rite-temper/reference/significance.md +10 -3
- package/pack/generated/devin/skills/rite-temper/reference/strategy-template.md +13 -2
- package/pack/generated/devin/skills/rite-vet/SKILL.md +4 -3
- package/pack/generated/devin/skills/rite-vet/reference/artifacts.md +1 -1
- package/pack/generated/omp/agents/devrites-code-reviewer.md +6 -3
- package/pack/generated/omp/agents/devrites-devex-reviewer.md +3 -1
- package/pack/generated/omp/agents/devrites-doubt-reviewer.md +7 -3
- package/pack/generated/omp/agents/devrites-evidence-scout.md +3 -1
- package/pack/generated/omp/agents/devrites-frontend-reviewer.md +3 -1
- package/pack/generated/omp/agents/devrites-performance-reviewer.md +3 -1
- package/pack/generated/omp/agents/devrites-plan-reviewer.md +3 -1
- package/pack/generated/omp/agents/devrites-proof-runner.md +3 -1
- package/pack/generated/omp/agents/devrites-retrospector.md +3 -1
- package/pack/generated/omp/agents/devrites-security-auditor.md +3 -1
- package/pack/generated/omp/agents/devrites-simplifier-reviewer.md +3 -1
- package/pack/generated/omp/agents/devrites-spec-reviewer.md +8 -5
- package/pack/generated/omp/agents/devrites-strategy-reviewer.md +3 -1
- package/pack/generated/omp/agents/devrites-test-analyst.md +3 -1
- package/pack/generated/omp/agents/devrites-upgrade-planner.md +3 -1
- package/pack/generated/omp/commands/rite-define.md +1 -1
- package/pack/generated/omp/commands/rite-handoff.md +1 -1
- package/pack/generated/omp/commands/rite-plan.md +1 -1
- package/pack/generated/omp/commands/rite-pressure-test.md +1 -1
- package/pack/generated/omp/commands/rite-quick.md +1 -1
- package/pack/generated/omp/commands/rite-status.md +1 -1
- package/pack/generated/omp/commands/rite-temper.md +1 -1
- package/pack/generated/omp/commands/rite-zoom-out.md +1 -1
- package/pack/generated/omp/skills/devrites-browser-proof/SKILL.md +2 -2
- package/pack/generated/omp/skills/devrites-frontend-craft/reference/design-references.md +18 -18
- package/pack/generated/omp/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
- package/pack/generated/omp/skills/devrites-interview/SKILL.md +4 -4
- package/pack/generated/omp/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
- package/pack/generated/omp/skills/devrites-lib/reference/standards/afk-hitl.md +11 -3
- package/pack/generated/omp/skills/devrites-lib/reference/standards/agents.md +3 -2
- package/pack/generated/omp/skills/devrites-lib/reference/standards/gates.md +6 -5
- package/pack/generated/omp/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
- package/pack/generated/omp/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
- package/pack/generated/omp/skills/devrites-lib/reference/standards/windows.md +3 -3
- package/pack/generated/omp/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
- package/pack/generated/omp/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
- package/pack/generated/omp/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
- package/pack/generated/omp/skills/devrites-ux-shape/SKILL.md +11 -12
- package/pack/generated/omp/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
- package/pack/generated/omp/skills/overhaul/SKILL.md +1 -1
- package/pack/generated/omp/skills/overhaul/references/orchestration.md +5 -3
- package/pack/generated/omp/skills/overhaul/references/records.md +39 -0
- package/pack/generated/omp/skills/overhaul/references/scoring.md +14 -4
- package/pack/generated/omp/skills/rite/reference/menu.md +1 -1
- package/pack/generated/omp/skills/rite-adopt/SKILL.md +8 -2
- package/pack/generated/omp/skills/rite-autocomplete/SKILL.md +12 -7
- package/pack/generated/omp/skills/rite-autocomplete/reference/decision-policy.md +3 -2
- package/pack/generated/omp/skills/rite-autocomplete/reference/loop.md +3 -3
- package/pack/generated/omp/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
- package/pack/generated/omp/skills/rite-build/SKILL.md +2 -1
- package/pack/generated/omp/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/omp/skills/rite-build/reference/checkpoint-protocol.md +1 -1
- package/pack/generated/omp/skills/rite-build/reference/checkpoint.md +5 -0
- package/pack/generated/omp/skills/rite-build/reference/parallel-batch.md +2 -2
- package/pack/generated/omp/skills/rite-build/reference/wright-dispatch.md +3 -2
- package/pack/generated/omp/skills/rite-clarify/SKILL.md +5 -4
- package/pack/generated/omp/skills/rite-clarify/reference/anti-patterns.md +2 -2
- package/pack/generated/omp/skills/rite-clarify/reference/decision-coverage.md +3 -2
- package/pack/generated/omp/skills/rite-converge/SKILL.md +2 -0
- package/pack/generated/omp/skills/rite-customize/SKILL.md +6 -4
- package/pack/generated/omp/skills/rite-define/SKILL.md +2 -0
- package/pack/generated/omp/skills/rite-define/reference/gates.md +8 -7
- package/pack/generated/omp/skills/rite-explain/SKILL.md +1 -1
- package/pack/generated/omp/skills/rite-explain/reference/intake.md +1 -1
- package/pack/generated/omp/skills/rite-fast/SKILL.md +1 -1
- package/pack/generated/omp/skills/rite-plan/SKILL.md +4 -3
- package/pack/generated/omp/skills/rite-plan/reference/replan-and-repair.md +4 -4
- package/pack/generated/omp/skills/rite-plan/reference/slicing.md +3 -3
- package/pack/generated/omp/skills/rite-polish/reference/anti-ai-slop.md +1 -1
- package/pack/generated/omp/skills/rite-prove/reference/browser-proof.md +5 -5
- package/pack/generated/omp/skills/rite-resolve/SKILL.md +3 -3
- package/pack/generated/omp/skills/rite-seal/SKILL.md +4 -3
- package/pack/generated/omp/skills/rite-seal/reference/phase-contract.md +3 -2
- package/pack/generated/omp/skills/rite-seal/reference/seal-template.md +2 -0
- package/pack/generated/omp/skills/rite-ship/SKILL.md +4 -2
- package/pack/generated/omp/skills/rite-ship/reference/git-ship.md +8 -2
- package/pack/generated/omp/skills/rite-ship/reference/ship-template.md +2 -1
- package/pack/generated/omp/skills/rite-spec/SKILL.md +2 -2
- package/pack/generated/omp/skills/rite-spec/reference/spec-checklists.md +1 -1
- package/pack/generated/omp/skills/rite-spec/reference/spec-template.md +7 -3
- package/pack/generated/omp/skills/rite-spec/reference/state-workspace.md +2 -0
- package/pack/generated/omp/skills/rite-temper/SKILL.md +14 -11
- package/pack/generated/omp/skills/rite-temper/reference/scope-modes.md +1 -1
- package/pack/generated/omp/skills/rite-temper/reference/significance.md +10 -3
- package/pack/generated/omp/skills/rite-temper/reference/strategy-template.md +13 -2
- package/pack/generated/omp/skills/rite-vet/SKILL.md +4 -3
- package/pack/generated/omp/skills/rite-vet/reference/artifacts.md +1 -1
- package/pack/generated/pi/AGENTS.md +1 -1
- package/pack/generated/pi/agents/devrites-code-reviewer.md +6 -3
- package/pack/generated/pi/agents/devrites-devex-reviewer.md +3 -1
- package/pack/generated/pi/agents/devrites-doubt-reviewer.md +7 -3
- package/pack/generated/pi/agents/devrites-evidence-scout.md +3 -1
- package/pack/generated/pi/agents/devrites-frontend-reviewer.md +3 -1
- package/pack/generated/pi/agents/devrites-performance-reviewer.md +3 -1
- package/pack/generated/pi/agents/devrites-plan-reviewer.md +3 -1
- package/pack/generated/pi/agents/devrites-proof-runner.md +3 -1
- package/pack/generated/pi/agents/devrites-retrospector.md +3 -1
- package/pack/generated/pi/agents/devrites-security-auditor.md +3 -1
- package/pack/generated/pi/agents/devrites-simplifier-reviewer.md +3 -1
- package/pack/generated/pi/agents/devrites-spec-reviewer.md +8 -5
- package/pack/generated/pi/agents/devrites-strategy-reviewer.md +3 -1
- package/pack/generated/pi/agents/devrites-test-analyst.md +3 -1
- package/pack/generated/pi/agents/devrites-upgrade-planner.md +3 -1
- package/pack/generated/pi/prompts/rite-define.md +1 -1
- package/pack/generated/pi/prompts/rite-handoff.md +1 -1
- package/pack/generated/pi/prompts/rite-plan.md +1 -1
- package/pack/generated/pi/prompts/rite-pressure-test.md +1 -1
- package/pack/generated/pi/prompts/rite-quick.md +1 -1
- package/pack/generated/pi/prompts/rite-status.md +1 -1
- package/pack/generated/pi/prompts/rite-temper.md +1 -1
- package/pack/generated/pi/prompts/rite-zoom-out.md +1 -1
- package/pack/generated/pi/skills/devrites-browser-proof/SKILL.md +2 -2
- package/pack/generated/pi/skills/devrites-frontend-craft/reference/design-references.md +18 -18
- package/pack/generated/pi/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
- package/pack/generated/pi/skills/devrites-interview/SKILL.md +4 -4
- package/pack/generated/pi/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
- package/pack/generated/pi/skills/devrites-lib/reference/standards/afk-hitl.md +11 -3
- package/pack/generated/pi/skills/devrites-lib/reference/standards/agents.md +3 -2
- package/pack/generated/pi/skills/devrites-lib/reference/standards/gates.md +6 -5
- package/pack/generated/pi/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
- package/pack/generated/pi/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
- package/pack/generated/pi/skills/devrites-lib/reference/standards/windows.md +3 -3
- package/pack/generated/pi/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
- package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
- package/pack/generated/pi/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
- package/pack/generated/pi/skills/devrites-ux-shape/SKILL.md +11 -12
- package/pack/generated/pi/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
- package/pack/generated/pi/skills/overhaul/SKILL.md +1 -1
- package/pack/generated/pi/skills/overhaul/references/orchestration.md +5 -3
- package/pack/generated/pi/skills/overhaul/references/records.md +39 -0
- package/pack/generated/pi/skills/overhaul/references/scoring.md +14 -4
- package/pack/generated/pi/skills/rite/reference/menu.md +1 -1
- package/pack/generated/pi/skills/rite-adopt/SKILL.md +8 -2
- package/pack/generated/pi/skills/rite-autocomplete/SKILL.md +12 -7
- package/pack/generated/pi/skills/rite-autocomplete/reference/decision-policy.md +3 -2
- package/pack/generated/pi/skills/rite-autocomplete/reference/loop.md +3 -3
- package/pack/generated/pi/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
- package/pack/generated/pi/skills/rite-build/SKILL.md +2 -1
- package/pack/generated/pi/skills/rite-build/reference/afk-discipline.md +1 -1
- package/pack/generated/pi/skills/rite-build/reference/checkpoint-protocol.md +1 -1
- package/pack/generated/pi/skills/rite-build/reference/checkpoint.md +5 -0
- package/pack/generated/pi/skills/rite-build/reference/parallel-batch.md +2 -2
- package/pack/generated/pi/skills/rite-build/reference/wright-dispatch.md +3 -2
- package/pack/generated/pi/skills/rite-clarify/SKILL.md +5 -4
- package/pack/generated/pi/skills/rite-clarify/reference/anti-patterns.md +2 -2
- package/pack/generated/pi/skills/rite-clarify/reference/decision-coverage.md +3 -2
- package/pack/generated/pi/skills/rite-converge/SKILL.md +2 -0
- package/pack/generated/pi/skills/rite-customize/SKILL.md +6 -4
- package/pack/generated/pi/skills/rite-define/SKILL.md +2 -0
- package/pack/generated/pi/skills/rite-define/reference/gates.md +8 -7
- package/pack/generated/pi/skills/rite-explain/SKILL.md +1 -1
- package/pack/generated/pi/skills/rite-explain/reference/intake.md +1 -1
- package/pack/generated/pi/skills/rite-fast/SKILL.md +1 -1
- package/pack/generated/pi/skills/rite-plan/SKILL.md +4 -3
- package/pack/generated/pi/skills/rite-plan/reference/replan-and-repair.md +4 -4
- package/pack/generated/pi/skills/rite-plan/reference/slicing.md +3 -3
- package/pack/generated/pi/skills/rite-polish/reference/anti-ai-slop.md +1 -1
- package/pack/generated/pi/skills/rite-prove/reference/browser-proof.md +5 -5
- package/pack/generated/pi/skills/rite-resolve/SKILL.md +3 -3
- package/pack/generated/pi/skills/rite-seal/SKILL.md +4 -3
- package/pack/generated/pi/skills/rite-seal/reference/phase-contract.md +3 -2
- package/pack/generated/pi/skills/rite-seal/reference/seal-template.md +2 -0
- package/pack/generated/pi/skills/rite-ship/SKILL.md +4 -2
- package/pack/generated/pi/skills/rite-ship/reference/git-ship.md +8 -2
- package/pack/generated/pi/skills/rite-ship/reference/ship-template.md +2 -1
- package/pack/generated/pi/skills/rite-spec/SKILL.md +2 -2
- package/pack/generated/pi/skills/rite-spec/reference/spec-checklists.md +1 -1
- package/pack/generated/pi/skills/rite-spec/reference/spec-template.md +7 -3
- package/pack/generated/pi/skills/rite-spec/reference/state-workspace.md +2 -0
- package/pack/generated/pi/skills/rite-temper/SKILL.md +14 -11
- package/pack/generated/pi/skills/rite-temper/reference/scope-modes.md +1 -1
- package/pack/generated/pi/skills/rite-temper/reference/significance.md +10 -3
- package/pack/generated/pi/skills/rite-temper/reference/strategy-template.md +13 -2
- package/pack/generated/pi/skills/rite-vet/SKILL.md +4 -3
- package/pack/generated/pi/skills/rite-vet/reference/artifacts.md +1 -1
- package/package.json +5 -4
- package/scripts/build-host-artifacts.sh +15 -0
- package/scripts/codex-generate.sh +1 -1
- package/scripts/devin-generate.sh +1 -1
- package/scripts/expand-includes.py +46 -0
- package/scripts/install-lib.sh +42 -7
- package/scripts/omp-generate.sh +11 -0
- package/scripts/pi-generate.sh +12 -1
- package/update.sh +1 -2
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/README.md +0 -7
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/architecture.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/assumptions.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/brief.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/decision-coverage.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/decisions.md +0 -4
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/eng-review.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/gates.md +0 -4
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/plan.md +0 -5
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/questions.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/spec.md +0 -6
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/state.md +0 -8
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/tasks.md +0 -1
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/test-plan.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/traceability.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/README.md +0 -7
- package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/assumptions.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/brief.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/decisions.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/questions.md +0 -3
- package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/spec.md +0 -6
- package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/state.md +0 -3
- package/engine/testdata/golden/TestParityCloseOut/active_pointed_elsewhere.golden +0 -2
- package/engine/testdata/golden/TestParityCloseOut/active_slug_cleared.golden +0 -2
- package/engine/testdata/golden/TestParityCloseOut/archive_clobber.golden +0 -1
- package/engine/testdata/golden/TestParityCloseOut/missing_slug.golden +0 -1
- package/engine/testdata/golden/TestParityCloseOut/missing_workspace.golden +0 -1
- package/engine/testdata/golden/TestParityLearnings/add.golden +0 -2
- package/engine/testdata/golden/TestParityLearnings/list.golden +0 -5
- package/engine/testdata/golden/TestParityLearnings/mine-no-archive.golden +0 -2
- package/engine/testdata/golden/TestParityLearnings/mine.golden +0 -5
- package/engine/testdata/golden/TestParityLearnings/nudge.golden +0 -2
- package/engine/testdata/golden/TestParityLearnings/unknown.golden +0 -1
- package/engine/testdata/golden/TestParityPackageExistence/ghost-workspace.golden +0 -1
- package/engine/testdata/golden/TestParityPackageExistence/no-manifest.golden +0 -1
- package/engine/testdata/golden/TestParityPackageExistence/not-git.golden +0 -1
- package/engine/testdata/golden/TestParityPackageExistence/undeclared.golden +0 -1
- package/engine/testdata/golden/TestParityPreamble/afk/a.golden +0 -14
- package/engine/testdata/golden/TestParityPreamble/hitl/active.golden +0 -18
- package/engine/testdata/golden/TestParityPreamble/hitl/bare.golden +0 -10
- package/engine/testdata/golden/TestParityPreamble/hitl/full.golden +0 -18
- package/engine/testdata/golden/TestParityPreamble/hitl/ghost.golden +0 -2
- package/engine/testdata/golden/TestParityPreamble/hitl/nonl.golden +0 -11
- package/engine/testdata/golden/TestParityPreamble/hitl/openend.golden +0 -13
- package/engine/testdata/golden/TestParityProgress/arg=allbuilt.golden +0 -4
- package/engine/testdata/golden/TestParityProgress/arg=done.golden +0 -3
- package/engine/testdata/golden/TestParityProgress/arg=ghost.golden +0 -1
- package/engine/testdata/golden/TestParityProgress/arg=mid.golden +0 -4
- package/engine/testdata/golden/TestParityProgress/arg=nophase.golden +0 -3
- package/engine/testdata/golden/TestParityProgress/arg=noslice.golden +0 -3
- package/engine/testdata/golden/TestParityProgress/arg=plan.golden +0 -4
- package/engine/testdata/golden/TestParityProgress/arg=seal.golden +0 -3
- package/engine/testdata/golden/TestParityResolve/answer/questions.md.golden +0 -9
- package/engine/testdata/golden/TestParityResolve/answer/state.md.golden +0 -7
- package/engine/testdata/golden/TestParityResolve/answer.golden +0 -4
- package/engine/testdata/golden/TestParityResolve/batch/questions.md.golden +0 -9
- package/engine/testdata/golden/TestParityResolve/batch-unterminated/questions.md.golden +0 -9
- package/engine/testdata/golden/TestParityResolve/batch-unterminated.golden +0 -2
- package/engine/testdata/golden/TestParityResolve/batch.golden +0 -3
- package/engine/testdata/golden/TestParityResolve/drop/questions.md.golden +0 -9
- package/engine/testdata/golden/TestParityResolve/drop/state.md.golden +0 -9
- package/engine/testdata/golden/TestParityResolve/drop.golden +0 -4
- package/engine/testdata/golden/TestParityResolve/missing-answer.golden +0 -1
- package/engine/testdata/golden/TestParityResolve/no-workspace.golden +0 -1
- package/engine/testdata/golden/TestParityResolve/not-found.golden +0 -1
- package/engine/testdata/golden/TestParityResolve/not-open.golden +0 -1
- package/engine/testdata/golden/TestStatusLiveWorkspace.golden +0 -10
- package/engine/testdata/golden/status/auth-tokens.txt +0 -9
- package/engine/testdata/golden/status/search-ranking.txt +0 -9
- package/engine/testdata/visual/open-visual-smoke.html +0 -675
- package/engine/testdata/visual/open-visual-smoke.outline.md +0 -54
- package/engine/tests/adr_0003_gate_exit_code_test.go +0 -32
- package/engine/tests/adr_0004_required_by_phase_test.go +0 -54
- package/engine/tests/adr_0011_define_plan_test.go +0 -32
- package/engine/tests/adr_0027_readiness_binding_test.go +0 -107
- package/engine/tests/cli_test.go +0 -126
- package/engine/tests/gate_test.go +0 -669
- package/engine/tests/meta_test.go +0 -37
- package/engine/tests/parity_closeout_test.go +0 -105
- package/engine/tests/parity_githelpers_test.go +0 -41
- package/engine/tests/parity_resolve_test.go +0 -136
- package/engine/tests/parity_test.go +0 -86
- package/engine/tests/workspace_observation_migration_test.go +0 -1069
|
@@ -231,10 +231,10 @@ func TestReduceCountsAndIds(t *testing.T) {
|
|
|
231
231
|
if len(red.UnapprIDs) != 2 {
|
|
232
232
|
t.Fatalf("unapproved ids=%v", red.UnapprIDs)
|
|
233
233
|
}
|
|
234
|
-
// A nil
|
|
234
|
+
// A nil approval surface approves nothing: every unmet runnable gate is unapproved.
|
|
235
235
|
red = doc.Reduce(nil)
|
|
236
|
-
if len(red.UnapprIDs) !=
|
|
237
|
-
t.Fatalf("nil approved must
|
|
236
|
+
if len(red.UnapprIDs) != 2 {
|
|
237
|
+
t.Fatalf("nil approved must flag every unmet runnable gate: %v", red.UnapprIDs)
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
|
|
@@ -293,8 +293,9 @@ func TestApprovedCommandsNoSection(t *testing.T) {
|
|
|
293
293
|
if approved := ApprovedCommands([]byte("# Plan\n\nno table\n")); len(approved) != 0 {
|
|
294
294
|
t.Fatalf("approved=%+v", approved)
|
|
295
295
|
}
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
// A nil plan approves nothing and reports it as an empty value, never nil.
|
|
297
|
+
if approved := ApprovedCommands(nil); approved == nil || len(approved) != 0 {
|
|
298
|
+
t.Fatalf("nil plan must approve nothing, and report it as a value: %+v", approved)
|
|
298
299
|
}
|
|
299
300
|
}
|
|
300
301
|
|
|
@@ -553,8 +554,9 @@ func TestLintMostlyManualAndCounts(t *testing.T) {
|
|
|
553
554
|
if !mostlyManual {
|
|
554
555
|
t.Fatalf("findings=%+v", findings)
|
|
555
556
|
}
|
|
557
|
+
// The one runnable gate (G1) has no approved row, so lint reports an error.
|
|
556
558
|
errs, warns := LintCounts(findings)
|
|
557
|
-
if errs !=
|
|
559
|
+
if errs != 1 || warns == 0 {
|
|
558
560
|
t.Fatalf("counts=%d/%d", errs, warns)
|
|
559
561
|
}
|
|
560
562
|
}
|
|
@@ -567,7 +569,7 @@ func TestScaffoldLedger(t *testing.T) {
|
|
|
567
569
|
if len(doc.Errors) != 0 || len(doc.Gates) != 1 || doc.Gates[0].ID != "G1" {
|
|
568
570
|
t.Fatalf("placeholder scaffold malformed: %v %+v", doc.Errors, doc.Gates)
|
|
569
571
|
}
|
|
570
|
-
spec := []byte("# Spec\n\n- AC-002 first\n- AC-001 second\n- AC-002 repeated\n")
|
|
572
|
+
spec := []byte("# Spec\n\n## Acceptance criteria\n\n- AC-002 first\n- AC-001 second\n- AC-002 repeated\n\n## Non-goals\n\n- AC-003 not required\n")
|
|
571
573
|
scaffolded := ScaffoldLedger("feat", spec)
|
|
572
574
|
doc = ParseLedger(scaffolded)
|
|
573
575
|
if len(doc.Errors) != 0 || len(doc.Gates) != 2 || doc.Gates[0].ID != "AC-002" || doc.Gates[1].ID != "AC-001" {
|
|
@@ -653,3 +655,292 @@ func mustRead(t *testing.T, path string) string {
|
|
|
653
655
|
}
|
|
654
656
|
return string(raw)
|
|
655
657
|
}
|
|
658
|
+
|
|
659
|
+
// An unresolvable approval surface is refused, never executed. Each consumer
|
|
660
|
+
// (run, reduce, lint) is asserted at its own guard, and nil and empty surfaces
|
|
661
|
+
// must behave identically.
|
|
662
|
+
|
|
663
|
+
func TestApprovedCommandsNeverNilSurface(t *testing.T) {
|
|
664
|
+
// ApprovedCommands never returns nil: a consumer must be able to refuse on an
|
|
665
|
+
// empty surface.
|
|
666
|
+
cases := map[string][]byte{
|
|
667
|
+
"absent file (empty input)": nil,
|
|
668
|
+
"invalid utf8": {0xff, 0xfe, 0x00, 'a'},
|
|
669
|
+
"no preflight section": []byte("# Test plan\n\n## Plan\nnothing here\n"),
|
|
670
|
+
"heading only": []byte("## Build-entry preflight\n"),
|
|
671
|
+
"header row only": []byte("## Build-entry preflight\n| command | cwd |\n"),
|
|
672
|
+
}
|
|
673
|
+
for name, in := range cases {
|
|
674
|
+
got := ApprovedCommands(in)
|
|
675
|
+
if got == nil {
|
|
676
|
+
t.Errorf("CASE %s: ApprovedCommands returned nil; nil reads as 'approval not applicable' so every CHECK executes unreviewed. Must return a non-nil (possibly empty) surface.", name)
|
|
677
|
+
continue
|
|
678
|
+
}
|
|
679
|
+
if len(got) != 0 {
|
|
680
|
+
t.Errorf("CASE %s: ApprovedCommands = %v; want non-nil empty (nothing was approved)", name, got)
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
func TestRunGatesRefusesUnresolvableApprovalSurface(t *testing.T) {
|
|
686
|
+
for _, tc := range []struct {
|
|
687
|
+
name string
|
|
688
|
+
approved []ApprovedCommand
|
|
689
|
+
}{
|
|
690
|
+
{"nil surface", nil},
|
|
691
|
+
{"empty non-nil surface", []ApprovedCommand{}},
|
|
692
|
+
} {
|
|
693
|
+
t.Run(tc.name, func(t *testing.T) {
|
|
694
|
+
project := t.TempDir()
|
|
695
|
+
work := filepath.Join(project, ".devrites", "work", "feat")
|
|
696
|
+
if err := os.MkdirAll(work, 0o755); err != nil {
|
|
697
|
+
t.Fatal(err)
|
|
698
|
+
}
|
|
699
|
+
ledgerPath := filepath.Join(work, GatesFile)
|
|
700
|
+
body := "- [ ] G1: unreviewed oracle\n CHECK: echo UNAPPROVED-MUST-NOT-RUN\n EXPECT: UNAPPROVED-MUST-NOT-RUN\n EVIDENCE: pending\n"
|
|
701
|
+
if err := os.WriteFile(ledgerPath, []byte(body), 0o644); err != nil {
|
|
702
|
+
t.Fatal(err)
|
|
703
|
+
}
|
|
704
|
+
doc := ParseLedger(mustRead(t, ledgerPath))
|
|
705
|
+
results := RunGates(context.Background(), project, ledgerPath, doc, tc.approved, false, 10*time.Second)
|
|
706
|
+
if len(results) != 1 {
|
|
707
|
+
t.Fatalf("results=%+v", results)
|
|
708
|
+
}
|
|
709
|
+
r := results[0]
|
|
710
|
+
if r.Ran {
|
|
711
|
+
t.Errorf("DEFECT: gate executed under a %s approval surface (passed=%v detail=%q). An unreviewed CHECK must not execute when approvals cannot be established.", tc.name, r.Passed, r.Detail)
|
|
712
|
+
}
|
|
713
|
+
if r.Passed {
|
|
714
|
+
t.Errorf("DEFECT: gate reported passed under a %s approval surface; certification must not happen.", tc.name)
|
|
715
|
+
}
|
|
716
|
+
if !strings.Contains(r.Detail, "not an approved") {
|
|
717
|
+
t.Errorf("detail=%q; want a refusal naming the unapproved CHECK", r.Detail)
|
|
718
|
+
}
|
|
719
|
+
after := mustRead(t, ledgerPath)
|
|
720
|
+
if strings.Contains(after, EvidenceMarker) {
|
|
721
|
+
t.Errorf("DEFECT: ledger was certified with automatic evidence under a %s approval surface:\n%s", tc.name, after)
|
|
722
|
+
}
|
|
723
|
+
if !strings.Contains(after, "EVIDENCE: pending") {
|
|
724
|
+
t.Errorf("ledger evidence was mutated under a %s approval surface:\n%s", tc.name, after)
|
|
725
|
+
}
|
|
726
|
+
if red := doc.Reduce(tc.approved); red.Unapproved != 1 {
|
|
727
|
+
t.Errorf("reduction under %s surface: Unapproved=%d; want 1 so `gates status` cannot report unapproved: 0", tc.name, red.Unapproved)
|
|
728
|
+
}
|
|
729
|
+
})
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
func TestLintFlagsNilAndEmptyApprovalSurfaceIdentically(t *testing.T) {
|
|
734
|
+
for _, tc := range []struct {
|
|
735
|
+
name string
|
|
736
|
+
approved []ApprovedCommand
|
|
737
|
+
}{
|
|
738
|
+
{"nil surface", nil},
|
|
739
|
+
{"empty surface", []ApprovedCommand{}},
|
|
740
|
+
} {
|
|
741
|
+
doc := &Document{Abandoned: map[string]string{}}
|
|
742
|
+
g := runnableGate("G1", true, "pending")
|
|
743
|
+
g.Check = "echo anything"
|
|
744
|
+
g.Cwd = ""
|
|
745
|
+
doc.Gates = []*Gate{g}
|
|
746
|
+
found := false
|
|
747
|
+
for _, f := range LintLedger(doc, tc.approved) {
|
|
748
|
+
if f.Rule == "unapproved-check" && strings.Contains(f.Message, "echo anything") {
|
|
749
|
+
found = true
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if !found {
|
|
753
|
+
t.Errorf("DEFECT: Lint(%s) reported no unapproved-check finding; `gates lint --strict` reports LINT OK instead of the authorization error.", tc.name)
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// Refusal applies only where a command would actually execute; manual and
|
|
759
|
+
// already-met gates must not be blocked by an unresolvable approval surface.
|
|
760
|
+
func TestUnresolvableApprovalDoesNotBlockNonExecutingGates(t *testing.T) {
|
|
761
|
+
project := t.TempDir()
|
|
762
|
+
|
|
763
|
+
// Manual gates execute nothing, so there is nothing to authorize.
|
|
764
|
+
manualOnly := ParseLedger("- [x] M1: human judged\n EVIDENCE: a stranger checked the transcript\n")
|
|
765
|
+
if red := manualOnly.Reduce(nil); !red.AllMet() {
|
|
766
|
+
t.Errorf("a manual-only ledger has no CHECK to approve and must still reduce all-met: %+v", red)
|
|
767
|
+
}
|
|
768
|
+
if red := manualOnly.Reduce(nil); red.Unapproved != 0 {
|
|
769
|
+
t.Errorf("manual gates are not executions and must not count as unapproved: %+v", red)
|
|
770
|
+
}
|
|
771
|
+
for _, f := range LintLedger(manualOnly, nil) {
|
|
772
|
+
if f.Rule == "unapproved-check" {
|
|
773
|
+
t.Errorf("manual gates must never be flagged unapproved: %+v", f)
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// An already-met runnable gate returns before the approval guard, so a
|
|
778
|
+
// workspace whose gates were vetted and met in an earlier run keeps its state.
|
|
779
|
+
met := runnableGate("R1", true, "")
|
|
780
|
+
met.Check = "echo already"
|
|
781
|
+
met.Expect = "already"
|
|
782
|
+
met.Evidence = FormatEvidence(met, OutputDigest("already\n"), 8, "2026-01-01T00:00:00Z")
|
|
783
|
+
if got := GateState(met, &Document{Abandoned: map[string]string{}}); got != StateMet {
|
|
784
|
+
t.Fatalf("fixture must be genuinely met, not %s", got)
|
|
785
|
+
}
|
|
786
|
+
manualUnmet := &Gate{ID: "M2", Title: "human judged", Evidence: "pending"}
|
|
787
|
+
doc := &Document{Abandoned: map[string]string{}, Gates: []*Gate{manualUnmet, met}}
|
|
788
|
+
for _, r := range RunGates(context.Background(), project, filepath.Join(project, "unused.md"), doc, nil, false, 10*time.Second) {
|
|
789
|
+
if strings.Contains(r.Detail, "not an approved") {
|
|
790
|
+
t.Errorf("gate %s was refused for approval although it never executes: %q", r.ID, r.Detail)
|
|
791
|
+
}
|
|
792
|
+
switch r.ID {
|
|
793
|
+
case "M2":
|
|
794
|
+
if !strings.Contains(r.Detail, "manual gate") {
|
|
795
|
+
t.Errorf("M2 detail=%q; want the manual-gate wording, proving the approval guard was never reached", r.Detail)
|
|
796
|
+
}
|
|
797
|
+
case "R1":
|
|
798
|
+
if !strings.Contains(r.Detail, "already met") {
|
|
799
|
+
t.Errorf("R1 detail=%q; want already-met, proving a vetted pass is not re-litigated", r.Detail)
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// An unreadable test-plan.md leaves every runnable CHECK unapproved: the runner
|
|
806
|
+
// refuses it and the reduction and lint report it, whatever the value's nil-ness.
|
|
807
|
+
func TestLoadTestPlanUnreadableApprovesNothing(t *testing.T) {
|
|
808
|
+
approved := loadTestPlan(filepath.Join(t.TempDir(), "missing", "test-plan.md"))
|
|
809
|
+
if Approved("echo hi", "", approved) {
|
|
810
|
+
t.Fatalf("unreadable plan approved a command: %+v", approved)
|
|
811
|
+
}
|
|
812
|
+
g := runnableGate("G1", true, "pending")
|
|
813
|
+
g.Check = "echo hi"
|
|
814
|
+
doc := &Document{Abandoned: map[string]string{}, Gates: []*Gate{g}}
|
|
815
|
+
if red := doc.Reduce(approved); red.Unapproved != 1 {
|
|
816
|
+
t.Fatalf("Unapproved=%d; want 1", red.Unapproved)
|
|
817
|
+
}
|
|
818
|
+
errs, _ := LintCounts(LintLedger(doc, approved))
|
|
819
|
+
if errs != 1 {
|
|
820
|
+
t.Fatalf("lint errs=%d; want 1 unapproved-check", errs)
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// `gates attest` refuses a placeholder note at write time, so a manual gate is
|
|
825
|
+
// never left checked on evidence the reader would later reject.
|
|
826
|
+
func TestAttestRefusesPlaceholderNotes(t *testing.T) {
|
|
827
|
+
placeholders := []string{"n/a", "tbd", "-", "ok", "done", "yes", "pending", "PENDING", "verified", "TODO", "N/A", "none", "n/a (see notes)", "done.", "AC-004: outcome seen", "outcome seen", "AC-004 - outcome seen", "**done**"}
|
|
828
|
+
for _, note := range placeholders {
|
|
829
|
+
project := t.TempDir()
|
|
830
|
+
root := filepath.Join(project, ".devrites")
|
|
831
|
+
work := filepath.Join(root, "work", "feat")
|
|
832
|
+
if err := os.MkdirAll(work, 0o755); err != nil {
|
|
833
|
+
t.Fatal(err)
|
|
834
|
+
}
|
|
835
|
+
ledgerPath := filepath.Join(work, GatesFile)
|
|
836
|
+
body := "- [ ] AC-004: outcome seen\n EVIDENCE: pending\n"
|
|
837
|
+
writeLedger(t, ledgerPath, body)
|
|
838
|
+
var stdout, stderr strings.Builder
|
|
839
|
+
if code := Run(root, []string{"attest", "feat", "AC-004", note}, &stdout, &stderr); code == ExitOK {
|
|
840
|
+
t.Errorf("placeholder %q was accepted at write time", note)
|
|
841
|
+
}
|
|
842
|
+
if !strings.Contains(stderr.String(), "placeholder") {
|
|
843
|
+
t.Errorf("placeholder %q: stderr=%q; want a message naming the placeholder", note, stderr.String())
|
|
844
|
+
}
|
|
845
|
+
if got := mustRead(t, ledgerPath); got != body {
|
|
846
|
+
t.Errorf("placeholder %q mutated the ledger:\n%s", note, got)
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// The refusal must say a trailing parenthetical after a placeholder word is
|
|
852
|
+
// ignored, since the note otherwise appears to already cite who and where.
|
|
853
|
+
func TestAttestRefusalExplainsIgnoredParenthetical(t *testing.T) {
|
|
854
|
+
project := t.TempDir()
|
|
855
|
+
root := filepath.Join(project, ".devrites")
|
|
856
|
+
work := filepath.Join(root, "work", "feat")
|
|
857
|
+
if err := os.MkdirAll(work, 0o755); err != nil {
|
|
858
|
+
t.Fatal(err)
|
|
859
|
+
}
|
|
860
|
+
writeLedger(t, filepath.Join(work, GatesFile), "- [ ] AC-004: outcome seen\n EVIDENCE: pending\n")
|
|
861
|
+
var stdout, stderr strings.Builder
|
|
862
|
+
note := "done (verified on staging by Ann, q-12)"
|
|
863
|
+
if code := Run(root, []string{"attest", "feat", "AC-004", note}, &stdout, &stderr); code == ExitOK {
|
|
864
|
+
t.Fatalf("note %q was accepted", note)
|
|
865
|
+
}
|
|
866
|
+
for _, want := range []string{"placeholder", "trailing (", "is ignored"} {
|
|
867
|
+
if !strings.Contains(stderr.String(), want) {
|
|
868
|
+
t.Errorf("stderr=%q; want it to contain %q", stderr.String(), want)
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
func TestAttestAcceptsSubstantiveNote(t *testing.T) {
|
|
874
|
+
project := t.TempDir()
|
|
875
|
+
root := filepath.Join(project, ".devrites")
|
|
876
|
+
work := filepath.Join(root, "work", "feat")
|
|
877
|
+
if err := os.MkdirAll(work, 0o755); err != nil {
|
|
878
|
+
t.Fatal(err)
|
|
879
|
+
}
|
|
880
|
+
ledgerPath := filepath.Join(work, GatesFile)
|
|
881
|
+
writeLedger(t, ledgerPath, "- [ ] AC-004: outcome seen\n EVIDENCE: pending\n")
|
|
882
|
+
var stdout, stderr strings.Builder
|
|
883
|
+
if code := Run(root, []string{"attest", "feat", "AC-004", "verified on staging by reviewer"}, &stdout, &stderr); code != ExitOK {
|
|
884
|
+
t.Fatalf("substantive note refused: code=%d stderr=%q", code, stderr.String())
|
|
885
|
+
}
|
|
886
|
+
doc := ParseLedger(mustRead(t, ledgerPath))
|
|
887
|
+
if len(doc.Gates) != 1 || GateState(doc.Gates[0], doc) != StateMet {
|
|
888
|
+
t.Fatalf("substantive attestation not met: %+v", doc.Gates)
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
func manualLedger(note string) *Document {
|
|
893
|
+
return ParseLedger("# Gates\n\n- [x] AC-004: outcome seen\n EVIDENCE: " + note + "\n")
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
func TestManualGatePlaceholdersNeverMet(t *testing.T) {
|
|
897
|
+
for _, ev := range []string{"n/a", "tbd", "-", "ok", "done", "yes", "pending", "PENDING", "Pending", "verified", "TODO", "N/A", "TBD", "none", "n/a (see notes)", "done.",
|
|
898
|
+
"AC-004 — outcome seen", "AC-004 - outcome seen", "`done`", "**done**", "\"n/a\"",
|
|
899
|
+
"AC-004: outcome seen", "outcome seen", "AC-004", "AC-004 – outcome seen", "*done*", "_done_", "'done'", "Done!", " yes. ", "N.A.", "—", "✅", "✓ done", "[done]", "> done", "~~tbd~~", "outcome seen (AC-004)", "AC-004 (outcome seen)", "AC004 outcome seen", "ac-004: OUTCOME SEEN.", "pass", "passed", "true", "0", "okay", "none.", "TODO: later", "not applicable", "N/A - not applicable", "AC-004 done", "done - AC-004", "AC004 outcome seen", "AC 004 done", "see above", "(done)", "TBD (see notes)"} {
|
|
900
|
+
d := manualLedger(ev)
|
|
901
|
+
if len(d.Gates) != 1 || d.Gates[0].ID != "AC-004" || d.Gates[0].Evidence == "" {
|
|
902
|
+
t.Logf("PARSE %q: gates=%d errs=%v", ev, len(d.Gates), d.Errors)
|
|
903
|
+
continue
|
|
904
|
+
}
|
|
905
|
+
if got := GateState(d.Gates[0], d); got == StateMet {
|
|
906
|
+
t.Errorf("placeholder %q reached met", ev)
|
|
907
|
+
}
|
|
908
|
+
if d.Reduce(nil).AllMet() {
|
|
909
|
+
t.Errorf("placeholder %q: AllMet", ev)
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
// A title's own trailing parenthetical is part of the title, so a note that
|
|
915
|
+
// repeats only that parenthetical restates the title and stays unmet.
|
|
916
|
+
func TestManualGateTitleParentheticalIsTitleText(t *testing.T) {
|
|
917
|
+
for _, title := range []string{"Refund appears in ledger. (REQ-002)", "Refund appears in ledger (REQ-002)"} {
|
|
918
|
+
for _, note := range []string{"REQ-002", "(REQ-002)", "req 002", "Refund appears in ledger (REQ-002)"} {
|
|
919
|
+
d := ParseLedger("# Gates\n\n- [x] AC-004: " + title + "\n EVIDENCE: " + note + "\n")
|
|
920
|
+
if len(d.Gates) != 1 {
|
|
921
|
+
t.Fatalf("title %q note %q: gates=%d errs=%v", title, note, len(d.Gates), d.Errors)
|
|
922
|
+
}
|
|
923
|
+
if got := GateState(d.Gates[0], d); got == StateMet {
|
|
924
|
+
t.Errorf("title %q: title-only note %q reached met", title, note)
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
d := ParseLedger("# Gates\n\n- [x] AC-004: " + title + "\n EVIDENCE: REQ-002 confirmed on staging by Brooke\n")
|
|
928
|
+
if got := GateState(d.Gates[0], d); got != StateMet {
|
|
929
|
+
t.Errorf("title %q: substantive note = %s, want met", title, got)
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
func TestManualGateSubstantiveNotesMet(t *testing.T) {
|
|
935
|
+
for _, ev := range []string{"verified on staging by reviewer", "Verified on staging by reviewer (ticket 42)", "done on prod: 3 orders replayed, outcome seen in dashboard",
|
|
936
|
+
"Done: reviewer confirmed checkout on staging (q-12)", "q-12: Brooke confirmed the outcome seen on staging", "Yes - Brooke saw the banner on iPhone 15 (q-7)",
|
|
937
|
+
"(q-12) Brooke confirmed refund on staging", "outcome seen on staging by Brooke", "AC-004 outcome seen on staging by Brooke, q-3", "(Brooke confirmed refund on staging, q-12)"} {
|
|
938
|
+
d := manualLedger(ev)
|
|
939
|
+
if got := GateState(d.Gates[0], d); got != StateMet {
|
|
940
|
+
t.Errorf("substantive %q = %s, want met", ev, got)
|
|
941
|
+
}
|
|
942
|
+
if !d.Reduce(nil).AllMet() {
|
|
943
|
+
t.Errorf("substantive %q not AllMet", ev)
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
@@ -21,12 +21,17 @@ type ApprovedCommand struct {
|
|
|
21
21
|
// other section approves execution — fenced examples, prose mentions, and
|
|
22
22
|
// consumptive-action rows are not re-runnable oracles. A test plan without
|
|
23
23
|
// the section approves nothing, so every runnable gate stays unapproved.
|
|
24
|
+
//
|
|
25
|
+
// The result is never nil: an absent, unreadable, or unparsable plan yields an
|
|
26
|
+
// empty surface rather than an absent one, because "approvals could not be
|
|
27
|
+
// determined" must be a value the caller can refuse on, never a nil that reads
|
|
28
|
+
// as "no approval is applicable".
|
|
24
29
|
func ApprovedCommands(testPlan []byte) []ApprovedCommand {
|
|
30
|
+
approved := []ApprovedCommand{}
|
|
25
31
|
structural, err := markdowntext.Structural(testPlan)
|
|
26
32
|
if err != nil {
|
|
27
|
-
return
|
|
33
|
+
return approved
|
|
28
34
|
}
|
|
29
|
-
var approved []ApprovedCommand
|
|
30
35
|
inSection := false
|
|
31
36
|
commandCol, cwdCol := -1, -1
|
|
32
37
|
for _, line := range strings.Split(string(structural), "\n") {
|
|
@@ -362,6 +362,9 @@ func cmdAttest(root string, args []string, stdout, stderr io.Writer) int {
|
|
|
362
362
|
if gate.Check != "" {
|
|
363
363
|
return fmt.Errorf("gate %s is runnable; evidence comes from `gates run`, not attestation", gateID)
|
|
364
364
|
}
|
|
365
|
+
if placeholderEvidence(note, gate.ID, gate.Title) {
|
|
366
|
+
return fmt.Errorf("evidence note %q is a placeholder: a note needs a word beyond done/n/a/ok/pending-style words, the gate ID or its title, and a trailing (…) after such words is ignored; say who observed what and where", note)
|
|
367
|
+
}
|
|
365
368
|
return writeResult(ledgerPath, gate, note, true)
|
|
366
369
|
})
|
|
367
370
|
if lockErr != nil {
|
|
@@ -6,6 +6,7 @@ import (
|
|
|
6
6
|
"fmt"
|
|
7
7
|
"regexp"
|
|
8
8
|
"strings"
|
|
9
|
+
"unicode"
|
|
9
10
|
)
|
|
10
11
|
|
|
11
12
|
// Evidence state vocabulary. A runnable gate is met only when its recorded
|
|
@@ -55,9 +56,8 @@ func GateState(gate *Gate, doc *Document) string {
|
|
|
55
56
|
return StateAbandoned
|
|
56
57
|
}
|
|
57
58
|
if gate.Check == "" {
|
|
58
|
-
// Manual gate: met when checked with
|
|
59
|
-
|
|
60
|
-
if gate.Checked && evidence != "" && evidence != "pending" {
|
|
59
|
+
// Manual gate: met when checked with substantive human evidence.
|
|
60
|
+
if gate.Checked && !placeholderEvidence(gate.Evidence, gate.ID, gate.Title) {
|
|
61
61
|
return StateMet
|
|
62
62
|
}
|
|
63
63
|
return StateUnmet
|
|
@@ -73,6 +73,68 @@ func GateState(gate *Gate, doc *Document) string {
|
|
|
73
73
|
return StateMet
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
// placeholderWords is the tautological vocabulary a manual attestation may not
|
|
77
|
+
// consist of (gates.md), as normalised words. A note whose every word comes
|
|
78
|
+
// from it, from the gate title, or is the gate ID is a placeholder.
|
|
79
|
+
var placeholderWords = map[string]bool{
|
|
80
|
+
"n": true, "a": true, "na": true, "tbd": true, "todo": true, "later": true,
|
|
81
|
+
"ok": true, "okay": true, "done": true, "yes": true, "pass": true, "passed": true,
|
|
82
|
+
"true": true, "0": true, "pending": true, "none": true, "verified": true,
|
|
83
|
+
"not": true, "applicable": true, "see": true, "above": true,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
var trailingParenRE = regexp.MustCompile(`\s*\([^()]*\)$`)
|
|
87
|
+
|
|
88
|
+
// splitWords lowercases text and splits on every run of non-alphanumeric
|
|
89
|
+
// characters (markdown marks, quotes, punctuation, dash variants).
|
|
90
|
+
func splitWords(text string) []string {
|
|
91
|
+
return strings.FieldsFunc(strings.ToLower(text), func(r rune) bool { return !unicode.IsLetter(r) && !unicode.IsDigit(r) })
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// noteWords is splitWords after dropping one trailing parenthetical when text
|
|
95
|
+
// remains before it. Gate titles use splitWords: their parenthetical is title
|
|
96
|
+
// text a note may not merely repeat.
|
|
97
|
+
func noteWords(text string) []string {
|
|
98
|
+
text = strings.TrimSpace(text)
|
|
99
|
+
if stripped := trailingParenRE.ReplaceAllString(text, ""); strings.TrimSpace(stripped) != "" {
|
|
100
|
+
text = stripped
|
|
101
|
+
}
|
|
102
|
+
return splitWords(text)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// placeholderEvidence reports whether a manual note is only a placeholder, so
|
|
106
|
+
// `N/A (see notes)`, `**done**`, `TODO: later` and `AC-004 - done` count while
|
|
107
|
+
// real prose does not. The gate ID is recognised in any spacing (`AC004`,
|
|
108
|
+
// `AC 004`, `AC-004`), and restating the gate title is also a placeholder.
|
|
109
|
+
func placeholderEvidence(evidence, id, title string) bool {
|
|
110
|
+
titleWords := map[string]bool{}
|
|
111
|
+
for _, w := range splitWords(title) {
|
|
112
|
+
titleWords[w] = true
|
|
113
|
+
}
|
|
114
|
+
compactID := strings.Join(noteWords(id), "")
|
|
115
|
+
words := noteWords(evidence)
|
|
116
|
+
for i := 0; i < len(words); {
|
|
117
|
+
if compactID != "" {
|
|
118
|
+
skip := 0
|
|
119
|
+
for k, joined := 1, ""; i+k <= len(words) && len(joined) < len(compactID); k++ {
|
|
120
|
+
joined += words[i+k-1]
|
|
121
|
+
if joined == compactID {
|
|
122
|
+
skip = k
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if skip > 0 {
|
|
126
|
+
i += skip
|
|
127
|
+
continue
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if !placeholderWords[words[i]] && !titleWords[words[i]] {
|
|
131
|
+
return false
|
|
132
|
+
}
|
|
133
|
+
i++
|
|
134
|
+
}
|
|
135
|
+
return true
|
|
136
|
+
}
|
|
137
|
+
|
|
76
138
|
// Reduction is the non-executing ledger verdict shared by `gates status` and
|
|
77
139
|
// the seal gate. Unmet counts every gate that is neither met nor abandoned;
|
|
78
140
|
// Stale and Unapproved are diagnostic subsets of it.
|
|
@@ -102,7 +164,9 @@ func (r Reduction) HandoffRequired() bool {
|
|
|
102
164
|
|
|
103
165
|
// Reduce computes the ledger reduction. approved is the vetted (command, cwd)
|
|
104
166
|
// surface from test-plan.md; a runnable gate whose CHECK is absent also
|
|
105
|
-
// records an unapproved diagnostic but always counts as unmet.
|
|
167
|
+
// records an unapproved diagnostic but always counts as unmet. A nil or empty
|
|
168
|
+
// approved surface approves nothing, so every unmet runnable gate is reported
|
|
169
|
+
// unapproved rather than silently counted as approved.
|
|
106
170
|
func (d *Document) Reduce(approved []ApprovedCommand) Reduction {
|
|
107
171
|
r := Reduction{Total: len(d.Gates)}
|
|
108
172
|
for _, gate := range d.Gates {
|
|
@@ -122,7 +186,7 @@ func (d *Document) Reduce(approved []ApprovedCommand) Reduction {
|
|
|
122
186
|
r.Stale++
|
|
123
187
|
r.StaleIDs = append(r.StaleIDs, gate.ID)
|
|
124
188
|
}
|
|
125
|
-
if
|
|
189
|
+
if !Approved(gate.Check, gate.Cwd, approved) {
|
|
126
190
|
r.Unapproved++
|
|
127
191
|
r.UnapprIDs = append(r.UnapprIDs, gate.ID)
|
|
128
192
|
}
|
|
@@ -61,7 +61,7 @@ func LintLedger(doc *Document, approved []ApprovedCommand) []Finding {
|
|
|
61
61
|
add("warn", gate.ID, "tautological-check",
|
|
62
62
|
"CHECK looks like a fixed-output command: %q; use an oracle that observes the named outcome", gate.Check)
|
|
63
63
|
}
|
|
64
|
-
if
|
|
64
|
+
if !Approved(gate.Check, gate.Cwd, approved) {
|
|
65
65
|
add("error", gate.ID, "unapproved-check",
|
|
66
66
|
"CHECK %q with CWD %q matches no Build-entry preflight row in test-plan.md; the runner refuses it", gate.Check, gate.Cwd)
|
|
67
67
|
}
|
|
@@ -60,8 +60,10 @@ func ReadLedgerFile(ledgerPath string) (string, error) {
|
|
|
60
60
|
// RunGates executes the runnable gates of ledgerPath. reverify re-runs every
|
|
61
61
|
// runnable gate including already-met ones; the normal mode runs only unmet
|
|
62
62
|
// runnable gates. approved is the vetted command set from test-plan.md; a
|
|
63
|
-
// CHECK outside it never executes
|
|
64
|
-
//
|
|
63
|
+
// CHECK outside it never executes, and neither does one outside a surface that
|
|
64
|
+
// could not be determined — an absent preflight is a refusal, not permission.
|
|
65
|
+
// Each pass writes definition-bound evidence; each failure clears the box and
|
|
66
|
+
// restores EVIDENCE: pending.
|
|
65
67
|
//
|
|
66
68
|
// The caller holds the feature lock across this call.
|
|
67
69
|
func RunGates(ctx context.Context, root, ledgerPath string, doc *Document, approved []ApprovedCommand, reverify bool, timeout time.Duration) []GateResult {
|
|
@@ -79,7 +81,7 @@ func RunGates(ctx context.Context, root, ledgerPath string, doc *Document, appro
|
|
|
79
81
|
results = append(results, GateResult{ID: gate.ID, Passed: true, Detail: "already met"})
|
|
80
82
|
continue
|
|
81
83
|
}
|
|
82
|
-
if
|
|
84
|
+
if !Approved(gate.Check, gate.Cwd, approved) {
|
|
83
85
|
results = append(results, GateResult{ID: gate.ID, Detail: "CHECK/CWD is not an approved test-plan.md preflight row; not executed"})
|
|
84
86
|
continue
|
|
85
87
|
}
|
|
@@ -2,8 +2,9 @@ package acceptance
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"fmt"
|
|
5
|
-
"regexp"
|
|
6
5
|
"strings"
|
|
6
|
+
|
|
7
|
+
"github.com/devrites/devrites/internal/state"
|
|
7
8
|
)
|
|
8
9
|
|
|
9
10
|
// ScaffoldLedger emits a template ledger: one pending gate per canonical
|
|
@@ -36,20 +37,8 @@ func ScaffoldLedger(slug string, spec []byte) string {
|
|
|
36
37
|
return b.String()
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// specACIDs returns the unique AC-### ids declared anywhere in the spec; the
|
|
42
|
-
// scaffold does not restrict to one section because the gate contract is the
|
|
43
|
-
// same set the acceptance map already enforces onto tasks.md/test-plan.md.
|
|
40
|
+
// specACIDs returns the unique AC-### ids in the spec's Acceptance criteria
|
|
41
|
+
// section, the same set the acceptance map enforces onto tasks.md/test-plan.md.
|
|
44
42
|
func specACIDs(spec []byte) []string {
|
|
45
|
-
|
|
46
|
-
seen := map[string]bool{}
|
|
47
|
-
var ids []string
|
|
48
|
-
for _, id := range found {
|
|
49
|
-
if !seen[id] {
|
|
50
|
-
seen[id] = true
|
|
51
|
-
ids = append(ids, id)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return ids
|
|
43
|
+
return state.ParseAcceptanceMap(spec, nil, nil, false, false).SpecIDs
|
|
55
44
|
}
|
|
@@ -77,7 +77,7 @@ func WorkspaceOverrideChecked(root, slug string) (string, error) {
|
|
|
77
77
|
})
|
|
78
78
|
canonicalWorkspace := relErr == nil && len(parts) == 2 &&
|
|
79
79
|
parts[0] == "work"
|
|
80
|
-
if sameRoot || !canonicalWorkspace || !
|
|
80
|
+
if sameRoot || !canonicalWorkspace || !ValidSlug(filepath.Base(path)) {
|
|
81
81
|
return "", fmt.Errorf("DRV-WORKSPACE-INVALID: DEVRITES_WORKSPACE %q is not a feature workspace; run `unset DEVRITES_WORKSPACE`", raw)
|
|
82
82
|
}
|
|
83
83
|
if slug != "" && filepath.Base(path) != slug {
|
|
@@ -99,7 +99,7 @@ func FeatureDir(root, slug string) string {
|
|
|
99
99
|
// control-plane commands use this instead of FeatureDir so an attacker cannot
|
|
100
100
|
// redirect archive/removal operations outside the selected DevRites root.
|
|
101
101
|
func ExistingFeatureDirChecked(root, slug string) (string, error) {
|
|
102
|
-
if !
|
|
102
|
+
if !ValidSlug(slug) {
|
|
103
103
|
return "", fmt.Errorf("DRV-WORKSPACE-INVALID: %q is not a feature slug", slug)
|
|
104
104
|
}
|
|
105
105
|
if ws, err := WorkspaceOverrideChecked(root, slug); err != nil {
|
|
@@ -113,7 +113,7 @@ func ExistingFeatureDirChecked(root, slug string) (string, error) {
|
|
|
113
113
|
return resolved, nil
|
|
114
114
|
}
|
|
115
115
|
if errors.Is(err, os.ErrNotExist) {
|
|
116
|
-
return "", os.ErrNotExist
|
|
116
|
+
return "", fmt.Errorf("no workspace for feature %q at %s: %w", slug, candidate, os.ErrNotExist)
|
|
117
117
|
}
|
|
118
118
|
return "", err
|
|
119
119
|
}
|
|
@@ -129,7 +129,7 @@ func ArchiveDirChecked(root string) (string, error) {
|
|
|
129
129
|
// must already exist. A live workspace never satisfies this lookup; callers
|
|
130
130
|
// that accept either location try ExistingFeatureDirChecked first.
|
|
131
131
|
func ExistingArchivedFeatureDirChecked(root, slug string) (string, error) {
|
|
132
|
-
if !
|
|
132
|
+
if !ValidSlug(slug) {
|
|
133
133
|
return "", fmt.Errorf("DRV-WORKSPACE-INVALID: %q is not a feature slug", slug)
|
|
134
134
|
}
|
|
135
135
|
candidate := filepath.Join(root, "archive", slug)
|
|
@@ -208,13 +208,14 @@ func ActiveSlug(root string) (string, error) {
|
|
|
208
208
|
return "", fmt.Errorf("read active feature: %w", err)
|
|
209
209
|
}
|
|
210
210
|
slug := strings.TrimSpace(string(raw))
|
|
211
|
-
if slug != "" && !
|
|
211
|
+
if slug != "" && !ValidSlug(slug) {
|
|
212
212
|
return "", fmt.Errorf("DRV-ACTIVE-INVALID: ACTIVE value %q is not a feature slug; run `rm -f %q`", slug, activePath)
|
|
213
213
|
}
|
|
214
214
|
return slug, nil
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
|
|
217
|
+
// ValidSlug reports whether slug is a single, non-empty path element.
|
|
218
|
+
func ValidSlug(slug string) bool {
|
|
218
219
|
return slug != "" && slug != "." && slug != ".." &&
|
|
219
220
|
filepath.Base(slug) == slug &&
|
|
220
221
|
!strings.ContainsAny(slug, `/\`)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package devritespaths
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
+
"errors"
|
|
4
5
|
"os"
|
|
5
6
|
"path/filepath"
|
|
6
7
|
"strings"
|
|
@@ -108,3 +109,20 @@ func TestActiveSlugRejectsPathTraversal(t *testing.T) {
|
|
|
108
109
|
t.Fatalf("ActiveSlug symlink error = %v, want stable pointer diagnostic", err)
|
|
109
110
|
}
|
|
110
111
|
}
|
|
112
|
+
|
|
113
|
+
func TestExistingFeatureDirCheckedMissingNamesSlugAndMatchesNotExist(t *testing.T) {
|
|
114
|
+
root := t.TempDir()
|
|
115
|
+
if err := os.MkdirAll(filepath.Join(root, "work"), 0o755); err != nil {
|
|
116
|
+
t.Fatal(err)
|
|
117
|
+
}
|
|
118
|
+
_, err := ExistingFeatureDirChecked(root, "nosuch")
|
|
119
|
+
if err == nil {
|
|
120
|
+
t.Fatal("want error for missing workspace")
|
|
121
|
+
}
|
|
122
|
+
if !errors.Is(err, os.ErrNotExist) {
|
|
123
|
+
t.Fatalf("err = %v, want errors.Is os.ErrNotExist", err)
|
|
124
|
+
}
|
|
125
|
+
if !strings.Contains(err.Error(), "nosuch") {
|
|
126
|
+
t.Fatalf("err = %q, want it to name the slug", err.Error())
|
|
127
|
+
}
|
|
128
|
+
}
|