naive-framework 0.1.0 → 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 (254) hide show
  1. package/AGENTS.md +2 -1
  2. package/docs/decisions/decisions.json +27 -0
  3. package/docs/reference/ROUTES.md +36 -37
  4. package/governance/layer.json +2 -1
  5. package/governance/venture-template/roles/venture-roles.json +62 -0
  6. package/interface/acting.mjs +83 -0
  7. package/interface/adapters/claude-code.json +16 -0
  8. package/interface/adapters/codex.json +14 -0
  9. package/interface/adapters/cursor.json +16 -0
  10. package/interface/adapters.mjs +182 -0
  11. package/interface/api/server.mjs +4 -2
  12. package/interface/boundaries.mjs +218 -0
  13. package/interface/brand.mjs +214 -0
  14. package/interface/cli/freshness.mjs +59 -0
  15. package/interface/cli/guard.mjs +6 -0
  16. package/interface/cli/mentura.mjs +78 -8
  17. package/interface/cli/naive.mjs +33 -8
  18. package/interface/context.mjs +524 -0
  19. package/interface/demo/board.mjs +1 -1
  20. package/interface/dev/setup.mjs +84 -0
  21. package/interface/gate-hooks.mjs +36 -0
  22. package/interface/harness/evals.mjs +3 -3
  23. package/interface/harness/run.mjs +4 -4
  24. package/interface/instrumentation.mjs +86 -0
  25. package/interface/kit-boundary.mjs +73 -0
  26. package/interface/layer.json +8 -2
  27. package/interface/mcp/server.mjs +47 -7
  28. package/interface/package-routes.mjs +196 -0
  29. package/interface/provenance.mjs +24 -1
  30. package/interface/reads.mjs +173 -0
  31. package/interface/release-card.mjs +42 -0
  32. package/interface/router.mjs +101 -28
  33. package/interface/skills/naive-setup/SKILL.md +71 -0
  34. package/interface/skills/naive-setup/artifact.html +83 -0
  35. package/interface/vitals.mjs +115 -0
  36. package/interface/writes.mjs +190 -0
  37. package/knowledge/freshness.json +85 -0
  38. package/knowledge/layer.json +11 -3
  39. package/knowledge/templates/glossary.md +23 -0
  40. package/operations/layer.json +10 -3
  41. package/operations/templates/marketing-brand.md +46 -0
  42. package/operations/templates/public-assets.md +39 -0
  43. package/package.json +3 -1
  44. package/packages/catalog.json +8 -0
  45. package/packages/customers/package.json +21 -1
  46. package/packages/deals/package.json +27 -0
  47. package/packages/decisions/package.json +12 -1
  48. package/packages/finance/frames/fund-without-ceding-control.frame.json +177 -0
  49. package/packages/foundation/package.json +8 -1
  50. package/packages/fund/package.json +48 -0
  51. package/packages/marketing/package.json +10 -4
  52. package/packages/money/package.json +24 -3
  53. package/packages/validation/package.json +13 -0
  54. package/platform/README.md +6 -0
  55. package/platform/adapter.json +15 -0
  56. package/platform/integrations/remote-image.mjs +79 -0
  57. package/platform/integrations/rho.mjs +7 -6
  58. package/platform/kits/README.md +8 -1
  59. package/platform/kits/agent-upgrade/kit.json +15 -0
  60. package/platform/kits/agent-upgrade/run.mjs +82 -0
  61. package/platform/kits/agent-upgrade/stand-in-agent.mjs +32 -0
  62. package/platform/kits/validation-kickoff/kit.json +29 -0
  63. package/platform/webhooks/server.mjs +70 -0
  64. package/purpose/frameworks/idea-map/ideamap.mjs +4 -2
  65. package/schema/README.md +1 -0
  66. package/schema/access.mjs +57 -0
  67. package/schema/adapter.schema.json +33 -0
  68. package/schema/assets.mjs +212 -0
  69. package/schema/brand.mjs +373 -0
  70. package/schema/build-release.mjs +61 -0
  71. package/schema/caching.mjs +505 -0
  72. package/schema/check-assets.mjs +24 -0
  73. package/schema/check-brand.mjs +24 -0
  74. package/schema/check-config.mjs +110 -0
  75. package/schema/check-nextjs-status.mjs +3 -1
  76. package/schema/check-people.mjs +70 -0
  77. package/schema/check-sources.mjs +9 -1
  78. package/schema/data-model.json +334 -8
  79. package/schema/deal.schema.json +80 -0
  80. package/schema/decisions.mjs +7 -1
  81. package/schema/examples/frames/judge.mjs +10 -0
  82. package/schema/examples/venture-type/jev.mjs +12 -0
  83. package/schema/examples/workspace/ventures/acme-labs/AGENTS.md +17 -0
  84. package/schema/examples/workspace/ventures/acme-labs/accounts/.gitkeep +0 -0
  85. package/schema/examples/workspace/ventures/acme-labs/decisions/discovery-goal.decision.json +23 -0
  86. package/schema/examples/workspace/ventures/acme-labs/decisions/statement-icp.decision.json +22 -0
  87. package/schema/examples/workspace/ventures/acme-labs/decisions/statement-problem.decision.json +22 -0
  88. package/schema/examples/workspace/ventures/acme-labs/decisions/venture.team.decision.json +37 -0
  89. package/schema/examples/workspace/ventures/acme-labs/knowledge/README.md +3 -0
  90. package/schema/examples/workspace/ventures/acme-labs/knowledge/sources.json +46 -0
  91. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000001.json +12 -0
  92. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000002.json +12 -0
  93. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000003.json +12 -0
  94. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000004.json +12 -0
  95. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000005.json +12 -0
  96. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000006.json +12 -0
  97. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000007.json +12 -0
  98. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000008.json +12 -0
  99. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000009.json +12 -0
  100. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000010.json +12 -0
  101. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000011.json +12 -0
  102. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000012.json +12 -0
  103. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000013.json +12 -0
  104. package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000014.json +12 -0
  105. package/schema/examples/workspace/ventures/acme-labs/money/_streams/transactions/stream.json +5 -0
  106. package/schema/examples/workspace/ventures/acme-labs/money/_summary.json +30 -0
  107. package/schema/examples/workspace/ventures/acme-labs/operations/departments/customer-service/README.md +5 -0
  108. package/schema/examples/workspace/ventures/acme-labs/operations/departments/customer-service/department.json +5 -0
  109. package/schema/examples/workspace/ventures/acme-labs/operations/departments/finance/README.md +5 -0
  110. package/schema/examples/workspace/ventures/acme-labs/operations/departments/finance/department.json +5 -0
  111. package/schema/examples/workspace/ventures/acme-labs/operations/departments/human-capital/README.md +5 -0
  112. package/schema/examples/workspace/ventures/acme-labs/operations/departments/human-capital/department.json +5 -0
  113. package/schema/examples/workspace/ventures/acme-labs/operations/departments/it/README.md +5 -0
  114. package/schema/examples/workspace/ventures/acme-labs/operations/departments/it/department.json +5 -0
  115. package/schema/examples/workspace/ventures/acme-labs/operations/departments/marketing-and-sales/README.md +5 -0
  116. package/schema/examples/workspace/ventures/acme-labs/operations/departments/marketing-and-sales/department.json +5 -0
  117. package/schema/examples/workspace/ventures/acme-labs/operations/departments/products/README.md +5 -0
  118. package/schema/examples/workspace/ventures/acme-labs/operations/departments/products/department.json +5 -0
  119. package/schema/examples/workspace/ventures/acme-labs/operations/departments/strategy/README.md +5 -0
  120. package/schema/examples/workspace/ventures/acme-labs/operations/departments/strategy/department.json +5 -0
  121. package/schema/examples/workspace/ventures/acme-labs/people/founders/maya-chen.json +15 -0
  122. package/schema/examples/workspace/ventures/acme-labs/people/people.json +22 -0
  123. package/schema/examples/workspace/ventures/acme-labs/pillars/brand.md +5 -0
  124. package/schema/examples/workspace/ventures/acme-labs/pillars/business.md +5 -0
  125. package/schema/examples/workspace/ventures/acme-labs/pillars/product.md +5 -0
  126. package/schema/examples/workspace/ventures/acme-labs/products/.gitkeep +0 -0
  127. package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.core-product.decision.json +28 -0
  128. package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.exists.decision.json +38 -0
  129. package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.flagship.decision.json +27 -0
  130. package/schema/examples/workspace/ventures/acme-labs/profile.md +12 -0
  131. package/schema/examples/workspace/ventures/acme-labs/provenance.jsonl +12 -0
  132. package/schema/examples/workspace/ventures/acme-labs/raw/dump.md +6 -0
  133. package/schema/examples/workspace/ventures/acme-labs/venture.json +27 -0
  134. package/schema/examples/workspace/ventures/northstar/AGENTS.md +17 -0
  135. package/schema/examples/workspace/ventures/northstar/accounts/.gitkeep +0 -0
  136. package/schema/examples/workspace/ventures/northstar/deals/ductline.json +8 -0
  137. package/schema/examples/workspace/ventures/northstar/deals/kilnworks.json +14 -0
  138. package/schema/examples/workspace/ventures/northstar/decisions/venture.team.decision.json +31 -0
  139. package/schema/examples/workspace/ventures/northstar/evidence/README.md +3 -0
  140. package/schema/examples/workspace/ventures/northstar/fund/decisions/terms.decision.json +27 -0
  141. package/schema/examples/workspace/ventures/northstar/fund/decisions/terms.first-close.decision.json +27 -0
  142. package/schema/examples/workspace/ventures/northstar/fund/decisions/thesis.decision.json +26 -0
  143. package/schema/examples/workspace/ventures/northstar/fund/terms.json +22 -0
  144. package/schema/examples/workspace/ventures/northstar/fund/thesis.json +22 -0
  145. package/schema/examples/workspace/ventures/northstar/governance/README.md +3 -0
  146. package/schema/examples/workspace/ventures/northstar/governance/departments/external-relationships/charter.md +5 -0
  147. package/schema/examples/workspace/ventures/northstar/governance/departments/external-relationships/department.json +5 -0
  148. package/schema/examples/workspace/ventures/northstar/governance/departments/finance/charter.md +5 -0
  149. package/schema/examples/workspace/ventures/northstar/governance/departments/finance/department.json +5 -0
  150. package/schema/examples/workspace/ventures/northstar/governance/departments/human-capital/charter.md +5 -0
  151. package/schema/examples/workspace/ventures/northstar/governance/departments/human-capital/department.json +5 -0
  152. package/schema/examples/workspace/ventures/northstar/governance/departments/risk-and-compliance/charter.md +5 -0
  153. package/schema/examples/workspace/ventures/northstar/governance/departments/risk-and-compliance/department.json +5 -0
  154. package/schema/examples/workspace/ventures/northstar/governance/departments/strategy/charter.md +5 -0
  155. package/schema/examples/workspace/ventures/northstar/governance/departments/strategy/department.json +5 -0
  156. package/schema/examples/workspace/ventures/northstar/knowledge/README.md +3 -0
  157. package/schema/examples/workspace/ventures/northstar/operations/README.md +3 -0
  158. package/schema/examples/workspace/ventures/northstar/operations/departments/external-relationships/README.md +5 -0
  159. package/schema/examples/workspace/ventures/northstar/operations/departments/external-relationships/department.json +5 -0
  160. package/schema/examples/workspace/ventures/northstar/operations/departments/finance/README.md +5 -0
  161. package/schema/examples/workspace/ventures/northstar/operations/departments/finance/department.json +5 -0
  162. package/schema/examples/workspace/ventures/northstar/operations/departments/human-capital/README.md +5 -0
  163. package/schema/examples/workspace/ventures/northstar/operations/departments/human-capital/department.json +5 -0
  164. package/schema/examples/workspace/ventures/northstar/operations/departments/risk-and-compliance/README.md +5 -0
  165. package/schema/examples/workspace/ventures/northstar/operations/departments/risk-and-compliance/department.json +5 -0
  166. package/schema/examples/workspace/ventures/northstar/operations/departments/strategy/README.md +5 -0
  167. package/schema/examples/workspace/ventures/northstar/operations/departments/strategy/department.json +5 -0
  168. package/schema/examples/workspace/ventures/northstar/people/founders/ana-ruiz.json +13 -0
  169. package/schema/examples/workspace/ventures/northstar/people/founders/ben-okafor.json +7 -0
  170. package/schema/examples/workspace/ventures/northstar/people/people.json +27 -0
  171. package/schema/examples/workspace/ventures/northstar/pillars/brand.md +5 -0
  172. package/schema/examples/workspace/ventures/northstar/pillars/business.md +5 -0
  173. package/schema/examples/workspace/ventures/northstar/pillars/product.md +5 -0
  174. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/AGENTS.md +17 -0
  175. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/accounts/.gitkeep +0 -0
  176. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/decisions/venture.team.decision.json +31 -0
  177. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/knowledge/README.md +3 -0
  178. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/customer-service/README.md +5 -0
  179. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/customer-service/department.json +5 -0
  180. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/finance/README.md +5 -0
  181. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/finance/department.json +5 -0
  182. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/human-capital/README.md +5 -0
  183. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/human-capital/department.json +5 -0
  184. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/it/README.md +5 -0
  185. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/it/department.json +5 -0
  186. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/marketing-and-sales/README.md +5 -0
  187. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/marketing-and-sales/department.json +5 -0
  188. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/products/README.md +5 -0
  189. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/products/department.json +5 -0
  190. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/strategy/README.md +5 -0
  191. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/strategy/department.json +5 -0
  192. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/brand.md +5 -0
  193. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/business.md +5 -0
  194. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/product.md +5 -0
  195. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/.gitkeep +0 -0
  196. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.core-product.decision.json +28 -0
  197. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.exists.decision.json +32 -0
  198. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.flagship.decision.json +27 -0
  199. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/profile.md +5 -0
  200. package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/venture.json +27 -0
  201. package/schema/examples/workspace/ventures/northstar/products/.gitkeep +0 -0
  202. package/schema/examples/workspace/ventures/northstar/profile.md +5 -0
  203. package/schema/examples/workspace/ventures/northstar/provenance.jsonl +3 -0
  204. package/schema/examples/workspace/ventures/northstar/purpose/README.md +3 -0
  205. package/schema/examples/workspace/ventures/northstar/venture.json +49 -0
  206. package/schema/founder.schema.json +72 -0
  207. package/schema/frame.schema.json +240 -0
  208. package/schema/frames.mjs +228 -0
  209. package/schema/freshness-log.schema.json +40 -0
  210. package/schema/freshness-profiles.schema.json +44 -0
  211. package/schema/freshness.mjs +473 -0
  212. package/schema/fund-terms.schema.json +107 -0
  213. package/schema/fund-thesis.schema.json +87 -0
  214. package/schema/gate-drafts.mjs +130 -0
  215. package/schema/gate.mjs +105 -11
  216. package/schema/glossary.schema.json +25 -0
  217. package/schema/init-venture.mjs +38 -8
  218. package/schema/judgment.schema.json +38 -0
  219. package/schema/kit.schema.json +47 -0
  220. package/schema/kits.mjs +24 -0
  221. package/schema/knowledge-sources.schema.json +145 -15
  222. package/schema/layer.json +16 -3
  223. package/schema/marketing-brand.schema.json +116 -0
  224. package/schema/migrations/kit-to-package.mjs +94 -0
  225. package/schema/migrations/package-layout.mjs +86 -0
  226. package/schema/model-steps.mjs +717 -0
  227. package/schema/money-summary.schema.json +138 -0
  228. package/schema/naive-config.mjs +165 -0
  229. package/schema/naive-config.schema.json +268 -0
  230. package/schema/need-now.json +171 -0
  231. package/schema/need-now.mjs +3 -2
  232. package/schema/packages.mjs +10 -5
  233. package/schema/people.schema.json +86 -0
  234. package/schema/public-assets.schema.json +76 -0
  235. package/schema/release-read.mjs +111 -0
  236. package/schema/releases.mjs +497 -0
  237. package/schema/setup.mjs +164 -0
  238. package/schema/stale.mjs +111 -0
  239. package/schema/start-release.mjs +41 -0
  240. package/schema/structure.mjs +186 -0
  241. package/schema/systems-catalog.json +126 -0
  242. package/schema/systems-catalog.schema.json +78 -0
  243. package/schema/trigger.schema.json +44 -0
  244. package/schema/triggers.mjs +237 -0
  245. package/schema/upgrade-registry.schema.json +60 -0
  246. package/schema/upgrade-venture.mjs +96 -118
  247. package/schema/upgrades.json +69 -0
  248. package/schema/upgrades.mjs +385 -0
  249. package/schema/validate.py +19 -10
  250. package/schema/venture-role.schema.json +64 -0
  251. package/schema/venture-type.mjs +62 -0
  252. package/schema/venture-types.json +346 -0
  253. package/schema/venture-types.schema.json +129 -0
  254. package/schema/venture.schema.json +53 -0
