Repo-specific rules for AI agents working in this repository. See
TEMPLATE_GUIDE.md for how the templates are authored.
- When the code you changed passes tests, create a PR and merge it.
After the full CI gate set passes locally —
pnpm typecheck,pnpm build,pnpm format:check, andpnpm -r --if-present test— commit on a branch, open a pull request, and merge it. Do not stop at "tests pass" and wait for a separate go-ahead.- 中文:你修改的代码测试通过后,创建 PR 并合并,无需再次等待确认。
- Never commit, push, or merge while any of those checks is failing.
- Work on a branch, not
main; let the PR merge bring changes intomain.
objectstack build validating clean does NOT mean the app boots, seeds, or
that hooks/flows actually run. Several bug classes only surface at runtime.
Before claiming a metadata change works, boot it (see "Running the all env")
and confirm Server is ready + seeded on empty DB + zero ERROR log lines.
- Hooks run body-only in a QuickJS sandbox. The handler ships as just its
function body, so it can reference only what is declared inside the handler.
A module-scope helper/const referenced from the handler throws
ReferenceErrorat runtime (but passes build). Define every helper/constant inside the handler body. Also: a hook may mutate only its incominginputpayload — a nested cross-object write (ctx.api...update/create) re-enters the sandbox and crashes the process (memory access out of bounds), andctx.services.datais undefined in-sandbox. (Platform: framework#1867.) - Flow trigger conditions: use the supported idioms.
previous.<field>and plain comparisons /!= nullwork.PRIOR(...)andisBlank(...)are not evaluated — the flow is silently skipped with no error and a clean build. (Platform: framework#1877.) - Flow
create_recorddate fields: never pass a literal'today()'/'now()'string — the runtime rejects it asinvalid_dateand the whole flow aborts. Use a field ref ('{rec.some_date}') or leave the field optional. - Flow action/
invoke_functionnodes pointing at a function no template registers (or ascriptnode with no realactionType, e.g. anaggregationsnode) build fine and silently no-op at runtime. Cross-object rollups are therefore seed/client-maintained, not live. (Platform: framework#1868/#1870.) - Multi-lookup (
multiple:true) fields aren't on the after-create record a record-change condition sees, so conditions likerecord.x != nullare false for them. (Platform: framework#1872.) - Script validations of
field == nulldon't fire on insert when the field is omitted entirely from the payload (they do on update / explicit null). A field with adefaultValueis always present, so its rules fire on insert. (Platform: framework#1871.) - Dashboard time-series on a
datetimefield render empty. The analytics dataset executor binds dashboard date tokens ({12_months_ago},{today},{N_weeks_ago}, …) as ISO date strings ("2025-06-18"). AField.datecolumn stores ISO text, socol >= '2025-06-18'matches; aField.datetimecolumn stores an integer epoch (e.g.1780012800000), and in SQLite an INTEGER always sorts before any TEXT, soepoch >= 'YYYY-MM-DD'is always false → the chart/KPI silently shows "No rows" even though the data exists and the un-filtered cube returns it. UseField.datefor any field a dashboard filters or groups by a date token (chart x-axes, "last N months" filters). Keepdatetimeonly where sub-day precision is load-bearing (e.g.helpdesk_ticket.resolved_at, used by SLA-resolution timing) — those charts stay empty until the platform binds epoch for datetime columns. (Platform: framework — analytics date-token vs datetime-column type mismatch.)
- Native driver:
better-sqlite3's prebuilt ABI may not match the local Node (e.g. Node 25). If the dev server logsNODE_MODULE_VERSIONmismatch, rebuild from source: innode_modules/.pnpm/better-sqlite3@*/node_modules/better-sqlite3, runnpm_config_build_from_source=true npx node-gyp rebuild. - Compile + run:
pnpm --filter @objectlab/all run compilecomposes every template intodist/objectstack.json, thenpnpm --filter @objectlab/all start(port 4000). The compile re-reads each template's freshly-builtdist/objectstack.json, so runpnpm -r buildfirst. - Seed data is org-scoped. Log in as the seeded dev admin
admin@objectos.ai/admin123to see seed data — a freshly registered user lands in an empty org and sees nothing. (READMEs document this.) - Console routes: object list
/_console/apps/<app>/<object>, dashboard/_console/apps/<app>/dashboard/<name>, create form/_console/apps/<app>/<object>/new. Home app cards are React-onClick divs and don't respond to scripted clicks — navigate by URL instead. - API:
/api/v1/data/<object>(list responses use{records}); login isPOST /api/v1/auth/sign-in/emailand requires anOriginheader (403 without it).
zh-CNships across all templates (PR #13) — it is intentional. Some older CHARTER "en only" lines are stale; reconcile the charter to reality, never delete translation files. When adding fields/options, update bothenandzh-CNbundles.
- Platform-level gaps surfaced by these templates:
objectstack-ai/frameworkissues #1867–#1877. - Template-side follow-ups (incl. cleanups blocked on those platform fixes): this repo's issues #45–#59 (umbrella tracker: #59).