Skip to content
QuarrySystemsPublic

Latest commit

 

History

317 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pangolin Scale

Secure, deterministic, auditable execution of AI agents — submit a DAG of tasks, fan out safely across an isolated, credential-sealed worker pool, and get back a reviewable patch artifact and a verifiable audit trail of exactly what ran — tamper-detecting by default, tamper-evident at the external-immutable (S3 Object Lock) tier.

A registry-backed dispatch SDK for sub-agent compute workloads. Integrators register capabilities, subagents, and env bundles once at deploy time, then dispatch against them at run time — the same code path running locally against Docker as in production against Fargate + S3. Provider seams (compute, credentials, storage, secret store, channel, result sink) keep the registry shape and dispatch contract identical across environments. The orchestrator layer adds a DAG planner on top: disjoint resource locks fan out in parallel; shared locks serialize; each finished task yields a reviewable patch (result_ref); the whole run produces a tamper-evident audit trail — verifiable at the external-immutable tier (S3 Object Lock), tamper-detecting on the local default path.

Pangolin Scale is source-available under the Business Source License 1.1 — see LICENSE and LICENSING.md.

📖 Docs: https://quarrysystems.github.io/pangolin

Install

pnpm add @quarry-systems/pangolin-client

The caller-side SDK pulls in @quarry-systems/pangolin-core (interface contracts only) transitively. Provider packages — pangolin-providers-*, pangolin-storage-* — are composed at the deployment boundary; install only the ones your target stack uses.

Hello World

import { PangolinClient, NoopCredentialProvider, StdoutResultSink } from '@quarry-systems/pangolin-client';
import { LocalStorageProvider } from '@quarry-systems/pangolin-storage-local';
import { LocalDockerProvider } from '@quarry-systems/pangolin-providers-local-docker';

const client = new PangolinClient({
  namespace: 'hello-world',
  compute: { 'local-docker': new LocalDockerProvider({ allowUnpinnedImage: true }) },
  credentials: { none: new NoopCredentialProvider() },
  storage: new LocalStorageProvider({ rootDir: '/tmp/pangolin' }),
  targets: { local: { compute: 'local-docker', credentials: 'none' } },
  resultSink: new StdoutResultSink(),
});

await client.capabilities.register({ name: 'echo-cap', files: { 'pangolin-setup.sh': '#!/bin/sh\necho "hello from pangolin-worker"\n' } });
await client.subagent.register({ name: 'echo', systemPrompt: 'Just exit.', capabilities: ['echo-cap'] });
await client.env.register({ name: 'minimal', values: { LOG_LEVEL: 'info' } });

const result = await client.dispatch({ subagent: 'echo', env: 'minimal', target: 'local', workerImage: 'ghcr.io/quarrysystems/pangolin-worker:latest' });
console.log(result.stdout);

The full runnable version (with mkdtemp + cleanup, comments, and a Fargate + S3 production variant) lives at examples/hello-world/.

Offload

The orchestrator surfaces as the pangolin orch subcommand. A plan.json describes a DAG of agent tasks with depends_on, resourceLocks, and per-task subagent/env/target bindings. Disjoint resource locks fan out in parallel; shared locks serialize automatically. Each finished task drops a reviewable patch artifact (result_ref). The run produces a tamper-evident audit bundle — verifiable at the external-immutable tier (S3 Object Lock), tamper-detecting on the local path.

pangolin orch serve              # long-running driver (sole DB owner)
pangolin orch validate plan.json # pre-flight plan validation, no submit
pangolin orch submit plan.json   # non-blocking; prints a run id
pangolin orch watch <run-id>     # follow the run to completion
pangolin orch audit <run-id>     # exportable evidence bundle (verifies; names the guarantee tier)
pangolin orch audit <run-id> --out bundle.json   # write the bundle to a file
pangolin verify bundle.json      # re-verify an exported bundle against its external anchor
pangolin pipeline register|validate|list         # manage declared worker pipelines

See examples/offload-fanout/ for the runnable demo — a three-task fan-out plan that exercises parallel locks, patch artifacts, and the audit command end-to-end.

Typed-product handoff

Tasks in a plan can now declare dependent inputs with needs instead of hand-wiring depends_on — a downstream item names what it consumes and which upstream task produces it, and the dependency edge is derived automatically:

"needs": { "patch": { "from": "edit-a", "select": { "kind": "patch" } } }

The orchestrator validates the whole DAG at submit (every needs must resolve to a real upstream item and the graph must stay acyclic), then at fire time resolves each upstream task's content-addressed product and hands it to the worker, which materializes it under inputs/ before the agent runs (e.g. inputs/patch). Both consumed inputRefs and produced outputRefs are sealed into the dispatch manifest and the audit evidence, and pangolin verify proves provenance closure — every consumed input ref must be a sealed product of a completed task in the same run — surfaced as a fifth handoff check row alongside the existing chain / root / signature / anchor checks. See examples/handoff-dag/ for the runnable demo — a two-task plan where edit-a produces a patch and apply-patch binds it via needs and applies it with git apply inputs/patch.