@@ -390,6 +390,16 @@
390
390
  },
391
391
  "why": "Written by the interfaces on every write, so it costs nothing; run mentura baseline once to adopt records written before it (EE-031)"
392
392
  },
393
+ "naive-config": {
394
+ "base": {
395
+ "discovery": 0.1,
396
+ "validation": 0.2,
397
+ "beachhead": 0.3,
398
+ "scale": 0.4,
399
+ "platform": 0.4
400
+ },
401
+ "why": "Every default holds without it; write one only to change a default: a route that fails closed, a check that only warns, a pinned package"
402
+ },
393
403
  "knowledge-sources": {
394
404
  "base": {
395
405
  "discovery": 0.05,
@@ -410,6 +420,16 @@
410
420
  },
411
421
  "why": "Once one fact (a price, a product name, a plan's limits) is repeated in several places, such as a site, newsletters and a payment provider; before launch there is rarely more than one copy"
412
422
  },
423
+ "freshness-log": {
424
+ "base": {
425
+ "discovery": 0.2,
426
+ "validation": 0.4,
427
+ "beachhead": 0.6,
428
+ "scale": 0.7,
429
+ "platform": 0.8
430
+ },
431
+ "why": "Written by mentura revalidate, verify and phase; costs nothing until a fact changes outside the venture, a record is checked without changing it, or the venture changes phase or pivots"
432
+ },
413
433
  "department": {
414
434
  "base": {
415
435
  "discovery": 0.3,
@@ -537,6 +557,16 @@
537
557
  },
538
558
  "why": "What the founder walks away with; written at the end of each pipeline run, cheap to refresh"
539
559
  },
560
+ "release": {
561
+ "base": {
562
+ "discovery": 0.3,
563
+ "validation": 0.4,
564
+ "beachhead": 0.6,
565
+ "scale": 0.7,
566
+ "platform": 0.7
567
+ },
568
+ "why": "A release to hand someone (an investor, a partner, a hire): the confirmed records frozen in, with named live holes (C-11, I-17). Built with node schema/build-release.mjs when someone outside needs it"
569
+ },
540
570
  "customer": {
541
571
  "base": {
542
572
  "discovery": 0.2,
@@ -596,6 +626,147 @@
596
626
  "platform": 0.3
597
627
  },
598
628
  "why": "The text of a raw source, beside source.json (EE-070)."
629
+ },
630
+ "judgment": {
631
+ "base": {
632
+ "discovery": 0.05,
633
+ "validation": 0.05,
634
+ "beachhead": 0.05,
635
+ "scale": 0.05,
636
+ "platform": 0.05
637
+ },
638
+ "why": "Never written by hand: a judgment is what a package's model step answers when mentura steps run asks it, so there is nothing to suggest"
639
+ },
640
+ "people": {
641
+ "base": {
642
+ "discovery": 0.6,
643
+ "validation": 0.7,
644
+ "beachhead": 0.8,
645
+ "scale": 0.9,
646
+ "platform": 0.9
647
+ },
648
+ "why": "Who is in the venture and which functions each owns; create-venture writes it"
649
+ },
650
+ "founder": {
651
+ "base": {
652
+ "discovery": 0.5,
653
+ "validation": 0.6,
654
+ "beachhead": 0.7,
655
+ "scale": 0.7,
656
+ "platform": 0.7
657
+ },
658
+ "when": [
659
+ {
660
+ "if": "team:cofounders",
661
+ "at_least": 0.8
662
+ }
663
+ ],
664
+ "why": "One file per founder, written by create-venture; links to the founder agreement"
665
+ },
666
+ "fund-thesis": {
667
+ "base": {
668
+ "discovery": 0.0,
669
+ "validation": 0.0,
670
+ "beachhead": 0.0,
671
+ "scale": 0.0,
672
+ "platform": 0.0
673
+ },
674
+ "when": [
675
+ {
676
+ "if": "type:vc-fund",
677
+ "at_least": 0.9
678
+ }
679
+ ],
680
+ "why": "A fund's foundation: what it invests in and why it wins"
681
+ },
682
+ "fund-terms": {
683
+ "base": {
684
+ "discovery": 0.0,
685
+ "validation": 0.0,
686
+ "beachhead": 0.0,
687
+ "scale": 0.0,
688
+ "platform": 0.0
689
+ },
690
+ "when": [
691
+ {
692
+ "if": "type:vc-fund",
693
+ "at_least": 0.9
694
+ }
695
+ ],
696
+ "why": "What the fund raises under; LPs ask for it first"
697
+ },
698
+ "deal": {
699
+ "base": {
700
+ "discovery": 0.0,
701
+ "validation": 0.0,
702
+ "beachhead": 0.0,
703
+ "scale": 0.0,
704
+ "platform": 0.0
705
+ },
706
+ "when": [
707
+ {
708
+ "if": "type:vc-fund",
709
+ "phase": "validation",
710
+ "at_least": 0.7
711
+ },
712
+ {
713
+ "if": "type:vc-fund",
714
+ "phase": "beachhead",
715
+ "at_least": 0.9
716
+ },
717
+ {
718
+ "if": "type:vc-fund",
719
+ "phase": "scale",
720
+ "at_least": 0.9
721
+ }
722
+ ],
723
+ "why": "A fund's pipeline, once it is investing"
724
+ },
725
+ "money-summary": {
726
+ "base": {
727
+ "discovery": 0.1,
728
+ "validation": 0.3,
729
+ "beachhead": 0.6,
730
+ "scale": 0.8,
731
+ "platform": 0.8
732
+ },
733
+ "when": [
734
+ {
735
+ "if": "funding:venture-capital",
736
+ "at_least": 0.6
737
+ }
738
+ ],
739
+ "why": "Written by the money source's sync; cash and runway once money moves"
740
+ },
741
+ "marketing-brand": {
742
+ "base": {
743
+ "discovery": 0.2,
744
+ "validation": 0.4,
745
+ "beachhead": 0.7,
746
+ "scale": 0.8,
747
+ "platform": 0.8
748
+ },
749
+ "why": "One brand every agent and interface reads (colors, licensed typefaces, voice rules, marks), once the venture shows itself in public"
750
+ },
751
+ "public-assets": {
752
+ "base": {
753
+ "discovery": 0.2,
754
+ "validation": 0.4,
755
+ "beachhead": 0.7,
756
+ "scale": 0.8,
757
+ "platform": 0.8
758
+ },
759
+ "why": "The source, license and credit of every file the venture ships as it is, before anything with rights attached is published"
760
+ },
761
+ "glossary": {
762
+ "base": {
763
+ "discovery": 0.1,
764
+ "validation": 0.3,
765
+ "beachhead": 0.5,
766
+ "scale": 0.6,
767
+ "platform": 0.7
768
+ },
769
+ "why": "A package's own terms, once two packages start using one word in different senses"
599
770
  }
