Complete bd-95: Add content-addressable identity (ContentHash field)

This commit is contained in:
Steve Yegge
2025-10-28 18:57:16 -07:00
parent ad267b5de6
commit d9eb273e15
10 changed files with 287 additions and 45 deletions

View File

@@ -2,6 +2,7 @@
package types
import (
"crypto/sha256"
"fmt"
"time"
)
@@ -9,6 +10,7 @@ import (
// Issue represents a trackable work item
type Issue struct {
ID string `json:"id"`
ContentHash string `json:"content_hash,omitempty"` // SHA256 hash of canonical content (excludes ID, timestamps)
Title string `json:"title"`
Description string `json:"description"`
Design string `json:"design,omitempty"`
@@ -32,6 +34,39 @@ type Issue struct {
Comments []*Comment `json:"comments,omitempty"` // Populated only for export/import
}
// ComputeContentHash creates a deterministic hash of the issue's content.
// Uses all substantive fields (excluding ID, timestamps, and compaction metadata)
// to ensure that identical content produces identical hashes across all clones.
func (i *Issue) ComputeContentHash() string {
h := sha256.New()
// Hash all substantive fields in a stable order
h.Write([]byte(i.Title))
h.Write([]byte{0}) // separator
h.Write([]byte(i.Description))
h.Write([]byte{0})
h.Write([]byte(i.Design))
h.Write([]byte{0})
h.Write([]byte(i.AcceptanceCriteria))
h.Write([]byte{0})
h.Write([]byte(i.Notes))
h.Write([]byte{0})
h.Write([]byte(i.Status))
h.Write([]byte{0})
h.Write([]byte(fmt.Sprintf("%d", i.Priority)))
h.Write([]byte{0})
h.Write([]byte(i.IssueType))
h.Write([]byte{0})
h.Write([]byte(i.Assignee))
h.Write([]byte{0})
if i.ExternalRef != nil {
h.Write([]byte(*i.ExternalRef))
}
return fmt.Sprintf("%x", h.Sum(nil))
}
// Validate checks if the issue has valid field values
func (i *Issue) Validate() error {
if len(i.Title) == 0 {