@owlmeans/viable-common 0.0.42 → 0.0.44

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 (322) hide show
  1. package/README.md +3 -3
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/agent-presentation/SKILL.md +1 -1
  4. package/agent-meta/skills/viable-common/SKILL.md +33 -15
  5. package/build/agent/consts.d.ts +58 -0
  6. package/build/agent/consts.d.ts.map +1 -0
  7. package/build/agent/consts.js +63 -0
  8. package/build/agent/consts.js.map +1 -0
  9. package/build/agent/consts.local.d.ts +21 -0
  10. package/build/agent/consts.local.d.ts.map +1 -0
  11. package/build/agent/consts.local.js +44 -0
  12. package/build/agent/consts.local.js.map +1 -0
  13. package/build/agent/index.d.ts +1 -0
  14. package/build/agent/index.d.ts.map +1 -1
  15. package/build/agent/index.js +1 -0
  16. package/build/agent/index.js.map +1 -1
  17. package/build/agent/presentation.d.ts +2 -86
  18. package/build/agent/presentation.d.ts.map +1 -1
  19. package/build/agent/presentation.js +2 -104
  20. package/build/agent/presentation.js.map +1 -1
  21. package/build/agent/types.d.ts +30 -0
  22. package/build/agent/types.d.ts.map +1 -1
  23. package/build/agent/types.local.d.ts +2 -0
  24. package/build/agent/types.local.d.ts.map +1 -0
  25. package/build/agent/types.local.js +2 -0
  26. package/build/agent/types.local.js.map +1 -0
  27. package/build/areas/consts.d.ts +5 -0
  28. package/build/areas/consts.d.ts.map +1 -1
  29. package/build/areas/consts.js +4 -0
  30. package/build/areas/consts.js.map +1 -1
  31. package/build/areas/tenancy.d.ts +1 -36
  32. package/build/areas/tenancy.d.ts.map +1 -1
  33. package/build/areas/tenancy.js +1 -5
  34. package/build/areas/tenancy.js.map +1 -1
  35. package/build/areas/types.d.ts +32 -0
  36. package/build/areas/types.d.ts.map +1 -1
  37. package/build/ba/types.d.ts +1 -1
  38. package/build/ba/types.d.ts.map +1 -1
  39. package/build/blueprint/consts.d.ts +41 -0
  40. package/build/blueprint/consts.d.ts.map +1 -1
  41. package/build/blueprint/consts.js +51 -0
  42. package/build/blueprint/consts.js.map +1 -1
  43. package/build/blueprint/consts.local.d.ts +2 -0
  44. package/build/blueprint/consts.local.d.ts.map +1 -0
  45. package/build/blueprint/consts.local.js +3 -0
  46. package/build/blueprint/consts.local.js.map +1 -0
  47. package/build/blueprint/index.d.ts +1 -0
  48. package/build/blueprint/index.d.ts.map +1 -1
  49. package/build/blueprint/index.js +1 -0
  50. package/build/blueprint/index.js.map +1 -1
  51. package/build/blueprint/types.d.ts +2 -50
  52. package/build/blueprint/types.d.ts.map +1 -1
  53. package/build/blueprint/types.js +1 -65
  54. package/build/blueprint/types.js.map +1 -1
  55. package/build/blueprint/utils.d.ts +11 -0
  56. package/build/blueprint/utils.d.ts.map +1 -0
  57. package/build/blueprint/utils.js +16 -0
  58. package/build/blueprint/utils.js.map +1 -0
  59. package/build/branding.d.ts +0 -8
  60. package/build/branding.d.ts.map +1 -1
  61. package/build/branding.js +0 -16
  62. package/build/branding.js.map +1 -1
  63. package/build/connect/consts.d.ts +0 -10
  64. package/build/connect/consts.d.ts.map +1 -1
  65. package/build/connect/consts.js +0 -23
  66. package/build/connect/consts.js.map +1 -1
  67. package/build/connect/entrypoints.d.ts +49 -86
  68. package/build/connect/entrypoints.d.ts.map +1 -1
  69. package/build/connect/entrypoints.js +5 -2
  70. package/build/connect/entrypoints.js.map +1 -1
  71. package/build/connect/errors.d.ts +32 -0
  72. package/build/connect/errors.d.ts.map +1 -1
  73. package/build/connect/errors.js +65 -0
  74. package/build/connect/errors.js.map +1 -1
  75. package/build/connect/index.d.ts +1 -0
  76. package/build/connect/index.d.ts.map +1 -1
  77. package/build/connect/index.js +1 -0
  78. package/build/connect/index.js.map +1 -1
  79. package/build/connect/references.d.ts +1 -153
  80. package/build/connect/references.d.ts.map +1 -1
  81. package/build/connect/references.js.map +1 -1
  82. package/build/connect/schemas.d.ts +2 -1
  83. package/build/connect/schemas.d.ts.map +1 -1
  84. package/build/connect/schemas.js +9 -0
  85. package/build/connect/schemas.js.map +1 -1
  86. package/build/connect/types.d.ts +214 -1
  87. package/build/connect/types.d.ts.map +1 -1
  88. package/build/connect/types.local.d.ts +4 -0
  89. package/build/connect/types.local.d.ts.map +1 -0
  90. package/build/connect/types.local.js +2 -0
  91. package/build/connect/types.local.js.map +1 -0
  92. package/build/connect/utils.d.ts +12 -0
  93. package/build/connect/utils.d.ts.map +1 -0
  94. package/build/connect/utils.js +25 -0
  95. package/build/connect/utils.js.map +1 -0
  96. package/build/consts.d.ts +8 -0
  97. package/build/consts.d.ts.map +1 -1
  98. package/build/consts.js +16 -0
  99. package/build/consts.js.map +1 -1
  100. package/build/convert/consts.d.ts +0 -12
  101. package/build/convert/consts.d.ts.map +1 -1
  102. package/build/convert/consts.js +0 -3
  103. package/build/convert/consts.js.map +1 -1
  104. package/build/convert/consts.local.d.ts +55 -0
  105. package/build/convert/consts.local.d.ts.map +1 -0
  106. package/build/convert/consts.local.js +104 -0
  107. package/build/convert/consts.local.js.map +1 -0
  108. package/build/convert/helpers.d.ts.map +1 -1
  109. package/build/convert/helpers.js +1 -102
  110. package/build/convert/helpers.js.map +1 -1
  111. package/build/convert/index.d.ts +1 -0
  112. package/build/convert/index.d.ts.map +1 -1
  113. package/build/convert/index.js +1 -0
  114. package/build/convert/index.js.map +1 -1
  115. package/build/convert/types.d.ts +10 -1
  116. package/build/convert/types.d.ts.map +1 -1
  117. package/build/convert/utils.d.ts +4 -0
  118. package/build/convert/utils.d.ts.map +1 -0
  119. package/build/convert/utils.js +5 -0
  120. package/build/convert/utils.js.map +1 -0
  121. package/build/design/consts.d.ts +37 -0
  122. package/build/design/consts.d.ts.map +1 -1
  123. package/build/design/consts.js +44 -8
  124. package/build/design/consts.js.map +1 -1
  125. package/build/design/runtime.d.ts +2 -103
  126. package/build/design/runtime.d.ts.map +1 -1
  127. package/build/design/runtime.js +1 -44
  128. package/build/design/runtime.js.map +1 -1
  129. package/build/design/schemas.d.ts +1 -9
  130. package/build/design/schemas.d.ts.map +1 -1
  131. package/build/design/schemas.js +1 -1
  132. package/build/design/schemas.js.map +1 -1
  133. package/build/design/types.d.ts +75 -1
  134. package/build/design/types.d.ts.map +1 -1
  135. package/build/dev/schemas.d.ts.map +1 -1
  136. package/build/dev/schemas.js.map +1 -1
  137. package/build/dev/types.local.d.ts +4 -0
  138. package/build/dev/types.local.d.ts.map +1 -0
  139. package/build/dev/types.local.js +2 -0
  140. package/build/dev/types.local.js.map +1 -0
  141. package/build/integrity/consts.d.ts +0 -117
  142. package/build/integrity/consts.d.ts.map +1 -1
  143. package/build/integrity/consts.js +0 -281
  144. package/build/integrity/consts.js.map +1 -1
  145. package/build/integrity/consts.local.d.ts +5 -0
  146. package/build/integrity/consts.local.d.ts.map +1 -0
  147. package/build/integrity/consts.local.js +5 -0
  148. package/build/integrity/consts.local.js.map +1 -0
  149. package/build/integrity/index.d.ts +1 -0
  150. package/build/integrity/index.d.ts.map +1 -1
  151. package/build/integrity/index.js +1 -0
  152. package/build/integrity/index.js.map +1 -1
  153. package/build/integrity/types.d.ts +33 -1
  154. package/build/integrity/types.d.ts.map +1 -1
  155. package/build/integrity/utils.d.ts +88 -0
  156. package/build/integrity/utils.d.ts.map +1 -0
  157. package/build/integrity/utils.js +280 -0
  158. package/build/integrity/utils.js.map +1 -0
  159. package/build/integrity/verify.d.ts.map +1 -1
  160. package/build/integrity/verify.js +2 -1
  161. package/build/integrity/verify.js.map +1 -1
  162. package/build/intent/consts.local.d.ts +4 -0
  163. package/build/intent/consts.local.d.ts.map +1 -0
  164. package/build/intent/consts.local.js +3 -0
  165. package/build/intent/consts.local.js.map +1 -0
  166. package/build/intent/entrypoints.d.ts +0 -1
  167. package/build/intent/entrypoints.d.ts.map +1 -1
  168. package/build/intent/flow.d.ts.map +1 -1
  169. package/build/intent/flow.js +2 -2
  170. package/build/intent/flow.js.map +1 -1
  171. package/build/intent/types.d.ts +2 -0
  172. package/build/intent/types.d.ts.map +1 -1
  173. package/build/metadata/consts.d.ts +33 -0
  174. package/build/metadata/consts.d.ts.map +1 -1
  175. package/build/metadata/consts.js +37 -0
  176. package/build/metadata/consts.js.map +1 -1
  177. package/build/metadata/types.d.ts +1 -33
  178. package/build/metadata/types.d.ts.map +1 -1
  179. package/build/metadata/types.js +1 -38
  180. package/build/metadata/types.js.map +1 -1
  181. package/build/planning/consts.d.ts +13 -1
  182. package/build/planning/consts.d.ts.map +1 -1
  183. package/build/planning/consts.js +13 -0
  184. package/build/planning/consts.js.map +1 -1
  185. package/build/planning/index.d.ts +0 -1
  186. package/build/planning/index.d.ts.map +1 -1
  187. package/build/planning/index.js +0 -1
  188. package/build/planning/index.js.map +1 -1
  189. package/build/planning/landing.d.ts +0 -12
  190. package/build/planning/landing.d.ts.map +1 -1
  191. package/build/planning/landing.js +1 -13
  192. package/build/planning/landing.js.map +1 -1
  193. package/build/planning/schemas.d.ts +37 -0
  194. package/build/planning/schemas.d.ts.map +1 -1
  195. package/build/planning/schemas.js +173 -4
  196. package/build/planning/schemas.js.map +1 -1
  197. package/build/planning/types.d.ts +2 -2
  198. package/build/planning/types.d.ts.map +1 -1
  199. package/build/preview/consts.d.ts +3 -1
  200. package/build/preview/consts.d.ts.map +1 -1
  201. package/build/preview/consts.js +2 -0
  202. package/build/preview/consts.js.map +1 -1
  203. package/build/preview/types.d.ts +17 -2
  204. package/build/preview/types.d.ts.map +1 -1
  205. package/build/scaffold/helpers.d.ts +1 -14
  206. package/build/scaffold/helpers.d.ts.map +1 -1
  207. package/build/scaffold/helpers.js +11 -0
  208. package/build/scaffold/helpers.js.map +1 -1
  209. package/build/scaffold/types.d.ts +2 -0
  210. package/build/scaffold/types.d.ts.map +1 -1
  211. package/build/slot/consts.d.ts +7 -13
  212. package/build/slot/consts.d.ts.map +1 -1
  213. package/build/slot/consts.js +10 -36
  214. package/build/slot/consts.js.map +1 -1
  215. package/build/slot/helpers.d.ts +1 -6
  216. package/build/slot/helpers.d.ts.map +1 -1
  217. package/build/slot/helpers.js.map +1 -1
  218. package/build/slot/index.d.ts +1 -0
  219. package/build/slot/index.d.ts.map +1 -1
  220. package/build/slot/index.js +1 -0
  221. package/build/slot/index.js.map +1 -1
  222. package/build/slot/layout.d.ts +1 -57
  223. package/build/slot/layout.d.ts.map +1 -1
  224. package/build/slot/layout.js +0 -12
  225. package/build/slot/layout.js.map +1 -1
  226. package/build/slot/types.d.ts +55 -1
  227. package/build/slot/types.d.ts.map +1 -1
  228. package/build/slot/utils.d.ts +18 -0
  229. package/build/slot/utils.d.ts.map +1 -0
  230. package/build/slot/utils.js +41 -0
  231. package/build/slot/utils.js.map +1 -0
  232. package/build/topology/card.d.ts +1 -6
  233. package/build/topology/card.d.ts.map +1 -1
  234. package/build/topology/card.js +1 -3
  235. package/build/topology/card.js.map +1 -1
  236. package/build/topology/consts.local.d.ts +4 -0
  237. package/build/topology/consts.local.d.ts.map +1 -0
  238. package/build/topology/consts.local.js +4 -0
  239. package/build/topology/consts.local.js.map +1 -0
  240. package/build/topology/types.d.ts +5 -0
  241. package/build/topology/types.d.ts.map +1 -1
  242. package/package.json +13 -13
  243. package/src/agent/consts.local.ts +47 -0
  244. package/src/agent/consts.ts +61 -0
  245. package/src/agent/index.ts +1 -0
  246. package/src/agent/presentation.ts +4 -147
  247. package/src/agent/types.local.ts +1 -0
  248. package/src/agent/types.ts +40 -0
  249. package/src/areas/consts.ts +7 -0
  250. package/src/areas/tenancy.ts +2 -38
  251. package/src/areas/types.ts +31 -0
  252. package/src/ba/types.ts +1 -1
  253. package/src/blueprint/consts.local.ts +3 -0
  254. package/src/blueprint/consts.ts +52 -0
  255. package/src/blueprint/index.ts +1 -0
  256. package/src/blueprint/types.ts +2 -72
  257. package/src/blueprint/utils.ts +20 -0
  258. package/src/branding.ts +0 -17
  259. package/src/connect/consts.ts +0 -22
  260. package/src/connect/entrypoints.ts +7 -35
  261. package/src/connect/errors.ts +75 -0
  262. package/src/connect/index.ts +1 -0
  263. package/src/connect/references.ts +4 -75
  264. package/src/connect/schemas.ts +11 -0
  265. package/src/connect/types.local.ts +5 -0
  266. package/src/connect/types.ts +124 -1
  267. package/src/connect/utils.ts +23 -0
  268. package/src/consts.ts +17 -0
  269. package/src/convert/consts.local.ts +120 -0
  270. package/src/convert/consts.ts +0 -14
  271. package/src/convert/helpers.ts +1 -119
  272. package/src/convert/index.ts +1 -0
  273. package/src/convert/types.ts +11 -5
  274. package/src/convert/utils.ts +8 -0
  275. package/src/design/consts.ts +48 -0
  276. package/src/design/runtime.ts +2 -115
  277. package/src/design/schemas.ts +2 -10
  278. package/src/design/types.ts +81 -1
  279. package/src/dev/schemas.ts +1 -3
  280. package/src/dev/types.local.ts +4 -0
  281. package/src/integrity/consts.local.ts +5 -0
  282. package/src/integrity/consts.ts +0 -348
  283. package/src/integrity/index.ts +1 -0
  284. package/src/integrity/types.ts +34 -1
  285. package/src/integrity/utils.ts +320 -0
  286. package/src/integrity/verify.ts +2 -4
  287. package/src/intent/consts.local.ts +3 -0
  288. package/src/intent/entrypoints.ts +0 -1
  289. package/src/intent/flow.ts +2 -3
  290. package/src/intent/types.ts +3 -0
  291. package/src/metadata/consts.ts +37 -0
  292. package/src/metadata/types.ts +1 -37
  293. package/src/planning/consts.ts +15 -2
  294. package/src/planning/index.ts +0 -1
  295. package/src/planning/landing.ts +1 -14
  296. package/src/planning/schemas.ts +191 -4
  297. package/src/planning/types.ts +2 -2
  298. package/src/preview/consts.ts +2 -0
  299. package/src/preview/types.ts +19 -0
  300. package/src/scaffold/helpers.ts +1 -4
  301. package/src/scaffold/types.ts +3 -0
  302. package/src/slot/consts.ts +11 -40
  303. package/src/slot/helpers.ts +1 -6
  304. package/src/slot/index.ts +1 -0
  305. package/src/slot/layout.ts +1 -62
  306. package/src/slot/types.ts +57 -1
  307. package/src/slot/utils.ts +45 -0
  308. package/src/topology/card.ts +2 -9
  309. package/src/topology/consts.local.ts +6 -0
  310. package/src/topology/types.ts +6 -0
  311. package/tests/branding.spec.ts +2 -2
  312. package/tests/connect-convert.spec.ts +21 -1
  313. package/tests/connect-errors.spec.ts +34 -1
  314. package/tests/convert.spec.ts +2 -3
  315. package/tests/error-status.spec.ts +7 -1
  316. package/tests/planning.spec.ts +3 -18
  317. package/tests/presentation.spec.ts +2 -4
  318. package/build/planning/flows.d.ts +0 -34
  319. package/build/planning/flows.d.ts.map +0 -1
  320. package/build/planning/flows.js +0 -174
  321. package/build/planning/flows.js.map +0 -1
  322. package/src/planning/flows.ts +0 -204
