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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
//go:build unix
|
|
2
|
+
|
|
3
|
+
package state
|
|
4
|
+
|
|
5
|
+
import (
|
|
6
|
+
"os"
|
|
7
|
+
"path/filepath"
|
|
8
|
+
"syscall"
|
|
9
|
+
"testing"
|
|
10
|
+
"time"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
type fifoObservationResult struct {
|
|
14
|
+
observation *WorkspaceObservation
|
|
15
|
+
observationErr error
|
|
16
|
+
setupErr error
|
|
17
|
+
fifoCreated bool
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func TestWorkspaceObservationFIFORegularSubstitutionDoesNotWaitForWriter(t *testing.T) {
|
|
21
|
+
root, slug := newObservationWorkspace(t)
|
|
22
|
+
writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
|
|
23
|
+
writeObservationArtifact(t, root, slug, "brief.md", []byte("regular\n"))
|
|
24
|
+
artifactPath := filepath.Join(root, "work", slug, "brief.md")
|
|
25
|
+
|
|
26
|
+
result := make(chan fifoObservationResult, 1)
|
|
27
|
+
go func() {
|
|
28
|
+
var setupErr error
|
|
29
|
+
fifoCreated := false
|
|
30
|
+
observation, observationErr := observeWorkspace(root, slug, func(stage observationStage, artifact ArtifactPath) error {
|
|
31
|
+
if stage != observationBeforeOpen || artifact != "brief.md" {
|
|
32
|
+
return nil
|
|
33
|
+
}
|
|
34
|
+
if err := os.Remove(artifactPath); err != nil {
|
|
35
|
+
setupErr = err
|
|
36
|
+
return nil
|
|
37
|
+
}
|
|
38
|
+
if err := syscall.Mkfifo(artifactPath, 0o600); err != nil {
|
|
39
|
+
setupErr = err
|
|
40
|
+
return nil
|
|
41
|
+
}
|
|
42
|
+
fifoCreated = true
|
|
43
|
+
return nil
|
|
44
|
+
})
|
|
45
|
+
result <- fifoObservationResult{
|
|
46
|
+
observation: observation,
|
|
47
|
+
observationErr: observationErr,
|
|
48
|
+
setupErr: setupErr,
|
|
49
|
+
fifoCreated: fifoCreated,
|
|
50
|
+
}
|
|
51
|
+
}()
|
|
52
|
+
|
|
53
|
+
select {
|
|
54
|
+
case got := <-result:
|
|
55
|
+
if got.setupErr != nil {
|
|
56
|
+
t.Fatalf("FIFO setup failed: %v", got.setupErr)
|
|
57
|
+
}
|
|
58
|
+
if !got.fifoCreated {
|
|
59
|
+
t.Fatal("FIFO setup reported success without creating the FIFO")
|
|
60
|
+
}
|
|
61
|
+
if got.observation != nil {
|
|
62
|
+
t.Fatalf("observation = %+v, want nil", got.observation)
|
|
63
|
+
}
|
|
64
|
+
assertObservationFailure(t, got.observationErr, ObservationConcurrentChange, "workspace observation: concurrent_change: workspace changed during acquisition; retry")
|
|
65
|
+
case <-time.After(2 * time.Second):
|
|
66
|
+
t.Fatal("ObserveWorkspace waited for a FIFO writer")
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -66,18 +66,19 @@ const (
|
|
|
66
66
|
PhaseDone Phase = "done" // archived completion
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
// ArtifactPath is the logical identity of an observed workspace artifact.
|
|
70
|
+
type ArtifactPath string
|
|
71
|
+
|
|
72
|
+
// PhasePolicy is the complete deterministic policy for one target Phase.
|
|
73
|
+
type PhasePolicy struct {
|
|
74
|
+
Target Phase
|
|
75
|
+
ResumeVerb string
|
|
76
|
+
TransitionRight string
|
|
77
|
+
RequiredSections []Section
|
|
78
|
+
RequiredArtifacts []ArtifactPath
|
|
79
|
+
ProofRequired bool
|
|
80
|
+
BlocksOpenQuestions bool
|
|
81
|
+
Shippable bool
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
var (
|
|
@@ -87,48 +88,43 @@ var (
|
|
|
87
88
|
sectionsProof = []Section{SectionSpec, SectionPlan, SectionDecisions, SectionTasks, SectionProof}
|
|
88
89
|
sectionsComplete = []Section{SectionSpec, SectionPlan, SectionDecisions, SectionTasks, SectionProof, SectionStatus}
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
91
|
+
artifactsFrame = []ArtifactPath{"state.md"}
|
|
92
|
+
artifactsSpec = []ArtifactPath{"brief.md", "spec.md", "state.md", "decisions.md", "assumptions.md", "questions.md"}
|
|
93
|
+
artifactsClarify = append(append([]ArtifactPath(nil), artifactsSpec...), "decision-coverage.md")
|
|
94
|
+
artifactsPlan = append(append([]ArtifactPath(nil), artifactsClarify...), "architecture.md", "plan.md", "tasks.md", "traceability.md")
|
|
95
|
+
artifactsVetted = append(append([]ArtifactPath(nil), artifactsPlan...), "eng-review.md", "test-plan.md")
|
|
96
|
+
artifactsProof = append(append([]ArtifactPath(nil), artifactsVetted...), "evidence.md", "touched-files.md")
|
|
97
|
+
artifactsFinal = append(append([]ArtifactPath(nil), artifactsProof...), "review.md", "seal.md")
|
|
97
98
|
)
|
|
98
99
|
|
|
99
100
|
// Completeness is phase-relative: a section not yet required (e.g. proof during
|
|
100
101
|
// spec) never blocks. Requirements are additive down the arc. Define is active
|
|
101
102
|
// authoring; Plan is the approved/repaired checkpoint that resumes at Vet.
|
|
102
|
-
var
|
|
103
|
-
{
|
|
104
|
-
{
|
|
105
|
-
{
|
|
106
|
-
{
|
|
107
|
-
{
|
|
108
|
-
{
|
|
109
|
-
{
|
|
110
|
-
{
|
|
111
|
-
{
|
|
112
|
-
{
|
|
113
|
-
{
|
|
114
|
-
{
|
|
115
|
-
{
|
|
116
|
-
{
|
|
117
|
-
{
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
WorkspaceRequired []string `json:"workspaceRequired"`
|
|
128
|
-
ProofRequired bool `json:"proofRequired,omitempty"`
|
|
129
|
-
BlocksOpenQuestions bool `json:"blocksOpenQuestions,omitempty"`
|
|
130
|
-
Shippable bool `json:"shippable,omitempty"`
|
|
131
|
-
}
|
|
103
|
+
var orderedPhasePolicies = []PhasePolicy{
|
|
104
|
+
{Target: PhaseFrame, ResumeVerb: "frame", TransitionRight: "Frame an unstructured request before lifecycle work.", RequiredArtifacts: artifactsFrame},
|
|
105
|
+
{Target: PhaseSpec, ResumeVerb: "spec", TransitionRight: "Author the product specification.", RequiredSections: sectionsSpec, RequiredArtifacts: artifactsSpec},
|
|
106
|
+
{Target: PhaseClarify, ResumeVerb: "clarify", TransitionRight: "Close decision coverage in the written specification.", RequiredSections: sectionsSpec, RequiredArtifacts: artifactsClarify, BlocksOpenQuestions: true},
|
|
107
|
+
{Target: PhaseTemper, ResumeVerb: "temper", TransitionRight: "Optionally challenge the clarified specification strategy.", RequiredSections: sectionsSpec, RequiredArtifacts: artifactsClarify, BlocksOpenQuestions: true},
|
|
108
|
+
{Target: PhaseDefine, ResumeVerb: "define", TransitionRight: "Author and approve the initial implementation plan.", RequiredSections: sectionsPlan, RequiredArtifacts: artifactsPlan, BlocksOpenQuestions: true},
|
|
109
|
+
{Target: PhasePlan, ResumeVerb: "vet", TransitionRight: "Hold the approved or repaired plan checkpoint for engineering review.", RequiredSections: sectionsPlan, RequiredArtifacts: artifactsPlan, BlocksOpenQuestions: true},
|
|
110
|
+
{Target: PhaseVet, ResumeVerb: "vet", TransitionRight: "Review implementation readiness before build.", RequiredSections: sectionsBuild, RequiredArtifacts: artifactsVetted, BlocksOpenQuestions: true},
|
|
111
|
+
{Target: PhaseBuild, ResumeVerb: "build", TransitionRight: "Implement the next approved vertical slice.", RequiredSections: sectionsBuild, RequiredArtifacts: artifactsVetted, BlocksOpenQuestions: true},
|
|
112
|
+
{Target: PhaseConverge, ResumeVerb: "converge", TransitionRight: "Recover unmet clarified intent into new slices.", RequiredSections: sectionsBuild, RequiredArtifacts: artifactsVetted, BlocksOpenQuestions: true},
|
|
113
|
+
{Target: PhaseProve, ResumeVerb: "prove", TransitionRight: "Produce acceptance evidence for the implementation.", RequiredSections: sectionsProof, RequiredArtifacts: artifactsProof, ProofRequired: true, BlocksOpenQuestions: true},
|
|
114
|
+
{Target: PhasePolish, ResumeVerb: "polish", TransitionRight: "Apply the bounded quality pass.", RequiredSections: sectionsProof, RequiredArtifacts: artifactsProof, ProofRequired: true, BlocksOpenQuestions: true},
|
|
115
|
+
{Target: PhaseReview, ResumeVerb: "review", TransitionRight: "Review the proven implementation.", RequiredSections: sectionsProof, RequiredArtifacts: artifactsProof, ProofRequired: true, BlocksOpenQuestions: true},
|
|
116
|
+
{Target: PhaseSeal, ResumeVerb: "seal", TransitionRight: "Decide the final GO or NO-GO.", RequiredSections: sectionsComplete, RequiredArtifacts: artifactsFinal, ProofRequired: true, BlocksOpenQuestions: true, Shippable: true},
|
|
117
|
+
{Target: PhaseShip, ResumeVerb: "ship", TransitionRight: "Perform authorized release and close-out mutations.", RequiredSections: sectionsComplete, RequiredArtifacts: artifactsFinal, ProofRequired: true, BlocksOpenQuestions: true, Shippable: true},
|
|
118
|
+
{Target: PhaseDone, TransitionRight: "Represent archived completion with no resume command.", RequiredSections: sectionsComplete, RequiredArtifacts: artifactsFinal, ProofRequired: true, BlocksOpenQuestions: true, Shippable: true},
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
var phasePolicyIndex = func() map[Phase]int {
|
|
122
|
+
index := make(map[Phase]int, len(orderedPhasePolicies))
|
|
123
|
+
for i, policy := range orderedPhasePolicies {
|
|
124
|
+
index[policy.Target] = i
|
|
125
|
+
}
|
|
126
|
+
return index
|
|
127
|
+
}()
|
|
132
128
|
|
|
133
129
|
// AuthorityPolicy owns the small cross-format trust and tracking assertions
|
|
134
130
|
// that otherwise drift between current docs.
|
|
@@ -147,122 +143,26 @@ func WorkflowAuthorityPolicy() AuthorityPolicy {
|
|
|
147
143
|
}
|
|
148
144
|
}
|
|
149
145
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
out = append(out, WorkflowPhase{
|
|
155
|
-
ID: definition.phase,
|
|
156
|
-
ResumeVerb: definition.resumeVerb,
|
|
157
|
-
TransitionRight: definition.transitionRight,
|
|
158
|
-
RequiredSections: append([]Section(nil), definition.required...),
|
|
159
|
-
WorkspaceRequired: append([]string(nil), definition.workspaceRequired...),
|
|
160
|
-
ProofRequired: definition.proofRequired,
|
|
161
|
-
BlocksOpenQuestions: definition.blocksOpenQuestions,
|
|
162
|
-
Shippable: definition.shippable,
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
return out
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// LifecyclePhases returns the ordered lifecycle. The returned slice is a copy,
|
|
169
|
-
// so callers cannot mutate the registry.
|
|
170
|
-
func LifecyclePhases() []Phase {
|
|
171
|
-
phases := make([]Phase, len(phaseDefinitions))
|
|
172
|
-
for i, definition := range phaseDefinitions {
|
|
173
|
-
phases[i] = definition.phase
|
|
174
|
-
}
|
|
175
|
-
return phases
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
func definitionFor(p Phase) (phaseDefinition, bool) {
|
|
179
|
-
for _, definition := range phaseDefinitions {
|
|
180
|
-
if definition.phase == p {
|
|
181
|
-
return definition, true
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return phaseDefinition{}, false
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// KnownPhase reports whether p is a phase the engine understands.
|
|
188
|
-
func KnownPhase(p Phase) bool {
|
|
189
|
-
_, ok := definitionFor(p)
|
|
190
|
-
return ok
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// ResumeVerb returns the public rite verb that resumes p. Terminal and unknown
|
|
194
|
-
// phases return an empty string.
|
|
195
|
-
func ResumeVerb(p Phase) string {
|
|
196
|
-
definition, ok := definitionFor(p)
|
|
197
|
-
if !ok {
|
|
198
|
-
return ""
|
|
199
|
-
}
|
|
200
|
-
return definition.resumeVerb
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// ShippablePhase reports whether p is allowed to claim a sealed/shipped result.
|
|
204
|
-
func ShippablePhase(p Phase) bool {
|
|
205
|
-
definition, ok := definitionFor(p)
|
|
206
|
-
return ok && definition.shippable
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// PhaseForName resolves a canonical phase ID.
|
|
210
|
-
func PhaseForName(name string) (Phase, bool) {
|
|
211
|
-
for _, definition := range phaseDefinitions {
|
|
212
|
-
if string(definition.phase) == name {
|
|
213
|
-
return definition.phase, true
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
return "", false
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// RequiredSections returns the sections required to complete the given phase,
|
|
220
|
-
// in canonical Sections order.
|
|
221
|
-
func RequiredSections(p Phase) []Section {
|
|
222
|
-
definition, ok := definitionFor(p)
|
|
223
|
-
if !ok {
|
|
224
|
-
return nil
|
|
225
|
-
}
|
|
226
|
-
want := definition.required
|
|
227
|
-
set := make(map[Section]bool, len(want))
|
|
228
|
-
for _, s := range want {
|
|
229
|
-
set[s] = true
|
|
230
|
-
}
|
|
231
|
-
out := make([]Section, 0, len(want))
|
|
232
|
-
for _, s := range Sections {
|
|
233
|
-
if set[s] {
|
|
234
|
-
out = append(out, s)
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
return out
|
|
146
|
+
func copyPhasePolicy(policy PhasePolicy) PhasePolicy {
|
|
147
|
+
policy.RequiredSections = append([]Section(nil), policy.RequiredSections...)
|
|
148
|
+
policy.RequiredArtifacts = append([]ArtifactPath(nil), policy.RequiredArtifacts...)
|
|
149
|
+
return policy
|
|
238
150
|
}
|
|
239
151
|
|
|
240
|
-
//
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
// runtime gates cannot silently ignore files added to the lifecycle registry.
|
|
244
|
-
func RequiredWorkspaceFiles(p Phase) []string {
|
|
245
|
-
definition, ok := definitionFor(p)
|
|
152
|
+
// PolicyFor returns the complete policy for target. Unknown phases have no fallback.
|
|
153
|
+
func PolicyFor(target Phase) (PhasePolicy, bool) {
|
|
154
|
+
index, ok := phasePolicyIndex[target]
|
|
246
155
|
if !ok {
|
|
247
|
-
return
|
|
156
|
+
return PhasePolicy{}, false
|
|
248
157
|
}
|
|
249
|
-
return
|
|
158
|
+
return copyPhasePolicy(orderedPhasePolicies[index]), true
|
|
250
159
|
}
|
|
251
160
|
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
var out []string
|
|
258
|
-
for _, definition := range phaseDefinitions {
|
|
259
|
-
for _, name := range definition.workspaceRequired {
|
|
260
|
-
if seen[name] {
|
|
261
|
-
continue
|
|
262
|
-
}
|
|
263
|
-
seen[name] = true
|
|
264
|
-
out = append(out, name)
|
|
265
|
-
}
|
|
161
|
+
// PhasePolicies returns all policies in lifecycle order.
|
|
162
|
+
func PhasePolicies() []PhasePolicy {
|
|
163
|
+
policies := make([]PhasePolicy, len(orderedPhasePolicies))
|
|
164
|
+
for i, policy := range orderedPhasePolicies {
|
|
165
|
+
policies[i] = copyPhasePolicy(policy)
|
|
266
166
|
}
|
|
267
|
-
return
|
|
167
|
+
return policies
|
|
268
168
|
}
|