Skip to content

Commit 843c18d

Browse files
grokifyclaude
andcommitted
feat(types): add annotations, alternatives, conditions, notes, and nested phases
Add new types and fields to support richer protocol descriptions: Types: - AnnotationType: security, performance, deprecated, info, warning, error - Annotation: typed annotation with text and optional details - Alternative: alternative flow path with condition and nested flows Fields: - Phase.Parent: enables nested phase hierarchies - Flow.Condition: conditional flow execution (when clause) - Flow.Note: visible notes displayed on diagrams - Flow.Annotations: typed annotations for tooling - Flow.Alternatives: alternative/error paths Helper methods: - Protocol.RootPhases(), ChildPhases(), PhaseDepth() - Flow.HasCondition(), HasNote(), HasAnnotations(), HasAlternatives() - IsValidAnnotationType() Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent a5f8f35 commit 843c18d

1 file changed

Lines changed: 114 additions & 0 deletions

File tree

pidl.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,45 @@ type Phase struct {
102102

103103
// Description of the phase.
104104
Description string `json:"description,omitempty"`
105+
106+
// Parent is the ID of the parent phase for nested phases.
107+
Parent string `json:"parent,omitempty"`
108+
}
109+
110+
// AnnotationType represents the type of annotation.
111+
type AnnotationType string
112+
113+
const (
114+
AnnotationTypeSecurity AnnotationType = "security"
115+
AnnotationTypePerformance AnnotationType = "performance"
116+
AnnotationTypeDeprecated AnnotationType = "deprecated"
117+
AnnotationTypeInfo AnnotationType = "info"
118+
AnnotationTypeWarning AnnotationType = "warning"
119+
AnnotationTypeError AnnotationType = "error"
120+
)
121+
122+
// Annotation represents a typed annotation on a flow.
123+
type Annotation struct {
124+
// Type categorizes the annotation.
125+
Type AnnotationType `json:"type"`
126+
127+
// Text is the annotation message.
128+
Text string `json:"text"`
129+
130+
// Details provides additional context.
131+
Details string `json:"details,omitempty"`
132+
}
133+
134+
// Alternative represents an alternative path in the flow.
135+
type Alternative struct {
136+
// Condition describes when this alternative is taken.
137+
Condition string `json:"condition"`
138+
139+
// Flows are the steps in this alternative path.
140+
Flows []Flow `json:"flows"`
141+
142+
// Description provides additional context.
143+
Description string `json:"description,omitempty"`
105144
}
106145

107146
// Flow represents an interaction between two entities.
@@ -129,6 +168,18 @@ type Flow struct {
129168

130169
// Sequence provides explicit ordering.
131170
Sequence int `json:"sequence,omitempty"`
171+
172+
// Condition specifies when this flow is executed (e.g., "token_valid", "error").
173+
Condition string `json:"condition,omitempty"`
174+
175+
// Note is a visible annotation displayed on the diagram.
176+
Note string `json:"note,omitempty"`
177+
178+
// Annotations are typed annotations for tooling and documentation.
179+
Annotations []Annotation `json:"annotations,omitempty"`
180+
181+
// Alternatives are alternative paths from this flow point.
182+
Alternatives []Alternative `json:"alternatives,omitempty"`
132183
}
133184

134185
// FlowMode represents the type of interaction.
@@ -209,3 +260,66 @@ func (p *Protocol) PhaseIDs() []string {
209260
}
210261
return ids
211262
}
263+
264+
// RootPhases returns phases that have no parent (top-level phases).
265+
func (p *Protocol) RootPhases() []Phase {
266+
var roots []Phase
267+
for _, ph := range p.Phases {
268+
if ph.Parent == "" {
269+
roots = append(roots, ph)
270+
}
271+
}
272+
return roots
273+
}
274+
275+
// ChildPhases returns phases that have the given parent ID.
276+
func (p *Protocol) ChildPhases(parentID string) []Phase {
277+
var children []Phase
278+
for _, ph := range p.Phases {
279+
if ph.Parent == parentID {
280+
children = append(children, ph)
281+
}
282+
}
283+
return children
284+
}
285+
286+
// PhaseDepth returns the nesting depth of a phase (0 for root phases).
287+
func (p *Protocol) PhaseDepth(phaseID string) int {
288+
depth := 0
289+
current := p.PhaseByID(phaseID)
290+
for current != nil && current.Parent != "" {
291+
depth++
292+
current = p.PhaseByID(current.Parent)
293+
}
294+
return depth
295+
}
296+
297+
// HasCondition returns true if the flow has a condition.
298+
func (f Flow) HasCondition() bool {
299+
return f.Condition != ""
300+
}
301+
302+
// HasAlternatives returns true if the flow has alternative paths.
303+
func (f Flow) HasAlternatives() bool {
304+
return len(f.Alternatives) > 0
305+
}
306+
307+
// HasAnnotations returns true if the flow has annotations.
308+
func (f Flow) HasAnnotations() bool {
309+
return len(f.Annotations) > 0
310+
}
311+
312+
// HasNote returns true if the flow has a note.
313+
func (f Flow) HasNote() bool {
314+
return f.Note != ""
315+
}
316+
317+
// IsValidAnnotationType checks if the annotation type is valid.
318+
func IsValidAnnotationType(t AnnotationType) bool {
319+
switch t {
320+
case AnnotationTypeSecurity, AnnotationTypePerformance, AnnotationTypeDeprecated,
321+
AnnotationTypeInfo, AnnotationTypeWarning, AnnotationTypeError:
322+
return true
323+
}
324+
return false
325+
}

0 commit comments

Comments
 (0)