devrites 3.2.15 → 3.2.17
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 +14 -0
- package/README.md +1 -1
- package/engine/hooks.go +20 -4
- package/engine/hooks_agent_dispatch.go +297 -48
- package/engine/hooks_events_test.go +40 -0
- package/engine/hooks_workspace.go +26 -6
- package/engine/internal/devritespaths/paths.go +80 -0
- package/engine/internal/lib/adoption.go +22 -7
- package/engine/internal/lib/adoption_test.go +30 -0
- package/engine/internal/lib/closeout.go +34 -11
- package/engine/internal/lib/closeout_test.go +99 -0
- package/engine/internal/lib/dispatchwaive.go +31 -0
- package/engine/internal/lib/dispatchwaive_test.go +23 -0
- package/engine/internal/lib/mutationgate.go +6 -2
- package/engine/internal/lib/reconcile.go +201 -64
- package/engine/internal/lib/reconcile_test.go +159 -12
- package/engine/internal/lib/testintegrity.go +4 -4
- package/engine/internal/lib/testintegrity_test.go +15 -0
- package/engine/internal/lib/util.go +128 -23
- package/engine/main.go +4 -1
- package/engine/testdata/golden/TestParityReconcile/close-window.golden +1 -0
- package/engine/testdata/golden/TestParityReconcile/not-git.golden +1 -1
- package/engine/testdata/golden/TestParityTestIntegrity/not-git.golden +1 -1
- package/engine/tests/hook_test.go +388 -17
- package/engine/tests/parity_reconcile_test.go +4 -1
- package/engine/tests/parity_testintegrity_test.go +1 -1
- package/pack/.claude/agents/devrites-code-reviewer.md +3 -0
- package/pack/.claude/agents/devrites-devex-reviewer.md +12 -8
- package/pack/.claude/agents/devrites-doubt-reviewer.md +3 -0
- package/pack/.claude/agents/devrites-forge-judge.md +4 -1
- package/pack/.claude/agents/devrites-frontend-reviewer.md +3 -0
- package/pack/.claude/agents/devrites-performance-reviewer.md +10 -9
- package/pack/.claude/agents/devrites-plan-reviewer.md +3 -0
- package/pack/.claude/agents/devrites-proof-runner.md +14 -14
- package/pack/.claude/agents/devrites-retrospector.md +3 -0
- package/pack/.claude/agents/devrites-security-auditor.md +3 -0
- package/pack/.claude/agents/devrites-simplifier-reviewer.md +3 -0
- package/pack/.claude/agents/devrites-slice-wright.md +6 -5
- package/pack/.claude/agents/devrites-spec-reviewer.md +3 -0
- package/pack/.claude/agents/devrites-strategy-reviewer.md +3 -0
- package/pack/.claude/agents/devrites-test-analyst.md +3 -0
- package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +8 -0
- package/pack/.claude/skills/devrites-lib/reference/standards/agents.md +10 -0
- package/pack/.claude/skills/devrites-source-driven/SKILL.md +1 -1
- package/pack/.claude/skills/rite-build/reference/one-slice-cycle.md +2 -2
- package/pack/.claude/skills/rite-build/reference/phase-contract.md +28 -4
- package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +7 -5
- package/pack/.claude/skills/rite-prove/SKILL.md +25 -14
- package/pack/.claude/skills/rite-temper/SKILL.md +1 -1
- package/pack/.claude/skills/rite-upgrade/SKILL.md +1 -1
- package/pack/.claude/skills/rite-vet/SKILL.md +18 -15
- package/pack/generated/claude/agents/devrites-code-reviewer.md +3 -0
- package/pack/generated/claude/agents/devrites-devex-reviewer.md +12 -8
- package/pack/generated/claude/agents/devrites-doubt-reviewer.md +3 -0
- package/pack/generated/claude/agents/devrites-forge-judge.md +4 -1
- package/pack/generated/claude/agents/devrites-frontend-reviewer.md +3 -0
- package/pack/generated/claude/agents/devrites-performance-reviewer.md +10 -9
- package/pack/generated/claude/agents/devrites-plan-reviewer.md +3 -0
- package/pack/generated/claude/agents/devrites-proof-runner.md +14 -14
- package/pack/generated/claude/agents/devrites-retrospector.md +3 -0
- package/pack/generated/claude/agents/devrites-security-auditor.md +3 -0
- package/pack/generated/claude/agents/devrites-simplifier-reviewer.md +3 -0
- package/pack/generated/claude/agents/devrites-slice-wright.md +6 -5
- package/pack/generated/claude/agents/devrites-spec-reviewer.md +3 -0
- package/pack/generated/claude/agents/devrites-strategy-reviewer.md +3 -0
- package/pack/generated/claude/agents/devrites-test-analyst.md +3 -0
- package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +8 -0
- package/pack/generated/claude/skills/devrites-lib/reference/standards/agents.md +10 -0
- package/pack/generated/claude/skills/devrites-source-driven/SKILL.md +1 -1
- package/pack/generated/claude/skills/rite-build/reference/one-slice-cycle.md +2 -2
- package/pack/generated/claude/skills/rite-build/reference/phase-contract.md +28 -4
- package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +7 -5
- package/pack/generated/claude/skills/rite-prove/SKILL.md +25 -14
- package/pack/generated/claude/skills/rite-temper/SKILL.md +1 -1
- package/pack/generated/claude/skills/rite-upgrade/SKILL.md +1 -1
- package/pack/generated/claude/skills/rite-vet/SKILL.md +18 -15
- package/pack/generated/codex/agents/devrites-code-reviewer.toml +3 -0
- package/pack/generated/codex/agents/devrites-devex-reviewer.toml +11 -7
- package/pack/generated/codex/agents/devrites-doubt-reviewer.toml +3 -0
- package/pack/generated/codex/agents/devrites-forge-judge.toml +4 -1
- package/pack/generated/codex/agents/devrites-frontend-reviewer.toml +3 -0
- package/pack/generated/codex/agents/devrites-performance-reviewer.toml +9 -8
- package/pack/generated/codex/agents/devrites-plan-reviewer.toml +3 -0
- package/pack/generated/codex/agents/devrites-proof-runner.toml +13 -13
- package/pack/generated/codex/agents/devrites-retrospector.toml +3 -0
- package/pack/generated/codex/agents/devrites-security-auditor.toml +3 -0
- package/pack/generated/codex/agents/devrites-simplifier-reviewer.toml +3 -0
- package/pack/generated/codex/agents/devrites-slice-wright.toml +6 -5
- package/pack/generated/codex/agents/devrites-spec-reviewer.toml +3 -0
- package/pack/generated/codex/agents/devrites-strategy-reviewer.toml +3 -0
- package/pack/generated/codex/agents/devrites-test-analyst.toml +3 -0
- package/pack/generated/codex/hooks.json +1 -1
- package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +8 -0
- package/pack/generated/codex/skills/devrites-lib/reference/standards/agents.md +10 -0
- package/pack/generated/codex/skills/devrites-source-driven/SKILL.md +1 -1
- package/pack/generated/codex/skills/rite-build/reference/one-slice-cycle.md +2 -2
- package/pack/generated/codex/skills/rite-build/reference/phase-contract.md +28 -4
- package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +7 -5
- package/pack/generated/codex/skills/rite-prove/SKILL.md +25 -14
- package/pack/generated/codex/skills/rite-temper/SKILL.md +1 -1
- package/pack/generated/codex/skills/rite-upgrade/SKILL.md +1 -1
- package/pack/generated/codex/skills/rite-vet/SKILL.md +18 -15
- package/package.json +1 -1
- package/scripts/codex-generate.sh +1 -1
|
@@ -1,42 +1,147 @@
|
|
|
1
1
|
package lib
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
+
"bytes"
|
|
5
|
+
"context"
|
|
6
|
+
"errors"
|
|
7
|
+
"fmt"
|
|
8
|
+
"os"
|
|
4
9
|
"os/exec"
|
|
5
10
|
"path/filepath"
|
|
6
11
|
"strings"
|
|
12
|
+
"time"
|
|
7
13
|
)
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
var errNotGitRepository = errors.New("not a git repository")
|
|
16
|
+
|
|
17
|
+
const (
|
|
18
|
+
gitCommandTimeout = 30 * time.Second
|
|
19
|
+
gitOutputLimit = 16 << 20
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
type cappedGitOutput struct {
|
|
23
|
+
bytes.Buffer
|
|
24
|
+
truncated bool
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
func (w *cappedGitOutput) Write(p []byte) (int, error) {
|
|
28
|
+
remaining := gitOutputLimit - w.Len()
|
|
29
|
+
if remaining > 0 {
|
|
30
|
+
if len(p) > remaining {
|
|
31
|
+
_, _ = w.Buffer.Write(p[:remaining])
|
|
32
|
+
w.truncated = true
|
|
33
|
+
} else {
|
|
34
|
+
_, _ = w.Buffer.Write(p)
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
w.truncated = true
|
|
38
|
+
}
|
|
39
|
+
return len(p), nil
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type gitCommandError struct {
|
|
43
|
+
args []string
|
|
44
|
+
output string
|
|
45
|
+
exitCode int
|
|
46
|
+
err error
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
func (e *gitCommandError) Error() string {
|
|
50
|
+
detail := strings.TrimSpace(e.output)
|
|
51
|
+
if detail == "" {
|
|
52
|
+
return fmt.Sprintf("git %s: %v", strings.Join(e.args, " "), e.err)
|
|
53
|
+
}
|
|
54
|
+
return fmt.Sprintf("git %s: %v: %s", strings.Join(e.args, " "), e.err, detail)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
func (e *gitCommandError) Unwrap() error { return e.err }
|
|
58
|
+
|
|
59
|
+
func runGitCommand(dir string, env []string, args ...string) ([]byte, error) {
|
|
60
|
+
ctx, cancel := context.WithTimeout(context.Background(), gitCommandTimeout)
|
|
61
|
+
defer cancel()
|
|
62
|
+
commandArgs := append([]string{"-C", dir}, args...)
|
|
63
|
+
cmd := exec.CommandContext(ctx, "git", commandArgs...)
|
|
64
|
+
cmd.WaitDelay = 2 * time.Second
|
|
65
|
+
if env == nil {
|
|
66
|
+
env = os.Environ()
|
|
67
|
+
} else {
|
|
68
|
+
env = append([]string{}, env...)
|
|
69
|
+
}
|
|
70
|
+
cmd.Env = append(
|
|
71
|
+
env,
|
|
72
|
+
"GIT_TERMINAL_PROMPT=0",
|
|
73
|
+
"GCM_INTERACTIVE=never",
|
|
74
|
+
"GIT_PAGER=cat",
|
|
75
|
+
"PAGER=cat",
|
|
76
|
+
"LC_ALL=C",
|
|
77
|
+
)
|
|
78
|
+
var output cappedGitOutput
|
|
79
|
+
cmd.Stdout = &output
|
|
80
|
+
cmd.Stderr = &output
|
|
81
|
+
err := cmd.Run()
|
|
82
|
+
if err == nil {
|
|
83
|
+
return output.Bytes(), nil
|
|
84
|
+
}
|
|
85
|
+
code := -1
|
|
86
|
+
var exitErr *exec.ExitError
|
|
87
|
+
if errors.As(err, &exitErr) {
|
|
88
|
+
code = exitErr.ExitCode()
|
|
89
|
+
}
|
|
90
|
+
if ctx.Err() != nil {
|
|
91
|
+
err = ctx.Err()
|
|
92
|
+
}
|
|
93
|
+
detail := output.String()
|
|
94
|
+
if output.truncated {
|
|
95
|
+
detail += "\n[git output truncated]"
|
|
96
|
+
}
|
|
97
|
+
return nil, &gitCommandError{
|
|
98
|
+
args: args,
|
|
99
|
+
output: detail,
|
|
100
|
+
exitCode: code,
|
|
101
|
+
err: err,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
func gitErrorExitCode(err error) (int, bool) {
|
|
106
|
+
var commandErr *gitCommandError
|
|
107
|
+
if !errors.As(err, &commandErr) {
|
|
108
|
+
return 0, false
|
|
109
|
+
}
|
|
110
|
+
return commandErr.exitCode, commandErr.exitCode >= 0
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// gitToplevel returns the absolute path of the Git working tree containing dir.
|
|
114
|
+
// Repository absence is distinct from Git execution failure so integrity gates
|
|
115
|
+
// can fail closed on a missing binary, corrupt repository, or poisoned runtime.
|
|
116
|
+
func gitToplevel(dir string) (string, error) {
|
|
117
|
+
out, err := runGitCommand(dir, nil, "rev-parse", "--show-toplevel")
|
|
14
118
|
if err != nil {
|
|
15
|
-
|
|
119
|
+
var commandErr *gitCommandError
|
|
120
|
+
if errors.As(err, &commandErr) {
|
|
121
|
+
detail := strings.ToLower(commandErr.output)
|
|
122
|
+
if strings.Contains(detail, "not a git repository") ||
|
|
123
|
+
strings.Contains(detail, "not a git work tree") {
|
|
124
|
+
return "", errNotGitRepository
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return "", err
|
|
128
|
+
}
|
|
129
|
+
root := strings.TrimSpace(string(out))
|
|
130
|
+
if root == "" {
|
|
131
|
+
return "", fmt.Errorf("git rev-parse returned an empty top-level path")
|
|
16
132
|
}
|
|
17
|
-
return filepath.Clean(
|
|
133
|
+
return filepath.Clean(root), nil
|
|
18
134
|
}
|
|
19
135
|
|
|
20
136
|
// gitDiffNames lists the paths that differ, relative to gitRoot. With one ref it
|
|
21
137
|
// diffs the working tree against that ref; with two it diffs the two tree objects.
|
|
22
|
-
func gitDiffNames(gitRoot string, refs ...string) []string {
|
|
23
|
-
args := append([]string{"
|
|
24
|
-
out, err :=
|
|
138
|
+
func gitDiffNames(gitRoot string, refs ...string) ([]string, error) {
|
|
139
|
+
args := append([]string{"diff", "--name-only"}, refs...)
|
|
140
|
+
out, err := runGitCommand(gitRoot, nil, args...)
|
|
25
141
|
if err != nil {
|
|
26
|
-
return nil
|
|
142
|
+
return nil, err
|
|
27
143
|
}
|
|
28
|
-
return splitLinesNoTrailing(out)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// stripASCIISpace removes every whitespace character from s (used to normalise an
|
|
32
|
-
// ACTIVE pointer before comparing it to a slug).
|
|
33
|
-
func stripASCIISpace(s string) string {
|
|
34
|
-
return strings.Map(func(r rune) rune {
|
|
35
|
-
if strings.ContainsRune(spaceChars, r) {
|
|
36
|
-
return -1
|
|
37
|
-
}
|
|
38
|
-
return r
|
|
39
|
-
}, s)
|
|
144
|
+
return splitLinesNoTrailing(out), nil
|
|
40
145
|
}
|
|
41
146
|
|
|
42
147
|
// isAllDigits reports whether s is a non-empty run of ASCII digits.
|
package/engine/main.go
CHANGED
|
@@ -56,7 +56,8 @@ Usage:
|
|
|
56
56
|
devrites-engine mutation-gate [slug] Advisory: detect the mutation runner and scope it
|
|
57
57
|
devrites-engine test-integrity [slug] Gate: no test deleted, skipped, or de-asserted
|
|
58
58
|
devrites-engine review-integrity [slug] Gate: no adversarial review axis is silent (zero findings, no justification)
|
|
59
|
-
devrites-engine
|
|
59
|
+
devrites-engine dispatch-waive <reason> Record a deterministic pre-dispatch STOP reason
|
|
60
|
+
devrites-engine reconcile <sub> [slug] A1 gate: snapshot|check|restore-check|close the wright's source writes
|
|
60
61
|
devrites-engine resolve <qid> "<ans>" Resolve an open question; keep state.md consistent
|
|
61
62
|
devrites-engine close-out <slug> Archive a shipped feature and clear ACTIVE
|
|
62
63
|
devrites-engine archive-search "<nouns>" Find prior shipped specs that overlap the query
|
|
@@ -238,6 +239,8 @@ func run(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
|
|
|
238
239
|
return lib.TestIntegrity(root, args[1:], stdout, stderr)
|
|
239
240
|
case "review-integrity":
|
|
240
241
|
return lib.ReviewIntegrity(root, args[1:], stdout, stderr)
|
|
242
|
+
case "dispatch-waive":
|
|
243
|
+
return lib.DispatchWaive(args[1:], stdout, stderr)
|
|
241
244
|
case "reconcile":
|
|
242
245
|
return lib.Reconcile(root, args[1:], stdout, stderr)
|
|
243
246
|
case "resolve":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
exit
|
|
1
|
+
exit 6
|
|
@@ -1 +1 @@
|
|
|
1
|
-
exit
|
|
1
|
+
exit 2
|