@@ -1,13 +1,15 @@
1
1
  import type { JSONSchemaType } from 'ajv'
2
- import { CODE_MAX } from '@owlmeans/planning'
3
- import { ProjectArea } from '../areas/consts.js'
4
- import { TENANCY_QUOTE_MAX } from '../areas/tenancy.js'
2
+ import { CODE_MAX, IntrinsicPolicy, IntrinsicStatus, SpecificationFormat, WorkcardKind, AnyTypeSchema, ProjectTypeSchema, RelationshipType, SpecificationSlot, StatusFlowSchema, WorkcardTypeSchema } from '@owlmeans/planning'
3
+ import { ProjectArea, TENANCY_QUOTE_MAX } from '../areas/consts.js'
5
4
  import { CASE_QUOTE_MAX, WorkKind } from '../blueprint/consts.js'
6
5
  import { StoryKind } from '../ba/consts.js'
7
6
  import { ConnectLlm, ConnectTarget } from '../connect/consts.js'
8
7
  import { ProjectOriginSchema } from '../convert/schemas.js'
9
- import { StoryActor } from '../design/runtime.js'
8
+ import { StoryActor, STORY_DESIGN_VERSION } from '../design/consts.js'
10
9
  import type { ViableProjectFields, ViableStoryFields } from './types.js'
