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
|
@@ -3,11 +3,13 @@ package render
|
|
|
3
3
|
import (
|
|
4
4
|
"encoding/json"
|
|
5
5
|
"fmt"
|
|
6
|
+
"maps"
|
|
6
7
|
"math/big"
|
|
7
8
|
"sort"
|
|
8
9
|
"strings"
|
|
9
10
|
|
|
10
11
|
"github.com/devrites/devrites/internal/overhaul/ovio"
|
|
12
|
+
"github.com/devrites/devrites/internal/overhaul/score"
|
|
11
13
|
)
|
|
12
14
|
|
|
13
15
|
// The HTML view leads with pictures of the gaps: a score answer, a domain ×
|
|
@@ -97,21 +99,21 @@ func laneDomain(sc map[string]any, lane, domain string) *big.Rat {
|
|
|
97
99
|
return ratOf(ovio.Obj(ovio.Obj(ovio.Obj(ovio.Obj(sc["lanes"])[lane])["domains"])[domain]))
|
|
98
100
|
}
|
|
99
101
|
|
|
100
|
-
// floorFor is the scope's recorded minimum
|
|
102
|
+
// floorFor is the scope's recorded minimum. It is nil when none was recorded
|
|
103
|
+
// or the recorded one cannot be read, so the view says the minimum is unknown
|
|
104
|
+
// instead of printing a number the record never held.
|
|
101
105
|
func floorFor(sc map[string]any, scope string) *big.Rat {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
if strings.HasPrefix(scope, "domain ") {
|
|
106
|
-
return big.NewRat(9, 1)
|
|
107
|
-
}
|
|
108
|
-
return big.NewRat(97, 10)
|
|
106
|
+
_, least, _ := threshold(sc, scope)
|
|
107
|
+
return least
|
|
109
108
|
}
|
|
110
109
|
|
|
111
110
|
func gapClass(val, floor *big.Rat) string {
|
|
112
111
|
if val == nil {
|
|
113
112
|
return "gx"
|
|
114
113
|
}
|
|
114
|
+
if floor == nil {
|
|
115
|
+
return "c-unk" // no floor was read, so no gap can be stated
|
|
116
|
+
}
|
|
115
117
|
gap := new(big.Rat).Sub(floor, val)
|
|
116
118
|
for _, s := range gapSteps {
|
|
117
119
|
if s.upTo == nil || gap.Cmp(s.upTo) <= 0 {
|
|
@@ -128,6 +130,14 @@ func f2(r *big.Rat) string {
|
|
|
128
130
|
return floor2(r)
|
|
129
131
|
}
|
|
130
132
|
|
|
133
|
+
// floorText names a floor in prose: the recorded minimum, or that none was.
|
|
134
|
+
func floorText(f *big.Rat) string {
|
|
135
|
+
if f == nil {
|
|
136
|
+
return "not recorded"
|
|
137
|
+
}
|
|
138
|
+
return f2(f)
|
|
139
|
+
}
|
|
140
|
+
|
|
131
141
|
// frac maps r/of onto 0..100 for SVG geometry.
|
|
132
142
|
func frac(r, of *big.Rat) float64 {
|
|
133
143
|
if r == nil || of.Sign() == 0 {
|
|
@@ -149,8 +159,10 @@ func bullet(val, floor, base *big.Rat, cls, label string) string {
|
|
|
149
159
|
if base != nil && (val == nil || base.Cmp(val) != 0) {
|
|
150
160
|
fmt.Fprintf(&w, `<rect class="was" x="%.2f" y="0" width="0.8" height="10"/>`, max(0, frac(base, ten)-0.4))
|
|
151
161
|
}
|
|
152
|
-
|
|
153
|
-
|
|
162
|
+
if floor != nil {
|
|
163
|
+
fmt.Fprintf(&w, `<rect class="tgt" x="%.2f" y="0" width="0.6" height="10"/>`, max(0, frac(floor, ten)-0.3))
|
|
164
|
+
}
|
|
165
|
+
return w.String() + "</svg>"
|
|
154
166
|
}
|
|
155
167
|
|
|
156
168
|
// stack draws one horizontal stacked bar: segments are (class, value, label)
|
|
@@ -216,13 +228,14 @@ func (v view) summaryBlock(b *built, summary string, decide bool) string {
|
|
|
216
228
|
fmt.Fprintf(&w, `<h1 class="verdict %s">%s</h1>`, tone(verdict), esc(v.redact(text)))
|
|
217
229
|
if q != nil {
|
|
218
230
|
fmt.Fprintf(&w, `<p class="hero-num">%s<span> / 10</span></p>`, f2(q))
|
|
219
|
-
|
|
220
|
-
|
|
231
|
+
if qf == nil {
|
|
232
|
+
w.WriteString(`<p class="muted">Target not recorded</p>`)
|
|
233
|
+
} else if gap := new(big.Rat).Sub(qf, q); gap.Sign() > 0 {
|
|
221
234
|
fmt.Fprintf(&w, `<p class="muted">Target %s · %s to go</p>`, f2(qf), f2(gap))
|
|
222
235
|
} else {
|
|
223
236
|
fmt.Fprintf(&w, `<p class="muted">Target %s · met</p>`, f2(qf))
|
|
224
237
|
}
|
|
225
|
-
w.WriteString(bullet(q, qf, scoreFor(base, "global"), gapClass(q, qf), "Global score "+f2(q)+" of 10, target "+
|
|
238
|
+
w.WriteString(bullet(q, qf, scoreFor(base, "global"), gapClass(q, qf), "Global score "+f2(q)+" of 10, target "+floorText(qf)))
|
|
226
239
|
} else {
|
|
227
240
|
w.WriteString(`<p class="hero-num muted">No score yet</p>`)
|
|
228
241
|
}
|
|
@@ -232,7 +245,7 @@ func (v view) summaryBlock(b *built, summary string, decide bool) string {
|
|
|
232
245
|
for _, l := range lanes {
|
|
233
246
|
s, fl := scoreFor(cur, "lane "+l), floorFor(cur, "lane "+l)
|
|
234
247
|
fmt.Fprintf(&w, `<li><span class="lbl">%s</span>%s<span class="val">%s</span></li>`, esc(v.redact(l)),
|
|
235
|
-
bullet(s, fl, scoreFor(base, "lane "+l), gapClass(s, fl), l+" lane "+f2(s)+" of 10, target "+
|
|
248
|
+
bullet(s, fl, scoreFor(base, "lane "+l), gapClass(s, fl), l+" lane "+f2(s)+" of 10, target "+floorText(fl)), f2(s))
|
|
236
249
|
}
|
|
237
250
|
w.WriteString(`</ul>`)
|
|
238
251
|
}
|
|
@@ -241,18 +254,41 @@ func (v view) summaryBlock(b *built, summary string, decide bool) string {
|
|
|
241
254
|
}
|
|
242
255
|
w.WriteString(`</div><div class="blockers">`)
|
|
243
256
|
gates := ovio.Obj(cur["gates"])
|
|
244
|
-
var open []string
|
|
245
|
-
passing := 0
|
|
257
|
+
var open, waived []string
|
|
258
|
+
passing, na := 0, 0
|
|
246
259
|
for _, g := range sortedKeys(gates) {
|
|
247
260
|
switch pyStr(gates[g]) {
|
|
248
|
-
case "PASS"
|
|
261
|
+
case "PASS":
|
|
249
262
|
passing++
|
|
263
|
+
case "NOT_APPLICABLE":
|
|
264
|
+
na++
|
|
265
|
+
case "WAIVED_OPERATIONAL": // score admits it only on G-CONCURRENCY with an approval
|
|
266
|
+
waived = append(waived, g)
|
|
250
267
|
default:
|
|
251
268
|
open = append(open, g)
|
|
252
269
|
}
|
|
253
270
|
}
|
|
271
|
+
// A scorecard that omits a gate its run requires has not cleared it.
|
|
272
|
+
if len(cur) > 0 {
|
|
273
|
+
absent := map[string]string{}
|
|
274
|
+
for _, g := range score.GateIDs(!ovio.Truthy(b.rj["assessment_only"])) {
|
|
275
|
+
if _, ok := gates[g]; !ok {
|
|
276
|
+
open = append(open, g)
|
|
277
|
+
absent[g] = absentGate
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if len(absent) > 0 {
|
|
281
|
+
gates = maps.Clone(gates)
|
|
282
|
+
if gates == nil {
|
|
283
|
+
gates = map[string]any{}
|
|
284
|
+
}
|
|
285
|
+
for g, st := range absent {
|
|
286
|
+
gates[g] = st
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
254
290
|
if len(open) == 0 && len(gates) > 0 {
|
|
255
|
-
w.WriteString(`<h2>Nothing blocks readiness</h2><p class="muted"
|
|
291
|
+
w.WriteString(`<h2>Nothing blocks readiness</h2><p class="muted">` + plural(passing, "gate passes", "gates pass") + v.gateRest(na, waived) + `.</p>`)
|
|
256
292
|
} else if len(open) > 0 {
|
|
257
293
|
w.WriteString(`<h2>What blocks readiness</h2><ul class="gates">`)
|
|
258
294
|
for _, g := range open {
|
|
@@ -270,8 +306,8 @@ func (v view) summaryBlock(b *built, summary string, decide bool) string {
|
|
|
270
306
|
tone(st), gateMark(st), esc(v.redact(name)), esc(v.redact(g)), esc(v.redact(st)))
|
|
271
307
|
}
|
|
272
308
|
w.WriteString(`</ul>`)
|
|
273
|
-
if passing > 0 {
|
|
274
|
-
w.WriteString(`<p class="muted">` + plural(passing, "other gate passes", "other gates pass") + `.</p>`)
|
|
309
|
+
if passing+na+len(waived) > 0 {
|
|
310
|
+
w.WriteString(`<p class="muted">` + plural(passing, "other gate passes", "other gates pass") + v.gateRest(na, waived) + `.</p>`)
|
|
275
311
|
}
|
|
276
312
|
}
|
|
277
313
|
w.WriteString(`</div></div>`)
|
|
@@ -284,8 +320,24 @@ func (v view) summaryBlock(b *built, summary string, decide bool) string {
|
|
|
284
320
|
return w.String() + `</header>`
|
|
285
321
|
}
|
|
286
322
|
|
|
323
|
+
// gateRest names the gates that neither pass nor block: not applicable, or
|
|
324
|
+
// waived under an approved degradation.
|
|
325
|
+
func (v view) gateRest(na int, waived []string) string {
|
|
326
|
+
s := ""
|
|
327
|
+
if na > 0 {
|
|
328
|
+
s += fmt.Sprintf(" · %d not applicable", na)
|
|
329
|
+
}
|
|
330
|
+
if len(waived) > 0 {
|
|
331
|
+
s += " · waived with approval: " + esc(v.redact(strings.Join(waived, ", ")))
|
|
332
|
+
}
|
|
333
|
+
return s
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// absentGate is the status shown for a required gate the scorecard omits.
|
|
337
|
+
const absentGate = "NOT_RECORDED"
|
|
338
|
+
|
|
287
339
|
func gateMark(status string) string {
|
|
288
|
-
if status == "UNKNOWN" {
|
|
340
|
+
if status == "UNKNOWN" || status == absentGate {
|
|
289
341
|
return "?"
|
|
290
342
|
}
|
|
291
343
|
return "✕"
|
|
@@ -305,14 +357,24 @@ func (b *built) scoreLanes(sc map[string]any) []string {
|
|
|
305
357
|
return out
|
|
306
358
|
}
|
|
307
359
|
|
|
360
|
+
// openFindings drops findings whose repair was independently verified.
|
|
361
|
+
func openFindings(fs []map[string]any) []map[string]any {
|
|
362
|
+
return filter(fs, func(f map[string]any) bool { return ovio.Str(f["status"]) != "verified" })
|
|
363
|
+
}
|
|
364
|
+
|
|
308
365
|
func (v view) severityStrip(b *built) string {
|
|
309
366
|
n := map[string]int{}
|
|
310
|
-
|
|
367
|
+
live := openFindings(b.cards["findings"])
|
|
368
|
+
for _, f := range live {
|
|
311
369
|
n[sevKey(f)]++
|
|
312
370
|
}
|
|
313
|
-
total := len(
|
|
371
|
+
total := len(live)
|
|
372
|
+
head := plural(total, "open finding", "open findings")
|
|
373
|
+
if done := len(b.cards["findings"]) - total; done > 0 {
|
|
374
|
+
head += fmt.Sprintf(" · %d verified repaired", done)
|
|
375
|
+
}
|
|
314
376
|
var w strings.Builder
|
|
315
|
-
fmt.Fprintf(&w, `<div class="strip"><h2>%s</h2>`,
|
|
377
|
+
fmt.Fprintf(&w, `<div class="strip"><h2>%s</h2>`, head)
|
|
316
378
|
if total == 0 {
|
|
317
379
|
return w.String() + `<p class="muted">None recorded.</p></div>`
|
|
318
380
|
}
|
|
@@ -326,7 +388,7 @@ func (v view) severityStrip(b *built) string {
|
|
|
326
388
|
segs = append(segs, [3]any{"s-" + s, float64(n[s]), label})
|
|
327
389
|
keys = append(keys, [2]string{"s-" + s, fmt.Sprintf(`<a href="#findings">%s</a> <strong>%d</strong>`, sevLabel[s], n[s])})
|
|
328
390
|
}
|
|
329
|
-
w.WriteString(stack(segs, float64(total), "
|
|
391
|
+
w.WriteString(stack(segs, float64(total), "Open findings by severity"))
|
|
330
392
|
return w.String() + legend(keys...) + `</div>`
|
|
331
393
|
}
|
|
332
394
|
|
|
@@ -363,7 +425,7 @@ func (v view) gapMap(b *built) string {
|
|
|
363
425
|
cell := func(s *big.Rat, who string) string {
|
|
364
426
|
cls := gapClass(s, fl)
|
|
365
427
|
return fmt.Sprintf(`<td class="cell %s"><span class="val">%s</span>%s</td>`, cls, f2(s),
|
|
366
|
-
bullet(s, fl, nil, cls, d+" · "+who+": "+f2(s)+" of 10, floor "+
|
|
428
|
+
bullet(s, fl, nil, cls, d+" · "+who+": "+f2(s)+" of 10, floor "+floorText(fl)))
|
|
367
429
|
}
|
|
368
430
|
w.WriteString(`<tr><th scope="row"><a href="#controls">` + esc(v.redact(d)) + `</a></th>` + cell(scoreFor(cur, "domain "+d), "all lanes"))
|
|
369
431
|
for _, l := range lanes {
|
|
@@ -376,7 +438,7 @@ func (v view) gapMap(b *built) string {
|
|
|
376
438
|
for _, s := range gapSteps {
|
|
377
439
|
keys = append(keys, [2]string{s.cls, s.label})
|
|
378
440
|
}
|
|
379
|
-
keys = append(keys, [2]string{"tgt", "floor"})
|
|
441
|
+
keys = append(keys, [2]string{"c-unk", "floor not recorded"}, [2]string{"gx", "not scored"}, [2]string{"tgt", "floor"})
|
|
380
442
|
return w.String() + legend(keys...) + `</section>`
|
|
381
443
|
}
|
|
382
444
|
|
|
@@ -394,7 +456,7 @@ func (v view) controlLoss(b *built) string {
|
|
|
394
456
|
for _, c := range objs(b.rubric["controls"]) {
|
|
395
457
|
d := pyStr(c["domain"])
|
|
396
458
|
st := pyStr(status[pyStr(c["id"])])
|
|
397
|
-
if st == "NOT_APPLICABLE" {
|
|
459
|
+
if c["na"] != nil || st == "NOT_APPLICABLE" {
|
|
398
460
|
continue
|
|
399
461
|
}
|
|
400
462
|
wt := 1.0
|
|
@@ -461,11 +523,11 @@ func (v view) hotspots(b *built) string {
|
|
|
461
523
|
score int
|
|
462
524
|
}
|
|
463
525
|
by := map[string]*spot{}
|
|
464
|
-
for _, f := range b.cards["findings"] {
|
|
526
|
+
for _, f := range openFindings(b.cards["findings"]) {
|
|
465
527
|
p := "(no location)"
|
|
466
528
|
if l := ovio.List(f["locations"]); len(l) > 0 {
|
|
467
529
|
if s := ovio.Str(ovio.Obj(l[0])["path"]); s != "" {
|
|
468
|
-
p = area(s)
|
|
530
|
+
p = area(v.redact(s))
|
|
469
531
|
}
|
|
470
532
|
}
|
|
471
533
|
s := by[p]
|
|
@@ -507,7 +569,7 @@ func (v view) hotspots(b *built) string {
|
|
|
507
569
|
most = max(most, s.total)
|
|
508
570
|
}
|
|
509
571
|
var w strings.Builder
|
|
510
|
-
w.WriteString(`<section id="hotspots"><h2>Where in the code</h2><p class="lede">
|
|
572
|
+
w.WriteString(`<section id="hotspots"><h2>Where in the code</h2><p class="lede">Open findings by code area, ranked by severity.</p><ul class="rows">`)
|
|
511
573
|
for _, s := range spots {
|
|
512
574
|
var segs [][3]any
|
|
513
575
|
var parts []string
|
|
@@ -517,8 +579,8 @@ func (v view) hotspots(b *built) string {
|
|
|
517
579
|
parts = append(parts, fmt.Sprintf("%s %d", sevLabel[k], s.n[k]))
|
|
518
580
|
}
|
|
519
581
|
}
|
|
520
|
-
fmt.Fprintf(&w, `<li><span class="lbl"><code>%s</code></span>%s<span class="val">%d</span></li>`, esc(v.redact(s.name)),
|
|
521
|
-
stack(segs, float64(most), s.name+": "+strings.Join(parts, ", ")), s.total)
|
|
582
|
+
fmt.Fprintf(&w, `<li><span class="lbl"><code>%s</code></span>%s<span class="val wide">%d · %s</span></li>`, esc(v.redact(s.name)),
|
|
583
|
+
stack(segs, float64(most), s.name+": "+strings.Join(parts, ", ")), s.total, esc(strings.Join(parts, ", ")))
|
|
522
584
|
}
|
|
523
585
|
w.WriteString(`</ul>`)
|
|
524
586
|
var keys [][2]string
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
package score
|
|
7
7
|
|
|
8
8
|
import (
|
|
9
|
+
"crypto/sha256"
|
|
10
|
+
"encoding/hex"
|
|
9
11
|
"encoding/json"
|
|
10
12
|
"fmt"
|
|
11
13
|
"io"
|
|
@@ -20,6 +22,16 @@ import (
|
|
|
20
22
|
|
|
21
23
|
const calc = "overhaul-score/1"
|
|
22
24
|
|
|
25
|
+
// GateIDs lists every gate a complete scorecard records: G-THRESHOLDS plus the
|
|
26
|
+
// audit gates, and the repair gates for a remediation run.
|
|
27
|
+
func GateIDs(remediation bool) []string {
|
|
28
|
+
ids := append([]string{"G-THRESHOLDS"}, auditGates...)
|
|
29
|
+
if remediation {
|
|
30
|
+
ids = append(ids, repairGates...)
|
|
31
|
+
}
|
|
32
|
+
return ids
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
const usage = `usage: overhaul score --rubric <r.json> --results <s.json> --gates <g.json> [--out <scorecard.json>]
|
|
24
36
|
overhaul score compare --rubric <r.json> --baseline <a.json> --candidate <b.json>`
|
|
25
37
|
|
|
@@ -438,6 +450,14 @@ func score(rubric, results, gates map[string]any) (map[string]any, error) {
|
|
|
438
450
|
if results["schema"] != "overhaul.results/1" {
|
|
439
451
|
return nil, fmt.Errorf("results schema must be overhaul.results/1")
|
|
440
452
|
}
|
|
453
|
+
// The scorecard copies both fields verbatim and every consumer reads them
|
|
454
|
+
// from there, so an absent one publishes a scorecard bound to no code state.
|
|
455
|
+
if ovio.Str(results["subject"]) == "" {
|
|
456
|
+
return nil, fmt.Errorf("results: subject must be a non-empty string")
|
|
457
|
+
}
|
|
458
|
+
if sum, err := hex.DecodeString(ovio.Str(results["fingerprint"])); err != nil || len(sum) != sha256.Size {
|
|
459
|
+
return nil, fmt.Errorf("results: fingerprint must be 64 hex characters")
|
|
460
|
+
}
|
|
441
461
|
rres := ovio.Obj(results["results"])
|
|
442
462
|
if rres == nil && ovio.Truthy(results["results"]) {
|
|
443
463
|
return nil, fmt.Errorf("results.results must be an object")
|
|
@@ -16,6 +16,8 @@ import (
|
|
|
16
16
|
|
|
17
17
|
var doms = []string{"correctness", "security", "reliability", "performance", "tests", "architecture", "ux", "operations"}
|
|
18
18
|
|
|
19
|
+
var fp = strings.Repeat("a", 64)
|
|
20
|
+
|
|
19
21
|
func ctl(i int, d string, w any, lanes ...string) map[string]any {
|
|
20
22
|
if len(lanes) == 0 {
|
|
21
23
|
lanes = []string{"backend"}
|
|
@@ -34,7 +36,7 @@ func resOf(status map[string]string) map[string]any {
|
|
|
34
36
|
for k, v := range status {
|
|
35
37
|
r[k] = map[string]any{"status": v, "evidence": []string{"EV-1"}}
|
|
36
38
|
}
|
|
37
|
-
return map[string]any{"schema": "overhaul.results/1", "subject": "candidate", "results": r}
|
|
39
|
+
return map[string]any{"schema": "overhaul.results/1", "subject": "candidate", "fingerprint": fp, "results": r}
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
func passing() map[string]any {
|
|
@@ -258,6 +260,46 @@ func TestMonotonicity(t *testing.T) {
|
|
|
258
260
|
}
|
|
259
261
|
}
|
|
260
262
|
|
|
263
|
+
// Adding a FAIL or UNKNOWN control strictly lowers its own domain and never raises any domain.
|
|
264
|
+
func TestAddedNonPassControlLowersItsDomain(t *testing.T) {
|
|
265
|
+
b := base()
|
|
266
|
+
top := mustScore(t, rubricOf(b), resOf(allPass(b)), passing())
|
|
267
|
+
for _, d := range doms {
|
|
268
|
+
for _, status := range []string{"FAIL", "UNKNOWN"} {
|
|
269
|
+
t.Run(d+"/"+status, func(t *testing.T) {
|
|
270
|
+
cs := append(base(), ctl(50, d, 1, "frontend", "backend"))
|
|
271
|
+
st := allPass(cs)
|
|
272
|
+
st["C-050"] = status
|
|
273
|
+
out := mustScore(t, rubricOf(cs), resOf(st), passing())
|
|
274
|
+
for _, o := range doms {
|
|
275
|
+
p := "global.domains." + o + ".exact"
|
|
276
|
+
cmp := exact(t, out, p).Cmp(exact(t, top, p))
|
|
277
|
+
if o == d && cmp >= 0 {
|
|
278
|
+
t.Fatalf("%s control did not lower %s: %s", status, d, get(out, p))
|
|
279
|
+
}
|
|
280
|
+
if cmp > 0 {
|
|
281
|
+
t.Fatalf("%s control in %s raised %s", status, d, o)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// A control shared by two lanes adds its weight to the global domain denominator once.
|
|
290
|
+
func TestSharedControlWeightCountsOnceGlobally(t *testing.T) {
|
|
291
|
+
cs := []map[string]any{ctl(0, "correctness", 5, "frontend", "backend"), ctl(1, "correctness", 5, "backend")}
|
|
292
|
+
for _, d := range doms[1:] {
|
|
293
|
+
cs = append(cs, ctl(2+len(cs), d, 5, "frontend", "backend"))
|
|
294
|
+
}
|
|
295
|
+
st := allPass(cs)
|
|
296
|
+
st["C-001"] = "FAIL"
|
|
297
|
+
out := mustScore(t, rubricOf(cs), resOf(st), passing())
|
|
298
|
+
if got := get(out, "global.domains.correctness.exact"); got != "5/1" {
|
|
299
|
+
t.Fatalf("correctness = %s, want 5/1", got)
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
261
303
|
// 8. Duplicate control ids, weights off the 1/3/5 scale and unknown evaluations are invalid input.
|
|
262
304
|
func TestInvalidCatalog(t *testing.T) {
|
|
263
305
|
zero := base()
|
|
@@ -479,3 +521,116 @@ func TestRubricDigestRequired(t *testing.T) {
|
|
|
479
521
|
}
|
|
480
522
|
}
|
|
481
523
|
}
|
|
524
|
+
|
|
525
|
+
// A results document that names no code state is invalid input: exit 2, one
|
|
526
|
+
// diagnostic naming the absent field, and no scorecard written.
|
|
527
|
+
func TestResultsMustIdentifyScoredState(t *testing.T) {
|
|
528
|
+
dir := t.TempDir()
|
|
529
|
+
b := base()
|
|
530
|
+
rp := writeJSON(t, dir, "r.json", rubricOf(b))
|
|
531
|
+
g := writeJSON(t, dir, "g.json", passing())
|
|
532
|
+
for i, tc := range []struct {
|
|
533
|
+
name string
|
|
534
|
+
mutate func(map[string]any)
|
|
535
|
+
want string
|
|
536
|
+
}{
|
|
537
|
+
{"fingerprint absent", func(r map[string]any) { delete(r, "fingerprint") }, "fingerprint"},
|
|
538
|
+
{"fingerprint null", func(r map[string]any) { r["fingerprint"] = nil }, "fingerprint"},
|
|
539
|
+
{"fingerprint empty", func(r map[string]any) { r["fingerprint"] = "" }, "fingerprint"},
|
|
540
|
+
{"fingerprint placeholder", func(r map[string]any) { r["fingerprint"] = "not-a-sha256" }, "fingerprint"},
|
|
541
|
+
{"fingerprint one short", func(r map[string]any) { r["fingerprint"] = fp[:len(fp)-1] }, "fingerprint"},
|
|
542
|
+
{"fingerprint non-hex", func(r map[string]any) { r["fingerprint"] = strings.Repeat("z", 64) }, "fingerprint"},
|
|
543
|
+
{"subject absent", func(r map[string]any) { delete(r, "subject") }, "subject"},
|
|
544
|
+
{"subject empty", func(r map[string]any) { r["subject"] = "" }, "subject"},
|
|
545
|
+
{"subject not a string", func(r map[string]any) { r["subject"] = 12 }, "subject"},
|
|
546
|
+
} {
|
|
547
|
+
res := pinned(t, rp, resOf(allPass(b)))
|
|
548
|
+
tc.mutate(res)
|
|
549
|
+
sp := writeJSON(t, dir, "s.json", res)
|
|
550
|
+
card := filepath.Join(dir, fmt.Sprintf("card-%d.json", i))
|
|
551
|
+
other := "fingerprint"
|
|
552
|
+
if tc.want == "fingerprint" {
|
|
553
|
+
other = "subject"
|
|
554
|
+
}
|
|
555
|
+
code, stdout, stderr := runCLI("--rubric", rp, "--results", sp, "--gates", g, "--out", card)
|
|
556
|
+
switch {
|
|
557
|
+
case code != 2:
|
|
558
|
+
t.Errorf("%s: exit %d, want 2 (stdout %q stderr %q)", tc.name, code, stdout, stderr)
|
|
559
|
+
case stdout != "":
|
|
560
|
+
t.Errorf("%s: published %q", tc.name, stdout)
|
|
561
|
+
case !strings.HasPrefix(stderr, "ERROR: "):
|
|
562
|
+
t.Errorf("%s: %q is not a tool diagnostic", tc.name, stderr)
|
|
563
|
+
case !strings.Contains(stderr, tc.want):
|
|
564
|
+
t.Errorf("%s: %q does not name %s", tc.name, stderr, tc.want)
|
|
565
|
+
case strings.Contains(stderr, other):
|
|
566
|
+
t.Errorf("%s: %q names %s, not %s", tc.name, stderr, other, tc.want)
|
|
567
|
+
case strings.Contains(stderr, "rubric_digest"):
|
|
568
|
+
t.Errorf("%s: the digest check fired, not the field check: %q", tc.name, stderr)
|
|
569
|
+
}
|
|
570
|
+
if _, err := os.Stat(card); err == nil {
|
|
571
|
+
t.Errorf("%s: wrote a scorecard for an unidentified code state", tc.name)
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// The exit 2 above is the absent field, not scoring: identified results score,
|
|
577
|
+
// and a failing control is a scorecard at exit 0 carrying the validated
|
|
578
|
+
// fingerprint verbatim.
|
|
579
|
+
func TestIdentifiedResultsStillScore(t *testing.T) {
|
|
580
|
+
dir := t.TempDir()
|
|
581
|
+
b := base()
|
|
582
|
+
rp := writeJSON(t, dir, "r.json", rubricOf(b))
|
|
583
|
+
g := writeJSON(t, dir, "g.json", passing())
|
|
584
|
+
card := filepath.Join(dir, "card.json")
|
|
585
|
+
code, stdout, stderr := runCLI("--rubric", rp, "--results", writeJSON(t, dir, "s.json", pinned(t, rp, resOf(allPass(b)))),
|
|
586
|
+
"--gates", g, "--out", card)
|
|
587
|
+
if code != 0 || stderr != "" {
|
|
588
|
+
t.Fatalf("identified results: exit %d stdout %q stderr %q", code, stdout, stderr)
|
|
589
|
+
}
|
|
590
|
+
c, err := ovio.LoadObject(card)
|
|
591
|
+
if err != nil {
|
|
592
|
+
t.Fatal(err)
|
|
593
|
+
}
|
|
594
|
+
if get(c, "fingerprint") != fp || get(c, "subject") != "candidate" || get(c, "readiness_verdict") != "MEETS_TARGETS" {
|
|
595
|
+
t.Fatalf("scorecard %v", c)
|
|
596
|
+
}
|
|
597
|
+
st := allPass(b)
|
|
598
|
+
st[b[0]["id"].(string)] = "FAIL"
|
|
599
|
+
code, _, stderr = runCLI("--rubric", rp, "--results", writeJSON(t, dir, "f.json", pinned(t, rp, resOf(st))), "--gates", g)
|
|
600
|
+
if code != 0 || stderr != "" {
|
|
601
|
+
t.Fatalf("failing control: exit %d stderr %q", code, stderr)
|
|
602
|
+
}
|
|
603
|
+
out := mustScore(t, rubricOf(b), resOf(st), passing())
|
|
604
|
+
if get(out, "readiness_verdict") != "NOT_READY" || get(out, "fingerprint") != fp {
|
|
605
|
+
t.Fatalf("failing control: verdict %s fingerprint %s", get(out, "readiness_verdict"), get(out, "fingerprint"))
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// compare scores both arms through the same check, so an arm that identifies no
|
|
610
|
+
// code state is rejected with the arm named.
|
|
611
|
+
func TestCompareArmsRequireScoredState(t *testing.T) {
|
|
612
|
+
dir := t.TempDir()
|
|
613
|
+
b := base()
|
|
614
|
+
rp := writeJSON(t, dir, "r.json", rubricOf(b))
|
|
615
|
+
arm := func(name string, identified bool) string {
|
|
616
|
+
res := pinned(t, rp, resOf(allPass(b)))
|
|
617
|
+
if !identified {
|
|
618
|
+
delete(res, "fingerprint")
|
|
619
|
+
}
|
|
620
|
+
return writeJSON(t, dir, name, res)
|
|
621
|
+
}
|
|
622
|
+
for _, tc := range []struct {
|
|
623
|
+
arm string
|
|
624
|
+
baseline string
|
|
625
|
+
candidate string
|
|
626
|
+
}{
|
|
627
|
+
{"baseline", arm("blank-baseline.json", false), arm("ok-candidate.json", true)},
|
|
628
|
+
{"candidate", arm("ok-baseline.json", true), arm("blank-candidate.json", false)},
|
|
629
|
+
} {
|
|
630
|
+
code, stdout, stderr := runCLI("compare", "--rubric", rp, "--baseline", tc.baseline, "--candidate", tc.candidate)
|
|
631
|
+
if code != 2 || stdout != "" || !strings.HasPrefix(stderr, "ERROR: "+tc.arm+": ") ||
|
|
632
|
+
!strings.Contains(stderr, "fingerprint") {
|
|
633
|
+
t.Fatalf("%s arm: exit %d stdout %q stderr %q", tc.arm, code, stdout, stderr)
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
@@ -9,6 +9,7 @@ package snapshot
|
|
|
9
9
|
|
|
10
10
|
import (
|
|
11
11
|
"bytes"
|
|
12
|
+
"context"
|
|
12
13
|
"encoding/json"
|
|
13
14
|
"errors"
|
|
14
15
|
"fmt"
|
|
@@ -22,6 +23,7 @@ import (
|
|
|
22
23
|
"slices"
|
|
23
24
|
"sort"
|
|
24
25
|
"strings"
|
|
26
|
+
"syscall"
|
|
25
27
|
"time"
|
|
26
28
|
|
|
27
29
|
"github.com/devrites/devrites/internal/gitenv"
|
|
@@ -38,10 +40,14 @@ const usage = `usage: devrites-engine overhaul snapshot <command> ...
|
|
|
38
40
|
`
|
|
39
41
|
|
|
40
42
|
var sensitive = []string{".env", ".env.*", "*.key", "*.p12", "*.pfx", "*.keystore", "*.jks", ".npmrc", ".pypirc", ".netrc",
|
|
41
|
-
"*credentials*", "*secret*", "*.tfstate", "*.tfvars"}
|
|
43
|
+
"*credentials*", "*secret*", "*.tfstate", "*.tfvars", "*.pem", "*.asc", "*.pgp", "*.gpg", "*.p8"}
|
|
42
44
|
|
|
43
|
-
//
|
|
44
|
-
var
|
|
45
|
+
// keyMarkers flag private key material in any file, whatever its name.
|
|
46
|
+
var keyMarkers = [][]byte{[]byte("PRIVATE KEY-----"), []byte("PRIVATE KEY BLOCK-----")}
|
|
47
|
+
|
|
48
|
+
// keyCarry is kept between reads so a marker split across two reads is still
|
|
49
|
+
// matched; it must be at least the longest marker minus one.
|
|
50
|
+
const keyCarry = 31
|
|
45
51
|
|
|
46
52
|
var diffArgs = []string{"-c", "diff.autoRefreshIndex=false", "diff", "--no-ext-diff", "--no-textconv", "--no-color",
|
|
47
53
|
"--src-prefix=a/", "--dst-prefix=b/", "--binary"}
|
|
@@ -127,18 +133,48 @@ func exit(err error) (int, error) {
|
|
|
127
133
|
return 0, nil
|
|
128
134
|
}
|
|
129
135
|
|
|
136
|
+
var gitTimeout = 60 * time.Second
|
|
137
|
+
|
|
138
|
+
// gitWaitDelay bounds how long git waits for output pipes to close after the
|
|
139
|
+
// timeout kill; a hook grandchild may keep them open.
|
|
140
|
+
const gitWaitDelay = 5 * time.Second
|
|
141
|
+
|
|
130
142
|
func git(root string, args ...string) ([]byte, error) {
|
|
131
|
-
|
|
143
|
+
var out bytes.Buffer
|
|
144
|
+
if err := gitTo(&out, root, args...); err != nil {
|
|
145
|
+
return nil, err
|
|
146
|
+
}
|
|
147
|
+
return out.Bytes(), nil
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// gitTo streams git's stdout to w; the run is killed after gitTimeout.
|
|
151
|
+
func gitTo(w io.Writer, root string, args ...string) error {
|
|
152
|
+
ctx, cancel := context.WithTimeout(context.Background(), gitTimeout)
|
|
153
|
+
defer cancel()
|
|
154
|
+
cmd := exec.CommandContext(ctx, "git", append([]string{"-C", root}, args...)...) // #nosec G204 -- fixed git binary; arguments passed as argv, no shell
|
|
132
155
|
cmd.Env = append(gitenv.Sanitize(os.Environ()), "GIT_OPTIONAL_LOCKS=0", "GIT_TERMINAL_PROMPT=0")
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
156
|
+
cmd.WaitDelay = gitWaitDelay
|
|
157
|
+
var stderr bytes.Buffer
|
|
158
|
+
cmd.Stdout, cmd.Stderr = w, &stderr
|
|
159
|
+
if err := cmd.Run(); err != nil {
|
|
160
|
+
if ctx.Err() != nil {
|
|
161
|
+
err = fmt.Errorf("%w: %v", ctx.Err(), err)
|
|
138
162
|
}
|
|
139
|
-
return
|
|
163
|
+
return fmt.Errorf("git %s: %v: %s", strings.Join(args, " "), err, bytes.TrimSpace(stderr.Bytes()))
|
|
140
164
|
}
|
|
141
|
-
return
|
|
165
|
+
return nil
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
func gitToFile(dst, root string, args ...string) error {
|
|
169
|
+
f, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600) // #nosec G304 -- destination inside the new owner-only snapshot directory
|
|
170
|
+
if err != nil {
|
|
171
|
+
return err
|
|
172
|
+
}
|
|
173
|
+
err = gitTo(f, root, args...)
|
|
174
|
+
if cerr := f.Close(); err == nil {
|
|
175
|
+
err = cerr
|
|
176
|
+
}
|
|
177
|
+
return err
|
|
142
178
|
}
|
|
143
179
|
|
|
144
180
|
func split0(b []byte) []string {
|
|
@@ -240,9 +276,12 @@ func permBits(m fs.FileMode) int {
|
|
|
240
276
|
|
|
241
277
|
func digest(p string) (string, int, error) {
|
|
242
278
|
fi, err := os.Lstat(p)
|
|
243
|
-
if err
|
|
279
|
+
if errors.Is(err, fs.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) {
|
|
244
280
|
return "deleted", 0, nil
|
|
245
281
|
}
|
|
282
|
+
if err != nil {
|
|
283
|
+
return "", 0, err
|
|
284
|
+
}
|
|
246
285
|
switch {
|
|
247
286
|
case fi.Mode()&fs.ModeSymlink != 0:
|
|
248
287
|
target, err := os.Readlink(p)
|
|
@@ -267,8 +306,25 @@ func holdsKey(p string) (bool, error) {
|
|
|
267
306
|
return false, err
|
|
268
307
|
}
|
|
269
308
|
defer func() { _ = f.Close() }()
|
|
270
|
-
|
|
271
|
-
|
|
309
|
+
const chunk = 65536
|
|
310
|
+
buf := make([]byte, chunk+keyCarry)
|
|
311
|
+
n := 0 // bytes of buf already holding carry
|
|
312
|
+
for {
|
|
313
|
+
m, err := f.Read(buf[n : n+chunk])
|
|
314
|
+
window := buf[:n+m]
|
|
315
|
+
for _, marker := range keyMarkers {
|
|
316
|
+
if bytes.Contains(window, marker) {
|
|
317
|
+
return true, nil
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if err == io.EOF {
|
|
321
|
+
return false, nil
|
|
322
|
+
}
|
|
323
|
+
if err != nil {
|
|
324
|
+
return true, err
|
|
325
|
+
}
|
|
326
|
+
n = copy(buf, window[max(0, len(window)-keyCarry):])
|
|
327
|
+
}
|
|
272
328
|
}
|
|
273
329
|
|
|
274
330
|
func isSensitiveName(p string) bool {
|
|
@@ -309,7 +365,8 @@ func state(root string) (map[string]*entry, error) {
|
|
|
309
365
|
return out, nil
|
|
310
366
|
}
|
|
311
367
|
|
|
312
|
-
|
|
368
|
+
// indexDigest is a variable so tests can simulate the index moving mid-capture.
|
|
369
|
+
var indexDigest = func(root string) (string, error) {
|
|
313
370
|
b, err := git(root, "ls-files", "-s", "-z")
|
|
314
371
|
if err != nil {
|
|
315
372
|
return "", err
|
|
@@ -420,11 +477,7 @@ func capture(root, out string, stdout io.Writer) error {
|
|
|
420
477
|
{"staged.patch", slices.Concat(diffArgs, []string{"--cached"}, safe)},
|
|
421
478
|
{"unstaged.patch", slices.Concat(diffArgs, safe)},
|
|
422
479
|
} {
|
|
423
|
-
|
|
424
|
-
if err != nil {
|
|
425
|
-
return err
|
|
426
|
-
}
|
|
427
|
-
if err := os.WriteFile(filepath.Join(out, o.name), b, 0o600); err != nil {
|
|
480
|
+
if err := gitToFile(filepath.Join(out, o.name), root, o.args...); err != nil {
|
|
428
481
|
return err
|
|
429
482
|
}
|
|
430
483
|
}
|
|
@@ -445,8 +498,12 @@ func capture(root, out string, stdout io.Writer) error {
|
|
|
445
498
|
if err != nil {
|
|
446
499
|
return err
|
|
447
500
|
}
|
|
501
|
+
fp := fingerprint(st)
|
|
502
|
+
if fingerprint(now) != fp {
|
|
503
|
+
return errors.New("working tree changed during capture; stop and reconcile with the user")
|
|
504
|
+
}
|
|
448
505
|
man := manifest{Schema: "overhaul.snapshot/1", Root: root, Head: head, IndexSHA256: before,
|
|
449
|
-
Fingerprint:
|
|
506
|
+
Fingerprint: fp, Files: st, Submodules: gitlinks}
|
|
450
507
|
if err := ovio.WriteJSON(filepath.Join(out, "manifest.json"), man, 0o600); err != nil {
|
|
451
508
|
return err
|
|
452
509
|
}
|