Document the Forge production cutover

cf23f84bb9ba · AtlantisPleb · · parent 8a5432a1f56f

Document the Forge production cutover

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

built
3 modules in 14.3 s
deployed
live · 3 modules on 3 nodes · push→live 53.9 s
deployed
needs_rolling_replace · 3 modules on 0 nodes · push→live —

Changed files

  • modified README.md
  • modified docs/architecture.md
  • modified docs/decisions/0007-cut-over-to-forge-canonical-source-control-after-proof.md
  • modified docs/runtime-configuration.md
  • modified docs/scv-planning.md

Diff

5 files changed, +95 -87

README.md modified +23 -25

@@ -14,11 +14,14 @@ The typed settings, safe feature profile, and redacted readiness command are in

14 14
Repository creation, one-time GitHub import, and the terminal client are
15 15
documented in the [OpenAgents CLI guide](docs/openagents-cli/index.md).
16 16
17
## Capability status
17
## Production status
18 18
19
No part of this repository is approved for production deployment yet.
19
OpenAgents runs at [openagents.com](https://openagents.com) on a three-node
20
production fleet. The owned Forge is the canonical Git remote for this
21
repository, and `MirrorWatch` exports accepted `main` commits to GitHub. Every
22
deployment starts from an exact commit that passed the release gate.
20 23
21
### Implemented and locally gated
24
### Active capabilities
22 25
23 26
- GitHub OAuth, encrypted server-side GitHub token storage, sessions, and
24 27
  account-scoped data rights.

@@ -37,29 +40,24 @@ No part of this repository is approved for production deployment yet.

37 40
  interruption recovery, rolling replacement, repository contracts, and a
38 41
  disposable packaged-release smoke test.
39 42
40
"Implemented" means the code and local tests exist. It does not mean the
41
feature has passed staging, security review, failure injection, or a soak.
43
Availability still depends on repository access, account authority, and the
44
runtime feature profile. A source module or passing local test does not by
45
itself establish that a feature is enabled for every production user.
42 46
43
### Disabled by default or staging-only
47
### Controlled capabilities
44 48
45 49
- Voice, recording, semantic recall, experimental program paths, and deployment
46 50
  workers remain controlled by runtime configuration.
47
- Direct BEAM loading, relup installation, rolling replacement, and boot
48
  convergence require isolated three-node staging proof before they can be
49
  enabled outside a disposable environment.
50
- The self-hosted forge is being hardened. GitHub remains the canonical remote
51
  for the OpenAgents platform repository until the proof-gated cutover in ADR
52
  0007; newly created hosted repositories use OpenAgents as their source of
53
  truth.
54
55
### Planned or blocked on hardening
56
57
- Staging qualification and release of repository creation, GitHub import, and
58
  the OpenAgents CLI.
59
- Separate web and distributed staging lanes, a full regression matrix,
60
  failure-injection drills, and a 48-hour soak.
61
- Any production rollout. Production remains explicitly out of scope until the
62
  staging plan is complete and separately approved.
51
- Forge direct loading accepts only verified BEAM changes whose modules match
52
  the production allowlist. Structural changes use a packaged relup or rolling
53
  replacement, and boot convergence prevents a restarted node from serving an
54
  older target.
55
- Staging remains the qualification environment for changes that require
56
  browser, distributed-cluster, failure-injection, migration, or configuration
57
  evidence before production promotion.
58
59
Read the [Forge hot loop runbook](docs/operations/forge-hot-loop.md) for the
60
current deployment contract and production evidence.
63 61
64 62
## Architecture
65 63

@@ -118,9 +116,9 @@ before you bootstrap, plan, or apply any staging resource.

118 116
119 117
## Contributing and source control
120 118
121
Read `AGENTS.md` before changing the application. GitHub is temporarily the
122
canonical remote during staging hardening. The forge becomes canonical only
123
after the durability, mirror, restore, and deployment proofs in ADR 0007 pass.
119
Read `AGENTS.md` before changing the application. Push accepted work to the
120
owned Forge. `MirrorWatch` maintains GitHub as the public mirror; do not treat
121
an independently pushed GitHub branch as production authority.
124 122
125 123
## License
126 124
docs/architecture.md modified +19 -14

@@ -1,8 +1,8 @@

1 1
# OpenAgents architecture
2 2
3
Date: 2026-08-20
3
Date: 2026-08-22
4 4
5
Status: Current product architecture and accepted hardening target
5
Status: Current production architecture
6 6
7 7
## Purpose
8 8

@@ -187,7 +187,12 @@ authority.

187 187
188 188
## Runtime and staging topology
189 189
190
The accepted target has two isolated staging lanes:
190
Production runs one OpenAgents release on a three-node BEAM fleet. PostgreSQL
191
holds durable product and deployment authority. The Forge owns Git refs,
192
promotion targets, build receipts, and deployment receipts. Boot convergence
193
keeps a restarted node out of service until it matches the live target.
194
195
Qualification keeps two isolated staging lanes:
191 196
192 197
- A web lane proves Phoenix, LiveView, PostgreSQL, authentication, chat, voice,
193 198
  data rights, and provider behavior without distributed deployment enabled.

@@ -196,8 +201,8 @@ The accepted target has two isolated staging lanes:

196 201
197 202
Both lanes use staging-only hosts, credentials, buckets, repositories, service
198 203
accounts, and a PostgreSQL instance that does not share a production failure
199
domain. Production is out of scope until all hardening gates, the complete
200
staging matrix, failure injection, and the 15-minute pinned-candidate soak pass.
204
domain. Use staging for browser, migration, configuration, distributed-cluster,
205
and failure-injection evidence before a production promotion requires it.
201 206
202 207
`OpenAgents.RuntimeConfig` validates the complete behavior-changing settings
203 208
boundary before migrations or traffic. The

@@ -205,17 +210,17 @@ boundary before migrations or traffic. The

205 210
feature profile, durable storage requirements, staging-gate admission, and
206 211
content-free readiness report.
207 212
208
## Source control transition
213
## Source control authority
209 214
210
GitHub remains the repository's temporary canonical remote during staging
211
hardening. The self-hosted forge becomes canonical only through an explicit
212
cutover after its Git, mirror, artifact, rollback, and recovery gates pass. The
213
cutover changes contributor instructions and push automation in the same
214
candidate. After cutover, the forge pushes a read-only GitHub mirror and direct
215
GitHub pushes become invalid.
215
The self-hosted Forge is canonical. Contributors and deployment automation push
216
accepted work to the owned Forge. `MirrorWatch` exports the accepted branch to
217
GitHub and reports mirror lag separately from deployment state. A GitHub mirror
218
update cannot promote a deployment, and a direct GitHub push does not become
219
production authority.
216 220
217
Do not describe the cutover as complete while contributor clones and automated
218
pushes still target GitHub.
221
Read [ADR 0007](decisions/0007-cut-over-to-forge-canonical-source-control-after-proof.md)
222
and the [Forge hot loop runbook](operations/forge-hot-loop.md) for the cutover
223
decision and current operator procedure.
219 224
220 225
## Decision records
221 226
docs/decisions/0007-cut-over-to-forge-canonical-source-control-after-proof.md modified +12 -12

@@ -2,22 +2,22 @@

2 2
3 3
Date: 2026-08-20
4 4
5
Status: Accepted; cutover pending
5
Status: Accepted; cutover completed on 2026-08-22
6 6
7 7
## Context
8 8
9
The product intends to host its canonical Git repositories on the OpenAgents
10
forge and keep GitHub as a discoverable read-only mirror. This repository still
11
uses GitHub as its configured canonical remote during staging hardening. A
12
documentation-only cutover would split contributor and deployment state.
9
The product hosts its canonical Git repositories on the OpenAgents Forge and
10
keeps GitHub as a discoverable read-only mirror. Before the cutover, this
11
repository used GitHub as its configured canonical remote during staging
12
hardening. A documentation-only cutover would have split contributor and
13
deployment state.
13 14
14 15
## Decision
15 16
16
Keep GitHub canonical until the self-hosted Git plane passes authentication,
17
authorization, durability, mirror, restore, and operational recovery gates.
18
Perform the cutover as one controlled change that updates contributor
19
instructions, operator automation, build source, deployment promotion, and
20
mirror monitoring.
17
The self-hosted Git plane passed its authentication, authorization, durability,
18
mirror, restore, and operational recovery gates. The 2026-08-22 cutover updated
19
contributor instructions, operator automation, build source, deployment
20
promotion, and mirror monitoring as one controlled change.
21 21
22 22
After cutover, accept pushes only through the forge for normal operation. Push
23 23
a one-way read-only mirror to GitHub, monitor mirror lag, and treat a direct

@@ -25,8 +25,8 @@ GitHub push as an incident. Do not let a mirror push promote a deployment.

25 25
26 26
## Consequences
27 27
28
- Current contributors keep one accurate remote during hardening.
29
- The future cutover has explicit prerequisites and rollback evidence.
28
- Contributors use one canonical Forge remote.
29
- The completed cutover retains explicit prerequisites and rollback evidence.
30 30
- GitHub remains available for discovery without becoming a second writable
31 31
  authority.
32 32
- The application must report canonical-source and mirror state separately.
docs/runtime-configuration.md modified +25 -21

@@ -1,6 +1,6 @@

1 1
# Runtime configuration
2 2
3
Date: 2026-08-20
3
Date: 2026-08-22
4 4
5 5
Status: Current
6 6

@@ -9,11 +9,11 @@ runtime settings. It runs before migrations, workers, or the endpoint. Invalid

9 9
configuration raises a diagnostic containing only the setting name and its
10 10
requirement; it never echoes a value.
11 11
12
Production releases require `OPENAGENTS_ENVIRONMENT=staging` or `production`.
13
Production remains locked: `OPENAGENTS_ENVIRONMENT=production` is refused while
14
`OPENAGENTS_PRODUCTION_DEPLOY_ENABLED=false`. Do not change that setting until
15
the staging matrix and soak in the hardening plan are complete and an operator
16
records a separate production decision.
12
Deployed releases require `OPENAGENTS_ENVIRONMENT=staging` or `production`.
13
Production startup fails closed unless
14
`OPENAGENTS_PRODUCTION_DEPLOY_ENABLED=true`. The production cutover recorded
15
that decision on 2026-08-21; a new environment must still set the value
16
explicitly and satisfy the rest of this contract.
17 17
18 18
## Readiness report
19 19

@@ -121,26 +121,26 @@ The compiled defaults cap concurrency at two simultaneous SCVs, the wall clock

121 121
at 15 minutes, and captured output at 16 MB. The lane runs read-only against a
122 122
disposable clone of a forge repository at an exact revision.
123 123
124
## Required release settings
124
## Required deployed-release settings
125 125
126
All settings in this section are mandatory in a production release unless
127
marked conditional. An empty value is accepted only where the table explicitly
128
says "empty disables." Secrets come from the staging secret manager through
129
the runtime identity; never put them in images, build arguments, repository
130
URLs, receipts, or checked-in environment files.
126
All settings in this section are mandatory in a staging or production release
127
unless marked conditional. An empty value is accepted only where the table
128
explicitly says "empty disables." Secrets come from the environment's secret
129
manager through the runtime identity; never put them in images, build
130
arguments, repository URLs, receipts, or checked-in environment files.
131 131
132 132
| Group | Environment setting | Requirement |
133 133
| --- | --- | --- |
134
| Release | `OPENAGENTS_ENVIRONMENT` | `staging`; `production` remains separately locked |
134
| Release | `OPENAGENTS_ENVIRONMENT` | `staging` or `production` |
135 135
| Release | `OPENAGENTS_STAGING_GATE` | Integer `0` through `16`; feature admission is tied to it |
136 136
| Release | `OPENAGENTS_STAGING_CLEANUP_ENABLED` | `true` only at staging Gate 12 or later; always `false` elsewhere |
137
| Release | `OPENAGENTS_PRODUCTION_DEPLOY_ENABLED` | `false` until a later production decision |
138
| Release | `OPENAGENTS_IMAGE_DIGEST` | Exact `sha256:` image digest at staging Gate 12 and later; empty before that gate |
139
| Endpoint | `PHX_HOST` | Exactly `staging.openagents.com` in staging |
140
| Endpoint | `OPENAGENTS_ALLOWED_ORIGINS` | Comma-separated exact HTTPS origins including `https://staging.openagents.com` |
137
| Release | `OPENAGENTS_PRODUCTION_DEPLOY_ENABLED` | `true` only for an admitted production release; `false` in staging |
138
| Release | `OPENAGENTS_IMAGE_DIGEST` | Exact `sha256:` image digest in production and at staging Gate 12 or later; empty only before that staging gate |
139
| Endpoint | `PHX_HOST` | Exactly `staging.openagents.com` in staging; use the admitted public host in production |
140
| Endpoint | `OPENAGENTS_ALLOWED_ORIGINS` | Comma-separated exact HTTPS origins including the environment's `PHX_HOST` |
141 141
| Endpoint | `OPENAGENTS_HTTPS_ALIASES` | Comma-separated hostnames; empty means no aliases |
142 142
| Endpoint | `OPENAGENTS_SECURE_COOKIES` | `true` in staging and production |
143
| Endpoint | `SECRET_KEY_BASE` | Staging-only secret |
143
| Endpoint | `SECRET_KEY_BASE` | Environment-specific secret |
144 144
| Endpoint | `PORT` | Port `1` through `65535` |
145 145
| Database | `OPENAGENTS_DATABASE_MODE` | `url` or `socket` |
146 146
| Database | `DATABASE_URL` | Required only in `url` mode |

@@ -148,14 +148,14 @@ URLs, receipts, or checked-in environment files.

148 148
| Database | `OPENAGENTS_DATABASE_IPV6` | Explicit `true` or `false` |
149 149
| Database | `POOL_SIZE` | Integer `1` through `200` |
150 150
| Database | `OPENAGENTS_MIGRATE_ON_BOOT` | `true` in staging and production |
151
| GitHub | `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET` | Staging OAuth application credentials |
151
| GitHub | `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET` | OAuth application credentials for the selected environment |
152 152
| GitHub | `GITHUB_REDIRECT_URI` | Exact HTTPS callback on `PHX_HOST` |
153 153
| GitHub | `GITHUB_OAUTH_SCOPES` | Exactly `repo,read:org`; repository import needs retained repository access and organization creation needs membership access |
154 154
| GitHub | `OPENAGENTS_ADMIN_GITHUB_IDS` | Comma-separated immutable numeric GitHub IDs allowed to use operator surfaces; never use logins |
155
| GitHub | `GITHUB_TOKEN_ENCRYPTION_KEY` | Base64-encoded 32-byte staging key |
155
| GitHub | `GITHUB_TOKEN_ENCRYPTION_KEY` | Base64-encoded 32-byte key for the selected environment |
156 156
| GitHub | `GITHUB_TOKEN_ENCRYPTION_KEY_ID` | Bounded active-key identifier prefixed with `development-`, `test-`, `staging-`, or `production-` to match the runtime |
157 157
| GitHub | `GITHUB_TOKEN_DECRYPTION_KEYS_JSON` | Optional map of at most 16 same-environment prior keys used only during rewrap; omit the active ID |
158
| Providers | `OPENAI_API_KEY` | Staging-only provider secret; required by the current text provider |
158
| Providers | `OPENAI_API_KEY` | Environment-specific provider secret; required by the current text provider |
159 159
| Providers | `OPENAGENTS_INFERENCE_PROXY_URL` | HTTPS URL without credentials when computers are enabled; empty disables |
160 160
| Computers | `OPENAGENTS_MACHINE_TOKEN_TTL_SECONDS` | `300` through `2592000`; Gate 5 uses the 30-day maximum |
161 161
| Recording | `VOICE_RECORDING_ENCRYPTION_KEY` | Base64-encoded 32-byte key when recording is enabled; empty disables recording storage |

@@ -170,6 +170,10 @@ compile-time default and the Gate 5 staging override are deliberately the same

170 170
safe value unless noted. Advancing `OPENAGENTS_STAGING_GATE` admits a feature;
171 171
it does not enable it automatically.
172 172
173
The table records compiled defaults and the Gate 5 staging template. It is not
174
a live production feature inventory. Run `bin/config-readiness` inside the
175
target release to inspect its redacted feature booleans.
176
173 177
| Feature | Environment setting | Default | Gate 5 staging | Earliest staging gate |
174 178
| --- | --- | --- | --- | --- |
175 179
| Tool catalog | `OPENAGENTS_FEATURE_TOOLS` | On | On | 5 |
docs/scv-planning.md modified +16 -15

@@ -1,11 +1,10 @@

1 1
# SCV planning
2 2
3
Date: 2026-08-20
3
Date: 2026-08-22
4 4
5
Status: OpenCode worker and Codex propose-only driver implemented; Codex runs
6
now retain durable leases, normalized events, and terminal reports; isolated
7
staging qualification, durable write effects, and autonomous deployment remain
8
disabled
5
Status: OpenCode worker, Codex propose-only driver, and operator-started
6
read-only deployment lane implemented; durable write effects and autonomous
7
promotion remain disabled
9 8
10 9
## Outcome
11 10

@@ -26,11 +25,12 @@ receipts preserve the SCV's identity and progress across those events.

26 25
The intended end state includes automatic deployment. The first implementation
27 26
must not bypass the repository's current safety contracts:
28 27
29
- GitHub remains canonical until the proof-gated cutover in
28
- The Forge is canonical after the proof-gated cutover in
30 29
  [ADR 0007](decisions/0007-cut-over-to-forge-canonical-source-control-after-proof.md).
31
- Forge fleet deployment remains disabled until the isolated staging gates in
32
  the [integration hardening plan](2026-08-20-integration-hardening-and-staging-readiness-recommendations.md)
33
  pass.
30
  SCV candidates must use its authenticated push and promotion boundaries.
31
- Forge fleet deployment is active. The SCV deployment lane remains a bounded,
32
  operator-started, read-only work job and does not grant repository writes or
33
  promotion authority.
34 34
- `SELF-EDIT-001` currently requires a human promotion. Enabling an SCV to
35 35
  promote a candidate requires an explicit invariant and architecture amendment,
36 36
  a typed service principal, and a policy-bound promotion receipt. Do not encode

@@ -1053,11 +1053,11 @@ Advance the integration ref through the normal authenticated Forge push path so

1053 1053
the WAL remains ref authority. Use compare-and-swap against the recorded base.
1054 1054
Do not update a bare repository ref directly from application code.
1055 1055
1056
Before Forge becomes canonical, keep an SCV in propose-only mode and reconcile
1057
its run refs through the existing GitHub review process. After the ADR 0007
1058
cutover, decide whether `scv/integration` becomes the default branch or merges
1059
into it through another policy-controlled fast-forward. Do not operate two
1060
writable canonical histories.
1056
The Forge is canonical. Keep an SCV in propose-only mode until a separately
1057
admitted write policy exists. Decide whether `scv/integration` becomes the
1058
default branch or merges into it through another policy-controlled
1059
fast-forward. Do not operate a second writable history through the GitHub
1060
mirror.
1061 1061
1062 1062
### Workspace lifecycle
1063 1063

@@ -1652,7 +1652,8 @@ The runtime boundary should reject:

1652 1652
- an executor path under `/tmp` in staging or production;
1653 1653
- an automatic mode before Forge deployment, boot convergence, durable
1654 1654
  artifacts, and isolated staging are enabled;
1655
- `production_auto` while production deployment remains globally disabled;
1655
- `production_auto` without a separate production-autonomy admission and
1656
  policy receipt;
1656 1657
- multiple active runs in the first policy revision;
1657 1658
- multiple repository writers for one integration history;
1658 1659
- a benchmark comparison across incompatible provenance;

This page updates live while a promote is in flight · changelog