From 7438455b8d75d140e2690a29a95bc4b9abf18d9b Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Thu, 1 Oct 2026 17:08:07 -0700 Subject: [PATCH 01/18] fix(audits): guard the route wrapper against lib/mothership, not the removed lib/copilot The Copilot modules moved to lib/mothership in the v1.0.0 rename, so the route-wrapper graph guard was banning a directory that no longer exists. --- scripts/check-application-graph.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/check-application-graph.ts b/scripts/check-application-graph.ts index 0281bde0a2c..c049f410816 100644 --- a/scripts/check-application-graph.ts +++ b/scripts/check-application-graph.ts @@ -108,7 +108,7 @@ const ROUTE_WRAPPER_FORBIDDEN_PREFIXES: Record = { 'the permission-group resolver — the wrapper only opens the memo scope; the resolver ' + 'belongs to the gate call sites, and it is what dragged billing in', 'lib/auth': 'the auth graph — the wrapper wraps handlers that authenticate, it does not', - 'lib/copilot/': 'the copilot graph', + 'lib/mothership/': 'the Mothership (Chat agent) graph', 'lib/knowledge/': 'the knowledge-base graph', } From fcfecd7e0913e0ff26a3c3173c659267fafb28f7 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Thu, 1 Oct 2026 17:08:09 -0700 Subject: [PATCH 02/18] improvement(audits): add check:guidance-refs and fix the stale references it found Agent guidance (CLAUDE.md, every AGENTS.md, .claude/rules, .agents/skills) names paths, scripts, skills, and import specifiers that agents follow literally. The new audit resolves each one and fails on any that no longer exists. Fixes the references it found: lib/copilot -> lib/mothership, stores/workflows/store -> stores/workflows/workflow/store, a relative landing path, deleted selector-provider and legacy landing mentions, and illustrative example imports rewritten as placeholders. --- .agents/skills/add-block/SKILL.md | 2 +- .agents/skills/add-enrichment/SKILL.md | 2 +- .agents/skills/add-integration/SKILL.md | 4 +- .../skills/add-permission-group-item/SKILL.md | 2 +- .agents/skills/add-selector/SKILL.md | 2 +- .../migrate-application-operation/SKILL.md | 10 +- .agents/skills/ship/SKILL.md | 4 +- .claude/rules/landing-seo-geo.md | 2 +- .claude/rules/sim-imports.md | 4 +- .claude/rules/sim-queries.md | 2 +- .claude/rules/sim-stores.md | 2 +- .claude/rules/sim-testing.md | 2 +- .claude/rules/sim-url-state.md | 6 +- .cursor/rules/landing-seo-geo.mdc | 2 +- .cursor/rules/sim-imports.mdc | 4 +- .cursor/rules/sim-queries.mdc | 2 +- .cursor/rules/sim-stores.mdc | 2 +- .cursor/rules/sim-testing.mdc | 2 +- .cursor/rules/sim-url-state.mdc | 6 +- apps/sim/app/(landing)/CLAUDE.md | 2 +- package.json | 1 + scripts/check-guidance-refs.ts | 320 ++++++++++++++++++ 22 files changed, 353 insertions(+), 32 deletions(-) create mode 100644 scripts/check-guidance-refs.ts diff --git a/.agents/skills/add-block/SKILL.md b/.agents/skills/add-block/SKILL.md index 24a0366b91f..27628cccf18 100644 --- a/.agents/skills/add-block/SKILL.md +++ b/.agents/skills/add-block/SKILL.md @@ -697,7 +697,7 @@ export const ServiceV2Block: BlockConfig = { Register the block in `apps/sim/blocks/registry-maps.ts` — add the import and an entry to each map alphabetically: ```typescript -import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/service' +import { ServiceBlock, ServiceBlockMeta } from '@/blocks/blocks/{service}' export const BLOCK_REGISTRY: Record = { // ... existing blocks ... diff --git a/.agents/skills/add-enrichment/SKILL.md b/.agents/skills/add-enrichment/SKILL.md index 34810e72f41..7a3a33c4664 100644 --- a/.agents/skills/add-enrichment/SKILL.md +++ b/.agents/skills/add-enrichment/SKILL.md @@ -118,7 +118,7 @@ Rules: In `apps/sim/enrichments/registry.ts`, import and add the entry (catalog order is registration order): ```typescript -import { myEnrichment } from '@/enrichments/my-enrichment' +import { myEnrichment } from '@/enrichments/{id}/{id}' export const ENRICHMENT_REGISTRY: EnrichmentRegistry = { // ...existing diff --git a/.agents/skills/add-integration/SKILL.md b/.agents/skills/add-integration/SKILL.md index 865681fa09b..4d5a8e51713 100644 --- a/.agents/skills/add-integration/SKILL.md +++ b/.agents/skills/add-integration/SKILL.md @@ -128,8 +128,8 @@ Three rules that are easy to get wrong when copying from existing blocks: - Every remote `selectorKey` must use the unified server selector path. Apply the `add-selector` skill: add browser-safe metadata to `apps/sim/lib/selectors/manifest.ts`, reuse or extract a server-only provider listing primitive, and add a credential- and destination-bound server attachment. Do not - add code under `hooks/selectors/providers`, a provider-specific query key, browser token acquisition, - or a selector-only API route. The shared context builder sends only active `dependsOn` values and + add a client provider fetcher, a provider-specific query key, browser token acquisition, or a + selector-only API route. The shared context builder sends only active `dependsOn` values and preserves exact `{{KEY}}` environment references for server-side resolution. - A `canonicalParamId` is a third name that neither member of a basic/advanced pair uses as its `id` (e.g. `channelSelector` + `channelId` → `canonicalParamId: 'channel'`). It is the only key that diff --git a/.agents/skills/add-permission-group-item/SKILL.md b/.agents/skills/add-permission-group-item/SKILL.md index 43ff11e4106..e0cb4447eeb 100644 --- a/.agents/skills/add-permission-group-item/SKILL.md +++ b/.agents/skills/add-permission-group-item/SKILL.md @@ -197,7 +197,7 @@ Add a case to `capabilities.test.ts` for any rule with logic beyond reading one | Guarded root | Forbidden | |---|---| | `lib/core/application/index.ts`, and `lib/permission-groups/` `capabilities.ts` / `capability-assertions.ts` / `config-scope.server.ts` | `providers/`, `blocks/`, `tools/`, `executor/`, `lib/uploads/`, `lib/workflows/` | -| `lib/core/utils/with-route-handler.ts` | those six **plus** `lib/billing/`, `lib/permission-groups/resolve.server`, `lib/auth`, `lib/copilot/`, `lib/knowledge/` | +| `lib/core/utils/with-route-handler.ts` | those six **plus** `lib/billing/`, `lib/permission-groups/resolve.server`, `lib/auth`, `lib/mothership/`, `lib/knowledge/` | `lib/billing/` stays allowed for the funnel roots because `resolve.server.ts` legitimately reads the subscription to decide whether an organization is on an enterprise plan; the wrapper is a lifecycle shim that opens the memo scope and nothing more. That split is why the scope is two files. diff --git a/.agents/skills/add-selector/SKILL.md b/.agents/skills/add-selector/SKILL.md index 3c4f0099f9d..439b16a61f6 100644 --- a/.agents/skills/add-selector/SKILL.md +++ b/.agents/skills/add-selector/SKILL.md @@ -98,7 +98,7 @@ Keep connector selector/manual canonical pairs and fork reconfiguration behavior Do not add: -- A module under `hooks/selectors/providers` or any client provider fetcher. +- A client provider fetcher. - A provider-specific React Query key. - A selector-specific OAuth-token request. - A selector-only API route when the provider primitive can be called directly. diff --git a/.agents/skills/migrate-application-operation/SKILL.md b/.agents/skills/migrate-application-operation/SKILL.md index 47ea0d2b618..25774902091 100644 --- a/.agents/skills/migrate-application-operation/SKILL.md +++ b/.agents/skills/migrate-application-operation/SKILL.md @@ -47,16 +47,16 @@ Read these files completely before editing: - `apps/sim/lib/api/server/routes/internal-json-route.ts` - `apps/sim/lib/api/server/routes/v2-json-route.ts` - `apps/sim/lib/auth/internal-delegation.ts` -- `apps/sim/lib/copilot/application/application-adapter.ts` -- `apps/sim/lib/copilot/auth/application-delegation.ts` +- `apps/sim/lib/mothership/application/application-adapter.ts` +- `apps/sim/lib/mothership/auth/application-delegation.ts` Use the file domain only as a representative golden slice: - `apps/sim/lib/workspace-files/application/operations.ts` - `apps/sim/lib/workspace-files/application/authorized-workspace-file-use-case.ts` - `apps/sim/lib/workspace-files/application/rename-workspace-file.ts` -- `apps/sim/lib/copilot/application/execute-file-use-case.ts` -- `apps/sim/lib/copilot/auth/file-delegation.ts` +- `apps/sim/lib/mothership/application/execute-file-use-case.ts` +- `apps/sim/lib/mothership/auth/file-delegation.ts` Then read the target domain's operation registry, application code, repositories, contracts, adapters, aliases, resume paths, and focused tests. Fail immediately if the shared foundation is absent. Do not recreate it inside the domain. @@ -250,7 +250,7 @@ Keep v1 middleware and routes unchanged unless explicitly included. ## Adapt Copilot -Copilot is a surface adapter, not a separate application layer. If an HTTP or other surface already uses an application use case, Copilot must call that exact use case rather than reimplementing protected business behavior under `lib/copilot`. +Copilot is a surface adapter, not a separate application layer. If an HTTP or other surface already uses an application use case, Copilot must call that exact use case rather than reimplementing protected business behavior under `lib/mothership`. Create one domain-level Copilot application adapter with `createCopilotApplicationAdapter` instead of constructing delegated principals in every tool: diff --git a/.agents/skills/ship/SKILL.md b/.agents/skills/ship/SKILL.md index 300118c485e..39fdae0dd29 100644 --- a/.agents/skills/ship/SKILL.md +++ b/.agents/skills/ship/SKILL.md @@ -48,7 +48,7 @@ When the user runs `/ship`: - `bun run check:migrations origin/staging` must pass (staging is the PR base). Do not silence a flagged statement with a `-- migration-safe:` annotation unless `/db-migrate` confirmed the old code no longer depends on it; otherwise split the destructive change into a later deploy. 6. **Run pre-ship checks** from the repo root before staging. This has two phases: first **regenerate** every committed artifact so generated files never drift into a CI failure (this is what catches things like `agent-stream-docs` going stale after a `models.ts` edit), then run the **full audit suite** CI's `Lint and Test` job enforces. Both phases parallelize — but only across commands that write **disjoint** outputs — and a bare `wait` swallows child exit codes, so both phases below explicitly collect each job's status and abort ship if any failed. - **Phase A — regenerate the always-in-repo committed artifacts (parallel), then let step 7 stage whatever changed.** Regenerate only the generators whose inputs live entirely in this repo and that any ordinary code change can drift — `agent-stream-docs:generate` (derives from the provider model registry), `docs-manifest:generate` (derives from docs page paths), and `skills:sync` (derives from `.agents/skills/**`). They write disjoint outputs (`apps/docs/…/agent.mdx`, `apps/sim/lib/copilot/generated/docs-manifest.ts`, and `.claude/skills` links), so they parallelize safely, and each is idempotent (a no-op when already in sync): + **Phase A — regenerate the always-in-repo committed artifacts (parallel), then let step 7 stage whatever changed.** Regenerate only the generators whose inputs live entirely in this repo and that any ordinary code change can drift — `agent-stream-docs:generate` (derives from the provider model registry), `docs-manifest:generate` (derives from docs page paths), and `skills:sync` (derives from `.agents/skills/**`). They write disjoint outputs (`apps/docs/…/agent.mdx`, `apps/sim/lib/mothership/generated/docs-manifest.ts`, and `.claude/skills` links), so they parallelize safely, and each is idempotent (a no-op when already in sync): ```bash rm -f /tmp/ship-gen-results for g in agent-stream-docs:generate docs-manifest:generate skills:sync; do @@ -63,7 +63,7 @@ When the user runs `/ship`: ``` Then `git status --short` to see what regenerated — those files must be staged in step 7 alongside your own changes. - **Do NOT blanket-run the domain generators here.** `mship:generate` (`generate-mship-contracts.ts`) is an **umbrella** that drives all nine mothership contract generators (`mship-contracts`, `billing-protocol-contract`, `mship-tools`, the four `trace-*`, `metrics-contract`, `vfs-snapshot-contract`) and biome-formats `apps/sim/lib/copilot/generated/` — never run it *and* its constituents (they write the same files and corrupt each other in parallel), and never run it on an ordinary ship: it reads an **external** copilot-contract source that isn't checked out in most worktrees, so it hard-fails with `ENOENT` and would abort ship for an unrelated reason. `generate:pi-model-catalog` (under `apps/sim`) likewise regenerates from the installed Pi package, not repo source. `scripts/generate-docs.ts` rewrites the integration docs and client-safe catalog; run it when this PR changes their block/icon/landing-content inputs or when `integration-catalog:check` reports drift, then review its broad generated diff. Only when **this PR's diff actually touches** a domain generator's input do you regenerate it deliberately and run its matching `:check` (`bun run mship:check` / the individual `*:check`) — with the external source present. + **Do NOT blanket-run the domain generators here.** `mship:generate` (`generate-mship-contracts.ts`) is an **umbrella** that drives all nine mothership contract generators (`mship-contracts`, `billing-protocol-contract`, `mship-tools`, the four `trace-*`, `metrics-contract`, `vfs-snapshot-contract`) and biome-formats `apps/sim/lib/mothership/generated/` — never run it *and* its constituents (they write the same files and corrupt each other in parallel), and never run it on an ordinary ship: it reads an **external** copilot-contract source that isn't checked out in most worktrees, so it hard-fails with `ENOENT` and would abort ship for an unrelated reason. `generate:pi-model-catalog` (under `apps/sim`) likewise regenerates from the installed Pi package, not repo source. `scripts/generate-docs.ts` rewrites the integration docs and client-safe catalog; run it when this PR changes their block/icon/landing-content inputs or when `integration-catalog:check` reports drift, then review its broad generated diff. Only when **this PR's diff actually touches** a domain generator's input do you regenerate it deliberately and run its matching `:check` (`bun run mship:check` / the individual `*:check`) — with the external source present. **Phase B — run lint + every audit CI enforces, in parallel, and abort ship if any fails.** Before running the commands, compare this list with `.github/workflows/test-build.yml`; when CI adds an audit, run it and update this skill instead of trusting a stale snapshot. The env-flag audit is currently an inline workflow block rather than a package script: when `apps/sim/lib/core/config/env-flags.ts` changed, run that current workflow block verbatim instead of copying a second version into this skill. Run `bun run lint` first (it autofixes formatting and mutates files, so don't parallelize it with the read-only audits), then run the base-sensitive block-registry check, then fan the independent audits out and collect exit codes: ```bash diff --git a/.claude/rules/landing-seo-geo.md b/.claude/rules/landing-seo-geo.md index 12752a34b56..d603c2723e7 100644 --- a/.claude/rules/landing-seo-geo.md +++ b/.claude/rules/landing-seo-geo.md @@ -16,7 +16,7 @@ paths: - All internal navigation uses Next.js `` with real `href`s — never `onClick` navigation. External links get `rel="noopener noreferrer"`. - All copy is server-rendered text: no text baked into images, no content that exists only after a client effect runs. - Navbar is a Server Component (no `'use client'`) for immediate crawlability. Logo `` has `priority` (LCP element). The navbar `