@formlm/cli 0.3.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +326 -65
  2. package/dist/commands/app.d.ts.map +1 -1
  3. package/dist/commands/app.js +74 -16
  4. package/dist/commands/app.js.map +1 -1
  5. package/dist/commands/auth.d.ts.map +1 -1
  6. package/dist/commands/auth.js +186 -7
  7. package/dist/commands/auth.js.map +1 -1
  8. package/dist/commands/connect.js +3 -3
  9. package/dist/commands/connect.js.map +1 -1
  10. package/dist/commands/doctor.d.ts +11 -0
  11. package/dist/commands/doctor.d.ts.map +1 -0
  12. package/dist/commands/doctor.js +109 -0
  13. package/dist/commands/doctor.js.map +1 -0
  14. package/dist/commands/expert.d.ts.map +1 -1
  15. package/dist/commands/expert.js +42 -18
  16. package/dist/commands/expert.js.map +1 -1
  17. package/dist/commands/field.d.ts.map +1 -1
  18. package/dist/commands/field.js +9 -11
  19. package/dist/commands/field.js.map +1 -1
  20. package/dist/commands/profile.js +1 -1
  21. package/dist/commands/profile.js.map +1 -1
  22. package/dist/commands/report.d.ts.map +1 -1
  23. package/dist/commands/report.js +39 -12
  24. package/dist/commands/report.js.map +1 -1
  25. package/dist/commands/scale.d.ts.map +1 -1
  26. package/dist/commands/scale.js +4 -1
  27. package/dist/commands/scale.js.map +1 -1
  28. package/dist/commands/share.d.ts.map +1 -1
  29. package/dist/commands/share.js +258 -28
  30. package/dist/commands/share.js.map +1 -1
  31. package/dist/commands/skill.d.ts.map +1 -1
  32. package/dist/commands/skill.js +2 -3
  33. package/dist/commands/skill.js.map +1 -1
  34. package/dist/commands/smart.d.ts.map +1 -1
  35. package/dist/commands/smart.js +337 -59
  36. package/dist/commands/smart.js.map +1 -1
  37. package/dist/commands/snapshot.d.ts +0 -11
  38. package/dist/commands/snapshot.d.ts.map +1 -1
  39. package/dist/commands/snapshot.js +168 -42
  40. package/dist/commands/snapshot.js.map +1 -1
  41. package/dist/config.d.ts +1 -0
  42. package/dist/config.d.ts.map +1 -1
  43. package/dist/config.js +1 -1
  44. package/dist/config.js.map +1 -1
  45. package/dist/doctor.d.ts +51 -0
  46. package/dist/doctor.d.ts.map +1 -0
  47. package/dist/doctor.js +202 -0
  48. package/dist/doctor.js.map +1 -0
  49. package/dist/exec.d.ts +39 -1
  50. package/dist/exec.d.ts.map +1 -1
  51. package/dist/exec.js +309 -4
  52. package/dist/exec.js.map +1 -1
  53. package/dist/index.js +55 -6
  54. package/dist/index.js.map +1 -1
  55. package/dist/mcp.d.ts.map +1 -1
  56. package/dist/mcp.js +283 -67
  57. package/dist/mcp.js.map +1 -1
  58. package/dist/output.d.ts +23 -1
  59. package/dist/output.d.ts.map +1 -1
  60. package/dist/output.js +69 -7
  61. package/dist/output.js.map +1 -1
  62. package/dist/summary.d.ts +17 -0
  63. package/dist/summary.d.ts.map +1 -0
  64. package/dist/summary.js +64 -0
  65. package/dist/summary.js.map +1 -0
  66. package/dist/utils.d.ts +10 -2
  67. package/dist/utils.d.ts.map +1 -1
  68. package/dist/utils.js +45 -6
  69. package/dist/utils.js.map +1 -1
  70. package/package.json +11 -2
package/README.md CHANGED
@@ -20,6 +20,28 @@ With `formlm-cli`, you can control FormLM directly from your terminal or plug it
20
20
 
21
21
  ---
22
22
 
