@descix/cli 3.0.0 → 3.0.2

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/README.md CHANGED
@@ -30,7 +30,8 @@ npm install -g @descix/cli
30
30
  ```
31
31
  An unconfigured workspace resolves to the declared default, PROD, and every network-bound
32
32
  command prints the environment, origin and source it resolved on stderr. For a local backend,
33
- name the URL: `descix config set-env dev --url https://localhost:4000`.
33
+ name the URL: per run `descix --api-url https://localhost:4000 <command>`, or persistently
34
+ `descix config set-env local --url https://localhost:4000` (`set-env` refuses a known name).
34
35
 
35
36
  3. **Check your status**:
36
37
  ```bash
@@ -111,21 +112,22 @@ The command is idempotent, so re-running it on a half-made app finishes the job.
111
112
  **server-side** as `{community}-{short}`; defaults to `--app`.
112
113
  - `--overwrite`: when creating, overwrite an existing app record intentionally.
113
114
  - `--kb <name>`: knowledge base name (default: `General`).
114
- - `-p, --path <dir>`: local app directory (default: auto-detected, else the current directory).
115
115
 
116
116
  **What it does, in order:**
117
117
 
118
118
  1. **Creates the app** (only when `-c` is given and the app does not exist): the server composes
119
119
  the unique `app_id` and writes `Products/{app_id}` and `Community/{community}/Apps/{app_id}`.
120
120
  Every app is guaranteed a default knowledge base at creation.
121
- 2. **Registers it in `.descix/workspace.json`** if it is not already mapped.
121
+ 2. **Writes it as `env.app` in `.descix/workspace.json`** — the current directory, the repo root,
122
+ becomes the workspace root. A workspace holds one app: a repo that already holds a different
123
+ app is refused, and so is a directory nested inside another DeSciX workspace.
122
124
  3. **Scaffolds the app folder**: creates `site/`, `microservice/` and `assets/`, and writes
123
125
  `assets/system_instructions.md` and `assets/app_description.md` when they do not exist.
124
126
  4. **Creates the knowledge base record** for Git-mode sync.
125
127
 
126
128
  It fails loud rather than guessing: initializing an app that does not exist without `-c` names the
127
129
  `-c` invocation that would create it; a `-c` that disagrees with the app's real community is
128
- refused; and `-p` against an already-mapped app names `descix app set-localpath` instead.
130
+ refused.
129
131
 
130
132
  **Next step** — author a corpus manifest at `.descix/manifests/<kb_name>.json`, then
131
133
  `descix kb corpus sync -a <app_id>`.
@@ -147,7 +149,7 @@ descix site upload --env dev
147
149
  ### `descix site init`
148
150
 
149
151
  Copies the site scaffold — `index.html`, `app.js`, `styles.css`, `DeSciXAppSDK.js`, `README.md` —
150
- into the app's `site/` directory. The app must already be mapped in `.descix/workspace.json`.
152
+ into the app's `site/` directory. The workspace must already hold the app (`env.app`, written by `descix app init`).
151
153
 
152
154
  - `-f, --force`: overwrite an existing `site/` folder.
153
155
  - `-c, --community <id>` / `-a, --app <id>`: auto-detected from context when omitted.
@@ -57,13 +57,12 @@ Keeping the scaffold's shape is what lets the service keep inheriting platform b
57
57
 
58
58
  ## Configuration (`workspace.json`)
59
59
 
60
- One `env.products[]` entry, written by `descix app init` and `descix app set-port` (never by hand):
60
+ The repo's `env.app`, written by `descix app init` (run from the repo root) and `descix app set-port` (never by hand):
61
61
 
62
62
  ```json
63
63
  {
64
64
  "appId": "my-community-my-dynamic-app",
65
65
  "communityId": "my-community",
66
- "localPath": "my-dynamic-app",
67
66
  "kbId": "General",
68
67
  "microservice": { "port": 4001 }
69
68
  }
@@ -39,14 +39,13 @@ example; `kb/General/` also works if that's where content ends up, e.g. from `de
39
39
 
40
40
  ## Configuration (`workspace.json`)
41
41
 
42
- One `env.products[]` entry, written by `descix app init` (never by hand); no `site` and no
43
- `microservice` slot:
42
+ The repo's `env.app`, written by `descix app init` (run from the repo root; never by hand); no `site`
43
+ and no `microservice` slot:
44
44
 
45
45
  ```json
46
46
  {
47
47
  "appId": "my-community-my-docs",
48
48
  "communityId": "my-community",
49
- "localPath": "my-docs",
50
49
  "kbId": "General"
51
50
  }
52
51
  ```