600
771
  }
601
772
  }
@@ -3,7 +3,8 @@
3
3
  // type and phase are in schema/need-now.json; facts about the venture raise or lower them:
4
4
  // phase, ambition, funding, legal_form, offering (of any product), software (any product),
5
5
  // path (go-to-market record), people, founders, agents, products (counts), publishes (a handoff
6
- // under public-commitment), team (the answer to Naive's team question: solo, cofounders, looking).
6
+ // under public-commitment), team (the answer to Naive's team question: solo, cofounders, looking),
7
+ // type (the venture type, EE-082).
7
8
  // Departments (EE-047) are scored the same way, from their priors in operations/departments.json, and
8
9
  // held once venture.json lists them. Records that already exist are listed as held; a record in a layer the venture has turned off is
9
10
  // listed as layer off, not suggested. Jev re-scores the priors per venture once the
@@ -37,7 +38,7 @@ export function factsOf(dir) {
37
38
  const td = existsSync(teamFile) ? load(teamFile) : null;
38
39
  const team = td?.status === "decided" ? ["solo", "cofounders", "looking"].find((t) => (td.answer ?? "").toLowerCase().startsWith(t)) ?? null : null;
39
40
  return {
40
- team, phase: v.phase, ambition: v.ambition, funding: v.form?.funding, legal_form: v.form?.legal_form,
41
+ team, type: v.type ?? null, phase: v.phase, ambition: v.ambition, funding: v.form?.funding, legal_form: v.form?.legal_form,
41
42
  offering: products.map((p) => p.offering), software: products.some((p) => p.software),
42
43
  path: json("purpose/validation/go-to-market.json")?.path,
43
44
  people: members.filter((m) => m.kind !== "agent").length + (v.owner === "self" && !members.some((m) => m.kind !== "agent") ? 1 : 0),
@@ -29,6 +29,8 @@ import { confirmedIn, filesOf } from "./foundation.mjs";
29
29
  import { route } from "../purpose/frameworks/idea-map/route.mjs";
30
30
 
31
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";
32
34
 
33
35
  const repo = new URL("..", import.meta.url).pathname;
34
36
  const load = (p) => JSON.parse(readFileSync(p, "utf8"));
@@ -107,6 +109,9 @@ export function packages(dir, { flags = {}, answers = null } = {}) {
107
109
  const v = load(join(dir, "venture.json"));
108
110
  const { phase, facts, questions } = situation(dir, { flags, answers });
109
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);
110
115
  let routes = null;
111
116
  try { routes = route(dir); } catch { routes = null; }
112
117
  const dest = new Map((routes?.destinations ?? []).map((d) => [d.id, d]));
@@ -126,20 +131,20 @@ export function packages(dir, { flags = {}, answers = null } = {}) {
126
131
  moves: s.status === "confirmed" ? "done" : waits.length ? "waits" : "now", ...(waits.length && s.status !== "confirmed" ? { waits_on: waits, waits_on_titles: waits.map(titleOf) } : {}),
127
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 } } : {}) };
128
133
  };