23
+ ## What's New in v0.5.0
24
+
25
+ Hardening round driven by real agent field reports (batch runs of 50 apps), plus a second pass that re-checked every reported item against the code and machine-verified all documented commands.
26
+
27
+ - **`share publish` now defaults to anonymous access** (`--access visitor`) and exposes `--access / --perm / --days / --no-style`; a new `share set` subcommand passes the raw server parameters through, so "anyone + permanent" no longer requires calling the internal API. Previously publish was hard-wired to `form-type all`, which **requires login** — anonymous respondents got the login page.
28
+ - **`expert config --enable` no longer self-destructs**: the value is forwarded space-separated (`--enable true`) and the server accepts it again. Before, `--enable=true` was rejected as an unknown option, the whole command was discarded, yet the envelope still reported success.
29
+ - **Parameter errors are no longer reported as success**: `picocli` validation failures now map to `code != 0` / `ok:false` instead of hiding the error text inside `data` with `code:0`.
30
+ - **Uniform machine output**: `snapshot` and `auth status` now honour `--json`/`FORMLM_JSON=1` with the same `{ok,code,message,data}` envelope as everything else, and human guidance lines moved to stderr, so stdout is a single parseable line.
31
+ - **`app remove` is a real alias of `app delete`**; `app list` gained `--all / --limit / --page / --with-urls`; `app urls` returns `shareToken`, `published`, `shareType/Perm/Day` and absolute https URLs.
32
+ - **New `doctor` command** (and MCP `formlm_doctor` tool): one read-only call per app covering scoring coverage, dead/empty experts, styling, unexpected certificate pages, language consistency (`--expect-lang`, `--deep` scans widget text) and share access + reachability.
33
+ - **New `snapshot --summary`** compact audit profile (counts, dimension names, report pages, expert flags, share type/perm/day + shareToken) — batch verification no longer needs to parse full module payloads.
34
+ - **Resume after the plan cache expires**: `smart plan --save-plan <file>` + `smart execute --plan-file <file>` (the server plan cache is ~10 minutes, and the docs now say so).
35
+ - **Retry/backoff**: read-only commands retry with exponential backoff on 408/429/5xx; writes are never auto-retried. Tunable via `FORMLM_RETRIES` / `FORMLM_TIMEOUT_MS`.
36
+ - `report page remove --name "结业证书"` resolves page names server-side; `report page update` verifies the page exists (opt into upsert with `--upsert`); write confirmations are compact; `widget remove` now persists (it previously returned success without saving).
37
+
38
+ - **`smart generate` now exists** as a resumability-preserving wrapper over `plan → execute×N → (--publish) → (--doctor)`, and the README finally matches the command surface. Earlier versions documented a `smart generate` that was never implemented (the first command every agent ran, and it failed).
39
+ - **Generation is now pin-able**: `smart plan --dimensions "A|B|C"` fixes the scoring dimension names and count, `--app-name` fixes the app display name, `--dry-run` validates a prompt without leaving a residue app. Unpinned dimensions used to be renamed/recounted by the AI, forcing page↔app rework (batch measurement: 11/13 pages).
40
+ - **Docs are now machine-verified against the command surface**: every `formlm-cli …` example in README/INSTALL is executed and checked for unknown/missing options (149 examples, 0 drifts), so documented commands cannot silently diverge again.
41
+ - `smart plan` output carries structured `modules` / `missingModules`, so callers can detect coverage gaps (e.g. no `expert` for non-consultation plans) without parsing prose; the raw exec `403` now lists the whitelisted command set.
42
+
43
+ ---
44
+
23
45
  ## What's New in v0.2.1
24
46
 
25
47
  - **Field ID validation**: `field add --id` now enforces snake_case regex (`^[a-zA-Z0-9_]+$`)
@@ -46,7 +68,7 @@ The MCP architecture has been completely redesigned from the ground up:
46
68
  │ AI Agent (any MCP Client: Claude / Cursor / │
47
69
  │ Codex CLI / Windsurf / Cline / ...) │
48
70
  ├─────────────────────────────────────────────────────────┤
49
- │ Tier 0: auth_login, auth_status │
71
+ │ Tier 0: auth_login, auth_email_code, auth_status │
50
72
  │ Tier 1: formlm_generate ← Smart Pipeline │
51
73
  │ Tier 2: formlm_snapshot, formlm_skill ← State + Knowledge│
52
74
  │ Tier 3: formlm_exec ← Direct Commands │
