Receber por email
← Voltar para o catálogo

sling-dispatch

Instruction dispatch pipeline for routing work items to available agents. Implements a 7-stage fetch-allocate-prepare-hook-store-launch-confirm pipeline with batch convoy mode, formula expansion, idempotent dispatch, and crash recovery.

65estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: NOASSERTION

Como adicionar

/plugin marketplace add Tibsfox/gsd-skill-creator

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/sling-dispatch/svg)](https://www.skillteca.com.br/skills/sling-dispatch)
#ai

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Sling Dispatch

Instruction dispatch unit for the Gastown chipset. The sling takes a work item (bead) and routes it to an available polecat through a 7-stage pipeline. In hardware terms, the sling is the instruction fetch-decode-dispatch unit -- it resolves work items from state, selects an execution unit (polecat), prepares the execution context, and launches the agent. The sling does not execute work; it sets up the conditions for execution and confirms the dispatch was recorded.

Activation Triggers

This skill activates when:

  • The mayor needs to assign work items to available polecats
  • A convoy of beads is ready for dispatch to a rig
  • A formula template needs expansion into ordered dispatch steps
  • A partial dispatch needs recovery after a crash or session restart

Core Capabilities

The 7-Stage Dispatch Pipeline

Every dispatch flows through seven stages in strict order. Each stage completes before the next begins. If any stage fails, the pipeline halts at that stage and the partial state is recoverable.

FETCH       ALLOCATE      PREPARE       HOOK         STORE        LAUNCH       CONFIRM
  |            |             |            |             |            |            |
  v            v             v            v             v            v            v
resolve    select or     create       update work   write args   start agent   record
bead ID    spawn idle    isolated     item status   to durable   session       dispatch
to work    polecat       workspace    to 'hooked',  state file   with GUPP     in convoy
item                     (dir+ctx)    set assignee  (crash-safe)  context      tracking

Stage 1 -- Fetch:

Resolve the bead ID to a concrete work item from state. The bead must exist and must be in open status. If the bead is already hooked, in_progress, or done, the dispatch is a no-op (idempotency guarantee).

const state = new StateManager({ stateDir: '.chipset/state/' });

async function fetchBead(beadId: string): Promise<WorkItem | null> {
  const workItem = await state.getWorkItem(beadId);

  if (!workItem) {
    // Bead does not exist -- dispatch fails
    return null;
  }

  if (workItem.status !== 'open') {
    // Already dispatched or completed -- idempotent no-op
    return null;
  }

  return workItem;
}

Stage 2 -- Allocate:

Select an available polecat from the agent pool, or spawn a new one if the pool has capacity. The allocator prefers idle polecats over spawning new ones to minimize resource usage.

async function allocatePolecat(rig: string): Promise<AgentIdentity | null> {
  // List all polecats for this rig
  const polecats = await state.listAgents({ role: 'polecat', rig });

  // Prefer idle polecats (already spawned, ready for work)
  const idle = polecats.filter(p => p.status === 'idle');
  if (idle.length > 0) {
    return idle[0];
  }

  // Check if we can spawn a new polecat (within max_parallel limit)
  const active = polecats.filter(p => p.status === 'active');
  const config = await state.getChipsetConfig();

  if (active.length >= config.dispatch.max_parallel) {
    // Pool is full -- cannot dispatch right now
    return null;
  }

  // Spawn a new polecat
  return state.createAgent({
    role: 'polecat',
    rig,
    status: 'idle',
  });
}

Stage 3 -- Prepare:

Create the isolated workspace for the polecat. This includes setting up the working directory (git worktree or clean checkout) and assembling the execution context (bead details, convoy membership, relevant file paths).

async function prepareWorkspace(
  polecat: AgentIdentity,
  workItem: WorkItem
): Promise<WorkspaceContext> {
  // Create a working branch for the polecat
  const branchName = `polecat/${workItem.beadId}`;

  // Assemble the execution context
  const context: WorkspaceContext = {
    agentId: polecat.id,
    beadId: workItem.beadId,
    branch: branchName,
    title: workItem.title,
    description: workItem.description,
    priority: workItem.priority,
  };

  return context;
}

Stage 4 -- Hook:

Update the work item status to hooked and set the assignee. This is the binding step -- after this, the bead is claimed by the polecat and cannot be dispatched to another agent.

async function hookBead(
  workItem: WorkItem,
  polecat: AgentIdentity
): Promise<void> {
  // Update work item status atomically
  workItem.status = 'hooked';
  workItem.assignee = polecat.id;
  workItem.hookStatus = 'pending';
  await state.updateWorkItem(workItem);

  // Set the polecat's hook
  await state.setHook(polecat.id, workItem.beadId, workItem.title);
}

This is the idempotency boundary. Re-dispatching a bead that is already hooked returns a no-op at Stage 1 (the fetch rejects non-open beads). The hook stage itself is atomic -- the work item status and hook file are written using the write-then-rename pattern.

Stage 5 -- Store:

Write the dispatch arguments to durable state. This creates a dispatch record that survives process crashes. If the sling crashes after Store but before Launch, the dispatch can be resumed from this record.

interface DispatchRecord {
  beadId: string;
  agentId: string;
  branch: string;
  context: WorkspaceContext;
  stage: 'stored' | 'launched' | 'confirmed';
  createdAt: string;
}

async function storeDispatch(
  context: WorkspaceContext,
  polecat: AgentIdentity
): Promise<void> {
  const record: DispatchRecord = {
    beadId: context.beadId,
    agentId: polecat.id,
    branch: context.branch,
    context,
    stage: 'stored',
    createdAt: new Date().toISOString(),
  };

  // Write atomically to dispatch state
  const recordPath = join(stateDir, 'dispatch', `${context.beadId}.json`);
  await atomicWrite(recordPath, serializeSorted(record));
}

Stage 6 -- Launch:

Start the polecat's agent session with the GUPP execution context. The polecat receives its hook (set in Stage 4) and the dispatch context (stored in Stage 5). GUPP activates immediately -- the polecat begins work without waiting for confirmation.

async function launchPolecat(
  polecat: AgentIdentity,
  context: WorkspaceContext
): Promise<void> {
  // Update agent status to active
  await state.updateAgentStatus(polecat.id, 'active');

  // Update dispatch record to 'launched'
  const recordPath = join(stateDir, 'dispatch', `${context.beadId}.json`);
  const record = await readJson<DispatchRecord>(recordPath);
  record.stage = 'launched';
  await atomicWrite(recordPath, serializeSorted(record));

  // Send work assignment mail to polecat
  const assignmentMail: AgentMessage = {
    from: 'mayor',
    to: polecat.id,
    channel: 'mail',
    payload: `ASSIGNED: ${context.beadId} - ${context.title}`,
    timestamp: new Date().toISOString(),
    durable: true,
  };
  await sendMail(assignmentMail);

  // The polecat detects the hook via polling and enters GUPP mode
}

Stage 7 -- Confirm:

Write the dispatch confirmation to convoy tracking. This closes the dispatch pipeline and records the bead-to-agent assignment in the convoy's progress state.

async function confirmDispatch(
  context: WorkspaceContext,
  polecat: AgentIdentity,
  convoyId?: string
): Promise<void> {
  // Update dispatch record to 'confirmed'
  const recordPath = join(stateDir, 'dispatch', `${context.beadId}.json`);
  const record = await readJson<DispatchRecord>(recordPath);
  record.stage = 'confirmed';
  await atomicWrite(recordPath, serializeSorted(record));

  // If part of a convoy, update convoy progress
  if (convoyId) {
    await state.updateConvoyProgress(convoyId);
  }

  // Notify the witness of the new dispatch
  const witnessMail: AgentMessage = {
    from: 'mayor',
    to: 'witness',
    channel: 'mail',
    payload: `DISPATCH: ${context.beadId} -> ${polecat.id} on branch ${context.branch}`,
    timestamp: new Date().toISOString(),
    durable: true,
  };
  await sendMail(witnessM
Compartilhar X LinkedIn