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.
- package/AGENTS.md +62 -0
- package/LICENSE +21 -0
- package/README.md +37 -2
- package/docs/decisions/decisions.json +888 -0
- package/docs/ontology.json +796 -0
- package/docs/ontology.md +163 -0
- package/docs/reference/ROUTES.md +124 -0
- package/evidence/benchmarks/2026-10-27-golden.jev.after-catalog-fix.json +558 -0
- package/evidence/benchmarks/2026-10-27-golden.jev.json +501 -0
- package/evidence/benchmarks/2026-10-27-golden.reasoning-answers.json +177 -0
- package/evidence/benchmarks/JEV_VS_REASONING_MODEL_2026-10-27.md +68 -0
- package/evidence/capabilities/agent-capabilities.json +86 -0
- package/evidence/design-documents.registry.json +2896 -0
- package/evidence/evals/evals.json +25 -0
- package/evidence/evals/harness-evals.json +140 -0
- package/evidence/layer.json +51 -0
- package/evidence/skills/agent-capabilities/SKILL.md +35 -0
- package/evidence/skills/design-coverage/SKILL.md +57 -0
- package/evidence/skills/design-coverage/check.mjs +192 -0
- package/evidence/skills/design-coverage/scan.mjs +45 -0
- package/evidence/skills/fidelity-ladder-audit/SKILL.md +121 -0
- package/evidence/skills/fidelity-ladder-audit/ladder-census.mjs +180 -0
- package/evidence/skills/findability/SKILL.md +32 -0
- package/evidence/skills/findability/inventory.rb +41 -0
- package/evidence/skills/foreshadowing-audit/SKILL.md +183 -0
- package/evidence/skills/metrics-review/SKILL.md +177 -0
- package/evidence/tooling/integrations.json +153 -0
- package/governance/layer.json +102 -0
- package/governance/references/references.json +26 -0
- package/governance/skills/board-design/SKILL.md +68 -0
- package/governance/skills/brand-pillar/SKILL.md +90 -0
- package/governance/skills/business-pillar/SKILL.md +96 -0
- package/governance/skills/chief-of-staff/SKILL.md +45 -0
- package/governance/skills/cofounder-structure/SKILL.md +64 -0
- package/governance/skills/cross-pillar-tradeoff/SKILL.md +168 -0
- package/governance/skills/equity-and-share-classes/SKILL.md +68 -0
- package/governance/skills/executive-roles/SKILL.md +95 -0
- package/governance/skills/exit-planning/SKILL.md +66 -0
- package/governance/skills/financing-and-investor-rights/SKILL.md +73 -0
- package/governance/skills/office-hours-mode/SKILL.md +113 -0
- package/governance/skills/product-pillar/SKILL.md +81 -0
- package/governance/skills/publication-policy/SKILL.md +63 -0
- package/governance/skills/role-and-candidate-authoring/SKILL.md +198 -0
- package/governance/skills/stakeholder-update/SKILL.md +177 -0
- package/governance/tooling/integrations.json +37 -0
- package/governance/venture-template/AGENT_ROLES_AND_DECISION_RIGHTS.md +58 -0
- package/governance/venture-template/COMPANY_VAULT_DEFINITION_2026-10-25.md +204 -0
- package/governance/venture-template/README.md +74 -0
- package/governance/venture-template/decision-rights.json +186 -0
- package/governance/venture-template/index.md +151 -0
- package/governance/venture-template/pillars/brand.md +209 -0
- package/governance/venture-template/pillars/business.md +255 -0
- package/governance/venture-template/pillars/product.md +254 -0
- package/governance/venture-template/render-roles.py +11 -0
- package/governance/venture-template/roles/README.md +85 -0
- package/governance/venture-template/roles/agent-roles.json +202 -0
- package/governance/venture-template/roles/ceo.md +163 -0
- package/governance/venture-template/roles/chief-of-staff.md +153 -0
- package/governance/venture-template/roles/cmo.md +165 -0
- package/governance/venture-template/roles/coo.md +189 -0
- package/governance/venture-template/roles/cto.md +158 -0
- package/governance/venture-template/roles/department-head.md +47 -0
- package/governance/venture-template/roles/forward-deployed-engineer.md +51 -0
- package/governance/venture-template/roles/founder.md +173 -0
- package/governance/venture-template/roles/hr-manager.md +49 -0
- package/governance/venture-template/roles/talent-acquisition-manager.md +50 -0
- package/governance/venture-template/roles/venture-roles.json +62 -0
- package/interface/acting.mjs +83 -0
- package/interface/adapters/claude-code.json +16 -0
- package/interface/adapters/codex.json +14 -0
- package/interface/adapters/cursor.json +16 -0
- package/interface/adapters.mjs +182 -0
- package/interface/api/server.mjs +71 -0
- package/interface/boundaries.mjs +218 -0
- package/interface/brand.mjs +214 -0
- package/interface/cli/find-venture.mjs +15 -0
- package/interface/cli/freshness.mjs +59 -0
- package/interface/cli/guard.mjs +6 -0
- package/interface/cli/mentura.mjs +341 -0
- package/interface/cli/naive.mjs +194 -0
- package/interface/context.mjs +524 -0
- package/interface/demo/board.mjs +581 -0
- package/interface/demo/decision-harness.mjs +91 -0
- package/interface/demo/live-agent.mjs +47 -0
- package/interface/dev/setup.mjs +84 -0
- package/interface/gate-hooks.mjs +36 -0
- package/interface/harness/evals.mjs +90 -0
- package/interface/harness/examples/pt-no-shows.dump.md +19 -0
- package/interface/harness/run.mjs +313 -0
- package/interface/harness/site.mjs +59 -0
- package/interface/instrumentation.mjs +86 -0
- package/interface/kit-boundary.mjs +73 -0
- package/interface/layer.json +37 -0
- package/interface/mcp/server.mjs +162 -0
- package/interface/operator-console/README.md +58 -0
- package/interface/package-routes.mjs +196 -0
- package/interface/provenance.mjs +65 -0
- package/interface/reads.mjs +173 -0
- package/interface/references/references.json +28 -0
- package/interface/release-card.mjs +42 -0
- package/interface/route-aliases.json +32 -0
- package/interface/router.mjs +653 -0
- package/interface/skills/install-mentura/SKILL.md +88 -0
- package/interface/skills/naive-setup/SKILL.md +71 -0
- package/interface/skills/naive-setup/artifact.html +83 -0
- package/interface/tooling/integrations.json +112 -0
- package/interface/vitals.mjs +115 -0
- package/interface/writes.mjs +190 -0
- package/knowledge/connectors/README.md +54 -0
- package/knowledge/connectors/catalog.mjs +118 -0
- package/knowledge/connectors/contract.mjs +56 -0
- package/knowledge/connectors/eval.mjs +176 -0
- package/knowledge/connectors/filesystem.mjs +79 -0
- package/knowledge/connectors/index.mjs +102 -0
- package/knowledge/connectors/resolve.mjs +44 -0
- package/knowledge/connectors/suite.mjs +80 -0
- package/knowledge/freshness.json +85 -0
- package/knowledge/layer.json +50 -0
- package/knowledge/skills/find-reference/SKILL.md +38 -0
- package/knowledge/skills/industry-awareness/SKILL.md +277 -0
- package/knowledge/templates/glossary.md +23 -0
- package/knowledge/tooling/integrations.json +127 -0
- package/knowledge/tooling/questions.md +46 -0
- package/operations/FOUNDER_OPERATING_MODEL_CAMPAIGN_2026-10-14.md +16 -0
- package/operations/departments.json +162 -0
- package/operations/handoff-v2.md +93 -0
- package/operations/layer.json +67 -0
- package/operations/marketing/check-public.mjs +68 -0
- package/operations/marketing/site/README.md +86 -0
- package/operations/marketing/site/matrix.json +731 -0
- package/operations/marketing/site/plan.mjs +117 -0
- package/operations/marketing/site/presence.mjs +252 -0
- package/operations/references/references.json +45 -0
- package/operations/skills/recruiting/SKILL.md +32 -0
- package/operations/skills/team-design/SKILL.md +36 -0
- package/operations/skills/tool-selection/SKILL.md +46 -0
- package/operations/templates/marketing-brand.md +46 -0
- package/operations/templates/public-assets.md +39 -0
- package/operations/templates/recruiting-brief.md +35 -0
- package/operations/tooling/integrations.json +158 -0
- package/package.json +59 -4
- package/packages/catalog.json +280 -0
- package/packages/cofounder/package.json +42 -0
- package/packages/counsel/package.json +47 -0
- package/packages/customers/package.json +41 -0
- package/packages/deals/package.json +27 -0
- package/packages/decisions/package.json +28 -0
- package/packages/engineering/package.json +41 -0
- package/packages/evidence/package.json +17 -0
- package/packages/finance/frames/fund-without-ceding-control.frame.json +177 -0
- package/packages/finance/package.json +48 -0
- package/packages/foundation/package.json +59 -0
- package/packages/fund/package.json +48 -0
- package/packages/investor/package.json +57 -0
- package/packages/investors/package.json +21 -0
- package/packages/legal/package.json +73 -0
- package/packages/marketing/package.json +63 -0
- package/packages/money/package.json +42 -0
- package/packages/operations/package.json +74 -0
- package/packages/partner/package.json +38 -0
- package/packages/people/package.json +64 -0
- package/packages/product/package.json +49 -0
- package/packages/raw/package.json +19 -0
- package/packages/relationships/package.json +52 -0
- package/packages/validation/package.json +112 -0
- package/platform/README.md +51 -0
- package/platform/adapter.json +15 -0
- package/platform/connectors/eval.mjs +154 -0
- package/platform/connectors/fake-github.mjs +91 -0
- package/platform/connectors/github.mjs +105 -0
- package/platform/integrations/jev.mjs +30 -0
- package/platform/integrations/langsmith-docket.mjs +53 -0
- package/platform/integrations/langsmith-setup.mjs +115 -0
- package/platform/integrations/langsmith.mjs +47 -0
- package/platform/integrations/remote-image.mjs +79 -0
- package/platform/integrations/rho.mjs +146 -0
- package/platform/integrations/site.mjs +75 -0
- package/platform/kits/README.md +14 -0
- package/platform/kits/agent-upgrade/kit.json +15 -0
- package/platform/kits/agent-upgrade/run.mjs +82 -0
- package/platform/kits/agent-upgrade/stand-in-agent.mjs +32 -0
- package/platform/kits/validation-kickoff/kit.json +29 -0
- package/platform/mcp/research.mjs +64 -0
- package/platform/webhooks/server.mjs +70 -0
- package/purpose/checklists/vault-and-tooling-consultancy-setup.md +216 -0
- package/purpose/frameworks/business-discovery-framework-amendments-2026-05-20.md +181 -0
- package/purpose/frameworks/business-discovery-framework.html +938 -0
- package/purpose/frameworks/business-discovery-framework.md +326 -0
- package/purpose/frameworks/idea-map/README.md +74 -0
- package/purpose/frameworks/idea-map/conventions.json +146 -0
- package/purpose/frameworks/idea-map/graph.mjs +182 -0
- package/purpose/frameworks/idea-map/ideamap.mjs +181 -0
- package/purpose/frameworks/idea-map/route.mjs +140 -0
- package/purpose/frameworks/onboarding-handoff-framework.md +269 -0
- package/purpose/frameworks/post-discovery-deliverable-playbook.md +274 -0
- package/purpose/frameworks/product-anatomy/README.md +63 -0
- package/purpose/frameworks/product-anatomy/anatomy.mjs +195 -0
- package/purpose/frameworks/product-anatomy/examples/polity.answers.reasoned.json +11 -0
- package/purpose/frameworks/product-anatomy/examples/polity.json +89 -0
- package/purpose/frameworks/product-anatomy/phases.json +107 -0
- package/purpose/frameworks/product-anatomy/questions.json +74 -0
- package/purpose/kits/validation/README.md +14 -0
- package/purpose/kits/validation/references/references.json +122 -0
- package/purpose/kits/validation/skills/problem-validation/SKILL.md +43 -0
- package/purpose/kits/validation/skills/validation-score/SKILL.md +35 -0
- package/purpose/kits/validation/templates/go-to-market.md +19 -0
- package/purpose/kits/validation/templates/operations-readiness.md +20 -0
- package/purpose/kits/validation/templates/pricing.md +22 -0
- package/purpose/kits/validation/templates/problem-interview.md +36 -0
- package/purpose/kits/validation/templates/problem.md +45 -0
- package/purpose/kits/validation/templates/product-market-fit.md +23 -0
- package/purpose/kits/validation/templates/solution.md +18 -0
- package/purpose/kits/validation/templates/team.md +19 -0
- package/purpose/kits/validation/weights.json +22 -0
- package/purpose/layer.json +53 -0
- package/purpose/references/references.json +324 -0
- package/purpose/skills/ambition-tier/SKILL.md +205 -0
- package/purpose/skills/telos/SKILL.md +52 -0
- package/purpose/strategic-foundation.json +133 -0
- package/purpose/templates/telos-based-smart.md +39 -0
- package/purpose/tooling/integrations.json +48 -0
- package/schema/README.md +62 -0
- package/schema/VERSION +1 -0
- package/schema/access.mjs +57 -0
- package/schema/account.schema.json +79 -0
- package/schema/adapter.schema.json +33 -0
- package/schema/add-department.mjs +41 -0
- package/schema/agent-capability.schema.json +94 -0
- package/schema/alignment.schema.json +61 -0
- package/schema/assess-problem.mjs +131 -0
- package/schema/assets.mjs +212 -0
- package/schema/bdd.mjs +56 -0
- package/schema/board.schema.json +101 -0
- package/schema/brand.mjs +373 -0
- package/schema/build-release.mjs +61 -0
- package/schema/caching.mjs +505 -0
- package/schema/check-assets.mjs +24 -0
- package/schema/check-boundary.mjs +54 -0
- package/schema/check-brand.mjs +24 -0
- package/schema/check-config.mjs +110 -0
- package/schema/check-data-model.mjs +170 -0
- package/schema/check-data-packages.mjs +83 -0
- package/schema/check-departments.mjs +45 -0
- package/schema/check-execution.mjs +85 -0
- package/schema/check-governance.mjs +98 -0
- package/schema/check-integrations.mjs +33 -0
- package/schema/check-nextjs-status.mjs +79 -0
- package/schema/check-nouns.mjs +49 -0
- package/schema/check-people.mjs +70 -0
- package/schema/check-private.mjs +61 -0
- package/schema/check-provenance.mjs +55 -0
- package/schema/check-publication.mjs +96 -0
- package/schema/check-ready.mjs +89 -0
- package/schema/check-sources.mjs +74 -0
- package/schema/check-team.mjs +94 -0
- package/schema/check-telos.mjs +59 -0
- package/schema/check-validation.mjs +165 -0
- package/schema/check-ventures.mjs +81 -0
- package/schema/check-where-used.mjs +58 -0
- package/schema/data-master.schema.json +14 -0
- package/schema/data-model.json +1584 -0
- package/schema/data-model.schema.json +152 -0
- package/schema/deal.schema.json +80 -0
- package/schema/decision-analytics.mjs +77 -0
- package/schema/decision-record.schema.json +290 -0
- package/schema/decision-rights.schema.json +34 -0
- package/schema/decision.schema.json +30 -0
- package/schema/decisions.mjs +327 -0
- package/schema/department-catalog.schema.json +55 -0
- package/schema/department.schema.json +15 -0
- package/schema/departments.mjs +32 -0
- package/schema/docket-eval.mjs +89 -0
- package/schema/docket.mjs +135 -0
- package/schema/eval-suite.schema.json +45 -0
- package/schema/evidence.schema.json +110 -0
- package/schema/examples/frames/judge.mjs +10 -0
- package/schema/examples/migrate/agent.mjs +12 -0
- package/schema/examples/venture-type/jev.mjs +12 -0
- package/schema/examples/workspace/ventures/acme-labs/AGENTS.md +17 -0
- package/schema/examples/workspace/ventures/acme-labs/accounts/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/acme-labs/decisions/discovery-goal.decision.json +23 -0
- package/schema/examples/workspace/ventures/acme-labs/decisions/statement-icp.decision.json +22 -0
- package/schema/examples/workspace/ventures/acme-labs/decisions/statement-problem.decision.json +22 -0
- package/schema/examples/workspace/ventures/acme-labs/decisions/venture.team.decision.json +37 -0
- package/schema/examples/workspace/ventures/acme-labs/knowledge/README.md +3 -0
- package/schema/examples/workspace/ventures/acme-labs/knowledge/sources.json +46 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000001.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000002.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000003.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000004.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000005.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000006.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000007.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000008.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000009.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000010.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000011.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000012.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000013.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000014.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/_streams/transactions/stream.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/money/_summary.json +30 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/customer-service/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/customer-service/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/finance/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/human-capital/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/human-capital/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/it/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/it/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/marketing-and-sales/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/marketing-and-sales/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/products/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/products/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/strategy/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/strategy/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/people/founders/maya-chen.json +15 -0
- package/schema/examples/workspace/ventures/acme-labs/people/people.json +22 -0
- package/schema/examples/workspace/ventures/acme-labs/pillars/brand.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/pillars/business.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/pillars/product.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/products/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.core-product.decision.json +28 -0
- package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.exists.decision.json +38 -0
- package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.flagship.decision.json +27 -0
- package/schema/examples/workspace/ventures/acme-labs/profile.md +12 -0
- package/schema/examples/workspace/ventures/acme-labs/provenance.jsonl +12 -0
- package/schema/examples/workspace/ventures/acme-labs/raw/dump.md +6 -0
- package/schema/examples/workspace/ventures/acme-labs/venture.json +27 -0
- package/schema/examples/workspace/ventures/northstar/AGENTS.md +17 -0
- package/schema/examples/workspace/ventures/northstar/accounts/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/northstar/deals/ductline.json +8 -0
- package/schema/examples/workspace/ventures/northstar/deals/kilnworks.json +14 -0
- package/schema/examples/workspace/ventures/northstar/decisions/venture.team.decision.json +31 -0
- package/schema/examples/workspace/ventures/northstar/evidence/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/fund/decisions/terms.decision.json +27 -0
- package/schema/examples/workspace/ventures/northstar/fund/decisions/terms.first-close.decision.json +27 -0
- package/schema/examples/workspace/ventures/northstar/fund/decisions/thesis.decision.json +26 -0
- package/schema/examples/workspace/ventures/northstar/fund/terms.json +22 -0
- package/schema/examples/workspace/ventures/northstar/fund/thesis.json +22 -0
- package/schema/examples/workspace/ventures/northstar/governance/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/external-relationships/charter.md +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/external-relationships/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/finance/charter.md +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/human-capital/charter.md +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/human-capital/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/risk-and-compliance/charter.md +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/risk-and-compliance/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/strategy/charter.md +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/strategy/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/knowledge/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/operations/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/external-relationships/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/external-relationships/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/finance/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/human-capital/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/human-capital/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/risk-and-compliance/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/risk-and-compliance/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/strategy/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/strategy/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/people/founders/ana-ruiz.json +13 -0
- package/schema/examples/workspace/ventures/northstar/people/founders/ben-okafor.json +7 -0
- package/schema/examples/workspace/ventures/northstar/people/people.json +27 -0
- package/schema/examples/workspace/ventures/northstar/pillars/brand.md +5 -0
- package/schema/examples/workspace/ventures/northstar/pillars/business.md +5 -0
- package/schema/examples/workspace/ventures/northstar/pillars/product.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/AGENTS.md +17 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/accounts/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/decisions/venture.team.decision.json +31 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/knowledge/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/customer-service/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/customer-service/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/finance/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/human-capital/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/human-capital/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/it/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/it/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/marketing-and-sales/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/marketing-and-sales/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/products/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/products/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/strategy/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/strategy/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/brand.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/business.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/product.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.core-product.decision.json +28 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.exists.decision.json +32 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.flagship.decision.json +27 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/profile.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/venture.json +27 -0
- package/schema/examples/workspace/ventures/northstar/products/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/northstar/profile.md +5 -0
- package/schema/examples/workspace/ventures/northstar/provenance.jsonl +3 -0
- package/schema/examples/workspace/ventures/northstar/purpose/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/venture.json +49 -0
- package/schema/examples/workspace/ventures/studio/accounts/bakery/account.json +18 -0
- package/schema/examples/workspace/ventures/studio/evidence/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/governance/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/knowledge/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/operations/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/print/knowledge/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/print/purpose/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/print/venture.json +37 -0
- package/schema/examples/workspace/ventures/studio/products/brand-care.json +19 -0
- package/schema/examples/workspace/ventures/studio/products/brand-kit.json +23 -0
- package/schema/examples/workspace/ventures/studio/provenance.jsonl +3 -0
- package/schema/examples/workspace/ventures/studio/purpose/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/venture.json +43 -0
- package/schema/examples/workspace/ventures/tandem/accounts/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/tandem/evidence/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/agreements/dee-fast.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/board.json +51 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/finance/charter.md +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/primary/marketing-and-sales/charter.md +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/primary/marketing-and-sales/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/exit.json +33 -0
- package/schema/examples/workspace/ventures/tandem/governance/founder-agreement.json +24 -0
- package/schema/examples/workspace/ventures/tandem/governance/founder-agreement.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/ownership.json +131 -0
- package/schema/examples/workspace/ventures/tandem/governance/publication-policy.json +171 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/research/friends-feedback-2026-08.md +3 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/research/pilot-2026-10.md +3 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/research/problem-interviews-2026-09.md +20 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/sources.json +8 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/where-used.json +13 -0
- package/schema/examples/workspace/ventures/tandem/operations/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/finance/README.md +5 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/primary/marketing-and-sales/README.md +5 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/primary/marketing-and-sales/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/pillars/brand.md +5 -0
- package/schema/examples/workspace/ventures/tandem/pillars/business.md +5 -0
- package/schema/examples/workspace/ventures/tandem/pillars/product.md +5 -0
- package/schema/examples/workspace/ventures/tandem/products/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/tandem/products/shop-app.json +22 -0
- package/schema/examples/workspace/ventures/tandem/profile.md +5 -0
- package/schema/examples/workspace/ventures/tandem/provenance.jsonl +13 -0
- package/schema/examples/workspace/ventures/tandem/purpose/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/purpose/telos.json +78 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/go-to-market.json +35 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/pricing.json +37 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/problem.json +74 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/product-market-fit.json +66 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/solution.json +33 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/team.json +52 -0
- package/schema/examples/workspace/ventures/tandem/venture.json +79 -0
- package/schema/examples/workspace/ventures/woodworking/knowledge/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/woodworking/venture.json +21 -0
- package/schema/examples/workspace/workspace.json +8 -0
- package/schema/exit.schema.json +74 -0
- package/schema/foundation.mjs +118 -0
- package/schema/founder-agreement.schema.json +83 -0
- package/schema/founder.schema.json +72 -0
- package/schema/frame.schema.json +240 -0
- package/schema/frames.mjs +228 -0
- package/schema/freshness-log.schema.json +40 -0
- package/schema/freshness-profiles.schema.json +44 -0
- package/schema/freshness.mjs +473 -0
- package/schema/fund-terms.schema.json +107 -0
- package/schema/fund-thesis.schema.json +87 -0
- package/schema/gate-drafts.mjs +130 -0
- package/schema/gate.mjs +133 -0
- package/schema/glossary.schema.json +25 -0
- package/schema/handoff.schema.json +239 -0
- package/schema/icp.schema.json +136 -0
- package/schema/idea-graph.schema.json +61 -0
- package/schema/init-venture.mjs +128 -0
- package/schema/integration.schema.json +143 -0
- package/schema/judgment.schema.json +38 -0
- package/schema/kit.schema.json +47 -0
- package/schema/kits.mjs +24 -0
- package/schema/knowledge-sources.schema.json +260 -0
- package/schema/layer.json +59 -0
- package/schema/layer.schema.json +119 -0
- package/schema/load-packages.mjs +26 -0
- package/schema/marketing-brand.schema.json +116 -0
- package/schema/marketing-sitemap.schema.json +232 -0
- package/schema/migrate-venture.mjs +192 -0
- package/schema/migrations/kit-to-package.mjs +94 -0
- package/schema/migrations/package-layout.mjs +86 -0
- package/schema/model-steps.mjs +717 -0
- package/schema/money-summary.schema.json +138 -0
- package/schema/naive-config.mjs +165 -0
- package/schema/naive-config.schema.json +268 -0
- package/schema/need-now.json +772 -0
- package/schema/need-now.mjs +108 -0
- package/schema/nextjs-status.schema.json +29 -0
- package/schema/ownership.schema.json +282 -0
- package/schema/packages.json +4 -0
- package/schema/packages.mjs +252 -0
- package/schema/payouts.mjs +91 -0
- package/schema/people.schema.json +86 -0
- package/schema/port-venture.mjs +161 -0
- package/schema/product.schema.json +223 -0
- package/schema/provenance-entry.schema.json +154 -0
- package/schema/public-assets.schema.json +76 -0
- package/schema/publication-policy.schema.json +293 -0
- package/schema/raw-source.schema.json +15 -0
- package/schema/reference.schema.json +115 -0
- package/schema/release-read.mjs +111 -0
- package/schema/releases.mjs +497 -0
- package/schema/route-aliases.schema.json +25 -0
- package/schema/run-handoff.mjs +51 -0
- package/schema/scaffold/defaults.json +54 -0
- package/schema/setup.mjs +164 -0
- package/schema/site-presence.schema.json +337 -0
- package/schema/stale.mjs +111 -0
- package/schema/start-release.mjs +41 -0
- package/schema/strategic-foundation.schema.json +74 -0
- package/schema/stream.schema.json +14 -0
- package/schema/structure.mjs +186 -0
- package/schema/systems-catalog.json +126 -0
- package/schema/systems-catalog.schema.json +78 -0
- package/schema/team-plan.schema.json +157 -0
- package/schema/telos.schema.json +197 -0
- package/schema/time-to-ready.mjs +93 -0
- package/schema/trigger.schema.json +44 -0
- package/schema/triggers.mjs +237 -0
- package/schema/upgrade-registry.schema.json +60 -0
- package/schema/upgrade-venture.mjs +107 -0
- package/schema/upgrades.json +69 -0
- package/schema/upgrades.mjs +385 -0
- package/schema/use-model.mjs +10 -0
- package/schema/validate.py +58 -0
- package/schema/validation-evidence.schema.json +123 -0
- package/schema/validation-go-to-market.schema.json +110 -0
- package/schema/validation-operations-readiness.schema.json +91 -0
- package/schema/validation-pricing.schema.json +114 -0
- package/schema/validation-problem.schema.json +118 -0
- package/schema/validation-product-market-fit.schema.json +135 -0
- package/schema/validation-solution.schema.json +79 -0
- package/schema/validation-team.schema.json +116 -0
- package/schema/venture-role.schema.json +64 -0
- package/schema/venture-type.mjs +62 -0
- package/schema/venture-types.json +346 -0
- package/schema/venture-types.schema.json +129 -0
- package/schema/venture.schema.json +460 -0
- package/schema/vocab/business-models.json +298 -0
- package/schema/where-used.schema.json +56 -0
- package/schema/workspace.schema.json +38 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// naive upgrade: moves one venture onto the installed Naive, like next upgrade and its codemods
|
|
3
|
+
// (EE-076, U-1 to U-6). The work is in schema/upgrades.mjs; this is its command line.
|
|
4
|
+
//
|
|
5
|
+
// node schema/upgrade-venture.mjs <venture dir> run the migrations and pin the framework and packages
|
|
6
|
+
// node schema/upgrade-venture.mjs <venture dir> --check say what it would do; change nothing
|
|
7
|
+
// node schema/upgrade-venture.mjs <venture dir> --guide [x.y.z] the guide for each version it crosses, or for one
|
|
8
|
+
// node schema/upgrade-venture.mjs <venture dir> --canary|--stable the channel (experimental packages need canary)
|
|
9
|
+
// node schema/upgrade-venture.mjs <venture dir> --adopt <package> adopt a later phase's package now
|
|
10
|
+
// node schema/upgrade-venture.mjs <venture dir> --drop <package> undo that
|
|
11
|
+
// node schema/upgrade-venture.mjs <venture dir> --stage upgrade a copy under .naive/upgrade/ and run the checks
|
|
12
|
+
// node schema/upgrade-venture.mjs <venture dir> --agent the same, with an agent working the copy (a Mentura kit)
|
|
13
|
+
// node schema/upgrade-venture.mjs <venture dir> --status the staged upgrade and its checks
|
|
14
|
+
// node schema/upgrade-venture.mjs <venture dir> --accept --confirm upgrade land a staged upgrade whose checks pass
|
|
15
|
+
// node schema/upgrade-venture.mjs <venture dir> --reject discard it
|
|
16
|
+
// node schema/upgrade-venture.mjs --framework [<venture dir>] update the installed framework first (git pull --ff-only)
|
|
17
|
+
//
|
|
18
|
+
// Files move with git mv when git tracks them. Provenance is appended, never rewritten. Old routes keep
|
|
19
|
+
// resolving through interface/route-aliases.json. --json prints the result as JSON.
|
|
20
|
+
|
|
21
|
+
import { spawnSync } from "node:child_process";
|
|
22
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
23
|
+
import { join, resolve } from "node:path";
|
|
24
|
+
import { accept, adopt, check, CONFIRM, draft, drop, guide, plan, registry, reject, setChannel, stage, updateFramework, upgrade } from "./upgrades.mjs";
|
|
25
|
+
import { kitFor } from "./kits.mjs";
|
|
26
|
+
|
|
27
|
+
const argv = process.argv.slice(2);
|
|
28
|
+
const has = (n) => argv.includes(`--${n}`);
|
|
29
|
+
const opt = (n) => { const i = argv.indexOf(`--${n}`); return i >= 0 && argv[i + 1] && !argv[i + 1].startsWith("--") ? argv[i + 1] : undefined; };
|
|
30
|
+
const valued = new Set(["guide", "adopt", "drop", "confirm", "by"]);
|
|
31
|
+
const dirArg = argv.find((a, i) => !a.startsWith("--") && !(i > 0 && valued.has(argv[i - 1].slice(2))));
|
|
32
|
+
const json = has("json");
|
|
33
|
+
const say = (x, text) => console.log(json ? JSON.stringify(x, null, 2) : text);
|
|
34
|
+
const fail = (e) => { console.error(e.message ?? String(e)); process.exit(1); };
|
|
35
|
+
const usage = () => { console.error("usage: node schema/upgrade-venture.mjs <venture dir> [--check | --guide [version] | --canary | --stable | --adopt <package> | --drop <package> | --stage | --agent | --status | --accept --confirm upgrade | --reject] [--json]\n node schema/upgrade-venture.mjs --framework [<venture dir>]"); process.exit(2); };
|
|
36
|
+
|
|
37
|
+
if (has("framework")) {
|
|
38
|
+
const r = updateFramework();
|
|
39
|
+
if (!r.ok) fail(new Error(r.error));
|
|
40
|
+
console.log(r.commits ? `updated Naive from ${r.from} to ${r.to} (${r.commits} commits)` : `Naive ${r.to} is up to date`);
|
|
41
|
+
if (!dirArg) process.exit(0);
|
|
42
|
+
// The upgrade runs in the code just pulled, not the code this process loaded.
|
|
43
|
+
const rest = argv.filter((a) => a !== "--framework");
|
|
44
|
+
process.exit(spawnSync("node", [new URL(import.meta.url).pathname, ...rest], { stdio: "inherit" }).status ?? 1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!dirArg || !existsSync(join(dirArg, "venture.json"))) usage();
|
|
48
|
+
const dir = resolve(dirArg);
|
|
49
|
+
const id = JSON.parse(readFileSync(join(dir, "venture.json"), "utf8")).id;
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
if (has("guide")) {
|
|
53
|
+
const reg = registry();
|
|
54
|
+
const versions = opt("guide") ? [opt("guide")] : plan(dir).steps.map((s) => s.version);
|
|
55
|
+
if (!versions.length) { say({ guides: [] }, `${id} is on Naive ${reg.framework}: no guide to read`); process.exit(0); }
|
|
56
|
+
const gs = versions.map((v) => guide(v, { reg }) ?? { version: v, path: null, text: `Naive ${v} has no guide.` });
|
|
57
|
+
say(gs, gs.map((g) => `${g.path ? `# ${g.path}\n\n` : ""}${g.text.replace(/^---\n[\s\S]*?\n---\n\n?/, "")}`).join("\n"));
|
|
58
|
+
} else if (has("canary") || has("stable")) {
|
|
59
|
+
const r = setChannel(dir, has("canary") ? "canary" : "stable");
|
|
60
|
+
say(r, r.changed ? `${id} is on the ${r.channel} channel` : `${id} was already on the ${r.channel} channel`);
|
|
61
|
+
} else if (opt("adopt")) {
|
|
62
|
+
const r = adopt(dir, opt("adopt"));
|
|
63
|
+
say(r, r.changed ? `adopted ${r.name} ${r.version} early${r.channel === "experimental" ? " (experimental)" : ""}: it opens now in the venture package` : r.note);
|
|
64
|
+
} else if (opt("drop")) {
|
|
65
|
+
const r = drop(dir, opt("drop"));
|
|
66
|
+
say(r, `dropped ${r.name}: it fits by its phase again`);
|
|
67
|
+
} else if (has("stage")) {
|
|
68
|
+
await stage(dir);
|
|
69
|
+
const d = check(dir);
|
|
70
|
+
report(d);
|
|
71
|
+
} else if (has("agent")) {
|
|
72
|
+
// The agent-run upgrade is a Mentura kit (U-3, I-29): the framework finds it and runs it as its own process.
|
|
73
|
+
const k = kitFor("upgrade --agent");
|
|
74
|
+
if (!k) fail(new Error("an agent-run upgrade is a Mentura kit (platform/kits/agent-upgrade), and none is installed here; --stage upgrades a copy without an agent"));
|
|
75
|
+
process.exit(spawnSync("node", [join(k.dir, k.entry), dir, ...(json ? ["--json"] : [])], { stdio: "inherit" }).status ?? 1);
|
|
76
|
+
} else if (has("status")) {
|
|
77
|
+
const d = draft(dir);
|
|
78
|
+
if (!d) { say(null, `no upgrade is staged for ${id}`); process.exit(0); }
|
|
79
|
+
report(check(dir));
|
|
80
|
+
} else if (has("accept")) {
|
|
81
|
+
const r = await accept(dir, { confirm: opt("confirm"), by: opt("by") ?? process.env.MENTURA_PERSON });
|
|
82
|
+
say(r, `accepted: ${id} is on Naive ${r.accepted} (${r.added} added, ${r.changed} changed, ${r.removed} removed)`);
|
|
83
|
+
} else if (has("reject")) {
|
|
84
|
+
say(reject(dir), `rejected the staged upgrade of ${id}; the venture is as it was`);
|
|
85
|
+
} else {
|
|
86
|
+
const r = await upgrade(dir, { dry: has("check") });
|
|
87
|
+
if (json) { console.log(JSON.stringify(r, null, 2)); process.exit(0); }
|
|
88
|
+
const moves = r.release.migrations.reduce((n, m) => n + m.moves.length, 0), rewrites = r.release.migrations.reduce((n, m) => n + m.rewrote.length, 0);
|
|
89
|
+
const pinned = r.packages.filter((x) => !x.missing && x.from !== x.to);
|
|
90
|
+
if (!r.pending && !r.changed) console.log(`${id} is on Naive ${r.to}, every package pinned: nothing to upgrade.`);
|
|
91
|
+
else console.log(`${r.dry ? "would upgrade" : "upgraded"} ${id} from Naive ${r.from} to ${r.to}: ${moves} files moved, ${rewrites} records rewritten, ${pinned.length} packages pinned, ${r.release.escalated.length} escalated for a decision.`);
|
|
92
|
+
for (const m of r.release.migrations) if (m.moves.length || m.rewrote.length || m.notes.length) console.log(`migrate ${m.id} (${m.version}): ${m.moves.length} moved, ${m.rewrote.length} rewritten${m.notes.length ? `; ${m.notes.join("; ")}` : ""}`);
|
|
93
|
+
for (const e of r.release.escalated) console.log(`escalate ${e}`);
|
|
94
|
+
for (const g of r.release.guides) console.log(`guide ${g}`);
|
|
95
|
+
if (r.release.guides.length) console.log(`Read the guides: node interface/cli/naive.mjs upgrade ${dirArg} --guide`);
|
|
96
|
+
}
|
|
97
|
+
} catch (e) { fail(e); }
|
|
98
|
+
|
|
99
|
+
function report(d) {
|
|
100
|
+
if (json) { console.log(JSON.stringify(d, null, 2)); return; }
|
|
101
|
+
console.log(`staged upgrade of ${id} from Naive ${d.from} to ${d.to}${d.by && d.by !== "naive" ? `, worked by ${d.by}` : ""}: ${d.status}`);
|
|
102
|
+
if (d.changes) console.log(`changes ${d.changes.added.length} added, ${d.changes.changed.length} changed, ${d.changes.removed.length} removed`);
|
|
103
|
+
for (const c of d.checks ?? []) console.log(`${c.passed ? "pass" : "FAIL"} ${c.check}${c.passed ? "" : `: ${c.output.split("\n").slice(-2).join(" / ")}`}`);
|
|
104
|
+
for (const e of d.escalated ?? []) console.log(`escalate ${e}`);
|
|
105
|
+
if (d.status === "ready") console.log(`Nothing has landed. To land it: node interface/cli/naive.mjs upgrade ${dirArg} --accept --confirm ${CONFIRM}`);
|
|
106
|
+
else if (d.status === "checks-failed") console.log(`Nothing has landed, and it cannot until the checks pass. Fix the copy in ${dirArg}/.naive/upgrade/venture and run --status, or --reject.`);
|
|
107
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"framework": "0.3.0",
|
|
3
|
+
"note": "Naive's versions, the migrations that move a venture from one to the next, and each package's version and channel (EE-076, the Next.js translation's chapter 18). naive upgrade reads this file from the installed copy, so a venture always upgrades to the framework it runs on. A version's guide is bundled here, in docs/upgrades/, so agents read the guide for the version installed (I-29).",
|
|
4
|
+
"channels": {
|
|
5
|
+
"stable": "Packages Naive models and computes fit for. The default.",
|
|
6
|
+
"canary": "Stable packages plus experimental ones: packages Naive does not model yet (fit is not computed), adopted only when a person asks for one by name."
|
|
7
|
+
},
|
|
8
|
+
"versions": [
|
|
9
|
+
{
|
|
10
|
+
"version": "0.1.0",
|
|
11
|
+
"date": "2026-10-27",
|
|
12
|
+
"summary": "The layer layout: records under purpose/, knowledge/, operations/, governance/ and pillars/ (EE-030, EE-032). A venture with no pin in naive.config.json is on this version.",
|
|
13
|
+
"guide": null,
|
|
14
|
+
"migrations": []
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"version": "0.2.0",
|
|
18
|
+
"date": "2026-10-29",
|
|
19
|
+
"summary": "The package folder layout: records move into foundation/, validation/, product/, marketing/, people/ and decisions/, with the old routes kept as aliases (EE-070).",
|
|
20
|
+
"guide": "docs/upgrades/0.2.0.md",
|
|
21
|
+
"migrations": ["package-layout"]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"version": "0.3.0",
|
|
25
|
+
"date": "2026-10-29",
|
|
26
|
+
"summary": "Packages are Naive's and kits are Mentura's (EE-071): naive.config.json pins the framework and each package, and routes inside records are package routes.",
|
|
27
|
+
"guide": "docs/upgrades/0.3.0.md",
|
|
28
|
+
"migrations": ["kit-to-package"]
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"migrations": [
|
|
32
|
+
{
|
|
33
|
+
"id": "package-layout",
|
|
34
|
+
"module": "schema/migrations/package-layout.mjs",
|
|
35
|
+
"package": null,
|
|
36
|
+
"decision": "EE-070",
|
|
37
|
+
"aliases": "interface/route-aliases.json"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "kit-to-package",
|
|
41
|
+
"module": "schema/migrations/kit-to-package.mjs",
|
|
42
|
+
"package": null,
|
|
43
|
+
"decision": "EE-071",
|
|
44
|
+
"aliases": "interface/route-aliases.json"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"packages": {
|
|
48
|
+
"foundation": { "version": "0.3.0", "channel": "stable" },
|
|
49
|
+
"validation": { "version": "0.3.0", "channel": "stable" },
|
|
50
|
+
"product": { "version": "0.3.0", "channel": "stable" },
|
|
51
|
+
"marketing": { "version": "0.3.0", "channel": "stable" },
|
|
52
|
+
"finance": { "version": "0.3.0", "channel": "stable" },
|
|
53
|
+
"people": { "version": "0.3.0", "channel": "stable" },
|
|
54
|
+
"investor": { "version": "0.3.0", "channel": "stable" },
|
|
55
|
+
"partner": { "version": "0.3.0", "channel": "stable" },
|
|
56
|
+
"cofounder": { "version": "0.3.0", "channel": "stable" },
|
|
57
|
+
"engineering": { "version": "0.3.0", "channel": "stable" },
|
|
58
|
+
"customers": { "version": "0.3.0", "channel": "stable" },
|
|
59
|
+
"investors": { "version": "0.3.0", "channel": "stable" },
|
|
60
|
+
"money": { "version": "0.3.0", "channel": "stable" },
|
|
61
|
+
"raw": { "version": "0.3.0", "channel": "stable" },
|
|
62
|
+
"decisions": { "version": "0.3.0", "channel": "stable" },
|
|
63
|
+
"evidence": { "version": "0.3.0", "channel": "stable" },
|
|
64
|
+
"legal": { "version": "0.3.0", "channel": "experimental", "note": "Not modeled: matters after Validation or under another governance model (EE-069)" },
|
|
65
|
+
"operations": { "version": "0.3.0", "channel": "experimental", "note": "Not modeled: matters after Validation or under another governance model (EE-069)" },
|
|
66
|
+
"relationships": { "version": "0.3.0", "channel": "experimental", "note": "Not modeled: matters after Validation or under another governance model (EE-069)" },
|
|
67
|
+
"counsel": { "version": "0.3.0", "channel": "experimental", "note": "Not modeled: co-owners, outside money or a regulated field (EE-069)" }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
// Upgrades (EE-076; the Next.js translation's chapter 18, rows U-1 to U-6): what `next upgrade`, its
|
|
2
|
+
// codemods, `--agent`, the canary channel and the version guides become in Naive.
|
|
3
|
+
//
|
|
4
|
+
// U-1 naive upgrade moves a venture onto the installed framework and pins it and its packages in
|
|
5
|
+
// naive.config.json; --framework first updates the installed framework (git pull --ff-only).
|
|
6
|
+
// U-2 migrations (schema/migrations/*.mjs) rewrite records when the framework or a package's schema
|
|
7
|
+
// changes, with route aliases for renamed folders. The kit-to-package rename is the first record
|
|
8
|
+
// migration; the package layout move before it is the first layout one.
|
|
9
|
+
// U-3 a staged upgrade runs on a copy under .naive/upgrade/, then the checks run on the copy; it lands
|
|
10
|
+
// only when they pass and a person types the confirmation. The agent that works the copy is a
|
|
11
|
+
// Mentura kit (platform/kits/agent-upgrade); this module is the part that decides.
|
|
12
|
+
// U-5 channels: stable, or canary for experimental packages; a later phase's package can be adopted
|
|
13
|
+
// early, by name.
|
|
14
|
+
// U-6 each framework version has a guide bundled in docs/upgrades/, printed from the installed copy.
|
|
15
|
+
//
|
|
16
|
+
// Code decides here: no model is called. The registry is schema/upgrades.json (NAIVE_UPGRADES points
|
|
17
|
+
// at another one, for tests).
|
|
18
|
+
|
|
19
|
+
import { execFileSync, spawnSync } from "node:child_process";
|
|
20
|
+
import { createHash } from "node:crypto";
|
|
21
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
22
|
+
import { dirname, isAbsolute, join } from "node:path";
|
|
23
|
+
import { pathToFileURL } from "node:url";
|
|
24
|
+
import { agentFromEnv, record } from "../interface/provenance.mjs";
|
|
25
|
+
import { routes, glob } from "../interface/router.mjs";
|
|
26
|
+
import { CONFIG, pins, readConfig, writeConfig } from "./naive-config.mjs";
|
|
27
|
+
import { packages as packageFit } from "./packages.mjs";
|
|
28
|
+
|
|
29
|
+
export const repo = new URL("..", import.meta.url).pathname;
|
|
30
|
+
export const STAGE = ".naive/upgrade";
|
|
31
|
+
export const STAGED = `${STAGE}/venture`;
|
|
32
|
+
export const DRAFT = `${STAGE}/draft.json`;
|
|
33
|
+
export const CONFIRM = "upgrade";
|
|
34
|
+
const load = (p) => JSON.parse(readFileSync(p, "utf8"));
|
|
35
|
+
const now = () => new Date().toISOString().replace(/\.\d+Z$/, "Z");
|
|
36
|
+
const sha = (buf) => createHash("sha256").update(buf).digest("hex");
|
|
37
|
+
|
|
38
|
+
/** Compares two x.y.z versions. */
|
|
39
|
+
export const cmp = (a, b) => {
|
|
40
|
+
const x = String(a).split(".").map(Number), y = String(b).split(".").map(Number);
|
|
41
|
+
for (let i = 0; i < 3; i++) if ((x[i] ?? 0) !== (y[i] ?? 0)) return (x[i] ?? 0) - (y[i] ?? 0);
|
|
42
|
+
return 0;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/** The upgrade registry of an installed framework (default: this copy). */
|
|
46
|
+
export function registry(root = repo) {
|
|
47
|
+
const f = root === repo && process.env.NAIVE_UPGRADES ? process.env.NAIVE_UPGRADES : join(root, "schema/upgrades.json");
|
|
48
|
+
return load(f);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const abs = (p, root = repo) => (isAbsolute(p) ? p : join(root, p));
|
|
52
|
+
|
|
53
|
+
/** The framework version a venture is on: its pin, or 0.1.0 for a venture made before pins. */
|
|
54
|
+
export function versionOf(dir) {
|
|
55
|
+
return readConfig(dir).naive?.version ?? "0.1.0";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const kindOf = (name) => { const f = join(repo, "packages", name, "package.json"); return existsSync(f) ? load(f).kind : null; };
|
|
59
|
+
|
|
60
|
+
/** The packages a venture should be pinned to: what it pins now, what fits its phase now, and its data folders. */
|
|
61
|
+
function wanted(dir, reg, cfg) {
|
|
62
|
+
const names = new Set(Object.keys(pins(cfg)));
|
|
63
|
+
try { const p = packageFit(dir); for (const x of [...p.core, ...p.handoff]) if (x.in === "now") names.add(x.id); } catch {}
|
|
64
|
+
for (const n of Object.keys(reg.packages)) if (["data", "raw", "folder"].includes(kindOf(n))) names.add(n);
|
|
65
|
+
return [...names].sort();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function loadMigration(m) {
|
|
69
|
+
const mod = await import(pathToFileURL(abs(m.module)).href);
|
|
70
|
+
if (typeof mod.apply !== "function") throw new Error(`${m.module} exports no apply(dir, ctx)`);
|
|
71
|
+
return { ...m, describe: mod.describe ?? m.id, apply: mod.apply };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* What an upgrade would do, without doing it: the framework versions it crosses, with their guides and
|
|
76
|
+
* migrations, and each package's pin before and after with the package migrations it runs.
|
|
77
|
+
*/
|
|
78
|
+
export function plan(dir, { reg = registry() } = {}) {
|
|
79
|
+
if (!existsSync(join(dir, "venture.json"))) throw new Error(`${dir} is not a venture (no venture.json)`);
|
|
80
|
+
const cfg = readConfig(dir);
|
|
81
|
+
const from = versionOf(dir), to = reg.framework;
|
|
82
|
+
const byId = new Map(reg.migrations.map((m) => [m.id, m]));
|
|
83
|
+
const steps = reg.versions.filter((v) => cmp(v.version, from) > 0 && cmp(v.version, to) <= 0).sort((a, b) => cmp(a.version, b.version))
|
|
84
|
+
.map((v) => ({ version: v.version, summary: v.summary, guide: v.guide, migrations: v.migrations.map((id) => { const m = byId.get(id); if (!m) throw new Error(`version ${v.version} names migration ${id}, which is not in the registry`); return m; }) }));
|
|
85
|
+
const current = pins(cfg);
|
|
86
|
+
const pkgs = wanted(dir, reg, cfg).map((name) => {
|
|
87
|
+
const info = reg.packages[name];
|
|
88
|
+
const was = current[name]?.version ?? null;
|
|
89
|
+
if (!info) return { name, from: was, to: was, missing: true, migrations: [] };
|
|
90
|
+
const migrations = reg.migrations.filter((m) => m.package === name && cmp(m.to, info.version) <= 0 && (was === null || (cmp(was, m.from ?? "0.0.0") >= 0 && cmp(was, m.to) < 0)));
|
|
91
|
+
return { name, from: was, to: info.version, channel: info.channel, early: !!current[name]?.early, migrations };
|
|
92
|
+
});
|
|
93
|
+
const pending = steps.length > 0 || pkgs.some((p) => !p.missing && (p.from === null || cmp(p.from, p.to) !== 0)) || cfg.naive?.version !== to;
|
|
94
|
+
return { venture: load(join(dir, "venture.json")).id, from, to, channel: cfg.naive?.channel ?? "stable", steps, packages: pkgs, pending };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// The changes one migration makes, all through here, so a dry run reports them and a real run logs them.
|
|
98
|
+
function context(dir, { dry, git, cfg, at, onConfig }) {
|
|
99
|
+
const moved = [], writes = [], escalated = [], notes = [], kept = [];
|
|
100
|
+
const tracked = (p) => git && spawnSync("git", ["ls-files", "--error-unmatch", p], { cwd: dir, stdio: "pipe" }).status === 0;
|
|
101
|
+
const removeEmpty = (p) => {
|
|
102
|
+
if (!existsSync(p) || !statSync(p).isDirectory()) return;
|
|
103
|
+
for (const e of readdirSync(p, { withFileTypes: true })) if (e.isDirectory()) removeEmpty(join(p, e.name));
|
|
104
|
+
if (readdirSync(p).length === 0) rmSync(p, { recursive: true });
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
at, config: cfg, moved, writes, escalated, notes, kept,
|
|
108
|
+
mv(a, b) {
|
|
109
|
+
if (!existsSync(join(dir, a))) return;
|
|
110
|
+
if (existsSync(join(dir, b)) && !moved.some(([, t]) => t === b)) throw new Error(`${b} already exists, so ${a} cannot move there; move one of them yourself and upgrade again`);
|
|
111
|
+
if (!dry) {
|
|
112
|
+
mkdirSync(dirname(join(dir, b)), { recursive: true });
|
|
113
|
+
if (tracked(a)) execFileSync("git", ["mv", a, b], { cwd: dir, stdio: "pipe" });
|
|
114
|
+
else renameSync(join(dir, a), join(dir, b));
|
|
115
|
+
}
|
|
116
|
+
moved.push([a, b]);
|
|
117
|
+
},
|
|
118
|
+
write(rel, text, { activity = "write", note, derived_from, log = true } = {}) {
|
|
119
|
+
if (!dry) { mkdirSync(dirname(join(dir, rel)), { recursive: true }); writeFileSync(join(dir, rel), text); }
|
|
120
|
+
writes.push({ path: rel, activity, note, derived_from, log });
|
|
121
|
+
},
|
|
122
|
+
escalate: (msg) => escalated.push(msg),
|
|
123
|
+
note: (msg) => notes.push(msg),
|
|
124
|
+
configChanged: () => onConfig(),
|
|
125
|
+
removeEmpty: (rel) => { if (!dry) removeEmpty(join(dir, rel)); },
|
|
126
|
+
keep(sub) {
|
|
127
|
+
if (existsSync(join(dir, sub))) return;
|
|
128
|
+
if (!dry) { mkdirSync(join(dir, sub), { recursive: true }); writeFileSync(join(dir, sub, ".gitkeep"), ""); }
|
|
129
|
+
kept.push(sub);
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Upgrades a venture in place (U-1, U-2): runs each migration the plan names, pins the framework and
|
|
136
|
+
* the packages in naive.config.json, writes .release/upgrade-<version>.json and logs every change in
|
|
137
|
+
* provenance. dry: report only. Triggers do not fire on an upgrade's own writes.
|
|
138
|
+
*/
|
|
139
|
+
export async function upgrade(dir, { reg = registry(), dry = false, git = true } = {}) {
|
|
140
|
+
const p = plan(dir, { reg });
|
|
141
|
+
const cfg = readConfig(dir);
|
|
142
|
+
const at = now();
|
|
143
|
+
let configChanged = false;
|
|
144
|
+
const ran = [];
|
|
145
|
+
const held = process.env.NAIVE_TRIGGERS_ACTIVE;
|
|
146
|
+
process.env.NAIVE_TRIGGERS_ACTIVE = "upgrade";
|
|
147
|
+
const agent = agentFromEnv("agent", "cli", { id: process.env.MENTURA_ACTOR_ID ?? "naive-upgrade" });
|
|
148
|
+
try {
|
|
149
|
+
const order = [...p.steps.flatMap((s) => s.migrations.map((m) => ({ ...m, version: s.version }))), ...p.packages.flatMap((x) => x.migrations.map((m) => ({ ...m, version: `${x.name}@${m.to}` })))];
|
|
150
|
+
// A dry run first, so a conflict stops the upgrade before anything moves.
|
|
151
|
+
if (!dry) for (const m of order) { const mod = await loadMigration(m); mod.apply(dir, context(dir, { dry: true, git, cfg: structuredClone(cfg), at, onConfig() {} })); }
|
|
152
|
+
for (const m of order) {
|
|
153
|
+
const mod = await loadMigration(m);
|
|
154
|
+
const ctx = context(dir, { dry, git, cfg, at, onConfig: () => { configChanged = true; } });
|
|
155
|
+
mod.apply(dir, ctx);
|
|
156
|
+
ran.push({ id: m.id, version: m.version, describe: mod.describe, decision: m.decision ?? null, moves: ctx.moved.map(([from, to]) => ({ from, to })),
|
|
157
|
+
rewrote: ctx.writes.filter((w) => w.activity === "write").map((w) => w.path), escalated: ctx.escalated, notes: ctx.notes });
|
|
158
|
+
if (dry) continue;
|
|
159
|
+
for (const [from, to] of ctx.moved) record(dir, { entity: to, activity: "move", agent, derived_from: [from], note: `moved from ${from} (${m.decision ?? m.id})` });
|
|
160
|
+
for (const w of ctx.writes.filter((x) => x.log)) record(dir, { entity: w.path, activity: w.activity, agent, derived_from: w.derived_from, note: `${m.id}: ${w.note ?? "rewritten"}`, decision: m.decision ?? undefined });
|
|
161
|
+
}
|
|
162
|
+
// Pins (U-1, U-4): the framework, the channel, and every package the venture uses.
|
|
163
|
+
const before = JSON.stringify(cfg);
|
|
164
|
+
cfg.naive = { ...(cfg.naive ?? {}), version: p.to, channel: cfg.naive?.channel ?? "stable" };
|
|
165
|
+
const now_ = pins(cfg);
|
|
166
|
+
const escalated = [];
|
|
167
|
+
for (const x of p.packages) {
|
|
168
|
+
if (x.missing) { escalated.push(`package ${x.name} is pinned but no longer in Naive ${p.to}; its pin is kept`); continue; }
|
|
169
|
+
now_[x.name] = { ...(now_[x.name] ?? {}), version: x.to, ...(x.channel === "experimental" ? { channel: "experimental" } : {}) };
|
|
170
|
+
}
|
|
171
|
+
// A package a migration named (a kit that was a package) is pinned to the installed version too.
|
|
172
|
+
for (const [n, v] of Object.entries(now_)) if (!v.version && reg.packages[n]) now_[n] = { ...v, version: reg.packages[n].version };
|
|
173
|
+
cfg.packages = Object.fromEntries(Object.entries(now_).sort(([a], [b]) => a.localeCompare(b)));
|
|
174
|
+
if (JSON.stringify(cfg) !== before) configChanged = true;
|
|
175
|
+
const release = { version: p.to, from: p.from, at, venture: p.venture, channel: cfg.naive.channel, migrations: ran,
|
|
176
|
+
packages: p.packages.filter((x) => !x.missing).map((x) => ({ name: x.name, from: x.from, to: x.to })), guides: p.steps.map((s) => s.guide).filter(Boolean), escalated: [...ran.flatMap((r) => r.escalated), ...escalated] };
|
|
177
|
+
if (!dry && (p.pending || configChanged)) {
|
|
178
|
+
if (configChanged) { writeConfig(dir, cfg); record(dir, { entity: CONFIG, activity: "write", agent, note: `pinned Naive ${p.to} and ${Object.keys(cfg.packages).length} packages (U-1)` }); }
|
|
179
|
+
const rel = `.release/upgrade-${p.to}.json`;
|
|
180
|
+
mkdirSync(join(dir, ".release"), { recursive: true });
|
|
181
|
+
writeFileSync(join(dir, rel), JSON.stringify(release, null, 2) + "\n");
|
|
182
|
+
record(dir, { entity: rel, activity: "release", agent, derived_from: [...new Set([...ran.flatMap((r) => [...r.moves.map((m) => m.to), ...r.rewrote]), ...(configChanged ? [CONFIG] : [])])], note: `upgraded from Naive ${p.from} to ${p.to}` });
|
|
183
|
+
// Adapters installed in the venture (Z-4) are refreshed, so their copies of package skills follow the upgrade.
|
|
184
|
+
release.adapters = await refreshAdapters(dir);
|
|
185
|
+
}
|
|
186
|
+
return { ...p, dry, release, changed: !dry && (p.pending || configChanged) };
|
|
187
|
+
} finally {
|
|
188
|
+
if (held === undefined) delete process.env.NAIVE_TRIGGERS_ACTIVE; else process.env.NAIVE_TRIGGERS_ACTIVE = held;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** The guide bundled for one framework version (U-6), or null. */
|
|
193
|
+
export function guide(version, { reg = registry() } = {}) {
|
|
194
|
+
const v = reg.versions.find((x) => x.version === version);
|
|
195
|
+
if (!v) throw new Error(`Naive has no version ${version}: ${reg.versions.map((x) => x.version).join(", ")}`);
|
|
196
|
+
return v.guide && existsSync(abs(v.guide)) ? { version, path: v.guide, text: readFileSync(abs(v.guide), "utf8") } : null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Switches the venture's channel (U-5): stable, or canary for experimental packages. */
|
|
200
|
+
export function setChannel(dir, channel, { reg = registry() } = {}) {
|
|
201
|
+
if (!["stable", "canary"].includes(channel)) throw new Error(`channel ${channel}: stable or canary`);
|
|
202
|
+
const cfg = readConfig(dir);
|
|
203
|
+
if (cfg.naive?.channel === channel) return { changed: false, channel };
|
|
204
|
+
const experimental = Object.entries(pins(cfg)).filter(([n]) => reg.packages[n]?.channel === "experimental").map(([n]) => n);
|
|
205
|
+
if (channel === "stable" && experimental.length) throw new Error(`the venture uses experimental packages (${experimental.join(", ")}): drop them first (--drop <package>)`);
|
|
206
|
+
cfg.naive = { version: versionOf(dir), ...(cfg.naive ?? {}), channel };
|
|
207
|
+
writeConfig(dir, cfg);
|
|
208
|
+
record(dir, { entity: CONFIG, activity: "write", agent: agentFromEnv(process.env.MENTURA_ACTOR === "agent" ? "agent" : "person", "cli"), note: `channel set to ${channel} (U-5)` });
|
|
209
|
+
return { changed: true, channel };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Adopts a package before its phase (U-5): it is pinned with early: true, and the venture package
|
|
214
|
+
* opens it now. An experimental package needs the canary channel. The venture must be on the
|
|
215
|
+
* installed framework first.
|
|
216
|
+
*/
|
|
217
|
+
export function adopt(dir, name, { reg = registry() } = {}) {
|
|
218
|
+
const info = reg.packages[name];
|
|
219
|
+
if (!info) throw new Error(`no package ${name} in Naive ${reg.framework}: ${Object.keys(reg.packages).join(", ")}`);
|
|
220
|
+
if (cmp(versionOf(dir), reg.framework) !== 0) throw new Error(`the venture is on Naive ${versionOf(dir)}: upgrade it to ${reg.framework} before adopting packages`);
|
|
221
|
+
const cfg = readConfig(dir);
|
|
222
|
+
if (info.channel === "experimental" && cfg.naive?.channel !== "canary") throw new Error(`${name} is experimental (${info.note ?? "not modeled yet"}): switch to the canary channel first (--canary)`);
|
|
223
|
+
const current = pins(cfg);
|
|
224
|
+
if (current[name]?.early) return { changed: false, name, note: `${name} is already adopted early` };
|
|
225
|
+
let fit = null;
|
|
226
|
+
try { fit = [...packageFit(dir).core, ...packageFit(dir).handoff].find((x) => x.id === name) ?? null; } catch {}
|
|
227
|
+
if (fit?.in === "now" && info.channel !== "experimental") return { changed: false, name, note: `${name} already fits this phase (fit ${fit.fit}); nothing to adopt` };
|
|
228
|
+
current[name] = { version: info.version, early: true, ...(info.channel === "experimental" ? { channel: "experimental" } : {}) };
|
|
229
|
+
cfg.packages = Object.fromEntries(Object.entries(current).sort(([a], [b]) => a.localeCompare(b)));
|
|
230
|
+
writeConfig(dir, cfg);
|
|
231
|
+
record(dir, { entity: CONFIG, activity: "write", agent: agentFromEnv(process.env.MENTURA_ACTOR === "agent" ? "agent" : "person", "cli"), note: `adopted the ${name} package early (U-5)` });
|
|
232
|
+
return { changed: true, name, version: info.version, channel: info.channel, fit: fit?.fit ?? null };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** Undoes an early adoption: the pin goes, and the package fits by its phase prior again. */
|
|
236
|
+
export function drop(dir, name) {
|
|
237
|
+
const cfg = readConfig(dir);
|
|
238
|
+
const current = pins(cfg);
|
|
239
|
+
if (!current[name]?.early) throw new Error(`${name} was not adopted early, so there is nothing to drop`);
|
|
240
|
+
delete current[name];
|
|
241
|
+
cfg.packages = current;
|
|
242
|
+
writeConfig(dir, cfg);
|
|
243
|
+
record(dir, { entity: CONFIG, activity: "write", agent: agentFromEnv(process.env.MENTURA_ACTOR === "agent" ? "agent" : "person", "cli"), note: `dropped the early adoption of ${name} (U-5)` });
|
|
244
|
+
return { changed: true, name };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Updates the installed framework (U-1): a fast-forward pull of the git checkout Naive runs from. A
|
|
249
|
+
* checkout with local changes, or one that cannot fast-forward, is left as it is.
|
|
250
|
+
*/
|
|
251
|
+
export function updateFramework(root = repo) {
|
|
252
|
+
const git = (...a) => spawnSync("git", ["-C", root, ...a], { encoding: "utf8" });
|
|
253
|
+
if (git("rev-parse", "--is-inside-work-tree").stdout.trim() !== "true") return { ok: false, error: `${root} is not a git checkout: install Naive again from its repository` };
|
|
254
|
+
if (git("status", "--porcelain", "--untracked-files=no").stdout.trim()) return { ok: false, error: `${root} has local changes: commit or stash them, then update` };
|
|
255
|
+
const from = registry(root).framework, head = git("rev-parse", "HEAD").stdout.trim();
|
|
256
|
+
const pull = git("pull", "--ff-only");
|
|
257
|
+
if (pull.status !== 0) return { ok: false, error: `could not fast-forward ${root}: ${(pull.stderr || pull.stdout).trim()}` };
|
|
258
|
+
const after = git("rev-parse", "HEAD").stdout.trim();
|
|
259
|
+
return { ok: true, from, to: registry(root).framework, commits: after === head ? 0 : Number(git("rev-list", "--count", `${head}..${after}`).stdout.trim()), head: after };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Staged upgrades (U-3). The copy holds everything but .naive/, _private/ (never sent to an agent) and
|
|
263
|
+
// nested ventures, which upgrade on their own.
|
|
264
|
+
export function snapshot(dir, { skipPrivate = true } = {}) {
|
|
265
|
+
const out = {};
|
|
266
|
+
const walk = (rel) => {
|
|
267
|
+
for (const e of readdirSync(join(dir, rel), { withFileTypes: true })) {
|
|
268
|
+
const r = rel ? `${rel}/${e.name}` : e.name;
|
|
269
|
+
if (!rel && (r === ".naive" || r === ".git" || (skipPrivate && r === "_private"))) continue;
|
|
270
|
+
if (e.isDirectory()) { if (!existsSync(join(dir, r, "venture.json"))) walk(r); }
|
|
271
|
+
else if (e.isFile()) out[r] = sha(readFileSync(join(dir, r)));
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
walk("");
|
|
275
|
+
return out;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const writeDraft = (dir, d) => { mkdirSync(join(dir, STAGE), { recursive: true }); writeFileSync(join(dir, DRAFT), JSON.stringify(d, null, 2) + "\n"); return d; };
|
|
279
|
+
/** Adds to the staged upgrade's draft record (what an agent did, say). */
|
|
280
|
+
export function annotate(dir, extra) {
|
|
281
|
+
const d = draft(dir);
|
|
282
|
+
if (!d) throw new Error("no upgrade is staged");
|
|
283
|
+
return writeDraft(dir, { ...d, ...extra });
|
|
284
|
+
}
|
|
285
|
+
/** The staged upgrade's draft record, or null. */
|
|
286
|
+
export const draft = (dir) => (existsSync(join(dir, DRAFT)) ? load(join(dir, DRAFT)) : null);
|
|
287
|
+
|
|
288
|
+
/** Copies the venture to .naive/upgrade/venture and upgrades the copy. Nothing in the venture changes. */
|
|
289
|
+
export async function stage(dir, { reg = registry(), by = "naive" } = {}) {
|
|
290
|
+
if (existsSync(join(dir, STAGE))) throw new Error(`an upgrade is already staged in ${STAGE}: accept it (--accept --confirm ${CONFIRM}) or reject it (--reject)`);
|
|
291
|
+
const p = plan(dir, { reg });
|
|
292
|
+
if (!p.pending) throw new Error(`${p.venture} is already on Naive ${p.to} with every package pinned: nothing to stage`);
|
|
293
|
+
const base = snapshot(dir);
|
|
294
|
+
const out = join(dir, STAGED);
|
|
295
|
+
for (const f of Object.keys(base)) { mkdirSync(dirname(join(out, f)), { recursive: true }); copyFileSync(join(dir, f), join(out, f)); }
|
|
296
|
+
const result = await upgrade(out, { reg, git: false });
|
|
297
|
+
return writeDraft(dir, { status: "staged", from: p.from, to: p.to, staged_at: now(), by, base, migrations: result.release.migrations.map((m) => ({ id: m.id, moves: m.moves.length, rewrote: m.rewrote.length })), escalated: result.release.escalated, guides: result.release.guides });
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// The checks a staged upgrade must pass before it lands: the venture-wide checkers, every routed JSON
|
|
301
|
+
// record against its schema, and nothing left to upgrade.
|
|
302
|
+
export const CHECKS = ["schema/check-ventures.mjs", "schema/check-provenance.mjs", "schema/decisions.mjs", "schema/check-data-packages.mjs", "schema/check-private.mjs", "schema/check-sources.mjs", "schema/check-where-used.mjs", "schema/check-governance.mjs"];
|
|
303
|
+
|
|
304
|
+
/** Runs the checks on any venture folder: [{ check, passed, output }]. */
|
|
305
|
+
export function runChecks(vdir, { reg = registry() } = {}) {
|
|
306
|
+
const out = CHECKS.map((c) => { const r = spawnSync("node", [join(repo, c), vdir], { encoding: "utf8" }); return { check: c, passed: r.status === 0, output: (r.stdout + r.stderr).trim().slice(-1500) }; });
|
|
307
|
+
const files = Object.keys(snapshot(vdir, { skipPrivate: true })).filter((f) => f.endsWith(".json"));
|
|
308
|
+
const bad = [];
|
|
309
|
+
let n = 0;
|
|
310
|
+
for (const r of routes().filter((x) => x.kind === "record" && x.schema && (x.form ?? "json") === "json")) {
|
|
311
|
+
for (const f of files.filter((f) => r.files.some((g) => glob(g).test(f)))) {
|
|
312
|
+
n++;
|
|
313
|
+
const v = spawnSync("python3", [join(repo, "schema/validate.py"), "--schema", r.schema.replace(/^schema\//, ""), "--file", join(vdir, f)], { encoding: "utf8" });
|
|
314
|
+
if (v.status !== 0) bad.push(`${f} does not match ${r.schema}: ${(v.stdout + v.stderr).trim().split("\n")[0]}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
out.push({ check: "records match their schemas", passed: !bad.length, output: bad.length ? bad.join("\n") : `${n} records valid` });
|
|
318
|
+
let left;
|
|
319
|
+
try { left = plan(vdir, { reg }); } catch (e) { left = { pending: true, error: e.message }; }
|
|
320
|
+
out.push({ check: "nothing left to upgrade", passed: !left.pending, output: left.pending ? (left.error ?? `still on ${left.from}, or a package is not pinned to ${left.to}`) : `on Naive ${left.to}` });
|
|
321
|
+
return out;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** What the staged copy changes: files added, changed and removed (the venture's _private/ is never removed). */
|
|
325
|
+
export function changes(dir) {
|
|
326
|
+
const live = snapshot(dir), staged = snapshot(join(dir, STAGED), { skipPrivate: false });
|
|
327
|
+
return {
|
|
328
|
+
added: Object.keys(staged).filter((f) => !(f in live) && !existsSync(join(dir, f))).sort(),
|
|
329
|
+
changed: Object.keys(staged).filter((f) => (f in live && live[f] !== staged[f]) || (!(f in live) && existsSync(join(dir, f)) && sha(readFileSync(join(dir, f))) !== staged[f])).sort(),
|
|
330
|
+
removed: Object.keys(live).filter((f) => !(f in staged)).sort(),
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/** Runs the checks on the staged copy and records the result: ready, or checks-failed. */
|
|
335
|
+
export function check(dir, { reg = registry() } = {}) {
|
|
336
|
+
const d = draft(dir);
|
|
337
|
+
if (!d) throw new Error("no upgrade is staged: stage one with --stage or --agent");
|
|
338
|
+
const checks = runChecks(join(dir, STAGED), { reg });
|
|
339
|
+
const ok = checks.every((c) => c.passed);
|
|
340
|
+
return writeDraft(dir, { ...d, status: ok ? "ready" : "checks-failed", checked_at: now(), checks, changes: changes(dir) });
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Lands a staged upgrade (U-3): only with the typed confirmation, only when the checks pass again now,
|
|
345
|
+
* and only when the venture has not changed since the copy was made. Its provenance log continues the
|
|
346
|
+
* venture's, so the chain holds; the person's acceptance is the last line.
|
|
347
|
+
*/
|
|
348
|
+
export async function accept(dir, { confirm, by, reg = registry() } = {}) {
|
|
349
|
+
const d = draft(dir);
|
|
350
|
+
if (!d) throw new Error("no upgrade is staged: stage one with --stage or --agent");
|
|
351
|
+
if (confirm !== CONFIRM) throw new Error(`not accepted: type the confirmation (--confirm ${CONFIRM})`);
|
|
352
|
+
const live = snapshot(dir);
|
|
353
|
+
const drift = [...new Set([...Object.keys(live), ...Object.keys(d.base)])].filter((f) => live[f] !== d.base[f]);
|
|
354
|
+
if (drift.length) throw new Error(`the venture changed since the upgrade was staged (${drift.slice(0, 5).join(", ")}): reject it and stage again`);
|
|
355
|
+
const checked = check(dir, { reg });
|
|
356
|
+
if (checked.status !== "ready") throw new Error(`not accepted: the checks fail on the staged copy:\n${checked.checks.filter((c) => !c.passed).map((c) => ` ${c.check}: ${c.output.split("\n").slice(-3).join(" / ")}`).join("\n")}`);
|
|
357
|
+
const ch = checked.changes;
|
|
358
|
+
const clash = ch.changed.filter((f) => f.startsWith("_private/"));
|
|
359
|
+
if (clash.length) throw new Error(`not accepted: the upgrade would overwrite private files that differ (${clash.join(", ")}); move them aside, reject and stage again`);
|
|
360
|
+
const src = join(dir, STAGED);
|
|
361
|
+
for (const f of [...ch.added, ...ch.changed]) { mkdirSync(dirname(join(dir, f)), { recursive: true }); copyFileSync(join(src, f), join(dir, f)); }
|
|
362
|
+
for (const f of ch.removed) rmSync(join(dir, f));
|
|
363
|
+
// Folders the upgrade emptied go too, unless the copy still has them.
|
|
364
|
+
const dirs = [...new Set(ch.removed.flatMap((f) => f.split("/").slice(0, -1).map((_, i, a) => a.slice(0, i + 1).join("/"))))].sort((a, b) => b.length - a.length);
|
|
365
|
+
for (const x of dirs) if (existsSync(join(dir, x)) && !existsSync(join(src, x)) && readdirSync(join(dir, x)).length === 0) rmSync(join(dir, x), { recursive: true });
|
|
366
|
+
rmSync(join(dir, STAGE), { recursive: true, force: true });
|
|
367
|
+
return landed(dir, d, ch, by);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
async function refreshAdapters(dir) {
|
|
371
|
+
try { const { refresh } = await import("../interface/adapters.mjs"); return refresh(dir); } catch (e) { return { error: e.message }; }
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
async function landed(dir, d, ch, by) {
|
|
375
|
+
const rel = `.release/upgrade-${d.to}.json`;
|
|
376
|
+
const e = existsSync(join(dir, rel)) ? record(dir, { entity: rel, activity: "accept", agent: agentFromEnv("person", "cli", by ? { id: by } : {}), note: `accepted the staged upgrade to Naive ${d.to}${d.by && d.by !== "naive" ? ` (worked by ${d.by})` : ""}` }) : null;
|
|
377
|
+
return { accepted: d.to, from: d.from, added: ch.added.length, changed: ch.changed.length, removed: ch.removed.length, provenance: e?.hash ?? null, adapters: await refreshAdapters(dir) };
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/** Discards a staged upgrade. The venture never changed, so nothing is logged. */
|
|
381
|
+
export function reject(dir) {
|
|
382
|
+
if (!existsSync(join(dir, STAGE))) throw new Error("no upgrade is staged");
|
|
383
|
+
rmSync(join(dir, STAGE), { recursive: true, force: true });
|
|
384
|
+
return { rejected: true };
|
|
385
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// "use model" (EE-073): a package lists the steps that call a model. A record written
|
|
2
|
+
// downstream of one of those steps carries agent provenance until a person confirms it
|
|
3
|
+
// or its checks pass.
|
|
4
|
+
|
|
5
|
+
/** "clear" once a person confirmed it or its checks passed. Otherwise "agent". */
|
|
6
|
+
export function provenanceOf({ use_model, confirmed, checksPass }) {
|
|
7
|
+
if (!Array.isArray(use_model) || use_model.length === 0) return "clear";
|
|
8
|
+
if (confirmed || checksPass) return "clear";
|
|
9
|
+
return "agent";
|
|
10
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Validates every record in the repository against its JSON Schema (EE-017).
|
|
2
|
+
|
|
3
|
+
python3 schema/validate.py
|
|
4
|
+
python3 schema/validate.py --schema <name>.schema.json --file <path> one file (used by the interfaces before a write)
|
|
5
|
+
|
|
6
|
+
Needs the jsonschema package (pip install jsonschema). Which files each schema governs comes from schema/data-model.json;
|
|
7
|
+
schema/check-data-model.mjs makes sure no JSON file is left without a record type.
|
|
8
|
+
"""
|
|
9
|
+
import glob, json, sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import jsonschema
|
|
14
|
+
except ImportError:
|
|
15
|
+
sys.exit("validate.py needs jsonschema: pip install jsonschema")
|
|
16
|
+
|
|
17
|
+
root = Path(__file__).resolve().parent.parent
|
|
18
|
+
# The data model names every record type, its schema and where its records live (EE-018).
|
|
19
|
+
# Only JSON records with a schema under schema/ are validated here; the methodology catalog's
|
|
20
|
+
# Markdown records are validated by ee.mjs.
|
|
21
|
+
model = json.loads((root / "schema/data-model.json").read_text())
|
|
22
|
+
RULES = [(r["id"], r["schema"], r.get("form", "json"), r["paths"]) for r in model["records"]
|
|
23
|
+
if r["schema"] and r["schema"].startswith("schema/") and r.get("form", "json") in ("json", "json-list", "json-lines")]
|
|
24
|
+
from referencing import Registry, Resource
|
|
25
|
+
|
|
26
|
+
# Every schema is registered by its $id, so one may $ref another (or itself) by file name.
|
|
27
|
+
schemas = {p.name: json.loads(p.read_text()) for p in (root / "schema").glob("*.schema.json")}
|
|
28
|
+
registry = Registry().with_resources((s.get("$id", n), Resource.from_contents(s)) for n, s in schemas.items())
|
|
29
|
+
failed = checked = 0
|
|
30
|
+
if "--file" in sys.argv:
|
|
31
|
+
one = json.loads(Path(sys.argv[sys.argv.index("--file") + 1]).read_text())
|
|
32
|
+
v = jsonschema.Draft202012Validator(schemas[sys.argv[sys.argv.index("--schema") + 1]], registry=registry, format_checker=jsonschema.FormatChecker())
|
|
33
|
+
errs = [f"{'/'.join(map(str, e.absolute_path)) or '(root)'}: {e.message}" for e in v.iter_errors(one)]
|
|
34
|
+
print("\n".join(errs) if errs else "valid")
|
|
35
|
+
sys.exit(1 if errs else 0)
|
|
36
|
+
# A file matched by two record types' globs is validated once, by the more specific glob (the one with
|
|
37
|
+
# more literal characters): .../departments/products/department.json is a department, not a product.
|
|
38
|
+
best = {}
|
|
39
|
+
for name, schema, form, globs in RULES:
|
|
40
|
+
for g in globs:
|
|
41
|
+
weight = len(g.replace("**/", "").replace("*", ""))
|
|
42
|
+
for f in glob.glob(str(root / g), recursive=True):
|
|
43
|
+
if f not in best or weight > best[f][0]:
|
|
44
|
+
best[f] = (weight, schema, form)
|
|
45
|
+
validators = {}
|
|
46
|
+
for f in sorted(best):
|
|
47
|
+
_, schema, form = best[f]
|
|
48
|
+
v = validators.setdefault(schema, jsonschema.Draft202012Validator(schemas[Path(schema).name], registry=registry, format_checker=jsonschema.FormatChecker()))
|
|
49
|
+
text = Path(f).read_text()
|
|
50
|
+
docs = [json.loads(l) for l in text.splitlines() if l.strip()] if form == "json-lines" else json.loads(text)
|
|
51
|
+
docs = docs if form != "json" else [docs]
|
|
52
|
+
for d in docs:
|
|
53
|
+
checked += 1
|
|
54
|
+
for e in v.iter_errors(d):
|
|
55
|
+
failed += 1
|
|
56
|
+
print(f"{Path(f).relative_to(root)}: {'/'.join(map(str, e.absolute_path)) or '(root)'}: {e.message}")
|
|
57
|
+
print(f"{checked} records checked against their schemas: {'all valid' if not failed else f'{failed} error(s)'}.")
|
|
58
|
+
sys.exit(1 if failed else 0)
|