You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .agents/skills/add-block-preview/SKILL.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -53,7 +53,7 @@ To pull an already-GA block from discovery surfaces on hosted (incident, depreca
53
53
-**Clone-not-remove:** gated blocks stay in `getAllBlocks()` output as clones with `hideFromToolbar: true` — `.find`-by-type consumers rely on this. Never filter them out.
54
54
-**Keys are registry block types.** Never `custom_block_*` (parse drops them — custom blocks have their own enabled/disabled lifecycle).
55
55
-**The shared hidden-predicate is `isHiddenUnder`** (`apps/sim/blocks/visibility/context.ts`). Never restate the preview/disabled rule inline at a new consumer.
56
-
-**Process-global caches stay ungated.**`getStaticComponentFiles` (VFS) and `getExposedIntegrationTools` build the ungated universe; per-viewer filtering happens at stamp/consumer time. Never move gating into a shared builder.
56
+
-**Process-global caches stay ungated.**Shared builders such as `getExposedIntegrationTools`(`lib/integrations/tool-catalog.ts`) build the ungated universe; per-viewer filtering happens at consumer time via `isHiddenUnder`. Never move gating into a shared builder.
57
57
- Gating is **surface hiding, not secrecy** — the full config ships in the client JS bundle. Anything truly secret cannot be a registered block.
**Critical:**Every subblock `id` must be unique within the block. Duplicate IDs cause conflicts even with different conditions.
76
+
**Critical:**Give every subblock a unique `id`: duplicates collide silently (the last definition wins). `blocks.test.ts` fails a duplicate within one condition unless the copies are a basic/advanced mode-swap pair, one basic plus trigger-mode copies, or all carry `canonicalParamId`. The only sanctioned cross-condition reuse is the hosted-key `apiKey` pair (`add-hosted-key` skill), where both fields deliberately share one value.
@@ -937,30 +956,17 @@ tool IDs through `tools.access` and does not change any tool's shape.
937
956
938
957
But if the same change also adds, edits **or removes** a tool, run `bun run tool-metadata:generate` and commit the result, or CI fails on stale artifacts. That matters here because a block's `outputs` are authored to match its tools' outputs, and the UI reads those from the generated metadata, not the executable registry — an unregenerated tool change makes the block's outputs disagree with what the panel renders. See `.agents/skills/tool-registry-boundary/SKILL.md`.
939
958
940
-
A visible integration block does require the generated integration catalog and docs to be refreshed.
941
-
After adding or changing one, run:
942
-
943
-
```bash
944
-
bun run scripts/generate-docs.ts
945
-
bun run deployment-config:generate
946
-
bun run integration-catalog:check
947
-
bun run deployment-config:check
948
-
bun run docs:check
949
-
```
950
-
951
-
The catalog check independently derives deployment metadata from the executable block registry and
952
-
compares it with the committed `packages/deployment-config/src/integrations.json`. The deployment
953
-
config check verifies the generated service-account facts against the canonical OAuth registry and
954
-
catalog. `docs:check` re-renders every generated docs artifact in memory and fails on any committed
955
-
file that differs — it runs in CI via `check:audits`, so commit the full generator output. If the
956
-
generator also trues up pages an earlier PR left stale, commit that catch-up too; reverting it as
957
-
"unrelated drift" makes `docs:check` fail. Review the generated diff and keep only intentional
958
-
changes.
959
+
A visible integration block does require the generated integration catalog and docs to be refreshed:
960
+
`bun run tool-metadata:generate` (only when a tool changed), `bun run scripts/generate-docs.ts`,
961
+
`bun run deployment-config:generate`, then `bun run check:audits`. Also run
962
+
`bun run apps/sim/scripts/check-block-registry.ts origin/staging` (CI runs it outside `check:audits`). Commit the
963
+
full generator output. For what each check verifies, see the `validate-integration` skill →
964
+
Regenerate Derived Artifacts.
959
965
960
966
## Checklist Before Finishing
961
967
962
968
-[ ]`integrationType` is set to the correct `IntegrationType` enum value
963
-
-[ ]`tags`array includes all applicable `IntegrationTag`values
969
+
-[ ]`{Service}BlockMeta.tags`lists every applicable `IntegrationTag`(tags live on the meta, not the block)
964
970
-[ ] All subBlocks have `id`, `title` (except switch), and `type`
965
971
-[ ] Conditions use correct syntax (field, value, not, and)
966
972
-[ ] DependsOn set for fields that need other values
@@ -996,7 +1002,7 @@ Validate the block against every tool in `tools.access`:
996
1002
2.**For each tool, verify the block has correct:**
997
1003
- SubBlock inputs that cover all required tool params (with correct `condition` to show for that operation)
998
1004
- SubBlock input types that match the tool param types (e.g., dropdown for enums, short-input for strings)
999
-
-`tools.config.params`correctly maps subBlock IDs to tool param names (if they differ)
1005
+
-Each subBlock (or its `canonicalParamId`) is named exactly after the tool param it fills. A required `user-only` param that is only renamed in `tools.config.params`fails `bun run apps/sim/scripts/check-block-registry.ts origin/staging`; remap only optional or `user-or-llm` params
1000
1006
- Type coercions in `tools.config.params` for any params that need conversion (Number(), Boolean(), JSON.parse())
1001
1007
3.**Verify block outputs** cover the key fields returned by all tools
1002
1008
4.**Verify conditions** — each subBlock should only show for the operations that actually use it
Copy file name to clipboardExpand all lines: .agents/skills/add-column-type/SKILL.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,7 +12,7 @@ A `case 'yourtype':` outside `column-types/` fails **silently** when missed (a w
12
12
13
13
## Hard Rule: the compiler tells you what to do
14
14
15
-
Do **not** hunt for places to edit. Add your typeto the `ColumnType` union first and let `tsc` produce the list:
15
+
Do **not** hunt for places to edit. Append your type's id to the `COLUMN_TYPES` array in `column-types/types.ts`first (`ColumnType` derives from it) and let `tsc` produce the list:
16
16
17
17
```bash
18
18
cd apps/sim && bun run type-check
@@ -86,7 +86,7 @@ export function Type{Pascal}(props: SVGProps<SVGSVGElement>) {
86
86
87
87
## Step 3: Write the type file
88
88
89
-
`apps/sim/lib/table/column-types/{name}.ts`. Copy the closest existing type and change what differs. Every field is required by the interface, so the compiler enumerates them for you — read the TSDoc in `types.ts`rather than guessing.
89
+
`apps/sim/lib/table/column-types/{name}.ts`. Copy the closest existing type and change what differs. Required fields are compiler-enforced; optional hooks (`isCompatibleWith`, `salvage`, `valueForEquality`, `filterOperatorsFor`, …) default sensibly — read the TSDoc in `types.ts`before overriding.
90
90
91
91
The three that are easy to get wrong:
92
92
@@ -132,18 +132,18 @@ Registering the *type* is compiler-enforced. Registering its *metadata* is not,
132
132
|`column-types/types.ts``TYPE_SPECIFIC_COLUMN_KEYS`| it is never stripped on conversion, and poisons the target type |
133
133
|`lib/api/contracts/tables.ts` — the schema slot in all three column schemas, plus `refineColumnOptions`| zod strips it at the boundary; silently never saved |
134
134
|`columns/service.ts``addTableColumn` param type | callers cannot pass it |
135
-
| A metadata-only update path (`updateColumnCurrency` is the model) + a branch in both column routes + the copilot tool| changing it on an existing column is a silent 200 no-op |
135
+
| A metadata-only update in `lib/table/columns/service.ts`(`updateColumnCurrency` is the model) + a branch in `performUpdateTableColumn` in `lib/table/orchestration/columns.ts`| changing it on an existing column is a silent 200 no-op |
136
136
|`column-config-sidebar.tsx`| no UI to set it |
137
137
|`table-grid.tsx` delete-column undo + `use-table-undo.ts` restore | undo silently resets it to the default |
138
138
139
139
`normalizeColumn`, `buildConvertedColumn`, and the undo snapshot read `TYPE_SPECIFIC_COLUMN_KEYS` generically, so those three are already zero-edit.
140
140
141
-
**Known gap:** the metadata-only update path is ~6 near-identical copies (service + 2 routes + copilot). A `metadataUpdate` descriptor on `ColumnTypeServerDefinition` would collapse them; until that exists, copy `currency`'s.
141
+
Copy `currency`'s service function and orchestration branch.
142
142
143
143
## Checklist Before Finishing
144
144
145
-
-[ ]Added to the `ColumnType` union in `column-types/types.ts`
146
-
-[ ]`column-types/{id}.ts` created, every interface field filled in
145
+
-[ ]Id appended to `COLUMN_TYPES` in `column-types/types.ts`
146
+
-[ ]`column-types/{id}.ts` created, every required field filled in
147
147
-[ ] Registered in **both**`registry.ts` and `registry.server.ts`
148
148
-[ ] Icon added, centered on the family's optical center, exported alphabetically
149
149
-[ ]`migrateCellsTo` / `migrateCellsFrom` added if the stored bytes change
@@ -155,6 +155,6 @@ Registering the *type* is compiler-enforced. Registering its *metadata* is not,
155
155
156
156
1.**`cd apps/sim && bun run type-check`** — must be clean. If any file *outside*`column-types/` errors, that file has a hardcoded type list; fix it to read the registry.
157
157
2.**Grep for leaks** — `grep -rnE "(===|!==) '{id}'|case '{id}':" apps/sim --include='*.ts' --include='*.tsx' | grep -v column-types/`. (All three forms: a plain `!==` and a `case` are how half of `currency`'s real branches are written.) Hits are expected; judge each. A hit is fine when it mounts a specific React component or encodes a genuinely one-off behavior (`json`'s mono textarea, `date`'s timezone-aware parsing). A hit is a **leak** when it restates something the registry could answer — an icon, a label, a colour, an operator set, a cast, a coercion. Leaks get a registry field, not a new branch.
158
-
3.**Run the suite** — `bun run --cwd apps/sim test lib/table 'app/workspace/[workspaceId]/tables' lib/api app/api/table app/api/v1 lib/copilot/tools/server/table`. Existing tests must pass **unchanged**; needing to edit one means you changed behavior for the other types.
159
-
4.**`bun run lint`, `bun run check:api-validation`, `bun run check:client-boundary`** from the repo root.
158
+
3.**Run the suite** — `bun run --cwd apps/sim test lib/table 'app/workspace/[workspaceId]/tables' lib/api app/api/table app/api/v1`. Existing tests must pass **unchanged**; needing to edit one means you changed behavior for the other types.
159
+
4.**`bun run lint`, `bun run check:api-validation:strict`, `bun run check:client-boundary`** from the repo root.
160
160
5.**Exercise it in the running app** on a table with one column of every type: create, edit inline / in the expanded popover / in the row modal, paste from a spreadsheet, filter, sort, convert to and from other types, export CSV, undo a column delete.
0 commit comments