@gravity-rail/sdk 0.32.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/workspace-builder/resource.ts","../src/workspace-builder/automation.ts","../src/workspace-builder/forms.ts","../src/workspace-builder/journeys.ts","../src/workspace-builder/role-update.ts","../src/workspace-builder/workflows.ts","../src/workspace-builder/orchestrator.ts","../src/types/generated/event_type.ts","../src/types/generated/ref.ts"],"sourcesContent":["import type { GravityRailWorkspaceClient } from '../client/workspace-client';\n\nexport type AnyRecord = Record<string, any>;\nexport type ResourceSummary = Record<string, Array<number | undefined>>;\n\nexport function isRecord(value: unknown): value is AnyRecord {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction isPlainRecord(value: unknown): value is AnyRecord {\n if (!isRecord(value)) return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nexport function slugify(name: string): string {\n return name.toLowerCase().replaceAll(' ', '_').replaceAll('-', '_');\n}\n\nexport abstract class WorkspaceBuilderResource {\n _id?: number;\n _uuid?: string;\n _created = false;\n _existed = false;\n\n /** Server-assigned numeric id — available after apply() or adopt(). */\n get id(): number {\n if (this._id === undefined) {\n throw new Error(\n `${this.constructor.name} has no id yet — ids are assigned during apply(). ` +\n 'Pass the builder object itself where a reference is needed; refs resolve at apply time.'\n );\n }\n return this._id;\n }\n\n /** Server-assigned uuid — available after apply() or adopt(). */\n get uuid(): string {\n if (this._uuid === undefined) {\n throw new Error(\n `${this.constructor.name} has no uuid yet — uuids are assigned during apply(). ` +\n 'Pass the builder object itself where a reference is needed; refs resolve at apply time.'\n );\n }\n return this._uuid;\n }\n\n /**\n * True for resources the server creates on our behalf (currently a\n * journey's `Start` step). They are kept in the resource list so edges can\n * reference them, but they are never created, printed, or counted.\n */\n get isImplicit(): boolean {\n return false;\n }\n\n /**\n * True when `apply()` is safe — and required — to run against a resource\n * that was ADOPTED rather than created.\n *\n * False by default because most builders create only: re-running their\n * `apply()` on an existing resource would make a duplicate. Override it\n * when `apply()` is an idempotent full write keyed on stable identities,\n * which is the only way a re-run can express an EDIT (a removed goal, a\n * reordered timeline) rather than just an addition.\n */\n get appliesWhenExisting(): boolean {\n return false;\n }\n\n abstract planLine(): string;\n abstract apply(client: GravityRailWorkspaceClient): Promise<void>;\n\n matchKey(): string | undefined {\n return undefined;\n }\n\n adopt(existing: AnyRecord): void {\n this._id = existing.id;\n this._uuid = existing.uuid;\n this._existed = true;\n }\n}\n\nexport function resolveRefs(params: AnyRecord): AnyRecord {\n return resolveRefValue(params) as AnyRecord;\n}\n\nfunction resolveRefValue(value: unknown): unknown {\n if (value instanceof WorkspaceBuilderResource) return value._uuid;\n if (Array.isArray(value)) return value.map(resolveRefValue);\n if (!isPlainRecord(value)) return value;\n\n const out: AnyRecord = {};\n for (const [key, nestedValue] of Object.entries(value)) {\n out[key] = resolveRefValue(nestedValue);\n }\n return out;\n}\n\n/**\n * Same substitution as `resolveRefs`, but to numeric ids.\n *\n * A few surfaces key on id rather than uuid — the query-engine IR is the main\n * one (`member.labelId` takes label ids). Without this a script would have to\n * apply once, read the ids back, and apply again just to write one filter.\n *\n * Returns `unknown` deliberately. A builder standing in a `number` slot is not\n * type-compatible with the payload it is going into, so the cast is real; a\n * generic `<T>(value: T): T` would only hide it, and would additionally claim a\n * `number` where an unresolved ref yields `undefined`. Callers cast at the one\n * place it matters, in view of the reader.\n */\nexport function resolveIdRefs(value: unknown): unknown {\n return resolveIdRefValue(value);\n}\n\nfunction resolveIdRefValue(value: unknown): unknown {\n // `.id` throws with a useful message when the ref has no id yet. Failing\n // here beats writing `undefined` into a payload: an id-keyed predicate that\n // silently loses a term matches everyone or no one, and looks fine doing it.\n if (value instanceof WorkspaceBuilderResource) return value.id;\n if (Array.isArray(value)) return value.map(resolveIdRefValue);\n if (!isPlainRecord(value)) return value;\n\n const out: AnyRecord = {};\n for (const [key, nestedValue] of Object.entries(value)) {\n out[key] = resolveIdRefValue(nestedValue);\n }\n return out;\n}\n","import {\n EventRuleEventType,\n EventRuleObjectType,\n type CreateRoutineRequest,\n type EventRuleActionType,\n type MemberFilterFormData,\n type NotificationRuleCreate,\n} from '../types';\nimport type { QueryPredicate } from '../types/query-engine-types';\nimport type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport type { AnyRecord } from './resource';\nimport { resolveIdRefs, WorkspaceBuilderResource } from './resource';\nimport type { WorkflowBuilder } from './workflows';\n\nexport class MemberFilterBuilder extends WorkspaceBuilderResource {\n readonly description: string;\n /** Query-engine predicate (JSON IR) authored on MemberFilter.query. */\n query: QueryPredicate | null = null;\n\n constructor(\n readonly name: string,\n options: AnyRecord = {}\n ) {\n super();\n this.description = options.description ?? '';\n this.query = options.query ?? null;\n }\n\n /**\n * Set the filter's query-engine predicate (JSON IR).\n *\n * Anywhere the IR wants a numeric id you may pass the builder that will own\n * it (e.g. a label in a `member.labelId` value); refs resolve at apply time.\n */\n setQuery(query: QueryPredicate): MemberFilterBuilder {\n this.query = query;\n return this;\n }\n\n planLine(): string {\n return `MemberFilter: ${this.name}${this.query ? ' (query)' : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const payload: MemberFilterFormData = {\n name: this.name,\n description: this.description,\n // Builder refs inside the IR become ids here; see resolveIdRefs.\n query: resolveIdRefs(this.query) as QueryPredicate | null,\n };\n const result = await client.createMemberFilter(payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n\ninterface RoutineRuleDraft {\n actionType: EventRuleActionType | string;\n workflow?: WorkflowBuilder;\n memberFilter?: MemberFilterBuilder;\n actionParams: AnyRecord;\n}\n\nexport class RoutineBuilder extends WorkspaceBuilderResource {\n readonly active: boolean;\n readonly description: string;\n readonly rules: RoutineRuleDraft[] = [];\n\n constructor(\n readonly name: string,\n readonly cronSchedule = '',\n options: AnyRecord = {}\n ) {\n super();\n this.active = options.active ?? false;\n this.description = options.description ?? '';\n }\n\n addRule(\n actionType: string,\n options: {\n workflow?: WorkflowBuilder;\n memberFilter?: MemberFilterBuilder;\n actionParams?: AnyRecord;\n } = {}\n ): RoutineBuilder {\n this.rules.push({\n actionType,\n workflow: options.workflow,\n memberFilter: options.memberFilter,\n actionParams: options.actionParams ?? {},\n });\n return this;\n }\n\n planLine(): string {\n const parts = [\n ...(this.cronSchedule ? [`cron=${this.cronSchedule}`] : []),\n ...(this.rules.length ? [`${this.rules.length} rules`] : []),\n this.active ? 'active' : 'inactive',\n ];\n return `Routine: ${this.name} (${parts.join(', ')})`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const eventRules = this.rules.map((rule) => {\n const actionParams = { ...rule.actionParams };\n if (rule.workflow?._id !== undefined) actionParams.workflowId = rule.workflow._id;\n if (rule.memberFilter?._id !== undefined)\n actionParams.memberFilterId = rule.memberFilter._id;\n return {\n uuid: crypto.randomUUID(),\n objectType: EventRuleObjectType.ROUTINE,\n eventType: EventRuleEventType.ROUTINE_TRIGGERED,\n actionType: rule.actionType as EventRuleActionType,\n actionParams,\n active: true,\n };\n });\n const payload: CreateRoutineRequest = {\n name: this.name,\n cronString: this.cronSchedule,\n scheduleMode: this.cronSchedule ? 'CRON' : undefined,\n scheduleEnabled: this.active,\n ...(this.description ? { description: this.description } : {}),\n ...(eventRules.length ? { eventRules } : {}),\n };\n const result = await client.createRoutine(payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n\nexport class NotificationRuleBuilder extends WorkspaceBuilderResource {\n readonly noticeType: string;\n readonly memberId: number;\n readonly workflow?: WorkflowBuilder;\n readonly prompt?: string;\n readonly notifySms: boolean;\n readonly notifyEmail: boolean;\n readonly notifyVoice: boolean;\n\n constructor(\n readonly name: string,\n options: AnyRecord = {}\n ) {\n super();\n this.noticeType = options.noticeType ?? options.notice_type ?? name;\n this.memberId = options.memberId ?? options.member_id;\n this.workflow = options.workflow;\n this.prompt = options.prompt ?? options.message;\n this.notifySms = Boolean(options.notifySms ?? options.notify_sms);\n this.notifyEmail = Boolean(options.notifyEmail ?? options.notify_email);\n this.notifyVoice = Boolean(options.notifyVoice ?? options.notify_voice);\n }\n\n planLine(): string {\n const parts: string[] = [];\n if (this.memberId !== undefined) parts.push(`memberId=${this.memberId}`);\n if (this.workflow) parts.push(`workflow='${this.workflow.name}'`);\n return `NotificationRule: ${this.name}${parts.length ? ` (${parts.join(', ')})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n if (this.memberId === undefined) {\n throw new Error(`Notification rule '${this.name}' requires memberId`);\n }\n const payload: NotificationRuleCreate = {\n noticeType: this.noticeType,\n memberId: this.memberId,\n workflowId: this.workflow?._id,\n prompt: this.prompt ?? null,\n notifySms: this.notifySms,\n notifyEmail: this.notifyEmail,\n notifyVoice: this.notifyVoice,\n };\n const result = await client.createNotificationRule(payload);\n this._id = result.id;\n this._created = true;\n }\n}\n","import {\n DataFieldType,\n EventRuleEventType,\n type DataTypeFormData,\n type EnumOption,\n type EventRuleActionType,\n type MemberLabelFormData,\n type SchemaField,\n} from '../types';\nimport type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport type { WorkspaceBuilderEventRule } from './event-rules';\nimport { type AnyRecord, isRecord, slugify, WorkspaceBuilderResource } from './resource';\n\n// The client DataFieldType enum and the generated SchemaField fieldType\n// literal union share the same string values, but TS string enums are\n// nominal — convert once at draft construction.\ntype WorkspaceFieldDraft = SchemaField;\n\nfunction normalizeOptions(options: any[]): EnumOption[] {\n if (options.length === 0) return [];\n const first = options[0];\n if (isRecord(first)) return options as EnumOption[];\n if (Array.isArray(first)) {\n return options.map((entry) => ({ label: String(entry[0]), value: entry[1] }));\n }\n return options.map((option) => ({ label: String(option), value: String(option) }));\n}\n\nfunction createFieldDraft(\n fieldType: DataFieldType,\n name: string,\n slug: string,\n options: {\n required?: boolean;\n order?: number;\n description?: string;\n choices?: EnumOption[];\n cel?: string;\n } = {}\n): WorkspaceFieldDraft {\n return {\n name,\n slug,\n fieldType: fieldType as SchemaField['fieldType'],\n required: Boolean(options.required),\n order: options.order ?? 0,\n ...(options.description ? { description: options.description } : {}),\n ...(options.choices ? { options: options.choices } : {}),\n ...(options.cel ? { celFunction: options.cel } : {}),\n };\n}\n\nexport class FormBuilder extends WorkspaceBuilderResource {\n readonly name: string;\n readonly slug: string;\n readonly description: string;\n readonly prompt: string;\n readonly collection: boolean;\n readonly fields: WorkspaceFieldDraft[] = [];\n readonly eventRules: WorkspaceBuilderEventRule[] = [];\n\n constructor(name: string, slug?: string, options: AnyRecord = {}) {\n super();\n this.name = name;\n this.slug = slug ?? slugify(name);\n this.description = options.description ?? '';\n this.prompt = options.prompt ?? '';\n this.collection = options.collection ?? false;\n\n for (const field of options.fields ?? []) {\n if (!isRecord(field) || !field.name) continue;\n const choices = field.options ? normalizeOptions(field.options) : undefined;\n this.fields.push(\n createFieldDraft(\n (field.fieldType ?? field.field_type ?? DataFieldType.TEXT) as DataFieldType,\n field.name,\n field.slug ?? slugify(field.name),\n {\n required: Boolean(field.required ?? field.isRequired),\n order: field.order ?? 0,\n description: field.description,\n choices,\n }\n )\n );\n }\n }\n\n field(\n fieldType: DataFieldType,\n name: string,\n slug: string,\n options: {\n required?: boolean;\n order?: number;\n description?: string;\n choices?: any[];\n cel?: string;\n } = {}\n ): FormBuilder {\n this.fields.push(createFieldDraft(fieldType, name, slug, options));\n return this;\n }\n\n enumField(name: string, slug: string, options: any[], settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.ENUM, name, slug, {\n ...settings,\n choices: normalizeOptions(options),\n });\n }\n\n textField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.TEXT, name, slug, settings);\n }\n\n numberField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.NUMBER, name, slug, settings);\n }\n\n dateField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.DATE, name, slug, settings);\n }\n\n booleanField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.BOOLEAN, name, slug, settings);\n }\n\n functionField(name: string, slug: string, cel: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.FUNCTION, name, slug, { ...settings, cel });\n }\n\n emailField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.EMAIL, name, slug, settings);\n }\n\n phoneField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.PHONE, name, slug, settings);\n }\n\n longtextField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.LONGTEXT, name, slug, settings);\n }\n\n integerField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.INTEGER, name, slug, settings);\n }\n\n datetimeField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.DATETIME, name, slug, settings);\n }\n\n timeOfDayField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.TIME_OF_DAY, name, slug, settings);\n }\n\n usZipCodeField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.US_ZIP_CODE, name, slug, settings);\n }\n\n arrayField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.ARRAY, name, slug, settings);\n }\n\n objectField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.OBJECT, name, slug, settings);\n }\n\n onRecordCreated(\n action: string,\n params: AnyRecord = {},\n condition?: string,\n name?: string\n ): FormBuilder {\n this.eventRules.push({\n eventType: EventRuleEventType.DATA_RECORD_CREATED,\n actionType: action as EventRuleActionType,\n actionParams: params,\n condition,\n name,\n });\n return this;\n }\n\n onRecordUpdated(\n action: string,\n params: AnyRecord = {},\n condition?: string,\n name?: string\n ): FormBuilder {\n this.eventRules.push({\n eventType: EventRuleEventType.DATA_RECORD_UPDATED,\n actionType: action as EventRuleActionType,\n actionParams: params,\n condition,\n name,\n });\n return this;\n }\n\n matchKey(): string {\n return this.slug;\n }\n\n planLine(): string {\n return `Form: ${this.name} (slug=${this.slug}, ${this.fields.length} fields)`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const payload: DataTypeFormData = {\n name: this.name,\n slug: this.slug,\n description: this.description,\n prompt: this.prompt,\n isCollection: this.collection,\n fields: this.fields,\n };\n const result = await client.createDataType(payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n\nexport class MemberLabelBuilder extends WorkspaceBuilderResource {\n readonly name: string;\n readonly slug: string;\n readonly color: string;\n readonly description: string;\n\n constructor(name: string, slug?: string, color = '8b5cf6', description = '') {\n super();\n this.name = name;\n this.slug = slug ?? slugify(name);\n this.color = color;\n this.description = description;\n }\n\n matchKey(): string {\n return this.slug;\n }\n\n planLine(): string {\n return `Label: ${this.name} (slug=${this.slug})`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const payload: MemberLabelFormData = {\n name: this.name,\n slug: this.slug,\n color: this.color,\n description: this.description,\n };\n const result = await client.createMemberLabel(payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n","import {\n EventRuleEventType,\n EventRuleActionType,\n type EventRuleInput,\n type JourneyGoalFormData,\n type JourneyStepConnectionFormData,\n type JourneyStepFormData,\n type JourneyV2DefinitionFormData,\n type JourneyV2EndingInput,\n type JourneyV2GoalInput,\n type JourneyV2TouchInput,\n type JourneyV2WaitInput,\n} from '../types';\nimport type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport { type AnyRecord, resolveRefs, WorkspaceBuilderResource } from './resource';\n\n/** Options for a DAG edge between two journey steps. */\nexport interface StepConnectionOptions {\n /**\n * CEL guard evaluated once the parent step is terminal. The child only\n * becomes eligible while this is true. Journey-edge CEL sees `member.*`\n * (including `member.labels`), `journey.enrolled_at`, `journey.status`,\n * and `parent_step.{status,completed_at,activated_at,eligible_at,name}`.\n */\n when?: string;\n /**\n * Space this step N days after the parent completed. Sugar for the CEL\n * `days_since(parent_step.completed_at) >= N`, AND-ed with `when`.\n *\n * This is how you build a follow-up cadence — NOT `abandonAfterDays`,\n * which gives up rather than waits.\n */\n afterDays?: number;\n /**\n * Give up on this edge after N days of the CEL staying false: the child\n * moves to TIMED_OUT instead of waiting forever. A deadline, not a delay.\n */\n abandonAfterDays?: number;\n /** Raw seconds form of `abandonAfterDays`. `abandonAfterDays` wins. */\n timeoutSeconds?: number;\n /** The child waits for THIS parent specifically, not just any parent. */\n required?: boolean;\n /** Edge evaluation order among a parent's outgoing edges. */\n order?: number;\n /** Restrict the edge to members matching a saved MemberFilter. */\n filterId?: number;\n}\n\n/** Options for a `JOURNEY_STEP_EXECUTE` outreach rule on a step. */\nexport interface StepRuleOptions {\n /** CEL guard — the action is skipped when this is false. */\n when?: string;\n /** Operator-facing rule name, shown in the journey editor. */\n name?: string;\n /** Delay the action this many seconds after the step activates. */\n delaySeconds?: number;\n active?: boolean;\n}\n\nexport interface StepRuleDraft {\n uuid: string;\n actionType: EventRuleActionType;\n actionParams: AnyRecord;\n options: StepRuleOptions;\n /**\n * The uuid the SERVER already stores for this rule, learned during\n * adoption. `uuid` above is minted by the script at authoring time and is\n * therefore different on every run of the same program; sending that as the\n * identity would make every re-run delete the live rule and create a\n * replacement, resetting its delivery bookkeeping. Preferred over `uuid`\n * when present. (v2 builder; the legacy builder never re-writes rules.)\n */\n adoptedUuid?: string;\n}\n\nexport interface StepConnectionDraft {\n parent: JourneyStepBuilder;\n child: JourneyStepBuilder;\n condition?: string;\n required: boolean;\n timeoutSeconds?: number;\n order?: number;\n filterId?: number;\n}\n\nexport interface JourneyGoalDraft {\n name: string;\n description: string;\n step?: JourneyStepBuilder;\n completionCel?: string;\n value?: number;\n order: number;\n}\n\n/**\n * A uuid the action needs, either literal or as the builder that will own it.\n * Builders resolve at apply time, so a step can reference a Workflow created in\n * the same script without the author threading ids through by hand.\n */\nexport type UuidRef = string | WorkspaceBuilderResource;\n\nconst SECONDS_PER_DAY = 86_400;\n\nfunction edgeKey(parentId: unknown, childId: unknown): string {\n return `${parentId}:${childId}`;\n}\n\n/** `days_since(parent_step.completed_at) >= N`, AND-ed onto any explicit CEL. */\nfunction edgeCondition(options: StepConnectionOptions): string | undefined {\n const clauses: string[] = [];\n if (options.afterDays !== undefined) {\n clauses.push(`days_since(parent_step.completed_at) >= ${options.afterDays}`);\n }\n if (options.when) clauses.push(`(${options.when})`);\n if (!clauses.length) return undefined;\n return clauses.join(' && ');\n}\n\nexport class JourneyStepBuilder extends WorkspaceBuilderResource {\n readonly connections: StepConnectionDraft[] = [];\n readonly rules: StepRuleDraft[] = [];\n readonly assigneeId?: number;\n readonly posX?: number;\n readonly posY?: number;\n\n // journey-decoupling Phase 7: a Journey step no longer links to a Workflow.\n // A step nudges via EventRule actions instead of running a Workflow, so the\n // builder no longer accepts or emits a workflow reference.\n constructor(\n readonly name: string,\n readonly journey: JourneyBuilder,\n readonly order = 0,\n readonly description = '',\n options: AnyRecord = {}\n ) {\n super();\n this.assigneeId = options.assigneeId;\n this.posX = options.posX;\n this.posY = options.posY;\n }\n\n /** Wire an edge to `child` and return the CHILD, so chains read linearly. */\n connectsTo(child: JourneyStepBuilder, options: StepConnectionOptions = {}): JourneyStepBuilder {\n if (child === this) {\n throw new Error(`Journey step '${this.name}' cannot connect to itself`);\n }\n const abandonSeconds =\n options.abandonAfterDays !== undefined\n ? options.abandonAfterDays * SECONDS_PER_DAY\n : options.timeoutSeconds;\n this.connections.push({\n parent: this,\n child,\n condition: edgeCondition(options),\n required: options.required ?? false,\n timeoutSeconds: abandonSeconds,\n order: options.order,\n filterId: options.filterId,\n });\n return child;\n }\n\n /**\n * Attach a `JOURNEY_STEP_EXECUTE` action — what this step actually DOES\n * when a member reaches it. A step with no rules is inert: the member\n * lands on it, nothing is sent, and the journey moves on.\n */\n onExecute(\n actionType: EventRuleActionType,\n params: AnyRecord = {},\n options: StepRuleOptions = {}\n ): JourneyStepBuilder {\n this.rules.push({\n uuid: crypto.randomUUID(),\n actionType,\n actionParams: params,\n options,\n });\n return this;\n }\n\n /**\n * Text the member. `phoneNumberUUID` is a workspace PhoneNumber with SMS\n * enabled. Pass `workflowUUID` to start an SMS workflow chat, or\n * `messageTemplate` for a one-off send.\n */\n sendsSms(\n params: {\n phoneNumberUUID: UuidRef;\n messageTemplate?: string;\n workflowUUID?: UuidRef;\n initialUserMessage?: string;\n },\n options: StepRuleOptions = {}\n ): JourneyStepBuilder {\n return this.onExecute(EventRuleActionType.SMS_SEND, params, options);\n }\n\n /**\n * Call the member. Both the workspace PhoneNumber uuid (voice enabled) and\n * the Workflow uuid that drives the call are required.\n */\n callsMember(\n params: { phoneNumberUUID: UuidRef; workflowUUID: UuidRef },\n options: StepRuleOptions = {}\n ): JourneyStepBuilder {\n return this.onExecute(EventRuleActionType.PHONE_CALL, params, options);\n }\n\n /** Email the member from a workspace inbox. */\n sendsEmail(\n params: {\n inboxUUID: UuidRef;\n subjectTemplate?: string;\n bodyTemplate?: string;\n workflowUUID?: UuidRef;\n initialUserMessage?: string;\n contentType?: string;\n },\n options: StepRuleOptions = {}\n ): JourneyStepBuilder {\n return this.onExecute(EventRuleActionType.EMAIL_SEND, params, options);\n }\n\n /** Label the member on arrival — pass label builders, not ids. */\n addsLabels(\n labels: WorkspaceBuilderResource[],\n options: StepRuleOptions = {}\n ): JourneyStepBuilder {\n return this.onExecute(\n EventRuleActionType.MEMBER_LABEL_ACTION,\n { addLabelIds: labels },\n options\n );\n }\n\n /** True once this step has something to do when a member reaches it. */\n get hasOutreach(): boolean {\n return this.rules.length > 0;\n }\n\n eventRuleInputs(): EventRuleInput[] {\n return this.rules.map((rule) => ({\n uuid: rule.uuid,\n eventType: EventRuleEventType.JOURNEY_STEP_EXECUTE,\n actionType: rule.actionType,\n actionParams: resolveRefs(rule.actionParams),\n ...(rule.options.name ? { name: rule.options.name } : {}),\n ...(rule.options.when ? { conditions: rule.options.when } : {}),\n ...(rule.options.delaySeconds ? { delay: rule.options.delaySeconds } : {}),\n active: rule.options.active ?? true,\n }));\n }\n\n planLine(): string {\n const actions = this.rules.map((rule) => rule.actionType).join(' + ');\n return `Step: ${this.name}${actions ? ` (${actions})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n if (this.journey._id === undefined) return;\n const rules = this.eventRuleInputs();\n const payload: JourneyStepFormData = {\n name: this.name,\n description: this.description,\n order: this.order,\n ...(this.assigneeId !== undefined ? { assigneeId: this.assigneeId } : {}),\n ...(this.posX !== undefined ? { posX: this.posX } : {}),\n ...(this.posY !== undefined ? { posY: this.posY } : {}),\n // Saved atomically with the step, so a partial failure cannot leave\n // an inert step behind.\n ...(rules.length ? { eventRules: rules } : {}),\n };\n const result = await client.createStep(this.journey._id, payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n\n/**\n * The auto-created `Start` step. `POST /journeys` always creates one and points\n * `journey.startStepId` at it, so the builder adopts it rather than creating a\n * second — and every real step hangs off it, directly or transitively.\n */\nclass StartStepBuilder extends JourneyStepBuilder {\n get isImplicit(): boolean {\n return true;\n }\n\n planLine(): string {\n return 'Step: Start (auto-created)';\n }\n\n async apply(): Promise<void> {\n // Adopted from the create-journey response; never created.\n }\n}\n\nexport class JourneyBuilder extends WorkspaceBuilderResource {\n readonly description: string;\n readonly steps: JourneyStepBuilder[] = [];\n readonly goals: JourneyGoalDraft[] = [];\n /** The auto-created `Start` step — connect the first real step to it. */\n readonly start: JourneyStepBuilder;\n /** `parentId:childId` for every edge the server already has (see `adopt`). */\n readonly existingEdges = new Set<string>();\n\n constructor(\n readonly name: string,\n options: AnyRecord = {}\n ) {\n super();\n this.description = options.description ?? '';\n this.start = new StartStepBuilder('Start', this, 0);\n this.steps.push(this.start);\n }\n\n step(name: string, options: AnyRecord = {}): JourneyStepBuilder {\n const step = new JourneyStepBuilder(\n name,\n this,\n options.order ?? this.steps.length,\n options.description ?? '',\n options\n );\n this.steps.push(step);\n return step;\n }\n\n /**\n * Declare a linear cadence: `Start → steps[0] → steps[1] → …`, each edge\n * carrying the matching entry from `spacing`.\n *\n * Chaining is not optional polish. A step created with no incoming edge is\n * a ROOT, and every root fires the moment a member enrols — a \"three\n * follow-ups over four days\" journey built without edges sends all three\n * at once.\n */\n sequence(steps: JourneyStepBuilder[], spacing: StepConnectionOptions[] = []): JourneyBuilder {\n let parent = this.start;\n steps.forEach((step, index) => {\n parent = parent.connectsTo(step, spacing[index] ?? {});\n });\n return this;\n }\n\n goal(name: string, options: AnyRecord = {}): JourneyBuilder {\n this.goals.push({\n name,\n description: options.description ?? '',\n step: options.step,\n completionCel: options.completionCel ?? options.completion_cel,\n value: options.value,\n order: options.order ?? this.goals.length,\n });\n return this;\n }\n\n /**\n * Authoring problems that make a journey silently misbehave at runtime.\n * Reported at plan/preview time, before anything is written.\n */\n validate(): string[] {\n const problems: string[] = [];\n const withParents = new Set<JourneyStepBuilder>();\n for (const step of this.steps) {\n for (const connection of step.connections) withParents.add(connection.child);\n }\n for (const step of this.steps) {\n if (step === this.start) continue;\n if (!withParents.has(step)) {\n problems.push(\n `step '${step.name}' has no incoming edge — it is a root and fires for ` +\n 'every member the moment they enrol. Connect it from journey.start or ' +\n 'a prior step.'\n );\n }\n if (!step.hasOutreach) {\n problems.push(\n `step '${step.name}' has no JOURNEY_STEP_EXECUTE action — a member ` +\n 'reaching it gets nothing. Add one with .sendsSms / .callsMember / ' +\n '.sendsEmail / .onExecute.'\n );\n }\n }\n if (!this.goals.length) {\n problems.push(`journey '${this.name}' has no goals — nothing measures whether it works.`);\n }\n return problems;\n }\n\n /**\n * Adopt an existing journey, its steps, and its EDGES, matched by name.\n *\n * Re-running a builder script is normal — a program is usually built in\n * stages as provisioning lands — and without adoption the second run would\n * create a duplicate journey and a duplicate set of steps beside the live\n * one, with members enrolled in neither.\n *\n * The edge set is recorded from the server's own `childConnections` rather\n * than inferred from \"both steps exist\". A first run that created the steps\n * and then failed before writing an edge leaves exactly that state, and\n * inferring would skip the missing edge on every subsequent run — leaving a\n * permanent root step that fires for every member at enrolment, silently.\n * The journey detail read eager-loads connections, so the real answer is\n * already in hand; there is no reason to guess.\n */\n adopt(existing: AnyRecord): void {\n super.adopt(existing);\n const existingSteps = (existing.steps ?? []) as AnyRecord[];\n const byName = new Map(existingSteps.map((step) => [step.name as string, step]));\n const startStep =\n existingSteps.find((step) => step.id === existing.startStepId) ?? byName.get('Start');\n if (startStep) this.start.adopt(startStep);\n for (const step of this.steps) {\n if (step === this.start) continue;\n const match = byName.get(step.name);\n if (match) step.adopt(match);\n }\n for (const step of existingSteps) {\n for (const edge of (step.childConnections ?? []) as AnyRecord[]) {\n this.existingEdges.add(edgeKey(edge.parentStepId, edge.childStepId));\n }\n }\n }\n\n /** True when the server already has this exact edge. */\n hasEdge(parent: JourneyStepBuilder, child: JourneyStepBuilder): boolean {\n if (parent._id === undefined || child._id === undefined) return false;\n return this.existingEdges.has(edgeKey(parent._id, child._id));\n }\n\n planLine(): string {\n const parts: string[] = [];\n const real = this.steps.filter((step) => step !== this.start);\n if (real.length) parts.push(`${real.length} steps`);\n if (this.goals.length) parts.push(`${this.goals.length} goals`);\n return `Journey: ${this.name}${parts.length ? ` (${parts.join(', ')})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const result = await client.createJourney({\n name: this.name,\n description: this.description,\n });\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n\n // Adopt the server's auto-created Start step so edges from\n // `journey.start` resolve to a real uuid instead of silently dropping.\n const startStep = (result.steps ?? []).find(\n (step) => step.id === result.startStepId || step.name === 'Start'\n );\n if (!startStep) {\n throw new Error(\n `Journey '${this.name}' was created without a Start step; ` +\n 'edges from journey.start cannot be wired.'\n );\n }\n this.start.adopt(startStep);\n }\n}\n\nexport function buildJourneyConnectionPayload(\n connection: StepConnectionDraft\n): JourneyStepConnectionFormData | undefined {\n if (!connection.parent._uuid || !connection.child._uuid) return undefined;\n return {\n parentStepUuid: connection.parent._uuid,\n childStepUuid: connection.child._uuid,\n ...(connection.condition ? { celCondition: connection.condition } : {}),\n ...(connection.required ? { required: true } : {}),\n ...(connection.timeoutSeconds ? { timeoutSeconds: connection.timeoutSeconds } : {}),\n ...(connection.order !== undefined ? { order: connection.order } : {}),\n ...(connection.filterId !== undefined ? { filterId: connection.filterId } : {}),\n };\n}\n\nexport function buildJourneyGoalPayload(goal: JourneyGoalDraft): JourneyGoalFormData {\n return {\n name: goal.name,\n description: goal.description,\n order: goal.order,\n ...(goal.step?._uuid ? { goalStepUuid: goal.step._uuid } : {}),\n ...(goal.completionCel ? { completionCel: goal.completionCel } : {}),\n ...(goal.value !== undefined ? { value: goal.value } : {}),\n };\n}\n\n// ===========================================================================\n// Journey v2 builder (plan §3.8)\n// ===========================================================================\n//\n// A SEPARATE class, not a flag on `JourneyBuilder`. The two engines disagree\n// about what a definition even is — legacy is an additive graph written\n// step-by-step, v2 is one ordered timeline written atomically — so a shared\n// class would be a permanent `if (v2)` in every method, and the plan is\n// explicit that \"the existing builder keeps its current legacy behavior unless\n// the caller selects a new v2 builder mode\".\n\n/** The wait on the edge INTO a touch (plan §3.5). */\nexport interface V2WaitOptions {\n /**\n * Whole elapsed days since the previous touch's durable acceptance. The ONE\n * canonical shape the structured control round-trips — the server\n * regenerates the CEL from this number.\n */\n afterDays?: number;\n /**\n * Any other valid CEL, stored byte for byte. `duration(\"4h\")`, member-local\n * schedules, and everything else lives here; the editor evaluates it but\n * declines to reinterpret it. Mutually exclusive with `afterDays`.\n */\n when?: string;\n /** Hold the touch until the member matches this saved MemberFilter. */\n filterId?: number;\n // NOTE: there is no `timeoutSeconds` here, unlike `StepConnectionOptions`.\n // That legacy option is a DEADLINE (`abandonAfterDays` — the child moves to\n // TIMED_OUT), and the v2 evaluator implements no deadline semantics at all,\n // so the server's v2 wait contract rejects the key rather than accepting a\n // setting that would never fire. Model \"stop waiting\" as an Ending instead:\n // it is evaluated on every tick and terminates the enrollment explicitly.\n // Whether v2 grows deadlines is a phase-6+ decision.\n}\n\nexport interface V2TouchOptions {\n description?: string;\n wait?: V2WaitOptions;\n}\n\nexport interface V2EndingOptions {\n /**\n * The Ending's CEL condition. Optional ONLY when `filterId` is given —\n * an Ending with neither predicate would match every enrollment\n * (rule-filters plan §3.2).\n */\n when?: string;\n /**\n * A saved MemberFilter the member must be in. Given alongside `when` the two\n * are ANDed: the Ending claims a member only when both pass.\n */\n filterId?: number;\n}\n\nexport interface V2GoalOptions {\n description?: string;\n /** Touch or Ending whose completion satisfies the goal. */\n step?: V2TouchBuilder | V2EndingBuilder;\n completionCel?: string;\n value?: number;\n}\n\n/** One arm of an exclusive branch (plan §3.7). */\nexport interface V2RouteOptions {\n /**\n * The route's CEL condition. Omit BOTH this and `filterId` to declare the\n * **Otherwise** route: an OPTIONAL fallback, taken immediately when nothing\n * above matched. At most one route per branch omits both, and it must be\n * declared last, because Otherwise matches immediately and anything after it\n * could never be reached.\n *\n * Declaring no Otherwise at all is the default shape, not an omission: the\n * branch is checked top to bottom on every pass and members WAIT at it until\n * a route matches. So there are two author intents, not one:\n *\n * - **wait for a match** — declare only conditional routes;\n * - **fall back immediately** — add a final route with no `when` and no\n * `filterId`.\n */\n when?: string;\n /**\n * A saved MemberFilter the member must be in (rule-filters plan §3.2).\n *\n * A route carrying only this is CONDITIONAL, not the fallback — that is the\n * whole reason `when` alone can no longer answer \"is this Otherwise?\".\n * Given alongside `when` the two are ANDed.\n */\n filterId?: number;\n /**\n * The touch this arm continues to after its own touches — the per-arm\n * terminus. Omit it and the arm ENDS: the enrollment completes after its\n * last touch unless an Ending applies. Absence is meaningful, so there is\n * no separate \"stop\" option to get out of step with it.\n */\n continueAt?: V2TouchBuilder;\n}\n\n/**\n * One route of a branch. Declaration order IS precedence — routes are checked\n * top to bottom and the first match wins.\n */\nexport class V2RouteBuilder {\n readonly touches: V2TouchBuilder[] = [];\n /**\n * The DECISION RULE uuid. Adopted for the same reason an Ending's is:\n * `MemberJourneyStep.entry_decision_rule_id` points at this row with\n * `ON DELETE SET NULL`, so recreating it on a re-run would erase which arm\n * every already-routed enrollment is on — invisibly, since both rules\n * \"exist\" afterwards.\n */\n _ruleUuid?: string;\n\n constructor(\n readonly name: string,\n readonly options: V2RouteOptions = {}\n ) {}\n\n /** Append a touch to this arm. Order is call order. */\n touch(name: string, options: V2TouchOptions = {}): V2TouchBuilder {\n const touch = new V2TouchBuilder(name, options);\n this.touches.push(touch);\n return touch;\n }\n}\n\n/**\n * The ordered route set attached to one touch.\n *\n * There is no branch ENTITY on the server and none is created here — a branch\n * is its rules, and its header is derived from the source touch. This class\n * exists only to group the routes with the touch that owns them.\n *\n * A branch needs at least one CONDITIONAL route. It does not need an Otherwise:\n * with none, members wait at the branch source and the routes are re-checked on\n * every pass until one matches. See {@link V2RouteOptions.when} for the two\n * fallback intents and how each is expressed.\n */\nexport class V2BranchBuilder {\n readonly routes: V2RouteBuilder[] = [];\n\n /** Append a route. Declaration order is evaluation order. */\n route(name: string, options: V2RouteOptions = {}): V2RouteBuilder {\n const route = new V2RouteBuilder(name, options);\n this.routes.push(route);\n return route;\n }\n}\n\n/** One ordinary touch in a v2 timeline, plus the wait that leads into it. */\nexport class V2TouchBuilder {\n readonly rules: StepRuleDraft[] = [];\n /** Filled in from the server's response so a re-run keeps this touch. */\n _uuid?: string;\n\n /**\n * The exclusive branch that follows this touch, when it has one. A touch\n * carrying a branch gets NO ordinary outgoing connection: its routes are\n * the only way out, so touches declared after it are reached only by an arm\n * naming them in `continueAt`.\n */\n _branch?: V2BranchBuilder;\n\n readonly name: string;\n\n /**\n * The name is CANONICALIZED here, once, and everything downstream reads it:\n * the `key:<name>` address, the payload, adoption's name lookup, and the\n * uniqueness gate. The API trims it before storing\n * (`JourneyV2TouchInput`/`JourneyV2EndingInput` name validators), so a\n * builder holding `\" Welcome \"` would send an address for a name the server\n * does not have, fail to find its own step on the way back, and treat it as\n * new on the next run — archiving the live step and its history. One\n * representation at the boundary is the only way that cannot happen; a\n * second trim anywhere downstream would be a place for the two to drift.\n */\n constructor(\n name: string,\n readonly options: V2TouchOptions = {}\n ) {\n this.name = name.trim();\n }\n\n /**\n * Attach an exclusive branch after this touch, or return the existing one.\n *\n * Idempotent so a script can add routes in stages without accidentally\n * declaring two branches on one touch — which the server has no shape for,\n * since a touch owns exactly one ordered route set.\n */\n branch(): V2BranchBuilder {\n this._branch ??= new V2BranchBuilder();\n return this._branch;\n }\n\n /**\n * The request-local address this step answers to (plan §3.8 / phase 6).\n *\n * A saved step is addressed by its uuid; an unsaved one by a `key` derived\n * from its authored name. Deriving from the NAME rather than minting a\n * uuid4 keeps the payload stable across re-runs of the same script — a\n * fresh random key on every run would make the request differ from itself\n * for no reason, and the server's EventRule sync matches on the uuids the\n * payload carries. Names are already asserted unique within a journey,\n * which is what makes a name-derived key unique.\n *\n * {@link V2EndingBuilder} INHERITS this rather than deriving its own: an\n * Ending's anchor key and a touch's key land in one server-side namespace\n * (`stepKey` is one field), so two derivations that drifted would produce\n * two spellings of the same address and a goal would 404 on the one its\n * step was not sent under.\n *\n * Two steps of one name therefore answer to one address. {@link preflight}\n * is the first enforcement point and refuses it before any write, counting\n * touches and Endings together and comparing names trimmed, as the API\n * stores them. Without that gate the collision surfaces twice and both\n * times too late: the server rejects the definition PUT after `apply()` has\n * created the Journey, and {@link indexStoredByName} rejects the SECOND run\n * of a script whose two stored steps make `adopt()` a coin flip.\n */\n get _address(): string {\n return this._uuid ?? `key:${this.name}`;\n }\n\n /**\n * Re-attach the EventRule uuids the server already stores for this touch.\n *\n * Identity is the operator-set rule NAME. `.sendsSms(...)` does not require\n * one, so an unnamed rule falls back to its actionType — but ONLY when that\n * answer is 1:1: exactly one unnamed draft of that actionType here, and\n * exactly one stored rule of it left unclaimed there. Anything else throws.\n *\n * The ordinal-within-actionType fallback this replaces was not a weaker\n * identity, it was the wrong one. Inserting a new unnamed rule ABOVE an\n * existing same-type rule shifts every position by one, so the new rule\n * adopted the existing rule's uuid — taking over its delivery bookkeeping —\n * and the existing rule was written as brand new and archived. Nothing in\n * the payload showed it: both rules \"exist\" afterwards. When the script\n * cannot say which rule is which, the honest answer is to ask the author to\n * name them, not to guess by position.\n */\n adoptRuleUuids(serverRules: AnyRecord[]): void {\n const namedDrafts = this.rules.filter((draft) => !!draft.options.name);\n const storedByName = indexStoredByName(\n serverRules,\n new Set(namedDrafts.map((draft) => draft.options.name as string)),\n `touch '${this.name}'`,\n 'action'\n );\n\n // A stored rule a named draft claims is out of the unnamed pool: it has\n // an owner, so it cannot also be the answer to an unnamed draft.\n const claimed = new Set<AnyRecord>();\n for (const draft of namedDrafts) {\n const match = storedByName.get(draft.options.name as string);\n // No stored rule of that name is an ordinary NEW rule — it keeps the\n // uuid the script minted and the server creates it. It must NOT fall\n // through to the unnamed path: a freshly named rule would there take\n // an existing rule's identity, and the existing rule would be\n // recreated and archived under it.\n if (!match) continue;\n draft.adoptedUuid = match.uuid as string;\n claimed.add(match);\n }\n\n const unnamedByActionType = new Map<string, StepRuleDraft[]>();\n for (const draft of this.rules) {\n if (draft.options.name) continue;\n const actionType = String(draft.actionType);\n unnamedByActionType.set(actionType, [\n ...(unnamedByActionType.get(actionType) ?? []),\n draft,\n ]);\n }\n for (const [actionType, drafts] of unnamedByActionType) {\n const candidates = serverRules.filter(\n (rule) => String(rule.actionType) === actionType && !claimed.has(rule)\n );\n // Nothing stored of this type: every draft is new, and creating them\n // is not a guess.\n if (!candidates.length) continue;\n if (drafts.length === 1 && candidates.length === 1) {\n drafts[0]!.adoptedUuid = candidates[0]!.uuid as string;\n continue;\n }\n throw new Error(\n `touch '${this.name}' has ${drafts.length} unnamed ${actionType} action(s) ` +\n `and the server has ${candidates.length} — so there is no way to tell ` +\n 'which stored action each one is. Adopting by position swaps their ' +\n 'identities the moment an action is inserted or removed, which moves ' +\n \"one action's delivery history onto another. Give these actions names \" +\n '(`{ name: ... }`) so each one can be matched to the right rule.'\n );\n }\n }\n\n /** Attach a `JOURNEY_STEP_EXECUTE` action. Same contract as legacy. */\n onExecute(\n actionType: EventRuleActionType,\n params: AnyRecord = {},\n options: StepRuleOptions = {}\n ): V2TouchBuilder {\n this.rules.push({\n uuid: crypto.randomUUID(),\n actionType,\n actionParams: params,\n options,\n });\n return this;\n }\n\n sendsSms(\n params: {\n phoneNumberUUID: UuidRef;\n messageTemplate?: string;\n workflowUUID?: UuidRef;\n initialUserMessage?: string;\n },\n options: StepRuleOptions = {}\n ): V2TouchBuilder {\n return this.onExecute(EventRuleActionType.SMS_SEND, params, options);\n }\n\n callsMember(\n params: { phoneNumberUUID: UuidRef; workflowUUID: UuidRef },\n options: StepRuleOptions = {}\n ): V2TouchBuilder {\n return this.onExecute(EventRuleActionType.PHONE_CALL, params, options);\n }\n\n sendsEmail(\n params: {\n inboxUUID: UuidRef;\n subjectTemplate?: string;\n bodyTemplate?: string;\n workflowUUID?: UuidRef;\n },\n options: StepRuleOptions = {}\n ): V2TouchBuilder {\n return this.onExecute(EventRuleActionType.EMAIL_SEND, params, options);\n }\n\n get hasOutreach(): boolean {\n return this.rules.length > 0;\n }\n\n eventRuleInputs(): EventRuleInput[] {\n return this.rules.map((rule) => ({\n uuid: rule.adoptedUuid ?? rule.uuid,\n eventType: EventRuleEventType.JOURNEY_STEP_EXECUTE,\n actionType: rule.actionType,\n actionParams: resolveRefs(rule.actionParams),\n ...(rule.options.name ? { name: rule.options.name } : {}),\n ...(rule.options.when ? { conditions: rule.options.when } : {}),\n ...(rule.options.delaySeconds ? { delay: rule.options.delaySeconds } : {}),\n active: rule.options.active ?? true,\n }));\n }\n}\n\n/** One ordered Ending. List position IS precedence — first match wins. */\nexport class V2EndingBuilder extends V2TouchBuilder {\n /**\n * The DECISION RULE uuid, distinct from `_uuid` (the anchor step's).\n *\n * An Ending is two rows: a `JourneyDecisionRule` carrying the condition and\n * precedence, and a `JourneyStep` anchor carrying its actions, goals, and\n * status history. Adopting only the anchor left the rule to be recreated on\n * every re-run — and `MemberJourney.latched_ending_rule_id` /\n * `JourneyStatusLog.journey_decision_rule_id` point at the RULE with\n * `ON DELETE SET NULL`, so every completed enrollment silently forgot which\n * Ending it took.\n */\n _ruleUuid?: string;\n\n constructor(\n name: string,\n readonly when: string | undefined,\n readonly filterId: number | undefined\n ) {\n super(name);\n }\n\n /**\n * An Ending cannot carry a branch, and saying so is the whole override.\n *\n * `V2EndingBuilder extends V2TouchBuilder` for the identity and addressing\n * an Ending's anchor shares with a touch, which also inherits every touch\n * method — `branch()` among them. Inherited unchanged it would set\n * `_branch` on an object nothing ever reads it from: the Ending serializer\n * writes `{uuid|key, name, celCondition, filterId, eventRules}` and no\n * `branch`, and `allTouches()` walks only the timeline, so the routes are\n * never numbered, validated, adopted or sent. The author gets no error and\n * a definition quietly missing what they asked for.\n *\n * An Ending is terminal by construction — it is the rule that ENDS an\n * enrollment — so there is no shape to serialize even if the payload had a\n * field for it. Refusing at the call is the only point where the author is\n * still holding the mistake.\n *\n * @see foreignAnchorProblem for why this names no Ending.\n */\n override branch(): never {\n throw new Error(\n 'an Ending cannot carry a branch. An Ending terminates an enrollment, ' +\n 'so there is nothing after it to route to, and the atomic definition ' +\n 'has no field to send one under — the routes would be silently ' +\n 'dropped. Put the branch on the touch that leads to this Ending ' +\n 'instead, and give each arm its own Ending.'\n );\n }\n}\n\nexport interface V2GoalDraft {\n name: string;\n description?: string;\n step?: V2TouchBuilder | V2EndingBuilder;\n completionCel?: string;\n value?: number;\n /** Server-assigned goal uuid, learned during adoption. */\n _uuid?: string;\n}\n\n/**\n * Build a Journey v2 definition and write it through the ATOMIC endpoint.\n *\n * One create plus one `PUT /v2-definition`, rather than the legacy builder's\n * create-step-then-connect-then-goal sequence. That is not an optimization: a\n * v2 definition is only valid as a whole, so a partial write would be rejected\n * by the publish validator anyway, and a half-applied timeline is exactly the\n * state the atomic endpoint exists to make impossible.\n */\nexport class JourneyV2Builder extends WorkspaceBuilderResource {\n readonly description: string;\n readonly touches: V2TouchBuilder[] = [];\n readonly endings: V2EndingBuilder[] = [];\n readonly goals: V2GoalDraft[] = [];\n /** Activate after the definition is written and validated. */\n readonly activate: boolean;\n /** Optimistic-concurrency token, from create or adoption. */\n private _expectedUpdatedAt?: string;\n /** Server status at adoption — decides whether a re-run must pause first. */\n private _status?: string;\n\n constructor(\n readonly name: string,\n options: AnyRecord = {}\n ) {\n super();\n this.description = options.description ?? '';\n this.activate = options.activate ?? false;\n }\n\n /**\n * A v2 definition write is idempotent, so an ADOPTED journey is written\n * too. That is the whole point of adopting one: the PUT is a full,\n * uuid-keyed replacement, so re-running a script is how an author expresses\n * an edit. The legacy builder stays create-only — its `apply()` only knows\n * how to create, and re-running it would duplicate.\n */\n get appliesWhenExisting(): boolean {\n return true;\n }\n\n /** Append a touch to the timeline. Order is call order. */\n touch(name: string, options: V2TouchOptions = {}): V2TouchBuilder {\n const touch = new V2TouchBuilder(name, options);\n this.touches.push(touch);\n return touch;\n }\n\n /**\n * Every touch in the timeline, arms included, depth first.\n *\n * Identity adoption, name-uniqueness and validation all have to see arm\n * touches — a walk over the top level alone would leave every arm touch\n * recreated on each re-run, silently archiving its member history.\n */\n allTouches(): V2TouchBuilder[] {\n const out: V2TouchBuilder[] = [];\n const walk = (touches: V2TouchBuilder[]): void => {\n for (const touch of touches) {\n out.push(touch);\n for (const route of touch._branch?.routes ?? []) walk(route.touches);\n }\n };\n walk(this.touches);\n return out;\n }\n\n /** Every route in the timeline, at every nesting depth, depth first. */\n allRoutes(): V2RouteBuilder[] {\n const out: V2RouteBuilder[] = [];\n for (const touch of this.allTouches()) {\n for (const route of touch._branch?.routes ?? []) out.push(route);\n }\n return out;\n }\n\n /** Append an Ending. Call order is evaluation order. */\n ending(name: string, options: V2EndingOptions): V2EndingBuilder {\n const ending = new V2EndingBuilder(name, options.when, options.filterId);\n this.endings.push(ending);\n return ending;\n }\n\n goal(name: string, options: V2GoalOptions = {}): JourneyV2Builder {\n this.goals.push({\n name,\n description: options.description,\n step: options.step,\n completionCel: options.completionCel,\n value: options.value,\n });\n return this;\n }\n\n /**\n * Authoring problems the server's publish validator would reject.\n *\n * A different rule set from the legacy builder's on purpose. \"No incoming\n * edge\" has no meaning in a timeline — position is the order — and the v2\n * failure modes are different ones: an action-less touch that is not an\n * explicit wait, and an Ending with no condition.\n */\n validate(): string[] {\n const problems: string[] = [];\n if (!this.touches.length) {\n problems.push(\n `journey '${this.name}' has no touches — an empty timeline has nothing to execute.`\n );\n }\n const armHeads = new Set(\n this.allRoutes()\n .map((route) => route.touches[0])\n .filter(Boolean) as V2TouchBuilder[]\n );\n this.allTouches().forEach((touch) => {\n if (touch.hasOutreach) return;\n const wait = touch.options.wait;\n // Mirrors the server's `_edge_can_hold`: only something that can\n // actually delay the child counts. An ARM HEAD can never qualify —\n // a route target has no incoming edge, so routing into it is\n // immediate and there is nothing for a wait to sit on.\n const isFirst = this.touches[0] === touch;\n const isExplicitWait =\n !isFirst &&\n !armHeads.has(touch) &&\n (wait?.afterDays !== undefined || !!wait?.when || wait?.filterId !== undefined);\n if (isExplicitWait) return;\n problems.push(\n `touch '${touch.name}' has no JOURNEY_STEP_EXECUTE action — a member ` +\n 'reaching it gets nothing. Add one, or give it a wait so it is an ' +\n 'explicit grace period.'\n );\n });\n for (const touch of this.allTouches()) {\n const branch = touch._branch;\n if (!branch) continue;\n // Otherwise is the route with NEITHER predicate. A filter-only route\n // is conditional, so counting it as a fallback here would report a\n // perfectly good branch as having two.\n const fallbacks = branch.routes.filter(\n (route) => !route.options.when?.trim() && route.options.filterId === undefined\n );\n // An Otherwise is OPTIONAL — a branch with only conditional routes\n // holds until one matches, and that is the default shape, so flagging\n // it would stop an author shipping the very thing the server prefers.\n // A CONDITIONAL route is still required: with nothing that can fail to\n // match, the first route takes every member and no decision is made.\n if (branch.routes.length - fallbacks.length < 1) {\n problems.push(\n `branch after touch '${touch.name}' needs at least one conditional ` +\n 'route — one declared with a `when`, a `filterId`, or both. ' +\n 'Members wait at the branch until a route matches, so an ' +\n 'Otherwise is optional.'\n );\n }\n if (fallbacks.length > 1) {\n problems.push(\n `branch after touch '${touch.name}' declares ${fallbacks.length} ` +\n 'Otherwise routes; a branch has at most one unconditional fallback.'\n );\n }\n if (fallbacks.length === 1 && branch.routes[branch.routes.length - 1] !== fallbacks[0]) {\n problems.push(\n `the Otherwise route of the branch after touch '${touch.name}' is ` +\n 'not last; it is taken immediately, so any route after it can ' +\n 'never be reached.'\n );\n }\n for (const route of branch.routes) {\n if (!route.touches.length && !route.options.continueAt) {\n problems.push(\n `route '${route.name}' has no target — give it at least one ` +\n 'touch, or a `continueAt` naming the touch it continues to.'\n );\n }\n }\n }\n for (const ending of this.endings) {\n if (!ending.when?.trim() && ending.filterId === undefined) {\n problems.push(\n `ending '${ending.name}' has no condition — an Ending that always ` +\n 'matches terminates every enrolment on evaluation order alone. ' +\n 'Give it a `when` expression, a `filterId`, or both.'\n );\n }\n }\n return problems;\n }\n\n /**\n * Shapes this definition cannot express, found BEFORE anything is written.\n *\n * A different list from {@link validate}, and a different consequence:\n * those are warnings the orchestrator prints and then writes anyway, these\n * are refusals. For each one the payload has no way to say what the script\n * asked for, so serializing past it would write a DIFFERENT program from\n * the one the script wrote, with nothing afterwards to say so.\n *\n * It has to run before the first write rather than during serialization,\n * because {@link apply} creates the Journey — or pauses a live one — before\n * it builds the payload. A refusal raised from `definitionPayload()` has\n * therefore already left an empty journey shell behind, or taken a\n * production program off the air.\n *\n * PURE: reads only what the script declared, never what the server holds,\n * so it is correct at any point — before adoption included — and\n * `WorkspaceBuilder.preflight()` can stay a synchronous, side-effect-free\n * check a caller may run directly. Nothing here needs adoption to have run:\n * an anchor the server has not seen is addressed by its request-local key,\n * so \"has this Ending been saved\" is no longer a question a refusal\n * depends on.\n */\n preflight(): string[] {\n const problems: string[] = [];\n this.allTouches().forEach((touch, index) => {\n const wait = touch.options.wait;\n if (wait?.afterDays !== undefined && wait.when) {\n problems.push(waitExclusivityProblem(index));\n }\n });\n const owned = this.ownedAnchors();\n this.goals.forEach((goal, index) => {\n const step = goal.step;\n if (step && !owned.has(step)) {\n problems.push(foreignAnchorProblem(index, anchorKind(step)));\n }\n });\n\n // Touches and Endings are ONE step-name namespace, and a repeat in it is\n // a defect whatever the save state. Unsaved, both address themselves\n // `key:<name>` and the definition resolves `stepKey` through a single\n // field, so two rows answer to one address — which the server refuses on\n // the definition PUT, i.e. after `apply()` has created the Journey or\n // paused a live one. Saved, they are two stored steps of one name, which\n // is what {@link indexStoredByName} refuses on the NEXT run.\n //\n // Names arrive canonical (`V2TouchBuilder` trims in its constructor, and\n // `V2EndingBuilder` inherits it), so `\"Welcome\"` and `\" Welcome \"` are\n // already one name here rather than two this gate would wave through.\n //\n // `assertUnambiguousNames()` checks each kind separately and runs from\n // `adopt()`, which a brand-new Journey never reaches — so it cannot be\n // this gate. It still owns routes and goals, whose namespaces are their\n // own.\n const stepNames = [\n ...this.allTouches().map((touch) => touch.name),\n ...this.endings.map((ending) => ending.name),\n ];\n const claims = new Map<string, number>();\n for (const name of stepNames) claims.set(name, (claims.get(name) ?? 0) + 1);\n const repeated = [...claims.values()].filter((count) => count > 1).length;\n if (repeated) problems.push(sharedStepNameProblem(repeated));\n\n // A name that is only whitespace canonicalizes to nothing, which the API\n // refuses (\"name cannot be empty\") — but on the definition PUT, after\n // `apply()` has created the Journey or paused a live one. It also has no\n // usable address: every empty name would claim `key:`. Refusing it here\n // is the same answer, before the first write.\n const nameless = stepNames.filter((name) => !name).length;\n if (nameless) problems.push(namelessStepProblem(nameless));\n return problems;\n }\n\n /**\n * Every step a goal in THIS journey can anchor to, compared by object\n * identity — touches AND Endings, which is why the element type names both\n * rather than leaning on `V2EndingBuilder extends V2TouchBuilder` to smuggle\n * Endings in under a touch-only annotation.\n *\n * A goal anchored to some other journey's builder is not a near miss the\n * server can catch: an unsaved one sends a `stepKey` this definition never\n * declares (a 404 whose cause is invisible), and a SAVED one sends a real\n * `stepUuid` belonging to a live step somewhere else.\n */\n private ownedAnchors(): ReadonlySet<V2TouchBuilder | V2EndingBuilder> {\n return new Set<V2TouchBuilder | V2EndingBuilder>([...this.allTouches(), ...this.endings]);\n }\n\n planLine(): string {\n const parts: string[] = [];\n const touchCount = this.allTouches().length;\n const routeCount = this.allRoutes().length;\n if (touchCount) parts.push(`${touchCount} touches`);\n if (routeCount) parts.push(`${routeCount} routes`);\n if (this.endings.length) parts.push(`${this.endings.length} endings`);\n if (this.goals.length) parts.push(`${this.goals.length} goals`);\n return `Journey (v2): ${this.name}${parts.length ? ` (${parts.join(', ')})` : ''}`;\n }\n\n /**\n * Re-attach every stable child identity the server already holds.\n *\n * The atomic endpoint is a FULL REPLACEMENT keyed on uuids: an omitted\n * uuid does not mean \"unchanged\", it means \"create a new one and archive\n * whatever the old one was\". So anything this misses is silently recreated\n * on every re-run of the same script — and a script is normally re-run,\n * because a program is built in stages. Each identity has a different thing\n * hanging off it, and losing it costs something specific:\n *\n * | identity | what re-creating it destroys |\n * |---|---|\n * | touch step uuid | the touch's `MemberJourneyStep` history |\n * | EventRule uuid | that action's delivery bookkeeping |\n * | Ending RULE uuid | which Ending completed enrollments latched |\n * | Ending anchor uuid | the Ending's status history and goal anchor |\n * | goal uuid | every member's satisfaction row for that goal |\n *\n * `existing` is the journey DETAIL or AUTHORING projection. Both carry\n * `steps[].eventRules`, `goals`, and `decisionRules` —\n * the read projection redacts CEL, not identity — so one fetch is enough\n * and no second round trip is needed. (The orchestrator asks for the\n * authoring projection anyway: this builder holds `journeys:write` because\n * it is about to PUT, and the superset costs nothing.)\n *\n * Names are the only key available on a FIRST adoption, and a duplicate\n * name makes adoption a coin flip between two live resources. That throws\n * rather than guessing: silently attaching a touch to the wrong step\n * archives real member history.\n */\n adopt(existing: AnyRecord): void {\n super.adopt(existing);\n this._expectedUpdatedAt = existing.updatedAt as string | undefined;\n this._status = existing.status as string | undefined;\n this.assertUnambiguousNames();\n this.adoptChildIdentities(existing);\n }\n\n /** Reject a script whose own names cannot identify a resource. */\n private assertUnambiguousNames(): void {\n assertUniqueNames(\n this.allTouches().map((touch) => touch.name),\n `journey '${this.name}'`,\n 'touch'\n );\n // Route names are the adoption key for a route's DECISION RULE, exactly\n // as an Ending's name is, so they must be unique across the whole\n // journey rather than only within their own branch — two branches each\n // with a route called \"Escalate\" would make adoption a coin flip\n // between two live rules.\n assertUniqueNames(\n this.allRoutes().map((route) => route.name),\n `journey '${this.name}'`,\n 'route'\n );\n assertUniqueNames(\n this.endings.map((ending) => ending.name),\n `journey '${this.name}'`,\n 'ending'\n );\n assertUniqueNames(\n this.goals.map((goal) => goal.name),\n `journey '${this.name}'`,\n 'goal'\n );\n for (const touch of [...this.allTouches(), ...this.endings]) {\n const names = touch.rules.map((rule) => rule.options.name).filter(Boolean) as string[];\n assertUniqueNames(names, `touch '${touch.name}'`, 'action name');\n }\n }\n\n private adoptChildIdentities(payload: AnyRecord): void {\n const steps = (payload.steps ?? []) as AnyRecord[];\n // The step names this script will actually look up. Everything below\n // matches STORED rows by name, and neither the table nor the publish\n // validator makes those names unique — so a plain `new Map(...)` would\n // quietly keep the last row of a duplicated name and adopt an arbitrary\n // one of two live identities, archiving the other's member history on\n // the next save. A duplicate the script never names is nobody's problem\n // and is left alone.\n const referencedStepNames = new Set([\n ...this.allTouches().map((touch) => touch.name),\n ...this.endings.map((ending) => ending.name),\n ]);\n const stepsByName = indexStoredByName(\n steps,\n referencedStepNames,\n `journey '${this.name}'`,\n 'step'\n );\n const stepsById = new Map(steps.map((step) => [step.id as number, step]));\n\n for (const touch of this.allTouches()) {\n const match = stepsByName.get(touch.name);\n if (!match) continue;\n touch._uuid = match.uuid as string;\n touch.adoptRuleUuids((match.eventRules ?? []) as AnyRecord[]);\n }\n\n // Branch ROUTES are the complement of the Ending filter below: same\n // table, same identity argument, different product. Indexed by name for\n // the same reason Endings are — a route's uuid is the only thing that\n // survives a re-run, and nothing else in the payload identifies it.\n const routeRules = ((payload.decisionRules ?? []) as AnyRecord[]).filter(\n (rule) => rule.sourceStepId !== null && rule.sourceStepId !== undefined\n );\n const declaredRoutes = this.allRoutes();\n const routesByName = indexStoredByName(\n routeRules,\n new Set(declaredRoutes.map((route) => route.name)),\n `journey '${this.name}'`,\n 'route'\n );\n for (const route of declaredRoutes) {\n const stored = routesByName.get(route.name);\n if (stored) route._ruleUuid = stored.uuid as string;\n }\n\n // An Ending's identity is its decision RULE; the anchor is reached\n // through the rule's target rather than by name, so an adopted Ending\n // never picks up a touch's step. (An Ending and a touch DECLARED under\n // one name are still two stored steps sharing a name, which the step\n // index above refuses — from the touch's side, where the ambiguity is\n // real.)\n const endingRules = ((payload.decisionRules ?? []) as AnyRecord[]).filter(\n (rule) => rule.sourceStepId === null || rule.sourceStepId === undefined\n );\n const rulesByName = indexStoredByName(\n endingRules,\n new Set(this.endings.map((ending) => ending.name)),\n `journey '${this.name}'`,\n 'ending'\n );\n for (const ending of this.endings) {\n const rule = rulesByName.get(ending.name);\n const anchor = rule\n ? stepsById.get(rule.targetStepId as number)\n : stepsByName.get(ending.name);\n if (rule) ending._ruleUuid = rule.uuid as string;\n if (!anchor) continue;\n ending._uuid = anchor.uuid as string;\n ending.adoptRuleUuids((anchor.eventRules ?? []) as AnyRecord[]);\n }\n\n const goalsByName = indexStoredByName(\n (payload.goals ?? []) as AnyRecord[],\n new Set(this.goals.map((goal) => goal.name)),\n `journey '${this.name}'`,\n 'goal'\n );\n for (const goal of this.goals) {\n const match = goalsByName.get(goal.name);\n if (match) goal._uuid = match.uuid as string;\n }\n }\n\n /** The atomic request body. Exposed so a test can assert it without HTTP. */\n definitionPayload(): JourneyV2DefinitionFormData {\n const owned = this.ownedAnchors();\n // Depth-first position, numbered exactly as `preflight()` numbers it, so\n // a refusal raised down in the serializer names the same touch the\n // pre-write gate would have named.\n const positions: ReadonlyMap<V2TouchBuilder, number> = new Map(\n this.allTouches().map((touch, index) => [touch, index])\n );\n return {\n expectedUpdatedAt: this._expectedUpdatedAt ?? '',\n touches: this.touches.map((touch) => serializeV2Touch(touch, positions)),\n endings: this.endings.map((ending): JourneyV2EndingInput => ({\n ...(ending._ruleUuid ? { uuid: ending._ruleUuid } : {}),\n // Anchor address, exactly as `serializeV2Touch` sends a touch's:\n // the saved anchor's uuid, or the request-local `key` a goal in\n // this same save names it by. Both come from `_address`, so the\n // Ending and the goal cannot be sent under two spellings.\n ...(ending._uuid ? { anchorUuid: ending._uuid } : { key: ending._address }),\n name: ending.name,\n // The two predicates are sent INDEPENDENTLY (rule-filters plan\n // §3.2). A filter-only Ending carries no `celCondition` at all\n // rather than an empty one the server would have to normalize.\n ...(ending.when ? { celCondition: ending.when } : {}),\n ...(ending.filterId !== undefined ? { filterId: ending.filterId } : {}),\n eventRules: ending.eventRuleInputs(),\n })),\n // ALWAYS sent, `[]` included. The field distinguishes omitted (leave\n // goals alone) from empty (delete them), and this builder owns the\n // goal list — so omitting an empty list would make goal REMOVAL the\n // one edit a script cannot express: delete the `.goal(...)` call, re-run,\n // and the goal stays live forever.\n goals: this.goals.map((goal, index): JourneyV2GoalInput => ({\n ...(goal._uuid ? { uuid: goal._uuid } : {}),\n name: goal.name,\n ...(goal.description ? { description: goal.description } : {}),\n ...serializeV2GoalAnchor(goal.step, index, owned),\n ...(goal.completionCel ? { completionCel: goal.completionCel } : {}),\n ...(goal.value !== undefined ? { value: goal.value } : {}),\n })),\n };\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n // `WorkspaceBuilder.apply()` gates this, but the class is exported and a\n // direct caller gets no gate at all — while the first statements below\n // are writes. Refuse here too, so an invalid plan never leaves an empty\n // shell behind or pauses a production Journey.\n const problems = this.preflight();\n if (problems.length) {\n throw new Error(\n `Journey (v2) has ${problems.length} problem(s) and was not applied:\\n` +\n problems.map((problem) => ` - ${problem}`).join('\\n')\n );\n }\n\n if (!this._existed) {\n const created = await client.createJourney({\n name: this.name,\n description: this.description,\n // Explicit, always. An omitted executionModel means `legacy` on the\n // server, so a v2 builder that forgot it would quietly author a\n // legacy Journey that happens to look like a timeline.\n executionModel: 'v2',\n });\n this._id = created.id;\n this._uuid = created.uuid;\n this._created = true;\n this._expectedUpdatedAt = created.updatedAt;\n } else if (this._status === 'active' && this.activate) {\n // A live Journey's topology is immutable, so a re-run has to pause\n // before it can write, and re-read for a fresh concurrency token.\n //\n // Only when the script ASKED for an active Journey. Pausing one it\n // did not ask to activate would take a production program off the air\n // as a side effect of re-running a script; without `activate` the\n // server's stable `journey_v2_structural_edit_not_allowed` refusal is\n // the right answer, and it tells the operator exactly what to do.\n const paused = await client.updateJourney(this.id, { status: 'paused' });\n this._expectedUpdatedAt = paused.updatedAt;\n }\n\n const saved = await client.putJourneyV2Definition(this.id, this.definitionPayload());\n this._expectedUpdatedAt = saved.updatedAt;\n this.adoptWrittenUuids(saved);\n\n if (this.activate) {\n await client.updateJourney(this.id, { status: 'active' });\n }\n }\n\n /**\n * Re-attach the uuids the server assigned, so a follow-up write matches.\n *\n * The PUT returns the AUTHORING projection, which is the same shape\n * `adopt` reads — so this is the same operation against a payload we just\n * caused, and it uses the same code path rather than a second, thinner\n * copy that would drift.\n */\n private adoptWrittenUuids(saved: AnyRecord): void {\n this.adoptChildIdentities(saved);\n }\n}\n\n/**\n * Index STORED rows by name, refusing a name the script matches that more than\n * one stored row answers to.\n *\n * The mirror image of {@link assertUniqueNames}: that one rejects a script\n * whose own names are ambiguous, this one rejects a SERVER state the script's\n * names cannot resolve. Both halves are needed, because nothing makes a\n * journey's step, Ending, goal, or action names unique — not the tables, not\n * the publish validator — so the ambiguity can arrive from the editor long\n * after a clean script was written.\n *\n * `referenced` is the set of names the script will look up. A stored duplicate\n * outside it is harmless: nothing in this script will ever choose between\n * those two rows, and refusing to run because of a resource the script does\n * not touch would be a gate the author cannot act on.\n */\nfunction indexStoredByName(\n rows: AnyRecord[],\n referenced: Set<string>,\n owner: string,\n kind: string\n): Map<string, AnyRecord> {\n const byName = new Map<string, AnyRecord>();\n const counts = new Map<string, number>();\n for (const row of rows) {\n const name = row.name;\n if (typeof name !== 'string' || !name) continue;\n counts.set(name, (counts.get(name) ?? 0) + 1);\n if (!byName.has(name)) byName.set(name, row);\n }\n for (const [name, count] of counts) {\n if (count < 2 || !referenced.has(name)) continue;\n throw new Error(\n `${owner} already has ${count} ${kind}s named '${name}'. This script adopts ` +\n `by name, so it cannot tell which ${kind} it owns — and the one it does ` +\n 'not pick is archived on the next save, taking its history with it. ' +\n `Rename them so each name identifies one ${kind}.`\n );\n }\n return byName;\n}\n\n/** Throw when a builder's own names cannot identify a resource. */\nfunction assertUniqueNames(names: string[], owner: string, kind: string): void {\n const seen = new Set<string>();\n for (const name of names) {\n if (seen.has(name)) {\n throw new Error(\n `${owner} has two ${kind}s named '${name}'. The v2 builder adopts an ` +\n 'existing journey by name, so duplicates would attach a builder to ' +\n \"either one at random — archiving the other's history on the next \" +\n 'save. Rename one.'\n );\n }\n seen.add(name);\n }\n}\n\n/** Translate builder wait options into the server's structured wait. */\n/**\n * Serialize one touch and, recursively, the branch it owns.\n *\n * A free function rather than a method so the recursion reads as one shape:\n * touch -> branch -> routes -> arm touches -> … . `key` is sent whenever the\n * touch has no server uuid yet, because an arm can only name an unsaved\n * rejoin target through the request-local address (plan §3.8).\n */\nfunction serializeV2Touch(\n touch: V2TouchBuilder,\n positions: ReadonlyMap<V2TouchBuilder, number>\n): JourneyV2TouchInput {\n return {\n ...(touch._uuid ? { uuid: touch._uuid } : { key: touch._address }),\n name: touch.name,\n ...(touch.options.description ? { description: touch.options.description } : {}),\n ...(touch.options.wait\n ? { wait: buildV2Wait(touch.options.wait, positions.get(touch)) }\n : {}),\n eventRules: touch.eventRuleInputs(),\n ...(touch._branch\n ? {\n branch: {\n routes: touch._branch.routes.map((route) => ({\n ...(route._ruleUuid ? { uuid: route._ruleUuid } : {}),\n name: route.name,\n // Omitted, not null, and INDEPENDENT of each other: a route\n // with neither predicate IS the Otherwise marker, one with\n // either is conditional, and one with both is ANDed\n // (rule-filters plan §3.2). The server normalizes \"\" to the\n // same thing as omitted.\n ...(route.options.when ? { celCondition: route.options.when } : {}),\n ...(route.options.filterId !== undefined\n ? { filterId: route.options.filterId }\n : {}),\n touches: route.touches.map((armTouch) => serializeV2Touch(armTouch, positions)),\n ...(route.options.continueAt\n ? { continueAt: route.options.continueAt._address }\n : {}),\n })),\n },\n }\n : {}),\n };\n}\n\n/**\n * How a goal names its anchor step in the atomic payload.\n *\n * A saved anchor is named by `stepUuid`. An unsaved one — a touch or an\n * Ending's anchor alike — is named by `stepKey`, carrying the same\n * request-local address the step itself is sent under, because on the FIRST\n * save of a timeline nothing has a uuid yet and a client cannot mint one.\n * Sending nothing there is not a missing decoration: an anchored goal is\n * satisfied only when its step is reached AND its CEL holds, so the goal that\n * reached the server would be a different rule from the one the script wrote.\n *\n * `owned` is the set of steps this journey declares, compared by object\n * identity: a goal anchored to another builder's step would otherwise send a\n * `stepKey` this definition never declares, or a live `stepUuid` belonging to\n * a step in some other journey. That is the one thing this cannot express, and\n * it THROWS rather than serializing to nothing — dropping an anchor is silent,\n * the payload is valid, the write succeeds, and nothing afterwards says so.\n *\n * The refusal is the LAST line of defence. `WorkspaceBuilder.apply()` gates on\n * {@link JourneyV2Builder.preflight} before it writes anything; this fires\n * only for a caller that reached `definitionPayload()` directly, and it raises\n * the identical sentence so the two paths cannot drift.\n */\nfunction serializeV2GoalAnchor(\n step: V2TouchBuilder | V2EndingBuilder | undefined,\n goalIndex: number,\n owned: ReadonlySet<V2TouchBuilder | V2EndingBuilder>\n): Pick<JourneyV2GoalInput, 'stepUuid' | 'stepKey'> {\n if (!step) return {};\n if (!owned.has(step)) throw new Error(foreignAnchorProblem(goalIndex, anchorKind(step)));\n if (step._uuid) return { stepUuid: step._uuid };\n return { stepKey: step._address };\n}\n\n/**\n * The two refusals, worded once.\n *\n * Both the pre-write gate and the serializer raise these, so an author who\n * trips the last line of defence reads the sentence the gate would have\n * printed. Each names the offender by POSITION and the anchor by KIND, never\n * by the name the script gave it: these strings reach operator terminals, CI\n * logs and exception trackers, and an authored touch, goal or Ending name is\n * workspace content that has no business in any of them.\n */\nfunction foreignAnchorProblem(goalIndex: number, kind: 'touch' | 'Ending'): string {\n return (\n `goal at index ${goalIndex} is anchored to ${kind === 'Ending' ? 'an' : 'a'} ` +\n `${kind} that belongs to a different journey builder. A goal anchor is ` +\n 'part of the same atomic definition as its step, so it can only name a ' +\n 'touch or Ending this journey declares.'\n );\n}\n\n/**\n * `touchIndex` is the touch's depth-first position, absent only for a direct\n * caller of {@link buildV2Wait} that has no timeline to position it in.\n *\n * @see foreignAnchorProblem for why these carry positions and not names.\n */\nfunction waitExclusivityProblem(touchIndex: number | undefined): string {\n const where = touchIndex === undefined ? 'this touch' : `touch at index ${touchIndex}`;\n return (\n `${where} sets both afterDays and when; fold the day count into \\`when\\`. ` +\n 'A v2 wait is either a whole-day count or Advanced CEL, not both.'\n );\n}\n\n/**\n * Step names claimed more than once, counted across touches AND Endings.\n *\n * @see foreignAnchorProblem for why this counts them and does not name them.\n */\nfunction sharedStepNameProblem(count: number): string {\n return (\n `${count} step name(s) are claimed more than once. Touches and Endings ` +\n 'are one namespace: until a save mints their uuids they address ' +\n 'themselves by name and the definition resolves those keys through one ' +\n 'field, and once saved they are stored steps the next run cannot tell ' +\n 'apart. Names are canonical (trimmed), as the API stores them. Rename one.'\n );\n}\n\n/**\n * Steps whose canonical name is empty.\n *\n * @see foreignAnchorProblem for why this counts them and does not name them.\n */\nfunction namelessStepProblem(count: number): string {\n return (\n `${count} step(s) have an empty name once trimmed. A step's name is its ` +\n 'request-local address until a save mints its uuid, so a nameless one ' +\n 'has nothing to be addressed by, and the API refuses it. Name them.'\n );\n}\n\n/** How a refusal names an anchor: by what it IS, never by what it is called. */\nfunction anchorKind(step: V2TouchBuilder | V2EndingBuilder): 'touch' | 'Ending' {\n return step instanceof V2EndingBuilder ? 'Ending' : 'touch';\n}\n\nexport function buildV2Wait(wait: V2WaitOptions, touchIndex?: number): JourneyV2WaitInput {\n if (wait.afterDays !== undefined && wait.when) {\n throw new Error(waitExclusivityProblem(touchIndex));\n }\n const extras = {\n ...(wait.filterId !== undefined ? { filterId: wait.filterId } : {}),\n };\n if (wait.afterDays !== undefined) {\n return { kind: 'wholeDays', days: wait.afterDays, ...extras };\n }\n if (wait.when) {\n return { kind: 'advanced', cel: wait.when, ...extras };\n }\n return { kind: 'none', ...extras };\n}\n","import type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport type { AnyRecord } from './resource';\nimport { WorkspaceBuilderResource } from './resource';\n\nexport class RoleUpdate extends WorkspaceBuilderResource {\n constructor(\n readonly roleId: number,\n readonly workflowIds?: number[],\n readonly dataTypeIds?: number[]\n ) {\n super();\n }\n\n planLine(): string {\n const parts: string[] = [];\n if (this.workflowIds) parts.push(`workflows=${JSON.stringify(this.workflowIds)}`);\n if (this.dataTypeIds) parts.push(`dataTypes=${JSON.stringify(this.dataTypeIds)}`);\n return `RoleUpdate: roleId=${this.roleId}${parts.length ? ` (${parts.join(', ')})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const payload: AnyRecord = {};\n if (this.workflowIds) payload.workflowIds = this.workflowIds;\n if (this.dataTypeIds) payload.dataTypeIds = this.dataTypeIds;\n if (Object.keys(payload).length) await client.updateMemberRole(this.roleId, payload);\n this._id = this.roleId;\n this._created = true;\n }\n}\n","import {\n EventRuleEventType,\n type CreateAgentRequest,\n type EventRuleActionType,\n type WorkflowFormData,\n} from '../types';\nimport type { Ability } from '../types/ability-types';\nimport type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport type { WorkspaceBuilderEventRule } from './event-rules';\nimport type { FormBuilder } from './forms';\nimport { type AnyRecord, WorkspaceBuilderResource } from './resource';\n\nconst PERM_KEYS: Record<string, string> = {\n canRead: 'canRead',\n canCreate: 'canCreate',\n canEdit: 'canEdit',\n can_read: 'canRead',\n can_create: 'canCreate',\n can_edit: 'canEdit',\n};\n\nconst ABILITY_TYPE_MAP: Record<string, string> = {\n data_access: 'integration:data_access',\n file_access: 'integration:file_access',\n escalation: 'oversight:escalation',\n};\n\nclass AbilityDef {\n readonly uuid = crypto.randomUUID();\n readonly config: AnyRecord;\n readonly enabled: boolean;\n readonly celCondition?: string;\n readonly form?: FormBuilder;\n readonly perms: AnyRecord = {};\n\n constructor(\n readonly abilityType: string,\n options: AnyRecord = {}\n ) {\n this.config = options.config ?? {};\n this.enabled = options.enabled ?? true;\n this.celCondition = options.celCondition ?? options.cel_condition;\n this.form = options.form;\n for (const [inputKey, outputKey] of Object.entries(PERM_KEYS)) {\n if (inputKey in options) this.perms[outputKey] = options[inputKey];\n }\n }\n\n toAbility(): Ability {\n const config = { ...this.config };\n if (this.form?._uuid) {\n config.dataTypeUuid = this.form._uuid;\n Object.assign(config, this.perms);\n }\n return {\n uuid: this.uuid,\n abilityType: ABILITY_TYPE_MAP[this.abilityType] ?? this.abilityType,\n config,\n enabled: this.enabled,\n ...(this.celCondition ? { celCondition: this.celCondition } : {}),\n };\n }\n}\n\nexport interface TaskTransition {\n parent: TaskBuilder;\n child: TaskBuilder;\n when: string;\n autoNext: boolean;\n required: boolean;\n celCondition?: string;\n}\n\nexport interface WorkflowBuilderOptions {\n description?: string;\n prompt?: string;\n copyFromAgentId?: number;\n}\n\nexport class TaskBuilder extends WorkspaceBuilderResource {\n readonly transitions: TaskTransition[] = [];\n readonly eventRules: WorkspaceBuilderEventRule[] = [];\n /** Child task ids the server already has, recorded when this task is adopted. */\n readonly existingChildIds = new Set<number>();\n\n /** Record the edges an adopted task already carries, so a re-run adds only what is missing. */\n adopt(existing: AnyRecord): void {\n super.adopt(existing);\n for (const child of (existing.childTasks ?? []) as AnyRecord[]) {\n const id = child.taskId ?? child.id;\n if (typeof id === 'number') this.existingChildIds.add(id);\n }\n }\n\n constructor(\n readonly name: string,\n readonly workflow: WorkflowBuilder,\n readonly prompt = '',\n readonly start = false,\n readonly description = ''\n ) {\n super();\n }\n\n transitionsTo(\n child: TaskBuilder,\n when: string,\n autoNext = false,\n required = false,\n celCondition?: string\n ): TaskBuilder {\n if (child === this) {\n throw new Error(`Task '${this.name}' cannot transition to itself`);\n }\n this.transitions.push({\n parent: this,\n child,\n when,\n autoNext,\n required,\n celCondition,\n });\n return this;\n }\n\n onEnter(action: string, params: AnyRecord = {}, name?: string): TaskBuilder {\n this.eventRules.push({\n eventType: EventRuleEventType.TASK_EXECUTE,\n actionType: action as EventRuleActionType,\n actionParams: params,\n name,\n });\n return this;\n }\n\n initialMessage(message: string, suggestions?: string[]): TaskBuilder {\n return this.onEnter('assistant:message', {\n message,\n ...(suggestions ? { suggestions } : {}),\n });\n }\n\n planLine(): string {\n return `Task: ${this.name}${this.start ? ' [start]' : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed || this.workflow._id === undefined) return;\n if (this.workflow._draftRevisionId === undefined) {\n // Root id without a draft revision id means the workflow was\n // created/adopted through a path that skipped revision resolution —\n // creating the task would attach it to whatever revision happens to\n // share the number (cross-workflow corruption). Fail loudly.\n throw new Error(\n `Workflow '${this.workflow.name}' has no draft revision id; ` +\n 'cannot create tasks. Tasks attach to a WorkflowRevision, ' +\n 'not the stable workflow root.'\n );\n }\n // Tasks belong to a revision graph — target the DRAFT revision\n // explicitly (edits always land on the draft; publish makes them live).\n const result = await client.createTask({\n workflowRevisionId: this.workflow._draftRevisionId,\n name: this.name,\n prompt: this.prompt,\n description: this.description,\n });\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n\nexport class WorkflowBuilder extends WorkspaceBuilderResource {\n readonly description: string;\n readonly prompt?: string;\n private copyFromAgentId?: number;\n readonly tasks: TaskBuilder[] = [];\n readonly abilities: AbilityDef[] = [];\n /** The DRAFT revision's id — where tasks and graph edits attach.\n * `_id` is the STABLE workflow root id; the two are different entities\n * and (after any publish) different numbers. */\n _draftRevisionId?: number;\n\n constructor(\n readonly name: string,\n options: WorkflowBuilderOptions = {}\n ) {\n super();\n this.description = options.description ?? '';\n this.prompt = options.prompt;\n this.copyFromAgentId = options.copyFromAgentId;\n }\n\n task(name: string, options: AnyRecord = {}): TaskBuilder {\n const task = new TaskBuilder(\n name,\n this,\n options.prompt ?? '',\n options.start ?? false,\n options.description ?? ''\n );\n this.tasks.push(task);\n return task;\n }\n\n ability(abilityType: string, options: AnyRecord = {}): WorkflowBuilder {\n this.abilities.push(new AbilityDef(abilityType, options));\n return this;\n }\n\n get startTask(): TaskBuilder | undefined {\n return this.tasks.find((task) => task.start) ?? this.tasks[0];\n }\n\n matchKey(): string {\n return this.name;\n }\n\n adopt(existing: AnyRecord): void {\n // Accepts the WorkflowDetail composition ({ workflow, draftRevision,\n // activeRevision }) — the orchestrator fetches it per matched name.\n // Root facts (id/uuid) live on `workflow`; graph facts (startTaskId)\n // live on the draft revision.\n const root = (existing.workflow ?? existing) as AnyRecord;\n super.adopt(root);\n const draft = existing.draftRevision as AnyRecord | undefined;\n this._draftRevisionId = (draft?.id ?? root.draftRevisionId) as number | undefined;\n const start = this.startTask;\n const startTaskId = draft?.startTaskId as number | undefined;\n if (start && startTaskId) {\n start._id = startTaskId;\n start._existed = true;\n }\n }\n\n planLine(): string {\n const details: string[] = [];\n if (this.tasks.length) details.push(`${this.tasks.length} tasks`);\n if (this.abilities.length) details.push(`${this.abilities.length} abilities`);\n return `Workflow: ${this.name}${details.length ? ` (${details.join(', ')})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const payload: WorkflowFormData = {\n name: this.name,\n description: this.description,\n createMode: 'taskless',\n ...(this.prompt ? { prompt: this.prompt } : {}),\n ...(this.copyFromAgentId ? { copyFromAgentId: this.copyFromAgentId } : {}),\n ...(this.abilities.length\n ? { abilities: this.abilities.map((ability) => ability.toAbility()) }\n : {}),\n };\n const result = await client.createWorkflow(payload);\n this._id = result.workflow.id;\n this._uuid = result.workflow.uuid;\n // Tasks attach to the draft revision, never the root — keep its id.\n this._draftRevisionId = result.draftRevision.id;\n this._created = true;\n }\n}\n\nexport class AgentBuilder extends WorkspaceBuilderResource {\n readonly chatModelId: string;\n readonly systemPrompt: string;\n readonly memberRoleId?: number;\n readonly tools: string[];\n readonly codeInterpreterEnabled: boolean;\n readonly webBrowserEnabled: boolean;\n\n constructor(\n readonly name: string,\n options: AnyRecord = {}\n ) {\n super();\n this.chatModelId = options.chatModelId ?? options.chat_model_id ?? '';\n this.systemPrompt = options.systemPrompt ?? options.system_prompt ?? '';\n this.memberRoleId = options.roleId ?? options.role_id;\n this.tools = options.tools ?? [];\n this.codeInterpreterEnabled =\n options.codeInterpreterEnabled ?? options.code_interpreter_enabled ?? false;\n this.webBrowserEnabled = options.webBrowserEnabled ?? options.web_browser_enabled ?? false;\n }\n\n planLine(): string {\n const parts: string[] = [];\n if (this.chatModelId) parts.push(`model=${this.chatModelId}`);\n if (this.tools.length) parts.push(`${this.tools.length} tools`);\n return `Agent: ${this.name}${parts.length ? ` (${parts.join(', ')})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n if (this.memberRoleId === undefined) {\n throw new Error(`Agent '${this.name}' requires memberRoleId`);\n }\n if (!this.chatModelId) {\n throw new Error(`Agent '${this.name}' requires chatModelId`);\n }\n\n const payload: CreateAgentRequest = {\n name: this.name,\n memberRoleId: this.memberRoleId,\n chatModelId: this.chatModelId,\n systemPrompt: this.systemPrompt,\n ...(this.tools.length ? { tools: this.tools } : {}),\n ...(this.codeInterpreterEnabled ? { codeInterpreterEnabled: true } : {}),\n ...(this.webBrowserEnabled ? { webBrowserEnabled: true } : {}),\n };\n const result = await client.createAgent(payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n","import {\n EventRuleObjectType,\n type EventRule,\n type EventRuleFormData,\n type UpdateEventRuleFormData,\n} from '../types';\nimport { ApiError } from '../api/base';\nimport type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport { MemberFilterBuilder, NotificationRuleBuilder, RoutineBuilder } from './automation';\nimport { FormBuilder, MemberLabelBuilder } from './forms';\nimport {\n buildJourneyConnectionPayload,\n buildJourneyGoalPayload,\n JourneyBuilder,\n JourneyStepBuilder,\n JourneyV2Builder,\n} from './journeys';\nimport {\n type AnyRecord,\n type ResourceSummary,\n resolveRefs,\n WorkspaceBuilderResource,\n} from './resource';\nimport { RoleUpdate } from './role-update';\nimport {\n AgentBuilder,\n TaskBuilder,\n type TaskTransition,\n WorkflowBuilder,\n type WorkflowBuilderOptions,\n} from './workflows';\n\nconst PHASES = new Map<Function, number>([\n [FormBuilder, 0],\n [MemberLabelBuilder, 0],\n [AgentBuilder, 1],\n [WorkflowBuilder, 2],\n [TaskBuilder, 3],\n [RoleUpdate, 4],\n [MemberFilterBuilder, 5],\n [RoutineBuilder, 6],\n [NotificationRuleBuilder, 6],\n [JourneyBuilder, 7],\n // Same phase as the legacy builder: a v2 Journey is written whole by its\n // own apply(), so it has no child resources to sequence after it.\n [JourneyV2Builder, 7],\n [JourneyStepBuilder, 8],\n]);\n\n/**\n * Page size for the adoption sweeps.\n *\n * Adoption has to see every resource of a type, not the first screenful — the\n * list routes default to 10 per page, so a workspace with a dozen routines\n * would leave the eleventh undiscovered and duplicated on every re-run. 100 is\n * the max these routes allow; `collectPages` walks the rest.\n */\nconst LIST_PAGE_SIZE = 100;\n\n/**\n * Read every page of a paginated list endpoint.\n *\n * `totalPages` is trusted for the bound but the walk also stops on an empty\n * page, so a backend that reports the count differently cannot spin here.\n */\nasync function collectPages<T>(\n fetchPage: (page: number) => Promise<{ items: T[]; totalPages?: number }>\n): Promise<T[]> {\n const first = await fetchPage(1);\n const all = [...first.items];\n const totalPages = first.totalPages ?? 1;\n for (let page = 2; page <= totalPages; page++) {\n const next = await fetchPage(page);\n if (!next.items.length) break;\n all.push(...next.items);\n }\n return all;\n}\n\nfunction sameIdSet(left: number[], right: number[]): boolean {\n const target = new Set(right);\n return target.size === new Set(left).size && left.every((id) => target.has(id));\n}\n\nfunction notificationRuleKey(\n noticeType: string,\n memberId: number,\n workflowId: number | null\n): string {\n return JSON.stringify([noticeType, memberId, workflowId]);\n}\n\n/**\n * Resolve a resource's build phase, walking the prototype chain.\n *\n * Keyed on the exact constructor a subclass (e.g. the journey `Start` step)\n * misses every entry and silently sorts to the end — applying its edges after\n * everything else and hiding ordering bugs behind an accident.\n */\nfunction phaseFor(resource: WorkspaceBuilderResource): number {\n let ctor: Function | null = resource.constructor;\n while (ctor) {\n const phase = PHASES.get(ctor);\n if (phase !== undefined) return phase;\n ctor = Object.getPrototypeOf(ctor) as Function | null;\n }\n return 99;\n}\n\nexport class WorkspaceBuilder {\n readonly resources: WorkspaceBuilderResource[] = [];\n\n constructor(readonly client: GravityRailWorkspaceClient) {}\n\n form(name: string, options: AnyRecord & { slug?: string } = {}): FormBuilder {\n const form = new FormBuilder(name, options.slug, options);\n this.resources.push(form);\n return form;\n }\n\n workflow(name: string, options: WorkflowBuilderOptions = {}): WorkflowBuilder {\n const workflow = new WorkflowBuilder(name, options);\n this.resources.push(workflow);\n return workflow;\n }\n\n label(\n name: string,\n options: { slug?: string; color?: string; description?: string } = {}\n ): MemberLabelBuilder {\n const label = new MemberLabelBuilder(\n name,\n options.slug,\n options.color,\n options.description ?? ''\n );\n this.resources.push(label);\n return label;\n }\n\n journey(name: string, options: AnyRecord = {}): JourneyBuilder {\n const journey = new JourneyBuilder(name, options);\n this.resources.push(journey);\n return journey;\n }\n\n /**\n * A Journey v2 timeline (plan §3.8): ordered touches, structured waits, and\n * ordered Endings, written through the atomic definition endpoint.\n *\n * A separate factory rather than an option on {@link journey}, because the\n * two return different builders with different vocabularies — `.touch()`\n * and `.ending()` versus `.step()` and `.connectsTo()`. The legacy builder\n * keeps its current behaviour untouched, which is the plan's explicit\n * compatibility requirement.\n */\n journeyV2(name: string, options: AnyRecord = {}): JourneyV2Builder {\n const journey = new JourneyV2Builder(name, options);\n this.resources.push(journey);\n return journey;\n }\n\n agent(name: string, options: AnyRecord = {}): AgentBuilder {\n const agent = new AgentBuilder(name, options);\n this.resources.push(agent);\n return agent;\n }\n\n routine(name: string, cronSchedule = '', options: AnyRecord = {}): RoutineBuilder {\n const routine = new RoutineBuilder(name, cronSchedule, options);\n this.resources.push(routine);\n return routine;\n }\n\n memberFilter(name: string, options: AnyRecord = {}): MemberFilterBuilder {\n const filter = new MemberFilterBuilder(name, options);\n this.resources.push(filter);\n return filter;\n }\n\n notificationRule(name: string, options: AnyRecord = {}): NotificationRuleBuilder {\n const rule = new NotificationRuleBuilder(name, options);\n this.resources.push(rule);\n return rule;\n }\n\n roleUpdate(roleId: number, workflowIds?: number[], dataTypeIds?: number[]): RoleUpdate {\n const update = new RoleUpdate(roleId, workflowIds, dataTypeIds);\n this.resources.push(update);\n return update;\n }\n\n plan(): void {\n const resources = this.sortedResources();\n writeLine(`\\n${'='.repeat(50)}`);\n writeLine('Plan');\n writeLine('='.repeat(50));\n const declared = resources.filter((resource) => !resource.isImplicit);\n for (const resource of declared) {\n writeLine(` + ${resource.planLine()}`);\n }\n const wiring = this.collectWiringSummary(resources);\n if (wiring.length) {\n writeLine('\\n Wiring:');\n for (const line of wiring) writeLine(` ${line}`);\n }\n this.reportJourneyWarnings();\n writeLine(`\\n Total: ${declared.length} resources, ${wiring.length} connections`);\n writeLine(`${'='.repeat(50)}\\n`);\n }\n\n async preview(): Promise<void> {\n const resources = this.sortedResources();\n await this.resolveExisting(resources);\n\n writeLine(`\\n${'='.repeat(50)}`);\n writeLine('Preview');\n writeLine('='.repeat(50));\n const declared = resources.filter((resource) => !resource.isImplicit);\n for (const resource of declared) {\n if (resource._existed) {\n writeLine(` = ${resource.planLine()} (exists, id=${resource._id})`);\n } else {\n writeLine(` + ${resource.planLine()}`);\n }\n }\n const wiring = this.collectWiringSummary(resources);\n if (wiring.length) {\n writeLine('\\n Wiring:');\n for (const line of wiring) writeLine(` ${line}`);\n }\n this.reportJourneyWarnings();\n const toCreate = declared.filter((resource) => !resource._existed);\n const existing = declared.filter((resource) => resource._existed);\n writeLine(\n `\\n Total: ${toCreate.length} to create, ${existing.length} existing, ${wiring.length} connections`\n );\n writeLine(`${'='.repeat(50)}\\n`);\n }\n\n /**\n * Print journey authoring problems that only bite at runtime — a step with\n * no incoming edge fires for every member at enrolment, and a step with no\n * action does nothing at all. Both look fine in the editor, so they are\n * surfaced before the write rather than discovered from a member's phone.\n */\n private reportJourneyWarnings(): void {\n const problems = this.resources\n .filter(\n (resource): resource is JourneyBuilder | JourneyV2Builder =>\n resource instanceof JourneyBuilder || resource instanceof JourneyV2Builder\n )\n .flatMap((journey) => journey.validate());\n if (!problems.length) return;\n writeLine('\\n Journey warnings:');\n for (const problem of problems) writeLine(` ! ${problem}`);\n }\n\n /**\n * Problems that make the plan unwritable, found before the first write.\n *\n * The API validates each CEL when you save it, and its diagnosis is right —\n * but it fires per-write, so a plan whose edges reference a non-collection\n * form gets four labels, two forms, a workflow and six tasks created before\n * the seventh call rejects it. The operator is left with a half-built\n * program to hand-repair. Checking here costs nothing and writes nothing.\n *\n * Deliberately narrow: only cross-resource facts the builder can see with\n * certainty. Per-field CEL schema checking stays server-side, where the\n * real validator lives — duplicating it here would drift.\n *\n * Pure: reads only what the plan declares, never what the server holds, so\n * it is correct before adoption and safe for a caller to run directly. It\n * is also the WHOLE gate: every anchor a v2 definition can name has a\n * request-local address whether or not the server has seen it, so no\n * refusal has to wait for adoption to decide it.\n */\n preflight(): string[] {\n const problems: string[] = [];\n const forms = this.resources.filter(\n (resource): resource is FormBuilder => resource instanceof FormBuilder\n );\n const collectionBySlug = new Map(forms.map((form) => [form.slug, form.collection]));\n\n // `assignment.collections.<slug>` requires <slug> to be a COLLECTION\n // form. This is the exact defect that shipped: the edges were right, the\n // form was declared without `collection: true`, and nothing said so\n // until fourteen resources existed.\n const reference = /assignment\\.collections\\.([A-Za-z0-9_]+)/g;\n for (const resource of this.sortedResources()) {\n if (!(resource instanceof TaskBuilder)) continue;\n for (const transition of resource.transitions) {\n const cel = transition.celCondition;\n if (!cel) continue;\n for (const [, slug] of cel.matchAll(reference)) {\n if (!collectionBySlug.has(slug)) continue; // server resolves it\n if (!collectionBySlug.get(slug)) {\n problems.push(\n `task '${transition.parent.name}' → '${transition.child.name}': CEL reads ` +\n `assignment.collections.${slug}, but this plan creates '${slug}' as a ` +\n `non-collection form. Declare it with { collection: true }.`\n );\n }\n }\n }\n }\n\n // A v2 Journey is written as ONE atomic PUT, and `JourneyV2Builder.apply()`\n // has to create the Journey — or pause a live one — before it can build\n // that payload. So a definition the builder cannot express has to be\n // refused here or the refusal lands after those writes, leaving an empty\n // journey shell or a production program off the air.\n for (const resource of this.resources) {\n if (resource instanceof JourneyV2Builder) problems.push(...resource.preflight());\n }\n return [...new Set(problems)];\n }\n\n /** The plan-rejection shape: every problem printed, nothing written. */\n private rejectIfProblems(problems: string[]): void {\n if (!problems.length) return;\n writeLine('\\nPlan rejected — nothing was created:');\n for (const problem of problems) writeLine(` ! ${problem}`);\n throw new Error(\n `Plan has ${problems.length} problem(s) and was not applied:\\n` +\n problems.map((problem) => ` - ${problem}`).join('\\n')\n );\n }\n\n async apply(): Promise<ResourceSummary> {\n const resources = this.sortedResources();\n\n // Refuse before writing anything, rather than failing part-way through.\n // One gate, and it is pure: nothing it decides depends on which\n // resources the server already holds, so adoption (reads only) can run\n // after it.\n this.rejectIfProblems(this.preflight());\n await this.resolveExisting(resources);\n\n const summary: ResourceSummary = {};\n\n writeLine('Applying...');\n for (const resource of resources) {\n try {\n // The server already made it (a journey's Start step) — it is here\n // only so edges can point at it.\n if (resource.isImplicit) continue;\n // Most builders are create-only: an adopted resource is left\n // exactly as the server has it, because their `apply()` knows only\n // how to CREATE and re-running it would duplicate. A resource that\n // declares `appliesWhenExisting` writes idempotently — its apply()\n // is a full, uuid-keyed replacement that handles the adopted case\n // itself — so skipping it here would make adoption pointless: the\n // second run of a script would read the journey, resolve every\n // identity, and then write nothing.\n if (resource._existed && !resource.appliesWhenExisting) {\n const key = resourceKey(resource);\n summary[key] ??= [];\n summary[key]!.push(resource._id);\n writeLine(` Exists ${resource.planLine()} -> id=${resource._id}`);\n continue;\n }\n\n const updating = resource._existed;\n await resource.apply(this.client);\n if (resource._created || resource._id !== undefined) {\n const key = resourceKey(resource);\n summary[key] ??= [];\n summary[key]!.push(resource._id);\n const startTag = resource instanceof TaskBuilder && resource.start ? ' [start]' : '';\n const verb = updating ? 'Updated' : 'Created';\n writeLine(` ${verb} ${resource.planLine()}${startTag} -> id=${resource._id}`);\n } else {\n writeLine(` Skipped: ${resource.planLine()}`);\n }\n } catch (err) {\n writeLine(formatApplyFailureLine(resource, err));\n throw new ApplyError(resource, err, summary);\n }\n }\n\n await this.applyTransitions();\n await this.applyEventRules(resources);\n await this.applyJourneyConnections(resources);\n await this.applyJourneyGoals(resources);\n\n const count = Object.values(summary).reduce((total, ids) => total + ids.length, 0);\n writeLine(`\\nDone! Created ${count} resources.`);\n return summary;\n }\n\n private async resolveExisting(resources: WorkspaceBuilderResource[]): Promise<void> {\n // Before the first server call: a journey name is the ONLY key adoption\n // has, and two builders declared under one name collapse into a single\n // entry of the name→builder map below — so one of them is silently never\n // adopted and never applied, while the other inherits whatever the\n // server holds under that name and (for v2) replaces it whole.\n assertUniqueJourneyNames(\n resources.filter(\n (resource): resource is JourneyBuilder | JourneyV2Builder =>\n resource instanceof JourneyBuilder || resource instanceof JourneyV2Builder\n )\n );\n\n const formSlugs = new Map(\n resources\n .filter((resource): resource is FormBuilder => resource instanceof FormBuilder)\n .map((resource) => [resource.slug, resource])\n );\n const labelSlugs = new Map(\n resources\n .filter(\n (resource): resource is MemberLabelBuilder => resource instanceof MemberLabelBuilder\n )\n .map((resource) => [resource.slug, resource])\n );\n const workflowNames = new Map(\n resources\n .filter((resource): resource is WorkflowBuilder => resource instanceof WorkflowBuilder)\n .map((resource) => [resource.name, resource])\n );\n\n if (formSlugs.size) {\n for (const existing of await this.client.getDataTypes()) {\n if (existing.slug && formSlugs.has(existing.slug)) {\n formSlugs.get(existing.slug)!.adopt(existing);\n }\n }\n }\n if (labelSlugs.size) {\n for (const existing of await this.client.getMemberLabels()) {\n if (existing.slug && labelSlugs.has(existing.slug)) {\n labelSlugs.get(existing.slug)!.adopt(existing);\n }\n }\n }\n\n const filterNames = new Map(\n resources\n .filter(\n (resource): resource is MemberFilterBuilder =>\n resource instanceof MemberFilterBuilder\n )\n .map((resource) => [resource.name, resource])\n );\n if (filterNames.size) {\n for (const existing of await this.client.getMemberFilters()) {\n if (existing.name && filterNames.has(existing.name)) {\n filterNames.get(existing.name)!.adopt(existing);\n }\n }\n }\n\n // Journeys adopt by name and pull a per-journey projection, because a\n // journey's identity for re-run purposes is its step graph, and the list\n // rows carry no steps.\n //\n // A v2 builder pulls the AUTHORING projection instead of the detail one.\n // Both carry the identities it adopts (step uuids, per-step eventRules,\n // goals, decisionRules), but the v2 write is a full\n // atomic REPLACEMENT, so it must not be a mixed-deploy question whether\n // this payload happens to include decision rules — an absent rule uuid\n // silently recreates the Ending. The builder already holds\n // `journeys:write`; it is about to PUT.\n const journeyNames = new Map(\n resources\n .filter(\n (resource): resource is JourneyBuilder | JourneyV2Builder =>\n resource instanceof JourneyBuilder || resource instanceof JourneyV2Builder\n )\n .map((resource) => [resource.name, resource])\n );\n if (journeyNames.size) {\n // Every page, not just the first: the default page holds 25 rows, so\n // a match on page 2 would be silently duplicated — and worse, two\n // same-name journeys SPLIT across pages would dodge the ambiguity\n // refusal below and adopt the first one destructively. Max page size,\n // walk totalPages (review round 10).\n const pageSize = 500;\n const firstPage = await this.client.getJourneys(false, { page: 1, pageSize });\n const allJourneys = [...firstPage.items];\n for (let page = 2; page <= firstPage.totalPages; page++) {\n const nextPage = await this.client.getJourneys(false, { page, pageSize });\n allJourneys.push(...nextPage.items);\n }\n // Group first, adopt second. Adopting inside the scan would attach the\n // builder to the FIRST stored journey of that name and then attach it\n // again to the second — each adoption a full, destructive replacement\n // of a different live journey. Only an unambiguous 1:1 match is\n // adoptable; zero matches is the ordinary create path.\n const storedByName = new Map<string, (typeof allJourneys)[number][]>();\n for (const existing of allJourneys) {\n if (!existing.name || !journeyNames.has(existing.name)) continue;\n storedByName.set(existing.name, [...(storedByName.get(existing.name) ?? []), existing]);\n }\n for (const [name, matches] of storedByName) {\n if (matches.length > 1) {\n throw new Error(\n `This workspace has ${matches.length} journeys named '${name}', and ` +\n 'the script adopts an existing journey by name — so it cannot tell ' +\n 'which one it owns. Adopting the wrong one replaces that journey ' +\n 'whole on the next save. Rename the others in the app, or rename ' +\n 'the journey in the script.'\n );\n }\n const existing = matches[0]!;\n const builder = journeyNames.get(name)!;\n const detail =\n builder instanceof JourneyV2Builder\n ? await this.client.getJourneyAuthoring(existing.id)\n : await this.client.getJourney(existing.id);\n builder.adopt(detail);\n }\n }\n\n const agentNames = new Map(\n resources\n .filter((resource): resource is AgentBuilder => resource instanceof AgentBuilder)\n .map((resource) => [resource.name, resource])\n );\n if (agentNames.size) {\n // Archived agents are deliberately not adopted: the list endpoint\n // excludes them, and re-adopting one would resurrect a resource the\n // workspace retired rather than create the agent the script asked for.\n for (const existing of await collectPages((page) =>\n this.client.getAgents({ page, pageSize: LIST_PAGE_SIZE })\n )) {\n if (existing.name && agentNames.has(existing.name)) {\n agentNames.get(existing.name)!.adopt(existing);\n }\n }\n }\n\n const routineNames = new Map(\n resources\n .filter((resource): resource is RoutineBuilder => resource instanceof RoutineBuilder)\n .map((resource) => [resource.name, resource])\n );\n if (routineNames.size) {\n for (const existing of await collectPages((page) =>\n this.client.getRoutines({ page, pageSize: LIST_PAGE_SIZE })\n )) {\n if (existing.name && routineNames.has(existing.name)) {\n routineNames.get(existing.name)!.adopt(existing);\n }\n }\n }\n\n await this.resolveExistingRoleUpdates(resources);\n await this.resolveExistingWorkflows(resources, workflowNames);\n // Last, because a notification rule's identity includes the workflow it\n // notifies about, and that id is only known once workflows are adopted.\n await this.resolveExistingNotificationRules(resources);\n }\n\n /**\n * Adopt a role update whose grants the server already has.\n *\n * A role update is a replace-semantics PUT, not a create, so its identity is\n * the role id and \"already applied\" means the id sets match exactly. Subset\n * would be wrong: `roleUpdate(7, [])` asks to *clear* the role's workflow\n * access, and treating that as satisfied by a role that still has grants\n * would silently skip a real change.\n *\n * Only the fields this update declares are compared — an update that passes\n * `workflowIds` and omits `dataTypeIds` never touches data-type access, so\n * that access cannot make it stale.\n */\n private async resolveExistingRoleUpdates(resources: WorkspaceBuilderResource[]): Promise<void> {\n const updates = resources.filter(\n (resource): resource is RoleUpdate => resource instanceof RoleUpdate\n );\n if (!updates.length) return;\n\n const rolesById = new Map(\n (await this.client.getMemberRoles()).map((role) => [role.id, role])\n );\n for (const update of updates) {\n const role = rolesById.get(update.roleId);\n if (!role) continue;\n // Grants carry an accessMode the builder has no way to express, so\n // the ids are the whole of the comparable fact.\n const workflowsSettled =\n update.workflowIds === undefined ||\n sameIdSet(\n update.workflowIds,\n (role.workflowAccess ?? []).map((access) => access.workflowId)\n );\n const dataTypesSettled =\n update.dataTypeIds === undefined ||\n sameIdSet(\n update.dataTypeIds,\n (role.dataTypeAccess ?? []).map((access) => access.dataTypeId)\n );\n if (workflowsSettled && dataTypesSettled) update.adopt(role);\n }\n }\n\n /**\n * Adopt notification rules the server already has.\n *\n * There is no name on the server row — `NotificationRule` is keyed by what\n * it does — so identity is the composite the API enforces uniqueness on in\n * practice: notice type, recipient, and subject workflow.\n */\n private async resolveExistingNotificationRules(\n resources: WorkspaceBuilderResource[]\n ): Promise<void> {\n const rules = resources.filter(\n (resource): resource is NotificationRuleBuilder =>\n resource instanceof NotificationRuleBuilder\n );\n if (!rules.length) return;\n\n const identified = rules.flatMap((rule) => {\n // memberId absent: apply() rejects it, so there is nothing to match.\n if (rule.memberId === undefined) return [];\n // A declared workflow with no id yet is a workflow this run will\n // create, so no server rule can be pointing at it. Matching on\n // \"workflow unset\" here would adopt an unrelated global rule.\n if (rule.workflow && rule.workflow._id === undefined) return [];\n return [\n [\n notificationRuleKey(rule.noticeType, rule.memberId, rule.workflow?._id ?? null),\n rule,\n ] as const,\n ];\n });\n if (!identified.length) return;\n\n const byKey = new Map(identified);\n for (const existing of await this.client.getNotificationRules()) {\n const key = notificationRuleKey(\n existing.noticeType,\n existing.memberId,\n existing.workflowId ?? null\n );\n byKey.get(key)?.adopt(existing);\n }\n }\n\n private async resolveExistingWorkflows(\n resources: WorkspaceBuilderResource[],\n workflowNames: Map<string, WorkflowBuilder>\n ): Promise<void> {\n if (!workflowNames.size) return;\n\n const existingWorkflows = await this.client.getWorkflows();\n for (const { workflow: existing } of existingWorkflows.items) {\n if (existing.name && workflowNames.has(existing.name)) {\n // List rows carry only the root + active-revision summary. Tasks\n // and startTaskId live on the DRAFT revision, so fetch the detail\n // composition for adoption (root ids and revision ids are\n // different entities — matching tasks by root id attaches them to\n // the wrong workflow once any workflow has been published).\n const detail = await this.client.getWorkflow(existing.id);\n workflowNames.get(existing.name)!.adopt(detail);\n }\n }\n\n const adoptedWorkflows = resources.filter(\n (resource): resource is WorkflowBuilder =>\n resource instanceof WorkflowBuilder && resource._existed && resource._id !== undefined\n );\n if (!adoptedWorkflows.length) return;\n\n const existingTasks = await this.client.getTasks();\n for (const workflow of adoptedWorkflows) {\n // Tasks belong to a revision graph — match against the adopted\n // workflow's DRAFT revision id (task.workflowRevisionId), falling\n // back to the legacy field for older payloads.\n const workflowTasks = existingTasks.filter(\n (task) =>\n ((task as { workflowRevisionId?: number }).workflowRevisionId ?? task.workflowId) ===\n workflow._draftRevisionId\n );\n const taskByName = new Map(workflowTasks.map((task) => [task.name, task]));\n for (const taskBuilder of workflow.tasks) {\n const match = taskByName.get(taskBuilder.name);\n if (match) taskBuilder.adopt(match);\n }\n\n const ids = new Map<number, TaskBuilder[]>();\n for (const taskBuilder of workflow.tasks) {\n if (taskBuilder._id !== undefined) {\n ids.set(taskBuilder._id, [...(ids.get(taskBuilder._id) ?? []), taskBuilder]);\n }\n }\n for (const builders of ids.values()) {\n if (builders.length <= 1) continue;\n const nameAdopted = builders.filter((task) => taskByName.has(task.name));\n for (const task of builders.filter((builder) => !nameAdopted.includes(builder))) {\n task._id = undefined;\n task._existed = false;\n }\n }\n }\n }\n\n private sortedResources(): WorkspaceBuilderResource[] {\n const all: WorkspaceBuilderResource[] = [];\n for (const resource of this.resources) {\n all.push(resource);\n if (resource instanceof WorkflowBuilder) {\n const start = resource.startTask;\n const tasks =\n start === undefined\n ? resource.tasks\n : [start, ...resource.tasks.filter((task) => task !== start)];\n all.push(...tasks);\n } else if (resource instanceof JourneyBuilder) {\n all.push(...resource.steps);\n }\n }\n return all.sort((a, b) => phaseFor(a) - phaseFor(b));\n }\n\n private collectWiringSummary(resources: WorkspaceBuilderResource[]): string[] {\n const lines: string[] = [];\n for (const resource of resources) {\n if (resource instanceof TaskBuilder) {\n for (const transition of resource.transitions) {\n lines.push(`${transition.parent.name} -> ${transition.child.name}`);\n }\n for (const rule of resource.eventRules) {\n lines.push(`${rule.actionType} on enter '${resource.name}'`);\n }\n } else if (resource instanceof FormBuilder) {\n for (const rule of resource.eventRules) {\n lines.push(`${rule.actionType} on ${rule.eventType} '${resource.name}'`);\n }\n } else if (resource instanceof RoutineBuilder) {\n for (const rule of resource.rules)\n lines.push(`${rule.actionType} rule on '${resource.name}'`);\n } else if (resource instanceof JourneyStepBuilder) {\n for (const connection of resource.connections) {\n const guard = connection.condition ? ` [${connection.condition}]` : '';\n lines.push(`${connection.parent.name} -> ${connection.child.name}${guard}`);\n }\n for (const rule of resource.rules) {\n lines.push(`${rule.actionType} on step '${resource.name}'`);\n }\n } else if (resource instanceof JourneyBuilder) {\n for (const goal of resource.goals) lines.push(`Goal: ${goal.name}`);\n } else if (resource instanceof JourneyV2Builder) {\n // A v2 timeline has no edges to name — position IS the order — so\n // the preview shows the sequence itself, then the Endings in the\n // precedence they will be evaluated in.\n resource.touches.forEach((touch, index) => {\n lines.push(`${index + 1}. ${touch.name}`);\n });\n for (const ending of resource.endings) lines.push(`Ending: ${ending.name}`);\n for (const goal of resource.goals) lines.push(`Goal: ${goal.name}`);\n }\n }\n return lines;\n }\n\n private async applyTransitions(): Promise<void> {\n const parentChildren = new Map<TaskBuilder, TaskTransition[]>();\n for (const resource of this.sortedResources()) {\n if (!(resource instanceof TaskBuilder)) continue;\n for (const transition of resource.transitions) {\n parentChildren.set(transition.parent, [\n ...(parentChildren.get(transition.parent) ?? []),\n transition,\n ]);\n }\n }\n\n for (const [parent, transitions] of parentChildren) {\n if (parent._id === undefined) continue;\n const childTasks = transitions.flatMap((transition) => {\n const taskId = transition.child._id;\n if (taskId === undefined || taskId === parent._id) return [];\n // Already wired on a previous run — re-sending it makes the API\n // reject the whole update as a conflict, which reads as \"the\n // template half-worked\" and sends the operator hand-repairing.\n if (parent.existingChildIds.has(taskId)) return [];\n return [\n {\n taskId,\n choicePrompt: transition.when,\n celCondition: transition.celCondition ?? null,\n autoNext: transition.autoNext,\n required: transition.required,\n },\n ];\n });\n if (!childTasks.length) continue;\n await this.client.updateTask(parent._id, { childTasks });\n writeLine(\n ` Wired: ${parent.name} -> [${transitions.map((tr) => tr.child.name).join(', ')}]`\n );\n }\n }\n\n private async applyEventRules(resources: WorkspaceBuilderResource[]): Promise<void> {\n for (const resource of resources) {\n if (resource instanceof TaskBuilder) {\n for (const rule of resource.eventRules) {\n try {\n const payload: EventRuleFormData = {\n objectType: EventRuleObjectType.TASK,\n taskId: resource._id,\n eventType: rule.eventType,\n actionType: rule.actionType,\n actionParams: resolveRefs(rule.actionParams),\n ...(rule.name ? { name: rule.name } : {}),\n };\n await this.applyEventRule(\n payload,\n `${rule.actionType} on enter '${resource.name}'`\n );\n } catch (err) {\n handleEventRuleApplyFailure(resource.name, err);\n }\n }\n } else if (resource instanceof FormBuilder) {\n for (const rule of resource.eventRules) {\n try {\n const payload: EventRuleFormData = {\n objectType: EventRuleObjectType.DATA_RECORD,\n dataTypeId: resource._id,\n eventType: rule.eventType,\n actionType: rule.actionType,\n actionParams: resolveRefs(rule.actionParams),\n ...(rule.condition ? { conditions: rule.condition } : {}),\n ...(rule.name ? { name: rule.name } : {}),\n };\n await this.applyEventRule(\n payload,\n `${rule.actionType} on ${rule.eventType} '${resource.name}'`\n );\n } catch (err) {\n handleEventRuleApplyFailure(resource.name, err);\n }\n }\n }\n }\n }\n\n private async applyEventRule(payload: EventRuleFormData, label: string): Promise<void> {\n const existing = await this.findMatchingEventRule(payload);\n if (!existing) {\n await this.client.createEventRule(payload);\n writeLine(` Wired: ${label}`);\n return;\n }\n\n const update = eventRuleUpdate(existing, payload);\n if (Object.keys(update).length) {\n await this.client.updateEventRule(existing.id, update);\n writeLine(` Updated: ${label}`);\n } else {\n writeLine(` Exists: ${label}`);\n }\n }\n\n private async findMatchingEventRule(payload: EventRuleFormData): Promise<EventRule | undefined> {\n const sourceFilter = eventRuleSourceFilter(payload);\n const candidates = await this.client.searchEventRules({\n objectType: payload.objectType,\n eventType: payload.eventType,\n actionType: payload.actionType,\n includeDisabled: true,\n ...sourceFilter,\n });\n return candidates.find((candidate) => eventRulesMatch(candidate, payload));\n }\n\n private async applyJourneyConnections(resources: WorkspaceBuilderResource[]): Promise<void> {\n for (const resource of resources) {\n if (!(resource instanceof JourneyStepBuilder)) continue;\n for (const connection of resource.connections) {\n if (resource.journey._id === undefined) continue;\n // Skip only an edge the SERVER actually reports (recorded during\n // adoption). \"Both steps exist\" is not the same fact: a first run\n // that created the steps and died before the edge leaves exactly\n // that state, and skipping there would strand a root step that\n // fires for every member at enrolment, on every future run.\n if (resource.journey.hasEdge(connection.parent, connection.child)) {\n writeLine(` Exists: ${connection.parent.name} -> ${connection.child.name}`);\n continue;\n }\n const payload = buildJourneyConnectionPayload(connection);\n if (!payload) continue;\n await this.client.createConnection(resource.journey._id, payload);\n writeLine(` Wired: ${connection.parent.name} -> ${connection.child.name}`);\n }\n }\n }\n\n private async applyJourneyGoals(resources: WorkspaceBuilderResource[]): Promise<void> {\n for (const resource of resources) {\n if (!(resource instanceof JourneyBuilder) || resource._id === undefined) continue;\n // Goals have no natural key to match on, so an adopted journey keeps\n // the goals it already has rather than accumulating a duplicate set\n // on every re-run. Say so per goal — the plan already listed them, and\n // a silent skip reads as \"created\" to anyone watching the output.\n if (resource._existed) {\n for (const goal of resource.goals) {\n writeLine(` Skipped (journey already exists): Goal: ${goal.name}`);\n }\n continue;\n }\n for (const goal of resource.goals) {\n await this.client.createGoal(resource._id, buildJourneyGoalPayload(goal));\n writeLine(` Created goal: ${goal.name}`);\n }\n }\n }\n}\n\nexport class ApplyError extends Error {\n readonly createdSoFar: ResourceSummary;\n readonly #resource: WorkspaceBuilderResource;\n readonly #cause: unknown;\n\n constructor(resource: WorkspaceBuilderResource, cause: unknown, createdSoFar: ResourceSummary) {\n super(formatApplyErrorMessage(resource, cause, createdSoFar));\n this.name = 'ApplyError';\n this.createdSoFar = createdSoFar;\n this.#resource = resource;\n this.#cause = cause;\n }\n\n get resource(): WorkspaceBuilderResource {\n return this.#resource;\n }\n\n get cause(): unknown {\n return this.#cause;\n }\n}\n\n/**\n * Refuse a script that declares two journeys under one name.\n *\n * A journey has no slug and no author-supplied key, so its NAME is the whole\n * of its identity for adoption. Two builders sharing one collapse into a\n * single map entry, which is silent: the plan prints both, one of them is\n * simply never adopted or applied, and the other inherits whatever the server\n * had under that name.\n */\nfunction assertUniqueJourneyNames(journeys: (JourneyBuilder | JourneyV2Builder)[]): void {\n const seen = new Set<string>();\n for (const journey of journeys) {\n if (seen.has(journey.name)) {\n throw new Error(\n `This script declares two journeys named '${journey.name}'. A journey is ` +\n 'adopted and re-applied by name, so only one of them could ever be ' +\n 'written — and a v2 apply replaces the journey it adopted whole. ' +\n 'Rename one.'\n );\n }\n seen.add(journey.name);\n }\n}\n\nfunction resourceKey(resource: WorkspaceBuilderResource): string {\n if (resource instanceof RoleUpdate) return 'roleUpdates';\n if (resource instanceof FormBuilder) return 'forms';\n if (resource instanceof MemberLabelBuilder) return 'labels';\n if (resource instanceof WorkflowBuilder) return 'workflows';\n if (resource instanceof TaskBuilder) return 'tasks';\n if (resource instanceof MemberFilterBuilder) return 'memberFilters';\n if (resource instanceof RoutineBuilder) return 'routines';\n if (resource instanceof NotificationRuleBuilder) return 'notificationRules';\n if (resource instanceof JourneyBuilder || resource instanceof JourneyV2Builder) {\n return 'journeys';\n }\n if (resource instanceof JourneyStepBuilder) return 'journeySteps';\n if (resource instanceof AgentBuilder) return 'agents';\n return 'resources';\n}\n\nconst SEARCHABLE_EVENT_RULE_SOURCE_FIELDS = [\n 'taskId',\n 'dataTypeId',\n 'routineId',\n 'workflowRevisionId',\n 'journeyStepId',\n] as const;\n\nconst EVENT_RULE_SOURCE_FIELDS = [\n ...SEARCHABLE_EVENT_RULE_SOURCE_FIELDS,\n 'calendarId',\n 'calendarEventTypeId',\n] as const;\n\ntype SearchableEventRuleSourceField = (typeof SEARCHABLE_EVENT_RULE_SOURCE_FIELDS)[number];\n\nfunction eventRuleSourceFilter(\n payload: EventRuleFormData\n): Partial<Record<SearchableEventRuleSourceField, number>> {\n const filter: Partial<Record<SearchableEventRuleSourceField, number>> = {};\n for (const field of SEARCHABLE_EVENT_RULE_SOURCE_FIELDS) {\n const value = payload[field];\n if (value !== undefined && value !== null) {\n filter[field] = value;\n }\n }\n return filter;\n}\n\nfunction eventRulesMatch(existing: EventRule, payload: EventRuleFormData): boolean {\n if (normalizeString(existing.name) !== normalizeString(payload.name)) return false;\n if (existing.objectType !== payload.objectType) return false;\n if (existing.eventType !== payload.eventType) return false;\n if (existing.actionType !== payload.actionType) return false;\n\n for (const field of EVENT_RULE_SOURCE_FIELDS) {\n if ((existing[field] ?? null) !== (payload[field] ?? null)) return false;\n }\n\n if (normalizeString(payload.name)) return true;\n if (normalizeString(existing.conditions) !== normalizeString(payload.conditions)) return false;\n if (!eventRuleValueEqual(existing.actionParams, payload.actionParams ?? null)) return false;\n if (!eventRuleValueEqual(existing.triggerParams, payload.triggerParams ?? null)) return false;\n return true;\n}\n\nfunction eventRuleUpdate(existing: EventRule, payload: EventRuleFormData): UpdateEventRuleFormData {\n const update: UpdateEventRuleFormData = {};\n const conditions = payload.conditions ?? null;\n if (normalizeString(existing.conditions) !== normalizeString(conditions)) {\n update.conditions = conditions;\n }\n const actionParams = payload.actionParams ?? null;\n if (!eventRuleValueEqual(existing.actionParams, actionParams)) {\n update.actionParams = payload.actionParams;\n }\n const triggerParams = payload.triggerParams ?? null;\n if (!eventRuleValueEqual(existing.triggerParams, triggerParams)) {\n update.triggerParams = payload.triggerParams;\n }\n const active = payload.active ?? true;\n if (existing.active !== active) {\n update.active = active;\n }\n const delay = payload.delay ?? 0;\n if (existing.delay !== delay) {\n update.delay = delay;\n }\n const order = payload.order ?? 0;\n if (existing.order !== order) {\n update.order = order;\n }\n return update;\n}\n\nfunction normalizeString(value: string | null | undefined): string {\n return value ?? '';\n}\n\nfunction eventRuleValueEqual(left: unknown, right: unknown): boolean {\n return JSON.stringify(stableValue(left)) === JSON.stringify(stableValue(right));\n}\n\nfunction stableValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(stableValue);\n if (!value || typeof value !== 'object') return value;\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) return value;\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, stableValue(nested)])\n );\n}\n\nfunction writeLine(message = ''): void {\n process.stdout.write(`${message}\\n`);\n}\n\nfunction handleEventRuleApplyFailure(resourceName: string, err: unknown): void {\n if (hasStatus(err, 403)) {\n writeLine(\n ` WARNING: Event rule on '${resourceName}' failed (retry exec() with scopes=['automations:admin'])`\n );\n return;\n }\n const summary = summarizeError(err);\n writeLine(` FAILED: Event rule on '${resourceName}': ${summary}`);\n throw new Error(`Failed wiring event rule on '${resourceName}': ${summary}`);\n}\n\nfunction writeScopeForResource(resource: WorkspaceBuilderResource): string | null {\n if (resource instanceof FormBuilder) return 'datatypes:write';\n if (resource instanceof WorkflowBuilder || resource instanceof TaskBuilder) {\n return 'workflows:write';\n }\n if (resource instanceof AgentBuilder) return 'agents:write';\n if (resource instanceof MemberLabelBuilder || resource instanceof MemberFilterBuilder) {\n return 'members:write';\n }\n if (resource instanceof RoutineBuilder || resource instanceof NotificationRuleBuilder) {\n return 'automations:admin';\n }\n if (\n resource instanceof JourneyBuilder ||\n resource instanceof JourneyStepBuilder ||\n resource instanceof JourneyV2Builder\n ) {\n return 'journeys:write';\n }\n if (resource instanceof RoleUpdate) return 'member_roles:write';\n return null;\n}\n\nfunction scopeRetryHint(resource: WorkspaceBuilderResource): string {\n const scope = writeScopeForResource(resource);\n return scope ? ` (retry exec with scopes=['${scope}'])` : '';\n}\n\nfunction formatApplyFailureLine(resource: WorkspaceBuilderResource, err: unknown): string {\n const line = ` FAILED: ${resource.planLine()}: ${summarizeError(err)}`;\n return hasStatus(err, 403) ? `${line}${scopeRetryHint(resource)}` : line;\n}\n\nfunction formatApplyErrorMessage(\n resource: WorkspaceBuilderResource,\n cause: unknown,\n createdSoFar: ResourceSummary\n): string {\n let message = `Failed creating ${resource.planLine()}: ${summarizeError(cause)}`;\n if (hasStatus(cause, 403)) {\n const scope = writeScopeForResource(resource);\n if (scope) {\n message += `\\nRetry exec with scopes=['${scope}']`;\n }\n }\n const createdKeys = Object.keys(createdSoFar);\n if (createdKeys.length > 0) {\n message += `\\nAlready created: ${JSON.stringify(createdSoFar)}`;\n }\n return message;\n}\n\nfunction summarizeError(err: unknown): string {\n if (hasStatus(err, 403)) {\n return 'Insufficient permissions for this operation';\n }\n if (err instanceof ApiError) {\n const msg = err.message.trim();\n const availableTypesIdx = msg.indexOf('Available types:');\n if (availableTypesIdx !== -1) {\n const head = msg.slice(0, availableTypesIdx).trim().replace(/\\.$/, '');\n return head ? `${head}.` : 'Request failed';\n }\n return msg.length > 240 ? `${msg.slice(0, 237)}...` : msg;\n }\n if (err instanceof Error) {\n // Name only, deliberately. A non-ApiError can still carry a message the\n // backend supplied, and this string is surfaced to the operator — see the\n // \"backend returned sensitive detail\" tests. Do not widen this.\n return err.name || 'Error';\n }\n return typeof err;\n}\n\nfunction hasStatus(err: unknown, status: number): boolean {\n if (typeof err === 'object' && err !== null) {\n const candidate = err as { status?: unknown; statusCode?: unknown };\n if (candidate.status === status || candidate.statusCode === status) return true;\n }\n const message = err instanceof Error ? err.message : typeof err === 'string' ? err : '';\n return message.includes(String(status));\n}\n\nexport async function runWorkspaceScript(\n client: GravityRailWorkspaceClient,\n build: (workspace: WorkspaceBuilder) => void | Promise<void>,\n mode = 'plan'\n): Promise<ResourceSummary | void> {\n const workspace = new WorkspaceBuilder(client);\n await build(workspace);\n if (mode === 'plan') return workspace.plan();\n if (mode === 'preview') return workspace.preview();\n if (mode === 'apply') return workspace.apply();\n throw new Error(`Unknown mode '${mode}'. Use plan, preview, or apply.`);\n}\n","/**\n * Generated by Orval, grouped by scripts/types-codegen/group_generated.ts\n * (group map from emit_openapi.py). Do not edit manually.\n * Group: event_type\n */\n\n\n/**\n * Scope-class capabilities that unlock event types in the feed.\n *\n * These are existing platform scope strings. The grant set is deliberately\n * coarse — scope-class capabilities and nothing finer. The workspace schemas'\n * second tier (bitwise role x data-type maps, folder ACLs, object-level\n * grants) is applied by the live authorizer at leaf enumeration, never copied\n * into the grants projection.\n */\nexport type ActivityCapability = typeof ActivityCapability[keyof typeof ActivityCapability];\n\n\nexport const ActivityCapability = {\n 'assignments:read': 'assignments:read',\n 'chats:read': 'chats:read',\n 'journeys:read': 'journeys:read',\n 'members:read': 'members:read',\n 'operator:read': 'operator:read',\n 'org:read': 'org:read',\n 'phones:read': 'phones:read',\n 'workflows:read': 'workflows:read',\n 'workspace:read': 'workspace:read',\n} as const;\n\n/**\n * Every occurrence kind the spine records. Closed; grows by review.\n */\nexport type ActivityEventType = typeof ActivityEventType[keyof typeof ActivityEventType];\n\n\nexport const ActivityEventType = {\n membercreated: 'member.created',\n memberremoved: 'member.removed',\n memberrole_changed: 'member.role_changed',\n memberlabels_changed: 'member.labels_changed',\n memberattributes_changed: 'member.attributes_changed',\n importstarted: 'import.started',\n importcompleted: 'import.completed',\n assignmentstarted: 'assignment.started',\n assignmentconcluded: 'assignment.concluded',\n journeyenrolled: 'journey.enrolled',\n journeyunenrolled: 'journey.unenrolled',\n journeycompleted: 'journey.completed',\n journeystep_transitioned: 'journey.step_transitioned',\n journeyactivated: 'journey.activated',\n chatstarted: 'chat.started',\n chatawaiting_human: 'chat.awaiting_human',\n chathuman_replied: 'chat.human_replied',\n escalationopened: 'escalation.opened',\n escalationresolved: 'escalation.resolved',\n callstarted: 'call.started',\n callcompleted: 'call.completed',\n callmissed: 'call.missed',\n presencewent_online: 'presence.went_online',\n presencewent_offline: 'presence.went_offline',\n operator_groupmember_added: 'operator_group.member_added',\n operator_groupmember_removed: 'operator_group.member_removed',\n voicemailreceived: 'voicemail.received',\n voicemaillistened: 'voicemail.listened',\n routinestarted: 'routine.started',\n routinecompleted: 'routine.completed',\n routinefailed: 'routine.failed',\n workflowpublished: 'workflow.published',\n subscriptionstarted: 'subscription.started',\n subscriptionupdated: 'subscription.updated',\n subscriptioncanceled: 'subscription.canceled',\n member_subscriptionstarted: 'member_subscription.started',\n member_subscriptioncanceled: 'member_subscription.canceled',\n purchasecompleted: 'purchase.completed',\n phone_numberprovisioned: 'phone_number.provisioned',\n phone_numberarchived: 'phone_number.archived',\n domainlinked: 'domain.linked',\n domainverified: 'domain.verified',\n configupdated: 'config.updated',\n} as const;\n\n/**\n * The visibility class an event is *born* with.\n *\n * ``ACCOUNT_PRIVATE`` is structural privacy: such an event is only ever\n * visible to the account named in ``account_uuid``, regardless of any scope a\n * viewer holds, and it never enters a workspace or org rollup. This is how\n * manager / DM / agent-job chat privacy survives aggregation.\n */\nexport type ActivityVisibility = typeof ActivityVisibility[keyof typeof ActivityVisibility];\n\n\nexport const ActivityVisibility = {\n workspace: 'workspace',\n org: 'org',\n account_private: 'account_private',\n} as const;\n","/**\n * Generated by Orval, grouped by scripts/types-codegen/group_generated.ts\n * (group map from emit_openapi.py). Do not edit manually.\n * Group: ref\n */\n\n\n/**\n * Who or what caused an occurrence.\n *\n * ``SYSTEM`` is the honest answer when a chokepoint serves a caller with no\n * session — a Temporal schedule, a backfill, a webhook with no member\n * attribution. It is never a placeholder for \"did not bother to look\".\n */\nexport type ActorKind = typeof ActorKind[keyof typeof ActorKind];\n\n\nexport const ActorKind = {\n account: 'account',\n agent: 'agent',\n connection: 'connection',\n member: 'member',\n org_account: 'org_account',\n system: 'system',\n} as const;\n\n/**\n * Closed vocabulary of entity kinds a spine ref may name.\n *\n * Adding a kind is a code change with review — the same gate the event-type\n * vocabulary gets. Kinds name *entities*, never fields or values.\n */\nexport type EntityKind = typeof EntityKind[keyof typeof EntityKind];\n\n\nexport const EntityKind = {\n account: 'account',\n org: 'org',\n org_account: 'org_account',\n workspace: 'workspace',\n agent: 'agent',\n connection: 'connection',\n member: 'member',\n assignment: 'assignment',\n journey: 'journey',\n journey_step: 'journey_step',\n routine: 'routine',\n task: 'task',\n workflow: 'workflow',\n workflow_revision: 'workflow_revision',\n call: 'call',\n chat: 'chat',\n escalation: 'escalation',\n inbox: 'inbox',\n phone_number: 'phone_number',\n voicemail: 'voicemail',\n domain: 'domain',\n import: 'import',\n invoice: 'invoice',\n member_label: 'member_label',\n member_subscription: 'member_subscription',\n operator_group: 'operator_group',\n purchase: 'purchase',\n subscription: 'subscription',\n data_type: 'data_type',\n workspace_config: 'workspace_config',\n} as const;\n\n/**\n * A typed reference to one entity, with the scope chain it was observed in.\n *\n * Stored in ``activity_events.refs`` (and in ``activity_open_items``'s\n * ``responsible``) as JSON. Never used for a join: the activities database\n * holds no foreign keys, and a ref whose entity was deleted renders as its\n * kind — the same behavior as a ref the viewer may not resolve.\n *\n * **Two names for one field, on purpose.** This class is a *storage* shape —\n * the JSON the recorder writes and the drain reads — and, since the serving\n * API returns typed detail payloads, it is also a *wire* shape. Storage wants\n * the snake_case names already committed to rows; the API contract requires\n * lowerCamelCase keys (root ``CLAUDE.md``). A serialization-only alias gives\n * both without a mapping layer: validation still reads ``workspace_uuid``, so\n * every stored row and every emitter is untouched, while ``by_alias=True`` —\n * which FastAPI uses to serialize a response, and which nothing on the write\n * path passes — emits ``workspaceUuid``.\n * :class:`lib.activity.details.ActivityDetailBase` carries the same config for\n * the same reason.\n */\nexport interface EntityRef {\n kind: EntityKind;\n uuid: string;\n workspaceUuid?: string | null;\n orgUuid?: string | null;\n accountUuid?: string | null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/workspace-builder/resource.ts","../src/workspace-builder/automation.ts","../src/workspace-builder/forms.ts","../src/workspace-builder/journeys.ts","../src/workspace-builder/role-update.ts","../src/workspace-builder/workflows.ts","../src/workspace-builder/orchestrator.ts","../src/types/generated/event_type.ts","../src/types/generated/ref.ts"],"sourcesContent":["import type { GravityRailWorkspaceClient } from '../client/workspace-client';\n\nexport type AnyRecord = Record<string, any>;\nexport type ResourceSummary = Record<string, Array<number | undefined>>;\n\nexport function isRecord(value: unknown): value is AnyRecord {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction isPlainRecord(value: unknown): value is AnyRecord {\n if (!isRecord(value)) return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nexport function slugify(name: string): string {\n return name.toLowerCase().replaceAll(' ', '_').replaceAll('-', '_');\n}\n\nexport abstract class WorkspaceBuilderResource {\n _id?: number;\n _uuid?: string;\n _created = false;\n _existed = false;\n\n /** Server-assigned numeric id — available after apply() or adopt(). */\n get id(): number {\n if (this._id === undefined) {\n throw new Error(\n `${this.constructor.name} has no id yet — ids are assigned during apply(). ` +\n 'Pass the builder object itself where a reference is needed; refs resolve at apply time.'\n );\n }\n return this._id;\n }\n\n /** Server-assigned uuid — available after apply() or adopt(). */\n get uuid(): string {\n if (this._uuid === undefined) {\n throw new Error(\n `${this.constructor.name} has no uuid yet — uuids are assigned during apply(). ` +\n 'Pass the builder object itself where a reference is needed; refs resolve at apply time.'\n );\n }\n return this._uuid;\n }\n\n /**\n * True for resources the server creates on our behalf (currently a\n * journey's `Start` step). They are kept in the resource list so edges can\n * reference them, but they are never created, printed, or counted.\n */\n get isImplicit(): boolean {\n return false;\n }\n\n /**\n * True when `apply()` is safe — and required — to run against a resource\n * that was ADOPTED rather than created.\n *\n * False by default because most builders create only: re-running their\n * `apply()` on an existing resource would make a duplicate. Override it\n * when `apply()` is an idempotent full write keyed on stable identities,\n * which is the only way a re-run can express an EDIT (a removed goal, a\n * reordered timeline) rather than just an addition.\n */\n get appliesWhenExisting(): boolean {\n return false;\n }\n\n abstract planLine(): string;\n abstract apply(client: GravityRailWorkspaceClient): Promise<void>;\n\n matchKey(): string | undefined {\n return undefined;\n }\n\n adopt(existing: AnyRecord): void {\n this._id = existing.id;\n this._uuid = existing.uuid;\n this._existed = true;\n }\n}\n\nexport function resolveRefs(params: AnyRecord): AnyRecord {\n return resolveRefValue(params) as AnyRecord;\n}\n\nfunction resolveRefValue(value: unknown): unknown {\n if (value instanceof WorkspaceBuilderResource) return value._uuid;\n if (Array.isArray(value)) return value.map(resolveRefValue);\n if (!isPlainRecord(value)) return value;\n\n const out: AnyRecord = {};\n for (const [key, nestedValue] of Object.entries(value)) {\n out[key] = resolveRefValue(nestedValue);\n }\n return out;\n}\n\n/**\n * Same substitution as `resolveRefs`, but to numeric ids.\n *\n * A few surfaces key on id rather than uuid — the query-engine IR is the main\n * one (`member.labelId` takes label ids). Without this a script would have to\n * apply once, read the ids back, and apply again just to write one filter.\n *\n * Returns `unknown` deliberately. A builder standing in a `number` slot is not\n * type-compatible with the payload it is going into, so the cast is real; a\n * generic `<T>(value: T): T` would only hide it, and would additionally claim a\n * `number` where an unresolved ref yields `undefined`. Callers cast at the one\n * place it matters, in view of the reader.\n */\nexport function resolveIdRefs(value: unknown): unknown {\n return resolveIdRefValue(value);\n}\n\nfunction resolveIdRefValue(value: unknown): unknown {\n // `.id` throws with a useful message when the ref has no id yet. Failing\n // here beats writing `undefined` into a payload: an id-keyed predicate that\n // silently loses a term matches everyone or no one, and looks fine doing it.\n if (value instanceof WorkspaceBuilderResource) return value.id;\n if (Array.isArray(value)) return value.map(resolveIdRefValue);\n if (!isPlainRecord(value)) return value;\n\n const out: AnyRecord = {};\n for (const [key, nestedValue] of Object.entries(value)) {\n out[key] = resolveIdRefValue(nestedValue);\n }\n return out;\n}\n","import {\n EventRuleEventType,\n EventRuleObjectType,\n type CreateRoutineRequest,\n type EventRuleActionType,\n type MemberFilterFormData,\n type NotificationRuleCreate,\n} from '../types';\nimport type { QueryPredicate } from '../types/query-engine-types';\nimport type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport type { AnyRecord } from './resource';\nimport { resolveIdRefs, WorkspaceBuilderResource } from './resource';\nimport type { WorkflowBuilder } from './workflows';\n\nexport class MemberFilterBuilder extends WorkspaceBuilderResource {\n readonly description: string;\n /** Query-engine predicate (JSON IR) authored on MemberFilter.query. */\n query: QueryPredicate | null = null;\n\n constructor(\n readonly name: string,\n options: AnyRecord = {}\n ) {\n super();\n this.description = options.description ?? '';\n this.query = options.query ?? null;\n }\n\n /**\n * Set the filter's query-engine predicate (JSON IR).\n *\n * Anywhere the IR wants a numeric id you may pass the builder that will own\n * it (e.g. a label in a `member.labelId` value); refs resolve at apply time.\n */\n setQuery(query: QueryPredicate): MemberFilterBuilder {\n this.query = query;\n return this;\n }\n\n planLine(): string {\n return `MemberFilter: ${this.name}${this.query ? ' (query)' : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const payload: MemberFilterFormData = {\n name: this.name,\n description: this.description,\n // Builder refs inside the IR become ids here; see resolveIdRefs.\n query: resolveIdRefs(this.query) as QueryPredicate | null,\n };\n const result = await client.createMemberFilter(payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n\ninterface RoutineRuleDraft {\n actionType: EventRuleActionType | string;\n workflow?: WorkflowBuilder;\n memberFilter?: MemberFilterBuilder;\n actionParams: AnyRecord;\n}\n\nexport class RoutineBuilder extends WorkspaceBuilderResource {\n readonly active: boolean;\n readonly description: string;\n readonly rules: RoutineRuleDraft[] = [];\n\n constructor(\n readonly name: string,\n readonly cronSchedule = '',\n options: AnyRecord = {}\n ) {\n super();\n this.active = options.active ?? false;\n this.description = options.description ?? '';\n }\n\n addRule(\n actionType: string,\n options: {\n workflow?: WorkflowBuilder;\n memberFilter?: MemberFilterBuilder;\n actionParams?: AnyRecord;\n } = {}\n ): RoutineBuilder {\n this.rules.push({\n actionType,\n workflow: options.workflow,\n memberFilter: options.memberFilter,\n actionParams: options.actionParams ?? {},\n });\n return this;\n }\n\n planLine(): string {\n const parts = [\n ...(this.cronSchedule ? [`cron=${this.cronSchedule}`] : []),\n ...(this.rules.length ? [`${this.rules.length} rules`] : []),\n this.active ? 'active' : 'inactive',\n ];\n return `Routine: ${this.name} (${parts.join(', ')})`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const eventRules = this.rules.map((rule) => {\n const actionParams = { ...rule.actionParams };\n if (rule.workflow?._id !== undefined) actionParams.workflowId = rule.workflow._id;\n if (rule.memberFilter?._id !== undefined)\n actionParams.memberFilterId = rule.memberFilter._id;\n return {\n uuid: crypto.randomUUID(),\n objectType: EventRuleObjectType.ROUTINE,\n eventType: EventRuleEventType.ROUTINE_TRIGGERED,\n actionType: rule.actionType as EventRuleActionType,\n actionParams,\n active: true,\n };\n });\n const payload: CreateRoutineRequest = {\n name: this.name,\n cronString: this.cronSchedule,\n scheduleMode: this.cronSchedule ? 'CRON' : undefined,\n scheduleEnabled: this.active,\n ...(this.description ? { description: this.description } : {}),\n ...(eventRules.length ? { eventRules } : {}),\n };\n const result = await client.createRoutine(payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n\nexport class NotificationRuleBuilder extends WorkspaceBuilderResource {\n readonly noticeType: string;\n readonly memberId: number;\n readonly workflow?: WorkflowBuilder;\n readonly prompt?: string;\n readonly notifySms: boolean;\n readonly notifyEmail: boolean;\n readonly notifyVoice: boolean;\n\n constructor(\n readonly name: string,\n options: AnyRecord = {}\n ) {\n super();\n this.noticeType = options.noticeType ?? options.notice_type ?? name;\n this.memberId = options.memberId ?? options.member_id;\n this.workflow = options.workflow;\n this.prompt = options.prompt ?? options.message;\n this.notifySms = Boolean(options.notifySms ?? options.notify_sms);\n this.notifyEmail = Boolean(options.notifyEmail ?? options.notify_email);\n this.notifyVoice = Boolean(options.notifyVoice ?? options.notify_voice);\n }\n\n planLine(): string {\n const parts: string[] = [];\n if (this.memberId !== undefined) parts.push(`memberId=${this.memberId}`);\n if (this.workflow) parts.push(`workflow='${this.workflow.name}'`);\n return `NotificationRule: ${this.name}${parts.length ? ` (${parts.join(', ')})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n if (this.memberId === undefined) {\n throw new Error(`Notification rule '${this.name}' requires memberId`);\n }\n const payload: NotificationRuleCreate = {\n noticeType: this.noticeType,\n memberId: this.memberId,\n workflowId: this.workflow?._id,\n prompt: this.prompt ?? null,\n notifySms: this.notifySms,\n notifyEmail: this.notifyEmail,\n notifyVoice: this.notifyVoice,\n };\n const result = await client.createNotificationRule(payload);\n this._id = result.id;\n this._created = true;\n }\n}\n","import {\n DataFieldType,\n EventRuleEventType,\n type DataTypeFormData,\n type EnumOption,\n type EventRuleActionType,\n type MemberLabelFormData,\n type SchemaField,\n} from '../types';\nimport type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport type { WorkspaceBuilderEventRule } from './event-rules';\nimport { type AnyRecord, isRecord, slugify, WorkspaceBuilderResource } from './resource';\n\n// The client DataFieldType enum and the generated SchemaField fieldType\n// literal union share the same string values, but TS string enums are\n// nominal — convert once at draft construction.\ntype WorkspaceFieldDraft = SchemaField;\n\nfunction normalizeOptions(options: any[]): EnumOption[] {\n if (options.length === 0) return [];\n const first = options[0];\n if (isRecord(first)) return options as EnumOption[];\n if (Array.isArray(first)) {\n return options.map((entry) => ({ label: String(entry[0]), value: entry[1] }));\n }\n return options.map((option) => ({ label: String(option), value: String(option) }));\n}\n\nfunction createFieldDraft(\n fieldType: DataFieldType,\n name: string,\n slug: string,\n options: {\n required?: boolean;\n order?: number;\n description?: string;\n choices?: EnumOption[];\n cel?: string;\n } = {}\n): WorkspaceFieldDraft {\n return {\n name,\n slug,\n fieldType: fieldType as SchemaField['fieldType'],\n required: Boolean(options.required),\n order: options.order ?? 0,\n ...(options.description ? { description: options.description } : {}),\n ...(options.choices ? { options: options.choices } : {}),\n ...(options.cel ? { celFunction: options.cel } : {}),\n };\n}\n\nexport class FormBuilder extends WorkspaceBuilderResource {\n readonly name: string;\n readonly slug: string;\n readonly description: string;\n readonly prompt: string;\n readonly collection: boolean;\n readonly fields: WorkspaceFieldDraft[] = [];\n readonly eventRules: WorkspaceBuilderEventRule[] = [];\n\n constructor(name: string, slug?: string, options: AnyRecord = {}) {\n super();\n this.name = name;\n this.slug = slug ?? slugify(name);\n this.description = options.description ?? '';\n this.prompt = options.prompt ?? '';\n this.collection = options.collection ?? false;\n\n for (const field of options.fields ?? []) {\n if (!isRecord(field) || !field.name) continue;\n const choices = field.options ? normalizeOptions(field.options) : undefined;\n this.fields.push(\n createFieldDraft(\n (field.fieldType ?? field.field_type ?? DataFieldType.TEXT) as DataFieldType,\n field.name,\n field.slug ?? slugify(field.name),\n {\n required: Boolean(field.required ?? field.isRequired),\n order: field.order ?? 0,\n description: field.description,\n choices,\n }\n )\n );\n }\n }\n\n field(\n fieldType: DataFieldType,\n name: string,\n slug: string,\n options: {\n required?: boolean;\n order?: number;\n description?: string;\n choices?: any[];\n cel?: string;\n } = {}\n ): FormBuilder {\n this.fields.push(createFieldDraft(fieldType, name, slug, options));\n return this;\n }\n\n enumField(name: string, slug: string, options: any[], settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.ENUM, name, slug, {\n ...settings,\n choices: normalizeOptions(options),\n });\n }\n\n textField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.TEXT, name, slug, settings);\n }\n\n numberField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.NUMBER, name, slug, settings);\n }\n\n dateField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.DATE, name, slug, settings);\n }\n\n booleanField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.BOOLEAN, name, slug, settings);\n }\n\n functionField(name: string, slug: string, cel: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.FUNCTION, name, slug, { ...settings, cel });\n }\n\n emailField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.EMAIL, name, slug, settings);\n }\n\n phoneField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.PHONE, name, slug, settings);\n }\n\n longtextField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.LONGTEXT, name, slug, settings);\n }\n\n integerField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.INTEGER, name, slug, settings);\n }\n\n datetimeField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.DATETIME, name, slug, settings);\n }\n\n timeOfDayField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.TIME_OF_DAY, name, slug, settings);\n }\n\n usZipCodeField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.US_ZIP_CODE, name, slug, settings);\n }\n\n arrayField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.ARRAY, name, slug, settings);\n }\n\n objectField(name: string, slug: string, settings: AnyRecord = {}): FormBuilder {\n return this.field(DataFieldType.OBJECT, name, slug, settings);\n }\n\n onRecordCreated(\n action: string,\n params: AnyRecord = {},\n condition?: string,\n name?: string\n ): FormBuilder {\n this.eventRules.push({\n eventType: EventRuleEventType.DATA_RECORD_CREATED,\n actionType: action as EventRuleActionType,\n actionParams: params,\n condition,\n name,\n });\n return this;\n }\n\n onRecordUpdated(\n action: string,\n params: AnyRecord = {},\n condition?: string,\n name?: string\n ): FormBuilder {\n this.eventRules.push({\n eventType: EventRuleEventType.DATA_RECORD_UPDATED,\n actionType: action as EventRuleActionType,\n actionParams: params,\n condition,\n name,\n });\n return this;\n }\n\n matchKey(): string {\n return this.slug;\n }\n\n planLine(): string {\n return `Form: ${this.name} (slug=${this.slug}, ${this.fields.length} fields)`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const payload: DataTypeFormData = {\n name: this.name,\n slug: this.slug,\n description: this.description,\n prompt: this.prompt,\n isCollection: this.collection,\n fields: this.fields,\n };\n const result = await client.createDataType(payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n\nexport class MemberLabelBuilder extends WorkspaceBuilderResource {\n readonly name: string;\n readonly slug: string;\n readonly color: string;\n readonly description: string;\n\n constructor(name: string, slug?: string, color = '8b5cf6', description = '') {\n super();\n this.name = name;\n this.slug = slug ?? slugify(name);\n this.color = color;\n this.description = description;\n }\n\n matchKey(): string {\n return this.slug;\n }\n\n planLine(): string {\n return `Label: ${this.name} (slug=${this.slug})`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const payload: MemberLabelFormData = {\n name: this.name,\n slug: this.slug,\n color: this.color,\n description: this.description,\n };\n const result = await client.createMemberLabel(payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n","import {\n EventRuleEventType,\n EventRuleActionType,\n type EventRuleInput,\n type JourneyGoalFormData,\n type JourneyStepConnectionFormData,\n type JourneyStepFormData,\n type JourneyV2DefinitionFormData,\n type JourneyV2EndingInput,\n type JourneyV2GoalInput,\n type JourneyV2TouchInput,\n type JourneyV2WaitInput,\n} from '../types';\nimport type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport { type AnyRecord, resolveRefs, WorkspaceBuilderResource } from './resource';\n\n/** Options for a DAG edge between two journey steps. */\nexport interface StepConnectionOptions {\n /**\n * CEL guard evaluated once the parent step is terminal. The child only\n * becomes eligible while this is true. Journey-edge CEL sees `member.*`\n * (including `member.labels`), `journey.enrolled_at`, `journey.status`,\n * and `parent_step.{status,completed_at,activated_at,eligible_at,name}`.\n */\n when?: string;\n /**\n * Space this step N days after the parent completed. Sugar for the CEL\n * `days_since(parent_step.completed_at) >= N`, AND-ed with `when`.\n *\n * This is how you build a follow-up cadence — NOT `abandonAfterDays`,\n * which gives up rather than waits.\n */\n afterDays?: number;\n /**\n * Give up on this edge after N days of the CEL staying false: the child\n * moves to TIMED_OUT instead of waiting forever. A deadline, not a delay.\n */\n abandonAfterDays?: number;\n /** Raw seconds form of `abandonAfterDays`. `abandonAfterDays` wins. */\n timeoutSeconds?: number;\n /** The child waits for THIS parent specifically, not just any parent. */\n required?: boolean;\n /** Edge evaluation order among a parent's outgoing edges. */\n order?: number;\n /** Restrict the edge to members matching a saved MemberFilter. */\n filterId?: number;\n}\n\n/** Options for a `JOURNEY_STEP_EXECUTE` outreach rule on a step. */\nexport interface StepRuleOptions {\n /** CEL guard — the action is skipped when this is false. */\n when?: string;\n /** Operator-facing rule name, shown in the journey editor. */\n name?: string;\n /** Delay the action this many seconds after the step activates. */\n delaySeconds?: number;\n active?: boolean;\n}\n\nexport interface StepRuleDraft {\n uuid: string;\n actionType: EventRuleActionType;\n actionParams: AnyRecord;\n options: StepRuleOptions;\n /**\n * The uuid the SERVER already stores for this rule, learned during\n * adoption. `uuid` above is minted by the script at authoring time and is\n * therefore different on every run of the same program; sending that as the\n * identity would make every re-run delete the live rule and create a\n * replacement, resetting its delivery bookkeeping. Preferred over `uuid`\n * when present. (v2 builder; the legacy builder never re-writes rules.)\n */\n adoptedUuid?: string;\n}\n\nexport interface StepConnectionDraft {\n parent: JourneyStepBuilder;\n child: JourneyStepBuilder;\n condition?: string;\n required: boolean;\n timeoutSeconds?: number;\n order?: number;\n filterId?: number;\n}\n\nexport interface JourneyGoalDraft {\n name: string;\n description: string;\n step?: JourneyStepBuilder;\n completionCel?: string;\n value?: number;\n order: number;\n}\n\n/**\n * A uuid the action needs, either literal or as the builder that will own it.\n * Builders resolve at apply time, so a step can reference a Workflow created in\n * the same script without the author threading ids through by hand.\n */\nexport type UuidRef = string | WorkspaceBuilderResource;\n\nconst SECONDS_PER_DAY = 86_400;\n\nfunction edgeKey(parentId: unknown, childId: unknown): string {\n return `${parentId}:${childId}`;\n}\n\n/** `days_since(parent_step.completed_at) >= N`, AND-ed onto any explicit CEL. */\nfunction edgeCondition(options: StepConnectionOptions): string | undefined {\n const clauses: string[] = [];\n if (options.afterDays !== undefined) {\n clauses.push(`days_since(parent_step.completed_at) >= ${options.afterDays}`);\n }\n if (options.when) clauses.push(`(${options.when})`);\n if (!clauses.length) return undefined;\n return clauses.join(' && ');\n}\n\nexport class JourneyStepBuilder extends WorkspaceBuilderResource {\n readonly connections: StepConnectionDraft[] = [];\n readonly rules: StepRuleDraft[] = [];\n readonly assigneeId?: number;\n readonly posX?: number;\n readonly posY?: number;\n\n // journey-decoupling Phase 7: a Journey step no longer links to a Workflow.\n // A step nudges via EventRule actions instead of running a Workflow, so the\n // builder no longer accepts or emits a workflow reference.\n constructor(\n readonly name: string,\n readonly journey: JourneyBuilder,\n readonly order = 0,\n readonly description = '',\n options: AnyRecord = {}\n ) {\n super();\n this.assigneeId = options.assigneeId;\n this.posX = options.posX;\n this.posY = options.posY;\n }\n\n /** Wire an edge to `child` and return the CHILD, so chains read linearly. */\n connectsTo(child: JourneyStepBuilder, options: StepConnectionOptions = {}): JourneyStepBuilder {\n if (child === this) {\n throw new Error(`Journey step '${this.name}' cannot connect to itself`);\n }\n const abandonSeconds =\n options.abandonAfterDays !== undefined\n ? options.abandonAfterDays * SECONDS_PER_DAY\n : options.timeoutSeconds;\n this.connections.push({\n parent: this,\n child,\n condition: edgeCondition(options),\n required: options.required ?? false,\n timeoutSeconds: abandonSeconds,\n order: options.order,\n filterId: options.filterId,\n });\n return child;\n }\n\n /**\n * Attach a `JOURNEY_STEP_EXECUTE` action — what this step actually DOES\n * when a member reaches it. A step with no rules is inert: the member\n * lands on it, nothing is sent, and the journey moves on.\n */\n onExecute(\n actionType: EventRuleActionType,\n params: AnyRecord = {},\n options: StepRuleOptions = {}\n ): JourneyStepBuilder {\n this.rules.push({\n uuid: crypto.randomUUID(),\n actionType,\n actionParams: params,\n options,\n });\n return this;\n }\n\n /**\n * Text the member. `phoneNumberUUID` is a workspace PhoneNumber with SMS\n * enabled. Pass `workflowUUID` to start an SMS workflow chat, or\n * `messageTemplate` for a one-off send.\n */\n sendsSms(\n params: {\n phoneNumberUUID: UuidRef;\n messageTemplate?: string;\n workflowUUID?: UuidRef;\n initialUserMessage?: string;\n },\n options: StepRuleOptions = {}\n ): JourneyStepBuilder {\n return this.onExecute(EventRuleActionType.SMS_SEND, params, options);\n }\n\n /**\n * Call the member. Both the workspace PhoneNumber uuid (voice enabled) and\n * the Workflow uuid that drives the call are required.\n */\n callsMember(\n params: { phoneNumberUUID: UuidRef; workflowUUID: UuidRef },\n options: StepRuleOptions = {}\n ): JourneyStepBuilder {\n return this.onExecute(EventRuleActionType.PHONE_CALL, params, options);\n }\n\n /** Email the member from a workspace inbox. */\n sendsEmail(\n params: {\n inboxUUID: UuidRef;\n subjectTemplate?: string;\n bodyTemplate?: string;\n workflowUUID?: UuidRef;\n initialUserMessage?: string;\n contentType?: string;\n },\n options: StepRuleOptions = {}\n ): JourneyStepBuilder {\n return this.onExecute(EventRuleActionType.EMAIL_SEND, params, options);\n }\n\n /** Label the member on arrival — pass label builders, not ids. */\n addsLabels(\n labels: WorkspaceBuilderResource[],\n options: StepRuleOptions = {}\n ): JourneyStepBuilder {\n return this.onExecute(\n EventRuleActionType.MEMBER_LABEL_ACTION,\n { addLabelIds: labels },\n options\n );\n }\n\n /** True once this step has something to do when a member reaches it. */\n get hasOutreach(): boolean {\n return this.rules.length > 0;\n }\n\n eventRuleInputs(): EventRuleInput[] {\n return this.rules.map((rule) => ({\n uuid: rule.uuid,\n eventType: EventRuleEventType.JOURNEY_STEP_EXECUTE,\n actionType: rule.actionType,\n actionParams: resolveRefs(rule.actionParams),\n ...(rule.options.name ? { name: rule.options.name } : {}),\n ...(rule.options.when ? { conditions: rule.options.when } : {}),\n ...(rule.options.delaySeconds ? { delay: rule.options.delaySeconds } : {}),\n active: rule.options.active ?? true,\n }));\n }\n\n planLine(): string {\n const actions = this.rules.map((rule) => rule.actionType).join(' + ');\n return `Step: ${this.name}${actions ? ` (${actions})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n if (this.journey._id === undefined) return;\n const rules = this.eventRuleInputs();\n const payload: JourneyStepFormData = {\n name: this.name,\n description: this.description,\n order: this.order,\n ...(this.assigneeId !== undefined ? { assigneeId: this.assigneeId } : {}),\n ...(this.posX !== undefined ? { posX: this.posX } : {}),\n ...(this.posY !== undefined ? { posY: this.posY } : {}),\n // Saved atomically with the step, so a partial failure cannot leave\n // an inert step behind.\n ...(rules.length ? { eventRules: rules } : {}),\n };\n const result = await client.createStep(this.journey._id, payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n\n/**\n * The auto-created `Start` step. `POST /journeys` always creates one and points\n * `journey.startStepId` at it, so the builder adopts it rather than creating a\n * second — and every real step hangs off it, directly or transitively.\n */\nclass StartStepBuilder extends JourneyStepBuilder {\n get isImplicit(): boolean {\n return true;\n }\n\n planLine(): string {\n return 'Step: Start (auto-created)';\n }\n\n async apply(): Promise<void> {\n // Adopted from the create-journey response; never created.\n }\n}\n\nexport class JourneyBuilder extends WorkspaceBuilderResource {\n readonly description: string;\n readonly steps: JourneyStepBuilder[] = [];\n readonly goals: JourneyGoalDraft[] = [];\n /** The auto-created `Start` step — connect the first real step to it. */\n readonly start: JourneyStepBuilder;\n /** `parentId:childId` for every edge the server already has (see `adopt`). */\n readonly existingEdges = new Set<string>();\n\n constructor(\n readonly name: string,\n options: AnyRecord = {}\n ) {\n super();\n this.description = options.description ?? '';\n this.start = new StartStepBuilder('Start', this, 0);\n this.steps.push(this.start);\n }\n\n step(name: string, options: AnyRecord = {}): JourneyStepBuilder {\n const step = new JourneyStepBuilder(\n name,\n this,\n options.order ?? this.steps.length,\n options.description ?? '',\n options\n );\n this.steps.push(step);\n return step;\n }\n\n /**\n * Declare a linear cadence: `Start → steps[0] → steps[1] → …`, each edge\n * carrying the matching entry from `spacing`.\n *\n * Chaining is not optional polish. A step created with no incoming edge is\n * a ROOT, and every root fires the moment a member enrols — a \"three\n * follow-ups over four days\" journey built without edges sends all three\n * at once.\n */\n sequence(steps: JourneyStepBuilder[], spacing: StepConnectionOptions[] = []): JourneyBuilder {\n let parent = this.start;\n steps.forEach((step, index) => {\n parent = parent.connectsTo(step, spacing[index] ?? {});\n });\n return this;\n }\n\n goal(name: string, options: AnyRecord = {}): JourneyBuilder {\n this.goals.push({\n name,\n description: options.description ?? '',\n step: options.step,\n completionCel: options.completionCel ?? options.completion_cel,\n value: options.value,\n order: options.order ?? this.goals.length,\n });\n return this;\n }\n\n /**\n * Authoring problems that make a journey silently misbehave at runtime.\n * Reported at plan/preview time, before anything is written.\n */\n validate(): string[] {\n const problems: string[] = [];\n const withParents = new Set<JourneyStepBuilder>();\n for (const step of this.steps) {\n for (const connection of step.connections) withParents.add(connection.child);\n }\n for (const step of this.steps) {\n if (step === this.start) continue;\n if (!withParents.has(step)) {\n problems.push(\n `step '${step.name}' has no incoming edge — it is a root and fires for ` +\n 'every member the moment they enrol. Connect it from journey.start or ' +\n 'a prior step.'\n );\n }\n if (!step.hasOutreach) {\n problems.push(\n `step '${step.name}' has no JOURNEY_STEP_EXECUTE action — a member ` +\n 'reaching it gets nothing. Add one with .sendsSms / .callsMember / ' +\n '.sendsEmail / .onExecute.'\n );\n }\n }\n if (!this.goals.length) {\n problems.push(`journey '${this.name}' has no goals — nothing measures whether it works.`);\n }\n return problems;\n }\n\n /**\n * Adopt an existing journey, its steps, and its EDGES, matched by name.\n *\n * Re-running a builder script is normal — a program is usually built in\n * stages as provisioning lands — and without adoption the second run would\n * create a duplicate journey and a duplicate set of steps beside the live\n * one, with members enrolled in neither.\n *\n * The edge set is recorded from the server's own `childConnections` rather\n * than inferred from \"both steps exist\". A first run that created the steps\n * and then failed before writing an edge leaves exactly that state, and\n * inferring would skip the missing edge on every subsequent run — leaving a\n * permanent root step that fires for every member at enrolment, silently.\n * The journey detail read eager-loads connections, so the real answer is\n * already in hand; there is no reason to guess.\n */\n adopt(existing: AnyRecord): void {\n super.adopt(existing);\n const existingSteps = (existing.steps ?? []) as AnyRecord[];\n const byName = new Map(existingSteps.map((step) => [step.name as string, step]));\n const startStep =\n existingSteps.find((step) => step.id === existing.startStepId) ?? byName.get('Start');\n if (startStep) this.start.adopt(startStep);\n for (const step of this.steps) {\n if (step === this.start) continue;\n const match = byName.get(step.name);\n if (match) step.adopt(match);\n }\n for (const step of existingSteps) {\n for (const edge of (step.childConnections ?? []) as AnyRecord[]) {\n this.existingEdges.add(edgeKey(edge.parentStepId, edge.childStepId));\n }\n }\n }\n\n /** True when the server already has this exact edge. */\n hasEdge(parent: JourneyStepBuilder, child: JourneyStepBuilder): boolean {\n if (parent._id === undefined || child._id === undefined) return false;\n return this.existingEdges.has(edgeKey(parent._id, child._id));\n }\n\n planLine(): string {\n const parts: string[] = [];\n const real = this.steps.filter((step) => step !== this.start);\n if (real.length) parts.push(`${real.length} steps`);\n if (this.goals.length) parts.push(`${this.goals.length} goals`);\n return `Journey: ${this.name}${parts.length ? ` (${parts.join(', ')})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const result = await client.createJourney({\n name: this.name,\n description: this.description,\n });\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n\n // Adopt the server's auto-created Start step so edges from\n // `journey.start` resolve to a real uuid instead of silently dropping.\n const startStep = (result.steps ?? []).find(\n (step) => step.id === result.startStepId || step.name === 'Start'\n );\n if (!startStep) {\n throw new Error(\n `Journey '${this.name}' was created without a Start step; ` +\n 'edges from journey.start cannot be wired.'\n );\n }\n this.start.adopt(startStep);\n }\n}\n\nexport function buildJourneyConnectionPayload(\n connection: StepConnectionDraft\n): JourneyStepConnectionFormData | undefined {\n if (!connection.parent._uuid || !connection.child._uuid) return undefined;\n return {\n parentStepUuid: connection.parent._uuid,\n childStepUuid: connection.child._uuid,\n ...(connection.condition ? { celCondition: connection.condition } : {}),\n ...(connection.required ? { required: true } : {}),\n ...(connection.timeoutSeconds ? { timeoutSeconds: connection.timeoutSeconds } : {}),\n ...(connection.order !== undefined ? { order: connection.order } : {}),\n ...(connection.filterId !== undefined ? { filterId: connection.filterId } : {}),\n };\n}\n\nexport function buildJourneyGoalPayload(goal: JourneyGoalDraft): JourneyGoalFormData {\n return {\n name: goal.name,\n description: goal.description,\n order: goal.order,\n ...(goal.step?._uuid ? { goalStepUuid: goal.step._uuid } : {}),\n ...(goal.completionCel ? { completionCel: goal.completionCel } : {}),\n ...(goal.value !== undefined ? { value: goal.value } : {}),\n };\n}\n\n// ===========================================================================\n// Journey v2 builder (plan §3.8)\n// ===========================================================================\n//\n// A SEPARATE class, not a flag on `JourneyBuilder`. The two engines disagree\n// about what a definition even is — legacy is an additive graph written\n// step-by-step, v2 is one ordered timeline written atomically — so a shared\n// class would be a permanent `if (v2)` in every method, and the plan is\n// explicit that \"the existing builder keeps its current legacy behavior unless\n// the caller selects a new v2 builder mode\".\n\n/** The wait on the edge INTO a touch (plan §3.5). */\nexport interface V2WaitOptions {\n /**\n * Whole elapsed days since the previous touch's durable acceptance. The ONE\n * canonical shape the structured control round-trips — the server\n * regenerates the CEL from this number.\n */\n afterDays?: number;\n /**\n * Any other valid CEL, stored byte for byte. `duration(\"4h\")`, member-local\n * schedules, and everything else lives here; the editor evaluates it but\n * declines to reinterpret it. Mutually exclusive with `afterDays`.\n */\n when?: string;\n /** Hold the touch until the member matches this saved MemberFilter. */\n filterId?: number;\n // NOTE: there is no `timeoutSeconds` here, unlike `StepConnectionOptions`.\n // That legacy option is a DEADLINE (`abandonAfterDays` — the child moves to\n // TIMED_OUT), and the v2 evaluator implements no deadline semantics at all,\n // so the server's v2 wait contract rejects the key rather than accepting a\n // setting that would never fire. Model \"stop waiting\" as an Ending instead:\n // it is evaluated on every tick and terminates the enrollment explicitly.\n // Whether v2 grows deadlines is a phase-6+ decision.\n}\n\nexport interface V2TouchOptions {\n description?: string;\n wait?: V2WaitOptions;\n}\n\nexport interface V2EndingOptions {\n /**\n * The Ending's CEL condition. Optional ONLY when `filterId` is given —\n * an Ending with neither predicate would match every enrollment\n * (rule-filters plan §3.2).\n */\n when?: string;\n /**\n * A saved MemberFilter the member must be in. Given alongside `when` the two\n * are ANDed: the Ending claims a member only when both pass.\n */\n filterId?: number;\n}\n\nexport interface V2GoalOptions {\n description?: string;\n /** Touch or Ending whose completion satisfies the goal. */\n step?: V2TouchBuilder | V2EndingBuilder;\n completionCel?: string;\n value?: number;\n}\n\n/** One arm of an exclusive branch (plan §3.7). */\nexport interface V2RouteOptions {\n /**\n * The route's CEL condition. Omit BOTH this and `filterId` to declare the\n * **Otherwise** route: an OPTIONAL fallback, taken immediately when nothing\n * above matched. At most one route per branch omits both, and it must be\n * declared last, because Otherwise matches immediately and anything after it\n * could never be reached.\n *\n * Declaring no Otherwise at all is the default shape, not an omission: the\n * branch is checked top to bottom on every pass and members WAIT at it until\n * a route matches. So there are two author intents, not one:\n *\n * - **wait for a match** — declare only conditional routes;\n * - **fall back immediately** — add a final route with no `when` and no\n * `filterId`.\n */\n when?: string;\n /**\n * A saved MemberFilter the member must be in (rule-filters plan §3.2).\n *\n * A route carrying only this is CONDITIONAL, not the fallback — that is the\n * whole reason `when` alone can no longer answer \"is this Otherwise?\".\n * Given alongside `when` the two are ANDed.\n */\n filterId?: number;\n /**\n * The touch this arm continues to after its own touches — the per-arm\n * terminus. Omit it and the arm ENDS: the enrollment completes after its\n * last touch unless an Ending applies. Absence is meaningful, so there is\n * no separate \"stop\" option to get out of step with it.\n */\n continueAt?: V2TouchBuilder;\n}\n\n/**\n * One route of a branch. Declaration order IS precedence — routes are checked\n * top to bottom and the first match wins.\n */\nexport class V2RouteBuilder {\n readonly touches: V2TouchBuilder[] = [];\n /**\n * The DECISION RULE uuid. Adopted for the same reason an Ending's is:\n * `MemberJourneyStep.entry_decision_rule_id` points at this row with\n * `ON DELETE SET NULL`, so recreating it on a re-run would erase which arm\n * every already-routed enrollment is on — invisibly, since both rules\n * \"exist\" afterwards.\n */\n _ruleUuid?: string;\n\n constructor(\n readonly name: string,\n readonly options: V2RouteOptions = {}\n ) {}\n\n /** Append a touch to this arm. Order is call order. */\n touch(name: string, options: V2TouchOptions = {}): V2TouchBuilder {\n const touch = new V2TouchBuilder(name, options);\n this.touches.push(touch);\n return touch;\n }\n}\n\n/**\n * The ordered route set attached to one touch.\n *\n * There is no branch ENTITY on the server and none is created here — a branch\n * is its rules, and its header is derived from the source touch. This class\n * exists only to group the routes with the touch that owns them.\n *\n * A branch needs at least one CONDITIONAL route. It does not need an Otherwise:\n * with none, members wait at the branch source and the routes are re-checked on\n * every pass until one matches. See {@link V2RouteOptions.when} for the two\n * fallback intents and how each is expressed.\n */\nexport class V2BranchBuilder {\n readonly routes: V2RouteBuilder[] = [];\n\n /** Append a route. Declaration order is evaluation order. */\n route(name: string, options: V2RouteOptions = {}): V2RouteBuilder {\n const route = new V2RouteBuilder(name, options);\n this.routes.push(route);\n return route;\n }\n}\n\n/** One ordinary touch in a v2 timeline, plus the wait that leads into it. */\nexport class V2TouchBuilder {\n readonly rules: StepRuleDraft[] = [];\n /** Filled in from the server's response so a re-run keeps this touch. */\n _uuid?: string;\n\n /**\n * The exclusive branch that follows this touch, when it has one. A touch\n * carrying a branch gets NO ordinary outgoing connection: its routes are\n * the only way out, so touches declared after it are reached only by an arm\n * naming them in `continueAt`.\n */\n _branch?: V2BranchBuilder;\n\n readonly name: string;\n\n /**\n * The name is CANONICALIZED here, once, and everything downstream reads it:\n * the `key:<name>` address, the payload, adoption's name lookup, and the\n * uniqueness gate. The API trims it before storing\n * (`JourneyV2TouchInput`/`JourneyV2EndingInput` name validators), so a\n * builder holding `\" Welcome \"` would send an address for a name the server\n * does not have, fail to find its own step on the way back, and treat it as\n * new on the next run — archiving the live step and its history. One\n * representation at the boundary is the only way that cannot happen; a\n * second trim anywhere downstream would be a place for the two to drift.\n */\n constructor(\n name: string,\n readonly options: V2TouchOptions = {}\n ) {\n this.name = name.trim();\n }\n\n /**\n * Attach an exclusive branch after this touch, or return the existing one.\n *\n * Idempotent so a script can add routes in stages without accidentally\n * declaring two branches on one touch — which the server has no shape for,\n * since a touch owns exactly one ordered route set.\n */\n branch(): V2BranchBuilder {\n this._branch ??= new V2BranchBuilder();\n return this._branch;\n }\n\n /**\n * The request-local address this step answers to (plan §3.8 / phase 6).\n *\n * A saved step is addressed by its uuid; an unsaved one by a `key` derived\n * from its authored name. Deriving from the NAME rather than minting a\n * uuid4 keeps the payload stable across re-runs of the same script — a\n * fresh random key on every run would make the request differ from itself\n * for no reason, and the server's EventRule sync matches on the uuids the\n * payload carries. Names are already asserted unique within a journey,\n * which is what makes a name-derived key unique.\n *\n * {@link V2EndingBuilder} INHERITS this rather than deriving its own: an\n * Ending's anchor key and a touch's key land in one server-side namespace\n * (`stepKey` is one field), so two derivations that drifted would produce\n * two spellings of the same address and a goal would 404 on the one its\n * step was not sent under.\n *\n * Two steps of one name therefore answer to one address. {@link preflight}\n * is the first enforcement point and refuses it before any write, counting\n * touches and Endings together and comparing names trimmed, as the API\n * stores them. Without that gate the collision surfaces twice and both\n * times too late: the server rejects the definition PUT after `apply()` has\n * created the Journey, and {@link indexStoredByName} rejects the SECOND run\n * of a script whose two stored steps make `adopt()` a coin flip.\n */\n get _address(): string {\n return this._uuid ?? `key:${this.name}`;\n }\n\n /**\n * Re-attach the EventRule uuids the server already stores for this touch.\n *\n * Identity is the operator-set rule NAME. `.sendsSms(...)` does not require\n * one, so an unnamed rule falls back to its actionType — but ONLY when that\n * answer is 1:1: exactly one unnamed draft of that actionType here, and\n * exactly one stored rule of it left unclaimed there. Anything else throws.\n *\n * The ordinal-within-actionType fallback this replaces was not a weaker\n * identity, it was the wrong one. Inserting a new unnamed rule ABOVE an\n * existing same-type rule shifts every position by one, so the new rule\n * adopted the existing rule's uuid — taking over its delivery bookkeeping —\n * and the existing rule was written as brand new and archived. Nothing in\n * the payload showed it: both rules \"exist\" afterwards. When the script\n * cannot say which rule is which, the honest answer is to ask the author to\n * name them, not to guess by position.\n */\n adoptRuleUuids(serverRules: AnyRecord[]): void {\n const namedDrafts = this.rules.filter((draft) => !!draft.options.name);\n const storedByName = indexStoredByName(\n serverRules,\n new Set(namedDrafts.map((draft) => draft.options.name as string)),\n `touch '${this.name}'`,\n 'action'\n );\n\n // A stored rule a named draft claims is out of the unnamed pool: it has\n // an owner, so it cannot also be the answer to an unnamed draft.\n const claimed = new Set<AnyRecord>();\n for (const draft of namedDrafts) {\n const match = storedByName.get(draft.options.name as string);\n // No stored rule of that name is an ordinary NEW rule — it keeps the\n // uuid the script minted and the server creates it. It must NOT fall\n // through to the unnamed path: a freshly named rule would there take\n // an existing rule's identity, and the existing rule would be\n // recreated and archived under it.\n if (!match) continue;\n draft.adoptedUuid = match.uuid as string;\n claimed.add(match);\n }\n\n const unnamedByActionType = new Map<string, StepRuleDraft[]>();\n for (const draft of this.rules) {\n if (draft.options.name) continue;\n const actionType = String(draft.actionType);\n unnamedByActionType.set(actionType, [\n ...(unnamedByActionType.get(actionType) ?? []),\n draft,\n ]);\n }\n for (const [actionType, drafts] of unnamedByActionType) {\n const candidates = serverRules.filter(\n (rule) => String(rule.actionType) === actionType && !claimed.has(rule)\n );\n // Nothing stored of this type: every draft is new, and creating them\n // is not a guess.\n if (!candidates.length) continue;\n if (drafts.length === 1 && candidates.length === 1) {\n drafts[0]!.adoptedUuid = candidates[0]!.uuid as string;\n continue;\n }\n throw new Error(\n `touch '${this.name}' has ${drafts.length} unnamed ${actionType} action(s) ` +\n `and the server has ${candidates.length} — so there is no way to tell ` +\n 'which stored action each one is. Adopting by position swaps their ' +\n 'identities the moment an action is inserted or removed, which moves ' +\n \"one action's delivery history onto another. Give these actions names \" +\n '(`{ name: ... }`) so each one can be matched to the right rule.'\n );\n }\n }\n\n /** Attach a `JOURNEY_STEP_EXECUTE` action. Same contract as legacy. */\n onExecute(\n actionType: EventRuleActionType,\n params: AnyRecord = {},\n options: StepRuleOptions = {}\n ): V2TouchBuilder {\n this.rules.push({\n uuid: crypto.randomUUID(),\n actionType,\n actionParams: params,\n options,\n });\n return this;\n }\n\n sendsSms(\n params: {\n phoneNumberUUID: UuidRef;\n messageTemplate?: string;\n workflowUUID?: UuidRef;\n initialUserMessage?: string;\n },\n options: StepRuleOptions = {}\n ): V2TouchBuilder {\n return this.onExecute(EventRuleActionType.SMS_SEND, params, options);\n }\n\n callsMember(\n params: { phoneNumberUUID: UuidRef; workflowUUID: UuidRef },\n options: StepRuleOptions = {}\n ): V2TouchBuilder {\n return this.onExecute(EventRuleActionType.PHONE_CALL, params, options);\n }\n\n sendsEmail(\n params: {\n inboxUUID: UuidRef;\n subjectTemplate?: string;\n bodyTemplate?: string;\n workflowUUID?: UuidRef;\n },\n options: StepRuleOptions = {}\n ): V2TouchBuilder {\n return this.onExecute(EventRuleActionType.EMAIL_SEND, params, options);\n }\n\n get hasOutreach(): boolean {\n return this.rules.length > 0;\n }\n\n eventRuleInputs(): EventRuleInput[] {\n return this.rules.map((rule) => ({\n uuid: rule.adoptedUuid ?? rule.uuid,\n eventType: EventRuleEventType.JOURNEY_STEP_EXECUTE,\n actionType: rule.actionType,\n actionParams: resolveRefs(rule.actionParams),\n ...(rule.options.name ? { name: rule.options.name } : {}),\n ...(rule.options.when ? { conditions: rule.options.when } : {}),\n ...(rule.options.delaySeconds ? { delay: rule.options.delaySeconds } : {}),\n active: rule.options.active ?? true,\n }));\n }\n}\n\n/** One ordered Ending. List position IS precedence — first match wins. */\nexport class V2EndingBuilder extends V2TouchBuilder {\n /**\n * The DECISION RULE uuid, distinct from `_uuid` (the anchor step's).\n *\n * An Ending is two rows: a `JourneyDecisionRule` carrying the condition and\n * precedence, and a `JourneyStep` anchor carrying its actions, goals, and\n * status history. Adopting only the anchor left the rule to be recreated on\n * every re-run — and `MemberJourney.latched_ending_rule_id` /\n * `JourneyStatusLog.journey_decision_rule_id` point at the RULE with\n * `ON DELETE SET NULL`, so every completed enrollment silently forgot which\n * Ending it took.\n */\n _ruleUuid?: string;\n\n constructor(\n name: string,\n readonly when: string | undefined,\n readonly filterId: number | undefined\n ) {\n super(name);\n }\n\n /**\n * An Ending cannot carry a branch, and saying so is the whole override.\n *\n * `V2EndingBuilder extends V2TouchBuilder` for the identity and addressing\n * an Ending's anchor shares with a touch, which also inherits every touch\n * method — `branch()` among them. Inherited unchanged it would set\n * `_branch` on an object nothing ever reads it from: the Ending serializer\n * writes `{uuid|key, name, celCondition, filterId, eventRules}` and no\n * `branch`, and `allTouches()` walks only the timeline, so the routes are\n * never numbered, validated, adopted or sent. The author gets no error and\n * a definition quietly missing what they asked for.\n *\n * An Ending is terminal by construction — it is the rule that ENDS an\n * enrollment — so there is no shape to serialize even if the payload had a\n * field for it. Refusing at the call is the only point where the author is\n * still holding the mistake.\n *\n * @see foreignAnchorProblem for why this names no Ending.\n */\n override branch(): never {\n throw new Error(\n 'an Ending cannot carry a branch. An Ending terminates an enrollment, ' +\n 'so there is nothing after it to route to, and the atomic definition ' +\n 'has no field to send one under — the routes would be silently ' +\n 'dropped. Put the branch on the touch that leads to this Ending ' +\n 'instead, and give each arm its own Ending.'\n );\n }\n}\n\nexport interface V2GoalDraft {\n name: string;\n description?: string;\n step?: V2TouchBuilder | V2EndingBuilder;\n completionCel?: string;\n value?: number;\n /** Server-assigned goal uuid, learned during adoption. */\n _uuid?: string;\n}\n\n/**\n * Build a Journey v2 definition and write it through the ATOMIC endpoint.\n *\n * One create plus one `PUT /v2-definition`, rather than the legacy builder's\n * create-step-then-connect-then-goal sequence. That is not an optimization: a\n * v2 definition is only valid as a whole, so a partial write would be rejected\n * by the publish validator anyway, and a half-applied timeline is exactly the\n * state the atomic endpoint exists to make impossible.\n */\nexport class JourneyV2Builder extends WorkspaceBuilderResource {\n readonly description: string;\n readonly touches: V2TouchBuilder[] = [];\n readonly endings: V2EndingBuilder[] = [];\n readonly goals: V2GoalDraft[] = [];\n /** Activate after the definition is written and validated. */\n readonly activate: boolean;\n /** Optimistic-concurrency token, from create or adoption. */\n private _expectedUpdatedAt?: string;\n /** Server status at adoption — decides whether a re-run must pause first. */\n private _status?: string;\n\n constructor(\n readonly name: string,\n options: AnyRecord = {}\n ) {\n super();\n this.description = options.description ?? '';\n this.activate = options.activate ?? false;\n }\n\n /**\n * A v2 definition write is idempotent, so an ADOPTED journey is written\n * too. That is the whole point of adopting one: the PUT is a full,\n * uuid-keyed replacement, so re-running a script is how an author expresses\n * an edit. The legacy builder stays create-only — its `apply()` only knows\n * how to create, and re-running it would duplicate.\n */\n get appliesWhenExisting(): boolean {\n return true;\n }\n\n /** Append a touch to the timeline. Order is call order. */\n touch(name: string, options: V2TouchOptions = {}): V2TouchBuilder {\n const touch = new V2TouchBuilder(name, options);\n this.touches.push(touch);\n return touch;\n }\n\n /**\n * Every touch in the timeline, arms included, depth first.\n *\n * Identity adoption, name-uniqueness and validation all have to see arm\n * touches — a walk over the top level alone would leave every arm touch\n * recreated on each re-run, silently archiving its member history.\n */\n allTouches(): V2TouchBuilder[] {\n const out: V2TouchBuilder[] = [];\n const walk = (touches: V2TouchBuilder[]): void => {\n for (const touch of touches) {\n out.push(touch);\n for (const route of touch._branch?.routes ?? []) walk(route.touches);\n }\n };\n walk(this.touches);\n return out;\n }\n\n /** Every route in the timeline, at every nesting depth, depth first. */\n allRoutes(): V2RouteBuilder[] {\n const out: V2RouteBuilder[] = [];\n for (const touch of this.allTouches()) {\n for (const route of touch._branch?.routes ?? []) out.push(route);\n }\n return out;\n }\n\n /** Append an Ending. Call order is evaluation order. */\n ending(name: string, options: V2EndingOptions): V2EndingBuilder {\n const ending = new V2EndingBuilder(name, options.when, options.filterId);\n this.endings.push(ending);\n return ending;\n }\n\n goal(name: string, options: V2GoalOptions = {}): JourneyV2Builder {\n this.goals.push({\n name,\n description: options.description,\n step: options.step,\n completionCel: options.completionCel,\n value: options.value,\n });\n return this;\n }\n\n /**\n * Authoring problems the server's publish validator would reject.\n *\n * A different rule set from the legacy builder's on purpose. \"No incoming\n * edge\" has no meaning in a timeline — position is the order — and the v2\n * failure modes are different ones: an action-less touch that is not an\n * explicit wait, and an Ending with no condition.\n */\n validate(): string[] {\n const problems: string[] = [];\n if (!this.touches.length) {\n problems.push(\n `journey '${this.name}' has no touches — an empty timeline has nothing to execute.`\n );\n }\n const armHeads = new Set(\n this.allRoutes()\n .map((route) => route.touches[0])\n .filter(Boolean) as V2TouchBuilder[]\n );\n this.allTouches().forEach((touch) => {\n if (touch.hasOutreach) return;\n const wait = touch.options.wait;\n // Mirrors the server's `_edge_can_hold`: only something that can\n // actually delay the child counts. An ARM HEAD can never qualify —\n // a route target has no incoming edge, so routing into it is\n // immediate and there is nothing for a wait to sit on.\n const isFirst = this.touches[0] === touch;\n const isExplicitWait =\n !isFirst &&\n !armHeads.has(touch) &&\n (wait?.afterDays !== undefined || !!wait?.when || wait?.filterId !== undefined);\n if (isExplicitWait) return;\n problems.push(\n `touch '${touch.name}' has no JOURNEY_STEP_EXECUTE action — a member ` +\n 'reaching it gets nothing. Add one, or give it a wait so it is an ' +\n 'explicit grace period.'\n );\n });\n for (const touch of this.allTouches()) {\n const branch = touch._branch;\n if (!branch) continue;\n // Otherwise is the route with NEITHER predicate. A filter-only route\n // is conditional, so counting it as a fallback here would report a\n // perfectly good branch as having two.\n const fallbacks = branch.routes.filter(\n (route) => !route.options.when?.trim() && route.options.filterId === undefined\n );\n // An Otherwise is OPTIONAL — a branch with only conditional routes\n // holds until one matches, and that is the default shape, so flagging\n // it would stop an author shipping the very thing the server prefers.\n // A CONDITIONAL route is still required: with nothing that can fail to\n // match, the first route takes every member and no decision is made.\n if (branch.routes.length - fallbacks.length < 1) {\n problems.push(\n `branch after touch '${touch.name}' needs at least one conditional ` +\n 'route — one declared with a `when`, a `filterId`, or both. ' +\n 'Members wait at the branch until a route matches, so an ' +\n 'Otherwise is optional.'\n );\n }\n if (fallbacks.length > 1) {\n problems.push(\n `branch after touch '${touch.name}' declares ${fallbacks.length} ` +\n 'Otherwise routes; a branch has at most one unconditional fallback.'\n );\n }\n if (fallbacks.length === 1 && branch.routes[branch.routes.length - 1] !== fallbacks[0]) {\n problems.push(\n `the Otherwise route of the branch after touch '${touch.name}' is ` +\n 'not last; it is taken immediately, so any route after it can ' +\n 'never be reached.'\n );\n }\n for (const route of branch.routes) {\n if (!route.touches.length && !route.options.continueAt) {\n problems.push(\n `route '${route.name}' has no target — give it at least one ` +\n 'touch, or a `continueAt` naming the touch it continues to.'\n );\n }\n }\n }\n for (const ending of this.endings) {\n if (!ending.when?.trim() && ending.filterId === undefined) {\n problems.push(\n `ending '${ending.name}' has no condition — an Ending that always ` +\n 'matches terminates every enrolment on evaluation order alone. ' +\n 'Give it a `when` expression, a `filterId`, or both.'\n );\n }\n }\n return problems;\n }\n\n /**\n * Shapes this definition cannot express, found BEFORE anything is written.\n *\n * A different list from {@link validate}, and a different consequence:\n * those are warnings the orchestrator prints and then writes anyway, these\n * are refusals. For each one the payload has no way to say what the script\n * asked for, so serializing past it would write a DIFFERENT program from\n * the one the script wrote, with nothing afterwards to say so.\n *\n * It has to run before the first write rather than during serialization,\n * because {@link apply} creates the Journey — or pauses a live one — before\n * it builds the payload. A refusal raised from `definitionPayload()` has\n * therefore already left an empty journey shell behind, or taken a\n * production program off the air.\n *\n * PURE: reads only what the script declared, never what the server holds,\n * so it is correct at any point — before adoption included — and\n * `WorkspaceBuilder.preflight()` can stay a synchronous, side-effect-free\n * check a caller may run directly. Nothing here needs adoption to have run:\n * an anchor the server has not seen is addressed by its request-local key,\n * so \"has this Ending been saved\" is no longer a question a refusal\n * depends on.\n */\n preflight(): string[] {\n const problems: string[] = [];\n this.allTouches().forEach((touch, index) => {\n const wait = touch.options.wait;\n if (wait?.afterDays !== undefined && wait.when) {\n problems.push(waitExclusivityProblem(index));\n }\n });\n const owned = this.ownedAnchors();\n this.goals.forEach((goal, index) => {\n const step = goal.step;\n if (step && !owned.has(step)) {\n problems.push(foreignAnchorProblem(index, anchorKind(step)));\n }\n });\n\n // Touches and Endings are ONE step-name namespace, and a repeat in it is\n // a defect whatever the save state. Unsaved, both address themselves\n // `key:<name>` and the definition resolves `stepKey` through a single\n // field, so two rows answer to one address — which the server refuses on\n // the definition PUT, i.e. after `apply()` has created the Journey or\n // paused a live one. Saved, they are two stored steps of one name, which\n // is what {@link indexStoredByName} refuses on the NEXT run.\n //\n // Names arrive canonical (`V2TouchBuilder` trims in its constructor, and\n // `V2EndingBuilder` inherits it), so `\"Welcome\"` and `\" Welcome \"` are\n // already one name here rather than two this gate would wave through.\n //\n // `assertUnambiguousNames()` checks each kind separately and runs from\n // `adopt()`, which a brand-new Journey never reaches — so it cannot be\n // this gate. It still owns routes and goals, whose namespaces are their\n // own.\n const stepNames = [\n ...this.allTouches().map((touch) => touch.name),\n ...this.endings.map((ending) => ending.name),\n ];\n const claims = new Map<string, number>();\n for (const name of stepNames) claims.set(name, (claims.get(name) ?? 0) + 1);\n const repeated = [...claims.values()].filter((count) => count > 1).length;\n if (repeated) problems.push(sharedStepNameProblem(repeated));\n\n // A name that is only whitespace canonicalizes to nothing, which the API\n // refuses (\"name cannot be empty\") — but on the definition PUT, after\n // `apply()` has created the Journey or paused a live one. It also has no\n // usable address: every empty name would claim `key:`. Refusing it here\n // is the same answer, before the first write.\n const nameless = stepNames.filter((name) => !name).length;\n if (nameless) problems.push(namelessStepProblem(nameless));\n return problems;\n }\n\n /**\n * Every step a goal in THIS journey can anchor to, compared by object\n * identity — touches AND Endings, which is why the element type names both\n * rather than leaning on `V2EndingBuilder extends V2TouchBuilder` to smuggle\n * Endings in under a touch-only annotation.\n *\n * A goal anchored to some other journey's builder is not a near miss the\n * server can catch: an unsaved one sends a `stepKey` this definition never\n * declares (a 404 whose cause is invisible), and a SAVED one sends a real\n * `stepUuid` belonging to a live step somewhere else.\n */\n private ownedAnchors(): ReadonlySet<V2TouchBuilder | V2EndingBuilder> {\n return new Set<V2TouchBuilder | V2EndingBuilder>([...this.allTouches(), ...this.endings]);\n }\n\n planLine(): string {\n const parts: string[] = [];\n const touchCount = this.allTouches().length;\n const routeCount = this.allRoutes().length;\n if (touchCount) parts.push(`${touchCount} touches`);\n if (routeCount) parts.push(`${routeCount} routes`);\n if (this.endings.length) parts.push(`${this.endings.length} endings`);\n if (this.goals.length) parts.push(`${this.goals.length} goals`);\n return `Journey (v2): ${this.name}${parts.length ? ` (${parts.join(', ')})` : ''}`;\n }\n\n /**\n * Re-attach every stable child identity the server already holds.\n *\n * The atomic endpoint is a FULL REPLACEMENT keyed on uuids: an omitted\n * uuid does not mean \"unchanged\", it means \"create a new one and archive\n * whatever the old one was\". So anything this misses is silently recreated\n * on every re-run of the same script — and a script is normally re-run,\n * because a program is built in stages. Each identity has a different thing\n * hanging off it, and losing it costs something specific:\n *\n * | identity | what re-creating it destroys |\n * |---|---|\n * | touch step uuid | the touch's `MemberJourneyStep` history |\n * | EventRule uuid | that action's delivery bookkeeping |\n * | Ending RULE uuid | which Ending completed enrollments latched |\n * | Ending anchor uuid | the Ending's status history and goal anchor |\n * | goal uuid | every member's satisfaction row for that goal |\n *\n * `existing` is the journey DETAIL or AUTHORING projection. Both carry\n * `steps[].eventRules`, `goals`, and `decisionRules` —\n * the read projection redacts CEL, not identity — so one fetch is enough\n * and no second round trip is needed. (The orchestrator asks for the\n * authoring projection anyway: this builder holds `journeys:write` because\n * it is about to PUT, and the superset costs nothing.)\n *\n * Names are the only key available on a FIRST adoption, and a duplicate\n * name makes adoption a coin flip between two live resources. That throws\n * rather than guessing: silently attaching a touch to the wrong step\n * archives real member history.\n */\n adopt(existing: AnyRecord): void {\n super.adopt(existing);\n this._expectedUpdatedAt = existing.updatedAt as string | undefined;\n this._status = existing.status as string | undefined;\n this.assertUnambiguousNames();\n this.adoptChildIdentities(existing);\n }\n\n /** Reject a script whose own names cannot identify a resource. */\n private assertUnambiguousNames(): void {\n assertUniqueNames(\n this.allTouches().map((touch) => touch.name),\n `journey '${this.name}'`,\n 'touch'\n );\n // Route names are the adoption key for a route's DECISION RULE, exactly\n // as an Ending's name is, so they must be unique across the whole\n // journey rather than only within their own branch — two branches each\n // with a route called \"Escalate\" would make adoption a coin flip\n // between two live rules.\n assertUniqueNames(\n this.allRoutes().map((route) => route.name),\n `journey '${this.name}'`,\n 'route'\n );\n assertUniqueNames(\n this.endings.map((ending) => ending.name),\n `journey '${this.name}'`,\n 'ending'\n );\n assertUniqueNames(\n this.goals.map((goal) => goal.name),\n `journey '${this.name}'`,\n 'goal'\n );\n for (const touch of [...this.allTouches(), ...this.endings]) {\n const names = touch.rules.map((rule) => rule.options.name).filter(Boolean) as string[];\n assertUniqueNames(names, `touch '${touch.name}'`, 'action name');\n }\n }\n\n private adoptChildIdentities(payload: AnyRecord): void {\n const steps = (payload.steps ?? []) as AnyRecord[];\n // The step names this script will actually look up. Everything below\n // matches STORED rows by name, and neither the table nor the publish\n // validator makes those names unique — so a plain `new Map(...)` would\n // quietly keep the last row of a duplicated name and adopt an arbitrary\n // one of two live identities, archiving the other's member history on\n // the next save. A duplicate the script never names is nobody's problem\n // and is left alone.\n const referencedStepNames = new Set([\n ...this.allTouches().map((touch) => touch.name),\n ...this.endings.map((ending) => ending.name),\n ]);\n const stepsByName = indexStoredByName(\n steps,\n referencedStepNames,\n `journey '${this.name}'`,\n 'step'\n );\n const stepsById = new Map(steps.map((step) => [step.id as number, step]));\n\n for (const touch of this.allTouches()) {\n const match = stepsByName.get(touch.name);\n if (!match) continue;\n touch._uuid = match.uuid as string;\n touch.adoptRuleUuids((match.eventRules ?? []) as AnyRecord[]);\n }\n\n // Branch ROUTES are the complement of the Ending filter below: same\n // table, same identity argument, different product. Indexed by name for\n // the same reason Endings are — a route's uuid is the only thing that\n // survives a re-run, and nothing else in the payload identifies it.\n const routeRules = ((payload.decisionRules ?? []) as AnyRecord[]).filter(\n (rule) => rule.sourceStepId !== null && rule.sourceStepId !== undefined\n );\n const declaredRoutes = this.allRoutes();\n const routesByName = indexStoredByName(\n routeRules,\n new Set(declaredRoutes.map((route) => route.name)),\n `journey '${this.name}'`,\n 'route'\n );\n for (const route of declaredRoutes) {\n const stored = routesByName.get(route.name);\n if (stored) route._ruleUuid = stored.uuid as string;\n }\n\n // An Ending's identity is its decision RULE; the anchor is reached\n // through the rule's target rather than by name, so an adopted Ending\n // never picks up a touch's step. (An Ending and a touch DECLARED under\n // one name are still two stored steps sharing a name, which the step\n // index above refuses — from the touch's side, where the ambiguity is\n // real.)\n const endingRules = ((payload.decisionRules ?? []) as AnyRecord[]).filter(\n (rule) => rule.sourceStepId === null || rule.sourceStepId === undefined\n );\n const rulesByName = indexStoredByName(\n endingRules,\n new Set(this.endings.map((ending) => ending.name)),\n `journey '${this.name}'`,\n 'ending'\n );\n for (const ending of this.endings) {\n const rule = rulesByName.get(ending.name);\n const anchor = rule\n ? stepsById.get(rule.targetStepId as number)\n : stepsByName.get(ending.name);\n if (rule) ending._ruleUuid = rule.uuid as string;\n if (!anchor) continue;\n ending._uuid = anchor.uuid as string;\n ending.adoptRuleUuids((anchor.eventRules ?? []) as AnyRecord[]);\n }\n\n const goalsByName = indexStoredByName(\n (payload.goals ?? []) as AnyRecord[],\n new Set(this.goals.map((goal) => goal.name)),\n `journey '${this.name}'`,\n 'goal'\n );\n for (const goal of this.goals) {\n const match = goalsByName.get(goal.name);\n if (match) goal._uuid = match.uuid as string;\n }\n }\n\n /** The atomic request body. Exposed so a test can assert it without HTTP. */\n definitionPayload(): JourneyV2DefinitionFormData {\n const owned = this.ownedAnchors();\n // Depth-first position, numbered exactly as `preflight()` numbers it, so\n // a refusal raised down in the serializer names the same touch the\n // pre-write gate would have named.\n const positions: ReadonlyMap<V2TouchBuilder, number> = new Map(\n this.allTouches().map((touch, index) => [touch, index])\n );\n return {\n expectedUpdatedAt: this._expectedUpdatedAt ?? '',\n touches: this.touches.map((touch) => serializeV2Touch(touch, positions)),\n endings: this.endings.map((ending): JourneyV2EndingInput => ({\n ...(ending._ruleUuid ? { uuid: ending._ruleUuid } : {}),\n // Anchor address, exactly as `serializeV2Touch` sends a touch's:\n // the saved anchor's uuid, or the request-local `key` a goal in\n // this same save names it by. Both come from `_address`, so the\n // Ending and the goal cannot be sent under two spellings.\n ...(ending._uuid ? { anchorUuid: ending._uuid } : { key: ending._address }),\n name: ending.name,\n // The two predicates are sent INDEPENDENTLY (rule-filters plan\n // §3.2). A filter-only Ending carries no `celCondition` at all\n // rather than an empty one the server would have to normalize.\n ...(ending.when ? { celCondition: ending.when } : {}),\n ...(ending.filterId !== undefined ? { filterId: ending.filterId } : {}),\n eventRules: ending.eventRuleInputs(),\n })),\n // ALWAYS sent, `[]` included. The field distinguishes omitted (leave\n // goals alone) from empty (delete them), and this builder owns the\n // goal list — so omitting an empty list would make goal REMOVAL the\n // one edit a script cannot express: delete the `.goal(...)` call, re-run,\n // and the goal stays live forever.\n goals: this.goals.map((goal, index): JourneyV2GoalInput => ({\n ...(goal._uuid ? { uuid: goal._uuid } : {}),\n name: goal.name,\n ...(goal.description ? { description: goal.description } : {}),\n ...serializeV2GoalAnchor(goal.step, index, owned),\n ...(goal.completionCel ? { completionCel: goal.completionCel } : {}),\n ...(goal.value !== undefined ? { value: goal.value } : {}),\n })),\n };\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n // `WorkspaceBuilder.apply()` gates this, but the class is exported and a\n // direct caller gets no gate at all — while the first statements below\n // are writes. Refuse here too, so an invalid plan never leaves an empty\n // shell behind or pauses a production Journey.\n const problems = this.preflight();\n if (problems.length) {\n throw new Error(\n `Journey (v2) has ${problems.length} problem(s) and was not applied:\\n` +\n problems.map((problem) => ` - ${problem}`).join('\\n')\n );\n }\n\n if (!this._existed) {\n const created = await client.createJourney({\n name: this.name,\n description: this.description,\n // Explicit, always. An omitted executionModel means `legacy` on the\n // server, so a v2 builder that forgot it would quietly author a\n // legacy Journey that happens to look like a timeline.\n executionModel: 'v2',\n });\n this._id = created.id;\n this._uuid = created.uuid;\n this._created = true;\n this._expectedUpdatedAt = created.updatedAt;\n } else if (this._status === 'active' && this.activate) {\n // A live Journey's topology is immutable, so a re-run has to pause\n // before it can write, and re-read for a fresh concurrency token.\n //\n // Only when the script ASKED for an active Journey. Pausing one it\n // did not ask to activate would take a production program off the air\n // as a side effect of re-running a script; without `activate` the\n // server's stable `journey_v2_structural_edit_not_allowed` refusal is\n // the right answer, and it tells the operator exactly what to do.\n const paused = await client.updateJourney(this.id, { status: 'paused' });\n this._expectedUpdatedAt = paused.updatedAt;\n }\n\n const saved = await client.putJourneyV2Definition(this.id, this.definitionPayload());\n this._expectedUpdatedAt = saved.updatedAt;\n this.adoptWrittenUuids(saved);\n\n if (this.activate) {\n await client.updateJourney(this.id, { status: 'active' });\n }\n }\n\n /**\n * Re-attach the uuids the server assigned, so a follow-up write matches.\n *\n * The PUT returns the AUTHORING projection, which is the same shape\n * `adopt` reads — so this is the same operation against a payload we just\n * caused, and it uses the same code path rather than a second, thinner\n * copy that would drift.\n */\n private adoptWrittenUuids(saved: AnyRecord): void {\n this.adoptChildIdentities(saved);\n }\n}\n\n/**\n * Index STORED rows by name, refusing a name the script matches that more than\n * one stored row answers to.\n *\n * The mirror image of {@link assertUniqueNames}: that one rejects a script\n * whose own names are ambiguous, this one rejects a SERVER state the script's\n * names cannot resolve. Both halves are needed, because nothing makes a\n * journey's step, Ending, goal, or action names unique — not the tables, not\n * the publish validator — so the ambiguity can arrive from the editor long\n * after a clean script was written.\n *\n * `referenced` is the set of names the script will look up. A stored duplicate\n * outside it is harmless: nothing in this script will ever choose between\n * those two rows, and refusing to run because of a resource the script does\n * not touch would be a gate the author cannot act on.\n */\nfunction indexStoredByName(\n rows: AnyRecord[],\n referenced: Set<string>,\n owner: string,\n kind: string\n): Map<string, AnyRecord> {\n const byName = new Map<string, AnyRecord>();\n const counts = new Map<string, number>();\n for (const row of rows) {\n const name = row.name;\n if (typeof name !== 'string' || !name) continue;\n counts.set(name, (counts.get(name) ?? 0) + 1);\n if (!byName.has(name)) byName.set(name, row);\n }\n for (const [name, count] of counts) {\n if (count < 2 || !referenced.has(name)) continue;\n throw new Error(\n `${owner} already has ${count} ${kind}s named '${name}'. This script adopts ` +\n `by name, so it cannot tell which ${kind} it owns — and the one it does ` +\n 'not pick is archived on the next save, taking its history with it. ' +\n `Rename them so each name identifies one ${kind}.`\n );\n }\n return byName;\n}\n\n/** Throw when a builder's own names cannot identify a resource. */\nfunction assertUniqueNames(names: string[], owner: string, kind: string): void {\n const seen = new Set<string>();\n for (const name of names) {\n if (seen.has(name)) {\n throw new Error(\n `${owner} has two ${kind}s named '${name}'. The v2 builder adopts an ` +\n 'existing journey by name, so duplicates would attach a builder to ' +\n \"either one at random — archiving the other's history on the next \" +\n 'save. Rename one.'\n );\n }\n seen.add(name);\n }\n}\n\n/** Translate builder wait options into the server's structured wait. */\n/**\n * Serialize one touch and, recursively, the branch it owns.\n *\n * A free function rather than a method so the recursion reads as one shape:\n * touch -> branch -> routes -> arm touches -> … . `key` is sent whenever the\n * touch has no server uuid yet, because an arm can only name an unsaved\n * rejoin target through the request-local address (plan §3.8).\n */\nfunction serializeV2Touch(\n touch: V2TouchBuilder,\n positions: ReadonlyMap<V2TouchBuilder, number>\n): JourneyV2TouchInput {\n return {\n ...(touch._uuid ? { uuid: touch._uuid } : { key: touch._address }),\n name: touch.name,\n ...(touch.options.description ? { description: touch.options.description } : {}),\n ...(touch.options.wait\n ? { wait: buildV2Wait(touch.options.wait, positions.get(touch)) }\n : {}),\n eventRules: touch.eventRuleInputs(),\n ...(touch._branch\n ? {\n branch: {\n routes: touch._branch.routes.map((route) => ({\n ...(route._ruleUuid ? { uuid: route._ruleUuid } : {}),\n name: route.name,\n // Omitted, not null, and INDEPENDENT of each other: a route\n // with neither predicate IS the Otherwise marker, one with\n // either is conditional, and one with both is ANDed\n // (rule-filters plan §3.2). The server normalizes \"\" to the\n // same thing as omitted.\n ...(route.options.when ? { celCondition: route.options.when } : {}),\n ...(route.options.filterId !== undefined\n ? { filterId: route.options.filterId }\n : {}),\n touches: route.touches.map((armTouch) => serializeV2Touch(armTouch, positions)),\n ...(route.options.continueAt\n ? { continueAt: route.options.continueAt._address }\n : {}),\n })),\n },\n }\n : {}),\n };\n}\n\n/**\n * How a goal names its anchor step in the atomic payload.\n *\n * A saved anchor is named by `stepUuid`. An unsaved one — a touch or an\n * Ending's anchor alike — is named by `stepKey`, carrying the same\n * request-local address the step itself is sent under, because on the FIRST\n * save of a timeline nothing has a uuid yet and a client cannot mint one.\n * Sending nothing there is not a missing decoration: an anchored goal is\n * satisfied only when its step is reached AND its CEL holds, so the goal that\n * reached the server would be a different rule from the one the script wrote.\n *\n * `owned` is the set of steps this journey declares, compared by object\n * identity: a goal anchored to another builder's step would otherwise send a\n * `stepKey` this definition never declares, or a live `stepUuid` belonging to\n * a step in some other journey. That is the one thing this cannot express, and\n * it THROWS rather than serializing to nothing — dropping an anchor is silent,\n * the payload is valid, the write succeeds, and nothing afterwards says so.\n *\n * The refusal is the LAST line of defence. `WorkspaceBuilder.apply()` gates on\n * {@link JourneyV2Builder.preflight} before it writes anything; this fires\n * only for a caller that reached `definitionPayload()` directly, and it raises\n * the identical sentence so the two paths cannot drift.\n */\nfunction serializeV2GoalAnchor(\n step: V2TouchBuilder | V2EndingBuilder | undefined,\n goalIndex: number,\n owned: ReadonlySet<V2TouchBuilder | V2EndingBuilder>\n): Pick<JourneyV2GoalInput, 'stepUuid' | 'stepKey'> {\n if (!step) return {};\n if (!owned.has(step)) throw new Error(foreignAnchorProblem(goalIndex, anchorKind(step)));\n if (step._uuid) return { stepUuid: step._uuid };\n return { stepKey: step._address };\n}\n\n/**\n * The two refusals, worded once.\n *\n * Both the pre-write gate and the serializer raise these, so an author who\n * trips the last line of defence reads the sentence the gate would have\n * printed. Each names the offender by POSITION and the anchor by KIND, never\n * by the name the script gave it: these strings reach operator terminals, CI\n * logs and exception trackers, and an authored touch, goal or Ending name is\n * workspace content that has no business in any of them.\n */\nfunction foreignAnchorProblem(goalIndex: number, kind: 'touch' | 'Ending'): string {\n return (\n `goal at index ${goalIndex} is anchored to ${kind === 'Ending' ? 'an' : 'a'} ` +\n `${kind} that belongs to a different journey builder. A goal anchor is ` +\n 'part of the same atomic definition as its step, so it can only name a ' +\n 'touch or Ending this journey declares.'\n );\n}\n\n/**\n * `touchIndex` is the touch's depth-first position, absent only for a direct\n * caller of {@link buildV2Wait} that has no timeline to position it in.\n *\n * @see foreignAnchorProblem for why these carry positions and not names.\n */\nfunction waitExclusivityProblem(touchIndex: number | undefined): string {\n const where = touchIndex === undefined ? 'this touch' : `touch at index ${touchIndex}`;\n return (\n `${where} sets both afterDays and when; fold the day count into \\`when\\`. ` +\n 'A v2 wait is either a whole-day count or Advanced CEL, not both.'\n );\n}\n\n/**\n * Step names claimed more than once, counted across touches AND Endings.\n *\n * @see foreignAnchorProblem for why this counts them and does not name them.\n */\nfunction sharedStepNameProblem(count: number): string {\n return (\n `${count} step name(s) are claimed more than once. Touches and Endings ` +\n 'are one namespace: until a save mints their uuids they address ' +\n 'themselves by name and the definition resolves those keys through one ' +\n 'field, and once saved they are stored steps the next run cannot tell ' +\n 'apart. Names are canonical (trimmed), as the API stores them. Rename one.'\n );\n}\n\n/**\n * Steps whose canonical name is empty.\n *\n * @see foreignAnchorProblem for why this counts them and does not name them.\n */\nfunction namelessStepProblem(count: number): string {\n return (\n `${count} step(s) have an empty name once trimmed. A step's name is its ` +\n 'request-local address until a save mints its uuid, so a nameless one ' +\n 'has nothing to be addressed by, and the API refuses it. Name them.'\n );\n}\n\n/** How a refusal names an anchor: by what it IS, never by what it is called. */\nfunction anchorKind(step: V2TouchBuilder | V2EndingBuilder): 'touch' | 'Ending' {\n return step instanceof V2EndingBuilder ? 'Ending' : 'touch';\n}\n\nexport function buildV2Wait(wait: V2WaitOptions, touchIndex?: number): JourneyV2WaitInput {\n if (wait.afterDays !== undefined && wait.when) {\n throw new Error(waitExclusivityProblem(touchIndex));\n }\n const extras = {\n ...(wait.filterId !== undefined ? { filterId: wait.filterId } : {}),\n };\n if (wait.afterDays !== undefined) {\n return { kind: 'wholeDays', days: wait.afterDays, ...extras };\n }\n if (wait.when) {\n return { kind: 'advanced', cel: wait.when, ...extras };\n }\n return { kind: 'none', ...extras };\n}\n","import type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport type { AnyRecord } from './resource';\nimport { WorkspaceBuilderResource } from './resource';\n\nexport class RoleUpdate extends WorkspaceBuilderResource {\n constructor(\n readonly roleId: number,\n readonly workflowIds?: number[],\n readonly dataTypeIds?: number[]\n ) {\n super();\n }\n\n planLine(): string {\n const parts: string[] = [];\n if (this.workflowIds) parts.push(`workflows=${JSON.stringify(this.workflowIds)}`);\n if (this.dataTypeIds) parts.push(`dataTypes=${JSON.stringify(this.dataTypeIds)}`);\n return `RoleUpdate: roleId=${this.roleId}${parts.length ? ` (${parts.join(', ')})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const payload: AnyRecord = {};\n if (this.workflowIds) payload.workflowIds = this.workflowIds;\n if (this.dataTypeIds) payload.dataTypeIds = this.dataTypeIds;\n if (Object.keys(payload).length) await client.updateMemberRole(this.roleId, payload);\n this._id = this.roleId;\n this._created = true;\n }\n}\n","import {\n EventRuleEventType,\n type CreateAgentRequest,\n type EventRuleActionType,\n type WorkflowFormData,\n} from '../types';\nimport type { Ability } from '../types/ability-types';\nimport type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport type { WorkspaceBuilderEventRule } from './event-rules';\nimport type { FormBuilder } from './forms';\nimport { type AnyRecord, WorkspaceBuilderResource } from './resource';\n\nconst PERM_KEYS: Record<string, string> = {\n canRead: 'canRead',\n canCreate: 'canCreate',\n canEdit: 'canEdit',\n can_read: 'canRead',\n can_create: 'canCreate',\n can_edit: 'canEdit',\n};\n\nconst ABILITY_TYPE_MAP: Record<string, string> = {\n data_access: 'integration:data_access',\n file_access: 'integration:file_access',\n escalation: 'oversight:escalation',\n};\n\nclass AbilityDef {\n readonly uuid = crypto.randomUUID();\n readonly config: AnyRecord;\n readonly enabled: boolean;\n readonly celCondition?: string;\n readonly form?: FormBuilder;\n readonly perms: AnyRecord = {};\n\n constructor(\n readonly abilityType: string,\n options: AnyRecord = {}\n ) {\n this.config = options.config ?? {};\n this.enabled = options.enabled ?? true;\n this.celCondition = options.celCondition ?? options.cel_condition;\n this.form = options.form;\n for (const [inputKey, outputKey] of Object.entries(PERM_KEYS)) {\n if (inputKey in options) this.perms[outputKey] = options[inputKey];\n }\n }\n\n toAbility(): Ability {\n const config = { ...this.config };\n if (this.form?._uuid) {\n config.dataTypeUuid = this.form._uuid;\n Object.assign(config, this.perms);\n }\n return {\n uuid: this.uuid,\n abilityType: ABILITY_TYPE_MAP[this.abilityType] ?? this.abilityType,\n config,\n enabled: this.enabled,\n ...(this.celCondition ? { celCondition: this.celCondition } : {}),\n };\n }\n}\n\nexport interface TaskTransition {\n parent: TaskBuilder;\n child: TaskBuilder;\n when: string;\n autoNext: boolean;\n required: boolean;\n celCondition?: string;\n}\n\nexport interface WorkflowBuilderOptions {\n description?: string;\n prompt?: string;\n copyFromAgentId?: number;\n}\n\nexport class TaskBuilder extends WorkspaceBuilderResource {\n readonly transitions: TaskTransition[] = [];\n readonly eventRules: WorkspaceBuilderEventRule[] = [];\n /** Child task ids the server already has, recorded when this task is adopted. */\n readonly existingChildIds = new Set<number>();\n\n /** Record the edges an adopted task already carries, so a re-run adds only what is missing. */\n adopt(existing: AnyRecord): void {\n super.adopt(existing);\n for (const child of (existing.childTasks ?? []) as AnyRecord[]) {\n const id = child.taskId ?? child.id;\n if (typeof id === 'number') this.existingChildIds.add(id);\n }\n }\n\n constructor(\n readonly name: string,\n readonly workflow: WorkflowBuilder,\n readonly prompt = '',\n readonly start = false,\n readonly description = ''\n ) {\n super();\n }\n\n transitionsTo(\n child: TaskBuilder,\n when: string,\n autoNext = false,\n required = false,\n celCondition?: string\n ): TaskBuilder {\n if (child === this) {\n throw new Error(`Task '${this.name}' cannot transition to itself`);\n }\n this.transitions.push({\n parent: this,\n child,\n when,\n autoNext,\n required,\n celCondition,\n });\n return this;\n }\n\n onEnter(action: string, params: AnyRecord = {}, name?: string): TaskBuilder {\n this.eventRules.push({\n eventType: EventRuleEventType.TASK_EXECUTE,\n actionType: action as EventRuleActionType,\n actionParams: params,\n name,\n });\n return this;\n }\n\n initialMessage(message: string, suggestions?: string[]): TaskBuilder {\n return this.onEnter('assistant:message', {\n message,\n ...(suggestions ? { suggestions } : {}),\n });\n }\n\n planLine(): string {\n return `Task: ${this.name}${this.start ? ' [start]' : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed || this.workflow._id === undefined) return;\n if (this.workflow._draftRevisionId === undefined) {\n // Root id without a draft revision id means the workflow was\n // created/adopted through a path that skipped revision resolution —\n // creating the task would attach it to whatever revision happens to\n // share the number (cross-workflow corruption). Fail loudly.\n throw new Error(\n `Workflow '${this.workflow.name}' has no draft revision id; ` +\n 'cannot create tasks. Tasks attach to a WorkflowRevision, ' +\n 'not the stable workflow root.'\n );\n }\n // Tasks belong to a revision graph — target the DRAFT revision\n // explicitly (edits always land on the draft; publish makes them live).\n const result = await client.createTask({\n workflowRevisionId: this.workflow._draftRevisionId,\n name: this.name,\n prompt: this.prompt,\n description: this.description,\n });\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n\nexport class WorkflowBuilder extends WorkspaceBuilderResource {\n readonly description: string;\n readonly prompt?: string;\n private copyFromAgentId?: number;\n readonly tasks: TaskBuilder[] = [];\n readonly abilities: AbilityDef[] = [];\n /** The DRAFT revision's id — where tasks and graph edits attach.\n * `_id` is the STABLE workflow root id; the two are different entities\n * and (after any publish) different numbers. */\n _draftRevisionId?: number;\n\n constructor(\n readonly name: string,\n options: WorkflowBuilderOptions = {}\n ) {\n super();\n this.description = options.description ?? '';\n this.prompt = options.prompt;\n this.copyFromAgentId = options.copyFromAgentId;\n }\n\n task(name: string, options: AnyRecord = {}): TaskBuilder {\n const task = new TaskBuilder(\n name,\n this,\n options.prompt ?? '',\n options.start ?? false,\n options.description ?? ''\n );\n this.tasks.push(task);\n return task;\n }\n\n ability(abilityType: string, options: AnyRecord = {}): WorkflowBuilder {\n this.abilities.push(new AbilityDef(abilityType, options));\n return this;\n }\n\n get startTask(): TaskBuilder | undefined {\n return this.tasks.find((task) => task.start) ?? this.tasks[0];\n }\n\n matchKey(): string {\n return this.name;\n }\n\n adopt(existing: AnyRecord): void {\n // Accepts the WorkflowDetail composition ({ workflow, draftRevision,\n // activeRevision }) — the orchestrator fetches it per matched name.\n // Root facts (id/uuid) live on `workflow`; graph facts (startTaskId)\n // live on the draft revision.\n const root = (existing.workflow ?? existing) as AnyRecord;\n super.adopt(root);\n const draft = existing.draftRevision as AnyRecord | undefined;\n this._draftRevisionId = (draft?.id ?? root.draftRevisionId) as number | undefined;\n const start = this.startTask;\n const startTaskId = draft?.startTaskId as number | undefined;\n if (start && startTaskId) {\n start._id = startTaskId;\n start._existed = true;\n }\n }\n\n planLine(): string {\n const details: string[] = [];\n if (this.tasks.length) details.push(`${this.tasks.length} tasks`);\n if (this.abilities.length) details.push(`${this.abilities.length} abilities`);\n return `Workflow: ${this.name}${details.length ? ` (${details.join(', ')})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n const payload: WorkflowFormData = {\n name: this.name,\n description: this.description,\n createMode: 'taskless',\n ...(this.prompt ? { prompt: this.prompt } : {}),\n ...(this.copyFromAgentId ? { copyFromAgentId: this.copyFromAgentId } : {}),\n ...(this.abilities.length\n ? { abilities: this.abilities.map((ability) => ability.toAbility()) }\n : {}),\n };\n const result = await client.createWorkflow(payload);\n this._id = result.workflow.id;\n this._uuid = result.workflow.uuid;\n // Tasks attach to the draft revision, never the root — keep its id.\n this._draftRevisionId = result.draftRevision.id;\n this._created = true;\n }\n}\n\nexport class AgentBuilder extends WorkspaceBuilderResource {\n readonly chatModelId: string;\n readonly systemPrompt: string;\n readonly memberRoleId?: number;\n readonly tools: string[];\n readonly codeInterpreterEnabled: boolean;\n readonly webBrowserEnabled: boolean;\n\n constructor(\n readonly name: string,\n options: AnyRecord = {}\n ) {\n super();\n this.chatModelId = options.chatModelId ?? options.chat_model_id ?? '';\n this.systemPrompt = options.systemPrompt ?? options.system_prompt ?? '';\n this.memberRoleId = options.roleId ?? options.role_id;\n this.tools = options.tools ?? [];\n this.codeInterpreterEnabled =\n options.codeInterpreterEnabled ?? options.code_interpreter_enabled ?? false;\n this.webBrowserEnabled = options.webBrowserEnabled ?? options.web_browser_enabled ?? false;\n }\n\n planLine(): string {\n const parts: string[] = [];\n if (this.chatModelId) parts.push(`model=${this.chatModelId}`);\n if (this.tools.length) parts.push(`${this.tools.length} tools`);\n return `Agent: ${this.name}${parts.length ? ` (${parts.join(', ')})` : ''}`;\n }\n\n async apply(client: GravityRailWorkspaceClient): Promise<void> {\n if (this._existed) return;\n if (this.memberRoleId === undefined) {\n throw new Error(`Agent '${this.name}' requires memberRoleId`);\n }\n if (!this.chatModelId) {\n throw new Error(`Agent '${this.name}' requires chatModelId`);\n }\n\n const payload: CreateAgentRequest = {\n name: this.name,\n memberRoleId: this.memberRoleId,\n chatModelId: this.chatModelId,\n systemPrompt: this.systemPrompt,\n ...(this.tools.length ? { tools: this.tools } : {}),\n ...(this.codeInterpreterEnabled ? { codeInterpreterEnabled: true } : {}),\n ...(this.webBrowserEnabled ? { webBrowserEnabled: true } : {}),\n };\n const result = await client.createAgent(payload);\n this._id = result.id;\n this._uuid = result.uuid;\n this._created = true;\n }\n}\n","import {\n EventRuleObjectType,\n type EventRule,\n type EventRuleFormData,\n type UpdateEventRuleFormData,\n} from '../types';\nimport { ApiError } from '../api/base';\nimport type { GravityRailWorkspaceClient } from '../client/workspace-client';\nimport { MemberFilterBuilder, NotificationRuleBuilder, RoutineBuilder } from './automation';\nimport { FormBuilder, MemberLabelBuilder } from './forms';\nimport {\n buildJourneyConnectionPayload,\n buildJourneyGoalPayload,\n JourneyBuilder,\n JourneyStepBuilder,\n JourneyV2Builder,\n} from './journeys';\nimport {\n type AnyRecord,\n type ResourceSummary,\n resolveRefs,\n WorkspaceBuilderResource,\n} from './resource';\nimport { RoleUpdate } from './role-update';\nimport {\n AgentBuilder,\n TaskBuilder,\n type TaskTransition,\n WorkflowBuilder,\n type WorkflowBuilderOptions,\n} from './workflows';\n\nconst PHASES = new Map<Function, number>([\n [FormBuilder, 0],\n [MemberLabelBuilder, 0],\n [AgentBuilder, 1],\n [WorkflowBuilder, 2],\n [TaskBuilder, 3],\n [RoleUpdate, 4],\n [MemberFilterBuilder, 5],\n [RoutineBuilder, 6],\n [NotificationRuleBuilder, 6],\n [JourneyBuilder, 7],\n // Same phase as the legacy builder: a v2 Journey is written whole by its\n // own apply(), so it has no child resources to sequence after it.\n [JourneyV2Builder, 7],\n [JourneyStepBuilder, 8],\n]);\n\n/**\n * Page size for the adoption sweeps.\n *\n * Adoption has to see every resource of a type, not the first screenful — the\n * list routes default to 10 per page, so a workspace with a dozen routines\n * would leave the eleventh undiscovered and duplicated on every re-run. 100 is\n * the max these routes allow; `collectPages` walks the rest.\n */\nconst LIST_PAGE_SIZE = 100;\n\n/**\n * Read every page of a paginated list endpoint.\n *\n * `totalPages` is trusted for the bound but the walk also stops on an empty\n * page, so a backend that reports the count differently cannot spin here.\n */\nasync function collectPages<T>(\n fetchPage: (page: number) => Promise<{ items: T[]; totalPages?: number }>\n): Promise<T[]> {\n const first = await fetchPage(1);\n const all = [...first.items];\n const totalPages = first.totalPages ?? 1;\n for (let page = 2; page <= totalPages; page++) {\n const next = await fetchPage(page);\n if (!next.items.length) break;\n all.push(...next.items);\n }\n return all;\n}\n\nfunction sameIdSet(left: number[], right: number[]): boolean {\n const target = new Set(right);\n return target.size === new Set(left).size && left.every((id) => target.has(id));\n}\n\nfunction notificationRuleKey(\n noticeType: string,\n memberId: number,\n workflowId: number | null\n): string {\n return JSON.stringify([noticeType, memberId, workflowId]);\n}\n\n/**\n * Resolve a resource's build phase, walking the prototype chain.\n *\n * Keyed on the exact constructor a subclass (e.g. the journey `Start` step)\n * misses every entry and silently sorts to the end — applying its edges after\n * everything else and hiding ordering bugs behind an accident.\n */\nfunction phaseFor(resource: WorkspaceBuilderResource): number {\n let ctor: Function | null = resource.constructor;\n while (ctor) {\n const phase = PHASES.get(ctor);\n if (phase !== undefined) return phase;\n ctor = Object.getPrototypeOf(ctor) as Function | null;\n }\n return 99;\n}\n\nexport class WorkspaceBuilder {\n readonly resources: WorkspaceBuilderResource[] = [];\n\n constructor(readonly client: GravityRailWorkspaceClient) {}\n\n form(name: string, options: AnyRecord & { slug?: string } = {}): FormBuilder {\n const form = new FormBuilder(name, options.slug, options);\n this.resources.push(form);\n return form;\n }\n\n workflow(name: string, options: WorkflowBuilderOptions = {}): WorkflowBuilder {\n const workflow = new WorkflowBuilder(name, options);\n this.resources.push(workflow);\n return workflow;\n }\n\n label(\n name: string,\n options: { slug?: string; color?: string; description?: string } = {}\n ): MemberLabelBuilder {\n const label = new MemberLabelBuilder(\n name,\n options.slug,\n options.color,\n options.description ?? ''\n );\n this.resources.push(label);\n return label;\n }\n\n journey(name: string, options: AnyRecord = {}): JourneyBuilder {\n const journey = new JourneyBuilder(name, options);\n this.resources.push(journey);\n return journey;\n }\n\n /**\n * A Journey v2 timeline (plan §3.8): ordered touches, structured waits, and\n * ordered Endings, written through the atomic definition endpoint.\n *\n * A separate factory rather than an option on {@link journey}, because the\n * two return different builders with different vocabularies — `.touch()`\n * and `.ending()` versus `.step()` and `.connectsTo()`. The legacy builder\n * keeps its current behaviour untouched, which is the plan's explicit\n * compatibility requirement.\n */\n journeyV2(name: string, options: AnyRecord = {}): JourneyV2Builder {\n const journey = new JourneyV2Builder(name, options);\n this.resources.push(journey);\n return journey;\n }\n\n agent(name: string, options: AnyRecord = {}): AgentBuilder {\n const agent = new AgentBuilder(name, options);\n this.resources.push(agent);\n return agent;\n }\n\n routine(name: string, cronSchedule = '', options: AnyRecord = {}): RoutineBuilder {\n const routine = new RoutineBuilder(name, cronSchedule, options);\n this.resources.push(routine);\n return routine;\n }\n\n memberFilter(name: string, options: AnyRecord = {}): MemberFilterBuilder {\n const filter = new MemberFilterBuilder(name, options);\n this.resources.push(filter);\n return filter;\n }\n\n notificationRule(name: string, options: AnyRecord = {}): NotificationRuleBuilder {\n const rule = new NotificationRuleBuilder(name, options);\n this.resources.push(rule);\n return rule;\n }\n\n roleUpdate(roleId: number, workflowIds?: number[], dataTypeIds?: number[]): RoleUpdate {\n const update = new RoleUpdate(roleId, workflowIds, dataTypeIds);\n this.resources.push(update);\n return update;\n }\n\n plan(): void {\n const resources = this.sortedResources();\n writeLine(`\\n${'='.repeat(50)}`);\n writeLine('Plan');\n writeLine('='.repeat(50));\n const declared = resources.filter((resource) => !resource.isImplicit);\n for (const resource of declared) {\n writeLine(` + ${resource.planLine()}`);\n }\n const wiring = this.collectWiringSummary(resources);\n if (wiring.length) {\n writeLine('\\n Wiring:');\n for (const line of wiring) writeLine(` ${line}`);\n }\n this.reportJourneyWarnings();\n writeLine(`\\n Total: ${declared.length} resources, ${wiring.length} connections`);\n writeLine(`${'='.repeat(50)}\\n`);\n }\n\n async preview(): Promise<void> {\n const resources = this.sortedResources();\n await this.resolveExisting(resources);\n\n writeLine(`\\n${'='.repeat(50)}`);\n writeLine('Preview');\n writeLine('='.repeat(50));\n const declared = resources.filter((resource) => !resource.isImplicit);\n for (const resource of declared) {\n if (resource._existed) {\n writeLine(` = ${resource.planLine()} (exists, id=${resource._id})`);\n } else {\n writeLine(` + ${resource.planLine()}`);\n }\n }\n const wiring = this.collectWiringSummary(resources);\n if (wiring.length) {\n writeLine('\\n Wiring:');\n for (const line of wiring) writeLine(` ${line}`);\n }\n this.reportJourneyWarnings();\n const toCreate = declared.filter((resource) => !resource._existed);\n const existing = declared.filter((resource) => resource._existed);\n writeLine(\n `\\n Total: ${toCreate.length} to create, ${existing.length} existing, ${wiring.length} connections`\n );\n writeLine(`${'='.repeat(50)}\\n`);\n }\n\n /**\n * Print journey authoring problems that only bite at runtime — a step with\n * no incoming edge fires for every member at enrolment, and a step with no\n * action does nothing at all. Both look fine in the editor, so they are\n * surfaced before the write rather than discovered from a member's phone.\n */\n private reportJourneyWarnings(): void {\n const problems = this.resources\n .filter(\n (resource): resource is JourneyBuilder | JourneyV2Builder =>\n resource instanceof JourneyBuilder || resource instanceof JourneyV2Builder\n )\n .flatMap((journey) => journey.validate());\n if (!problems.length) return;\n writeLine('\\n Journey warnings:');\n for (const problem of problems) writeLine(` ! ${problem}`);\n }\n\n /**\n * Problems that make the plan unwritable, found before the first write.\n *\n * The API validates each CEL when you save it, and its diagnosis is right —\n * but it fires per-write, so a plan whose edges reference a non-collection\n * form gets four labels, two forms, a workflow and six tasks created before\n * the seventh call rejects it. The operator is left with a half-built\n * program to hand-repair. Checking here costs nothing and writes nothing.\n *\n * Deliberately narrow: only cross-resource facts the builder can see with\n * certainty. Per-field CEL schema checking stays server-side, where the\n * real validator lives — duplicating it here would drift.\n *\n * Pure: reads only what the plan declares, never what the server holds, so\n * it is correct before adoption and safe for a caller to run directly. It\n * is also the WHOLE gate: every anchor a v2 definition can name has a\n * request-local address whether or not the server has seen it, so no\n * refusal has to wait for adoption to decide it.\n */\n preflight(): string[] {\n const problems: string[] = [];\n const forms = this.resources.filter(\n (resource): resource is FormBuilder => resource instanceof FormBuilder\n );\n const collectionBySlug = new Map(forms.map((form) => [form.slug, form.collection]));\n\n // `assignment.collections.<slug>` requires <slug> to be a COLLECTION\n // form. This is the exact defect that shipped: the edges were right, the\n // form was declared without `collection: true`, and nothing said so\n // until fourteen resources existed.\n const reference = /assignment\\.collections\\.([A-Za-z0-9_]+)/g;\n for (const resource of this.sortedResources()) {\n if (!(resource instanceof TaskBuilder)) continue;\n for (const transition of resource.transitions) {\n const cel = transition.celCondition;\n if (!cel) continue;\n for (const [, slug] of cel.matchAll(reference)) {\n if (!collectionBySlug.has(slug)) continue; // server resolves it\n if (!collectionBySlug.get(slug)) {\n problems.push(\n `task '${transition.parent.name}' → '${transition.child.name}': CEL reads ` +\n `assignment.collections.${slug}, but this plan creates '${slug}' as a ` +\n `non-collection form. Declare it with { collection: true }.`\n );\n }\n }\n }\n }\n\n // A v2 Journey is written as ONE atomic PUT, and `JourneyV2Builder.apply()`\n // has to create the Journey — or pause a live one — before it can build\n // that payload. So a definition the builder cannot express has to be\n // refused here or the refusal lands after those writes, leaving an empty\n // journey shell or a production program off the air.\n for (const resource of this.resources) {\n if (resource instanceof JourneyV2Builder) problems.push(...resource.preflight());\n }\n return [...new Set(problems)];\n }\n\n /** The plan-rejection shape: every problem printed, nothing written. */\n private rejectIfProblems(problems: string[]): void {\n if (!problems.length) return;\n writeLine('\\nPlan rejected — nothing was created:');\n for (const problem of problems) writeLine(` ! ${problem}`);\n throw new Error(\n `Plan has ${problems.length} problem(s) and was not applied:\\n` +\n problems.map((problem) => ` - ${problem}`).join('\\n')\n );\n }\n\n async apply(): Promise<ResourceSummary> {\n const resources = this.sortedResources();\n\n // Refuse before writing anything, rather than failing part-way through.\n // One gate, and it is pure: nothing it decides depends on which\n // resources the server already holds, so adoption (reads only) can run\n // after it.\n this.rejectIfProblems(this.preflight());\n await this.resolveExisting(resources);\n\n const summary: ResourceSummary = {};\n\n writeLine('Applying...');\n for (const resource of resources) {\n try {\n // The server already made it (a journey's Start step) — it is here\n // only so edges can point at it.\n if (resource.isImplicit) continue;\n // Most builders are create-only: an adopted resource is left\n // exactly as the server has it, because their `apply()` knows only\n // how to CREATE and re-running it would duplicate. A resource that\n // declares `appliesWhenExisting` writes idempotently — its apply()\n // is a full, uuid-keyed replacement that handles the adopted case\n // itself — so skipping it here would make adoption pointless: the\n // second run of a script would read the journey, resolve every\n // identity, and then write nothing.\n if (resource._existed && !resource.appliesWhenExisting) {\n const key = resourceKey(resource);\n summary[key] ??= [];\n summary[key]!.push(resource._id);\n writeLine(` Exists ${resource.planLine()} -> id=${resource._id}`);\n continue;\n }\n\n const updating = resource._existed;\n await resource.apply(this.client);\n if (resource._created || resource._id !== undefined) {\n const key = resourceKey(resource);\n summary[key] ??= [];\n summary[key]!.push(resource._id);\n const startTag = resource instanceof TaskBuilder && resource.start ? ' [start]' : '';\n const verb = updating ? 'Updated' : 'Created';\n writeLine(` ${verb} ${resource.planLine()}${startTag} -> id=${resource._id}`);\n } else {\n writeLine(` Skipped: ${resource.planLine()}`);\n }\n } catch (err) {\n writeLine(formatApplyFailureLine(resource, err));\n throw new ApplyError(resource, err, summary);\n }\n }\n\n await this.applyTransitions();\n await this.applyEventRules(resources);\n await this.applyJourneyConnections(resources);\n await this.applyJourneyGoals(resources);\n\n const count = Object.values(summary).reduce((total, ids) => total + ids.length, 0);\n writeLine(`\\nDone! Created ${count} resources.`);\n return summary;\n }\n\n private async resolveExisting(resources: WorkspaceBuilderResource[]): Promise<void> {\n // Before the first server call: a journey name is the ONLY key adoption\n // has, and two builders declared under one name collapse into a single\n // entry of the name→builder map below — so one of them is silently never\n // adopted and never applied, while the other inherits whatever the\n // server holds under that name and (for v2) replaces it whole.\n assertUniqueJourneyNames(\n resources.filter(\n (resource): resource is JourneyBuilder | JourneyV2Builder =>\n resource instanceof JourneyBuilder || resource instanceof JourneyV2Builder\n )\n );\n\n const formSlugs = new Map(\n resources\n .filter((resource): resource is FormBuilder => resource instanceof FormBuilder)\n .map((resource) => [resource.slug, resource])\n );\n const labelSlugs = new Map(\n resources\n .filter(\n (resource): resource is MemberLabelBuilder => resource instanceof MemberLabelBuilder\n )\n .map((resource) => [resource.slug, resource])\n );\n const workflowNames = new Map(\n resources\n .filter((resource): resource is WorkflowBuilder => resource instanceof WorkflowBuilder)\n .map((resource) => [resource.name, resource])\n );\n\n if (formSlugs.size) {\n for (const existing of await this.client.getDataTypes()) {\n if (existing.slug && formSlugs.has(existing.slug)) {\n formSlugs.get(existing.slug)!.adopt(existing);\n }\n }\n }\n if (labelSlugs.size) {\n for (const existing of await this.client.getMemberLabels()) {\n if (existing.slug && labelSlugs.has(existing.slug)) {\n labelSlugs.get(existing.slug)!.adopt(existing);\n }\n }\n }\n\n const filterNames = new Map(\n resources\n .filter(\n (resource): resource is MemberFilterBuilder =>\n resource instanceof MemberFilterBuilder\n )\n .map((resource) => [resource.name, resource])\n );\n if (filterNames.size) {\n for (const existing of await this.client.getMemberFilters()) {\n if (existing.name && filterNames.has(existing.name)) {\n filterNames.get(existing.name)!.adopt(existing);\n }\n }\n }\n\n // Journeys adopt by name and pull a per-journey projection, because a\n // journey's identity for re-run purposes is its step graph, and the list\n // rows carry no steps.\n //\n // A v2 builder pulls the AUTHORING projection instead of the detail one.\n // Both carry the identities it adopts (step uuids, per-step eventRules,\n // goals, decisionRules), but the v2 write is a full\n // atomic REPLACEMENT, so it must not be a mixed-deploy question whether\n // this payload happens to include decision rules — an absent rule uuid\n // silently recreates the Ending. The builder already holds\n // `journeys:write`; it is about to PUT.\n const journeyNames = new Map(\n resources\n .filter(\n (resource): resource is JourneyBuilder | JourneyV2Builder =>\n resource instanceof JourneyBuilder || resource instanceof JourneyV2Builder\n )\n .map((resource) => [resource.name, resource])\n );\n if (journeyNames.size) {\n // Every page, not just the first: the default page holds 25 rows, so\n // a match on page 2 would be silently duplicated — and worse, two\n // same-name journeys SPLIT across pages would dodge the ambiguity\n // refusal below and adopt the first one destructively. Max page size,\n // walk totalPages (review round 10).\n const pageSize = 500;\n const firstPage = await this.client.getJourneys(false, { page: 1, pageSize });\n const allJourneys = [...firstPage.items];\n for (let page = 2; page <= firstPage.totalPages; page++) {\n const nextPage = await this.client.getJourneys(false, { page, pageSize });\n allJourneys.push(...nextPage.items);\n }\n // Group first, adopt second. Adopting inside the scan would attach the\n // builder to the FIRST stored journey of that name and then attach it\n // again to the second — each adoption a full, destructive replacement\n // of a different live journey. Only an unambiguous 1:1 match is\n // adoptable; zero matches is the ordinary create path.\n const storedByName = new Map<string, (typeof allJourneys)[number][]>();\n for (const existing of allJourneys) {\n if (!existing.name || !journeyNames.has(existing.name)) continue;\n storedByName.set(existing.name, [...(storedByName.get(existing.name) ?? []), existing]);\n }\n for (const [name, matches] of storedByName) {\n if (matches.length > 1) {\n throw new Error(\n `This workspace has ${matches.length} journeys named '${name}', and ` +\n 'the script adopts an existing journey by name — so it cannot tell ' +\n 'which one it owns. Adopting the wrong one replaces that journey ' +\n 'whole on the next save. Rename the others in the app, or rename ' +\n 'the journey in the script.'\n );\n }\n const existing = matches[0]!;\n const builder = journeyNames.get(name)!;\n const detail =\n builder instanceof JourneyV2Builder\n ? await this.client.getJourneyAuthoring(existing.id)\n : await this.client.getJourney(existing.id);\n builder.adopt(detail);\n }\n }\n\n const agentNames = new Map(\n resources\n .filter((resource): resource is AgentBuilder => resource instanceof AgentBuilder)\n .map((resource) => [resource.name, resource])\n );\n if (agentNames.size) {\n // Archived agents are deliberately not adopted: the list endpoint\n // excludes them, and re-adopting one would resurrect a resource the\n // workspace retired rather than create the agent the script asked for.\n for (const existing of await collectPages((page) =>\n this.client.getAgents({ page, pageSize: LIST_PAGE_SIZE })\n )) {\n if (existing.name && agentNames.has(existing.name)) {\n agentNames.get(existing.name)!.adopt(existing);\n }\n }\n }\n\n const routineNames = new Map(\n resources\n .filter((resource): resource is RoutineBuilder => resource instanceof RoutineBuilder)\n .map((resource) => [resource.name, resource])\n );\n if (routineNames.size) {\n for (const existing of await collectPages((page) =>\n this.client.getRoutines({ page, pageSize: LIST_PAGE_SIZE })\n )) {\n if (existing.name && routineNames.has(existing.name)) {\n routineNames.get(existing.name)!.adopt(existing);\n }\n }\n }\n\n await this.resolveExistingRoleUpdates(resources);\n await this.resolveExistingWorkflows(resources, workflowNames);\n // Last, because a notification rule's identity includes the workflow it\n // notifies about, and that id is only known once workflows are adopted.\n await this.resolveExistingNotificationRules(resources);\n }\n\n /**\n * Adopt a role update whose grants the server already has.\n *\n * A role update is a replace-semantics PUT, not a create, so its identity is\n * the role id and \"already applied\" means the id sets match exactly. Subset\n * would be wrong: `roleUpdate(7, [])` asks to *clear* the role's workflow\n * access, and treating that as satisfied by a role that still has grants\n * would silently skip a real change.\n *\n * Only the fields this update declares are compared — an update that passes\n * `workflowIds` and omits `dataTypeIds` never touches data-type access, so\n * that access cannot make it stale.\n */\n private async resolveExistingRoleUpdates(resources: WorkspaceBuilderResource[]): Promise<void> {\n const updates = resources.filter(\n (resource): resource is RoleUpdate => resource instanceof RoleUpdate\n );\n if (!updates.length) return;\n\n const rolesById = new Map(\n (await this.client.getMemberRoles()).map((role) => [role.id, role])\n );\n for (const update of updates) {\n const role = rolesById.get(update.roleId);\n if (!role) continue;\n // Grants carry an accessMode the builder has no way to express, so\n // the ids are the whole of the comparable fact.\n const workflowsSettled =\n update.workflowIds === undefined ||\n sameIdSet(\n update.workflowIds,\n (role.workflowAccess ?? []).map((access) => access.workflowId)\n );\n const dataTypesSettled =\n update.dataTypeIds === undefined ||\n sameIdSet(\n update.dataTypeIds,\n (role.dataTypeAccess ?? []).map((access) => access.dataTypeId)\n );\n if (workflowsSettled && dataTypesSettled) update.adopt(role);\n }\n }\n\n /**\n * Adopt notification rules the server already has.\n *\n * There is no name on the server row — `NotificationRule` is keyed by what\n * it does — so identity is the composite the API enforces uniqueness on in\n * practice: notice type, recipient, and subject workflow.\n */\n private async resolveExistingNotificationRules(\n resources: WorkspaceBuilderResource[]\n ): Promise<void> {\n const rules = resources.filter(\n (resource): resource is NotificationRuleBuilder =>\n resource instanceof NotificationRuleBuilder\n );\n if (!rules.length) return;\n\n const identified = rules.flatMap((rule) => {\n // memberId absent: apply() rejects it, so there is nothing to match.\n if (rule.memberId === undefined) return [];\n // A declared workflow with no id yet is a workflow this run will\n // create, so no server rule can be pointing at it. Matching on\n // \"workflow unset\" here would adopt an unrelated global rule.\n if (rule.workflow && rule.workflow._id === undefined) return [];\n return [\n [\n notificationRuleKey(rule.noticeType, rule.memberId, rule.workflow?._id ?? null),\n rule,\n ] as const,\n ];\n });\n if (!identified.length) return;\n\n const byKey = new Map(identified);\n for (const existing of await this.client.getNotificationRules()) {\n const key = notificationRuleKey(\n existing.noticeType,\n existing.memberId,\n existing.workflowId ?? null\n );\n byKey.get(key)?.adopt(existing);\n }\n }\n\n private async resolveExistingWorkflows(\n resources: WorkspaceBuilderResource[],\n workflowNames: Map<string, WorkflowBuilder>\n ): Promise<void> {\n if (!workflowNames.size) return;\n\n const existingWorkflows = await this.client.getWorkflows();\n for (const { workflow: existing } of existingWorkflows.items) {\n if (existing.name && workflowNames.has(existing.name)) {\n // List rows carry only the root + active-revision summary. Tasks\n // and startTaskId live on the DRAFT revision, so fetch the detail\n // composition for adoption (root ids and revision ids are\n // different entities — matching tasks by root id attaches them to\n // the wrong workflow once any workflow has been published).\n const detail = await this.client.getWorkflow(existing.id);\n workflowNames.get(existing.name)!.adopt(detail);\n }\n }\n\n const adoptedWorkflows = resources.filter(\n (resource): resource is WorkflowBuilder =>\n resource instanceof WorkflowBuilder && resource._existed && resource._id !== undefined\n );\n if (!adoptedWorkflows.length) return;\n\n const existingTasks = await this.client.getTasks();\n for (const workflow of adoptedWorkflows) {\n // Tasks belong to a revision graph — match against the adopted\n // workflow's DRAFT revision id (task.workflowRevisionId), falling\n // back to the legacy field for older payloads.\n const workflowTasks = existingTasks.filter(\n (task) =>\n ((task as { workflowRevisionId?: number }).workflowRevisionId ?? task.workflowId) ===\n workflow._draftRevisionId\n );\n const taskByName = new Map(workflowTasks.map((task) => [task.name, task]));\n for (const taskBuilder of workflow.tasks) {\n const match = taskByName.get(taskBuilder.name);\n if (match) taskBuilder.adopt(match);\n }\n\n const ids = new Map<number, TaskBuilder[]>();\n for (const taskBuilder of workflow.tasks) {\n if (taskBuilder._id !== undefined) {\n ids.set(taskBuilder._id, [...(ids.get(taskBuilder._id) ?? []), taskBuilder]);\n }\n }\n for (const builders of ids.values()) {\n if (builders.length <= 1) continue;\n const nameAdopted = builders.filter((task) => taskByName.has(task.name));\n for (const task of builders.filter((builder) => !nameAdopted.includes(builder))) {\n task._id = undefined;\n task._existed = false;\n }\n }\n }\n }\n\n private sortedResources(): WorkspaceBuilderResource[] {\n const all: WorkspaceBuilderResource[] = [];\n for (const resource of this.resources) {\n all.push(resource);\n if (resource instanceof WorkflowBuilder) {\n const start = resource.startTask;\n const tasks =\n start === undefined\n ? resource.tasks\n : [start, ...resource.tasks.filter((task) => task !== start)];\n all.push(...tasks);\n } else if (resource instanceof JourneyBuilder) {\n all.push(...resource.steps);\n }\n }\n return all.sort((a, b) => phaseFor(a) - phaseFor(b));\n }\n\n private collectWiringSummary(resources: WorkspaceBuilderResource[]): string[] {\n const lines: string[] = [];\n for (const resource of resources) {\n if (resource instanceof TaskBuilder) {\n for (const transition of resource.transitions) {\n lines.push(`${transition.parent.name} -> ${transition.child.name}`);\n }\n for (const rule of resource.eventRules) {\n lines.push(`${rule.actionType} on enter '${resource.name}'`);\n }\n } else if (resource instanceof FormBuilder) {\n for (const rule of resource.eventRules) {\n lines.push(`${rule.actionType} on ${rule.eventType} '${resource.name}'`);\n }\n } else if (resource instanceof RoutineBuilder) {\n for (const rule of resource.rules)\n lines.push(`${rule.actionType} rule on '${resource.name}'`);\n } else if (resource instanceof JourneyStepBuilder) {\n for (const connection of resource.connections) {\n const guard = connection.condition ? ` [${connection.condition}]` : '';\n lines.push(`${connection.parent.name} -> ${connection.child.name}${guard}`);\n }\n for (const rule of resource.rules) {\n lines.push(`${rule.actionType} on step '${resource.name}'`);\n }\n } else if (resource instanceof JourneyBuilder) {\n for (const goal of resource.goals) lines.push(`Goal: ${goal.name}`);\n } else if (resource instanceof JourneyV2Builder) {\n // A v2 timeline has no edges to name — position IS the order — so\n // the preview shows the sequence itself, then the Endings in the\n // precedence they will be evaluated in.\n resource.touches.forEach((touch, index) => {\n lines.push(`${index + 1}. ${touch.name}`);\n });\n for (const ending of resource.endings) lines.push(`Ending: ${ending.name}`);\n for (const goal of resource.goals) lines.push(`Goal: ${goal.name}`);\n }\n }\n return lines;\n }\n\n private async applyTransitions(): Promise<void> {\n const parentChildren = new Map<TaskBuilder, TaskTransition[]>();\n for (const resource of this.sortedResources()) {\n if (!(resource instanceof TaskBuilder)) continue;\n for (const transition of resource.transitions) {\n parentChildren.set(transition.parent, [\n ...(parentChildren.get(transition.parent) ?? []),\n transition,\n ]);\n }\n }\n\n for (const [parent, transitions] of parentChildren) {\n if (parent._id === undefined) continue;\n const childTasks = transitions.flatMap((transition) => {\n const taskId = transition.child._id;\n if (taskId === undefined || taskId === parent._id) return [];\n // Already wired on a previous run — re-sending it makes the API\n // reject the whole update as a conflict, which reads as \"the\n // template half-worked\" and sends the operator hand-repairing.\n if (parent.existingChildIds.has(taskId)) return [];\n return [\n {\n taskId,\n choicePrompt: transition.when,\n celCondition: transition.celCondition ?? null,\n autoNext: transition.autoNext,\n required: transition.required,\n },\n ];\n });\n if (!childTasks.length) continue;\n await this.client.updateTask(parent._id, { childTasks });\n writeLine(\n ` Wired: ${parent.name} -> [${transitions.map((tr) => tr.child.name).join(', ')}]`\n );\n }\n }\n\n private async applyEventRules(resources: WorkspaceBuilderResource[]): Promise<void> {\n for (const resource of resources) {\n if (resource instanceof TaskBuilder) {\n for (const rule of resource.eventRules) {\n try {\n const payload: EventRuleFormData = {\n objectType: EventRuleObjectType.TASK,\n taskId: resource._id,\n eventType: rule.eventType,\n actionType: rule.actionType,\n actionParams: resolveRefs(rule.actionParams),\n ...(rule.name ? { name: rule.name } : {}),\n };\n await this.applyEventRule(\n payload,\n `${rule.actionType} on enter '${resource.name}'`\n );\n } catch (err) {\n handleEventRuleApplyFailure(resource.name, err);\n }\n }\n } else if (resource instanceof FormBuilder) {\n for (const rule of resource.eventRules) {\n try {\n const payload: EventRuleFormData = {\n objectType: EventRuleObjectType.DATA_RECORD,\n dataTypeId: resource._id,\n eventType: rule.eventType,\n actionType: rule.actionType,\n actionParams: resolveRefs(rule.actionParams),\n ...(rule.condition ? { conditions: rule.condition } : {}),\n ...(rule.name ? { name: rule.name } : {}),\n };\n await this.applyEventRule(\n payload,\n `${rule.actionType} on ${rule.eventType} '${resource.name}'`\n );\n } catch (err) {\n handleEventRuleApplyFailure(resource.name, err);\n }\n }\n }\n }\n }\n\n private async applyEventRule(payload: EventRuleFormData, label: string): Promise<void> {\n const existing = await this.findMatchingEventRule(payload);\n if (!existing) {\n await this.client.createEventRule(payload);\n writeLine(` Wired: ${label}`);\n return;\n }\n\n const update = eventRuleUpdate(existing, payload);\n if (Object.keys(update).length) {\n await this.client.updateEventRule(existing.id, update);\n writeLine(` Updated: ${label}`);\n } else {\n writeLine(` Exists: ${label}`);\n }\n }\n\n private async findMatchingEventRule(payload: EventRuleFormData): Promise<EventRule | undefined> {\n const sourceFilter = eventRuleSourceFilter(payload);\n const candidates = await this.client.searchEventRules({\n objectType: payload.objectType,\n eventType: payload.eventType,\n actionType: payload.actionType,\n includeDisabled: true,\n ...sourceFilter,\n });\n return candidates.find((candidate) => eventRulesMatch(candidate, payload));\n }\n\n private async applyJourneyConnections(resources: WorkspaceBuilderResource[]): Promise<void> {\n for (const resource of resources) {\n if (!(resource instanceof JourneyStepBuilder)) continue;\n for (const connection of resource.connections) {\n if (resource.journey._id === undefined) continue;\n // Skip only an edge the SERVER actually reports (recorded during\n // adoption). \"Both steps exist\" is not the same fact: a first run\n // that created the steps and died before the edge leaves exactly\n // that state, and skipping there would strand a root step that\n // fires for every member at enrolment, on every future run.\n if (resource.journey.hasEdge(connection.parent, connection.child)) {\n writeLine(` Exists: ${connection.parent.name} -> ${connection.child.name}`);\n continue;\n }\n const payload = buildJourneyConnectionPayload(connection);\n if (!payload) continue;\n await this.client.createConnection(resource.journey._id, payload);\n writeLine(` Wired: ${connection.parent.name} -> ${connection.child.name}`);\n }\n }\n }\n\n private async applyJourneyGoals(resources: WorkspaceBuilderResource[]): Promise<void> {\n for (const resource of resources) {\n if (!(resource instanceof JourneyBuilder) || resource._id === undefined) continue;\n // Goals have no natural key to match on, so an adopted journey keeps\n // the goals it already has rather than accumulating a duplicate set\n // on every re-run. Say so per goal — the plan already listed them, and\n // a silent skip reads as \"created\" to anyone watching the output.\n if (resource._existed) {\n for (const goal of resource.goals) {\n writeLine(` Skipped (journey already exists): Goal: ${goal.name}`);\n }\n continue;\n }\n for (const goal of resource.goals) {\n await this.client.createGoal(resource._id, buildJourneyGoalPayload(goal));\n writeLine(` Created goal: ${goal.name}`);\n }\n }\n }\n}\n\nexport class ApplyError extends Error {\n readonly createdSoFar: ResourceSummary;\n readonly #resource: WorkspaceBuilderResource;\n readonly #cause: unknown;\n\n constructor(resource: WorkspaceBuilderResource, cause: unknown, createdSoFar: ResourceSummary) {\n super(formatApplyErrorMessage(resource, cause, createdSoFar));\n this.name = 'ApplyError';\n this.createdSoFar = createdSoFar;\n this.#resource = resource;\n this.#cause = cause;\n }\n\n get resource(): WorkspaceBuilderResource {\n return this.#resource;\n }\n\n get cause(): unknown {\n return this.#cause;\n }\n}\n\n/**\n * Refuse a script that declares two journeys under one name.\n *\n * A journey has no slug and no author-supplied key, so its NAME is the whole\n * of its identity for adoption. Two builders sharing one collapse into a\n * single map entry, which is silent: the plan prints both, one of them is\n * simply never adopted or applied, and the other inherits whatever the server\n * had under that name.\n */\nfunction assertUniqueJourneyNames(journeys: (JourneyBuilder | JourneyV2Builder)[]): void {\n const seen = new Set<string>();\n for (const journey of journeys) {\n if (seen.has(journey.name)) {\n throw new Error(\n `This script declares two journeys named '${journey.name}'. A journey is ` +\n 'adopted and re-applied by name, so only one of them could ever be ' +\n 'written — and a v2 apply replaces the journey it adopted whole. ' +\n 'Rename one.'\n );\n }\n seen.add(journey.name);\n }\n}\n\nfunction resourceKey(resource: WorkspaceBuilderResource): string {\n if (resource instanceof RoleUpdate) return 'roleUpdates';\n if (resource instanceof FormBuilder) return 'forms';\n if (resource instanceof MemberLabelBuilder) return 'labels';\n if (resource instanceof WorkflowBuilder) return 'workflows';\n if (resource instanceof TaskBuilder) return 'tasks';\n if (resource instanceof MemberFilterBuilder) return 'memberFilters';\n if (resource instanceof RoutineBuilder) return 'routines';\n if (resource instanceof NotificationRuleBuilder) return 'notificationRules';\n if (resource instanceof JourneyBuilder || resource instanceof JourneyV2Builder) {\n return 'journeys';\n }\n if (resource instanceof JourneyStepBuilder) return 'journeySteps';\n if (resource instanceof AgentBuilder) return 'agents';\n return 'resources';\n}\n\nconst SEARCHABLE_EVENT_RULE_SOURCE_FIELDS = [\n 'taskId',\n 'dataTypeId',\n 'routineId',\n 'workflowRevisionId',\n 'journeyStepId',\n] as const;\n\nconst EVENT_RULE_SOURCE_FIELDS = [\n ...SEARCHABLE_EVENT_RULE_SOURCE_FIELDS,\n 'calendarId',\n 'calendarEventTypeId',\n] as const;\n\ntype SearchableEventRuleSourceField = (typeof SEARCHABLE_EVENT_RULE_SOURCE_FIELDS)[number];\n\nfunction eventRuleSourceFilter(\n payload: EventRuleFormData\n): Partial<Record<SearchableEventRuleSourceField, number>> {\n const filter: Partial<Record<SearchableEventRuleSourceField, number>> = {};\n for (const field of SEARCHABLE_EVENT_RULE_SOURCE_FIELDS) {\n const value = payload[field];\n if (value !== undefined && value !== null) {\n filter[field] = value;\n }\n }\n return filter;\n}\n\nfunction eventRulesMatch(existing: EventRule, payload: EventRuleFormData): boolean {\n if (normalizeString(existing.name) !== normalizeString(payload.name)) return false;\n if (existing.objectType !== payload.objectType) return false;\n if (existing.eventType !== payload.eventType) return false;\n if (existing.actionType !== payload.actionType) return false;\n\n for (const field of EVENT_RULE_SOURCE_FIELDS) {\n if ((existing[field] ?? null) !== (payload[field] ?? null)) return false;\n }\n\n if (normalizeString(payload.name)) return true;\n if (normalizeString(existing.conditions) !== normalizeString(payload.conditions)) return false;\n if (!eventRuleValueEqual(existing.actionParams, payload.actionParams ?? null)) return false;\n if (!eventRuleValueEqual(existing.triggerParams, payload.triggerParams ?? null)) return false;\n return true;\n}\n\nfunction eventRuleUpdate(existing: EventRule, payload: EventRuleFormData): UpdateEventRuleFormData {\n const update: UpdateEventRuleFormData = {};\n const conditions = payload.conditions ?? null;\n if (normalizeString(existing.conditions) !== normalizeString(conditions)) {\n update.conditions = conditions;\n }\n const actionParams = payload.actionParams ?? null;\n if (!eventRuleValueEqual(existing.actionParams, actionParams)) {\n update.actionParams = payload.actionParams;\n }\n const triggerParams = payload.triggerParams ?? null;\n if (!eventRuleValueEqual(existing.triggerParams, triggerParams)) {\n update.triggerParams = payload.triggerParams;\n }\n const active = payload.active ?? true;\n if (existing.active !== active) {\n update.active = active;\n }\n const delay = payload.delay ?? 0;\n if (existing.delay !== delay) {\n update.delay = delay;\n }\n const order = payload.order ?? 0;\n if (existing.order !== order) {\n update.order = order;\n }\n return update;\n}\n\nfunction normalizeString(value: string | null | undefined): string {\n return value ?? '';\n}\n\nfunction eventRuleValueEqual(left: unknown, right: unknown): boolean {\n return JSON.stringify(stableValue(left)) === JSON.stringify(stableValue(right));\n}\n\nfunction stableValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(stableValue);\n if (!value || typeof value !== 'object') return value;\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) return value;\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, nested]) => [key, stableValue(nested)])\n );\n}\n\nfunction writeLine(message = ''): void {\n process.stdout.write(`${message}\\n`);\n}\n\nfunction handleEventRuleApplyFailure(resourceName: string, err: unknown): void {\n if (hasStatus(err, 403)) {\n writeLine(\n ` WARNING: Event rule on '${resourceName}' failed (retry exec() with scopes=['automations:admin'])`\n );\n return;\n }\n const summary = summarizeError(err);\n writeLine(` FAILED: Event rule on '${resourceName}': ${summary}`);\n throw new Error(`Failed wiring event rule on '${resourceName}': ${summary}`);\n}\n\nfunction writeScopeForResource(resource: WorkspaceBuilderResource): string | null {\n if (resource instanceof FormBuilder) return 'datatypes:write';\n if (resource instanceof WorkflowBuilder || resource instanceof TaskBuilder) {\n return 'workflows:write';\n }\n if (resource instanceof AgentBuilder) return 'agents:write';\n if (resource instanceof MemberLabelBuilder || resource instanceof MemberFilterBuilder) {\n return 'members:write';\n }\n if (resource instanceof RoutineBuilder || resource instanceof NotificationRuleBuilder) {\n return 'automations:admin';\n }\n if (\n resource instanceof JourneyBuilder ||\n resource instanceof JourneyStepBuilder ||\n resource instanceof JourneyV2Builder\n ) {\n return 'journeys:write';\n }\n if (resource instanceof RoleUpdate) return 'member_roles:write';\n return null;\n}\n\nfunction scopeRetryHint(resource: WorkspaceBuilderResource): string {\n const scope = writeScopeForResource(resource);\n return scope ? ` (retry exec with scopes=['${scope}'])` : '';\n}\n\nfunction formatApplyFailureLine(resource: WorkspaceBuilderResource, err: unknown): string {\n const line = ` FAILED: ${resource.planLine()}: ${summarizeError(err)}`;\n return hasStatus(err, 403) ? `${line}${scopeRetryHint(resource)}` : line;\n}\n\nfunction formatApplyErrorMessage(\n resource: WorkspaceBuilderResource,\n cause: unknown,\n createdSoFar: ResourceSummary\n): string {\n let message = `Failed creating ${resource.planLine()}: ${summarizeError(cause)}`;\n if (hasStatus(cause, 403)) {\n const scope = writeScopeForResource(resource);\n if (scope) {\n message += `\\nRetry exec with scopes=['${scope}']`;\n }\n }\n const createdKeys = Object.keys(createdSoFar);\n if (createdKeys.length > 0) {\n message += `\\nAlready created: ${JSON.stringify(createdSoFar)}`;\n }\n return message;\n}\n\nfunction summarizeError(err: unknown): string {\n if (hasStatus(err, 403)) {\n return 'Insufficient permissions for this operation';\n }\n if (err instanceof ApiError) {\n const msg = err.message.trim();\n const availableTypesIdx = msg.indexOf('Available types:');\n if (availableTypesIdx !== -1) {\n const head = msg.slice(0, availableTypesIdx).trim().replace(/\\.$/, '');\n return head ? `${head}.` : 'Request failed';\n }\n return msg.length > 240 ? `${msg.slice(0, 237)}...` : msg;\n }\n if (err instanceof Error) {\n // Name only, deliberately. A non-ApiError can still carry a message the\n // backend supplied, and this string is surfaced to the operator — see the\n // \"backend returned sensitive detail\" tests. Do not widen this.\n return err.name || 'Error';\n }\n return typeof err;\n}\n\nfunction hasStatus(err: unknown, status: number): boolean {\n if (typeof err === 'object' && err !== null) {\n const candidate = err as { status?: unknown; statusCode?: unknown };\n if (candidate.status === status || candidate.statusCode === status) return true;\n }\n const message = err instanceof Error ? err.message : typeof err === 'string' ? err : '';\n return message.includes(String(status));\n}\n\nexport async function runWorkspaceScript(\n client: GravityRailWorkspaceClient,\n build: (workspace: WorkspaceBuilder) => void | Promise<void>,\n mode = 'plan'\n): Promise<ResourceSummary | void> {\n const workspace = new WorkspaceBuilder(client);\n await build(workspace);\n if (mode === 'plan') return workspace.plan();\n if (mode === 'preview') return workspace.preview();\n if (mode === 'apply') return workspace.apply();\n throw new Error(`Unknown mode '${mode}'. Use plan, preview, or apply.`);\n}\n","/**\n * Generated by Orval, grouped by scripts/types-codegen/group_generated.ts\n * (group map from emit_openapi.py). Do not edit manually.\n * Group: event_type\n */\n\n\n/**\n * Scope-class capabilities that unlock event types in the feed.\n *\n * These are existing platform scope strings. A grant carries scope-class\n * capabilities and nothing finer, and they decide which event rows a viewer\n * may read. The workspace schemas' second tier (bitwise role x data-type\n * maps, folder ACLs, object-level grants) is never copied into the grants\n * projection: it applies live, per object, when a ref is hydrated into a name\n * (:mod:`lib.activity.ref_readers`).\n */\nexport type ActivityCapability = typeof ActivityCapability[keyof typeof ActivityCapability];\n\n\nexport const ActivityCapability = {\n 'assignments:read': 'assignments:read',\n 'chats:read': 'chats:read',\n 'journeys:read': 'journeys:read',\n 'members:read': 'members:read',\n 'operator:read': 'operator:read',\n 'org:read': 'org:read',\n 'phones:read': 'phones:read',\n 'workflows:read': 'workflows:read',\n 'workspace:read': 'workspace:read',\n} as const;\n\n/**\n * Every occurrence kind the spine records. Closed; grows by review.\n */\nexport type ActivityEventType = typeof ActivityEventType[keyof typeof ActivityEventType];\n\n\nexport const ActivityEventType = {\n membercreated: 'member.created',\n memberremoved: 'member.removed',\n memberrole_changed: 'member.role_changed',\n memberlabels_changed: 'member.labels_changed',\n memberattributes_changed: 'member.attributes_changed',\n importstarted: 'import.started',\n importcompleted: 'import.completed',\n assignmentstarted: 'assignment.started',\n assignmentconcluded: 'assignment.concluded',\n journeyenrolled: 'journey.enrolled',\n journeyunenrolled: 'journey.unenrolled',\n journeycompleted: 'journey.completed',\n journeystep_transitioned: 'journey.step_transitioned',\n journeyactivated: 'journey.activated',\n chatstarted: 'chat.started',\n chatawaiting_human: 'chat.awaiting_human',\n chathuman_replied: 'chat.human_replied',\n chatcall_ended: 'chat.call_ended',\n escalationopened: 'escalation.opened',\n escalationresolved: 'escalation.resolved',\n callstarted: 'call.started',\n callcompleted: 'call.completed',\n callmissed: 'call.missed',\n presencewent_online: 'presence.went_online',\n presencewent_offline: 'presence.went_offline',\n operator_groupmember_added: 'operator_group.member_added',\n operator_groupmember_removed: 'operator_group.member_removed',\n voicemailreceived: 'voicemail.received',\n voicemaillistened: 'voicemail.listened',\n routinestarted: 'routine.started',\n routinecompleted: 'routine.completed',\n routinefailed: 'routine.failed',\n workflowpublished: 'workflow.published',\n subscriptionstarted: 'subscription.started',\n subscriptionupdated: 'subscription.updated',\n subscriptioncanceled: 'subscription.canceled',\n member_subscriptionstarted: 'member_subscription.started',\n member_subscriptioncanceled: 'member_subscription.canceled',\n purchasecompleted: 'purchase.completed',\n phone_numberprovisioned: 'phone_number.provisioned',\n phone_numberarchived: 'phone_number.archived',\n domainlinked: 'domain.linked',\n domainverified: 'domain.verified',\n configupdated: 'config.updated',\n} as const;\n\n/**\n * The visibility class an event is *born* with.\n *\n * ``ACCOUNT_PRIVATE`` is structural privacy: such an event is only ever\n * visible to the account named in ``account_uuid``, regardless of any scope a\n * viewer holds, and it never enters a workspace or org rollup. This is how\n * manager and agent-job chat privacy survives aggregation.\n */\nexport type ActivityVisibility = typeof ActivityVisibility[keyof typeof ActivityVisibility];\n\n\nexport const ActivityVisibility = {\n workspace: 'workspace',\n org: 'org',\n account_private: 'account_private',\n} as const;\n","/**\n * Generated by Orval, grouped by scripts/types-codegen/group_generated.ts\n * (group map from emit_openapi.py). Do not edit manually.\n * Group: ref\n */\n\n\n/**\n * Who or what caused an occurrence.\n *\n * ``SYSTEM`` is the honest answer when a chokepoint serves a caller with no\n * session — a Temporal schedule, a backfill, a webhook with no member\n * attribution. It is never a placeholder for \"did not bother to look\".\n */\nexport type ActorKind = typeof ActorKind[keyof typeof ActorKind];\n\n\nexport const ActorKind = {\n account: 'account',\n agent: 'agent',\n connection: 'connection',\n member: 'member',\n org_account: 'org_account',\n system: 'system',\n} as const;\n\n/**\n * Closed vocabulary of entity kinds a spine ref may name.\n *\n * Adding a kind is a code change with review — the same gate the event-type\n * vocabulary gets. Kinds name *entities*, never fields or values.\n */\nexport type EntityKind = typeof EntityKind[keyof typeof EntityKind];\n\n\nexport const EntityKind = {\n account: 'account',\n org: 'org',\n org_account: 'org_account',\n workspace: 'workspace',\n agent: 'agent',\n connection: 'connection',\n member: 'member',\n assignment: 'assignment',\n journey: 'journey',\n journey_step: 'journey_step',\n routine: 'routine',\n task: 'task',\n workflow: 'workflow',\n workflow_revision: 'workflow_revision',\n call: 'call',\n chat: 'chat',\n escalation: 'escalation',\n inbox: 'inbox',\n phone_number: 'phone_number',\n voicemail: 'voicemail',\n domain: 'domain',\n import: 'import',\n invoice: 'invoice',\n member_label: 'member_label',\n member_subscription: 'member_subscription',\n operator_group: 'operator_group',\n purchase: 'purchase',\n subscription: 'subscription',\n data_type: 'data_type',\n workspace_config: 'workspace_config',\n} as const;\n\n/**\n * A typed reference to one entity, with the scope chain it was observed in.\n *\n * Stored in ``activity_events.refs`` (and in ``activity_open_items``'s\n * ``responsible``) as JSON. Never used for a join: the activities database\n * holds no foreign keys, and a ref whose entity was deleted renders as its\n * kind — the same behavior as a ref the viewer may not resolve.\n *\n * **Two names for one field, on purpose.** This class is a *storage* shape —\n * the JSON the recorder writes and the drain reads — and, since the serving\n * API returns typed detail payloads, it is also a *wire* shape. Storage wants\n * the snake_case names already committed to rows; the API contract requires\n * lowerCamelCase keys (root ``CLAUDE.md``). A serialization-only alias gives\n * both without a mapping layer: validation still reads ``workspace_uuid``, so\n * every stored row and every emitter is untouched, while ``by_alias=True`` —\n * which FastAPI uses to serialize a response, and which nothing on the write\n * path passes — emits ``workspaceUuid``.\n * :class:`lib.activity.details.ActivityDetailBase` carries the same config for\n * the same reason.\n */\nexport interface EntityRef {\n kind: EntityKind;\n uuid: string;\n workspaceUuid?: string | null;\n orgUuid?: string | null;\n accountUuid?: string | null;\n}\n"],"mappings":"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","names":[]}