10
+ import { StoryDesignSchema } from '../design/schemas.js'
11
+ import { ScaffoldPlanSchema } from '../scaffold/schemas.js'
12
+ import { VIABLE_BUG_CODE, VIABLE_BUG_TYPE, VIABLE_DESIGN_REVISIONS_KEPT, VIABLE_IMPROVEMENT_CODE, VIABLE_IMPROVEMENT_TYPE, VIABLE_PROJECT_CODE, VIABLE_PROJECT_FLOW, VIABLE_PROJECT_TYPE, VIABLE_REQUIREMENT_CODE, VIABLE_REQUIREMENT_TYPE, VIABLE_SPEC_FLOW, VIABLE_SPEC_TYPE, VIABLE_STORY_CODE, VIABLE_STORY_FLOW, VIABLE_STORY_TYPE, ViableProjectStatus, ViableProjectTransition, ViableRelationship, ViableSpecCategory, ViableSpecStatus, ViableStoryStatus, ViableStoryTransition, ViableTone } from './consts.js'
11
13
 
12
14
  /**
13
15
  * The `fields` schema of a `viable:project` card.
@@ -109,3 +111,188 @@ export const ViableSpecFieldsSchema = {
109
111
  required: [],
110
112
  additionalProperties: false,
111
113
  } as unknown as JSONSchemaType<Record<string, never>>
114
+
115
+ /**
116
+ * The story flow.
117
+ *
118
+ * `failed` maps to PLANNED: a failed story is work still to do, so "done" is the closed count and
119
+ * a retry is simply `start` again. `reset` from anywhere is the manual recovery — the one move a
120
+ * completed story still accepts.
121
+ */
122
+ export const VIABLE_STORY_FLOW_SCHEMA: StatusFlowSchema = {
123
+ id: VIABLE_STORY_FLOW,
124
+ version: 1,
125
+ statuses: [
126
+ { key: ViableStoryStatus.Planned, intrinsic: IntrinsicStatus.Planned, initial: true, tone: ViableTone.Blue },
127
+ { key: ViableStoryStatus.InProgress, intrinsic: IntrinsicStatus.InProgress, tone: ViableTone.Yellow },
128
+ { key: ViableStoryStatus.Completed, intrinsic: IntrinsicStatus.Closed, tone: ViableTone.Green },
129
+ { key: ViableStoryStatus.Failed, intrinsic: IntrinsicStatus.Planned, tone: ViableTone.Red },
130
+ ],
131
+ transitions: [
132
+ {
133
+ name: ViableStoryTransition.Start,
134
+ from: [ViableStoryStatus.Planned, ViableStoryStatus.Failed],
135
+ to: ViableStoryStatus.InProgress,
136
+ explicit: true,
137
+ },
138
+ {
139
+ name: ViableStoryTransition.Complete,
140
+ from: [ViableStoryStatus.InProgress],
141
+ to: ViableStoryStatus.Completed,
142
+ explicit: true,
143
+ },
144
+ {
145
+ name: ViableStoryTransition.Fail,
146
+ from: [ViableStoryStatus.InProgress],
147
+ to: ViableStoryStatus.Failed,
148
+ },
149
+ { name: ViableStoryTransition.Reset, from: '*', to: ViableStoryStatus.Planned, explicit: true },
150
+ ],
151
+ }
152
+
153
+ /**
154
+ * The project flow.
155
+ *
156
+ * A create lands at `draft`; confirming the brief is `confirm`; the end of an initialization is
157
+ * `activate`. A reinitialization and a failed initialization are SLOT facts, not transitions, and
158
+ * destroying a project is a `delete` plus the platform's cascade — never `archive`.
159
+ */
160
+ export const VIABLE_PROJECT_FLOW_SCHEMA: StatusFlowSchema = {
161
+ id: VIABLE_PROJECT_FLOW,
162
+ version: 1,
163
+ statuses: [
164
+ { key: ViableProjectStatus.Draft, intrinsic: IntrinsicStatus.Planned, initial: true, tone: ViableTone.Blue },
165
+ { key: ViableProjectStatus.Confirmed, intrinsic: IntrinsicStatus.InProgress, tone: ViableTone.Yellow },
166
+ { key: ViableProjectStatus.Active, intrinsic: IntrinsicStatus.InProgress, tone: ViableTone.Green },
167
+ { key: ViableProjectStatus.Archived, intrinsic: IntrinsicStatus.Closed, tone: ViableTone.Neutral },
168
+ ],
169
+ transitions: [
170
+ {
171
+ name: ViableProjectTransition.Confirm,
172
+ from: [ViableProjectStatus.Draft],
173
+ to: ViableProjectStatus.Confirmed,
174
+ explicit: true,
175
+ },
176
+ {
177
+ name: ViableProjectTransition.Activate,
178
+ from: [ViableProjectStatus.Confirmed],
179
+ to: ViableProjectStatus.Active,
180
+ },
181
+ { name: ViableProjectTransition.Archive, from: '*', to: ViableProjectStatus.Archived, explicit: true },
182
+ {
183
+ name: ViableProjectTransition.Reopen,
184
+ from: [ViableProjectStatus.Archived],
185
+ to: ViableProjectStatus.Active,
186
+ explicit: true,
187
+ },
188
+ ],
189
+ }
190
+
191
+ /** A document is written or revised; it has no lifecycle to move through. */
192
+ export const VIABLE_SPEC_FLOW_SCHEMA: StatusFlowSchema = {
193
+ id: VIABLE_SPEC_FLOW,
194
+ version: 1,
195
+ statuses: [
196
+ { key: ViableSpecStatus.Current, intrinsic: IntrinsicStatus.Closed, initial: true, tone: ViableTone.Neutral },
197
+ ],
198
+ transitions: [],
199
+ }
200
+
201
+ export const slot = (
202
+ category: ViableSpecCategory, format: SpecificationFormat, extra: Partial<SpecificationSlot> = {},
203
+ ): SpecificationSlot => ({ category, format, type: VIABLE_SPEC_TYPE, ...extra })
204
+
205
+ /** The brief a person confirms, and the plan the scaffold draws from it. */
206
+ export const VIABLE_PROJECT_SLOTS: SpecificationSlot[] = [
207
+ slot(ViableSpecCategory.Specification, SpecificationFormat.Markdown, { required: true }),
208
+ slot(ViableSpecCategory.Vision, SpecificationFormat.Markdown),
209
+ slot(ViableSpecCategory.DesignSystem, SpecificationFormat.Markdown),
210
+ slot(ViableSpecCategory.Scaffold, SpecificationFormat.Json, {
211
+ revisioned: true, keepRevisions: VIABLE_DESIGN_REVISIONS_KEPT, schema: ScaffoldPlanSchema,
212
+ }),
213
+ ]
214
+
215
+ /** A story's design — the payload the implementation stage consumes. */
216
+ export const VIABLE_STORY_SLOTS: SpecificationSlot[] = [
217
+ slot(ViableSpecCategory.Design, SpecificationFormat.Json, {
218
+ revisioned: true,
219
+ keepRevisions: VIABLE_DESIGN_REVISIONS_KEPT,
220
+ schema: StoryDesignSchema,
221
+ version: STORY_DESIGN_VERSION,
222
+ }),
223
+ ]
224
+
225
+ export const storyLink = (name: ViableRelationship): RelationshipType =>
226
+ ({ name, from: [VIABLE_STORY_TYPE], to: [VIABLE_STORY_TYPE], single: true })
227
+
228
+ export const VIABLE_STORY_RELATIONSHIPS: RelationshipType[] = [
229
+ storyLink(ViableRelationship.Follows),
230
+ storyLink(ViableRelationship.SharesWidget),
231
+ storyLink(ViableRelationship.SharesScreen),
232
+ ]
233
+
234
+ export const VIABLE_PROJECT_TYPE_SCHEMA: ProjectTypeSchema = {
235
+ type: VIABLE_PROJECT_TYPE,
236
+ kind: WorkcardKind.Project,
237
+ version: 1,
238
+ fields: ViableProjectFieldsSchema,
239
+ flows: [VIABLE_PROJECT_FLOW],
240
+ intrinsic: IntrinsicPolicy.Primary,
241
+ specifications: VIABLE_PROJECT_SLOTS,
242
+ code: VIABLE_PROJECT_CODE,
243
+ cardTypes: [VIABLE_STORY_TYPE],
244
+ }
245
+
246
+ export const VIABLE_STORY_TYPE_SCHEMA: WorkcardTypeSchema = {
247
+ type: VIABLE_STORY_TYPE,
248
+ kind: WorkcardKind.Card,
249
+ version: 1,
250
+ fields: ViableStoryFieldsSchema,
251
+ flows: [VIABLE_STORY_FLOW],
252
+ intrinsic: IntrinsicPolicy.Primary,
253
+ specifications: VIABLE_STORY_SLOTS,
254
+ relationships: VIABLE_STORY_RELATIONSHIPS,
255
+ code: VIABLE_STORY_CODE,
256
+ }
257
+
258
+ export const VIABLE_SPEC_TYPE_SCHEMA: WorkcardTypeSchema = {
259
+ type: VIABLE_SPEC_TYPE,
260
+ kind: WorkcardKind.Specification,
261
+ version: 1,
262
+ fields: ViableSpecFieldsSchema,
263
+ flows: [VIABLE_SPEC_FLOW],
264
+ specifications: [],
265
+ }
266
+
267
+ export const reserved = (type: string, code: WorkcardTypeSchema['code']): WorkcardTypeSchema => ({
268
+ type,
269
+ kind: WorkcardKind.Card,
270
+ version: 1,
271
+ fields: ViableOpenFieldsSchema,
272
+ flows: [VIABLE_STORY_FLOW],
273
+ intrinsic: IntrinsicPolicy.Primary,
274
+ specifications: [],
275
+ code,
276
+ })
277
+
278
+ /** Registered so their prefixes and flow are decided once; not creatable under a project yet. */
279
+ export const VIABLE_RESERVED_TYPE_SCHEMAS: WorkcardTypeSchema[] = [
280
+ reserved(VIABLE_BUG_TYPE, VIABLE_BUG_CODE),
281
+ reserved(VIABLE_IMPROVEMENT_TYPE, VIABLE_IMPROVEMENT_CODE),
282
+ reserved(VIABLE_REQUIREMENT_TYPE, VIABLE_REQUIREMENT_CODE),
283
+ ]
284
+
285
+ /** Every Viable type — what a planning plugin registers. */
286
+ export const VIABLE_TYPE_SCHEMAS: AnyTypeSchema[] = [
287
+ VIABLE_PROJECT_TYPE_SCHEMA,
288
+ VIABLE_STORY_TYPE_SCHEMA,
289
+ VIABLE_SPEC_TYPE_SCHEMA,
290
+ ...VIABLE_RESERVED_TYPE_SCHEMAS,
291
+ ]
292
+
293
+ /** Every Viable flow — registered beside the types. */
294
+ export const VIABLE_FLOW_SCHEMAS: StatusFlowSchema[] = [
295
+ VIABLE_PROJECT_FLOW_SCHEMA,
296
+ VIABLE_STORY_FLOW_SCHEMA,
297
+ VIABLE_SPEC_FLOW_SCHEMA,
298
+ ]
@@ -1,11 +1,11 @@
1
1
  import type { Card, Project, Specification } from '@owlmeans/planning'