@@ -84,43 +106,96 @@ For a detailed step-by-step guide (including MCP setup for Claude Desktop / Curs
84
106
  ### 1. Login
85
107
 
86
108
  ```bash
87
- formlm-cli auth login
88
- # or use a token directly
109
+ # Recommended: copy your Access Token from the web app
110
+ # (formlm.me → sign in → Workspace → top-right user menu → Account Settings → Access Token → Copy)
89
111
  formlm-cli auth login --token <your-token>
112
+
113
+ # Interactive login — pick one of three methods:
114
+ # 1) Access Token (same as above)
115
+ # 2) Email verification code (no password, no browser — fully in the terminal)
116
+ # 3) Email + password (only if your account has set a password —
117
+ # email-verification-code and Google accounts have none)
118
+ formlm-cli auth login
90
119
  ```
91
120
 
92
121
  ### 2. Smart Pipeline (AI-recommended)
93
122
 
123
+ Creation is a **two-phase pipeline** (`plan` → `execute` per module). `smart generate` is the one-shot wrapper
124
+ of the same steps when you do not need per-module control:
125
+
94
126
  ```bash
95
- # Generate a complete assessment app from natural language
96
- # This includes form design, scale config, report pages, AND visual styling — all in one step.
97
- # Expected time: 60-120s for assessment, 180-300s for consultation. Do NOT cancel.
98
- formlm-cli smart generate --input "Create a workplace stress assessment with 10 questions, 3 dimensions, and detailed score interpretations"
127
+ # One-shot: plan → execute every module → publish anonymously → quality audit
128
+ formlm-cli smart generate \
129
+ --input "Create a workplace stress assessment with 10 questions, 3 dimensions (workload, autonomy, support), and detailed score interpretations" \
130
+ --plan-type assessment --question-count 10-15 --lang en --publish --doctor
99
131
  ```
100
132
 
101
- > **⚠️ Smart generate already includes visual styling.** If you skip smart generate and use Direct Commands (below) instead, you MUST run `connect style apply-all` to beautify your form — otherwise it will use the default unstyled appearance.
133
+ Or step by step (recommended for batches — every step is resumable):
134
+
135
+ ```bash
136
+ # Phase 1 — plan (~10-30s): creates the app and returns appId + task list.
137
+ # --save-plan keeps the full plan JSON on disk so modules can still be executed
138
+ # after the server-side plan cache (~10 min) expires.
139
+ formlm-cli smart plan --input "Create a workplace stress assessment with 10 questions, 3 dimensions, and detailed score interpretations" \
140
+ --plan-type assessment --question-count 10-15 --lang en --dimensions "Workload|Autonomy|Support" --save-plan plan.json
141
+
142
+ # Phase 2 — execute every module listed by the plan, in order (~30-120s each):
143
+ formlm-cli smart execute --app <appId> --module form
144
+ formlm-cli smart execute --app <appId> --module scale
145
+ formlm-cli smart execute --app <appId> --module connect
146
+ formlm-cli smart execute --app <appId> --module report
147
+ formlm-cli smart execute --app <appId> --module share
148
+
149
+ # Publish so anonymous visitors can fill it in (each respondent submits once, permanent):
150
+ formlm-cli share publish --app <appId> # --access visitor is the default
151
+
152
+ # Verify quality in one read-only call (see Doctor below):
153
+ formlm-cli doctor --app <appId> --expect-lang en
154
+ ```
155
+
156
+ > **⚠️ Module coverage depends on planType.** Only `consultation` plans include an `expert` task;
157
+ > `assessment / exam / report / survey / learn` do not. `smart plan` prints a warning when a module is
158
+ > missing — add an expert explicitly with `formlm-cli expert config --app <appId> --name ... --role ... --kbText ...`.
159
+
160
+ > **⚠️ Styling:** the `connect` module of the pipeline applies the visual style. If you skip the pipeline and use
161
+ > Direct Commands instead, you MUST run `connect style apply-all`, otherwise the form keeps the plain unstyled look.
102
162
 
103
163
  ### 3. Get All App URLs (after creating)
104
164
 
105
165
  ```bash
106
- # Get fill-in, editor, and data management URLs in one call
166
+ # Get fill-in, editor, data management, and Data API URLs in one call
107
167
  formlm-cli app urls --app <appId>
108
- # Returns: shareUrl (fill-in), builderUrl (editor), dataUrl (data management)
168
+ # Returns: shareUrl (relative /s/<token>), shareUrlAbsolute (https, iframe-ready),
169
+ # shareToken, published, shareType/sharePerm/shareDay,
170
+ # builderUrl (editor), dataUrl (data management),
171
+ # apiUrl + apiHelpUrl (Data API, empty until enabled)
109
172
  ```
110
173
 
111
- ### 4. Beautify Your Form (if using Direct Commands)
174
+ ### 4. Enable the Data API (form backend for any page)
175
+
176
+ ```bash
177
+ # Turn a form into a data endpoint — static sites, local pages, and AI apps
178
+ # can POST submissions straight to it (CORS enabled, no server needed)
179
+ formlm-cli share api --app <appId> --submit true --query true
180
+ # Then point your HTML form / fetch / curl at the returned endpoint.
181
+ # Append ?help to the endpoint for its Markdown docs (readable by AI agents).
182
+ ```
183
+
184
+ ### 5. Beautify Your Form (if using Direct Commands)
112
185
 
113
186
  ```bash
114
187
  # Apply AI-generated visual style to all pages (takes 30-120s)
115
188
  formlm-cli connect style apply-all --app <appId> --look "职场压力评估,深蓝专业风格" --theme minimalist
116
189
  ```
117
190
 
118
- ### 5. Direct Commands (for fine-grained control)
191
+ ### 6. Direct Commands (for fine-grained control)
119
192
 
120
193
  ```bash
121
194
  # Get a snapshot of all module states
122
195
  formlm-cli snapshot --app <appId>
123
196
  formlm-cli snapshot --app <appId> --md # Markdown format (token-efficient for AI)
197
+ formlm-cli snapshot --app <appId> --summary # compact audit profile (batch verification)
198
+ formlm-cli snapshot --app <appId> --with-values # include report widget body text
124
199
 
125
200
  # Read a skill document before constructing commands
126
201
  formlm-cli skill form
@@ -130,25 +205,31 @@ formlm-cli skill scale
130
205
  formlm-cli scale query --app <appId>
131
206
  formlm-cli scale add --app <appId> --id stress --name "Stress Level" --format sum --kbText "..."
132
207
  formlm-cli scale keys add --app <appId> --scale stress --fields q1,q2,q3
133
- formlm-cli scale data add --app <appId> --scale stress --ranges "0-10:Low,11-20:Moderate,21-30:High"
208
+ formlm-cli scale data add --app <appId> --scale stress --bands "Low:desc||Moderate:desc||High:desc" # recommended: server auto-computes even boundaries + 999 sentinel
134
209
 
135
210
  # Report commands
136
211
  formlm-cli report query --app <appId>
137
- formlm-cli report page add --app <appId> --name "Summary" --layout grid
138
- formlm-cli report widget add --app <appId> --page <pageId> --type chart --chartType bar --name "Score Chart"
212
+ formlm-cli report page add --app <appId> --name "Summary" # page type defaults to A4
213
+ formlm-cli report widget add --app <appId> --page <pageId> --type scale-chart --format bar --scaleId <dim> --x 0 --y 0 --w 24 --h 12
214
+ formlm-cli report widget logic add --app <appId> --page <pageId> --id <widgetId> --min 0 --max 20 --content "<p>Keep it up</p>"
139
215
 
140
- # Expert commands
216
+ # Expert commands (--name and --kbText are required by the server)
141
217
  formlm-cli expert query --app <appId>
142
- formlm-cli expert config --app <appId> --enableChat true
218
+ formlm-cli expert config --app <appId> --name "Career Coach" --role "资深职业规划师" --kbText "..." --theme Warm
219
+ formlm-cli expert set --app <appId> --property enable --value true # single-property toggle
220
+
221
+ # Quality audit (read-only)
222
+ formlm-cli doctor --app <appId>
223
+ formlm-cli doctor --app <appId> --expect-lang en --deep
143
224
  ```
144
225
 
145
- ### 6. Use as MCP Server
226
+ ### 7. Use as MCP Server
146
227
 
147
228
  ```bash
148
229
  formlm-cli mcp
149
230
  ```
150
231
 
151
- This starts the MCP Server (stdio transport) with 6 tools + 6 resources, ready for AI Agents to connect.
232
+ This starts the MCP Server (stdio transport) with 9 tools + 6 resources, ready for AI Agents to connect.
152
233
 
153
234
  ---
154
235
 
@@ -156,11 +237,37 @@ This starts the MCP Server (stdio transport) with 6 tools + 6 resources, ready f
156
237
 
157
238
  ### Smart Pipeline (AI-recommended)
158
239
 
240
+ There are two ways in: `smart plan` + `smart execute` (explicit, resumable — recommended for batches),
241
+ or `smart generate`, which is a thin wrapper over exactly those steps:
242
+
159
243
  ```bash
160
- # Generate a complete app from natural language
161
- formlm-cli smart generate --input "..." [--plan-type assessment] [--style "温暖亲切"] [--question-count 10-15]
244
+ # Phase 1 — plan only (creates the app, returns appId + tasks; cached server-side ~10min)
245
+ formlm-cli smart plan --input "..." [--plan-type assessment] [--style "温暖亲切"] [--question-count 10-15] \
246
+ [--lang en] [--dimensions "Focus|Sleep|Load"] [--app-name "Team Focus Check"] \
247
+ [--save-plan plan.json] [--dry-run]
248
+
249
+ # Phase 2 — execute one module at a time (form / scale / connect / report / expert / share)
250
+ formlm-cli smart execute --app <appId> --module form
251
+ formlm-cli smart execute --app <appId> --module scale --plan-file plan.json # after the cache expired
252
+ formlm-cli smart execute --app <appId> --module scale --clear-first # re-run without duplicating dimensions
253
+
254
+ # One-shot wrapper — plan → execute every module → optional publish → optional doctor
255
+ formlm-cli smart generate --input "..." --plan-type assessment --lang en --publish --doctor
256
+ formlm-cli smart generate --input "..." --only form,scale,report # partial build
257
+ formlm-cli smart generate --input "..." --skip connect # leave styling out
162
258
  ```
163
259
 
260
+ > **Pinning vs. improvising.** By default the Plan AI invents dimension names/count and the app name, which
261
+ > breaks page↔app consistency in batch runs. Use `--dimensions` to pin the dimension list (exact names + count)
262
+ > and `--app-name` to pin the display name; verify afterwards with `snapshot --summary` (it reports `dimNames`).
263
+ >
264
+ > **`--dry-run`** validates a prompt/spec and deletes the probe app again (the server always creates an app when
265
+ > planning), so experimentation leaves no residue.
266
+ >
267
+ > **Success is machine-readable**: `smart execute` returns `data.taskStatus` (`success` / `error`), and
268
+ > `smart generate` returns `{appId, modules:[{module,status,error}], publish, doctor, resumeHint}` — trust those
269
+ > fields, not the human wording. On a mid-run failure the app is kept and `resumeHint` gives the exact resume command.
270
+
164
271
  ### Snapshot
165
272
 
166
273
  ```bash
@@ -168,8 +275,38 @@ formlm-cli smart generate --input "..." [--plan-type assessment] [--style "温
168
275
  formlm-cli snapshot --app <appId>
169
276
  formlm-cli snapshot --app <appId> --module scale # Only scale module
170
277
  formlm-cli snapshot --app <appId> --md # Markdown format (token-efficient for AI)
278
+ formlm-cli snapshot --app <appId> --summary # Compact audit profile (counts/dim names/report pages/expert/share + shareToken)
279
+ formlm-cli snapshot --app <appId> --with-values # + report widget body text (per-page queries)
280
+ formlm-cli snapshot --apps <id1,id2,...> --summary # Batch: N apps in ONE process (connection reuse, FORMLM_CONCURRENCY parallel apps, default 4)
281
+ ```
282
+
283
+ Measured: 5 apps × 7 module queries = 35 requests in ~13s in a single process, versus one cold Node
284
+ process per app before (the old serial-subprocess pattern took roughly 5× that, plus no connection reuse).
285
+
286
+ `snapshot` is **client-synthesized**: it fans out to the 6 `assess <module> query` commands. There is no
287
+ server-side `assess snapshot`, so calling that over raw `POST /api/v1/mcp/exec` returns 403 by design — loop
288
+ the 6 queries yourself when you need HTTP-side batching. If a module fetch fails, the result carries
289
+ `_errors` / `_degraded` (treat it as unknown, not as "empty module").
290
+
291
+ ### Doctor (read-only quality audit)
292
+
293
+ ```bash
294
+ # One call per app: content/scoring coverage, expert sanity, styling,
295
+ # unexpected certificate pages, share access semantics, link reachability
296
+ formlm-cli doctor --app <appId>
297
+
298
+ # Whole batch in one process (aggregate envelope; exit 1 if any app fails)
299
+ formlm-cli doctor --apps <id1,id2,...> --expect-lang en
300
+
301
+ # Add the language-consistency scan (classic batch defect: English app shipped with Chinese boilerplate)
302
+ formlm-cli doctor --app <appId> --expect-lang en # titles/labels
303
+ formlm-cli doctor --app <appId> --expect-lang zh-hant --deep # also scan report widget body text
304
+ formlm-cli doctor --app <appId> --no-probe # skip the fill-in URL reachability probe
171
305
  ```
172
306
 
307
+ Output is the standard envelope; `ok:false` + exit 1 when a `fail`-level finding exists, so batch drivers
308
+ can gate on it. Each finding carries a ready-to-run `fix` command. Read-only — it never writes.
309
+
173
310
  ### Skill Documents
174
311
 
175
312
  ```bash
@@ -185,9 +322,9 @@ formlm-cli skill share # Share/publish rules
185
322
  ### Auth
186
323
 
187
324
  ```bash
188
- formlm-cli auth login # Interactive login
189
- formlm-cli auth login --token <tok> # Login with token
190
- formlm-cli auth status # Check current login state
325
+ formlm-cli auth login --token <tok> # Login with Access Token (recommended: formlm.me → Account Settings)
326
+ formlm-cli auth login # Interactive login — 1) Access Token, 2) email verification code (no password needed), 3) email + password
327
+ formlm-cli auth status # Check current login state (tokens expire after 7 days)
191
328
  formlm-cli auth logout # Clear local token
192
329
  ```
193
330
 
@@ -203,11 +340,17 @@ formlm-cli --profile work app list # Use a profile for one command
203
340
  ### App
204
341
 
205
342
  ```bash
206
- formlm-cli app list
343
+ formlm-cli app list # first page (latest 20)
344
+ formlm-cli app list --all # full inventory (server page size capped at 500)
345
+ formlm-cli app list --limit 100 --page 2 # explicit paging
346
+ formlm-cli app list --all --with-urls # + published/shareType/sharePerm/shareDay/shareUrl/shareToken per app
347
+ formlm-cli app list --name "wellness" # filter by app name
207
348
  formlm-cli app create --name "My Form" --description "..."
349
+ formlm-cli app get --app <appId>
208
350
  formlm-cli app update --app <appId> --name "New Name" --theme blue
209
- formlm-cli app remove --app <appId> # Delete an app (irreversible)
210
- formlm-cli app urls --app <appId> # Get fill-in / editor / data URLs
351
+ formlm-cli app delete --app <appId> # Delete an app (irreversible)
352
+ formlm-cli app remove --app <appId> # alias of app delete
353
+ formlm-cli app urls --app <appId> # Get fill-in / editor / data URLs + shareToken
211
354
  ```
212
355
 
213
356
  ### Field
@@ -230,7 +373,7 @@ formlm-cli scale query --app <appId> # List all dimensi
230
373
  formlm-cli scale find --app <appId> --id <scaleId> # Find a dimension
231
374
  formlm-cli scale add --app <appId> --id stress --name "Stress" --format sum --kbText "..."
232
375
  formlm-cli scale update --app <appId> --id stress --name "Stress Level"
233
- formlm-cli scale set --app <appId> --id stress --direction negative
376
+ formlm-cli scale set --app <appId> --id stress --property direction --value negative
234
377
  formlm-cli scale remove --app <appId> --id stress
235
378
  formlm-cli scale clear --app <appId>
236
379
  formlm-cli scale config --app <appId> --enable-single true
@@ -242,7 +385,8 @@ formlm-cli scale keys list --app <appId> --scale stress
242
385
  formlm-cli scale keys set --app <appId> --scale stress --fields q3 --negScore true
243
386
 
244
387
  # Configure score ranges
245
- formlm-cli scale data add --app <appId> --scale stress --ranges "0-10:Low,11-20:High"
388
+ formlm-cli scale data add --app <appId> --scale stress --bands "Low:desc||Moderate:desc||High:desc" # recommended: server auto-computes even boundaries + 999 sentinel (ordered lowest→highest score)
389
+ formlm-cli scale data add --app <appId> --scale stress --ranges "0-10:Low,11-20:High" # manual boundaries; only for non-even knowledge-specified thresholds
246
390
  formlm-cli scale data update --app <appId> --scale stress --id <dataId> --value "Moderate"
247
391
  formlm-cli scale data remove --app <appId> --scale stress --id <dataId>
248
392
  formlm-cli scale data list --app <appId> --scale stress
@@ -258,7 +402,7 @@ formlm-cli connect types [--category cover|main|final] --verbose
258
402
  formlm-cli connect config --category cover --format rich-text
259
403
 
260
404
  # Cover page management
261
- formlm-cli connect cover-page add --app <appId> --id cover_main --name "Welcome" --format text --value "<h1>Hello</h1>"
405
+ formlm-cli connect cover-page add --app <appId> --id cover_main --name "Welcome" --format rich-text --value "<h1>Hello</h1>"
262
406
  formlm-cli connect cover-page update --app <appId> --id cover_main --name "New Title"
263
407
  formlm-cli connect cover-page find --app <appId> [--id cover_main]
264
408
  formlm-cli connect cover-page remove --app <appId> [--id cover_main]
@@ -286,50 +430,85 @@ formlm-cli connect style move --app <appId> --id <pageId> --direction up
286
430
  ```bash
287
431
  formlm-cli report query --app <appId> # List all report pages
288
432
  formlm-cli report find --app <appId> --filter <keyword> # Find report widget
289
- formlm-cli report update --app <appId> --page <pageId> --name "New Name"
290
433
 
291
- # Page management
292
- formlm-cli report page add --app <appId> --name "Summary" --layout grid
293
- formlm-cli report page update --app <appId> --id <pageId> --name "Overview"
434
+ # Note: update goes through the explicit owners — `report page update` (page name/bg/style/svg)
435
+ # and `report widget update` (widget props). The server also accepts the merged
436
+ # `assess report update --page <pageId> [--id <widgetId>]` form on the raw exec channel.
437
+
438
+ # Page management (a page is a 48-col × 68-row grid canvas; layout comes from widget x/y/w/h, not a page flag)
439
+ formlm-cli report page add --app <appId> --name "Summary" [--type A4]
440
+ formlm-cli report page update --app <appId> --id <pageId> --name "Overview" # fails if the id does not exist
441
+ formlm-cli report page update --app <appId> --id <pageId> --name "Overview" --upsert # opt into the server upsert (creates a blank page)
294
442
  formlm-cli report page remove --app <appId> --id <pageId>
443
+ formlm-cli report page remove --app <appId> --name "结业证书" # locate by human-readable name
295
444
 
296
- # Widget management
445
+ # Widget management (every widget command needs --page; set/find/update/remove also need --id)
297
446
  formlm-cli report widget list --app <appId> --page <pageId>
298
- formlm-cli report widget find --app <appId> --filter <keyword>
299
- formlm-cli report widget set --app <appId> --id <widgetId> --value "{{TotalScore}}"
300
- formlm-cli report widget add --app <appId> --page <pageId> --type chart --chartType bar --name "Score Chart"
301
- formlm-cli report widget update --app <appId> --id <widgetId> --name "Updated Chart"
302
- formlm-cli report widget remove --app <appId> --id <widgetId>
303
- formlm-cli report widget types --category chart
304
- formlm-cli report widget config --type chart --prop chartType
305
-
306
- # Logic rules
307
- formlm-cli report logic add --app <appId> --page <pageId> --condition "score>20" --action show
308
- formlm-cli report logic list --app <appId> --page <pageId>
309
- formlm-cli report logic remove --app <appId> --id <logicId>
447
+ formlm-cli report widget find --app <appId> --page <pageId> --id <widgetId> # full detail incl. HTML value
448
+ formlm-cli report widget set --app <appId> --page <pageId> --id <widgetId> --property value --value "{{TotalScore}}"
449
+ formlm-cli report widget add --app <appId> --page <pageId> --type scale-chart --format bar --scaleId <dim> --x 0 --y 0 --w 24 --h 12
450
+ formlm-cli report widget update --app <appId> --page <pageId> --id <widgetId> --name "Updated Chart"
451
+ formlm-cli report widget remove --app <appId> --page <pageId> --id <widgetId>
452
+ formlm-cli report widget types --verbose # all widget types (+ descriptions)
453
+ formlm-cli report widget config --type scale-chart # configurable properties of one type
454
+
455
+ # Conditional display rules (logic lives UNDER widget)
456
+ formlm-cli report widget logic add --app <appId> --page <pageId> --id <widgetId> --min 0 --max 20 --content "<p>Low band text</p>"
457
+ formlm-cli report widget logic list --app <appId> --page <pageId> --id <widgetId>
458
+ formlm-cli report widget logic remove --app <appId> --page <pageId> --id <widgetId> --logicId <logicId>
310
459
  ```
311
460
 
312
461
  ### Expert (AI Interpretation)
313
462
 
314
463
  ```bash
315
- formlm-cli expert query --app <appId> # Query expert config
316
- formlm-cli expert find --app <appId> # Find expert details
317
- formlm-cli expert config --app <appId> --enableChat true # Full configuration
318
- formlm-cli expert set --app <appId> --key model --value gpt-4
319
- formlm-cli expert avatar --app <appId> --name "Dr. AI" --avatar <url>
464
+ formlm-cli expert query --app <appId> # Query expert config (--md for a compact table)
465
+ formlm-cli expert find --app <appId> # Full config incl. prompt/welcome text
466
+ formlm-cli expert config --app <appId> --name "Dr. AI" --role "Career coach" \
467
+ --kbText "..." [--welcome ...] [--question1 ...] [--theme Warm] [--enable true] # create/update (name + kbText required)
468
+ formlm-cli expert set --app <appId> --property enable --value true # single-property toggle;
469
+ # properties: name/role/description/style/welcome/
470
+ # prompt/question1..3/kbText/enable/enableWelcome/theme
471
+ formlm-cli expert avatar --app <appId> --url <url> --enable true # needs an existing expert (config first)
320
472
  formlm-cli expert remove --app <appId>
321
- formlm-cli expert chat --app <appId> --message "Explain my score"
473
+ formlm-cli expert chat --app <appId> --input "Explain my score"
322
474
  ```
323
475
 
324
- ### Share
476
+ > Boolean flags are forwarded space-separated (`--enable true`), never `--enable=true` — the server parses them
477
+ > with picocli `arity 0..1`. `expert config` enables the agent by default; pass `--enable false` to configure it
478
+ > while leaving it switched off.
479
+
480
+ ### Share (Publish & Access)
325
481
 
326
482
  ```bash
327
- formlm-cli share publish --app <appId> # Publish (each respondent can submit once; unlimited respondents)
328
- formlm-cli share unpublish --app <appId> # Unpublish
329
- formlm-cli share query --app <appId> # Check publish status
330
- formlm-cli share url --app <appId> # Get the shareable URL
483
+ # Access types (know these — "public" is ambiguous):
484
+ # visitor = anonymous, no login required → "anyone can fill" (the usual public form)
485
+ # all = every LOGGED-IN FormLM user → anonymous visitors hit the login page
486
+ # secret = password-protected | owner = creator only | no = unpublish
487
+ formlm-cli share publish --app <appId> # anonymous (visitor) + one submission + permanent
488
+ formlm-cli share publish --app <appId> --access all --perm 2 --days 14 # explicit control
489
+ formlm-cli share publish --app <appId> --no-style # skip the automatic style fallback
490
+ formlm-cli share set --app <appId> --type visitor --perm 1 --day 0 # raw server parameters (idempotent)
491
+ formlm-cli share unpublish --app <appId>
492
+ formlm-cli share query --app <appId> # authoritative type/perm/day triple
493
+ formlm-cli share verify --app <appId> # published + anonymous + permanent + reachability in one call
494
+ formlm-cli share url --app <appId> # URLs incl. shareToken
495
+ formlm-cli share api --app <appId> # Configure the Data API (form backend endpoint)
496
+ formlm-cli share api --app <appId> --submit true --query true --auto-create true
331
497
  ```
332
498
 
499
+ > **Validity rule (server-side):** only `--days 1..30` are honoured as a finite window; `0`, `forever`, or anything
500
+ > above 30 normalizes to permanent (sentinel `3650000`). There is no 90-day/1-year publish window on this channel.
501
+ >
502
+ > **Verifying "anyone can access":** `curl` returning 200 on the share URL proves nothing — the SPA shell answers 200
503
+ > even behind the login gate. Use `share verify` (or read `share query`'s type/perm/day triple).
504
+ >
505
+ > **`smart execute --module share` vs `share publish`:** the pipeline's share module applies the plan's publish
506
+ > settings; `share publish` is the explicit, idempotent CLI entry that also guarantees anonymous + permanent
507
+ > defaults and prints the final URLs/`shareToken`. Re-running `share publish` is safe. If you never styled the
508
+ > app, publish auto-applies a default style first (30-120s AI generation) — pass `--no-style` to skip that.
509
+
510
+ The Data API turns a form into an HTTP data endpoint: `POST` JSON to the endpoint (or use the `/form` path for native HTML forms), read records back via the query endpoint, and hand the `?help` URL to an AI agent so it can discover the API on its own.
511
+
333
512
  ---
334
513
 
335
514
  ## MCP Integration
@@ -338,18 +517,21 @@ FormLM CLI works as a standard MCP Server over stdio and plugs into **any MCP-co
338
517
 
339
518
  > **⚠️ macOS/Linux users:** desktop AI clients often launch the MCP server without your full terminal PATH, which can cause `command not found` errors. See **[INSTALL.md → Step 4](INSTALL.md#step-4--connect-to-an-ai-agent-mcp-mode)** for the `env.PATH` fix, per-platform config file locations (including Codex CLI's TOML format), and the full setup guide.
340
519
 
341
- > **No token? No problem.** If you omit `FORMLM_TOKEN`, the AI will prompt you to authenticate via the `auth_login` tool — just provide your email + password (or token) directly in the chat.
520
+ > **No token? No problem.** If you omit `FORMLM_TOKEN`, the AI will prompt you to authenticate via the `auth_login` tool — paste your Access Token (from formlm.me → Workspace → Account Settings; recommended), complete an in-chat email verification-code login via `auth_email_code` (no browser needed), or use email + password directly in the chat.
342
521
 
343
522
  ---
344
523
 
345
- ## Available MCP Tools (6)
524
+ ## Available MCP Tools (9)
346
525
 
347
526
  | Tier | Tool | Description |
348
527
  |---|---|---|
349
- | 0 | `auth_login` | Login with token or email + password |
528
+ | 0 | `auth_login` | Login with Access Token (recommended), email verification code, or email + password |
529
+ | 0 | `auth_email_code` | Email verification-code login — fetch the captcha image & send the code (fully in-chat) |
350
530
  | 0 | `auth_status` | Check current login status |
351
- | 1 | `formlm_generate` | Generate a complete app from natural language (AssessAgent pipeline) |
352
- | 2 | `formlm_snapshot` | Get aggregated state of all modules (form/scale/connect/report/expert/share) |
531
+ | 1 | `formlm_generate` | Generate the execution plan (Phase 1: creates the app, returns appId + tasks) |
532
+ | 1 | `formlm_execute` | Execute plan modules one by one after `formlm_generate` |
533
+ | 2 | `formlm_doctor` | Read-only quality audit of one app (scoring coverage, dead experts, styling, certificate pages, language consistency, share access, reachability) |
534
+ | 2 | `formlm_snapshot` | Aggregated state of all modules; `summary: true` returns the compact audit profile |
353
535
  | 2 | `formlm_skill` | Fetch SKILL.md domain knowledge for a skill module |
354
536
  | 3 | `formlm_exec` | Execute any whitelisted CLI command directly |
355
537
 
@@ -371,7 +553,86 @@ FormLM CLI works as a standard MCP Server over stdio and plugs into **any MCP-co
371
553
  | Variable | Description |
372
554
  |---|---|
373
555
  | `FORMLM_BASE_URL` | FormLM server URL (default: `https://formlm.me`) |
374
- | `FORMLM_TOKEN` | Your auth token (alternative to `auth login`) |
556
+ | `FORMLM_TOKEN` | Your auth token (alternative to `auth login`; keeps secrets out of shell history) |
557
+ | `FORMLM_JSON=1` | Machine output: every command prints ONE parseable line `{ok,code,message,data}` on stdout (equivalent to the global `--json` flag) |
558
+ | `FORMLM_NO_EXIT=1` | Batch safety: never `process.exit()` on failure — a bad command cannot kill your driver loop (errors surface as `ok:false` envelopes / thrown errors) |
559
+ | `FORMLM_TIMEOUT_MS` | Default per-command request timeout (ms, default 60000) |
560
+ | `FORMLM_TIMEOUT_PLAN` / `FORMLM_TIMEOUT_EXECUTE` / `FORMLM_TIMEOUT_STYLE` | Override the smart-plan (120s), smart-execute (300s) and style (600s) timeouts |
561
+ | `FORMLM_RETRIES` | Max attempts for transient failures (default 3). Read-only commands retry on 408/429/5xx; writes are never auto-retried |
562
+ | `FORMLM_CONCURRENCY` | In-process parallelism for batch commands (`snapshot --apps`, `doctor --apps`), default 4 |
563
+
564
+ ---
565
+
566
+ ## Scripting & Batch Use
567
+
568
+ ```bash
569
+ # One parseable line per command; guidance/hints go to stderr, stdout stays clean:
570
+ FORMLM_JSON=1 FORMLM_NO_EXIT=1 formlm-cli snapshot --app <appId> --summary
571
+ FORMLM_JSON=1 formlm-cli share verify --app <appId> # {ok, data:{type,forever,anonymous,httpStatus,shareToken}}
572
+ FORMLM_JSON=1 formlm-cli doctor --app <appId> --expect-lang en # ok:false when a fail-level finding exists
573
+
574
+ # Whole batch in one process (no per-app Node cold start; tunable with FORMLM_CONCURRENCY):
575
+ FORMLM_JSON=1 formlm-cli doctor --apps id1,id2,id3 --expect-lang en
576
+ FORMLM_JSON=1 formlm-cli snapshot --apps id1,id2,id3 --summary
577
+ ```
578
+
579
+ Envelope: `{ "ok": bool, "code": int, "message": string, "data": object|null }` — `data` is always parsed
580
+ (no double-decoding needed), and validation/parameter errors now come back with a non-zero `code`
581
+ instead of hiding the error text inside `data` while reporting success.
582
+
583
+ ### Status codes
584
+
585
+ | Code | Meaning | What to do |
586
+ |---|---|---|
587
+ | `0` | Success | — |
588
+ | `207` | Partial (multi-module reads where one module failed) | Result carries `_errors`/`_degraded`; re-check that module, don't assume it is empty |
589
+ | `400` | Bad request / parameter or validation error | Read `message`; the server echoes picocli's hint (valid values, missing option) |
590
+ | `401` | Not authenticated | `formlm-cli auth login --token-stdin` (or set `FORMLM_TOKEN`) |
591
+ | `403` | Command not on the exec whitelist, or wrong credentials/verification code | See the whitelist below; for MCP check `auth_status` |
592
+ | `408` | Request timed out client-side | Retry read-only; for `smart execute` re-run that module (writes are not auto-retried) |
593
+ | `429` | Rate limited (login attempts, send-code quotas) | Wait, then retry with backoff |
594
+ | `500` | Transport failure or server error | Retried automatically for read-only commands |
595
+
596
+ ### Raw `POST /api/v1/mcp/exec` whitelist
597
+
598
+ The exec channel accepts 3-token command paths only (`assess <module> <action>`). Everything else returns
599
+ `403 not allowed via MCP` **by design** — notably `assess snapshot` and `assess field …` do not exist on the
600
+ server (they are client-side wrappers), so batch HTTP consumers must call the underlying queries:
601
+
602
+ ```
603
+ assess app list | create | use | current | update | remove | urls
604
+ assess form query | find | types | config | add | update | remove | move | set-property
605
+ assess scale query | find | add | update | set | remove | clear | config | keys | data
606
+ assess connect query | find | types | config | cover-page | final-page | main-page | style
607
+ assess report query | find | update | page | widget (conditional logic is `report widget logic …`)
608
+ assess expert query | find | config | set | avatar | remove | chat
609
+ assess share set | query | url | api | flavor
610
+ assess smart plan | execute
611
+ assess skill form | scale | connect | report | expert | share
612
+ ```
613
+
614
+ ### Throughput notes
615
+
616
+ - Every CLI invocation is a fresh Node process plus its own HTTP calls; for large batches, run independent
617
+ apps concurrently (the server tolerates moderate parallelism) rather than serially.
618
+ - `snapshot`/`doctor` fan out their module queries in parallel; use `--module` / `--summary` to keep payloads small.
619
+ - Slow server? Raise `FORMLM_TIMEOUT_MS` and `FORMLM_RETRIES` instead of hand-rolling retry loops.
620
+ - Batch over many apps **inside one process**: `snapshot --apps …` / `doctor --apps …`, or import the built
621
+ module directly (`import { execCommand } from '@formlm/cli/dist/exec.js'`) and loop — HTTP connections are
622
+ reused and there is no per-app Node cold start.
623
+
624
+ ### Version coupling (CLI ↔ server)
625
+
626
+ Some commands rely on server options added together with them; against an older server they fail with a
627
+ visible `400 Unknown option …` (never a silent success, thanks to the false-success guard):
628
+
629
+ | Needs server support | Command / flag |
630
+ |---|---|
631
+ | ✔ | `app list --all / --limit / --page / --with-urls` |
632
+ | ✔ | `app urls` native `shareToken` + `published/shareType/…` (the CLI fills `shareToken` from `shareUrl` as a fallback) |
633
+ | ✔ | `report page remove --name "…"` (name→id resolution moved server-side, so raw exec benefits too) |
634
+ | ✔ | `expert config --enable true\|false` (fall back to `expert set --property enable` on an old server) |
635
+ | ✔ | `smart plan --dimensions / --app-name`, `smart execute --plan-file` (`--plan-b64` transport) |
375
636
 
376
637
  ---
377
638
 
@@ -388,7 +649,7 @@ FormLM CLI works as a standard MCP Server over stdio and plugs into **any MCP-co
388
649
 
389
650
  Have questions, feedback, or need help getting started?
390
651
 
391
- 📧 **[formlm.me@gmail.com](mailto:formlm.me@gmail.com)**
652
+ 📧 **[hello@formlm.me](mailto:hello@formlm.me)**
392
653
 
393
654
  Feel free to reach out — we're happy to help.
394
655
 
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/commands/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CA8ExD"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/commands/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAwHxD"}