@descix/cli 1.0.1 → 1.0.3
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/LICENSE.md +671 -0
- package/README.md +43 -4
- package/agent-assets/guides/README.md +2 -2
- package/agent-assets/guides/dynamic-site-pattern.md +29 -14
- package/agent-assets/guides/knowledge-only-pattern.md +5 -5
- package/agent-assets/guides/microservice-pattern.md +48 -4
- package/agent-assets/guides/static-site-pattern.md +8 -0
- package/agent-assets/instructions/app-asset-validation.md +5 -5
- package/agent-assets/instructions/onboarding-flow.md +4 -4
- package/agent-assets/instructions/standard-folder-structure.md +20 -11
- package/agent-assets/reference/app-creation.md +42 -20
- package/agent-assets/reference/architecture.md +24 -22
- package/agent-assets/reference/local-dev.md +230 -67
- package/agent-assets/reference/mcp-integration.md +9 -9
- package/agent-assets/reference/platform-api-consumer.md +244 -0
- package/agent-assets/reference/workspace-config.md +7 -7
- package/agent-assets/rules/descix_mcp.template.mdc +8 -8
- package/bin/descix.js +2559 -1435
- package/bin/kb-deny-lint.mjs +91 -0
- package/bin/mcp-server.js +175 -91
- package/lib/agent-files.js +37 -25
- package/lib/api-client.js +223 -56
- package/lib/auth-guard.js +13 -3
- package/lib/chat-session.js +187 -0
- package/lib/cli-version.js +59 -0
- package/lib/commands/airdrop.js +251 -0
- package/lib/commands/auth.js +254 -72
- package/lib/commands/briefer/errors.js +88 -0
- package/lib/commands/briefer/index.js +319 -0
- package/lib/commands/briefer/sources/canonical-sources.js +129 -0
- package/lib/commands/briefer/sources/entitlements.js +209 -0
- package/lib/commands/briefer/sources/environments.js +205 -0
- package/lib/commands/briefer/sources/identifiers.js +214 -0
- package/lib/commands/briefer/sources/microservice-deploy.js +267 -0
- package/lib/commands/briefer/sources/routing.js +275 -0
- package/lib/commands/briefer/sources/what-is-not.js +223 -0
- package/lib/commands/briefer/stitcher.js +134 -0
- package/lib/commands/briefer/util/source-reader.js +502 -0
- package/lib/commands/config.js +210 -90
- package/lib/commands/corpus.js +978 -0
- package/lib/commands/credits.js +122 -0
- package/lib/commands/health.js +627 -0
- package/lib/commands/kb-list-render.js +32 -0
- package/lib/commands/kb.js +190 -413
- package/lib/commands/mcp.js +5 -5
- package/lib/commands/microservice-restart.js +359 -0
- package/lib/commands/model-config.js +313 -0
- package/lib/commands/retired-kb-sync.js +134 -0
- package/lib/commands/serve.js +26 -1
- package/lib/commands/status.js +23 -51
- package/lib/commands/update.js +36 -107
- package/lib/core/Chunker.js +491 -17
- package/lib/core/CorpusDenyLint.js +326 -0
- package/lib/core/CorpusWalker.js +357 -0
- package/lib/core/Hydrator.js +75 -29
- package/lib/core/ManifestLoader.js +533 -0
- package/lib/core/SiteWalker.js +218 -0
- package/lib/core/Syncer.js +163 -11
- package/lib/diagnostic-log.js +41 -0
- package/lib/environment-report.js +100 -0
- package/lib/global-config.js +4 -1
- package/lib/oauth-client.js +164 -0
- package/lib/origin.js +143 -0
- package/lib/service-api-client.js +95 -0
- package/lib/wallet-environment.js +49 -0
- package/lib/wallet-file.js +16 -2
- package/lib/wizard/setup.js +10 -9
- package/lib/workspace-config.js +380 -235
- package/lib/workspace-identity.js +92 -0
- package/lib/workspace-utils.js +41 -61
- package/package.json +19 -6
- package/templates/agent-claude.md +157 -9
- package/templates/agent-cline.md +68 -8
- package/templates/agent-copilot.md +68 -8
- package/templates/agent-cursor.md +68 -8
- package/templates/alignment-schema.json +20 -0
- package/templates/cloud-brain-hook.sh +20 -0
- package/templates/drive/README.md +1 -1
- package/templates/drive_templates/README.md +2 -2
- package/templates/scaffolds/README.md +6 -10
- package/templates/scaffolds/microservice/SERVICE_README_sdk.md +30 -0
- package/templates/scaffolds/microservice/app.js +51 -10
- package/templates/scaffolds/microservice/app.yaml +2 -2
- package/templates/scaffolds/microservice/defaults-config-dev.json +4 -0
- package/templates/scaffolds/microservice/dev-overrides.example.json +5 -0
- package/templates/scaffolds/microservice/manifest.json +0 -1
- package/templates/scaffolds/microservice/package.json +3 -3
- package/templates/scaffolds/microservice/scripts/register.js +56 -41
- package/templates/scaffolds/microservice/services/mcpClient.js +55 -65
- package/templates/scaffolds/microservice/services/utils.js +20 -238
- package/templates/scaffolds/microservice/templates/SERVICE_README_TEMPLATE.md +24 -0
- package/lib/commands/app-wizard.js +0 -627
- package/lib/commands/folder.js +0 -291
- package/lib/core/PathContext.js +0 -335
- package/templates/scaffolds/microservice/dev-overrides.json.example +0 -5
- package/templates/scaffolds/site/DeSciXAppSDK.js +0 -62
- package/templates/scaffolds/site/README.md +0 -51
- package/templates/scaffolds/site/app.js +0 -22
- package/templates/scaffolds/site/index.html +0 -42
- package/templates/scaffolds/site/styles.css +0 -123
|
@@ -16,9 +16,9 @@ This approach unifies three distinct scenarios:
|
|
|
16
16
|
| Aspect | Git Mode (CLI) | Drive Mode (PWA) |
|
|
17
17
|
|--------|---------------|-----------------|
|
|
18
18
|
| **User Type** | Developers | Non-technical users |
|
|
19
|
-
| **Content Source** | Local git repo (MD exports pulled from Drive via `
|
|
19
|
+
| **Content Source** | Local git repo (MD exports pulled from Drive via `descix drive pull`) | Google Drive |
|
|
20
20
|
| **Version Control** | Git | Drive/GCS/Firestore |
|
|
21
|
-
| **KB Processing** | `descix
|
|
21
|
+
| **KB Processing** | `descix kb corpus sync` — manifest-driven git-aware sync → Pinecone | Server-side pipeline (Drive → GCS → Pinecone) — PWA users only |
|
|
22
22
|
| **Configuration** | `workspace.json` | N/A (PWA handles) |
|
|
23
23
|
| **Tools** | CLI, VSCode, Git | PWA only |
|
|
24
24
|
|
|
@@ -28,104 +28,185 @@ Instead of exposing implementation details (like GCS bucket URLs or specific por
|
|
|
28
28
|
|
|
29
29
|
### 2.1. Route Patterns
|
|
30
30
|
|
|
31
|
-
|
|
|
32
|
-
| :--- | :--- | :--- |
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
31
|
+
| Canonical Path | Production Target (LB) | Local Target (Gateway) |
|
|
32
|
+
| :--- | :--- | :--- |
|
|
33
|
+
| `/apifront`, `/api`, `/mcp`, `/oauth`, `/.well-known/oauth-*` | Core API | the resolved **API origin** (see §3.2) |
|
|
34
|
+
| `/powch` | Powch PWA | the origin the workspace names. **No route at all when unset** — there is no default wallet origin |
|
|
35
|
+
| `/s/{appId}` | service | `http://localhost:{microservice.port}` — prefix **stripped** |
|
|
36
|
+
| `/p/{appId}` | app site | `{proto}://localhost:{site.port}` (**no** path rewrite), or served from disk when the product has `site.static` |
|
|
37
|
+
| `/Community`, `/.proxy/gcs_media` | GCS public bucket | proxied to `storage.googleapis.com` |
|
|
38
|
+
| `/__descix/app-binding.json` | (not served in production) | answered by the gateway itself |
|
|
39
|
+
| `/` | PWA bucket | the resolved **Shell origin** (see §3.2) — always matched **last** |
|
|
38
40
|
|
|
39
41
|
## 3. The "Local Mesh" Proxy
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
`descix serve` spins up a **Local Gateway**: one HTTPS origin that proxies the whole mesh. It is a Vite server used only as proxy + static + TLS, and it **starts nothing else** — no backend, no app dev server. An unreachable target surfaces as a 502/`ECONNREFUSED`; nothing is masked or retried against a fallback.
|
|
44
|
+
|
|
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
|
+
|
|
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.
|
|
48
|
+
|
|
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
|
+
|
|
51
|
+
### `/p/<appId>` is a LOCAL route only
|
|
52
|
+
|
|
53
|
+
The gateway serves your app at `/p/<appId>`. **That path does not exist in the cloud.** Deployed
|
|
54
|
+
apps are served on their own host, `{appId}.{env}.descix.net`. Measured against dev:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
# LOCAL — the /p/ form, served by your own gateway
|
|
58
|
+
https://localhost:5173/p/egpt-godsworld/ works (gateway port varies)
|
|
59
|
+
|
|
60
|
+
# CLOUD — measured against dev
|
|
61
|
+
https://egpt-godsworld.dev.descix.net/ -> 200 (the deployed app, per-app host)
|
|
62
|
+
https://dev.descix.net/p/egpt-godsworld/ -> 404 (the /p/ form does not exist here)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
So a URL that works all through local development 404s the moment you point it at a deployed
|
|
66
|
+
environment. If you are writing a link, a redirect, or a test that must survive deployment, use
|
|
67
|
+
the per-app host; keep `/p/` for the local gateway, where it is the correct and necessary form.
|
|
68
|
+
|
|
69
|
+
**Every app the shell iframes is on the GATEWAY origin** — `/p/{appId}`, never the app's own dev-server port. The shell dispatches chat action blocks by reaching straight into `iframe.contentWindow.DeSciX_Actions` (direct interframe scripting, no postMessage bridge), so a cross-origin iframe kills SplitView with a `SecurityError`. **Powch is the deliberate exception** and stays cross-origin: it holds passkeys and the HD wallet, and same-origin would expose it to that same reach.
|
|
70
|
+
|
|
71
|
+
Typical app-dev session, in full:
|
|
72
|
+
|
|
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
|
|
78
|
+
```
|
|
42
79
|
|
|
43
80
|
### 3.1. Configuration: `.descix/workspace.json`
|
|
44
81
|
The `workspace.json` file is the **single source of truth** for local routing and app configuration. This is the only configuration methodology - `.descix.app/context.json` files are no longer used.
|
|
45
82
|
|
|
46
83
|
**Key Features:**
|
|
47
|
-
- Workspace root detection (
|
|
84
|
+
- Workspace root detection (walks upward looking for `.descix/workspace.json`)
|
|
48
85
|
- App context autodiscovery (CLI commands auto-detect community/app from cwd)
|
|
49
|
-
-
|
|
50
|
-
- Drive folder configuration for `
|
|
51
|
-
|
|
86
|
+
- Explicit port registration for local dev servers — there is **no auto-allocation**
|
|
87
|
+
- Drive folder configuration for `descix drive pull` / `descix drive push`
|
|
88
|
+
|
|
89
|
+
**Author it with CLI verbs, never by hand:**
|
|
90
|
+
|
|
91
|
+
| Key | Verb |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `env.apiUrl` | `descix config set-env <dev\|demo\|prod> [--url <url>]` (env is positional) |
|
|
94
|
+
| `env.gateway.port` | `descix config set-gateway-port <n\|none>` |
|
|
95
|
+
| `env.devCerts` | `descix config set-dev-certs --dir\|--cert\|--key\|--clear` |
|
|
96
|
+
| `env.powchUrl` | `descix config set-powch-url <url\|none>` |
|
|
97
|
+
| `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` |
|
|
52
99
|
|
|
53
|
-
####
|
|
100
|
+
#### Format (v2.1 — the only format)
|
|
54
101
|
|
|
55
102
|
```json
|
|
56
103
|
{
|
|
57
104
|
"version": "2.1",
|
|
58
|
-
"workspaceRoot": "/path/to/workspace",
|
|
59
|
-
"serve-port": 5173,
|
|
60
|
-
"driveConfig": { "base_folder_id": "..." },
|
|
61
105
|
"env": {
|
|
62
106
|
"environment": "DEV",
|
|
107
|
+
"apiUrl": "https://dev.descix.net",
|
|
108
|
+
"gateway": { "port": 5599 },
|
|
109
|
+
"devCerts": { "dir": "/Users/you/.descix/dev-certs-san" },
|
|
110
|
+
"powchUrl": "https://powch.dev.descix.net/",
|
|
63
111
|
"platform": {
|
|
64
112
|
"appId": "daita",
|
|
65
113
|
"localPath": "DeSciX_Cloud",
|
|
66
|
-
"site": { "port": 5174
|
|
67
|
-
"microservice": { "port": 4000
|
|
114
|
+
"site": { "port": 5174 },
|
|
115
|
+
"microservice": { "port": 4000 }
|
|
68
116
|
},
|
|
69
117
|
"products": [
|
|
70
|
-
{
|
|
71
|
-
|
|
72
|
-
"localPath": "DeSciX_Powch",
|
|
73
|
-
"site": { "port": 5175, "devCommand": "npm run dev:site" },
|
|
74
|
-
"microservice": { "port": 3003, "devCommand": "npm run dev:service" }
|
|
75
|
-
}
|
|
118
|
+
{ "appId": "my-app", "localPath": "my-app", "site": { "static": "." } },
|
|
119
|
+
{ "appId": "other-app", "localPath": "other", "site": { "port": 5599 }, "microservice": { "port": 4001 } }
|
|
76
120
|
]
|
|
77
121
|
}
|
|
78
122
|
}
|
|
79
123
|
```
|
|
80
124
|
|
|
81
|
-
`env.platform
|
|
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.
|
|
82
126
|
|
|
83
|
-
####
|
|
127
|
+
#### KB sync is manifest-driven
|
|
128
|
+
|
|
129
|
+
`descix kb corpus sync -a <app-id> [-k <KB>]` is the KB sync. It is **git-aware**: it walks the
|
|
130
|
+
sources named in a manifest at `<checkout>/.descix/manifests/<KB>.json`, resolves them at a git
|
|
131
|
+
ref (`main` unless `--ref` overrides), and upserts only what changed — stale blob SHAs are purged
|
|
132
|
+
in the same pass. **No manifest means nothing to sync**, so the manifest is the first thing a new
|
|
133
|
+
KB needs, not an optimisation.
|
|
134
|
+
|
|
135
|
+
Check before you write: `--dry-run` enumerates would-be upserts and purges with **no** Pinecone
|
|
136
|
+
writes (exit 0 = no drift, 1 = drift), and `--show-walk` prints the resolved ref and the walked
|
|
137
|
+
files. `descix kb corpus status` shows files, chunks, last sync and resolved ref.
|
|
138
|
+
|
|
139
|
+
**Only `.md` is ingested.** The corpus walk takes Markdown; a `.mdc` file is shipped and read
|
|
140
|
+
from disk but never enters a knowledge base. That matters for
|
|
141
|
+
`agent-assets/rules/descix_mcp.template.mdc`, which agents read as a file and which no amount of
|
|
142
|
+
KB querying will surface. If you fix something there, the fix reaches readers of the file and
|
|
143
|
+
nobody asking the KB — so do not assume KB coverage for a surface that has none. This is a known
|
|
144
|
+
boundary, not a defect.
|
|
145
|
+
|
|
146
|
+
`descix kb chunk`, `descix kb sync` and `descix update kb` still run but are **superseded
|
|
147
|
+
duplicates** — each names `kb corpus sync` as its replacement in its own `--help` and is slated
|
|
148
|
+
for removal. Do not put them in new instructions.
|
|
149
|
+
|
|
150
|
+
#### What you put in a KB changes what comes out of it
|
|
151
|
+
|
|
152
|
+
Retrieval is **vocabulary-dominated**, and when it goes wrong it does so silently. Measured against
|
|
153
|
+
a live KB of primary papers: a domain-plausible paraphrase of a paper's thesis returned a *sibling*
|
|
154
|
+
paper at 0.469 and never surfaced the correct one at all; rephrasing the same question in the
|
|
155
|
+
paper's own wording returned it at 0.575. Same KB, same document, correctly indexed the whole time.
|
|
156
|
+
|
|
157
|
+
Neither failure looked like a failure. Both returned confident, on-topic prose scoring in the same
|
|
158
|
+
0.45–0.58 band as the right answer, so nothing in the response told the caller they had the wrong
|
|
159
|
+
document.
|
|
160
|
+
|
|
161
|
+
For callers:
|
|
162
|
+
- Phrase queries in the **source's own vocabulary**; quote a distinctive phrase where you can.
|
|
163
|
+
- Never treat rank-1 as authoritative alone. Pull `limit >= 3` and **check `fileName`**.
|
|
164
|
+
- A confident, well-scored answer is not evidence the right document was retrieved. Verify by
|
|
165
|
+
**document identity**, not by score.
|
|
166
|
+
|
|
167
|
+
For curators, which is the part that bites: **mixing overview or summary documents into a KB with
|
|
168
|
+
the primary sources they describe systematically shadows those primaries.** Overviews are written in
|
|
169
|
+
general vocabulary, so they match paraphrases *better* than the specific documents they summarise —
|
|
170
|
+
the survey outranks the paper for exactly the reader who does not yet know the paper's terms.
|
|
171
|
+
|
|
172
|
+
### 3.2. Target resolution (one owner, explicit-first)
|
|
173
|
+
|
|
174
|
+
| Target | 1. flag / env | 2. workspace | 3. global | 4. default |
|
|
175
|
+
|---|---|---|---|---|
|
|
176
|
+
| **API** | `--api-url` / `--env` / `DESCIX_API_URL` | `env.apiUrl`, then the legacy top-level `apiUrl` | `~/.descix/config.json` `api_url` | **the declared default: PROD** |
|
|
177
|
+
| **Shell** (`/`) | `--site-url` | `env.siteUrl` | **the API origin, when the API is remote** | `env.platform.site.port`, else fail loud |
|
|
178
|
+
|
|
179
|
+
**There is no port-derived step for the API.** An environment NAME never becomes an origin, and
|
|
180
|
+
`env.platform.microservice.port` is not consulted: a local backend is a URL you name
|
|
181
|
+
(`descix config set-env dev --url https://localhost:4000`, or `env.apiUrl` direct). The single
|
|
182
|
+
owner of this order is `lib/origin.js::PRECEDENCE`; this table is a description of it, not a
|
|
183
|
+
second copy of the rule.
|
|
184
|
+
|
|
185
|
+
**Every resolution carries its SOURCE, and every network-bound command prints it on stderr** —
|
|
186
|
+
always, not only when it lands on the default:
|
|
84
187
|
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"communities": {
|
|
89
|
-
"descix": {
|
|
90
|
-
"apps": {
|
|
91
|
-
"myapp": {
|
|
92
|
-
"localPath": "myapp",
|
|
93
|
-
"kbId": "General",
|
|
94
|
-
"site": { "port": 3000, "devCommand": "npm run dev" },
|
|
95
|
-
"service": { "port": 4001, "devCommand": "npm run start" }
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
"driveConfig": { "base_folder_id": "..." }
|
|
101
|
-
}
|
|
188
|
+
```
|
|
189
|
+
env: prod (default — no workspace config; `descix config init --env dev` targets DEV) <prod origin>
|
|
190
|
+
env: dev (.descix/workspace.json env.apiUrl) https://dev.descix.net
|
|
102
191
|
```
|
|
103
192
|
|
|
104
|
-
|
|
105
|
-
|
|
193
|
+
An unconfigured workspace resolving to PROD is the shipped product's declared target, not a
|
|
194
|
+
fallback; what makes it legitimate is that it is announced. A configured-but-unusable origin is
|
|
195
|
+
a different case and FAILS LOUD naming the remedy, rather than quietly becoming the default.
|
|
106
196
|
|
|
107
|
-
|
|
108
|
-
- **`/powch`** → `env.products.find(p => p.appId === 'powch').site.port`
|
|
109
|
-
- **`/s/{community}/{appId}`** → `localhost:{microservice.port}` for each product in `workspace.json`
|
|
110
|
-
- **`/Community/{c}/Apps/{a}/site`** → `localhost:{site.port}` for local app dev
|
|
111
|
-
- **`/Community`** → GCS fallback
|
|
112
|
-
- **`/.proxy/gcs_media`** → GCS media proxy
|
|
197
|
+
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`).
|
|
113
198
|
|
|
114
199
|
## 4. Scenarios
|
|
115
200
|
|
|
116
|
-
### Scenario 1:
|
|
117
|
-
* **User**:
|
|
118
|
-
* **Setup**:
|
|
119
|
-
* **Result**:
|
|
201
|
+
### Scenario 1: App Dev (the common case)
|
|
202
|
+
* **User**: App developer. No platform checkout.
|
|
203
|
+
* **Setup**: `descix config set-env dev`, `descix app init`, `descix app set-site`, then `cd my-app && descix serve`.
|
|
204
|
+
* **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.
|
|
120
205
|
|
|
121
|
-
### Scenario 2:
|
|
122
|
-
* **User**:
|
|
123
|
-
* **Setup**:
|
|
124
|
-
* **Result**:
|
|
125
|
-
* `/apps/my-community/my-app` -> **Localhost** (User's Dev Server).
|
|
126
|
-
* `/apps/other-app` -> **Production** (Live GCS).
|
|
127
|
-
* `/api/core` -> **Production** (Live API).
|
|
128
|
-
* `/*` (PWA Shell) -> **Production** (Live PWA).
|
|
206
|
+
### Scenario 2: Platform Dev ("Dogfooding")
|
|
207
|
+
* **User**: Core team, full repo checkout.
|
|
208
|
+
* **Setup**: start the backend (`:4000`), the platform site (`:5174`), Powch site/service as needed, then `descix serve --site-url https://localhost:5174`.
|
|
209
|
+
* **Result**: the gateway routes `/` to the local shell, `/apifront` to the local Core, `/powch` to the configured Powch origin, `/s/*` to microservices, `/p/{appId}` to product sites.
|
|
129
210
|
|
|
130
211
|
### Scenario 3: Production
|
|
131
212
|
* **User**: End User.
|
|
@@ -134,5 +215,87 @@ The gateway uses `createViteProxyConfig` from `@descix/app-sdk/dev` to generate
|
|
|
134
215
|
|
|
135
216
|
## 5. Client-Side Implications
|
|
136
217
|
|
|
137
|
-
* **"Dumb"
|
|
138
|
-
* **
|
|
218
|
+
* **"Dumb" client**: the shell constructs a canonical relative path and lets the gateway (locally) or the LB (in production) resolve it. No GCS-URL rewriting in client code.
|
|
219
|
+
* **The credential is a body field**, not a cookie and not a header: every call is a relative `POST /apifront/` with the token in the JSON body. There is no `SameSite` problem, no credentialed CORS preflight, and the browser origin is irrelevant to the mesh — same-origin is required for *frame scripting*, not for auth.
|
|
220
|
+
* **Set your framework's base path to `/p/{appId}`.** The gateway does not rewrite paths, so assets requested at `/` will 404.
|
|
221
|
+
|
|
222
|
+
## 6. Running from a git worktree
|
|
223
|
+
|
|
224
|
+
`.descix/workspace.json` is gitignored, so no worktree has one. The gateway walks **up** from cwd to find it, so an in-repo worktree silently inherits the **main checkout's** workspace — its port, its products, its `localPath`s. Copying the file into a worktree does not help: a saved workspace bakes an absolute `workspaceRoot` and prefers it over the discovered root, pointing back at the original checkout. Out-of-repo worktrees fail earlier and more confusingly: a credential-loading command reports **"Authentication required… Run: descix login"** when the real cause is a missing workspace file.
|
|
225
|
+
|
|
226
|
+
Rules of thumb: run the CLI from the canonical checkout, and treat an auth error raised from a worktree as a workspace-resolution suspect *before* re-authenticating.
|
|
227
|
+
|
|
228
|
+
### Deploying: probe the credential the action actually uses
|
|
229
|
+
|
|
230
|
+
`deploy-env.sh` will refuse to start rather than fail halfway:
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
gcloud credentials are NOT usable (expired user session, or no active account)...
|
|
234
|
+
Refusing to start a real deploy that would fail partway through.
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
That refusal is the script working correctly, and **an expired gcloud user session alongside live
|
|
238
|
+
ADC is a normal steady state**, not a broken machine. The two are different credentials behind one
|
|
239
|
+
word: the deploy path needs the **user session**, while most quick probes reach for **ADC**.
|
|
240
|
+
|
|
241
|
+
This is the trap: `gcloud auth application-default print-access-token` returns a token, you record
|
|
242
|
+
"gcloud is fine", and that observation is *true and irrelevant*. **Probe the credential the action
|
|
243
|
+
actually uses, not an adjacent one that happens to answer.**
|
|
244
|
+
|
|
245
|
+
The remedy is one line, needs no re-auth prompt, and the script prints it itself:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
export CLOUDSDK_AUTH_ACCESS_TOKEN="$(gcloud auth application-default print-access-token)"
|
|
249
|
+
[ -n "$CLOUDSDK_AUTH_ACCESS_TOKEN" ] || { echo "empty token"; exit 1; }
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Assert it non-empty before launching — an empty token reproduces the same refusal one layer later,
|
|
253
|
+
where it is harder to recognise.
|
|
254
|
+
|
|
255
|
+
**Why this is written down rather than left to be rediscovered:** without it, the next agent reads
|
|
256
|
+
a correct fail-loud refusal as *platform unreachable* and stops under the platform-reachability
|
|
257
|
+
rule — halting a lane and escalating, over a one-line export the script had already told it. A
|
|
258
|
+
fail-loud message nobody knows how to act on still costs a lane.
|
|
259
|
+
|
|
260
|
+
### Exit codes from wrappers are not evidence
|
|
261
|
+
|
|
262
|
+
A deploy wrapper ending in `| tail` returns **tail's** status, not the deploy's. A run can report
|
|
263
|
+
exit 0 while the deploy correctly returned 1. Capture the real status *before* anything pipes it:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
deploy-env.sh dev; rc=$? # capture FIRST
|
|
267
|
+
deploy-env.sh dev 2>&1 | tail -40 # then look at output separately
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
To confirm a deploy succeeded, **read the log, not the exit code** — and where the artifact is
|
|
271
|
+
observable (a served object's timestamp, a string in the shipped bundle), check that instead. A
|
|
272
|
+
pipe silently drops information in both directions: `| tail` hides a failure, and `| head` hides
|
|
273
|
+
later matches from a search that looks complete.
|
|
274
|
+
|
|
275
|
+
### The SDK you edit is not always the SDK you serve
|
|
276
|
+
|
|
277
|
+
A second, sharper worktree trap, and it is silent. `DeSciX_Cloud/site/node_modules/@descix/app-sdk`
|
|
278
|
+
is a **symlink into the canonical Core checkout**:
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
$ readlink DeSciX_Cloud/site/node_modules/@descix/app-sdk
|
|
282
|
+
../../../../DeSciX_Core/descix-app-sdk
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
and `@descix/app-sdk` has **no build step** — its `main` and its `.` export both point straight at
|
|
286
|
+
`./src/index.js`, so Vite serves the package source as-is. Put those two facts together: **`descix
|
|
287
|
+
serve` serves whatever the CANONICAL Core working tree contains**, no matter which worktree you are
|
|
288
|
+
editing in. Change `app-sdk` on a branch, reload, and you are still running canonical `main` — your
|
|
289
|
+
edit is not in the page, nothing errors, and the obvious conclusion ("my change had no effect") is
|
|
290
|
+
wrong.
|
|
291
|
+
|
|
292
|
+
Verify what is actually being served before you conclude anything about a change:
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
readlink DeSciX_Cloud/site/node_modules/@descix/app-sdk # where the symlink points
|
|
296
|
+
node -p "require.resolve('@descix/app-sdk')" # from the site directory
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
If it resolves to the canonical checkout and you are editing elsewhere, you are measuring the wrong
|
|
300
|
+
tree. Re-point the symlink at your worktree for the measurement **and restore it afterwards** — it
|
|
301
|
+
is untracked, so nothing will remind you.
|
|
@@ -133,7 +133,7 @@ tell_me_how({
|
|
|
133
133
|
|
|
134
134
|
### 3.5 Integration with SDK V2 Setup
|
|
135
135
|
|
|
136
|
-
After `descix
|
|
136
|
+
After `descix mcp quickstart` completes:
|
|
137
137
|
|
|
138
138
|
1. `workspace.json` is created with community/app mappings
|
|
139
139
|
2. Credentials are saved to `.descix/wallet.json`
|
|
@@ -233,7 +233,7 @@ const result = await execute_remote_command({
|
|
|
233
233
|
### 5.1 Initial Setup Phase
|
|
234
234
|
|
|
235
235
|
```
|
|
236
|
-
descix
|
|
236
|
+
descix mcp quickstart
|
|
237
237
|
│
|
|
238
238
|
▼
|
|
239
239
|
Prerequisites Check (gcloud, ADC)
|
|
@@ -368,7 +368,7 @@ if (tools.recommended_tools.length > 0) {
|
|
|
368
368
|
|
|
369
369
|
**Pattern: Project-Scoped Operations**
|
|
370
370
|
```javascript
|
|
371
|
-
// Only works after descix
|
|
371
|
+
// Only works after descix mcp quickstart
|
|
372
372
|
const tools = await tell_me_how({
|
|
373
373
|
question: "How do I update this app?",
|
|
374
374
|
scope: "project" // Uses workspace.json
|
|
@@ -395,7 +395,7 @@ descix microservice vectorize -r SERVICE_README.md
|
|
|
395
395
|
**Solution:**
|
|
396
396
|
```bash
|
|
397
397
|
# Run setup first
|
|
398
|
-
descix
|
|
398
|
+
descix mcp quickstart
|
|
399
399
|
|
|
400
400
|
# Or ensure you're in the workspace root
|
|
401
401
|
cd /path/to/workspace
|
|
@@ -416,9 +416,9 @@ cd /path/to/workspace
|
|
|
416
416
|
|
|
417
417
|
| Component | Path |
|
|
418
418
|
|-----------|------|
|
|
419
|
-
| MCP Tools | `DeSciX_Core/descix-cli/
|
|
420
|
-
| tell_me_how Implementation | `DeSciX_Cloud/services/commandHandlers/ragCommands.js` |
|
|
421
|
-
| execute_remote_command | `DeSciX_Cloud/services/apiFront.js` |
|
|
422
|
-
| SERVICE_README Template | `
|
|
419
|
+
| MCP Tools | `DeSciX_Core/descix-cli/bin/mcp-server.js` |
|
|
420
|
+
| tell_me_how Implementation | `DeSciX_Cloud/microservice/services/commandHandlers/ragCommands.js` |
|
|
421
|
+
| execute_remote_command | `DeSciX_Cloud/microservice/services/apiFront.js` |
|
|
422
|
+
| SERVICE_README Template | `DeSciX_Core/descix-cli/templates/scaffolds/microservice/templates/SERVICE_README_TEMPLATE.md` |
|
|
423
423
|
| Workspace Config | `DeSciX_Core/descix-cli/lib/workspace-config.js` |
|
|
424
|
-
| Service Registration | `DeSciX_Core/descix-cli/
|
|
424
|
+
| Service Registration | `DeSciX_Core/descix-cli/bin/descix.js` |
|