Replay explanations through shared history selections

This commit is contained in:
2026-10-26 17:01:32 +00:00
parent 4b4e15fc58
commit 738c8a9cc7
12 changed files with 386 additions and 135 deletions

View File

@@ -19,12 +19,14 @@ const (
// historySourcePayload keeps source values and replacement facts under the
// shared model's ownership. Application documents remain shared when immutable.
type historySourcePayload struct {
kind historySourcePayloadKind
application historyApplication
overlay overlayRecord
path Path
origin Origin
contributions []historyPayloadRef
kind historySourcePayloadKind
application historyApplication
overlay overlayRecord
applicationRef historyPayloadRef
hasApplicationRef bool
path Path
origin Origin
contributions []historyPayloadRef
}
func (builder *historyBuilder) observeBaseline(root *document.Node) {
@@ -53,11 +55,22 @@ func (builder *historyBuilder) observeSourceEvidence(root *document.Node, origin
if len(applications) == 0 && len(records) == 0 {
return
}
applicationsBySource := make(map[string]historyPayloadRef)
applicationsByLayer := make(map[Layer][]historyPayloadRef)
for index := range applications {
application := applications[index]
payload := builder.addSourcePayload(&application, nil)
applicationsByLayer[application.layer] = append(applicationsByLayer[application.layer], payload)
walkHistoryApplication(application, func(_, effective Path, node *document.Node) {
if node.Location.SourceID != "" {
applicationsBySource[node.Location.SourceID] = payload
}
origin := sourceApplicationOrigin(application, node)
for _, location := range origin.Locations {
if location.SourceID != "" {
applicationsBySource[location.SourceID] = payload
}
}
attribution := builder.addAttribution(origin, nil, nil)
builder.addObservation(historyObservation{
path: effective, phase: historyPhaseSources, payload: payload,
@@ -70,6 +83,12 @@ func (builder *historyBuilder) observeSourceEvidence(root *document.Node, origin
for index := range records {
record := records[index]
payload := builder.addSourcePayload(nil, &record)
applicationRef, hasApplication := sourceApplicationForRecord(record, applicationsBySource, applicationsByLayer)
if hasApplication {
owned := &builder.model.sourcePayloads[payload.id]
owned.applicationRef = applicationRef
owned.hasApplicationRef = true
}
for displacedIndex, displaced := range record.displaced {
definitionPayload := payload
definitionPayload.substep = displacedIndex + 1
@@ -119,6 +138,19 @@ func (builder *historyBuilder) observeSourceEvidence(root *document.Node, origin
})
}
func sourceApplicationForRecord(record overlayRecord, bySource map[string]historyPayloadRef, byLayer map[Layer][]historyPayloadRef) (historyPayloadRef, bool) {
for _, location := range record.change.Origin.Locations {
if reference, found := bySource[location.SourceID]; found && location.SourceID != "" {
return reference, true
}
}
applications := byLayer[record.change.Origin.Layer]
if len(applications) == 1 {
return applications[0], true
}
return historyPayloadRef{}, false
}
func (builder *historyBuilder) addSourcePayload(application *historyApplication, overlay *overlayRecord) historyPayloadRef {
payload := builder.nextPayload(historyPhaseSources)
if payload.id != len(builder.model.sourcePayloads) {