CAT-K4: a record is written in a draft, one section a call: open, write, remove, order, submit, drop, take-over

A draft is a key of the state drafts (author, fields, sections as title, digest and the sequence of their write-section);
write puts the text into the record's history at once, submit makes the draft a version through the rules propose is
judged by and writes no section again. Only the author writes; take-over hands a draft, a proposal or a reserved number
to the caller with the reason in the next version's message. A new version of an effort starts from the served sections
and keeps its title, date and deciders (the rows of the commit folded in, now run over the ledger too). A tool call is
named to the ledger so the runtime stamps the caller it proved.

Issue 1966.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 11:52:53 +01:00
parent 285099a940
commit 17ba95bca6
9 changed files with 1066 additions and 114 deletions
@@ -90,11 +90,14 @@ type ledgerStore struct {
heads map[Key]*headState
texts map[string]string
scanned bool
// drafted are the sections written for a draft and named by no version yet: a version that carries one reuses its
// write-section and writes none again.
drafted map[Key][]sectionRef
}
// newLedgerStore is the store over a pipe and the module's states.
func newLedgerStore(p Pipe, s States) *ledgerStore {
return &ledgerStore{pipe: p, states: s, heads: map[Key]*headState{}, texts: map[string]string{}}
return &ledgerStore{pipe: p, states: s, heads: map[Key]*headState{}, texts: map[string]string{}, drafted: map[Key][]sectionRef{}}
}
// stripped is r as a stored record naming its sections by ref: the refs of the sections already written are kept, the
@@ -341,7 +344,7 @@ func (s *ledgerStore) Create(ctx context.Context, v Version) error {
return ErrExists
}
v.N = 1
refs, err := s.write(ctx, k, v.Record, nil)
refs, err := s.write(ctx, k, v.Record, s.drafted[k])
if err != nil {
return err
}
@@ -360,9 +363,56 @@ func (s *ledgerStore) commit(ctx context.Context, k Key, op string, e *entryHead
return err
}
s.heads[k] = &headState{Kind: k.Kind, Number: k.Number, Entry: e, Sequence: seq}
delete(s.drafted, k)
return nil
}
// WriteSection appends a write-section of the record (SectionWriter): a draft's text is in the history at once.
func (s *ledgerStore) WriteSection(ctx context.Context, k Key, title, text string) (sectionRef, error) {
s.mu.Lock()
defer s.mu.Unlock()
if len(text) > MostSectionBytes {
return sectionRef{}, fmt.Errorf("the section %q is %d bytes; a section holds at most %d: split it", title, len(text), MostSectionBytes)
}
d := SectionDigest(text)
seq, err := s.apply(ctx, k, OpWriteSection, map[string]any{"title": title, "text": text, "digest": d})
if err != nil {
return sectionRef{}, err
}
s.texts[d] = text
ref := sectionRef{Name: title, Digest: d, Sequence: seq}
s.drafted[k] = append(s.drafted[k], ref)
return ref, nil
}
// SectionText is the text a ref names (SectionWriter).
func (s *ledgerStore) SectionText(_ context.Context, k Key, ref sectionRef) (string, error) {
s.mu.Lock()
defer s.mu.Unlock()
return s.text(ref, k)
}
// Working is the refs of the version a writer works on (SectionWriter).
func (s *ledgerStore) Working(_ context.Context, k Key) ([]sectionRef, error) {
s.mu.Lock()
defer s.mu.Unlock()
h, err := s.fresh(k)
if err != nil || h == nil {
return nil, err
}
if h.Entry.Pending != nil {
return append([]sectionRef(nil), h.Entry.Pending.Sections...), nil
}
return append([]sectionRef(nil), h.Entry.Current.Sections...), nil
}
// Known tells the store sections already written for a draft, after a restart (SectionWriter).
func (s *ledgerStore) Known(k Key, refs []sectionRef) {
s.mu.Lock()
defer s.mu.Unlock()
s.drafted[k] = append([]sectionRef(nil), refs...)
}
func (s *ledgerStore) Save(ctx context.Context, v Version, current, clearPending bool, revision int64) error {
s.mu.Lock()
defer s.mu.Unlock()
@@ -381,7 +431,7 @@ func (s *ledgerStore) Save(ctx context.Context, v Version, current, clearPending
if err != nil {
return err
}
var known []sectionRef
known := append([]sectionRef(nil), s.drafted[k]...)
for _, sr := range []*storedRecord{h.Entry.Current, h.Entry.Pending} {
if sr != nil {
known = append(known, sr.Sections...)