2
2
  import type { ProjectArea } from '../areas/consts.js'
3
3
  import type { WorkKind } from '../blueprint/consts.js'
4
- import type { ViableTenancyDecision } from '../areas/tenancy.js'
4
+ import type { ViableTenancyDecision } from '../areas/types.js'
5
5
  import type { StoryKind } from '../ba/consts.js'
6
6
  import type { ConnectLlm, ConnectTarget } from '../connect/consts.js'
7
7
  import type { ProjectOrigin } from '../convert/types.js'
8
- import type { StoryActor } from '../design/runtime.js'
8
+ import type { StoryActor } from '../design/consts.js'
9
9
  import type { StoryWriteInput } from '../metadata/types.js'
10
10
 
11
11
  /**
@@ -6,4 +6,6 @@ export enum PreviewEventType {
6
6
  CaughtError = 'OWLMEANS_PREVIEW_CONSOLE_ERROR',
7
7
  PromiseRejection = 'OWLMEANS_PREVIEW_PROMISE_REJECTION',
8
8
  FetchError = 'OWLMEANS_PREVIEW_FETCH_ERROR',
9
+ /** An analytics event a target's web logged through `@owlmeans/log` (browser → manager frame). */
10
+ Analytics = 'OWLMEANS_PREVIEW_ANALYTICS',
9
11
  }
