refactor: Organize Issue struct with section comments (bd-5l59)
Group 50+ fields into 15 logical sections with clear separators: - Core Identification (ID, ContentHash) - Issue Content (Title, Description, Design, AcceptanceCriteria, Notes) - Status & Workflow (Status, Priority, IssueType) - Assignment (Assignee, EstimatedMinutes) - Timestamps (CreatedAt, CreatedBy, UpdatedAt, ClosedAt, CloseReason) - External Integration (ExternalRef) - Compaction Metadata - Internal Routing (not exported) - Relational Data (Labels, Dependencies, Comments) - Tombstone Fields (soft-delete) - Messaging Fields (inter-agent communication) - Context Markers (Pinned, IsTemplate) - Bonding Fields (compound molecule lineage) - HOP Fields (entity tracking) - Gate Fields (async coordination) - Source Tracing Fields - Agent Identity Fields All tests pass, JSON serialization unchanged. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,77 +9,94 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Issue represents a trackable work item
|
// Issue represents a trackable work item.
|
||||||
|
// Fields are organized into logical groups for maintainability.
|
||||||
type Issue struct {
|
type Issue struct {
|
||||||
ID string `json:"id"`
|
// ===== Core Identification =====
|
||||||
ContentHash string `json:"-"` // Internal: SHA256 hash of canonical content (excludes ID, timestamps) - NOT exported to JSONL
|
ID string `json:"id"`
|
||||||
Title string `json:"title"`
|
ContentHash string `json:"-"` // Internal: SHA256 of canonical content - NOT exported to JSONL
|
||||||
Description string `json:"description,omitempty"`
|
|
||||||
Design string `json:"design,omitempty"`
|
|
||||||
AcceptanceCriteria string `json:"acceptance_criteria,omitempty"`
|
|
||||||
Notes string `json:"notes,omitempty"`
|
|
||||||
Status Status `json:"status,omitempty"`
|
|
||||||
Priority int `json:"priority"` // No omitempty: 0 is valid (P0/critical)
|
|
||||||
IssueType IssueType `json:"issue_type,omitempty"`
|
|
||||||
Assignee string `json:"assignee,omitempty"`
|
|
||||||
EstimatedMinutes *int `json:"estimated_minutes,omitempty"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
CreatedBy string `json:"created_by,omitempty"` // Who created this issue (GH#748)
|
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
ClosedAt *time.Time `json:"closed_at,omitempty"`
|
|
||||||
CloseReason string `json:"close_reason,omitempty"` // Reason provided when closing the issue
|
|
||||||
ExternalRef *string `json:"external_ref,omitempty"` // e.g., "gh-9", "jira-ABC"
|
|
||||||
CompactionLevel int `json:"compaction_level,omitempty"`
|
|
||||||
CompactedAt *time.Time `json:"compacted_at,omitempty"`
|
|
||||||
CompactedAtCommit *string `json:"compacted_at_commit,omitempty"` // Git commit hash when compacted
|
|
||||||
OriginalSize int `json:"original_size,omitempty"`
|
|
||||||
SourceRepo string `json:"-"` // Internal: Which repo owns this issue (multi-repo support) - NOT exported to JSONL
|
|
||||||
IDPrefix string `json:"-"` // Internal: Override prefix for ID generation - NOT exported to JSONL
|
|
||||||
Labels []string `json:"labels,omitempty"` // Populated only for export/import
|
|
||||||
Dependencies []*Dependency `json:"dependencies,omitempty"` // Populated only for export/import
|
|
||||||
Comments []*Comment `json:"comments,omitempty"` // Populated only for export/import
|
|
||||||
// Tombstone fields: inline soft-delete support
|
|
||||||
DeletedAt *time.Time `json:"deleted_at,omitempty"` // When the issue was deleted
|
|
||||||
DeletedBy string `json:"deleted_by,omitempty"` // Who deleted the issue
|
|
||||||
DeleteReason string `json:"delete_reason,omitempty"` // Why the issue was deleted
|
|
||||||
OriginalType string `json:"original_type,omitempty"` // Issue type before deletion (for tombstones)
|
|
||||||
|
|
||||||
// Messaging fields: inter-agent communication support
|
// ===== Issue Content =====
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Design string `json:"design,omitempty"`
|
||||||
|
AcceptanceCriteria string `json:"acceptance_criteria,omitempty"`
|
||||||
|
Notes string `json:"notes,omitempty"`
|
||||||
|
|
||||||
|
// ===== Status & Workflow =====
|
||||||
|
Status Status `json:"status,omitempty"`
|
||||||
|
Priority int `json:"priority"` // No omitempty: 0 is valid (P0/critical)
|
||||||
|
IssueType IssueType `json:"issue_type,omitempty"`
|
||||||
|
|
||||||
|
// ===== Assignment =====
|
||||||
|
Assignee string `json:"assignee,omitempty"`
|
||||||
|
EstimatedMinutes *int `json:"estimated_minutes,omitempty"`
|
||||||
|
|
||||||
|
// ===== Timestamps =====
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
CreatedBy string `json:"created_by,omitempty"` // Who created this issue (GH#748)
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
ClosedAt *time.Time `json:"closed_at,omitempty"`
|
||||||
|
CloseReason string `json:"close_reason,omitempty"` // Reason provided when closing
|
||||||
|
|
||||||
|
// ===== External Integration =====
|
||||||
|
ExternalRef *string `json:"external_ref,omitempty"` // e.g., "gh-9", "jira-ABC"
|
||||||
|
|
||||||
|
// ===== Compaction Metadata =====
|
||||||
|
CompactionLevel int `json:"compaction_level,omitempty"`
|
||||||
|
CompactedAt *time.Time `json:"compacted_at,omitempty"`
|
||||||
|
CompactedAtCommit *string `json:"compacted_at_commit,omitempty"` // Git commit hash when compacted
|
||||||
|
OriginalSize int `json:"original_size,omitempty"`
|
||||||
|
|
||||||
|
// ===== Internal Routing (not exported to JSONL) =====
|
||||||
|
SourceRepo string `json:"-"` // Which repo owns this issue (multi-repo support)
|
||||||
|
IDPrefix string `json:"-"` // Override prefix for ID generation
|
||||||
|
|
||||||
|
// ===== Relational Data (populated for export/import) =====
|
||||||
|
Labels []string `json:"labels,omitempty"`
|
||||||
|
Dependencies []*Dependency `json:"dependencies,omitempty"`
|
||||||
|
Comments []*Comment `json:"comments,omitempty"`
|
||||||
|
|
||||||
|
// ===== Tombstone Fields (soft-delete support) =====
|
||||||
|
DeletedAt *time.Time `json:"deleted_at,omitempty"` // When deleted
|
||||||
|
DeletedBy string `json:"deleted_by,omitempty"` // Who deleted
|
||||||
|
DeleteReason string `json:"delete_reason,omitempty"` // Why deleted
|
||||||
|
OriginalType string `json:"original_type,omitempty"` // Issue type before deletion
|
||||||
|
|
||||||
|
// ===== Messaging Fields (inter-agent communication) =====
|
||||||
Sender string `json:"sender,omitempty"` // Who sent this (for messages)
|
Sender string `json:"sender,omitempty"` // Who sent this (for messages)
|
||||||
Ephemeral bool `json:"ephemeral,omitempty"` // If true, not exported to JSONL; bulk-deleted when closed
|
Ephemeral bool `json:"ephemeral,omitempty"` // If true, not exported to JSONL
|
||||||
// NOTE: RepliesTo, RelatesTo, DuplicateOf, SupersededBy moved to dependencies table
|
// NOTE: RepliesTo, RelatesTo, DuplicateOf, SupersededBy moved to dependencies table
|
||||||
// per Decision 004 (Edge Schema Consolidation). Use dependency API instead.
|
// per Decision 004 (Edge Schema Consolidation). Use dependency API instead.
|
||||||
|
|
||||||
// Pinned field: persistent context markers
|
// ===== Context Markers =====
|
||||||
Pinned bool `json:"pinned,omitempty"` // If true, issue is a persistent context marker, not a work item
|
Pinned bool `json:"pinned,omitempty"` // Persistent context marker, not a work item
|
||||||
|
IsTemplate bool `json:"is_template,omitempty"` // Read-only template molecule
|
||||||
|
|
||||||
// Template field: template molecule support
|
// ===== Bonding Fields (compound molecule lineage) =====
|
||||||
IsTemplate bool `json:"is_template,omitempty"` // If true, issue is a read-only template molecule
|
|
||||||
|
|
||||||
// Bonding fields: compound molecule lineage
|
|
||||||
BondedFrom []BondRef `json:"bonded_from,omitempty"` // For compounds: constituent protos
|
BondedFrom []BondRef `json:"bonded_from,omitempty"` // For compounds: constituent protos
|
||||||
|
|
||||||
// HOP fields: entity tracking for CV chains
|
// ===== HOP Fields (entity tracking for CV chains) =====
|
||||||
Creator *EntityRef `json:"creator,omitempty"` // Who created this issue (human, agent, or org)
|
Creator *EntityRef `json:"creator,omitempty"` // Who created (human, agent, or org)
|
||||||
Validations []Validation `json:"validations,omitempty"` // Who validated/approved this work
|
Validations []Validation `json:"validations,omitempty"` // Who validated/approved
|
||||||
|
|
||||||
// Gate fields: async coordination primitives
|
// ===== Gate Fields (async coordination primitives) =====
|
||||||
AwaitType string `json:"await_type,omitempty"` // Condition type: gh:run, gh:pr, timer, human, mail
|
AwaitType string `json:"await_type,omitempty"` // Condition type: gh:run, gh:pr, timer, human, mail
|
||||||
AwaitID string `json:"await_id,omitempty"` // Condition identifier (e.g., run ID, PR number)
|
AwaitID string `json:"await_id,omitempty"` // Condition identifier (run ID, PR number, etc.)
|
||||||
Timeout time.Duration `json:"timeout,omitempty"` // Max wait time before escalation
|
Timeout time.Duration `json:"timeout,omitempty"` // Max wait time before escalation
|
||||||
Waiters []string `json:"waiters,omitempty"` // Mail addresses to notify when gate clears
|
Waiters []string `json:"waiters,omitempty"` // Mail addresses to notify when gate clears
|
||||||
|
|
||||||
// Source tracing fields: track where this issue came from during cooking
|
// ===== Source Tracing Fields (formula cooking origin) =====
|
||||||
SourceFormula string `json:"source_formula,omitempty"` // Formula name where this step was defined
|
SourceFormula string `json:"source_formula,omitempty"` // Formula name where step was defined
|
||||||
SourceLocation string `json:"source_location,omitempty"` // Path within source: "steps[0]", "advice[0].after"
|
SourceLocation string `json:"source_location,omitempty"` // Path: "steps[0]", "advice[0].after"
|
||||||
|
|
||||||
// Agent identity fields: agent-as-bead support
|
// ===== Agent Identity Fields (agent-as-bead support) =====
|
||||||
HookBead string `json:"hook_bead,omitempty"` // Current work attached to agent's hook (0..1)
|
HookBead string `json:"hook_bead,omitempty"` // Current work on agent's hook (0..1)
|
||||||
RoleBead string `json:"role_bead,omitempty"` // Role definition bead (required for agents)
|
RoleBead string `json:"role_bead,omitempty"` // Role definition bead (required for agents)
|
||||||
AgentState AgentState `json:"agent_state,omitempty"` // Agent-reported state (idle|running|stuck|stopped)
|
AgentState AgentState `json:"agent_state,omitempty"` // Agent state: idle|running|stuck|stopped
|
||||||
LastActivity *time.Time `json:"last_activity,omitempty"` // Updated on each agent action (for timeout detection)
|
LastActivity *time.Time `json:"last_activity,omitempty"` // Updated on each action (timeout detection)
|
||||||
RoleType string `json:"role_type,omitempty"` // Agent role: polecat|crew|witness|refinery|mayor|deacon
|
RoleType string `json:"role_type,omitempty"` // Role: polecat|crew|witness|refinery|mayor|deacon
|
||||||
Rig string `json:"rig,omitempty"` // Rig name (empty for town-level agents like mayor/deacon)
|
Rig string `json:"rig,omitempty"` // Rig name (empty for town-level agents)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComputeContentHash creates a deterministic hash of the issue's content.
|
// ComputeContentHash creates a deterministic hash of the issue's content.
|
||||||
|
|||||||
Reference in New Issue
Block a user