Skip to content

Commit 61b9fbd

Browse files
committed
Merge remote-tracking branch 'origin/improvement/platform-core-chat' into test/chat-steering-e2e-final
The org conversation moved to app/_organization-conversation; the wiring test takes the composer type from there. Two new delivery-pass tests counted disposition reads as steers; they now count reads on the read route.
2 parents 5e4f1c6 + 6693cfc commit 61b9fbd

534 files changed

Lines changed: 7318 additions & 4511 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/implement-platform/SKILL.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ Start in the Sim checkout containing the requested product work. Read the [Platf
1313
3. **Choose or change the owner.** Start with the behavior. An action, navigation row, value picker, or disclosure has an existing keyboard and pointer contract. Different interactions may share visual roles while retaining different semantics. Use the existing family and named props for a change in size, intent, icon, or content. Put unique anatomy and its CSS beside the route component. Keep page files free of styling. Only EMCN owns the appearance of its controls. Use Base UI there for complex keyboard, floating, and dismissal behavior.
1414
4. **Trace the full change.** On a second independent feature use, promote the original implementation and migrate both callers. For consolidation, compare semantics, map every consumer to its replacement, then remove the obsolete implementation, export, variant styles, and unused registrations. For deletion, also check menus, preferences, fixture data, workbench references, and tests that existed only for the removed feature. Preserve unrelated consumers and historical Paper evidence. A new variant needs a reachable product use. Edit the source or compiler for generated foundations and recipes.
1515
5. **Verify where people use it.** Run the design audit and applicable checks from the README. Render the changed product route with empty, full, stress, and fixture-off data as relevant. Check both themes, widths between artboards, long content, text scaling, keyboard, and pointer states. Compare shared controls in their actual consumers. Check the actual scroll edge and the open popup when space is tight. For shell, panel, or desktop work, exercise the real Electron renderer. For substantial implementations and consolidations, use an independent agent during design or implementation and for a final review of the changed owners and routes. Provide the working localhost route for visual review.
16-
6. **Keep decisions durable.** Follow the contract’s maintenance guidance when an approved correction changes a shared rule. Record feature-specific decisions with their feature. For sustained work, keep a task checkpoint with the code revision, verified states, evidence, and outstanding work. Include the branch or PR, checkpoint path, and localhost route in a handoff. On resumption, compare the checkpoint with the current branch, working tree, and relevant live sources before acting.
16+
6. **Keep non-UI code in one place.** When work touches both the zone and `apps/sim/platform/embedded`, converge first rather than porting: only markup may differ. Follow "Converging a domain" in `apps/sim/platform/AGENTS.md`; `bun run check:platform-convergence` fails a new parallel file.
17+
7. **Keep decisions durable.** Follow the contract’s maintenance guidance when an approved correction changes a shared rule. Record feature-specific decisions with their feature. For sustained work, keep a task checkpoint with the code revision, verified states, evidence, and outstanding work. Include the branch or PR, checkpoint path, and localhost route in a handoff. On resumption, compare the checkpoint with the current branch, working tree, and relevant live sources before acting.

‎.claude/rules/sim-platform-views.md‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
description: One pattern per job across the organization views (Settings, People, Integrations, Links, Home)
33
paths:
44
- "apps/sim/platform/embedded/app/(shell)/{settings,people,integrations,links,home}/**"
5+
- "apps/sim/platform/embedded/lib/**"
6+
- "apps/sim/platform/shared/**"
57
- "apps/sim/platform/design-system/components/{status,modal,picker,settings-section,search-field,activity-row}/**"
68
- "apps/sim/app/o/*/**"
79
- "apps/sim/app/o/*/settings/**"
@@ -56,9 +58,13 @@ user activation is spent, `cancel` cannot be prevented, so `OverlayDialog` reope
5658
- A section with more than one job splits by job: `group-detail.tsx` is the shell, `group-general-tab.tsx`
5759
and `group-catalog-tabs.tsx` its bodies, `use-group-draft.ts` its write.
5860
- Merge logic worth a test is a pure module next to the view, such as `secrets-draft.ts`.
59-
- `section-parts/` holds what only settings needs: `SectionStack`, `FieldStack`, `SectionToolbar`,
61+
- `(shell)/_components/section-parts/` holds what settings and the secrets page share: `SectionStack`, `FieldStack`, `SectionToolbar`,
6062
`DetailHeader`, `HeadingRow`, `Muted`, `SectionSkeleton`, `DraftConflictNotice`. `useServerDraft` is in `_components/`, since Integrations uses it too.
6163

64+
## Non-UI code lives once
65+
66+
A view's data and logic belong in `apps/sim/platform/embedded/lib/data` when only these views use them, and in `apps/sim/platform/shared` when the zone has the same thing. A view reads hooks through that layer; a real adapter owns the mutation, its toasts and any mapping, and is never a re-export. Before adding a file to `embedded/`, look for its counterpart under `apps/sim/platform/lib` and follow "Converging a domain" in `apps/sim/platform/AGENTS.md`. `check:platform-convergence` fails a new file here or a new path both trees hold.
67+
6268
## Legacy workspace settings
6369

6470
`apps/sim/app/workspace/*/settings/**` keeps `SettingsPanel` from `@/components/settings/settings-panel`,

‎.cursor/rules/sim-platform-views.mdc‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
description: "One pattern per job across the organization views (Settings, People, Integrations, Links, Home)"
3-
globs: ["apps/sim/platform/embedded/app/(shell)/{settings,people,integrations,links,home}/**","apps/sim/platform/design-system/components/{status,modal,picker,settings-section,search-field,activity-row}/**","apps/sim/app/o/*/**","apps/sim/app/o/*/settings/**"]
3+
globs: ["apps/sim/platform/embedded/app/(shell)/{settings,people,integrations,links,home}/**","apps/sim/platform/embedded/lib/**","apps/sim/platform/shared/**","apps/sim/platform/design-system/components/{status,modal,picker,settings-section,search-field,activity-row}/**","apps/sim/app/o/*/**","apps/sim/app/o/*/settings/**"]
44
---
55

66
<!-- Generated from .claude/rules/sim-platform-views.md by `bun run skills:sync`. Edit the source, not this file. -->
@@ -54,9 +54,13 @@ user activation is spent, `cancel` cannot be prevented, so `OverlayDialog` reope
5454
- A section with more than one job splits by job: `group-detail.tsx` is the shell, `group-general-tab.tsx`
5555
and `group-catalog-tabs.tsx` its bodies, `use-group-draft.ts` its write.
5656
- Merge logic worth a test is a pure module next to the view, such as `secrets-draft.ts`.
57-
- `section-parts/` holds what only settings needs: `SectionStack`, `FieldStack`, `SectionToolbar`,
57+
- `(shell)/_components/section-parts/` holds what settings and the secrets page share: `SectionStack`, `FieldStack`, `SectionToolbar`,
5858
`DetailHeader`, `HeadingRow`, `Muted`, `SectionSkeleton`, `DraftConflictNotice`. `useServerDraft` is in `_components/`, since Integrations uses it too.
5959

60+
## Non-UI code lives once
61+
62+
A view's data and logic belong in `apps/sim/platform/embedded/lib/data` when only these views use them, and in `apps/sim/platform/shared` when the zone has the same thing. A view reads hooks through that layer; a real adapter owns the mutation, its toasts and any mapping, and is never a re-export. Before adding a file to `embedded/`, look for its counterpart under `apps/sim/platform/lib` and follow "Converging a domain" in `apps/sim/platform/AGENTS.md`. `check:platform-convergence` fails a new file here or a new path both trees hold.
63+
6064
## Legacy workspace settings
6165

6266
`apps/sim/app/workspace/*/settings/**` keeps `SettingsPanel` from `@/components/settings/settings-panel`,

‎.github/CI.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ Every HTTP and browser group consumes the same production build in an isolated j
4646

4747
The Platform's fixture and live suites stay in `platform-design.yml`, outside `checks / ci`. The HTTP and production matrices consume one `next-build` artifact, built without `SIM_PLATFORM_ORIGIN`, while the `zone` topology bakes that origin into its rewrite and also builds the Platform app, so it needs its own job, gate flag and plan output rather than a suite entry. A task that depends on `ci:shared` would select two 16-vCPU jobs of up to 75 minutes for nearly every app PR and hold every staging push's deployment gate on them. The cost is that a red run is advisory, and a path-filtered workflow cannot be a required check: one that never starts never reports, so the status does not block a merge until the suite joins the aggregate.
4848

49+
The `zone` job runs its build through several phases on one database: the suite, the zone gone, the zone answering 503, the zone back, the flag off, flags read from a fixture of AppConfig's service with one organization targeted, and misconfigured zones that must refuse to start. The `flag-off` job runs its no-zone build, then the same build self-hosted. The two cannot read each other's reports, so `check:platform-parity --job` holds each to its own rows.
50+
4951
Desktop inbox protocol, assistant actions UI, and organization search UI run as three parallel HTTP jobs with isolated databases, apps, and reports. Each harness owns its acceptance task, so an edit selects its own job. The inbox protocol task depends on server and realtime code; the browser tasks also depend on workspace UI. Desktop inbox needs no browser. The UI jobs and browser extension install Chromium while their app starts, waiting for both before executing assertions; browser-install failures still fail the job and preserve the install log. No acceptance assertions are removed by the split.
5052

5153
Live Electron acceptance tracks its live-app suite, fixtures, and Playwright configuration separately from shell-only smoke tests. Changing a shell-only smoke case runs the dedicated desktop workflow without starting the app's production build and live lease checks.

‎.github/scripts/http-e2e.sh‎

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ platform_pid=''
3636
platform_tag=''
3737
platform_log=''
3838
agent_pid=''
39+
failing_zone_pid=''
40+
appconfig_pid=''
3941
browsers_pid=''
4042
local_app_url=''
4143
# `dev` or `start`; a group sets it before start_app.
@@ -78,6 +80,14 @@ finish() {
7880
kill "$agent_pid" 2>/dev/null || true
7981
wait "$agent_pid" 2>/dev/null || true
8082
fi
83+
if [ -n "$failing_zone_pid" ]; then
84+
kill "$failing_zone_pid" 2>/dev/null || true
85+
wait "$failing_zone_pid" 2>/dev/null || true
86+
fi
87+
if [ -n "$appconfig_pid" ]; then
88+
kill "$appconfig_pid" 2>/dev/null || true
89+
wait "$appconfig_pid" 2>/dev/null || true
90+
fi
8191
if [ -n "$browsers_pid" ]; then
8292
kill -- "-$browsers_pid" 2>/dev/null || true
8393
wait "$browsers_pid" 2>/dev/null || true
@@ -162,11 +172,18 @@ start_platform() {
162172
platform_log="$report_dir/platform-live-platform.log"
163173
E2E_APP="$platform_tag" SIM_PLATFORM_API_ORIGIN="$local_app_url" SIM_PLATFORM_BASE_PATH=/org setsid node \
164174
../../node_modules/next/dist/bin/next start platform --hostname 127.0.0.1 --port "$port" \
165-
> "$platform_log" 2>&1 &
175+
>> "$platform_log" 2>&1 &
166176
platform_pid=$!
167177
wait_ready "$platform_pid" "http://127.0.0.1:$port/org" 'Platform zone'
168178
}
169179

180+
# stop_platform: takes the zone away from under a running main app, as an outage does.
181+
stop_platform() {
182+
bash "$GITHUB_WORKSPACE/.github/scripts/stop-session.sh" "$platform_pid" "$platform_tag"
183+
wait "$platform_pid" 2>/dev/null || true
184+
platform_pid=''
185+
}
186+
170187
# platform_live_environment: one hosted Enterprise organization, the deterministic seed its specs
171188
# read, and a scripted worker in place of the model. Hosted is decided by the app's hostname, which
172189
# the job maps to loopback. Google and Microsoft answer only to real credentials, so those clients
@@ -208,6 +225,8 @@ platform_live_environment() {
208225
export PLATFORM_LIVE_ROLE_TARGET_EMAIL=rae@platform-live.test
209226
export PLATFORM_LIVE_REMOVABLE_EMAIL=remy@platform-live.test
210227
export PLATFORM_LIVE_REFUSED_INVITE_EMAIL=otto@platform-live.test
228+
export PLATFORM_LIVE_OFF_ORGANIZATION_ID=platform-live-organization-off
229+
export PLATFORM_LIVE_OFF_EMAIL=odessa@platform-live.test
211230
export PLATFORM_LIVE_ORCHESTRATOR=1
212231
bun --no-env-file scripts/platform-live-seed.ts
213232
}
@@ -488,9 +507,11 @@ JS
488507
bun run test:landing-seo:e2e
489508
;;
490509

491-
# The zone as deployed: flag on, /org rewritten to the Platform build. Then the same build
492-
# with the flag off, which must put everyone back on the legacy surface. Both report, whichever
493-
# fails.
510+
# The zone as deployed: flag on, /org rewritten to the Platform build. Then, on that running app,
511+
# the zone goes away, answers 503 to everything, and comes back. Then the same build with the flag
512+
# off, which must put everyone back on the legacy surface. Then that build with its flags read from
513+
# AppConfig, the real rollout path, targeting one organization by id. Last, that zone's build
514+
# misconfigured, which must refuse to start. Every phase reports, whichever fails.
494515
platform-live-zone)
495516
platform_live_environment
496517
export SIM_PLATFORM_ORIGIN=http://127.0.0.1:3028
@@ -504,21 +525,56 @@ JS
504525
wait_for_browsers
505526
live_status=0
506527
run_platform_live zone platform-live || live_status=$?
528+
stop_platform
529+
run_platform_live zone-down platform-live-zone-down || live_status=$?
530+
bun --no-env-file platform/checks/live/support/failing-zone.ts 3028 \
531+
> "$report_dir/platform-live-failing-zone.log" 2>&1 &
532+
failing_zone_pid=$!
533+
wait_ready "$failing_zone_pid" http://127.0.0.1:3028/health 'failing zone'
534+
run_platform_live zone-down platform-live-zone-5xx || live_status=$?
535+
kill "$failing_zone_pid"
536+
wait "$failing_zone_pid" 2>/dev/null || true
537+
failing_zone_pid=''
538+
start_platform 3028
539+
run_platform_live zone-recovered platform-live-zone-recovered || live_status=$?
507540
stop_app
508541
start_app platform-live-flag-off 3027 'Platform main, flag off' record-http-status
509542
run_platform_live flag-off platform-live-flag-off || live_status=$?
543+
stop_app
544+
bun --no-env-file platform/checks/live/support/appconfig-service.ts 3033 \
545+
> "$report_dir/platform-live-appconfig.log" 2>&1 &
546+
appconfig_pid=$!
547+
wait_ready "$appconfig_pid" http://127.0.0.1:3033/health 'AppConfig fixture'
548+
export APPCONFIG_APPLICATION=platform-live APPCONFIG_ENVIRONMENT=ci AWS_REGION=us-east-1
549+
export AWS_ACCESS_KEY_ID=platform-live-ci AWS_SECRET_ACCESS_KEY=platform-live-ci
550+
export AWS_ENDPOINT_URL_APPCONFIGDATA=http://127.0.0.1:3033
551+
export PLATFORM_LIVE_APPCONFIG_URL=http://127.0.0.1:3033
552+
start_app platform-live-rollout 3027 'Platform main, per-organization rollout' record-http-status
553+
run_platform_live rollout platform-live-rollout || live_status=$?
554+
run_platform_live zone-boot platform-live-zone-boot || live_status=$?
510555
exit "$live_status"
511556
;;
512557

513558
# No zone at all: built without SIM_PLATFORM_ORIGIN, so even with the flag on nothing may change.
559+
# Then that image as a self-hoster runs it: not on a Sim hostname, billing off, no rollout flag.
560+
# Both report, whichever fails.
514561
platform-live-flag-off)
515562
platform_live_environment
516563
export PLATFORM_ORG_UI=true
564+
export ALLOWED_ORIGINS=http://127.0.0.1:3027
517565
start_browser_install platform-live --only-shell chromium
518566
start_app platform-live-flag-off 3027 'Main, no zone' record-http-status
519567
start_realtime platform-live-flag-off 3030
520568
wait_for_browsers
521-
run_platform_live flag-off platform-live-flag-off
569+
live_status=0
570+
run_platform_live flag-off platform-live-flag-off || live_status=$?
571+
stop_app
572+
unset PLATFORM_ORG_UI BILLING_ENABLED NEXT_PUBLIC_BILLING_ENABLED
573+
unset ENTERPRISE_ENABLED NEXT_PUBLIC_ENTERPRISE_ENABLED
574+
export E2E_APP_PUBLIC_URL=http://127.0.0.1:3027 PLATFORM_LIVE_ORIGIN=http://127.0.0.1:3027
575+
start_app platform-live-self-hosted 3027 'Main, self-hosted' record-http-status
576+
run_platform_live self-hosted platform-live-self-hosted || live_status=$?
577+
exit "$live_status"
522578
;;
523579

