clay

Timeline
Login
Hosted by Hypnotoad
www.etoyoc.com
— Etoyoc Industries on Etsy
— Support this project: Buy some merch

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

50 most recent check-ins

2026-09-29
09:57
Tweak to the Dziwak schema to support the new module verse. Added a new module satyricon. This module is a harness for story telling. It uses context manipulation and history management to allow an LLM to tell a story a passage at time and maintain a particular style, elaborate story beats, and continue the flow of a work across passages. Added "verse". This module is a way of maintaining lore and contuity across several projects with the concept of a federated knowledge base. Universe specific details are maintained in a central sqlite database. Project specific details are maintained in a local sqlite database. This project builds on the schema and methodology of dziwak. Leaf check-in: b46471664a user: hypnotoad tags: mudpuppy-apps
2026-09-22
14:39
Updates to clay-epic check-in: c060d8a37d user: hypnotoad tags: mudpuppy-apps
2026-08-31
16:28
Add tested Clay Epic story model check-in: 8de9deb3ec user: hypnotoad tags: mudpuppy-apps
2026-08-30
19:45
clay-ui M2: thin canvas surface as clay-ui-tk 0.1 New module modules/clay-ui-tk — the retained canvas renderer, depending only on clay-ui-core, clay, clay-event and Tk. - surface.tcl: owns one principal canvas, the root stack, the component registry, focus chain and theme; schedules one coalesced idle pipeline pass (model→reconcile→measure→arrange→paint→focus→announce) through clay-event, plus a synchronous drain for tests and tools. Public API: model set/get, drain, action invoke, focus, component get, hit, transcript, diagnostics, destroy. Item creation applies the §5.6 ownership tags (clay-ui, surface:, component:, role:, state:, part:) and records every item; diagnostics reports orphans. - reconcile.tcl: ID/kind diffing — update in place, replace on kind change, create additions, dispose removals; action-group children are reconciled recursively; registry rebuilt from the live tree each pass so disposed ids are unreachable. - component.tcl + components.tcl: retained realization base with the create→update→measure→arrange→paint→dispose lifecycle, per-part owned items and data-only visual states (normal/hover/pressed/focused/ disabled — never class changes); stack/row containers, wrapped canvas text (heading levels, paragraph, notice with accent bar), the semantic action button with minimum target size, and a visible placeholder for kinds not yet realized (data-table, form, layer). - layout.tcl + theme.tcl: pure measure/arrange arithmetic and greedy wrap driven by a metrics delegate (headless mock included); Tk theme binds tokens to fonts/colors and classifies metric vs color change notifications. Input dispatch: pointer press/release, motion hover, Tab/Shift-Tab focus traversal over enabled actions, Return/Space activation; Escape is reserved for M3 blocking layers. Tests: 9 headless layout tests + 12 Tk integration tests (realization, tags/ownership/leak checks, reconciliation retain/replace, hit testing, pointer and keyboard dispatch, focus fallback, placeholder diagnostics, destruction with pending pipeline, resize reflow), plus an examples/ harness.tcl demo. Runtime matrix updated in modules/clay-ui/docs/ m0-lessons.md: MacPorts wish 8.6.18 is the reference Tk; wishkit 8.6.17 has a broken TKApplication tkProcessEvent: selector (never enter Tk_MainLoop; the suite ends with exit); event generate only delivers on mapped windows, so fixtures park their windows off-screen. M2 gate status: pointer and programmatic activation reach the same semantic action through one controller protocol with no private scheduler and no business logic on canvas ids. Cuneiform HTML leg deferred by the owner's ruling; transcript covers the full v1 vocabulary including kinds this renderer build still placeholders. check-in: dd4377d157 user: hypnotoad tags: mudpuppy-apps
17:03
clay-ui M1: headless semantic core as clay-ui-core 0.1 New module modules/clay-ui-core — the renderer-neutral semantic layer, no Tk anywhere. Sources in build/, 104 headless tests, docs in docs/. - node.tcl: one stable Clay node class with the Cuneiform-shape protocol (id/kind/property/content/child/parent/find/walk/path_to), fluent tag authoring with schema-checked kinds, and a lossless dub round trip. - schema.tcl: the versioned v1 vocabulary (screen, heading, paragraph, notice, data-table, form, action-group, action, navigation, announcement, layer) as data, with an enumerated-wildcard child grammar, strict unknown-field rejection, props for extension data, and kind_add/extend registration for trusted application kinds. - model.tcl: normalization to canonical dubs (dub canonical, dict accepted) plus relational rules — schema version, id uniqueness, focus/form/dismiss references, table cell keys, codec value normalization, active-layer invariants, and the submit-orphan rule. Errors carry semantic path, field, expected shape, message. - codec.tcl: text/integer/real/toggle/choice/multi codecs with the legacy four-verb pipeline (import/interpret/export/display) plus validate/normalize and an application registration registry. - action.tcl: request/result envelopes and the framework guard — unknown-action, blocked (blocking layer), disabled (with reason), stale (revision), validation (declared values only, readonly fields rejected, focus = first invalid field). - transcript.tcl: deterministic text renderer over the canonical model. - driver.tcl: headless driver (screen/sections/actions/focus/action/ submit/transcript/assert-visible/assert-enabled) guarding every action through the envelope and forwarding cleared requests to the <controller> delegate. - pipeline.tcl: ordered signal stages with implications, coalescing, explicit handler wiring, loud unhandled-stage errors; the owner schedules drains (clay-event), the pipeline only books work. - theme.tcl: semantic token registry with metric/color classification and theme_changed notifications for the invalidate rules. M1 exit gate: the cargo-grid/form/layer example validates, renders a deterministic transcript, and executes actions through one controller protocol (clay-ui-transcript.test, clay-ui-driver.test). Deviations from the proposal text, recorded in docs/: layout containers are renderer policy in v1 (no stack/row model kinds); the Cuneiform adapter is deferred to the next pass (node protocol is Cuneiform-shaped); disabled actions require disabledReason (stricter than 5.1, matching the game's truthfulness rules). check-in: d0468dd001 user: hypnotoad tags: mudpuppy-apps
15:47
clay-ui M0: freeze legacy 0.1 with characterization tests and archaeology record Track the generatorless clay-ui 0.1 amalgamation byte-stable as the frozen legacy package, add clay-ui-legacy.test (33 characterization tests covering load order, class inventory, the broken attach path, the manual mixinmap/mixin value pipelines, the form registration tables with their known quirks, widget_select resolution, and siground), and record the M0 findings in docs/legacy.md and docs/m0-lessons.md: - zero consumers of clay-ui 0.1 anywhere in the tree - undeclared clay dependency (package provide runs before ::clay::define) - ::clay::ui::form never initializes its ensemble dispatcher - element.attach cannot complete under clay 0.10.1 (namespace datatype: colon-key lookup misses; generated body dies reading ::regen) - select/select_keyvalue/enumerated/vector/number/percentage/siground quirks recorded as characterized behavior, not fixed - runtime matrix: Tcl 8.6 floor, Tk 8.6 target, Tcl 9 deferred check-in: f7c8f35fad user: hypnotoad tags: mudpuppy-apps
14:25
Shape clay-ui around Cuneiform node composition check-in: 3308dc67a7 user: hypnotoad tags: mudpuppy-apps
14:20
Ground clay-ui proposal in Clay event architecture check-in: 2859b37874 user: hypnotoad tags: mudpuppy-apps
14:00
Propose canvas-native clay-ui architecture check-in: dc8e00ce1b user: hypnotoad tags: mudpuppy-apps
13:49
Fixing a bug with dub Pathset check-in: 54c1941ad1 user: hypnotoad tags: mudpuppy-apps
2026-08-29
17:46
Removing generated files from the repository (again) check-in: dd2bb2dc97 user: hypnotoad tags: mudpuppy-apps
17:38
CLosing fork check-in: 03cbbf70c0 user: hypnotoad tags: mudpuppy-apps
17:31
Checkpoint remaining Clay and mudpuppy worktree changes check-in: 0128a8c0e6 user: hypnotoad tags: mudpuppy-apps
17:28
Normalize dub data handling and move state pipeline into clay-stage check-in: 31220436ad user: hypnotoad tags: mudpuppy-apps
2026-08-16
16:10
Simpficiation of the mudpuppy agents. Removed the concept of the context factory. check-in: 03000b2e6c user: hypnotoad tags: mudpuppy-apps
2026-07-27
14:15
Event service debugging Leaf check-in: 2276841bf2 user: swoods tags: stable
2026-07-25
17:39
Goals and events: dziwak-backed intent tracking, event timelines, and a status screen Splits project paperwork into the two things it actually is. A goal is a plan to bring events about; an event is a record that something happened. They get separate stores because their sharing rules differ: planning is private to a project, subject matter is shared between projects. NEW: skills/goal — persistent units of intent, in the project's dziwak store (shared with memory, so goals surface through recall). Absorbs the milestone skill: a milestone was a phase-numbered checkpoint with a status and priority, which is a goal with a phase number, not a separate concept. Its phase grouping and percentage rollup survive as goal_tree/goal_progress. Actionability is derived at read time from blocked_by rows rather than cached, so it cannot go stale; goal_depend refuses dependency cycles, since two goals waiting on each other can never become actionable and would make the status screen lie. NEW: skills/timeline — events, their accounts, and their order. One event holds many accounts, each with its own source_uuid and confidence, so a scene told from several viewpoints keeps every version instead of overwriting down to one truth. event_precedes records plain sequence; event_causes records sequence and causation, and is what causal chain queries follow. NEW: skills/corpus — named, reusable world-knowledge stores. Bindings persist in the registry against the project root, so reopening a project reattaches its corpus. An unbound project auto-provisions a private corpus on first use, so single-project work needs no setup while two projects can still share one. NEW: modules/dziwak/build/timeline.tcl — ordering edges and the query over them. No new tables: per docs/plans/entity-unification.md D3 ("claims subsume links"), an ordering edge is a two-participant claim, using the existing free-text claim_entity.role column. Ordering is a claim rather than a property because it is not a bare fact — you may be unsure of it, sources may disagree, and the reason you believe it is worth keeping. entity::timeline returns topologically LAYERED order: events sharing a layer have no known order between them, which is the honest representation of soft-dated material rather than a fabricated sequence. Cycles are reported, never silently resolved — a contradictory ordering is a finding about the source material. Field/claim split throughout: bare facts (status, priority, phase, hardness, date text, appears_in, detail pointers) are entity properties; anything contested or narrated (accounts, participants, ordering, why a goal changed) is a claim. STATUS SCREEN: context_state.tcl's background_material now also contributes the goal skill's status screen, so current goals reach the model every turn without spending a tool call — the same reason a GM keeps a screen in front of them. It returns nothing for a project with no goals, so an empty project costs nothing, and degrades to no block when the goal skill or agent is absent. FIX: project_use never propagated. project_root was set only on the project skill's own config, while every other skill read it from its own — so project-scoped memory silently fell back to global and codebase reported "No project active" no matter how many times project_use had been called. Now broadcast to sibling skill delegates via the agent. FIX: dziwak FTS searched for an exact phrase. A whole query was wrapped in one pair of quotes, so a two-word search demanded the words be adjacent and matched almost nothing; `*` was mapped to SQL LIKE's `%`, disabling FTS5 prefix search. Terms are now quoted individually and ANDed, with trailing `*` preserved. Fixed in both entity::search and claim::search. FIX: todowrite could not clear its list. An empty JSON array was treated as "no valid tasks" and rejected, conflating a valid clear instruction with a malformed payload. Distinguished: an empty array clears; a non-empty array with no usable items throws and leaves the previous list intact. REMOVED: skills/knowledge — a fourth parallel entity/claim/link implementation with its own tables and ad-hoc UUIDs, superseded by dziwak and loaded by no app. REMOVED: the goal/lane MCP methods in api_domain.tcl and their JSON-file backing in store.tcl, plus the goals/goal_deps/goal_revisions/lanes index tables. They were registered and advertised but never called, and their storage was never read back. project_open, get_updates and record_decision are kept, since ziggurat mixes this class in. Lanes are deferred until something coordinates multiple agents. TESTS: first coverage dziwak has ever had (timeline.test, 21). goal 40, timeline 25, corpus 14. todowrite.test rewritten against the current Tool convention — it had been calling tools positionally and expecting list-of-dict returns, so all 5 tests failed. Removed a stray runAllTests from 11 skill suites: after cleanupTests it re-ran the containing directory, so each file recursively re-invoked itself and no suite could terminate. Unicode in Tool descriptions made knowledge and deliberation unloadable (the DSL requires ASCII); fossil.test computed its library root one directory too high. Test scratch dirs now anchor to TMPDIR instead of tcltest's cwd default, which had been scattering SQLite files through skills/. Also: workspace and minion now inherit skill::base. Without a constructor, InitializePublic never runs, so every Variable default was silently ignored — workspace's whitelist and blacklist did not exist, meaning its path access rules never applied. check-in: cad90da803 user: hypnotoad tags: mudpuppy-apps
2026-07-07
14:32
Eliminated the idea of passing packets as objects. Provided helper functions to areas of the code that expected packets to have their own behavior. check-in: 766f4dd545 user: hypnotoad tags: mudpuppy-apps
2026-06-28
17:50
Merge Swift support from leaf 4fd1364f00 into mudpuppy-apps Integrates the orphan Swift commit (4fd1364f00, by yoda) into the mudpuppy-apps branch via fossil merge --integrate. The original commit modified 4 practcl build files but left the new implementation files (product.swift, swift.tcl) as untracked extras in both working directories. This merge adds them so the commit is complete. Changes: - modules/practcl/build/build.tcl: add swift.tcl and product.swift to amalgamation list - modules/practcl/build/class/product.tcl: route .swift files to ::practcl::product.swiftfile - modules/practcl/build/class/project/library.tcl: support no_c_amalgamation, add refresh-toolset method - modules/practcl/build/class/toolset/baseclass.tcl: auto-detect Swift sources for toolset selection - modules/practcl/build/class/product.swift: NEW — product handler for .swift source files - modules/practcl/build/class/toolset/swift.tcl: NEW — Swift toolset (swiftc compiler) - apps/penny/main.tcl: state manager can be disabled via AGENT_PENNY_STATE_MANAGER=0 check-in: 008e722993 user: hypnotoad tags: mudpuppy-apps
17:50
Sprint: merge gateway+batch into ziggurat core, merge sagdub into mudpuppy Gateway & batch processing folded into deps/clay/modules/ziggurat/ziggurat.tcl as ::ziggurat::core_domain mixin (not a separate module). Provider registry, llm_forward, batch methods, content handlers, and dispatch routes all in core. Merged sagdub into mudpuppy — one coding assistant app, not two. All ::sagdub:: namespaces renamed to ::mudpuppy::. Deleted ziggurat-batch module — was orphaned dead code, useful parts absorbed into ziggurat core. Rewrote apps/ziggurat/main.tcl as the gateway process (was dead sanga code). Updated skills/project/project.tcl (sagdub -> mudpuppy). check-in: 1aeb99ab69 user: hypnotoad tags: mudpuppy-apps
17:36
Adding Swift support to Practcl Closed-Leaf check-in: 4fd1364f00 user: yoda
2026-06-23
13:10
ziggurat-batch connector: distributed batch dispatch over HTTP New module ziggurat-batch — the meeting point between clay::app::batch and ziggurat HTTP transport. Neither clay-app nor ziggurat knows about the other; the connector is the only place they meet. Components: - ::ziggurat::batch::domain (dispatch.tcl) — method dispatch mixin. Maps work_submit/work_claim/work_complete/work_fail/work_result/ work_status/work_list + worker_register/worker_unregister/ worker_heartbeat/worker_list to ziggurat's method dispatch. Posts bus events on app_entry (readable via get_updates long-poll by remote clients, and via bus subscribe/wait by local clients). - ::ziggurat::batch::registry (registry.tcl) — worker registration table (batch_worker). Tracks worker_id, capabilities, worker_kinds, cpu_count, max_concurrent, heartbeat liveness, state (idle/busy/gone). Periodic reaping of workers not seen in heartbeat_timeout_ms. - ::clay::app::batch::remote::submitter (remote_submitter.tcl) — HTTP-backed batch submitter. Same API as ::clay::app::batch (enqueue/ await/fanout/collect/status). await uses get_updates long-poll. Must be called from a coroutine for await/collect. - ::clay::app::batch::remote::worker (remote_worker.tcl) — HTTP claim → local pool execution → HTTP complete. Registers with server, heartbeats every 30s, long-polls for work_available when idle. Uses the existing four local worker kinds for execution. Schema additions to app_work (in CREATE TABLE + additive migration): - requires TEXT — space-separated capability tags for filtering - assigned_to TEXT — directed work for a specific worker_id Enhanced batch::queue::claim now accepts capabilities parameter and filters: work with requires tags only claimable if all requires are in worker's capabilities; work with assigned_to only claimable by that worker_id; work with neither is open to anyone (SETI@Home mode). Fixed double-COMMIT bug in claim method (was running COMMIT twice — once after UPDATE, once after post-commit SELECT). Bus events posted on work_available, work_completed, work_failed, worker_available, worker_gone — all on app_entry, all readable via get_updates. Tests: 11 ziggurat-batch tests (work_submit/claim/complete/fail/ result/status/list, worker_register/heartbeat/unregister/list, bus events via get_updates). Full suite: 141/141 across all modules. check-in: 56e28e1730 user: hypnotoad tags: mudpuppy-apps
2026-06-22
23:49
Unify bus schema: ziggurat::bus targets app_entry, not bus_event Ziggurat's bus is now a layer on clay::app::bus. Both share the same app_entry table — no bridge, no duplicate bus_event table. Schema changes (additive): - app_entry gains typed columns: room_uuid, sender_uuid, event_type, content_type (all optional, nullable). clay::app::bus uses stream/ payload and ignores them. ziggurat populates them for SQL-level filtering. - New indexes: idx_app_entry_room_eid, idx_app_entry_type - _migrate_entry_columns: idempotent ALTER TABLE for existing databases clay::app::bus changes: - post: accepts optional -room_uuid, -sender_uuid, -event_type, -content_type, -expires flags - poll: accepts optional -event_type, -room_uuid filters; returns 8-element rows (eid stream payload created room_uuid sender_uuid event_type content_type) - at: returns 8-element rows ziggurat::bus changes: - schema_install: no-op (app_entry already has the columns) - event_post: INSERT into app_entry with stream=realm_uuid + typed cols - event_poll: SELECT from app_entry WHERE stream=realm_uuid (+ optional room_uuid filter). Returns rows with aliased stream AS realm_uuid for backward compatibility with get_updates. ziggurat store changes: - open_control and new_runtime now create ::clay::app::store (was ::clay::object). This gives them app_entry, app_work, app_config tables automatically. The store's internal db connection is closed and replaced with the WAL-configured handle. dziwak attach is called to create the dziwak.* schema namespace. - build.tcl: added package require clay-app, clay-bi, clay-sqlite. ziggurat.test: added clay-bi, clay-app, clay-os, clay-http, dziwak, clay-stage to support section. Added auto_path for module discovery. (The test still has pre-existing failures from dub::fromDict bug and missing ::ziggurat::schema class — not introduced by this change.) All 129 module tests pass: clay-app 50, clay-bi 56, clay-sqlite 2, mudpuppy 27. check-in: a27bad1379 user: hypnotoad tags: mudpuppy-apps
20:13
Batch processing layer: honest parallel worker systems New ::clay::app::batch module with four worker kinds that share a common design language (queue contract, result-dict shape) but do NOT hide their different semantics behind a false abstraction. Components: - ::clay::app::batch::queue — durable SQLite work queue on the app_work table. Additive schema migration (phase, priority, after_eid, worker_kind, timeout_ms). Atomic claim via BEGIN IMMEDIATE + UPDATE...RETURNING. Orphan reaping. Phase chaining via after_eid (blocked → pending when parent completes). - ::clay::app::batch::worker::coroutine — cooperative coroutine worker. Shares memory, no true parallelism (single event loop). Yields during I/O. Best for LLM calls, HTTP requests. - ::clay::app::batch::worker::subprocess — sync pipe subprocess. Full OS isolation. Blocking exec with reliable exit code capture. Best for crash-prone scripts, external tools, untrusted code. - ::clay::app::batch::worker::thread — child thread worker. True parallelism (separate Tcl interp + event loop per thread). Isolated memory. Communication via thread::send + shared SQLite (WAL mode). The thread runs its own claim→execute→complete loop autonomously. Requires init_script to load packages. - ::clay::app::batch::worker::processman — async managed subprocess via tcllib's processman. Non-blocking (spawn + onexit callback + coroutine yield). Managed lifecycle (kill, relaunch, zombie harvesting). Best for long-running subprocesses, kill/cancel. - ::clay::app::batch::pool — worker pool manager. Start/stop/scale, CPU detection (sysctl/nproc/NUMBER_OF_PROCESSORS), idle reaping, health monitoring (restart crashed thread/subprocess workers). A pool manages workers of ONE kind — different kinds have different semantics and should be managed separately. - ::clay::app::batch::pipeline — declarative phase chaining. define/submit/submit_chain/on_phase. Fan-out and fan-in via after_eid dependency edges. - ::clay::app::batch::collect — parallel fan-out + result collection. fanout/collect/collect_any/map. Built on coroutines. - ::clay::app::batch — composition root. enqueue/await/drain/ start_workers/stop_workers/fanout/collect/map/pipeline. The await API: enqueue work, await the eid from a coroutine. Workers notify awaiters via the <batch> delegate when jobs complete. Schema: additive ALTER TABLE on app_work (phase, priority, after_eid, worker_kind, timeout_ms). No changes to existing store methods. Tests: 50 total (14 queue, 5 worker, 8 batch, 23 existing clay-app). Full suite: 129/129 across all modules. check-in: 9a74d05256 user: hypnotoad tags: mudpuppy-apps
18:10
Sprint 1: mudpuppy runner rebuild + recipe system ::mudpuppy::llm::runner rebuilt in-place as a ::clay::app::runner subclass. The runner IS its own worker — the retry loop (inherited from clay::app::runner) calls execute_work, which does one LLM turn (tool-call loop + error classification). Error classification (mudpuppy-specific): HTTP 429/503/502/timeout -> transient (retry with backoff) HTTP 400/402/404/other -> persistent (circuit breaker) decode errors -> persistent The retry loop now uses coroutine-aware sleep (yields during backoff when called from a coroutine) and emits state transitions via <kin> (running, retrying, succeeded, failed, circuit_open). API: - run_transcript: backward-compatible, wraps execute with the retry loop. Returns {ok 1 status done reply ...} / {ok 0 status error ...}. - execute: overridden to call execute_work as the worker. Returns the clay::app::runner result dict {ok state attempts result error_log}. - dispatch + await: non-blocking coroutine-based execution. - runner_state: query current state. - on_state: subscribe to state transitions. - recipe_name option: construct LLM connector from a recipe. - llm_connector: resolves from llm delegate, agent's llm, or recipe. New file: modules/mudpuppy/build/recipe.tcl ::mudpuppy::llm::recipe — thin subclass of ::clay::app::recipe. Knows about LLM connector construction conventions. mudpuppy build.tcl: added clay-sqlite + clay-app package requires, added recipe.tcl to the build file list. All test support sections updated to source clay-app. runner.test expanded from 1 to 5 tests: 1.0: backward-compat (mock LLM, one turn) 2.0: transient (429) then success — retry works 3.0: persistent (402) — no retry 4.0: state transitions visible via runner_state 5.0: dispatch + await (coroutine async) Full suite: 103/103 (clay-app 23, clay-bi 56, clay-sqlite 2, runner 5, hull 5, session 6, channel_loopback 5, context_factory 6, webui_request 5). check-in: 855a17edfa user: hypnotoad tags: mudpuppy-apps
17:54
Sprint 1: non-blocking dispatch + await + state events Runner now supports coroutine-based async execution: - dispatch $work: runs execute in a new coroutine, returns immediately. State transitions (running, retrying, succeeded, failed, circuit_open) are emitted via the <kin> delegate. - await: parks the calling coroutine until the runner reaches a terminal state. Returns the result dict. Requires a coroutine context. - result: returns the last result dict (poll from non-coroutine context). - on_state $script: subscribe to state transitions. Callback invoked as {*}$script <runner> <state> on each transition. - _sleep uses coroutine-aware sleep (yields + after) when called from a coroutine, blocks at top level. 4 new tests covering dispatch/await, dispatch with retry, spawn+dispatch child with parent await, and state subscription. All 23 clay-app tests pass. Full suite: 98/98. check-in: 81f55380ad user: hypnotoad tags: mudpuppy-apps
17:21
Sprint 1: clay-app module — runner, recipe, store, bus foundation New module clay-app: a barebones Tcl application framework built on clay-bi's yggdrasil tree. A clay-app node is a work tree node that can run work, spawn children, introspect their state, and report to parents. Components: - ::clay::app (core.tcl): yggdrasil subclass, base app node with child::delegate (passes store+recipe to children) and app::introspect (recursive tree snapshot). - ::clay::app::store (store.tcl): folded from clay-os's store.sqlite. Owns the clay-app schema (app_work, app_config, app_entry tables). Subclasses ::clay::sqlite. Config get/set on app_config. - ::clay::app::recipe (recipe.tcl): general-purpose named construction dicts. Source Tcl config files, query by name, build objects from recipe (class + args + mixins). Works for any clay object. - ::clay::app::runner (runner.tcl): general-purpose work executor. Vague mega-object — constructed empty, assembled piecewise with a worker delegate. Retry with exponential backoff on transient failure, circuit breaker on persistent failure. State tracking (idle, running, retrying, succeeded, failed, circuit_open). Child runner spawning via yggdrasil child::add. Introspection via node_dump augmentation. Worker contract: {ok 1 result ...} / {ok 0 failure_type transient ...} / {ok 0 failure_type persistent ...}. - ::clay::app::bus (bus.tcl): folded from clay-bus. Post/poll/cursor/ subscribe/wait on the app_entry table. In-process notification via ::clay::bi::kin. - ::clay::bi::mu.home (mu_home.tcl): moved from clay-sqlite. Unchanged code — durable sqlite journal, still a ::clay::bi::mu subclass. Module dependency chain: clay -> clay-bi -> clay-sqlite (keeps ::clay::sqlite) clay -> clay-bi -> clay-sqlite -> clay-app (store subclasses ::clay::sqlite) clay-app -> mudpuppy (mudpuppy::llm::runner will subclass clay::app::runner) Cleanup: - Deleted clay-bus module (zero consumers, folded into clay-app::bus). - Removed ::clay::config::store.sqlite from clay-os (moved to clay-app::store). connector.sqlite superclass updated to ::clay::app::store. - Removed mu_home.tcl from clay-sqlite (moved to clay-app). clay-sqlite now only owns ::clay::sqlite (the connection base). - Updated clay-sqlite.test: removed mu.home tests (now in clay-app.test). Tests: clay-app 19/19, clay-sqlite 2/2, clay-bi 56/56, clay-os 32/33 (1 pre-existing failure: dispatch-httpd-0001 deferred to future sprint). All mudpuppy tests unchanged: 28/28 across 6 suites. check-in: 9ada2d5e90 user: hypnotoad tags: mudpuppy-apps
12:52
Restore clay-sqlite as sole owner of ::clay::sqlite; fix module dependency chain clay-bi is now binary-free (no sqlite3 dependency): - Removed duplicate ::clay::sqlite class definition from build/home.tcl (it was copied from clay-sqlite but clay-os already depends on clay-sqlite for the real definition). - Moved ::clay::bi::mu.home (durable sqlite-backed journal) from clay-bi/build/mu.tcl to clay-sqlite/build/mu_home.tcl. The in-memory ::clay::bi::mu stays in clay-bi. - Removed catch {package require sqlite3} from clay-bi amalgamation header. clay-bi no longer references sqlite3 at all. - Moved 4 mu.home tests from clay-bi.test to clay-sqlite.test; added 2 ::clay::sqlite attach/detach tests. clay-bi: 56/56, clay-sqlite: 6/6. clay-sqlite dependency chain fixed: - Added package require clay-bi to build/core.tcl. Chain is now: clay -> clay-bi -> clay-sqlite. package require sqlite3 is hard, no catch. clay-os fixed: - Added package require clay-bi to build/build.tcl. Chain is now: clay -> clay-bi -> clay-sqlite -> clay-os. - Removed store.sqlite::attach {filename} override that shadowed the inherited ::clay::sqlite::attach {handle filename {class}} contract. Primary-DB-open logic inlined into the store.sqlite constructor. connector.sqlite instances can now call 'attach dziwak <path> ::dziwak::schema' (SQL ATTACH with schema mixin) as intended. clay-bus fixed: - Replaced catch {package require sqlite3} with package require clay-sqlite. 6/6 tests pass. check-in: cd378dcaea user: hypnotoad tags: mudpuppy-apps
11:23
Eliminate shims: redevelop all apps to use hull from the ground up Remove all four app packet_queue overrides (sagdub, sukkal, gilgamesh, clay::Agent) and the dead contextDict/packet_field_* state from llm::agent. Every app now builds via ::mudpuppy::hull with delegates. Library changes: - llm::agent: removed dead Variable contextDict and packet_field_* methods. packet_queue is now purely the compat shim (delegates to context_factory, lazily creating one if no hull wired it). - context_factory: added context_log_level and work_dir options (previously app-specific), added db delegate forwarding, added packet_enrich hook for subclass extension. - hull: channel_options now passes agent+llm to channel constructor (needed for connector.stdio which auto-starts on construct). Factory option forwarding uses public 'config get' (TclOO private method rule: uppercase = private, only callable via my). App redevelopment: - clay::Agent (make-procs.tcl): removed packet_queue override. do_prompt builds a hull + connector.stdio channel. do_server builds a hull + channel::webui (already done, kept). - sagdub: removed packet_queue override. server/prompt modes use hull. run mode uses hull with channel_class=channel::loopback. script mode stays legacy (uses sagdub::context::files, separate track). - sukkal: removed packet_queue override. Added context_class option (default ::dziwak::context). Both stdio and webui channels built via hull; db delegate wired onto context_factory post-start. - gilgamesh: removed packet_queue override. Stage-session injection moved to ::stageplay::context_factory subclass (overrides packet_enrich). Both server and default modes use hull. - llmhub: webui server mode now builds via hull. 28 tests across 6 suites, all green. check-in: 51f160d5d2 user: hypnotoad tags: mudpuppy-apps
11:00
Hull refactor: composition root + delegate extraction (milestones 1-5) Introduce ::mudpuppy::hull as the top-level composition root and extract the major responsibilities from the fused connector+context classes into swappable delegates. Per .opencode/knowledge/hull-architecture.md. Milestone 1 (runner): ::mudpuppy::llm::runner owns one LLM turn (transcript -> complete -> tool-call loop -> reply). webui::connector now delegates its turn through runner instead of the inherited llm::context::llm_complete. (build/runner.tcl, runner.test) Milestone 2 (hull + channel::webui): ::mudpuppy::hull creates and wires agent/runner/channel/server/sessions/context_factory delegates. ::mudpuppy::channel::webui is the hull-shaped webui transport: it skips httpd ownership (the hull owns the server via attach_server). Direct webui::connector construction stays backwards-compatible via InitializeHttpd template method. do_server builds a hull. Milestone 3 (sessions): ::mudpuppy::session::registry owns session/request lookup, request_seq, and TTL cleanup. webui::connector keeps thin delegating wrappers so reply mixins call my <connector> request_* unchanged. Milestone 4 (loopback channel): ::mudpuppy::channel::loopback is the hull-shaped batch channel -- does NOT subclass llm::context, owns only prompt/output/context file I/O, delegates the turn to the hull runner. sagdub main.tcl run mode builds a hull + channel::loopback. Milestone 5 (shrink llm::agent): ::mudpuppy::llm::context_factory owns the per-coro context registry (the old contextDict). llm::agent::packet_queue is a compat shim that delegates to a context_factory delegate, lazily creating one if none is wired -- stream transports unchanged. Coroutine constraint: clay::http::geturl/complete/run_transcript yield; LLM turns must execute inside a coroutine (documented in hull-architecture.md). 28 tests across 6 suites, all green. check-in: 6e9a2cc88b user: hypnotoad tags: mudpuppy-apps
2026-06-19
09:11
Sprint 10 foundation: reform clay-bi primitives + new clay-bus module clay-bi reform (60 tests, all green): - Coroutine.next/peek: fix upvar 1 [lindex $args 0] -> upvar 1 $eventvar (the Driver dequeue substrate); regression test added. - io.tcl (new): ::clay::bi::io mixin salvaged from the retired kinda -- Vwait / Wait_Readable / Read_Line / Read_Exact / Read_To_Eof + ::clay::bi::VWaitTrace (coroutine-aware channel I/O). - sig: freeze / frozen? / ensure_mutable ({SIG FROZEN}); constructor materializes config (fixes latent read-before-write). - sig.header (new class): normalizing header bag (case-fold + alias table). - codec.tcl (new): ::clay::bi::codec registry (register/encode/decode/ content_type/mode_for/modes); built-in json/jsonl/text/binary. - imim: rebuilt as routing accessors (sender/stream/type/cursor/created/ recipient) + one normalizing <header> bag + body codec; {IMIM FROZEN}; serialize/restore; dropped the vestigial <state> bag. - imim_gi.tcl (new): ::clay::bi::imim.gi reply (status/code) on the repaired base, inheriting the codec. - mu: mu.home durable sqlite journal (attach/append/poll/index/last/size/ cursor/expire/streams), guarded by catch {package require sqlite3}. - kin: wait <event> ?timeout? -- coroutine parks until emit ({KIN CONTEXT}/{KIN TIMEOUT}); emit wakes waiters. - agent: register_participant/unregister_participant; route by recipient->stream->context->respond; IsImim guard; backward-compatible. - retired kinda.tcl (kaskal never existed; I/O -> io, decode_as -> codec). - packet_contract.test: dropped stale clay-kinda use. clay-bus (new module, 6 tests, all green): - ::clay::bus on reformed clay-bi: attach/post/poll/at/subscribe/wait/ cursor/expire/streams. post persists soup->mu, stamps cursor, emits; poll rehydrates via ::clay::bi::revive; subscribe is in-process callback; wait is kin-wait sugar. The bus carries data (serialized soups + eid), not live objects. Foundation only -- no user-facing change. The HTTP reorganization (clay-http, dispatch primitive, httpd rebase, ziggurat::api re-home) is deferred to a dedicated 'HTTP on clay-bi' sprint. Amalgamations are not tracked; run 'tclsh deps/clay/make.tcl modules' to regenerate. check-in: 999daf0a83 user: hypnotoad tags: mudpuppy-apps
2026-06-18
17:44
Sprint 9: Moirai orchestrator (compiler + roles + pipeline) Sprint 9 - the Moirai (three-LLM pipeline): Clotho (driver) — emits vocabulary text from player input + state Lachesis (judge) — approves/rejects proposed mutations (S9 stub) Atropos (narrator) — produces final prose from new state New files: - compiler.tcl: ::mudpuppy::compiler namespace procs. Pure text->mutations. 15 vocabulary patterns (entity CRUD, properties, claims, emotion, events, scene). _infer_property_key with emotion/location/role word lists (WordNet deferred to S12). compile, apply, build_correction procs. - tools.tcl: 11 Tool declarations on ::mudpuppy::llm::context/state for the single-LLM tool-calling paradigm (NOT used by Moirai). Tools: entity_create/delete, prop_set/get, claim_add/list, emotion_set/get, event_emit, scene_advance, state_render. - roles.tcl: Role mixins for the three Moirai LLMs. - role.base: transcript management + memory pruning (none/sliding:N/full) - driver: capability mixin, single LLM call -> compile text -> mutations - role.driver: sliding:3 memory, driver system prompt - role.narrator: full memory, narrator system prompt, call method - role.judge: stateless, approve-everything stub (puppetable via stub_verdict Option for testing) - moirai.tcl: ::mudpuppy::moirai orchestrator. Owns the while loop: driver -> compile -> judge -> apply -> narrator. Correction loop with max_retries. Judge rejection routes to narrator. Compile failure after max retries routes to narrator (clarification). Refactored files: - interp.tcl: <state> and <slave> as clay delegates (no manual destructors needed — objects live in instance namespace, cleaned up automatically). Removed state accessor method (use my <state> or clay delegate <state>). - context_state.tcl: <interp> delegate. interp_init_delegate method for post-mixin application (clay mixinmap doesn't re-run constructors). tool_spec method collecting Tool declarations from class ancestry. background_material calls interp_init_delegate lazily. - build.tcl: load order updated (compiler.tcl tools.tcl roles.tcl moirai.tcl after context_state.tcl, before api_domain.tcl). Design decisions: - No tool calling in the Moirai pipeline. Tools (tools.tcl) are for the single-LLM paradigm where driver+narrator are fused. Future sprint could add a judge that approves tool requests before they hit the model. - Judge returns Tcl dict (approved/cost/reasoning), not JSON. S11 will add a real LLM judge + policy mixins (Fate rules, accounting). - Each LLM has its own memory policy (driver: sliding:3, narrator: full, judge: none). Memory is per-hybrid, not per-pipeline. - Three connector instances, hand-configured (no role registry, no profiles, no model_roles). User may use different providers per LLM. 47 assertions in tests/sprint_9.test, all pass. All 8 test suites green (Sprints 1,2,3,4,6,7,8,9). check-in: e8e70d9081 user: hypnotoad tags: mudpuppy-apps
15:30
Sprint 7: state model + safe interp + render; clay-bi: home/sqlite consolidation Sprint 7 - mudpuppy state primitives: - New ::mudpuppy::state clay class (state.tcl): named entities (name/kind/ properties/claims), global emotion dict, event log, scene pointer. Ensemble dispatch for entity/prop/claim/emotion/event/scene sub-methods. render -> dub (filterable: -entities, -kind, -min_conf, -include_props, -include_claims). render_text -> text block for LLM consumption. Constructor added to trigger InitializePublic (clay ensembles require a constructor - see CLAY_ERRATA). - New ::mudpuppy::state::interp (interp.tcl): wraps state + safe slave interp. Allow-list excludes while/for (defense in depth against infinite loops; foreach is bounded). interp recursionlimit (default 200) for recursion. interp bgerror handler for async. State commands aliased slave->host. proc kept native in slave (aliasing it defines procs in host, not slave - see CLAY_ERRATA). proc-redefinition hardening deferred to a future sprint. - New ::mudpuppy::llm::context/state mixin (context_state.tcl): holds state interp; overrides background_material to inject render_text output. Wired via clay mixinmap state in connector_llm.tcl. - build.tcl load order: state.tcl interp.tcl context_state.tcl added after connector_llm.tcl. clay-os and clay-sqlite package requires dropped (clay-bi now provides home + sqlite). - 36 assertions in tests/sprint_7.test, all pass. clay-bi - clay-os made optional: - New clay-bi/build/home.tcl: ::clay::home config|state|data ensemble (XDG dirs). Backward-compat aliases ::clay::config_home / data_home / state_home kept. ::clay::sqlite class moved here from clay-sqlite (conditional on sqlite3 availability - catch {package require sqlite3}). - clay-bi build.tcl: includes home.tcl; optional sqlite3 require. - All mudpuppy build files updated: ::clay::config_home -> ::clay::home config, ::clay::data_home -> ::clay::home data. - All 6 apps updated (sukkal, penny, sagdub, gilgamesh, llmhub, ziggurat). Rationale: clay-os is heavyweight (Thread, ip, port database); most apps only need XDG dirs + a SQLite base. clay-http stays separate (different concern, TLS dependency, 692 lines). check-in: e45a492874 user: hypnotoad tags: mudpuppy-apps
14:12
Sprint 6 audit (Phases A-E) + Sprint 8: dub bug fixes + dub::mu->dub::array Sprint 6 audit: - Phase A: Dead code deletion (dub.tcl, geturl.tcl, arena_scene, 9 dead procs in baseclass.tcl, debug puts) - Phase B: Bug fixes (kin.tcl my terminal->my is terminal, connector_llm.tcl append tool_prompt, server.tcl _build_tree leak) - Phase C: Raw TclOO removal in task.tcl (class-level CoroutineMain, no oo::objdefine) - Phase D: Structural split (::mudpuppy::* procs moved from ziggurat to mudpuppy/store.tcl; ::mudpuppy::api_domain mixin extracted) - Phase E: catch->try migration (opencode_lookup, registry_reindex, bus event_post, schema installs) - skill_manager.tcl: lazy singleton (::mudpuppy::skill::manager_instance), namespace collision fixed (::mudpuppy::skill::base) - store.tcl: opencode_lookup uses XDG data home (was hardcoded $env(HOME)) - Apps updated to use lazy singleton accessor Sprint 8 - dub bug fixes: - fromDict: fix nonsense 'dict exists . $value' check -> _is_dub - fromDict: fix boolean detection using $value instead of $v - Type: fix _is_mu $value -> _is_mu $node for nested mu - JSON: surrogate pairs for codepoints >U+FFFF (was truncated to \uXXXX) - Boolean: normalize to true/false (was 1/0, matching True/False procs and JSON) - object_destroy: fix undefined $obj -> $objname (clay/build/init.tcl) - cron: fix $::tool::trace -> $::cron::trace with info exists guard (cron.tcl:733,787) Sprint 8 - dub::mu -> dub::array rename: - Rename ::dub::mu namespace -> ::dub::array - dub array create/append/keys/size/list/for/with/pop/shift is canonical path - ::dub::mu kept as backward-compatible ensemble alias - dub mu X Y Z still works as create-shortcut - Add dub::array::For and dub::array::With (parity with object side) - Delete dub toValue/fromValue (no-op pass-throughs) - Fix readme.md: ::mudpuppy::run -> ::mudpuppy::main, run -once -> run_until_complete - Fix store.tcl: dub array $x -> dub array create {*}$x (5 sites) All 6 test suites pass (Sprints 1,2,3,4,6,8). check-in: 3dd778b40e user: hypnotoad tags: mudpuppy-apps
02:10
Tweaks to penny app check-in: 78c71bcaef user: yoda
2026-06-17
16:32
Sprint 6: schedule store verb/payload + processman kill -0 fix ziggurat schedule store: - Add verb, payload_json columns to schedule table in index_schema - schedule_default accepts verb+payload (6 args, was 4) - schedule_write and reindex handle verb+payload_json processman (tcllib): - subprocess_exists fallback: bare 'exec ps' (only shows TTY-attached procs on macOS/BSD, misses background procs) replaced with POSIX 'kill -0 $pid' — works for any process we may signal Re-amalgamated ziggurat. check-in: 33ec3d3c99 user: hypnotoad tags: mudpuppy-apps
16:05
Migrate to XDG Base Directory layout Add ::clay::config_home/state_home/data_home namespace procs to clay-os (XDG_CONFIG_HOME/XDG_STATE_HOME/XDG_DATA_HOME on Unix; %APPDATA%/ %LOCALAPPDATA% split on Windows). app_root is a deprecated alias for config_home. default_file uses config_home. Update all clay apps (gilgamesh, penny, sukkal, sagdub, llmhub) to use config_home for config/keys and data_home for agent memory/data. Move agent_path computation after clay-os is sourced so ::clay::data_home is available. Update mudpuppy module (baseclass, credentials, skill_manager) to use config_home for credentials/prefs/skills and data_home for agents. Update ziggurat registry_dir to data_home/registry. Update memory skill (dziwak DB) and project skill (sagdub DB) to data_home. Update make.tcl + scripts/make-procs.tcl with standalone XDG procs (no clay dependency for the build tool). do_install default dest is now data_home. Re-amalgamated clay-os, mudpuppy, ziggurat modules. check-in: 48f45db802 user: hypnotoad tags: mudpuppy-apps
13:30
edubba::index: JSON-backed SQLite index module. Schema-declared, mtime-based staleness, consumes clay::schema::dict. Leaf check-in: cb3142a7a7 user: hypnotoad tags: edubba
13:21
edubba: clay-schema module (::clay::schema::dict), clay-db bug fixes (table::objects typo, ensemble dispatch, compound, file_restore), migration framework (register_migration, migrate) check-in: 109503f6b0 user: hypnotoad tags: edubba
13:20
Create new branch named "edubba" check-in: 6419c54816 user: hypnotoad tags: edubba
10:25
Mudpuppy: API response status codes + dub return values (lessons 8p/8q), real lane_release MCP entry, lane_claim conflict arg fix, lane_status released count check-in: c8981332a8 user: hypnotoad tags: mudpuppy-apps
2026-06-16
18:42
mudpuppy Sprint 1: PM verb re-skin, MCP framing, ziggurat::dispatch mixin, dziwak schema fix modules/ziggurat/build/server.tcl: Replaced game verbs (createRoom, getRoom, actorAct, etc.) with 9 project-management verbs (project_open, goal_seed, goal_commit, goal_adapt, goal_resolve, lane_claim, lane_status, get_updates, record_decision). Added MCP JSON-RPC framing (dispatch_raw, dispatch_mcp, mcp_tools_list, mcp_tools_call). Added mudpuppy store helpers (store_init, store_write, store_read) and SQLite reindex with schema. Defined ::ziggurat::dispatch as a Dispatch_Local mixin (matches POST /mudpuppy, routes to ::ziggurat::content.json content handler). modules/ziggurat/build/helper.tcl: Fixed dziwak schema install bug where sqlite3 creates the db file before dziwak::attach's [file exists] check, so CREATE TABLE never runs. Added catch-wrapped schema DDL call. modules/ziggurat/build/core.tcl: Same dziwak schema fix in new_runtime. check-in: 647a6c7d6c user: hypnotoad tags: mudpuppy-apps
18:42
Create new branch named "mudpuppy-apps" check-in: 161a175065 user: hypnotoad tags: mudpuppy-apps
2026-06-15
19:43
Bug fixes check-in: 6b4b75de6d user: hypnotoad
16:05
Pulling in a state-of-the-art coroutine package. The snapshot of Tcllib we usually use is stale check-in: d20ddb6ae3 user: yoda
15:40
Development snapshot Lots of refactoring check-in: 271b121352 user: yoda
2026-06-12
22:21
Consosidated some of the new datatypes of lesser activity to oblivion. Yggdrasil, singleton, and coroutine moved to this module. They are common enough to be called by a large application, but not worth bloating the clay core for. Migrated in all of the test for yggdrasil, coroutine, and singleton check-in: f86b9dd8ed user: yoda
22:17
Moved yggdrasil to the clay-bi module. Removed singleton tests check-in: 5d2e68e305 user: yoda
2026-06-11
21:05
Cleaning up the clay-bi namespace. Shifting the http-like objects out. Importing more primitives that provide design patterns check-in: 1c9d18b446 user: hypnotoad
16:00
clean mudpuppy phase-one cruft and fix ziggurat roundtrip foreach syntax check-in: e5eea296dc user: yoda