@bongos/core 1.19.669 → 1.19.671

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.
package/.bongos-core.json CHANGED
@@ -2,22 +2,22 @@
2
2
  "artifact": "bongos-core",
3
3
  "manifest_schema": 1,
4
4
  "generator": "scripts/gds/package-core.js",
5
- "core_version": "1.19.669",
6
- "core_contract": "1.19.669",
7
- "source_commit": "db01ff449e0ec3309c33d4eae81dfdedad7b5a62",
5
+ "core_version": "1.19.671",
6
+ "core_contract": "1.19.671",
7
+ "source_commit": "0a763ef9ec340852f55a3965a6c19986a45046ff",
8
8
  "source_ref": "HEAD",
9
- "built_at": "2026-09-11T16:04:31.249Z",
9
+ "built_at": "2026-09-11T17:22:28.926Z",
10
10
  "redaction": {
11
11
  "model": "docs-redacted+functional-verbatim",
12
12
  "docs_redacted": 474,
13
13
  "agent_docs_stubbed": 24,
14
- "functional_verbatim": 2117,
14
+ "functional_verbatim": 2118,
15
15
  "rules": 3,
16
16
  "gate_literals": 3,
17
17
  "gate": "passed"
18
18
  },
19
- "file_count": 2615,
20
- "tree_sha256": "5afa597392cde4d8a5783032728f5ea81ba2c271f4226d71e893d0fc19f2cf04",
19
+ "file_count": 2616,
20
+ "tree_sha256": "42280e5e37aea19c48662a7b0ebca8185a73ccbcc99dbda54ebe92b4677d1f9b",
21
21
  "files": [
22
22
  {
23
23
  "path": ".claude/skills/ask-for-help/SKILL.md",
@@ -197,7 +197,7 @@
197
197
  {
198
198
  "path": ".claude/skills/new-project/SKILL.md",
199
199
  "mode": "0000644",
200
- "sha256": "5187e211cb0ff19f41ade425016b6f6909aa35f220fc77dba87e56784bf16d21"
200
+ "sha256": "d530f15de6e7c4a07c595d624d403c5616d66380e99e564ef3c63b3518141441"
201
201
  },
202
202
  {
203
203
  "path": ".claude/skills/otb-character-review/SKILL.md",
@@ -1942,12 +1942,12 @@
1942
1942
  {
1943
1943
  "path": "docs/copy-inventory.md",
1944
1944
  "mode": "0000644",
1945
- "sha256": "9faae742143a1492fe9bbc3075bb6cfa87efa9eebd2225d98743e708f138110f"
1945
+ "sha256": "108d5f76c932420b5fa59294964f5539dc7d0ffcebf702908ad99057fab23b96"
1946
1946
  },
1947
1947
  {
1948
1948
  "path": "docs/copy-registry.json",
1949
1949
  "mode": "0000644",
1950
- "sha256": "fa55c6a5c2a89e7ac27dcbb12b8efe5c7d812e5386aeb4726412419d53ac577f"
1950
+ "sha256": "712bb18fa67b3d3117a2462f42df103c5de14189e02614002b6bdc1d235c5d74"
1951
1951
  },
1952
1952
  {
1953
1953
  "path": "docs/design/apex-pass-2-direction.md",
@@ -2792,7 +2792,7 @@
2792
2792
  {
2793
2793
  "path": "docs/module-api-changelog.md",
2794
2794
  "mode": "0000644",
2795
- "sha256": "f2ca27e78e014e1980d45622dbd0ff7e71f049c69e7ac84485fb6d12cac8aa23"
2795
+ "sha256": "8a01d9a97452117af49288c971f85d7a79469bb6ba69e90916b4c8f9d687c16e"
2796
2796
  },
2797
2797
  {
2798
2798
  "path": "docs/modules-contract.md",
@@ -6462,7 +6462,7 @@
6462
6462
  {
6463
6463
  "path": "modules/provisioning/onboard-plan.js",
6464
6464
  "mode": "0000644",
6465
- "sha256": "31f14cbf3d649c25f1f17c508ae19be2f39d9e1991fde17cdce08cb15837ffa1"
6465
+ "sha256": "3c36bb1b163a35492ccd3d231e50039bded945fbccac076166c70a67767a687d"
6466
6466
  },
6467
6467
  {
6468
6468
  "path": "modules/provisioning/paid-shape-gate.js",
@@ -6757,7 +6757,7 @@
6757
6757
  {
6758
6758
  "path": "modules/public-landing/public/assets/cosmos.css",
6759
6759
  "mode": "0000644",
6760
- "sha256": "17637a0fd4eafddcd3235dec51c0ff196a8b39360918ab7a4c0370fc21d3a20f"
6760
+ "sha256": "2e05801f13227c5d6d0b26f9f0c476ad767fd9bbe2c034f82a3e315045781eb9"
6761
6761
  },
6762
6762
  {
6763
6763
  "path": "modules/public-landing/public/assets/verro-medallion.png",
@@ -7017,7 +7017,7 @@
7017
7017
  {
7018
7018
  "path": "modules/public-landing/public/projects.html",
7019
7019
  "mode": "0000644",
7020
- "sha256": "864b6ee7a8b1866196d6595914f614e388a51c2a160fd86f454ab4a32a4740d5"
7020
+ "sha256": "746c73316bc99c129e8194a221f254b949eb7627adee4bc34dc8c2b252b2d8aa"
7021
7021
  },
7022
7022
  {
7023
7023
  "path": "modules/public-landing/public/projects.probes.json",
@@ -7027,7 +7027,7 @@
7027
7027
  {
7028
7028
  "path": "modules/public-landing/public/projects.states.json",
7029
7029
  "mode": "0000644",
7030
- "sha256": "a2d3ecc5e893bcaa5632c2d693d5b642c7041cc285e382d572954284ad64e241"
7030
+ "sha256": "8036ab52536938c3b13be9e1828c82b3c09a18ab5d16d3453377b7ffc2661495"
7031
7031
  },
7032
7032
  {
7033
7033
  "path": "modules/public-landing/public/terms.html",
@@ -7762,12 +7762,12 @@
7762
7762
  {
7763
7763
  "path": "package-lock.json",
7764
7764
  "mode": "0000644",
7765
- "sha256": "11cc0033b8ee7fa774319888e0f0fe6dc24af043e607d5d99ce59bfc7969efba"
7765
+ "sha256": "8084af7f816968cec2558f8f21bee36c4b787f8603ed7434c6f8b696e012d595"
7766
7766
  },
7767
7767
  {
7768
7768
  "path": "package.json",
7769
7769
  "mode": "0000644",
7770
- "sha256": "8d94b2f718aeb052f7e3c0464fbde8afa6f06c2a8096c90f26abddbf368aeb9f"
7770
+ "sha256": "840f76afd4ba0411b424c261cc6ac47249e290f750d0689fcc3d0dbb6a092fec"
7771
7771
  },
7772
7772
  {
7773
7773
  "path": "public-docs/index.html",
@@ -9527,7 +9527,7 @@
9527
9527
  {
9528
9528
  "path": "src/module-api.js",
9529
9529
  "mode": "0000644",
9530
- "sha256": "5c09f13b72c589166b1fb7152b89bb76cccbef4475ae7d3047a515a59cfb31a2"
9530
+ "sha256": "8ab93337256fc2149eb837340f00431d7eda915d8c0d99be9d5ae5a7b2b47648"
9531
9531
  },
9532
9532
  {
9533
9533
  "path": "src/module-loader/catalog.js",
@@ -11757,7 +11757,7 @@
11757
11757
  {
11758
11758
  "path": "tests/onboard.mjs",
11759
11759
  "mode": "0000644",
11760
- "sha256": "b77d62d7dd83ff167e25c53787527ea044bd99df88482ee24ee02ba2137000f7"
11760
+ "sha256": "932cb047550c1fe02875f752e2a65fd1c592e3196fca1a25cec6a43e7ca45264"
11761
11761
  },
11762
11762
  {
11763
11763
  "path": "tests/onboarding_gate.mjs",
@@ -12027,7 +12027,7 @@
12027
12027
  {
12028
12028
  "path": "tests/projects_hub_pre_uat.mjs",
12029
12029
  "mode": "0000644",
12030
- "sha256": "e16e0488e1364a09503cec17a85e19ed6045fd8c6430c472c050934e1cad4013"
12030
+ "sha256": "b9e399b507c7382f6ef8643a0d7dda145fb435d97e9bf53fa47615cb4d03fb56"
12031
12031
  },
12032
12032
  {
12033
12033
  "path": "tests/promote_goal_id.mjs",
@@ -13054,6 +13054,11 @@
13054
13054
  "mode": "0000644",
13055
13055
  "sha256": "74ffbc7e4585e651d00ab879ece6f3d23089d7c9ae7acb15483d3752b47bbdc0"
13056
13056
  },
13057
+ {
13058
+ "path": "tests/wizard_intent_resume.mjs",
13059
+ "mode": "0000644",
13060
+ "sha256": "d3d6fe02e18598ea9a146b3af7c3dff96a69a68ca9e95a7227e3c6549bbd6cc4"
13061
+ },
13057
13062
  {
13058
13063
  "path": "tests/wizard_preselect_why.mjs",
13059
13064
  "mode": "0000644",
@@ -22,18 +22,35 @@ Interview the owner for: product name, world name, company; the **GitHub repo**
22
22
 
23
23
  ### 2. Tell us about the project — OPTIONAL, and skipping it is fine (task 1002334)
24
24
 
25
- Ask two things, and offer the skip in the same breath — a "you can leave this blank" that arrives *after* the question reads as a test:
25
+ Ask three things, and offer the skip in the same breath — a "you can leave this blank" that arrives *after* the question reads as a test:
26
26
 
27
27
  - **What are you building?** A sentence or two. This is the project's **description**, and it is half of the publish gate ([ADR 0182](../../../docs/adr/<redacted>.md) D4: a project is on the public map iff it has a name AND a description).
28
28
  - **Who's building it?** `solo` / `small-team` / `community`. This is what the platform's setup recommendations read.
29
+ - **What kind of project is it?** `game` / `research` / `business` / `non-profit` / `not-sure` — the declared **type**, and the one answer that does real work downstream: it keys the starter bundle the next step preselects ([ADR 0237](../../../docs/adr/<redacted>.md)). `not-sure` is a real answer, not a missing one.
29
30
 
30
- Both ride the provisioning request as `description` and `detail: { team_shape }`. **Skipping is a supported default, not a failure:** the project stands up exactly the same, it just stays *dark matter* — off the public map and un-joinable — until a description exists. Say that plainly when the owner skips, and say the way back with it: `PATCH /provisioning/instances/:id/detail` fills either answer in later, and publishes the project the moment the description lands.
31
+ All three ride the provisioning request `description`, `detail: { team_shape }`, and `type` — and each is independently skippable. **Skipping is a supported default, not a failure:** the project stands up exactly the same, it just stays *dark matter* — off the public map and un-joinable — until a description exists. Say that plainly when the owner skips, and say the way back with it: `PATCH /provisioning/instances/:id/detail` takes `description`, `detail` and `modules` later, and publishes the project the moment the description lands.
32
+
33
+ **`type` is the one answer with no way back yet** — the detail PATCH does not accept it, and an owner-facing "change my project type" surface is still open work (task 1003504). Do not tell an owner they can change it later. It is still safe to leave unanswered: `not-sure` and an absent type both simply mean the next step has no type-specific bundle to preselect, and the modules themselves stay editable forever.
31
34
 
32
35
  Never gate the standup on this step, and never invent an answer the owner didn't give — a recommendation built on a guess is worse than no recommendation.
33
36
 
34
37
  **Read the verdict back rather than asserting one (task 1002335).** Every instance read and the detail PATCH answer with `publish: { publishable, missing, missing_phrase }` — the server's own derivation of the gate. Report *that*, verbatim: "it's on the public map" or "it has no description, so it isn't on the map yet". Do not compute publishability yourself from the fields you happen to have sent; the owner's project page renders the same server verdict, and two surfaces disagreeing about whether a project is published is worse than either being briefly stale. If `publish` is absent, this platform has no public map — say nothing about one.
35
38
 
36
- ### 3. DNS token preflightBEFORE you commit the address (task 1980)
39
+ ### 3. Pick its extrasOPTIONAL, and the skip is the recommendation (task 1002339)
40
+
41
+ Every project runs the **always-on core** whatever you do here; this step is only about the **optional** modules on top. Read the preselection out of the server, never a list you carry: `GET /provisioning/starter-bundles` returns the always-on core once, then one resolved bundle per type — and the bundle for the type answered in step 2 is what the picker shows ticked ([ADR 0237](../../../docs/adr/<redacted>.md)). Show the owner what is already ticked and why, then let them add or remove.
42
+
43
+ The type is not the only input: the **team shape** from step 2 adjusts the bundle too, and the server reports each adjustment that actually changed something, with its reason. Those belong to the bundle itself, not to a note beside it — render them as part of what is ticked, so cause and effect arrive together ([ADR 0243](../../../docs/adr/<redacted>.md)). A rule whose module the bundle already carries records nothing, so an empty adjustment list means the shape changed nothing, not that it was ignored.
44
+
45
+ **Skipping means "take the bundle", and that is a real default, not a deferral** ([ADR 0240](../../../docs/adr/<redacted>.md)). Three answers, three different meanings — say them apart, because two of them look alike and are not:
46
+
47
+ - **Skip** — send no `modules` key at all. The row stores nothing and the bundle is resolved **on read**, so the project ends up with exactly the set the picker had ticked. A later change to the bundle for that type reaches this project too.
48
+ - **An explicit list** — `modules: ["…"]`, the opt-in keys only, never the always-on core. This is now the project's own answer and it stops tracking the bundle.
49
+ - **`modules: []`** — the deliberate "none of them". Not the same as skipping, and a flow that collapses the two takes a choice away.
50
+
51
+ Nothing here is final: modules can be added after creation from the project's own page, which is why this step should never feel like a gate. If the owner is unsure, say that the bundle is the recommendation and move on — an owner stalled choosing modules is the failure this step's default exists to prevent.
52
+
53
+ ### 4. DNS token preflight — BEFORE you commit the address (task 1980)
37
54
 
38
55
  Before anything is provisioned, verify the control-plane's Cloudflare token can actually manage the domain's zone (a mismatched-zone token is exactly what broke the Emersonian standup mid-flow):
39
56
 
@@ -44,12 +61,12 @@ node scripts/gds/provision.js dns-check <domain>
44
61
  - ✓ reachable → continue.
45
62
  - ✗ not reachable → **STOP and resolve it now**, don't push past it. The command prints the fix; usually: widen the Cloudflare API token to include the domain's zone (CF dashboard → My Profile → API Tokens → edit → Zone Resources → Include → the zone), then re-run `dns-check` until green. Only then proceed.
46
63
 
47
- ### 4. `bongos init` — scaffold (greenfield) **or** `--adopt` (brownfield)
64
+ ### 5. `bongos init` — scaffold (greenfield) **or** `--adopt` (brownfield)
48
65
 
49
66
  **This is the one leg that branches** (ADR 0121 §Decision 1). Pick the mode that matches the repo:
50
67
 
51
68
  - **Greenfield** — a NEW, empty repo. The default below.
52
- - **Brownfield / adopt** — an EXISTING repo (code, history, a backlog). Run `node bin/bongos.js init --adopt` instead. It DETECTS the repo's stack, runs a conflict **pre-flight** (migration-namespace / fitness-boundary / protected-path / CI-check collisions) and writes **nothing until you accept** (interactive y/N, or `--accept`); a genuine BLOCK (e.g. a `core_`-prefixed migration) is a hard stop, not accept-able. On accept it LAYERS the lean config + the pinned `@cloudbongos/core` dep + `.claude/` **additively** (merges-or-leaves-and-reports; never clobbers, never the `--force` path), captures the repo's **REAL** current version/goal, and imports its existing backlog (open GitHub issues via `GITHUB_TOKEN`/`GH_TOKEN`, else a `TODO`/`ROADMAP`/`BACKLOG` file). Then **skip step 5** — adopt layered onto the existing repo, there is no empty repo to scaffold — and continue from step 6 (provision). Every other leg is identical.
69
+ - **Brownfield / adopt** — an EXISTING repo (code, history, a backlog). Run `node bin/bongos.js init --adopt` instead. It DETECTS the repo's stack, runs a conflict **pre-flight** (migration-namespace / fitness-boundary / protected-path / CI-check collisions) and writes **nothing until you accept** (interactive y/N, or `--accept`); a genuine BLOCK (e.g. a `core_`-prefixed migration) is a hard stop, not accept-able. On accept it LAYERS the lean config + the pinned `@cloudbongos/core` dep + `.claude/` **additively** (merges-or-leaves-and-reports; never clobbers, never the `--force` path), captures the repo's **REAL** current version/goal, and imports its existing backlog (open GitHub issues via `GITHUB_TOKEN`/`GH_TOKEN`, else a `TODO`/`ROADMAP`/`BACKLOG` file). Then **skip step 6** — adopt layered onto the existing repo, there is no empty repo to scaffold — and continue from step 7 (provision). Every other leg is identical.
53
70
 
54
71
  Greenfield:
55
72
 
@@ -59,11 +76,11 @@ node bin/bongos.js init # interview (or: init --from spec.json for non-
59
76
 
60
77
  It writes lean `config/branding.json` / `config/modules.json` / `config/hierarchy.json`, seeds the first version + its done-when goal, files the human-only kickoff tasks, and — when you opt into hosting — files a **provisioning request** (`POST /provisioning/instances`). Choose **hosting shape `standalone`**. Enable the `provisioning` module on the target so the request is honored (`config/modules.json` → `"provisioning": true`).
61
78
 
62
- ### 5. Scaffold the standalone repo
79
+ ### 6. Scaffold the standalone repo
63
80
 
64
- Materialize the instance's own repo (ADR 0108): clone the empty GitHub repo to the standalone root (`${PROVISION_STANDALONE_BASE:-/srv/cloudbongos}/<slug>` on the control plane), drop in the `config/` + `.claude/` from step 4, and pin the core as a dependency (`@cloudbongos/core` in the instance `package.json`). Commit + push. This checkout is what the standalone service will run from.
81
+ Materialize the instance's own repo (ADR 0108): clone the empty GitHub repo to the standalone root (`${PROVISION_STANDALONE_BASE:-/srv/cloudbongos}/<slug>` on the control plane), drop in the `config/` + `.claude/` from step 5, and pin the core as a dependency (`@cloudbongos/core` in the instance `package.json`). Commit + push. This checkout is what the standalone service will run from.
65
82
 
66
- ### 6. Provision — core + DB + address + service (task 1978)
83
+ ### 7. Provision — core + DB + address + service (task 1978)
67
84
 
68
85
  The web tier only **enqueued** the request; the **control-plane runner** does the real work (it alone holds the DO/Cloudflare tokens):
69
86
 
@@ -72,9 +89,9 @@ node scripts/gds/provision.js run-intents --apply # drains the queue
72
89
  # or, for one instance: node scripts/gds/provision.js provision <slug> --apply
73
90
  ```
74
91
 
75
- For `standalone` this composes: allocate a port → `git pull` + `npm ci --omit=dev` (installs the pinned core) → `createdb` + **instance-root** migrate (`node_modules/@cloudbongos/core/scripts/migrate.sh`) → per-instance `/etc/<slug>/web.env` → a **standalone systemd unit** (runs the core package's `platform-server.js` from the instance repo) → DNS A-record UPSERT → per-instance Caddy snippet (on-demand TLS) → `/healthz`. It is idempotent + dry-run-by-default (omit `--apply` to preview). It **fail-fasts on the step-2 DNS preflight** if step 2's token check was skipped.
92
+ For `standalone` this composes: allocate a port → `git pull` + `npm ci --omit=dev` (installs the pinned core) → `createdb` + **instance-root** migrate (`node_modules/@cloudbongos/core/scripts/migrate.sh`) → per-instance `/etc/<slug>/web.env` → a **standalone systemd unit** (runs the core package's `platform-server.js` from the instance repo) → DNS A-record UPSERT → per-instance Caddy snippet (on-demand TLS) → `/healthz`. It is idempotent + dry-run-by-default (omit `--apply` to preview). It **fail-fasts on the step-4 DNS preflight** if that token check was skipped.
76
93
 
77
- ### 7. GitHub sign-in — ONE click (App Manifest flow), or a manual OAuth app + first sign-in
94
+ ### 8. GitHub sign-in — ONE click (App Manifest flow), or a manual OAuth app + first sign-in
78
95
 
79
96
  **Recommended — one click (task 2080, ADR 0133).** GitHub has no create-an-OAuth-App API, but it *does* let us pre-fill a **GitHub App Manifest**: the owner clicks one link, approves on GitHub, and GitHub hands the control plane the credentials automatically — **no OAuth app to hand-create, no secret to copy-paste ever.** From the control-plane hall, **Start a project → “Set up GitHub sign-in”** (the button appears once the instance is requested; it needs the instance's **domain** set). Under the hood it:
80
97
 
@@ -103,7 +120,7 @@ node scripts/gds/oauth-secret.js place <slug> --client-id <id> --client-secret <
103
120
 
104
121
  **Human-only — first sign-in.** The owner opens `https://<domain>` and signs in with GitHub **once**. This seats the **founding Archon** — config alone seats no one, so this step is inherent and cannot be automated.
105
122
 
106
- ### 8. Verify
123
+ ### 9. Verify
107
124
 
108
125
  ```bash
109
126
  curl -s https://<domain>/healthz # → {"ok":true,"auth_configured":true}
@@ -111,25 +128,56 @@ curl -s https://<domain>/healthz # → {"ok":true,"auth_configured":tru
111
128
 
112
129
  Confirm the owner is **Archon** (their profile / the hall roster). If `auth_configured` is `false`, re-run the `oauth-secret place` step and recheck the OAuth app values.
113
130
 
114
- ### 9. Brand
131
+ ### 10. Brand
115
132
 
116
133
  Fill the instance **look** — theme / palette / fonts in `config/branding.json` (see `docs/branding-fill-prompt.md`). The identity strings were set at init; this is the visual layer. "Brand with your own LLM."
117
134
 
118
- ### 10. Enter your builders hall
135
+ ### 11. Enter your builders hall
119
136
 
120
137
  The hall is the point of everything above — end there, not at brand (task 1002703):
121
138
 
122
139
  - **With a domain:** open `https://<domain>/builders` — that's the project's home.
123
140
  - **No domain yet:** run `bongos dev` in the repo checkout — it stands the instance up locally and serves the hall on the owner's machine ([ADR 0149](../../../docs/adr/<redacted>.md)).
124
141
 
142
+ ### 12. Decide how the project stands — the four axes (BV1.R05/R10/R12, ADR 0182)
143
+
144
+ **These are not asked during creation, and that is deliberate.** A new project starts on today's behaviour — `platform_visibility: public`, `joinability: apply`, `visibility: public`, `join_grant: full` — and the owner changes them afterwards from the project's own page, each card PATCHing `…/instances/:id/settings` with its own key. Do not invent a visibility question in the creation flow; walk the owner through these once they are in, when the project is real enough for the answers to mean something.
145
+
146
+ Four axes, four different questions — they are **not** synonyms, and an owner may set them independently ([ADR 0182](../../../docs/adr/<redacted>.md)):
147
+
148
+ | Key | Asks | Values |
149
+ |---|---|---|
150
+ | `platform_visibility` | who may **read** this project's own pages | `public` · `gated` |
151
+ | `joinability` | **how** someone becomes a member | `open` · `apply` · `invite_only` |
152
+ | `visibility` | how it stands on the platform's **map** | `public` · `private` · `stealth` |
153
+ | `join_grant` | what joining a **public** project grants | `view` · `apply` · `full` |
154
+
155
+ Four things worth saying plainly, each of which has already confused someone:
156
+
157
+ - **`visibility` does not put the project on the map — publishability does.** A project is on the public map iff it has a name AND a description ([ADR 0182](../../../docs/adr/<redacted>.md) D4); that is derived, never stored, and no value of `visibility` puts a husk on the map. Read the server's `publish: { publishable, missing, missing_phrase }` back verbatim rather than computing it (step 2's rule, and it applies here too).
158
+ - **`gated` is enforced on the instance, not by the hub** — a middleware ahead of every surface refuses a session-less stranger with a door that carries the way in ([ADR 0192](../../../docs/adr/<redacted>.md)). It grants nothing; every rank check behind it still runs.
159
+ - **Gated and apply-to-join compose, and a stranger can still apply** ([ADR 0278](../../../docs/adr/<redacted>.md)): the member door exempts the application write and the applicant's own status poll, each scoped to one verb, so the owner's applicant queue keeps the door in front of it. Before that fix the two settings silently composed into "nobody can apply".
160
+ - **The door is one composed answer, and a refusal never names which knob closed it** ([ADR 0247](../../../docs/adr/<redacted>.md)). `join_grant` is the ceiling on the visibility axis that `joinability` may only narrow, and it governs the `public` state alone.
161
+
162
+ A settings change rides web.env and is applied by a **restart**, so the project's own manifest is the only honest source for what it currently runs — the saved choice and the running value differ for the whole life of a push, and a surface that collapses them is lying in one direction or the other ([ADR 0190](../../../docs/adr/<redacted>.md)).
163
+
164
+ ### 13. Invite the first builder — the done panel's first act, not a rail step (ADR 0249)
165
+
166
+ Deliberately **outside** the numbered rail above: a step that can only run once the project exists is not a step in creating it, and putting it in the rail would buy a renumbering coupling and still have to be reordered to sit after Create ([ADR 0249](../../../docs/adr/<redacted>.md)). It appears the moment the created record has an id and a slug, it is skippable there, and **the same widget is the way back** — the project's own page carries it beside *Its extras*, one implementation mounted twice, so an owner who skipped is never stuck.
167
+
168
+ `GET /provisioning/instances/:id/invite-suggestions` answers who is worth inviting. Treat that list as a **recruiting surface**: it owes the people on it the recruiting opt-out, and an owner who is shown names has to be shown them honestly ([ADR 0251](../../../docs/adr/<redacted>.md)).
169
+
125
170
  ## Done-when
126
171
 
127
- A new owner has gone zero → live: their own standalone repo on a pinned core, provisioned with no hand-editing of servers, the four human-only steps done UI-first + verified, and they are signed in as the founding Archon on their own domain. That is goal 35's `project-creation-flow` criterion.
172
+ A new owner has gone zero → live: their own standalone repo on a pinned core, provisioned with no hand-editing of servers, the six human-only steps done UI-first + verified, and they are signed in as the founding Archon on their own domain. That is goal 35's `project-creation-flow` criterion.
173
+
174
+ Steps 12 and 13 are **not** part of that criterion and must never gate it. They are what the owner does once the project is theirs — how it stands on the platform, and who else is in it — and both have a way back, so an owner who does neither has still finished creating a project.
128
175
 
129
176
  ## Constraints
130
177
 
131
- - **This skill is the source of truth for the sequence.** If a step changes, change it here; `bongos onboard` (task 1982) and the hall wizard (task 1983) must render the same sequence.
178
+ - **This skill is the source of truth for the sequence.** If a step changes, change it here; `bongos onboard` (task 1982) and the hall wizard (task 1983) must render the same sequence. The machine-readable twin is [`modules/provisioning/onboard-plan.js`](../../../modules/provisioning/onboard-plan.js), served at `GET /provisioning/onboard-plan` — a **rail** step added here gets a step there in the same change, or the two drift and each claims to be canonical.
179
+ - **Steps 12 and 13 are deliberately NOT in that plan**, and that is the distinction to keep: the plan is the creation rail, and both of those run only once the project exists. A step that can only run after the terminal step is not a step in the rail ([ADR 0249](../../../docs/adr/<redacted>.md)) — it belongs to the done panel and the project's own page, each of which carries its own way back.
132
180
  - **Standalone only** (ADR 0108) — do not fall back to editing this monorepo's checkout for a new project.
133
181
  - **Never weaken the trust boundary** — the web tier enqueues; only the control-plane runner (`provision.js`) touches cloud tokens (ADR 0016 / 0111 §2).
134
182
  - **Live docs are automatic** — a standalone instance's session-log index regenerates on deploy (`provision.js` runs `regen-instance-docs.js` after migrate; `bongos init`/`upgrade` seed+refresh it), and the whole-file nav docs are gitignored so `git reset --hard` never wipes them ([ADR 0147](../../../docs/adr/<redacted>.md)). If you wire a **bespoke** deploy script for an instance, it MUST call `node node_modules/@bongos/core/scripts/gds/regen-instance-docs.js` after `git reset` + migrate — see [`docs/recipes/standalone-live-docs.md`](../../../docs/recipes/standalone-live-docs.md).
135
- - **Adopting an EXISTING repo** (brownfield) is the other branch of the scaffold leg (step 4) — `bongos init --adopt` ([ADR 0121](../../../docs/adr/<redacted>.md)): detect → accept-gated conflict pre-flight → additive layering (never clobbers) → real version/goal + backlog import. Built; the `bongos onboard` CLI and the hall "start a project" wizard offer the same greenfield-vs-adopt choice.
183
+ - **Adopting an EXISTING repo** (brownfield) is the other branch of the scaffold leg (step 5) — `bongos init --adopt` ([ADR 0121](../../../docs/adr/<redacted>.md)): detect → accept-gated conflict pre-flight → additive layering (never clobbers) → real version/goal + backlog import. Built; the `bongos onboard` CLI and the hall "start a project" wizard offer the same greenfield-vs-adopt choice.