naive-framework 0.1.0 → 0.3.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 (281) hide show
  1. package/AGENTS.md +2 -1
  2. package/docs/decisions/decisions.json +42 -0
  3. package/docs/reference/ROUTES.md +36 -37
  4. package/evidence/skills/fidelity-ladder-audit/ladder-census.mjs +2 -1
  5. package/governance/layer.json +2 -1
  6. package/governance/venture-template/roles/venture-roles.json +62 -0
  7. package/interface/acting.mjs +83 -0
  8. package/interface/adapters/claude-code.json +16 -0
  9. package/interface/adapters/codex.json +14 -0
  10. package/interface/adapters/cursor.json +16 -0
  11. package/interface/adapters.mjs +183 -0
  12. package/interface/api/server.mjs +4 -2
  13. package/interface/boundaries.mjs +219 -0
  14. package/interface/brand.mjs +215 -0
  15. package/interface/cli/freshness.mjs +59 -0
  16. package/interface/cli/guard.mjs +6 -0
  17. package/interface/cli/mentura.mjs +82 -11
  18. package/interface/cli/naive.mjs +44 -14
  19. package/interface/context.mjs +525 -0
  20. package/interface/demo/board.mjs +9 -8
  21. package/interface/demo/decision-harness.mjs +4 -3
  22. package/interface/dev/setup.mjs +84 -0
  23. package/interface/gate-hooks.mjs +37 -0
  24. package/interface/harness/evals.mjs +10 -9
  25. package/interface/harness/run.mjs +16 -15
  26. package/interface/instrumentation.mjs +87 -0
  27. package/interface/kit-boundary.mjs +73 -0
  28. package/interface/layer.json +8 -2
  29. package/interface/mcp/server.mjs +47 -7
  30. package/interface/package-routes.mjs +197 -0
  31. package/interface/provenance.mjs +28 -4
  32. package/interface/reads.mjs +174 -0
  33. package/interface/release-card.mjs +43 -0
  34. package/interface/router.mjs +110 -36
  35. package/interface/skills/naive-setup/SKILL.md +71 -0
  36. package/interface/skills/naive-setup/artifact.html +83 -0
  37. package/interface/vitals.mjs +116 -0
  38. package/interface/writes.mjs +190 -0
  39. package/knowledge/connectors/catalog.mjs +3 -2
  40. package/knowledge/connectors/filesystem.mjs +10 -5
  41. package/knowledge/connectors/index.mjs +3 -2
  42. package/knowledge/freshness.json +85 -0
  43. package/knowledge/layer.json +11 -3
  44. package/knowledge/templates/glossary.md +23 -0
  45. package/operations/layer.json +10 -3
  46. package/operations/marketing/check-public.mjs +7 -6
  47. package/operations/marketing/site/plan.mjs +4 -3
  48. package/operations/marketing/site/presence.mjs +4 -3
  49. package/operations/templates/marketing-brand.md +46 -0
  50. package/operations/templates/public-assets.md +39 -0
  51. package/package.json +3 -1
  52. package/packages/catalog.json +8 -0
  53. package/packages/customers/package.json +21 -1
  54. package/packages/deals/package.json +27 -0
  55. package/packages/decisions/package.json +12 -1
  56. package/packages/finance/frames/fund-without-ceding-control.frame.json +177 -0
  57. package/packages/foundation/package.json +8 -1
  58. package/packages/fund/package.json +48 -0
  59. package/packages/marketing/package.json +10 -4
  60. package/packages/money/package.json +24 -3
  61. package/packages/validation/package.json +13 -0
  62. package/platform/README.md +6 -0
  63. package/platform/adapter.json +15 -0
  64. package/platform/integrations/remote-image.mjs +79 -0
  65. package/platform/integrations/rho.mjs +9 -7
  66. package/platform/kits/README.md +8 -1
  67. package/platform/kits/agent-upgrade/kit.json +15 -0
  68. package/platform/kits/agent-upgrade/run.mjs +82 -0
  69. package/platform/kits/agent-upgrade/stand-in-agent.mjs +32 -0
  70. package/platform/kits/validation-kickoff/kit.json +29 -0
  71. package/platform/webhooks/server.mjs +70 -0
  72. package/purpose/frameworks/idea-map/ideamap.mjs +4 -2
  73. package/purpose/frameworks/idea-map/route.mjs +5 -4
  74. package/purpose/frameworks/product-anatomy/anatomy.mjs +2 -1
  75. package/schema/README.md +1 -0
  76. package/schema/access.mjs +58 -0
  77. package/schema/adapter.schema.json +33 -0
  78. package/schema/add-department.mjs +3 -2
  79. package/schema/assess-problem.mjs +3 -2
  80. package/schema/assets.mjs +213 -0
  81. package/schema/brand.mjs +374 -0
  82. package/schema/build-release.mjs +61 -0
  83. package/schema/caching.mjs +506 -0
  84. package/schema/check-assets.mjs +24 -0
  85. package/schema/check-brand.mjs +24 -0
  86. package/schema/check-config.mjs +111 -0
  87. package/schema/check-data-model.mjs +2 -1
  88. package/schema/check-data-packages.mjs +5 -4
  89. package/schema/check-execution.mjs +4 -3
  90. package/schema/check-nextjs-status.mjs +3 -1
  91. package/schema/check-people.mjs +84 -0
  92. package/schema/check-private.mjs +2 -1
  93. package/schema/check-ready.mjs +6 -5
  94. package/schema/check-sources.mjs +11 -2
  95. package/schema/check-where-used.mjs +4 -3
  96. package/schema/data-model.json +334 -8
  97. package/schema/deal.schema.json +80 -0
  98. package/schema/decision-analytics.mjs +2 -1
  99. package/schema/decisions.mjs +21 -12
  100. package/schema/examples/frames/judge.mjs +10 -0
  101. package/schema/examples/venture-type/jev.mjs +12 -0
  102. package/schema/examples/workspace/ventures/acme-labs/AGENTS.md +17 -0
  103. package/schema/examples/workspace/ventures/acme-labs/accounts/.gitkeep +0 -0
  104. package/schema/examples/workspace/ventures/acme-labs/decisions/discovery-goal.decision.json +23 -0
  105. package/schema/examples/workspace/ventures/acme-labs/decisions/statement-icp.decision.json +22 -0
  106. package/schema/examples/workspace/ventures/acme-labs/decisions/statement-problem.decision.json +22 -0
  107. package/schema/examples/workspace/ventures/acme-labs/decisions/venture.team.decision.json +37 -0
  108. package/schema/examples/workspace/ventures/acme-labs/knowledge/README.md +3 -0
  109. package/schema/examples/workspace/ventures/acme-labs/knowledge/sources.json +46 -0
  110. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000001.json +12 -0
  111. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000002.json +12 -0
  112. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000003.json +12 -0
  113. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000004.json +12 -0
  114. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000005.json +12 -0
  115. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000006.json +12 -0
  116. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000007.json +12 -0
  117. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000008.json +12 -0
  118. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000009.json +12 -0
  119. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000010.json +12 -0
  120. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000011.json +12 -0
  121. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000012.json +12 -0
  122. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000013.json +12 -0
  123. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000014.json +12 -0
  124. package/schema/examples/workspace/ventures/acme-labs/money/_streams/transactions/stream.json +5 -0
  125. package/schema/examples/workspace/ventures/acme-labs/money/_summary.json +30 -0
  126. package/schema/examples/workspace/ventures/acme-labs/operations/departments/customer-service/README.md +5 -0
  127. package/schema/examples/workspace/ventures/acme-labs/operations/departments/customer-service/department.json +5 -0
  128. package/schema/examples/workspace/ventures/acme-labs/operations/departments/finance/README.md +5 -0
  129. package/schema/examples/workspace/ventures/acme-labs/operations/departments/finance/department.json +5 -0
  130. package/schema/examples/workspace/ventures/acme-labs/operations/departments/human-capital/README.md +5 -0
  131. package/schema/examples/workspace/ventures/acme-labs/operations/departments/human-capital/department.json +5 -0
  132. package/schema/examples/workspace/ventures/acme-labs/operations/departments/it/README.md +5 -0
  133. package/schema/examples/workspace/ventures/acme-labs/operations/departments/it/department.json +5 -0
  134. package/schema/examples/workspace/ventures/acme-labs/operations/departments/marketing-and-sales/README.md +5 -0
  135. package/schema/examples/workspace/ventures/acme-labs/operations/departments/marketing-and-sales/department.json +5 -0
  136. package/schema/examples/workspace/ventures/acme-labs/operations/departments/products/README.md +5 -0
  137. package/schema/examples/workspace/ventures/acme-labs/operations/departments/products/department.json +5 -0
  138. package/schema/examples/workspace/ventures/acme-labs/operations/departments/strategy/README.md +5 -0
  139. package/schema/examples/workspace/ventures/acme-labs/operations/departments/strategy/department.json +5 -0
  140. package/schema/examples/workspace/ventures/acme-labs/people/founders/maya-chen.json +15 -0
  141. package/schema/examples/workspace/ventures/acme-labs/people/people.json +22 -0
  142. package/schema/examples/workspace/ventures/acme-labs/pillars/brand.md +5 -0
  143. package/schema/examples/workspace/ventures/acme-labs/pillars/business.md +5 -0
  144. package/schema/examples/workspace/ventures/acme-labs/pillars/product.md +5 -0
  145. package/schema/examples/workspace/ventures/acme-labs/products/.gitkeep +0 -0
  146. package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.core-product.decision.json +28 -0
  147. package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.exists.decision.json +38 -0
  148. package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.flagship.decision.json +27 -0
  149. package/schema/examples/workspace/ventures/acme-labs/profile.md +12 -0
  150. package/schema/examples/workspace/ventures/acme-labs/provenance.jsonl +12 -0
  151. package/schema/examples/workspace/ventures/acme-labs/raw/dump.md +6 -0
  152. package/schema/examples/workspace/ventures/acme-labs/venture.json +27 -0
  153. package/schema/examples/workspace/ventures/northstar/AGENTS.md +17 -0
  154. package/schema/examples/workspace/ventures/northstar/accounts/.gitkeep +0 -0
  155. package/schema/examples/workspace/ventures/northstar/deals/ductline.json +8 -0
  156. package/schema/examples/workspace/ventures/northstar/deals/kilnworks.json +14 -0
  157. package/schema/examples/workspace/ventures/northstar/decisions/venture.team.decision.json +31 -0
  158. package/schema/examples/workspace/ventures/northstar/evidence/README.md +3 -0
  159. package/schema/examples/workspace/ventures/northstar/fund/decisions/terms.decision.json +27 -0
  160. package/schema/examples/workspace/ventures/northstar/fund/decisions/terms.first-close.decision.json +27 -0
  161. package/schema/examples/workspace/ventures/northstar/fund/decisions/thesis.decision.json +26 -0
  162. package/schema/examples/workspace/ventures/northstar/fund/terms.json +22 -0
  163. package/schema/examples/workspace/ventures/northstar/fund/thesis.json +22 -0
  164. package/schema/examples/workspace/ventures/northstar/governance/README.md +3 -0
  165. package/schema/examples/workspace/ventures/northstar/governance/departments/external-relationships/charter.md +5 -0
  166. package/schema/examples/workspace/ventures/northstar/governance/departments/external-relationships/department.json +5 -0
  167. package/schema/examples/workspace/ventures/northstar/governance/departments/finance/charter.md +5 -0
  168. package/schema/examples/workspace/ventures/northstar/governance/departments/finance/department.json +5 -0
  169. package/schema/examples/workspace/ventures/northstar/governance/departments/human-capital/charter.md +5 -0
  170. package/schema/examples/workspace/ventures/northstar/governance/departments/human-capital/department.json +5 -0
  171. package/schema/examples/workspace/ventures/northstar/governance/departments/risk-and-compliance/charter.md +5 -0
  172. package/schema/examples/workspace/ventures/northstar/governance/departments/risk-and-compliance/department.json +5 -0
  173. package/schema/examples/workspace/ventures/northstar/governance/departments/strategy/charter.md +5 -0
  174. package/schema/examples/workspace/ventures/northstar/governance/departments/strategy/department.json +5 -0
  175. package/schema/examples/workspace/ventures/northstar/knowledge/README.md +3 -0
  176. package/schema/examples/workspace/ventures/northstar/operations/README.md +3 -0
  177. package/schema/examples/workspace/ventures/northstar/operations/departments/external-relationships/README.md +5 -0
  178. package/schema/examples/workspace/ventures/northstar/operations/departments/external-relationships/department.json +5 -0
  179. package/schema/examples/workspace/ventures/northstar/operations/departments/finance/README.md +5 -0
  180. package/schema/examples/workspace/ventures/northstar/operations/departments/finance/department.json +5 -0
  181. package/schema/examples/workspace/ventures/northstar/operations/departments/human-capital/README.md +5 -0
  182. package/schema/examples/workspace/ventures/northstar/operations/departments/human-capital/department.json +5 -0
  183. package/schema/examples/workspace/ventures/northstar/operations/departments/risk-and-compliance/README.md +5 -0
  184. package/schema/examples/workspace/ventures/northstar/operations/departments/risk-and-compliance/department.json +5 -0
  185. package/schema/examples/workspace/ventures/northstar/operations/departments/strategy/README.md +5 -0
  186. package/schema/examples/workspace/ventures/northstar/operations/departments/strategy/department.json +5 -0
  187. package/schema/examples/workspace/ventures/northstar/people/founders/ana-ruiz.json +13 -0
  188. package/schema/examples/workspace/ventures/northstar/people/founders/ben-okafor.json +7 -0
  189. package/schema/examples/workspace/ventures/northstar/people/people.json +27 -0
  190. package/schema/examples/workspace/ventures/northstar/pillars/brand.md +5 -0
  191. package/schema/examples/workspace/ventures/northstar/pillars/business.md +5 -0
  192. package/schema/examples/workspace/ventures/northstar/pillars/product.md +5 -0
  193. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/AGENTS.md +17 -0
  194. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/accounts/.gitkeep +0 -0
  195. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/decisions/venture.team.decision.json +31 -0
  196. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/knowledge/README.md +3 -0
  197. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/customer-service/README.md +5 -0
  198. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/customer-service/department.json +5 -0
  199. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/finance/README.md +5 -0
  200. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/finance/department.json +5 -0
  201. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/human-capital/README.md +5 -0
  202. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/human-capital/department.json +5 -0
  203. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/it/README.md +5 -0
  204. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/it/department.json +5 -0
  205. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/marketing-and-sales/README.md +5 -0
  206. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/marketing-and-sales/department.json +5 -0
  207. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/products/README.md +5 -0
  208. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/products/department.json +5 -0
  209. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/strategy/README.md +5 -0
  210. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/strategy/department.json +5 -0
  211. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/brand.md +5 -0
  212. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/business.md +5 -0
  213. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/product.md +5 -0
  214. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/.gitkeep +0 -0
  215. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.core-product.decision.json +28 -0
  216. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.exists.decision.json +32 -0
  217. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.flagship.decision.json +27 -0
  218. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/profile.md +5 -0
  219. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/venture.json +27 -0
  220. package/schema/examples/workspace/ventures/northstar/products/.gitkeep +0 -0
  221. package/schema/examples/workspace/ventures/northstar/profile.md +5 -0
  222. package/schema/examples/workspace/ventures/northstar/provenance.jsonl +3 -0
  223. package/schema/examples/workspace/ventures/northstar/purpose/README.md +3 -0
  224. package/schema/examples/workspace/ventures/northstar/venture.json +49 -0
  225. package/schema/foundation.mjs +8 -7
  226. package/schema/founder.schema.json +72 -0
  227. package/schema/frame.schema.json +240 -0
  228. package/schema/frames.mjs +229 -0
  229. package/schema/freshness-log.schema.json +40 -0
  230. package/schema/freshness-profiles.schema.json +44 -0
  231. package/schema/freshness.mjs +474 -0
  232. package/schema/fund-terms.schema.json +107 -0
  233. package/schema/fund-thesis.schema.json +87 -0
  234. package/schema/gate-drafts.mjs +131 -0
  235. package/schema/gate.mjs +105 -11
  236. package/schema/glossary.schema.json +25 -0
  237. package/schema/init-venture.mjs +69 -21
  238. package/schema/judgment.schema.json +38 -0
  239. package/schema/kit.schema.json +47 -0
  240. package/schema/kits.mjs +24 -0
  241. package/schema/knowledge-sources.schema.json +145 -15
  242. package/schema/layer.json +16 -3
  243. package/schema/marketing-brand.schema.json +116 -0
  244. package/schema/migrate-venture.mjs +8 -7
  245. package/schema/migrations/kit-to-package.mjs +95 -0
  246. package/schema/migrations/package-layout.mjs +90 -0
  247. package/schema/model-steps.mjs +718 -0
  248. package/schema/money-summary.schema.json +138 -0
  249. package/schema/naive-config.mjs +166 -0
  250. package/schema/naive-config.schema.json +268 -0
  251. package/schema/need-now.json +171 -0
  252. package/schema/need-now.mjs +8 -6
  253. package/schema/packages.mjs +21 -15
  254. package/schema/payouts.mjs +3 -2
  255. package/schema/people.schema.json +85 -0
  256. package/schema/port-venture.mjs +206 -132
  257. package/schema/public-assets.schema.json +76 -0
  258. package/schema/release-read.mjs +112 -0
  259. package/schema/releases.mjs +498 -0
  260. package/schema/run-handoff.mjs +5 -4
  261. package/schema/setup.mjs +165 -0
  262. package/schema/stale.mjs +112 -0
  263. package/schema/start-release.mjs +41 -0
  264. package/schema/structure.mjs +187 -0
  265. package/schema/systems-catalog.json +126 -0
  266. package/schema/systems-catalog.schema.json +78 -0
  267. package/schema/time-to-ready.mjs +7 -6
  268. package/schema/trigger.schema.json +44 -0
  269. package/schema/triggers.mjs +238 -0
  270. package/schema/upgrade-registry.schema.json +60 -0
  271. package/schema/upgrade-venture.mjs +96 -118
  272. package/schema/upgrades.json +69 -0
  273. package/schema/upgrades.mjs +386 -0
  274. package/schema/validate.py +19 -10
  275. package/schema/venture-paths.mjs +85 -0
  276. package/schema/venture-role.schema.json +64 -0
  277. package/schema/venture-type.mjs +62 -0
  278. package/schema/venture-types.json +346 -0
  279. package/schema/venture-types.schema.json +129 -0
  280. package/schema/venture.schema.json +61 -0
  281. package/schema/workspace.schema.json +5 -1
@@ -0,0 +1,87 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "fund-thesis.schema.json",
4
+ "title": "Fund thesis",
5
+ "description": "What a fund invests in and why it wins (fund/thesis.json): rounds, sectors, geographies, check size, and the edge. The fund's strategic foundation, as the problem record is a startup's.",
6
+ "type": "object",
7
+ "required": [
8
+ "venture",
9
+ "statement",
10
+ "rounds",
11
+ "sectors",
12
+ "check_size"
13
+ ],
14
+ "additionalProperties": false,
15
+ "properties": {
16
+ "venture": {
17
+ "type": "string"
18
+ },
19
+ "statement": {
20
+ "type": "string",
21
+ "description": "The thesis in one or two sentences"
22
+ },
23
+ "rounds": {
24
+ "type": "array",
25
+ "minItems": 1,
26
+ "items": {
27
+ "enum": [
28
+ "pre-seed",
29
+ "seed",
30
+ "series-a",
31
+ "series-b",
32
+ "growth",
33
+ "late"
34
+ ]
35
+ }
36
+ },
37
+ "sectors": {
38
+ "type": "array",
39
+ "minItems": 1,
40
+ "items": {
41
+ "type": "string"
42
+ }
43
+ },
44
+ "geographies": {
45
+ "type": "array",
46
+ "items": {
47
+ "type": "string"
48
+ }
49
+ },
50
+ "check_size": {
51
+ "type": "object",
52
+ "required": [
53
+ "min",
54
+ "max",
55
+ "currency"
56
+ ],
57
+ "additionalProperties": false,
58
+ "properties": {
59
+ "min": {
60
+ "type": "number",
61
+ "minimum": 0
62
+ },
63
+ "max": {
64
+ "type": "number",
65
+ "minimum": 0
66
+ },
67
+ "currency": {
68
+ "type": "string",
69
+ "pattern": "^[A-Z]{3}$"
70
+ }
71
+ }
72
+ },
73
+ "ownership_target": {
74
+ "type": "number",
75
+ "minimum": 0,
76
+ "maximum": 1,
77
+ "description": "Target ownership at entry, as a fraction"
78
+ },
79
+ "edge": {
80
+ "type": "string",
81
+ "description": "Why this fund sees, wins or helps deals others do not"
82
+ },
83
+ "why_now": {
84
+ "type": "string"
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+ // Held writes (X-2): where the gate's drafts wait and for whom. The gate (schema/gate.mjs) decides;
3
+ // this stores what it held. A held write lands in _drafts/ as before, with a sidecar
4
+ // (<draft>.gate) saying which rule held it and the function owner it was sent to. Where a rule (or
5
+ // gate.variants in naive.config.json) keeps variants, a second agent draft that differs from the
6
+ // first is kept beside it instead of replacing it, like an A/B rewrite: variant a is <draft>,
7
+ // variant b is <draft>.b, and so on. One open decision, in the decisions/ folder beside the record,
8
+ // asks the founder which to accept. Accepting one variant (mentura accept <route> --pick b) decides
9
+ // that decision and removes the others.
10
+ //
11
+ // node schema/gate-drafts.mjs <venture dir> [--owner <role>] [--json] the drafts waiting, by owner
12
+
13
+ import { createHash } from "node:crypto";
14
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
15
+ import { basename, dirname, join } from "node:path";
16
+ import { approve } from "./decisions.mjs";
17
+ import { ventureFile } from "./venture-paths.mjs";
18
+
19
+ const sha = (s) => createHash("sha256").update(s).digest("hex");
20
+ const LETTERS = "abcdefghijklmnopqrstuvwxyz";
21
+ export const sidecarOf = (draft) => `${draft}.gate`;
22
+ export const variantPath = (draft, v) => (v === "a" ? draft : `${draft}.${v}`);
23
+
24
+ /** The decision that holds a record's variants side by side: its id and venture-relative file. */
25
+ export function variantsDecision(file) {
26
+ const stem = file.replace(/\.json$/, "");
27
+ const id = `variants-${stem.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "")}`;
28
+ const at = dirname(file) === "." ? "decisions" : `${dirname(file)}/decisions`;
29
+ return { id, path: `${at}/${basename(stem)}.variants.decision.json` };
30
+ }
31
+
32
+ const readJson = (f) => JSON.parse(readFileSync(f, "utf8"));
33
+
34
+ /** The sidecar of a draft, or null. */
35
+ export function sidecar(dir, draft) {
36
+ const f = join(dir, sidecarOf(draft));
37
+ return existsSync(f) ? readJson(f) : null;
38
+ }
39
+
40
+ /**
41
+ * Stores a held write. dir: the venture; draft: _drafts/<file>.draft; file: the record's path; text:
42
+ * the record; verdict: the gate's, or null when only a decision class held it; route; agent: who wrote it.
43
+ * Returns { written, variant, variants, decision }.
44
+ */
45
+ export function writeHeld(dir, { draft, file, text, verdict, route, agent = {} }) {
46
+ const dest = ventureFile(dir, draft);
47
+ mkdirSync(dirname(dest), { recursive: true });
48
+ const at = new Date().toISOString();
49
+ const by = agent.id ?? agent.kind ?? "agent";
50
+ const meta = sidecar(dir, draft);
51
+ const keep = !!verdict?.variants && existsSync(dest);
52
+ if (!keep) {
53
+ writeFileSync(dest, text);
54
+ for (const v of meta?.variants ?? []) if (v.variant !== "a") rmSync(join(dir, variantPath(draft, v.variant)), { force: true });
55
+ if (verdict && verdict.then !== "pass") {
56
+ writeFileSync(join(dir, sidecarOf(draft)), JSON.stringify({ route, file, rule: verdict.rule, source: verdict.source, then: verdict.then,
57
+ ...(verdict.owner ? { owner: verdict.owner, function: verdict.function ?? null } : {}), variants: [{ variant: "a", file: draft, by, at, sha256: sha(text) }] }, null, 2) + "\n");
58
+ } else rmSync(join(dir, sidecarOf(draft)), { force: true });
59
+ return { written: draft, variant: "a" };
60
+ }
61
+ // Variants: the first draft stays as a; a draft equal to one already held is that variant.
62
+ const variants = meta?.variants?.length ? meta.variants : [{ variant: "a", file: draft, by: "agent", at, sha256: sha(readFileSync(dest)) }];
63
+ const same = variants.find((v) => v.sha256 === sha(text));
64
+ if (same) return { written: same.file, variant: same.variant, variants: variants.map((v) => v.variant), decision: meta?.decision ?? null };
65
+ const next = LETTERS[variants.length];
66
+ if (!next) throw new Error(`${route} already holds ${variants.length} drafts side by side; accept one first`);
67
+ const vfile = variantPath(draft, next);
68
+ writeFileSync(ventureFile(dir, vfile), text);
69
+ variants.push({ variant: next, file: vfile, by, at, sha256: sha(text) });
70
+ const dec = variantsDecision(file);
71
+ const record = {
72
+ id: dec.id,
73
+ question: `Which draft of ${route} do you accept?`,
74
+ decides: { path: file },
75
+ parent: "venture",
76
+ boundary: "fail-open",
77
+ status: "open",
78
+ options: variants.map((v) => `${v.variant}: drafted by ${v.by} at ${v.at}`),
79
+ answer: null,
80
+ note: `The gate kept ${variants.length} differing drafts side by side (rule ${verdict.rule}). Accept one: mentura accept ${route} --pick <letter>`,
81
+ provenance: { drafted_by: { kind: "framework" } },
82
+ };
83
+ mkdirSync(dirname(ventureFile(dir, dec.path)), { recursive: true });
84
+ writeFileSync(ventureFile(dir, dec.path), JSON.stringify(record, null, 2) + "\n");
85
+ writeFileSync(join(dir, sidecarOf(draft)), JSON.stringify({ ...(meta ?? { route, file, rule: verdict.rule, source: verdict.source, then: verdict.then, ...(verdict.owner ? { owner: verdict.owner, function: verdict.function ?? null } : {}) }), variants, decision: dec.id }, null, 2) + "\n");
86
+ return { written: vfile, variant: next, variants: variants.map((v) => v.variant), decision: dec.id };
87
+ }
88
+
89
+ /** The file of one variant of a draft, to accept. Throws when a draft holds variants and none, or an unknown one, is picked. */
90
+ export function pick(dir, draft, letter) {
91
+ const meta = sidecar(dir, draft);
92
+ const vs = meta?.variants ?? [];
93
+ if (vs.length > 1 && !letter) throw new Error(`${meta.route} holds ${vs.length} drafts side by side (${vs.map((v) => v.variant).join(", ")}): pick one with --pick <letter>`);
94
+ if (!letter || letter === "a") return draft;
95
+ const v = vs.find((x) => x.variant === letter);
96
+ if (!v) throw new Error(`no draft ${letter} of ${meta?.route ?? draft}${vs.length ? ` (there are ${vs.map((x) => x.variant).join(", ")})` : ""}`);
97
+ return v.file;
98
+ }
99
+
100
+ /** After a person accepts a draft: removes every variant and the sidecar, and decides the variants decision. */
101
+ export function settle(dir, draft, { picked = "a", by } = {}) {
102
+ const meta = sidecar(dir, draft);
103
+ for (const v of meta?.variants ?? []) rmSync(ventureFile(dir, v.file), { force: true });
104
+ rmSync(ventureFile(dir, draft), { force: true });
105
+ rmSync(join(dir, sidecarOf(draft)), { force: true });
106
+ if (!meta?.decision) return { picked };
107
+ const d = approve(dir, meta.decision, { by: by ?? process.env.MENTURA_PERSON ?? "founder", answer: picked, note: `accepted draft ${picked} of ${meta.route}` });
108
+ return { picked, decision: meta.decision, decided: d.ok, ...(d.ok ? {} : { error: d.error }) };
109
+ }
110
+
111
+ /** The drafts waiting in a venture: route, rule, owner and variants. A draft with no sidecar was held by its decision class. */
112
+ export function inbox(dir, owner) {
113
+ const d = join(ventureFile(dir, "_drafts"));
114
+ if (!existsSync(d)) return [];
115
+ return readdirSync(d).filter((f) => f.endsWith(".draft")).sort().map((f) => {
116
+ const draft = `_drafts/${f}`;
117
+ const meta = sidecar(dir, draft);
118
+ return { draft, file: f.replace(/\.draft$/, "").replace(/__/g, "/"), route: meta?.route ?? null, rule: meta?.rule ?? null, then: meta?.then ?? "draft",
119
+ owner: meta?.owner ?? null, variants: (meta?.variants ?? [{ variant: "a" }]).map((v) => v.variant), decision: meta?.decision ?? null };
120
+ }).filter((x) => !owner || x.owner === owner);
121
+ }
122
+
123
+ if (import.meta.url === `file://${process.argv[1]}`) {
124
+ const [dir] = process.argv.slice(2).filter((a, i, all) => !a.startsWith("--") && !(i && all[i - 1] === "--owner"));
125
+ if (!dir || !existsSync(join(dir, "venture.json"))) { console.error("usage: node schema/gate-drafts.mjs <venture dir> [--owner <role>] [--json]"); process.exit(2); }
126
+ const i = process.argv.indexOf("--owner");
127
+ const rows = inbox(dir, i > 0 ? process.argv[i + 1] : undefined);
128
+ if (process.argv.includes("--json")) console.log(JSON.stringify(rows, null, 2));
129
+ else if (!rows.length) console.log("no drafts waiting");
130
+ else for (const r of rows) console.log(`${r.file.padEnd(36)} ${r.then.padEnd(6)} ${r.owner ?? "-"} ${r.rule ?? "decision class"} variants ${r.variants.join(", ")}`);
131
+ }
package/schema/gate.mjs CHANGED
@@ -1,14 +1,24 @@
1
- // The gate (EE-073): checks that run before a write. One per venture. Static rules live in
2
- // naive.config.json. Per-package rules are the gates on each package definition. The gate
3
- // matches the router's path patterns and never calls a model. Confidence routing reads a
4
- // score that was already computed.
1
+ // The gate (EE-073, P-5, X-1 to X-6): what happens to a write before it lands. One gate per venture
2
+ // (X-5). Its rules come from three places: the venture's naive.config.json (fail_closed routes and
3
+ // rules), each package's gate_rules in its package definition (imported, unless the config leaves a
4
+ // package out), and two the framework always applies: pinned package versions (U-4) and the acting
5
+ // role's write access (P-27). A rule names the routes it covers in the router's own path patterns
6
+ // (X-6) and says what happens: hold the write as a draft, send it as a draft to the function owner
7
+ // (X-2), or refuse it.
8
+ //
9
+ // The gate is fast and never calls a model (X-4). Confidence routing reads a score the write already
10
+ // carries; a write without a score is never held for confidence. Access is checked here and again
11
+ // at the record by the router, on every read and write (F-5). The gate decides; storing a held
12
+ // write, and keeping differing drafts side by side, is schema/gate-drafts.mjs.
5
13
 
6
14
  import { existsSync, readFileSync, readdirSync } from "node:fs";
7
15
  import { join } from "node:path";
16
+ import { may } from "./access.mjs";
17
+ import { configFor, functionOf, packageDefs, packagesOf, pinsBlocking, threshold } from "./naive-config.mjs";
8
18
 
9
19
  const repo = new URL("..", import.meta.url).pathname;
10
20
 
11
- /** Package gates, imported from packages/<name>/package.json. No model, no network. */
21
+ /** Package gates, imported from packages/<name>/package.json: the completion gates, as written. No model, no network. */
12
22
  export function packageGates() {
13
23
  const dir = join(repo, "packages");
14
24
  if (!existsSync(dir)) return [];
@@ -21,8 +31,8 @@ export function packageGates() {
21
31
  }
22
32
 
23
33
  /**
24
- * Whether an agent write is held as a draft. fail_closed names path prefixes
25
- * (foundation, or foundation/problem). A person is not held.
34
+ * Whether an agent write is held as a draft by fail_closed alone. fail_closed names path prefixes
35
+ * (foundation, or foundation/problem). A person is not held. Kept for callers of the first gate.
26
36
  */
27
37
  export function hold(config, route, actor) {
28
38
  if (actor === "person") return null;
@@ -31,9 +41,93 @@ export function hold(config, route, actor) {
31
41
  return hit ? { hold: "draft", rule: hit } : null;
32
42
  }
33
43
 
34
- /** The venture's naive.config.json, or an empty config. */
44
+ /** The gate section of the venture's naive.config.json, with its defaults. */
35
45
  export function configOf(dir) {
36
- const f = dir && join(dir, "naive.config.json");
37
- if (!f || !existsSync(f)) return { fail_closed: [] };
38
- return JSON.parse(readFileSync(f, "utf8")).gate ?? { fail_closed: [] };
46
+ return configFor(dir).gate;
47
+ }
48
+
49
+ /**
50
+ * A route pattern as a regular expression, in the router's own path syntax (X-6): a plain route
51
+ * matches itself; an [id] (any [name]) segment or * is one segment; ** is any depth, and a trailing
52
+ * /** covers the route above it too (validation/** covers validation).
53
+ */
54
+ export function patternRe(pattern) {
55
+ const segs = pattern.split("/").filter(Boolean);
56
+ let re = "", sep = false;
57
+ segs.forEach((s, i) => {
58
+ if (s === "**") {
59
+ if (i === segs.length - 1) re += sep ? "(?:/.*)?" : ".*";
60
+ else { re += sep ? "(?:/[^/]+)*/" : "(?:[^/]+/)*"; sep = false; }
61
+ return;
62
+ }
63
+ re += (sep ? "/" : "") + (/^\[[a-z.]+\]$/.test(s) || s === "*" ? "[^/]+" : s.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]*"));
64
+ sep = true;
65
+ });
66
+ return new RegExp(`^${re}$`);
67
+ }
68
+
69
+ /** Whether a rule's pattern covers a write: the concrete route (product/kettle) or its table route (product/[id]). */
70
+ export function matches(pattern, route, tableRoute) {
71
+ const re = patternRe(pattern);
72
+ return re.test(route) || (!!tableRoute && (pattern === tableRoute || re.test(tableRoute)));
73
+ }
74
+
75
+ /** Gate rules imported from the package definitions (X-5): each package's gate_rules, tagged with the package. */
76
+ export function packageRules(config) {
77
+ const sel = config?.gate?.packages ?? true;
78
+ if (sel === false) return [];
79
+ return packageDefs().filter((p) => sel === true || sel[p.name] !== false)
80
+ .flatMap((p) => (p.gate_rules ?? []).map((r) => ({ ...r, source: `package ${p.name}`, package: p.name })));
81
+ }
82
+
83
+ /** Every rule the venture's gate applies, in order: fail_closed, the config's rules, then the packages'. */
84
+ export function rulesFor(config) {
85
+ const g = config?.gate ?? {};
86
+ return [
87
+ ...(g.fail_closed ?? []).map((p) => ({ id: p, routes: [p, `${p}/**`], then: "draft", actors: ["agent"], source: "naive.config.json", fail_closed: true })),
88
+ ...(g.rules ?? []).map((r) => ({ ...r, source: "naive.config.json" })),
89
+ ...packageRules(config),
90
+ ];
91
+ }
92
+
93
+ const SEVERITY = { pass: 0, draft: 1, owner: 2, refuse: 3 };
94
+
95
+ /**
96
+ * The gate's verdict on one write. Input: config (resolved, from configFor), dir (for access),
97
+ * route (concrete), table (its route-table pattern), record (type), actor (person or agent), role
98
+ * (team-plan id), confidence (a score the write carries, or undefined), exists (the record exists
99
+ * now), decisionOwner (the owner of the record's decision class, if any).
100
+ * Returns { then: pass | draft | owner | refuse, rule, source, owner, variants, why, matched }.
101
+ */
102
+ export function evaluate({ config, dir, route, table, requested, record, actor = "agent", role, confidence, exists, decisionOwner }) {
103
+ const pins = pinsBlocking(config, record);
104
+ if (pins.length) return { then: "refuse", rule: "pinned-version", source: "naive.config.json packages", matched: ["pinned-version"],
105
+ why: pins.map((p) => `${p.package} is pinned to ${p.pinned} but ${p.installed ?? "nothing"} is installed`).join("; ") + ": change the pin or the install first" };
106
+ if (dir && role && ![route, table, requested].some((x) => x && may(dir, role, "write", x)))
107
+ return { then: "refuse", rule: "access", source: "team plan", matched: ["access"], why: `${role} may not write ${route} (team plan routes)` };
108
+ const hits = [];
109
+ for (const r of rulesFor(config)) {
110
+ if (!(r.actors ?? ["agent"]).includes(actor)) continue;
111
+ if (r.roles?.length && !r.roles.includes(role)) continue;
112
+ if (!r.routes.some((p) => matches(p, route, table))) continue;
113
+ const w = r.when ?? {};
114
+ if (w.exists !== undefined && w.exists !== !!exists) continue;
115
+ if (w.confidence_below !== undefined) {
116
+ const limit = typeof w.confidence_below === "number" ? w.confidence_below : threshold(config, w.confidence_below, threshold(config, "confidence", 0.7));
117
+ if (typeof confidence !== "number" || confidence >= limit) continue;
118
+ }
119
+ hits.push(r);
120
+ }
121
+ if (!hits.length) return { then: "pass", rule: null, source: null, matched: [] };
122
+ const top = hits.reduce((a, b) => (SEVERITY[b.then] > SEVERITY[a.then] ? b : a));
123
+ const fn = functionOf(record);
124
+ // The owner: the rule's, else naive.config.json owners by function or by package, else the record's decision-class owner, else the founder.
125
+ const keys = [fn, top.package, ...packagesOf(record).map((p) => p.name)].filter(Boolean);
126
+ const owner = top.then === "owner" ? top.owner ?? keys.map((k) => config?.owners?.[k]).find(Boolean) ?? decisionOwner ?? "founder" : undefined;
127
+ const variants = !!(top.variants ?? config?.gate?.variants);
128
+ const where = top.fail_closed ? `${top.id} fails closed in naive.config.json` : `rule ${top.id} (${top.source})`;
129
+ const why = top.then === "refuse" ? `${where} refuses this write${top.note ? `: ${top.note}` : ""}`
130
+ : top.then === "owner" ? `${where} sends this write to its function owner, ${owner}: written as a draft for them to accept`
131
+ : `${where}: written as a draft for a person to accept`;
132
+ return { then: top.then, rule: top.id, source: top.source, ...(owner ? { owner, function: fn } : {}), variants, why, matched: hits.map((h) => h.id) };
39
133
  }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "glossary.schema.json",
4
+ "title": "Package glossary",
5
+ "description": "A package's own terms, at glossary/<package>.json (Y-2, the scoping idea of CSS Modules): each term stays local to the package unless export is true, so an agent working in another package sees only exported terms. Two packages exporting one term with different meanings fail schema/check-brand.mjs. Version 0.x, unevaluated.",
6
+ "type": "object",
7
+ "required": ["package", "terms"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "package": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$", "description": "The package whose terms these are; the file is glossary/<package>.json" },
11
+ "terms": {
12
+ "type": "array",
13
+ "items": {
14
+ "type": "object",
15
+ "required": ["term", "meaning"],
16
+ "additionalProperties": false,
17
+ "properties": {
18
+ "term": { "type": "string", "minLength": 1 },
19
+ "meaning": { "type": "string", "minLength": 1 },
20
+ "export": { "type": "boolean", "description": "true: other packages see it too" }
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
@@ -3,6 +3,11 @@
3
3
  // (EE-011). Starting layers come from scaffold/defaults.json, by phase (EE-012).
4
4
  //
5
5
  // node schema/init-venture.mjs <dir> <id> [--phase discovery] [--parent <id>] [--legal-form llc] [--layers purpose,governance]
6
+ // [--type <venture type>]
7
+ //
8
+ // --type (schema/venture-types.json, EE-082) decides the package folders, the functions venture.json
9
+ // imports and the first decisions: a software startup answers the product questions, a VC fund its
10
+ // thesis and terms. Without it, every package folder is made and the product questions are asked.
6
11
  //
7
12
  // --layers turns on only the layers named, for a builder adopting part of the system (EE-030);
8
13
  // without it the phase's defaults apply.
@@ -10,48 +15,68 @@
10
15
  // Creates new ventures only, like create-next-app: it refuses a directory that exists and is not empty,
11
16
  // so it can never overwrite a founder's files. An existing project comes in through naive port (EE-076).
12
17
 
18
+ import { spawnSync } from "node:child_process";
13
19
  import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
14
20
  import { dirname, join, relative } from "node:path";
15
21
  import { fileURLToPath } from "node:url";
22
+ import { ventureFile } from "./venture-paths.mjs";
16
23
 
17
24
  const here = dirname(fileURLToPath(import.meta.url));
18
25
  const repo = join(here, "..");
19
26
  const { layers, formalized, pillars, readme } = JSON.parse(readFileSync(join(here, "scaffold/defaults.json"), "utf8"));
20
27
  const args = process.argv.slice(2);
21
28
  const flag = (name) => { const i = args.indexOf(`--${name}`); return i < 0 ? null : args.splice(i, 2)[1]; };
22
- const phase = flag("phase") ?? "discovery", parent = flag("parent"), legalForm = flag("legal-form"), only = flag("layers");
29
+ const phase = flag("phase") ?? "discovery", parent = flag("parent"), legalForm = flag("legal-form"), only = flag("layers"), typeId = flag("type");
30
+ // --layout structured (EE-086): knowledge/, meta/ and an org chart in venture.json; without it, the flat layout.
31
+ const layout = flag("layout") ?? "flat";
32
+ if (!["flat", "structured"].includes(layout)) { console.error(`unknown layout ${layout}: flat or structured`); process.exit(2); }
33
+ const structured = layout === "structured";
34
+ const vtype = typeId ? JSON.parse(readFileSync(join(here, "venture-types.json"), "utf8")).types.find((t) => t.id === typeId) : null;
35
+ if (typeId && !vtype) { console.error(`unknown venture type ${typeId}: see node schema/venture-type.mjs list`); process.exit(2); }
23
36
  const [dir, id] = args;
24
37
  if (!dir || !id) { console.error("usage: node schema/init-venture.mjs <dir> <id> [--phase discovery] [--parent <id>] [--legal-form llc]"); process.exit(2); }
25
38
  if (!layers[phase]) { console.error(`unknown phase ${phase}: one of ${Object.keys(layers).join(", ")}`); process.exit(2); }
26
39
  if (existsSync(dir) && readdirSync(dir).length) { console.error(`${dir} already exists and is not empty: init creates new ventures only, and never writes into an existing project`); process.exit(1); }
27
40
 
28
41
  const ALL = ["purpose", "knowledge", "operations", "evidence", "governance", "interface"];
29
- const on = only !== null ? only.split(",").filter(Boolean) : [...layers[phase], ...(legalForm && legalForm !== "none" ? formalized : [])];
42
+ const on = only !== null ? only.split(",").filter(Boolean) : [...new Set([...layers[phase], ...(vtype?.layers ?? []), ...(legalForm && legalForm !== "none" ? formalized : [])])];
30
43
  const unknown = on.filter((l) => !ALL.includes(l));
31
44
  if (unknown.length) { console.error(`unknown layers: ${unknown.join(", ")}; one of ${ALL.join(", ")}`); process.exit(2); }
32
45
  mkdirSync(dir, { recursive: true });
33
- const venture = { id, name: id, parent: parent ?? null, phase };
34
- if (legalForm) venture.form = { legal_form: legalForm };
46
+ const venture = { id, name: id, ...(vtype ? { type: vtype.id } : {}), parent: parent ?? null, phase };
47
+ if (legalForm || vtype?.funding) venture.form = { ...(legalForm ? { legal_form: legalForm } : {}), ...(vtype?.funding ? { funding: vtype.funding } : {}) };
35
48
  if (phase !== "discovery") venture.core = { promise: "", promised_to: "", must_not: "", competence: "" };
36
- Object.assign(venture, { owner: "self", status: "active", profile: "profile.md", layers: {} });
37
- for (const layer of ALL) {
49
+ Object.assign(venture, { owner: "self", status: "active", profile: structured ? "README.md" : "profile.md", layers: {} });
50
+ // The package folders (EE-070); a typed venture gets its type's packages.
51
+ const packageDirs = vtype ? vtype.packages : ["foundation", "validation", "product", "marketing", "finance", "people", "customers", "investors", "money"];
52
+ if (structured) {
53
+ // venture.json first, so every path below resolves into knowledge/ and meta/. The org chart starts flat:
54
+ // one function per package, owned by no one until create-venture or the founder names the owner.
55
+ venture.layout = "structured";
56
+ venture.functions = Object.fromEntries(packageDirs.map((p) => [p, { owner: null }]));
57
+ for (const layer of ALL) venture.layers[layer] = on.includes(layer) ? { location: "knowledge/" } : false;
58
+ writeFileSync(join(dir, "venture.json"), JSON.stringify(venture, null, 2) + "\n");
59
+ for (const sub of ["knowledge", "meta"]) mkdirSync(ventureFile(dir, sub), { recursive: true });
60
+ }
61
+ for (const layer of structured ? [] : ALL) {
38
62
  if (!on.includes(layer)) { if (only !== null || !["governance", "interface"].includes(layer)) venture.layers[layer] = false; continue; }
39
- mkdirSync(join(dir, layer), { recursive: true });
63
+ mkdirSync(ventureFile(dir, layer), { recursive: true });
40
64
  writeFileSync(join(dir, layer, "README.md"), `# ${layer}\n\n${readme[layer]}\n`);
41
65
  venture.layers[layer] = { location: `${layer}/` };
42
66
  }
43
- for (const sub of ["products", "accounts"]) { mkdirSync(join(dir, sub), { recursive: true }); writeFileSync(join(dir, sub, ".gitkeep"), ""); }
67
+ if (!structured) for (const sub of ["products", "accounts"]) { mkdirSync(ventureFile(dir, sub), { recursive: true }); writeFileSync(join(dir, sub, ".gitkeep"), ""); }
44
68
  // The package folder layout (EE-070). Old layer folders above stay for one release.
45
- for (const sub of ["raw/dump", "raw/sources", "ideas", "foundation", "validation", "product", "marketing", "finance", "people", "customers", "investors", "money", "decisions", "evidence", "public", "_private", "_drafts", ".release"]) {
46
- mkdirSync(join(dir, sub), { recursive: true });
69
+ // A typed venture gets its type's packages; the rest stay out until need-now suggests them.
70
+ for (const sub of ["raw/dump", "raw/sources", "ideas", ...packageDirs, "decisions", "evidence", ...(structured ? [] : ["public"]), "_private", "_drafts", ".release"]) {
71
+ mkdirSync(ventureFile(dir, sub), { recursive: true });
47
72
  }
48
- mkdirSync(join(dir, "pillars"), { recursive: true });
49
- for (const [name, what] of Object.entries(pillars.stubs)) {
50
- const guide = relative(join(dir, "pillars"), join(repo, pillars.guides, `${name}.md`));
51
- writeFileSync(join(dir, "pillars", `${name}.md`), `# ${name[0].toUpperCase() + name.slice(1)} pillar\n\n${what}\n\nGuide: [${name} pillar](${guide})\n`);
73
+ if (!structured) mkdirSync(join(ventureFile(dir, "pillars")), { recursive: true });
74
+ for (const [name, what] of Object.entries(structured ? {} : pillars.stubs)) {
75
+ const guide = relative(join(ventureFile(dir, "pillars")), join(repo, pillars.guides, `${name}.md`));
76
+ writeFileSync(join(ventureFile(dir, "pillars"), `${name}.md`), `# ${name[0].toUpperCase() + name.slice(1)} pillar\n\n${what}\n\nGuide: [${name} pillar](${guide})\n`);
52
77
  }
53
- writeFileSync(join(dir, "profile.md"), `# ${id}\n\nWhat this venture is, in a few sentences. Its machine fields are in venture.json (EE-011).\n\n## Changelog\n`);
54
- writeFileSync(join(dir, "venture.json"), JSON.stringify(venture, null, 2) + "\n");
78
+ writeFileSync(join(ventureFile(dir, "profile.md")), `# ${id}\n\nWhat this venture is, in a few sentences. Its machine fields are in venture.json (EE-011).\n\n## Changelog\n`);
79
+ if (!structured) writeFileSync(join(dir, "venture.json"), JSON.stringify(venture, null, 2) + "\n");
55
80
  // The venture's root layout (EE-072, I-4): every route's layout chain starts here. Lines shaped
56
81
  // "key: value" are instructions the router hands an agent with the layout.
57
82
  writeFileSync(join(dir, "AGENTS.md"), `# AGENTS.md: ${id}
@@ -87,12 +112,35 @@ const productFoundation = [
87
112
  ];
88
113
  // The team question (EE-060): asked in Discovery, failing open, so validation never waits on it. A
89
114
  // founding team, or a founder looking for one, gets the founder-agreement kit beside validation.
90
- mkdirSync(join(dir, "decisions"), { recursive: true });
91
- writeFileSync(join(dir, "decisions/venture.team.decision.json"), JSON.stringify({ id: "founding-team", question: "Who is founding this venture: you alone, you with cofounders, or you looking for cofounders?",
115
+ mkdirSync(join(ventureFile(dir, "decisions")), { recursive: true });
116
+ writeFileSync(join(ventureFile(dir, "decisions/venture.team.decision.json")), JSON.stringify({ id: "founding-team", question: "Who is founding this venture: you alone, you with cofounders, or you looking for cofounders?",
92
117
  decides: { record: "founder-agreement", path: "governance/founder-agreement.json" }, layer: "governance", boundary: "fail-open", needed_in: phase, status: "open",
93
118
  options: ["Solo: I am founding it alone", "Cofounders: we are founding it together", "Looking: I want cofounders"],
94
119
  unlocks: [{ activity: "Draft the founder agreement with the founding-agreement kit", routes: ["governance/founder-agreement"] }], provenance: framework }, null, 2) + "\n");
95
- mkdirSync(join(dir, "products/decisions"), { recursive: true });
96
- for (const d of productFoundation) writeFileSync(join(dir, "products/decisions", `product.${d.id.replace(/^product-/, "")}.decision.json`),
120
+ // A fund's foundation (EE-082): the thesis first, then the terms it raises under, then the first close.
121
+ const fundFoundation = [
122
+ { id: "fund-thesis", question: "What does the fund invest in, and why does it win: rounds, sectors, geographies, check size and its edge?", decides: { record: "fund-thesis", path: "fund/thesis.json" },
123
+ unlocks: [{ activity: "Screen deals against the thesis", routes: ["deals/*"] }] },
124
+ { id: "fund-terms", parent: "fund-thesis", question: "What are the fund's terms: target size, vintage, structure, management fee, carry and term?", decides: { record: "fund-terms", path: "fund/terms.json" },
125
+ unlocks: [{ activity: "Raise from limited partners", routes: ["investors/*"] }] },
126
+ { id: "first-close", parent: "fund-terms", question: "When is the first close, and how much must be committed to hold it?", decides: { record: "fund-terms", path: "fund/terms.json" },
127
+ unlocks: [{ activity: "Make the first investment", routes: ["portfolio/*"] }] },
128
+ ];
129
+ const decisionSet = vtype?.decisions ?? "product-foundation";
130
+ if (decisionSet === "fund-foundation") {
131
+ mkdirSync(join(ventureFile(dir, "fund/decisions")), { recursive: true });
132
+ for (const d of fundFoundation) writeFileSync(join(ventureFile(dir, "fund/decisions"), `${d.id === "first-close" ? "terms.first-close" : d.id.replace(/^fund-/, "")}.decision.json`),
133
+ JSON.stringify({ ...d, layer: "purpose", boundary: "fail-closed", needed_in: phase, status: "open", provenance: framework }, null, 2) + "\n");
134
+ }
135
+ // The product questions sit beside the products: product/ in the structured layout, products/ in the flat one.
136
+ const productDecisions = structured ? "product/decisions" : "products/decisions";
137
+ if (decisionSet === "product-foundation") mkdirSync(join(ventureFile(dir, productDecisions)), { recursive: true });
138
+ if (decisionSet === "product-foundation") for (const d of productFoundation) writeFileSync(join(ventureFile(dir, productDecisions), `product.${d.id.replace(/^product-/, "")}.decision.json`),
97
139
  JSON.stringify({ ...d, layer: "purpose", boundary: "fail-closed", needed_in: phase, status: "open", provenance: framework }, null, 2) + "\n");
98
- console.log(`created venture ${id} (${phase}) in ${dir} with ${on.join(", ") || "no layers"}, products/, accounts/ and the three pillars.${venture.core ? " Fill in the core product before ranking products." : ""}`);
140
+ // The type's functions are imported like any department (EE-047): listed in venture.json, with their folders.
141
+ // In the structured layout the org chart is venture.json's functions; the flat layout imports departments.
142
+ if (vtype && !structured) for (const d of vtype.departments) {
143
+ const r = spawnSync("node", [join(here, "add-department.mjs"), dir, d], { encoding: "utf8" });
144
+ if (r.status !== 0) { console.error((r.stderr || r.stdout).trim()); process.exit(1); }
145
+ }
146
+ console.log(`created ${vtype ? `${vtype.label.toLowerCase()} ` : ""}venture ${id} (${phase}) in ${dir} with ${on.join(", ") || "no layers"}, products/, accounts/ and the three pillars.${venture.core ? " Fill in the core product before ranking products." : ""}`);
@@ -0,0 +1,38 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "judgment.schema.json",
4
+ "title": "Judgment",
5
+ "description": "The output of one model step (\"use model\", EE-073), at <venture>/knowledge/judgments/<id>.json: the package and step that asked, the item it was asked about, the paths the model was given, its typed answer and confidence, the computed values it had to keep, and what code did with it. A judgment is the agent's until a person confirms it; the records it read stay their authors'. Written by schema/model-steps.mjs through the router.",
6
+ "type": "object",
7
+ "required": ["id", "package", "step", "kind", "question", "reads", "outcome", "answer", "by"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$", "description": "<package>-<step>-<item>, or <package>-<step> for a step asked once" },
11
+ "package": { "type": "string", "description": "The package (or kit) that declares the step" },
12
+ "step": { "type": "string", "description": "The step id in the package's use_model" },
13
+ "kind": { "enum": ["classify", "noul", "choice", "score", "draft"], "description": "classify a fragment, judge fit (noul: yes, no or unknown), choose among options, rate on a scale, or draft prose. Only a draft is model-only" },
14
+ "item": { "type": ["string", "null"], "description": "The record id the step was asked about, for a step asked for each item of a collection" },
15
+ "question": { "type": "string", "description": "The question as asked, its {paths} pointing into the state" },
16
+ "reads": { "type": "array", "items": { "type": "string" }, "description": "The venture-relative files and the field paths the model was given, and nothing else" },
17
+ "outcome": { "enum": ["answer", "overruled", "uncertain"], "description": "answer: typed, at or above threshold, and every check passed. overruled: a code check disagreed and the code's value stands. uncertain: below threshold, malformed or unanswered, and routed to a person" },
18
+ "answer": { "description": "The typed answer (the code's value when overruled; null when uncertain)" },
19
+ "confidence": { "type": ["number", "null"], "minimum": 0, "maximum": 1 },
20
+ "threshold": { "type": ["number", "null"], "minimum": 0, "maximum": 1 },
21
+ "why": { "type": "string", "description": "Why the outcome is what it is" },
22
+ "kept": { "type": "object", "description": "Computed values the answer had to carry unchanged, and they did" },
23
+ "overruled": { "type": "object", "additionalProperties": false, "properties": { "judgment": {}, "code": {}, "check": { "type": "string" } } },
24
+ "decision": { "type": "string", "description": "The open decision a person answers when the judgment is uncertain" },
25
+ "by": {
26
+ "type": "object",
27
+ "required": ["kind"],
28
+ "additionalProperties": false,
29
+ "properties": {
30
+ "kind": { "enum": ["model", "person"] },
31
+ "model": { "type": "string" },
32
+ "name": { "type": "string" }
33
+ }
34
+ },
35
+ "state_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$", "description": "Hash of the question and the state the model was given; a later run reuses the judgment while it is unchanged" },
36
+ "asked_at": { "type": "string", "format": "date-time" }
37
+ }
38
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "kit.schema.json",
4
+ "title": "Kit",
5
+ "description": "A Mentura kit (EE-071): an enhanced package, at platform/kits/<name>/kit.json. It extends one Naive package (automations, agent workflows, skills, connectors on top of it) or one framework command (an agent-run upgrade), and never replaces it. The framework reads this manifest as data and runs the kit's entry as its own process; it never imports platform code (schema/kits.mjs). Automations are triggers a venture turns on by listing the kit in naive.config.json kits; each runs only once the package it needs is complete (schema/triggers.mjs).",
6
+ "type": "object",
7
+ "required": ["name", "title", "purpose", "extends", "use_model", "status"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "name": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
11
+ "title": { "type": "string" },
12
+ "purpose": { "type": "string" },
13
+ "extends": {
14
+ "type": "object",
15
+ "additionalProperties": false,
16
+ "minProperties": 1,
17
+ "maxProperties": 1,
18
+ "properties": {
19
+ "package": { "type": "string", "description": "The Naive package it enhances (packages/<name>/package.json)" },
20
+ "command": { "type": "string", "description": "The framework command it extends, such as \"upgrade --agent\"" }
21
+ }
22
+ },
23
+ "entry": { "type": "string", "description": "The kit's program, relative to its folder, run as node <entry> <venture dir>" },
24
+ "agent": {
25
+ "type": "object",
26
+ "additionalProperties": false,
27
+ "required": ["command"],
28
+ "properties": {
29
+ "command": { "type": "array", "items": { "type": "string" }, "description": "The agent it runs by default; MENTURA_AGENT_CMD replaces it" },
30
+ "env": { "type": "array", "items": { "type": "string", "pattern": "^[A-Z][A-Z0-9_]*$" }, "description": "Environment variables it reads, by name" }
31
+ }
32
+ },
33
+ "automations": {
34
+ "type": "array",
35
+ "items": { "$ref": "trigger.schema.json" },
36
+ "description": "Triggers the kit brings; each names the package it needs (needs)"
37
+ },
38
+ "use_model": {
39
+ "type": "array",
40
+ "items": { "type": "string" },
41
+ "description": "The steps that call a model (\"use model\", S-9); empty when none does"
42
+ },
43
+ "checks": { "type": "array", "items": { "type": "string" }, "description": "What decides whether the kit's work lands; always framework code" },
44
+ "status": { "enum": ["built", "experimental"] },
45
+ "note": { "type": "string" }
46
+ }
47
+ }