Autonomy CLI runbook — connector goals from the shell

Practical runbook: how Subactor turns a natural-language (NL) goal into governed URI Process steps, starting from the shell CLI. Focus example: documentation in the docs repo published to docs.subactor.com httpdocs.

Related (platform-internal, more detailed on single concerns):

DocScope
platform/docs/URI_PROCESS_AUTONOMY.mdContract AQL / OQL / URI layers
platform/docs/GITHUB_PLESK_URI_PROCESSES.mdGitHub + Plesk recipes, www sync
platform/docs/AUTONOMY_CONTRACTS.mdAutonomy contracts + delegation
www/deployment/PLESK.mdwww → subactor.com httpdocs (working path)
orchestrator/README.mdThin NL\ticket\OQL → urirun hub

1. Current state (what works)

Stack map

LayerWhereRoleStatus (after recent www/ publish)
Founder CLIplatform/bin/subactor (PATH: ~/.local/bin/subactor)NL ask → control :8091, tickets, plans, REST proxyWorks when platform is up + SUBACTOR_ADMIN_TOKEN
Orchestrator CLIorchestrator/bin/subactor-run.mjsRecipe / ticket / stub-NL → AQL gate → urirunWorks for known recipes; NL is stub (no free-form URI invent)
Control / panel:8091Plans, autonomy contracts, integrations, delegationLocal Docker stack
Planfile:8765 + .planfile/Tickets with uri_processesImport recipes work (e.g. www sync)
AQL / contractscontracts/, runtimeWHO may run WHATPortfolio + TestQL validation
OQLcontrol / bridgeWHAT (process.run, plesk.site.sync, …)Dry-run planners; apply via urirun
URI / urirunconnectors/services/urirun-nodeHOW (plesk://…, github://…)Live Plesk sync path proven for www
OpenRouteragents llm-gatewayIntent / planning onlyOptional; deterministic connectors do FTP/SFTP
Vaultbrowser-agent / encrypted entriesCredentials (plesk-runtime, plesk-sftp, …)Bootstrap + lease model exists
Plesk syncplesk://host/site/command/syncTree upload to /httpdocswww → subactor.com dry-run + apply (gate PLESK_SYNC_APPLY=1)

CLI entry points (start here)

# Founder control plane (needs live platform :8091)
ln -sfn ~/github/subactor/platform/bin/subactor ~/.local/bin/subactor
subactor health
subactor ask "zsynchronizuj www do httpdocs"          # LLM intent → ticket/plan
subactor ask "..." --execute                          # approve + execute
subactor ask "..." --autonomous <contract_id>         # within contract bounds
subactor tickets
subactor plans --status proposed
subactor dispatch

# Thin orchestrator (recipe-first; no OpenRouter key in this package)
cd ~/github/subactor/orchestrator
node bin/subactor-run.mjs --recipe ../www/deployment/www-httpdocs-sync.urirun.json
node bin/subactor-run.mjs --nl "zsynchronizuj www"    # phrase stub only
# Founder bypass: SUBACTOR_ADMIN_TOKEN set → human_approval skipped; still dry-run by default
# Live apply: --execute + PLESK_SYNC_APPLY=1 on urirun-node

What already works for publish

CapabilityCurrentNotes
Probe SFTP/FTPplesk://host/site/query/methodsDeterministic
Dry-run syncplesk://host/site/command/sync apply=falseDefault; hashes + file plan
Apply syncsame URI apply=true + PLESK_SYNC_APPLY=1Env gate, not LLM
Source allowlistbasename www or docs or PLESK_SYNC_ALLOWED_SOURCESdocs allowlisted
NL phrases (www + docs)agents/nlp-uri-phrases.yamlPolish/English sync phrases → dry-run URI
Recipe + Planfile importwww/deployment/www-httpdocs-sync.*, docs/deployment/docs-httpdocs-sync.*Reusable ticket shapes
Founder CLI bypassSUBACTOR_ADMIN_TOKEN on subactor-runAllowlist *; still respects apply env

OpenRouter role today: intent / model selection / plan proposal only. Once URI + payload are known, FTP/SFTP ensure and sync are **deterministic connector calls** — no LLM in the upload path.


2. Gaps (better autonomy + subtask delegation)

GapWhy it blocks the docs goalTarget
Auto-create SFTP from subscriptionVault entries often hand-bootstrappedplesk://host/ftpuser/command/ensure → vault plesk-sftp as a first URI step
Multi-repo / multi-domain syncAllowlist is www-centricAllow docs (and prefixes) for docs.subactor.com
Docs recipeOnly www recipe existsdocs-httpdocs-sync.urirun.json + Planfile import
NL routing for multi-step goalsStub NL / single-intent modelsDecompose NL → ordered uri_processes + content subtask
Content generation into docs/Manual / external editorOptional LLM step → write files → commit; sync stays deterministic
Domain / subscription capabilityManual Plesk UI / APIPreflight URI: domain exists, TLS, httpdocs writable
Vault lease in CLI pathIntegrations UI / secret-linkCLI/recipe can ensure-then-lease without pasting secrets
Founder vs bot allowlistsAdmin * vs bot plesk://*Document + TestQL: founder bypass ≠ bot expand
Delegation of subtasksTicket respond/delegate existsAuto-split: content bot vs publish bot vs human TLS check
HTTPS verifyManual curlURI or OQL health check after apply

3. Proposed model — NL only example

User says only:

„stwórz dokumentację w folderze docs i repo docs i opublikuj dokumentację
dla systemu subactor pod domeną docs.subactor.com”

Pipeline (target)

flowchart TD
  NL[NL shell: subactor ask / subactor-run] --> LLM[OpenRouter via llm-gateway]
  LLM --> Plan[Planfile ticket + uri_processes]
  Plan --> AQL[Contract AQL gate]
  AQL --> OQL[OQL process.run / plesk.*]
  OQL --> URI[urirun-node]
  URI --> Pre[Domain / subscription preflight]
  Pre --> Cred[ftpuser ensure → vault]
  Cred --> Content[LLM or human: docs content]
  Content --> Sync[plesk://…/sync dry-run then apply]
  Sync --> Verify[HTTPS verify docs.subactor.com]
  AQL -.->|out of contract| Human[human:founder ticket]

Ordered steps (current vs target)

#StepCurrentTargetLLM?
0Parse NL → intent + fieldssubactor ask / intent models; orchestrator NL stubSame + multi-goal decomposition (docs content + publish)Yes (intent only)
1Open Planfile ticket with uri_processesManual import / www recipeAuto from NL + recipe template docs-httpdocs-syncNo (template fill)
2AQL gateContracts + founder bypassSame; docs publish under ALLOW URI_PROCESS plesk://*No
3Ensure domain / subscriptionManual / Integrations UIplesk://… query (domain, hosting, TLS flags)No
4Ensure SFTP → vaultDocumented URI; often manualAlways first automated step before syncNo
5Generate/update docs in docs/Human / CursorOptional content bot; commit to subactor/docsOptional
6Sync dry-runWorks for www; not for docs allowlistSame URI, source_dir=…/docs, domain docs.subactor.comNo
7Sync applyPLESK_SYNC_APPLY=1Same gate; founder may --executeNo
8Verify HTTPSManualCurl/health URI; fail → ticketNo

4. Where the LLM participates vs deterministic steps

PhaseActorToolingLLM
Intent extractionllm-gateway → OpenRoutersubactor ask, /api/llm/intentYes — typed JSON intent / model id
Plan shapeorchestrator / controlrecipe + uri_processesPrefer no — fill known recipe
Contract checkruntime AQLcontractCheckerNo
Credential ensureurirun Plesk connectorplesk://host/ftpuser/command/ensureNo
File syncurirun Plesk connectorplesk://host/site/command/syncNo
Docs prose / structureoptional content agentwrite into docs/ gitOptional
Escalation textcontrol / Planfileticket responseOptional

Rule: OpenRouter never holds FTP/SFTP passwords and never performs upload. Connectors read vault leases; apply requires explicit env gate.


5. USER vs SYSTEM — APIs / languages / CLIs

Start from the shell. Prefer deterministic CLIs when the URI is already known.

StepUSER doesSYSTEM doesCLI / API / language
Bootstrap PATH + tokenSymlink CLI; set SUBACTOR_ADMIN_TOKEN in platform/.envbash: subactor
Healthsubactor healthControl :8091HTTP GET /health
NL goalTypes Polish/English sentenceIntent → ticket → proposed plansubactor ask "…" → POST control LLM + Planfile
Or skip LLMPass recipe pathLoad uri_processes, topo-runnode bin/subactor-run.mjs --recipe …
Approve / autonomy--execute or --autonomous <id> or panel approveAQL check; dispatchCLI flags / REST /api/plans/*
Founder bypassExport admin tokenSkip human_approval; widen URI allowlistenv SUBACTOR_ADMIN_TOKEN
Ensure SFTPOnce: approve high-risk step if contract requiresCreate user, write vault entryURI plesk://host/ftpuser/command/ensure via urirun POST /run
ContentReviews PR/diff or writes docsOptional LLM write + git commitgit in docs/ repo; not urirun
Dry-run syncReviews file plan / hashesPlan onlyURI sync apply=false
Live syncSets PLESK_SYNC_APPLY=1 on node (or founder policy)Upload via SFTP/FTPURI sync apply=true
VerifySpot-check browserOptional automated GETcurl -fsS https://docs.subactor.com/
Out of scopeMaintains preauthorized mandates/providersResolution Engine selects actor/provider and monitors SLAPlanfile + authority graph

Languages / packages (no secrets in docs)

ConcernPackage / path
Shell founder CLIplatform/bin/subactor (bash → curl → :8091)
Orchestrator@subactor/orchestrator — JS (runTask)
Bridge OQL plannerconnectors/services/bridgeplanHttpdocsSync
Plesk connectorurirun-connector-plesk (external) — Python site_sync
Phrasesagents/nlp-uri-phrases.yaml
Contractscontracts/**/*.contract.aql

6. Concrete flow — docs → docs.subactor.com

Mirror of the proven www → subactor.com path, adapted for docs.

6.1 Preconditions

CheckCurrentTarget
Domain docs.subactor.com on Plesk subscriptionAssumed / CNAME in repoPreflight URI confirms
Vault plesk-sftp (or ftp)Often manualftpuser/command/ensure
Allowlist includes docs treeGap (www only by default)PLESK_SYNC_ALLOWED_SOURCES includes docs path or basename docs
RecipeMissingAdd beside www recipe
CNAME / site files in docs/Present (docs.subactor.com)Keep; sync preserves remote .htaccess / .well-known

6.2 Target recipe shape (illustrative — no secrets)

{
  "id": "docs-httpdocs-sync",
  "name": "Sync docs → Plesk httpdocs (docs.subactor.com)",
  "situation": {
    "source_dir": "/home/tom/github/subactor/docs",
    "host": "prototypowanie.pl",
    "domain": "docs.subactor.com"
  },
  "uri_processes": [
    {
      "id": "docs-domain-preflight",
      "uri": "plesk://host/api/query/request",
      "payload": {"path": "/api/v2/domains"},
      "human_approval": false
    },
    {
      "id": "docs-sftp-ensure",
      "uri": "plesk://host/ftpuser/command/ensure",
      "payload": {
        "kind": "system",
        "domain": "docs.subactor.com",
        "vault_entry_id": "plesk-sftp"
      },
      "depends_on": ["docs-domain-preflight"],
      "human_approval": true
    },
    {
      "id": "docs-methods",
      "uri": "plesk://host/site/query/methods",
      "payload": {"host": "prototypowanie.pl"},
      "depends_on": ["docs-sftp-ensure"],
      "human_approval": false
    },
    {
      "id": "docs-sync-dry-run",
      "uri": "plesk://host/site/command/sync",
      "payload": {
        "source_dir": "/home/tom/github/subactor/docs",
        "remote_path": "/httpdocs",
        "host": "prototypowanie.pl",
        "domain": "docs.subactor.com",
        "apply": false
      },
      "depends_on": ["docs-methods"],
      "human_approval": false
    },
    {
      "id": "docs-sync-apply",
      "uri": "plesk://host/site/command/sync",
      "payload": {
        "source_dir": "/home/tom/github/subactor/docs",
        "remote_path": "/httpdocs",
        "host": "prototypowanie.pl",
        "domain": "docs.subactor.com",
        "apply": true
      },
      "depends_on": ["docs-sync-dry-run"],
      "human_approval": false
    }
  ]
}

Content generation (LLM) is a separate preceding ticket or plan step writing into the git repo — not an argument to sync.

6.3 Operator cheat sheet (today → tomorrow)

Today (www pattern, adapt manually for docs):

# 1) Prefer recipe without inventing URI
cd ~/github/subactor/orchestrator
node bin/subactor-run.mjs --recipe ../www/deployment/www-httpdocs-sync.urirun.json

# 2) Or founder NL → control (intent only)
subactor ask "zsynchronizuj www do httpdocs" --json

# 3) Live apply only after dry-run OK
# on urirun-node host: export PLESK_SYNC_APPLY=1
node bin/subactor-run.mjs --recipe ../www/deployment/www-httpdocs-sync.urirun.json --execute

Tomorrow (docs autonomy):

# NL (intent → multi-step ticket)
subactor ask "stwórz dokumentację w folderze docs i opublikuj na docs.subactor.com" \
  --autonomous <docs-publish-contract-id>

# Or deterministic
node bin/subactor-run.mjs --recipe ../docs/deployment/docs-httpdocs-sync.urirun.json
# content bot ticket completes first; then:
node bin/subactor-run.mjs --recipe ../docs/deployment/docs-httpdocs-sync.urirun.json --execute
curl -fsS -o /dev/null -w "%{http_code}\n" https://docs.subactor.com/

6.4 Allowlist / safety

ControlMechanism
Source dirsbasename allowlist / PLESK_SYNC_ALLOWED_SOURCES
Live uploadPLESK_SYNC_APPLY=1 on urirun-node
Who may callContract AQL ALLOW URI_PROCESS plesk://*
Irreversible credshuman_approval: true on ensure (unless founder admin policy)
SecretsVault entries only; never in URI payload, tickets, or this doc

7. Subtask delegation (autonomy pattern)

SubtaskPreferred actorQueueApproval
Intent / plan proposalbot + LLM gatewaysystemnone (propose only)
SFTP ensurebot:project-operator-botbothuman once / founder contract
Docs contentcontent bot or humandocsreview diff
Sync dry-runproject-operator-botbotnone
Sync applyproject-operator-botbotenv gate (or human)
HTTPS / DNS failescalatehuman:founderdecision

Use Planfile Respond + Delegate so note, assignee, queue, and status stay one history entry (see URI Process autonomy doc).


8. Implementation backlog (docs publish autonomy)

Ordered, small tickets — one concern each:

  1. Allowlist docs (or prefix) for sync planner + connector.
  2. Add docs/deployment/docs-httpdocs-sync.urirun.json + Planfile import.
  3. Wire ftpuser/command/ensure as first step; vault id convention.
  4. NL phrases + optional LLM model docs-httpdocs-sync.pl.aql.
  5. Optional content-generation ticket template (LLM → files → commit).
  6. Post-apply HTTPS verify step / TestQL scenario.
  7. Contract portfolio entry for docs publish (human-signed).

9. Quick reference — OpenRouter vs connectors

OpenRouter (LLM)Connectors (urirun)
JobIntent, planning, optional proseFTP/SFTP ensure, sync, API queries
Called fromllm-gateway / subactor askurirun-node POST /run
Sees secrets?NoVia vault lease only
Can upload httpdocs?NoYes, if apply gate set
Failure modeDeterministic fallback / escalateStructured error codes → ticket

Canonical path: docs/autonomy-cli-runbook.md (this file). Umbrella link: repo root README.md.