G V-8 (A-3): the finding writer is generic over the contract's body types and works on their wire form

Writer[F, C, S, A any] marshals a body, reads and sets kind, scope, id, subject, at, since and
observer by their contract names; the interfaces FindingBody, ClearedBody, StatedBody, AskedBody
and the constructors go. A body whose wire form lacks a field the contract names is refused when
the writer is made. views.CheckFinding(any) judges the wire form. WriterFindings takes only the
writer.

Builds: design 47 G §686, §640, §687, §689, A-3 (.work/47-G/dev2-ledger.md)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 21:38:04 +01:00
parent bdb3814e1d
commit adb0acdfae
5 changed files with 268 additions and 289 deletions
+31 -23
View File
@@ -619,43 +619,51 @@ func (r *Reader) Tools(prefix string) []stdio.Tool {
// FindingScope is the scope of a views reader's findings: they are findings of the part's module (design 47 G §687).
const FindingScope = "module"
// WriterFindings writes a views reader's findings through the part's mesh-sdk writer, as kinds of the reader's own
// (design 47 G §639, §580, §687): the Findings of a reader, never a writer of its own. mesh-sdk lays each finding out
// through the body's setters, and the part supplies only New, the generated contract's constructor of a finding body:
// `kind` the finding's, `scope` module, `id` the finding's id escaped as a key's name is, `severity` warning but urgent
// for view-too-large, `source` views, `subject` the part's module on its node, `summary` and `headline` the finding's
// texts. The writer's statement covers the reader's open findings beside its observe's.
type WriterFindings struct {
Writer *Writer
New func() FindingBody
// wireWriter is the part of a Writer[F, C, S, A] a views reader's findings use, whatever the contract's body types.
type wireWriter interface {
WriteWire(ctx context.Context, finding map[string]any) error
Clear(ctx context.Context, scope, id, kind, why string) error
ModuleNode() (module, node string)
}
func (o WriterFindings) body(f Finding) FindingBody {
b := o.New()
b.SetKind(f.Kind)
b.SetScope(FindingScope)
b.SetID(keys.EscapeName(f.ID))
b.SetSeverity("warning")
// WriterFindings writes a views reader's findings through the part's mesh-sdk writer, as kinds of the reader's own
// (design 47 G §639, §580, §687): the Findings of a reader, never a writer of its own. mesh-sdk lays each finding out on
// its wire form: `kind` the finding's, `scope` module, `id` the finding's id escaped as a key's name is, `severity`
// warning but urgent for view-too-large, `source` views, `subject` the part's module on its node, `summary` and
// `headline` the finding's texts. The writer's statement covers the reader's open findings beside its observe's. Writer
// is the part's *Writer[F, C, S, A].
type WriterFindings struct {
Writer wireWriter
}
func (o WriterFindings) body(f Finding) map[string]any {
module, node := o.Writer.ModuleNode()
sev := "warning"
if f.Kind == TooLargeKind {
b.SetSeverity("urgent")
sev = "urgent"
}
subject := map[string]any{"scope": FindingScope, "id": module}
if node != "" {
subject["machine"] = node
}
b := map[string]any{"kind": f.Kind, "scope": FindingScope, "id": keys.EscapeName(f.ID), "severity": sev, "source": "views",
"subject": subject, "summary": f.Summary}
if f.Headline != "" {
b["headline"] = f.Headline
}
b.SetSource("views")
b.SetSubject(nil, o.Writer.cfg.Module, o.Writer.cfg.Node, FindingScope)
b.SetSummary(f.Summary)
b.SetHeadline(f.Headline)
if !f.At.IsZero() {
b.SetAt(f.At)
b["at"] = f.At
}
return b
}
// Put writes one finding.
func (o WriterFindings) Put(f Finding) error {
return o.Writer.Write(context.Background(), o.body(f))
return o.Writer.WriteWire(context.Background(), o.body(f))
}
// Delete clears one finding.
func (o WriterFindings) Delete(f Finding) error {
b := o.body(f)
return o.Writer.Clear(context.Background(), b.Scope(), b.ID(), b.Kind(), "the part no longer observes it")
return o.Writer.Clear(context.Background(), FindingScope, b["id"].(string), f.Kind, "the part no longer observes it")
}