direxio-deployer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/AGENTS.md +92 -0
  2. package/LICENSE +21 -0
  3. package/README.md +221 -0
  4. package/README_zh.md +218 -0
  5. package/SKILL.md +722 -0
  6. package/agents/README.md +25 -0
  7. package/agents/openai.yaml +12 -0
  8. package/bin/direxio-deployer.mjs +375 -0
  9. package/package.json +28 -0
  10. package/references/agent-targets.md +128 -0
  11. package/references/architecture.md +44 -0
  12. package/references/bug-history.md +78 -0
  13. package/references/deployment-lessons.md +218 -0
  14. package/references/deployment-optimization-audit.md +317 -0
  15. package/references/deployment-workflow.md +341 -0
  16. package/references/iam-policy.json +52 -0
  17. package/references/runtime-wiring.md +209 -0
  18. package/references/state-machine.md +46 -0
  19. package/references/token-refresh.md +81 -0
  20. package/references/tooling.md +106 -0
  21. package/references/troubleshooting.md +26 -0
  22. package/references/user-journey.md +75 -0
  23. package/references/verification-recovery.md +84 -0
  24. package/references/voip-turn-runbook.md +154 -0
  25. package/references/windows-deployment-notes.md +119 -0
  26. package/scripts/aws-credentials.sh +195 -0
  27. package/scripts/cloud-init/Caddyfile +48 -0
  28. package/scripts/cloud-init/docker-compose.yml +125 -0
  29. package/scripts/cloud-init/init-tokens.sh +238 -0
  30. package/scripts/cloud-init/user-data.yaml +40 -0
  31. package/scripts/destroy.ps1 +77 -0
  32. package/scripts/destroy.sh +589 -0
  33. package/scripts/lib/aws.sh +73 -0
  34. package/scripts/lib/domain.sh +175 -0
  35. package/scripts/lib/operation_report.sh +240 -0
  36. package/scripts/lib/ops.sh +230 -0
  37. package/scripts/lib/paths.sh +35 -0
  38. package/scripts/lib/state.sh +137 -0
  39. package/scripts/mcp-tools-list.mjs +95 -0
  40. package/scripts/orchestrate.ps1 +112 -0
  41. package/scripts/orchestrate.sh +1126 -0
  42. package/scripts/phases/s0_prereq_aws.sh +39 -0
  43. package/scripts/phases/s1_preflight.sh +72 -0
  44. package/scripts/phases/s2_domain.sh +103 -0
  45. package/scripts/phases/s3_provision.sh +421 -0
  46. package/scripts/phases/s4_bootstrap_stack.sh +38 -0
  47. package/scripts/phases/s5_init_tokens.sh +118 -0
  48. package/scripts/phases/s6_wire_local.sh +1435 -0
  49. package/scripts/phases/s7_verify_e2e.sh +136 -0
  50. package/scripts/pricing-estimate.sh +256 -0
  51. package/scripts/render/render-userdata.sh +86 -0
  52. package/scripts/reset-app-data.sh +40 -0
  53. package/scripts/update.sh +30 -0
  54. package/tests/aws_credentials_test.sh +139 -0
  55. package/tests/connect_daemon_runtime_check_test.sh +120 -0
  56. package/tests/default_paths_test.sh +58 -0
  57. package/tests/destroy_local_bridge_test.sh +154 -0
  58. package/tests/destroy_root_identity_test.sh +91 -0
  59. package/tests/destroy_route53_zone_test.sh +80 -0
  60. package/tests/domain_authoritative_dns_test.sh +49 -0
  61. package/tests/mcp_doctor_runtime_check_test.sh +86 -0
  62. package/tests/mcp_smoke_runtime_check_test.sh +121 -0
  63. package/tests/mcp_tools_runtime_check_test.sh +123 -0
  64. package/tests/npm_skill_distribution_test.sh +95 -0
  65. package/tests/operation_report_test.sh +258 -0
  66. package/tests/orchestrate_status_recovery_test.sh +91 -0
  67. package/tests/phase_timeout_test.sh +88 -0
  68. package/tests/pricing_estimate_test.sh +159 -0
  69. package/tests/render_userdata_remote_nodes_test.sh +40 -0
  70. package/tests/root_volume_tracking_test.sh +41 -0
  71. package/tests/route53_overwrite_guard_test.sh +86 -0
  72. package/tests/route53_zone_auto_create_test.sh +66 -0
  73. package/tests/runtime_summary_check_test.sh +203 -0
  74. package/tests/s6_wire_local_test.sh +405 -0
  75. package/tests/skill_structure_test.sh +298 -0
  76. package/tests/update_reset_ops_test.sh +230 -0
  77. package/tests/user_confirmation_gates_test.sh +152 -0
