@synap-core/workspace-templates 0.9.3 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +137 -44
- package/dist/index.js +1816 -128
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__fixtures__/default-relation-defs.json +208 -0
- package/src/__fixtures__/report-automation-flow.json +393 -0
- package/src/agent-fleet.yaml +6 -1
- package/src/base.template.test.ts +160 -0
- package/src/base.yaml +839 -0
- package/src/business-developer.template.test.ts +79 -10
- package/src/business-developer.yaml +61 -39
- package/src/concept-guard.test.ts +47 -31
- package/src/concept-guard.ts +23 -19
- package/src/content-os.yaml +22 -0
- package/src/corpus-flow-validity.test.ts +130 -0
- package/src/crm.yaml +125 -8
- package/src/define.primary-surface.test.ts +2 -4
- package/src/define.ts +28 -0
- package/src/ecosystem.yaml +14 -0
- package/src/enterprise-os.yaml +1 -1
- package/src/foundation.yaml +8 -0
- package/src/grants.yaml +8 -0
- package/src/life-os.yaml +6 -1
- package/src/operations.yaml +270 -0
- package/src/outreach-comms.yaml +196 -0
- package/src/project-management.yaml +6 -1
- package/src/templates.ts +1717 -371
- package/src/types.ts +113 -37
- package/src/validate-flow.ts +186 -7
- package/src/validate-onboarding.test.ts +88 -0
- package/src/validate.ts +148 -12
package/src/validate.ts
CHANGED
|
@@ -152,6 +152,11 @@ export const SYSTEM_PROFILES = new Set([
|
|
|
152
152
|
"research",
|
|
153
153
|
"knowledge",
|
|
154
154
|
"user_observation",
|
|
155
|
+
// Generated artifact — a workspace-scoped pod system profile
|
|
156
|
+
// (`ensure-system-profiles.ts`) written by the `base` report automation. It
|
|
157
|
+
// was simply missing from this hand-maintained list; the flow's
|
|
158
|
+
// `create-report` node references it, so referential integrity needs it here.
|
|
159
|
+
"report",
|
|
155
160
|
]);
|
|
156
161
|
|
|
157
162
|
// ── Dependency-vocabulary closure (compose vs require semantics) ─────────────
|
|
@@ -274,7 +279,8 @@ export function validateTemplate(
|
|
|
274
279
|
if (!tpl.meta) add("meta-required", "meta", "Missing required field: meta");
|
|
275
280
|
else {
|
|
276
281
|
for (const f of REQUIRED_META_FIELDS) {
|
|
277
|
-
if (!tpl.meta[f])
|
|
282
|
+
if (!tpl.meta[f])
|
|
283
|
+
add("meta-field-required", `meta.${f}`, `meta.${f} is required`);
|
|
278
284
|
}
|
|
279
285
|
}
|
|
280
286
|
if (!tpl.workspace)
|
|
@@ -283,12 +289,33 @@ export function validateTemplate(
|
|
|
283
289
|
for (const f of REQUIRED_WORKSPACE_FIELDS) {
|
|
284
290
|
if (!tpl.workspace[f])
|
|
285
291
|
add(
|
|
286
|
-
"workspace-field-required",
|
|
292
|
+
"workspace-field-required",
|
|
293
|
+
`workspace.${f}`,
|
|
294
|
+
`workspace.${f} is required`
|
|
287
295
|
);
|
|
288
296
|
}
|
|
289
297
|
}
|
|
290
|
-
|
|
291
|
-
|
|
298
|
+
// A template earns validity by declaring a data-schema profile OR by carrying
|
|
299
|
+
// operational defaults (relation vocabulary / commands / automations). The
|
|
300
|
+
// `base` template is the latter: pod-wide operational config with no
|
|
301
|
+
// data-schema profile of its own (its report automation writes the `report`
|
|
302
|
+
// system profile and reads other system profiles, none declared here). Without
|
|
303
|
+
// this carve-out a legitimate operational-defaults template fails the gate,
|
|
304
|
+
// while a data template that forgot its profiles still does (it carries no
|
|
305
|
+
// operational config either).
|
|
306
|
+
const carriesOperationalDefaults =
|
|
307
|
+
(tpl.relationDefs && tpl.relationDefs.length > 0) ||
|
|
308
|
+
(tpl.commands && tpl.commands.length > 0) ||
|
|
309
|
+
(tpl.automations && tpl.automations.length > 0);
|
|
310
|
+
if (
|
|
311
|
+
(!tpl.profiles || tpl.profiles.length === 0) &&
|
|
312
|
+
!carriesOperationalDefaults
|
|
313
|
+
) {
|
|
314
|
+
add(
|
|
315
|
+
"profiles-required",
|
|
316
|
+
"profiles",
|
|
317
|
+
"At least one profile is required (or operational defaults: relationDefs / commands / automations)"
|
|
318
|
+
);
|
|
292
319
|
}
|
|
293
320
|
if (
|
|
294
321
|
tpl.app &&
|
|
@@ -434,7 +461,110 @@ export function validateTemplate(
|
|
|
434
461
|
}
|
|
435
462
|
}
|
|
436
463
|
|
|
437
|
-
|
|
464
|
+
const onboarding = tpl.onboarding;
|
|
465
|
+
if (onboarding) {
|
|
466
|
+
if (typeof onboarding.goal !== "string" || onboarding.goal.trim() === "") {
|
|
467
|
+
add(
|
|
468
|
+
"onboarding-goal-empty",
|
|
469
|
+
"onboarding.goal",
|
|
470
|
+
"onboarding.goal must be a non-empty string"
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
if (
|
|
474
|
+
typeof onboarding.framing !== "string" ||
|
|
475
|
+
onboarding.framing.trim() === ""
|
|
476
|
+
) {
|
|
477
|
+
add(
|
|
478
|
+
"onboarding-framing-empty",
|
|
479
|
+
"onboarding.framing",
|
|
480
|
+
"onboarding.framing must be a non-empty string"
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
if (!Array.isArray(onboarding.collect) || onboarding.collect.length === 0) {
|
|
484
|
+
add(
|
|
485
|
+
"onboarding-collect-empty",
|
|
486
|
+
"onboarding.collect",
|
|
487
|
+
"onboarding.collect must contain at least one structured target"
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const expertise = onboarding.expertise;
|
|
492
|
+
for (const [field, values] of [
|
|
493
|
+
["starters", expertise?.starters],
|
|
494
|
+
["blindSpots", expertise?.blindSpots],
|
|
495
|
+
] as const) {
|
|
496
|
+
if (
|
|
497
|
+
values !== undefined &&
|
|
498
|
+
(!Array.isArray(values) ||
|
|
499
|
+
values.some(
|
|
500
|
+
(value) => typeof value !== "string" || value.trim() === ""
|
|
501
|
+
))
|
|
502
|
+
) {
|
|
503
|
+
add(
|
|
504
|
+
"onboarding-expertise-invalid",
|
|
505
|
+
`onboarding.expertise.${field}`,
|
|
506
|
+
`onboarding.expertise.${field} must contain only non-empty strings`
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
if (
|
|
511
|
+
expertise?.bar !== undefined &&
|
|
512
|
+
(typeof expertise.bar !== "string" || expertise.bar.trim() === "")
|
|
513
|
+
) {
|
|
514
|
+
add(
|
|
515
|
+
"onboarding-expertise-invalid",
|
|
516
|
+
"onboarding.expertise.bar",
|
|
517
|
+
"onboarding.expertise.bar must be a non-empty string"
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (
|
|
522
|
+
onboarding.openingQuestions !== undefined &&
|
|
523
|
+
(!Array.isArray(onboarding.openingQuestions) ||
|
|
524
|
+
onboarding.openingQuestions.some(
|
|
525
|
+
(question) => typeof question !== "string" || question.trim() === ""
|
|
526
|
+
))
|
|
527
|
+
) {
|
|
528
|
+
add(
|
|
529
|
+
"onboarding-opening-questions-invalid",
|
|
530
|
+
"onboarding.openingQuestions",
|
|
531
|
+
"onboarding.openingQuestions must contain only non-empty strings"
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
if (
|
|
535
|
+
onboarding.doneWhen !== undefined &&
|
|
536
|
+
(typeof onboarding.doneWhen !== "string" ||
|
|
537
|
+
onboarding.doneWhen.trim() === "")
|
|
538
|
+
) {
|
|
539
|
+
add(
|
|
540
|
+
"onboarding-done-when-invalid",
|
|
541
|
+
"onboarding.doneWhen",
|
|
542
|
+
"onboarding.doneWhen must be a non-empty string"
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
for (const c of onboarding?.collect || []) {
|
|
548
|
+
if (typeof c.what !== "string" || c.what.trim() === "") {
|
|
549
|
+
add(
|
|
550
|
+
"onboarding-collect-what-empty",
|
|
551
|
+
`onboarding.collect.${c.profileSlug}.what`,
|
|
552
|
+
`onboarding.collect target "${c.profileSlug}" must describe what to capture`
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
if (
|
|
556
|
+
c.keyFields !== undefined &&
|
|
557
|
+
(!Array.isArray(c.keyFields) ||
|
|
558
|
+
c.keyFields.some(
|
|
559
|
+
(field) => typeof field !== "string" || field.trim() === ""
|
|
560
|
+
))
|
|
561
|
+
) {
|
|
562
|
+
add(
|
|
563
|
+
"onboarding-collect-key-fields-invalid",
|
|
564
|
+
`onboarding.collect.${c.profileSlug}.keyFields`,
|
|
565
|
+
`onboarding.collect target "${c.profileSlug}" keyFields must contain only non-empty strings`
|
|
566
|
+
);
|
|
567
|
+
}
|
|
438
568
|
if (!known(c.profileSlug))
|
|
439
569
|
add(
|
|
440
570
|
"onboarding-ref-unknown",
|
|
@@ -457,14 +587,17 @@ export function validateTemplate(
|
|
|
457
587
|
for (const a of tpl.automations || []) {
|
|
458
588
|
const refs: Array<{ where: string; slug: string }> = [];
|
|
459
589
|
collectProfileSlugRefs(
|
|
460
|
-
a.triggerConfig,
|
|
590
|
+
a.triggerConfig,
|
|
591
|
+
`automation "${a.name}".triggerConfig`,
|
|
461
592
|
refs
|
|
462
593
|
);
|
|
463
594
|
collectProfileSlugRefs(a.flow, `automation "${a.name}".flow`, refs);
|
|
464
595
|
for (const r of refs)
|
|
465
596
|
if (!known(r.slug))
|
|
466
597
|
add(
|
|
467
|
-
"automation-ref-unknown",
|
|
598
|
+
"automation-ref-unknown",
|
|
599
|
+
r.where,
|
|
600
|
+
`${r.where} references unknown profile "${r.slug}"`
|
|
468
601
|
);
|
|
469
602
|
|
|
470
603
|
// Node-contract validation. Previously validate.ts checked automations for
|
|
@@ -476,9 +609,8 @@ export function validateTemplate(
|
|
|
476
609
|
// author time); the structural + per-node contract checks always run.
|
|
477
610
|
const flow = a.flow ?? (a as { flowDefinition?: unknown }).flowDefinition;
|
|
478
611
|
if (flow != null) {
|
|
479
|
-
const { errors: flowErrors
|
|
480
|
-
|
|
481
|
-
for (const fe of flowErrors) {
|
|
612
|
+
const { errors: flowErrors } = validateFlowDefinition(flow);
|
|
613
|
+
for (const fe of flowErrors) {
|
|
482
614
|
const loc = fe.nodeId
|
|
483
615
|
? `automation "${a.name}".flow.node "${fe.nodeId}"`
|
|
484
616
|
: fe.edgeId
|
|
@@ -602,11 +734,15 @@ export function validateTemplate(
|
|
|
602
734
|
|
|
603
735
|
const doors: Array<
|
|
604
736
|
[
|
|
605
|
-
string,
|
|
737
|
+
string,
|
|
738
|
+
Array<{ widgetType?: unknown }>,
|
|
739
|
+
Array<{ viewName?: unknown; kind?: unknown }>,
|
|
606
740
|
]
|
|
607
741
|
> = [
|
|
608
742
|
[
|
|
609
|
-
"tRPC createFromDefinition",
|
|
743
|
+
"tRPC createFromDefinition",
|
|
744
|
+
definition.bentoLayout ?? [],
|
|
745
|
+
definition.bentoViewBlocks ?? [],
|
|
610
746
|
],
|
|
611
747
|
["CP packages/apply", pkg.bentoLayout ?? [], pkg.bentoViewBlocks ?? []],
|
|
612
748
|
];
|