@@ -46,6 +46,19 @@ export interface OwlMeansFetchErrorPayload {
46
46
  incidentId?: string
47
47
  }
48
48
 
49
+ /**
50
+ * Payload of an analytics event of a target's web — `AnalyticsEvent` of `@owlmeans/log`, as the
51
+ * target's `viablePreviewPlugin` posts it. Untrusted: it comes from generated code.
52
+ */
53
+ export interface OwlMeansAnalyticsPayload {
54
+ event: string
55
+ scope: string
56
+ time: number
57
+ level: 'debug' | 'info' | 'warn' | 'error'
58
+ message: string
59
+ data?: unknown
60
+ }
61
+
49
62
  /**
50
63
  * Specific message types for each event kind
51
64
  */
@@ -65,6 +78,10 @@ export interface OwlMeansCaughtErrorMessage extends OwlMeansPreviewMessage<OwlMe
65
78
  type: PreviewEventType.CaughtError
66
79
  }
67
80
 
81
+ export interface OwlMeansAnalyticsMessage extends OwlMeansPreviewMessage<OwlMeansAnalyticsPayload> {
82
+ type: PreviewEventType.Analytics
83
+ }
84
+
68
85
  /**
69
86
  * Union type for all possible OwlMeans preview messages
70
87
  */
@@ -73,9 +90,11 @@ export type OwlMeansPreviewMessages =
73
90
  | OwlMeansPromiseRejectionMessage
74
91
  | OwlMeansFetchErrorMessage
75
92
  | OwlMeansCaughtErrorMessage
93
+ | OwlMeansAnalyticsMessage
76
94
 
77
95
  export type OwlMenasPreviewPayloads =
78
96
  | OwlMeansErrorPayload
79
97
  | OwlMeansPromiseRejectionPayload
80
98
  | OwlMeansFetchErrorPayload
81
99
  | OwlMeansCaughtErrorPayload
100
+ | OwlMeansAnalyticsPayload
@@ -1,4 +1,4 @@
1
- import type { ScaffoldPlan, ScaffoldStoryPlan } from './types.js'
1
+ import type { ScaffoldPlan, ScaffoldStoryPlan, ShareKind } from './types.js'
2
2
 
