This Skill helps an AI Agent develop AI GO Custom Apps. Supports Antigravity / Claude Code / Cursor.
Design Philosophy
AI GO Custom App adopts the TypeScript (frontend) + Python (backend) curated language combination, with features such as a low error rate, static type safety, and LLM generation optimization, making it most suitable for AI Coding beginners and non-technical workers to develop reliable internal company systems.
Data access uniformly goes through the API, without directly connecting to the database—avoiding non-technical AI Coders repeatedly creating similar tables or fields. AI GO has predefined database structures (default tables) common to small and medium-sized enterprises, while retaining the extension flexibility ofcustom tables.
See
references/custom-app-dev-guide.md§21 Architecture Design Philosophy. For terminology, first readCONTEXT.md—tables only havedefault tables/custom tablestwo major categories; "CustomObject / Data Reference / extended fields / app_domain" are mechanism terms, not a third category of tables. The six terms are easily confused, and confusing them leads to writing wrong code. (The "SaaS table" in older documents = default table, now deprecated)
Phase -1: Skill self-update (executed on every trigger; forced sync upon discovering a new version)
If the SessionStart hook is already installed (see README "Keeping Updated"), this phase is automatically skipped (throttled), and does not need to be executed repeatedly.
python scripts/check_update.py # macOS / Linux 用 python3
- Zero dependencies, no uv—implemented with the standard library, it can run directly under any project.
- The script acts on its own, without asking: as long as the remote
VERSIONis newer than the local one, the scriptdirectly forces all locally registered installations to sync to the remote main—git installationfetch+reset --hard+clean, copy-style installation (skills CLI) downloadsmain.zipmirror overwrite. Local modifications, diverged commits, and extra files are all replaced by the remote; it does not ask the user or wait for a reply. You also do not need to, andmust notmake the "whether to update" decision on behalf of the user. - No output = nothing to do: if it is already the latest version, offline, or the same version has already failed once within 3 hours, it ends silently and goes directly to Phase 0. (Throttling only suppresses network fetching and failure retries; version comparison is done every time, so multiple local installations share the remote cache, and if any one is behind, it will still be caught.)
- Output = it has already been synced (or the sync failed), handle it line by line:
- "Synced"→ immediately re-read
SKILL.mdand the relatedreferences/, so the new instructions take effect in this turn; informthe userof the version gap and change summary (inform, not ask—the update is already complete, there is no option to refuse). - "Failed"→ give the user the failure reason and the manual instructions printed by the script, and ask them to handle it before continuing.
If there is also a "breaking change" warning (
--jsonis"breaking": true): this type of version means staying on the old version will cause failures, and the failure messages usually do not point to the real cause(For example, the tenant URL rule in 1.7.0, whose symptom is a 401 that looks exactly the same as a wrong password) — explicitly tell the user "what will happen if you don't deal with it", and when encountering related errors laterfirst suspect a version mismatch, and don't dig deeper in other directions. - "Development copy, skip"→ that one is the workspace where the skill is being modified (the local version is higher than the remote, or git is not on the main/master branch), it's not an installation, no need to handle it or mention it.
- "Synced"→ immediately re-read
- The registry only recognizes installations that have run the 1.17.0+ check— if the user mentions that other projects also have this skill installed but weren't synced, remind them to trigger the skill in that project once; after that, that copy will be listed and synced along with the others next time.
- Bypassing is prohibited: do not skip this phase to preserve local modifications, switch to
--check-only, or suggest the user do so. To change the skill content, go through the repo's PR; the copy installed locally can only be a mirror of the remote main.
Source intent triage (read before entering the process)
Before any work begins, first distinguish which kind of intent the user has — the three tracks start completely differently.For those who want to build an app (the first two rows), first judge: has this project entered production(there are real users using it, or there is production data that cannot be lost) — not yet (brand new, or has code but isn't live) → first see whether Custom App can do it; already in production, with existing code to migrate → guide them to Hosted App; the criteria and exceptions are in references/product-line-decision.md §0, those building from scratch are considered not yet in production, if there's an existing system and you're unsure, ask the user, don't guess from the repo:
| Intent | Approach |
|---|---|
| Develop a new App(build new functionality from scratch) | Follow the main process (Phase 0 →),but before building the app you must first complete the requirements inventory in Phase 1.5 §1.0(the four questions + Custom App capability boundary check, symmetric with §2.0 of the migration track) — the user's opening sentence is the topic, not the requirement; the product line decision (Custom/Hosted/hybrid) and the authorization architecture (who can open it, what role to attach) are finalized in Phase 1.5 before building the app |
| Migrate an existing App(there is an existing system/repo/DB to migrate into AI GO) | First read references/migration-workflow.md, start from the stack inventory in §2.0(architect's perspective: first inventory the structure of frontend/backend/data, then triage the product line), and only then return to the main process; for those judged to go with a Hosted App, the main process follows references/hosted-migration-runbook.md(inventory → test → cutover → decommission) |
| Data operations, not app development(query, modify, batch, export data you have permission for) | Follow references/data-operations.md 's short process:aigo_auth.py status → aigo_data.py me → perm-check → route to look up that file's §4 → call/export. Does not enter Phase 0's VFS review, does not build an app, does not go through the proxy — use the logged-in user's own token and permissions.Before writing, you must pass that file's §3.5 write gate— this track hits the one and only production dataset, there is no sandbox and no restore path |
| Member/role management, not app development(batch invitations, create links, grant roles, change permissions, set app role whitelists) | Follow references/member-admin.md(§2 Endpoints, §4 Invitation flow, §5 Role CRUD): the logged-in user's own JWT; do not create an app, do not go through /open/*; writes likewise go through data-operations.md §3.5 gate (both invitations and role changes are irreversible formal data) |
Detection signals for data operation intent: the user wants to "look something up / change a batch / export / load data" without mentioning screens, features, or the app; or asks "do I have permission to view a certain table". The permissions on this line are the user's permissions on the platform interface: default tables follow module roles (sale.read , etc.), custom tables require builder.access— make it clear to the user first before acting; before writing, user confirmation is mandatory.
Detection signals for migration-in intent(if any appears, proactively confirm; do not wait for the user to say "migrate" themselves): the user mentions an existing system, an existing website, some repo, Supabase / Google Sheet / MySQL or other data sources, words like "move over", "transfer", "switch to AI GO"; or during Phase 0 you discover that the working directory is a complete project with a non-AI GO structure. Once judged as migration-in, if there are multiple systems (≥2), additionally layer on the global inventory of Phase 1.25.
Phase 0: Review existing code (★ mandatory step)
Before starting any development work, this step must be executed first.
Nine steps (★ for the full version and each step's endpoints and report contents → references/review-workflow.md)
uv run --project scripts python scripts/aigo_auth.py status # 1. 找工作區、定目標
# 2. get_token() 自動取 JWT——★ 不要向用戶要密碼、不代填、不放進指令列
# 3-5. review_app() 一次做完:取 VFS → 檔案清單與 [SDK]/[INJ] 標記 → 路由與頁面 → legacy 偵測
# → builder.access 破口偵測 → webhook 宣告 → Data Reference 盤點 → CSS 相容性
Three inventories that cannot be skipped(the cost of skipping any of them is only discovered afterwards, and requires redoing the work):
| What to inventory | Why | How to inventory |
|---|---|---|
| Tenant's existing custom tables(★ mandatory) | Custom tables aretenant-leveland not in the VFS — if two apps each create a "customer" table, the data splits into two copies | GET /data-center/tables; also scan naming along the way (^tbl(_\d+)?$ and other fallback names, rule 18.5),inventory only, do not touch |
| Existing schedules | republish or changing an action name will trigger schedules to auto-pause | GET /builder/apps/{app_id}/crons |
| Outbound calls and Egress | Old code running does not mean the new slug also works; those relying on platform-injected keys and raw httpx bothmust be changed |
Extract all ctx.http.call slugs and external domains in the actions |
- For Data Reference, always use
GET /api/v1/refs/apps/{app_id}; do not readsrc/db.json(measured to always be{}) - ⚠️ When the custom table list cannot be obtained, returnan empty list— an empty list does not mean "the tenant has no tables, so it is safe to create new ones"
- Step 9: Only after confirming you fully understand the existing structure may you proceed to development
Phase 1: Environment setup
Three hard rules (★ must not be violated; for full explanations see references/environment.md)
- All APIs must target the tenant space
https://[tenant].ai-go.app/*。apexhttps://ai-go.appcannot infer the tenant; ★ measured to return401 帳號或密碼錯誤——exactly the same shape as a genuinely wrong password, which will send you off in the wrong direction.*.apps.ai-go.appis the app runtime domain, not the API host - Credentials are filled in by the user themselves:
~/.aigo/.env(machine-level) or<工作區>/.aigo/.env(override). The agent must not fill in passwords on the user's behalf, must not print tokens, and must not write them into the repo - The workspace cannot be placed in the skill installation directory—An update rebuilds the entire folder, wiping credentials and the registry.
Shortest setup path
uv run --project scripts python scripts/aigo_auth.py setup # 建 ~/.aigo/.env 範本(用戶自己填)
uv run --project scripts python scripts/aigo_auth.py setup-workspace <目錄> # 建工作區 .aigo/config.json
uv run --project scripts python scripts/aigo_auth.py status # 確認實際生效的租戶空間與憑證
uv run --project scripts python scripts/aigo_auth.py login # 驗證憑證(不印 token)
uv run --project scripts python scripts/aigo_auth.py app add <alias> --id <uuid> # 登錄 app
- Three-layer model: device (one copy of the skill) → workspace (one directory per tenant,
base_urlinconfig.json) → app (the workspace'sappsregistry; if multiple apps exist and none is specified, it errors out listing the aliases and does not guess) - Create new apps via the API, no need to go through the UI:
POST /api/v1/builder/apps,name+template_slugis required; ★ access_mode is determined by the template and cannot be changed after creation, andapp creation only happens after the Phase 1.5 plan is confirmed (starter-internalis the default;starter-externalonly used when the assignment table explicitly says so) →custom-app-dev-guide.md§26 - Use only the two starters to scaffold, do not use a business template's slug to create an app: templates are raw material—
GET /templates/{slug}/previewfetch the full code, copy it back locally and adapt it; provision tables/references/external services yourself according to the effect-binding table (references/template-workflow.md) config.jsonfields,base_url's three-layer source and priority order, troubleshooting 401 on login →references/environment.md- For Hosted App using the
aigoCLI: first pass thehosted-apps.md§3.3 version gate (scripts/aigo_cli_check.py); for an existing app that only needs deployment → the user provides a Deploy Token; for creating a new app / session-only → the user does it themselvesaigo login --workspace(§3.1)
Phase 1.25: Multi-system migration inventory (conditionally triggered)
Trigger condition: the user has 2 or more external systems(each with its own Supabase / Google Sheet / MySQL etc. DB) to migrate into AI GO; if only 1 system is being migrated or it is a purely new App → skip and go straight to Phase 1.5 (for purely new, start from §1.0 requirements inventory). When triggered → read
references/migration-workflow.md§1: before starting Phase 1.5 on any single App, establish aglobal view, to avoid each App going its own way and causing data architecture chaos; the resulting "migration panorama table" is continuously referenced in the Phase 1.5 of each subsequent App.
Phase 1.5: Requirements inventory and implementation plan (★ mandatory step)
Before any development work begins (including creating an app, starting from a template, or adding new features to an existing app), you must first complete the requirements inventory, propose an implementation plan, and obtain user confirmation. It is forbidden to skip this step and go straight into Phase 2 to write code; it is also forbidden to create an app before the §1.0 inventory and plan are confirmed—template =
access_mode, cannot be changed after creation.
1.0 Requirements inventory → four questions (★ missing any one means do not enter 1.5)
The user's opening one-lineris a prompt, not a requirement. Finish the four questions in one round; if information is insufficient, ask, do not guess;
do not re-ask what was already said in the conversation; for migration scenarios, these four questions are derived by migration-workflow.md §2.0 inventory, and are not asked separately. Before the four questions, first confirm whether the project has entered the production environment (product-line-decision.md §0)—if it has entered and there is existing code to migrate, switch to the migration track, and the four questions follow the previous sentence and are derived by §2.0.
| # | What to ask |
|---|---|
| One | Who uses it—list the user groups, and whether there are pages that must be viewable without logging in |
| Two | What it does—feature list, usage scenarios and flows, which data entities are involved |
| Three | External-facing—whether a custom domain, SEO, and anonymous browsing of the entire site are needed |
| Four | Mechanism requirements—verify item by item against product-line-decision.md §2's Custom App capability boundary table |
Also check along the way (feed it plan items 4.5–4.7): third-party APIs, external webhooks, scheduled jobs, file uploads.
Produce a “requirement shape conclusion”(fill in according to resources/new_app_requirements_template.md ).
The rationale for the four questions, the options to give when they cannot answer, and the conclusion format → references/planning.md §1.0。
1.0.5 Template inventory (★ done for all development, including incremental development of existing apps)
After the four questions and before the plan takes shape, check the template catalog (GET /templates, for categories see the industry suite with the slug prefix, not only category),
write the conclusion as one of three choices into the plan:(a) can be used directly /(b) there is a close match (state which one to modify and what to change) → both go through “preview fetch code → interrogate effect binding → starter scaffolding → provision yourself”, producing theeffect binding table;(c) neither applies → write one sentence of rationale,
still read the closest one or two. Approach, endpoints, and permissions → references/template-workflow.md(script scripts/aigo_template.py)。
The plan content must include (★ expand item by item in references/planning.md)
| # | Item | SSOT |
|---|---|---|
| 1 | Requirements analysis: feature list, usage scenarios, user flows | §1.0 Question 2 |
| 1.3 | Template inventory conclusion(a/b/c);a、b → Effect binding table(each non-default binding = changing the ports implementation) | template-workflow.md §2、§4 |
| 1.5 | Product line and mode determination(the result is irreversible) → produce the app allocation table | product-line-decision.md |
| 1.7 | Authorization architecture selection(roles,access_role_ids, invitations) → produce the authorization architecture table |
member-admin.md §1 |
| 2 | Feature group splitting (split the app only for 2 or more groups with different purposes) | product-line-decision.md §7 |
| 3 | Dual-track data architecture routing → produce the data carrying table(every self-built table must have “the default table it was compared against / reason for not adopting”) | custom-app-dev-guide.md §19、default-table-lookup.md |
| 4 | Page and component planning, routing structure | — |
| 4.5–4.7 | External APIs (egress), webhooks, scheduling, files | event-triggers.md、custom-app-dev-guide.md §25 |
| 5 | Verification methods and milestones | verification-details.md |
For both resident (always_on) lines there must be a conclusion; the default for both is false—Hosted passes hosted-apps.md §3.0's three questions;
Custom passes custom-app-dev-guide.md §28.1 (the answer is almost always “off”; if there is no real-time interaction signal hit, there is no need to ask the owner).
Plan gate (★ seven items; if any is missing, you may not enter Phase 2)
- The four questions are not complete, or the plan is missing any one of “requirement shape conclusion”, “app allocation table”, “authorization architecture table”, or “data carrying table” → not complete
- Any row of the app allocation tablehas no resident conclusion → not complete (writing “on” must carry “reason X; exit condition Y” + confirm the paid plan)
- Any self-built table in the data carrying table lacks “the default table it was compared against / reason for not adopting” → not complete (issue #53: without it, the first version of the 46-table migration case judged 40 self-built tables, and after comparison only 13 remained)
- There is no template inventory conclusion (a/b/c), or (c) has no written rationale → not complete
- If the “implementation action” of any row in the effect binding table has no corresponding item in the plan → not complete
- **Only after the user explicitly replies "agree"** does it proceed to Phase 2; if the user changes requirements → update the plan and confirm again
- Fixed actions after confirmation: create apps according to the app allocation table (the only point at which apps are created), and
aigo_auth.py app addregister, recordapp_domain, create roles and send invitations according to the authorization architecture table (member-admin.md§3–§5, pass through each stepdata-operations.md§3.5 write gate); transition to Hosted if determinedhosted-apps.md
The rationale for each gate and the pitfalls encountered → references/planning.md。
Phase 2: Project scaffolding
Decide the strategy based on the Phase 0 Review results:
-
VFS is empty: generate a brand-new project structure
- Single-page/multi-page follows the page architecture in Phase 1.5 plan item 4,do not ask separately; if the plan does not specify it, the plan is incomplete, go back to 1.5 to supplement
- Single-page: render directly, do not use Router
- Multi-page: HashRouter + Sidebar navigation
- Available
scripts/aigo_scaffold.py'sscaffold_new_project()
-
VFS has content:
aigo_scaffold.pyofdownload_vfs_to_local()download to local for incremental development, preserve existing code -
Start from a template(inventory conclusion a/b): for the starter empty shell, first clear the demo action and
_template.json(do not clear the release 409EGRESS_NOT_READY)→aigo_template.py previewfetch the template code toanotherreference directory → copy into the project and adapt (change non-default bindings to ports implementation) → provision according to the effect binding table (template-workflow.md§5)
Phase 3: Development guidelines
Core rules (must be strictly followed)
- Framework:React 18 + TypeScript
- Routing: multi-page uses
HashRouter(do not useBrowserRouter); single-page may not use Router - CSS: global
App.css, CSS Modules / Tailwind not supported - CSS variables: must use
:host, :root { }dual selector - HTML reset: must use
html, :host { }dual selector - Entry point: must be
src/main.tsx, andimport "./App.css" - Layout: the outermost container must
height: 100vh; overflow-y: auto - Runtime modules: react, react-dom, lucide-react, react-router-dom, react-hot-toast are provided by the Runtime, do not install them yourself
- SDK must not be modified:api.ts, db.ts, action.ts, data.json, db.json, actions.json
- Server-Side Actions: Python, placed in the
actions/directory, defining theexecute(ctx)function - Shadow DOM limitations:
confirm()/alert()/prompt()unavailable → use React state or react-hot-toast instead - Frontend
db.tsdb.update() Bug: need to use{"data": {...}}to wrap the payload (fetch directly, do not go through the SDK)- ⚠️ Injected before 2026-09-01,
db.tssendsPUT, the data proxy only acceptsPATCH——update()always returns 405, updates never took effect(#1416 fixes the SDK template). If an existing app'ssrc/db.tsis still themethod: 'PUT'version, replace it with the platform's latest template (Builder re-injects) or fetch directly usingPATCH; do not investigate 405 as a permissions issue
- ⚠️ Injected before 2026-09-01,
- Frontend
db.tsdb.insert() Bug: same as above, need to use{"data": {...}}to wrap- ⚠️ Frontend only. Server Action's
ctx.db.insert(table, data)receivesa flat dict, wrapping it instead gets filtered out and returns 400. Custom tables'insert_row/update_rowlikewise accept a flat dict
- ⚠️ Frontend only. Server Action's
- Development restrictions: After obtaining the App ID, first use
scripts/aigo_limits.py'sget_limits(base_url, token, app_id)to query the target platform's VFS, Action, and egress limits, and go by the response. 404/503 or connection failure means unknown; do not use historical values from the docs to infer the current quota. ——Files exceeding the per-file limit will still be skipped; you must checkskipped_files, and must not treatsuccess: trueas fully included. Values are subject to the platform, seereferences/custom-app-dev-guide.md§4 - Complete code principle: Each time a VFS file is updated, 100% complete content must be provided;
// ...省略placeholders are prohibited - Dynamic import is not supported:
import()syntax is not supported (except lazy loading; esbuild supports code splitting) - Node.js native modules are not supported: fs, path, crypto, etc. cannot be used
Rules 18–34 (data, events, permissions, time, URLs, rendering, UAT, revocation) quick reference—the full version is in
references/dev-rules.md, Check each item before starting; violating items marked ★ means stop, violating items marked ⚠️ will not error but will only compute incorrectly:
| # | Rule | Marker |
|---|---|---|
| 18 | Data carrier: dual-track routing | ★ Mandatory |
| 18.5 | Custom table naming convention: entity names must always be in English | ★ Mandatory |
| 19 | app_domain tag convention | ★ Mandatory |
| 20 | Webhook / scheduled action must be idempotent | ★ Mandatory |
| 21 | Webhook declaration only takes effect after release | |
| 22 | The four hard limits of scheduling | |
| 23 | Roles/permissions follow the platform; do not build your own set | ★ Mandatory |
| 24 | Writes to default tables may be intercepted by approval | ★ Mandatory |
| 25 | A table lacking tenant_id does not mean it is unprotected |
★ Mandatory |
| 26 | offset Pagination must always include a unique key sort |
★ Mandatory; ⚠️ silent error |
| 27 | ctx.erp.validate_picking Idempotency depends on the details, not the document state |
★ Mandatory |
| 28 | Native TIMESTAMP/DATE is offset-naive UTC; before parsing, Z |
★ Mandatory; ⚠️ silent error |
| 29 | All APIs must go through the tenant space https://[tenant].ai-go.app/* |
★ Mandatory |
| 30 | Render skeleton on startup; do not let long APIs block the first render | ★ Mandatory |
| 31 | Internal app frontend is prohibited from directly calling custom table SDKs | ★ Mandatory |
| 32 | Hosted App is prohibited from hosting a database or storage | ★ Mandatory |
| 33 | Every app to be released must have a “UAT conclusion” | ★ Mandatory |
| 34 | Apps that use AI GO login while retaining their own authentication backend must implement “real-time revocation” | ★ Mandatory |
Full explanations, criteria, and empirical evidence are in
references/dev-rules.md(includes table of contents); Rule 18 dual-track branching, 18.5 two-step naming method, 23 role reuse must-read original text.
Writing Server-Side Actions (★ four hard rules;ctx see list at custom-app-dev-guide.md §7)
def execute(ctx):
data = ctx.params.get("key", "default") # webhook / cron 事件也走 ctx.params
ctx.response.json({"result": data})
- All external calls must go through
ctx.http.call(<egress-slug>, <path>)—the runner is default-deny egress, rawimport httpx / requests / urllib.requestcannot connect out (measured 20-second timeout). ⚠️ These packages can be imported(the language-level sandbox has been removed, as actually tested on 2026-09-13)—what blocks it is thenetwork layer, don't take "can be imported" to mean usable - the slug must first have a same-named "external service" created in the Builder and authorized for this app, otherwise it cannot connect out.
This is a configuration issue; changing the code cannot fix it; a disabled service is blocked the same way (publish 409
service_inactive) - The key is supplied by the app itself: the gateway only verifies the domain and does not inject credentials (ADR 0010)—store
ctx.secrets, the action assemblesAuthorizationheader ctx.dbhas no structural operations: at runtime it cannot create tables or alter columns; this is a deliberate capability boundary- ★ External services and keys: AI may set them up on the user's behalf, but must explain clearly before acting: before creating/authorizing an external service or writing secrets, tell the user in plain language
which domain it connects to, what data will be sent out, and which action uses it,obtain consent separately(do not fold into plan consent; if the domain or data changes, ask again);
the key value is filled in by the user into a local file with 600 permissions, and
aigo_secrets.pyreads the file and writes it in,never transmitted in the conversation, never printed, never read back. Permissions: external servicebuilder.access+ this App owner orsystem.admin; keybuilder.access+ can see that app (dev-guide §25.2). A gapis not a bug, do not report it
There are two timeouts and the original text uses the same form for both: manifest
timeout_ms(1000–120000; old apps must be republished to take on the new value) and the egress gateway's servicetimeout_ms(default 10000, hard cap 30000). An action going throughctx.http.callbeing cut off early is the latter,not the manifest failing to take effect. The gateway also has limits of 8 MiB per request / 5 MiB per response / 120 times per minute →custom-app-dev-guide.md§25.4. A data-layer 403 carryingreason/rule_idis blocked by tenant data access rules; changing the code will not help → dev-guide §27.
Frontend calls Action
import { runAction, downloadFile } from "../action";
const { data, file } = await runAction("my_action", { key: "value" });
if (file) downloadFile(file);
Phase 4: Deployment + automated verification (★ must be executed after every code change)
Principle: after every code change, the "sync → compile → verify" loop must be completed. Only after passing the verification gate may you proceed to publish or continue to the next round of development. For extremely small changes (such as text-only edits or minor CSS adjustments), Custom Data and Action tests may be skipped, but compile verification cannot be skipped.
4.1 Standard deployment workflow
- Determine the target and print it out:
app = resolve_app(root, alias)→print(app.describe())→ after GET appassert_remote_matches(app, info). If the workspace has multiple apps and this session did not specify one →resolve_appwill error out listing the aliases,ask the user, do not guess。full_deploy()itself will also print the target line - Sync VFS: read local files → PATCH
/api/v1/builder/apps/{id}/source/files- script:
scripts/aigo_sync.py'ssync_to_cloud() - ★ Built-in double verification: after PATCH, automatically GET to confirm vfs_version increments + the file is actually written
- ★ PATCH does not delete files: the
actions/*.pydeleted locally remains on the remote and can still be called after publishing (removing the registration from the manifest does not take it down), so when the remote hasactions/files that do not exist locally, sync by defaultaborts before writing and lists them—give the list to the user for confirmation, then usefull_deploy(..., on_remote_only="delete", delete_paths=[用戶確認過的路徑])/delete_remote_files()(take down) oron_remote_only="keep"(keep) →troubleshooting.md"deleted actions can still be called" list 1.5. semantic check(★ mandatory when the frontend has substantive changes):uv run --project scripts python scripts/aigo_typecheck.py <專案目錄> - compile uses esbuild, which only transpiles and does not type-check: errors such as TDZ, name not found, and duplicate declarations are all green at compile time, and after publishing
the runtime shows a white screen (the stack only has minified names,
troubleshooting.mdwhite-screen list)—this step is the only gate that can catch it before publishing - The script onlyblocks semantic errors that would crash the runtime(TS2448/2454/2451/2300/2304…),
noise from missing type packages is only listed and not blocked; if Node is not available locally, it prints a notice and skips—in this case you musttell the user
that this gate did not run, or ask the user to use
check_typesin Builder AI to run it retroactively (the platform has this tool but no REST endpoint)
- script:
- Compile:POST
/api/v1/compile/compile/{slug}?dev=true- Script:
scripts/aigo_compile.pythecompile_app() - On both success and failure, read
skipped_filesand tell the user each path / UTF-8 bytes / reason;[]only indicates it was not skipped; a missing field or null indicates an old service or that this run did not compile, and it must not be treated as fully included. The publish response is checked for this field as well. - ⚠️
success: trueandcompile_errors: []only meanstranspilation succeeded, not that the program is semantically correct (see 1.5) - To let the userview the draft in the browser: for internal, open
{tenant}.ai-go.app/runtime/version-test/{識別碼}(requiresbuilder.access); the external test URL also requires?preview_token=(the Builder toolbar "Preview" adds it automatically), for the shape table and identifier rules seereferences/platform-behaviors.md§6.2——do not assemble it yourself
- Script:
- Compilation failed: parse error → try automatic repair → resync → recompile (up to 5 times)
- Compilation succeeded → enter the verification gate(Phase 4.2)
4.2 Verification Gate
After each successful compilation, based on thechange scopeautomatically determine the verification items that need to be run:
Change scope determination rules
| Change type | Impact scope | Verification to run |
|---|---|---|
| CSS tweak(only App.css changed) | Very small | ✅ Compile output |
| Copy/UI change(only TSX changed, no new imports) | Small | ✅ Compile output |
| Component addition/refactor(new TSX, route changes) | Medium | ✅ Compile artifacts + ✅ Publish consistency |
| Custom Data related(Modified code that uses api.ts/db.ts) | Medium | ✅ Compile artifacts + ✅ Custom Data CRUD |
| Server Action changes(actions/*.py modified) | Medium | ✅ Compile artifacts + ✅ Server Action calls |
| Multiple scopes changed simultaneously | Large | ✅ All 4 verifications |
| First deployment or architecture change | Large | ✅ All 4 verifications |
Yesactually runthese four verifications →
references/verification-details.md§1 has the complete check items and function signatures for each one.
4.3 Post-verification decision
| Verification result | Next step |
|---|---|
| ✅ All passed | Can proceed to publish (4.4) or continue development |
| ❌ Compile failed | Go back to Phase 3 to fix the code |
| ❌ CRUD/Action failed | Check API usage, table structure, Action logic |
| ❌ Publish consistency failed | Re-sync → compile → publish |
If any item fails → first check
references/troubleshooting.mdfor the symptom, then make changes. ⚠️ When CRUD verification hits the default table, a returnedapproval_status: "pending"or the "approval workflow required" exception does not count as verification failure—that is the tenant approval workflow intercepting (Core Rule 24); do not treat it as a bug and change the code.
4.4 Publish
Publish only after passing the verification gate:
- POST
/api/v1/builder/apps/{id}/publish- Script:
scripts/aigo_publish.py'spublish_app() - ★ Built-in secondary verification: after POST, automatically GET to confirm status == "published"
- ★ Built-in before POST
egress_preflight(): compare_template.json'srequired_egressdeclaration,actions/*.py's literalctx.http.callslug and the external services authorized for this App—leftover starteropenaiwill be pointed out here, without waiting for 409 (troubleshooting.mdEGRESS_NOT_READY column; see dev-guide §26.2 for the two files to clean in the starter) - By default, none of the three query parameters are included,when 409 comes back, first read
codebefore deciding(dev-guide §8 routing table):confirm_removal=trueonly when the user confirms they want to remove that action;confirm_egress_gaps=trueonly when it is certain that that slug is not needed;auto_rollback=trueis automatic compile verification after publish, reverting to the previous version and returning 422 on failure—enable it so the user knows it will roll back
- Script:
- After publishing, run the Publish consistency verification;a 503 returned by calling the action immediately after publishing is a runner cold start, wait
Retry-Afterthen try again; it is not a publish failure (troubleshooting.md503 column)
Optimistic locking
- Record
vfs_version - Include
expected_version - 409 → GET again → merge → retry
Automatic repair strategy
| Detected problem | Automatic repair |
|---|---|
:root { None :host |
→ :host, :root { |
html { None :host |
→ html, :host { |
| BrowserRouter | → HashRouter |
Missing import "./App.css" |
→ Add at the top of main.tsx |
Available scripts/aigo_sync.py、aigo_compile.py、aigo_publish.py。
Phase 5: Full E2E verification (milestone verification)
Phase 4's verification gate runs automatically on every iteration; Phase 5 isdevelopment milestone complete(all features complete, ready for delivery) full verification at that time. To execute →
references/verification-details.md§2 has the complete checklist and invocation examples.
Verification process quick reference
每次 code 變更:
sync → compile → ✅ Compile 產物驗證
└─ (若涉及 Data) → ✅ Custom Data CRUD
└─ (若涉及 Action) → ✅ Server Action 呼叫
└─ (若涉及路由/元件) → publish → ✅ Publish 一致性
里程碑交付:
上述全部 + 角色白名單實測(用不在 `access_role_ids` 內的帳號開 app 應 404)+ 匿名存取(僅判進 external 的 app)
+ 常駐狀態對帳(dev-guide §28.1):用 `GET /builder/apps` **列表**讀回 `always_on`+`has_messaging_trigger`
(Builder 線沒有 `GET /runtime-settings`),必須等於計畫那列的結論;寫「開」才在 publish 後
`PATCH .../runtime-settings {"always_on": true}` 並確認回 `effective_mode: "always_on"`
+ 交付連結實開(照 `platform-behaviors.md` §6.2 組**正式版**網址,用非開發者帳號/external 使用者開一次;`verification-details.md` 第 8 項)
+ UAT 結論對帳(`dev-rules.md` 規則 33):計畫寫「有」的,`uat-environment.md` §4 驗證表要全過;寫「無」的,理由與風險要在交付說明裡
Hosted App 線(不走 Phase 2–4):
任何 `aigo` 指令前 → ✅ hosted-apps.md §3.3 版本閘門(`aigo_cli_check.py` 非零=瀏覽器登入不可用,先重裝;找不到 `aigo` 時連 token 部署也不行)
deploy/redeploy → ✅ hosted-apps.md §3.4 部署後驗證閘門(含讀回 `always_on`=§3.0 決策;未通過不得對外交付)
資料操作線(不開發 app):
寫入前 → ✅ data-operations.md §3.5 寫入閘門(估影響面 → 備份 → 試一筆 → 用戶確認)
Error handling
If any step fails, or an unexpected status code is received → First check
references/troubleshooting.md, do not speculate on a fix yourself. If the symptom is not found, or it is still stuck after handling per the table → Automaticallyenter the five-step "Issue reporting" below; do not retry repeatedly, do not take detours or force changes.
Status code semantic distinction:403 Permissions (structural operations datacenter.schema_write/system.admin and records builder.access downgrade actions differ; body carries
reason/rule_id are tenant data access rules → dev-guide §27) |409 quota or conflict |422 invalid input |
400 business rule rejection |503 "app runner temporarily unavailable" three causes have the same shape: first ask whether there is a publish
(status: draft retrying will not help) → cold start just after publishing (wait Retry-After) → body carries quota_hint is tenant
compute quota (not a code problem, forward the original text to the user) |aigo login browser login 401 "incorrect account or password"
First run aigo_cli_check.py to check the version, then check whether the login page URL is the tenant subdomain, and only then check the account and password (troubleshooting.md)。
★ When an Action external call fails, do not rush to change the code: first read out the status and error message in full.
timeout/cannot connect = raw httpx direct connection (change ctx.http.call) or the slug has no external service with the same name/not authorized;
401 = the action's own header or ctx.secrets key is wrong (the gateway neither injects nor strips credentials).
If it points to Egress or permissions, stop changing the program immediately—that is a configuration problem, and changing it repeatedly will give the same result. Confirm that the external service was not created/
disabled/not authorized or the key is missing (publish 409 gaps[].kind ∈ service_missing/service_inactive/unauthorized/
secret_missing, or at call time the egress_service_not_found/egress_service_inactive/egress_not_authorized)→
configuration gap, not a platform bug, do not report: list the missing items, explain the destination and data to the user per Action hard rule 5, obtain consent, and
have the AI fill them in (re-enable disabled ones, do not recreate ones with the same name), then verify again (custom-app-dev-guide.md §25.2、§25.3)。
Issue reporting (platform issue → development team)
★ By default the platform must be correct; if development or use fails, by default it is your own operational error. If uncertain, do not report.
Only one channel:scripts/report_issue.py submit(a card on the development team's Scrum Board), platform defects anddocumentation gaps
all go through this channel; no need to ask the user where to post it; do not open issues for the user on GitHub (including this skill repo). In the user's or other documentation's
"opinion card", "report card", "development team's card" all refer to this channel (references/issue-reporting.md prefix).
When to enter automatically(if any one holds, no need to wait for the user to request it, do not retry repeatedly, do not take detours or force changes):
troubleshooting.md No such condition found, still stuck when handled per the table, actual test and references/ the explicit statement do not match, endpoint 5xx/process hard-blocked.
Prioritize excluding: egress/secrets configuration gaps (the "error handling" in the previous section) do not count as "still stuck when handled per the table" or "process hard-blocked";
just supplement the configuration and it does not enter the reporting process; only when the configuration write itself abnormally fails, or after configuration is completed the readback/publish result contradicts the configuration, does it count.
Five fixed steps: automatic trigger → complete references/pre-report-self-grill.md six rounds of self-review (every branch must have
commands + output as evidence) → determine (if it is not a platform issue, fix it directly; if there is still something at the frontier pending investigation, do not report) → Proactively ask the user whether to send
(provide a non-technical summary,must not decide for the user) → only after consent submit。
Three hard conditions(if any one is missing, it is rejected; the CLI will block it):
- Content writesbehavior, not solutions— the four sections "scenario → operation → result → expectation"; if wording that prescribes a remedy such as "suggest changing/root cause is" appears, it is rejected
--ruled-out: the condensed excluded list from self-review, one item per line, at least three items--user-confirmed: indicates that step 4 has already asked the user and the user said to send —carrying it without having asked is the most serious violation in this section
Commands, parameters, attach screenshots, track progress, preflight check for existing stuck items → references/issue-reporting.md。
Reference documents
| File | Content |
|---|---|
CONTEXT.md |
★ Glossary — two major categories, preset tables/self-built tables, + four mechanism terms (including title mapping and forbidden terms: the old term SaaS table and external product names do not appear) |
references/dev-rules.md |
Full version of Phase 3 rules 18–34(dual-track data routing, self-built table naming, app_domain, idempotency, scheduling limits, role reuse, approval interception, pagination sorting, time, tenant URL, skeleton, builder.access breach, the sole exception that Hosted does not carry DB and external libraries, UAT conclusions, immediate revocation) — the main file has only the quick reference table; read the original before acting |
references/planning.md |
Full version of Phase 1.5: §1.0 the reasons and options for the four questions, the twelve plan items expanded one by one, the reasons for the seven gates and the pitfall records |
references/template-workflow.md |
Phase 1.5 §1.0.5 template inventory and the "templates as material" flow: query endpoint and slug prefix classification, a/b/c conclusions,preview code retrieval and effect list, effect binding table, starter shell creation and self-provisioning, endpoint permission table |
references/environment.md |
Full version of Phase 1: derivation of tenant URL rules and the cause of 401 taking the same form, three-layer model,config.json schema 2 and base_url three-layer sources, six configuration steps, credential rules |
references/review-workflow.md |
Full version of Phase 0: which endpoint each of the nine steps calls, what the Review report should list, which situations are marked "must change" |
references/custom-app-dev-guide.md |
Core API specifications and architectural philosophy;§6.0 SDK mode-based routing table、§29 master table of endpoints for the four access channels (internal/external/anonymous/open)、§15.1 the platform's three approval states for anonymous access, §12 Storage pitfall table,§27 tenant data access rules (Auth gate: 403 with reason source), §28 cold start/resident (always_on)+§28.1 Custom line resident decision gate (default off) |
references/data-center.md |
Full spec for self-built tables (types, quotas, permissions, SDK) + extended fields (§10) |
references/default-table-lookup.md |
When determining "whether the platform has an entity with the same semantics" (Phase 1.5 item 3, migrated into §2.4 required check for every table): Business language → default table quick lookup, table name prefix reading, Meta side ↔ reference side comparison, required fields and read-only tables, common migration misjudgments |
references/event-triggers.md |
Webhook and App scheduling (idempotency requirements, declaration, limits) |
references/product-line-decision.md |
When determining product line and mode in Phase 1.5 (both paths share the SSOT): Default Custom App and deviation signals, Custom App capability boundary checklist, two questions four quadrants (logged-in users are always internal), hybrid solution division of labor (including Hosted as Custom backend), irreversible prerequisites, app allocation table |
references/member-admin.md |
SSOT for authorization architecture selection in Phase 1.5 item 1.7 + member/role management playbook: Stance on internal and external personnel sharing an account system, three questions and authorization architecture table, invitation/role endpoints and permissions,access_role_ids(two lines), batch invitation flow and four boundaries, Hosted internal identity acquisition (header + members context), existing system user migration, 403 interpretation |
references/migration-workflow.md |
When there is an existing system to migrate in: Stack inventory (§2.0, do first;four stack shapes, including "BaaS as backend, browser direct connection"; placement of original cloud topology and local/external microservices and scheduling), migration input for product line determination (§2.1), project deconstruction, Schema mapping, placement of users and login (§2.4.5), data migration, cutover preparation (§2.6: external registrations, hardcoded production resources) |
references/hosted-migration-runbook.md |
Main flow for determining migration cases going the Hosted App route: First confirm the real production site, seven stages and pass conditions, resident PaaS hidden assumption scan, UAT test data strategy, functional test order (template resources/hosted_migration_test_plan_template.md), cutover day steps and rollback, observation and old site retirement |
references/uat-environment.md |
Practice of Rule 33: How to reach a UAT conclusion,version-test why it does not count, mirrored topology,-uat naming, independent database and credentials, clone Hosted production configuration window and visibility reset, egress/secrets/Open Proxy references, supplement testers only, verification table, operations and retirement |
references/verification-details.md |
When verification is to be executed: Complete definitions of the four verifications, Phase 5 milestones |
references/troubleshooting.md |
When an error occurs: Error quick reference table |
references/pre-report-self-grill.md |
Before reporting a platform issue (mandatory): Default platform correctness, six-round self-review exclusion tree, submission conditions, excluded list |
references/issue-reporting.md |
When reporting a platform issue: BDD writing conventions, commands, progress tracking |
references/platform-behaviors.md |
Measured behavior addendum: DB Proxy pagination and record count limits,custom_data no server-side filtering, TIMESTAMP format, seed table read-only,ctx.erp allowlist,app runtime URL summary table (§6.2: internal/external × production/test), deep links and the three layers of "app not found" (§6.2), empty render detection, API permission gate (app axis; for personnel axis see dev-guide §27) |
references/hosted-apps.md |
Hosted App ("Custom App") product line: Boundary with Custom App, hard rules for application shape, deployment API,post-deployment verification gate (§3.4 = equivalent of Phase 4.2), env rules, error code reference — read when Phase 1.5 determines this line or a hybrid approach |
references/data-operations.md |
Data operation mode (no app development): Four user identity data planes and permission gates,write gate (§3.5, production data is irreversible), module REST conventions, export allowlist, Meta value ranges, error and reporting outlets (§7) — read when the source intent is determined to be "data operation" |