524580
*)

‎.github/workflows/platform-design.yml‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ jobs:
112112

113113
# The Platform against the real stack: Postgres, Redis, migrations, the production main app and
114114
# the production Platform. `zone` is the deployed topology, and then that same build with the flag
115-
# off. `flag-off` builds with no zone at all, so it is the only proof /org is truly absent.
115+
# off. `flag-off` builds with no zone at all, so it is the only proof /org is truly absent, and
116+
# then runs that build self-hosted.
116117
# Group environment and seed: `.github/scripts/http-e2e.sh`.
117118
live:
118119
name: live (${{ matrix.topology }})
@@ -189,8 +190,21 @@ jobs:
189190
if: always() && matrix.topology == 'zone'
190191
run: >-
191192
bun run check:platform-parity
193+
--job zone
192194
--report "$RUNNER_TEMP/e2e/platform-live/report.json"
195+
--report "$RUNNER_TEMP/e2e/platform-live-zone-down/report.json"
196+
--report "$RUNNER_TEMP/e2e/platform-live-zone-5xx/report.json"
197+
--report "$RUNNER_TEMP/e2e/platform-live-zone-recovered/report.json"
193198
--report "$RUNNER_TEMP/e2e/platform-live-flag-off/report.json"
199+
--report "$RUNNER_TEMP/e2e/platform-live-rollout/report.json"
200+
--report "$RUNNER_TEMP/e2e/platform-live-zone-boot/report.json"
201+
- name: Hold the parity ledger's flag-off rows to this run
202+
if: always() && matrix.topology == 'flag-off'
203+
run: >-
204+
bun run check:platform-parity
205+
--job flag-off
206+
--report "$RUNNER_TEMP/e2e/platform-live-flag-off/report.json"
207+
--report "$RUNNER_TEMP/e2e/platform-live-self-hosted/report.json"
194208
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
195209
if: always()
196210
with:

