devrites 4.1.0 → 4.2.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 +6 -0
- package/README.md +1 -1
- package/docs/engine/commands.md +65 -6
- package/engine/go.mod +1 -1
- package/engine/internal/gate/gate.go +154 -46
- package/engine/internal/gate/gate_test.go +290 -2
- package/engine/internal/gate/readiness_binding.go +66 -100
- package/engine/internal/gate/readiness_binding_test.go +126 -3
- package/engine/internal/lib/resolve.go +6 -6
- package/engine/internal/state/cmd/workflowmanifest/main.go +32 -3
- package/engine/internal/state/feature.go +1 -100
- package/engine/internal/state/observation.go +584 -0
- package/engine/internal/state/observation_open_other.go +9 -0
- package/engine/internal/state/observation_open_unix.go +12 -0
- package/engine/internal/state/observation_test.go +960 -0
- package/engine/internal/state/observation_unix_test.go +68 -0
- package/engine/internal/state/schema.go +60 -160
- package/engine/internal/state/state_test.go +489 -101
- package/engine/internal/state/status.go +67 -48
- package/engine/tests/adr_0004_required_by_phase_test.go +16 -13
- package/engine/tests/adr_0011_define_plan_test.go +14 -12
- package/engine/tests/gate_test.go +403 -28
- package/engine/tests/workspace_observation_migration_test.go +1065 -0
- package/pack/.claude/skills/devrites-debug-recovery/SKILL.md +1 -10
- package/pack/.claude/skills/devrites-lib/reference/standards/acceptance-preserving-reslice.md +30 -0
- package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +2 -9
- package/pack/.claude/skills/devrites-lib/reference/standards/one-shot-actions.md +1 -6
- package/pack/.claude/skills/devrites-lib/reference/standards/workflow-artifacts.md +411 -102
- package/pack/.claude/skills/rite-autocomplete/SKILL.md +98 -146
- package/pack/.claude/skills/rite-autocomplete/reference/decision-policy.md +11 -5
- package/pack/.claude/skills/rite-autocomplete/reference/loop.md +96 -134
- package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +92 -131
- package/pack/.claude/skills/rite-build/SKILL.md +51 -79
- package/pack/.claude/skills/rite-build/reference/phase-contract.md +3 -17
- package/pack/.claude/skills/rite-plan/SKILL.md +17 -17
- package/pack/.claude/skills/rite-plan/reference/anti-patterns.md +11 -1
- package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +10 -3
- package/pack/.claude/skills/rite-prove/SKILL.md +95 -153
- package/pack/.claude/skills/rite-vet/SKILL.md +121 -174
- package/pack/.claude/skills/rite-vet/reference/anti-patterns.md +14 -2
- package/pack/.claude/skills/rite-vet/reference/artifacts.md +10 -6
- package/pack/.claude/skills/rite-vet/reference/depth.md +10 -3
- package/pack/.claude/skills/rite-vet/reference/review-axes.md +12 -4
- package/pack/generated/claude/skills/devrites-debug-recovery/SKILL.md +1 -10
- package/pack/generated/claude/skills/devrites-lib/reference/standards/acceptance-preserving-reslice.md +30 -0
- package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +2 -9
- package/pack/generated/claude/skills/devrites-lib/reference/standards/one-shot-actions.md +1 -6
- package/pack/generated/claude/skills/devrites-lib/reference/standards/workflow-artifacts.md +411 -102
- package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +98 -146
- package/pack/generated/claude/skills/rite-autocomplete/reference/decision-policy.md +11 -5
- package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +96 -134
- package/pack/generated/claude/skills/rite-autocomplete/reference/stop-conditions.md +92 -131
- package/pack/generated/claude/skills/rite-build/SKILL.md +51 -79
- package/pack/generated/claude/skills/rite-build/reference/phase-contract.md +3 -17
- package/pack/generated/claude/skills/rite-plan/SKILL.md +17 -17
- package/pack/generated/claude/skills/rite-plan/reference/anti-patterns.md +11 -1
- package/pack/generated/claude/skills/rite-plan/reference/replan-and-repair.md +10 -3
- package/pack/generated/claude/skills/rite-prove/SKILL.md +95 -153
- package/pack/generated/claude/skills/rite-vet/SKILL.md +121 -174
- package/pack/generated/claude/skills/rite-vet/reference/anti-patterns.md +14 -2
- package/pack/generated/claude/skills/rite-vet/reference/artifacts.md +10 -6
- package/pack/generated/claude/skills/rite-vet/reference/depth.md +10 -3
- package/pack/generated/claude/skills/rite-vet/reference/review-axes.md +12 -4
- package/pack/generated/codex/skills/devrites-debug-recovery/SKILL.md +1 -10
- package/pack/generated/codex/skills/devrites-lib/reference/standards/acceptance-preserving-reslice.md +30 -0
- package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +2 -9
- package/pack/generated/codex/skills/devrites-lib/reference/standards/one-shot-actions.md +1 -6
- package/pack/generated/codex/skills/devrites-lib/reference/standards/workflow-artifacts.md +411 -102
- package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +98 -146
- package/pack/generated/codex/skills/rite-autocomplete/reference/decision-policy.md +11 -5
- package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +96 -134
- package/pack/generated/codex/skills/rite-autocomplete/reference/stop-conditions.md +92 -131
- package/pack/generated/codex/skills/rite-build/SKILL.md +51 -79
- package/pack/generated/codex/skills/rite-build/reference/phase-contract.md +3 -17
- package/pack/generated/codex/skills/rite-plan/SKILL.md +17 -17
- package/pack/generated/codex/skills/rite-plan/reference/anti-patterns.md +11 -1
- package/pack/generated/codex/skills/rite-plan/reference/replan-and-repair.md +10 -3
- package/pack/generated/codex/skills/rite-prove/SKILL.md +95 -153
- package/pack/generated/codex/skills/rite-vet/SKILL.md +121 -174
- package/pack/generated/codex/skills/rite-vet/reference/anti-patterns.md +14 -2
- package/pack/generated/codex/skills/rite-vet/reference/artifacts.md +10 -6
- package/pack/generated/codex/skills/rite-vet/reference/depth.md +10 -3
- package/pack/generated/codex/skills/rite-vet/reference/review-axes.md +12 -4
- package/package.json +1 -1
|
@@ -6,78 +6,94 @@ import (
|
|
|
6
6
|
)
|
|
7
7
|
|
|
8
8
|
// Report is the computed completeness status of a feature at its current phase.
|
|
9
|
-
// It embeds the loaded Feature (Slug, Phase, Present) and adds the phase-relative
|
|
10
|
-
// required set and the missing sections.
|
|
11
9
|
type Report struct {
|
|
12
|
-
|
|
10
|
+
Slug string
|
|
11
|
+
Phase Phase
|
|
13
12
|
Required map[Section]bool
|
|
14
|
-
Missing []Section //
|
|
13
|
+
Missing []Section // required-but-empty sections, in policy order
|
|
15
14
|
RequiredFiles map[string]bool
|
|
16
15
|
MissingFiles []string // required-but-empty workspace files, in lifecycle order
|
|
16
|
+
present map[Section]bool
|
|
17
|
+
diagnostics []ArtifactDiagnostic
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
// Status computes
|
|
20
|
-
// the files directly. It reports completeness relative to the feature's current
|
|
21
|
-
// phase only.
|
|
20
|
+
// Status computes phase-relative completeness from one retained workspace observation.
|
|
22
21
|
func Status(root, slug string) (*Report, error) {
|
|
23
|
-
|
|
22
|
+
return statusWithCallback(root, slug, nil)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func statusWithCallback(root, slug string, callback observationCallback) (*Report, error) {
|
|
26
|
+
observation, err := observeWorkspace(root, slug, callback)
|
|
27
|
+
if err != nil {
|
|
28
|
+
return nil, err
|
|
29
|
+
}
|
|
30
|
+
phase, err := observation.DeclaredPhase()
|
|
24
31
|
if err != nil {
|
|
25
32
|
return nil, fmt.Errorf("compute status: %w", err)
|
|
26
33
|
}
|
|
27
|
-
|
|
34
|
+
policy, _ := PolicyFor(phase)
|
|
35
|
+
return newObservationReport(observation, phase, policy), nil
|
|
28
36
|
}
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
func newObservationReport(observation *WorkspaceObservation, phase Phase, policy PhasePolicy) *Report {
|
|
39
|
+
present := observationSectionPresence(observation)
|
|
40
|
+
required := requiredSections(policy)
|
|
41
|
+
requiredFiles := requiredArtifactSet(policy)
|
|
42
|
+
missingArtifacts, diagnostics := observation.Missing(policy.RequiredArtifacts)
|
|
43
|
+
missingFiles := make([]string, len(missingArtifacts))
|
|
44
|
+
for i, artifact := range missingArtifacts {
|
|
45
|
+
missingFiles[i] = string(artifact)
|
|
36
46
|
}
|
|
37
|
-
requiredFiles := make(map[string]bool)
|
|
38
|
-
for _, name := range RequiredWorkspaceFiles(f.Phase) {
|
|
39
|
-
requiredFiles[name] = true
|
|
40
|
-
}
|
|
41
|
-
missingFiles := MissingWorkspaceFiles(f, f.Phase)
|
|
42
47
|
return &Report{
|
|
43
|
-
|
|
48
|
+
Slug: observation.Slug(),
|
|
49
|
+
Phase: phase,
|
|
44
50
|
Required: required,
|
|
45
|
-
Missing:
|
|
51
|
+
Missing: missingObservationSections(present, policy.RequiredSections),
|
|
46
52
|
RequiredFiles: requiredFiles,
|
|
47
53
|
MissingFiles: missingFiles,
|
|
54
|
+
present: present,
|
|
55
|
+
diagnostics: diagnostics,
|
|
48
56
|
}
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
func observationSectionPresence(observation *WorkspaceObservation) map[Section]bool {
|
|
60
|
+
present := make(map[Section]bool, len(Sections))
|
|
61
|
+
for _, section := range Sections {
|
|
62
|
+
for _, name := range sectionFiles[section] {
|
|
63
|
+
fact, ok := observation.Fact(ArtifactPath(name))
|
|
64
|
+
if ok && fact.State() == ArtifactPresent {
|
|
65
|
+
present[section] = true
|
|
66
|
+
break
|
|
67
|
+
}
|
|
68
|
+
}
|
|
60
69
|
}
|
|
70
|
+
return present
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
func missingObservationSections(present map[Section]bool, required []Section) []Section {
|
|
61
74
|
var missing []Section
|
|
62
|
-
for _,
|
|
63
|
-
if
|
|
64
|
-
missing = append(missing,
|
|
75
|
+
for _, section := range required {
|
|
76
|
+
if !present[section] {
|
|
77
|
+
missing = append(missing, section)
|
|
65
78
|
}
|
|
66
79
|
}
|
|
67
80
|
return missing
|
|
68
81
|
}
|
|
69
82
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
var missing []string
|
|
75
|
-
for _, name := range RequiredWorkspaceFiles(p) {
|
|
76
|
-
if !f.PresentFiles[name] {
|
|
77
|
-
missing = append(missing, name)
|
|
78
|
-
}
|
|
83
|
+
func requiredSections(policy PhasePolicy) map[Section]bool {
|
|
84
|
+
required := make(map[Section]bool, len(policy.RequiredSections))
|
|
85
|
+
for _, section := range policy.RequiredSections {
|
|
86
|
+
required[section] = true
|
|
79
87
|
}
|
|
80
|
-
return
|
|
88
|
+
return required
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
func requiredArtifactSet(policy PhasePolicy) map[string]bool {
|
|
92
|
+
required := make(map[string]bool, len(policy.RequiredArtifacts))
|
|
93
|
+
for _, artifact := range policy.RequiredArtifacts {
|
|
94
|
+
required[string(artifact)] = true
|
|
95
|
+
}
|
|
96
|
+
return required
|
|
81
97
|
}
|
|
82
98
|
|
|
83
99
|
// Complete reports whether every concrete canonical-workspace file required by
|
|
@@ -92,19 +108,22 @@ func (r *Report) Render() string {
|
|
|
92
108
|
var b strings.Builder
|
|
93
109
|
fmt.Fprintf(&b, "feature: %s\n", r.Slug)
|
|
94
110
|
fmt.Fprintf(&b, "phase: %s\n", r.Phase)
|
|
95
|
-
for _,
|
|
111
|
+
for _, section := range Sections {
|
|
96
112
|
state := "empty"
|
|
97
|
-
if r.
|
|
113
|
+
if r.present[section] {
|
|
98
114
|
state = "present"
|
|
99
115
|
}
|
|
100
116
|
mark := ""
|
|
101
|
-
if r.Required[
|
|
117
|
+
if r.Required[section] {
|
|
102
118
|
mark = "required"
|
|
103
119
|
}
|
|
104
|
-
line := fmt.Sprintf(" %-10s %-8s %s",
|
|
120
|
+
line := fmt.Sprintf(" %-10s %-8s %s", section, state, mark)
|
|
105
121
|
b.WriteString(strings.TrimRight(line, " "))
|
|
106
122
|
b.WriteByte('\n')
|
|
107
123
|
}
|
|
124
|
+
for _, diagnostic := range r.diagnostics {
|
|
125
|
+
fmt.Fprintf(&b, "artifact: %s: %s (%s)\n", diagnostic.Path, diagnostic.State, diagnostic.Code)
|
|
126
|
+
}
|
|
108
127
|
if r.Complete() {
|
|
109
128
|
b.WriteString("result: complete\n")
|
|
110
129
|
} else {
|
|
@@ -13,31 +13,34 @@ import (
|
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
func TestADR0004RequiredSectionsAreAdditiveDownTheArc(t *testing.T) {
|
|
16
|
-
|
|
17
|
-
for _,
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
policies := state.PhasePolicies()
|
|
17
|
+
for _, policy := range policies {
|
|
18
|
+
lookedUp, ok := state.PolicyFor(policy.Target)
|
|
19
|
+
if !ok || lookedUp.Target != policy.Target {
|
|
20
|
+
t.Fatalf("phase %q in the arc is not a known phase", policy.Target)
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
// Each phase's required set must contain everything the previous phase
|
|
24
25
|
// required: completeness only accumulates, never regresses.
|
|
25
|
-
for i := 1; i < len(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
for
|
|
29
|
-
if !
|
|
26
|
+
for i := 1; i < len(policies); i++ {
|
|
27
|
+
previous := asSet(policies[i-1].RequiredSections)
|
|
28
|
+
current := asSet(policies[i].RequiredSections)
|
|
29
|
+
for section := range previous {
|
|
30
|
+
if !current[section] {
|
|
30
31
|
t.Errorf("phase %q dropped section %q that %q required: arc must be additive",
|
|
31
|
-
|
|
32
|
+
policies[i].Target, section, policies[i-1].Target)
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
// Anchors: framing requires nothing; seal requires the full section set.
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
frame, _ := state.PolicyFor(state.PhaseFrame)
|
|
39
|
+
if len(frame.RequiredSections) != 0 {
|
|
40
|
+
t.Errorf("frame requires %v, want none", frame.RequiredSections)
|
|
39
41
|
}
|
|
40
|
-
|
|
42
|
+
seal, _ := state.PolicyFor(state.PhaseSeal)
|
|
43
|
+
if got, want := len(seal.RequiredSections), len(state.Sections); got != want {
|
|
41
44
|
t.Errorf("seal requires %d sections, want the full set of %d", got, want)
|
|
42
45
|
}
|
|
43
46
|
}
|
|
@@ -7,24 +7,26 @@ import (
|
|
|
7
7
|
)
|
|
8
8
|
|
|
9
9
|
func TestADR0011DefineAndPlanHaveDistinctTransitionRights(t *testing.T) {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
define, ok := state.PolicyFor(state.PhaseDefine)
|
|
11
|
+
if !ok || define.ResumeVerb != "define" {
|
|
12
|
+
t.Fatalf("define policy=(%+v,%v), want resume verb define", define, ok)
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
plan, ok := state.PolicyFor(state.PhasePlan)
|
|
15
|
+
if !ok || plan.ResumeVerb != "vet" {
|
|
16
|
+
t.Fatalf("plan policy=(%+v,%v), want resume verb vet", plan, ok)
|
|
15
17
|
}
|
|
16
|
-
if
|
|
17
|
-
t.Fatalf("planning alias=(
|
|
18
|
+
if policy, ok := state.PolicyFor(state.Phase("planning")); ok {
|
|
19
|
+
t.Fatalf("planning alias=(%+v,true), want speculative alias rejected", policy)
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
rights := map[string]state.Phase{}
|
|
21
|
-
for _,
|
|
22
|
-
if
|
|
23
|
-
t.Fatalf("phase %q has no transition right",
|
|
23
|
+
for _, policy := range state.PhasePolicies() {
|
|
24
|
+
if policy.TransitionRight == "" {
|
|
25
|
+
t.Fatalf("phase %q has no transition right", policy.Target)
|
|
24
26
|
}
|
|
25
|
-
if prior := rights[
|
|
26
|
-
t.Fatalf("phases %q and %q share transition right %q", prior,
|
|
27
|
+
if prior := rights[policy.TransitionRight]; prior != "" {
|
|
28
|
+
t.Fatalf("phases %q and %q share transition right %q", prior, policy.Target, policy.TransitionRight)
|
|
27
29
|
}
|
|
28
|
-
rights[
|
|
30
|
+
rights[policy.TransitionRight] = policy.Target
|
|
29
31
|
}
|
|
30
32
|
}
|