What's in this repo

Sixteen packages under packages/:

Package One-liner
pangolin-core Types-only contract package. Every other pangolin package depends on this; nothing depends on anything else by default.
pangolin-client Caller-side SDK. PangolinClient is the single entry point integrators construct: registration + dispatch surface, with wired-in providers.
pangolin-product Consumer-side read of a dispatch's product — the output sentinel and the content-addressed artifacts it names. Keyed on storage + dispatchId, so a caller that never held (or has since lost) the fire() handle can still recover what a dispatch produced. Depends only on pangolin-core.
pangolin-cli The pangolin binary. Thin CLI over PangolinClient that resolves pangolin.config.{ts,js,mjs} and dispatches to subcommands. Canonical privileged entry point.
pangolin-mcp Stdio MCP server exposing exactly nine run-time, orchestration-safe tools. register / assign are deliberately absent — privileged ops never reach the AI loop.
pangolin-worker Container-side runtime. One process per dispatch. Fetches bundles, verifies integrity, overlays the workspace, resolves secrets, hands off to a RuntimeAdapter. The runtime is a block-pipeline runner — agent / script / capture blocks, seal auto-appended.
pangolin-runtime-claude-code MVP RuntimeAdapter implementation. Prompt rendering, claude --print invocation, Claude-specific merge rules, needs_input sentinel detection.
pangolin-providers-fargate ComputeProvider backed by AWS ECS Fargate (RunTask / DescribeTasks / StopTask). Production target.
pangolin-providers-local-docker ComputeProvider backed by the local Docker daemon via dockerode. Developer iteration + local smoke suite.
pangolin-providers-aws-creds CredentialProvider wrapping the AWS SDK default credential chain. Lazy resolution, no extra caching.
pangolin-storage-s3 StorageProvider backed by S3. Content-addressed object layout, integrity-verified on read. Production target.
pangolin-storage-local StorageProvider backed by the local filesystem. Pairs with pangolin-providers-local-docker for the local stack.
pangolin-secret-store SecretStore seam plus impls — AwsSecretStore (AWS Secrets Manager), LocalSecretStore (on-disk), and a storeFromConfig factory. pangolin-client takes injected per-target stores (secretStores); the worker builds its store via storeFromConfig.
pangolin-orchestrator Orchestrator engine (codename pangolin-offload): named queues, depends_on resolution, resource locks, a fire-and-reconcile tick loop, SQLite run-state, typed-product handoff (needs → content-addressed inputRefs), per-queue execution patterns with audited dynamic spawn, and provenance-closure verification, behind pluggable Executor / Trigger seams.
pangolin-signer-aws-kms AWS KMS asymmetric ECDSA-P256 Signer for the audit seal. Keeps the KMS SDK out of pangolin-core.
pangolin-verify Standalone audit-bundle verifier — the artifact an auditor runs, with no orchestrator dependency. Owns the RFC 3161 / ASN.1 (pkijs) dependency so pangolin-core stays dependency-light.

Plus:

  • examples/ — runnable worked examples: hello-world/ (the §4.4 worked example, also the integrator on-ramp); offload-fanout/ (the headline offload demo — locks + deps + concurrency + patch escape + audit); handoff-dag/ (typed-product handoff: B builds on A's patch); pattern-mapreduce/ (dynamic fan-out: one item grows to five, provenance-verified); pattern-dogfood/ (gated circle-back via spawn); data-mapreduce/ (the data pack: a second domain on the same engine, fully offline).
  • Architecture decisions — ADRs for the substantive design decisions taken during MVP design (published in the docs site).
  • docker/ — the published worker OCI image build context.

User guides

Start here if you're new:

  • Getting started — zero-to-first-dispatch on local Docker. Build the worker image, write pangolin.config.mjs, wire the CLI and MCP server, register and dispatch.
  • Your first offload run — submit a small DAG, watch it fan out under resource locks, and verify the audit bundle.

Reference:

  • Dispatch lifecycle — what each event in the worker stdout stream means, which lifecycle step each dispatch.failed reason maps to.
  • Worker file layout — where to put files so the worker picks them up (skills, settings, plugins, setup scripts), and the pangolin-setup.sh single-slot constraint that catches first-time authors.
  • Sync capabilities & subagents — pangolin capabilities sync / pangolin subagent sync reference, the claude-code and stoa providers shipped today, and how to author a new one.
  • Handle needs_input — how a sub-agent pauses for clarification, what the orchestrator does with the question, and how re-dispatch threads continuity through partial_state.
  • How an offload run executes — run a DAG of agent tasks unattended with pangolin orch serve | submit | watch | cancel | audit: queues/deps/resource-locks, the patch escape (result_ref), and the verifiable audit bundle + guarantee tiers.

Extension + deployment:

  • Writing a provider — plug in a new compute backend, storage layer, credential source, or result sink.
  • Remote Docker dispatch — orchestrate from one machine, run workers on another machine's Docker daemon.

Architecture

For the end-to-end runtime process (register → CLI/MCP surfaces + the §10.6 privilege boundary → dispatch vs orch → worker sandbox → patch escape → tamper-evident audit), see the Architecture overview — one rendered diagram of the whole flow. The graph below is the complementary package dependency view.

The package dependency graph (§8 of the spec). pangolin-core is the types-only sink; every arrow flows toward it:

graph TD
  core[pangolin-core<br/><i>types only</i>]
  client[pangolin-client]
  cli[pangolin-cli]
  mcp[pangolin-mcp]
  worker[pangolin-worker]
  runtime[pangolin-runtime-claude-code]
  pfargate[pangolin-providers-fargate]
  plocal[pangolin-providers-local-docker]
  pawscreds[pangolin-providers-aws-creds]
  ss3[pangolin-storage-s3]
  slocal[pangolin-storage-local]
  secretstore[pangolin-secret-store]
  orch[pangolin-orchestrator<br/><i>offload engine</i>]
  product[pangolin-product<br/><i>product read</i>]
  signerkms[pangolin-signer-aws-kms]
  verify[pangolin-verify<br/><i>auditor-run verifier</i>]

  client --> core
  client --> secretstore
  cli --> client
  mcp --> client
  mcp --> orch
  worker --> core
  worker --> secretstore
  worker --> ss3
  worker --> slocal
  runtime --> core
  pfargate --> core
  plocal --> core
  pawscreds --> core
  ss3 --> core
  slocal --> core
  secretstore --> core
  orch --> core
  orch --> client
  product --> core
  signerkms --> core
  verify --> core
Loading

ASCII rendering of the same graph:

pangolin-core                              (types only)
   ▲
   ├── pangolin-client                     (caller-side SDK)
   │     ▲
   │     ├── pangolin-cli                  (binary `pangolin`)
   │     ├── pangolin-mcp                  (stdio MCP server, run-time tools only; also depends on pangolin-orchestrator)
   │     └── pangolin-orchestrator         (offload engine — queues/deps/locks, serve, operations API, tamper-evident audit; CLI `pangolin orch` + client MCP tools)
   ├── pangolin-worker                     (container-side runtime; also depends on pangolin-secret-store + both storage packages)
   ├── pangolin-runtime-claude-code        (RuntimeAdapter impl)
   ├── pangolin-providers-fargate          (ComputeProvider, AWS Fargate)
   ├── pangolin-providers-local-docker     (ComputeProvider, local Docker)
   ├── pangolin-providers-aws-creds        (CredentialProvider, AWS)
   ├── pangolin-storage-s3                 (StorageProvider, S3)
   ├── pangolin-storage-local              (StorageProvider, local FS)
   ├── pangolin-secret-store               (SecretStore seam: AWS + Local; pangolin-client and pangolin-worker also depend on it)
   ├── pangolin-product                    (consumer-side product read — sentinel + artifacts, keyed on storage + dispatchId)
   ├── pangolin-signer-aws-kms             (Signer impl, AWS KMS ECDSA-P256)
   └── pangolin-verify                     (standalone audit-bundle verifier — no orchestrator dependency)

No Pangolin Scale package depends on another Quarry Systems library (Stoa, Bedrock, RaState, etc.). The constraint is enforced by a CI allowlist check on package.json dependencies.

Documentation

  • Roadmap — what's shipped in V1, what's planned next (V1.1, additive), and what's left as a branch. Also as a docs-site page.
  • Changelog — notable changes per release. Releasing documents how a release is cut (manual today).
  • Full MVP design spec — the §1–§11 design canon.
  • Orchestrator architecture spec — the pangolin-offload design: registries, effect tiers, queues/deps/locks, the intent outbox, and the trunk trap-check driving the pangolin-orchestrator package.
  • Offload V1 delivery spec — the shipped V1 slice (serve + escape + tamper-evident audit + operator surface), the security/determinism/auditability edge, and the honesty constraints. See also How an offload run executes.
  • Architecture decisions — twenty ADRs covering package scope, repo location, runtime-adapter seam, secret TTL, lifecycle vocabulary, MCP auth model, the source-available (BSL) license, orchestration-as-a-separate-layer (ADR-0018, superseding ADR-0010), target as an isolation boundary rather than a router (ADR-0019), the dispatch product read as a storage-keyed public contract (ADR-0020), and more.
  • Examples — worked, runnable demonstrations against the local provider stack.

Common commands

pnpm install            # install workspace deps
pnpm -r run lint        # lint every package
pnpm -r run test        # test every package
pnpm -r run typecheck   # typecheck every package
pnpm -r run build       # build every package

License

Pangolin Scale is source-available under the Business Source License 1.1 — see LICENSE and LICENSING.md.

Releases

Packages

Contributors

Languages