@elevasis/sdk 1.24.0 → 1.26.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/cli.cjs +875 -834
- package/dist/index.d.ts +4857 -4547
- package/dist/index.js +564 -2338
- package/dist/node/index.d.ts +693 -1356
- package/dist/node/index.js +1 -1
- package/dist/test-utils/index.d.ts +4186 -4139
- package/dist/test-utils/index.js +694 -2769
- package/dist/types/worker/adapters/clickup.d.ts +22 -0
- package/dist/types/worker/adapters/index.d.ts +1 -0
- package/dist/types/worker/index.d.ts +3 -2
- package/dist/types/worker/platform.d.ts +2 -2
- package/dist/worker/index.js +427 -2803
- package/package.json +2 -2
- package/reference/_navigation.md +11 -1
- package/reference/_reference-manifest.json +70 -0
- package/reference/claude-config/rules/organization-model.md +12 -1
- package/reference/claude-config/rules/organization-os.md +12 -1
- package/reference/claude-config/skills/om/SKILL.md +13 -5
- package/reference/claude-config/skills/om/operations/codify-level-a.md +109 -100
- package/reference/claude-config/skills/om/operations/customers.md +10 -6
- package/reference/claude-config/skills/om/operations/features.md +7 -3
- package/reference/claude-config/skills/om/operations/goals.md +10 -6
- package/reference/claude-config/skills/om/operations/identity.md +8 -5
- package/reference/claude-config/skills/om/operations/labels.md +17 -1
- package/reference/claude-config/skills/om/operations/offerings.md +11 -7
- package/reference/claude-config/skills/om/operations/roles.md +11 -7
- package/reference/claude-config/skills/om/operations/techStack.md +10 -2
- package/reference/claude-config/sync-notes/2026-05-20-om-define-helpers.md +32 -0
- package/reference/claude-config/sync-notes/2026-05-22-access-model-and-right-panel.md +43 -0
- package/reference/claude-config/sync-notes/2026-05-22-lead-gen-tenant-config.md +40 -0
- package/reference/claude-config/sync-notes/2026-05-22-org-model-multi-file-split.md +61 -0
- package/reference/cli-management.mdx +539 -0
- package/reference/cli.mdx +579 -808
- package/reference/concepts.mdx +134 -146
- package/reference/deployment/api.mdx +296 -297
- package/reference/deployment/command-center.mdx +208 -209
- package/reference/deployment/index.mdx +194 -195
- package/reference/deployment/provided-features.mdx +110 -107
- package/reference/deployment/ui-execution.mdx +249 -250
- package/reference/framework/index.mdx +111 -195
- package/reference/framework/resource-documentation.mdx +90 -0
- package/reference/framework/tutorial-system.mdx +135 -135
- package/reference/getting-started.mdx +141 -142
- package/reference/index.mdx +95 -106
- package/reference/packages/ui/src/auth/README.md +6 -6
- package/reference/platform-tools/adapters-integration.mdx +300 -301
- package/reference/platform-tools/adapters-platform.mdx +552 -553
- package/reference/platform-tools/index.mdx +216 -217
- package/reference/platform-tools/type-safety.mdx +82 -82
- package/reference/resources/index.mdx +348 -349
- package/reference/resources/patterns.mdx +446 -449
- package/reference/resources/types.mdx +115 -116
- package/reference/roadmap.mdx +164 -165
- package/reference/rules/organization-model.md +14 -0
- package/reference/runtime.mdx +172 -173
- package/reference/scaffold/operations/propagation-pipeline.md +1 -1
- package/reference/scaffold/recipes/customize-crm-actions.md +45 -46
- package/reference/scaffold/recipes/extend-crm.md +253 -255
- package/reference/scaffold/recipes/extend-lead-gen.md +130 -77
- package/reference/scaffold/recipes/index.md +43 -44
- package/reference/scaffold/reference/contracts.md +1275 -1432
- package/reference/scaffold/reference/glossary.md +8 -6
- package/reference/scaffold/ui/feature-flags-and-gating.md +59 -46
- package/reference/scaffold/ui/feature-shell.mdx +11 -11
- package/reference/scaffold/ui/recipes.md +24 -24
- package/reference/troubleshooting.mdx +222 -223
package/dist/test-utils/index.js
CHANGED
|
@@ -3938,6 +3938,12 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
3938
3938
|
}
|
|
3939
3939
|
return combined;
|
|
3940
3940
|
};
|
|
3941
|
+
|
|
3942
|
+
// ../core/src/execution/engine/workflow/types.ts
|
|
3943
|
+
var StepType = {
|
|
3944
|
+
LINEAR: "linear",
|
|
3945
|
+
CONDITIONAL: "conditional"
|
|
3946
|
+
};
|
|
3941
3947
|
function errorToString(error) {
|
|
3942
3948
|
if (error instanceof ZodError) {
|
|
3943
3949
|
return JSON.stringify(error.issues, null, 2);
|
|
@@ -3959,6 +3965,26 @@ function getErrorDetails(error) {
|
|
|
3959
3965
|
return details;
|
|
3960
3966
|
}
|
|
3961
3967
|
|
|
3968
|
+
// ../core/src/execution/engine/workflow/log-truncate.ts
|
|
3969
|
+
var LOG_STRING_TRUNCATE_LIMIT = 200;
|
|
3970
|
+
function truncateForLogging(value) {
|
|
3971
|
+
if (value === null || value === void 0) return value;
|
|
3972
|
+
if (typeof value === "string") {
|
|
3973
|
+
return value.length > LOG_STRING_TRUNCATE_LIMIT ? value.slice(0, LOG_STRING_TRUNCATE_LIMIT) + `\u2026 [${value.length} chars]` : value;
|
|
3974
|
+
}
|
|
3975
|
+
if (Array.isArray(value)) {
|
|
3976
|
+
return value.map(truncateForLogging);
|
|
3977
|
+
}
|
|
3978
|
+
if (typeof value === "object") {
|
|
3979
|
+
const result = {};
|
|
3980
|
+
for (const [k2, v2] of Object.entries(value)) {
|
|
3981
|
+
result[k2] = truncateForLogging(v2);
|
|
3982
|
+
}
|
|
3983
|
+
return result;
|
|
3984
|
+
}
|
|
3985
|
+
return value;
|
|
3986
|
+
}
|
|
3987
|
+
|
|
3962
3988
|
// ../core/src/execution/engine/base/errors.ts
|
|
3963
3989
|
var ExecutionError = class extends Error {
|
|
3964
3990
|
/**
|
|
@@ -3999,6 +4025,305 @@ var ExecutionError = class extends Error {
|
|
|
3999
4025
|
}
|
|
4000
4026
|
};
|
|
4001
4027
|
|
|
4028
|
+
// ../core/src/execution/engine/workflow/errors.ts
|
|
4029
|
+
var WorkflowStepError = class extends ExecutionError {
|
|
4030
|
+
type = "workflow_step_error";
|
|
4031
|
+
severity = "critical";
|
|
4032
|
+
category = "workflow";
|
|
4033
|
+
constructor(message, context) {
|
|
4034
|
+
super(message, context);
|
|
4035
|
+
}
|
|
4036
|
+
};
|
|
4037
|
+
var WorkflowValidationError = class extends ExecutionError {
|
|
4038
|
+
type = "workflow_validation_error";
|
|
4039
|
+
severity = "info";
|
|
4040
|
+
category = "validation";
|
|
4041
|
+
constructor(message, context) {
|
|
4042
|
+
super(message, context);
|
|
4043
|
+
}
|
|
4044
|
+
};
|
|
4045
|
+
|
|
4046
|
+
// ../core/src/execution/engine/workflow/utils.ts
|
|
4047
|
+
function validateEntryPoint(steps, entryPoint) {
|
|
4048
|
+
if (!(entryPoint in steps)) {
|
|
4049
|
+
throw new WorkflowValidationError(`Entry point step '${entryPoint}' not found in workflow`, {
|
|
4050
|
+
entryPoint
|
|
4051
|
+
});
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
function findTerminalSteps(steps) {
|
|
4055
|
+
return Object.values(steps).filter((step) => step.next === null);
|
|
4056
|
+
}
|
|
4057
|
+
function validateTerminalSteps(steps, workflowId) {
|
|
4058
|
+
const terminalSteps = findTerminalSteps(steps);
|
|
4059
|
+
if (terminalSteps.length === 0) {
|
|
4060
|
+
throw new WorkflowValidationError(`Workflow '${workflowId}' must have at least one terminal step (next: null)`, {
|
|
4061
|
+
workflowId
|
|
4062
|
+
});
|
|
4063
|
+
}
|
|
4064
|
+
}
|
|
4065
|
+
function validateStepReferences(steps) {
|
|
4066
|
+
for (const [id, step] of Object.entries(steps)) {
|
|
4067
|
+
if (step.next === null) {
|
|
4068
|
+
continue;
|
|
4069
|
+
}
|
|
4070
|
+
if (step.next.type === StepType.LINEAR) {
|
|
4071
|
+
if (!(step.next.target in steps)) {
|
|
4072
|
+
throw new WorkflowValidationError(`Step '${id}' references non-existent target '${step.next.target}'`, {
|
|
4073
|
+
stepId: id,
|
|
4074
|
+
target: step.next.target
|
|
4075
|
+
});
|
|
4076
|
+
}
|
|
4077
|
+
} else if (step.next.type === StepType.CONDITIONAL) {
|
|
4078
|
+
const targets = [...step.next.routes.map((r2) => r2.target), step.next.default];
|
|
4079
|
+
for (const target of targets) {
|
|
4080
|
+
if (!(target in steps)) {
|
|
4081
|
+
throw new WorkflowValidationError(`Step '${id}' references non-existent target '${target}'`, {
|
|
4082
|
+
stepId: id,
|
|
4083
|
+
target
|
|
4084
|
+
});
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
4087
|
+
}
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
function detectCycle(visited, executionPath, currentStepId) {
|
|
4091
|
+
if (visited.has(currentStepId)) {
|
|
4092
|
+
const cycle = executionPath.slice(executionPath.indexOf(currentStepId));
|
|
4093
|
+
throw new WorkflowStepError(`Cycle detected in workflow: ${cycle.join(" -> ")} -> ${currentStepId}`, {
|
|
4094
|
+
stepId: currentStepId,
|
|
4095
|
+
cycle: [...cycle, currentStepId]
|
|
4096
|
+
});
|
|
4097
|
+
}
|
|
4098
|
+
}
|
|
4099
|
+
function validateTerminalOutput(stepId, output, outputSchema) {
|
|
4100
|
+
if (!outputSchema) {
|
|
4101
|
+
return;
|
|
4102
|
+
}
|
|
4103
|
+
try {
|
|
4104
|
+
outputSchema.parse(output);
|
|
4105
|
+
} catch (error) {
|
|
4106
|
+
throw new WorkflowValidationError(
|
|
4107
|
+
`Terminal step '${stepId}' produced invalid output: ${error instanceof Error ? error.message : String(error)}`,
|
|
4108
|
+
{ stepId, validationError: error instanceof Error ? error.message : String(error) }
|
|
4109
|
+
);
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4112
|
+
async function determineNextStep(step, currentData, context) {
|
|
4113
|
+
const { next } = step;
|
|
4114
|
+
if (next === null) {
|
|
4115
|
+
return null;
|
|
4116
|
+
}
|
|
4117
|
+
if (next.type === StepType.LINEAR) {
|
|
4118
|
+
return next.target;
|
|
4119
|
+
}
|
|
4120
|
+
if (next.type === StepType.CONDITIONAL) {
|
|
4121
|
+
return evaluateConditionalRoutes(step.id, next, currentData, context);
|
|
4122
|
+
}
|
|
4123
|
+
throw new WorkflowStepError(`Unknown next configuration type in step ${step.id}`, {
|
|
4124
|
+
stepId: step.id
|
|
4125
|
+
});
|
|
4126
|
+
}
|
|
4127
|
+
async function evaluateConditionalRoutes(stepId, next, currentData, context) {
|
|
4128
|
+
for (const route of next.routes) {
|
|
4129
|
+
try {
|
|
4130
|
+
if (route.condition(currentData)) {
|
|
4131
|
+
context.logger.debug(`Conditional route taken: ${stepId} -> ${route.target}`, {
|
|
4132
|
+
type: "workflow",
|
|
4133
|
+
contextType: "conditional-route",
|
|
4134
|
+
stepId,
|
|
4135
|
+
target: route.target
|
|
4136
|
+
});
|
|
4137
|
+
return route.target;
|
|
4138
|
+
}
|
|
4139
|
+
} catch (error) {
|
|
4140
|
+
context.logger.warn(`Error evaluating condition in step ${stepId}: ${error}`, {
|
|
4141
|
+
type: "workflow",
|
|
4142
|
+
contextType: "conditional-route",
|
|
4143
|
+
stepId,
|
|
4144
|
+
target: "",
|
|
4145
|
+
error: errorToString(error)
|
|
4146
|
+
});
|
|
4147
|
+
}
|
|
4148
|
+
}
|
|
4149
|
+
context.logger.debug(`Using default route: ${stepId} -> ${next.default}`, {
|
|
4150
|
+
type: "workflow",
|
|
4151
|
+
contextType: "conditional-route",
|
|
4152
|
+
stepId,
|
|
4153
|
+
target: next.default
|
|
4154
|
+
});
|
|
4155
|
+
return next.default;
|
|
4156
|
+
}
|
|
4157
|
+
function logWorkflowStart(context, workflowId, workflowName) {
|
|
4158
|
+
context.logger.info(`Executing workflow: ${workflowId}`, {
|
|
4159
|
+
type: "workflow",
|
|
4160
|
+
contextType: "workflow-execution",
|
|
4161
|
+
executionId: context.executionId,
|
|
4162
|
+
workflowId,
|
|
4163
|
+
workflowName,
|
|
4164
|
+
organizationId: context.organizationId
|
|
4165
|
+
});
|
|
4166
|
+
}
|
|
4167
|
+
function logWorkflowSuccess(context, workflowId, executionPath) {
|
|
4168
|
+
context.logger.info(`Workflow completed successfully: ${workflowId}`, {
|
|
4169
|
+
type: "workflow",
|
|
4170
|
+
contextType: "workflow-execution",
|
|
4171
|
+
executionId: context.executionId,
|
|
4172
|
+
workflowId,
|
|
4173
|
+
organizationId: context.organizationId,
|
|
4174
|
+
executionPath
|
|
4175
|
+
});
|
|
4176
|
+
}
|
|
4177
|
+
function logWorkflowFailure(context, workflowId, error) {
|
|
4178
|
+
context.logger.error(`Execution failed: workflow/${workflowId}`, {
|
|
4179
|
+
type: "workflow",
|
|
4180
|
+
contextType: "workflow-failure",
|
|
4181
|
+
executionId: context.executionId,
|
|
4182
|
+
workflowId,
|
|
4183
|
+
error: errorToString(error)
|
|
4184
|
+
});
|
|
4185
|
+
}
|
|
4186
|
+
function logStepStart(context, stepId, stepName, input, startTime) {
|
|
4187
|
+
context.logger.info(`Step started: ${stepName}`, {
|
|
4188
|
+
type: "workflow",
|
|
4189
|
+
contextType: "step-started",
|
|
4190
|
+
stepId,
|
|
4191
|
+
stepStatus: "started",
|
|
4192
|
+
input: truncateForLogging(input),
|
|
4193
|
+
startTime
|
|
4194
|
+
});
|
|
4195
|
+
}
|
|
4196
|
+
function logStepSuccess(context, stepId, stepName, output, duration, isTerminal, startTime, endTime) {
|
|
4197
|
+
context.logger.info(`Step completed: ${stepName}`, {
|
|
4198
|
+
type: "workflow",
|
|
4199
|
+
contextType: "step-completed",
|
|
4200
|
+
stepId,
|
|
4201
|
+
stepStatus: "completed",
|
|
4202
|
+
output: truncateForLogging(output),
|
|
4203
|
+
duration,
|
|
4204
|
+
isTerminal,
|
|
4205
|
+
startTime,
|
|
4206
|
+
endTime
|
|
4207
|
+
});
|
|
4208
|
+
}
|
|
4209
|
+
function logStepFailure(context, stepId, stepName, error, duration, startTime, endTime) {
|
|
4210
|
+
context.logger.error(`Step failed: ${stepName}`, {
|
|
4211
|
+
type: "workflow",
|
|
4212
|
+
contextType: "step-failed",
|
|
4213
|
+
stepId,
|
|
4214
|
+
stepStatus: "failed",
|
|
4215
|
+
error: errorToString(error),
|
|
4216
|
+
duration,
|
|
4217
|
+
startTime,
|
|
4218
|
+
endTime
|
|
4219
|
+
});
|
|
4220
|
+
}
|
|
4221
|
+
function logExecutionPath(context, executionPath) {
|
|
4222
|
+
context.logger.info(`Workflow completed. Execution path: ${executionPath.join(" -> ")}`, {
|
|
4223
|
+
type: "workflow",
|
|
4224
|
+
contextType: "execution-path",
|
|
4225
|
+
executionPath
|
|
4226
|
+
});
|
|
4227
|
+
}
|
|
4228
|
+
|
|
4229
|
+
// ../core/src/execution/engine/workflow/workflow.ts
|
|
4230
|
+
var Workflow = class {
|
|
4231
|
+
config;
|
|
4232
|
+
contract;
|
|
4233
|
+
steps;
|
|
4234
|
+
entryPoint;
|
|
4235
|
+
// Derived properties (computed from definition)
|
|
4236
|
+
shouldGenerateOutput;
|
|
4237
|
+
/**
|
|
4238
|
+
* Create a new workflow instance from definition
|
|
4239
|
+
*
|
|
4240
|
+
* @param definition - Workflow definition with config, contract, steps, and entryPoint
|
|
4241
|
+
*/
|
|
4242
|
+
constructor(definition) {
|
|
4243
|
+
this.config = definition.config;
|
|
4244
|
+
this.contract = definition.contract;
|
|
4245
|
+
this.steps = definition.steps;
|
|
4246
|
+
this.entryPoint = definition.entryPoint;
|
|
4247
|
+
this.shouldGenerateOutput = !!definition.contract.outputSchema;
|
|
4248
|
+
validateEntryPoint(this.steps, this.entryPoint);
|
|
4249
|
+
validateTerminalSteps(this.steps, this.config.resourceId);
|
|
4250
|
+
validateStepReferences(this.steps);
|
|
4251
|
+
}
|
|
4252
|
+
/**
|
|
4253
|
+
* Execute the workflow with graph-based flow control
|
|
4254
|
+
* Context is required for execution tracking, logging, and organization isolation
|
|
4255
|
+
* @returns Validated output matching contract.outputSchema, or null if no output schema
|
|
4256
|
+
*/
|
|
4257
|
+
async execute(input, context) {
|
|
4258
|
+
logWorkflowStart(context, this.config.resourceId, this.config.name);
|
|
4259
|
+
try {
|
|
4260
|
+
const validated = this.contract.inputSchema.parse(input);
|
|
4261
|
+
const visited = /* @__PURE__ */ new Set();
|
|
4262
|
+
const executionPath = [];
|
|
4263
|
+
let currentData = validated;
|
|
4264
|
+
let currentStepId = this.entryPoint;
|
|
4265
|
+
while (currentStepId !== null) {
|
|
4266
|
+
detectCycle(visited, executionPath, currentStepId);
|
|
4267
|
+
visited.add(currentStepId);
|
|
4268
|
+
executionPath.push(currentStepId);
|
|
4269
|
+
const step = this.steps[currentStepId];
|
|
4270
|
+
if (!step) {
|
|
4271
|
+
throw new WorkflowStepError(`Step '${currentStepId}' not found in workflow`, {
|
|
4272
|
+
stepId: currentStepId,
|
|
4273
|
+
workflowId: this.config.resourceId,
|
|
4274
|
+
executionId: context.executionId,
|
|
4275
|
+
organizationId: context.organizationId,
|
|
4276
|
+
executionPath
|
|
4277
|
+
});
|
|
4278
|
+
}
|
|
4279
|
+
const stepStartTime = Date.now();
|
|
4280
|
+
logStepStart(context, step.id, step.name, currentData, stepStartTime);
|
|
4281
|
+
try {
|
|
4282
|
+
const validatedInput = step.inputSchema.parse(currentData);
|
|
4283
|
+
const rawOutput = await step.handler(validatedInput, context);
|
|
4284
|
+
currentData = step.outputSchema.parse(rawOutput);
|
|
4285
|
+
if (step.next === null && this.shouldGenerateOutput) {
|
|
4286
|
+
validateTerminalOutput(step.id, currentData, this.contract.outputSchema);
|
|
4287
|
+
}
|
|
4288
|
+
const stepEndTime = Date.now();
|
|
4289
|
+
const duration = stepEndTime - stepStartTime;
|
|
4290
|
+
logStepSuccess(
|
|
4291
|
+
context,
|
|
4292
|
+
step.id,
|
|
4293
|
+
step.name,
|
|
4294
|
+
currentData,
|
|
4295
|
+
duration,
|
|
4296
|
+
step.next === null,
|
|
4297
|
+
stepStartTime,
|
|
4298
|
+
stepEndTime
|
|
4299
|
+
);
|
|
4300
|
+
currentStepId = await determineNextStep(step, currentData, context);
|
|
4301
|
+
} catch (error) {
|
|
4302
|
+
const stepEndTime = Date.now();
|
|
4303
|
+
const duration = stepEndTime - stepStartTime;
|
|
4304
|
+
logStepFailure(context, step.id, step.name, error, duration, stepStartTime, stepEndTime);
|
|
4305
|
+
throw new WorkflowStepError(`Step failed [${step.id}:${step.name}]: ${errorToString(error)}`, {
|
|
4306
|
+
stepId: step.id,
|
|
4307
|
+
stepName: step.name,
|
|
4308
|
+
workflowId: this.config.resourceId,
|
|
4309
|
+
executionId: context.executionId,
|
|
4310
|
+
duration: stepEndTime - stepStartTime
|
|
4311
|
+
});
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
4314
|
+
logExecutionPath(context, executionPath);
|
|
4315
|
+
logWorkflowSuccess(context, this.config.resourceId, executionPath);
|
|
4316
|
+
if (!this.shouldGenerateOutput) {
|
|
4317
|
+
return null;
|
|
4318
|
+
}
|
|
4319
|
+
return currentData;
|
|
4320
|
+
} catch (error) {
|
|
4321
|
+
logWorkflowFailure(context, this.config.resourceId, error);
|
|
4322
|
+
throw error;
|
|
4323
|
+
}
|
|
4324
|
+
}
|
|
4325
|
+
};
|
|
4326
|
+
|
|
4002
4327
|
// ../core/src/execution/engine/agent/observability/logging.ts
|
|
4003
4328
|
function createAgentLogger(logger, agentId, sessionId) {
|
|
4004
4329
|
return {
|
|
@@ -5532,8 +5857,8 @@ async function processMemory(memoryManager, response, logger, iteration) {
|
|
|
5532
5857
|
continue;
|
|
5533
5858
|
}
|
|
5534
5859
|
const startTime = Date.now();
|
|
5535
|
-
const
|
|
5536
|
-
memoryManager.set(key,
|
|
5860
|
+
const stringValue = typeof content === "string" ? content : JSON.stringify(content);
|
|
5861
|
+
memoryManager.set(key, stringValue);
|
|
5537
5862
|
const endTime = Date.now();
|
|
5538
5863
|
logger.action("memory-set", `Set: ${key}`, iteration, startTime, endTime, endTime - startTime);
|
|
5539
5864
|
}
|
|
@@ -6598,7 +6923,7 @@ var LabelSchema = z.string().trim().min(1).max(120);
|
|
|
6598
6923
|
var DescriptionSchema = z.string().trim().min(1).max(2e3);
|
|
6599
6924
|
var ColorTokenSchema = z.string().trim().min(1).max(50);
|
|
6600
6925
|
var IconNameSchema = OrganizationModelIconTokenSchema;
|
|
6601
|
-
|
|
6926
|
+
z.string().trim().startsWith("/").max(300);
|
|
6602
6927
|
var ReferenceIdsSchema = z.array(ModelIdSchema).default([]);
|
|
6603
6928
|
var DisplayMetadataSchema = z.object({
|
|
6604
6929
|
label: LabelSchema,
|
|
@@ -6637,190 +6962,25 @@ DisplayMetadataSchema.extend({
|
|
|
6637
6962
|
techStack: TechStackEntrySchema.optional()
|
|
6638
6963
|
});
|
|
6639
6964
|
|
|
6640
|
-
// ../core/src/organization-model/
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
}
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
ownedBySystemId: ModelIdSchema.meta({ ref: "system" }),
|
|
6656
|
-
table: z.string().trim().min(1).max(255).optional(),
|
|
6657
|
-
rowSchema: ModelIdSchema.optional(),
|
|
6658
|
-
stateCatalogId: ModelIdSchema.optional(),
|
|
6659
|
-
links: z.array(EntityLinkSchema).optional()
|
|
6660
|
-
});
|
|
6661
|
-
var EntitiesDomainSchema = z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
6662
|
-
message: "Each entity entry id must match its map key"
|
|
6663
|
-
}).default({});
|
|
6664
|
-
var ENTITY_ENTRY_INPUTS = [
|
|
6665
|
-
{
|
|
6666
|
-
id: "crm.deal",
|
|
6667
|
-
order: 10,
|
|
6668
|
-
label: "Deal",
|
|
6669
|
-
description: "A CRM opportunity or sales pipeline record.",
|
|
6670
|
-
ownedBySystemId: "sales.crm",
|
|
6671
|
-
table: "crm_deals",
|
|
6672
|
-
stateCatalogId: "crm.pipeline",
|
|
6673
|
-
links: [{ toEntity: "crm.contact", kind: "has-many", via: "deal_contacts", label: "contacts" }]
|
|
6674
|
-
},
|
|
6675
|
-
{
|
|
6676
|
-
id: "crm.contact",
|
|
6677
|
-
order: 20,
|
|
6678
|
-
label: "CRM Contact",
|
|
6679
|
-
description: "A person associated with a CRM relationship or deal.",
|
|
6680
|
-
ownedBySystemId: "sales.crm",
|
|
6681
|
-
table: "crm_contacts"
|
|
6682
|
-
},
|
|
6683
|
-
{
|
|
6684
|
-
id: "leadgen.list",
|
|
6685
|
-
order: 30,
|
|
6686
|
-
label: "Lead List",
|
|
6687
|
-
description: "A prospecting list that groups companies and contacts for acquisition workflows.",
|
|
6688
|
-
ownedBySystemId: "sales.lead-gen",
|
|
6689
|
-
table: "acq_lists",
|
|
6690
|
-
links: [
|
|
6691
|
-
{ toEntity: "leadgen.company", kind: "has-many", via: "acq_list_companies", label: "companies" },
|
|
6692
|
-
{ toEntity: "leadgen.contact", kind: "has-many", via: "acq_list_members", label: "contacts" }
|
|
6693
|
-
]
|
|
6694
|
-
},
|
|
6695
|
-
{
|
|
6696
|
-
id: "leadgen.company",
|
|
6697
|
-
order: 40,
|
|
6698
|
-
label: "Lead Company",
|
|
6699
|
-
description: "A company record sourced, enriched, and qualified during prospecting.",
|
|
6700
|
-
ownedBySystemId: "sales.lead-gen",
|
|
6701
|
-
table: "acq_list_companies",
|
|
6702
|
-
stateCatalogId: "lead-gen.company",
|
|
6703
|
-
links: [
|
|
6704
|
-
{ toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
|
|
6705
|
-
{ toEntity: "leadgen.contact", kind: "has-many", via: "company_id", label: "contacts" }
|
|
6706
|
-
]
|
|
6707
|
-
},
|
|
6708
|
-
{
|
|
6709
|
-
id: "leadgen.contact",
|
|
6710
|
-
order: 50,
|
|
6711
|
-
label: "Lead Contact",
|
|
6712
|
-
description: "A prospect contact discovered or enriched during lead generation.",
|
|
6713
|
-
ownedBySystemId: "sales.lead-gen",
|
|
6714
|
-
table: "acq_list_members",
|
|
6715
|
-
stateCatalogId: "lead-gen.contact",
|
|
6716
|
-
links: [
|
|
6717
|
-
{ toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
|
|
6718
|
-
{ toEntity: "leadgen.company", kind: "belongs-to", via: "company_id", label: "company" }
|
|
6719
|
-
]
|
|
6720
|
-
},
|
|
6721
|
-
{
|
|
6722
|
-
id: "delivery.project",
|
|
6723
|
-
order: 60,
|
|
6724
|
-
label: "Project",
|
|
6725
|
-
description: "A client delivery project.",
|
|
6726
|
-
ownedBySystemId: "projects",
|
|
6727
|
-
table: "projects",
|
|
6728
|
-
links: [
|
|
6729
|
-
{ toEntity: "delivery.milestone", kind: "has-many", via: "project_id", label: "milestones" },
|
|
6730
|
-
{ toEntity: "delivery.task", kind: "has-many", via: "project_id", label: "tasks" }
|
|
6731
|
-
]
|
|
6732
|
-
},
|
|
6733
|
-
{
|
|
6734
|
-
id: "delivery.milestone",
|
|
6735
|
-
order: 70,
|
|
6736
|
-
label: "Milestone",
|
|
6737
|
-
description: "A delivery checkpoint within a project.",
|
|
6738
|
-
ownedBySystemId: "projects",
|
|
6739
|
-
table: "project_milestones",
|
|
6740
|
-
links: [
|
|
6741
|
-
{ toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
|
|
6742
|
-
{ toEntity: "delivery.task", kind: "has-many", via: "milestone_id", label: "tasks" }
|
|
6743
|
-
]
|
|
6744
|
-
},
|
|
6745
|
-
{
|
|
6746
|
-
id: "delivery.task",
|
|
6747
|
-
order: 80,
|
|
6748
|
-
label: "Task",
|
|
6749
|
-
description: "A delivery task that can move through the task status catalog.",
|
|
6750
|
-
ownedBySystemId: "projects",
|
|
6751
|
-
table: "project_tasks",
|
|
6752
|
-
stateCatalogId: "delivery.task",
|
|
6753
|
-
links: [
|
|
6754
|
-
{ toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
|
|
6755
|
-
{ toEntity: "delivery.milestone", kind: "belongs-to", via: "milestone_id", label: "milestone" }
|
|
6756
|
-
]
|
|
6965
|
+
// ../core/src/organization-model/helpers.ts
|
|
6966
|
+
function childSystemsOf(system) {
|
|
6967
|
+
return system.systems ?? system.subsystems ?? {};
|
|
6968
|
+
}
|
|
6969
|
+
function listAllSystems(model) {
|
|
6970
|
+
const results = [];
|
|
6971
|
+
function walk(map2, prefix) {
|
|
6972
|
+
for (const [localId, system] of Object.entries(map2)) {
|
|
6973
|
+
const fullPath = prefix ? `${prefix}.${localId}` : localId;
|
|
6974
|
+
results.push({ path: fullPath, system });
|
|
6975
|
+
const childSystems = childSystemsOf(system);
|
|
6976
|
+
if (Object.keys(childSystems).length > 0) {
|
|
6977
|
+
walk(childSystems, fullPath);
|
|
6978
|
+
}
|
|
6979
|
+
}
|
|
6757
6980
|
}
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
const parsed = EntitySchema.parse(entity);
|
|
6762
|
-
return [parsed.id, parsed];
|
|
6763
|
-
})
|
|
6764
|
-
);
|
|
6765
|
-
|
|
6766
|
-
// ../core/src/organization-model/domains/actions.ts
|
|
6767
|
-
var ActionResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
|
|
6768
|
-
z.enum(["slash-command", "mcp-tool", "api-endpoint", "script-execution"]).meta({ label: "Invocation kind" });
|
|
6769
|
-
var ActionIdSchema = ModelIdSchema;
|
|
6770
|
-
var ActionScopeSchema = z.union([
|
|
6771
|
-
z.literal("global"),
|
|
6772
|
-
z.object({
|
|
6773
|
-
domain: ModelIdSchema
|
|
6774
|
-
})
|
|
6775
|
-
]);
|
|
6776
|
-
var ActionRefSchema = z.object({
|
|
6777
|
-
actionId: ActionIdSchema.meta({ ref: "action" }),
|
|
6778
|
-
intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
|
|
6779
|
-
});
|
|
6780
|
-
var SlashCommandInvocationSchema = z.object({
|
|
6781
|
-
kind: z.literal("slash-command"),
|
|
6782
|
-
command: z.string().trim().min(1).max(200).regex(/^\/[^\s].*$/, "Slash commands must start with /"),
|
|
6783
|
-
toolFactory: ModelIdSchema.optional()
|
|
6784
|
-
});
|
|
6785
|
-
var McpToolInvocationSchema = z.object({
|
|
6786
|
-
kind: z.literal("mcp-tool"),
|
|
6787
|
-
server: ModelIdSchema,
|
|
6788
|
-
name: ModelIdSchema
|
|
6789
|
-
});
|
|
6790
|
-
var ApiEndpointInvocationSchema = z.object({
|
|
6791
|
-
kind: z.literal("api-endpoint"),
|
|
6792
|
-
method: z.enum(["GET", "POST", "PATCH", "DELETE"]).meta({ label: "HTTP method" }),
|
|
6793
|
-
path: z.string().trim().startsWith("/").max(500),
|
|
6794
|
-
requestSchema: ModelIdSchema.optional(),
|
|
6795
|
-
responseSchema: ModelIdSchema.optional()
|
|
6796
|
-
});
|
|
6797
|
-
var ScriptExecutionInvocationSchema = z.object({
|
|
6798
|
-
kind: z.literal("script-execution"),
|
|
6799
|
-
resourceId: ActionResourceIdSchema
|
|
6800
|
-
});
|
|
6801
|
-
var ActionInvocationSchema = z.discriminatedUnion("kind", [
|
|
6802
|
-
SlashCommandInvocationSchema,
|
|
6803
|
-
McpToolInvocationSchema,
|
|
6804
|
-
ApiEndpointInvocationSchema,
|
|
6805
|
-
ScriptExecutionInvocationSchema
|
|
6806
|
-
]);
|
|
6807
|
-
var ActionSchema = z.object({
|
|
6808
|
-
id: ActionIdSchema,
|
|
6809
|
-
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
6810
|
-
order: z.number(),
|
|
6811
|
-
label: LabelSchema,
|
|
6812
|
-
description: DescriptionSchema.optional(),
|
|
6813
|
-
scope: ActionScopeSchema.default("global"),
|
|
6814
|
-
resourceId: ActionResourceIdSchema.optional(),
|
|
6815
|
-
affects: z.array(EntityIdSchema.meta({ ref: "entity" })).optional(),
|
|
6816
|
-
invocations: z.array(ActionInvocationSchema).default([]),
|
|
6817
|
-
knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
|
|
6818
|
-
lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
|
|
6819
|
-
});
|
|
6820
|
-
var ActionsDomainSchema = z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
6821
|
-
message: "Each action entry id must match its map key"
|
|
6822
|
-
}).default({});
|
|
6823
|
-
var DEFAULT_ORGANIZATION_MODEL_ACTIONS = {};
|
|
6981
|
+
walk(model.systems, "");
|
|
6982
|
+
return results;
|
|
6983
|
+
}
|
|
6824
6984
|
|
|
6825
6985
|
// ../core/src/organization-model/domains/prospecting.ts
|
|
6826
6986
|
DisplayMetadataSchema.extend({
|
|
@@ -6874,2469 +7034,13 @@ DisplayMetadataSchema.extend({
|
|
|
6874
7034
|
id: ModelIdSchema,
|
|
6875
7035
|
steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
|
|
6876
7036
|
});
|
|
6877
|
-
var DTC_RECORD_COLUMNS = {
|
|
6878
|
-
populated: {
|
|
6879
|
-
company: [
|
|
6880
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
6881
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
6882
|
-
{ key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
|
|
6883
|
-
{ key: "apollo-industry", label: "Apollo industry", path: "company.category" },
|
|
6884
|
-
{ key: "location", label: "Location", path: "company.locationState" }
|
|
6885
|
-
]
|
|
6886
|
-
},
|
|
6887
|
-
crawled: {
|
|
6888
|
-
company: [
|
|
6889
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
6890
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
6891
|
-
{ key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
|
|
6892
|
-
{ key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
|
|
6893
|
-
]
|
|
6894
|
-
},
|
|
6895
|
-
extracted: {
|
|
6896
|
-
company: [
|
|
6897
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
6898
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
6899
|
-
{ key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
|
|
6900
|
-
{ key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
|
|
6901
|
-
{
|
|
6902
|
-
key: "automation-gaps",
|
|
6903
|
-
label: "Automation gaps",
|
|
6904
|
-
path: "company.enrichmentData.websiteCrawl.automationGaps",
|
|
6905
|
-
renderType: "json"
|
|
6906
|
-
},
|
|
6907
|
-
{
|
|
6908
|
-
key: "contact-count",
|
|
6909
|
-
label: "Contacts",
|
|
6910
|
-
path: "company.enrichmentData.websiteCrawl.emailCount",
|
|
6911
|
-
renderType: "count"
|
|
6912
|
-
}
|
|
6913
|
-
]
|
|
6914
|
-
},
|
|
6915
|
-
qualified: {
|
|
6916
|
-
company: [
|
|
6917
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
6918
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
6919
|
-
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
6920
|
-
{ key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
|
|
6921
|
-
{
|
|
6922
|
-
key: "disqualified-reason",
|
|
6923
|
-
label: "Disqualified reason",
|
|
6924
|
-
path: "processingState.qualified.data.disqualifiedReason"
|
|
6925
|
-
}
|
|
6926
|
-
]
|
|
6927
|
-
},
|
|
6928
|
-
decisionMakers: {
|
|
6929
|
-
contact: [
|
|
6930
|
-
{ key: "name", label: "Name", path: "contact.name" },
|
|
6931
|
-
{ key: "title", label: "Title", path: "contact.title" },
|
|
6932
|
-
{ key: "email", label: "Email", path: "contact.email" },
|
|
6933
|
-
{ key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
|
|
6934
|
-
{
|
|
6935
|
-
key: "priority-score",
|
|
6936
|
-
label: "Priority",
|
|
6937
|
-
path: "contact.enrichmentData.apollo.priorityScore",
|
|
6938
|
-
renderType: "badge"
|
|
6939
|
-
}
|
|
6940
|
-
]
|
|
6941
|
-
},
|
|
6942
|
-
uploaded: {
|
|
6943
|
-
company: [
|
|
6944
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
6945
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
6946
|
-
{
|
|
6947
|
-
key: "contacts",
|
|
6948
|
-
label: "Contacts",
|
|
6949
|
-
path: "company.enrichmentData.approvedLeadListExport.contacts",
|
|
6950
|
-
renderType: "json"
|
|
6951
|
-
},
|
|
6952
|
-
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
6953
|
-
{
|
|
6954
|
-
key: "approval",
|
|
6955
|
-
label: "Approval",
|
|
6956
|
-
path: "company.enrichmentData.approvedLeadListExport.approvalStatus",
|
|
6957
|
-
renderType: "badge"
|
|
6958
|
-
}
|
|
6959
|
-
]
|
|
6960
|
-
}
|
|
6961
|
-
};
|
|
6962
|
-
var PROSPECTING_STEPS = {
|
|
6963
|
-
localServices: {
|
|
6964
|
-
sourceCompanies: {
|
|
6965
|
-
id: "source-companies",
|
|
6966
|
-
label: "Companies found",
|
|
6967
|
-
primaryEntity: "company",
|
|
6968
|
-
outputs: ["company"],
|
|
6969
|
-
stageKey: "populated",
|
|
6970
|
-
dependencyMode: "per-record-eligibility",
|
|
6971
|
-
actionKey: "lead-gen.company.source",
|
|
6972
|
-
defaultBatchSize: 100,
|
|
6973
|
-
maxBatchSize: 250
|
|
6974
|
-
},
|
|
6975
|
-
analyzeWebsites: {
|
|
6976
|
-
id: "analyze-websites",
|
|
6977
|
-
label: "Websites analyzed",
|
|
6978
|
-
primaryEntity: "company",
|
|
6979
|
-
outputs: ["company"],
|
|
6980
|
-
stageKey: "extracted",
|
|
6981
|
-
dependsOn: ["source-companies"],
|
|
6982
|
-
dependencyMode: "per-record-eligibility",
|
|
6983
|
-
actionKey: "lead-gen.company.website-extract",
|
|
6984
|
-
defaultBatchSize: 50,
|
|
6985
|
-
maxBatchSize: 100
|
|
6986
|
-
},
|
|
6987
|
-
qualifyCompanies: {
|
|
6988
|
-
id: "qualify-companies",
|
|
6989
|
-
label: "Companies qualified",
|
|
6990
|
-
primaryEntity: "company",
|
|
6991
|
-
outputs: ["company"],
|
|
6992
|
-
stageKey: "qualified",
|
|
6993
|
-
dependsOn: ["analyze-websites"],
|
|
6994
|
-
dependencyMode: "per-record-eligibility",
|
|
6995
|
-
actionKey: "lead-gen.company.qualify",
|
|
6996
|
-
defaultBatchSize: 100,
|
|
6997
|
-
maxBatchSize: 250
|
|
6998
|
-
},
|
|
6999
|
-
findContacts: {
|
|
7000
|
-
id: "find-contacts",
|
|
7001
|
-
label: "Decision-makers found",
|
|
7002
|
-
primaryEntity: "contact",
|
|
7003
|
-
outputs: ["contact"],
|
|
7004
|
-
stageKey: "discovered",
|
|
7005
|
-
dependsOn: ["qualify-companies"],
|
|
7006
|
-
dependencyMode: "per-record-eligibility",
|
|
7007
|
-
actionKey: "lead-gen.contact.discover",
|
|
7008
|
-
defaultBatchSize: 50,
|
|
7009
|
-
maxBatchSize: 100
|
|
7010
|
-
},
|
|
7011
|
-
verifyEmails: {
|
|
7012
|
-
id: "verify-emails",
|
|
7013
|
-
label: "Emails verified",
|
|
7014
|
-
primaryEntity: "contact",
|
|
7015
|
-
outputs: ["contact"],
|
|
7016
|
-
stageKey: "verified",
|
|
7017
|
-
dependsOn: ["find-contacts"],
|
|
7018
|
-
dependencyMode: "per-record-eligibility",
|
|
7019
|
-
actionKey: "lead-gen.contact.verify-email",
|
|
7020
|
-
defaultBatchSize: 100,
|
|
7021
|
-
maxBatchSize: 500
|
|
7022
|
-
},
|
|
7023
|
-
personalize: {
|
|
7024
|
-
id: "personalize",
|
|
7025
|
-
label: "Personalize",
|
|
7026
|
-
primaryEntity: "contact",
|
|
7027
|
-
outputs: ["contact"],
|
|
7028
|
-
stageKey: "personalized",
|
|
7029
|
-
dependsOn: ["verify-emails"],
|
|
7030
|
-
dependencyMode: "per-record-eligibility",
|
|
7031
|
-
actionKey: "lead-gen.contact.personalize",
|
|
7032
|
-
defaultBatchSize: 25,
|
|
7033
|
-
maxBatchSize: 100
|
|
7034
|
-
},
|
|
7035
|
-
review: {
|
|
7036
|
-
id: "review",
|
|
7037
|
-
label: "Reviewed and exported",
|
|
7038
|
-
primaryEntity: "contact",
|
|
7039
|
-
outputs: ["export"],
|
|
7040
|
-
stageKey: "uploaded",
|
|
7041
|
-
dependsOn: ["personalize"],
|
|
7042
|
-
dependencyMode: "per-record-eligibility",
|
|
7043
|
-
actionKey: "lead-gen.review.outreach-ready",
|
|
7044
|
-
defaultBatchSize: 25,
|
|
7045
|
-
maxBatchSize: 100
|
|
7046
|
-
}
|
|
7047
|
-
},
|
|
7048
|
-
dtcApolloClickup: {
|
|
7049
|
-
importApolloSearch: {
|
|
7050
|
-
id: "import-apollo-search",
|
|
7051
|
-
label: "Companies found",
|
|
7052
|
-
description: "Pull companies and seed contact data from a predefined Apollo search or list.",
|
|
7053
|
-
primaryEntity: "company",
|
|
7054
|
-
outputs: ["company", "contact"],
|
|
7055
|
-
stageKey: "populated",
|
|
7056
|
-
dependencyMode: "per-record-eligibility",
|
|
7057
|
-
actionKey: "lead-gen.company.apollo-import",
|
|
7058
|
-
defaultBatchSize: 250,
|
|
7059
|
-
maxBatchSize: 1e3,
|
|
7060
|
-
recordColumns: DTC_RECORD_COLUMNS.populated,
|
|
7061
|
-
credentialRequirements: [
|
|
7062
|
-
{
|
|
7063
|
-
key: "apollo",
|
|
7064
|
-
provider: "apollo",
|
|
7065
|
-
credentialType: "api-key-secret",
|
|
7066
|
-
label: "Apollo API key",
|
|
7067
|
-
required: true,
|
|
7068
|
-
selectionMode: "single",
|
|
7069
|
-
inputPath: "credential"
|
|
7070
|
-
}
|
|
7071
|
-
]
|
|
7072
|
-
},
|
|
7073
|
-
apifyCrawl: {
|
|
7074
|
-
id: "apify-crawl",
|
|
7075
|
-
label: "Websites crawled",
|
|
7076
|
-
description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis. Overwrites the synthetic seed Apollo Import wrote with real page content.",
|
|
7077
|
-
primaryEntity: "company",
|
|
7078
|
-
outputs: ["company"],
|
|
7079
|
-
stageKey: "crawled",
|
|
7080
|
-
dependsOn: ["import-apollo-search"],
|
|
7081
|
-
dependencyMode: "per-record-eligibility",
|
|
7082
|
-
actionKey: "lead-gen.company.apify-crawl",
|
|
7083
|
-
defaultBatchSize: 50,
|
|
7084
|
-
maxBatchSize: 100,
|
|
7085
|
-
recordColumns: DTC_RECORD_COLUMNS.crawled,
|
|
7086
|
-
credentialRequirements: [
|
|
7087
|
-
{
|
|
7088
|
-
key: "apify",
|
|
7089
|
-
provider: "apify",
|
|
7090
|
-
credentialType: "api-key-secret",
|
|
7091
|
-
label: "Apify API token",
|
|
7092
|
-
required: true,
|
|
7093
|
-
selectionMode: "single",
|
|
7094
|
-
inputPath: "credential",
|
|
7095
|
-
verifyOnRun: true
|
|
7096
|
-
}
|
|
7097
|
-
]
|
|
7098
|
-
},
|
|
7099
|
-
analyzeWebsites: {
|
|
7100
|
-
id: "analyze-websites",
|
|
7101
|
-
label: "Websites analyzed",
|
|
7102
|
-
description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
|
|
7103
|
-
primaryEntity: "company",
|
|
7104
|
-
outputs: ["company"],
|
|
7105
|
-
stageKey: "extracted",
|
|
7106
|
-
dependsOn: ["apify-crawl"],
|
|
7107
|
-
dependencyMode: "per-record-eligibility",
|
|
7108
|
-
actionKey: "lead-gen.company.website-extract",
|
|
7109
|
-
defaultBatchSize: 50,
|
|
7110
|
-
maxBatchSize: 100,
|
|
7111
|
-
recordColumns: DTC_RECORD_COLUMNS.extracted
|
|
7112
|
-
},
|
|
7113
|
-
scoreDtcFit: {
|
|
7114
|
-
id: "score-dtc-fit",
|
|
7115
|
-
label: "Companies qualified",
|
|
7116
|
-
description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
|
|
7117
|
-
primaryEntity: "company",
|
|
7118
|
-
outputs: ["company"],
|
|
7119
|
-
stageKey: "qualified",
|
|
7120
|
-
dependsOn: ["analyze-websites"],
|
|
7121
|
-
dependencyMode: "per-record-eligibility",
|
|
7122
|
-
actionKey: "lead-gen.company.dtc-subscription-qualify",
|
|
7123
|
-
defaultBatchSize: 100,
|
|
7124
|
-
maxBatchSize: 250,
|
|
7125
|
-
recordColumns: DTC_RECORD_COLUMNS.qualified
|
|
7126
|
-
},
|
|
7127
|
-
enrichDecisionMakers: {
|
|
7128
|
-
id: "enrich-decision-makers",
|
|
7129
|
-
label: "Decision-makers found",
|
|
7130
|
-
description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
|
|
7131
|
-
primaryEntity: "company",
|
|
7132
|
-
outputs: ["contact"],
|
|
7133
|
-
stageKey: "decision-makers-enriched",
|
|
7134
|
-
recordEntity: "contact",
|
|
7135
|
-
dependsOn: ["score-dtc-fit"],
|
|
7136
|
-
dependencyMode: "per-record-eligibility",
|
|
7137
|
-
actionKey: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
7138
|
-
defaultBatchSize: 100,
|
|
7139
|
-
maxBatchSize: 250,
|
|
7140
|
-
recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
|
|
7141
|
-
credentialRequirements: [
|
|
7142
|
-
{
|
|
7143
|
-
key: "apollo",
|
|
7144
|
-
provider: "apollo",
|
|
7145
|
-
credentialType: "api-key-secret",
|
|
7146
|
-
label: "Apollo API key",
|
|
7147
|
-
required: true,
|
|
7148
|
-
selectionMode: "single",
|
|
7149
|
-
inputPath: "credential"
|
|
7150
|
-
}
|
|
7151
|
-
]
|
|
7152
|
-
},
|
|
7153
|
-
reviewAndExport: {
|
|
7154
|
-
id: "review-and-export",
|
|
7155
|
-
label: "Reviewed and exported",
|
|
7156
|
-
description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
|
|
7157
|
-
primaryEntity: "company",
|
|
7158
|
-
outputs: ["export"],
|
|
7159
|
-
stageKey: "uploaded",
|
|
7160
|
-
recordsStageKey: "uploaded",
|
|
7161
|
-
recordSourceStageKey: "qualified",
|
|
7162
|
-
dependsOn: ["enrich-decision-makers"],
|
|
7163
|
-
dependencyMode: "per-record-eligibility",
|
|
7164
|
-
actionKey: "lead-gen.export.list",
|
|
7165
|
-
defaultBatchSize: 100,
|
|
7166
|
-
maxBatchSize: 250,
|
|
7167
|
-
recordColumns: DTC_RECORD_COLUMNS.uploaded,
|
|
7168
|
-
credentialRequirements: [
|
|
7169
|
-
{
|
|
7170
|
-
key: "clickup",
|
|
7171
|
-
provider: "clickup",
|
|
7172
|
-
credentialType: "api-key-secret",
|
|
7173
|
-
label: "ClickUp API token",
|
|
7174
|
-
required: true,
|
|
7175
|
-
selectionMode: "single",
|
|
7176
|
-
inputPath: "clickupCredential",
|
|
7177
|
-
verifyOnRun: true
|
|
7178
|
-
}
|
|
7179
|
-
]
|
|
7180
|
-
}
|
|
7181
|
-
}
|
|
7182
|
-
};
|
|
7183
|
-
|
|
7184
|
-
// ../core/src/business/acquisition/build-templates.ts
|
|
7185
|
-
var BUILD_TEMPLATE_CATALOG = [
|
|
7186
|
-
{
|
|
7187
|
-
id: "local-services",
|
|
7188
|
-
label: "Local Services",
|
|
7189
|
-
description: "Source, analyze, qualify, and personalize local service businesses for outreach.",
|
|
7190
|
-
steps: Object.values(PROSPECTING_STEPS.localServices)
|
|
7191
|
-
},
|
|
7192
|
-
{
|
|
7193
|
-
id: "dtc-subscription-apollo-clickup",
|
|
7194
|
-
label: "DTC Subscription (Apollo + ClickUp)",
|
|
7195
|
-
description: "Import DTC brand leads from Apollo, crawl their websites, score fit, enrich contacts, and export via ClickUp.",
|
|
7196
|
-
steps: Object.values(PROSPECTING_STEPS.dtcApolloClickup)
|
|
7197
|
-
}
|
|
7198
|
-
];
|
|
7199
|
-
var PROSPECTING_BUILD_TEMPLATE_OPTIONS = BUILD_TEMPLATE_CATALOG.map(({ id, label, description }) => ({
|
|
7200
|
-
id,
|
|
7201
|
-
label,
|
|
7202
|
-
description
|
|
7203
|
-
}));
|
|
7204
|
-
function isProspectingBuildTemplateId(value) {
|
|
7205
|
-
return PROSPECTING_BUILD_TEMPLATE_OPTIONS.some((template) => template.id === value);
|
|
7206
|
-
}
|
|
7207
|
-
var OrganizationModelBrandingSchema = z.object({
|
|
7208
|
-
organizationName: LabelSchema,
|
|
7209
|
-
productName: LabelSchema,
|
|
7210
|
-
shortName: z.string().trim().min(1).max(40),
|
|
7211
|
-
description: DescriptionSchema.optional(),
|
|
7212
|
-
logos: z.object({
|
|
7213
|
-
light: z.string().trim().min(1).max(2048).optional(),
|
|
7214
|
-
dark: z.string().trim().min(1).max(2048).optional()
|
|
7215
|
-
}).default({})
|
|
7216
|
-
});
|
|
7217
|
-
var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
|
|
7218
|
-
organizationName: "Default Organization",
|
|
7219
|
-
productName: "Elevasis",
|
|
7220
|
-
shortName: "Elevasis",
|
|
7221
|
-
logos: {}
|
|
7222
|
-
};
|
|
7223
|
-
var BusinessHoursDaySchema = z.object({
|
|
7224
|
-
open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
|
|
7225
|
-
close: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format")
|
|
7226
|
-
});
|
|
7227
|
-
var BusinessHoursSchema = z.object({
|
|
7228
|
-
monday: BusinessHoursDaySchema.optional(),
|
|
7229
|
-
tuesday: BusinessHoursDaySchema.optional(),
|
|
7230
|
-
wednesday: BusinessHoursDaySchema.optional(),
|
|
7231
|
-
thursday: BusinessHoursDaySchema.optional(),
|
|
7232
|
-
friday: BusinessHoursDaySchema.optional(),
|
|
7233
|
-
saturday: BusinessHoursDaySchema.optional(),
|
|
7234
|
-
sunday: BusinessHoursDaySchema.optional()
|
|
7235
|
-
}).default({});
|
|
7236
|
-
var IdentityDomainSchema = z.object({
|
|
7237
|
-
/** Why the organization exists — one or two plain-language sentences. */
|
|
7238
|
-
mission: z.string().trim().max(1e3).default(""),
|
|
7239
|
-
/** Long-term direction the organization is moving toward. */
|
|
7240
|
-
vision: z.string().trim().max(1e3).default(""),
|
|
7241
|
-
/** Legal registered name of the entity. */
|
|
7242
|
-
legalName: z.string().trim().max(200).default(""),
|
|
7243
|
-
/**
|
|
7244
|
-
* Type of legal entity (e.g. "LLC", "Corporation", "Sole Proprietor",
|
|
7245
|
-
* "Non-profit"). Free-form string so it covers any jurisdiction.
|
|
7246
|
-
*/
|
|
7247
|
-
entityType: z.string().trim().max(100).default(""),
|
|
7248
|
-
/**
|
|
7249
|
-
* Primary jurisdiction of registration or operation
|
|
7250
|
-
* (e.g. "United States – Delaware", "Canada – Ontario").
|
|
7251
|
-
*/
|
|
7252
|
-
jurisdiction: z.string().trim().max(200).default(""),
|
|
7253
|
-
/**
|
|
7254
|
-
* Industry category — broad classification (e.g. "Marketing Agency",
|
|
7255
|
-
* "Software / SaaS", "Professional Services").
|
|
7256
|
-
*/
|
|
7257
|
-
industryCategory: z.string().trim().max(200).default(""),
|
|
7258
|
-
/**
|
|
7259
|
-
* Geographic focus — where the organization primarily operates or serves
|
|
7260
|
-
* (e.g. "North America", "Global", "Southeast Asia").
|
|
7261
|
-
*/
|
|
7262
|
-
geographicFocus: z.string().trim().max(200).default(""),
|
|
7263
|
-
/**
|
|
7264
|
-
* IANA timezone identifier for the organization's primary operating timezone
|
|
7265
|
-
* (e.g. "America/Los_Angeles", "Europe/London", "UTC").
|
|
7266
|
-
*/
|
|
7267
|
-
timeZone: z.string().trim().max(100).default("UTC"),
|
|
7268
|
-
/** Typical operating hours per day of week. Empty object means not configured. */
|
|
7269
|
-
businessHours: BusinessHoursSchema,
|
|
7270
|
-
/**
|
|
7271
|
-
* Long-form markdown capturing client context, problem narrative, and domain
|
|
7272
|
-
* background. Populated by /setup; surfaced to agents as organizational context.
|
|
7273
|
-
* Optional — many projects have no external client.
|
|
7274
|
-
*/
|
|
7275
|
-
clientBrief: z.string().trim().default("")
|
|
7276
|
-
});
|
|
7277
|
-
var DEFAULT_ORGANIZATION_MODEL_IDENTITY = {
|
|
7278
|
-
mission: "",
|
|
7279
|
-
vision: "",
|
|
7280
|
-
legalName: "",
|
|
7281
|
-
entityType: "",
|
|
7282
|
-
jurisdiction: "",
|
|
7283
|
-
industryCategory: "",
|
|
7284
|
-
geographicFocus: "",
|
|
7285
|
-
timeZone: "UTC",
|
|
7286
|
-
businessHours: {},
|
|
7287
|
-
clientBrief: ""
|
|
7288
|
-
};
|
|
7289
|
-
var FirmographicsSchema = z.object({
|
|
7290
|
-
/** Industry vertical (e.g. "Marketing Agency", "Legal", "Real Estate"). */
|
|
7291
|
-
industry: z.string().trim().max(200).optional(),
|
|
7292
|
-
/**
|
|
7293
|
-
* Company headcount band (e.g. "1–10", "11–50", "51–200", "200+").
|
|
7294
|
-
* Free-form string to accommodate any band notation.
|
|
7295
|
-
*/
|
|
7296
|
-
companySize: z.string().trim().max(100).optional(),
|
|
7297
|
-
/**
|
|
7298
|
-
* Primary geographic region the segment operates in or is targeted from
|
|
7299
|
-
* (e.g. "North America", "Europe", "Global").
|
|
7300
|
-
*/
|
|
7301
|
-
region: z.string().trim().max(200).optional()
|
|
7302
|
-
});
|
|
7303
|
-
var CustomerSegmentSchema = z.object({
|
|
7304
|
-
/** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
|
|
7305
|
-
id: z.string().trim().min(1).max(100),
|
|
7306
|
-
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
7307
|
-
order: z.number(),
|
|
7308
|
-
/** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
|
|
7309
|
-
name: z.string().trim().max(200).default(""),
|
|
7310
|
-
/** One or two sentences describing who this segment is. */
|
|
7311
|
-
description: z.string().trim().max(2e3).default(""),
|
|
7312
|
-
/**
|
|
7313
|
-
* The primary job(s) this segment is trying to get done — the goal they hire
|
|
7314
|
-
* a product/service to accomplish. Plain-language narrative or bullet list.
|
|
7315
|
-
*/
|
|
7316
|
-
jobsToBeDone: z.string().trim().max(2e3).default(""),
|
|
7317
|
-
/**
|
|
7318
|
-
* Pains — frustrations, obstacles, and risks the segment experiences
|
|
7319
|
-
* when trying to accomplish their jobs-to-be-done.
|
|
7320
|
-
*/
|
|
7321
|
-
pains: z.array(z.string().trim().max(500)).default([]),
|
|
7322
|
-
/**
|
|
7323
|
-
* Gains — outcomes and benefits the segment desires; positive motivators
|
|
7324
|
-
* beyond merely resolving pains.
|
|
7325
|
-
*/
|
|
7326
|
-
gains: z.array(z.string().trim().max(500)).default([]),
|
|
7327
|
-
/** Firmographic profile for targeting and filtering. */
|
|
7328
|
-
firmographics: FirmographicsSchema.default({}),
|
|
7329
|
-
/**
|
|
7330
|
-
* Value proposition — one or two sentences stating why this organization's
|
|
7331
|
-
* offering is uniquely suited for this segment's needs.
|
|
7332
|
-
*/
|
|
7333
|
-
valueProp: z.string().trim().max(2e3).default("")
|
|
7334
|
-
});
|
|
7335
|
-
var CustomersDomainSchema = z.record(z.string(), CustomerSegmentSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
7336
|
-
message: "Each segment entry id must match its map key"
|
|
7337
|
-
}).default({});
|
|
7338
|
-
var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {};
|
|
7339
|
-
var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]).meta({ label: "Pricing model", color: "green" });
|
|
7340
|
-
var ProductSchema = z.object({
|
|
7341
|
-
/** Stable unique identifier for the product (e.g. "product-starter-plan"). */
|
|
7342
|
-
id: z.string().trim().min(1).max(100),
|
|
7343
|
-
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
7344
|
-
order: z.number(),
|
|
7345
|
-
/** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
|
|
7346
|
-
name: z.string().trim().max(200).default(""),
|
|
7347
|
-
/** One or two sentences describing what this product/service delivers. */
|
|
7348
|
-
description: z.string().trim().max(2e3).default(""),
|
|
7349
|
-
/**
|
|
7350
|
-
* How this product is priced:
|
|
7351
|
-
* - "one-time" — single purchase (setup fee, project fee)
|
|
7352
|
-
* - "subscription" — recurring (monthly/annual SaaS, retainer)
|
|
7353
|
-
* - "usage-based" — metered by consumption (API calls, seats)
|
|
7354
|
-
* - "custom" — negotiated or bespoke pricing
|
|
7355
|
-
*/
|
|
7356
|
-
pricingModel: PricingModelSchema.default("custom"),
|
|
7357
|
-
/** Base price amount (≥ 0). Currency unit defined by `currency`. */
|
|
7358
|
-
price: z.number().min(0).default(0),
|
|
7359
|
-
/**
|
|
7360
|
-
* ISO 4217 currency code (e.g. "USD", "EUR", "GBP").
|
|
7361
|
-
* Free-form string to accommodate any currency; defaults to "USD".
|
|
7362
|
-
*/
|
|
7363
|
-
currency: z.string().trim().max(10).default("USD"),
|
|
7364
|
-
/**
|
|
7365
|
-
* IDs of customer segments this product targets.
|
|
7366
|
-
* Each id must reference a declared `customers.segments[].id`.
|
|
7367
|
-
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
7368
|
-
*/
|
|
7369
|
-
targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
|
|
7370
|
-
/**
|
|
7371
|
-
* Optional: ID of the platform system responsible for delivering this product.
|
|
7372
|
-
* When present, must reference a declared `systems.systems[].id`.
|
|
7373
|
-
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
7374
|
-
*/
|
|
7375
|
-
deliveryFeatureId: z.string().trim().min(1).optional()
|
|
7376
|
-
});
|
|
7377
|
-
var OfferingsDomainSchema = z.record(z.string(), ProductSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
7378
|
-
message: "Each product entry id must match its map key"
|
|
7379
|
-
}).default({});
|
|
7380
|
-
var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {};
|
|
7381
|
-
var OntologyKindSchema = z.enum([
|
|
7382
|
-
"object",
|
|
7383
|
-
"link",
|
|
7384
|
-
"action",
|
|
7385
|
-
"catalog",
|
|
7386
|
-
"event",
|
|
7387
|
-
"interface",
|
|
7388
|
-
"value-type",
|
|
7389
|
-
"property",
|
|
7390
|
-
"group",
|
|
7391
|
-
"surface"
|
|
7392
|
-
]);
|
|
7393
|
-
var SYSTEM_PATH_PATTERN = "[a-z0-9][a-z0-9-]*(?:\\.[a-z0-9][a-z0-9-]*)*";
|
|
7394
|
-
var LOCAL_ID_PATTERN = "[a-z0-9][a-z0-9._-]*";
|
|
7395
|
-
var ONTOLOGY_ID_PATTERN = `^(global|${SYSTEM_PATH_PATTERN}):(${OntologyKindSchema.options.join("|")})\\/(${LOCAL_ID_PATTERN})$`;
|
|
7396
|
-
var ONTOLOGY_ID_REGEX = new RegExp(ONTOLOGY_ID_PATTERN);
|
|
7397
|
-
var OntologyIdSchema = z.string().trim().min(1).max(300).regex(
|
|
7398
|
-
ONTOLOGY_ID_REGEX,
|
|
7399
|
-
"Ontology IDs must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
|
|
7400
|
-
);
|
|
7401
|
-
function parseOntologyId(id) {
|
|
7402
|
-
const normalized = OntologyIdSchema.parse(id);
|
|
7403
|
-
const match = ONTOLOGY_ID_REGEX.exec(normalized);
|
|
7404
|
-
if (match === null) {
|
|
7405
|
-
throw new Error(`Invalid ontology ID "${id}"`);
|
|
7406
|
-
}
|
|
7407
|
-
return {
|
|
7408
|
-
id: normalized,
|
|
7409
|
-
scope: match[1],
|
|
7410
|
-
kind: match[2],
|
|
7411
|
-
localId: match[3],
|
|
7412
|
-
isGlobal: match[1] === "global"
|
|
7413
|
-
};
|
|
7414
|
-
}
|
|
7415
|
-
function formatOntologyId(input) {
|
|
7416
|
-
return OntologyIdSchema.parse(`${input.scope}:${input.kind}/${input.localId}`);
|
|
7417
|
-
}
|
|
7418
|
-
var OntologyReferenceListSchema = z.array(OntologyIdSchema).default([]).optional();
|
|
7419
|
-
var OntologyRecordBaseSchema = z.object({
|
|
7420
|
-
id: OntologyIdSchema,
|
|
7421
|
-
label: z.string().trim().min(1).max(160).optional(),
|
|
7422
|
-
description: z.string().trim().min(1).max(2e3).optional(),
|
|
7423
|
-
ownerSystemId: z.string().trim().min(1).max(200).optional(),
|
|
7424
|
-
aliases: z.array(OntologyIdSchema).optional()
|
|
7425
|
-
}).passthrough();
|
|
7426
|
-
var OntologyObjectTypeSchema = OntologyRecordBaseSchema.extend({
|
|
7427
|
-
properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
|
|
7428
|
-
storage: z.record(z.string(), z.unknown()).optional()
|
|
7429
|
-
});
|
|
7430
|
-
var OntologyLinkTypeSchema = OntologyRecordBaseSchema.extend({
|
|
7431
|
-
from: OntologyIdSchema,
|
|
7432
|
-
to: OntologyIdSchema,
|
|
7433
|
-
cardinality: z.string().trim().min(1).max(80).optional(),
|
|
7434
|
-
via: z.string().trim().min(1).max(255).optional()
|
|
7435
|
-
});
|
|
7436
|
-
var OntologyActionTypeSchema = OntologyRecordBaseSchema.extend({
|
|
7437
|
-
actsOn: OntologyReferenceListSchema,
|
|
7438
|
-
input: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
|
|
7439
|
-
effects: z.array(z.record(z.string(), z.unknown())).optional()
|
|
7440
|
-
});
|
|
7441
|
-
var OntologyCatalogTypeSchema = OntologyRecordBaseSchema.extend({
|
|
7442
|
-
kind: z.string().trim().min(1).max(120).optional(),
|
|
7443
|
-
appliesTo: OntologyIdSchema.optional(),
|
|
7444
|
-
entries: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
|
|
7445
|
-
});
|
|
7446
|
-
var OntologyEventTypeSchema = OntologyRecordBaseSchema.extend({
|
|
7447
|
-
payload: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
|
|
7448
|
-
});
|
|
7449
|
-
var OntologyInterfaceTypeSchema = OntologyRecordBaseSchema.extend({
|
|
7450
|
-
properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
|
|
7451
|
-
});
|
|
7452
|
-
var OntologyValueTypeSchema = OntologyRecordBaseSchema.extend({
|
|
7453
|
-
primitive: z.string().trim().min(1).max(120).optional()
|
|
7454
|
-
});
|
|
7455
|
-
var OntologySharedPropertySchema = OntologyRecordBaseSchema.extend({
|
|
7456
|
-
valueType: OntologyIdSchema.optional(),
|
|
7457
|
-
searchable: z.boolean().optional(),
|
|
7458
|
-
pii: z.boolean().optional()
|
|
7459
|
-
});
|
|
7460
|
-
var OntologyGroupSchema = OntologyRecordBaseSchema.extend({
|
|
7461
|
-
members: OntologyReferenceListSchema
|
|
7462
|
-
});
|
|
7463
|
-
var OntologySurfaceTypeSchema = OntologyRecordBaseSchema.extend({
|
|
7464
|
-
route: z.string().trim().min(1).max(500).optional()
|
|
7465
|
-
});
|
|
7466
|
-
var OntologyScopeSchema = z.object({
|
|
7467
|
-
objectTypes: z.record(OntologyIdSchema, OntologyObjectTypeSchema).default({}).optional(),
|
|
7468
|
-
linkTypes: z.record(OntologyIdSchema, OntologyLinkTypeSchema).default({}).optional(),
|
|
7469
|
-
actionTypes: z.record(OntologyIdSchema, OntologyActionTypeSchema).default({}).optional(),
|
|
7470
|
-
catalogTypes: z.record(OntologyIdSchema, OntologyCatalogTypeSchema).default({}).optional(),
|
|
7471
|
-
eventTypes: z.record(OntologyIdSchema, OntologyEventTypeSchema).default({}).optional(),
|
|
7472
|
-
interfaceTypes: z.record(OntologyIdSchema, OntologyInterfaceTypeSchema).default({}).optional(),
|
|
7473
|
-
valueTypes: z.record(OntologyIdSchema, OntologyValueTypeSchema).default({}).optional(),
|
|
7474
|
-
sharedProperties: z.record(OntologyIdSchema, OntologySharedPropertySchema).default({}).optional(),
|
|
7475
|
-
groups: z.record(OntologyIdSchema, OntologyGroupSchema).default({}).optional(),
|
|
7476
|
-
surfaces: z.record(OntologyIdSchema, OntologySurfaceTypeSchema).default({}).optional()
|
|
7477
|
-
}).default({});
|
|
7478
|
-
var DEFAULT_ONTOLOGY_SCOPE = {
|
|
7479
|
-
valueTypes: {
|
|
7480
|
-
"global:value-type/uuid": {
|
|
7481
|
-
id: "global:value-type/uuid",
|
|
7482
|
-
label: "UUID",
|
|
7483
|
-
primitive: "string"
|
|
7484
|
-
},
|
|
7485
|
-
"global:value-type/text": {
|
|
7486
|
-
id: "global:value-type/text",
|
|
7487
|
-
label: "Text",
|
|
7488
|
-
primitive: "string"
|
|
7489
|
-
},
|
|
7490
|
-
"global:value-type/url": {
|
|
7491
|
-
id: "global:value-type/url",
|
|
7492
|
-
label: "URL",
|
|
7493
|
-
primitive: "string"
|
|
7494
|
-
},
|
|
7495
|
-
"global:value-type/email": {
|
|
7496
|
-
id: "global:value-type/email",
|
|
7497
|
-
label: "Email",
|
|
7498
|
-
primitive: "string"
|
|
7499
|
-
}
|
|
7500
|
-
}
|
|
7501
|
-
};
|
|
7502
|
-
var SCOPE_KIND = {
|
|
7503
|
-
objectTypes: "object",
|
|
7504
|
-
linkTypes: "link",
|
|
7505
|
-
actionTypes: "action",
|
|
7506
|
-
catalogTypes: "catalog",
|
|
7507
|
-
eventTypes: "event",
|
|
7508
|
-
interfaceTypes: "interface",
|
|
7509
|
-
valueTypes: "value-type",
|
|
7510
|
-
sharedProperties: "property",
|
|
7511
|
-
groups: "group",
|
|
7512
|
-
surfaces: "surface"
|
|
7513
|
-
};
|
|
7514
|
-
var SCOPE_KEYS = Object.keys(SCOPE_KIND);
|
|
7515
|
-
function listResolvedOntologyRecords(index2) {
|
|
7516
|
-
return SCOPE_KEYS.flatMap((scopeKey) => {
|
|
7517
|
-
const kind = SCOPE_KIND[scopeKey];
|
|
7518
|
-
return Object.entries(index2[scopeKey]).sort(([leftId], [rightId]) => leftId.localeCompare(rightId)).map(([id, record]) => ({
|
|
7519
|
-
id,
|
|
7520
|
-
kind,
|
|
7521
|
-
record
|
|
7522
|
-
}));
|
|
7523
|
-
});
|
|
7524
|
-
}
|
|
7525
|
-
function originFromContext(context) {
|
|
7526
|
-
return {
|
|
7527
|
-
kind: context.kind,
|
|
7528
|
-
source: context.source,
|
|
7529
|
-
path: context.path,
|
|
7530
|
-
...context.systemPath !== void 0 ? { systemPath: context.systemPath } : {},
|
|
7531
|
-
...context.legacyId !== void 0 ? { legacyId: context.legacyId } : {}
|
|
7532
|
-
};
|
|
7533
|
-
}
|
|
7534
|
-
function createEmptyIndex() {
|
|
7535
|
-
return {
|
|
7536
|
-
objectTypes: {},
|
|
7537
|
-
linkTypes: {},
|
|
7538
|
-
actionTypes: {},
|
|
7539
|
-
catalogTypes: {},
|
|
7540
|
-
eventTypes: {},
|
|
7541
|
-
interfaceTypes: {},
|
|
7542
|
-
valueTypes: {},
|
|
7543
|
-
sharedProperties: {},
|
|
7544
|
-
groups: {},
|
|
7545
|
-
surfaces: {}
|
|
7546
|
-
};
|
|
7547
|
-
}
|
|
7548
|
-
function sortResolvedOntologyIndex(index2) {
|
|
7549
|
-
const sorted = createEmptyIndex();
|
|
7550
|
-
for (const scopeKey of SCOPE_KEYS) {
|
|
7551
|
-
const target = sorted[scopeKey];
|
|
7552
|
-
for (const [id, record] of Object.entries(index2[scopeKey]).sort(
|
|
7553
|
-
([leftId], [rightId]) => leftId.localeCompare(rightId)
|
|
7554
|
-
)) {
|
|
7555
|
-
target[id] = record;
|
|
7556
|
-
}
|
|
7557
|
-
}
|
|
7558
|
-
return sorted;
|
|
7559
|
-
}
|
|
7560
|
-
function childSystemsOf(system) {
|
|
7561
|
-
return system.systems ?? system.subsystems ?? {};
|
|
7562
|
-
}
|
|
7563
|
-
function addRecord(index2, diagnostics, sourcesById, scopeKey, record, context) {
|
|
7564
|
-
let parsed;
|
|
7565
|
-
try {
|
|
7566
|
-
parsed = parseOntologyId(record.id);
|
|
7567
|
-
} catch {
|
|
7568
|
-
diagnostics.push({
|
|
7569
|
-
code: "invalid_ontology_id",
|
|
7570
|
-
message: `Invalid ontology ID "${record.id}" from ${context.source} at ${context.path.join(".")}`,
|
|
7571
|
-
id: record.id,
|
|
7572
|
-
path: context.path,
|
|
7573
|
-
source: context.source,
|
|
7574
|
-
origin: originFromContext(context)
|
|
7575
|
-
});
|
|
7576
|
-
return;
|
|
7577
|
-
}
|
|
7578
|
-
const expectedKind = SCOPE_KIND[scopeKey];
|
|
7579
|
-
if (parsed.kind !== expectedKind) {
|
|
7580
|
-
diagnostics.push({
|
|
7581
|
-
code: "ontology_kind_mismatch",
|
|
7582
|
-
message: `Ontology ID "${record.id}" has kind "${parsed.kind}" but was authored in ${scopeKey} (${expectedKind}) at ${context.path.join(".")}`,
|
|
7583
|
-
id: record.id,
|
|
7584
|
-
path: context.path,
|
|
7585
|
-
source: context.source,
|
|
7586
|
-
origin: originFromContext(context)
|
|
7587
|
-
});
|
|
7588
|
-
return;
|
|
7589
|
-
}
|
|
7590
|
-
const existing = sourcesById.get(parsed.id);
|
|
7591
|
-
if (existing !== void 0) {
|
|
7592
|
-
diagnostics.push({
|
|
7593
|
-
code: "duplicate_ontology_id",
|
|
7594
|
-
message: `Duplicate ontology ID "${parsed.id}" from ${context.source} at ${context.path.join(".")} conflicts with ${existing.source} at ${existing.path.join(".")}`,
|
|
7595
|
-
id: parsed.id,
|
|
7596
|
-
path: context.path,
|
|
7597
|
-
source: context.source,
|
|
7598
|
-
origin: originFromContext(context),
|
|
7599
|
-
existingSource: existing.source,
|
|
7600
|
-
existingOrigin: originFromContext(existing)
|
|
7601
|
-
});
|
|
7602
|
-
return;
|
|
7603
|
-
}
|
|
7604
|
-
sourcesById.set(parsed.id, context);
|
|
7605
|
-
index2[scopeKey][parsed.id] = {
|
|
7606
|
-
...record,
|
|
7607
|
-
origin: originFromContext(context)
|
|
7608
|
-
};
|
|
7609
|
-
}
|
|
7610
|
-
function addScope(index2, diagnostics, sourcesById, scope, source, path) {
|
|
7611
|
-
if (scope === void 0) return;
|
|
7612
|
-
for (const scopeKey of SCOPE_KEYS) {
|
|
7613
|
-
const records = scope[scopeKey] ?? {};
|
|
7614
|
-
for (const [key, record] of Object.entries(records)) {
|
|
7615
|
-
addRecord(index2, diagnostics, sourcesById, scopeKey, record, {
|
|
7616
|
-
source,
|
|
7617
|
-
path: [...path, scopeKey, key],
|
|
7618
|
-
kind: "authored",
|
|
7619
|
-
systemPath: source.startsWith("system:") ? source.slice("system:".length, -".ontology".length) : void 0
|
|
7620
|
-
});
|
|
7621
|
-
}
|
|
7622
|
-
}
|
|
7623
|
-
}
|
|
7624
|
-
function legacyObjectId(entity) {
|
|
7625
|
-
return formatOntologyId({ scope: entity.ownedBySystemId, kind: "object", localId: entity.id });
|
|
7626
|
-
}
|
|
7627
|
-
function legacyActionOwner(action, entities) {
|
|
7628
|
-
const firstAffectedEntityId = action.affects?.find((entityId) => entities[entityId] !== void 0);
|
|
7629
|
-
if (firstAffectedEntityId !== void 0) {
|
|
7630
|
-
return entities[firstAffectedEntityId].ownedBySystemId;
|
|
7631
|
-
}
|
|
7632
|
-
if (typeof action.scope === "object") {
|
|
7633
|
-
return action.scope.domain;
|
|
7634
|
-
}
|
|
7635
|
-
return "global";
|
|
7636
|
-
}
|
|
7637
|
-
function addLegacyEntityProjections(index2, diagnostics, sourcesById, entities) {
|
|
7638
|
-
for (const entity of Object.values(entities)) {
|
|
7639
|
-
const objectType = {
|
|
7640
|
-
id: legacyObjectId(entity),
|
|
7641
|
-
label: entity.label,
|
|
7642
|
-
description: entity.description,
|
|
7643
|
-
ownerSystemId: entity.ownedBySystemId,
|
|
7644
|
-
...entity.table !== void 0 ? {
|
|
7645
|
-
storage: {
|
|
7646
|
-
kind: "table",
|
|
7647
|
-
table: entity.table
|
|
7648
|
-
}
|
|
7649
|
-
} : {},
|
|
7650
|
-
...entity.rowSchema !== void 0 ? { rowSchema: entity.rowSchema } : {},
|
|
7651
|
-
...entity.stateCatalogId !== void 0 ? { stateCatalogId: entity.stateCatalogId } : {}
|
|
7652
|
-
};
|
|
7653
|
-
addRecord(index2, diagnostics, sourcesById, "objectTypes", objectType, {
|
|
7654
|
-
source: "legacy.entities",
|
|
7655
|
-
path: ["entities", entity.id],
|
|
7656
|
-
kind: "projected",
|
|
7657
|
-
systemPath: entity.ownedBySystemId,
|
|
7658
|
-
legacyId: entity.id
|
|
7659
|
-
});
|
|
7660
|
-
entity.links?.forEach((link, linkIndex) => {
|
|
7661
|
-
const targetEntity = entities[link.toEntity];
|
|
7662
|
-
if (targetEntity === void 0) return;
|
|
7663
|
-
const linkType = {
|
|
7664
|
-
id: formatOntologyId({
|
|
7665
|
-
scope: entity.ownedBySystemId,
|
|
7666
|
-
kind: "link",
|
|
7667
|
-
localId: `${entity.id}-${link.toEntity}-${linkIndex}`
|
|
7668
|
-
}),
|
|
7669
|
-
label: link.label ?? link.kind,
|
|
7670
|
-
ownerSystemId: entity.ownedBySystemId,
|
|
7671
|
-
from: legacyObjectId(entity),
|
|
7672
|
-
to: legacyObjectId(targetEntity),
|
|
7673
|
-
cardinality: link.kind,
|
|
7674
|
-
...link.via !== void 0 ? { via: link.via } : {}
|
|
7675
|
-
};
|
|
7676
|
-
addRecord(index2, diagnostics, sourcesById, "linkTypes", linkType, {
|
|
7677
|
-
source: "legacy.entities.links",
|
|
7678
|
-
path: ["entities", entity.id, "links", linkIndex],
|
|
7679
|
-
kind: "projected",
|
|
7680
|
-
systemPath: entity.ownedBySystemId,
|
|
7681
|
-
legacyId: `${entity.id}.links.${linkIndex}`
|
|
7682
|
-
});
|
|
7683
|
-
});
|
|
7684
|
-
}
|
|
7685
|
-
}
|
|
7686
|
-
function addLegacyActionProjections(index2, diagnostics, sourcesById, actions, entities) {
|
|
7687
|
-
for (const action of Object.values(actions)) {
|
|
7688
|
-
const ownerSystemId = legacyActionOwner(action, entities);
|
|
7689
|
-
const actionType = {
|
|
7690
|
-
id: formatOntologyId({ scope: ownerSystemId, kind: "action", localId: action.id }),
|
|
7691
|
-
label: action.label,
|
|
7692
|
-
description: action.description,
|
|
7693
|
-
ownerSystemId,
|
|
7694
|
-
actsOn: action.affects?.map((entityId) => entities[entityId] ? legacyObjectId(entities[entityId]) : void 0).filter((id) => id !== void 0),
|
|
7695
|
-
...action.resourceId !== void 0 ? { resourceId: action.resourceId } : {},
|
|
7696
|
-
...action.invocations !== void 0 ? { invocations: action.invocations } : {},
|
|
7697
|
-
...action.lifecycle !== void 0 ? { lifecycle: action.lifecycle } : {},
|
|
7698
|
-
legacyActionId: action.id
|
|
7699
|
-
};
|
|
7700
|
-
addRecord(index2, diagnostics, sourcesById, "actionTypes", actionType, {
|
|
7701
|
-
source: "legacy.actions",
|
|
7702
|
-
path: ["actions", action.id],
|
|
7703
|
-
kind: "projected",
|
|
7704
|
-
systemPath: ownerSystemId,
|
|
7705
|
-
legacyId: action.id
|
|
7706
|
-
});
|
|
7707
|
-
}
|
|
7708
|
-
}
|
|
7709
|
-
function addSystemScopes(index2, diagnostics, sourcesById, systems, prefix, schemaPath) {
|
|
7710
|
-
for (const [key, system] of Object.entries(systems)) {
|
|
7711
|
-
const systemPath = prefix ? `${prefix}.${key}` : key;
|
|
7712
|
-
const currentPath = [...schemaPath, key];
|
|
7713
|
-
addScope(index2, diagnostics, sourcesById, system.ontology, `system:${systemPath}.ontology`, [
|
|
7714
|
-
...currentPath,
|
|
7715
|
-
"ontology"
|
|
7716
|
-
]);
|
|
7717
|
-
addSystemScopes(index2, diagnostics, sourcesById, childSystemsOf(system), systemPath, [
|
|
7718
|
-
...currentPath,
|
|
7719
|
-
system.systems !== void 0 ? "systems" : "subsystems"
|
|
7720
|
-
]);
|
|
7721
|
-
}
|
|
7722
|
-
}
|
|
7723
|
-
function compileOrganizationOntology(model) {
|
|
7724
|
-
const ontology = createEmptyIndex();
|
|
7725
|
-
const diagnostics = [];
|
|
7726
|
-
const sourcesById = /* @__PURE__ */ new Map();
|
|
7727
|
-
addScope(ontology, diagnostics, sourcesById, model.ontology, "organization.ontology", ["ontology"]);
|
|
7728
|
-
addSystemScopes(ontology, diagnostics, sourcesById, model.systems ?? {}, "", ["systems"]);
|
|
7729
|
-
addLegacyEntityProjections(ontology, diagnostics, sourcesById, model.entities ?? {});
|
|
7730
|
-
addLegacyActionProjections(ontology, diagnostics, sourcesById, model.actions ?? {}, model.entities ?? {});
|
|
7731
|
-
return { ontology: sortResolvedOntologyIndex(ontology), diagnostics };
|
|
7732
|
-
}
|
|
7733
|
-
|
|
7734
|
-
// ../core/src/organization-model/domains/systems.ts
|
|
7735
|
-
var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
|
|
7736
|
-
var SystemLifecycleSchema = z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
|
|
7737
|
-
var SystemStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Status", color: "teal" });
|
|
7738
|
-
var SystemIdSchema = ModelIdSchema;
|
|
7739
|
-
var SystemPathSchema = z.string().trim().min(1).regex(
|
|
7740
|
-
/^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
|
|
7741
|
-
'must be a dotted lowercase path (e.g. "sales.lead-gen" or "sales.crm")'
|
|
7742
|
-
);
|
|
7743
|
-
var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]).meta({ label: "UI position" });
|
|
7744
|
-
var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(
|
|
7745
|
-
/^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
|
|
7746
|
-
"Node references must use kind:dotted-path (e.g. system:sales.crm or resource:lead-gen.company.qualify)"
|
|
7747
|
-
);
|
|
7748
|
-
var SystemUiSchema = z.object({
|
|
7749
|
-
path: PathSchema,
|
|
7750
|
-
surfaces: ReferenceIdsSchema,
|
|
7751
|
-
icon: IconNameSchema.optional(),
|
|
7752
|
-
order: z.number().int().optional()
|
|
7753
|
-
});
|
|
7754
|
-
var JsonValueSchema = z.lazy(
|
|
7755
|
-
() => z.union([
|
|
7756
|
-
z.string(),
|
|
7757
|
-
z.number(),
|
|
7758
|
-
z.boolean(),
|
|
7759
|
-
z.null(),
|
|
7760
|
-
z.array(JsonValueSchema),
|
|
7761
|
-
z.record(z.string(), JsonValueSchema)
|
|
7762
|
-
])
|
|
7763
|
-
);
|
|
7764
|
-
var SystemConfigSchema = z.record(z.string().trim().min(1).max(200), JsonValueSchema).default({}).optional();
|
|
7765
|
-
var SystemEntrySchema = z.object({
|
|
7766
|
-
/** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
|
|
7767
|
-
id: SystemIdSchema,
|
|
7768
|
-
/** Human-readable system label shown in UI, governance, and operations surfaces. */
|
|
7769
|
-
label: LabelSchema.optional(),
|
|
7770
|
-
/** @deprecated Use label. Accepted for pre-consolidation System declarations. */
|
|
7771
|
-
title: LabelSchema.optional(),
|
|
7772
|
-
/** One-paragraph purpose statement for the bounded context. */
|
|
7773
|
-
description: DescriptionSchema.optional(),
|
|
7774
|
-
/** Closed system shape enum; catalog values remain tenant-defined. */
|
|
7775
|
-
kind: SystemKindSchema.optional(),
|
|
7776
|
-
/** Optional self-reference for System hierarchy. */
|
|
7777
|
-
parentSystemId: SystemIdSchema.optional(),
|
|
7778
|
-
/** Optional UI presence. Systems without UI omit this. */
|
|
7779
|
-
ui: SystemUiSchema.optional(),
|
|
7780
|
-
/** Canonical lifecycle state. Replaces Feature.enabled/devOnly and System.status. */
|
|
7781
|
-
lifecycle: SystemLifecycleSchema.optional(),
|
|
7782
|
-
/** Optional role responsible for this system. */
|
|
7783
|
-
responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
7784
|
-
/** Optional knowledge nodes that govern this system. */
|
|
7785
|
-
governedByKnowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
|
|
7786
|
-
/** Optional actions this system exposes or consumes. */
|
|
7787
|
-
actions: z.array(ActionRefSchema).optional(),
|
|
7788
|
-
/** Optional operational policies that apply to this system. */
|
|
7789
|
-
policies: z.array(ModelIdSchema.meta({ ref: "policy" })).default([]).optional(),
|
|
7790
|
-
/** Optional goals this system contributes to. */
|
|
7791
|
-
drivesGoals: z.array(ModelIdSchema.meta({ ref: "goal" })).default([]).optional(),
|
|
7792
|
-
/** @deprecated Use lifecycle. Accepted for one publish cycle. */
|
|
7793
|
-
status: SystemStatusSchema.optional(),
|
|
7794
|
-
/** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
|
|
7795
|
-
path: PathSchema.optional(),
|
|
7796
|
-
/** @deprecated Use ui.icon. Kept for one-cycle Feature compatibility. */
|
|
7797
|
-
icon: IconNameSchema.optional(),
|
|
7798
|
-
/** @deprecated Feature color token, retained for one-cycle compatibility. */
|
|
7799
|
-
color: ColorTokenSchema.optional(),
|
|
7800
|
-
/** @deprecated UI placement hint, retained for one-cycle compatibility. */
|
|
7801
|
-
uiPosition: UiPositionSchema.optional(),
|
|
7802
|
-
/** @deprecated Use lifecycle. */
|
|
7803
|
-
enabled: z.boolean().optional(),
|
|
7804
|
-
/** @deprecated Use lifecycle: "beta". */
|
|
7805
|
-
devOnly: z.boolean().optional(),
|
|
7806
|
-
requiresAdmin: z.boolean().optional(),
|
|
7807
|
-
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
7808
|
-
order: z.number(),
|
|
7809
|
-
/**
|
|
7810
|
-
* System-local JSON settings and defaults. Strongly typed OM fields,
|
|
7811
|
-
* secrets, credentials, and runtime state stay outside this bucket.
|
|
7812
|
-
*/
|
|
7813
|
-
config: SystemConfigSchema,
|
|
7814
|
-
/**
|
|
7815
|
-
* System-owned ontology declarations. `systems` is now the canonical child
|
|
7816
|
-
* key; this scope holds the object, action, catalog, link, event, and
|
|
7817
|
-
* shared contract records owned by this system.
|
|
7818
|
-
*/
|
|
7819
|
-
ontology: OntologyScopeSchema.optional(),
|
|
7820
|
-
/**
|
|
7821
|
-
* Recursive child systems, authored via nesting (per L11).
|
|
7822
|
-
* The key is the local system id; the full path is computed by joining
|
|
7823
|
-
* ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
|
|
7824
|
-
* Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
|
|
7825
|
-
* position-derived paths. Both still exist on this schema for backward compat.
|
|
7826
|
-
*/
|
|
7827
|
-
systems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional(),
|
|
7828
|
-
/** @deprecated Use systems. Accepted as a compatibility alias during the ontology bridge. */
|
|
7829
|
-
subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
|
|
7830
|
-
}).strict().refine((system) => system.label !== void 0 || system.title !== void 0, {
|
|
7831
|
-
path: ["label"],
|
|
7832
|
-
message: "System must provide label or title"
|
|
7833
|
-
}).transform((system) => {
|
|
7834
|
-
const normalizedSystem = system.systems !== void 0 && system.subsystems === void 0 ? { ...system, subsystems: system.systems } : system;
|
|
7835
|
-
if (normalizedSystem.status === void 0) return normalizedSystem;
|
|
7836
|
-
console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
|
|
7837
|
-
return normalizedSystem.lifecycle === void 0 ? { ...normalizedSystem, lifecycle: normalizedSystem.status } : normalizedSystem;
|
|
7838
|
-
});
|
|
7839
|
-
var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
7840
|
-
message: "Each system entry id must match its map key"
|
|
7841
|
-
}).default({});
|
|
7842
|
-
var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {};
|
|
7843
|
-
|
|
7844
|
-
// ../core/src/organization-model/domains/resources.ts
|
|
7845
|
-
var ContractRefSchema = z.string().trim().min(1).max(500).regex(
|
|
7846
|
-
/^[A-Za-z0-9@](?:[A-Za-z0-9_./@-]*[A-Za-z0-9_])?\/?[A-Za-z0-9_./@-]*#[A-Za-z_$][A-Za-z0-9_$]*$/,
|
|
7847
|
-
"ContractRef must be in the format package/subpath#ExportName (e.g. @repo/elevasis-core/contracts/apollo-import#inputSchema)"
|
|
7848
|
-
);
|
|
7849
|
-
z.enum(["workflow", "agent", "integration", "script"]).meta({ label: "Resource kind", color: "orange" });
|
|
7850
|
-
var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Governance status", color: "teal" });
|
|
7851
|
-
var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "platform"]).meta({ label: "Agent kind", color: "violet" });
|
|
7852
|
-
var ScriptResourceLanguageSchema = z.enum(["shell", "sql", "typescript", "python"]).meta({ label: "Language" });
|
|
7853
|
-
var CodeReferenceRoleSchema = z.enum(["entrypoint", "handler", "schema", "test", "docs", "config"]).meta({ label: "Code reference role", color: "blue" });
|
|
7854
|
-
var ResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
|
|
7855
|
-
var EventIdSchema = z.string().trim().min(1).max(300).regex(
|
|
7856
|
-
/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*:[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
|
|
7857
|
-
"Event IDs must use <owner-id>:<event-key>"
|
|
7858
|
-
);
|
|
7859
|
-
var EventKeySchema = ModelIdSchema;
|
|
7860
|
-
var EventEmissionDescriptorSchema = z.object({
|
|
7861
|
-
eventKey: EventKeySchema,
|
|
7862
|
-
label: z.string().trim().min(1).max(120),
|
|
7863
|
-
payloadSchema: ModelIdSchema.optional(),
|
|
7864
|
-
lifecycle: SystemLifecycleSchema.optional()
|
|
7865
|
-
});
|
|
7866
|
-
EventEmissionDescriptorSchema.extend({
|
|
7867
|
-
id: EventIdSchema,
|
|
7868
|
-
ownerId: z.union([ResourceIdSchema, ModelIdSchema]),
|
|
7869
|
-
ownerKind: z.enum(["resource", "entity"]).meta({ label: "Owner kind" })
|
|
7870
|
-
});
|
|
7871
|
-
var ResourceOntologyBindingSchema = z.object({
|
|
7872
|
-
actions: z.array(OntologyIdSchema).optional(),
|
|
7873
|
-
primaryAction: OntologyIdSchema.optional(),
|
|
7874
|
-
reads: z.array(OntologyIdSchema).optional(),
|
|
7875
|
-
writes: z.array(OntologyIdSchema).optional(),
|
|
7876
|
-
usesCatalogs: z.array(OntologyIdSchema).optional(),
|
|
7877
|
-
emits: z.array(OntologyIdSchema).optional(),
|
|
7878
|
-
/**
|
|
7879
|
-
* Optional typed contract binding for this resource's workflow I/O.
|
|
7880
|
-
* Each ref is a `package/subpath#ExportName` string that resolves to a
|
|
7881
|
-
* Zod schema in `@repo/elevasis-core` (or the consumer's equivalent package).
|
|
7882
|
-
*
|
|
7883
|
-
* Absence of this field preserves all existing behavior — it is additive + optional.
|
|
7884
|
-
* Tier-1 validation (schema.ts): ref-string shape only (browser-safe, no imports).
|
|
7885
|
-
* Tier-2 validation (om:verify): intra-package typed-map resolution asserts ZodType.
|
|
7886
|
-
*/
|
|
7887
|
-
contract: z.object({
|
|
7888
|
-
input: ContractRefSchema.optional(),
|
|
7889
|
-
output: ContractRefSchema.optional()
|
|
7890
|
-
}).optional()
|
|
7891
|
-
}).superRefine((binding, ctx) => {
|
|
7892
|
-
if (binding.primaryAction === void 0) return;
|
|
7893
|
-
if (binding.actions?.includes(binding.primaryAction)) return;
|
|
7894
|
-
ctx.addIssue({
|
|
7895
|
-
code: z.ZodIssueCode.custom,
|
|
7896
|
-
path: ["primaryAction"],
|
|
7897
|
-
message: "Resource ontology primaryAction must be included in actions"
|
|
7898
|
-
});
|
|
7899
|
-
});
|
|
7900
|
-
var CodeReferenceSchema = z.object({
|
|
7901
|
-
path: z.string().trim().min(1).max(500).regex(/^[A-Za-z0-9_./$@()[\] -]+$/, "Code reference paths must be repo-relative paths"),
|
|
7902
|
-
role: CodeReferenceRoleSchema,
|
|
7903
|
-
symbol: z.string().trim().min(1).max(200).optional(),
|
|
7904
|
-
description: z.string().trim().min(1).max(300).optional()
|
|
7905
|
-
});
|
|
7906
|
-
var ResourceEntryBaseSchema = z.object({
|
|
7907
|
-
/** Canonical resource id; runtime resourceId derives from this value. */
|
|
7908
|
-
id: ResourceIdSchema,
|
|
7909
|
-
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
7910
|
-
order: z.number().default(0),
|
|
7911
|
-
/** Required single System membership — value is a dot-separated system path (e.g. "sales.lead-gen"). */
|
|
7912
|
-
systemPath: SystemPathSchema.meta({ ref: "system" }),
|
|
7913
|
-
/** Executable display title owned by the OM Resource descriptor. */
|
|
7914
|
-
title: LabelSchema.optional(),
|
|
7915
|
-
/** Executable display description owned by the OM Resource descriptor. */
|
|
7916
|
-
description: DescriptionSchema.optional(),
|
|
7917
|
-
/** Optional role responsible for maintaining this resource. */
|
|
7918
|
-
ownerRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
7919
|
-
status: ResourceGovernanceStatusSchema,
|
|
7920
|
-
/**
|
|
7921
|
-
* Ontology contract bindings for the semantic work this resource performs.
|
|
7922
|
-
* `emits` stays nested here so top-level resource emits descriptors remain
|
|
7923
|
-
* compatible with graph event projection during the bridge.
|
|
7924
|
-
*/
|
|
7925
|
-
ontology: ResourceOntologyBindingSchema.optional(),
|
|
7926
|
-
/** Repo-relative implementation breadcrumbs for agents and operators. */
|
|
7927
|
-
codeRefs: z.array(CodeReferenceSchema).default([])
|
|
7928
|
-
});
|
|
7929
|
-
var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
7930
|
-
kind: z.literal("workflow"),
|
|
7931
|
-
emits: z.array(EventEmissionDescriptorSchema).optional()
|
|
7932
|
-
});
|
|
7933
|
-
var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
7934
|
-
kind: z.literal("agent"),
|
|
7935
|
-
/** Mirrors code-side AgentConfig.kind. */
|
|
7936
|
-
agentKind: AgentKindSchema,
|
|
7937
|
-
/** Role this agent embodies, if any. */
|
|
7938
|
-
actsAsRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
7939
|
-
/** Mirrors AgentConfig.sessionCapable. */
|
|
7940
|
-
sessionCapable: z.boolean(),
|
|
7941
|
-
/** Broad/composite callable entry points orchestrated by this agent. */
|
|
7942
|
-
invocations: z.array(ActionInvocationSchema).default([]),
|
|
7943
|
-
emits: z.array(EventEmissionDescriptorSchema).optional()
|
|
7944
|
-
});
|
|
7945
|
-
var IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
7946
|
-
kind: z.literal("integration"),
|
|
7947
|
-
provider: z.string().trim().min(1).max(100)
|
|
7948
|
-
});
|
|
7949
|
-
var ScriptResourceSourceSchema = z.union([
|
|
7950
|
-
z.string().trim().min(1).max(5e4),
|
|
7951
|
-
z.object({
|
|
7952
|
-
file: z.string().trim().min(1).max(500)
|
|
7953
|
-
})
|
|
7954
|
-
]);
|
|
7955
|
-
var ScriptResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
7956
|
-
kind: z.literal("script"),
|
|
7957
|
-
language: ScriptResourceLanguageSchema,
|
|
7958
|
-
source: ScriptResourceSourceSchema
|
|
7959
|
-
});
|
|
7960
|
-
var ResourceEntrySchema = z.discriminatedUnion("kind", [
|
|
7961
|
-
WorkflowResourceEntrySchema,
|
|
7962
|
-
AgentResourceEntrySchema,
|
|
7963
|
-
IntegrationResourceEntrySchema,
|
|
7964
|
-
ScriptResourceEntrySchema
|
|
7965
|
-
]);
|
|
7966
|
-
var ResourcesDomainSchema = z.record(z.string(), ResourceEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
7967
|
-
message: "Each resource entry id must match its map key"
|
|
7968
|
-
}).default({});
|
|
7969
|
-
var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {};
|
|
7970
|
-
|
|
7971
|
-
// ../core/src/organization-model/domains/roles.ts
|
|
7972
|
-
var RoleIdSchema = ModelIdSchema;
|
|
7973
|
-
var HumanRoleHolderSchema = z.object({
|
|
7974
|
-
kind: z.literal("human"),
|
|
7975
|
-
userId: z.string().trim().min(1).max(200)
|
|
7976
|
-
});
|
|
7977
|
-
var AgentRoleHolderSchema = z.object({
|
|
7978
|
-
kind: z.literal("agent"),
|
|
7979
|
-
agentId: ResourceIdSchema.meta({ ref: "resource" })
|
|
7980
|
-
});
|
|
7981
|
-
var TeamRoleHolderSchema = z.object({
|
|
7982
|
-
kind: z.literal("team"),
|
|
7983
|
-
memberIds: z.array(z.string().trim().min(1).max(200)).min(1)
|
|
7984
|
-
});
|
|
7985
|
-
var RoleHolderSchema = z.discriminatedUnion("kind", [
|
|
7986
|
-
HumanRoleHolderSchema,
|
|
7987
|
-
AgentRoleHolderSchema,
|
|
7988
|
-
TeamRoleHolderSchema
|
|
7989
|
-
]);
|
|
7990
|
-
var RoleHoldersSchema = z.union([RoleHolderSchema, z.array(RoleHolderSchema).min(1)]);
|
|
7991
|
-
var RoleSchema = z.object({
|
|
7992
|
-
/** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
|
|
7993
|
-
id: RoleIdSchema,
|
|
7994
|
-
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
7995
|
-
order: z.number(),
|
|
7996
|
-
/** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
|
|
7997
|
-
title: z.string().trim().min(1).max(200),
|
|
7998
|
-
/**
|
|
7999
|
-
* List of responsibilities this role owns - plain-language descriptions of
|
|
8000
|
-
* what the person in this role is accountable for delivering.
|
|
8001
|
-
* Defaults to empty array so minimal role definitions stay concise.
|
|
8002
|
-
*/
|
|
8003
|
-
responsibilities: z.array(z.string().trim().max(500)).default([]),
|
|
8004
|
-
/**
|
|
8005
|
-
* Optional: ID of another role this role reports to.
|
|
8006
|
-
* When present, must reference another `roles[].id` in the same organization.
|
|
8007
|
-
*/
|
|
8008
|
-
reportsToId: RoleIdSchema.meta({ ref: "role" }).optional(),
|
|
8009
|
-
/**
|
|
8010
|
-
* Optional: human, agent, or team holder currently filling this role.
|
|
8011
|
-
* Agent holders reference OM Resource IDs and are validated at the model level.
|
|
8012
|
-
*/
|
|
8013
|
-
heldBy: RoleHoldersSchema.optional(),
|
|
8014
|
-
/**
|
|
8015
|
-
* Optional Systems this role is accountable for.
|
|
8016
|
-
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
8017
|
-
*/
|
|
8018
|
-
responsibleFor: z.array(SystemIdSchema.meta({ ref: "system" })).optional()
|
|
8019
|
-
});
|
|
8020
|
-
var RolesDomainSchema = z.record(z.string(), RoleSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
8021
|
-
message: "Each role entry id must match its map key"
|
|
8022
|
-
}).default({});
|
|
8023
|
-
var DEFAULT_ORGANIZATION_MODEL_ROLES = {};
|
|
8024
|
-
var KeyResultSchema = z.object({
|
|
8025
|
-
/** Stable unique identifier for the measurable outcome (e.g. "kr-revenue-q1"). */
|
|
8026
|
-
id: z.string().trim().min(1).max(100),
|
|
8027
|
-
/** Plain-language description of this measurable outcome (e.g. "Increase trial-to-paid conversion"). */
|
|
8028
|
-
description: z.string().trim().min(1).max(500),
|
|
8029
|
-
/**
|
|
8030
|
-
* What is being measured — the metric name (e.g. "monthly revenue", "NPS score",
|
|
8031
|
-
* "trial-to-paid conversion rate"). Free-form string.
|
|
8032
|
-
*/
|
|
8033
|
-
targetMetric: z.string().trim().min(1).max(200),
|
|
8034
|
-
/** Current measured value. Defaults to 0 when not yet tracked. */
|
|
8035
|
-
currentValue: z.number().default(0),
|
|
8036
|
-
/**
|
|
8037
|
-
* Target value to reach for this measurable outcome to be considered achieved.
|
|
8038
|
-
* Optional — omit if the outcome is directional (e.g. "reduce churn") without
|
|
8039
|
-
* a hard numeric target.
|
|
8040
|
-
*/
|
|
8041
|
-
targetValue: z.number().optional()
|
|
8042
|
-
});
|
|
8043
|
-
var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
8044
|
-
var ObjectiveSchema = z.object({
|
|
8045
|
-
/** Stable unique identifier for the goal (e.g. "goal-grow-arr-q1-2026"). */
|
|
8046
|
-
id: z.string().trim().min(1).max(100),
|
|
8047
|
-
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
8048
|
-
order: z.number(),
|
|
8049
|
-
/** Plain-language description of what the organization wants to achieve. */
|
|
8050
|
-
description: z.string().trim().min(1).max(1e3),
|
|
8051
|
-
/**
|
|
8052
|
-
* Start of the period this goal is active for — ISO 8601 date string (YYYY-MM-DD).
|
|
8053
|
-
* Must be strictly before `periodEnd`.
|
|
8054
|
-
*/
|
|
8055
|
-
periodStart: z.string().regex(ISO_DATE_REGEX, "periodStart must be an ISO date string (YYYY-MM-DD)"),
|
|
8056
|
-
/**
|
|
8057
|
-
* End of the period this goal is active for — ISO 8601 date string (YYYY-MM-DD).
|
|
8058
|
-
* Must be strictly after `periodStart`.
|
|
8059
|
-
* Enforced via `OrganizationModelSchema.superRefine()`.
|
|
8060
|
-
*/
|
|
8061
|
-
periodEnd: z.string().regex(ISO_DATE_REGEX, "periodEnd must be an ISO date string (YYYY-MM-DD)"),
|
|
8062
|
-
/**
|
|
8063
|
-
* List of measurable outcomes that define success for this goal.
|
|
8064
|
-
* Defaults to empty array so goals can be declared before outcomes are defined.
|
|
8065
|
-
*/
|
|
8066
|
-
keyResults: z.array(KeyResultSchema).default([])
|
|
8067
|
-
});
|
|
8068
|
-
var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
8069
|
-
message: "Each objective entry id must match its map key"
|
|
8070
|
-
}).default({});
|
|
8071
|
-
var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
|
|
8072
|
-
var SecretLikeMetadataKeySchema = /(?:secret|password|passwd|token|api[-_]?key|credential|private[-_]?key)/i;
|
|
8073
|
-
var SecretLikeMetadataValueSchema = /(?:sk-[A-Za-z0-9_-]{12,}|pk_live_[A-Za-z0-9_-]{12,}|eyJ[A-Za-z0-9_-]{20,}|-----BEGIN (?:RSA |OPENSSH |EC )?PRIVATE KEY-----)/;
|
|
8074
|
-
z.enum([
|
|
8075
|
-
"system",
|
|
8076
|
-
"resource",
|
|
8077
|
-
"ontology",
|
|
8078
|
-
"policy",
|
|
8079
|
-
"role",
|
|
8080
|
-
"trigger",
|
|
8081
|
-
"humanCheckpoint",
|
|
8082
|
-
"externalResource"
|
|
8083
|
-
]);
|
|
8084
|
-
var OmTopologyRelationshipKindSchema = z.enum(["triggers", "uses", "approval"]);
|
|
8085
|
-
var OmTopologyNodeRefSchema = z.discriminatedUnion("kind", [
|
|
8086
|
-
z.object({ kind: z.literal("system"), id: ModelIdSchema }),
|
|
8087
|
-
z.object({ kind: z.literal("resource"), id: ResourceIdSchema }),
|
|
8088
|
-
z.object({ kind: z.literal("ontology"), id: OntologyIdSchema }),
|
|
8089
|
-
z.object({ kind: z.literal("policy"), id: ModelIdSchema }),
|
|
8090
|
-
z.object({ kind: z.literal("role"), id: ModelIdSchema }),
|
|
8091
|
-
z.object({ kind: z.literal("trigger"), id: ResourceIdSchema }),
|
|
8092
|
-
z.object({ kind: z.literal("humanCheckpoint"), id: ResourceIdSchema }),
|
|
8093
|
-
z.object({ kind: z.literal("externalResource"), id: ResourceIdSchema })
|
|
8094
|
-
]);
|
|
8095
|
-
var OmTopologyMetadataSchema = z.record(z.string().trim().min(1).max(120), JsonValueSchema).superRefine((metadata, ctx) => {
|
|
8096
|
-
function visit(value, path) {
|
|
8097
|
-
if (typeof value === "string" && SecretLikeMetadataValueSchema.test(value)) {
|
|
8098
|
-
ctx.addIssue({
|
|
8099
|
-
code: z.ZodIssueCode.custom,
|
|
8100
|
-
path,
|
|
8101
|
-
message: "Topology metadata must not contain secret-like values"
|
|
8102
|
-
});
|
|
8103
|
-
return;
|
|
8104
|
-
}
|
|
8105
|
-
if (Array.isArray(value)) {
|
|
8106
|
-
value.forEach((entry, index2) => visit(entry, [...path, index2]));
|
|
8107
|
-
return;
|
|
8108
|
-
}
|
|
8109
|
-
if (typeof value !== "object" || value === null) return;
|
|
8110
|
-
Object.entries(value).forEach(([key, entry]) => {
|
|
8111
|
-
if (SecretLikeMetadataKeySchema.test(key)) {
|
|
8112
|
-
ctx.addIssue({
|
|
8113
|
-
code: z.ZodIssueCode.custom,
|
|
8114
|
-
path: [...path, key],
|
|
8115
|
-
message: `Topology metadata key "${key}" looks secret-like`
|
|
8116
|
-
});
|
|
8117
|
-
}
|
|
8118
|
-
visit(entry, [...path, key]);
|
|
8119
|
-
});
|
|
8120
|
-
}
|
|
8121
|
-
visit(metadata, []);
|
|
8122
|
-
});
|
|
8123
|
-
var OmTopologyRelationshipSchema = z.object({
|
|
8124
|
-
from: OmTopologyNodeRefSchema,
|
|
8125
|
-
kind: OmTopologyRelationshipKindSchema,
|
|
8126
|
-
to: OmTopologyNodeRefSchema,
|
|
8127
|
-
systemPath: SystemPathSchema.optional(),
|
|
8128
|
-
required: z.boolean().optional(),
|
|
8129
|
-
metadata: OmTopologyMetadataSchema.optional()
|
|
8130
|
-
});
|
|
8131
|
-
var OmTopologyDomainSchema = z.object({
|
|
8132
|
-
version: z.literal(1).default(1),
|
|
8133
|
-
relationships: z.record(z.string().trim().min(1).max(255), OmTopologyRelationshipSchema).default({})
|
|
8134
|
-
}).default({ version: 1, relationships: {} });
|
|
8135
|
-
var DEFAULT_ORGANIZATION_MODEL_TOPOLOGY = {
|
|
8136
|
-
version: 1,
|
|
8137
|
-
relationships: {}
|
|
8138
|
-
};
|
|
8139
|
-
var PolicyIdSchema = ModelIdSchema;
|
|
8140
|
-
var PolicyApplicabilitySchema = z.object({
|
|
8141
|
-
systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
|
|
8142
|
-
actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
|
|
8143
|
-
resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
|
|
8144
|
-
roleIds: z.array(ModelIdSchema.meta({ ref: "role" })).default([])
|
|
8145
|
-
});
|
|
8146
|
-
var PolicyTriggerSchema = z.discriminatedUnion("kind", [
|
|
8147
|
-
z.object({
|
|
8148
|
-
kind: z.literal("event"),
|
|
8149
|
-
eventId: EventIdSchema.meta({ ref: "event" })
|
|
8150
|
-
}),
|
|
8151
|
-
z.object({
|
|
8152
|
-
kind: z.literal("action-invocation"),
|
|
8153
|
-
actionId: ModelIdSchema.meta({ ref: "action" })
|
|
8154
|
-
}),
|
|
8155
|
-
z.object({
|
|
8156
|
-
kind: z.literal("schedule"),
|
|
8157
|
-
cron: z.string().trim().min(1).max(120)
|
|
8158
|
-
}),
|
|
8159
|
-
z.object({
|
|
8160
|
-
kind: z.literal("manual")
|
|
8161
|
-
})
|
|
8162
|
-
]);
|
|
8163
|
-
var PolicyPredicateSchema = z.discriminatedUnion("kind", [
|
|
8164
|
-
z.object({
|
|
8165
|
-
kind: z.literal("always")
|
|
8166
|
-
}),
|
|
8167
|
-
z.object({
|
|
8168
|
-
kind: z.literal("expression"),
|
|
8169
|
-
expression: z.string().trim().min(1).max(2e3)
|
|
8170
|
-
}),
|
|
8171
|
-
z.object({
|
|
8172
|
-
kind: z.literal("threshold"),
|
|
8173
|
-
metric: ModelIdSchema,
|
|
8174
|
-
operator: z.enum(["lt", "lte", "eq", "gte", "gt"]).meta({ label: "Operator" }),
|
|
8175
|
-
value: z.number()
|
|
8176
|
-
})
|
|
8177
|
-
]);
|
|
8178
|
-
var PolicyEffectSchema = z.discriminatedUnion("kind", [
|
|
8179
|
-
z.object({
|
|
8180
|
-
kind: z.literal("require-approval"),
|
|
8181
|
-
roleId: ModelIdSchema.meta({ ref: "role" }).optional()
|
|
8182
|
-
}),
|
|
8183
|
-
z.object({
|
|
8184
|
-
kind: z.literal("invoke-action"),
|
|
8185
|
-
actionId: ModelIdSchema.meta({ ref: "action" })
|
|
8186
|
-
}),
|
|
8187
|
-
z.object({
|
|
8188
|
-
kind: z.literal("notify-role"),
|
|
8189
|
-
roleId: ModelIdSchema.meta({ ref: "role" })
|
|
8190
|
-
}),
|
|
8191
|
-
z.object({
|
|
8192
|
-
kind: z.literal("block")
|
|
8193
|
-
})
|
|
8194
|
-
]);
|
|
8195
|
-
var PolicySchema = z.object({
|
|
8196
|
-
id: PolicyIdSchema,
|
|
8197
|
-
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
8198
|
-
order: z.number(),
|
|
8199
|
-
label: LabelSchema,
|
|
8200
|
-
description: DescriptionSchema.optional(),
|
|
8201
|
-
trigger: PolicyTriggerSchema,
|
|
8202
|
-
predicate: PolicyPredicateSchema.default({ kind: "always" }),
|
|
8203
|
-
actions: z.array(PolicyEffectSchema).min(1),
|
|
8204
|
-
appliesTo: PolicyApplicabilitySchema.default({
|
|
8205
|
-
systemIds: [],
|
|
8206
|
-
actionIds: [],
|
|
8207
|
-
resourceIds: [],
|
|
8208
|
-
roleIds: []
|
|
8209
|
-
}),
|
|
8210
|
-
lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
|
|
8211
|
-
});
|
|
8212
|
-
var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
8213
|
-
message: "Each policy entry id must match its map key"
|
|
8214
|
-
}).default({});
|
|
8215
|
-
var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
|
|
8216
|
-
var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
|
|
8217
|
-
z.object({
|
|
8218
|
-
id: ModelIdSchema,
|
|
8219
|
-
label: LabelSchema,
|
|
8220
|
-
path: PathSchema,
|
|
8221
|
-
surfaceType: SurfaceTypeSchema,
|
|
8222
|
-
description: DescriptionSchema.optional(),
|
|
8223
|
-
enabled: z.boolean().default(true),
|
|
8224
|
-
devOnly: z.boolean().optional(),
|
|
8225
|
-
icon: IconNameSchema.optional(),
|
|
8226
|
-
systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
|
|
8227
|
-
entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
|
|
8228
|
-
resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
|
|
8229
|
-
actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
|
|
8230
|
-
parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
|
|
8231
|
-
});
|
|
8232
|
-
var SidebarSurfaceTargetsSchema = z.object({
|
|
8233
|
-
systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
|
|
8234
|
-
entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
|
|
8235
|
-
resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
|
|
8236
|
-
actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
|
|
8237
|
-
}).default({});
|
|
8238
|
-
var SidebarNodeSchema = z.lazy(
|
|
8239
|
-
() => z.discriminatedUnion("type", [
|
|
8240
|
-
z.object({
|
|
8241
|
-
type: z.literal("group"),
|
|
8242
|
-
label: LabelSchema,
|
|
8243
|
-
description: DescriptionSchema.optional(),
|
|
8244
|
-
icon: IconNameSchema.optional(),
|
|
8245
|
-
order: z.number().int().optional(),
|
|
8246
|
-
children: z.record(z.string(), SidebarNodeSchema).default({})
|
|
8247
|
-
}),
|
|
8248
|
-
z.object({
|
|
8249
|
-
type: z.literal("surface"),
|
|
8250
|
-
label: LabelSchema,
|
|
8251
|
-
path: PathSchema,
|
|
8252
|
-
surfaceType: SurfaceTypeSchema,
|
|
8253
|
-
description: DescriptionSchema.optional(),
|
|
8254
|
-
icon: IconNameSchema.optional(),
|
|
8255
|
-
order: z.number().int().optional(),
|
|
8256
|
-
targets: SidebarSurfaceTargetsSchema.optional(),
|
|
8257
|
-
devOnly: z.boolean().optional(),
|
|
8258
|
-
requiresAdmin: z.boolean().optional()
|
|
8259
|
-
})
|
|
8260
|
-
])
|
|
8261
|
-
);
|
|
8262
|
-
var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
|
|
8263
|
-
var SidebarNavigationSchema = z.object({
|
|
8264
|
-
primary: SidebarSectionSchema,
|
|
8265
|
-
bottom: SidebarSectionSchema
|
|
8266
|
-
}).default({ primary: {}, bottom: {} });
|
|
8267
|
-
var OrganizationModelNavigationSchema = z.object({
|
|
8268
|
-
sidebar: SidebarNavigationSchema
|
|
8269
|
-
}).default({ sidebar: { primary: {}, bottom: {} } });
|
|
8270
|
-
z.object({
|
|
8271
|
-
id: ModelIdSchema,
|
|
8272
|
-
label: LabelSchema,
|
|
8273
|
-
placement: z.string().trim().min(1).max(50),
|
|
8274
|
-
surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
|
|
8275
|
-
});
|
|
8276
|
-
var KnowledgeTargetKindSchema = z.enum([
|
|
8277
|
-
"system",
|
|
8278
|
-
"resource",
|
|
8279
|
-
"knowledge",
|
|
8280
|
-
"stage",
|
|
8281
|
-
"action",
|
|
8282
|
-
"role",
|
|
8283
|
-
"goal",
|
|
8284
|
-
"customer-segment",
|
|
8285
|
-
"offering",
|
|
8286
|
-
"ontology"
|
|
8287
|
-
]).meta({ label: "Target kind" });
|
|
8288
|
-
var KnowledgeTargetRefSchema = z.object({
|
|
8289
|
-
kind: KnowledgeTargetKindSchema,
|
|
8290
|
-
// Ontology targets use the canonical '<scope>:<kind>/<local-id>' ontology id format.
|
|
8291
|
-
// Business-logic validation of target existence is done in OrganizationModelSchema.superRefine.
|
|
8292
|
-
id: z.string().trim().min(1).max(300)
|
|
8293
|
-
}).superRefine((target, ctx) => {
|
|
8294
|
-
if (target.kind !== "ontology") return;
|
|
8295
|
-
const result = OntologyIdSchema.safeParse(target.id);
|
|
8296
|
-
if (!result.success) {
|
|
8297
|
-
ctx.addIssue({
|
|
8298
|
-
code: z.ZodIssueCode.custom,
|
|
8299
|
-
path: ["id"],
|
|
8300
|
-
message: "Ontology knowledge targets must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
|
|
8301
|
-
});
|
|
8302
|
-
}
|
|
8303
|
-
});
|
|
8304
|
-
var LegacyKnowledgeLinkSchema = z.object({
|
|
8305
|
-
nodeId: z.union([NodeIdStringSchema, z.templateLiteral(["ontology:", OntologyIdSchema])])
|
|
8306
|
-
}).superRefine((link, ctx) => {
|
|
8307
|
-
const [kind] = link.nodeId.split(":");
|
|
8308
|
-
if (!KnowledgeTargetKindSchema.safeParse(kind).success) {
|
|
8309
|
-
ctx.addIssue({
|
|
8310
|
-
code: z.ZodIssueCode.custom,
|
|
8311
|
-
path: ["nodeId"],
|
|
8312
|
-
message: `Unknown knowledge target kind "${kind}"`
|
|
8313
|
-
});
|
|
8314
|
-
}
|
|
8315
|
-
});
|
|
8316
|
-
var CanonicalKnowledgeLinkSchema = z.object({
|
|
8317
|
-
target: KnowledgeTargetRefSchema
|
|
8318
|
-
});
|
|
8319
|
-
function nodeIdFromTarget(target) {
|
|
8320
|
-
return `${target.kind}:${target.id}`;
|
|
8321
|
-
}
|
|
8322
|
-
function targetFromNodeId(nodeId) {
|
|
8323
|
-
const [kind, ...idParts] = nodeId.split(":");
|
|
8324
|
-
return {
|
|
8325
|
-
kind: KnowledgeTargetKindSchema.parse(kind),
|
|
8326
|
-
id: idParts.join(":")
|
|
8327
|
-
};
|
|
8328
|
-
}
|
|
8329
|
-
var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
|
|
8330
|
-
const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
|
|
8331
|
-
return {
|
|
8332
|
-
target,
|
|
8333
|
-
nodeId: nodeIdFromTarget(target)
|
|
8334
|
-
};
|
|
8335
|
-
});
|
|
8336
|
-
var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
|
|
8337
|
-
var OrgKnowledgeNodeSchema = z.object({
|
|
8338
|
-
id: ModelIdSchema,
|
|
8339
|
-
kind: OrgKnowledgeKindSchema,
|
|
8340
|
-
title: z.string().trim().min(1).max(200),
|
|
8341
|
-
summary: z.string().trim().min(1).max(1e3),
|
|
8342
|
-
icon: IconNameSchema.optional(),
|
|
8343
|
-
/** Canonical documentation URL when body content is a local summary. */
|
|
8344
|
-
externalUrl: z.string().trim().url().max(500).optional(),
|
|
8345
|
-
/** Optional generated source file path for local MDX-backed knowledge nodes. */
|
|
8346
|
-
sourceFilePath: z.string().trim().min(1).max(500).optional(),
|
|
8347
|
-
/** Raw MDX string. Phase 2 will introduce a structured block format. */
|
|
8348
|
-
body: z.string().trim().min(1),
|
|
8349
|
-
/**
|
|
8350
|
-
* Graph links to other OM nodes this knowledge node governs.
|
|
8351
|
-
* Each link emits a `governs` edge: knowledge-node -> target node.
|
|
8352
|
-
*/
|
|
8353
|
-
links: z.array(KnowledgeLinkSchema).default([]),
|
|
8354
|
-
/** Role identifiers that own this knowledge node. */
|
|
8355
|
-
ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
|
|
8356
|
-
/** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
|
|
8357
|
-
updatedAt: z.string().trim().min(1).max(50)
|
|
8358
|
-
});
|
|
8359
|
-
var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
|
|
8360
|
-
|
|
8361
|
-
// ../core/src/organization-model/schema.ts
|
|
8362
|
-
z.enum([
|
|
8363
|
-
"branding",
|
|
8364
|
-
"identity",
|
|
8365
|
-
"customers",
|
|
8366
|
-
"offerings",
|
|
8367
|
-
"roles",
|
|
8368
|
-
"goals",
|
|
8369
|
-
"systems",
|
|
8370
|
-
"ontology",
|
|
8371
|
-
"resources",
|
|
8372
|
-
"topology",
|
|
8373
|
-
"actions",
|
|
8374
|
-
"entities",
|
|
8375
|
-
"policies",
|
|
8376
|
-
"knowledge"
|
|
8377
|
-
]);
|
|
8378
|
-
var OrganizationModelDomainMetadataSchema = z.object({
|
|
8379
|
-
version: z.literal(1).default(1),
|
|
8380
|
-
lastModified: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "lastModified must be an ISO date string (YYYY-MM-DD)")
|
|
8381
|
-
});
|
|
8382
|
-
var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
|
|
8383
|
-
branding: { version: 1, lastModified: "2026-05-10" },
|
|
8384
|
-
identity: { version: 1, lastModified: "2026-05-10" },
|
|
8385
|
-
customers: { version: 1, lastModified: "2026-05-10" },
|
|
8386
|
-
offerings: { version: 1, lastModified: "2026-05-10" },
|
|
8387
|
-
roles: { version: 1, lastModified: "2026-05-10" },
|
|
8388
|
-
goals: { version: 1, lastModified: "2026-05-10" },
|
|
8389
|
-
systems: { version: 1, lastModified: "2026-05-10" },
|
|
8390
|
-
ontology: { version: 1, lastModified: "2026-05-14" },
|
|
8391
|
-
resources: { version: 1, lastModified: "2026-05-10" },
|
|
8392
|
-
topology: { version: 1, lastModified: "2026-05-14" },
|
|
8393
|
-
actions: { version: 1, lastModified: "2026-05-10" },
|
|
8394
|
-
entities: { version: 1, lastModified: "2026-05-10" },
|
|
8395
|
-
policies: { version: 1, lastModified: "2026-05-10" },
|
|
8396
|
-
knowledge: { version: 1, lastModified: "2026-05-10" }
|
|
8397
|
-
};
|
|
8398
|
-
var OrganizationModelDomainMetadataByDomainSchema = z.object({
|
|
8399
|
-
branding: OrganizationModelDomainMetadataSchema,
|
|
8400
|
-
identity: OrganizationModelDomainMetadataSchema,
|
|
8401
|
-
customers: OrganizationModelDomainMetadataSchema,
|
|
8402
|
-
offerings: OrganizationModelDomainMetadataSchema,
|
|
8403
|
-
roles: OrganizationModelDomainMetadataSchema,
|
|
8404
|
-
goals: OrganizationModelDomainMetadataSchema,
|
|
8405
|
-
systems: OrganizationModelDomainMetadataSchema,
|
|
8406
|
-
ontology: OrganizationModelDomainMetadataSchema,
|
|
8407
|
-
resources: OrganizationModelDomainMetadataSchema,
|
|
8408
|
-
topology: OrganizationModelDomainMetadataSchema,
|
|
8409
|
-
actions: OrganizationModelDomainMetadataSchema,
|
|
8410
|
-
entities: OrganizationModelDomainMetadataSchema,
|
|
8411
|
-
policies: OrganizationModelDomainMetadataSchema,
|
|
8412
|
-
knowledge: OrganizationModelDomainMetadataSchema
|
|
8413
|
-
}).partial().default(DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA).transform((metadata) => ({ ...DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, ...metadata }));
|
|
8414
|
-
var OrganizationModelSchemaBase = z.object({
|
|
8415
|
-
version: z.literal(1).default(1),
|
|
8416
|
-
domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
|
|
8417
|
-
branding: OrganizationModelBrandingSchema,
|
|
8418
|
-
navigation: OrganizationModelNavigationSchema,
|
|
8419
|
-
identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
|
|
8420
|
-
customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
|
|
8421
|
-
offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
|
|
8422
|
-
roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
|
|
8423
|
-
goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
|
|
8424
|
-
systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
|
|
8425
|
-
ontology: OntologyScopeSchema.default(DEFAULT_ONTOLOGY_SCOPE),
|
|
8426
|
-
resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
|
|
8427
|
-
topology: OmTopologyDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_TOPOLOGY),
|
|
8428
|
-
actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
|
|
8429
|
-
entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
|
|
8430
|
-
policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
|
|
8431
|
-
// D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
|
|
8432
|
-
knowledge: KnowledgeDomainSchema.default({})
|
|
8433
|
-
});
|
|
8434
|
-
function addIssue(ctx, path, message) {
|
|
8435
|
-
ctx.addIssue({
|
|
8436
|
-
code: z.ZodIssueCode.custom,
|
|
8437
|
-
path,
|
|
8438
|
-
message
|
|
8439
|
-
});
|
|
8440
|
-
}
|
|
8441
|
-
function isLifecycleEnabled(lifecycle, enabled) {
|
|
8442
|
-
if (enabled === false) return false;
|
|
8443
|
-
return lifecycle !== "deprecated" && lifecycle !== "archived";
|
|
8444
|
-
}
|
|
8445
|
-
function defaultSystemPathFor(id) {
|
|
8446
|
-
return `/${id.replaceAll(".", "/")}`;
|
|
8447
|
-
}
|
|
8448
|
-
function asRoleHolderArray(heldBy) {
|
|
8449
|
-
return Array.isArray(heldBy) ? heldBy : [heldBy];
|
|
8450
|
-
}
|
|
8451
|
-
function isKnowledgeKindCompatibleWithTarget(knowledgeKind, targetKind) {
|
|
8452
|
-
if (knowledgeKind === "reference") return true;
|
|
8453
|
-
if (knowledgeKind === "playbook") {
|
|
8454
|
-
return ["system", "resource", "stage", "action", "ontology"].includes(targetKind);
|
|
8455
|
-
}
|
|
8456
|
-
if (knowledgeKind === "strategy") {
|
|
8457
|
-
return ["system", "goal", "offering", "customer-segment", "ontology"].includes(targetKind);
|
|
8458
|
-
}
|
|
8459
|
-
return false;
|
|
8460
|
-
}
|
|
8461
|
-
function isRecord(value) {
|
|
8462
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8463
|
-
}
|
|
8464
|
-
OrganizationModelSchemaBase.superRefine((model, ctx) => {
|
|
8465
|
-
function collectAllSystems(systems, prefix = "", schemaPath = ["systems"]) {
|
|
8466
|
-
const result = [];
|
|
8467
|
-
for (const [key, system] of Object.entries(systems)) {
|
|
8468
|
-
const path = prefix ? `${prefix}.${key}` : key;
|
|
8469
|
-
const currentSchemaPath = [...schemaPath, key];
|
|
8470
|
-
result.push({ path, schemaPath: currentSchemaPath, system });
|
|
8471
|
-
const childSystems = system.systems ?? system.subsystems;
|
|
8472
|
-
if (childSystems !== void 0) {
|
|
8473
|
-
result.push(
|
|
8474
|
-
...collectAllSystems(childSystems, path, [
|
|
8475
|
-
...currentSchemaPath,
|
|
8476
|
-
system.systems !== void 0 ? "systems" : "subsystems"
|
|
8477
|
-
])
|
|
8478
|
-
);
|
|
8479
|
-
}
|
|
8480
|
-
}
|
|
8481
|
-
return result;
|
|
8482
|
-
}
|
|
8483
|
-
const allSystems = collectAllSystems(model.systems);
|
|
8484
|
-
const systemsById = /* @__PURE__ */ new Map();
|
|
8485
|
-
for (const { path, system } of allSystems) {
|
|
8486
|
-
systemsById.set(path, system);
|
|
8487
|
-
systemsById.set(system.id, system);
|
|
8488
|
-
}
|
|
8489
|
-
const systemIdsByEffectivePath = /* @__PURE__ */ new Map();
|
|
8490
|
-
allSystems.forEach(({ path, schemaPath, system }) => {
|
|
8491
|
-
if (system.parentSystemId !== void 0 && !systemsById.has(system.parentSystemId)) {
|
|
8492
|
-
addIssue(
|
|
8493
|
-
ctx,
|
|
8494
|
-
[...schemaPath, "parentSystemId"],
|
|
8495
|
-
`System "${system.id}" references unknown parent "${system.parentSystemId}"`
|
|
8496
|
-
);
|
|
8497
|
-
}
|
|
8498
|
-
const hasChildren = Object.keys(system.systems ?? system.subsystems ?? {}).length > 0 || allSystems.some(
|
|
8499
|
-
(candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".")
|
|
8500
|
-
);
|
|
8501
|
-
const contributesRoutePath = system.ui?.path !== void 0 || system.path !== void 0 || !hasChildren;
|
|
8502
|
-
if (contributesRoutePath) {
|
|
8503
|
-
const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path);
|
|
8504
|
-
const existingSystemId = systemIdsByEffectivePath.get(effectivePath);
|
|
8505
|
-
if (existingSystemId !== void 0) {
|
|
8506
|
-
addIssue(
|
|
8507
|
-
ctx,
|
|
8508
|
-
[...schemaPath, system.ui?.path !== void 0 ? "ui" : "path"],
|
|
8509
|
-
`System "${path}" effective path "${effectivePath}" duplicates system "${existingSystemId}"`
|
|
8510
|
-
);
|
|
8511
|
-
} else {
|
|
8512
|
-
systemIdsByEffectivePath.set(effectivePath, path);
|
|
8513
|
-
}
|
|
8514
|
-
}
|
|
8515
|
-
if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
|
|
8516
|
-
const hasEnabledDescendant = Object.values(system.systems ?? system.subsystems ?? {}).some(
|
|
8517
|
-
(candidate) => isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
|
|
8518
|
-
) || allSystems.some(
|
|
8519
|
-
(candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
|
|
8520
|
-
);
|
|
8521
|
-
if (!hasEnabledDescendant) {
|
|
8522
|
-
addIssue(ctx, [...schemaPath, "lifecycle"], `System "${path}" is active but has no active descendants`);
|
|
8523
|
-
}
|
|
8524
|
-
}
|
|
8525
|
-
});
|
|
8526
|
-
allSystems.forEach(({ schemaPath, system }) => {
|
|
8527
|
-
const visited = /* @__PURE__ */ new Set();
|
|
8528
|
-
let currentParentId = system.parentSystemId;
|
|
8529
|
-
while (currentParentId !== void 0) {
|
|
8530
|
-
if (currentParentId === system.id || visited.has(currentParentId)) {
|
|
8531
|
-
addIssue(ctx, [...schemaPath, "parentSystemId"], `System "${system.id}" has a parent cycle`);
|
|
8532
|
-
return;
|
|
8533
|
-
}
|
|
8534
|
-
visited.add(currentParentId);
|
|
8535
|
-
currentParentId = systemsById.get(currentParentId)?.parentSystemId;
|
|
8536
|
-
}
|
|
8537
|
-
});
|
|
8538
|
-
function normalizeRoutePath(path) {
|
|
8539
|
-
return path.length > 1 ? path.replace(/\/+$/, "") : path;
|
|
8540
|
-
}
|
|
8541
|
-
const sidebarNodeIds = /* @__PURE__ */ new Map();
|
|
8542
|
-
const sidebarSurfacePaths = /* @__PURE__ */ new Map();
|
|
8543
|
-
const sidebarSurfaces = [];
|
|
8544
|
-
function collectSidebarNodes(nodes, schemaPath) {
|
|
8545
|
-
Object.entries(nodes).forEach(([nodeId, node]) => {
|
|
8546
|
-
const nodePath = [...schemaPath, nodeId];
|
|
8547
|
-
const existingNodePath = sidebarNodeIds.get(nodeId);
|
|
8548
|
-
if (existingNodePath !== void 0) {
|
|
8549
|
-
addIssue(ctx, nodePath, `Sidebar node id "${nodeId}" duplicates another sidebar node`);
|
|
8550
|
-
} else {
|
|
8551
|
-
sidebarNodeIds.set(nodeId, nodePath);
|
|
8552
|
-
}
|
|
8553
|
-
if (node.type === "group") {
|
|
8554
|
-
collectSidebarNodes(node.children, [...nodePath, "children"]);
|
|
8555
|
-
return;
|
|
8556
|
-
}
|
|
8557
|
-
sidebarSurfaces.push({ id: nodeId, node, path: nodePath });
|
|
8558
|
-
const normalizedPath = normalizeRoutePath(node.path);
|
|
8559
|
-
const existingSurfaceId = sidebarSurfacePaths.get(normalizedPath);
|
|
8560
|
-
if (existingSurfaceId !== void 0) {
|
|
8561
|
-
addIssue(
|
|
8562
|
-
ctx,
|
|
8563
|
-
[...nodePath, "path"],
|
|
8564
|
-
`Sidebar surface path "${node.path}" duplicates surface "${existingSurfaceId}"`
|
|
8565
|
-
);
|
|
8566
|
-
} else {
|
|
8567
|
-
sidebarSurfacePaths.set(normalizedPath, nodeId);
|
|
8568
|
-
}
|
|
8569
|
-
node.targets?.systems?.forEach((systemId, systemIndex) => {
|
|
8570
|
-
if (!systemsById.has(systemId)) {
|
|
8571
|
-
addIssue(
|
|
8572
|
-
ctx,
|
|
8573
|
-
[...nodePath, "targets", "systems", systemIndex],
|
|
8574
|
-
`Sidebar surface "${nodeId}" references unknown system "${systemId}"`
|
|
8575
|
-
);
|
|
8576
|
-
}
|
|
8577
|
-
});
|
|
8578
|
-
});
|
|
8579
|
-
}
|
|
8580
|
-
collectSidebarNodes(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]);
|
|
8581
|
-
collectSidebarNodes(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"]);
|
|
8582
|
-
const segmentsById = new Map(Object.entries(model.customers));
|
|
8583
|
-
Object.values(model.offerings).forEach((product) => {
|
|
8584
|
-
product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
|
|
8585
|
-
if (!segmentsById.has(segmentId)) {
|
|
8586
|
-
addIssue(
|
|
8587
|
-
ctx,
|
|
8588
|
-
["offerings", product.id, "targetSegmentIds", segmentIndex],
|
|
8589
|
-
`Product "${product.id}" references unknown customer segment "${segmentId}"`
|
|
8590
|
-
);
|
|
8591
|
-
}
|
|
8592
|
-
});
|
|
8593
|
-
if (product.deliveryFeatureId !== void 0 && !systemsById.has(product.deliveryFeatureId)) {
|
|
8594
|
-
addIssue(
|
|
8595
|
-
ctx,
|
|
8596
|
-
["offerings", product.id, "deliveryFeatureId"],
|
|
8597
|
-
`Product "${product.id}" references unknown delivery system "${product.deliveryFeatureId}"`
|
|
8598
|
-
);
|
|
8599
|
-
}
|
|
8600
|
-
});
|
|
8601
|
-
Object.values(model.goals).forEach((objective) => {
|
|
8602
|
-
if (objective.periodEnd <= objective.periodStart) {
|
|
8603
|
-
addIssue(
|
|
8604
|
-
ctx,
|
|
8605
|
-
["goals", objective.id, "periodEnd"],
|
|
8606
|
-
`Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
|
|
8607
|
-
);
|
|
8608
|
-
}
|
|
8609
|
-
});
|
|
8610
|
-
const goalsById = new Map(Object.entries(model.goals));
|
|
8611
|
-
const knowledgeById = new Map(Object.entries(model.knowledge));
|
|
8612
|
-
const actionsById = new Map(Object.entries(model.actions));
|
|
8613
|
-
const entitiesById = new Map(Object.entries(model.entities));
|
|
8614
|
-
const policiesById = new Map(Object.entries(model.policies));
|
|
8615
|
-
sidebarSurfaces.forEach(({ id, node, path }) => {
|
|
8616
|
-
node.targets?.entities?.forEach((entityId, entityIndex) => {
|
|
8617
|
-
if (!entitiesById.has(entityId)) {
|
|
8618
|
-
addIssue(
|
|
8619
|
-
ctx,
|
|
8620
|
-
[...path, "targets", "entities", entityIndex],
|
|
8621
|
-
`Sidebar surface "${id}" references unknown entity "${entityId}"`
|
|
8622
|
-
);
|
|
8623
|
-
}
|
|
8624
|
-
});
|
|
8625
|
-
node.targets?.actions?.forEach((actionId, actionIndex) => {
|
|
8626
|
-
if (!actionsById.has(actionId)) {
|
|
8627
|
-
addIssue(
|
|
8628
|
-
ctx,
|
|
8629
|
-
[...path, "targets", "actions", actionIndex],
|
|
8630
|
-
`Sidebar surface "${id}" references unknown action "${actionId}"`
|
|
8631
|
-
);
|
|
8632
|
-
}
|
|
8633
|
-
});
|
|
8634
|
-
});
|
|
8635
|
-
Object.values(model.entities).forEach((entity) => {
|
|
8636
|
-
if (!systemsById.has(entity.ownedBySystemId)) {
|
|
8637
|
-
addIssue(
|
|
8638
|
-
ctx,
|
|
8639
|
-
["entities", entity.id, "ownedBySystemId"],
|
|
8640
|
-
`Entity "${entity.id}" references unknown ownedBySystemId "${entity.ownedBySystemId}"`
|
|
8641
|
-
);
|
|
8642
|
-
}
|
|
8643
|
-
entity.links?.forEach((link, linkIndex) => {
|
|
8644
|
-
if (!entitiesById.has(link.toEntity)) {
|
|
8645
|
-
addIssue(
|
|
8646
|
-
ctx,
|
|
8647
|
-
["entities", entity.id, "links", linkIndex, "toEntity"],
|
|
8648
|
-
`Entity "${entity.id}" links to unknown entity "${link.toEntity}"`
|
|
8649
|
-
);
|
|
8650
|
-
}
|
|
8651
|
-
});
|
|
8652
|
-
});
|
|
8653
|
-
const rolesById = new Map(Object.entries(model.roles));
|
|
8654
|
-
Object.values(model.roles).forEach((role) => {
|
|
8655
|
-
if (role.reportsToId !== void 0 && !rolesById.has(role.reportsToId)) {
|
|
8656
|
-
addIssue(
|
|
8657
|
-
ctx,
|
|
8658
|
-
["roles", role.id, "reportsToId"],
|
|
8659
|
-
`Role "${role.id}" references unknown reportsToId "${role.reportsToId}"`
|
|
8660
|
-
);
|
|
8661
|
-
}
|
|
8662
|
-
});
|
|
8663
|
-
Object.values(model.roles).forEach((role) => {
|
|
8664
|
-
const visited = /* @__PURE__ */ new Set();
|
|
8665
|
-
let currentReportsToId = role.reportsToId;
|
|
8666
|
-
while (currentReportsToId !== void 0) {
|
|
8667
|
-
if (currentReportsToId === role.id || visited.has(currentReportsToId)) {
|
|
8668
|
-
addIssue(ctx, ["roles", role.id, "reportsToId"], `Role "${role.id}" has a reportsToId cycle`);
|
|
8669
|
-
return;
|
|
8670
|
-
}
|
|
8671
|
-
visited.add(currentReportsToId);
|
|
8672
|
-
currentReportsToId = rolesById.get(currentReportsToId)?.reportsToId;
|
|
8673
|
-
}
|
|
8674
|
-
});
|
|
8675
|
-
Object.values(model.roles).forEach((role) => {
|
|
8676
|
-
role.responsibleFor?.forEach((systemId, systemIndex) => {
|
|
8677
|
-
if (!systemsById.has(systemId)) {
|
|
8678
|
-
addIssue(
|
|
8679
|
-
ctx,
|
|
8680
|
-
["roles", role.id, "responsibleFor", systemIndex],
|
|
8681
|
-
`Role "${role.id}" references unknown responsibleFor system "${systemId}"`
|
|
8682
|
-
);
|
|
8683
|
-
}
|
|
8684
|
-
});
|
|
8685
|
-
});
|
|
8686
|
-
allSystems.forEach(({ schemaPath, system }) => {
|
|
8687
|
-
if (system.responsibleRoleId !== void 0 && !rolesById.has(system.responsibleRoleId)) {
|
|
8688
|
-
addIssue(
|
|
8689
|
-
ctx,
|
|
8690
|
-
[...schemaPath, "responsibleRoleId"],
|
|
8691
|
-
`System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
|
|
8692
|
-
);
|
|
8693
|
-
}
|
|
8694
|
-
system.governedByKnowledge?.forEach((nodeId, nodeIndex) => {
|
|
8695
|
-
if (!knowledgeById.has(nodeId)) {
|
|
8696
|
-
addIssue(
|
|
8697
|
-
ctx,
|
|
8698
|
-
[...schemaPath, "governedByKnowledge", nodeIndex],
|
|
8699
|
-
`System "${system.id}" references unknown knowledge node "${nodeId}"`
|
|
8700
|
-
);
|
|
8701
|
-
}
|
|
8702
|
-
});
|
|
8703
|
-
system.drivesGoals?.forEach((goalId, goalIndex) => {
|
|
8704
|
-
if (!goalsById.has(goalId)) {
|
|
8705
|
-
addIssue(
|
|
8706
|
-
ctx,
|
|
8707
|
-
[...schemaPath, "drivesGoals", goalIndex],
|
|
8708
|
-
`System "${system.id}" references unknown goal "${goalId}"`
|
|
8709
|
-
);
|
|
8710
|
-
}
|
|
8711
|
-
});
|
|
8712
|
-
system.actions?.forEach((actionRef, actionIndex) => {
|
|
8713
|
-
if (!actionsById.has(actionRef.actionId)) {
|
|
8714
|
-
addIssue(
|
|
8715
|
-
ctx,
|
|
8716
|
-
[...schemaPath, "actions", actionIndex, "actionId"],
|
|
8717
|
-
`System "${system.id}" references unknown action "${actionRef.actionId}"`
|
|
8718
|
-
);
|
|
8719
|
-
}
|
|
8720
|
-
});
|
|
8721
|
-
system.policies?.forEach((policyId, policyIndex) => {
|
|
8722
|
-
if (!policiesById.has(policyId)) {
|
|
8723
|
-
addIssue(
|
|
8724
|
-
ctx,
|
|
8725
|
-
[...schemaPath, "policies", policyIndex],
|
|
8726
|
-
`System "${system.id}" references unknown policy "${policyId}"`
|
|
8727
|
-
);
|
|
8728
|
-
}
|
|
8729
|
-
});
|
|
8730
|
-
});
|
|
8731
|
-
Object.values(model.actions).forEach((action) => {
|
|
8732
|
-
action.affects?.forEach((entityId, entityIndex) => {
|
|
8733
|
-
if (!entitiesById.has(entityId)) {
|
|
8734
|
-
addIssue(
|
|
8735
|
-
ctx,
|
|
8736
|
-
["actions", action.id, "affects", entityIndex],
|
|
8737
|
-
`Action "${action.id}" affects unknown entity "${entityId}"`
|
|
8738
|
-
);
|
|
8739
|
-
}
|
|
8740
|
-
});
|
|
8741
|
-
});
|
|
8742
|
-
const resourcesById = new Map(Object.entries(model.resources));
|
|
8743
|
-
sidebarSurfaces.forEach(({ id, node, path }) => {
|
|
8744
|
-
node.targets?.resources?.forEach((resourceId, resourceIndex) => {
|
|
8745
|
-
if (!resourcesById.has(resourceId)) {
|
|
8746
|
-
addIssue(
|
|
8747
|
-
ctx,
|
|
8748
|
-
[...path, "targets", "resources", resourceIndex],
|
|
8749
|
-
`Sidebar surface "${id}" references unknown resource "${resourceId}"`
|
|
8750
|
-
);
|
|
8751
|
-
}
|
|
8752
|
-
});
|
|
8753
|
-
});
|
|
8754
|
-
const actionIds = new Set(Object.keys(model.actions));
|
|
8755
|
-
const offeringsById = new Map(Object.entries(model.offerings));
|
|
8756
|
-
const ontologyCompilation = compileOrganizationOntology(model);
|
|
8757
|
-
const stageIds = /* @__PURE__ */ new Set();
|
|
8758
|
-
for (const catalog of Object.values(ontologyCompilation.ontology.catalogTypes)) {
|
|
8759
|
-
if (catalog.kind !== "stage") continue;
|
|
8760
|
-
for (const stageId of Object.keys(catalog.entries ?? {})) {
|
|
8761
|
-
stageIds.add(stageId);
|
|
8762
|
-
}
|
|
8763
|
-
}
|
|
8764
|
-
const ontologyIndexByKind = {
|
|
8765
|
-
object: ontologyCompilation.ontology.objectTypes,
|
|
8766
|
-
link: ontologyCompilation.ontology.linkTypes,
|
|
8767
|
-
action: ontologyCompilation.ontology.actionTypes,
|
|
8768
|
-
catalog: ontologyCompilation.ontology.catalogTypes,
|
|
8769
|
-
event: ontologyCompilation.ontology.eventTypes,
|
|
8770
|
-
interface: ontologyCompilation.ontology.interfaceTypes,
|
|
8771
|
-
"value-type": ontologyCompilation.ontology.valueTypes,
|
|
8772
|
-
property: ontologyCompilation.ontology.sharedProperties,
|
|
8773
|
-
group: ontologyCompilation.ontology.groups,
|
|
8774
|
-
surface: ontologyCompilation.ontology.surfaces
|
|
8775
|
-
};
|
|
8776
|
-
const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index2) => Object.keys(index2)));
|
|
8777
|
-
function topologyTargetExists(ref) {
|
|
8778
|
-
if (ref.kind === "system") return systemsById.has(ref.id);
|
|
8779
|
-
if (ref.kind === "resource") return resourcesById.has(ref.id);
|
|
8780
|
-
if (ref.kind === "ontology") return ontologyIds.has(ref.id);
|
|
8781
|
-
if (ref.kind === "policy") return policiesById.has(ref.id);
|
|
8782
|
-
if (ref.kind === "role") return rolesById.has(ref.id);
|
|
8783
|
-
return true;
|
|
8784
|
-
}
|
|
8785
|
-
Object.entries(model.topology.relationships).forEach(([relationshipId, relationship]) => {
|
|
8786
|
-
["from", "to"].forEach((side) => {
|
|
8787
|
-
const ref = relationship[side];
|
|
8788
|
-
if (topologyTargetExists(ref)) return;
|
|
8789
|
-
addIssue(
|
|
8790
|
-
ctx,
|
|
8791
|
-
["topology", "relationships", relationshipId, side],
|
|
8792
|
-
`Topology relationship "${relationshipId}" ${side} references unknown ${ref.kind} "${ref.id}"`
|
|
8793
|
-
);
|
|
8794
|
-
});
|
|
8795
|
-
});
|
|
8796
|
-
const ontologyReferenceKeyKinds = {
|
|
8797
|
-
valueType: "value-type",
|
|
8798
|
-
catalogType: "catalog",
|
|
8799
|
-
objectType: "object",
|
|
8800
|
-
eventType: "event",
|
|
8801
|
-
actionType: "action",
|
|
8802
|
-
linkType: "link",
|
|
8803
|
-
interfaceType: "interface",
|
|
8804
|
-
propertyType: "property",
|
|
8805
|
-
groupType: "group",
|
|
8806
|
-
surfaceType: "surface",
|
|
8807
|
-
stepCatalog: "catalog"
|
|
8808
|
-
};
|
|
8809
|
-
function validateKnownOntologyReferences(ownerId, value, path, seen = /* @__PURE__ */ new WeakSet()) {
|
|
8810
|
-
if (Array.isArray(value)) {
|
|
8811
|
-
value.forEach((entry, index2) => validateKnownOntologyReferences(ownerId, entry, [...path, index2], seen));
|
|
8812
|
-
return;
|
|
8813
|
-
}
|
|
8814
|
-
if (!isRecord(value)) return;
|
|
8815
|
-
if (seen.has(value)) return;
|
|
8816
|
-
seen.add(value);
|
|
8817
|
-
Object.entries(value).forEach(([key, entry]) => {
|
|
8818
|
-
const expectedKind = ontologyReferenceKeyKinds[key];
|
|
8819
|
-
if (expectedKind !== void 0) {
|
|
8820
|
-
if (typeof entry !== "string") {
|
|
8821
|
-
addIssue(ctx, [...path, key], `Ontology record "${ownerId}" ${key} must be an ontology ID string`);
|
|
8822
|
-
} else if (ontologyIndexByKind[expectedKind][entry] === void 0) {
|
|
8823
|
-
addIssue(
|
|
8824
|
-
ctx,
|
|
8825
|
-
[...path, key],
|
|
8826
|
-
`Ontology record "${ownerId}" ${key} references unknown ${expectedKind} ontology ID "${entry}"`
|
|
8827
|
-
);
|
|
8828
|
-
}
|
|
8829
|
-
}
|
|
8830
|
-
validateKnownOntologyReferences(ownerId, entry, [...path, key], seen);
|
|
8831
|
-
});
|
|
8832
|
-
}
|
|
8833
|
-
for (const { id, record } of listResolvedOntologyRecords(ontologyCompilation.ontology)) {
|
|
8834
|
-
validateKnownOntologyReferences(id, record, record.origin.path);
|
|
8835
|
-
}
|
|
8836
|
-
Object.values(model.policies).forEach((policy) => {
|
|
8837
|
-
policy.appliesTo.systemIds.forEach((systemId, systemIndex) => {
|
|
8838
|
-
if (!systemsById.has(systemId)) {
|
|
8839
|
-
addIssue(
|
|
8840
|
-
ctx,
|
|
8841
|
-
["policies", policy.id, "appliesTo", "systemIds", systemIndex],
|
|
8842
|
-
`Policy "${policy.id}" applies to unknown system "${systemId}"`
|
|
8843
|
-
);
|
|
8844
|
-
}
|
|
8845
|
-
});
|
|
8846
|
-
policy.appliesTo.actionIds.forEach((actionId, actionIndex) => {
|
|
8847
|
-
if (!actionsById.has(actionId)) {
|
|
8848
|
-
addIssue(
|
|
8849
|
-
ctx,
|
|
8850
|
-
["policies", policy.id, "appliesTo", "actionIds", actionIndex],
|
|
8851
|
-
`Policy "${policy.id}" applies to unknown action "${actionId}"`
|
|
8852
|
-
);
|
|
8853
|
-
}
|
|
8854
|
-
});
|
|
8855
|
-
policy.actions.forEach((action, actionIndex) => {
|
|
8856
|
-
if (action.kind === "invoke-action" && !actionsById.has(action.actionId)) {
|
|
8857
|
-
addIssue(
|
|
8858
|
-
ctx,
|
|
8859
|
-
["policies", policy.id, "actions", actionIndex, "actionId"],
|
|
8860
|
-
`Policy "${policy.id}" invokes unknown action "${action.actionId}"`
|
|
8861
|
-
);
|
|
8862
|
-
}
|
|
8863
|
-
if ((action.kind === "notify-role" || action.kind === "require-approval") && action.roleId !== void 0 && !rolesById.has(action.roleId)) {
|
|
8864
|
-
addIssue(
|
|
8865
|
-
ctx,
|
|
8866
|
-
["policies", policy.id, "actions", actionIndex, "roleId"],
|
|
8867
|
-
`Policy "${policy.id}" references unknown role "${action.roleId}"`
|
|
8868
|
-
);
|
|
8869
|
-
}
|
|
8870
|
-
});
|
|
8871
|
-
if (policy.trigger.kind === "action-invocation" && !actionsById.has(policy.trigger.actionId)) {
|
|
8872
|
-
addIssue(
|
|
8873
|
-
ctx,
|
|
8874
|
-
["policies", policy.id, "trigger", "actionId"],
|
|
8875
|
-
`Policy "${policy.id}" references unknown trigger action "${policy.trigger.actionId}"`
|
|
8876
|
-
);
|
|
8877
|
-
}
|
|
8878
|
-
});
|
|
8879
|
-
function knowledgeTargetExists(kind, id) {
|
|
8880
|
-
if (kind === "system") return systemsById.has(id);
|
|
8881
|
-
if (kind === "resource") return resourcesById.has(id);
|
|
8882
|
-
if (kind === "knowledge") return knowledgeById.has(id);
|
|
8883
|
-
if (kind === "stage") return stageIds.has(id);
|
|
8884
|
-
if (kind === "action") return actionIds.has(id);
|
|
8885
|
-
if (kind === "role") return rolesById.has(id);
|
|
8886
|
-
if (kind === "goal") return goalsById.has(id);
|
|
8887
|
-
if (kind === "customer-segment") return segmentsById.has(id);
|
|
8888
|
-
if (kind === "offering") return offeringsById.has(id);
|
|
8889
|
-
if (kind === "ontology") return ontologyIds.has(id);
|
|
8890
|
-
return false;
|
|
8891
|
-
}
|
|
8892
|
-
Object.entries(model.knowledge).forEach(([nodeId, node]) => {
|
|
8893
|
-
node.links.forEach((link, linkIndex) => {
|
|
8894
|
-
if (!knowledgeTargetExists(link.target.kind, link.target.id)) {
|
|
8895
|
-
addIssue(
|
|
8896
|
-
ctx,
|
|
8897
|
-
["knowledge", nodeId, "links", linkIndex, "target"],
|
|
8898
|
-
`Knowledge node "${node.id}" references unknown ${link.target.kind} target "${link.target.id}"`
|
|
8899
|
-
);
|
|
8900
|
-
}
|
|
8901
|
-
if (!isKnowledgeKindCompatibleWithTarget(node.kind, link.target.kind)) {
|
|
8902
|
-
addIssue(
|
|
8903
|
-
ctx,
|
|
8904
|
-
["knowledge", nodeId, "links", linkIndex, "target", "kind"],
|
|
8905
|
-
`Knowledge node "${node.id}" kind "${node.kind}" cannot govern ${link.target.kind} targets`
|
|
8906
|
-
);
|
|
8907
|
-
}
|
|
8908
|
-
});
|
|
8909
|
-
});
|
|
8910
|
-
Object.values(model.resources).forEach((resource) => {
|
|
8911
|
-
if (!systemsById.has(resource.systemPath)) {
|
|
8912
|
-
addIssue(
|
|
8913
|
-
ctx,
|
|
8914
|
-
["resources", resource.id, "systemPath"],
|
|
8915
|
-
`Resource "${resource.id}" references unknown system path "${resource.systemPath}"`
|
|
8916
|
-
);
|
|
8917
|
-
}
|
|
8918
|
-
if (resource.ownerRoleId !== void 0 && !rolesById.has(resource.ownerRoleId)) {
|
|
8919
|
-
addIssue(
|
|
8920
|
-
ctx,
|
|
8921
|
-
["resources", resource.id, "ownerRoleId"],
|
|
8922
|
-
`Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
|
|
8923
|
-
);
|
|
8924
|
-
}
|
|
8925
|
-
if (resource.kind === "agent" && resource.actsAsRoleId !== void 0 && !rolesById.has(resource.actsAsRoleId)) {
|
|
8926
|
-
addIssue(
|
|
8927
|
-
ctx,
|
|
8928
|
-
["resources", resource.id, "actsAsRoleId"],
|
|
8929
|
-
`Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
|
|
8930
|
-
);
|
|
8931
|
-
}
|
|
8932
|
-
});
|
|
8933
|
-
function validateResourceOntologyBinding(resourceId, bindingKey, expectedKind, ids) {
|
|
8934
|
-
const ontologyIds2 = ids === void 0 ? [] : Array.isArray(ids) ? ids : [ids];
|
|
8935
|
-
ontologyIds2.forEach((ontologyId, ontologyIndex) => {
|
|
8936
|
-
if (ontologyIndexByKind[expectedKind][ontologyId] === void 0) {
|
|
8937
|
-
addIssue(
|
|
8938
|
-
ctx,
|
|
8939
|
-
["resources", resourceId, "ontology", bindingKey, ...Array.isArray(ids) ? [ontologyIndex] : []],
|
|
8940
|
-
`Resource "${resourceId}" ontology binding "${bindingKey}" references unknown ${expectedKind} ontology ID "${ontologyId}"`
|
|
8941
|
-
);
|
|
8942
|
-
}
|
|
8943
|
-
});
|
|
8944
|
-
}
|
|
8945
|
-
Object.values(model.resources).forEach((resource) => {
|
|
8946
|
-
const binding = resource.ontology;
|
|
8947
|
-
if (binding === void 0) return;
|
|
8948
|
-
validateResourceOntologyBinding(resource.id, "actions", "action", binding.actions);
|
|
8949
|
-
validateResourceOntologyBinding(resource.id, "primaryAction", "action", binding.primaryAction);
|
|
8950
|
-
validateResourceOntologyBinding(resource.id, "reads", "object", binding.reads);
|
|
8951
|
-
validateResourceOntologyBinding(resource.id, "writes", "object", binding.writes);
|
|
8952
|
-
validateResourceOntologyBinding(resource.id, "usesCatalogs", "catalog", binding.usesCatalogs);
|
|
8953
|
-
validateResourceOntologyBinding(resource.id, "emits", "event", binding.emits);
|
|
8954
|
-
if (binding.contract !== void 0) {
|
|
8955
|
-
const contractEntries = [
|
|
8956
|
-
["input", binding.contract.input],
|
|
8957
|
-
["output", binding.contract.output]
|
|
8958
|
-
];
|
|
8959
|
-
for (const [side, ref] of contractEntries) {
|
|
8960
|
-
if (ref === void 0) continue;
|
|
8961
|
-
const result = ContractRefSchema.safeParse(ref);
|
|
8962
|
-
if (!result.success) {
|
|
8963
|
-
addIssue(
|
|
8964
|
-
ctx,
|
|
8965
|
-
["resources", resource.id, "ontology", "contract", side],
|
|
8966
|
-
`Resource "${resource.id}" contract.${side} "${ref}" is not a valid ContractRef (expected "package/subpath#ExportName")`
|
|
8967
|
-
);
|
|
8968
|
-
}
|
|
8969
|
-
}
|
|
8970
|
-
}
|
|
8971
|
-
});
|
|
8972
|
-
Object.values(model.roles).forEach((role) => {
|
|
8973
|
-
if (role.heldBy === void 0) return;
|
|
8974
|
-
asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
|
|
8975
|
-
if (holder.kind !== "agent") return;
|
|
8976
|
-
const resource = resourcesById.get(holder.agentId);
|
|
8977
|
-
if (resource === void 0) {
|
|
8978
|
-
addIssue(
|
|
8979
|
-
ctx,
|
|
8980
|
-
["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
|
|
8981
|
-
`Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
|
|
8982
|
-
);
|
|
8983
|
-
return;
|
|
8984
|
-
}
|
|
8985
|
-
if (resource.kind !== "agent") {
|
|
8986
|
-
addIssue(
|
|
8987
|
-
ctx,
|
|
8988
|
-
["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
|
|
8989
|
-
`Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
|
|
8990
|
-
);
|
|
8991
|
-
}
|
|
8992
|
-
});
|
|
8993
|
-
});
|
|
8994
|
-
Object.entries(model.knowledge).forEach(([nodeId, node]) => {
|
|
8995
|
-
node.ownerIds.forEach((roleId, ownerIndex) => {
|
|
8996
|
-
if (!rolesById.has(roleId)) {
|
|
8997
|
-
addIssue(
|
|
8998
|
-
ctx,
|
|
8999
|
-
["knowledge", nodeId, "ownerIds", ownerIndex],
|
|
9000
|
-
`Knowledge node "${node.id}" references unknown owner role "${roleId}"`
|
|
9001
|
-
);
|
|
9002
|
-
}
|
|
9003
|
-
});
|
|
9004
|
-
});
|
|
9005
|
-
for (const diagnostic of ontologyCompilation.diagnostics) {
|
|
9006
|
-
addIssue(ctx, diagnostic.path, diagnostic.message);
|
|
9007
|
-
}
|
|
9008
|
-
});
|
|
9009
|
-
|
|
9010
|
-
// ../core/src/organization-model/defaults.ts
|
|
9011
|
-
var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
|
|
9012
|
-
var DEFAULT_ORGANIZATION_MODEL_ENTITIES2 = {};
|
|
9013
|
-
var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
|
|
9014
|
-
sidebar: {
|
|
9015
|
-
primary: {},
|
|
9016
|
-
bottom: {}
|
|
9017
|
-
}
|
|
9018
|
-
};
|
|
9019
|
-
var DEFAULT_ORGANIZATION_MODEL = {
|
|
9020
|
-
version: 1,
|
|
9021
|
-
domainMetadata: DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA,
|
|
9022
|
-
branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
|
|
9023
|
-
navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
|
|
9024
|
-
identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
|
|
9025
|
-
customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
|
|
9026
|
-
offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
|
|
9027
|
-
roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
|
|
9028
|
-
goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
|
|
9029
|
-
// Generic empty systems map. Elevasis-specific systems (platform, sales, sales.crm,
|
|
9030
|
-
// sales.lead-gen, monitoring, settings, admin, etc.) have been relocated to
|
|
9031
|
-
// `@repo/elevasis-core/src/organization-model/systems.ts` via `canonicalOrganizationModel`.
|
|
9032
|
-
// Tenant OM configs supply their own systems via `resolveOrganizationModel`.
|
|
9033
|
-
systems: {},
|
|
9034
|
-
ontology: DEFAULT_ONTOLOGY_SCOPE,
|
|
9035
|
-
resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
|
|
9036
|
-
topology: DEFAULT_ORGANIZATION_MODEL_TOPOLOGY,
|
|
9037
|
-
// Generic empty actions map. Elevasis-specific action entries have been relocated to
|
|
9038
|
-
// `@repo/elevasis-core/src/organization-model/actions.ts`.
|
|
9039
|
-
actions: {},
|
|
9040
|
-
entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
|
|
9041
|
-
policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
|
|
9042
|
-
knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
|
|
9043
|
-
};
|
|
9044
|
-
var SalesStageSemanticClassSchema = z.enum(["open", "active", "nurturing", "closed_won", "closed_lost"]);
|
|
9045
|
-
var SalesStageSchema = DisplayMetadataSchema.extend({
|
|
9046
|
-
id: ModelIdSchema,
|
|
9047
|
-
order: z.number().int().min(0),
|
|
9048
|
-
semanticClass: SalesStageSemanticClassSchema,
|
|
9049
|
-
surfaceIds: ReferenceIdsSchema,
|
|
9050
|
-
resourceIds: ReferenceIdsSchema
|
|
9051
|
-
});
|
|
9052
|
-
z.object({
|
|
9053
|
-
id: ModelIdSchema,
|
|
9054
|
-
label: z.string().trim().min(1).max(120),
|
|
9055
|
-
description: DescriptionSchema.optional(),
|
|
9056
|
-
entityId: ModelIdSchema,
|
|
9057
|
-
stages: z.array(SalesStageSchema).min(1)
|
|
9058
|
-
});
|
|
9059
|
-
var CRM_DISCOVERY_REPLIED_STATE = {
|
|
9060
|
-
stateKey: "discovery_replied",
|
|
9061
|
-
label: "Discovery Replied"
|
|
9062
|
-
};
|
|
9063
|
-
var CRM_DISCOVERY_LINK_SENT_STATE = {
|
|
9064
|
-
stateKey: "discovery_link_sent",
|
|
9065
|
-
label: "Discovery Link Sent"
|
|
9066
|
-
};
|
|
9067
|
-
var CRM_DISCOVERY_NUDGING_STATE = {
|
|
9068
|
-
stateKey: "discovery_nudging",
|
|
9069
|
-
label: "Discovery Nudging"
|
|
9070
|
-
};
|
|
9071
|
-
var CRM_DISCOVERY_BOOKING_CANCELLED_STATE = {
|
|
9072
|
-
stateKey: "discovery_booking_cancelled",
|
|
9073
|
-
label: "Discovery Booking Cancelled"
|
|
9074
|
-
};
|
|
9075
|
-
var CRM_REPLY_SENT_STATE = {
|
|
9076
|
-
stateKey: "reply_sent",
|
|
9077
|
-
label: "Reply Sent"
|
|
9078
|
-
};
|
|
9079
|
-
var CRM_FOLLOWUP_1_SENT_STATE = {
|
|
9080
|
-
stateKey: "followup_1_sent",
|
|
9081
|
-
label: "Follow-up 1 Sent"
|
|
9082
|
-
};
|
|
9083
|
-
var CRM_FOLLOWUP_2_SENT_STATE = {
|
|
9084
|
-
stateKey: "followup_2_sent",
|
|
9085
|
-
label: "Follow-up 2 Sent"
|
|
9086
|
-
};
|
|
9087
|
-
var CRM_FOLLOWUP_3_SENT_STATE = {
|
|
9088
|
-
stateKey: "followup_3_sent",
|
|
9089
|
-
label: "Follow-up 3 Sent"
|
|
9090
|
-
};
|
|
9091
|
-
var CRM_PIPELINE_DEFINITION = {
|
|
9092
|
-
pipelineKey: "crm",
|
|
9093
|
-
label: "CRM",
|
|
9094
|
-
entityKey: "crm.deal",
|
|
9095
|
-
stages: [
|
|
9096
|
-
{
|
|
9097
|
-
stageKey: "interested",
|
|
9098
|
-
label: "Interested",
|
|
9099
|
-
color: "blue",
|
|
9100
|
-
states: [
|
|
9101
|
-
CRM_DISCOVERY_REPLIED_STATE,
|
|
9102
|
-
CRM_DISCOVERY_LINK_SENT_STATE,
|
|
9103
|
-
CRM_DISCOVERY_NUDGING_STATE,
|
|
9104
|
-
CRM_DISCOVERY_BOOKING_CANCELLED_STATE,
|
|
9105
|
-
CRM_REPLY_SENT_STATE,
|
|
9106
|
-
CRM_FOLLOWUP_1_SENT_STATE,
|
|
9107
|
-
CRM_FOLLOWUP_2_SENT_STATE,
|
|
9108
|
-
CRM_FOLLOWUP_3_SENT_STATE
|
|
9109
|
-
]
|
|
9110
|
-
},
|
|
9111
|
-
{ stageKey: "proposal", label: "Proposal", color: "yellow", states: [] },
|
|
9112
|
-
{ stageKey: "closing", label: "Closing", color: "orange", states: [] },
|
|
9113
|
-
{ stageKey: "closed_won", label: "Closed Won", color: "green", states: [] },
|
|
9114
|
-
{ stageKey: "closed_lost", label: "Closed Lost", color: "red", states: [] },
|
|
9115
|
-
{ stageKey: "nurturing", label: "Nurturing", color: "grape", states: [] }
|
|
9116
|
-
]
|
|
9117
|
-
};
|
|
9118
|
-
|
|
9119
|
-
// ../core/src/organization-model/migration-helpers.ts
|
|
9120
|
-
function catalogRecords(model) {
|
|
9121
|
-
return Object.values(compileOrganizationOntology(model).ontology.catalogTypes);
|
|
9122
|
-
}
|
|
9123
|
-
function systemScope(id, fallback) {
|
|
9124
|
-
return parseOntologyId(id).scope || fallback || "";
|
|
9125
|
-
}
|
|
9126
|
-
function entriesOf(catalog) {
|
|
9127
|
-
return Object.entries(catalog.entries ?? {}).map(([id, value]) => [
|
|
9128
|
-
id,
|
|
9129
|
-
value && typeof value === "object" && !Array.isArray(value) ? value : {}
|
|
9130
|
-
]);
|
|
9131
|
-
}
|
|
9132
|
-
function stringValue(value) {
|
|
9133
|
-
return typeof value === "string" ? value : void 0;
|
|
9134
|
-
}
|
|
9135
|
-
function stringArray(value) {
|
|
9136
|
-
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
9137
|
-
}
|
|
9138
|
-
function numberValue(value, fallback = 0) {
|
|
9139
|
-
return typeof value === "number" ? value : fallback;
|
|
9140
|
-
}
|
|
9141
|
-
function appliesToLocalId(catalog) {
|
|
9142
|
-
const appliesTo = catalog.appliesTo;
|
|
9143
|
-
if (appliesTo === void 0) return void 0;
|
|
9144
|
-
return parseOntologyId(appliesTo).localId;
|
|
9145
|
-
}
|
|
9146
|
-
function appliesToEntityKind(catalog) {
|
|
9147
|
-
const id = appliesToLocalId(catalog);
|
|
9148
|
-
if (id === "company" || id === "contact" || id === "project" || id === "milestone" || id === "task") return id;
|
|
9149
|
-
if (id === "deal") return void 0;
|
|
9150
|
-
return void 0;
|
|
9151
|
-
}
|
|
9152
|
-
function getLeadGenStageCatalog(model) {
|
|
9153
|
-
const results = {};
|
|
9154
|
-
for (const catalog of catalogRecords(model).filter(
|
|
9155
|
-
(record) => record.kind === "stage" && (record.ownerSystemId ?? systemScope(record.id)) === "sales.lead-gen"
|
|
9156
|
-
)) {
|
|
9157
|
-
const catalogEntity = appliesToEntityKind(catalog);
|
|
9158
|
-
if (catalogEntity !== "company" && catalogEntity !== "contact") continue;
|
|
9159
|
-
for (const [entryId, entry] of entriesOf(catalog)) {
|
|
9160
|
-
const entity = entry.entity === "contact" ? "contact" : entry.entity === "company" ? "company" : catalogEntity;
|
|
9161
|
-
const additionalEntities = stringArray(entry.additionalEntities).filter(
|
|
9162
|
-
(item) => item === "company" || item === "contact"
|
|
9163
|
-
);
|
|
9164
|
-
const recordEntity = entry.recordEntity === "company" || entry.recordEntity === "contact" ? entry.recordEntity : void 0;
|
|
9165
|
-
const recordStageKey = stringValue(entry.recordStageKey);
|
|
9166
|
-
results[entryId] = {
|
|
9167
|
-
key: entryId,
|
|
9168
|
-
label: stringValue(entry.label) ?? entryId,
|
|
9169
|
-
description: stringValue(entry.description) ?? "",
|
|
9170
|
-
order: numberValue(entry.order),
|
|
9171
|
-
entity,
|
|
9172
|
-
...additionalEntities.length > 0 ? { additionalEntities } : {},
|
|
9173
|
-
...recordEntity ? { recordEntity } : {},
|
|
9174
|
-
...recordStageKey ? { recordStageKey } : {}
|
|
9175
|
-
};
|
|
9176
|
-
}
|
|
9177
|
-
}
|
|
9178
|
-
return Object.fromEntries(
|
|
9179
|
-
Object.entries(results).sort(([, a3], [, b2]) => a3.order - b2.order || a3.key.localeCompare(b2.key))
|
|
9180
|
-
);
|
|
9181
|
-
}
|
|
9182
|
-
|
|
9183
|
-
// ../core/src/business/acquisition/ontology-validation.ts
|
|
9184
|
-
var CRM_PIPELINE_CATALOG_ONTOLOGY_ID = formatOntologyId({
|
|
9185
|
-
scope: "sales.crm",
|
|
9186
|
-
kind: "catalog",
|
|
9187
|
-
localId: "crm.pipeline"
|
|
9188
|
-
});
|
|
9189
|
-
var LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
|
|
9190
|
-
scope: "sales.lead-gen",
|
|
9191
|
-
kind: "catalog",
|
|
9192
|
-
localId: "lead-gen.stage-catalog"
|
|
9193
|
-
});
|
|
9194
|
-
var CRM_DEAL_OBJECT_ONTOLOGY_ID = formatOntologyId({
|
|
9195
|
-
scope: "sales.crm",
|
|
9196
|
-
kind: "object",
|
|
9197
|
-
localId: "crm.deal"
|
|
9198
|
-
});
|
|
9199
|
-
function createCrmPipelineCatalog() {
|
|
9200
|
-
return {
|
|
9201
|
-
id: CRM_PIPELINE_CATALOG_ONTOLOGY_ID,
|
|
9202
|
-
label: CRM_PIPELINE_DEFINITION.label,
|
|
9203
|
-
ownerSystemId: "sales.crm",
|
|
9204
|
-
kind: "pipeline",
|
|
9205
|
-
appliesTo: CRM_DEAL_OBJECT_ONTOLOGY_ID,
|
|
9206
|
-
entries: Object.fromEntries(
|
|
9207
|
-
CRM_PIPELINE_DEFINITION.stages.map((stage, index2) => [
|
|
9208
|
-
stage.stageKey,
|
|
9209
|
-
{
|
|
9210
|
-
key: stage.stageKey,
|
|
9211
|
-
label: stage.label,
|
|
9212
|
-
order: (index2 + 1) * 10,
|
|
9213
|
-
...stage.color !== void 0 ? { color: stage.color } : {},
|
|
9214
|
-
states: stage.states.map((state) => ({ ...state }))
|
|
9215
|
-
}
|
|
9216
|
-
])
|
|
9217
|
-
),
|
|
9218
|
-
legacyPipelineKey: CRM_PIPELINE_DEFINITION.pipelineKey,
|
|
9219
|
-
legacyEntityKey: CRM_PIPELINE_DEFINITION.entityKey
|
|
9220
|
-
};
|
|
9221
|
-
}
|
|
9222
|
-
function createLeadGenStageCatalog(model) {
|
|
9223
|
-
return {
|
|
9224
|
-
id: LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID,
|
|
9225
|
-
label: "Lead Gen Processing Stages",
|
|
9226
|
-
ownerSystemId: "sales.lead-gen",
|
|
9227
|
-
kind: "processing-stage-catalog",
|
|
9228
|
-
entries: Object.fromEntries(
|
|
9229
|
-
Object.entries(getLeadGenStageCatalog(model)).map(([key, entry]) => [
|
|
9230
|
-
key,
|
|
9231
|
-
{
|
|
9232
|
-
...entry
|
|
9233
|
-
}
|
|
9234
|
-
])
|
|
9235
|
-
),
|
|
9236
|
-
legacyCatalogKey: "LEAD_GEN_STAGE_CATALOG"
|
|
9237
|
-
};
|
|
9238
|
-
}
|
|
9239
|
-
function isPlainRecord(value) {
|
|
9240
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9241
|
-
}
|
|
9242
|
-
function mergeBridgeCatalogs(model) {
|
|
9243
|
-
const baseCatalogTypes = model.ontology?.catalogTypes ?? {};
|
|
9244
|
-
const bridgeCatalogTypes = {};
|
|
9245
|
-
if (baseCatalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID] === void 0) {
|
|
9246
|
-
bridgeCatalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID] = createCrmPipelineCatalog();
|
|
9247
|
-
}
|
|
9248
|
-
if (baseCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] === void 0) {
|
|
9249
|
-
bridgeCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] = createLeadGenStageCatalog(model);
|
|
9250
|
-
}
|
|
9251
|
-
if (Object.keys(bridgeCatalogTypes).length === 0) return model;
|
|
9252
|
-
return {
|
|
9253
|
-
...model,
|
|
9254
|
-
ontology: {
|
|
9255
|
-
...model.ontology ?? {},
|
|
9256
|
-
catalogTypes: {
|
|
9257
|
-
...baseCatalogTypes,
|
|
9258
|
-
...bridgeCatalogTypes
|
|
9259
|
-
}
|
|
9260
|
-
}
|
|
9261
|
-
};
|
|
9262
|
-
}
|
|
9263
|
-
function compileBusinessOntologyValidationIndex(model = DEFAULT_ORGANIZATION_MODEL) {
|
|
9264
|
-
const compilation = compileOrganizationOntology(mergeBridgeCatalogs(model));
|
|
9265
|
-
if (compilation.diagnostics.length > 0) {
|
|
9266
|
-
const summary = compilation.diagnostics.map((diagnostic) => diagnostic.message).join("; ");
|
|
9267
|
-
throw new Error(`Business ontology validation index failed to compile: ${summary}`);
|
|
9268
|
-
}
|
|
9269
|
-
const crmPipelineCatalog = compilation.ontology.catalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID];
|
|
9270
|
-
const leadGenStageCatalog = compilation.ontology.catalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID];
|
|
9271
|
-
if (crmPipelineCatalog === void 0 || leadGenStageCatalog === void 0) {
|
|
9272
|
-
throw new Error("Business ontology validation index is missing CRM or lead-gen catalog bridge records");
|
|
9273
|
-
}
|
|
9274
|
-
return {
|
|
9275
|
-
ontology: compilation.ontology,
|
|
9276
|
-
crmPipelineCatalog,
|
|
9277
|
-
leadGenStageCatalog,
|
|
9278
|
-
actionTypesByLegacyId: indexActionTypesByLegacyId(compilation.ontology.actionTypes)
|
|
9279
|
-
};
|
|
9280
|
-
}
|
|
9281
|
-
function indexActionTypesByLegacyId(actionTypes) {
|
|
9282
|
-
const byLegacyId = {};
|
|
9283
|
-
for (const actionType of Object.values(actionTypes)) {
|
|
9284
|
-
const legacyActionId = actionType["legacyActionId"];
|
|
9285
|
-
if (typeof legacyActionId === "string") {
|
|
9286
|
-
byLegacyId[legacyActionId] = actionType;
|
|
9287
|
-
}
|
|
9288
|
-
}
|
|
9289
|
-
return byLegacyId;
|
|
9290
|
-
}
|
|
9291
|
-
var BUSINESS_ONTOLOGY_VALIDATION_INDEX = compileBusinessOntologyValidationIndex();
|
|
9292
|
-
function getCatalogEntries(catalog) {
|
|
9293
|
-
return isPlainRecord(catalog.entries) ? catalog.entries : {};
|
|
9294
|
-
}
|
|
9295
|
-
function asCrmStageEntry(key, value) {
|
|
9296
|
-
const record = isPlainRecord(value) ? value : {};
|
|
9297
|
-
const label = typeof record.label === "string" ? record.label : key;
|
|
9298
|
-
const order = typeof record.order === "number" ? record.order : 0;
|
|
9299
|
-
const color = typeof record.color === "string" ? record.color : void 0;
|
|
9300
|
-
const rawStates = Array.isArray(record.states) ? record.states : [];
|
|
9301
|
-
const states = rawStates.flatMap((state) => {
|
|
9302
|
-
if (!isPlainRecord(state) || typeof state.stateKey !== "string") return [];
|
|
9303
|
-
return [
|
|
9304
|
-
{
|
|
9305
|
-
stateKey: state.stateKey,
|
|
9306
|
-
label: typeof state.label === "string" ? state.label : state.stateKey
|
|
9307
|
-
}
|
|
9308
|
-
];
|
|
9309
|
-
});
|
|
9310
|
-
return {
|
|
9311
|
-
key,
|
|
9312
|
-
label,
|
|
9313
|
-
order,
|
|
9314
|
-
...color !== void 0 ? { color } : {},
|
|
9315
|
-
states
|
|
9316
|
-
};
|
|
9317
|
-
}
|
|
9318
|
-
var CRM_STAGE_KEYS_FROM_ONTOLOGY = Object.keys(
|
|
9319
|
-
getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.crmPipelineCatalog)
|
|
9320
|
-
);
|
|
9321
|
-
var CRM_STATE_KEYS_FROM_ONTOLOGY = Object.values(
|
|
9322
|
-
getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.crmPipelineCatalog)
|
|
9323
|
-
).flatMap((entry, index2) => {
|
|
9324
|
-
const stageKey = CRM_STAGE_KEYS_FROM_ONTOLOGY[index2];
|
|
9325
|
-
if (stageKey === void 0) return [];
|
|
9326
|
-
return asCrmStageEntry(stageKey, entry).states.map((state) => state.stateKey);
|
|
9327
|
-
});
|
|
9328
|
-
Object.keys(
|
|
9329
|
-
getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.leadGenStageCatalog)
|
|
9330
|
-
);
|
|
9331
7037
|
|
|
9332
7038
|
// ../core/src/business/acquisition/api-schemas.ts
|
|
9333
7039
|
var ProcessingStageStatusSchema = z.enum(["success", "no_result", "skipped", "error"]);
|
|
9334
7040
|
var LeadGenStageKeySchema = z.string().trim().min(1);
|
|
9335
7041
|
var LeadGenActionKeySchema = z.string().trim().min(1);
|
|
9336
|
-
var
|
|
9337
|
-
var
|
|
9338
|
-
var CrmStageKeySchema = z.enum(crmStageKeys);
|
|
9339
|
-
var CrmStateKeySchema = z.enum(crmStateKeys);
|
|
7042
|
+
var CrmStageKeySchema = z.string().trim().min(1);
|
|
7043
|
+
var CrmStateKeySchema = z.string().trim().min(1);
|
|
9340
7044
|
var ProcessingStateEntrySchema = z.object({
|
|
9341
7045
|
status: ProcessingStageStatusSchema,
|
|
9342
7046
|
data: z.unknown().optional()
|
|
@@ -9594,8 +7298,10 @@ var PipelineStageSchema = z.object({
|
|
|
9594
7298
|
enabled: z.boolean().optional(),
|
|
9595
7299
|
order: z.number().int().optional()
|
|
9596
7300
|
});
|
|
7301
|
+
var DataModeSchema = z.enum(["mock", "live"]);
|
|
9597
7302
|
var PipelineConfigSchema = z.object({
|
|
9598
|
-
stages: z.array(PipelineStageSchema).optional()
|
|
7303
|
+
stages: z.array(PipelineStageSchema).optional(),
|
|
7304
|
+
dataMode: DataModeSchema.optional()
|
|
9599
7305
|
});
|
|
9600
7306
|
var BuildPlanSnapshotStepSchema = z.object({
|
|
9601
7307
|
id: z.string().trim().min(1).max(100),
|
|
@@ -9652,9 +7358,7 @@ var BuildPlanSnapshotSchema = z.object({
|
|
|
9652
7358
|
var AcqListMetadataSchema = z.object({
|
|
9653
7359
|
buildPlanSnapshot: BuildPlanSnapshotSchema.optional()
|
|
9654
7360
|
}).catchall(z.unknown());
|
|
9655
|
-
var ProspectingBuildTemplateIdSchema = z.string().trim().min(1).max(100)
|
|
9656
|
-
message: "buildTemplateId must match a known prospecting build template"
|
|
9657
|
-
});
|
|
7361
|
+
var ProspectingBuildTemplateIdSchema = z.string().trim().min(1).max(100);
|
|
9658
7362
|
var ListStageCountsSchema = z.object({
|
|
9659
7363
|
// Attempted counts by canonical lead-gen stage. The detailed status
|
|
9660
7364
|
// distribution lives on ListProgress; telemetry keeps the overview payload small.
|
|
@@ -10514,25 +8218,323 @@ createAdapter("execution", ["trigger", "triggerAsync"]);
|
|
|
10514
8218
|
|
|
10515
8219
|
// src/worker/adapters/email.ts
|
|
10516
8220
|
createAdapter("email", ["send"]);
|
|
10517
|
-
|
|
10518
|
-
|
|
8221
|
+
var OntologyKindSchema = z.enum([
|
|
8222
|
+
"object",
|
|
8223
|
+
"link",
|
|
8224
|
+
"action",
|
|
8225
|
+
"catalog",
|
|
8226
|
+
"event",
|
|
8227
|
+
"interface",
|
|
8228
|
+
"value-type",
|
|
8229
|
+
"property",
|
|
8230
|
+
"group",
|
|
8231
|
+
"surface"
|
|
8232
|
+
]);
|
|
8233
|
+
var SYSTEM_PATH_PATTERN = "[a-z0-9][a-z0-9-]*(?:\\.[a-z0-9][a-z0-9-]*)*";
|
|
8234
|
+
var LOCAL_ID_PATTERN = "[a-z0-9][a-z0-9._-]*";
|
|
8235
|
+
var ONTOLOGY_ID_PATTERN = `^(global|${SYSTEM_PATH_PATTERN}):(${OntologyKindSchema.options.join("|")})\\/(${LOCAL_ID_PATTERN})$`;
|
|
8236
|
+
var ONTOLOGY_ID_REGEX = new RegExp(ONTOLOGY_ID_PATTERN);
|
|
8237
|
+
var OntologyIdSchema = z.string().trim().min(1).max(300).regex(
|
|
8238
|
+
ONTOLOGY_ID_REGEX,
|
|
8239
|
+
"Ontology IDs must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
|
|
8240
|
+
);
|
|
8241
|
+
function parseOntologyId(id) {
|
|
8242
|
+
const normalized = OntologyIdSchema.parse(id);
|
|
8243
|
+
const match = ONTOLOGY_ID_REGEX.exec(normalized);
|
|
8244
|
+
if (match === null) {
|
|
8245
|
+
throw new Error(`Invalid ontology ID "${id}"`);
|
|
8246
|
+
}
|
|
8247
|
+
return {
|
|
8248
|
+
id: normalized,
|
|
8249
|
+
scope: match[1],
|
|
8250
|
+
kind: match[2],
|
|
8251
|
+
localId: match[3],
|
|
8252
|
+
isGlobal: match[1] === "global"
|
|
8253
|
+
};
|
|
8254
|
+
}
|
|
8255
|
+
function formatOntologyId(input) {
|
|
8256
|
+
return OntologyIdSchema.parse(`${input.scope}:${input.kind}/${input.localId}`);
|
|
8257
|
+
}
|
|
8258
|
+
var OntologyReferenceListSchema = z.array(OntologyIdSchema).default([]).optional();
|
|
8259
|
+
var OntologyRecordBaseSchema = z.object({
|
|
8260
|
+
id: OntologyIdSchema,
|
|
8261
|
+
label: z.string().trim().min(1).max(160).optional(),
|
|
8262
|
+
description: z.string().trim().min(1).max(2e3).optional(),
|
|
8263
|
+
ownerSystemId: z.string().trim().min(1).max(200).optional(),
|
|
8264
|
+
aliases: z.array(OntologyIdSchema).optional()
|
|
8265
|
+
}).passthrough();
|
|
8266
|
+
var OntologyObjectTypeSchema = OntologyRecordBaseSchema.extend({
|
|
8267
|
+
properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
|
|
8268
|
+
storage: z.record(z.string(), z.unknown()).optional()
|
|
8269
|
+
});
|
|
8270
|
+
var OntologyLinkTypeSchema = OntologyRecordBaseSchema.extend({
|
|
8271
|
+
from: OntologyIdSchema,
|
|
8272
|
+
to: OntologyIdSchema,
|
|
8273
|
+
cardinality: z.string().trim().min(1).max(80).optional(),
|
|
8274
|
+
via: z.string().trim().min(1).max(255).optional()
|
|
8275
|
+
});
|
|
8276
|
+
var OntologyActionTypeSchema = OntologyRecordBaseSchema.extend({
|
|
8277
|
+
actsOn: OntologyReferenceListSchema,
|
|
8278
|
+
input: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
|
|
8279
|
+
effects: z.array(z.record(z.string(), z.unknown())).optional()
|
|
8280
|
+
});
|
|
8281
|
+
var OntologyCatalogTypeSchema = OntologyRecordBaseSchema.extend({
|
|
8282
|
+
kind: z.string().trim().min(1).max(120).optional(),
|
|
8283
|
+
appliesTo: OntologyIdSchema.optional(),
|
|
8284
|
+
entries: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
|
|
8285
|
+
});
|
|
8286
|
+
var OntologyEventTypeSchema = OntologyRecordBaseSchema.extend({
|
|
8287
|
+
payload: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
|
|
8288
|
+
});
|
|
8289
|
+
var OntologyInterfaceTypeSchema = OntologyRecordBaseSchema.extend({
|
|
8290
|
+
properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
|
|
8291
|
+
});
|
|
8292
|
+
var OntologyValueTypeSchema = OntologyRecordBaseSchema.extend({
|
|
8293
|
+
primitive: z.string().trim().min(1).max(120).optional()
|
|
8294
|
+
});
|
|
8295
|
+
var OntologySharedPropertySchema = OntologyRecordBaseSchema.extend({
|
|
8296
|
+
valueType: OntologyIdSchema.optional(),
|
|
8297
|
+
searchable: z.boolean().optional(),
|
|
8298
|
+
pii: z.boolean().optional()
|
|
8299
|
+
});
|
|
8300
|
+
var OntologyGroupSchema = OntologyRecordBaseSchema.extend({
|
|
8301
|
+
members: OntologyReferenceListSchema
|
|
8302
|
+
});
|
|
8303
|
+
var OntologySurfaceTypeSchema = OntologyRecordBaseSchema.extend({
|
|
8304
|
+
route: z.string().trim().min(1).max(500).optional()
|
|
8305
|
+
});
|
|
8306
|
+
z.object({
|
|
8307
|
+
objectTypes: z.record(OntologyIdSchema, OntologyObjectTypeSchema).default({}).optional(),
|
|
8308
|
+
linkTypes: z.record(OntologyIdSchema, OntologyLinkTypeSchema).default({}).optional(),
|
|
8309
|
+
actionTypes: z.record(OntologyIdSchema, OntologyActionTypeSchema).default({}).optional(),
|
|
8310
|
+
catalogTypes: z.record(OntologyIdSchema, OntologyCatalogTypeSchema).default({}).optional(),
|
|
8311
|
+
eventTypes: z.record(OntologyIdSchema, OntologyEventTypeSchema).default({}).optional(),
|
|
8312
|
+
interfaceTypes: z.record(OntologyIdSchema, OntologyInterfaceTypeSchema).default({}).optional(),
|
|
8313
|
+
valueTypes: z.record(OntologyIdSchema, OntologyValueTypeSchema).default({}).optional(),
|
|
8314
|
+
sharedProperties: z.record(OntologyIdSchema, OntologySharedPropertySchema).default({}).optional(),
|
|
8315
|
+
groups: z.record(OntologyIdSchema, OntologyGroupSchema).default({}).optional(),
|
|
8316
|
+
surfaces: z.record(OntologyIdSchema, OntologySurfaceTypeSchema).default({}).optional()
|
|
8317
|
+
}).default({});
|
|
8318
|
+
var SCOPE_KIND = {
|
|
8319
|
+
objectTypes: "object",
|
|
8320
|
+
linkTypes: "link",
|
|
8321
|
+
actionTypes: "action",
|
|
8322
|
+
catalogTypes: "catalog",
|
|
8323
|
+
eventTypes: "event",
|
|
8324
|
+
interfaceTypes: "interface",
|
|
8325
|
+
valueTypes: "value-type",
|
|
8326
|
+
sharedProperties: "property",
|
|
8327
|
+
groups: "group",
|
|
8328
|
+
surfaces: "surface"
|
|
8329
|
+
};
|
|
8330
|
+
var SCOPE_KEYS = Object.keys(SCOPE_KIND);
|
|
8331
|
+
function originFromContext(context) {
|
|
8332
|
+
return {
|
|
8333
|
+
kind: context.kind,
|
|
8334
|
+
source: context.source,
|
|
8335
|
+
path: context.path,
|
|
8336
|
+
...context.systemPath !== void 0 ? { systemPath: context.systemPath } : {},
|
|
8337
|
+
...context.legacyId !== void 0 ? { legacyId: context.legacyId } : {}
|
|
8338
|
+
};
|
|
8339
|
+
}
|
|
8340
|
+
function createEmptyIndex() {
|
|
8341
|
+
return {
|
|
8342
|
+
objectTypes: {},
|
|
8343
|
+
linkTypes: {},
|
|
8344
|
+
actionTypes: {},
|
|
8345
|
+
catalogTypes: {},
|
|
8346
|
+
eventTypes: {},
|
|
8347
|
+
interfaceTypes: {},
|
|
8348
|
+
valueTypes: {},
|
|
8349
|
+
sharedProperties: {},
|
|
8350
|
+
groups: {},
|
|
8351
|
+
surfaces: {}
|
|
8352
|
+
};
|
|
8353
|
+
}
|
|
8354
|
+
function sortResolvedOntologyIndex(index2) {
|
|
8355
|
+
const sorted = createEmptyIndex();
|
|
8356
|
+
for (const scopeKey of SCOPE_KEYS) {
|
|
8357
|
+
const target = sorted[scopeKey];
|
|
8358
|
+
for (const [id, record] of Object.entries(index2[scopeKey]).sort(
|
|
8359
|
+
([leftId], [rightId]) => leftId.localeCompare(rightId)
|
|
8360
|
+
)) {
|
|
8361
|
+
target[id] = record;
|
|
8362
|
+
}
|
|
8363
|
+
}
|
|
8364
|
+
return sorted;
|
|
8365
|
+
}
|
|
10519
8366
|
function childSystemsOf2(system) {
|
|
10520
8367
|
return system.systems ?? system.subsystems ?? {};
|
|
10521
8368
|
}
|
|
10522
|
-
function
|
|
10523
|
-
|
|
10524
|
-
|
|
10525
|
-
|
|
10526
|
-
|
|
10527
|
-
|
|
10528
|
-
|
|
10529
|
-
|
|
10530
|
-
|
|
10531
|
-
|
|
8369
|
+
function addRecord(index2, diagnostics, sourcesById, scopeKey, record, context) {
|
|
8370
|
+
let parsed;
|
|
8371
|
+
try {
|
|
8372
|
+
parsed = parseOntologyId(record.id);
|
|
8373
|
+
} catch {
|
|
8374
|
+
diagnostics.push({
|
|
8375
|
+
code: "invalid_ontology_id",
|
|
8376
|
+
message: `Invalid ontology ID "${record.id}" from ${context.source} at ${context.path.join(".")}`,
|
|
8377
|
+
id: record.id,
|
|
8378
|
+
path: context.path,
|
|
8379
|
+
source: context.source,
|
|
8380
|
+
origin: originFromContext(context)
|
|
8381
|
+
});
|
|
8382
|
+
return;
|
|
8383
|
+
}
|
|
8384
|
+
const expectedKind = SCOPE_KIND[scopeKey];
|
|
8385
|
+
if (parsed.kind !== expectedKind) {
|
|
8386
|
+
diagnostics.push({
|
|
8387
|
+
code: "ontology_kind_mismatch",
|
|
8388
|
+
message: `Ontology ID "${record.id}" has kind "${parsed.kind}" but was authored in ${scopeKey} (${expectedKind}) at ${context.path.join(".")}`,
|
|
8389
|
+
id: record.id,
|
|
8390
|
+
path: context.path,
|
|
8391
|
+
source: context.source,
|
|
8392
|
+
origin: originFromContext(context)
|
|
8393
|
+
});
|
|
8394
|
+
return;
|
|
8395
|
+
}
|
|
8396
|
+
const existing = sourcesById.get(parsed.id);
|
|
8397
|
+
if (existing !== void 0) {
|
|
8398
|
+
diagnostics.push({
|
|
8399
|
+
code: "duplicate_ontology_id",
|
|
8400
|
+
message: `Duplicate ontology ID "${parsed.id}" from ${context.source} at ${context.path.join(".")} conflicts with ${existing.source} at ${existing.path.join(".")}`,
|
|
8401
|
+
id: parsed.id,
|
|
8402
|
+
path: context.path,
|
|
8403
|
+
source: context.source,
|
|
8404
|
+
origin: originFromContext(context),
|
|
8405
|
+
existingSource: existing.source,
|
|
8406
|
+
existingOrigin: originFromContext(existing)
|
|
8407
|
+
});
|
|
8408
|
+
return;
|
|
8409
|
+
}
|
|
8410
|
+
sourcesById.set(parsed.id, context);
|
|
8411
|
+
index2[scopeKey][parsed.id] = {
|
|
8412
|
+
...record,
|
|
8413
|
+
origin: originFromContext(context)
|
|
8414
|
+
};
|
|
8415
|
+
}
|
|
8416
|
+
function addScope(index2, diagnostics, sourcesById, scope, source, path) {
|
|
8417
|
+
if (scope === void 0) return;
|
|
8418
|
+
for (const scopeKey of SCOPE_KEYS) {
|
|
8419
|
+
const records = scope[scopeKey] ?? {};
|
|
8420
|
+
for (const [key, record] of Object.entries(records)) {
|
|
8421
|
+
addRecord(index2, diagnostics, sourcesById, scopeKey, record, {
|
|
8422
|
+
source,
|
|
8423
|
+
path: [...path, scopeKey, key],
|
|
8424
|
+
kind: "authored",
|
|
8425
|
+
systemPath: source.startsWith("system:") ? source.slice("system:".length, -".ontology".length) : void 0
|
|
8426
|
+
});
|
|
10532
8427
|
}
|
|
10533
8428
|
}
|
|
10534
|
-
|
|
10535
|
-
|
|
8429
|
+
}
|
|
8430
|
+
function legacyObjectId(entity) {
|
|
8431
|
+
return formatOntologyId({ scope: entity.ownedBySystemId, kind: "object", localId: entity.id });
|
|
8432
|
+
}
|
|
8433
|
+
function legacyActionOwner(action, entities) {
|
|
8434
|
+
const firstAffectedEntityId = action.affects?.find((entityId) => entities[entityId] !== void 0);
|
|
8435
|
+
if (firstAffectedEntityId !== void 0) {
|
|
8436
|
+
return entities[firstAffectedEntityId].ownedBySystemId;
|
|
8437
|
+
}
|
|
8438
|
+
if (typeof action.scope === "object") {
|
|
8439
|
+
return action.scope.domain;
|
|
8440
|
+
}
|
|
8441
|
+
return "global";
|
|
8442
|
+
}
|
|
8443
|
+
function addLegacyEntityProjections(index2, diagnostics, sourcesById, entities) {
|
|
8444
|
+
for (const entity of Object.values(entities)) {
|
|
8445
|
+
const objectType = {
|
|
8446
|
+
id: legacyObjectId(entity),
|
|
8447
|
+
label: entity.label,
|
|
8448
|
+
description: entity.description,
|
|
8449
|
+
ownerSystemId: entity.ownedBySystemId,
|
|
8450
|
+
...entity.table !== void 0 ? {
|
|
8451
|
+
storage: {
|
|
8452
|
+
kind: "table",
|
|
8453
|
+
table: entity.table
|
|
8454
|
+
}
|
|
8455
|
+
} : {},
|
|
8456
|
+
...entity.rowSchema !== void 0 ? { rowSchema: entity.rowSchema } : {},
|
|
8457
|
+
...entity.stateCatalogId !== void 0 ? { stateCatalogId: entity.stateCatalogId } : {}
|
|
8458
|
+
};
|
|
8459
|
+
addRecord(index2, diagnostics, sourcesById, "objectTypes", objectType, {
|
|
8460
|
+
source: "legacy.entities",
|
|
8461
|
+
path: ["entities", entity.id],
|
|
8462
|
+
kind: "projected",
|
|
8463
|
+
systemPath: entity.ownedBySystemId,
|
|
8464
|
+
legacyId: entity.id
|
|
8465
|
+
});
|
|
8466
|
+
entity.links?.forEach((link, linkIndex) => {
|
|
8467
|
+
const targetEntity = entities[link.toEntity];
|
|
8468
|
+
if (targetEntity === void 0) return;
|
|
8469
|
+
const linkType = {
|
|
8470
|
+
id: formatOntologyId({
|
|
8471
|
+
scope: entity.ownedBySystemId,
|
|
8472
|
+
kind: "link",
|
|
8473
|
+
localId: `${entity.id}-${link.toEntity}-${linkIndex}`
|
|
8474
|
+
}),
|
|
8475
|
+
label: link.label ?? link.kind,
|
|
8476
|
+
ownerSystemId: entity.ownedBySystemId,
|
|
8477
|
+
from: legacyObjectId(entity),
|
|
8478
|
+
to: legacyObjectId(targetEntity),
|
|
8479
|
+
cardinality: link.kind,
|
|
8480
|
+
...link.via !== void 0 ? { via: link.via } : {}
|
|
8481
|
+
};
|
|
8482
|
+
addRecord(index2, diagnostics, sourcesById, "linkTypes", linkType, {
|
|
8483
|
+
source: "legacy.entities.links",
|
|
8484
|
+
path: ["entities", entity.id, "links", linkIndex],
|
|
8485
|
+
kind: "projected",
|
|
8486
|
+
systemPath: entity.ownedBySystemId,
|
|
8487
|
+
legacyId: `${entity.id}.links.${linkIndex}`
|
|
8488
|
+
});
|
|
8489
|
+
});
|
|
8490
|
+
}
|
|
8491
|
+
}
|
|
8492
|
+
function addLegacyActionProjections(index2, diagnostics, sourcesById, actions, entities) {
|
|
8493
|
+
for (const action of Object.values(actions)) {
|
|
8494
|
+
const ownerSystemId = legacyActionOwner(action, entities);
|
|
8495
|
+
const actionType = {
|
|
8496
|
+
id: formatOntologyId({ scope: ownerSystemId, kind: "action", localId: action.id }),
|
|
8497
|
+
label: action.label,
|
|
8498
|
+
description: action.description,
|
|
8499
|
+
ownerSystemId,
|
|
8500
|
+
actsOn: action.affects?.map((entityId) => entities[entityId] ? legacyObjectId(entities[entityId]) : void 0).filter((id) => id !== void 0),
|
|
8501
|
+
...action.resourceId !== void 0 ? { resourceId: action.resourceId } : {},
|
|
8502
|
+
...action.invocations !== void 0 ? { invocations: action.invocations } : {},
|
|
8503
|
+
...action.lifecycle !== void 0 ? { lifecycle: action.lifecycle } : {},
|
|
8504
|
+
legacyActionId: action.id
|
|
8505
|
+
};
|
|
8506
|
+
addRecord(index2, diagnostics, sourcesById, "actionTypes", actionType, {
|
|
8507
|
+
source: "legacy.actions",
|
|
8508
|
+
path: ["actions", action.id],
|
|
8509
|
+
kind: "projected",
|
|
8510
|
+
systemPath: ownerSystemId,
|
|
8511
|
+
legacyId: action.id
|
|
8512
|
+
});
|
|
8513
|
+
}
|
|
8514
|
+
}
|
|
8515
|
+
function addSystemScopes(index2, diagnostics, sourcesById, systems, prefix, schemaPath) {
|
|
8516
|
+
for (const [key, system] of Object.entries(systems)) {
|
|
8517
|
+
const systemPath = prefix ? `${prefix}.${key}` : key;
|
|
8518
|
+
const currentPath = [...schemaPath, key];
|
|
8519
|
+
addScope(index2, diagnostics, sourcesById, system.ontology, `system:${systemPath}.ontology`, [
|
|
8520
|
+
...currentPath,
|
|
8521
|
+
"ontology"
|
|
8522
|
+
]);
|
|
8523
|
+
addSystemScopes(index2, diagnostics, sourcesById, childSystemsOf2(system), systemPath, [
|
|
8524
|
+
...currentPath,
|
|
8525
|
+
system.systems !== void 0 ? "systems" : "subsystems"
|
|
8526
|
+
]);
|
|
8527
|
+
}
|
|
8528
|
+
}
|
|
8529
|
+
function compileOrganizationOntology(model) {
|
|
8530
|
+
const ontology = createEmptyIndex();
|
|
8531
|
+
const diagnostics = [];
|
|
8532
|
+
const sourcesById = /* @__PURE__ */ new Map();
|
|
8533
|
+
addScope(ontology, diagnostics, sourcesById, model.ontology, "organization.ontology", ["ontology"]);
|
|
8534
|
+
addSystemScopes(ontology, diagnostics, sourcesById, model.systems ?? {}, "", ["systems"]);
|
|
8535
|
+
addLegacyEntityProjections(ontology, diagnostics, sourcesById, model.entities ?? {});
|
|
8536
|
+
addLegacyActionProjections(ontology, diagnostics, sourcesById, model.actions ?? {}, model.entities ?? {});
|
|
8537
|
+
return { ontology: sortResolvedOntologyIndex(ontology), diagnostics };
|
|
10536
8538
|
}
|
|
10537
8539
|
z.object({
|
|
10538
8540
|
success: z.boolean(),
|
|
@@ -11182,34 +9184,11 @@ function captureConsole(executionId, logs) {
|
|
|
11182
9184
|
postLog
|
|
11183
9185
|
};
|
|
11184
9186
|
}
|
|
11185
|
-
|
|
11186
|
-
|
|
11187
|
-
if (value === null || value === void 0) return value;
|
|
11188
|
-
if (typeof value === "string") {
|
|
11189
|
-
return value.length > LOG_STRING_TRUNCATE_LIMIT ? value.slice(0, LOG_STRING_TRUNCATE_LIMIT) + `\u2026 [${value.length} chars]` : value;
|
|
11190
|
-
}
|
|
11191
|
-
if (Array.isArray(value)) {
|
|
11192
|
-
return value.map(truncateForLogging);
|
|
11193
|
-
}
|
|
11194
|
-
if (typeof value === "object") {
|
|
11195
|
-
const result = {};
|
|
11196
|
-
for (const [k2, v2] of Object.entries(value)) {
|
|
11197
|
-
result[k2] = truncateForLogging(v2);
|
|
11198
|
-
}
|
|
11199
|
-
return result;
|
|
11200
|
-
}
|
|
11201
|
-
return value;
|
|
11202
|
-
}
|
|
11203
|
-
function resolveNext(next, data) {
|
|
11204
|
-
if (next === null) return null;
|
|
11205
|
-
if (next.type === "linear") return next.target;
|
|
11206
|
-
for (const route of next.routes) {
|
|
11207
|
-
if (route.condition(data)) return route.target;
|
|
11208
|
-
}
|
|
11209
|
-
return next.default;
|
|
9187
|
+
function isZodSchema(schema) {
|
|
9188
|
+
return typeof schema === "object" && schema !== null && "parse" in schema && "_def" in schema;
|
|
11210
9189
|
}
|
|
11211
9190
|
function safeZodToJsonSchema(schema) {
|
|
11212
|
-
if (!
|
|
9191
|
+
if (!isZodSchema(schema)) return void 0;
|
|
11213
9192
|
try {
|
|
11214
9193
|
const result = zodToJsonSchema(schema, { $refStrategy: "none", errorMessages: true });
|
|
11215
9194
|
if (result && typeof result === "object" && Object.keys(result).some((k2) => k2 !== "$schema")) {
|
|
@@ -11228,84 +9207,28 @@ async function executeWorkflow(workflow, input, context) {
|
|
|
11228
9207
|
const logs = [];
|
|
11229
9208
|
const { restore, postLog } = captureConsole(context.executionId, logs);
|
|
11230
9209
|
try {
|
|
11231
|
-
|
|
11232
|
-
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
|
|
11240
|
-
|
|
11241
|
-
|
|
11242
|
-
|
|
11243
|
-
|
|
11244
|
-
|
|
11245
|
-
|
|
11246
|
-
|
|
11247
|
-
|
|
11248
|
-
|
|
11249
|
-
const rawOutput = await step.handler(stepInput, {
|
|
11250
|
-
executionId: context.executionId,
|
|
11251
|
-
organizationId: context.organizationId,
|
|
11252
|
-
organizationName: context.organizationName,
|
|
11253
|
-
resourceId: workflow.config.resourceId,
|
|
11254
|
-
sessionId: context.sessionId,
|
|
11255
|
-
sessionTurnNumber: context.sessionTurnNumber,
|
|
11256
|
-
parentExecutionId: context.parentExecutionId,
|
|
11257
|
-
executionDepth: context.executionDepth,
|
|
11258
|
-
adapters: context.adapters,
|
|
11259
|
-
store: /* @__PURE__ */ new Map(),
|
|
11260
|
-
logger: {
|
|
11261
|
-
debug: (msg) => console.log(`[debug] ${msg}`),
|
|
11262
|
-
info: (msg) => console.log(`[info] ${msg}`),
|
|
11263
|
-
warn: (msg) => console.warn(`[warn] ${msg}`),
|
|
11264
|
-
error: (msg) => console.error(`[error] ${msg}`)
|
|
11265
|
-
}
|
|
11266
|
-
});
|
|
11267
|
-
currentData = step.outputSchema.parse(rawOutput);
|
|
11268
|
-
const stepEndTime = Date.now();
|
|
11269
|
-
const nextStepId = resolveNext(step.next, currentData);
|
|
11270
|
-
postLog("info", `Step '${step.name}' completed (${stepEndTime - stepStartTime}ms)`, {
|
|
11271
|
-
type: "workflow",
|
|
11272
|
-
contextType: "step-completed",
|
|
11273
|
-
stepId: step.id,
|
|
11274
|
-
stepStatus: "completed",
|
|
11275
|
-
output: truncateForLogging(currentData),
|
|
11276
|
-
duration: stepEndTime - stepStartTime,
|
|
11277
|
-
isTerminal: nextStepId === null,
|
|
11278
|
-
startTime: stepStartTime,
|
|
11279
|
-
endTime: stepEndTime
|
|
11280
|
-
});
|
|
11281
|
-
if (step.next?.type === "conditional" && nextStepId !== null) {
|
|
11282
|
-
postLog("info", `Routing from '${step.name}' to '${nextStepId}'`, {
|
|
11283
|
-
type: "workflow",
|
|
11284
|
-
contextType: "conditional-route",
|
|
11285
|
-
stepId: step.id,
|
|
11286
|
-
target: nextStepId
|
|
11287
|
-
});
|
|
11288
|
-
}
|
|
11289
|
-
stepId = nextStepId;
|
|
11290
|
-
} catch (err) {
|
|
11291
|
-
const stepEndTime = Date.now();
|
|
11292
|
-
postLog("error", `Step '${step.name}' failed: ${String(err)}`, {
|
|
11293
|
-
type: "workflow",
|
|
11294
|
-
contextType: "step-failed",
|
|
11295
|
-
stepId: step.id,
|
|
11296
|
-
stepStatus: "failed",
|
|
11297
|
-
error: String(err),
|
|
11298
|
-
duration: stepEndTime - stepStartTime,
|
|
11299
|
-
startTime: stepStartTime,
|
|
11300
|
-
endTime: stepEndTime
|
|
11301
|
-
});
|
|
11302
|
-
throw err;
|
|
9210
|
+
const workflowInstance = new Workflow(workflow);
|
|
9211
|
+
const workerContext = {
|
|
9212
|
+
executionId: context.executionId,
|
|
9213
|
+
organizationId: context.organizationId,
|
|
9214
|
+
organizationName: context.organizationName,
|
|
9215
|
+
resourceId: workflow.config.resourceId,
|
|
9216
|
+
sessionId: context.sessionId,
|
|
9217
|
+
sessionTurnNumber: context.sessionTurnNumber,
|
|
9218
|
+
parentExecutionId: context.parentExecutionId,
|
|
9219
|
+
executionDepth: context.executionDepth,
|
|
9220
|
+
signal: context.signal,
|
|
9221
|
+
adapters: context.adapters,
|
|
9222
|
+
store: /* @__PURE__ */ new Map(),
|
|
9223
|
+
logger: {
|
|
9224
|
+
debug: (message, logContext) => postLog("debug", message, logContext),
|
|
9225
|
+
info: (message, logContext) => postLog("info", message, logContext),
|
|
9226
|
+
warn: (message, logContext) => postLog("warn", message, logContext),
|
|
9227
|
+
error: (message, logContext) => postLog("error", message, logContext)
|
|
11303
9228
|
}
|
|
11304
|
-
}
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
}
|
|
11308
|
-
return { output: currentData, logs };
|
|
9229
|
+
};
|
|
9230
|
+
const output = await workflowInstance.execute(input, workerContext);
|
|
9231
|
+
return { output, logs };
|
|
11309
9232
|
} finally {
|
|
11310
9233
|
restore();
|
|
11311
9234
|
}
|
|
@@ -11444,7 +9367,8 @@ function startWorker(org) {
|
|
|
11444
9367
|
sessionId,
|
|
11445
9368
|
sessionTurnNumber,
|
|
11446
9369
|
parentExecutionId,
|
|
11447
|
-
executionDepth: executionDepth ?? 0
|
|
9370
|
+
executionDepth: executionDepth ?? 0,
|
|
9371
|
+
signal: localAbortController.signal
|
|
11448
9372
|
});
|
|
11449
9373
|
const durationMs = Date.now() - startTime;
|
|
11450
9374
|
console.log(`[SDK-WORKER] Workflow '${resourceId}' completed (${durationMs}ms)`);
|
|
@@ -11488,9 +9412,10 @@ function startWorker(org) {
|
|
|
11488
9412
|
parentPort.postMessage({ type: "result", status: "completed", output, logs, metrics: { durationMs } });
|
|
11489
9413
|
} catch (err) {
|
|
11490
9414
|
const durationMs = Date.now() - startTime;
|
|
11491
|
-
const
|
|
11492
|
-
|
|
11493
|
-
|
|
9415
|
+
const errorRecord = err instanceof Error ? err : void 0;
|
|
9416
|
+
const errorMessage = errorRecord?.message ?? String(err);
|
|
9417
|
+
err !== null && typeof err === "object" && "code" in err ? String(err.code) : "unknown";
|
|
9418
|
+
const errorName = errorRecord?.name ?? (err !== null && typeof err === "object" && err.constructor?.name ? err.constructor.name : "Error");
|
|
11494
9419
|
console.error(`[SDK-WORKER] Agent '${resourceId}' failed (${durationMs}ms): [${errorName}] ${errorMessage}`);
|
|
11495
9420
|
parentPort.postMessage({
|
|
11496
9421
|
type: "result",
|