# Deploy

> Set up and run hoistable on this machine, then self-test it and report honestly what worked. It ships as a recipe, and on first use it fetches a verified toolchain, brings hoistable up in a sandbox, and grades it.

- Skill: `3dl-dev/deploy-2` (Agent Skill)
- Install (CLI): `npx skillmds@latest add 3dl-dev/deploy-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/3dl-dev/deploy-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: 3dl-dev (https://skillmd.com/u/3dl-dev)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/3dl-dev/deploy-2

---


# This skill sets hoistable up before it reports hoistable is up

You are about to bring **hoistable** up from a *recipe*, not from a finished instance. The
skill ships hoistable as source: a carried recipe plus the pin to the code that runs it, like
a self-extracting archive that carries both its contents and the unpacker. Before you tell
anyone hoistable is running, deploy it against **this** target and GRADE it honestly. You do
the work in-loop; nobody runs a command line. The material is the carried recipe, the
binds, the checks, and the acceptance in the sections below.

Two roles run through this. The **author** packaged hoistable as this skill on their machine.
The **receiver** is whoever installs it, a different target, whose substrate, secrets, and
paths you resolve here. You work so the receiver reaches a real, graded hoistable, or an honest
reason it could not, never a silent success.

## Recipe (run before your first report that hoistable is up)

1. **Cache / idempotency.** If hoistable is already up on this target in this session (a prior
   graded namespace exists, or a resolution is recorded here), reuse it, emit the Reusing
   line, and skip to step 6. Do not re-deploy over a live instance.

2. **Resolve the binds.** For each entry in the binds section, probe this target for the
   matching capability, and resolve the isolation substrate to the required strength the
   carried recipe names. If a *required* bind has no match here, or no substrate meets the
   required strength, STOP, deploy nothing, and report cannot-build naming the missing one.
   Never guess and never substitute. If you cannot positively confirm a required bind,
   treat it as missing.

3. **Self-extract the runtime (the bootstrap).** The carried recipe carries a pin under
   `operators` (`version`, `url`, `sha256`), but the code that runs the deploy lives
   *inside* that kit, so you unpack it yourself first, and only after verifying it. Do
   exactly this: (a) fetch the tarball at the pin `url`; (b) compute its sha256 and confirm
   it equals the pin's `sha256`, if it does not, STOP and report cannot-build (tampered or
   wrong kit), and never unpack or run an unverified tarball; (c) extract the verified
   tarball, that unpack IS the self-extraction, and it yields the runtime: `hoist/pins.py`
   (fetch and verify), `envelope/` (the enforced grader: isolation, honest grade,
   teardown), and the operator steps. From here the extracted runtime drives the graded
   pass and re-verifies the kit into its cache. Because you checked the sha256 by hand
   before unpacking, nothing unverified executes.

4. **Know early, then deploy.** Run the pre-check first, it deploys nothing. If it says
   cannot-build, stop at the door and give the user the named reason. Otherwise run the
   full graded pass through the extracted grader, which *enforces* the invariants: a
   runner-owned isolated namespace (non-destructive), and teardown. You never re-run
   hoistable's own singular deployment onto a live host.

5. **Grade.** The acceptance checks rebuild on THIS target. Compute the honest transfer
   score, how many of the acceptance checks passed, N of M, and name every check that did
   not transfer.

6. **Report** the outcome in one line, using one of the templates below. Never let a design
   read as a running system; if it did not transfer, say what did not.

7. **Hand off.** Point the user at any follow-up the carried recipe includes (how to
   extend it, operate it, or keep it running), so they can use hoistable, not merely have it
   installed.

Before your first report, state in one line what happened, only one line, and do not
narrate the loop, using one of these templates:
- "Built hoistable. Acceptance transferred N of M on this target. Ready."
- "Built hoistable, but N of M acceptance checks did not transfer here: [the specific checks]."
- "Cannot build hoistable: this target is missing [the named bind or substrate strength]."
- "Reusing the hoistable setup from earlier this session. Ready."

The failure to avoid: reporting hoistable is up because the recipe *looks* right. It is up only
when it deployed and its acceptance transferred on this target. Grade it, then report what
you measured.

## The carried recipe (the authority; the operators pin travels with it)

```json
{
  "_authored_by": "hoist author (self-hosting reference: hoistable's own Layer 2 config)",
  "app": "hoistable",
  "binds": [
    {
      "name": "git",
      "probe": "git --version",
      "required": true
    },
    {
      "name": "python3",
      "probe": "python3 --version",
      "required": true
    }
  ],
  "default_profile": "default",
  "operators": {
    "sha256": "8b1c4b72964d190f65fac09d0ef31611fbab6e4ba5d2dd17b9de985028fb7225",
    "url": "https://github.com/3dl-dev/hoistable/releases/download/operators-v0.7.0/hoistable-operators-0.7.0.tgz",
    "version": "0.7.0"
  },
  "profiles": {
    "default": {
      "acceptance": [
        {
          "check": "python3 tests/test_author.py",
          "name": "test_author"
        },
        {
          "check": "python3 tests/test_envelope.py",
          "name": "test_envelope"
        },
        {
          "check": "python3 tests/test_hoist.py",
          "name": "test_hoist"
        },
        {
          "check": "python3 tests/test_builder.py",
          "name": "test_builder"
        }
      ],
      "bringup": [
        {
          "name": "no-build",
          "run": "true"
        }
      ],
      "health": [
        {
          "check": "test -e .",
          "name": "clone-present"
        }
      ],
      "isolation": {
        "none": true,
        "why": "hermetic: runs the project's own tests in a throwaway clone; starts no daemons, binds no host ports, writes no shared state"
      }
    }
  },
  "source": {
    "clone": "https://github.com/3dl-dev/hoistable.git",
    "dir": "hoistable"
  }
}
```

## Binds (resolve these on the target; a missing required one is cannot-build)

- `git` (required), probe: `git --version`
- `python3` (required), probe: `python3 --version`
- isolation substrate: none required, this profile is hermetic (hermetic: runs the project's own tests in a throwaway clone; starts no daemons, binds no host ports, writes no shared state).

## Checks (invariants every deploy obeys)

- **Non-destructive.** The deploy lands in a runner-owned isolated namespace (its own name, ports, storage); a profile that declares no isolation is refused; teardown always runs. It never re-runs hoistable's own singular deployment onto a live host.
- **No silent success.** hoistable is graded on the real target; a run that cannot say it worked says what did not transfer. A design never reads as a running system.
- **Verified runtime.** The fetched kit is run only after its sha256 matches the carried pin; a tampered or unreachable kit is cannot-build, named.

## Acceptance (the held-back transfer test; the honest score)

- `test_author`: `python3 tests/test_author.py`
- `test_envelope`: `python3 tests/test_envelope.py`
- `test_hoist`: `python3 tests/test_hoist.py`
- `test_builder`: `python3 tests/test_builder.py`

