Entity lifecycle operations for lings (slaves, tasks, claims).
CRUD operations for:
DDD: Repository pattern for swarm entities.
Entity lifecycle operations for lings (slaves, tasks, claims). CRUD operations for: - Slave entities (add, update, remove) - Task entities (add, complete, fail) - Claim entities (claim, release, batch release) - Critical operations guard (kill protection) - Claim TTL (stale detection, auto-expiration) DDD: Repository pattern for swarm entities.
(add-slave! slave-id
{:keys [name status depth parent presets cwd project-id
kanban-task-id]
:or {status :idle depth 1}})Add a new slave to the swarm.
Arguments: slave-id - Unique identifier (required) opts - Map with optional keys: :name - Human-readable name (defaults to slave-id) :status - Initial status (default :idle) :depth - Hierarchy depth (default 1 for ling) :parent - Parent slave-id string :presets - Collection of preset names :cwd - Working directory :project-id - Project ID for scoping (derived from cwd) :kanban-task-id - Optional kanban task ID this ling is working on
Stamps :slave/alive? true and :slave/last-active-at (epoch millis), so
the new row is visible to the default (non-:include-stale?) queries.
Returns: Transaction report with :tempids
Add a new slave to the swarm.
Arguments:
slave-id - Unique identifier (required)
opts - Map with optional keys:
:name - Human-readable name (defaults to slave-id)
:status - Initial status (default :idle)
:depth - Hierarchy depth (default 1 for ling)
:parent - Parent slave-id string
:presets - Collection of preset names
:cwd - Working directory
:project-id - Project ID for scoping (derived from cwd)
:kanban-task-id - Optional kanban task ID this ling is working on
Stamps `:slave/alive? true` and `:slave/last-active-at` (epoch millis), so
the new row is visible to the default (non-`:include-stale?`) queries.
Returns:
Transaction report with :tempids(add-task! task-id
slave-id
{:keys [status prompt files] :or {status :dispatched}})Add a new task to the swarm.
Arguments: task-id - Unique identifier (optional, auto-generated if nil) slave-id - Owning slave's id opts - Map with keys: :status - Initial status (default :dispatched) :prompt - Task description :files - Collection of file paths
Returns: Transaction report with :tempids The task-id (generated or provided) is in (:tempids report)
Add a new task to the swarm.
Arguments:
task-id - Unique identifier (optional, auto-generated if nil)
slave-id - Owning slave's id
opts - Map with keys:
:status - Initial status (default :dispatched)
:prompt - Task description
:files - Collection of file paths
Returns:
Transaction report with :tempids
The task-id (generated or provided) is in (:tempids report)(add-to-wait-queue! ling-id file-path)Add a ling to the wait queue for a specific file.
If the ling is already waiting for this file, this is a no-op (upsert behavior via composite unique key).
Arguments: ling-id - ID of the ling waiting for access file-path - Path to the file being waited on
Returns: Transaction report
Add a ling to the wait queue for a specific file. If the ling is already waiting for this file, this is a no-op (upsert behavior via composite unique key). Arguments: ling-id - ID of the ling waiting for access file-path - Path to the file being waited on Returns: Transaction report
(append-stdout! slave-id lines)Append output lines to a headless ling's ring buffer. Evicts oldest lines when buffer exceeds max capacity (FIFO).
Arguments: slave-id - The ling's slave-id lines - String or collection of strings to append
Returns: Number of lines currently in buffer after append
Append output lines to a headless ling's ring buffer. Evicts oldest lines when buffer exceeds max capacity (FIFO). Arguments: slave-id - The ling's slave-id lines - String or collection of strings to append Returns: Number of lines currently in buffer after append
(archive-claim-to-history! file-path
{:keys [slave-id prior-hash released-hash lines-added
lines-removed]})CC.6: Archive a claim to history when releasing with changes.
Called by coordinator/contextual-claim-release! when a file was modified during the claim period. Records:
Arguments: file-path - Path of the file being released opts - Map with: :slave-id - ID of the slave that held the claim (required) :prior-hash - Content hash at acquire time :released-hash - Content hash at release time :lines-added - Number of lines added (optional) :lines-removed - Number of lines removed (optional)
Returns: Transaction report
CC.6: Archive a claim to history when releasing with changes.
Called by coordinator/contextual-claim-release! when a file was modified
during the claim period. Records:
- Prior and released content hashes
- Lines added/removed (if provided)
- Release timestamp
Arguments:
file-path - Path of the file being released
opts - Map with:
:slave-id - ID of the slave that held the claim (required)
:prior-hash - Content hash at acquire time
:released-hash - Content hash at release time
:lines-added - Number of lines added (optional)
:lines-removed - Number of lines removed (optional)
Returns:
Transaction report(can-kill? slave-id)Check if a slave can be killed safely. Returns false if slave has any critical operations in progress.
Arguments: slave-id - Slave to check
Returns: {:can-kill? bool :blocking-ops #{...}}
Check if a slave can be killed safely.
Returns false if slave has any critical operations in progress.
Arguments:
slave-id - Slave to check
Returns:
{:can-kill? bool :blocking-ops #{...}}(claim-age-ms file-path)Get the age of a claim in milliseconds.
Arguments: file-path - Path to check
Returns: Age in ms, or nil if claim not found
Get the age of a claim in milliseconds. Arguments: file-path - Path to check Returns: Age in ms, or nil if claim not found
(claim-file! file-path slave-id & [{:keys [task-id prior-hash qn mode]}])Create a file claim for a slave/task.
Arguments:
file-path - Key to claim (must be unique). A whole-file claim keys on the
path; a span claim keys on path#qn (see
hive-mcp.swarm.claim.span/key-of).
slave-id - Slave making the claim
opts - Optional map with:
:task-id - Task associated with claim
:prior-hash - File content hash at acquire time (CC.3)
:qn - Qualified name, when the claim is on one form
:mode - :file, :body or :signature
:qn and :mode are what make a span claim legible on the way BACK out.
Without them a stored row can only be decoded by parsing its key, and a key
deliberately excludes mode (a :body and a :signature claim on one form must
collide on :db/unique, so they share a key). A claim that does not persist
its mode therefore reads back as :body, which silently disables the
signature-versus-caller rule for every stored claim. Measured: it did.
Returns: Transaction report
Note: Due to :db/unique on :claim/file, attempting to claim an already-claimed file will upsert (update the existing claim). Use has-conflict? to check first if you want to prevent this.
Create a file claim for a slave/task.
Arguments:
file-path - Key to claim (must be unique). A whole-file claim keys on the
path; a span claim keys on `path#qn` (see
hive-mcp.swarm.claim.span/key-of).
slave-id - Slave making the claim
opts - Optional map with:
:task-id - Task associated with claim
:prior-hash - File content hash at acquire time (CC.3)
:qn - Qualified name, when the claim is on one form
:mode - :file, :body or :signature
`:qn` and `:mode` are what make a span claim legible on the way BACK out.
Without them a stored row can only be decoded by parsing its key, and a key
deliberately excludes mode (a :body and a :signature claim on one form must
collide on :db/unique, so they share a key). A claim that does not persist
its mode therefore reads back as :body, which silently disables the
signature-versus-caller rule for every stored claim. Measured: it did.
Returns:
Transaction report
Note: Due to :db/unique on :claim/file, attempting to claim
an already-claimed file will upsert (update the existing claim).
Use has-conflict? to check first if you want to prevent this.(claim-stale? file-path)(claim-stale? file-path threshold-ms)Check if a claim is stale (older than threshold).
Arguments: file-path - Path to check threshold-ms - Optional threshold (default: 10 minutes)
Returns: true if claim exists and is older than threshold
Check if a claim is stale (older than threshold). Arguments: file-path - Path to check threshold-ms - Optional threshold (default: 10 minutes) Returns: true if claim exists and is older than threshold
(cleanup-stale-claims!)(cleanup-stale-claims! threshold-ms)Release all stale claims (older than threshold).
Arguments: threshold-ms - Optional threshold (default: 10 minutes)
Returns: Map with :released-count and :released-files
Release all stale claims (older than threshold). Arguments: threshold-ms - Optional threshold (default: 10 minutes) Returns: Map with :released-count and :released-files
(cleanup-stdout-buffer! slave-id)Remove the stdout buffer for a ling (call on kill/terminate).
Arguments: slave-id - The ling's slave-id
Returns: true if buffer existed and was removed, false otherwise
Remove the stdout buffer for a ling (call on kill/terminate). Arguments: slave-id - The ling's slave-id Returns: true if buffer existed and was removed, false otherwise
(complete-task! task-id)Mark a task as completed and update slave stats.
Arguments: task-id - Task to complete
Returns: Transaction report or nil if task not found
Mark a task as completed and update slave stats. Arguments: task-id - Task to complete Returns: Transaction report or nil if task not found
Claims older than 10 minutes are considered stale (600,000 ms).
Claims older than 10 minutes are considered stale (600,000 ms).
(enter-critical-op! slave-id op-type)Mark a slave as being in a critical operation. Prevents swarm_kill from terminating this slave.
Arguments: slave-id - Slave entering critical operation op-type - Type of operation (:wrap :commit :dispatch)
Returns: Transaction report or nil if slave not found
Mark a slave as being in a critical operation. Prevents swarm_kill from terminating this slave. Arguments: slave-id - Slave entering critical operation op-type - Type of operation (:wrap :commit :dispatch) Returns: Transaction report or nil if slave not found
(exit-critical-op! slave-id op-type)Mark a slave as having completed a critical operation.
Arguments: slave-id - Slave exiting critical operation op-type - Type of operation (:wrap :commit :dispatch)
Returns: Transaction report or nil if slave not found
Mark a slave as having completed a critical operation. Arguments: slave-id - Slave exiting critical operation op-type - Type of operation (:wrap :commit :dispatch) Returns: Transaction report or nil if slave not found
(fail-task! task-id status)Mark a task as failed with error or timeout.
Arguments: task-id - Task to fail status - Failure status (:error or :timeout)
Returns: Transaction report or nil if task not found
Mark a task as failed with error or timeout. Arguments: task-id - Task to fail status - Failure status (:error or :timeout) Returns: Transaction report or nil if task not found
Get all active claims with their metadata. Delegates to queries/get-all-claims.
Get all active claims with their metadata. Delegates to queries/get-all-claims.
Get claim information for a file path. Delegates to queries/get-claims-for-file.
Get claim information for a file path. Delegates to queries/get-claims-for-file.
(get-critical-ops slave-id)Get current critical operations for a slave.
Returns: Set of active critical operations, or empty set if none/not found
Get current critical operations for a slave. Returns: Set of active critical operations, or empty set if none/not found
(get-stale-claims)(get-stale-claims threshold-ms)Get all claims that are older than the threshold.
Arguments: threshold-ms - Optional threshold (default: 10 minutes)
Returns: Sequence of stale claim maps with :file, :slave-id, :age-ms, :age-minutes
Get all claims that are older than the threshold. Arguments: threshold-ms - Optional threshold (default: 10 minutes) Returns: Sequence of stale claim maps with :file, :slave-id, :age-ms, :age-minutes
(get-stdout slave-id)(get-stdout slave-id n)Read the last N lines from a headless ling's stdout buffer.
Arguments: slave-id - The ling's slave-id n - Number of lines to read (default: 100)
Returns: Vector of {:idx N :text "..." :ts <inst>} maps, ordered oldest-first. Empty vector if no buffer exists.
Read the last N lines from a headless ling's stdout buffer.
Arguments:
slave-id - The ling's slave-id
n - Number of lines to read (default: 100)
Returns:
Vector of {:idx N :text "..." :ts <inst>} maps, ordered oldest-first.
Empty vector if no buffer exists.(get-stdout-buffer-info slave-id)Get metadata about a ling's stdout buffer (for diagnostics).
Arguments: slave-id - The ling's slave-id
Returns: Map with :line-count, :next-idx, :oldest-idx, :newest-idx or nil if no buffer exists.
Get metadata about a ling's stdout buffer (for diagnostics). Arguments: slave-id - The ling's slave-id Returns: Map with :line-count, :next-idx, :oldest-idx, :newest-idx or nil if no buffer exists.
(get-stdout-since slave-id since-idx)Read lines from a headless ling's stdout buffer since a given index. Uses binary search for O(log n) lookup on the monotonic :idx field.
Arguments: slave-id - The ling's slave-id since-idx - Return lines with :idx > since-idx
Returns: Vector of {:idx N :text "..." :ts <inst>} maps after since-idx. Empty vector if no buffer exists or no new lines.
Read lines from a headless ling's stdout buffer since a given index.
Uses binary search for O(log n) lookup on the monotonic :idx field.
Arguments:
slave-id - The ling's slave-id
since-idx - Return lines with :idx > since-idx
Returns:
Vector of {:idx N :text "..." :ts <inst>} maps after since-idx.
Empty vector if no buffer exists or no new lines.(init-stdout-buffer! slave-id)Initialize a stdout ring buffer for a headless ling. Called during headless spawn. Idempotent - resets if already exists.
Arguments: slave-id - The ling's slave-id
Returns: The buffer atom
Initialize a stdout ring buffer for a headless ling. Called during headless spawn. Idempotent - resets if already exists. Arguments: slave-id - The ling's slave-id Returns: The buffer atom
(refresh-claim! file-path)Refresh a claim's timestamp to prevent staleness. Use when a long-running operation needs to keep a claim active.
Arguments: file-path - Path to refresh
Returns: Transaction report or nil if claim not found
Refresh a claim's timestamp to prevent staleness. Use when a long-running operation needs to keep a claim active. Arguments: file-path - Path to refresh Returns: Transaction report or nil if claim not found
(release-claim! file-path)Release a file claim and dispatch :claim/file-released event.
When a claim is released, the event system notifies any lings that were waiting for access to this file (file-claim event cascade).
DUAL-STORE SYNC: the :claim-released hook (installed by the host) clears the claim from the logic db too, so no ghost claim is left there.
Arguments: file-path - Path to release
Returns: Transaction report or nil if claim not found
Release a file claim and dispatch :claim/file-released event. When a claim is released, the event system notifies any lings that were waiting for access to this file (file-claim event cascade). DUAL-STORE SYNC: the :claim-released hook (installed by the host) clears the claim from the logic db too, so no ghost claim is left there. Arguments: file-path - Path to release Returns: Transaction report or nil if claim not found
(release-claims-for-slave! slave-id)Release all file claims held by a slave.
Arguments: slave-id - Slave whose claims to release
Returns: Number of claims released
Release all file claims held by a slave. Arguments: slave-id - Slave whose claims to release Returns: Number of claims released
(release-claims-for-task! task-id)Release all file claims associated with a task.
Arguments: task-id - Task whose claims to release
Returns: Number of claims released
Release all file claims associated with a task. Arguments: task-id - Task whose claims to release Returns: Number of claims released
(remove-slave! slave-id)Remove a slave from the swarm. Also releases any file claims held by this slave.
Arguments: slave-id - Slave to remove
Returns: Transaction report or nil if slave not found
Remove a slave from the swarm. Also releases any file claims held by this slave. Arguments: slave-id - Slave to remove Returns: Transaction report or nil if slave not found
(reset-stdout-buffers!)Reset all stdout buffers (for testing only). Production code should use cleanup-stdout-buffer! per slave.
Reset all stdout buffers (for testing only). Production code should use cleanup-stdout-buffer! per slave.
Maximum number of stdout lines retained per headless ling. FIFO eviction drops oldest lines when cap is reached.
Maximum number of stdout lines retained per headless ling. FIFO eviction drops oldest lines when cap is reached.
Registry of stdout ring buffers for headless lings. Map of slave-id -> atom of {:lines [...] :next-idx N}. Lives outside DataScript because it's ephemeral mutable state.
Registry of stdout ring buffers for headless lings.
Map of slave-id -> atom of {:lines [...] :next-idx N}.
Lives outside DataScript because it's ephemeral mutable state.(update-slave! slave-id updates)Update an existing slave's attributes.
Arguments: slave-id - Slave to update updates - Map of attributes to update (supports all slave attrs)
Returns: Transaction report or nil if slave not found
Update an existing slave's attributes. Arguments: slave-id - Slave to update updates - Map of attributes to update (supports all slave attrs) Returns: Transaction report or nil if slave not found
(update-task! task-id updates)Update an existing task's attributes.
Arguments: task-id - Task to update updates - Map of attributes to update (uses :task/* keys)
Returns: Transaction report or nil if task not found
Common updates: {:task/status :completed :task/completed-at (conn/now)} {:task/status :error}
Update an existing task's attributes.
Arguments:
task-id - Task to update
updates - Map of attributes to update (uses :task/* keys)
Returns:
Transaction report or nil if task not found
Common updates:
{:task/status :completed :task/completed-at (conn/now)}
{:task/status :error}(with-critical-op slave-id op-type & body)Execute body while holding a critical operation guard. Ensures the critical op is properly released even on exception.
Usage: (with-critical-op slave-id :wrap (do-wrap-stuff))
Execute body while holding a critical operation guard.
Ensures the critical op is properly released even on exception.
Usage:
(with-critical-op slave-id :wrap
(do-wrap-stuff))cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |