naive-framework 0.0.0-stage → 0.2.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 (549) hide show
  1. package/AGENTS.md +62 -0
  2. package/LICENSE +21 -0
  3. package/README.md +37 -2
  4. package/docs/decisions/decisions.json +888 -0
  5. package/docs/ontology.json +796 -0
  6. package/docs/ontology.md +163 -0
  7. package/docs/reference/ROUTES.md +124 -0
  8. package/evidence/benchmarks/2026-10-27-golden.jev.after-catalog-fix.json +558 -0
  9. package/evidence/benchmarks/2026-10-27-golden.jev.json +501 -0
  10. package/evidence/benchmarks/2026-10-27-golden.reasoning-answers.json +177 -0
  11. package/evidence/benchmarks/JEV_VS_REASONING_MODEL_2026-10-27.md +68 -0
  12. package/evidence/capabilities/agent-capabilities.json +86 -0
  13. package/evidence/design-documents.registry.json +2896 -0
  14. package/evidence/evals/evals.json +25 -0
  15. package/evidence/evals/harness-evals.json +140 -0
  16. package/evidence/layer.json +51 -0
  17. package/evidence/skills/agent-capabilities/SKILL.md +35 -0
  18. package/evidence/skills/design-coverage/SKILL.md +57 -0
  19. package/evidence/skills/design-coverage/check.mjs +192 -0
  20. package/evidence/skills/design-coverage/scan.mjs +45 -0
  21. package/evidence/skills/fidelity-ladder-audit/SKILL.md +121 -0
  22. package/evidence/skills/fidelity-ladder-audit/ladder-census.mjs +180 -0
  23. package/evidence/skills/findability/SKILL.md +32 -0
  24. package/evidence/skills/findability/inventory.rb +41 -0
  25. package/evidence/skills/foreshadowing-audit/SKILL.md +183 -0
  26. package/evidence/skills/metrics-review/SKILL.md +177 -0
  27. package/evidence/tooling/integrations.json +153 -0
  28. package/governance/layer.json +102 -0
  29. package/governance/references/references.json +26 -0
  30. package/governance/skills/board-design/SKILL.md +68 -0
  31. package/governance/skills/brand-pillar/SKILL.md +90 -0
  32. package/governance/skills/business-pillar/SKILL.md +96 -0
  33. package/governance/skills/chief-of-staff/SKILL.md +45 -0
  34. package/governance/skills/cofounder-structure/SKILL.md +64 -0
  35. package/governance/skills/cross-pillar-tradeoff/SKILL.md +168 -0
  36. package/governance/skills/equity-and-share-classes/SKILL.md +68 -0
  37. package/governance/skills/executive-roles/SKILL.md +95 -0
  38. package/governance/skills/exit-planning/SKILL.md +66 -0
  39. package/governance/skills/financing-and-investor-rights/SKILL.md +73 -0
  40. package/governance/skills/office-hours-mode/SKILL.md +113 -0
  41. package/governance/skills/product-pillar/SKILL.md +81 -0
  42. package/governance/skills/publication-policy/SKILL.md +63 -0
  43. package/governance/skills/role-and-candidate-authoring/SKILL.md +198 -0
  44. package/governance/skills/stakeholder-update/SKILL.md +177 -0
  45. package/governance/tooling/integrations.json +37 -0
  46. package/governance/venture-template/AGENT_ROLES_AND_DECISION_RIGHTS.md +58 -0
  47. package/governance/venture-template/COMPANY_VAULT_DEFINITION_2026-10-25.md +204 -0
  48. package/governance/venture-template/README.md +74 -0
  49. package/governance/venture-template/decision-rights.json +186 -0
  50. package/governance/venture-template/index.md +151 -0
  51. package/governance/venture-template/pillars/brand.md +209 -0
  52. package/governance/venture-template/pillars/business.md +255 -0
  53. package/governance/venture-template/pillars/product.md +254 -0
  54. package/governance/venture-template/render-roles.py +11 -0
  55. package/governance/venture-template/roles/README.md +85 -0
  56. package/governance/venture-template/roles/agent-roles.json +202 -0
  57. package/governance/venture-template/roles/ceo.md +163 -0
  58. package/governance/venture-template/roles/chief-of-staff.md +153 -0
  59. package/governance/venture-template/roles/cmo.md +165 -0
  60. package/governance/venture-template/roles/coo.md +189 -0
  61. package/governance/venture-template/roles/cto.md +158 -0
  62. package/governance/venture-template/roles/department-head.md +47 -0
  63. package/governance/venture-template/roles/forward-deployed-engineer.md +51 -0
  64. package/governance/venture-template/roles/founder.md +173 -0
  65. package/governance/venture-template/roles/hr-manager.md +49 -0
  66. package/governance/venture-template/roles/talent-acquisition-manager.md +50 -0
  67. package/governance/venture-template/roles/venture-roles.json +62 -0
  68. package/interface/acting.mjs +83 -0
  69. package/interface/adapters/claude-code.json +16 -0
  70. package/interface/adapters/codex.json +14 -0
  71. package/interface/adapters/cursor.json +16 -0
  72. package/interface/adapters.mjs +182 -0
  73. package/interface/api/server.mjs +71 -0
  74. package/interface/boundaries.mjs +218 -0
  75. package/interface/brand.mjs +214 -0
  76. package/interface/cli/find-venture.mjs +15 -0
  77. package/interface/cli/freshness.mjs +59 -0
  78. package/interface/cli/guard.mjs +6 -0
  79. package/interface/cli/mentura.mjs +341 -0
  80. package/interface/cli/naive.mjs +194 -0
  81. package/interface/context.mjs +524 -0
  82. package/interface/demo/board.mjs +581 -0
  83. package/interface/demo/decision-harness.mjs +91 -0
  84. package/interface/demo/live-agent.mjs +47 -0
  85. package/interface/dev/setup.mjs +84 -0
  86. package/interface/gate-hooks.mjs +36 -0
  87. package/interface/harness/evals.mjs +90 -0
  88. package/interface/harness/examples/pt-no-shows.dump.md +19 -0
  89. package/interface/harness/run.mjs +313 -0
  90. package/interface/harness/site.mjs +59 -0
  91. package/interface/instrumentation.mjs +86 -0
  92. package/interface/kit-boundary.mjs +73 -0
  93. package/interface/layer.json +37 -0
  94. package/interface/mcp/server.mjs +162 -0
  95. package/interface/operator-console/README.md +58 -0
  96. package/interface/package-routes.mjs +196 -0
  97. package/interface/provenance.mjs +65 -0
  98. package/interface/reads.mjs +173 -0
  99. package/interface/references/references.json +28 -0
  100. package/interface/release-card.mjs +42 -0
  101. package/interface/route-aliases.json +32 -0
  102. package/interface/router.mjs +653 -0
  103. package/interface/skills/install-mentura/SKILL.md +88 -0
  104. package/interface/skills/naive-setup/SKILL.md +71 -0
  105. package/interface/skills/naive-setup/artifact.html +83 -0
  106. package/interface/tooling/integrations.json +112 -0
  107. package/interface/vitals.mjs +115 -0
  108. package/interface/writes.mjs +190 -0
  109. package/knowledge/connectors/README.md +54 -0
  110. package/knowledge/connectors/catalog.mjs +118 -0
  111. package/knowledge/connectors/contract.mjs +56 -0
  112. package/knowledge/connectors/eval.mjs +176 -0
  113. package/knowledge/connectors/filesystem.mjs +79 -0
  114. package/knowledge/connectors/index.mjs +102 -0
  115. package/knowledge/connectors/resolve.mjs +44 -0
  116. package/knowledge/connectors/suite.mjs +80 -0
  117. package/knowledge/freshness.json +85 -0
  118. package/knowledge/layer.json +50 -0
  119. package/knowledge/skills/find-reference/SKILL.md +38 -0
  120. package/knowledge/skills/industry-awareness/SKILL.md +277 -0
  121. package/knowledge/templates/glossary.md +23 -0
  122. package/knowledge/tooling/integrations.json +127 -0
  123. package/knowledge/tooling/questions.md +46 -0
  124. package/operations/FOUNDER_OPERATING_MODEL_CAMPAIGN_2026-10-14.md +16 -0
  125. package/operations/departments.json +162 -0
  126. package/operations/handoff-v2.md +93 -0
  127. package/operations/layer.json +67 -0
  128. package/operations/marketing/check-public.mjs +68 -0
  129. package/operations/marketing/site/README.md +86 -0
  130. package/operations/marketing/site/matrix.json +731 -0
  131. package/operations/marketing/site/plan.mjs +117 -0
  132. package/operations/marketing/site/presence.mjs +252 -0
  133. package/operations/references/references.json +45 -0
  134. package/operations/skills/recruiting/SKILL.md +32 -0
  135. package/operations/skills/team-design/SKILL.md +36 -0
  136. package/operations/skills/tool-selection/SKILL.md +46 -0
  137. package/operations/templates/marketing-brand.md +46 -0
  138. package/operations/templates/public-assets.md +39 -0
  139. package/operations/templates/recruiting-brief.md +35 -0
  140. package/operations/tooling/integrations.json +158 -0
  141. package/package.json +59 -4
  142. package/packages/catalog.json +280 -0
  143. package/packages/cofounder/package.json +42 -0
  144. package/packages/counsel/package.json +47 -0
  145. package/packages/customers/package.json +41 -0
  146. package/packages/deals/package.json +27 -0
  147. package/packages/decisions/package.json +28 -0
  148. package/packages/engineering/package.json +41 -0
  149. package/packages/evidence/package.json +17 -0
  150. package/packages/finance/frames/fund-without-ceding-control.frame.json +177 -0
  151. package/packages/finance/package.json +48 -0
  152. package/packages/foundation/package.json +59 -0
  153. package/packages/fund/package.json +48 -0
  154. package/packages/investor/package.json +57 -0
  155. package/packages/investors/package.json +21 -0
  156. package/packages/legal/package.json +73 -0
  157. package/packages/marketing/package.json +63 -0
  158. package/packages/money/package.json +42 -0
  159. package/packages/operations/package.json +74 -0
  160. package/packages/partner/package.json +38 -0
  161. package/packages/people/package.json +64 -0
  162. package/packages/product/package.json +49 -0
  163. package/packages/raw/package.json +19 -0
  164. package/packages/relationships/package.json +52 -0
  165. package/packages/validation/package.json +112 -0
  166. package/platform/README.md +51 -0
  167. package/platform/adapter.json +15 -0
  168. package/platform/connectors/eval.mjs +154 -0
  169. package/platform/connectors/fake-github.mjs +91 -0
  170. package/platform/connectors/github.mjs +105 -0
  171. package/platform/integrations/jev.mjs +30 -0
  172. package/platform/integrations/langsmith-docket.mjs +53 -0
  173. package/platform/integrations/langsmith-setup.mjs +115 -0
  174. package/platform/integrations/langsmith.mjs +47 -0
  175. package/platform/integrations/remote-image.mjs +79 -0
  176. package/platform/integrations/rho.mjs +146 -0
  177. package/platform/integrations/site.mjs +75 -0
  178. package/platform/kits/README.md +14 -0
  179. package/platform/kits/agent-upgrade/kit.json +15 -0
  180. package/platform/kits/agent-upgrade/run.mjs +82 -0
  181. package/platform/kits/agent-upgrade/stand-in-agent.mjs +32 -0
  182. package/platform/kits/validation-kickoff/kit.json +29 -0
  183. package/platform/mcp/research.mjs +64 -0
  184. package/platform/webhooks/server.mjs +70 -0
  185. package/purpose/checklists/vault-and-tooling-consultancy-setup.md +216 -0
  186. package/purpose/frameworks/business-discovery-framework-amendments-2026-05-20.md +181 -0
  187. package/purpose/frameworks/business-discovery-framework.html +938 -0
  188. package/purpose/frameworks/business-discovery-framework.md +326 -0
  189. package/purpose/frameworks/idea-map/README.md +74 -0
  190. package/purpose/frameworks/idea-map/conventions.json +146 -0
  191. package/purpose/frameworks/idea-map/graph.mjs +182 -0
  192. package/purpose/frameworks/idea-map/ideamap.mjs +181 -0
  193. package/purpose/frameworks/idea-map/route.mjs +140 -0
  194. package/purpose/frameworks/onboarding-handoff-framework.md +269 -0
  195. package/purpose/frameworks/post-discovery-deliverable-playbook.md +274 -0
  196. package/purpose/frameworks/product-anatomy/README.md +63 -0
  197. package/purpose/frameworks/product-anatomy/anatomy.mjs +195 -0
  198. package/purpose/frameworks/product-anatomy/examples/polity.answers.reasoned.json +11 -0
  199. package/purpose/frameworks/product-anatomy/examples/polity.json +89 -0
  200. package/purpose/frameworks/product-anatomy/phases.json +107 -0
  201. package/purpose/frameworks/product-anatomy/questions.json +74 -0
  202. package/purpose/kits/validation/README.md +14 -0
  203. package/purpose/kits/validation/references/references.json +122 -0
  204. package/purpose/kits/validation/skills/problem-validation/SKILL.md +43 -0
  205. package/purpose/kits/validation/skills/validation-score/SKILL.md +35 -0
  206. package/purpose/kits/validation/templates/go-to-market.md +19 -0
  207. package/purpose/kits/validation/templates/operations-readiness.md +20 -0
  208. package/purpose/kits/validation/templates/pricing.md +22 -0
  209. package/purpose/kits/validation/templates/problem-interview.md +36 -0
  210. package/purpose/kits/validation/templates/problem.md +45 -0
  211. package/purpose/kits/validation/templates/product-market-fit.md +23 -0
  212. package/purpose/kits/validation/templates/solution.md +18 -0
  213. package/purpose/kits/validation/templates/team.md +19 -0
  214. package/purpose/kits/validation/weights.json +22 -0
  215. package/purpose/layer.json +53 -0
  216. package/purpose/references/references.json +324 -0
  217. package/purpose/skills/ambition-tier/SKILL.md +205 -0
  218. package/purpose/skills/telos/SKILL.md +52 -0
  219. package/purpose/strategic-foundation.json +133 -0
  220. package/purpose/templates/telos-based-smart.md +39 -0
  221. package/purpose/tooling/integrations.json +48 -0
  222. package/schema/README.md +62 -0
  223. package/schema/VERSION +1 -0
  224. package/schema/access.mjs +57 -0
  225. package/schema/account.schema.json +79 -0
  226. package/schema/adapter.schema.json +33 -0
  227. package/schema/add-department.mjs +41 -0
  228. package/schema/agent-capability.schema.json +94 -0
  229. package/schema/alignment.schema.json +61 -0
  230. package/schema/assess-problem.mjs +131 -0
  231. package/schema/assets.mjs +212 -0
  232. package/schema/bdd.mjs +56 -0
  233. package/schema/board.schema.json +101 -0
  234. package/schema/brand.mjs +373 -0
  235. package/schema/build-release.mjs +61 -0
  236. package/schema/caching.mjs +505 -0
  237. package/schema/check-assets.mjs +24 -0
  238. package/schema/check-boundary.mjs +54 -0
  239. package/schema/check-brand.mjs +24 -0
  240. package/schema/check-config.mjs +110 -0
  241. package/schema/check-data-model.mjs +170 -0
  242. package/schema/check-data-packages.mjs +83 -0
  243. package/schema/check-departments.mjs +45 -0
  244. package/schema/check-execution.mjs +85 -0
  245. package/schema/check-governance.mjs +98 -0
  246. package/schema/check-integrations.mjs +33 -0
  247. package/schema/check-nextjs-status.mjs +79 -0
  248. package/schema/check-nouns.mjs +49 -0
  249. package/schema/check-people.mjs +70 -0
  250. package/schema/check-private.mjs +61 -0
  251. package/schema/check-provenance.mjs +55 -0
  252. package/schema/check-publication.mjs +96 -0
  253. package/schema/check-ready.mjs +89 -0
  254. package/schema/check-sources.mjs +74 -0
  255. package/schema/check-team.mjs +94 -0
  256. package/schema/check-telos.mjs +59 -0
  257. package/schema/check-validation.mjs +165 -0
  258. package/schema/check-ventures.mjs +81 -0
  259. package/schema/check-where-used.mjs +58 -0
  260. package/schema/data-master.schema.json +14 -0
  261. package/schema/data-model.json +1584 -0
  262. package/schema/data-model.schema.json +152 -0
  263. package/schema/deal.schema.json +80 -0
  264. package/schema/decision-analytics.mjs +77 -0
  265. package/schema/decision-record.schema.json +290 -0
  266. package/schema/decision-rights.schema.json +34 -0
  267. package/schema/decision.schema.json +30 -0
  268. package/schema/decisions.mjs +327 -0
  269. package/schema/department-catalog.schema.json +55 -0
  270. package/schema/department.schema.json +15 -0
  271. package/schema/departments.mjs +32 -0
  272. package/schema/docket-eval.mjs +89 -0
  273. package/schema/docket.mjs +135 -0
  274. package/schema/eval-suite.schema.json +45 -0
  275. package/schema/evidence.schema.json +110 -0
  276. package/schema/examples/frames/judge.mjs +10 -0
  277. package/schema/examples/migrate/agent.mjs +12 -0
  278. package/schema/examples/venture-type/jev.mjs +12 -0
  279. package/schema/examples/workspace/ventures/acme-labs/AGENTS.md +17 -0
  280. package/schema/examples/workspace/ventures/acme-labs/accounts/.gitkeep +0 -0
  281. package/schema/examples/workspace/ventures/acme-labs/decisions/discovery-goal.decision.json +23 -0
  282. package/schema/examples/workspace/ventures/acme-labs/decisions/statement-icp.decision.json +22 -0
  283. package/schema/examples/workspace/ventures/acme-labs/decisions/statement-problem.decision.json +22 -0
  284. package/schema/examples/workspace/ventures/acme-labs/decisions/venture.team.decision.json +37 -0
  285. package/schema/examples/workspace/ventures/acme-labs/knowledge/README.md +3 -0
  286. package/schema/examples/workspace/ventures/acme-labs/knowledge/sources.json +46 -0
  287. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000001.json +12 -0
  288. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000002.json +12 -0
  289. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000003.json +12 -0
  290. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000004.json +12 -0
  291. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000005.json +12 -0
  292. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000006.json +12 -0
  293. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000007.json +12 -0
  294. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000008.json +12 -0
  295. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000009.json +12 -0
  296. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000010.json +12 -0
  297. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000011.json +12 -0
  298. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000012.json +12 -0
  299. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000013.json +12 -0
  300. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000014.json +12 -0
  301. package/schema/examples/workspace/ventures/acme-labs/money/_streams/transactions/stream.json +5 -0
  302. package/schema/examples/workspace/ventures/acme-labs/money/_summary.json +30 -0
  303. package/schema/examples/workspace/ventures/acme-labs/operations/departments/customer-service/README.md +5 -0
  304. package/schema/examples/workspace/ventures/acme-labs/operations/departments/customer-service/department.json +5 -0
  305. package/schema/examples/workspace/ventures/acme-labs/operations/departments/finance/README.md +5 -0
  306. package/schema/examples/workspace/ventures/acme-labs/operations/departments/finance/department.json +5 -0
  307. package/schema/examples/workspace/ventures/acme-labs/operations/departments/human-capital/README.md +5 -0
  308. package/schema/examples/workspace/ventures/acme-labs/operations/departments/human-capital/department.json +5 -0
  309. package/schema/examples/workspace/ventures/acme-labs/operations/departments/it/README.md +5 -0
  310. package/schema/examples/workspace/ventures/acme-labs/operations/departments/it/department.json +5 -0
  311. package/schema/examples/workspace/ventures/acme-labs/operations/departments/marketing-and-sales/README.md +5 -0
  312. package/schema/examples/workspace/ventures/acme-labs/operations/departments/marketing-and-sales/department.json +5 -0
  313. package/schema/examples/workspace/ventures/acme-labs/operations/departments/products/README.md +5 -0
  314. package/schema/examples/workspace/ventures/acme-labs/operations/departments/products/department.json +5 -0
  315. package/schema/examples/workspace/ventures/acme-labs/operations/departments/strategy/README.md +5 -0
  316. package/schema/examples/workspace/ventures/acme-labs/operations/departments/strategy/department.json +5 -0
  317. package/schema/examples/workspace/ventures/acme-labs/people/founders/maya-chen.json +15 -0
  318. package/schema/examples/workspace/ventures/acme-labs/people/people.json +22 -0
  319. package/schema/examples/workspace/ventures/acme-labs/pillars/brand.md +5 -0
  320. package/schema/examples/workspace/ventures/acme-labs/pillars/business.md +5 -0
  321. package/schema/examples/workspace/ventures/acme-labs/pillars/product.md +5 -0
  322. package/schema/examples/workspace/ventures/acme-labs/products/.gitkeep +0 -0
  323. package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.core-product.decision.json +28 -0
  324. package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.exists.decision.json +38 -0
  325. package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.flagship.decision.json +27 -0
  326. package/schema/examples/workspace/ventures/acme-labs/profile.md +12 -0
  327. package/schema/examples/workspace/ventures/acme-labs/provenance.jsonl +12 -0
  328. package/schema/examples/workspace/ventures/acme-labs/raw/dump.md +6 -0
  329. package/schema/examples/workspace/ventures/acme-labs/venture.json +27 -0
  330. package/schema/examples/workspace/ventures/northstar/AGENTS.md +17 -0
  331. package/schema/examples/workspace/ventures/northstar/accounts/.gitkeep +0 -0
  332. package/schema/examples/workspace/ventures/northstar/deals/ductline.json +8 -0
  333. package/schema/examples/workspace/ventures/northstar/deals/kilnworks.json +14 -0
  334. package/schema/examples/workspace/ventures/northstar/decisions/venture.team.decision.json +31 -0
  335. package/schema/examples/workspace/ventures/northstar/evidence/README.md +3 -0
  336. package/schema/examples/workspace/ventures/northstar/fund/decisions/terms.decision.json +27 -0
  337. package/schema/examples/workspace/ventures/northstar/fund/decisions/terms.first-close.decision.json +27 -0
  338. package/schema/examples/workspace/ventures/northstar/fund/decisions/thesis.decision.json +26 -0
  339. package/schema/examples/workspace/ventures/northstar/fund/terms.json +22 -0
  340. package/schema/examples/workspace/ventures/northstar/fund/thesis.json +22 -0
  341. package/schema/examples/workspace/ventures/northstar/governance/README.md +3 -0
  342. package/schema/examples/workspace/ventures/northstar/governance/departments/external-relationships/charter.md +5 -0
  343. package/schema/examples/workspace/ventures/northstar/governance/departments/external-relationships/department.json +5 -0
  344. package/schema/examples/workspace/ventures/northstar/governance/departments/finance/charter.md +5 -0
  345. package/schema/examples/workspace/ventures/northstar/governance/departments/finance/department.json +5 -0
  346. package/schema/examples/workspace/ventures/northstar/governance/departments/human-capital/charter.md +5 -0
  347. package/schema/examples/workspace/ventures/northstar/governance/departments/human-capital/department.json +5 -0
  348. package/schema/examples/workspace/ventures/northstar/governance/departments/risk-and-compliance/charter.md +5 -0
  349. package/schema/examples/workspace/ventures/northstar/governance/departments/risk-and-compliance/department.json +5 -0
  350. package/schema/examples/workspace/ventures/northstar/governance/departments/strategy/charter.md +5 -0
  351. package/schema/examples/workspace/ventures/northstar/governance/departments/strategy/department.json +5 -0
  352. package/schema/examples/workspace/ventures/northstar/knowledge/README.md +3 -0
  353. package/schema/examples/workspace/ventures/northstar/operations/README.md +3 -0
  354. package/schema/examples/workspace/ventures/northstar/operations/departments/external-relationships/README.md +5 -0
  355. package/schema/examples/workspace/ventures/northstar/operations/departments/external-relationships/department.json +5 -0
  356. package/schema/examples/workspace/ventures/northstar/operations/departments/finance/README.md +5 -0
  357. package/schema/examples/workspace/ventures/northstar/operations/departments/finance/department.json +5 -0
  358. package/schema/examples/workspace/ventures/northstar/operations/departments/human-capital/README.md +5 -0
  359. package/schema/examples/workspace/ventures/northstar/operations/departments/human-capital/department.json +5 -0
  360. package/schema/examples/workspace/ventures/northstar/operations/departments/risk-and-compliance/README.md +5 -0
  361. package/schema/examples/workspace/ventures/northstar/operations/departments/risk-and-compliance/department.json +5 -0
  362. package/schema/examples/workspace/ventures/northstar/operations/departments/strategy/README.md +5 -0
  363. package/schema/examples/workspace/ventures/northstar/operations/departments/strategy/department.json +5 -0
  364. package/schema/examples/workspace/ventures/northstar/people/founders/ana-ruiz.json +13 -0
  365. package/schema/examples/workspace/ventures/northstar/people/founders/ben-okafor.json +7 -0
  366. package/schema/examples/workspace/ventures/northstar/people/people.json +27 -0
  367. package/schema/examples/workspace/ventures/northstar/pillars/brand.md +5 -0
  368. package/schema/examples/workspace/ventures/northstar/pillars/business.md +5 -0
  369. package/schema/examples/workspace/ventures/northstar/pillars/product.md +5 -0
  370. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/AGENTS.md +17 -0
  371. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/accounts/.gitkeep +0 -0
  372. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/decisions/venture.team.decision.json +31 -0
  373. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/knowledge/README.md +3 -0
  374. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/customer-service/README.md +5 -0
  375. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/customer-service/department.json +5 -0
  376. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/finance/README.md +5 -0
  377. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/finance/department.json +5 -0
  378. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/human-capital/README.md +5 -0
  379. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/human-capital/department.json +5 -0
  380. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/it/README.md +5 -0
  381. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/it/department.json +5 -0
  382. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/marketing-and-sales/README.md +5 -0
  383. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/marketing-and-sales/department.json +5 -0
  384. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/products/README.md +5 -0
  385. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/products/department.json +5 -0
  386. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/strategy/README.md +5 -0
  387. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/strategy/department.json +5 -0
  388. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/brand.md +5 -0
  389. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/business.md +5 -0
  390. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/product.md +5 -0
  391. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/.gitkeep +0 -0
  392. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.core-product.decision.json +28 -0
  393. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.exists.decision.json +32 -0
  394. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.flagship.decision.json +27 -0
  395. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/profile.md +5 -0
  396. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/venture.json +27 -0
  397. package/schema/examples/workspace/ventures/northstar/products/.gitkeep +0 -0
  398. package/schema/examples/workspace/ventures/northstar/profile.md +5 -0
  399. package/schema/examples/workspace/ventures/northstar/provenance.jsonl +3 -0
  400. package/schema/examples/workspace/ventures/northstar/purpose/README.md +3 -0
  401. package/schema/examples/workspace/ventures/northstar/venture.json +49 -0
  402. package/schema/examples/workspace/ventures/studio/accounts/bakery/account.json +18 -0
  403. package/schema/examples/workspace/ventures/studio/evidence/.gitkeep +0 -0
  404. package/schema/examples/workspace/ventures/studio/governance/.gitkeep +0 -0
  405. package/schema/examples/workspace/ventures/studio/knowledge/.gitkeep +0 -0
  406. package/schema/examples/workspace/ventures/studio/operations/.gitkeep +0 -0
  407. package/schema/examples/workspace/ventures/studio/print/knowledge/.gitkeep +0 -0
  408. package/schema/examples/workspace/ventures/studio/print/purpose/.gitkeep +0 -0
  409. package/schema/examples/workspace/ventures/studio/print/venture.json +37 -0
  410. package/schema/examples/workspace/ventures/studio/products/brand-care.json +19 -0
  411. package/schema/examples/workspace/ventures/studio/products/brand-kit.json +23 -0
  412. package/schema/examples/workspace/ventures/studio/provenance.jsonl +3 -0
  413. package/schema/examples/workspace/ventures/studio/purpose/.gitkeep +0 -0
  414. package/schema/examples/workspace/ventures/studio/venture.json +43 -0
  415. package/schema/examples/workspace/ventures/tandem/accounts/.gitkeep +0 -0
  416. package/schema/examples/workspace/ventures/tandem/evidence/README.md +3 -0
  417. package/schema/examples/workspace/ventures/tandem/governance/README.md +3 -0
  418. package/schema/examples/workspace/ventures/tandem/governance/agreements/dee-fast.md +3 -0
  419. package/schema/examples/workspace/ventures/tandem/governance/board.json +51 -0
  420. package/schema/examples/workspace/ventures/tandem/governance/departments/finance/charter.md +5 -0
  421. package/schema/examples/workspace/ventures/tandem/governance/departments/finance/department.json +5 -0
  422. package/schema/examples/workspace/ventures/tandem/governance/departments/primary/marketing-and-sales/charter.md +5 -0
  423. package/schema/examples/workspace/ventures/tandem/governance/departments/primary/marketing-and-sales/department.json +5 -0
  424. package/schema/examples/workspace/ventures/tandem/governance/exit.json +33 -0
  425. package/schema/examples/workspace/ventures/tandem/governance/founder-agreement.json +24 -0
  426. package/schema/examples/workspace/ventures/tandem/governance/founder-agreement.md +3 -0
  427. package/schema/examples/workspace/ventures/tandem/governance/ownership.json +131 -0
  428. package/schema/examples/workspace/ventures/tandem/governance/publication-policy.json +171 -0
  429. package/schema/examples/workspace/ventures/tandem/knowledge/README.md +3 -0
  430. package/schema/examples/workspace/ventures/tandem/knowledge/research/friends-feedback-2026-08.md +3 -0
  431. package/schema/examples/workspace/ventures/tandem/knowledge/research/pilot-2026-10.md +3 -0
  432. package/schema/examples/workspace/ventures/tandem/knowledge/research/problem-interviews-2026-09.md +20 -0
  433. package/schema/examples/workspace/ventures/tandem/knowledge/sources.json +8 -0
  434. package/schema/examples/workspace/ventures/tandem/knowledge/where-used.json +13 -0
  435. package/schema/examples/workspace/ventures/tandem/operations/README.md +3 -0
  436. package/schema/examples/workspace/ventures/tandem/operations/departments/finance/README.md +5 -0
  437. package/schema/examples/workspace/ventures/tandem/operations/departments/finance/department.json +5 -0
  438. package/schema/examples/workspace/ventures/tandem/operations/departments/primary/marketing-and-sales/README.md +5 -0
  439. package/schema/examples/workspace/ventures/tandem/operations/departments/primary/marketing-and-sales/department.json +5 -0
  440. package/schema/examples/workspace/ventures/tandem/pillars/brand.md +5 -0
  441. package/schema/examples/workspace/ventures/tandem/pillars/business.md +5 -0
  442. package/schema/examples/workspace/ventures/tandem/pillars/product.md +5 -0
  443. package/schema/examples/workspace/ventures/tandem/products/.gitkeep +0 -0
  444. package/schema/examples/workspace/ventures/tandem/products/shop-app.json +22 -0
  445. package/schema/examples/workspace/ventures/tandem/profile.md +5 -0
  446. package/schema/examples/workspace/ventures/tandem/provenance.jsonl +13 -0
  447. package/schema/examples/workspace/ventures/tandem/purpose/README.md +3 -0
  448. package/schema/examples/workspace/ventures/tandem/purpose/telos.json +78 -0
  449. package/schema/examples/workspace/ventures/tandem/purpose/validation/go-to-market.json +35 -0
  450. package/schema/examples/workspace/ventures/tandem/purpose/validation/pricing.json +37 -0
  451. package/schema/examples/workspace/ventures/tandem/purpose/validation/problem.json +74 -0
  452. package/schema/examples/workspace/ventures/tandem/purpose/validation/product-market-fit.json +66 -0
  453. package/schema/examples/workspace/ventures/tandem/purpose/validation/solution.json +33 -0
  454. package/schema/examples/workspace/ventures/tandem/purpose/validation/team.json +52 -0
  455. package/schema/examples/workspace/ventures/tandem/venture.json +79 -0
  456. package/schema/examples/workspace/ventures/woodworking/knowledge/.gitkeep +0 -0
  457. package/schema/examples/workspace/ventures/woodworking/venture.json +21 -0
  458. package/schema/examples/workspace/workspace.json +8 -0
  459. package/schema/exit.schema.json +74 -0
  460. package/schema/foundation.mjs +118 -0
  461. package/schema/founder-agreement.schema.json +83 -0
  462. package/schema/founder.schema.json +72 -0
  463. package/schema/frame.schema.json +240 -0
  464. package/schema/frames.mjs +228 -0
  465. package/schema/freshness-log.schema.json +40 -0
  466. package/schema/freshness-profiles.schema.json +44 -0
  467. package/schema/freshness.mjs +473 -0
  468. package/schema/fund-terms.schema.json +107 -0
  469. package/schema/fund-thesis.schema.json +87 -0
  470. package/schema/gate-drafts.mjs +130 -0
  471. package/schema/gate.mjs +133 -0
  472. package/schema/glossary.schema.json +25 -0
  473. package/schema/handoff.schema.json +239 -0
  474. package/schema/icp.schema.json +136 -0
  475. package/schema/idea-graph.schema.json +61 -0
  476. package/schema/init-venture.mjs +128 -0
  477. package/schema/integration.schema.json +143 -0
  478. package/schema/judgment.schema.json +38 -0
  479. package/schema/kit.schema.json +47 -0
  480. package/schema/kits.mjs +24 -0
  481. package/schema/knowledge-sources.schema.json +260 -0
  482. package/schema/layer.json +59 -0
  483. package/schema/layer.schema.json +119 -0
  484. package/schema/load-packages.mjs +26 -0
  485. package/schema/marketing-brand.schema.json +116 -0
  486. package/schema/marketing-sitemap.schema.json +232 -0
  487. package/schema/migrate-venture.mjs +192 -0
  488. package/schema/migrations/kit-to-package.mjs +94 -0
  489. package/schema/migrations/package-layout.mjs +86 -0
  490. package/schema/model-steps.mjs +717 -0
  491. package/schema/money-summary.schema.json +138 -0
  492. package/schema/naive-config.mjs +165 -0
  493. package/schema/naive-config.schema.json +268 -0
  494. package/schema/need-now.json +772 -0
  495. package/schema/need-now.mjs +108 -0
  496. package/schema/nextjs-status.schema.json +29 -0
  497. package/schema/ownership.schema.json +282 -0
  498. package/schema/packages.json +4 -0
  499. package/schema/packages.mjs +252 -0
  500. package/schema/payouts.mjs +91 -0
  501. package/schema/people.schema.json +86 -0
  502. package/schema/port-venture.mjs +161 -0
  503. package/schema/product.schema.json +223 -0
  504. package/schema/provenance-entry.schema.json +154 -0
  505. package/schema/public-assets.schema.json +76 -0
  506. package/schema/publication-policy.schema.json +293 -0
  507. package/schema/raw-source.schema.json +15 -0
  508. package/schema/reference.schema.json +115 -0
  509. package/schema/release-read.mjs +111 -0
  510. package/schema/releases.mjs +497 -0
  511. package/schema/route-aliases.schema.json +25 -0
  512. package/schema/run-handoff.mjs +51 -0
  513. package/schema/scaffold/defaults.json +54 -0
  514. package/schema/setup.mjs +164 -0
  515. package/schema/site-presence.schema.json +337 -0
  516. package/schema/stale.mjs +111 -0
  517. package/schema/start-release.mjs +41 -0
  518. package/schema/strategic-foundation.schema.json +74 -0
  519. package/schema/stream.schema.json +14 -0
  520. package/schema/structure.mjs +186 -0
  521. package/schema/systems-catalog.json +126 -0
  522. package/schema/systems-catalog.schema.json +78 -0
  523. package/schema/team-plan.schema.json +157 -0
  524. package/schema/telos.schema.json +197 -0
  525. package/schema/time-to-ready.mjs +93 -0
  526. package/schema/trigger.schema.json +44 -0
  527. package/schema/triggers.mjs +237 -0
  528. package/schema/upgrade-registry.schema.json +60 -0
  529. package/schema/upgrade-venture.mjs +107 -0
  530. package/schema/upgrades.json +69 -0
  531. package/schema/upgrades.mjs +385 -0
  532. package/schema/use-model.mjs +10 -0
  533. package/schema/validate.py +58 -0
  534. package/schema/validation-evidence.schema.json +123 -0
  535. package/schema/validation-go-to-market.schema.json +110 -0
  536. package/schema/validation-operations-readiness.schema.json +91 -0
  537. package/schema/validation-pricing.schema.json +114 -0
  538. package/schema/validation-problem.schema.json +118 -0
  539. package/schema/validation-product-market-fit.schema.json +135 -0
  540. package/schema/validation-solution.schema.json +79 -0
  541. package/schema/validation-team.schema.json +116 -0
  542. package/schema/venture-role.schema.json +64 -0
  543. package/schema/venture-type.mjs +62 -0
  544. package/schema/venture-types.json +346 -0
  545. package/schema/venture-types.schema.json +129 -0
  546. package/schema/venture.schema.json +460 -0
  547. package/schema/vocab/business-models.json +298 -0
  548. package/schema/where-used.schema.json +56 -0
  549. package/schema/workspace.schema.json +38 -0
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env node
2
+ // Venture packages (EE-067, EE-069): the venture's business source of truth, and the gate between
3
+ // idea and automation. Core packages are where the records live, one per department plus the
4
+ // foundation; each record has one home and other packages read it. Handoff packages hold no records:
5
+ // each is a snapshot of core packages for one receiver (investors, partners, a cofounder, engineering,
6
+ // counsel). A package is complete when a person has confirmed its required records and every record it
7
+ // reads; then MAD's automation tier may run the work that depends on it (schema/packages.json unlocks).
8
+ // Which packages fit depends on the phase and the venture's situation: priors per phase, raised or
9
+ // lowered by facts (the need-now form, EE-028); facts come from the records first, and the question
10
+ // matrix asks a reasoning model only what the records do not settle. Inside a package, a record moves
11
+ // on its own once everything it reads first is confirmed, and waits otherwise (records.after): that is
12
+ // what Route shows. Agents never come in a package: an agent working a package is an enhancement.
13
+ //
14
+ // Each record also carries its route: where the founder's ideas for it stand and the one step that
15
+ // moves it (purpose/ideas/routes, EE-061).
16
+ //
17
+ // node schema/packages.mjs <venture> [--raising] [--hiring] [--answers <jev.json>] [--write] [--json]
18
+ // node schema/packages.mjs request <venture> the Jev request for the questions the records leave open
19
+ //
20
+ // --write renders a readable view of the venture package into <venture>/package/: venture-package.json
21
+ // (the manifest, with its versions), README.md (the index) and one Markdown document per open package.
22
+ // The records themselves stay where they are; the view is regenerated. The documents are internal:
23
+ // anything public goes through its public variant (EE-064).
24
+
25
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
26
+ import { join } from "node:path";
27
+ import { factsOf as needFacts, probability } from "./need-now.mjs";
28
+ import { confirmedIn, filesOf } from "./foundation.mjs";
29
+ import { route } from "../purpose/frameworks/idea-map/route.mjs";
30
+
31
+ import { loadPackages } from "./load-packages.mjs";
32
+ // Upgrades hook (U-5): packages a venture adopted early in naive.config.json open now.
33
+ import { adopted } from "./naive-config.mjs";
34
+
35
+ const repo = new URL("..", import.meta.url).pathname;
36
+ const load = (p) => JSON.parse(readFileSync(p, "utf8"));
37
+ export const PACKAGES = loadPackages(repo);
38
+ export const OUT = "package";
39
+ const MODEL = load(join(repo, "schema/data-model.json"));
40
+ const PHASES = ["discovery", "validation", "beachhead", "scale", "platform"];
41
+ const r2 = (x) => Math.round(x * 100) / 100;
42
+ const json = (dir, f) => existsSync(join(dir, f)) ? load(join(dir, f)) : null;
43
+
44
+ /** The facts the packages test: need-now's, the founder's flags, and the question matrix's answers. */
45
+ export function situation(dir, { flags = {}, answers = null } = {}) {
46
+ const f = needFacts(dir);
47
+ const phase = PHASES.includes(f.phase) ? f.phase : "discovery";
48
+ const icp = json(dir, "foundation/icp.json") ?? json(dir, "purpose/icp.json");
49
+ const profiles = icp?.profiles ?? [];
50
+ const products = filesOf(dir, "product").map((p) => json(dir, p)).filter(Boolean);
51
+ // What the records settle, by question; undefined means they do not.
52
+ const settled = {
53
+ raising: flags.raising != null ? !!flags.raising : f.funding === "bootstrapped" ? false : undefined,
54
+ // A site read by site presence; a planned sitemap does not count, since the pipeline plans one for every venture.
55
+ site: existsSync(join(dir, "operations/marketing/site-presence.json")) || undefined,
56
+ partner_led: profiles.some((p) => p.reached_through?.length) || products.some((p) => (p.offered_to ?? []).some((id) => profiles.some((y) => y.reached_through?.includes(id)))) || undefined,
57
+ hiring: flags.hiring != null ? !!flags.hiring : f.team === "looking" ? true : undefined,
58
+ regulated: undefined,
59
+ exit_intent: json(dir, "governance/exit.json") ? true : undefined,
60
+ };
61
+ const Q = PACKAGES.questions;
62
+ // Jev's answers from the last written package stand, unless new answers replace them.
63
+ const last = existsSync(join(dir, OUT, "venture-package.json")) ? Object.fromEntries(load(join(dir, OUT, "venture-package.json")).situation.questions.filter((q) => q.p != null).map((q) => [`q:${q.id}`, { noul: q.p }])) : {};
64
+ answers = { ...last, ...(answers ?? {}) };
65
+ const questions = Q.items.filter((q) => q.phases.includes(phase)).map((q) => {
66
+ if (settled[q.id] !== undefined) return { ...q, value: settled[q.id], by: "records" };
67
+ const a = answers?.[`q:${q.id}`]?.noul;
68
+ if (a == null) return { ...q, value: null, by: "open" };
69
+ return { ...q, p: r2(a), value: a >= Q.set_at ? true : a <= Q.clear_at ? false : null, by: a >= Q.set_at || a <= Q.clear_at ? "jev" : "open" };
70
+ });
71
+ for (const q of questions) if (q.value != null) f[q.id] = q.value;
72
+ return { phase, facts: f, questions };
73
+ }
74
+
75
+ /** The Jev request: one typed question per fact the records leave open, over what the venture's records say. */
76
+ export function request(dir) {
77
+ const { questions } = situation(dir);
78
+ const v = load(join(dir, "venture.json"));
79
+ const say = (o) => o ? JSON.stringify(o).slice(0, 1200) : null;
80
+ const dumpFile = ["raw/dump.md", "purpose/ideas/dump.md"].find((f) => existsSync(join(dir, f)));
81
+ const dump = dumpFile ? readFileSync(join(dir, dumpFile), "utf8").slice(0, 2500) : null;
82
+ const problem = json(dir, "foundation/problem.json") ?? json(dir, "purpose/validation/problem.json");
83
+ const icpRec = json(dir, "foundation/icp.json") ?? json(dir, "purpose/icp.json");
84
+ return { state: { venture: say({ name: v.name, phase: v.phase, ambition: v.ambition, form: v.form, core: v.core }), problem: say(problem), icp: say(icpRec),
85
+ products: say(filesOf(dir, "product").map((p) => json(dir, p)).filter(Boolean).map((p) => ({ name: p.name, offering: p.offering, description: p.description }))), ideas: dump,
86
+ guidelines: "These are one venture's own records and its founder's idea dump. Answer only from what they say; when they do not say, answer low." },
87
+ model: "jev-latest", questions: Object.fromEntries(questions.filter((q) => q.by === "open").map((q) => [`q:${q.id}`, { type: "noul", instructions: q.ask, criteria: { true: "Yes, the records say or clearly imply it", false: "No, or the records do not say" } }])) };
88
+ }
89
+
90
+ /** A record's state in this venture: confirmed by a person, written by an agent, waiting as a draft, or missing. */
91
+ function stateOf(dir, type) {
92
+ const files = filesOf(dir, type).filter((f) => existsSync(join(dir, f)) && !(f.endsWith(".json") && ["retired", "archived"].includes(json(dir, f)?.status)));
93
+ const drafts = (filesOf(dir, type).length ? filesOf(dir, type) : [MODEL.records.find((r) => r.id === type)?.paths?.find((p) => p.startsWith("instance/**/"))?.slice(12)].filter(Boolean))
94
+ .filter((f) => !f.includes("*") && existsSync(join(dir, `_drafts/${f.replace(/\//g, "__")}.draft`)));
95
+ if (!files.length) return { status: drafts.length ? "draft" : "missing", files: [], drafts };
96
+ const confirmed = files.every((f) => confirmedIn(dir, f, null));
97
+ return { status: drafts.length ? "draft" : confirmed ? "confirmed" : "agent", files, drafts };
98
+ }
99
+
100
+ export const TITLES = { "venture-profile": "Venture profile", "validation-product-market-fit": "Product-market fit", "validation-operations-readiness": "Operations readiness", "marketing-sitemap": "The planned site (sitemap)",
101
+ "marketing-content": "Public content variants", "site-presence": "Site presence", "team-plan": "Team plan", "decision-rights": "Decision rights", "founder-agreement": "Founder agreement", "publication-policy": "Publication policy",
102
+ department: "Departments", handoff: "Handoffs", evidence: "Evidence", ownership: "Ownership", board: "Board", exit: "Exit", account: "Accounts" };
103
+ const STATUS = { confirmed: 1, agent: 0.5, draft: 0.5, missing: 0 };
104
+
105
+ /** Which core package each record lives in. */
106
+ export const HOME = Object.fromEntries(Object.entries(PACKAGES.core).flatMap(([id, p]) => [...p.required, ...p.optional].map((r) => [r, id])));
107
+
108
+ export function packages(dir, { flags = {}, answers = null } = {}) {
109
+ const v = load(join(dir, "venture.json"));
110
+ const { phase, facts, questions } = situation(dir, { flags, answers });
111
+ const next = PHASES[PHASES.indexOf(phase) + 1];
112
+ // Upgrades hook (U-5): a package adopted early opens now, even an experimental one Naive does not model.
113
+ const early = adopted(dir);
114
+ const adopt = (id, f) => (early.has(id) && f.in !== "now" ? { ...f, in: "now", early: true, why: `${f.why}; adopted early in naive.config.json` } : f);
115
+ let routes = null;
116
+ try { routes = route(dir); } catch { routes = null; }
117
+ const dest = new Map((routes?.destinations ?? []).map((d) => [d.id, d]));
118
+ const titleOf = (type) => dest.get(type)?.title ?? TITLES[type] ?? type.replace(/-/g, " ").replace(/^./, (c) => c.toUpperCase());
119
+ const states = new Map();
120
+ const st = (type) => (states.has(type) || states.set(type, stateOf(dir, type)), states.get(type));
121
+ const fitOf = (p) => {
122
+ const fit = r2(probability(p, phase, facts)), later = next ? r2(probability(p, next, facts)) : null;
123
+ const moved = (p.when ?? []).filter((w) => (!w.phase || w.phase === phase) && probability({ base: { [phase]: p.base[phase] }, when: [w] }, phase, facts) !== p.base[phase]).map((w) => w.if);
124
+ return { fit, next_phase: later, in: fit >= PACKAGES.fit ? "now" : later != null && later >= PACKAGES.fit ? "next" : "held", why: moved.length ? `${p.why}; here: ${moved.join(", ")}` : p.why };
125
+ };
126
+ // A record moves on its own once everything it reads first is confirmed; otherwise it waits on those.
127
+ const row = (type, role) => {
128
+ const s = st(type), d = dest.get(type);
129
+ const waits = (PACKAGES.records[type]?.after ?? []).filter((a) => st(a).status !== "confirmed");
130
+ return { record: type, title: titleOf(type), role, home: HOME[type], status: s.status, files: s.files,
131
+ moves: s.status === "confirmed" ? "done" : waits.length ? "waits" : "now", ...(waits.length && s.status !== "confirmed" ? { waits_on: waits, waits_on_titles: waits.map(titleOf) } : {}),
132
+ ...(d ? { route: { stage: d.stage, ideas: d.ideas.length, next: d.next ? { by: d.next.by, do: d.next.do, command: d.next.command } : null } } : {}) };
133
+ };
134
+ const core = Object.entries(PACKAGES.core).filter(([id, p]) => !p.not_modeled || early.has(id)).map(([id, p]) => {
135
+ const records = [...p.required.map((t) => row(t, "required")), ...p.optional.map((t) => row(t, "optional")), ...p.refs.map((t) => row(t, "reads"))];
136
+ const gate = records.filter((r) => r.role !== "optional");
137
+ const weight = (r) => (r.role === "optional" ? 0.5 : 1);
138
+ const progress = r2(records.reduce((s, r) => s + STATUS[r.status] * weight(r), 0) / records.reduce((s, r) => s + weight(r), 0));
139
+ const state = gate.every((r) => r.status === "confirmed") ? "complete" : gate.every((r) => r.status !== "missing") ? "review" : "building";
140
+ return { kind: "core", id, title: p.title, department: p.department, purpose: p.purpose, ...adopt(id, fitOf(p)), state, progress, records, planned: p.planned, unlocks: p.unlocks,
141
+ missing: gate.filter((r) => r.status === "missing").map((r) => r.record), to_review: gate.filter((r) => r.status === "agent" || r.status === "draft").map((r) => r.record),
142
+ moving: records.filter((r) => r.moves === "now" && r.role !== "reads").map((r) => r.record) };
143
+ });
144
+ const byId = Object.fromEntries(core.map((p) => [p.id, p]));
145
+ const handoff = Object.entries(PACKAGES.handoff).filter(([id, p]) => !p.not_modeled || early.has(id)).map(([id, p]) => {
146
+ const from = p.from.map((c) => byId[c]).filter(Boolean);
147
+ return { kind: "handoff", id, title: p.title, for: p.for, from: p.from, ...adopt(id, fitOf(p)), state: from.every((c) => c.state === "complete") ? "complete" : "building",
148
+ progress: r2(from.reduce((s, c) => s + c.progress, 0) / from.length), waits_on: from.filter((c) => c.state !== "complete").map((c) => c.id), unlocks: p.unlocks };
149
+ });
150
+ const order = (a, b) => ({ now: 0, next: 1, held: 2 }[a.in] - { now: 0, next: 1, held: 2 }[b.in]) || b.fit - a.fit;
151
+ core.sort(order); handoff.sort(order);
152
+ const open = core.filter((p) => p.in === "now");
153
+ return { version: PACKAGES.version, venture: v.id, name: v.name, phase, built_at: new Date().toISOString().replace(/\.\d+Z$/, "Z"),
154
+ situation: { facts: Object.fromEntries(questions.map((q) => [q.id, q.value])), questions: questions.map((q) => ({ id: q.id, ask: q.ask, value: q.value, by: q.by, ...(q.p != null ? { p: q.p } : {}), moves: q.moves })) },
155
+ progress: open.length ? r2(open.reduce((s, p) => s + p.progress, 0) / open.length) : 0,
156
+ complete: [...core, ...handoff].filter((p) => p.in === "now" && p.state === "complete").map((p) => p.id),
157
+ core, handoff, assumes: PACKAGES.assumes, not_modeled: [...Object.entries(PACKAGES.core), ...Object.entries(PACKAGES.handoff)].filter(([id, p]) => p.not_modeled && !early.has(id)).map(([id, p]) => ({ id, title: p.title, why: p.not_modeled })),
158
+ enhancements: PACKAGES.enhancements,
159
+ routing: routes ? { included: true, note: "Hackathon demo: each record shows where the founder's ideas for it stand and the one step that moves it (EE-061).", loose: routes.loose?.length ?? 0 } : { included: false } };
160
+ }
161
+
162
+ // Render a record as readable Markdown, whatever its shape: the package documents are for people.
163
+ const HIDE = new Set(["$schema", "version", "venture"]);
164
+ const label = (k) => k.replace(/[_-]+/g, " ").replace(/^./, (c) => c.toUpperCase());
165
+ function md(x, depth = 0) {
166
+ const pad = " ".repeat(depth);
167
+ if (x == null || x === "") return "";
168
+ if (typeof x !== "object") return String(x);
169
+ if (Array.isArray(x)) return x.map((e) => typeof e === "object" && e ? `${pad}- ${md(lead(e), 0)}\n${md(rest(e), depth + 1)}` : `${pad}- ${e}`).join("\n").replace(/\n+$/, "");
170
+ return Object.entries(x).filter(([k, v]) => !HIDE.has(k) && v != null && v !== "" && !(Array.isArray(v) && !v.length)).map(([k, v]) =>
171
+ typeof v === "object" ? `${pad}- **${label(k)}**\n${md(v, depth + 1)}` : `${pad}- **${label(k)}**: ${v}`).join("\n");
172
+ }
173
+ const LEAD = ["name", "title", "who", "statement", "question", "label", "id"];
174
+ const lead = (o) => { const k = LEAD.find((k) => typeof o[k] === "string"); return k ? o[k] : ""; };
175
+ const rest = (o) => { const k = LEAD.find((k) => typeof o[k] === "string"); return Object.fromEntries(Object.entries(o).filter(([x]) => x !== k)); };
176
+ const body = (dir, f) => {
177
+ const t = readFileSync(join(dir, f), "utf8");
178
+ if (f.endsWith(".json")) return md(JSON.parse(t));
179
+ return t.replace(/^---\n[\s\S]*?\n---\n/, "").replace(/^#\s.*\n/, "").trim();
180
+ };
181
+ const MARK = { confirmed: "confirmed", agent: "drafted by an agent, not yet reviewed", draft: "a draft waiting for you", missing: "not written yet" };
182
+ const STATE = { complete: "complete: its automation may run", review: "every record is written; some wait for your review", building: "still being written" };
183
+
184
+ /** A new version each time a package completes or the phase changes; earlier versions are kept. */
185
+ export function versions(dir, r) {
186
+ const f = join(dir, OUT, "venture-package.json");
187
+ const before = existsSync(f) ? load(f) : null;
188
+ const list = before?.versions ?? [];
189
+ const last = list.at(-1);
190
+ const done = r.complete.slice().sort();
191
+ const changed = !last || last.phase !== r.phase || done.some((id) => !last.complete.includes(id));
192
+ if (!changed) return list;
193
+ const n = list.length + 1;
194
+ return [...list, { version: n, at: r.built_at, phase: r.phase, complete: done, why: !last ? "first package" : last.phase !== r.phase ? `phase changed to ${r.phase}` : `completed: ${done.filter((id) => !last.complete.includes(id)).join(", ")}`, tag: `package/${r.venture}/v${n}` }];
195
+ }
196
+
197
+ /** Write the readable view: the manifest, the index, and one document per open core package. */
198
+ export function write(dir, r) {
199
+ const out = join(dir, OUT);
200
+ mkdirSync(out, { recursive: true });
201
+ r.versions = versions(dir, r);
202
+ writeFileSync(join(out, "venture-package.json"), JSON.stringify(r, null, 2) + "\n");
203
+ const open = r.core.filter((p) => p.in === "now");
204
+ for (const p of open) {
205
+ const doc = [`# ${r.name}: ${p.title}`, "", p.purpose, "",
206
+ `Internal: these are the venture's own records. Anything public is a separate variant that passes the public gate (EE-064).`, "",
207
+ `State: ${STATE[p.state]} (${Math.round(p.progress * 100)}%). Unlocks: ${p.unlocks.join(", ")}.`, ""];
208
+ for (const x of p.records) {
209
+ doc.push(`## ${x.title}${x.role === "optional" ? " (optional)" : x.role === "reads" ? ` (read from ${PACKAGES.core[x.home]?.title ?? x.home})` : ""}`, "",
210
+ `*${MARK[x.status]}*${x.waits_on ? `. Waits on: ${x.waits_on.map(titleOf0).join(", ")}` : ""}${x.route?.next && x.status !== "confirmed" ? `. Next: ${x.route.next.do}` : ""}`, "");
211
+ if (x.role === "reads") continue;
212
+ for (const f of x.files) { if (x.files.length > 1) doc.push(`### ${f}`, ""); doc.push(body(dir, f) || "(empty)", ""); }
213
+ }
214
+ if (p.planned.length) doc.push("## Not in Naive yet", "", ...p.planned.map((x) => `- ${x}`), "");
215
+ writeFileSync(join(out, `${p.id}.md`), doc.join("\n").replace(/\n{3,}/g, "\n\n"));
216
+ }
217
+ const pct = (x) => `${Math.round(x * 100)}%`;
218
+ const fm = ["---", "type: venture-package", "source: generated", `created: ${r.built_at}`, "ai-model: none", `tags: [venture-package, ${r.venture}, ${r.phase}]`, `description: "${r.name}'s venture package in ${r.phase}, version ${r.versions.at(-1)?.version ?? 1} (EE-067, EE-069)."`, "---", ""];
219
+ const idx = [...fm, `# ${r.name}: venture package`, "", `Phase: ${r.phase}. ${pct(r.progress)} across the core packages open now. Complete, so their automation may run: ${r.complete.length ? r.complete.join(", ") : "none yet"}.`, "",
220
+ "## Core packages", "", "| Package | Fit now | State | Progress | Moving now | Still to write | To review |", "|---|---|---|---|---|---|---|",
221
+ ...r.core.filter((p) => p.in !== "held").map((p) => `| ${p.in === "now" ? `[${p.title}](${p.id}.md)` : `${p.title} (next phase)`} | ${p.fit} | ${p.state} | ${pct(p.progress)} | ${p.moving.join(", ") || "none"} | ${p.missing.join(", ") || "none"} | ${p.to_review.join(", ") || "none"} |`), "",
222
+ `Held: ${r.core.filter((p) => p.in === "held").map((p) => p.title).join(", ") || "none"}.`, "",
223
+ "## Handoff packages", "", "| Package | For | Fit now | Draws on | Waits on |", "|---|---|---|---|---|",
224
+ ...r.handoff.filter((p) => p.in !== "held").map((p) => `| ${p.title} | ${p.for} | ${p.fit} | ${p.from.join(", ")} | ${p.waits_on.join(", ") || "nothing: ready"} |`), "",
225
+ `Held: ${r.handoff.filter((p) => p.in === "held").map((p) => p.title).join(", ") || "none"}.`, "",
226
+ "## What decided this", "", ...r.situation.questions.map((q) => `- ${q.ask} **${q.value == null ? "open: yours to answer" : q.value ? "yes" : "no"}** (${q.by === "records" ? "from the records" : q.by === "jev" ? `Jev, ${q.p}` : "the records do not say"})`), "",
227
+ "## Versions", "", ...r.versions.map((x) => `- v${x.version}, ${x.at}, ${x.phase}: ${x.why}. Tag: \`${x.tag}\``), "",
228
+ "## Assumed", "", `- ${r.assumes.note}`, "", "## Not included", "", `- Agents. ${r.enhancements.agents}`, ...r.not_modeled.map((x) => `- ${x.title}. ${x.why}`), ""];
229
+ writeFileSync(join(out, "README.md"), idx.join("\n"));
230
+ return out;
231
+ }
232
+ const titleOf0 = (t) => TITLES[t] ?? t.replace(/-/g, " ");
233
+
234
+ if (import.meta.url === `file://${process.argv[1]}`) {
235
+ const args = process.argv.slice(2);
236
+ const opt = (n) => { const i = args.indexOf(`--${n}`); return i >= 0 ? args[i + 1] : null; };
237
+ const has = (n) => args.includes(`--${n}`);
238
+ if (args[0] === "request") { console.log(JSON.stringify(request(args[1]))); process.exit(0); }
239
+ const dir = args[0];
240
+ if (!dir || !existsSync(join(dir, "venture.json"))) { console.error("usage: node schema/packages.mjs <venture> [--raising] [--hiring] [--answers <jev.json>] [--write] [--json] | request <venture>"); process.exit(2); }
241
+ const answers = opt("answers") ? load(opt("answers")).answers : null;
242
+ const r = packages(dir, { flags: Object.fromEntries(["raising", "hiring"].filter(has).map((k) => [k, true])), answers });
243
+ if (has("write")) console.error(`wrote ${write(dir, r)}`);
244
+ if (has("json")) console.log(JSON.stringify(r, null, 2));
245
+ else {
246
+ console.log(`${r.name} (${r.phase}): ${Math.round(r.progress * 100)}% across the open core packages; complete: ${r.complete.join(", ") || "none yet"}`);
247
+ for (const p of r.core) console.log(`core ${p.in.padEnd(5)} ${p.title.padEnd(22)} fit ${String(p.fit).padEnd(5)} ${p.in === "now" ? `${p.state.padEnd(9)} ${Math.round(p.progress * 100)}% moving: ${p.moving.join(", ") || "none"}` : p.why}`);
248
+ for (const p of r.handoff) console.log(`handoff ${p.in.padEnd(5)} ${p.title.padEnd(22)} fit ${String(p.fit).padEnd(5)} ${p.in === "now" ? `waits on ${p.waits_on.join(", ") || "nothing"}` : p.why}`);
249
+ const open = r.situation.questions.filter((q) => q.value == null);
250
+ if (open.length) console.log(`Open: ${open.map((q) => q.ask).join(" ")}`);
251
+ }
252
+ }
@@ -0,0 +1,91 @@
1
+ // Computes who gets what if the venture is sold, from <venture>/governance/ownership.json
2
+ // and the scenarios in exit.json (EE-022): the preference stack. Indicative only, not
3
+ // legal, tax or financial advice: the signed documents decide, and real deals add debt,
4
+ // fees, escrow and earn-outs that this leaves out.
5
+ //
6
+ // node schema/payouts.mjs <venture dir> every scenario in exit.json
7
+ // node schema/payouts.mjs <venture dir> <value> one sale value
8
+ // node schema/payouts.mjs <venture dir> --json as data
9
+ //
10
+ // Rules, from standard terms (NVCA model documents; Feld and Mendelson, Venture Deals):
11
+ // preferred classes are paid first, highest seniority first, equal ranks pro rata; a
12
+ // non-participating preference takes the greater of its preference or converting to common;
13
+ // a participating one takes both. A post-money SAFE or note takes the greater of its amount
14
+ // or its as-converted share (amount over valuation cap), on par with the lowest-ranked
15
+ // preferred. The unissued option pool is paid nothing. What is left goes pro rata to common.
16
+
17
+ import { existsSync, readFileSync } from "node:fs";
18
+ import { join } from "node:path";
19
+
20
+ export function payouts(own, value) {
21
+ const classes = new Map(own.classes.map((c) => [c.id, c]));
22
+ const kindOf = new Map(own.holders.map((h) => [h.id, h.kind]));
23
+ const grants = own.grants.filter((g) => kindOf.get(g.holder) !== "pool");
24
+ const issued = grants.reduce((n, g) => n + g.amount, 0);
25
+ const instruments = own.instruments ?? [];
26
+ const safeShare = instruments.reduce((n, i) => n + (i.valuation_cap ? i.amount / i.valuation_cap : 0), 0);
27
+ const ranks = own.classes.filter((c) => c.kind === "preferred").map((c) => c.liquidation?.seniority ?? 0);
28
+ const lowest = ranks.length ? Math.min(...ranks) : 0;
29
+
30
+ // One position per grant or instrument: its as-converted fraction and its preference.
31
+ const pos = [
32
+ ...grants.map((g) => {
33
+ const c = classes.get(g.class);
34
+ const pref = c.kind === "preferred" ? g.amount * (c.price_per_share ?? 0) * (c.liquidation?.multiple ?? 1) : 0;
35
+ return { holder: g.holder, of: g.class, fraction: (1 - safeShare) * g.amount / issued, pref, rank: c.liquidation?.seniority ?? 0, participating: !!c.liquidation?.participating };
36
+ }),
37
+ ...instruments.map((i) => ({ holder: i.holder, of: i.id, fraction: i.valuation_cap ? i.amount / i.valuation_cap : 0, pref: i.amount, rank: lowest, participating: false })),
38
+ ];
39
+
40
+ const run = (converted) => {
41
+ let left = value;
42
+ const paid = pos.map(() => 0);
43
+ const takesPref = (p, i) => p.pref > 0 && !converted.has(i);
44
+ for (const rank of [...new Set(pos.filter(takesPref).map((p) => p.rank))].sort((a, b) => b - a)) {
45
+ const group = pos.map((p, i) => [p, i]).filter(([p, i]) => takesPref(p, i) && p.rank === rank);
46
+ const owed = group.reduce((n, [p]) => n + p.pref, 0);
47
+ const pay = Math.min(left, owed);
48
+ for (const [p, i] of group) paid[i] += pay * p.pref / owed;
49
+ left -= pay;
50
+ }
51
+ const sharers = pos.map((p, i) => [p, i]).filter(([p, i]) => p.pref === 0 || p.participating || converted.has(i));
52
+ const total = sharers.reduce((n, [p]) => n + p.fraction, 0);
53
+ for (const [p, i] of sharers) paid[i] += total ? left * p.fraction / total : 0;
54
+ return paid;
55
+ };
56
+
57
+ // Each non-participating preference converts when converting pays it more; repeat until stable.
58
+ const converted = new Set();
59
+ for (let changed = true, guard = 0; changed && guard < 50; guard++) {
60
+ changed = false;
61
+ const now = run(converted);
62
+ for (const [i, p] of pos.entries()) {
63
+ if (p.pref === 0 || p.participating || converted.has(i)) continue;
64
+ const tryIt = new Set([...converted, i]);
65
+ if (run(tryIt)[i] > now[i] + 1e-9) { converted.add(i); changed = true; break; }
66
+ }
67
+ }
68
+ const paid = run(converted);
69
+ const byHolder = new Map();
70
+ for (const [i, p] of pos.entries()) byHolder.set(p.holder, (byHolder.get(p.holder) ?? 0) + paid[i]);
71
+ return { value, converted: [...converted].map((i) => pos[i].of), payouts: [...byHolder].map(([holder, amount]) => ({ holder, amount: Math.round(amount * 100) / 100 })) };
72
+ }
73
+
74
+ if (import.meta.url === `file://${process.argv[1]}`) {
75
+ const [dir, arg] = process.argv.slice(2);
76
+ if (!dir) { console.error("usage: node schema/payouts.mjs <venture dir> [value] [--json]"); process.exit(2); }
77
+ const own = JSON.parse(readFileSync(join(dir, "governance/ownership.json"), "utf8"));
78
+ const exitFile = join(dir, "governance/exit.json");
79
+ const scenarios = arg && !arg.startsWith("--") ? [{ id: "given", value: Number(arg) }]
80
+ : existsSync(exitFile) ? JSON.parse(readFileSync(exitFile, "utf8")).scenarios ?? [] : [];
81
+ if (!scenarios.length) { console.error("no scenarios: pass a value or add scenarios to governance/exit.json"); process.exit(2); }
82
+ const results = scenarios.map((s) => ({ scenario: s.id, ...payouts(own, s.value) }));
83
+ if (process.argv.includes("--json")) { console.log(JSON.stringify(results, null, 2)); process.exit(0); }
84
+ const names = new Map(own.holders.map((h) => [h.id, h.name]));
85
+ const cur = own.currency ?? "";
86
+ for (const r of results) {
87
+ console.log(`\n${r.scenario}: sale value ${r.value.toLocaleString("en-US")} ${cur}${r.converted.length ? ` (converts to common: ${r.converted.join(", ")})` : ""}`);
88
+ for (const p of r.payouts) console.log(` ${(names.get(p.holder) ?? p.holder).padEnd(28)} ${p.amount.toLocaleString("en-US", { maximumFractionDigits: 0 }).padStart(14)} ${(100 * p.amount / (r.value || 1)).toFixed(1).padStart(5)}%`);
89
+ }
90
+ console.log("\nIndicative only; the signed documents decide. Not legal, tax or financial advice.");
91
+ }
@@ -0,0 +1,86 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "people.schema.json",
4
+ "title": "People",
5
+ "description": "The venture's people (people/people.json): who is in it, in which role, and which functions (hats) each owns. It is to human capital what venture.json is to the venture. A founder also has a file in people/founders/. Names only: no personal details.",
6
+ "type": "object",
7
+ "required": [
8
+ "venture",
9
+ "mode",
10
+ "people"
11
+ ],
12
+ "additionalProperties": false,
13
+ "properties": {
14
+ "venture": {
15
+ "type": "string"
16
+ },
17
+ "mode": {
18
+ "enum": [
19
+ "solo",
20
+ "team"
21
+ ],
22
+ "description": "solo: one person owns every function the venture imports"
23
+ },
24
+ "people": {
25
+ "type": "array",
26
+ "minItems": 1,
27
+ "items": {
28
+ "type": "object",
29
+ "required": [
30
+ "id",
31
+ "name",
32
+ "role",
33
+ "hats"
34
+ ],
35
+ "additionalProperties": false,
36
+ "properties": {
37
+ "id": {
38
+ "type": "string",
39
+ "pattern": "^[a-z0-9-]+$"
40
+ },
41
+ "name": {
42
+ "type": "string"
43
+ },
44
+ "role": {
45
+ "type": "string",
46
+ "description": "A role id from governance/venture-template/roles/venture-roles.json"
47
+ },
48
+ "hats": {
49
+ "type": "array",
50
+ "items": {
51
+ "enum": [
52
+ "strategy",
53
+ "products",
54
+ "marketing-and-sales",
55
+ "supply-chain",
56
+ "service-delivery",
57
+ "customer-service",
58
+ "human-capital",
59
+ "it",
60
+ "finance",
61
+ "assets",
62
+ "risk-and-compliance",
63
+ "external-relationships",
64
+ "capabilities"
65
+ ]
66
+ },
67
+ "uniqueItems": true,
68
+ "description": "The functions this person owns (operations/departments.json)"
69
+ },
70
+ "founder_file": {
71
+ "type": "string",
72
+ "pattern": "^people/founders/[a-z0-9-]+\\.json$"
73
+ }
74
+ }
75
+ }
76
+ },
77
+ "founder_agreement": {
78
+ "type": "string",
79
+ "description": "The founder agreement, once there is one (governance/founder-agreement.json)"
80
+ },
81
+ "updated": {
82
+ "type": "string",
83
+ "format": "date"
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ // naive port: brings an existing project into a new venture by keeping its files as they are (EE-076).
3
+ // Each file is placed, unchanged, in the package directory its name or folder points to; a code
4
+ // repository or anything that should stay where it is becomes a pointer in knowledge/sources.json;
5
+ // what fits nowhere is left behind, by name, so nothing disappears silently. Migrate (rewriting a
6
+ // project into the Naive convention) is the other way in, and is not this command.
7
+ //
8
+ // node schema/port-venture.mjs --from <project> --venture <new venture dir>
9
+ // writes the plan to <venture>/.release/port-plan.json and prints it; changes nothing else
10
+ // node schema/port-venture.mjs --venture <dir> --apply --confirm port
11
+ // carries out the plan as it now reads; the founder may first set any item's action to
12
+ // port, point or leave
13
+ //
14
+ // The project is only ever read. A port never overwrites a file in the venture, refuses a plan
15
+ // whose source files changed since it was written, and records every copy in provenance.jsonl
16
+ // with the source path it was derived from.
17
+
18
+ import { createHash } from "node:crypto";
19
+ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
20
+ import { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
21
+ import { record } from "../interface/provenance.mjs";
22
+ import { SECRET } from "./migrate-venture.mjs";
23
+
24
+ export const PLAN = ".release/port-plan.json";
25
+ const SKIP = new Set([".git", "node_modules", ".next", ".turbo", "dist", "build", ".venv", "__pycache__", ".DS_Store"]);
26
+ const REPO_MARKERS = [".git", "package.json", "Cargo.toml", "go.mod", "pyproject.toml", "Gemfile", "pom.xml"];
27
+ const CODE = new Set([".js", ".mjs", ".cjs", ".ts", ".tsx", ".jsx", ".py", ".rb", ".go", ".rs", ".java", ".kt", ".swift", ".c", ".h", ".cpp", ".cs", ".php", ".sh", ".sql", ".css", ".scss", ".html", ".lock", ".yml", ".yaml", ".toml"]);
28
+ const MAX_BYTES = 5 * 1024 * 1024;
29
+
30
+ // The first rule whose pattern matches wins: the file name is tried before its folders, so a file
31
+ // says more about itself than the folder it sits in. Patterns match words in lowercase paths.
32
+ const RULES = [
33
+ [/\b(problem|pain[- ]?points?)\b/, "foundation", "states the problem"],
34
+ [/\b(icp|personas?|ideal[- ]customer|customer[- ]profile|segments?)\b/, "foundation", "describes the customer"],
35
+ [/\b(vision|mission|tagline|values|manifesto|one[- ]pager|strategy)\b/, "foundation", "states what the venture is for"],
36
+ [/\b(interviews?|surveys?|user[- ]research|customer[- ]research|discovery|experiments?|hypothes[ie]s|validation)\b/, "validation", "is evidence about the problem or the solution"],
37
+ [/\b(investors?|pitch|deck|fundrais\w*|safe|term[- ]sheet|cap[- ]table|data[- ]room)\b/, "investors", "is for or about investors"],
38
+ [/\b(pricing|prices?|revenue|budget|forecast|runway|financ\w*|p&l|burn|unit[- ]economics|model)\b/, "finance", "is about money the venture plans or earns"],
39
+ [/\b(brand\w*|marketing|copy|landing|seo|social|launch|blog|newsletter|campaigns?|content|go[- ]to[- ]market|gtm)\b/, "marketing", "is marketing or sales"],
40
+ [/\b(roadmap|specs?|prd|requirements|features?|product|designs?|ux|ui|wireframes?|mockups?|backlog)\b/, "product", "describes the product"],
41
+ [/\b(team|hiring|roles?|org[- ]chart|founders?|equity|vesting|people|onboarding|handbook|culture)\b/, "people", "is about the people"],
42
+ [/\b(customers?|clients?|accounts|crm|leads|pipeline)\b/, "customers", "is about customers"],
43
+ [/\b(decisions?|adrs?|decision[- ]log)\b/, "decisions", "records decisions"],
44
+ [/\b(legal|contracts?|agreements?|incorporation|bylaws|operating[- ]agreement|nda|terms|privacy|trademark|ip)\b/, "_private/legal", "is a legal document, kept private so it never reaches a model"],
45
+ ];
46
+ const BANK = /\b(bank|transactions?|ledger|payroll|tax(es)?)\b/;
47
+
48
+ const words = (s) => s.toLowerCase().replace(/[_.]+/g, " ");
49
+ const sha = (f) => createHash("sha256").update(readFileSync(f)).digest("hex");
50
+ const slug = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "project";
51
+
52
+ /** Where one file goes, or why it stays behind. `rel` is relative to the project root. */
53
+ export function place(rel, bytes) {
54
+ const name = basename(rel, extname(rel));
55
+ const ext = extname(rel).toLowerCase();
56
+ if (bytes > MAX_BYTES) return { action: "leave", reason: `larger than ${MAX_BYTES / 1024 / 1024} MB; point to it instead` };
57
+ if (CODE.has(ext)) return { action: "leave", reason: "code or configuration: it stays in its repository" };
58
+ const folders = dirname(rel) === "." ? [] : dirname(rel).split(sep).reverse();
59
+ for (const [where, confidence] of [[name, "high"], ...folders.map((f) => [f, "low"])]) {
60
+ if (BANK.test(words(where))) return { action: "leave", reason: "bank and payroll data come from the bank connection, not from files" };
61
+ const hit = RULES.find(([re]) => re.test(words(where)));
62
+ if (hit) return { action: "port", to: `${hit[1]}/${basename(rel)}`, function: hit[1].split("/").at(-1), confidence, reason: `${confidence === "high" ? "its name" : `its folder ${where}`} ${hit[2]}` };
63
+ }
64
+ if (/^readme$/i.test(name)) return { action: "leave", reason: "the venture has its own AGENTS.md and profile.md; read this to write profile.md" };
65
+ return { action: "leave", reason: "nothing in its name or folders matches a package; place it by hand or migrate it" };
66
+ }
67
+
68
+ function walk(root, rel = "", out = { files: [], repos: [], secrets: [] }) {
69
+ for (const e of readdirSync(join(root, rel), { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
70
+ if (SKIP.has(e.name) || e.isSymbolicLink()) continue;
71
+ const r = rel ? join(rel, e.name) : e.name;
72
+ if (e.isDirectory()) {
73
+ if (REPO_MARKERS.some((m) => existsSync(join(root, r, m)))) out.repos.push(r);
74
+ else walk(root, r, out);
75
+ } else if (e.isFile() && SECRET.test(r)) out.secrets.push(r);
76
+ else if (e.isFile() && !e.name.startsWith(".")) out.files.push(r);
77
+ }
78
+ return out;
79
+ }
80
+
81
+ /** The plan for porting `from` into the venture at `dir`. Reads both, writes neither. */
82
+ export function plan(from, dir) {
83
+ const src = resolve(from);
84
+ if (!existsSync(src) || !statSync(src).isDirectory()) throw new Error(`${from} is not a directory`);
85
+ if (!existsSync(join(dir, "venture.json"))) throw new Error(`${dir} is not a venture: create one first with naive init`);
86
+ if (resolve(dir).startsWith(src + sep) || resolve(dir) === src) throw new Error("the venture cannot sit inside the project it ports from");
87
+ const { files, repos, secrets } = walk(src);
88
+ const items = secrets.map((f) => ({ from: f, action: "leave", reason: "looks like a secret, so it was never opened" }));
89
+ // The project itself is a repository when it carries a marker at its root: point to it, and still
90
+ // port its documents.
91
+ for (const r of REPO_MARKERS.some((m) => existsSync(join(src, m))) ? ["", ...repos] : repos)
92
+ items.push({ from: r || ".", action: "point", source: slug(r ? basename(r) : basename(src)), reason: "a code repository stays where it is; the venture points to it" });
93
+ const taken = new Set();
94
+ for (const f of files) {
95
+ const p = place(f, statSync(join(src, f)).size);
96
+ if (p.action === "port") {
97
+ // Two files with one name in one package: the second keeps its folder name in front.
98
+ if (taken.has(p.to)) p.to = `${dirname(p.to)}/${slug(basename(dirname(f)))}-${basename(f)}`;
99
+ if (taken.has(p.to) || existsSync(join(dir, p.to))) Object.assign(p, { action: "leave", reason: `${p.to} already exists in the venture; a port never overwrites` });
100
+ else taken.add(p.to);
101
+ }
102
+ items.push({ from: f, sha256: sha(join(src, f)), ...p });
103
+ }
104
+ const count = (a) => items.filter((i) => i.action === a).length;
105
+ return { from: src, venture: JSON.parse(readFileSync(join(dir, "venture.json"), "utf8")).id, at: new Date().toISOString(),
106
+ summary: { port: count("port"), point: count("point"), leave: count("leave") }, items };
107
+ }
108
+
109
+ /** Carries out a plan as the founder left it. Returns what was done. */
110
+ export function apply(dir, p, agent = { kind: "person", via: "cli" }) {
111
+ const src = p.from;
112
+ for (const i of p.items.filter((x) => x.action === "port")) {
113
+ if (!existsSync(join(src, i.from)) || sha(join(src, i.from)) !== i.sha256) throw new Error(`${i.from} changed since the plan was written; write the plan again`);
114
+ if (existsSync(join(dir, i.to))) throw new Error(`${i.to} already exists in the venture; a port never overwrites`);
115
+ }
116
+ const done = { ported: [], pointed: [] };
117
+ for (const i of p.items.filter((x) => x.action === "port")) {
118
+ mkdirSync(dirname(join(dir, i.to)), { recursive: true });
119
+ copyFileSync(join(src, i.from), join(dir, i.to));
120
+ record(dir, { entity: i.to, activity: "port", agent, derived_from: [`file://${join(src, i.from)}`], note: `ported unchanged: ${i.reason}` });
121
+ done.ported.push(i.to);
122
+ }
123
+ const points = p.items.filter((x) => x.action === "point");
124
+ if (points.length) {
125
+ const f = join(dir, "knowledge/sources.json");
126
+ const map = existsSync(f) ? JSON.parse(readFileSync(f, "utf8")) : { sources: [], records: {} };
127
+ for (const i of points) {
128
+ if (map.sources.some((s) => s.id === i.source)) continue;
129
+ map.sources.push({ id: i.source, connector: "filesystem", writes: "none", root: join(src, i.from === "." ? "" : i.from), note: `ported as a pointer: ${i.reason}` });
130
+ done.pointed.push(i.source);
131
+ }
132
+ mkdirSync(dirname(f), { recursive: true });
133
+ writeFileSync(f, JSON.stringify(map, null, 2) + "\n");
134
+ if (done.pointed.length) record(dir, { entity: "knowledge/sources.json", activity: "port", agent, note: `pointers to ${done.pointed.join(", ")}` });
135
+ }
136
+ return done;
137
+ }
138
+
139
+ if (import.meta.url === `file://${process.argv[1]}`) {
140
+ const args = process.argv.slice(2);
141
+ const opt = (k) => { const i = args.indexOf(`--${k}`); return i < 0 ? undefined : args[i + 1]; };
142
+ const dir = opt("venture");
143
+ if (!dir) { console.error("usage: node schema/port-venture.mjs --from <project> --venture <dir> | --venture <dir> --apply --confirm port"); process.exit(2); }
144
+ try {
145
+ if (args.includes("--apply")) {
146
+ if (opt("confirm") !== "port") { console.error("type --confirm port to carry out the plan"); process.exit(1); }
147
+ if (!existsSync(join(dir, PLAN))) { console.error(`no plan at ${join(dir, PLAN)}: run with --from first`); process.exit(1); }
148
+ const d = apply(dir, JSON.parse(readFileSync(join(dir, PLAN), "utf8")));
149
+ console.log(`ported ${d.ported.length} files unchanged; pointed to ${d.pointed.length} source${d.pointed.length === 1 ? "" : "s"}`);
150
+ } else {
151
+ const from = opt("from");
152
+ if (!from) { console.error("--from <project> is needed to write a plan"); process.exit(2); }
153
+ const p = plan(from, dir);
154
+ mkdirSync(join(dir, ".release"), { recursive: true });
155
+ writeFileSync(join(dir, PLAN), JSON.stringify(p, null, 2) + "\n");
156
+ for (const i of p.items) console.log(`${i.action.padEnd(5)} ${i.from}${i.to ? ` -> ${i.to}` : i.source ? ` -> source ${i.source}` : ""} (${i.reason})`);
157
+ console.log(`\n${p.summary.port} to port, ${p.summary.point} to point to, ${p.summary.leave} left behind. Nothing has changed yet.`);
158
+ console.log(`Read ${relative(process.cwd(), join(dir, PLAN))}, set any item's action to port, point or leave, then run with --apply --confirm port.`);
159
+ }
160
+ } catch (e) { console.error(e.message); process.exit(1); }
161
+ }