@@ -82,14 +82,13 @@ out until something depends on the difference.
82
82
 
83
83
  ## Configuration (`workspace.json`)
84
84
 
85
- One `env.products[]` entry, written by `descix app init`, `descix app set-port` and (for the optional
86
- frontend) `descix app set-site` — never by hand:
85
+ The repo's `env.app`, written by `descix app init` (run from the repo root), `descix app set-port` and
86
+ (for the optional frontend) `descix app set-site` — never by hand:
87
87
 
88
88
  ```json
89
89
  {
90
90
  "appId": "my-community-my-service",
91
91
  "communityId": "my-community",
92
- "localPath": "my-service",
93
92
  "kbId": "General",
94
93
  "site": { "static": "site" },
95
94
  "microservice": { "port": 4001 }
@@ -44,20 +44,19 @@ my-site/
44
44
 
45
45
  ## Configuration (`workspace.json`)
46
46
 
47
- One `env.products[]` entry, written by `descix app init` and `descix app set-site` (never by hand):
47
+ The repo's `env.app`, written by `descix app init` (run from the repo root) and `descix app set-site` (never by hand):
48
48
 
49
49
  ```json
50
50
  {
51
51
  "appId": "my-community-my-site",
52
52
  "communityId": "my-community",
53
- "localPath": "my-site",
54
53
  "kbId": "General",
55
54
  "site": { "static": "site" }
56
55
  }
57
56
  ```
58
57
 
59
58
  For a framework dev server instead of files on disk, `descix app set-site -a <app_id> --port 3000`
60
- writes `"site": { "port": 3000 }`; the gateway proxies `/p/<app_id>` to it without rewriting paths,
59
+ writes `"site": { "port": 3000 }`; `--static` takes a directory relative to the repo root (`site`, `site/dist`, `.`, `../scratch`) and refuses an absolute path; the gateway proxies `/p/<app_id>` to it without rewriting paths,
61
60
  so the framework's base path must be `/p/<app_id>/`.
62
61
 
63
62
  ## CLI Workflow
@@ -12,22 +12,21 @@ DeSciX uses **workspace.json** as the sole configuration file.
12
12
 
13
13
  Location: `{workspace_root}/.descix/workspace.json`
14
14
 
15
- Purpose: Maps local folders to DeSciX apps and stores all configuration.
15
+ Purpose: names THE app this repository holds (v3 single-app: one repo, one app, and the repo root
16
+ is the workspace root) and stores its configuration.
16
17
 
17
18
  ```json
