cial/.claude/skills.src/cial:build/unrestricted.md
Eliot M 8505981889 feat(self-edit): make POST /api/v1/self/deploy synchronous
Old behaviour returned 202 with a deployId and expected the agent to
poll GET /deploy/:id — but that route lives on the Better-Auth-gated
deploy module, so localhost curl from inside the container got 401 on
every poll. The agent had no terminal signal and no log visibility,
matching the symptoms Eliot observed (stale-looking session, repeated
401s in core-back logs, no build output).

Mirror old-Cial's ergonomics: one synchronous request, blocks until
the build (and post-build restart) reach a terminal state, returns
{ ok, status, durationMs, exitCode, errorSummary, logTail } with HTTP
200 on success or 500 on failure. logTail is the last 8KB of the
deploy log file so the agent has the failure context inline without
needing a second round-trip.

- DeployService.waitForDone(deployId, timeoutMs): EventEmitter-based
  promise that resolves on the next 'done'/'cancelled' event for the
  given deployId, or immediately if the row is already terminal.
- DeployService.getLogPath(deployId) + DeployRepository.getLogPath:
  surface the persisted log_path for tail reading.
- self/router.ts: await waitForDone, read log tail, respond once.
- cial:build skills (restricted + unrestricted): drop the polling
  loop, document the synchronous response shape.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-29 14:44:47 +00:00

2.1 KiB

name description
cial:build Build any package inside the dev container (UNRESTRICTED mode). Default scope = all (protocol, sdk, core-ui, core-back, core-front, edge, platform-back, platform-front). Always invoke before cial:restart.

cial:build (unrestricted mode)

CIAL_UNRESTRICTED=1 — full workspace is buildable.

When to use

  • After any edit in platform/* or core/* (back, front, edge, protocol, sdk, ui).
  • Before invoking cial:restart.

Endpoint

POST http://127.0.0.1:4000/api/v1/self/deploy — localhost-gated, no auth. Hit core-back directly on port 4000; edge does not proxy /api/v1/*.

Synchronous: the request blocks until the build (and post-build restart) reach a terminal state. No polling. No separate status endpoint.

Steps

  1. Run the build (a full scope: "all" rebuild can take several minutes — be patient, do not retry):
    curl -sS --max-time 600 -X POST http://127.0.0.1:4000/api/v1/self/deploy \
      -H 'content-type: application/json' \
      -d "{\"scope\":\"auto\",\"sessionId\":\"$CIAL_SESSION_ID\"}"
    
  2. Read the response.
    • Success (HTTP 200):
      { "ok": true, "deployId": "...", "status": "ok", "scope": "all", "durationMs": 142103, "exitCode": 0, "errorSummary": null, "logTail": "..." }
      
    • Failure (HTTP 500):
      { "ok": false, "deployId": "...", "status": "error", "scope": "all", "durationMs": ..., "exitCode": 1, "errorSummary": "...", "logTail": "<last 8KB of build log>" }
      
      Read errorSummary + logTail, fix the code, re-run from step 1.

Scope

  • scope: "auto" (default) → all.
  • scope: "platform" → just platform packages — use this if you only changed platform/* (much faster, skips core).
  • scope: "all" → builds protocol, sdk, core-ui, core-back, core-front, edge, platform-back, platform-front.

Errors

  • 403 not_localhost — should never happen from inside the container.

See also

  • docs/self-edit/api.md — full contract.
  • docs/self-edit/recipes.md — copy-paste flows.
  • docs/architecture/deploy-pipeline.md — what happens under the hood.
  • docs/ops/deploy-logs.md — log location.