Skip to content

Commit 0030a36

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
Merge staging into Oracle Fusion foundation
Retain the Oracle origin and credential safeguards while respecting staging test cleanup. Adopt shared test mocks and keep unused internal types private for current audit compatibility.
2 parents 15294a2 + d9a6769 commit 0030a36

12,476 files changed

Lines changed: 2958763 additions & 588173 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/add-block-preview/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ To pull an already-GA block from discovery surfaces on hosted (incident, depreca
5353
- **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.
5454
- **Keys are registry block types.** Never `custom_block_*` (parse drops them — custom blocks have their own enabled/disabled lifecycle).
5555
- **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` (`apps/sim/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.
5757
- Gating is **surface hiding, not secrecy** — the full config ships in the client JS bundle. Anything truly secret cannot be a registered block.
5858

5959
## Tests

‎.agents/skills/add-block/SKILL.md‎

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export const {ServiceName}Block: BlockConfig = {
3535
docsLink: 'https://docs.sim.ai/integrations/{service}',
3636
category: 'tools', // 'tools' | 'blocks' | 'triggers'
3737
integrationType: IntegrationType.X, // Primary category (see IntegrationType enum)
38-
tags: ['oauth', 'api'], // Cross-cutting tags (see IntegrationTag type)
3938
bgColor: '#HEXCOLOR', // Brand color
4039
icon: {ServiceName}Icon,
4140

@@ -63,7 +62,7 @@ export const {ServiceName}Block: BlockConfig = {
6362
},
6463

6564
inputs: {
66-
// Optional: define expected inputs from other blocks
65+
// Required: the params the block accepts, keyed by tool param / canonical id
6766
},
6867

6968
outputs: {
@@ -74,7 +73,7 @@ export const {ServiceName}Block: BlockConfig = {
7473

7574
## SubBlock Types Reference
7675

77-
**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.
7877

7978
### Text Inputs
8079
```typescript
@@ -129,6 +128,7 @@ export const {ServiceName}Block: BlockConfig = {
129128
id: 'credential',
130129
title: 'Account',
131130
type: 'oauth-input',
131+
canonicalParamId: 'oauthCredential',
132132
serviceId: '{service}', // Must match OAuth provider service key
133133
requiredScopes: getScopesForService('{service}'), // Import from @/lib/oauth/utils
134134
placeholder: 'Select account',
@@ -310,7 +310,7 @@ When several fields are mutually exclusive alternatives, mark them all `required
310310
other paths ever get a chance to supply the value.
311311

312312
**Constraints (block-wide):**
313-
- `canonicalParamId` must not equal any subblock `id` in the block.
313+
- `canonicalParamId` may equal only the `id` of a member of its own group, as `channel` does in the canonicalParamId Pattern below; it must never equal any other subblock's `id`. (`blocks.test.ts` enforces the case of a subblock with no `canonicalParamId`.)
314314
- One canonical id links exactly one basic/advanced pair for one logical parameter. Groups are keyed by canonical id across every subblock and hold one `basicId`, so two operations that each need a pair need two canonical ids.
315315
- All members of a group share the same `required` status.
316316

@@ -370,8 +370,6 @@ Declare the **canonical** id with `type: 'json'` — the subblock ids never reac
370370
```typescript
371371
inputs: {
372372
file: { type: 'json', description: 'File to upload (UserFile or reference)' },
373-
// Legacy field for backwards compatibility
374-
fileContent: { type: 'string', description: 'Legacy: base64 encoded content' },
375373
}
376374
```
377375

@@ -500,6 +498,7 @@ Controls which UI view shows the field.
500498
- `'advanced'` - Only in advanced view
501499
- `'both'` - Both views (default if not specified)
502500
- `'trigger'` - Only in trigger configuration
501+
- `'trigger-advanced'` - The advanced side of a trigger field (a canonical pair member, or a standalone field under the block-level advanced toggle)
503502

504503
### canonicalParamId Pattern
505504

@@ -616,7 +615,7 @@ tools: {
616615
- `items` property - This is only for tool outputs with array types
617616

618617
Block outputs only support:
619-
- `type` - The data type ('string', 'number', 'boolean', 'json', 'array')
618+
- `type` - The data type ('string', 'number', 'boolean', 'json', 'array', 'file', 'file[]', 'any')
620619
- `description` - Human readable description
621620
- `condition` - Optional visibility condition
622621
- `hiddenFromDisplay` - Optional flag to hide from the output display
@@ -679,7 +678,7 @@ export const ServiceV2Block: BlockConfig = {
679678
access: ServiceBlock.tools?.access?.map(id => `${id}_v2`) || [],
680679
config: {
681680
tool: createVersionedToolSelector({
682-
baseToolSelector: (params) => (ServiceBlock.tools?.config as any)?.tool(params),
681+
baseToolSelector: (params) => ServiceBlock.tools.config?.tool(params) ?? 'service_default',
683682
suffix: '_v2',
684683
fallbackToolId: 'service_default_v2',
685684
}),
@@ -697,7 +696,7 @@ export const ServiceV2Block: BlockConfig = {
697696
Register the block in `apps/sim/blocks/registry-maps.ts` — add the import and an entry to each map alphabetically:
698697

699698
```typescript
700-
import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/service'
699+
import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/{service}'
701700

702701
export const BLOCK_REGISTRY: Record<string, BlockConfig> = {
703702
// ... existing blocks ...
@@ -726,11 +725,23 @@ export const ServiceBlock: BlockConfig = {
726725
docsLink: 'https://docs.sim.ai/integrations/service',
727726
category: 'tools',
728727
integrationType: IntegrationType.DeveloperTools,
729-
tags: ['oauth', 'api'],
730728
bgColor: '#FF6B6B',
731729
icon: ServiceIcon,
732730
authMode: AuthMode.OAuth,
733731

732+
// Sentence rules: apps/sim/blocks/AGENTS.md → "Canvas sentences"
733+
canvasPresentation: {
734+
defaultTitle: 'Create Resource',
735+
sentences: {
736+
byOperation: {
737+
create: [{ text: 'Create resource', field: 'name', core: true }],
738+
read: [{ text: 'Read resource', field: 'resourceId', core: true }],
739+
update: [{ text: 'Update resource', field: 'resourceId', core: true }],
740+
delete: [{ text: 'Delete resource', field: 'resourceId', core: true }],
741+
},
742+
},
743+
},
744+
734745
subBlocks: [
735746
{
736747
id: 'operation',
@@ -748,6 +759,7 @@ export const ServiceBlock: BlockConfig = {
748759
id: 'credential',
749760
title: 'Service Account',
750761
type: 'oauth-input',
762+
canonicalParamId: 'oauthCredential',
751763
serviceId: 'service',
752764
requiredScopes: getScopesForService('service'),
753765
placeholder: 'Select account',
@@ -778,6 +790,13 @@ export const ServiceBlock: BlockConfig = {
778790
},
779791
},
780792

793+
inputs: {
794+
operation: { type: 'string', description: 'Operation to perform' },
795+
oauthCredential: { type: 'string', description: 'Service access token' },
796+
resourceId: { type: 'string', description: 'Resource ID' },
797+
name: { type: 'string', description: 'Resource name' },
798+
},
799+
781800
outputs: {
782801
id: { type: 'string', description: 'Resource ID' },
783802
name: { type: 'string', description: 'Resource name' },
@@ -902,16 +921,16 @@ Every block declares a one-line prose summary that replaces its card's field row
902921

903922
```
904923
Slack ← header (already names the block)
905-
Posts ⟨Ship it 🚀⟩ to ⟨#eng⟩ ← the sentence; ⟨…⟩ are live value chips
924+
Post ⟨Ship it 🚀⟩ to ⟨#eng⟩ ← the sentence; ⟨…⟩ are live value chips
906925
```
907926

908927
Write one `byOperation` entry per operation dropdown option (or a single `default`
909928
when the block has no operation dropdown).
910929

911-
**The full authoring contract — voice, structure, and the two mistakes that break
930+
**The full authoring contract — voice, structure, and the four mistakes that break
912931
cards silently — is `apps/sim/blocks/AGENTS.md` → "Canvas sentences". Read it
913-
before writing any.** The two failures worth repeating here, because both are
914-
invisible at runtime:
932+
before writing any.** Two of those four are worth repeating here, because both
933+
are invisible at runtime:
915934

916935
1. A clause naming only one member of a `canonicalParamId` pair drops the sentence
917936
for every advanced-mode user. List all members:
@@ -927,35 +946,27 @@ bun run apps/sim/scripts/check-canvas-sentences.ts --block={service}
927946

928947
## Generated artifacts
929948

949+
When adding or changing `sunset.replacedBy`, run `bun run generate:block-successors` and commit
950+
`apps/sim/lib/permission-groups/block-successors.generated.ts`. Authorization uses this generated
951+
map to resolve legacy and current block IDs consistently without importing the executable registry.
952+
Verify it with `bun run check:block-successors`.
953+
930954
Adding a block on its own needs no **tool metadata** regeneration — a block references existing
931955
tool IDs through `tools.access` and does not change any tool's shape.
932956

933957
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`.
934958

935-
A visible integration block does require the generated integration catalog and docs to be refreshed.
936-
After adding or changing one, run:
937-
938-
```bash
939-
bun run scripts/generate-docs.ts
940-
bun run deployment-config:generate
941-
bun run integration-catalog:check
942-
bun run deployment-config:check
943-
bun run docs:check
944-
```
945-
946-
The catalog check independently derives deployment metadata from the executable block registry and
947-
compares it with the committed `packages/deployment-config/src/integrations.json`. The deployment
948-
config check verifies the generated service-account facts against the canonical OAuth registry and
949-
catalog. `docs:check` re-renders every generated docs artifact in memory and fails on any committed
950-
file that differs — it runs in CI via `check:audits`, so commit the full generator output. If the
951-
generator also trues up pages an earlier PR left stale, commit that catch-up too; reverting it as
952-
"unrelated drift" makes `docs:check` fail. Review the generated diff and keep only intentional
953-
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.
954965

955966
## Checklist Before Finishing
956967

957968
- [ ] `integrationType` is set to the correct `IntegrationType` enum value
958-
- [ ] `tags` array includes all applicable `IntegrationTag` values
969+
- [ ] `{Service}BlockMeta.tags` lists every applicable `IntegrationTag` (tags live on the meta, not the block)
959970
- [ ] All subBlocks have `id`, `title` (except switch), and `type`
960971
- [ ] Conditions use correct syntax (field, value, not, and)
961972
- [ ] DependsOn set for fields that need other values
@@ -969,6 +980,7 @@ changes.
969980
- [ ] Tools.config.tool returns correct tool ID (snake_case)
970981
- [ ] Outputs match tool outputs
971982
- [ ] Block + meta registered in registry-maps.ts (`BLOCK_REGISTRY` / `BLOCK_META_REGISTRY`)
983+
- [ ] If `sunset.replacedBy` changed: regenerated and committed the block successor map; `bun run check:block-successors` passes
972984
- [ ] If any tool was added, changed or removed alongside the block: ran `bun run tool-metadata:generate` and committed the artifacts
973985
- [ ] Ran `bun run scripts/generate-docs.ts`, reviewed the generated diff, and committed the integration catalog changes
974986
- [ ] `bun run integration-catalog:check` passes
@@ -990,7 +1002,7 @@ Validate the block against every tool in `tools.access`:
9901002
2. **For each tool, verify the block has correct:**
9911003
- SubBlock inputs that cover all required tool params (with correct `condition` to show for that operation)
9921004
- SubBlock input types that match the tool param types (e.g., dropdown for enums, short-input for strings)
993-
- `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
9941006
- Type coercions in `tools.config.params` for any params that need conversion (Number(), Boolean(), JSON.parse())
9951007
3. **Verify block outputs** cover the key fields returned by all tools
9961008
4. **Verify conditions** — each subBlock should only show for the operations that actually use it

‎.agents/skills/add-column-type/SKILL.md‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ A `case 'yourtype':` outside `column-types/` fails **silently** when missed (a w
1212

1313
## Hard Rule: the compiler tells you what to do
1414

15-
Do **not** hunt for places to edit. Add your type to 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:
1616

1717
```bash
1818
cd apps/sim && bun run type-check
@@ -86,7 +86,7 @@ export function Type{Pascal}(props: SVGProps<SVGSVGElement>) {
8686

8787
## Step 3: Write the type file
8888

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.
9090

9191
The three that are easy to get wrong:
9292

@@ -132,29 +132,29 @@ Registering the *type* is compiler-enforced. Registering its *metadata* is not,
132132
| `column-types/types.ts` `TYPE_SPECIFIC_COLUMN_KEYS` | it is never stripped on conversion, and poisons the target type |
133133
| `lib/api/contracts/tables.ts` — the schema slot in all three column schemas, plus `refineColumnOptions` | zod strips it at the boundary; silently never saved |
134134
| `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 |
136136
| `column-config-sidebar.tsx` | no UI to set it |
137137
| `table-grid.tsx` delete-column undo + `use-table-undo.ts` restore | undo silently resets it to the default |
138138

139139
`normalizeColumn`, `buildConvertedColumn`, and the undo snapshot read `TYPE_SPECIFIC_COLUMN_KEYS` generically, so those three are already zero-edit.
140140

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.
142142

143143
## Checklist Before Finishing
144144

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
147147
- [ ] Registered in **both** `registry.ts` and `registry.server.ts`
148148
- [ ] Icon added, centered on the family's optical center, exported alphabetically
149149
- [ ] `migrateCellsTo` / `migrateCellsFrom` added if the stored bytes change
150150
- [ ] New metadata keys added to `TYPE_SPECIFIC_COLUMN_KEYS` + `FOREIGN_METADATA_VERB`
151-
- [ ] Unit tests for `coerce` / `isCompatibleWith` round-trips, verified to fail without the code
151+
- [ ] Unit tests for `coerce` / `isCompatibleWith` round-trips only if they pass the `test-audit` authoring gate, verified to fail without the code
152152
- [ ] Docs row added to `apps/docs/content/docs/tables/index.mdx`
153153

154154
## Final Validation (Required)
155155

156156
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.
157157
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** — `bunx vitest run 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:check`, `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.
160160
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

Comments
 (0)