129
- const core = Object.entries(PACKAGES.core).filter(([, p]) => !p.not_modeled).map(([id, p]) => {
134
+ const core = Object.entries(PACKAGES.core).filter(([id, p]) => !p.not_modeled || early.has(id)).map(([id, p]) => {
130
135
  const records = [...p.required.map((t) => row(t, "required")), ...p.optional.map((t) => row(t, "optional")), ...p.refs.map((t) => row(t, "reads"))];
131
136
  const gate = records.filter((r) => r.role !== "optional");
132
137
  const weight = (r) => (r.role === "optional" ? 0.5 : 1);
133
138
  const progress = r2(records.reduce((s, r) => s + STATUS[r.status] * weight(r), 0) / records.reduce((s, r) => s + weight(r), 0));
134
139
  const state = gate.every((r) => r.status === "confirmed") ? "complete" : gate.every((r) => r.status !== "missing") ? "review" : "building";
135
- return { kind: "core", id, title: p.title, department: p.department, purpose: p.purpose, ...fitOf(p), state, progress, records, planned: p.planned, unlocks: p.unlocks,
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,
136
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),
137
142
  moving: records.filter((r) => r.moves === "now" && r.role !== "reads").map((r) => r.record) };
138
143
  });
139
144
  const byId = Object.fromEntries(core.map((p) => [p.id, p]));
140
- const handoff = Object.entries(PACKAGES.handoff).filter(([, p]) => !p.not_modeled).map(([id, p]) => {
145
+ const handoff = Object.entries(PACKAGES.handoff).filter(([id, p]) => !p.not_modeled || early.has(id)).map(([id, p]) => {
141
146
  const from = p.from.map((c) => byId[c]).filter(Boolean);
142
- return { kind: "handoff", id, title: p.title, for: p.for, from: p.from, ...fitOf(p), state: from.every((c) => c.state === "complete") ? "complete" : "building",
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",
143
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 };
144
149
  });
145
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;
@@ -149,7 +154,7 @@ export function packages(dir, { flags = {}, answers = null } = {}) {
149
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 })) },
150
155
  progress: open.length ? r2(open.reduce((s, p) => s + p.progress, 0) / open.length) : 0,
