@fui-org/fui-cli 2.1.4 → 2.2.0
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 +27 -7
- package/dist/fui-qrb1j9jz.js +397 -0
- package/dist/fui.js +1 -1
- package/package.json +1 -1
- package/skills/fui/SKILL.md +143 -38
- package/skills/fui/agents/fui-builder.md +62 -0
- package/skills/fui/agents/fui-tester.md +77 -0
- package/skills/{fui-skill → fui}/assets/projectdefaultstyle.css +489 -489
- package/skills/{fui-skill → fui}/examples/component.vue +162 -162
- package/skills/{fui-skill → fui}/references/INDEX.md +5 -4
- package/skills/{fui-skill → fui}/references/advanced-techniques.md +170 -168
- package/skills/{fui-skill → fui}/references/component-design.md +2 -2
- package/skills/{fui-skill → fui}/references/component-quickref.md +78 -78
- package/skills/{fui-skill → fui}/references/component-table.md +287 -287
- package/skills/{fui-skill → fui}/references/components-dialog.md +191 -191
- package/skills/{fui-skill → fui}/references/components-display.md +141 -141
- package/skills/{fui-skill → fui}/references/components-echart.md +316 -316
- package/skills/{fui-skill → fui}/references/components-input.md +335 -335
- package/skills/{fui-skill → fui}/references/controls-patterns.md +2 -2
- package/skills/{fui-skill → fui}/references/controls-styling-vocabulary.md +173 -173
- package/skills/{fui-skill → fui}/references/db-workflow.md +9 -9
- package/skills/{fui-skill → fui}/references/default-function.md +456 -456
- package/skills/{fui-skill → fui}/references/design-modes.md +57 -57
- package/skills/{fui-skill → fui}/references/echart-templates.md +489 -489
- package/skills/{fui-skill → fui}/references/fastproject.md +99 -99
- package/skills/{fui-skill → fui}/references/fullstack-workflow.md +314 -313
- package/skills/{fui-skill → fui}/references/module-data-patterns.md +117 -117
- package/skills/{fui-skill → fui}/references/module-json-anatomy.md +132 -132
- package/skills/{fui-skill → fui}/references/module-structure.md +144 -144
- package/skills/{fui-skill → fui}/references/new-session.md +1 -2
- package/skills/{fui-skill → fui}/references/pdfmake.md +60 -60
- package/skills/{fui-skill → fui}/references/permission-system.md +1 -1
- package/skills/{fui-skill → fui}/references/platform-architecture.md +269 -269
- package/skills/{fui-skill → fui}/references/project-config.md +303 -303
- package/skills/{fui-skill → fui}/references/project-provisioning.md +4 -4
- package/skills/{fui-skill → fui}/references/script-map.md +262 -262
- package/skills/{fui-skill → fui}/references/sql-clr-functions.md +225 -225
- package/skills/{fui-skill → fui}/references/system-design.md +2 -2
- package/skills/{fui-skill → fui}/references/tapi-permission-patterns.md +156 -156
- package/skills/{fui-skill → fui}/references/tapi-reference.md +474 -474
- package/skills/fui/references/team-run.md +141 -0
- package/skills/fui/references/tools-registry.md +211 -0
- package/skills/{fui-skill → fui}/references/ui-crosswindow-patterns.md +321 -321
- package/skills/{fui-skill → fui}/references/ui-dialog-patterns.md +255 -255
- package/skills/{fui-skill → fui}/references/ui-layout-patterns.md +176 -176
- package/skills/{fui-skill → fui}/references/ui-patterns.md +303 -303
- package/skills/{fui-skill → fui}/references/ui-screenshot-review.md +95 -95
- package/skills/{fui-skill → fui}/references/ui-table-cell-patterns.md +318 -318
- package/skills/{fui-skill → fui}/references/verification.md +11 -11
- package/skills/{fui-skill → fui}/references/watcher-patterns.md +163 -163
- package/skills/{fui-skill → fui}/references/websocket-realtime.md +271 -271
- package/skills/{fui-skill → fui}/scripts/component-3.0.js +2715 -2715
- package/skills/{fui-skill → fui}/scripts/component.js +3147 -3147
- package/skills/{fui-skill → fui}/scripts/componentTable-3.0.js +1038 -1038
- package/skills/{fui-skill → fui}/scripts/componentTable.js +891 -891
- package/skills/{fui-skill → fui}/scripts/defaultfunction-3.0.js +866 -866
- package/skills/{fui-skill → fui}/scripts/defaultfunction.js +1051 -1051
- package/skills/{fui-skill → fui}/scripts/fastproject-3.0.js +870 -870
- package/skills/{fui-skill → fui}/scripts/fastproject.js +828 -828
- package/dist/fui-h4z7zhk2.js +0 -381
- package/skills/fui-skill/SKILL.md +0 -139
- package/skills/fui-skill/references/tools-registry.md +0 -84
- /package/skills/{fui-skill → fui}/assets/projectdefaultstyle-3.0.css +0 -0
- /package/skills/{fui-skill → fui}/design-md/airbnb/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/airbnb/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/airtable/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/airtable/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/apple/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/apple/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/asu/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/asu/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/binance/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/binance/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw-m/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bmw-m/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bugatti/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/bugatti/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cal/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cal/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/claude/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/claude/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clay/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clay/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clickhouse/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/clickhouse/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cohere/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cohere/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/coinbase/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/coinbase/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/composio/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/composio/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cursor/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/cursor/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/elevenlabs/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/elevenlabs/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/expo/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/expo/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ferrari/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ferrari/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/figma/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/figma/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/framer/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/framer/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/fui/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/hashicorp/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/hashicorp/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ibm/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ibm/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/intercom/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/intercom/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/kraken/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/kraken/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lamborghini/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lamborghini/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/linear.app/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/linear.app/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lovable/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/lovable/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mastercard/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mastercard/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/meta/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/meta/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/minimax/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/minimax/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mintlify/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mintlify/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/miro/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/miro/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mistral.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mistral.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mongodb/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/mongodb/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nike/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nike/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/notion/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/notion/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nvidia/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/nvidia/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ollama/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/ollama/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/opencode.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/opencode.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/pinterest/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/pinterest/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/playstation/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/playstation/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/posthog/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/posthog/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/raycast/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/raycast/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/renault/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/renault/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/replicate/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/replicate/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/resend/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/resend/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/revolut/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/revolut/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/runwayml/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/runwayml/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sanity/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sanity/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sentry/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/sentry/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/shopify/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/shopify/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/slack/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spacex/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spacex/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spotify/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/spotify/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/starbucks/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/starbucks/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/stripe/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/stripe/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/supabase/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/supabase/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/superhuman/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/superhuman/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/tesla/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/tesla/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/theverge/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/theverge/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/together.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/together.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/uber/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/uber/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vercel/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vercel/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vodafone/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/vodafone/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/voltagent/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/voltagent/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/warp/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/warp/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/webflow/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/webflow/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wired/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wired/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wise/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/wise/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/x.ai/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/x.ai/README.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/zapier/DESIGN.md +0 -0
- /package/skills/{fui-skill → fui}/design-md/zapier/README.md +0 -0
- /package/skills/{fui-skill → fui}/examples/f-table-patterns.json +0 -0
- /package/skills/{fui-skill → fui}/examples/module-patterns.json +0 -0
- /package/skills/{fui-skill → fui}/examples/project-patterns.json +0 -0
- /package/skills/{fui-skill → fui}/references/coding-standards.md +0 -0
- /package/skills/{fui-skill → fui}/references/db-table-design.md +0 -0
- /package/skills/{fui-skill → fui}/references/fsheet.md +0 -0
- /package/skills/{fui-skill → fui}/references/tapi-file-api.md +0 -0
- /package/skills/{fui-skill → fui}/references/ui-templates.md +0 -0
- /package/skills/{fui-skill → fui}/scripts/fechart.js +0 -0
- /package/skills/{fui-skill → fui}/scripts/fsheet.js +0 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Team run — plan, build, test, fix, then one approval
|
|
2
|
+
|
|
3
|
+
The `fui` skill sends you here when a request is big enough for a team (see its "Choose how to work"). The user wants to stop supervising every step, testing by hand and describing bugs back to you. In a team run they answer your questions **once at the start** and approve the release **once at the end**. Everything between is yours: a builder builds, a tester who has not seen the builder's reasoning checks the result, and the builder fixes what the tester found.
|
|
4
|
+
|
|
5
|
+
You are the **planner**. You do not write the module or the stored procedures yourself, even when it looks quicker: your judgment is what decides whether the work is done, and it stays independent only if the work is not yours.
|
|
6
|
+
|
|
7
|
+
## Before the first run
|
|
8
|
+
|
|
9
|
+
- The two sub-agents are `fui-builder` and `fui-tester`; fui installs them for Claude Code with its skill, and a session started before that does not see them. If your agent list does not have them, do not stop: follow "Without sub-agents" at the end, and say in the review packet that a new session gives the next run an independent tester.
|
|
10
|
+
- The rules of the `fui` skill apply to you and to both agents. If you have not read `references/INDEX.md` this session, run `fui skill ref references/INDEX.md` first.
|
|
11
|
+
- One module per run, with the stored procedures it calls. For a system of several modules, plan the modules with [system-design.md](system-design.md), then run them one at a time.
|
|
12
|
+
- Use the `fui` CLI only. If FUI MCP tools are also connected to this session, do not call them: the approval rules cover `fui` commands, not MCP tools.
|
|
13
|
+
|
|
14
|
+
## The run
|
|
15
|
+
|
|
16
|
+
Pick a run id `YYYYMMDD-HHMM-<short-name>` and keep everything about the run in `{workspace}/_team/<runId>/`.
|
|
17
|
+
|
|
18
|
+
### 1. Plan
|
|
19
|
+
|
|
20
|
+
1. Read what exists: `fui module get` (it overwrites local files, so do it now, before anyone edits), `fui module outline`, `fui schema --search`, `fui sp get` for procedures the task touches, and one or two similar modules of the project for its conventions.
|
|
21
|
+
2. Collect everything only the user can decide and **ask it in one message**: what the feature must do where the request is ambiguous; plain `module.json` or a `uc-*.vue` component (approach A or B in [fullstack-workflow.md](fullstack-workflow.md) §Step 1b); App-mode or Web-mode when unclear; which connection (`--db`) when the project has several. Propose an answer to each so the user can reply "ok".
|
|
22
|
+
3. A new module needs its record first: `fui module new`, then `fui module get`. This asks the user for approval; it is part of the start.
|
|
23
|
+
4. Write `_team/<runId>/plan.md` from the template below. The acceptance criteria are the heart of it: the tester checks them and nothing else, so each must be something a command or a screenshot can show to be true or false.
|
|
24
|
+
|
|
25
|
+
### 2. Build
|
|
26
|
+
|
|
27
|
+
Start `fui-builder` with: the path of `plan.md`, the project and module ids, and the connection. Nothing more; the plan must stand on its own.
|
|
28
|
+
|
|
29
|
+
Wait until it has finished before doing anything else. Run it in the foreground when the Agent tool lets you choose; otherwise wait for its completion notice. Its last message is a hand-off: files changed, what it checked and how, open doubts, and any question it could not answer from the plan. Answer a question yourself when the plan or the user's answers settle it; otherwise ask the user, then continue the same builder.
|
|
30
|
+
|
|
31
|
+
### 3. Test
|
|
32
|
+
|
|
33
|
+
1. Before the tester starts, record the state of the work: `fui file status`, and a listing with sizes and modification times of the module folder and of the `.sql` files the plan names.
|
|
34
|
+
2. Start a **new** `fui-tester` with only the path of `plan.md`, the ids and the connection. Do not pass the builder's hand-off, its mocks or your own opinion of the work: a tester told what to expect finds less.
|
|
35
|
+
3. When it has finished, read `_team/<runId>/test-<round>.md`, then record the same state again. A module or `.sql` file that changed during the test means the tester edited the work: tell the user, and do not trust that round.
|
|
36
|
+
|
|
37
|
+
### 4. Fix
|
|
38
|
+
|
|
39
|
+
If the report lists defects, send the same builder (by its id or name, so it keeps its context) the path of the report and ask it to fix every defect and say what it changed for each. A continued agent runs in the background: wait for its completion notice. Then go back to step 3 with a new tester.
|
|
40
|
+
|
|
41
|
+
Stop the loop when the tester reports no defect, after **three** fix rounds, or when the same criterion fails twice with no visible change. In the last two cases the run has not succeeded: go to step 5 and say so.
|
|
42
|
+
|
|
43
|
+
A builder that keeps failing the same way usually means the plan is wrong, not the code. Re-read the criterion before sending it back a third time.
|
|
44
|
+
|
|
45
|
+
### 5. Review packet
|
|
46
|
+
|
|
47
|
+
Write `_team/<runId>/release.md` and show it to the user:
|
|
48
|
+
|
|
49
|
+
- each acceptance criterion: passed or failed, with the evidence the tester gave (command, report line, screenshot path);
|
|
50
|
+
- files changed and still unpublished (`fui file status`), and what the server will receive (`fui module preview`: its change list, including any `deleted component` line, and its approval token);
|
|
51
|
+
- tables or columns to create, procedures to deploy, with the connection;
|
|
52
|
+
- warnings the tester left open, in its words;
|
|
53
|
+
- the release command (next section).
|
|
54
|
+
|
|
55
|
+
Report a failed run as failed. A packet that hides an open defect costs the user more than the defect.
|
|
56
|
+
|
|
57
|
+
### 6. Release
|
|
58
|
+
|
|
59
|
+
After the user has read the packet, run the release as **one** command, steps joined with `&&` so it stops at the first failure, in this order:
|
|
60
|
+
|
|
61
|
+
1. table changes (`fui exec -f <file> --db <connection>`), only those the plan lists;
|
|
62
|
+
2. `fui sp deploy <name> --db <connection>` for each procedure;
|
|
63
|
+
3. project-level files the module depends on (`fui component new|update <name> -p <project>` with no `-m`, `fui project publish-config`);
|
|
64
|
+
4. the module: `fui module publish html --approval <token>` when header, body or title changed, otherwise `fui file push <changed files...>`.
|
|
65
|
+
|
|
66
|
+
Show the packet and this command in one message and ask the user to approve it. That is the one approval of the run: run the command only after a clear yes, and do not ask again step by step. Builder and tester cannot run any of these commands; you are the only one who releases.
|
|
67
|
+
|
|
68
|
+
Then report what each step printed. If a step failed, say which, what ran before it, and what is now on the server. A deploy that fails on a SQL error is a defect: send it to the builder (step 4), and release again with only the steps that did not run.
|
|
69
|
+
|
|
70
|
+
Finish with `fui file status`: nothing of this module should be left unpublished.
|
|
71
|
+
|
|
72
|
+
## Rules that keep the run honest
|
|
73
|
+
|
|
74
|
+
- **Nothing reaches the server before the release.** No publish, deploy, `fui exec`, `--confirm-write` or delete during plan, build, test or fix. The agents are blocked from these, and you run them only with the user's yes.
|
|
75
|
+
- **One exception, asked for separately.** A module cannot be rendered while a project-level `uc-*.vue` or `project.json` differs from the server (`--render` hard-blocks). If the task changes one, the builder checks it alone with `fui component preview`, then you ask the user to approve publishing just that file so the module can be rendered. Say this in the plan so the user expects it.
|
|
76
|
+
- **Stored procedures are never run to test them.** The builder and the tester read the body and reason about it (`fui sp verify`); the UI is tested on mock data shaped by that body. A SQL syntax error therefore first shows at deploy. Tell the user this limit in the packet when the run adds or changes procedures.
|
|
77
|
+
- **Never sync in the middle.** `fui module get`, `fui project sync` and `fui schema pull` replace local files with the server copy. After step 1 nobody runs them until the release is done.
|
|
78
|
+
- **Agents work one at a time.** Never start the tester while the builder is running, and never two builders on one module.
|
|
79
|
+
|
|
80
|
+
## plan.md
|
|
81
|
+
|
|
82
|
+
```markdown
|
|
83
|
+
# <run id>: <one line goal>
|
|
84
|
+
|
|
85
|
+
Project / module: <projectId> / <moduleId> (new or existing)
|
|
86
|
+
Connection: <project/connectionName>, apiName <apiName>
|
|
87
|
+
Approach: A (module.json) or B (uc-*.vue): <why>
|
|
88
|
+
Design mode: App or Web
|
|
89
|
+
|
|
90
|
+
## What the user asked
|
|
91
|
+
|
|
92
|
+
<the request in their words, then the answers they gave to your questions>
|
|
93
|
+
|
|
94
|
+
## Scope
|
|
95
|
+
|
|
96
|
+
In: <screens, actions, procedures, tables>
|
|
97
|
+
Out: <what this run must not touch>
|
|
98
|
+
|
|
99
|
+
## Data contract
|
|
100
|
+
|
|
101
|
+
For each API the module calls:
|
|
102
|
+
|
|
103
|
+
- spAPI_<Name> (new | changed | existing): params <@a type, ...> → columns <A, B, ...>; errors <when it must RAISERROR>
|
|
104
|
+
|
|
105
|
+
## Acceptance criteria
|
|
106
|
+
|
|
107
|
+
- AC1 <observable fact>. Check: <assert on vueData | what the screenshot must show | what the procedure body must contain>
|
|
108
|
+
- AC2 ...
|
|
109
|
+
|
|
110
|
+
## Needs the user during the run
|
|
111
|
+
|
|
112
|
+
<"nothing", or the project-level file that must be published before rendering>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Write criteria about behavior and data, not about wording in `module.json`: "after Save with an empty name the dialog stays open and shows the server message" can be checked; "uses f-table" cannot fail usefully. Cover the empty list, the server error and the permission-limited user wherever the feature has them.
|
|
116
|
+
|
|
117
|
+
## release.md
|
|
118
|
+
|
|
119
|
+
```markdown
|
|
120
|
+
# <run id>: <passed | NOT passed>
|
|
121
|
+
|
|
122
|
+
| Criterion | Result | Evidence |
|
|
123
|
+
| --------- | ------ | -------------------------- |
|
|
124
|
+
| AC1 ... | pass | test-2.md, render-full.png |
|
|
125
|
+
|
|
126
|
+
Fix rounds: <n>
|
|
127
|
+
Open defects and warnings: <none, or the list>
|
|
128
|
+
Not verified: <e.g. SQL syntax of new procedures, seen only at deploy>
|
|
129
|
+
|
|
130
|
+
## What will change on the server
|
|
131
|
+
|
|
132
|
+
<module files, components created/updated/deleted, procedures, tables>
|
|
133
|
+
|
|
134
|
+
## Release command
|
|
135
|
+
|
|
136
|
+
<the single command>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Without sub-agents
|
|
140
|
+
|
|
141
|
+
On an agent that cannot start sub-agents, or when `fui-builder` and `fui-tester` are not installed, do the same steps yourself, in the same order, with the same files. For step 3, close the build first: write the hand-off, then re-read `plan.md` and test from the criteria as if someone else had built it, writing your own mocks from `fui sp verify`.
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# fui commands — safety registry
|
|
2
|
+
|
|
3
|
+
> Owns: **risk class of every command, "which command for which file" publish rules, what users say → command, DB guards enforced in code, the error-log loop**. DB/SP procedure: [db-workflow.md](db-workflow.md); definition of done: [verification.md](verification.md). Flags: `fui <command> --help` (`fui <group> --help` lists a group, e.g. `fui right --help`).
|
|
4
|
+
|
|
5
|
+
Two axes per command:
|
|
6
|
+
|
|
7
|
+
- `R` reads only (touches no byte on disk) / `M` writes the server **or the local workspace**. A command that "only fetches" still **overwrites local files**, which is how unpublished edits get lost; the old copy goes to `_history/` first.
|
|
8
|
+
- ✅ Safe: run freely · ⚠️ Confirm: summarize for the user and wait for OK · 🔴 Destructive: full summary, then an explicit yes.
|
|
9
|
+
|
|
10
|
+
**Default:** a command is mutating and needs confirmation unless this file marks it `R` / ✅. **Per call:** judge the actual input; the same command can be safe or not.
|
|
11
|
+
|
|
12
|
+
**Strict mode (`FUI_STRICT=1`)**, for runs nobody reviews step by step: `module publish json|html|script|css`, `component new|update`, `project publish-config` and `sp deploy` are **blocked** until the skill was loaded this session (`fui skill get` / `fui skill ref`), and validator **errors block** publishing module.json. Without it both are warnings.
|
|
13
|
+
|
|
14
|
+
## Sync before reading
|
|
15
|
+
|
|
16
|
+
Every file fetched from the server (`module.json`, `header.html`, `body.html`, `script.js`, `_moduleInfo.json`, `uc-*.vue`, `project.json`, `_db/{connectionName}/*.sql`…) is a copy from the last checkout; someone may have changed the server since.
|
|
17
|
+
|
|
18
|
+
**Older than 48 hours → refresh before reading or editing**, so you never review a stale copy or publish over newer work. `module validate`, `outline`, `simulate`, `preview`, `schema` and `sp verify` print `warning: ... last synced N days ago ... run: <command>`: run that command first.
|
|
19
|
+
|
|
20
|
+
Each refresh rewrites **every** file in its scope, never one file:
|
|
21
|
+
|
|
22
|
+
| Files | Refreshed by |
|
|
23
|
+
| --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
|
|
24
|
+
| `module.json`, `header.html`, `body.html`, `script.js`, `_moduleInfo.json`, module-scope `uc-*.vue`, import contents (both scopes) | `fui module get` |
|
|
25
|
+
| project-scope `uc-*.vue` (`{projectId}/components/`) | `fui component get`, or `fui project sync` for all |
|
|
26
|
+
| `project.json`, `_projectInfo.json`, `_modules.json`, `imports/*` (contents too) | `fui project sync` |
|
|
27
|
+
| `_db/{connectionName}/schema.json` and all its `*.sql`, **one connection per call** | `fui schema pull` |
|
|
28
|
+
| one SP | `fui sp get` |
|
|
29
|
+
|
|
30
|
+
**It always overwrites and never asks.** What protects local edits is `{workspace}/_history/`: each file about to be overwritten or deleted is copied there first, same path shape, timestamp in the name:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
_history/{projectId}/modules/{moduleId}/module_20260801_143022.json
|
|
34
|
+
_history/{projectId}/_db/{connectionName}/spAPI_X_20260801_143022.sql
|
|
35
|
+
_history/{projectId}/components/uc-abc_20260801_143022_deleted.vue ← deleted, not overwritten
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`archived N local file(s) that differed from the server` is a notice, not a question. Bring a copy back with `fui file restore <path>` (`fui file history <path>` lists versions), then publish or deploy as usual. `_history` is never cleaned up automatically.
|
|
39
|
+
|
|
40
|
+
## What users say → command
|
|
41
|
+
|
|
42
|
+
Users name commands loosely, often in Vietnamese.
|
|
43
|
+
|
|
44
|
+
| User says | Command |
|
|
45
|
+
| ------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- |
|
|
46
|
+
| "which module is active" / "đang làm module gì" | `fui use` |
|
|
47
|
+
| "switch module" / "chọn module", a pasted module URL or `/project/module` route, or just a module name | `fui use <target>` |
|
|
48
|
+
| "list projects" / "danh sách project" | `fui project list` |
|
|
49
|
+
| "new project from scratch" / "tạo dự án mới", "tạo DB + project FUI mới" | [project-provisioning.md](project-provisioning.md), 6 steps; do not start with `fui project new` |
|
|
50
|
+
| "new database", "register an alias" / "đăng ký alias", "thêm DB vào tAPI" | `fui db alias new` |
|
|
51
|
+
| "let someone edit this project" / "cấp quyền admin project", "thêm người vào project" | `fui user search` → `fui user add` |
|
|
52
|
+
| "who can edit this project" / "ai được sửa project này" | `fui user list` |
|
|
53
|
+
| "update project.json", "edit the project menu" / "sửa menu project" | edit `{projectId}/project.json`, then `fui project publish-config` |
|
|
54
|
+
| "connect the DB but I only know the alias" / "không có dbToken" | `fui db alias list` → `fui db add-by-name` |
|
|
55
|
+
| "sync / refresh the project" / "đồng bộ project", "lấy project.json" | `fui project sync` |
|
|
56
|
+
| "get / pull / clone / refresh the module" / "lấy module về", "pull mới nhất" | `fui module get` |
|
|
57
|
+
| "new module" / "tạo module mới" | `fui module new` |
|
|
58
|
+
| "rename the module", "change its ID / framework" / "đổi tên module" | `fui module update` |
|
|
59
|
+
| "delete the module" / "xóa module" | `fui module delete` |
|
|
60
|
+
| "preview", "diff before upload" / "xem trước", "kiểm tra trước khi up" | `fui module preview` |
|
|
61
|
+
| "validate" / "kiểm tra module.json" | `fui module validate` |
|
|
62
|
+
| "review the layout", "outline" / "review giao diện", "xem layout" | `fui module outline` |
|
|
63
|
+
| "simulate", "test the flow" / "mô phỏng", "chạy thử action" | `fui module simulate` |
|
|
64
|
+
| "render the UI", "screenshot", "check on mobile" / "render giao diện", "xem trên mobile" | `fui module simulate --render` |
|
|
65
|
+
| "push module.json" / "cập nhật module.json" | `fui module publish json` |
|
|
66
|
+
| "push header / body / html" / "up header", "up body", "đẩy lên" | `fui module preview` → `fui module publish html` |
|
|
67
|
+
| "push script" / "up script", "cập nhật script" | `fui module publish script` |
|
|
68
|
+
| "push style / CSS" / "up style", "cập nhật CSS module" | `fui module publish css` |
|
|
69
|
+
| "test the component alone" / "thử component", "component trên mobile" | `fui component preview` |
|
|
70
|
+
| "new component" / "tạo component" | `fui component new` |
|
|
71
|
+
| "push the component" / "up component", "sửa component" | `fui component update` |
|
|
72
|
+
| "sync components" / "sync component" | `fui component list` |
|
|
73
|
+
| "list / sync import files" / "danh sách import file" | `fui import list` |
|
|
74
|
+
| "new SP", "deploy the SP" / "tạo SP mới", "cập nhật SP" | `fui sp save` → `fui sp deploy` |
|
|
75
|
+
| "add a function right" / "thêm quyền chức năng", "tạo FunctionRight" | `fui right function new` |
|
|
76
|
+
| "save the user token" / "lưu user token", "token để gọi API" | `fui db user-token` |
|
|
77
|
+
| "DB password changed" / "đổi password DB", "rebuild dbToken" | `fui db token-rebuild` |
|
|
78
|
+
| "which DBs does this project use" / "project này đang nối những DB nào" | `fui db list` |
|
|
79
|
+
| "connect one more database" / "nối thêm một database nữa" | `fui db add` again with the new apiName |
|
|
80
|
+
| **"sync the db", "refresh schema"** / **"đồng bộ db", "cập nhật schema", "làm mới schema"** | `fui schema pull`, **never `fui project sync`**. No connection yet → ask for the connection details; do not run something else instead |
|
|
81
|
+
| "list designs" / "có style nào" · "use style X" / "dùng style X" | `fui design list` · `fui design read <brand>` |
|
|
82
|
+
|
|
83
|
+
## Commands
|
|
84
|
+
|
|
85
|
+
### Session, project, users
|
|
86
|
+
|
|
87
|
+
| Command | R/M | Risk | Notes |
|
|
88
|
+
| ----------------------------------------- | --- | ---- | ----- |
|
|
89
|
+
| `use`, `resolve`, `file where` | R | ✅ | read the target and how it resolved |
|
|
90
|
+
| `use <target>`, `use --clear` | M | ✅ | session target only; no data changes |
|
|
91
|
+
| `project list` | R | ✅ | |
|
|
92
|
+
| `project sync` | M | ✅ | refreshes every project-level file and import content; removes local `.vue`/import files that were tracked and are gone on the server (unpublished new ones are kept) |
|
|
93
|
+
| `project new` | M | ⚠️ | needs `SystemRight >= 3` on `fp`; the server reads **6 fields only** (`ProjectID`, `ProjectName`, `GroupName`, `Framework`, `pDomain`, `Router`). `title`/`login`/`apiDomain`/`menu` are ignored silently: runtime config goes through `project publish-config`. Full procedure: [project-provisioning.md](project-provisioning.md) |
|
|
94
|
+
| `project update` | M | ⚠️ | edits an existing project; `projectData.id` is required (without it the server would create) |
|
|
95
|
+
| `project publish-config` | M | ⚠️ | pushes the local **file** `{projectId}/project.json`; edit the file first. A JSON syntax error is a hard stop (pushing `{}` would wipe menu and settings). Skips when unchanged |
|
|
96
|
+
| `user search`, `user list` | R | ✅ | `user search` is the only source of the exact `UserID`: show its rows and let the user pick. `user list` = who may edit the project in the FUI IDE (`UserRight` 1/2/3), **not** the `acc` `SystemRight` ([permission-system.md](permission-system.md)) |
|
|
97
|
+
| `user add`, `user set` | M | ⚠️ | `add` only for a user with no right, `set` only for one who has it; each hard-errors in the other case. Levels: 1 view · 2 develop · 3 admin |
|
|
98
|
+
| `user remove` | M | 🔴 | revokes the right; summarize and wait for a yes |
|
|
99
|
+
|
|
100
|
+
### Modules
|
|
101
|
+
|
|
102
|
+
| Command | R/M | Risk | Notes |
|
|
103
|
+
| ------------------------------------------------------- | --- | ---- | ----- |
|
|
104
|
+
| `module list` | R | ✅ | also refreshes the local module cache (`_modules.json`) |
|
|
105
|
+
| `module get` | M | ✅ | rewrites the whole module locally and sets the target; differing local files go to `_history/`; `.vue`/import files the server dropped are removed (`_deleted` copy kept) |
|
|
106
|
+
| `module get-ui`, `module get-html` | M | ✅ | overwrite local `module.json` / `body.html` when the module is checked out. Not read-only |
|
|
107
|
+
| `module new` | M | ⚠️ | creates an **empty** module on the server; confirm id and name first, then `fui module get`. An id already in `_modules.json` is a hard error |
|
|
108
|
+
| `module update` | M | ⚠️ | metadata of an existing module. Changing `ModuleID` changes its URL (old links break) and renames the local folder: warn the user |
|
|
109
|
+
| `module delete` | M | 🔴 | **permanent on the server, no history there**; archives the local folder and clears a matching session target |
|
|
110
|
+
| `module validate`, `module outline`, `module preview` | R | ✅ | `validate` does **not** read `script.js`: an `EXE`/`FUN` calling an unwritten function only shows in `--render` as `... is not defined` ([advanced-techniques.md](advanced-techniques.md) §2). `[design]` warnings must be fixed unless the user asked for that style |
|
|
111
|
+
| `module simulate`, `module check`, `component preview` | R | ✅ | write only `_preview/`, `_componentPreview/` and `_testdata/`; an unmocked read-only API may be called for real ([verification.md](verification.md)) |
|
|
112
|
+
| `module publish json` | M | ⚠️ | **only** module.json; no preview needed |
|
|
113
|
+
| `module publish script`, `module publish css` | M | ⚠️ | an **empty** file clears it on the server; a missing file is refused |
|
|
114
|
+
| `module publish html` | M | ⚠️ | header/body/title **and** module.json; needs the token from `module preview`, which covers the whole payload (any file edited after the preview voids it). Also pushes non-empty `script.js`/`style.css`, and **reconciles `components/*.vue` with the server: a server component with no local file is DELETED** (the preview lists it as `deleted component <name>`) |
|
|
115
|
+
|
|
116
|
+
### Components
|
|
117
|
+
|
|
118
|
+
| Command | R/M | Risk | Notes |
|
|
119
|
+
| ------------------- | --- | ---- | ----- |
|
|
120
|
+
| `component get` | M | ✅ | prints the source and overwrites the local `.vue` (old copy to `_history/`) |
|
|
121
|
+
| `component list` | M | ✅ | refreshes `_components.json`; removes tracked `.vue` files the server dropped |
|
|
122
|
+
| `component preview` | R | ✅ | one local `.vue` alone in a real browser; works before it is pushed ([component-design.md](component-design.md)) |
|
|
123
|
+
| `component new` | M | ⚠️ | first push. Refreshes `_components.json` from the server **first**; a name that exists is a hard error (a blind insert makes two records with one name) |
|
|
124
|
+
| `component update` | M | ⚠️ | later pushes; hard-errors when the component is not on the server, never creates. Sends `<style scoped>` as `ComCSS` |
|
|
125
|
+
| `component delete` | M | 🔴 | **permanent on the server**; archives the local `.vue` |
|
|
126
|
+
|
|
127
|
+
Scope, for every component command:
|
|
128
|
+
|
|
129
|
+
| Given | Scope |
|
|
130
|
+
| -------------------------------------------------- | --------------------------------- |
|
|
131
|
+
| `-p P -m M` | module `M` |
|
|
132
|
+
| `-p P` only | project (global, loaded everywhere) |
|
|
133
|
+
| nothing, inside a module folder or a module target | that module |
|
|
134
|
+
| nothing, inside a project folder only | project (global) |
|
|
135
|
+
|
|
136
|
+
### Imports
|
|
137
|
+
|
|
138
|
+
| Command | R/M | Risk | Notes |
|
|
139
|
+
| ----------------------------- | --- | ---- | ----- |
|
|
140
|
+
| `import list` | R | ✅ | with `-p` it also syncs local `_imports.json` (metadata only) and removes orphaned content files |
|
|
141
|
+
| `import get` | R | ✅ | prints one file and writes it to every local `imports/` that declares it |
|
|
142
|
+
| `import new`, `import update` | M | ⚠️ | sort below the scope floor is raised: project ≥ 20, module ≥ 50 (framework uses ~1–10). `update` edits metadata, not the source |
|
|
143
|
+
| `import upload` | M | ⚠️ | overwrites the source on the server and the local copies |
|
|
144
|
+
| `import delete` | M | 🔴 | **permanent**; cleans the local copies |
|
|
145
|
+
|
|
146
|
+
### Database and rights
|
|
147
|
+
|
|
148
|
+
| Command | R/M | Risk | Notes |
|
|
149
|
+
| ------------------------------------------ | --- | ---- | ----- |
|
|
150
|
+
| `db list`, `db test`, `token decode` | R | ✅ | never print secrets |
|
|
151
|
+
| `db alias list` | R | ✅ | databases your token may manage on `acc`; run it when an alias is unknown or `db add-by-name` finds nothing |
|
|
152
|
+
| `db add`, `db add-by-name` | M | ✅ | test, save, fetch the schema. `add-by-name` borrows a SQL login from a connection on the same `apiDomain`; "not found" means the alias does not exist **or** you may not manage it |
|
|
153
|
+
| `db user-token`, `db default`, `db migrate` | M | ✅ | local only |
|
|
154
|
+
| `db token-rebuild` | M | ⚠️ | overwrites the stored token; `--db` is required when the project has several connections |
|
|
155
|
+
| `db alias new` | M | ⚠️ | registers an existing database as a tAPI alias on `acc`; the login must be the **application** account (execute-only), never a `db_owner` dev login. Ask the user first |
|
|
156
|
+
| `schema`, `sp list`, `sp path`, `sp help`, `sp verify` | R | ✅ | `schema` reads one connection: a "missing" table usually means the wrong connection. `sp list` covers every connection unless `--db`. `sp help` also clears the tAPI cache for that function |
|
|
157
|
+
| `schema pull` | M | ✅ | rewrites `_db/{connectionName}/` of **one** connection, bodies included. Files of procedures dropped on the server are archived. Files in neither schema are only **listed** (maybe an undeployed draft): read that note and ask before `--prune-local-only` |
|
|
158
|
+
| `sp get` | M | ✅ | overwrites `_db/{connectionName}/{name}.sql` (old copy to `_history/`). Not read-only |
|
|
159
|
+
| `sp save` | M | ⚠️ | local only. There is no "create SP" command: a new SP is `sp save` → `sp deploy`; with several connections name `--db` on the first save |
|
|
160
|
+
| `sp rename` | M | ⚠️ | renames on the server and the local file; summarize first |
|
|
161
|
+
| `query` | R/M | ⚠️ | reads and, on the user's request, writes real data. Default cap 200 rows; `TOP 20` to look at structure; no `varbinary(max)`/large `nvarchar(max)` columns |
|
|
162
|
+
| `exec` | R/M | 🔴 | DDL/DML. A `CREATE`/`ALTER PROCEDURE` here gets **no auto-grant and no cache clear**; the output names the command to run next |
|
|
163
|
+
| `sp deploy`, `sp delete` | M | 🔴 | `deploy` saves the live definition to `_history/` (the rollback copy), fixes CREATE/ALTER, grants, clears the tAPI cache; summarize the SP and wait. `delete` is permanent |
|
|
164
|
+
| `right system list`, `right function list` | R | ✅ | read `acc` and refresh `{projectId}/_db/rights.json`; **until they ran once, validate/simulate/render cannot check right codes** |
|
|
165
|
+
| `right system new/update`, `right function new/update` | M | ⚠️ | create and edit are separate; `update` needs the id from `list` |
|
|
166
|
+
| `right system delete`, `right function delete` | M | 🔴 | `function delete` also removes every user assignment of that code |
|
|
167
|
+
|
|
168
|
+
Guarding with a right code that is not defined fails silently: `rightTest()` is always false, the control vanishes with no JS error, and **the preview still shows it** ([permission-system.md](permission-system.md)).
|
|
169
|
+
|
|
170
|
+
### Skill, workspace files, maintenance
|
|
171
|
+
|
|
172
|
+
| Command | R/M | Risk | Notes |
|
|
173
|
+
| --------------------------------------------------------------- | --- | ---- | ----- |
|
|
174
|
+
| `skill get`, `skill ref`, `design list`, `design read`, `library` | R | ✅ | `skill get` prints SKILL.md + the router; Tier A files come from `skill ref` |
|
|
175
|
+
| `remote module`, `remote project`, `remote diff` | R | ✅ | server copy, no local writes |
|
|
176
|
+
| `file status`, `file history`, `file ledger` | R | ✅ | `file ledger --mark` only records a file as published; it pushes nothing |
|
|
177
|
+
| `file restore` | M | ✅ | local only; the current file is archived first |
|
|
178
|
+
| `file push` | M | ⚠️ | routes each path to its publisher above; the same rules apply |
|
|
179
|
+
| `log read` | R | ✅ | failures grouped by command and error signature, most frequent first |
|
|
180
|
+
| `log clear` | M | ✅ | after the patterns were folded into the skill |
|
|
181
|
+
|
|
182
|
+
**Error-log loop.** Every failed command is appended to `{workspace}/_logs/tool-errors.jsonl`, except a block that only waits for `--confirm-write`. A group that keeps repeating in `fui log read` is a gap in these references: fix the reference, then `fui log clear`. The `guards that blocked by design` list at the end (DROP TABLE, data-losing ALTER TABLE, DELETE/UPDATE without WHERE) is not a gap.
|
|
183
|
+
|
|
184
|
+
## Publish: which command for which file
|
|
185
|
+
|
|
186
|
+
- Before publishing module.json: `fui module validate`, fix every error, then `fui module outline` (row widths, dialogs nobody opens, actions nobody calls). For complex runtime logic (action chains, watch cascades, dialog flows) also `fui module simulate` the main flow with asserts.
|
|
187
|
+
- Only `module.json` → `fui module publish json` (no preview needed).
|
|
188
|
+
- `header.html` / `body.html` / title (with or without module.json) → `fui module preview`, the user reads the diff and approves, then `fui module publish html --approval <token>`. It pushes module.json too. Never run it without the user's approval.
|
|
189
|
+
- `script.js` (also to clear it) → `fui module publish script`. `module publish json` does not push it.
|
|
190
|
+
- `style.css` (also to clear it) → `fui module publish css`.
|
|
191
|
+
- `uc-*.vue` → `fui component new <name>` the first time, `fui component update <name>` after. A **project-scope** component must be previewed and pushed **before** rendering a module that uses it: `--render` hard-blocks when the local file differs from the server.
|
|
192
|
+
- Several files changed → one command per file, in turn. `fui file push <path...>` routes each path to its publisher.
|
|
193
|
+
|
|
194
|
+
**Backstop, not a substitute.** Each module keeps a local ledger of content hashes from the last publish/sync. Forgot a file → `module validate` and the publish commands print `unpublished local files: ...`, and `fui file status` lists each with its command. It never blocks a publish. The same ledger skips duplicates: `module publish json|script|css` and `component update` print `skip <file> unchanged since the last publish/sync` and make no request. `module publish html` always pushes.
|
|
195
|
+
|
|
196
|
+
## Database rules (enforced in code)
|
|
197
|
+
|
|
198
|
+
- `query` / `exec`: say what the SQL does and what data it touches, and wait for the user. Writes (INSERT, UPDATE…SET, DELETE, MERGE, TRUNCATE, `SELECT … INTO` a real table, a write inside `EXEC('…')` or `sp_executesql`, `DROP PROCEDURE`/`FUNCTION`/`VIEW`, ALTER COLUMN) exit 3 until `--confirm-write`, added only after the user approved that exact write. It is a confirmation gate, not an obstacle to work around.
|
|
199
|
+
- Table DDL is judged by data loss, **per statement**: free `ALTER TABLE … ADD` and `DROP CONSTRAINT` · `--confirm-write` for `ALTER COLUMN` (narrowing numeric or date precision loses data silently) · always blocked `DROP TABLE`, `DROP DATABASE`, `DROP COLUMN`, `SWITCH`, `xp_cmdshell` and any action fui cannot parse. A blocked statement wins over a confirmable one. `DELETE`/`UPDATE` without `WHERE` is blocked too, in `query` and `exec` (a `MERGE` is scoped by its `ON`). A `--` or a quote inside a `[name]` or `"name"` does not hide the statements after it. Show blocked SQL for the user to run by hand; no flag unlocks it.
|
|
200
|
+
- Never call a live API SP or run sub-queries "to test" it: read its body (`fui sp get`) and reason, or `fui sp verify <name|Fn>`. `sp verify` calls no endpoint; its only network reads are metadata (`OBJECT_DEFINITION` when no local `.sql`, permissions with `--check-grant`). An unreadable body is a hard error: it never guesses from the name.
|
|
201
|
+
- `--mocks` for an SP that **exists** must be the snippet `fui sp verify` prints, never a guessed shape. On `🚨 UNVERIFIED MOCK SHAPE` stop, run `fui sp verify`, copy the snippet. Invented data is right only for an SP that does not exist yet.
|
|
202
|
+
- `fui sp deploy` asks the server whether the object exists, so `CREATE PROCEDURE` for an existing SP is fine: do not edit the file to `ALTER` and redeploy. tAPI parameters with a default value are hard-blocked.
|
|
203
|
+
- After an `ALTER PROCEDURE` through `exec`, run `fui sp help <name>` once to clear the tAPI cache, or tAPI keeps serving the old signature.
|
|
204
|
+
- Never write `GRANT` into the `.sql` file: tAPI sends one batch without `GO`, so it would become part of the procedure body. `sp deploy` grants new procedures and re-checks; on `lacks EXECUTE` run the printed command, **do not redeploy**.
|
|
205
|
+
- A project can use several databases. `fui db add` stores each in `{projectId}/_db/_connections.json` under a `connectionName` (its `_db/` folder); `apiName` is a separate field, only the route alias, and may repeat across zones. `--db` takes a connectionName (a unique apiName also works); when ambiguous, commands print a menu: pick a line, never guess. Project unclear → ask the user.
|
|
206
|
+
- Secrets only via stdin (`-`) or `--*-env VAR`; never print `_db/_connections.json`.
|
|
207
|
+
|
|
208
|
+
## Concurrency
|
|
209
|
+
|
|
210
|
+
- Read-only commands can run in parallel.
|
|
211
|
+
- Never in parallel: any 🔴 command, `module publish html` with anything else, two `sp deploy`.
|