Per-agent buffer = persist append-only log stream + kv drain cursor; commit-with-trace! drains everything-since-last-commit into a console-trace object and binds it git-note style (ref notes/trace/<commit-cid> -> trace cid). Trace never enters the commit tree; binding is a re-bindable ref layer over immutable objects; failed commits keep the buffer; plain commit! leaves binding to the agent. 35/35 (153/153 total). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
136 lines
4.1 KiB
Plaintext
136 lines
4.1 KiB
Plaintext
; lib/agentic/trace.sx — agentic-sx Phase 3: console traces as ATTACHED
|
|
; content-addressed objects. An agent's console/tool output accumulates in a
|
|
; per-agent append-only persist log stream; the commit verb drains everything
|
|
; since the last commit into a console-trace object and binds it to the new
|
|
; commit git-note style: ref "notes/trace/<commit-cid>" -> trace cid. The
|
|
; trace is NOT in the commit's tree — attaching never changes the commit cid,
|
|
; and the note is a re-bindable ref layer over immutable objects.
|
|
; Granularity = the commit, agent-chosen: whatever was logged since the last
|
|
; drain travels with the next commit.
|
|
; Requires: lib/agentic/branch.sx (and its deps).
|
|
|
|
; ---- buffer stream + drain cursor (namespaced under the repo prefix) ----
|
|
(define
|
|
agentic/trace-stream
|
|
(fn
|
|
(sp agent)
|
|
(str (get (agentic/space-repo sp) :prefix) "/trace/" agent)))
|
|
|
|
(define
|
|
agentic/trace-cursor-key
|
|
(fn
|
|
(sp agent)
|
|
(str (get (agentic/space-repo sp) :prefix) "/trace-cursor/" agent)))
|
|
|
|
; append one console/tool entry to the agent's buffer => true
|
|
(define
|
|
agentic/trace!
|
|
(fn
|
|
(sp agent kind text)
|
|
(begin
|
|
(persist/append
|
|
(git/repo-db (agentic/space-repo sp))
|
|
(agentic/trace-stream sp agent)
|
|
"trace-entry"
|
|
0
|
|
(agentic/trace-entry kind text))
|
|
true)))
|
|
|
|
; entries logged since the last drain, oldest first
|
|
(define
|
|
agentic/trace-pending
|
|
(fn
|
|
(sp agent)
|
|
(let
|
|
((db (git/repo-db (agentic/space-repo sp))))
|
|
(let
|
|
((cur (persist/kv-get db (agentic/trace-cursor-key sp agent))))
|
|
(map
|
|
(fn (e) (persist/event-data e))
|
|
(persist/read-from
|
|
db
|
|
(agentic/trace-stream sp agent)
|
|
(+ (if (nil? cur) 0 cur) 1)))))))
|
|
|
|
; advance the drain cursor to the stream's high-water mark
|
|
(define
|
|
agentic/trace-mark!
|
|
(fn
|
|
(sp agent)
|
|
(let
|
|
((db (git/repo-db (agentic/space-repo sp))))
|
|
(begin
|
|
(persist/kv-put
|
|
db
|
|
(agentic/trace-cursor-key sp agent)
|
|
(persist/last-seq db (agentic/trace-stream sp agent)))
|
|
true))))
|
|
|
|
; ---- git-note-style binding: commit cid -> trace cid ----
|
|
(define
|
|
agentic/trace-note-ref
|
|
(fn (commit-cid) (str "notes/trace/" commit-cid)))
|
|
|
|
; write the trace object and bind it to the commit => trace cid | {:error}
|
|
(define
|
|
agentic/attach-trace!
|
|
(fn
|
|
(sp commit-cid trace-obj)
|
|
(let
|
|
((repo (agentic/space-repo sp)))
|
|
(if
|
|
(not (agentic/console-trace? trace-obj))
|
|
{:error "not-a-console-trace"}
|
|
(let
|
|
((tcid (git/write repo trace-obj)))
|
|
(begin
|
|
(git/ref-set! repo (agentic/trace-note-ref commit-cid) tcid)
|
|
tcid))))))
|
|
|
|
(define
|
|
agentic/trace-cid-for
|
|
(fn
|
|
(sp commit-cid)
|
|
(git/ref-get (agentic/space-repo sp) (agentic/trace-note-ref commit-cid))))
|
|
|
|
(define
|
|
agentic/trace-for
|
|
(fn
|
|
(sp commit-cid)
|
|
(let
|
|
((tcid (agentic/trace-cid-for sp commit-cid)))
|
|
(if (nil? tcid) nil (git/read (agentic/space-repo sp) tcid)))))
|
|
|
|
; ---- the commit verb with trace binding ----
|
|
; commit! then drain the buffer into an attached console-trace.
|
|
; => {:cid cid :trace tcid} | {:cid cid} when nothing was logged
|
|
; | commit!'s {:error ...}/{:conflict ...} passthrough (buffer kept)
|
|
(define
|
|
agentic/commit-with-trace!
|
|
(fn
|
|
(sp agent kind files meta)
|
|
(let
|
|
((cid (agentic/commit! sp agent kind files meta)))
|
|
(if
|
|
(dict? cid)
|
|
cid
|
|
(let
|
|
((entries (agentic/trace-pending sp agent)))
|
|
(if
|
|
(= (len entries) 0)
|
|
{:cid cid}
|
|
(let
|
|
((tcid (agentic/attach-trace! sp cid (agentic/console-trace entries {:agent agent :commit cid}))))
|
|
(begin (agentic/trace-mark! sp agent) {:trace tcid :cid cid}))))))))
|
|
|
|
; (commit-cid trace-cid) pairs for the agent's session, newest first,
|
|
; commits without a bound trace omitted
|
|
(define
|
|
agentic/session-traces
|
|
(fn
|
|
(sp agent)
|
|
(filter
|
|
(fn (p) (not (nil? (nth p 1))))
|
|
(map
|
|
(fn (cid) (list cid (agentic/trace-cid-for sp cid)))
|
|
(agentic/session-log sp agent))))) |