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:
@@ -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...)
|
||||
|
||||
Reference in New Issue
Block a user