package/SKILL.md ADDED
@@ -0,0 +1,722 @@
1
+ ---
2
+ name: direxio-deployer
3
+ description: Deploy, resume, verify, destroy, and locally wire a production P2P-IM Matrix server on AWS for any connent/connect-supported local agent runtime. Use when installing or updating this skill itself; install the versioned npm package `direxio-deployer` and use its CLI to place the skill in the runtime-specific project-local path from references/agent-targets.md unless the user explicitly asks for a global installation.
4
+ ---
5
+
6
+ # Direxio Deployer
7
+
8
+ This skill is the agent-facing deployment runbook for a production Direxio message server. It combines user confirmation, local tool checks, AWS provisioning, DNS waiting, service bootstrap, credential delivery, local agent wiring, verification, and teardown.
9
+
10
+ Agents should treat this repository root as the execution engine. The runnable entrypoints are:
11
+
12
+ ```text
13
+ scripts/orchestrate.sh
14
+ scripts/orchestrate.ps1
15
+ scripts/destroy.sh
16
+ scripts/destroy.ps1
17
+ ```
18
+
19
+ ## Skill Freshness Gate
20
+
21
+ Before following this local Skill for deployment, repair, verification,
22
+ teardown, runtime wiring, or skill installation, make one freshness attempt
23
+ against the versioned npm package:
24
+
25
+ ```bash
26
+ npm install -g direxio-deployer@latest
27
+ direxio-deployer skill refresh --agent <runtime> --scope project --project <project-root>
28
+ ```
29
+
30
+ Use the current runtime name for `<runtime>` when known, such as `codex`,
31
+ `claudecode`, `gemini`, `cursor`, `openclaw`, or `hermes`. Prefer project scope
32
+ when a project or workspace root exists. Use `--scope global` only when the
33
+ user explicitly asks for a global installation or no project target exists.
34
+
35
+ `direxio-deployer skill refresh` checks the latest npm version, updates the
36
+ global CLI when npm reports a newer package, and refreshes the managed skill
37
+ copy in the selected runtime directory. If npm is unavailable, offline, or not
38
+ authenticated, report that freshness could not be checked and continue with
39
+ this local copy.
40
+
41
+ If this Skill is running from a Git clone whose origin is
42
+ `YingSuiAI/direxio-deployer`, Git may be used as a developer fallback: fetch
43
+ `origin main` and compare the local HEAD with `origin/main`. Fast-forward only
44
+ when it is safe and does not overwrite local edits. If the clone has local
45
+ changes, do not discard them; report the divergence and continue from the local
46
+ copy unless the user approves a specific update action.
47
+
48
+ Do not fall back to older P2P-IM skill repositories or unmanaged copied skill bundles unless the user explicitly asks for one of those repositories. Never print or commit AWS credentials, initialization codes, agent tokens, or local credential files while refreshing the Skill.
49
+
50
+ ## Cloud Account And Domain Onboarding
51
+
52
+ Before running any deployment command or creating paid cloud resources, make
53
+ sure the user has the three real-world prerequisites: an active AWS account, a
54
+ stable domain, and AWS credentials that the agent can use without seeing or
55
+ printing secrets.
56
+
57
+ For first-time users, guide them step by step. Do not front-load the whole
58
+ cloud setup checklist. Ask only the next blocking question, wait for the user's
59
+ answer or completion, then continue to the next step.
60
+
61
+ Default tone for new users:
62
+
63
+ - Use product language such as account, domain, access key file, DNS provider,
64
+ server, fixed IP, and monthly AWS cost.
65
+ - Avoid technical labels such as EC2, EIP, IAM policy, security group, EBS,
66
+ Matrix `server_name`, Route53 hosted zone, federation identity, or TURN unless
67
+ the user asks what they mean or the term appears in an AWS screen they must
68
+ operate.
69
+ - When a technical term is unavoidable, explain it in one short sentence before
70
+ asking the user to act.
71
+ - Never give a long architecture explanation during onboarding unless the user
72
+ explicitly asks why the step is needed.
73
+
74
+ Step-by-step onboarding flow:
75
+
76
+ 1. **AWS account.**
77
+ - **Shortcut:** If the user already provided valid AWS credentials (a
78
+ configured profile or a CSV that passed `aws sts get-caller-identity`),
79
+ skip the browser sign-in and email questions entirely. The agent already
80
+ has AWS access.
81
+ - Ask: "Do you already have an AWS account you can log into?"
82
+ - If yes, continue to the access key step.
83
+ - If no, ask the user to open
84
+ `https://signin.aws.amazon.com/signup?request_type=register` and register
85
+ in their browser, then stop until they say the account is ready.
86
+ - Do not explain AWS resource details at this stage unless asked.
87
+ - Never ask for, collect, paste, log, or store payment card details, root
88
+ password, MFA code, email verification code, or phone verification code.
89
+ - **After credentials are configured and verified** (`aws sts
90
+ get-caller-identity` succeeds), do NOT ask "what is your AWS email" or
91
+ attempt browser sign-in. Use the CLI for all AWS operations — DNS checks,
92
+ Route53 zone inspection, EC2 provisioning.
93
+
94
+ 2. **AWS access key or profile.**
95
+ - Ask: "Do you already have an AWS access key CSV file or AWS profile for
96
+ deployment?"
97
+ - If yes, ask only for the local CSV path or profile name, then verify it
98
+ with `aws sts get-caller-identity`.
99
+ - If no, default to a temporary IAM administrator user for MVP deployment.
100
+ Explain in one sentence: "This temporary user lets the deployment tool
101
+ create and later destroy this Direxio node; delete or disable it after
102
+ deployment."
103
+ - Root access keys are allowed when the operator explicitly chooses them.
104
+ Prefer a temporary `DirexioDeployer` IAM user for routine deployments, but
105
+ do not block deployment only because `aws sts get-caller-identity` returns
106
+ an ARN ending in `:root`. Warn once that root credentials are highly
107
+ privileged and should be rotated or removed when no longer needed, then
108
+ continue if the user accepts that risk.
109
+ - Guide only one or two clicks at a time:
110
+ 1. Open `https://console.aws.amazon.com/iam/home#/users/create`.
111
+ 2. Create a user named `DirexioDeployer-YYYYMMDD` or `DirexioDeployer`.
112
+ 3. Attach the AWS managed policy `AdministratorAccess`. State plainly
113
+ that this is a temporary MVP deployment permission, not the long-term
114
+ least-privilege target.
115
+ 4. Open the new user's `Security credentials`.
116
+ 5. In `Access keys`, choose `Create access key`.
117
+ 6. Select `Command Line Interface (CLI)`, confirm the warning, then
118
+ continue.
119
+ 7. Choose `Create access key`, download the `.csv` file, and provide only
120
+ the local file path.
121
+ - After credentials are configured, run `aws sts get-caller-identity`,
122
+ report only the account, whether the identity is root, and the redacted
123
+ ARN.
124
+ - Prefer the repository helper for CSV import and redacted verification:
125
+ ```bash
126
+ bash scripts/aws-credentials.sh import-csv /path/to/accessKeys.csv direxio-deployer <region>
127
+ export AWS_PROFILE=direxio-deployer
128
+ bash scripts/aws-credentials.sh verify direxio-deployer
129
+ ```
130
+ The helper verifies the CSV credentials with STS before writing them,
131
+ writes only to the local AWS credentials/config files with mode `0600`,
132
+ and prints only a redacted ARN plus `root=true|false`.
133
+ - For long-term hardening after MVP deployment, the operator may replace
134
+ `AdministratorAccess` with a narrower policy such as
135
+ `references/iam-policy.json`, but do not make a nontechnical first-time
136
+ user debug least-privilege IAM before the first deployment.
137
+ - **Reading the CSV file:** On some platforms, terminal output-level
138
+ redaction may truncate credential values (e.g. `AKIAQ6...W47B` instead of
139
+ the full key). In that case, use Python to read the raw CSV bytes and
140
+ configure AWS CLI — see `references/windows-deployment-notes.md` for the
141
+ exact code snippet.
142
+ - The agent may read the local CSV path, but must never print the Access Key
143
+ ID together with the Secret Access Key, and must never write secrets into
144
+ the repository, skill files, logs, or chat output.
145
+
146
+ 3. **Domain.**
147
+ - Ask: "Do you already own a domain or subdomain you want to use for this
148
+ Direxio node?"
149
+ - If yes, ask for the domain.
150
+ - If no, **before asking them to buy one**, first check whether they already
151
+ own domains registered in the same AWS account:
152
+ ```bash
153
+ aws route53domains list-domains --profile <profile>
154
+ ```
155
+ If the account has domains, present the list and ask if they want to use
156
+ one of them. This avoids unnecessary purchases when the user forgot what
157
+ they own.
158
+ - If no domains exist in the account either, ask them to buy or prepare one
159
+ first, then stop until they have it.
160
+ - When guiding domain purchase, keep it concrete and short:
161
+ 1. Open one official registrar URL in the browser.
162
+ 2. Search for a domain name.
163
+ 3. Buy the domain.
164
+ 4. Return with the domain name. In examples and templates, represent it
165
+ as `__DOMAIN__`.
166
+ - Use plain official URLs instead of complex Markdown links. Do not invent
167
+ deep links or wrap one URL inside another.
168
+ - Suggested official registrar URLs:
169
+ - AWS Route53 domain registration: `https://console.aws.amazon.com/route53/domains/home#/DomainSearch`
170
+ - Alibaba Cloud domain registration: `https://wanwang.aliyun.com/domain/`
171
+ - Cloudflare domain registration: `https://dash.cloudflare.com/`
172
+ - GoDaddy domain registration: `https://www.godaddy.com/domains`
173
+ - Explain only this much by default: "Use a real long-term domain because
174
+ changing it later means creating a new chat server identity."
175
+ - Do not use localhost, raw IP addresses, wildcard domains, disposable
176
+ domains, temporary `sslip.io`, or other throwaway names for production.
177
+
178
+ 4. **DNS control.**
179
+ - Ask: "Is this domain managed in AWS Route53, or somewhere else like
180
+ Cloudflare, GoDaddy, or Alibaba Cloud?"
181
+ - If AWS Route53, use `DOMAIN_MODE=route53` only after the user confirms AWS
182
+ may create or update the domain's hosted zone and A record. S3 will reuse
183
+ a matching hosted zone or create one, record the hosted zone id and NS
184
+ nameservers in state, then upsert the A record. If an existing A record
185
+ points to a different IP, S3 must stop with `waiting_user` and record the
186
+ old and pending values; continue only after the user confirms overwrite:
187
+ `DIREXIO_CONFIRM_DNS_OVERWRITE=1`.
188
+ - If another provider exposes an API and the user grants that provider's DNS
189
+ authorization, prefer provider automation. If no provider automation is
190
+ available, use `DOMAIN_MODE=user` as a fallback and treat it as a waiting
191
+ external-action state, not a finished deployment. Later, when the script
192
+ emits the fixed IP, ask the user to create exactly:
193
+
194
+ ```text
195
+ <DOMAIN> A <PUBLIC_IP>
196
+ ```
197
+
198
+ - **Route53 delegation from another provider** — If the user prefers Route53
199
+ even though the domain is registered elsewhere (Alibaba, GoDaddy,
200
+ Cloudflare, etc.), S3 can create the Route53 hosted zone and record its
201
+ NS nameservers. The user or a provider-specific DNS connector must still
202
+ delegate those NS records at the current registrar before authoritative
203
+ DNS can resolve. Do not continue past DNS verification until authoritative
204
+ DNS points to the new public IP.
205
+
206
+ 5. **Billing confirmation.**
207
+ - Give a short billing warning before the first mutating AWS command:
208
+ "This will create paid AWS resources for the server. They keep billing
209
+ until destroyed."
210
+ - **Provide an upfront monthly cost estimate** based on the selected
211
+ region and instance type, so the user can decide whether to proceed.
212
+ `scripts/orchestrate.sh` records `cost_estimate` in state before the
213
+ first mutating AWS phase, and S3 refreshes it after the final EC2
214
+ instance type is selected. For a manual preflight estimate before state
215
+ exists, run:
216
+
217
+ ```bash
218
+ bash scripts/pricing-estimate.sh \
219
+ --region <aws-region> \
220
+ --instance-type t3.small \
221
+ --disk-gb 8 \
222
+ --domain-mode <user|route53>
223
+ ```
224
+
225
+ For an existing service state, refresh and persist the estimate with:
226
+
227
+ ```bash
228
+ bash scripts/pricing-estimate.sh --state ~/.direxio/nodes/<service_id>/state.json --write-state
229
+ ```
230
+
231
+ The helper queries AWS Price List when available and falls back to
232
+ conservative values with an explicit `pricing_status=fallback` warning.
233
+ Default estimate scope is EC2 `t3.small`, 8 GB gp3, and ~730 hours/month:
234
+
235
+ | Resource | Monthly Cost |
236
+ |---|---:|
237
+ | EC2 t3.small (Linux) | query current regional On-Demand rate |
238
+ | EBS gp3 (8 GB) | calculate from current regional gp3 rate |
239
+ | Public IPv4 / Elastic IP | billed hourly by AWS, even when attached |
240
+ | Route53 hosted zone | included when `DOMAIN_MODE=route53` |
241
+ | Outbound data and TURN relay traffic | depends on actual usage |
242
+ | **Total** | **sum the current regional rates before asking for approval** |
243
+
244
+ Do not present a fixed final quote from this file. Present the current
245
+ helper output, identify whether it is `queried` or `fallback`, and say
246
+ that it excludes data transfer, TURN relay traffic, domain registration,
247
+ taxes, and AWS credits. Tell the user to verify any AWS credits in AWS
248
+ Billing Console; the AWS Billing Console is the source of truth because
249
+ credits only apply when the account, plan, region, and service usage are
250
+ eligible. Recommend setting an AWS Budget or billing alert before leaving
251
+ the node running.
252
+ - If the user asks what is billed, mention EC2/server, fixed public IPv4 or
253
+ Elastic IP, storage, DNS, network traffic, and call relay traffic.
254
+
255
+ Required first-time deployment confirmation:
256
+
257
+ ```text
258
+ I confirm that I have an active AWS account, a real long-lived domain, and an AWS access key CSV or AWS profile for this deployment. I understand this can create billable AWS resources and that they keep billing until destroyed.
259
+ ```
260
+
261
+ If any prerequisite is missing, stop deployment and guide the user through that
262
+ specific step before running `scripts/orchestrate.sh`.
263
+
264
+ ## Deployment Mode Boundary
265
+
266
+ Current MVP deployment path is EC2-only. The supported production path creates
267
+ an EC2 instance, gp3 root volume, public IPv4/Elastic IP, security group, key
268
+ pair, Route53 DNS record when authorized, Caddy/TLS, message-server bootstrap,
269
+ local `direxio-connect`, and service-scoped MCP snippets.
270
+
271
+ The default instance type is EC2 `t3.small` on x86/amd64. Do not put ordinary
272
+ users into a cloud product selection flow. Recommend the closest appropriate
273
+ AWS region, calculate the current regional estimate, explain billing, and then
274
+ run the EC2 path after confirmation. Use `INSTANCE_TYPE` only when the operator
275
+ explicitly chooses a larger EC2 size.
276
+
277
+ Lightsail is a future deployment mode, not a current automatic option. Lightsail requires a separate deploy_mode=lightsail implementation before it can be offered: separate instance creation, Static IP, firewall, SSH/init handling, DNS, state recording, destroy evidence, pricing, and tests. Do not describe it as available through the current EC2 state machine.
278
+
279
+ ## Skill And Runtime Targets
280
+
281
+ When the user asks to install or update this skill itself, or asks to wire Direxio into a local agent runtime, read `references/agent-targets.md` first. It is the source of truth for connent/connect agent targets, legacy host-runtime aliases, generic targets, and unknown targets.
282
+
283
+ For this skill repository itself, first determine whether the current working directory belongs to a project or workspace. Treat an explicit workspace root, project files, or an existing agent-specific directory such as `.codex/`, `.claude/`, `.gemini/`, `.cursor/`, `.github/copilot/`, `.devin/`, `.opencode/`, `.qoder/`, `.pi/`, `.openclaw/`, or `.hermes/` as a project target.
284
+
285
+ If a project target exists, install or update this skill with the versioned npm CLI at the runtime-specific project-local path from `references/agent-targets.md`:
286
+
287
+ ```bash
288
+ npm install -g direxio-deployer@latest
289
+ direxio-deployer skill install --agent <runtime> --scope project --project <project-root>
290
+ direxio-deployer skill update --agent <runtime> --scope project --project <project-root>
291
+ ```
292
+
293
+ The installer writes `.direxio-skill-install.json` into the target directory and refuses to overwrite unmanaged existing content unless the operator explicitly uses `--force`. Use global runtime skill directories only when the user explicitly asks for a global install or no project target exists:
294
+
295
+ ```bash
296
+ direxio-deployer skill install --agent <runtime> --scope global
297
+ ```
298
+
299
+ Use a Git clone only for development or local patching of this deployer, not as the normal end-user installation path.
300
+
301
+ ## Agent Recognition
302
+
303
+ Use this skill when the user asks to deploy, resume, verify, destroy, repair, or wire a P2P-IM Matrix server. The instructions are runtime-neutral and can be followed by any agent that can run shell commands and read files. The local bridge target must be one of the connent/connect agents unless the user explicitly supplies compatible custom TOML. OpenClaw and Hermes are host runtimes that S6 wires through the generic connent/connect `acp` agent.
304
+
305
+ For local agent integration after deployment, S6 writes service-specific credentials and environment files under `~/.direxio/nodes/<service_id>/`, where `service_id` is derived from the deployed domain. It also writes MCP client snippets under `~/.direxio/nodes/<service_id>/mcp/` for MCP-capable hosts such as Codex, OpenClaw, and Hermes. It does not write root-level compatibility credentials, shell profiles, Windows user environment variables, or mutate each host's global MCP config.
306
+
307
+ ```bash
308
+ DIREXIO_DOMAIN=https://<DOMAIN>
309
+ DIREXIO_AGENT_TOKEN=<agent_token>
310
+ DIREXIO_AGENT_ROOM_ID=<agent_room_id>
311
+ DIREXIO_AGENT_NODE_ID=<agent_node_id>
312
+ ```
313
+
314
+ Post-deploy agent wiring is controlled by:
315
+
316
+ ```bash
317
+ DIREXIO_AGENT_PLATFORM=auto
318
+ DIREXIO_CC_CONNECT_AGENT=<optional connect agent>
319
+ DIREXIO_OPENCLAW_ACP_URL=<required for OpenClaw gateway URL>
320
+ DIREXIO_OPENCLAW_ACP_TOKEN_FILE=<required for OpenClaw gateway token file>
321
+ DIREXIO_OPENCLAW_ACP_SESSION=<required for OpenClaw ACP session>
322
+ DIREXIO_AGENT_INSTALL=recommend
323
+ DIREXIO_AGENT_INSTALL_MODE=recommended
324
+ ```
325
+
326
+ The only supported local conversation bridge is `direxio-connect`, installed from `direxio-connent@latest` by default or built from `https://github.com/YingSuiAI/direxio-connect.git`. S6 creates a Matrix session for `@agent:<server>`, writes `~/.direxio/nodes/<service_id>/cc-connect/config.toml`, and restricts the bridge to the real `agent_room_id`.
327
+
328
+ The local MCP tool surface is `direxio-mcp`, installed from `direxio-mcp@latest` by default. S6 writes `mcp/codex.toml`, `mcp/openclaw.md`, `mcp/openclaw-server.json`, `mcp/hermes.mcp.json`, `mcp/mcp-servers.json`, and `mcp/env`; these artifacts point to `credentials.json` by `DIREXIO_CREDENTIALS_FILE`. OpenClaw must be configured through the generated `openclaw mcp set` command in `mcp/openclaw.md`; do not paste MCP JSON into `~/.openclaw/openclaw.json`. Keep this separate from cc-connect: cc-connect must use its direct Matrix config and must not use `DIREXIO_CREDENTIALS_FILE`.
329
+
330
+ `DIREXIO_CC_CONNECT_AGENT` is the preferred explicit selector. Supported values match connent/connect: `acp`, `antigravity`, `claudecode`, `codex`, `copilot`, `cursor`, `devin`, `gemini`, `iflow`, `kimi`, `opencode`, `pi`, `qoder`, `reasonix`, and `tmux`. Detected OpenClaw and Hermes runtimes map to `cc_connect_agent=acp`; they are not native connect agent types. OpenClaw uses `cmd = "openclaw"` but S6 requires the current agent/operator to supply the real `DIREXIO_OPENCLAW_ACP_URL`, `DIREXIO_OPENCLAW_ACP_TOKEN_FILE`, and `DIREXIO_OPENCLAW_ACP_SESSION`; do not guess these values or reuse old chat output. Hermes uses `cmd = "direxio-connect"` with `args = ["hermes-acp-adapter", "--", "hermes", "acp"]` so the Direxio compatibility layer can suppress Hermes reasoning text before it reaches the Matrix room. Use `DIREXIO_CC_CONNECT_AGENT_CMD`, `DIREXIO_<AGENT>_COMMAND`, and when needed `DIREXIO_CC_CONNECT_AGENT_OPTIONS_TOML` for agent-specific launch details. OpenClaw and Hermes also accept `DIREXIO_OPENCLAW_COMMAND`, `DIREXIO_HERMES_COMMAND`, `DIREXIO_HERMES_ACP_ADAPTER_COMMAND`, `DIREXIO_OPENCLAW_ACP_ARGS_TOML`, and `DIREXIO_HERMES_ACP_ARGS_TOML`; Hermes custom args are child Hermes args and S6 prefixes the adapter wrapper automatically.
331
+
332
+ `DIREXIO_AGENT_PLATFORM` describes the host runtime following the skill, while `DIREXIO_CC_CONNECT_AGENT` describes the local agent backend that `direxio-connect` should launch. Host runtimes such as Hermes or OpenClaw are not native cc-connect backend types; S6 maps them to the generic ACP backend by default and records `cc_connect_agent=acp`. Override `DIREXIO_CC_CONNECT_AGENT` only when the operator intentionally wants a different local backend.
333
+
334
+ `DIREXIO_AGENT_INSTALL` may be `skip`, `recommend`, or `auto`. Only `auto` attempts to run `npm install -g direxio-connent@latest` and `direxio-connect daemon install --config ~/.direxio/nodes/<service_id>/cc-connect/config.toml --service-name <service_id> --force`; the default `recommend` records and prints the command without mutating local daemon state. An automatic install is reported as installed only when `direxio-connect daemon status --service-name <service_id>` returns `Status: Running` and recent daemon logs do not show ACP session initialization failure; otherwise S6 records `agent_install_status=install_failed`.
335
+
336
+ Voice input is supported through `direxio-connect` speech-to-text. When `DIREXIO_SPEECH_API_KEY` or a provider-specific key such as `DIREXIO_SPEECH_QWEN_API_KEY`, `OPENAI_API_KEY`, `GROQ_API_KEY`, `DASHSCOPE_API_KEY`, `GEMINI_API_KEY`, or `GOOGLE_API_KEY` is present, S6 writes `[speech] enabled = true` into the generated config. Without an STT key, do not claim voice input is enabled.
337
+
338
+ ## Product Completion Gates
339
+
340
+ S7 green is not the final product-complete state. S7 proves the deployed server
341
+ passed automated infrastructure and API checks; it does not prove the user has
342
+ initialized the App or that the current agent runtime has discovered and used
343
+ the local MCP tools.
344
+
345
+ For a new deployment, the product completion state requires all of these gates:
346
+
347
+ 1. The user receives the app domain and the eight-digit app initialization code.
348
+ The backend stores this value in the `password` field; user-facing delivery
349
+ must call it an initialization code, not a password.
350
+ 2. The user can enter the domain and eight-digit app initialization code in the
351
+ App, enter the initialization flow, and complete initialization.
352
+ 3. The local `direxio-connect` bridge is wired to the real `agent_room_id` for
353
+ the selected service under `~/.direxio/nodes/<service_id>/`.
354
+ 4. MCP snippets for the selected service exist under
355
+ `~/.direxio/nodes/<service_id>/mcp/`, and `direxio-mcp doctor --json`
356
+ succeeds with `DIREXIO_CREDENTIALS_FILE` pointing at that service's
357
+ `credentials.json`.
358
+ 5. Agent/MCP validation is non-polluting by default: prefer `direxio-mcp
359
+ doctor`, tool discovery, read-only backend calls, and runtime/channel probes.
360
+ Do not auto-send a normal chat message as a deployment test. If the user
361
+ wants a real chat experience check, ask the user to send the test message
362
+ from the App or agent chat box.
363
+
364
+ Delivery reports must separate automated gates from user-confirmed gates. If
365
+ the App initialization or real chat experience has not yet been confirmed, say
366
+ that explicitly instead of declaring the whole product deployment complete.
367
+ After S6 writes MCP snippets, record the non-polluting MCP doctor evidence with:
368
+
369
+ ```bash
370
+ DOMAIN=<DOMAIN> bash scripts/orchestrate.sh verify runtime
371
+ DOMAIN=<DOMAIN> bash scripts/orchestrate.sh verify connect_daemon
372
+ DOMAIN=<DOMAIN> bash scripts/orchestrate.sh verify mcp_doctor
373
+ DOMAIN=<DOMAIN> bash scripts/orchestrate.sh verify mcp_tools
374
+ DOMAIN=<DOMAIN> bash scripts/orchestrate.sh verify mcp_smoke
375
+ ```
376
+
377
+ Use `verify runtime` as the normal aggregate check. It runs the service-scoped
378
+ connect daemon check plus MCP doctor, MCP `tools/list`, and read-only backend
379
+ smoke, then writes `runtime_checks.summary`. The individual commands are useful
380
+ when diagnosing one layer. These commands write `runtime_checks.connect_daemon`,
381
+ `runtime_checks.mcp_doctor`, `runtime_checks.mcp_tools`, and
382
+ `runtime_checks.mcp_smoke` into `state.json` and the operation report.
383
+ `connect_daemon` verifies that `direxio-connect daemon status --service-name
384
+ <service_id>` is `Running` and that its `WorkDir` matches this service's
385
+ `~/.direxio/nodes/<service_id>/cc-connect` directory, so another node's daemon
386
+ cannot be mistaken for the current deployment. `mcp_tools` starts the
387
+ configured MCP stdio server and records MCP `tools/list` discovery.
388
+ `mcp_smoke` uses the current `agent_token` and `agent_room_id` to call the
389
+ read-only backend action `mcp.messages.list` with `limit=1`; it must not send a
390
+ chat message. These checks do not by themselves confirm the full
391
+ `agent_mcp_runtime` product gate; the selected runtime or channel probe is
392
+ still required before confirming that gate.
393
+ When the user later confirms a manual gate, write that confirmation back to the
394
+ service state before regenerating the operation report:
395
+
396
+ ```bash
397
+ DIREXIO_CONFIRM_EVIDENCE="user completed app initialization" \
398
+ DOMAIN=<DOMAIN> bash scripts/orchestrate.sh confirm app_initialization
399
+
400
+ DIREXIO_CONFIRM_EVIDENCE="user sent a message and saw the agent reply" \
401
+ DOMAIN=<DOMAIN> bash scripts/orchestrate.sh confirm real_chat
402
+
403
+ DIREXIO_CONFIRM_RUNTIME_PROBE=1 \
404
+ DIREXIO_CONFIRM_EVIDENCE="MCP doctor/tool discovery and runtime probe confirmed" \
405
+ DOMAIN=<DOMAIN> bash scripts/orchestrate.sh confirm agent_mcp_runtime
406
+ ```
407
+
408
+ Only record a gate after the user or runtime evidence actually proves it. Do
409
+ not mark `real_chat` confirmed from a non-polluting internal probe alone. Every
410
+ `confirm` command requires `DIREXIO_CONFIRM_EVIDENCE`; do not let the script
411
+ write a manual gate with a generic default evidence string. The evidence note
412
+ must be concrete and at least 12 characters; avoid placeholders such as `ok`,
413
+ `yes`, or `done`.
414
+ `agent_mcp_runtime` confirmation is intentionally stricter: first run
415
+ `verify runtime` until `runtime_checks.summary.status` is `passed`, then set
416
+ `DIREXIO_CONFIRM_RUNTIME_PROBE=1` only after the selected runtime/channel probe
417
+ has actually seen the service-scoped MCP tools.
418
+
419
+ ## Core Rule
420
+
421
+ Deploy only to a real, long-lived domain. Matrix `server_name` is identity; changing it later is effectively a new homeserver with new accounts, rooms, federation identity, TURN realm, and client configuration.
422
+
423
+ Do not deploy until the user explicitly confirms:
424
+
425
+ ```bash
426
+ DOMAIN=<final-domain>
427
+ DOMAIN_MODE=user
428
+ CONFIRM_DOMAIN_BINDING=1
429
+ ```
430
+
431
+ Use `DOMAIN_MODE=route53` when the user confirms AWS may manage the domain's
432
+ A record through Route53. S3 reuses a matching hosted zone or creates one and
433
+ records `route53_zone_id`, `route53_zone_name`, `route53_name_servers`, and
434
+ whether the zone was deployer-created. If the domain is registered at another
435
+ provider, the user or provider-specific automation must delegate the recorded
436
+ NS nameservers before authoritative DNS can resolve. Never use temporary
437
+ `sslip.io`, IP-derived, localhost, wildcard, or disposable domains.
438
+
439
+ ## Deployment Flow
440
+
441
+ 1. Complete the Cloud Account And Domain Onboarding gate above for first-time users or whenever AWS credentials, domain ownership, or DNS authority are unclear.
442
+ 2. Read `references/tooling.md`; inspect the user OS and install or prepare missing `bash`, `aws`, `jq`, `ssh`, `scp`, `curl`, and DNS lookup capability only after approval.
443
+ 3. Inspect DNS, AWS credentials, region defaults, local tooling, and existing deployment state before asking the user anything that can be discovered automatically.
444
+ **DNS tool preflight:** Before any DNS propagation or Route53 delegation
445
+ check, confirm the environment has at least one working DNS lookup path:
446
+ `dig`, `nslookup`, Windows PowerShell `Resolve-DnsName`, or `getent`.
447
+ Prefer an existing tool. If no DNS lookup tool is available, ask before
448
+ installing the OS package from `references/tooling.md` (`dnsutils`,
449
+ `bind-utils`, or `bind-tools`), or use the platform fallback. Do not treat
450
+ "dig is missing" as DNS failure; fix the missing tool or use a fallback,
451
+ then rerun the same deployment step.
452
+ **Multi-domain state check:** Before finalising the domain, scan for existing
453
+ nodes across all domains to avoid deploying the same domain twice or
454
+ colliding with an active node:
455
+
456
+ ```bash
457
+ # Check local deploy state for any active/in-progress deployment
458
+ bash scripts/orchestrate.sh status
459
+ DOMAIN=<DOMAIN> bash scripts/orchestrate.sh status
460
+
461
+ # Check Route53 A records to see which domains already have a server
462
+ for zid in $(aws route53 list-hosted-zones --query "HostedZones[].Id" --output text); do
463
+ zone_name=$(aws route53 list-hosted-zones --query "HostedZones[?Id=='$zid'].Name" --output text)
464
+ a_rec=$(aws route53 list-resource-record-sets --hosted-zone-id "$zid" --query "ResourceRecordSets[?Type=='A'].{Name:Name,Value:ResourceRecords[0].Value}" --output json)
465
+ echo "$zone_name -> A=$a_rec"
466
+ done
467
+ ```
468
+
469
+ If the chosen domain already has an A record pointing to a different IP,
470
+ or has a local node directory under `~/.direxio/nodes/`, warn the user
471
+ and suggest using a different domain or destroying the existing deployment
472
+ first. If the user intentionally wants this deployment to replace the old A
473
+ record, record the old value and require `DIREXIO_CONFIRM_DNS_OVERWRITE=1`
474
+ before continuing. If the domain was deployed multiple times recently, warn
475
+ about Let's Encrypt rate limits (max 5 certificates per domain per 7 days).
476
+ 4. Present one complete deployment configuration and request one consolidated confirmation covering the final domain and irreversible binding, DNS mode, AWS region and billing, credentials source, instance type, message-server image, required installs, and existing-state action.
477
+ 5. Apply the approved existing-state action for `${DIREXIO_HOME:-$HOME/.direxio}/nodes/<service_id>/state.json`: continue, destroy, or use a different domain/service directory.
478
+ 6. Run `scripts/orchestrate.sh` with the confirmed environment. Let the state machine own AWS calls, state, polling, cloud-init, token/password handling, verification, and destroy behavior.
479
+ **Credential freshness:** The synced `password` and owner `access_token`
480
+ are one-time/volatile values. User login or token exchange can reset them
481
+ on the server. Before reporting the eight-digit app initialization code or using an owner
482
+ `access_token` for API calls, rerun the credential sync path or pull the
483
+ latest `/opt/p2p/bootstrap.json` from the server; do not reuse values from
484
+ old chat output, old `state.json`, or stale local `credentials.json`.
485
+ **Runtime detection note:** S6 checks active-process signals before stale
486
+ config directories, so current-session markers, environment variables, and
487
+ process names win over historical runtime directories. If a session still
488
+ appears ambiguous, set `DIREXIO_AGENT_PLATFORM=<runtime>` or
489
+ `DIREXIO_CC_CONNECT_AGENT=<agent>` explicitly before deployment. For
490
+ OpenClaw and Hermes, prefer `DIREXIO_AGENT_PLATFORM=openclaw|hermes` so S6
491
+ keeps the ACP-backed defaults. Also see
492
+ `references/windows-deployment-notes.md`.
493
+ **Route53 delegation note:** If S3 creates a hosted zone for a domain that is
494
+ registered at Alibaba, GoDaddy, Cloudflare, or another non-Route53 registrar,
495
+ report the recorded NS nameservers and wait for registrar delegation or
496
+ provider API automation. The hosted zone and public IPv4 may bill while DNS
497
+ is waiting, and destroy will try to delete deployer-created hosted zones.
498
+ **⚠️ Let's Encrypt certificate rate limit:** A single domain can get at most
499
+ 5 certificates per 7 days (504 hours). If the chosen domain has been
500
+ deployed and destroyed repeatedly within the past week, S4 will fail with
501
+ `healthz did not return 200 before timeout` because Caddy cannot issue a new
502
+ cert. Before running, check the domain's recent cert history by inspecting
503
+ Caddy data on an existing EC2 instance, or simply choose a domain that has
504
+ not been deployed recently. See `references/deployment-workflow.md` → "S4
505
+ Bootstrap Timeout / Certificate Rate Limit Recovery" for recovery steps.
506
+ 7. For `DOMAIN_MODE=user`, pause when the script emits an Elastic IP and ask the user to set:
507
+ ```text
508
+ <DOMAIN> A <PUBLIC_IP>
509
+ ```
510
+ This is a fallback when no DNS provider automation is available. For
511
+ `DOMAIN_MODE=route53` where NS delegation was just changed or the hosted
512
+ zone was just created, DNS propagation of the new nameservers is required
513
+ before the script can verify the A record.
514
+
515
+ 8. After authoritative DNS resolves, rerun the same command with `DNS_READY=1`.
516
+ 9. After S7 passes, read `references/runtime-wiring.md` and `references/agent-targets.md`, then report the app domain, eight-digit app initialization code, automated gate status, user-confirmation gates still pending, agent token status, real `agent_room_id`, persistent Direxio env status, cc-connect config path, MCP config paths, Matrix bridge user/device, resources, SSH command, state path, and stop-billing guidance that tells the user to ask the agent to destroy the node when finished. Do not treat S7 green as final product completion unless App initialization and agent/MCP runtime confirmation are also recorded.
517
+ 10. Read the selected connect agent from S6 state (`cc_connect_agent`) and report the recorded `agent_install_command` and `agent_install_status`. For OpenClaw or Hermes, also report that the detected host runtime is ACP-backed and `cc_connect_agent` is expected to be `acp`. If `DIREXIO_AGENT_INSTALL=auto` was explicitly set, treat the daemon as installed only when S6 recorded `agent_install_status=installed`; `install_failed` means the daemon command failed, status was not `Running`, or recent logs reported ACP session initialization failure. Otherwise leave installation as an explicit operator action.
518
+
519
+ ## Status And Recovery
520
+
521
+ When a deployment is waiting or failed, run `bash scripts/orchestrate.sh status`
522
+ for the current service before giving advice. The status output includes a
523
+ `Recovery summary` that must be reflected in user-facing language:
524
+
525
+ - Where it is blocked: the current S0-S7 phase and its plain-language meaning.
526
+ - Billing impact: whether EC2, public IPv4/EIP, or EBS resources are recorded
527
+ and may still be billing.
528
+ - Resume safety: whether rerunning the same command is safe, or whether the
529
+ operator must preserve `state.json` and continue with
530
+ `P2P_EXISTING_STATE_ACTION=continue`.
531
+ - Local refresh: if `agent_install_status=refresh_pending`, update/reset
532
+ cleared old credentials, user confirmations, runtime checks, and bridge
533
+ install proof; the next action is to rerun the deployment workflow to refresh S4-S7, local credentials, MCP snippets, and runtime checks.
534
+ - Next action: the concrete diagnostic or user action for the current phase.
535
+ - Stop-loss: whether no cloud destroy is needed yet, or how to ask the agent to
536
+ run destroy / run `scripts/destroy.sh` on POSIX or `.\scripts\destroy.ps1` on
537
+ Windows PowerShell.
538
+
539
+ Do not tell a nontechnical user only that a phase failed. Translate the recovery
540
+ summary into current status, cost impact, resumability, next action, and
541
+ stop-loss. Do not recommend deleting or resetting state after S3 unless the
542
+ recorded AWS resources have been destroyed or deliberately preserved.
543
+
544
+ ## Operation Reports
545
+
546
+ Every operation must produce a short user-facing explanation and, when state is
547
+ available, a machine-readable `operation-report.json` with redacted fields.
548
+ Reports must never include the eight-digit initialization code, AWS secrets,
549
+ `access_token`, `agent_token`, Matrix session access tokens, or full credential
550
+ values. Because users may paste an initialization code into confirmation
551
+ evidence, report generation also redacts eight-or-more digit numeric strings
552
+ from user/runtime evidence text.
553
+
554
+ Current script support:
555
+
556
+ - `new_deploy`: `scripts/orchestrate.sh` writes
557
+ `~/.direxio/nodes/<service_id>/operation-report.json` after S7 and also
558
+ supports `bash scripts/orchestrate.sh report new_deploy`.
559
+ - `destroy`: `scripts/destroy.sh` writes
560
+ `~/.direxio/reports/<service_id>/operation-report.json`, because the service
561
+ directory under `~/.direxio/nodes/<service_id>/` is normally removed. The
562
+ destroy report must include `destroy.evidence` from AWS read-back checks for
563
+ the EC2 instance, EBS root volume, Elastic IP, security group, key pair,
564
+ Route53 A record, and deployer-created hosted zone.
565
+ - `repair_or_verify`, `update`, and `reset_app_data`: `bash
566
+ scripts/orchestrate.sh report <operation>` can generate a redacted report
567
+ from current state.
568
+ - User-confirmed gates can be written with `bash scripts/orchestrate.sh confirm
569
+ app_initialization`, `bash scripts/orchestrate.sh confirm real_chat`, and
570
+ `bash scripts/orchestrate.sh confirm agent_mcp_runtime`; regenerate the
571
+ report afterwards.
572
+
573
+ The report records operation type, status, S0-S7 automated gates, user
574
+ confirmation gates, `gates.user_confirmation_details`, service-scoped
575
+ credential/config paths, cc-connect/MCP metadata, AWS resource IDs, billing
576
+ reminders, `billing.cost_estimate`, destroy read-back evidence when applicable,
577
+ `billing.destroy_cleanup_status`, `billing.possible_remaining_billable_resources`,
578
+ and secret-redaction evidence. It also records local refresh state:
579
+ `credentials.status`, `connect.install_status`, and `mcp.status` must show
580
+ `refresh_pending` after update/reset until S5/S6/S7 and runtime verification
581
+ write fresh evidence. User confirmation evidence is redacted before it is
582
+ written to the operation report, so initialization codes and tokens are not
583
+ copied into handoff artifacts.
584
+ If a destroy report lists possible remaining billable resources, tell the user
585
+ that AWS Console/Billing is the source of truth and continue cleanup instead of
586
+ claiming teardown is finished. Use the report as the Agent/maintainer handoff artifact.
587
+ The ordinary user explanation should still be shorter and say what the user can
588
+ do next.
589
+
590
+ ## Destroy Flow
591
+
592
+ Use `scripts/destroy.sh` for teardown on POSIX shells and `.\scripts\destroy.ps1` from PowerShell on Windows. The Windows wrapper selects Git for Windows Bash for the Bash state machine, sets Windows-compatible local path mode, and converts explicit Windows state paths before invoking `scripts/destroy.sh`. Destroy first checks `direxio-connect daemon status --service-name <service_id>` and stops plus uninstalls only that named daemon when the reported `WorkDir` matches the current service directory, `~/.direxio/nodes/<service_id>/cc-connect`. After AWS resources are terminated and released, destroy reads AWS back and records `destroy.evidence` before removing the corresponding local service directory under `~/.direxio/nodes/<service_id>`. This prevents stale state, credentials, bridge files, and stale local service registrations from blocking or misleading the next deployment while still preserving a reportable AWS cleanup audit trail. It leaves unrelated node credential directories intact.
593
+
594
+ Destroy uses the same AWS identity boundary as deployment: root AWS access-key
595
+ identity is allowed when the operator explicitly chose root credentials. Prefer
596
+ using the same temporary `DirexioDeployer` IAM user/profile for teardown when
597
+ that was used for provisioning.
598
+
599
+ If an operator needs to preserve local state files for debugging, run destroy with `P2P_KEEP_WORKDIR=1` and explicitly report that the stale service directory remains.
600
+
601
+ ### Full reset / "treat me as a brand new user"
602
+
603
+ When the user asks for a complete fresh start — "destroy everything", "start over from zero", "treat me as a brand new user" — running `scripts/destroy.sh` alone is **not sufficient**. The destroy script only handles infrastructure and local service directory cleanup. The agent should also clear any runtime-supported persistent memory about the old deployment. Specifically:
604
+
605
+ 1. **Run `scripts/destroy.sh` first** (infra teardown).
606
+ 2. **Clear agent memory entries only through capabilities available in the current runtime.** If the runtime provides an explicit memory-management tool, remove entries referencing the old domain, deployment URLs, credentials, passwords, tokens, node IDs, room IDs, service IDs, AWS account info, cc-connect config paths, and skill install/update history. If no such capability exists, say that memory cleanup cannot be automated in this runtime and avoid inventing tool calls.
607
+ 3. **Verify runtime-specific memory stores only when they are known and accessible.** Use the current agent's native memory/config mechanism if exposed; otherwise report the limitation.
608
+ 4. **Then start from Step 1** of the Cloud Account And Domain Onboarding section — ask about AWS account first, don't assume anything carried over.
609
+
610
+ > ⚠️ Do not skip step 2. Stale credentials (URLs, passwords, tokens) in agent memory can leak into the new deployment's Delivery report or cause the agent to skip onboarding steps by referencing facts that no longer apply. A true fresh start requires both infra cleanup **and** agent memory cleanup.
611
+
612
+ ## Image Refresh And Data Reset
613
+
614
+ When the user only asks to pull a newer image on an existing EC2 instance, do not destroy cloud resources and do not delete application or TLS storage. Run `scripts/update.sh` against the current state. It SSHes to the existing node, optionally updates `MESSAGE_SERVER_IMAGE`, runs Docker Compose pull/up, reruns `/opt/p2p/init-tokens.sh`, clears stale local secret fields, clears old user-confirmation/runtime-check evidence, marks `agent_install_status=refresh_pending`, stops only the matching service-scoped direxio-connect daemon when its `WorkDir` matches this service, marks S4-S7 pending, and writes a redacted `operation-report.json`.
615
+
616
+ When the user asks to reset application data on an existing EC2 instance, do not destroy EC2, public IPv4/EIP, DNS, or Caddy TLS storage. Run `scripts/reset-app-data.sh` only after explicit destructive confirmation with `DIREXIO_RESET_APP_DATA_CONFIRM=1`. It clears only the application volumes (`postgres-data`, `message-config`, `message-data`), generates a new backend password/init-code field, restarts the stack, reruns `/opt/p2p/init-tokens.sh`, clears stale local secret fields, clears old user-confirmation/runtime-check evidence, marks `agent_install_status=refresh_pending`, stops only the matching service-scoped direxio-connect daemon when its `WorkDir` matches this service, marks S4-S7 pending, and writes a redacted `operation-report.json`.
617
+
618
+ Current message-server images require `P2P_PORTAL_PASSWORD` and an explicit `portal.bootstrap`; `init-tokens.sh` owns that cloud-side bootstrap and creates a real Matrix `agent_room_id` when the backend credentials file does not already include one.
619
+
620
+ Do not delete caddy-data or caddy-config during an image-only refresh. Removing Caddy's ACME storage loses the existing production certificate and can trigger CA duplicate-certificate rate limits. Preserve `caddy-data` and `caddy-config`; clear only `postgres-data message-config message-data` when the requested reset needs a clean homeserver/database.
621
+
622
+ For repeated test refreshes, rerun `scripts/orchestrate.sh` normally after update/reset. S4-S7 will re-run from state, and S6 only rewrites local credentials and environment files unless `DIREXIO_AGENT_INSTALL=auto` is explicitly set.
623
+
624
+ ## Minimal Invocation
625
+
626
+ ```bash
627
+ AWS_DEFAULT_REGION=us-east-1 \
628
+ DOMAIN=__DOMAIN__ \
629
+ DOMAIN_MODE=user \
630
+ CONFIRM_DOMAIN_BINDING=1 \
631
+ INSTANCE_TYPE=t3.small \
632
+ MESSAGE_SERVER_IMAGE=direxio/message-server:latest \
633
+ bash scripts/orchestrate.sh
634
+ ```
635
+
636
+ Use an `AWS_PROFILE` or temporary `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` for the selected AWS identity. Root access keys are allowed when the operator explicitly chooses them; a temporary `DirexioDeployer` IAM user remains the recommended routine path. Do not write AWS secrets, initialization codes, or agent tokens into skill files or the repository.
637
+
638
+ On Windows, prefer `.\scripts\orchestrate.ps1` and `.\scripts\destroy.ps1` from PowerShell. These wrappers select Git for Windows Bash for the Bash phases and write Windows-compatible local `direxio-connect` paths.
639
+
640
+ ## Required Confirmation
641
+
642
+ Ask once, plainly and in the user's language. The confirmation message must summarize:
643
+
644
+ - Domain binding: `CONFIRM_DOMAIN_BINDING=1`.
645
+ - DNS mode: `user` or `route53`.
646
+ - AWS region and billable resources: EC2, Elastic IP, security group, EBS, network egress, TURN traffic.
647
+ - Instance type: default `t3.small`.
648
+ - Message-server image: default `direxio/message-server:latest`; override with `MESSAGE_SERVER_IMAGE`.
649
+ - AWS credentials source, including whether root access keys are being used.
650
+ - AWS/domain onboarding status: active AWS account, real long-lived domain, access key CSV or AWS profile, DNS authority, and billing/deletion acknowledgement.
651
+ - Existing state action: `continue`, `destroy`, or different `DOMAIN`/service directory.
652
+ - Network/system installs: package managers, AWS CLI, jq, Git Bash/MSYS2/WSL, Homebrew, apt/dnf/yum/pacman/zypper.
653
+
654
+ After the user confirms the summary, proceed without re-confirming individual fields. Ask again only when the configuration materially changes, an unapproved destructive action becomes necessary, or an external action such as DNS must be completed by the user.
655
+
656
+ ## Delivery
657
+
658
+ After S7 passes, report:
659
+
660
+ ```text
661
+ App domain : <DOMAIN>
662
+ init code : <eight-digit app initialization code>
663
+ product gate : S7 green; App initialization and real chat confirmation are user-confirmed gates
664
+ agent_node_id: <agent_node_id>
665
+ service_id : <service_id>
666
+ service_dir : ~/.direxio/nodes/<service_id>
667
+ agent_token : written to ~/.direxio/nodes/<service_id>/credentials.json
668
+ agent_room_id: written to ~/.direxio/nodes/<service_id>/credentials.json
669
+ env vars : DIREXIO_DOMAIN, DIREXIO_AGENT_TOKEN, DIREXIO_AGENT_ROOM_ID, DIREXIO_AGENT_NODE_ID persisted
670
+ connect pkg : direxio-connent@latest
671
+ connect agent : <cc_connect_agent>
672
+ connect config: <cc_connect_config>
673
+ connect user : <cc_connect_matrix_user>
674
+ connect device: <cc_connect_matrix_device>
675
+ agent command : <cc_connect_agent_cmd or default PATH lookup>
676
+ install mode : policy=<skip|recommend|auto> mode=<cc-connect> status=<...>
677
+ install cmd : <agent_install_command>
678
+ mcp pkg : direxio-mcp@latest
679
+ mcp server : <mcp_server_name>
680
+ mcp config dir: <mcp_config_dir>
681
+ mcp codex : <mcp_codex_config>
682
+ mcp openclaw : <mcp_openclaw_config>
683
+ mcp hermes : <mcp_hermes_config>
684
+ mcp install : <mcp_install_command>
685
+ mcp doctor : <mcp_doctor_command>
686
+ skill clone : <agent_skill_install_path>
687
+ AWS region : <region>
688
+ EC2 : <instance-id> (<public-ip>)
689
+ SSH : ssh -i <key-file> ubuntu@<public-ip>
690
+ state.json : <state path>
691
+ stop billing : ask the agent to destroy this node when finished
692
+ security : delete or disable any temporary DirexioDeployer access key after deployment; rotate/remove root access keys if used
693
+ report : <operation-report.json path>
694
+ ```
695
+
696
+ Mention that AWS resources keep billing until destroyed. User-managed DNS and purchased domains are not removed by destroy. After destroy, report which `~/.direxio/nodes/<service_id>` service directory was removed or, if `P2P_KEEP_WORKDIR=1` was used, which local directory remains.
697
+
698
+ If `DIREXIO_AGENT_INSTALL=auto` was not used, or if it recorded `install_failed`, give the manual command:
699
+
700
+ ```bash
701
+ npm install -g direxio-connent@latest
702
+ direxio-connect daemon install --config <cc_connect_config> --service-name <service_id> --force
703
+ direxio-connect daemon status --service-name <service_id>
704
+ ```
705
+
706
+ For MCP-capable hosts, also give the recorded MCP command and snippet paths:
707
+
708
+ ```bash
709
+ npm install -g direxio-mcp@latest
710
+ DIREXIO_CREDENTIALS_FILE=<mcp_credentials_file> direxio-mcp doctor --json
711
+ ```
712
+
713
+ ## References
714
+
715
+ - Tool setup by OS: `references/tooling.md`
716
+ - Agent-specific skill and cc-connect targets: `references/agent-targets.md`
717
+ - Deployment and resume workflow: `references/deployment-workflow.md`
718
+ - Runtime and agent wiring: `references/runtime-wiring.md`
719
+ - Verification and recovery: `references/verification-recovery.md`
720
+ - State machine details: `references/state-machine.md`
721
+ - Architecture and troubleshooting: `references/architecture.md`, `references/troubleshooting.md`
722
+ - Windows deployment notes: `references/windows-deployment-notes.md` — bash prerequisites, credential setup, direxio-connect install checks, background-buffer notes, and Route53 DNS tips for Git Bash / Windows 10+.