3
3
  /**
4
4
  * ONE reading of who owns a drawn artifact, so no consumer has to interpret the plan itself.
@@ -12,9 +12,6 @@ import type { ScaffoldPlan, ScaffoldStoryPlan } from './types.js'
12
12
  * so the stampers and the scaffold loop can read a plan that is already sane.
13
13
  */
14
14
 
15
- /** Which field the arrow is being followed along. */
16
- export type ShareKind = 'widget' | 'screen'
17
-
18
15
  const pointerOf = (story: ScaffoldStoryPlan, kind: ShareKind): string | undefined =>
19
16
  kind === 'widget' ? story.sharesWidgetWith : story.sharesScreenWith
20
17
 
@@ -266,3 +266,6 @@ export interface ScaffoldPlan {
266
266
  */
267
267
  motifs: string
268
268
  }
269
+
270
+ /** Which field the arrow is being followed along. */
271
+ export type ShareKind = 'widget' | 'screen'
@@ -19,6 +19,8 @@
19
19
  * commands are executed by the connector on that machine, and nothing about it is provisioned,
20
20
  * routed, reconciled or published.
21
21
  */
22
+ import { TargetLayout } from '../integrity/index.js'
23
+
22
24
  export enum WorkloadKind {
23
25
  Ephemeral = 'ephemeral',
24
26
  Production = 'production',
@@ -368,46 +370,15 @@ export const FILE_COMMAND_TIMEOUTS: Partial<Record<SlotFileCommand, number>> = {
368
370
  [SlotFileCommand.ReadHead]: 70_000,
369
371
  }
370
372
 
371
- /** The per-command caller bound for one command, or nothing where its type's default is right. */
372
- const perCommandTimeout = (type: SlotCommandType, command: string): number | undefined => {
373
- switch (type) {
374
- case SlotCommandType.Shell: return SHELL_COMMAND_TIMEOUTS[command]
375
- case SlotCommandType.Git: return GIT_COMMAND_TIMEOUTS[command as SlotGitCommand]
376
- case SlotCommandType.Database: return COMMAND_TIMEOUTS[SlotCommandType.Database]
377
- default: return FILE_COMMAND_TIMEOUTS[command as SlotFileCommand]
378
- }
379
- }
380
-
381
- /**
382
- * Resolve the caller-side bound for one command.
383
- *
384
- * One function rather than three lookups at each call site: an asker that forgets the per-command
385
- * table inherits twenty minutes for a fifteen-second command, which is the failure this table was
386
- * added to stop.
387
- */
388
- export const commandTimeout = (
389
- type: SlotCommandType, command: string, override?: number
390
- ): number => override
391
- ?? perCommandTimeout(type, command)
392
- ?? COMMAND_TIMEOUTS[type]
393
- ?? DEFAULT_COMMAND_TIMEOUT
394
-
395
373
  /**
396
- * Resolve the executor-side deadline for one command.
374
+ * The one marker per layout, chosen because it exists in that layout and in no other.
397
375
  *
398
- * Per-command first, per-type second. It was per-type only, which is how a clone inherited the
399
- * bound of a `git status` — the same shape as the shell table above, and added for the same
400
- * reason.
376
+ * `sources/api` cannot appear in a v1 tree and `packages/backend` cannot appear in a v2 one, so a
377
+ * single `stat` settles it. Deliberately not `sources/` alone: v1 packages each have their own
378
+ * `src`, and a directory name that differs by one letter is not something to hang a runtime path
379
+ * resolution on. Ordered — the first marker found wins.
401
380
  */
402
- export const commandDeadline = (type: SlotCommandType, command: string): number => {
403
- switch (type) {
404
- case SlotCommandType.Shell:
405
- return COMMAND_DEADLINES[command] ?? DEFAULT_COMMAND_DEADLINE
406
- case SlotCommandType.Git:
407
- return GIT_COMMAND_DEADLINES[command as SlotGitCommand] ?? DEFAULT_GIT_COMMAND_DEADLINE
408
- case SlotCommandType.Database:
409
- return 30_000
410
- default:
411
- return FILE_COMMAND_DEADLINES[command as SlotFileCommand] ?? DEFAULT_FILE_COMMAND_DEADLINE
412
- }
413
- }
381
+ export const LAYOUT_MARKERS: Array<[TargetLayout, string]> = [
382
+ [TargetLayout.V2, 'sources/api'],
383
+ [TargetLayout.V1, 'packages/backend'],
384
+ ]
@@ -1,10 +1,5 @@
1
1
  import { WorkloadKind } from './consts.js'
2
-
3
- /** The minimum a caller must know about a slot to address it. */
4
- export interface AddressableSlot {
5
- kind?: WorkloadKind
6
- host?: string
7
- }
2
+ import type { AddressableSlot } from './types.js'
8
3
 
9
4
  /**
10
5
  * The origin a slot's application answers at.
package/src/slot/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './consts.js'
2
+ export * from './utils.js'
2
3
  export * from './schemas.js'
3
4
  export * from './layout.js'
4
5
  export * from './helpers.js'
@@ -1,55 +1,7 @@
1
1
  import { TargetLayout } from '../integrity/index.js'
2
2
  import { packageForRole, resolveTopology, topologyOf } from '../topology/index.js'
3
3
  import { SubProject } from './consts.js'
4
-
5
- /**
6
- * Where each role lives, for one layout. Directory names are target-root-relative.
7
- *
8
- * The pure half of layout resolution. Whoever holds the tree — the publisher over a pod volume,
9
- * the connector over a directory on a developer's machine — adds the two filesystem probes that
10
- * pick the layout and turn these names into absolute paths. The TABLES are shared so the two
11
- * cannot disagree about what a role means.
12
- */
13
- export interface TargetPaths {
14
- layout: TargetLayout
15
- /** The directory holding the workspace packages — `packages` or `sources`. */
16
- dir: string
17
- /** The package whose `dist/index.js` runs as the target's HTTP server. */
18
- api: string
19
- /** The package whose `dist/` is served to a browser. */
20
- web: string
21
- /** The shared library the other two compile against. */
22
- common: string
23
- /**
24
- * The package whose `dist/index.js` runs as the target's queue worker, when the target has one.
25
- *
26
- * Absent for v1, which had no such package and never will — a target's tree is the one it was
27
- * initialized with. Present for v2 as a NAME, not as a promise: every caller checks the disk
28
- * before acting on it.
29
- */
30
- worker?: string
31
- /**
32
- * Every package a full build runs, in dependency order.
33
- *
34
- * Longer than the three roles for v2, whose `backend` is a library that both `api` and `worker`
35
- * import. A caller skips whatever is not on disk — a target need not have a worker.
36
- */
37
- build: string[]
38
- /**
39
- * The packages built with `tsc -b` and consumed through their `build/` output, in dependency
40
- * order — never bundled, so their output has to be on disk at RUN time, not only at build time.
41
- *
42
- * The bundled packages keep every dependency external, so `bun dist/index.js` resolves
43
- * `project-backend` from `node_modules` at startup, follows its `main` to `build/index.js` — and
44
- * if nothing built it, Bun answers `Cannot find package 'project-backend'` and the target exits 1
45
- * with a message that names a dependency rather than a missing build.
46
- *
47
- * v1 got away without this list: it had ONE library and the template shipped its `build/`
48
- * prebuilt. v2 deleted those artifacts and added a second library, so every path that builds a
49
- * target has to build these first or it can never start.
50
- */
51
- libraries: string[]
52
- }
4
+ import type { TargetPaths } from './types.js'
53
5
 
54
6
  /**
55
7
  * Where every role lives, per layout — DERIVED from that layout's topology.
@@ -114,19 +66,6 @@ export const ROLE_DIRS: Record<TargetLayout, Record<SubProject, string>> = {
114
66
  [TargetLayout.V2]: roleDirsOfTopology(TargetLayout.V2),
115
67
  }
116
68
 
117
- /**
118
- * The one marker per layout, chosen because it exists in that layout and in no other.
119
- *
120
- * `sources/api` cannot appear in a v1 tree and `packages/backend` cannot appear in a v2 one, so a
121
- * single `stat` settles it. Deliberately not `sources/` alone: v1 packages each have their own
122
- * `src`, and a directory name that differs by one letter is not something to hang a runtime path
123
- * resolution on. Ordered — the first marker found wins.
124
- */
125
- export const LAYOUT_MARKERS: Array<[TargetLayout, string]> = [
126
- [TargetLayout.V2, 'sources/api'],
127
- [TargetLayout.V1, 'packages/backend'],
128
- ]
129
-
130
69
  /**
131
70
  * Resolve a wire-level role to the directory it names in a given layout.
132
71
  *
package/src/slot/types.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { SlotCommandType, SlotDatabaseCommand, SlotFileCommand, SlotGitCommand, SlotShellCommand, SubProject } from './consts.js'
1
+ import { type SlotCommandType, type SlotDatabaseCommand, type SlotFileCommand, type SlotGitCommand, type SlotShellCommand, type SubProject, WorkloadKind } from './consts.js'
2
+ import { TargetLayout } from '../integrity/index.js'
2
3
 
3
4
  export type SlotCommand = SlotFileCommand | SlotShellCommand | SlotGitCommand | SlotDatabaseCommand
4
5
 
@@ -191,3 +192,58 @@ export interface SlotShellArgs {
191
192
  args?: string
192
193
  skipBuild?: boolean
193
194
  }
195
+
196
+ /** The minimum a caller must know about a slot to address it. */
197
+ export interface AddressableSlot {
198
+ kind?: WorkloadKind
199
+ host?: string
200
+ }
201
+
202
+ /**
203
+ * Where each role lives, for one layout. Directory names are target-root-relative.
204
+ *
205
+ * The pure half of layout resolution. Whoever holds the tree — the publisher over a pod volume,
206
+ * the connector over a directory on a developer's machine — adds the two filesystem probes that
207
+ * pick the layout and turn these names into absolute paths. The TABLES are shared so the two
208
+ * cannot disagree about what a role means.
209
+ */
210
+ export interface TargetPaths {
211
+ layout: TargetLayout
212
+ /** The directory holding the workspace packages — `packages` or `sources`. */
213
+ dir: string
214
+ /** The package whose `dist/index.js` runs as the target's HTTP server. */
215
+ api: string
216
+ /** The package whose `dist/` is served to a browser. */
217
+ web: string
218
+ /** The shared library the other two compile against. */
219
+ common: string
220
+ /**
221
+ * The package whose `dist/index.js` runs as the target's queue worker, when the target has one.
222
+ *
223
+ * Absent for v1, which had no such package and never will — a target's tree is the one it was
224
+ * initialized with. Present for v2 as a NAME, not as a promise: every caller checks the disk
225
+ * before acting on it.
226
+ */
227
+ worker?: string
228
+ /**
229
+ * Every package a full build runs, in dependency order.
230
+ *
231
+ * Longer than the three roles for v2, whose `backend` is a library that both `api` and `worker`
232
+ * import. A caller skips whatever is not on disk — a target need not have a worker.
233
+ */
234
+ build: string[]
235
+ /**
236
+ * The packages built with `tsc -b` and consumed through their `build/` output, in dependency
237
+ * order — never bundled, so their output has to be on disk at RUN time, not only at build time.
238
+ *
239
+ * The bundled packages keep every dependency external, so `bun dist/index.js` resolves
240
+ * `project-backend` from `node_modules` at startup, follows its `main` to `build/index.js` — and
241
+ * if nothing built it, Bun answers `Cannot find package 'project-backend'` and the target exits 1
242
+ * with a message that names a dependency rather than a missing build.
243
+ *
244
+ * v1 got away without this list: it had ONE library and the template shipped its `build/`
245
+ * prebuilt. v2 deleted those artifacts and added a second library, so every path that builds a
246
+ * target has to build these first or it can never start.
247
+ */
248
+ libraries: string[]
249
+ }
@@ -0,0 +1,45 @@
1
+ import { COMMAND_DEADLINES, COMMAND_TIMEOUTS, DEFAULT_COMMAND_DEADLINE, DEFAULT_COMMAND_TIMEOUT, DEFAULT_FILE_COMMAND_DEADLINE, DEFAULT_GIT_COMMAND_DEADLINE, FILE_COMMAND_DEADLINES, FILE_COMMAND_TIMEOUTS, GIT_COMMAND_DEADLINES, GIT_COMMAND_TIMEOUTS, SHELL_COMMAND_TIMEOUTS, SlotCommandType, SlotFileCommand, SlotGitCommand } from './consts.js'
2
+
3
+ /** The per-command caller bound for one command, or nothing where its type's default is right. */
4
+ const perCommandTimeout = (type: SlotCommandType, command: string): number | undefined => {
5
+ switch (type) {
6
+ case SlotCommandType.Shell: return SHELL_COMMAND_TIMEOUTS[command]
7
+ case SlotCommandType.Git: return GIT_COMMAND_TIMEOUTS[command as SlotGitCommand]
8
+ case SlotCommandType.Database: return COMMAND_TIMEOUTS[SlotCommandType.Database]
9
+ default: return FILE_COMMAND_TIMEOUTS[command as SlotFileCommand]
10
+ }
11
+ }
12
+
13
+ /**
14
+ * Resolve the caller-side bound for one command.
15
+ *
16
+ * One function rather than three lookups at each call site: an asker that forgets the per-command
17
+ * table inherits twenty minutes for a fifteen-second command, which is the failure this table was
18
+ * added to stop.
19
+ */
20
+ export const commandTimeout = (
21
+ type: SlotCommandType, command: string, override?: number
22
+ ): number => override
23
+ ?? perCommandTimeout(type, command)
24
+ ?? COMMAND_TIMEOUTS[type]
25
+ ?? DEFAULT_COMMAND_TIMEOUT
26
+
27
+ /**
28
+ * Resolve the executor-side deadline for one command.
29
+ *
30
+ * Per-command first, per-type second. It was per-type only, which is how a clone inherited the
31
+ * bound of a `git status` — the same shape as the shell table above, and added for the same
32
+ * reason.
33
+ */
34
+ export const commandDeadline = (type: SlotCommandType, command: string): number => {
35
+ switch (type) {
36
+ case SlotCommandType.Shell:
37
+ return COMMAND_DEADLINES[command] ?? DEFAULT_COMMAND_DEADLINE
38
+ case SlotCommandType.Git:
39
+ return GIT_COMMAND_DEADLINES[command as SlotGitCommand] ?? DEFAULT_GIT_COMMAND_DEADLINE
40
+ case SlotCommandType.Database:
41
+ return 30_000
42
+ default:
43
+ return FILE_COMMAND_DEADLINES[command as SlotFileCommand] ?? DEFAULT_FILE_COMMAND_DEADLINE
44
+ }
45
+ }
@@ -1,16 +1,9 @@
1
1
  import { SubProject } from '../slot/consts.js'
2
2
  import { TOPOLOGY_VERSION } from './consts.js'
3
3
  import { orderPackages } from './helpers.js'
4
- import type { TargetPackageDescriptor, TargetPackageKind, TopologyDescriptor } from './types.js'
4
+ import type { TargetPackageDescriptor, TargetPackageKind, TopologyDescriptor, TopologyMeta } from './types.js'
5
+ import { KINDS, ROLES } from './consts.local.js'
5
6
 
6
- /** What `.agents/memory/topology.md` carries in its frontmatter. */
7
- export interface TopologyMeta extends TopologyDescriptor {
8
- version: number
9
- updatedAt: string
10
- }
11
-
12
- const ROLES = new Set<string>(Object.values(SubProject))
13
- const KINDS = new Set<TargetPackageKind>(['library', 'bundle'])
14
7
 
15
8
  const asStrings = (value: unknown): string[] =>
16
9
  Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : []
@@ -0,0 +1,6 @@
1
+ import { SubProject } from '../slot/consts.js'
2
+ import type { TargetPackageKind } from './types.js'
3
+
4
+ export const ROLES = new Set<string>(Object.values(SubProject))
5
+
6
+ export const KINDS = new Set<TargetPackageKind>(['library', 'bundle'])
@@ -84,3 +84,9 @@ export interface ResolvedTopology extends TopologyDescriptor {
84
84
  /** Role → the packages holding it, in topology order. */
85
85
  byRole: Partial<Record<SubProject, TargetPackageDescriptor[]>>
86
86
  }
87
+
88
+ /** What `.agents/memory/topology.md` carries in its frontmatter. */
89
+ export interface TopologyMeta extends TopologyDescriptor {
90
+ version: number
91
+ updatedAt: string
92
+ }
@@ -1,7 +1,7 @@
1
1
  import { describe, expect, it } from 'bun:test'
2
2
 
3
- import { BRANDING_ENV_KEYS, brandingEnv } from '../src/branding.js'
4
- import { metadataConfigs, metadataLists } from '../src/consts.js'
3
+ import { brandingEnv } from '../src/branding.js'
4
+ import { BRANDING_ENV_KEYS, metadataConfigs, metadataLists } from '../src/consts.js'
5
5
 
6
6
  /**
7
7
  * `BRANDING_CREDIT` is the one key whose ABSENCE means something different from an explicit
@@ -8,7 +8,7 @@ import { connectProtocols } from '../src/connect/entrypoints.js'
8
8
  import { connectRef } from '../src/connect/references.js'
9
9
  import {
10
10
  ConnectCapabilitiesSchema, ConnectConvertCreateBodySchema, ConnectConvertProceedBodySchema,
11
- ConnectInquiryParamsSchema, ConnectPipelineResumeBodySchema, InquiryAnswerSchema
11
+ ConnectConvertStartBodySchema, ConnectInquiryParamsSchema, ConnectPipelineResumeBodySchema, InquiryAnswerSchema
12
12
  } from '../src/connect/schemas.js'
13
13
  import { ConnectExecutor } from '../src/connect/consts.js'
14
14
  import { InquiryKind } from '@owlmeans/llm-common'
@@ -39,6 +39,7 @@ describe('viable-common - the conversion additions to the connector contract', (
39
39
  ['InquiryAnswerSchema', InquiryAnswerSchema],
40
40
  ['ConnectInquiryParamsSchema', ConnectInquiryParamsSchema],
41
41
  ['ConnectConvertCreateBodySchema', ConnectConvertCreateBodySchema],
42
+ ['ConnectConvertStartBodySchema', ConnectConvertStartBodySchema],
42
43
  ['ConnectConvertProceedBodySchema', ConnectConvertProceedBodySchema],
43
44
  ['ConnectPipelineResumeBodySchema', ConnectPipelineResumeBodySchema],
44
45
  ['ConnectCapabilitiesSchema', ConnectCapabilitiesSchema],
@@ -81,6 +82,25 @@ describe('viable-common - the conversion additions to the connector contract', (
81
82
  expect(proceed({ decision: 'teleport' })).toBe(false)
82
83
  })
83
84
 
85
+ test('start and proceed carry the person\'s confirmation, and nothing else new', () => {
86
+ const ajv = compiler()
87
+ const start = ajv.compile(ConnectConvertStartBodySchema as never)
88
+ const proceed = ajv.compile(ConnectConvertProceedBodySchema as never)
89
+
90
+ expect(start({})).toBe(true)
91
+ expect(start({ confirm: true })).toBe(true)
92
+ // An unset optional serialised as `null` is "not confirmed", never a refused body.
93
+ expect(start({ confirm: null })).toBe(true)
94
+ expect(start({ confirm: 'yes' })).toBe(false)
95
+ expect(start({ restart: true })).toBe(false)
96
+ expect(proceed({ decision: ConversionDecision.Implement, confirm: true })).toBe(true)
97
+ expect(proceed({ decision: ConversionDecision.Implement, confirm: 1 })).toBe(false)
98
+ })
99
+
100
+ test('the start declares its body, so a confirmation reaches the handler', () => {
101
+ expect(entrypointOf(connect.convert.start).contract?.requestSchemas.body).toEqual(ConnectConvertStartBodySchema as never)
102
+ })
103
+
84
104
  test('capabilities accept an executor kind this platform has never heard of', () => {
85
105
  // The SDK and the platform ship separately: a connector built against a newer package must not
86
106
  // be refused a session because it advertises one more capability than this platform knows.