; lib/agentic/schema.sx — agentic-sx Phase 1: the object types. ; An agentic structure IS the open-branch set of a repo: one branch = one ; agent, seeded by a briefing. All objects are plain SX dicts, typed by ; :type, content-addressed via sx-git's native CID (git/cid, git/write) — ; same store, same identity rules as blob/tree/commit/tag. ; ; Two families: ; object types — standalone: briefing, console-trace, behaviour (TAG only, ; library HELD Phase 8). :type carries the type name. ; commit kinds — agent-commit (extensible base) + subtypes spawn/finding/ ; refactor/test/session-merge/decision. These ARE git ; commits (:type "commit") so the whole DAG/branch/merge ; machinery applies; the kind rides in :agent-type and ; participates in the CID like any extra commit field. ; ; Full fed-sx DefineType/SubtypeOf + federation is HELD (Phase 7) — this ; registry declares the tags and the subtype relation locally. ; Requires: lib/git/object.sx (and its persist/artdag deps). ; ---- type registry ---- (define agentic/types {:refactor {:parent "agent-commit" :kind "commit" :doc "behaviour-preserving restructure"} :console-trace {:parent nil :kind "object" :doc "console/tool output attached to a commit by cid"} :test {:parent "agent-commit" :kind "commit" :doc "adds or repairs tests"} :spawn {:parent "agent-commit" :kind "commit" :doc "genesis commit seeding an agent branch from a briefing"} :finding {:parent "agent-commit" :kind "commit" :doc "a discovered fact worth recording"} :briefing {:parent nil :kind "object" :doc "branch genesis — why an agent exists"} :decision {:parent "agent-commit" :kind "commit" :doc "records a choice and its rationale"} :session-merge {:parent "agent-commit" :kind "commit" :doc "merges another agent session's branch"} :agent-commit {:parent nil :kind "commit" :doc "extensible base for typed agent commits"} :behaviour {:parent nil :kind "object" :doc "behaviour TAG only — library HELD (Phase 8)"}}) (define agentic/type? (fn (name) (and (string? name) (has-key? agentic/types name)))) (define agentic/type-info (fn (name) (if (agentic/type? name) (get agentic/types name) nil))) (define agentic/type-parent (fn (name) (let ((info (agentic/type-info name))) (if (dict? info) (get info :parent) nil)))) (define agentic/type-kind (fn (name) (let ((info (agentic/type-info name))) (if (dict? info) (get info :kind) nil)))) ; reflexive + transitive subtype walk, bounded against registry cycles (define agentic/is-a-n? (fn (name ancestor depth) (cond ((<= depth 0) false) ((not (agentic/type? name)) false) ((= name ancestor) true) (else (let ((p (agentic/type-parent name))) (if (nil? p) false (agentic/is-a-n? p ancestor (- depth 1)))))))) (define agentic/is-a? (fn (name ancestor) (agentic/is-a-n? name ancestor 10))) ; extend the registry (downstream: sx-gitea review kinds, behaviour library). ; create-only; parent must exist when given. => name | nil (define agentic/register-type! (fn (name parent kind doc) (if (and (string? name) (not (agentic/type? name)) (or (nil? parent) (agentic/type? parent))) (begin (set! agentic/types (assoc agentic/types name {:parent parent :kind kind :doc doc})) name) nil))) (define agentic/commit-kind? (fn (kind) (and (agentic/type? kind) (= (agentic/type-kind kind) "commit") (agentic/is-a? kind "agent-commit")))) ; all registered commit kinds (incl. the base), sorted (define agentic/commit-kinds (fn () (sort (filter (fn (n) (agentic/commit-kind? n)) (keys agentic/types))))) ; ---- briefing — branch genesis / "why" ---- (define agentic/briefing (fn (title goal meta) (merge meta {:type "briefing" :title title :goal goal}))) (define agentic/briefing? (fn (obj) (and (dict? obj) (= (get obj :type) "briefing")))) (define agentic/briefing-title (fn (obj) (get obj :title))) (define agentic/briefing-goal (fn (obj) (get obj :goal))) ; ---- agent-commit — a git commit carrying an agentic kind ---- ; kind must be a registered commit kind; :agent-type is protected, all other ; meta is open (:briefing :agent :message :behaviour-cid ... round-trip and ; participate in the CID). => commit dict | nil on unknown kind (define agentic/agent-commit (fn (tree-cid parents kind meta) (if (agentic/commit-kind? kind) (git/commit tree-cid parents (merge meta {:agent-type kind})) nil))) (define agentic/commit-kind (fn (obj) (if (dict? obj) (get obj :agent-type) nil))) (define agentic/agent-commit? (fn (obj) (and (git/commit? obj) (agentic/commit-kind? (agentic/commit-kind obj))))) ; is obj an agent-commit of (a subtype of) kind? (define agentic/kind-of? (fn (obj kind) (and (agentic/agent-commit? obj) (agentic/is-a? (agentic/commit-kind obj) kind)))) (define agentic/commit-briefing (fn (obj) (get obj :briefing))) (define agentic/commit-agent (fn (obj) (get obj :agent))) (define agentic/commit-behaviour (fn (obj) (get obj :behaviour-cid))) ; ---- console-trace — attached to a commit by cid (binding is Phase 3) ---- (define agentic/trace-entry (fn (kind text) {:text text :kind kind})) (define agentic/console-trace (fn (entries meta) (merge meta {:type "console-trace" :entries entries}))) (define agentic/console-trace? (fn (obj) (and (dict? obj) (= (get obj :type) "console-trace")))) (define agentic/trace-entries (fn (obj) (get obj :entries))) ; ---- behaviour — TAG declared, library HELD (Phase 8) ---- (define agentic/behaviour (fn (name body meta) (merge meta {:name name :type "behaviour" :body body}))) (define agentic/behaviour? (fn (obj) (and (dict? obj) (= (get obj :type) "behaviour"))))