151
156
  complete: [...core, ...handoff].filter((p) => p.in === "now" && p.state === "complete").map((p) => p.id),
152
- core, handoff, assumes: PACKAGES.assumes, not_modeled: [...Object.entries(PACKAGES.core), ...Object.entries(PACKAGES.handoff)].filter(([, p]) => p.not_modeled).map(([id, p]) => ({ id, title: p.title, why: p.not_modeled })),
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 })),
153
158
  enhancements: PACKAGES.enhancements,
154
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 } };
155
160
  }
@@ -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,76 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "public-assets.schema.json",
4
+ "title": "Public assets",
5
+ "description": "The register of what the venture ships as it is, at public/assets.json (I-23, J-2, J-3, J-4): each file in public/ with its source, license and credit, facts read by code from its bytes, and alt text with who wrote it; remote images as links with a note in raw/sources/<id>/; and remote_hosts, the hosts an agent may fetch from. Checked by schema/check-assets.mjs. Version 0.x, unevaluated.",
6
+ "type": "object",
7
+ "required": ["version", "assets"],
8
+ "additionalProperties": false,
9
+ "$defs": {
10
+ "alt": {
11
+ "type": "object",
12
+ "required": ["text", "by"],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "text": { "type": "string", "minLength": 1 },
16
+ "by": { "enum": ["agent", "person"], "description": "Who wrote it. An agent's alt text stays pending until a person confirms it in provenance" }
17
+ }
18
+ },
19
+ "facts": {
20
+ "type": "object",
21
+ "required": ["type", "bytes", "sha256"],
22
+ "additionalProperties": false,
23
+ "description": "Read from the bytes by code (schema/assets.mjs), never written by hand",
24
+ "properties": {
25
+ "type": { "type": "string" },
26
+ "width": { "type": "integer" },
27
+ "height": { "type": "integer" },
28
+ "sizes": { "type": "array", "items": { "type": "string" } },
29
+ "bytes": { "type": "integer" },
30
+ "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
31
+ "filled_at": { "type": "string" }
32
+ }
33
+ }
34
+ },
35
+ "properties": {
36
+ "version": { "type": "string" },
37
+ "remote_hosts": { "type": "array", "items": { "type": "string" }, "description": "Hosts an agent may fetch images from (exact, or *.example.com); the platform fetcher refuses any other" },
38
+ "assets": {
39
+ "type": "array",
40
+ "items": {
41
+ "type": "object",
42
+ "required": ["path", "source", "license"],
43
+ "additionalProperties": false,
44
+ "properties": {
45
+ "path": { "type": "string", "pattern": "^public/(?!.*\\.\\./).+" },
46
+ "source": { "type": "string", "description": "Where it came from: who made it, or a URL" },
47
+ "license": { "type": "string", "description": "An SPDX id (CC-BY-4.0, OFL-1.1), owned (made by or for the venture), licensed (bought), or the restriction (all-rights-reserved)" },
48
+ "credit": { "type": "string", "description": "Who to credit; a missing credit fails the check" },
49
+ "alt": { "$ref": "#/$defs/alt" },
50
+ "decorative": { "type": "boolean", "description": "An image that says nothing, so it needs no alt text" },
51
+ "origin_url": { "type": "string", "description": "The remote work this is a copy of" },
52
+ "design_system": { "type": "string", "description": "The design system (brand design_systems id) this came from" },
53
+ "facts": { "$ref": "#/$defs/facts" }
54
+ }
55
+ }
56
+ },
57
+ "remote": {
58
+ "type": "array",
59
+ "description": "Remote images the venture links to rather than ships",
60
+ "items": {
61
+ "type": "object",
62
+ "required": ["id", "url", "license"],
63
+ "additionalProperties": false,
64
+ "properties": {
65
+ "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$", "description": "The raw source holding the note: raw/sources/<id>/" },
66
+ "url": { "type": "string" },
67
+ "license": { "type": "string" },
68
+ "credit": { "type": "string" },
69
+ "alt": { "$ref": "#/$defs/alt" },
70
+ "fetched": { "$ref": "#/$defs/facts", "description": "Facts from a fetch by the platform; the original stays private in raw/sources/<id>/original.*" },
71
+ "copy": { "type": "string", "pattern": "^public/", "description": "Where a full copy was kept, only when the license allows it" }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,111 @@
1
+ // Reading a release without the router (C-12, I-17). A release is the venture's static shell
2
+ // (C-11): the confirmed records frozen in, and named holes for what stays live. Everything here
3
+ // reads <venture>/.release/ and nothing else, so a release can be read after the venture's records
4
+ // change, on a machine with no router, or handed to an investor as files. It never imports
5
+ // interface/router.mjs; schema/releases-test.mjs checks that.
6
+ //
7
+ // The answer to a path is { status, type, body }:
8
+ // / the release index: venture, phase, release id, routes in the release, holes
9
+ // /release.json the manifest; /card.json the release card's data (P-25, O-7)
10
+ // /records/<file> one frozen record, as it was when it was confirmed
11
+ // /<route> a route as the release holds it: a frozen record, a collection's frozen items,
12
+ // a frozen command answer (H-4), or a hole that names where to read it live.
13
+ // An item the release does not hold answers 404 with the items it does and the
14
+ // command that adds it without rebuilding the rest (C-18, N-10).
15
+ // Any method other than GET or HEAD answers 405: a release is read-only.
16
+
17
+ import { existsSync, readFileSync } from "node:fs";
18
+ import { join, normalize } from "node:path";
19
+
20
+ export const RELEASE_DIR = ".release";
21
+ export const MANIFEST = ".release/release.json";
22
+ export const CARD = ".release/card.json";
23
+ export const RECORDS = ".release/records";
24
+
25
+ /** The release manifest of a venture, or null when it has none. */
26
+ export function readRelease(dir) {
27
+ const f = join(dir, MANIFEST);
28
+ return existsSync(f) ? JSON.parse(readFileSync(f, "utf8")) : null;
29
+ }
30
+
31
+ /** The frozen copy of one record in a release, as text, or null. */
32
+ export function frozenText(dir, file) {
33
+ const rel = normalize(file);
34
+ if (rel.startsWith("..") || rel.startsWith("/")) return null;
35
+ const f = join(dir, RECORDS, rel);
36
+ return existsSync(f) ? readFileSync(f, "utf8") : null;
37
+ }
38
+
39
+ const parse = (file, text) => file.endsWith(".json") ? JSON.parse(text) : text;
40
+ const json = (status, body) => ({ status, type: "application/json; charset=utf-8", body: JSON.stringify(body, null, 2) + "\n" });
41
+
42
+ /** The index a reader starts from. */
43
+ export function index(m) {
44
+ return { release: m.release, venture: m.venture, name: m.name, phase: m.phase, built_at: m.built_at, now: m.now,
45
+ routes: m.routes.filter((r) => r.in === "release").map((r) => r.route),
46
+ holes: m.holes.map((h) => ({ kind: h.kind, route: h.route, name: h.name, why: h.why })),
47
+ card: "/card.json", manifest: "/release.json",
48
+ note: "A release is read-only. Holes stay live: read them in the venture through the router." };
49
+ }
50
+
51
+ /** What a route holds in a release: { status, body }. Matches a concrete route (product/kettle) to its entry. */
52
+ export function resolveRoute(dir, m, route) {
53
+ route = route.replace(/^\/+|\/+$/g, "");
54
+ const exact = m.routes.find((r) => r.route === route);
55
+ const entry = exact ?? m.routes.find((r) => r.route.endsWith("/[id]") && route.startsWith(r.route.slice(0, -4)) && !route.slice(r.route.length - 4).includes("/"));
56
+ if (!entry) return { status: 404, body: { error: `no route ${route} in release ${m.release}` } };
57
+ const id = exact ? null : route.slice(entry.route.length - 4);
58
+ const holes = m.holes.filter((h) => h.route === route || h.route_template === entry.route);
59
+ // A decision is also found by its id (decisions/founding-team), whatever its file is called.
60
+ const own = holes.find((h) => (h.route === route || (h.kind === "decision" && `decisions/${h.name}` === route)) && h.kind !== "attribute");
61
+ if (entry.in === "hole") return { status: 200, body: { route, hole: true, kind: own?.kind ?? entry.kind, why: own?.why ?? entry.why, live: own?.live ?? entry.live ?? null, ...(own ? {} : { holes }) } };
62
+ if (entry.in === "left out") return { status: 404, body: { route, left_out: true, why: entry.why } };
63
+ if (entry.kind === "command") {
64
+ const out = m.commands?.[entry.route];
65
+ return out === undefined ? { status: 404, body: { route, empty: true, why: entry.why ?? "not in this release" } } : { status: 200, body: { route, frozen: true, built_from: out.built_from, result: out.result } };
66
+ }
67
+ const recs = m.records.filter((r) => r.route_template === entry.route);
68
+ const fieldHoles = (r) => m.holes.filter((h) => h.kind === "attribute" && h.file === r.file).map((h) => h.field);
69
+ const one = (r) => ({ file: r.file, as_of: r.as_of, confirmed_by: r.confirmed_by, ...(fieldHoles(r).length ? { live_fields: fieldHoles(r) } : {}), record: parse(r.file, frozenText(dir, r.file)) });
70
+ if (entry.collection === "list") {
71
+ const items = m.records.filter((r) => r.route_template === `${entry.route}/[id]`);
72
+ return { status: 200, body: { route, items: Object.fromEntries(items.map((r) => [r.id, one(r)])), holes } };
73
+ }
74
+ if (entry.collection === "item") {
75
+ const hit = recs.find((r) => r.id === id);
76
+ if (own) return { status: 200, body: { route, hole: true, kind: own.kind, why: own.why, live: own.live ?? null } };
77
+ if (!hit) return { status: 404, body: { route, not_in_release: true, release: m.release, items: recs.map((r) => r.id), ...(holes.length ? { live_items: holes.filter((h) => h.kind !== "attribute").map((h) => h.name) } : {}),
78
+ note: `${route} was not known when release ${m.release} was built`, add: `node schema/build-release.mjs <venture dir> --add ${route}` } };
79
+ return { status: 200, body: { route, ...one(hit) } };
80
+ }
81
+ if (!recs.length) return { status: 404, body: { route, empty: true, why: entry.why ?? "no confirmed record when the release was built" } };
82
+ return { status: 200, body: { route, ...(recs.length === 1 ? one(recs[0]) : { records: recs.map(one) }) } };
83
+ }
84
+
85
+ /**
86
+ * Answers one request against a venture's release. draw, when given, turns the card's data into an
87
+ * image (the interface's job, O-7): draw(card) -> SVG text.
88
+ */
89
+ export function answer(dir, method, path, { draw } = {}) {
90
+ if (method !== "GET" && method !== "HEAD") return { ...json(405, { error: "a release is read-only: only GET and HEAD" }), allow: "GET, HEAD" };
91
+ const m = readRelease(dir);
92
+ if (!m) return json(503, { error: `no release in ${dir}: run node schema/build-release.mjs ${dir} first` });
93
+ const p = decodeURIComponent(path.split("?")[0]);
94
+ if (p.split("/").includes("..")) return json(400, { error: "no .. in a release path" });
95
+ if (p === "/" || p === "") return json(200, index(m));
96
+ if (p === "/release.json") return json(200, m);
97
+ if (p === "/card.json") return existsSync(join(dir, CARD)) ? json(200, JSON.parse(readFileSync(join(dir, CARD), "utf8"))) : json(404, { error: "this release has no card" });
98
+ if (p === "/card.svg") {
99
+ if (!draw) return json(404, { error: "no card drawing here" });
100
+ return { status: 200, type: "image/svg+xml; charset=utf-8", body: draw(JSON.parse(readFileSync(join(dir, CARD), "utf8"))) };
101
+ }
102
+ if (p.startsWith("/records/")) {
103
+ const file = p.slice("/records/".length);
104
+ const r = m.records.find((x) => x.file === file);
105
+ const text = r ? frozenText(dir, file) : null;
106
+ if (text === null) return json(404, { error: `${file} is not in release ${m.release}` });
107
+ return { status: 200, type: file.endsWith(".json") ? "application/json; charset=utf-8" : "text/markdown; charset=utf-8", body: text };
108
+ }
109
+ const r = resolveRoute(dir, m, p);
110
+ return json(r.status, r.body);
111
+ }