‎apps/desktop/e2e/local-files.spec.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ import { ToastProvider } from '@sim/emcn';
6363
import { AppRouterContext } from 'next/dist/shared/lib/app-router-context.shared-runtime';
6464
import { PathParamsContext } from 'next/dist/shared/lib/hooks-client-context.shared-runtime';
6565
import { Desktop } from '@/app/workspace/[workspaceId]/settings/components/desktop/desktop';
66-
import { FeatureFlagsProvider } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider';
66+
import { FeatureFlagsProvider } from '@/lib/core/config/feature-flags-context';
6767
import { SettingsHeaderProvider, SettingsHeaderShell } from '@/components/settings/settings-header';
6868
import { SettingsSectionProvider } from '@/components/settings/settings-panel';
6969
const router = { bfcacheId: 'fixture', back: () => history.back(), forward: () => history.forward(), refresh: () => location.reload(), push: url => location.assign(url), replace: url => location.replace(url), prefetch: () => {} };

apps/sim/app/o/[organizationId]/home/components/composer/composer-parts.tsx renamed to apps/sim/app/_organization-conversation/composer/composer-parts.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import type { ReactNode } from 'react'
44
import { ASSISTANT_IMAGE_ACCEPT_ATTRIBUTE } from '@/lib/uploads/shared/assistant-images'
55
import { MOTHERSHIP_ACCEPT_ATTRIBUTE } from '@/lib/uploads/utils/validation'
6-
import type { ConversationComposerProps } from '@/app/o/[organizationId]/home/components/composer/use-composer'
6+
import type { ConversationComposerProps } from '@/app/_organization-conversation/composer/use-composer'
77
import { AttachedFilesList } from '@/app/workspace/[workspaceId]/home/components/user-input/components/attached-files-list/attached-files-list'
88
import { DropOverlay } from '@/app/workspace/[workspaceId]/home/components/user-input/components/drop-overlay/drop-overlay'
99

apps/sim/app/o/[organizationId]/home/components/composer/index.ts renamed to apps/sim/app/_organization-conversation/composer/index.ts

File renamed without changes.

apps/sim/app/o/[organizationId]/home/components/composer/use-composer.ts renamed to apps/sim/app/_organization-conversation/composer/use-composer.ts

File renamed without changes.

0 commit comments

Comments
 (0)