18
19
  {
19
- "version": "2.1",
20
+ "version": "3.0",
21
+ "type": "workspace",
20
22
  "env": {
21
- "environment": "DEV",
22
- "apiUrl": "https://dev.descix.net",
23
- "products": [
24
- {
25
- "appId": "daita-appsdk",
26
- "communityId": "daita",
27
- "localPath": "daita/appsdk",
28
- "kbId": "General"
29
- }
30
- ]
23
+ "environment": "PROD",
24
+ "apiUrl": "https://descix.net",
25
+ "app": {
26
+ "appId": "daita-appsdk",
27
+ "communityId": "daita",
28
+ "kbId": "General"
29
+ }
31
30
  },
32
31
  "driveConfig": {
33
32
  "base_folder_id": "..."
@@ -35,18 +34,19 @@ Purpose: Maps local folders to DeSciX apps and stores all configuration.
35
34
  }
36
35
  ```
37
36
 
38
- A `communities`-keyed block with no `env` block is the removed v1 shape — the loader refuses it:
39
- `v1 workspace format is not supported. Migrate to v2.1.`
37
+ The loader refuses the retired shapes by name: a `communities`-keyed block with no `env` block
38
+ (`v1 workspace format is not supported. Migrate to v3.`) and an `env.platform` / `env.products`
39
+ block (`v2.1 multi-app workspace format is not supported. Migrate to v3 (single-app).`).
40
40
 
41
41
  **Used for:**
42
- - CLI auto-detection of community/app from current directory
42
+ - CLI auto-detection of the app from the current directory (anywhere under the repo root)
43
43
  - `tell_me_how --scope project` to discover project-specific tools
44
- - MCP server to know which apps are in scope
44
+ - MCP server to know which app is in scope
45
45
  - CLI to find the workspace root
46
46
 
47
47
  ### Key Principle
48
48
 
49
- **workspace.json** is the single configuration file that maps local folders to DeSciX apps and contains all sync configuration. It is created once at the workspace root during onboarding.
49
+ **workspace.json** is the single configuration file for the app this repo holds. `descix app init` creates it at the repo root during onboarding; inside another DeSciX workspace it refuses — app repos are sibling checkouts, never nested.
50
50
 
51
51
  ---
52
52
 
@@ -66,8 +66,8 @@ START
66
66
  ├── Is this a fresh workspace (no .descix/workspace.json)?
67
67
  │ └── YES → Run Full Setup Flow
68
68
  │
69
- ├── Does workspace.json exist but has unconfigured apps?
70
- │ └── YES → Run App Configuration Flow
69
+ ├── Does the user want to work on an app this repo does not hold?
70
+ │ └── YES → Run App Configuration Flow (that app gets its own repo)
71
71
  │
72
72
  └── Is everything configured?
73
73
  └── YES → Ready for development
@@ -109,69 +109,51 @@ Service Slots:
109
109
  - {slot_count} available for microservice deployment
110
110
  ```
111
111
 
112
- ### Step 3: Scan Workspace Folders
112
+ ### Step 3: Choose the App This Repo Holds
113
113
 
114
- Identify potential project folders:
115
- - Look for directories with `package.json`, `Cargo.toml`, `requirements.txt`
116
- - Ignore: `node_modules`, `.git`, `dist`, `build`, `.descix`
117
- - Note folders that are already registered in `workspace.json`
118
-
119
- ### Step 4: Ask User About Folder Mappings
120
-
121
- Present options:
114
+ One repo holds one app. Ask which of the user's apps this repository is for — or whether it is a
115
+ new app.
122
116
 
123
117
  ```
124
- I see these folders in your workspace:
125
- - frontend/ (React app with build system)
126
- - backend/ (Node.js with Express)
127
- - docs/ (Markdown documentation)
128
-
129
- Would you like to map any to your apps?
130
-
131
- Suggested mappings based on folder contents:
132
- - frontend/ → {community}/pwa (Static Site)
133
- - backend/ → {community}/api (Microservice)
134
- - docs/ → {community}/docs (Knowledge Only)
135
-
136
- Which mappings should I create?
118
+ This repository will hold ONE DeSciX app. Which one?
119
+ - {community_id}/{app_id} ({app_name})
120
+ - ...
121
+ - a new app in {community_id}
137
122
  ```
138
123
 
139
- ### Step 5: Create Configuration Files
124
+ ### Step 4: Create the Configuration
140
125
 
141
- For each mapping, create appropriate config:
126
+ `workspace.json` is written by CLI verbs, never by hand. From the **repo root**:
142
127
 
143
- 1. **workspace.json** (root level) — written by CLI verbs, never by hand:
144
- ```bash
145
- descix config init --env dev # creates workspace.json, pins env.apiUrl
146
- descix app init -a {app_id} -c {community_id} -p {folder} # adds env.products[] entry
147
- ```
148
- Each mapping becomes one `env.products[]` entry (`appId`, `communityId`, `localPath`, `kbId`).
128
+ ```bash
129
+ descix config init --env prod # creates workspace.json, pins env.apiUrl
130
+ descix app init -a {app_id} # an existing app: writes env.app
131
+ descix app init -a {name} -c {community_id} # a new app: creates it, then writes env.app
132
+ ```
149
133
 
150
134
  ## App Configuration Flow
151
135
 
152
136
  For apps that exist in entitlements but aren't configured locally:
153
137
 
154
- ### Step 1: Identify Unconfigured Apps
138
+ ### Step 1: Identify the Other Apps
155
139
 
156
- Compare:
157
- - Apps from `fetch_my_purchases`
158
- - Mappings in `workspace.json`
140
+ Compare the apps from `fetch_my_purchases` with `env.app` in this repo's `workspace.json`. Every
141
+ other app lives in its own repository.
159
142
 
160
- ### Step 2: Ask About Each Unconfigured App
143
+ ### Step 2: Ask About Each One
161
144
 
162
145
  ```
163
- You have these apps that aren't linked to local folders:
146
+ You have these apps that this repository does not hold:
164
147
  - {community}/{app} - {description}
165
148
 
166
- Would you like to:
167
- 1. Link to an existing folder
168
- 2. Create a new folder for this app
169
- 3. Skip for now
149
+ Each app is its own repository. Would you like to:
150
+ 1. Clone or create that app's repo as a sibling of this one, then run `descix app init` from its root
151
+ 2. Skip for now
170
152
  ```
171
153
 
172
154
  ### Step 3: Determine Packaging Type
173
155
 
174
- For each folder being configured:
156
+ For the app this repo holds:
175
157
 
176
158
  1. Read [guides/README.md](../guides/README.md) for the decision tree (Knowledge-Only / Static
177
159
  Site / Microservice / Dynamic Site)
@@ -186,7 +168,7 @@ For each folder being configured:
186
168
  After determining packaging type, ensure the folder follows the [Standard Folder Structure](./standard-folder-structure.md):
187
169
 
188
170
  ```
189
- {app_folder}/
171
+ {repo_root}/
190
172
  ├── assets/ # App identity (required)
191
173
  ├── .descix/manifests/<KB>.json # Corpus manifest — required for RAG, see below
192
174
  ├── site/ # Static site (required)
@@ -252,7 +234,7 @@ Your app structure is now ready. Run `descix app sync-assets` to sync.
252
234
  ## Key Principles
253
235
 
254
236
  ### Never Assume
255
- - Always ask before creating mappings
237
+ - Always ask which app a repo holds before running `descix app init`
256
238
  - Present options, let user choose
257
239
  - Explain trade-offs of each packaging type
258
240
 
@@ -273,8 +255,8 @@ User hasn't purchased anything yet. Direct them to the PWA store.
273
255
  ### "App not in entitlements"
274
256
  User is trying to configure an app they don't own. Suggest purchase.
275
257
 
276
- ### "Folder already configured"
277
- Check if configuration matches intended app. Offer to update or skip.
258
+ ### "This workspace already holds app '<id>'"
259
+ A repo holds one app. Work on the other app in its own repo (a sibling checkout).
278
260
 
279
261
  ### Powch sign-in under `descix serve` fails ("User cancelled", or "WebAuthn is not supported on sites with TLS certificate errors")
280
262
  The gateway's dev certificate is not trusted. Run `descix dev-certs check`. If it is not trusted,
@@ -327,7 +309,7 @@ You have access to:
327
309
  - {app_2} - {app_2_status}
328
310
 
329
311
  Would you like me to help you:
330
- 1. Link a folder to one of your apps
312
+ 1. Connect this repository to one of your apps
331
313
  2. Explore what you can do with a specific app
332
314
  3. Something else
333
315
  ```
@@ -343,9 +325,9 @@ Based on your purchases, here's what you can work with:
343
325
  | {name} | {role} | {count} |
344
326
 
345
327
  **Your Apps:**
346
- | App | Status | Local Folder |
347
- |-----|--------|--------------|
348
- | {app_id} | Configured / Not linked | {folder or "—"} |
328
+ | App | Status | Local Repo |
329
+ |-----|--------|------------|
330
+ | {app_id} | Held by this repo / Not here | {repo or "—"} |
349
331
 
350
332
  Which app would you like to work on?
351
333
  ```
@@ -358,7 +340,7 @@ All done! Your app is configured.
358
340
  **Summary:**
359
341
  - App: {community}/{app}
360
342
  - Type: {packaging_type}
361
- - Folder: {folder_path}
343
+ - Repo: {repo_root}
362
344
 
363
345
  **What you can do now:**
364
346
  - Use `tell_me_how` to discover tools
@@ -101,25 +101,28 @@ descix kb corpus sync # Walk the manifest's sources, chunk what changed, upsert
101
101
 
102
102
  ## Configuration Files
103
103
 
104
- ### `.descix/workspace.json` (Root) — v2.1, the only supported format
104
+ ### `.descix/workspace.json` (Root) — v3 single-app, the only supported format
105
105
 
106
106
  ```json
107
107
  {
108
- "version": "2.1",
108
+ "version": "3.0",
109
+ "type": "workspace",
109
110
  "env": {
110
- "environment": "DEV",
111
- "apiUrl": "https://dev.descix.net",
112
- "products": [
113
- { "appId": "my-dao-governance", "communityId": "my-dao", "localPath": "my-dao/governance", "kbId": "General" },
114
- { "appId": "my-dao-treasury", "communityId": "my-dao", "localPath": "my-dao/treasury", "kbId": "General" }
115
- ]
111
+ "environment": "PROD",
112
+ "apiUrl": "https://descix.net",
113
+ "app": { "appId": "my-dao-governance", "communityId": "my-dao", "kbId": "General" }
116
114
  }
117
115
  }
118
116
  ```
119
117
 
120
- Written by CLI verbs only — `descix config init`, `descix app init`, `descix app set-site`,
121
- `descix app set-port`. A `communities`-keyed block with no `env` block is the removed v1 shape and
122
- is refused on load: `v1 workspace format is not supported. Migrate to v2.1.`
118
+ One repo, one app: `env.app` is THE app and the repo root is the workspace root. A second app
119
+ (`my-dao-treasury`) is its own repo, a sibling checkout with its own `workspace.json`.
120
+
121
+ Written by CLI verbs only — `descix config init`, `descix app init` (from the repo root; refused
122
+ inside another workspace), `descix app set-site`, `descix app set-port`. The loader refuses the
123
+ retired shapes by name: a `communities`-keyed block with no `env` block (`v1 workspace format is not
124
+ supported. Migrate to v3.`) and an `env.platform` / `env.products` block (`v2.1 multi-app workspace
125
+ format is not supported. Migrate to v3 (single-app).`).
123
126
 
124
127
  **Sync mode:** The CLI only performs **git-mode** operations (local files → corpus manifest →
125
128
  Pinecone, via `descix kb corpus sync`). Drive-mode (Drive → GCS → Pinecone, fully server-side) is
@@ -12,7 +12,7 @@ This document describes how apps and communities are created in the DeSciX platf
12
12
 
13
13
  **"One path to an app"**
14
14
 
15
- - **Apps:** `descix app init -a <name> -c <community> -p <dir>` creates the app on the platform (`create_app_for_community`, which composes the id `<community>-<short>` and guarantees the default KB) and registers it in the local workspace in one idempotent step. The PWA creates apps too; both reach the same server command. Entitlement checks run server-side either way.
15
+ - **Apps:** `descix app init -a <name> -c <community>`, run from the app repo's root, creates the app on the platform (`create_app_for_community`, which composes the id `<community>-<short>` and guarantees the default KB) and writes it as the repo's `env.app` in one idempotent step. The PWA creates apps too; both reach the same server command. Entitlement checks run server-side either way.
16
16
  - **Communities:** created by platform admins only (`descix community create` is `[ADMIN]` and writes live Polygon). A developer builds inside an existing community.
17
17
  - **Development:** the CLI is the tool for the local workspace, content, and syncing to the cloud.
18
18
 
@@ -211,18 +211,19 @@ sequenceDiagram
211
211
  ## 4. Local Workspace
212
212
 
213
213
  There is no PWA "workspace builder" hand-off and no hydration step. The local workspace is built by
214
- CLI verbs, each writing one part of `.descix/workspace.json` (v2.1 — see `workspace-config.md`):
214
+ CLI verbs, each writing one part of `.descix/workspace.json` (v3 single-app — see `workspace-config.md`). Run them
215
+ from the repo root — it becomes the workspace root:
215
216
 
216
217
  ```bash
217
- descix config init --env dev # creates .descix/workspace.json, pins env.apiUrl
218
+ descix config init --env prod # creates .descix/workspace.json, pins env.apiUrl
218
219
  descix login # .descix/wallet.json (add it to .gitignore yourself)
219
- descix app init -a <name> -c <community> -p . # env.products[] entry + site/ microservice/ assets/ + default KB
220
+ descix app init -a <name> -c <community> # env.app + site/ microservice/ assets/ + default KB
220
221
  descix app set-site -a <app_id> --static site # what the gateway serves at /p/<app_id>
221
222
  descix app set-port -a <app_id> -p 4001 # required before descix microservice init
222
223
  ```
223
224
 
224
225
  `descix app init` creates `site/`, `microservice/` and `assets/` (with starter
225
- `system_instructions.md` and `app_description.md`) under the app directory. Knowledge-base content
226
+ `system_instructions.md` and `app_description.md`) under the repo root. Knowledge-base content
226
227
  is whatever your corpus manifest names (`.descix/manifests/<KB>.json`); Drive content arrives via
227
228
  `descix drive pull -c <community> -a <app_id>` into `kb/<KB>/` and goes back via `descix drive push`.
228
229
  The CLI auto-detects the app from the directory you are standing in; `-c`/`-a` flags win over
@@ -304,13 +305,13 @@ async function copyFolderRecursive(sourceFolderId, destParentId, newName) {
304
305
  ### App Creation
305
306
 
306
307
  ```bash
307
- descix config init --env dev # pin the environment first (no default)
308
+ descix config init --env prod # pin the environment first
308
309
  descix login # device-code sign-in
309
- descix app init -a <name> -c <community> -p . # create on the platform + register locally + default KB
310
+ descix app init -a <name> -c <community> # create on the platform + write env.app + default KB
310
311
  ```
311
312
 
312
313
  An app created in the PWA is initialized locally with the same verb, minus `-c`:
313
- `descix app init -a <app_id> -p .`.
314
+ `descix app init -a <app_id>`, from the repo root.
314
315
 
315
316
  ### Post-Creation Commands
316
317
 
@@ -111,31 +111,28 @@ folder of JSON chunk files to manage.
111
111
 
112
112
  ```json
113
113
  {
114
- "version": "2.1",
114
+ "version": "3.0",
115
115
  "type": "workspace",
116
- "workspaceRoot": "/path/to/workspace",
116
+ "workspaceRoot": "/path/to/daita-agent-repo",
117
117
  "env": {
118
- "environment": "DEV",
119
- "apiUrl": "https://dev.descix.net",
118
+ "environment": "PROD",
119
+ "apiUrl": "https://descix.net",
120
120
  "gateway": { "port": 5599 },
121
- "products": [
122
- {
123
- "appId": "daita-agent",
124
- "communityId": "daita",
125
- "localPath": "daita/agent",
126
- "kbId": "General",
127
- "site": { "port": 3000 },
128
- "microservice": { "port": 4001 }
129
- }
130
- ]
121
+ "app": {
122
+ "appId": "daita-agent",
123
+ "communityId": "daita",
124
+ "kbId": "General",
125
+ "site": { "port": 3000 },
126
+ "microservice": { "port": 4001 }
127
+ }
131
128
  },
132
129
  "driveConfig": { "base_folder_id": "1ABC..." }
133
130
  }
134
131
  ```
135
132
 
136
- Every key is written by a CLI verb (`descix config init --env …`, `descix app init`, `descix app set-site`, `descix app set-port`, …) — see `workspace-config.md` for the key → verb table. A `communities` block without `env` (the v1 shape) is refused on load.
133
+ Every key is written by a CLI verb (`descix config init --env …`, `descix app init`, `descix app set-site`, `descix app set-port`, …) — see `workspace-config.md` for the key → verb table. One repo holds one app (`env.app`), and the repo root is the workspace root. A `communities` block without `env` (the v1 shape) and an `env.platform` / `env.products` block (the v2.1 multi-app shape) are refused on load.
137
134
 
138
- **Note:** `.descix.app/context.json` files are no longer used. All app configuration is stored in `workspace.json`. The CLI auto-detects app context from the current working directory by matching against registered app paths.
135
+ **Note:** `.descix.app/context.json` files are no longer used. All app configuration is stored in `workspace.json`. The CLI auto-detects the app (`env.app`) when the current working directory is the repo root or below it.
139
136
 
140
137
  ---
141
138
 
@@ -169,7 +166,7 @@ The DeSciX CLI publishes content with one verb per plane. Each command resolves
169
166
  |---------|-------------|
170
167
  | `descix site init` | Copy site template to current app's `site/` folder |
171
168
  | `descix site upload` | Deploy site to GCS |
172
- | `descix app set-site -a <app_id> --port <port>` | Register the local dev-server port for the app's site (`env.products[].site.port`) |
169
+ | `descix app set-site -a <app_id> --port <port>` | Register the local dev-server port for the app's site (`env.app.site.port`) |
173
170
  | `descix microservice init` | Copy microservice template to current app's `microservice/` folder |
174
171
  | `descix microservice register -r SERVICE_README.md` | Register microservice AND vectorize the README for `tell_me_how` discovery, in one step |
175
172
 
@@ -44,7 +44,7 @@ Instead of exposing implementation details (like GCS bucket URLs or specific por
44
44
 
45
45
  **Port:** `--port` → `env.gateway.port` → built-in `5173`, with `strictPort` on. The resolved port and **its source** are printed at startup. Do not assume `:5173`; give a checkout its own with `descix config set-gateway-port <n>`.
46
46
 
47
- **It serves ONE app, standalone — the shell opens ON your app instead of the store.** (Standalone is the INITIAL VIEW, not a reduced mode: the platform views stay reachable by navigation.) The app is detected from the directory you are standing in (the product whose `localPath` contains your cwd; longest match wins), or named with `--app <id>`. Nothing is persisted to `workspace.json`. When it cannot name an app it fails loud and lists the workspace's apps rather than falling back to the store.
47
+ **It serves ONE app, standalone — the shell opens ON your app instead of the store.** (Standalone is the INITIAL VIEW, not a reduced mode: the platform views stay reachable by navigation.) The app is detected from the directory you are standing in (the app whose repo root contains your cwd — your own repo's `env.app`, or on a gateway workspace the `env.gateway` repo you are inside; longest match wins), or named with `--app <id>`. Nothing is persisted to `workspace.json`. When it cannot name an app it fails loud and lists the workspace's apps rather than falling back to the store.
48
48
 
49
49
  The binding is **served, not compiled**: the gateway answers `GET /__descix/app-binding.json` on the shell's own origin with `{mode:'standalone', appId, appUrl, source}`, and the shell reads it before it mounts. One pre-built cloud shell bundle therefore boots as the store on `descix.net` and as your app locally, with no rebuild. No binding (or a timeout, or a malformed body) means the store — the safe degradation. There is no `__STANDALONE_APP_ID__` build define; an app that builds itself standalone declares it at its own mount, `<AppShell appId="..." standalone>`.
50
50
 
@@ -71,10 +71,11 @@ the per-app host; keep `/p/` for the local gateway, where it is the correct and
71
71
  Typical app-dev session, in full:
72
72
 
73
73
  ```bash
74
- descix config set-env dev
75
- descix app init -a <app-id> -p ./my-app
76
- descix app set-site -a <app-id> --static .
77
- cd my-app && descix serve
74
+ cd my-app-repo # the repo root is the workspace root
75
+ descix config init --env prod # pins env.apiUrl
76
+ descix app init -a <app-id> # writes env.app
77
+ descix app set-site -a <app-id> --static site # relative to the repo root
78
+ descix serve
78
79
  ```
79
80
 
80
81
  ### 3.1. Configuration: `.descix/workspace.json`
@@ -90,39 +91,43 @@ The `workspace.json` file is the **single source of truth** for local routing an
90
91
 
91
92
  | Key | Verb |
92
93
  |---|---|
93
- | `env.apiUrl` | `descix config set-env <dev\|demo\|prod> [--url <url>]` (env is positional) |
94
+ | `env.apiUrl` | `descix config init --env dev\|demo\|prod`, or `descix config set-env <custom-name> --url <url>` (`--url` is refused on a known name) |
94
95
  | `env.gateway.port` | `descix config set-gateway-port <n\|none>` |
96
+ | `env.gateway.shell` | `descix config gateway set-shell <repo\|none>` (gateway workspaces only) |
97
+ | `env.gateway.appRepos[]` | `descix config gateway add-repo <repo>` / `remove-repo <repo>` (gateway workspaces only) |
95
98
  | `env.devCerts` | `descix config set-dev-certs --dir\|--cert\|--key\|--clear` |
96
99
  | `env.powchUrl` | `descix config set-powch-url <url\|none>` |
97
100
  | `env.siteUrl` | `descix config set-site-url <url\|none>` |
98
- | `env.products[]` | `descix app init` / `app set-site` / `app set-port` / `app set-localpath` / `app unmap` |
101
+ | `env.app` | `descix app init` / `app set-site` / `app set-port` |
99
102
 
100
- #### Format (v2.1 — the only format)
103
+ #### Format (v3 — single-app)
101
104
 
102
105
  ```json
103
106
  {
104
- "version": "2.1",
107
+ "version": "3.0",
108
+ "type": "workspace",
105
109
  "env": {
106
- "environment": "DEV",
107
- "apiUrl": "https://dev.descix.net",
110
+ "environment": "PROD",
111
+ "apiUrl": "https://descix.net",
108
112
  "gateway": { "port": 5599 },
109
113
  "devCerts": { "dir": "/Users/you/.descix/dev-certs-san" },
110
- "powchUrl": "https://powch.dev.descix.net/",
111
- "platform": {
112
- "appId": "daita",
113
- "localPath": "DeSciX_Cloud",
114
- "site": { "port": 5174 },
115
- "microservice": { "port": 4000 }
116
- },
117
- "products": [
118
- { "appId": "my-app", "localPath": "my-app", "site": { "static": "." } },
119
- { "appId": "other-app", "localPath": "other", "site": { "port": 5599 }, "microservice": { "port": 4001 } }
120
- ]
114
+ "app": {
115
+ "appId": "my-app",
116
+ "communityId": "egpt",
117
+ "kbId": "General",
118
+ "site": { "static": "site" },
119
+ "microservice": { "port": 4001 }
120
+ }
121
121
  }
122
122
  }
123
123
  ```
124
124
 
125
- `env.platform` is optional — an app developer has no platform checkout and needs none. A top-level `apiUrl` key (the v1 shape) fails loud naming its replacement.
125
+ One repo, one app: `env.app` is THE app, and the repo root is the workspace root (`descix app init`
126
+ from the repo root; inside another workspace it refuses). A gateway workspace that serves several
127
+ local app repos lists them as `env.gateway.shell` and `env.gateway.appRepos[]` (paths relative to its
128
+ root), and each listed repo carries its own v3 workspace — see `reference/workspace-config.md`. A
129
+ top-level `apiUrl` key (the v1 shape) and an `env.platform` / `env.products` block (the v2.1
130
+ multi-app shape) fail loud on load, naming the migration.
126
131
 
127
132
  #### KB sync is manifest-driven
128
133
 
@@ -164,15 +169,14 @@ the survey outranks the paper for exactly the reader who does not yet know the p
164
169
 
165
170
  | Target | 1. flag / env | 2. workspace | 3. global | 4. default |
166
171
  |---|---|---|---|---|
167
- | **API** | `--api-url` / `--env` / `DESCIX_API_URL` | `env.apiUrl`, then the legacy top-level `apiUrl` | `~/.descix/config.json` `api_url` | **the declared default: PROD** |
168
- | **Shell** (`/`) | `--site-url` | `env.siteUrl` | **the API origin, when the API is remote** | `env.platform.site.port`, else fail loud |
172
+ | **API** | `--api-url` / `--env` / `DESCIX_API_URL` | `env.apiUrl` | `~/.descix/config.json` `api_url` | **the declared default: PROD** |
173
+ | **Shell** (`/`) | `--site-url` | `env.siteUrl` | **the API origin, when the API is remote** | the `env.gateway.shell` repo's own `site.port`, else fail loud |
169
174
 
170
- **There is no port-derived step for the API.** An environment NAME never becomes an origin, and
171
- `env.platform.microservice.port` is not consulted: a local backend is a URL you name
172
- (`descix config set-env dev --url https://localhost:4000`, or `env.apiUrl` direct). **This is
175
+ **There is no port-derived step for the API.** An environment NAME never becomes an origin: a
176
+ local backend is a URL you name — per run with `descix --api-url https://localhost:4000 <command>`,
177
+ or persistently under a custom name with `descix config set-env local --url https://localhost:4000`. **This is
173
178
  platform-dev mode** — running your own local backend (Scenario 2 below), not part of standard app
174
- development, which targets a hosted environment (`descix config set-env dev` with no `--url`, or
175
- `demo`/`prod`). The single owner of this order is `lib/origin.js::PRECEDENCE`; this table is a
179
+ development, which targets a hosted environment (`descix config init --env dev|demo|prod`). The single owner of this order is `lib/origin.js::PRECEDENCE`; this table is a
176
180
  description of it, not a second copy of the rule.
177
181
 
178
182
  **Every resolution carries its SOURCE, and every network-bound command prints it on stderr** —
@@ -187,7 +191,7 @@ An unconfigured workspace resolving to PROD is the shipped product's declared ta
187
191
  fallback; what makes it legitimate is that it is announced. A configured-but-unusable origin is
188
192
  a different case and FAILS LOUD naming the remedy, rather than quietly becoming the default.
189
193
 
190
- The derived Shell rule is the important one: point the API at a cloud environment and the shell comes from that same origin, so one origin carries shell + app + `/apifront` with nothing else configured. A stale `env.platform.site` block does not hijack the root once the API is remote. Platform developers opt IN to a local shell by naming it (`--site-url https://localhost:5174` or `env.siteUrl`).
194
+ The derived Shell rule is the important one: point the API at a cloud environment and the shell comes from that same origin, so one origin carries shell + app + `/apifront` with nothing else configured. A local shell repo listed in `env.gateway.shell` does not hijack the root once the API is remote. Platform developers opt IN to a local shell by naming it (`--site-url https://localhost:5174` or `env.siteUrl`).
191
195
 
192
196
  ### 3.3. The dev certificate and passkey sign-in
193
197
 
@@ -233,7 +237,7 @@ human it is unverified.
233
237
 
234
238
  ### Scenario 1: App Dev (the common case)
235
239
  * **User**: App developer. No platform checkout.
236
- * **Setup**: `descix config set-env dev`, `descix app init`, `descix app set-site`, `descix dev-certs check` (if not trusted, the human runs `descix dev-certs trust` once — §3.3), then `cd my-app && descix serve`.
240
+ * **Setup**: from the app repo's root, `descix config init --env prod`, `descix app init`, `descix app set-site`, `descix dev-certs check` (if not trusted, the human runs `descix dev-certs trust` once — §3.3), then `descix serve`.
237
241
  * **Result**: one HTTPS origin. `/` → the cloud App Shell, `/apifront` → the cloud API, `/p/my-app` → your app, and the shell boots **standalone into your app** — its INITIAL VIEW is your app rather than the store, with the platform views still reachable from there.
238
242
 
239
243
  ### Scenario 2: Platform Dev ("Dogfooding")