@synap-core/workspace-templates 0.11.0 → 0.23.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.
Files changed (249) hide show
  1. package/README.md +483 -0
  2. package/automations/bookmark-enrichment.automation.json +321 -0
  3. package/automations/github-pr-events.automation.json +505 -0
  4. package/automations/mail-feed.automation.json +86 -0
  5. package/automations/ship-a-change-checks-green.automation.json +106 -0
  6. package/automations/ship-a-change-checks-red.automation.json +106 -0
  7. package/automations/ship-a-change-deployed.automation.json +56 -0
  8. package/automations/ship-a-change-pr-merged.automation.json +110 -0
  9. package/automations/ship-a-change-pr-opened.automation.json +104 -0
  10. package/automations/url-bookmark-capture.automation.json +132 -0
  11. package/capabilities/agency-skills.capability.json +157 -0
  12. package/capabilities/apify.capability.json +265 -0
  13. package/capabilities/apollo.capability.json +120 -0
  14. package/capabilities/arch-backend.capability.json +97 -0
  15. package/capabilities/arch-client-intelligence.capability.json +401 -0
  16. package/capabilities/backblaze-b2.capability.json +205 -0
  17. package/capabilities/cal-com.capability.json +266 -0
  18. package/capabilities/canva.capability.json +274 -0
  19. package/capabilities/claude-code-routines.capability.json +172 -0
  20. package/capabilities/claude-managed-agents.capability.json +215 -0
  21. package/capabilities/client-comms-report.capability.json +246 -0
  22. package/capabilities/content-idea-to-production.capability.json +29 -0
  23. package/capabilities/datagouv.capability.json +315 -0
  24. package/capabilities/discord-bot.capability.json +157 -0
  25. package/capabilities/dropbox.capability.json +281 -0
  26. package/capabilities/exa.capability.json +109 -0
  27. package/capabilities/fal-ai.capability.json +83 -0
  28. package/capabilities/fal-media-lab.capability.json +158 -0
  29. package/capabilities/fireflies.capability.json +191 -0
  30. package/capabilities/freellmapi.capability.json +114 -0
  31. package/capabilities/generic-apikey.capability.json +92 -0
  32. package/capabilities/github-merge.capability.json +99 -0
  33. package/capabilities/github-read.capability.json +325 -0
  34. package/capabilities/governance-tighten-recommender.capability.json +81 -0
  35. package/capabilities/jev.capability.json +226 -0
  36. package/capabilities/lead-conversion-enrollment.capability.json +246 -0
  37. package/capabilities/mail-feed.capability.json +277 -0
  38. package/capabilities/mailgun.capability.json +52 -0
  39. package/capabilities/nango-google.capability.json +639 -0
  40. package/capabilities/notion.capability.json +417 -0
  41. package/capabilities/omniroute.capability.json +137 -0
  42. package/capabilities/posthog-analytics.capability.json +258 -0
  43. package/capabilities/postiz.capability.json +467 -0
  44. package/capabilities/proactive-digest.capability.json +190 -0
  45. package/capabilities/proton.capability.json +288 -0
  46. package/capabilities/replicate-rvm.capability.json +97 -0
  47. package/capabilities/research-methods.capability.json +57 -0
  48. package/capabilities/shopify.capability.json +395 -0
  49. package/capabilities/slack.capability.json +369 -0
  50. package/capabilities/stripe.capability.json +420 -0
  51. package/capabilities/telegram-bridge.capability.json +56 -0
  52. package/capabilities/treg.capability.json +102 -0
  53. package/capabilities/unipile-linkedin.capability.json +471 -0
  54. package/capabilities/vercel.capability.json +424 -0
  55. package/dist/define-CPS0n8BV.d.ts +1331 -0
  56. package/dist/index.d.ts +189 -900
  57. package/dist/index.js +24654 -21639
  58. package/dist/index.js.map +1 -1
  59. package/dist/wire.d.ts +222 -0
  60. package/dist/wire.js +77 -0
  61. package/dist/wire.js.map +1 -0
  62. package/package.json +41 -27
  63. package/packs/bookmark-views-pack.json +33 -0
  64. package/packs/crm-pack.json +76 -0
  65. package/packs/customer-profile.json +28 -0
  66. package/packs/deep-research.playbook.json +30 -0
  67. package/packs/event-views-pack.json +33 -0
  68. package/packs/habit-profile.json +27 -0
  69. package/packs/hr-pack.json +54 -0
  70. package/packs/invoice-profile.json +28 -0
  71. package/packs/knowledge-base-pack.json +56 -0
  72. package/packs/meeting-profile.json +29 -0
  73. package/packs/product-profile.json +30 -0
  74. package/packs/project-management-pack.json +49 -0
  75. package/packs/recipe-profile.json +29 -0
  76. package/packs/task-views-pack.json +39 -0
  77. package/retired.yaml +136 -0
  78. package/skills/app-factory-build-slice/SKILL.md +70 -0
  79. package/skills/app-factory-build-slice.catalog.json +17 -0
  80. package/skills/app-factory-design-canvas/SKILL.md +96 -0
  81. package/skills/app-factory-design-canvas.catalog.json +17 -0
  82. package/skills/app-factory-design-review/SKILL.md +99 -0
  83. package/skills/app-factory-design-review.catalog.json +18 -0
  84. package/skills/app-factory-research/SKILL.md +123 -0
  85. package/skills/app-factory-research.catalog.json +17 -0
  86. package/skills/bookmark-enrichment/SKILL.md +40 -0
  87. package/skills/carousel-format/carousel-format.skill.json +18 -0
  88. package/skills/collage-broll/collage-broll.skill.json +20 -0
  89. package/skills/content-taste/content-taste.skill.json +18 -0
  90. package/skills/creative-director/creative-director.skill.json +18 -0
  91. package/skills/design-critique/SKILL.md +135 -0
  92. package/skills/design-critique.catalog.json +12 -0
  93. package/skills/designing-with-real-components/SKILL.md +140 -0
  94. package/skills/designing-with-real-components.catalog.json +12 -0
  95. package/skills/edit-loop/edit-loop.skill.json +25 -0
  96. package/skills/facecam-edit/facecam-edit.skill.json +24 -0
  97. package/skills/mapping-the-server/SKILL.md +54 -0
  98. package/skills/math-explainer-manimgx/math-explainer-manimgx.skill.json +20 -0
  99. package/skills/motion-quality-gates/motion-quality-gates.skill.json +20 -0
  100. package/skills/open-design-edit/open-design-edit.skill.json +24 -0
  101. package/skills/reading-client-progress/SKILL.md +65 -0
  102. package/skills/routing-to-channels/SKILL.md +54 -0
  103. package/skills/stellar-scf-grants-advisor/ASSOCIATE-CHEATSHEET.md +133 -0
  104. package/skills/stellar-scf-grants-advisor/ASSOCIATE-ONBOARDING-GUIDE.md +761 -0
  105. package/skills/stellar-scf-grants-advisor/CLIENT-FAQ.md +181 -0
  106. package/skills/stellar-scf-grants-advisor/PARTNER-HANDOVER.md +130 -0
  107. package/skills/stellar-scf-grants-advisor/SKILL.md +102 -0
  108. package/skills/stellar-scf-grants-advisor/examples/README.md +43 -0
  109. package/skills/stellar-scf-grants-advisor/examples/chat-summary-templates.md +158 -0
  110. package/skills/stellar-scf-grants-advisor/examples/corpus-comparable-rows.md +136 -0
  111. package/skills/stellar-scf-grants-advisor/examples/q10-team-rewrites.md +109 -0
  112. package/skills/stellar-scf-grants-advisor/examples/q2-description-rewrites.md +88 -0
  113. package/skills/stellar-scf-grants-advisor/examples/q6-integration-rewrites.md +107 -0
  114. package/skills/stellar-scf-grants-advisor/examples/tranche-structures.md +176 -0
  115. package/skills/stellar-scf-grants-advisor/reference/01-methodology.md +96 -0
  116. package/skills/stellar-scf-grants-advisor/reference/02-scoring-framework.md +199 -0
  117. package/skills/stellar-scf-grants-advisor/reference/03-rejection-patterns.md +241 -0
  118. package/skills/stellar-scf-grants-advisor/reference/04-winner-patterns.md +120 -0
  119. package/skills/stellar-scf-grants-advisor/reference/05-comeback-patterns.md +92 -0
  120. package/skills/stellar-scf-grants-advisor/reference/06-budget-benchmarks.md +125 -0
  121. package/skills/stellar-scf-grants-advisor/reference/07-integration-list.md +147 -0
  122. package/skills/stellar-scf-grants-advisor/reference/08-abstract-fields.md +258 -0
  123. package/skills/stellar-scf-grants-advisor/reference/09-build-fields.md +259 -0
  124. package/skills/stellar-scf-grants-advisor/reference/10-corpus-winners.md +135 -0
  125. package/skills/stellar-scf-grants-advisor/reference/11-corpus-rejects.md +267 -0
  126. package/skills/stellar-scf-grants-advisor/reference/12-client-communication.md +131 -0
  127. package/skills/stellar-scf-grants-advisor/reference/13-excel-output-spec.md +199 -0
  128. package/skills/stellar-scf-grants-advisor/reference/14-worked-examples.md +160 -0
  129. package/skills/stellar-scf-grants-advisor/templates/abstract-review-builder.py +253 -0
  130. package/skills/stellar-scf-grants-advisor/templates/build-review-builder.py +213 -0
  131. package/skills/video-direction/video-direction.skill.json +20 -0
  132. package/skills/video-style-vocabulary/video-style-vocabulary.skill.json +20 -0
  133. package/skills/video-toolbox/video-toolbox.skill.json +20 -0
  134. package/src/__fixtures__/lifecycle-presets.flat-before.json +205 -0
  135. package/src/agency-os.yaml +122 -0
  136. package/src/agent-os-skill-slugs.test.ts +65 -0
  137. package/src/apify-social-reader.test.ts +317 -0
  138. package/src/base.template.test.ts +25 -19
  139. package/src/base.yaml +95 -39
  140. package/src/blockchain-ecosystem.yaml +1 -0
  141. package/src/brand-library.yaml +525 -14
  142. package/src/builder-dev-fold.template.test.ts +113 -0
  143. package/src/builder.yaml +798 -92
  144. package/src/business-model-catalog-description.test.ts +47 -0
  145. package/src/business-model-grp.template.test.ts +214 -0
  146. package/src/business-model.yaml +598 -0
  147. package/src/catalog-safety.test.ts +198 -0
  148. package/src/catalog.template-items.test.ts +75 -0
  149. package/src/catalog.ts +85 -2
  150. package/src/civic-france.yaml +102 -0
  151. package/src/concept-guard.test.ts +28 -8
  152. package/src/concept-guard.ts +2 -2
  153. package/src/content-creation.template.test.ts +52 -0
  154. package/src/content-creation.yaml +192 -0
  155. package/src/content-os.edit-loop.template.test.ts +210 -0
  156. package/src/content-os.publish-due-posts.template.test.ts +261 -0
  157. package/src/content-os.template.test.ts +322 -0
  158. package/src/content-os.video-takes.template.test.ts +338 -0
  159. package/src/content-os.work-a-take.template.test.ts +125 -0
  160. package/src/content-os.yaml +1830 -39
  161. package/src/content-studio-retired.template.test.ts +82 -0
  162. package/src/corpus-flow-validity.test.ts +4 -5
  163. package/src/crm-absorbs-outreach.template.test.ts +117 -0
  164. package/src/crm-build-plan.template.test.ts +128 -0
  165. package/src/crm-lists.template.test.ts +96 -0
  166. package/src/crm-messages-cadence.template.test.ts +164 -0
  167. package/src/crm-one-send-door.template.test.ts +65 -0
  168. package/src/crm.yaml +1456 -181
  169. package/src/decisions-wave.template.test.ts +186 -0
  170. package/src/define.ts +130 -17
  171. package/src/design-to-implementation.template.test.ts +94 -0
  172. package/src/dist-freshness.test.ts +97 -0
  173. package/src/domain-template-type.test.ts +75 -0
  174. package/src/ecosystem.yaml +27 -66
  175. package/src/enterprise-os.yaml +10 -134
  176. package/src/facecam-edit.audio-studio.test.ts +188 -0
  177. package/src/fal-generate-image.test.ts +200 -0
  178. package/src/fal-media-lab-pod-files.test.ts +180 -0
  179. package/src/finance.yaml +254 -1
  180. package/src/foundation.yaml +130 -28
  181. package/src/frame-host-modules.d.mts +6 -0
  182. package/src/frame-host-modules.mjs +58 -0
  183. package/src/generate.mjs +9 -3
  184. package/src/github-merge.test.ts +210 -0
  185. package/src/grants.yaml +57 -17
  186. package/src/hr.yaml +39 -6
  187. package/src/index.ts +36 -1
  188. package/src/intent.test.ts +161 -0
  189. package/src/internal-runbook.yaml +19 -1
  190. package/src/jev.test.ts +356 -0
  191. package/src/legal.yaml +33 -1
  192. package/src/life-os.yaml +65 -240
  193. package/src/lifecycle-coverage.test.ts +124 -0
  194. package/src/lifecycle-declarations.test.ts +252 -0
  195. package/src/lifecycle-presets.test.ts +468 -0
  196. package/src/lifecycle-presets.ts +494 -0
  197. package/src/lifecycle-stuck.test.ts +46 -0
  198. package/src/lifecycle-waits.parity.test.ts +319 -0
  199. package/src/marketing.yaml +108 -4
  200. package/src/meetings-knowledge.yaml +18 -0
  201. package/src/networking.yaml +23 -2
  202. package/src/operations.yaml +304 -4
  203. package/src/pipeline-views.template.test.ts +88 -0
  204. package/src/playbook-goal-placeholders.test.ts +57 -0
  205. package/src/postiz-contract.test.ts +134 -0
  206. package/src/presentation-declarations.test.ts +174 -0
  207. package/src/process-contract.validate.test.ts +352 -0
  208. package/src/project-management.yaml +39 -740
  209. package/src/publish-body.d.mts +29 -0
  210. package/src/publish-body.mjs +74 -0
  211. package/src/publish-body.test.ts +74 -0
  212. package/src/publish-official-lib.test.ts +176 -0
  213. package/src/replicate-rvm.test.ts +504 -0
  214. package/src/research-base.yaml +119 -20
  215. package/src/research-decision.yaml +60 -3
  216. package/src/reserved-profile-slugs.test.ts +83 -0
  217. package/src/retired-goal-kinds.test.ts +58 -0
  218. package/src/role-reference-and-step-domain.test.ts +192 -0
  219. package/src/seed-obligation.test.ts +176 -0
  220. package/src/send-message-maps.test.ts +227 -0
  221. package/src/shared-role-ssot.test.ts +42 -1
  222. package/src/ship-a-change.template.test.ts +177 -0
  223. package/src/skills.test.ts +170 -0
  224. package/src/social.yaml +85 -27
  225. package/src/space-packages.freshness.test.ts +97 -0
  226. package/src/space-packages.generated.ts +40 -0
  227. package/src/space-packages.test.ts +125 -0
  228. package/src/space-packages.ts +73 -0
  229. package/src/start.test.ts +188 -0
  230. package/src/task-intents.test.ts +293 -0
  231. package/src/templates.ts +21639 -21522
  232. package/src/types.ts +443 -60
  233. package/src/unipile-publish-post.test.ts +162 -0
  234. package/src/validate-flow.drift.test.ts +2 -3
  235. package/src/validate-flow.ts +32 -2
  236. package/src/validate-onboarding.test.ts +59 -0
  237. package/src/validate.test.ts +156 -3
  238. package/src/validate.ts +1384 -7
  239. package/src/wire-core.ts +231 -0
  240. package/src/wire.test.ts +159 -0
  241. package/src/wire.ts +107 -0
  242. package/src/__fixtures__/report-automation-flow.json +0 -393
  243. package/src/agent-fleet.yaml +0 -1645
  244. package/src/business-developer.template.test.ts +0 -351
  245. package/src/business-developer.yaml +0 -860
  246. package/src/content-studio.yaml +0 -361
  247. package/src/dev-dashboard.yaml +0 -990
  248. package/src/outreach-comms.yaml +0 -486
  249. package/src/the-arch.yaml +0 -201
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Jev (capability `jev`): the four verbs speak TypeSafe's System One API.
3
+ *
4
+ * SEAM: each verb's REAL `code` body, run the way the pod's executor wraps it
5
+ * (`async (args, context) => { <code> }` with `callProvider` in scope), against
6
+ * responses shaped like TypeSafe's documented examples
7
+ * (https://docs.typesafe.ai/api/system-one.md, OpenAPI 0.2.0, read 2026-10-28).
8
+ * The request asserted is exactly what `callProvider` would send.
9
+ *
10
+ * NOT covered: Jev's live behaviour (the founder's own install is the live
11
+ * test), the pod's `{{param}}` interpolation (simulated below the way
12
+ * `interpolateDeep` does it) and the IS isolate (Node's AsyncFunction is used).
13
+ */
14
+ import { readFileSync } from "node:fs";
15
+ import { dirname, join } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+ import { describe, expect, it } from "vitest";
18
+
19
+ const HERE = dirname(fileURLToPath(import.meta.url));
20
+ const manifest = JSON.parse(
21
+ readFileSync(join(HERE, "../capabilities/jev.capability.json"), "utf8")
22
+ );
23
+ type Skill = {
24
+ name: string;
25
+ code?: string;
26
+ parameters?: Record<string, string>;
27
+ };
28
+ const skills = manifest.spec.skills as Skill[];
29
+
30
+ const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor as new (
31
+ ...args: string[]
32
+ ) => (...a: unknown[]) => Promise<unknown>;
33
+
34
+ type Call = {
35
+ tool: string;
36
+ method: string;
37
+ path: string;
38
+ input: Record<string, any>;
39
+ };
40
+ function verb(name: string) {
41
+ const code = skills.find((s) => s.name === name)!.code!;
42
+ const body = new AsyncFunction("args", "context", "callProvider", code);
43
+ return async (
44
+ args: Record<string, unknown>,
45
+ answers: Record<string, unknown>,
46
+ status = 200
47
+ ) => {
48
+ const calls: Call[] = [];
49
+ const callProvider = async (
50
+ tool: string,
51
+ method: string,
52
+ path: string,
53
+ input: Record<string, any>
54
+ ) => {
55
+ calls.push({ tool, method, path, input });
56
+ return {
57
+ status,
58
+ headers: {},
59
+ body: {
60
+ model: input.model,
61
+ answers,
62
+ usage: { input_tokens: 120, output_tokens: 12 },
63
+ },
64
+ };
65
+ };
66
+ const out = (await body(args, {}, callProvider)) as Record<string, any>;
67
+ return { out, calls };
68
+ };
69
+ }
70
+
71
+ /**
72
+ * What the pod checks BEFORE a verb runs (backend validate-verb-parameters.ts):
73
+ * each declared field's base type against the argument's runtime type, and
74
+ * required fields present. The live run of 28 Oct was refused there ("options
75
+ * should be array, got object") while every code-level test passed.
76
+ */
77
+ function declaredTypeErrors(
78
+ name: string,
79
+ args: Record<string, unknown>
80
+ ): string[] {
81
+ const declared = skills.find((s) => s.name === name)!.parameters ?? {};
82
+ const kind = (v: unknown) =>
83
+ Array.isArray(v) ? "array" : v === null ? "null" : typeof v;
84
+ const errors: string[] = [];
85
+ for (const [field, type] of Object.entries(declared)) {
86
+ const optional = type.endsWith("?");
87
+ const base = type.replace(/\?$/, "");
88
+ if (!(field in args)) {
89
+ if (!optional) errors.push(`${field} missing`);
90
+ continue;
91
+ }
92
+ if (kind(args[field]) !== base)
93
+ errors.push(`${field} should be ${base}, got ${kind(args[field])}`);
94
+ }
95
+ return errors;
96
+ }
97
+
98
+ const STATE =
99
+ "I was charged twice for my subscription this month. Please refund the extra charge.";
100
+
101
+ describe("jev_choose — one choice question, Jev's probabilities and confidence back", () => {
102
+ it("sends one POST /v1/systemone through jev_api with the options as criteria", async () => {
103
+ const { out, calls } = await verb("jev_choose")(
104
+ {
105
+ state: STATE,
106
+ question: "What is the tone?",
107
+ options: ["angry", "calm"],
108
+ descriptions: { angry: "An upset message", calm: "A polite message" },
109
+ minConfidence: 0.6,
110
+ },
111
+ {
112
+ decision: {
113
+ type: "choice",
114
+ choice: "calm",
115
+ confidence: 0.7,
116
+ probabilities: { angry: 0.2, calm: 0.8 },
117
+ },
118
+ }
119
+ );
120
+ expect(calls).toEqual([
121
+ {
122
+ tool: "jev_api",
123
+ method: "POST",
124
+ path: "/v1/systemone",
125
+ input: {
126
+ model: "jev-latest",
127
+ state: STATE,
128
+ questions: {
129
+ decision: {
130
+ type: "choice",
131
+ instructions: "What is the tone?",
132
+ criteria: { angry: "An upset message", calm: "A polite message" },
133
+ },
134
+ },
135
+ },
136
+ },
137
+ ]);
138
+ expect(out).toMatchObject({
139
+ choice: "calm",
140
+ confidence: 0.7,
141
+ confident: true,
142
+ probabilities: { angry: 0.2, calm: 0.8 },
143
+ model: "jev-latest",
144
+ });
145
+ });
146
+
147
+ it("a list of options becomes criteria keyed by the option; under minConfidence is not confident", async () => {
148
+ const { out, calls } = await verb("jev_choose")(
149
+ {
150
+ state: STATE,
151
+ question: "Which team?",
152
+ options: ["billing", "support", "none_of_these"],
153
+ minConfidence: 0.8,
154
+ },
155
+ {
156
+ decision: {
157
+ type: "choice",
158
+ choice: "billing",
159
+ confidence: 0.55,
160
+ probabilities: { billing: 0.6, support: 0.3, none_of_these: 0.1 },
161
+ },
162
+ }
163
+ );
164
+ expect(calls[0].input.questions.decision.criteria).toEqual({
165
+ billing: "billing",
166
+ support: "support",
167
+ none_of_these: "none_of_these",
168
+ });
169
+ expect(out.confident).toBe(false);
170
+ });
171
+
172
+ it("a model passed in the call is the one sent", async () => {
173
+ const { calls } = await verb("jev_choose")(
174
+ {
175
+ state: STATE,
176
+ question: "Tone?",
177
+ options: ["angry", "calm"],
178
+ model: "jev-1.14.0",
179
+ },
180
+ {
181
+ decision: {
182
+ type: "choice",
183
+ choice: "calm",
184
+ confidence: 0.9,
185
+ probabilities: {},
186
+ },
187
+ }
188
+ );
189
+ expect(calls[0].input.model).toBe("jev-1.14.0");
190
+ });
191
+
192
+ it("refuses fewer than 2 options or no state, before calling Jev", async () => {
193
+ await expect(
194
+ verb("jev_choose")(
195
+ { state: STATE, question: "Tone?", options: ["calm"] },
196
+ {}
197
+ )
198
+ ).rejects.toThrow(/at least 2 options/);
199
+ await expect(
200
+ verb("jev_choose")({ question: "Tone?", options: ["a", "b"] }, {})
201
+ ).rejects.toThrow(/state is required/);
202
+ });
203
+
204
+ it("a non-2xx answer fails loudly with Jev's status", async () => {
205
+ await expect(
206
+ verb("jev_choose")(
207
+ { state: STATE, question: "Tone?", options: ["a", "b"] },
208
+ {},
209
+ 429
210
+ )
211
+ ).rejects.toThrow(/Jev answered 429/);
212
+ });
213
+ });
214
+
215
+ describe("the template can be updated on every pod", () => {
216
+ // The pod's capability reconcile refuses to re-apply a skill whose code carries an
217
+ // install-time {{param}} ("manual re-apply needed"): on 28 Oct every installed jev was stuck
218
+ // on its install-day version because each verb baked {{jevModel}} into its code.
219
+ const codeSkills = skills.filter((s) => s.code && s.name.startsWith("jev_"));
220
+
221
+ it("sees every verb's code (the scan is not empty)", () => {
222
+ expect(codeSkills.map((s) => s.name).sort()).toEqual([
223
+ "jev_ask",
224
+ "jev_choose",
225
+ "jev_noul",
226
+ "jev_score",
227
+ ]);
228
+ });
229
+
230
+ it.each(codeSkills.map((s) => [s.name, s.code!] as const))(
231
+ "%s carries no install-time placeholder in its code",
232
+ (_name, code) => {
233
+ expect(code).not.toMatch(/\{\{\s*\w+\s*\}\}/);
234
+ }
235
+ );
236
+ });
237
+
238
+ describe("every verb speaks System One", () => {
239
+ // Each verb carries its own copy of the call helper (skill code is standalone), so each is checked.
240
+ const cases: Array<[string, Record<string, unknown>]> = [
241
+ [
242
+ "jev_choose",
243
+ {
244
+ state: STATE,
245
+ question: "Tone?",
246
+ options: ["a", "b"],
247
+ descriptions: { a: "first", b: "second" },
248
+ },
249
+ ],
250
+ [
251
+ "jev_score",
252
+ { state: STATE, question: "Urgency?", levels: ["low", "high"] },
253
+ ],
254
+ ["jev_noul", { state: STATE, question: "Billing?" }],
255
+ [
256
+ "jev_ask",
257
+ {
258
+ state: STATE,
259
+ questions: { q: { type: "noul", instructions: "Billing?" } },
260
+ },
261
+ ],
262
+ ];
263
+ it.each(cases)(
264
+ "%s posts to /v1/systemone through jev_api with the default model",
265
+ async (name, args) => {
266
+ expect(declaredTypeErrors(name, args)).toEqual([]);
267
+ const { calls } = await verb(name)(args, {});
268
+ expect(calls).toHaveLength(1);
269
+ expect(calls[0]).toMatchObject({
270
+ tool: "jev_api",
271
+ method: "POST",
272
+ path: "/v1/systemone",
273
+ input: { model: "jev-latest", state: STATE },
274
+ });
275
+ }
276
+ );
277
+ });
278
+
279
+ describe("jev_score, jev_noul, jev_ask — the other primitives", () => {
280
+ it("jev_score sends ordered levels as criteria and returns the score", async () => {
281
+ const { out, calls } = await verb("jev_score")(
282
+ {
283
+ state: STATE,
284
+ question: "How urgent?",
285
+ levels: ["Can wait", "This week", "Today"],
286
+ },
287
+ {
288
+ rating: {
289
+ type: "score",
290
+ score: 1.7,
291
+ confidence: 0.55,
292
+ legend: { "0": "Can wait", "1": "This week", "2": "Today" },
293
+ probabilities: { "0": 0.1, "1": 0.1, "2": 0.8 },
294
+ },
295
+ }
296
+ );
297
+ expect(calls[0].input.questions).toEqual({
298
+ rating: {
299
+ type: "score",
300
+ instructions: "How urgent?",
301
+ criteria: ["Can wait", "This week", "Today"],
302
+ },
303
+ });
304
+ expect(out).toMatchObject({ score: 1.7, confidence: 0.55 });
305
+ });
306
+
307
+ it("jev_noul asks a yes/no question and returns the probability of yes", async () => {
308
+ const { out, calls } = await verb("jev_noul")(
309
+ { state: STATE, question: "Is this about billing?" },
310
+ { answer: { type: "noul", noul: 0.98 } }
311
+ );
312
+ expect(calls[0].input.questions).toEqual({
313
+ answer: { type: "noul", instructions: "Is this about billing?" },
314
+ });
315
+ expect(out.probabilityYes).toBe(0.98);
316
+ });
317
+
318
+ it("jev_ask sends several questions in ONE call and returns the answers by name", async () => {
319
+ const questions = {
320
+ billing: { type: "noul", instructions: "Is this about billing?" },
321
+ tone: {
322
+ type: "choice",
323
+ instructions: "Tone?",
324
+ criteria: { angry: "upset", calm: "polite" },
325
+ },
326
+ };
327
+ const answers = {
328
+ billing: { type: "noul", noul: 0.98 },
329
+ tone: {
330
+ type: "choice",
331
+ choice: "calm",
332
+ confidence: 0.7,
333
+ probabilities: { angry: 0.2, calm: 0.8 },
334
+ },
335
+ };
336
+ const { out, calls } = await verb("jev_ask")(
337
+ { state: STATE, questions },
338
+ answers
339
+ );
340
+ expect(calls).toHaveLength(1);
341
+ expect(calls[0].input.questions).toEqual(questions);
342
+ expect(out.answers).toEqual(answers);
343
+ });
344
+
345
+ it("jev_ask refuses a question type Jev does not have", async () => {
346
+ await expect(
347
+ verb("jev_ask")(
348
+ {
349
+ state: STATE,
350
+ questions: { q: { type: "generate", instructions: "Write a reply" } },
351
+ },
352
+ {}
353
+ )
354
+ ).rejects.toThrow(/use choice, score or noul/);
355
+ });
356
+ });
package/src/legal.yaml CHANGED
@@ -13,6 +13,12 @@ meta:
13
13
  color: "#4338CA"
14
14
  tags: [legal, contracts, compliance, ip]
15
15
  isPublic: true
16
+ # What this space PRODUCES (homes): the purpose word, then its kinds/roles.
17
+ intent:
18
+ label: Legal
19
+ produces:
20
+ - profile: legal-contract
21
+ - profile: compliance-item
16
22
 
17
23
  workspace:
18
24
  name: Legal
@@ -20,7 +26,10 @@ workspace:
20
26
  proposalId: legal-v1
21
27
  subtype: legal
22
28
  visibility: members
23
- workspaceType: operational
29
+ # A DOMAIN workspace that holds entities — NOT `operational`. `operational`
30
+ # marks an admin/system surface: `isDomainHomeWorkspace` refuses filing
31
+ # entities into it and excludes it from auto-placement (2026-09-25).
32
+ workspaceType: personal
24
33
  capabilities:
25
34
  - legal.contracts
26
35
  - legal.compliance
@@ -74,6 +83,17 @@ profiles:
74
83
  icon: file-signature
75
84
  color: violet
76
85
  description: "A legal agreement with a counterparty — its status, term, and renewal."
86
+ # The ONE lifecycle (work model L1): every option's category.
87
+ lifecycle:
88
+ property: status
89
+ options:
90
+ - { key: draft, category: open }
91
+ - { key: in-review, category: active }
92
+ - { key: negotiation, category: active }
93
+ - { key: signed, category: active }
94
+ - { key: active, category: active }
95
+ - { key: expired, category: done }
96
+ - { key: terminated, category: lost }
77
97
  properties:
78
98
  - slug: contractType
79
99
  label: Type
@@ -139,6 +159,15 @@ profiles:
139
159
  icon: shield-check
140
160
  color: cyan
141
161
  description: "A regulatory or legal obligation with an owner and a deadline."
162
+ # The ONE lifecycle (work model L1): every option's category.
163
+ lifecycle:
164
+ property: status
165
+ options:
166
+ - { key: not-started, category: open }
167
+ - { key: in-progress, category: active }
168
+ - { key: submitted, category: active }
169
+ - { key: complete, category: done }
170
+ - { key: overdue, category: active }
142
171
  properties:
143
172
  - slug: obligationType
144
173
  label: Obligation Type
@@ -498,14 +527,17 @@ onboarding:
498
527
  lawyer, and not one invented legal conclusion anywhere in it.
499
528
  collect:
500
529
  - profileSlug: legal-entity
530
+ min: 1
501
531
  what: The company's legal entities and the jurisdictions they operate in.
502
532
  cardinality: few
503
533
  keyFields: [entityType, jurisdiction, status]
504
534
  - profileSlug: legal-contract
535
+ min: 1
505
536
  what: The key live agreements — the ones with real obligations, value, or renewal dates.
506
537
  cardinality: several
507
538
  keyFields: [contractType, status, counterparty, renewalDate]
508
539
  - profileSlug: compliance-item
540
+ min: 1
509
541
  what: Compliance obligations and filings with real deadlines.
510
542
  cardinality: several
511
543
  keyFields: [obligationType, dueDate, owner]