naive-framework 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -1
- package/docs/decisions/decisions.json +42 -0
- package/docs/reference/ROUTES.md +36 -37
- package/evidence/skills/fidelity-ladder-audit/ladder-census.mjs +2 -1
- package/governance/layer.json +2 -1
- 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 +183 -0
- package/interface/api/server.mjs +4 -2
- package/interface/boundaries.mjs +219 -0
- package/interface/brand.mjs +215 -0
- package/interface/cli/freshness.mjs +59 -0
- package/interface/cli/guard.mjs +6 -0
- package/interface/cli/mentura.mjs +82 -11
- package/interface/cli/naive.mjs +44 -14
- package/interface/context.mjs +525 -0
- package/interface/demo/board.mjs +9 -8
- package/interface/demo/decision-harness.mjs +4 -3
- package/interface/dev/setup.mjs +84 -0
- package/interface/gate-hooks.mjs +37 -0
- package/interface/harness/evals.mjs +10 -9
- package/interface/harness/run.mjs +16 -15
- package/interface/instrumentation.mjs +87 -0
- package/interface/kit-boundary.mjs +73 -0
- package/interface/layer.json +8 -2
- package/interface/mcp/server.mjs +47 -7
- package/interface/package-routes.mjs +197 -0
- package/interface/provenance.mjs +28 -4
- package/interface/reads.mjs +174 -0
- package/interface/release-card.mjs +43 -0
- package/interface/router.mjs +110 -36
- package/interface/skills/naive-setup/SKILL.md +71 -0
- package/interface/skills/naive-setup/artifact.html +83 -0
- package/interface/vitals.mjs +116 -0
- package/interface/writes.mjs +190 -0
- package/knowledge/connectors/catalog.mjs +3 -2
- package/knowledge/connectors/filesystem.mjs +10 -5
- package/knowledge/connectors/index.mjs +3 -2
- package/knowledge/freshness.json +85 -0
- package/knowledge/layer.json +11 -3
- package/knowledge/templates/glossary.md +23 -0
- package/operations/layer.json +10 -3
- package/operations/marketing/check-public.mjs +7 -6
- package/operations/marketing/site/plan.mjs +4 -3
- package/operations/marketing/site/presence.mjs +4 -3
- package/operations/templates/marketing-brand.md +46 -0
- package/operations/templates/public-assets.md +39 -0
- package/package.json +3 -1
- package/packages/catalog.json +8 -0
- package/packages/customers/package.json +21 -1
- package/packages/deals/package.json +27 -0
- package/packages/decisions/package.json +12 -1
- package/packages/finance/frames/fund-without-ceding-control.frame.json +177 -0
- package/packages/foundation/package.json +8 -1
- package/packages/fund/package.json +48 -0
- package/packages/marketing/package.json +10 -4
- package/packages/money/package.json +24 -3
- package/packages/validation/package.json +13 -0
- package/platform/README.md +6 -0
- package/platform/adapter.json +15 -0
- package/platform/integrations/remote-image.mjs +79 -0
- package/platform/integrations/rho.mjs +9 -7
- package/platform/kits/README.md +8 -1
- 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/webhooks/server.mjs +70 -0
- package/purpose/frameworks/idea-map/ideamap.mjs +4 -2
- package/purpose/frameworks/idea-map/route.mjs +5 -4
- package/purpose/frameworks/product-anatomy/anatomy.mjs +2 -1
- package/schema/README.md +1 -0
- package/schema/access.mjs +58 -0
- package/schema/adapter.schema.json +33 -0
- package/schema/add-department.mjs +3 -2
- package/schema/assess-problem.mjs +3 -2
- package/schema/assets.mjs +213 -0
- package/schema/brand.mjs +374 -0
- package/schema/build-release.mjs +61 -0
- package/schema/caching.mjs +506 -0
- package/schema/check-assets.mjs +24 -0
- package/schema/check-brand.mjs +24 -0
- package/schema/check-config.mjs +111 -0
- package/schema/check-data-model.mjs +2 -1
- package/schema/check-data-packages.mjs +5 -4
- package/schema/check-execution.mjs +4 -3
- package/schema/check-nextjs-status.mjs +3 -1
- package/schema/check-people.mjs +84 -0
- package/schema/check-private.mjs +2 -1
- package/schema/check-ready.mjs +6 -5
- package/schema/check-sources.mjs +11 -2
- package/schema/check-where-used.mjs +4 -3
- package/schema/data-model.json +334 -8
- package/schema/deal.schema.json +80 -0
- package/schema/decision-analytics.mjs +2 -1
- package/schema/decisions.mjs +21 -12
- package/schema/examples/frames/judge.mjs +10 -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/foundation.mjs +8 -7
- package/schema/founder.schema.json +72 -0
- package/schema/frame.schema.json +240 -0
- package/schema/frames.mjs +229 -0
- package/schema/freshness-log.schema.json +40 -0
- package/schema/freshness-profiles.schema.json +44 -0
- package/schema/freshness.mjs +474 -0
- package/schema/fund-terms.schema.json +107 -0
- package/schema/fund-thesis.schema.json +87 -0
- package/schema/gate-drafts.mjs +131 -0
- package/schema/gate.mjs +105 -11
- package/schema/glossary.schema.json +25 -0
- package/schema/init-venture.mjs +69 -21
- 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 +145 -15
- package/schema/layer.json +16 -3
- package/schema/marketing-brand.schema.json +116 -0
- package/schema/migrate-venture.mjs +8 -7
- package/schema/migrations/kit-to-package.mjs +95 -0
- package/schema/migrations/package-layout.mjs +90 -0
- package/schema/model-steps.mjs +718 -0
- package/schema/money-summary.schema.json +138 -0
- package/schema/naive-config.mjs +166 -0
- package/schema/naive-config.schema.json +268 -0
- package/schema/need-now.json +171 -0
- package/schema/need-now.mjs +8 -6
- package/schema/packages.mjs +21 -15
- package/schema/payouts.mjs +3 -2
- package/schema/people.schema.json +85 -0
- package/schema/port-venture.mjs +206 -132
- package/schema/public-assets.schema.json +76 -0
- package/schema/release-read.mjs +112 -0
- package/schema/releases.mjs +498 -0
- package/schema/run-handoff.mjs +5 -4
- package/schema/setup.mjs +165 -0
- package/schema/stale.mjs +112 -0
- package/schema/start-release.mjs +41 -0
- package/schema/structure.mjs +187 -0
- package/schema/systems-catalog.json +126 -0
- package/schema/systems-catalog.schema.json +78 -0
- package/schema/time-to-ready.mjs +7 -6
- package/schema/trigger.schema.json +44 -0
- package/schema/triggers.mjs +238 -0
- package/schema/upgrade-registry.schema.json +60 -0
- package/schema/upgrade-venture.mjs +96 -118
- package/schema/upgrades.json +69 -0
- package/schema/upgrades.mjs +386 -0
- package/schema/validate.py +19 -10
- package/schema/venture-paths.mjs +85 -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 +61 -0
- package/schema/workspace.schema.json +5 -1
package/schema/kits.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Mentura kits, as the framework sees them (EE-071): data only. A kit lives at
|
|
2
|
+
// platform/kits/<name>/kit.json and extends one Naive package or one framework command. The framework
|
|
3
|
+
// reads a kit's manifest by path and runs its entry as a separate process, never importing platform
|
|
4
|
+
// code (schema/check-boundary.mjs), the way a Next.js build loads a deployment adapter it was pointed
|
|
5
|
+
// at. A copy of the framework without platform/ has no kits, and nothing here fails because of it.
|
|
6
|
+
|
|
7
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
|
|
10
|
+
const repo = new URL("..", import.meta.url).pathname;
|
|
11
|
+
export const KITS = "platform/kits";
|
|
12
|
+
|
|
13
|
+
/** Every installed kit: { name, path, dir, ...kit.json }. */
|
|
14
|
+
export function kits(root = process.env.NAIVE_KITS ?? join(repo, KITS)) {
|
|
15
|
+
if (!existsSync(root)) return [];
|
|
16
|
+
return readdirSync(root, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync(join(root, e.name, "kit.json")))
|
|
17
|
+
.map((e) => ({ ...JSON.parse(readFileSync(join(root, e.name, "kit.json"), "utf8")), dir: join(root, e.name), path: join(root, e.name, "kit.json") }));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** The kit that extends a framework command (such as "upgrade --agent"), or null. */
|
|
21
|
+
export const kitFor = (command) => kits().find((k) => k.extends?.command === command) ?? null;
|
|
22
|
+
|
|
23
|
+
/** One kit by name, or null. */
|
|
24
|
+
export const kit = (name) => kits().find((k) => k.name === name) ?? null;
|
|
@@ -2,27 +2,75 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "knowledge-sources.schema.json",
|
|
4
4
|
"title": "Knowledge sources",
|
|
5
|
-
"description": "A venture's source map (<venture>/knowledge/sources.json, EE-037): the sources its records live in and which record types live where. Optional: a record type it does not name, and every record of a venture without one, lives in the venture's own folder (the implicit `venture` source). The venture decides its own layout; Mentura does not. Rules make it a source-of-truth matrix: a system of record per record type, attribute and context, written for a fast model to read (EE-042). Each source names a connector from the registry (an integration with a `connector` in knowledge/tooling/integrations.json). Credentials are named by environment variable, never stored.",
|
|
5
|
+
"description": "A venture's source map (<venture>/knowledge/sources.json, EE-037): the sources its records live in and which record types live where. Optional: a record type it does not name, and every record of a venture without one, lives in the venture's own folder (the implicit `venture` source). The venture decides its own layout; Mentura does not. Rules make it a source-of-truth matrix: a system of record per record type, attribute and context, written for a fast model to read (EE-042). Each source names a connector from the registry (an integration with a `connector` in knowledge/tooling/integrations.json). Credentials are named by environment variable, never stored. Beside the sources Naive reads records from, `functions` says where each of the venture's functions keeps its truth outside Naive (EE-083): the repo, hosting and analytics for the product, a payments or store account for sales, the bank for money, a folder or signing service for legal documents. Those are pointers to systems of record; a system Naive reads through code is connected, one it only knows of is pointed. `truth` says where the venture's source of truth as a whole lives.",
|
|
6
6
|
"type": "object",
|
|
7
|
-
"required": [
|
|
7
|
+
"required": [
|
|
8
|
+
"sources",
|
|
9
|
+
"records"
|
|
10
|
+
],
|
|
8
11
|
"additionalProperties": false,
|
|
9
12
|
"properties": {
|
|
10
13
|
"sources": {
|
|
11
14
|
"type": "array",
|
|
12
15
|
"items": {
|
|
13
16
|
"type": "object",
|
|
14
|
-
"required": [
|
|
17
|
+
"required": [
|
|
18
|
+
"id",
|
|
19
|
+
"connector"
|
|
20
|
+
],
|
|
15
21
|
"properties": {
|
|
16
|
-
"id": {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
|
|
22
|
+
"id": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"pattern": "^[a-z][a-z0-9-]*$",
|
|
25
|
+
"not": {
|
|
26
|
+
"const": "venture"
|
|
27
|
+
},
|
|
28
|
+
"description": "The source's id; `venture` is reserved for the venture's own folder"
|
|
29
|
+
},
|
|
30
|
+
"connector": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "An integration id with a connector: filesystem, github"
|
|
33
|
+
},
|
|
34
|
+
"writes": {
|
|
35
|
+
"enum": [
|
|
36
|
+
"direct",
|
|
37
|
+
"pull-request",
|
|
38
|
+
"none"
|
|
39
|
+
],
|
|
40
|
+
"description": "How writes reach it; the connector's default when left out"
|
|
41
|
+
},
|
|
42
|
+
"root": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"description": "filesystem: the folder, relative to the venture folder or absolute. github: the folder inside the repository"
|
|
45
|
+
},
|
|
46
|
+
"repo": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"pattern": "^[\\w.-]+/[\\w.-]+$",
|
|
49
|
+
"description": "github: owner/name"
|
|
50
|
+
},
|
|
51
|
+
"ref": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"description": "github: the branch (default main)"
|
|
54
|
+
},
|
|
55
|
+
"token": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"pattern": "^[A-Z][A-Z0-9_]*$",
|
|
58
|
+
"description": "github: the environment variable holding a token (default GITHUB_TOKEN)"
|
|
59
|
+
},
|
|
60
|
+
"api": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "github: the API base, for GitHub Enterprise"
|
|
63
|
+
},
|
|
64
|
+
"search": {
|
|
65
|
+
"enum": [
|
|
66
|
+
"api",
|
|
67
|
+
"scan"
|
|
68
|
+
],
|
|
69
|
+
"description": "github: code search (default) or a scan of the files"
|
|
70
|
+
},
|
|
71
|
+
"note": {
|
|
72
|
+
"type": "string"
|
|
73
|
+
}
|
|
26
74
|
},
|
|
27
75
|
"additionalProperties": false
|
|
28
76
|
}
|
|
@@ -30,7 +78,9 @@
|
|
|
30
78
|
"records": {
|
|
31
79
|
"type": "object",
|
|
32
80
|
"description": "Record type id (from schema/data-model.json) -> source id. Unnamed record types stay in the venture folder.",
|
|
33
|
-
"additionalProperties": {
|
|
81
|
+
"additionalProperties": {
|
|
82
|
+
"type": "string"
|
|
83
|
+
}
|
|
34
84
|
},
|
|
35
85
|
"rules": {
|
|
36
86
|
"type": "array",
|
|
@@ -125,6 +175,86 @@
|
|
|
125
175
|
}
|
|
126
176
|
}
|
|
127
177
|
},
|
|
128
|
-
"note": {
|
|
178
|
+
"note": {
|
|
179
|
+
"type": "string"
|
|
180
|
+
},
|
|
181
|
+
"truth": {
|
|
182
|
+
"type": "string",
|
|
183
|
+
"description": "local: this device is the source of truth; otherwise the address of the host every system is backed up to or hosted on (EE-083)"
|
|
184
|
+
},
|
|
185
|
+
"functions": {
|
|
186
|
+
"type": "object",
|
|
187
|
+
"description": "Each function's systems of record, by department id (operations/departments.json) or legal (EE-083)",
|
|
188
|
+
"propertyNames": {
|
|
189
|
+
"enum": [
|
|
190
|
+
"strategy",
|
|
191
|
+
"products",
|
|
192
|
+
"marketing-and-sales",
|
|
193
|
+
"supply-chain",
|
|
194
|
+
"service-delivery",
|
|
195
|
+
"customer-service",
|
|
196
|
+
"human-capital",
|
|
197
|
+
"it",
|
|
198
|
+
"finance",
|
|
199
|
+
"assets",
|
|
200
|
+
"risk-and-compliance",
|
|
201
|
+
"external-relationships",
|
|
202
|
+
"capabilities",
|
|
203
|
+
"legal"
|
|
204
|
+
]
|
|
205
|
+
},
|
|
206
|
+
"additionalProperties": {
|
|
207
|
+
"type": "object",
|
|
208
|
+
"required": [
|
|
209
|
+
"systems"
|
|
210
|
+
],
|
|
211
|
+
"additionalProperties": false,
|
|
212
|
+
"properties": {
|
|
213
|
+
"systems": {
|
|
214
|
+
"type": "array",
|
|
215
|
+
"items": {
|
|
216
|
+
"type": "object",
|
|
217
|
+
"required": [
|
|
218
|
+
"system",
|
|
219
|
+
"status"
|
|
220
|
+
],
|
|
221
|
+
"additionalProperties": false,
|
|
222
|
+
"properties": {
|
|
223
|
+
"system": {
|
|
224
|
+
"type": "string",
|
|
225
|
+
"description": "A system id from schema/systems-catalog.json"
|
|
226
|
+
},
|
|
227
|
+
"address": {
|
|
228
|
+
"type": "string"
|
|
229
|
+
},
|
|
230
|
+
"source": {
|
|
231
|
+
"type": "string",
|
|
232
|
+
"description": "The source in `sources` that reads it, when it is one"
|
|
233
|
+
},
|
|
234
|
+
"status": {
|
|
235
|
+
"enum": [
|
|
236
|
+
"connected",
|
|
237
|
+
"pointed"
|
|
238
|
+
],
|
|
239
|
+
"description": "connected: read by code (a connector or an integration); pointed: known, not read yet"
|
|
240
|
+
},
|
|
241
|
+
"synced": {
|
|
242
|
+
"type": "string",
|
|
243
|
+
"format": "date-time"
|
|
244
|
+
},
|
|
245
|
+
"fixture": {
|
|
246
|
+
"type": "boolean",
|
|
247
|
+
"description": "The last sync replayed a saved answer, not the live system"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
"note": {
|
|
253
|
+
"type": "string",
|
|
254
|
+
"description": "What the founder said about this function, in their words"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
129
259
|
}
|
|
130
260
|
}
|
package/schema/layer.json
CHANGED
|
@@ -16,12 +16,19 @@
|
|
|
16
16
|
"need-now",
|
|
17
17
|
"provenance",
|
|
18
18
|
"venture-packages",
|
|
19
|
-
"venture-package"
|
|
19
|
+
"venture-package",
|
|
20
|
+
"release",
|
|
21
|
+
"naive-config",
|
|
22
|
+
"venture-types",
|
|
23
|
+
"frame",
|
|
24
|
+
"upgrade-registry",
|
|
25
|
+
"kit"
|
|
20
26
|
],
|
|
21
27
|
"reads": [
|
|
22
28
|
"product",
|
|
23
29
|
"account",
|
|
24
|
-
"decision"
|
|
30
|
+
"decision",
|
|
31
|
+
"team-plan"
|
|
25
32
|
],
|
|
26
33
|
"writes": [],
|
|
27
34
|
"checks": [
|
|
@@ -39,7 +46,13 @@
|
|
|
39
46
|
"schema/packages.mjs",
|
|
40
47
|
"schema/packages-test.mjs",
|
|
41
48
|
"schema/decision-analytics.mjs",
|
|
42
|
-
"schema/decision-analytics-test.mjs"
|
|
49
|
+
"schema/decision-analytics-test.mjs",
|
|
50
|
+
"schema/check-config.mjs",
|
|
51
|
+
"schema/gate-test.mjs",
|
|
52
|
+
"schema/upgrades.mjs",
|
|
53
|
+
"schema/upgrades-test.mjs",
|
|
54
|
+
"schema/triggers.mjs",
|
|
55
|
+
"schema/stale.mjs"
|
|
43
56
|
],
|
|
44
57
|
"gaps": [],
|
|
45
58
|
"name": "system"
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "marketing-brand.schema.json",
|
|
4
|
+
"title": "Brand",
|
|
5
|
+
"description": "The venture's brand tokens, in the marketing package at marketing/brand.json: colors, typefaces with their licenses, the font each role uses, voice rules (the global stylesheet for words), the logo and marks, outside design systems by reference, and scopes where a route prefix overrides the venture brand (nearer context wins). Read by every agent's layout and every interface; checked by schema/check-brand.mjs. Translates Next.js global CSS, next/font and file-based icons (Y-3, Y-4, Y-5, T-1, T-2, P-24). Version 0.x, unevaluated.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["version", "venture"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"$defs": {
|
|
10
|
+
"colors": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"description": "Token name -> hex color",
|
|
13
|
+
"propertyNames": { "pattern": "^[a-z][a-z0-9-]*$" },
|
|
14
|
+
"additionalProperties": { "type": "string", "pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$" }
|
|
15
|
+
},
|
|
16
|
+
"fonts": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"description": "Role (body, heading, mono, display...) -> typeface id",
|
|
19
|
+
"propertyNames": { "pattern": "^[a-z][a-z0-9-]*$" },
|
|
20
|
+
"additionalProperties": { "type": "string" }
|
|
21
|
+
},
|
|
22
|
+
"rule": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"required": ["id", "avoid"],
|
|
25
|
+
"additionalProperties": false,
|
|
26
|
+
"properties": {
|
|
27
|
+
"id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
|
|
28
|
+
"avoid": { "oneOf": [{ "type": "string", "minLength": 1 }, { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } }], "description": "A phrase, or phrases, the venture's words never use; matched as whole words, ignoring case" },
|
|
29
|
+
"use": { "type": "string", "description": "What to write instead" },
|
|
30
|
+
"why": { "type": "string" }
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"voice": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"additionalProperties": false,
|
|
36
|
+
"properties": {
|
|
37
|
+
"tone": { "type": "array", "items": { "type": "string" }, "description": "How the venture sounds, in a few words each" },
|
|
38
|
+
"rules": { "type": "array", "items": { "$ref": "#/$defs/rule" } }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"properties": {
|
|
43
|
+
"version": { "type": "string" },
|
|
44
|
+
"venture": { "type": "string" },
|
|
45
|
+
"name": { "type": "string", "description": "The name as the brand writes it" },
|
|
46
|
+
"colors": { "$ref": "#/$defs/colors" },
|
|
47
|
+
"typefaces": {
|
|
48
|
+
"type": "array",
|
|
49
|
+
"description": "Each typeface, defined once with its license (T-1). self-hosted: its files are in public/ and registered, so a browser makes no outside request; system: the reader's own fonts; remote: served from another host (the check fails it)",
|
|
50
|
+
"items": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"required": ["id", "family", "source"],
|
|
53
|
+
"additionalProperties": false,
|
|
54
|
+
"properties": {
|
|
55
|
+
"id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
|
|
56
|
+
"family": { "type": "string" },
|
|
57
|
+
"source": { "enum": ["self-hosted", "system", "remote"] },
|
|
58
|
+
"license": { "type": "string", "description": "An SPDX id such as OFL-1.1, or owned, or licensed" },
|
|
59
|
+
"files": { "type": "array", "items": { "type": "string", "pattern": "^public/" } },
|
|
60
|
+
"url": { "type": "string" },
|
|
61
|
+
"fallback": { "type": "array", "items": { "type": "string" } },
|
|
62
|
+
"credit": { "type": "string" }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"fonts": { "$ref": "#/$defs/fonts", "description": "The font each role uses everywhere, as the root layout applies it (T-2)" },
|
|
67
|
+
"voice": { "$ref": "#/$defs/voice" },
|
|
68
|
+
"marks": {
|
|
69
|
+
"type": "array",
|
|
70
|
+
"description": "The logo and marks (P-24), each a registered file in public/",
|
|
71
|
+
"items": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"required": ["kind", "asset"],
|
|
74
|
+
"additionalProperties": false,
|
|
75
|
+
"properties": {
|
|
76
|
+
"kind": { "enum": ["logo", "icon", "apple-icon", "favicon"] },
|
|
77
|
+
"asset": { "type": "string", "pattern": "^public/" },
|
|
78
|
+
"use": { "type": "string" }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"design_systems": {
|
|
83
|
+
"type": "array",
|
|
84
|
+
"description": "Outside design systems the brand builds on, by reference: linked, with a version and license, never copied in (Y-4)",
|
|
85
|
+
"items": {
|
|
86
|
+
"type": "object",
|
|
87
|
+
"required": ["id", "name", "url", "license"],
|
|
88
|
+
"additionalProperties": false,
|
|
89
|
+
"properties": {
|
|
90
|
+
"id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
|
|
91
|
+
"name": { "type": "string" },
|
|
92
|
+
"url": { "type": "string" },
|
|
93
|
+
"version": { "type": "string" },
|
|
94
|
+
"license": { "type": "string" },
|
|
95
|
+
"uses": { "type": "array", "items": { "type": "string" }, "description": "What the venture takes from it" }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"scopes": {
|
|
100
|
+
"type": "array",
|
|
101
|
+
"description": "Overrides for a route prefix (a package such as investors, or one item such as investors/deck). Nearer context wins: a deeper prefix over a shallower one, any scope over the venture brand (Y-5, T-2)",
|
|
102
|
+
"items": {
|
|
103
|
+
"type": "object",
|
|
104
|
+
"required": ["for"],
|
|
105
|
+
"additionalProperties": false,
|
|
106
|
+
"properties": {
|
|
107
|
+
"for": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*(/[a-z0-9][a-z0-9-]*)*$" },
|
|
108
|
+
"colors": { "$ref": "#/$defs/colors" },
|
|
109
|
+
"fonts": { "$ref": "#/$defs/fonts" },
|
|
110
|
+
"voice": { "$ref": "#/$defs/voice" },
|
|
111
|
+
"note": { "type": "string" }
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -21,6 +21,7 @@ import { fileURLToPath } from "node:url";
|
|
|
21
21
|
import { call, routes } from "../interface/router.mjs";
|
|
22
22
|
import { agentFromEnv, record as prov } from "../interface/provenance.mjs";
|
|
23
23
|
import { propose } from "./decisions.mjs";
|
|
24
|
+
import { ventureFile } from "./venture-paths.mjs";
|
|
24
25
|
|
|
25
26
|
export const PLAN = ".release/migrate-plan.json";
|
|
26
27
|
const MAX_FILE = 512 * 1024;
|
|
@@ -117,7 +118,7 @@ Files: ${JSON.stringify(Object.fromEntries(given.map((f) => [f.path, f.text])))}
|
|
|
117
118
|
/** Writes the plan into the venture and proposes one open decision per function it touches. */
|
|
118
119
|
export function proposeDecisions(dir, p) {
|
|
119
120
|
mkdirSync(join(dir, dirname(PLAN)), { recursive: true });
|
|
120
|
-
writeFileSync(
|
|
121
|
+
writeFileSync(ventureFile(dir, PLAN), JSON.stringify(p, null, 2) + "\n");
|
|
121
122
|
prov(dir, { entity: PLAN, activity: "draft", agent: agentFromEnv("agent", "migrate", { id: "naive-migrate" }), note: `migrate plan from ${p.from}: ${p.items.length} records, ${p.left_behind.length} left behind` });
|
|
122
123
|
const groups = new Map();
|
|
123
124
|
for (const it of p.items) groups.set(functionOf(it.route), [...(groups.get(functionOf(it.route)) ?? []), it]);
|
|
@@ -139,8 +140,8 @@ const answerOf = (d) => { const a = String(d?.answer ?? "").toLowerCase(); retur
|
|
|
139
140
|
|
|
140
141
|
/** Writes what a person decided, through the router. Open decisions wait. */
|
|
141
142
|
export async function apply(dir) {
|
|
142
|
-
const p = load(
|
|
143
|
-
const decisionOf = (fn) => { const f = join(dir, "decisions", `migrate-${fn}.decision.json`); return existsSync(f) ? load(f) : null; };
|
|
143
|
+
const p = load(ventureFile(dir, PLAN));
|
|
144
|
+
const decisionOf = (fn) => { const f = join(ventureFile(dir, "decisions"), `migrate-${fn}.decision.json`); return existsSync(f) ? load(f) : null; };
|
|
144
145
|
const done = { brought: 0, drafted: 0, pointed: 0, left: 0, waiting: 0, failed: 0 };
|
|
145
146
|
let pointed = false;
|
|
146
147
|
for (const it of p.items.filter((x) => x.status === "planned")) {
|
|
@@ -157,7 +158,7 @@ export async function apply(dir) {
|
|
|
157
158
|
done[it.status]++;
|
|
158
159
|
}
|
|
159
160
|
if (pointed) {
|
|
160
|
-
const f = join(dir, "knowledge/sources.json");
|
|
161
|
+
const f = join(ventureFile(dir, "knowledge/sources.json"));
|
|
161
162
|
const s = existsSync(f) ? load(f) : { sources: [], records: {} };
|
|
162
163
|
const id = slug(basename(p.from));
|
|
163
164
|
if (!s.sources.some((x) => x.id === id)) s.sources.push({ id, connector: "filesystem", writes: "none", root: p.from, note: "migrate: a person chose to point to these files rather than rewrite them" });
|
|
@@ -165,7 +166,7 @@ export async function apply(dir) {
|
|
|
165
166
|
writeFileSync(f, JSON.stringify(s, null, 2) + "\n");
|
|
166
167
|
prov(dir, { entity: "knowledge/sources.json", activity: "write", agent: agentFromEnv("agent", "migrate", { id: "naive-migrate" }), note: `points to ${p.from}, read-only` });
|
|
167
168
|
}
|
|
168
|
-
writeFileSync(
|
|
169
|
+
writeFileSync(ventureFile(dir, PLAN), JSON.stringify(p, null, 2) + "\n");
|
|
169
170
|
return done;
|
|
170
171
|
}
|
|
171
172
|
|
|
@@ -176,7 +177,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
|
|
176
177
|
if (!dir || !existsSync(join(dir, "venture.json"))) { console.error("usage: node schema/migrate-venture.mjs --from <project> --venture <dir> | --venture <dir> --apply"); process.exit(2); }
|
|
177
178
|
try {
|
|
178
179
|
if (args.includes("--apply")) {
|
|
179
|
-
if (!existsSync(
|
|
180
|
+
if (!existsSync(ventureFile(dir, PLAN))) { console.error(`no plan at ${ventureFile(dir, PLAN)}: run with --from first`); process.exit(1); }
|
|
180
181
|
const d = await apply(dir);
|
|
181
182
|
console.log(Object.entries(d).filter(([, n]) => n).map(([k, n]) => `${n} ${k}`).join(", ") || "nothing to do");
|
|
182
183
|
} else {
|
|
@@ -186,7 +187,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
|
|
186
187
|
for (const i of p.items) console.log(`${i.id} ${i.from.join(", ")} -> ${i.route} (${i.reshaping})`);
|
|
187
188
|
for (const l of p.left_behind) console.log(`left ${l.from} (${l.why})`);
|
|
188
189
|
console.log(`\n${p.items.length} records planned, ${p.left_behind.length} left behind. Nothing is written yet.`);
|
|
189
|
-
if (decisions.length) console.log(`Read ${relative(process.cwd(),
|
|
190
|
+
if (decisions.length) console.log(`Read ${relative(process.cwd(), ventureFile(dir, PLAN))}, then decide ${decisions.join(", ")} with mentura decide (answer "bring in", "point to them" or "leave them"), then run with --apply.`);
|
|
190
191
|
}
|
|
191
192
|
} catch (e) { console.error(e.message); process.exit(1); }
|
|
192
193
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Migration kit-to-package (framework 0.3.0, EE-071): packages are Naive's, kits are Mentura's. The
|
|
2
|
+
// first record migration, like a Next.js codemod that rewrites code for a renamed API:
|
|
3
|
+
//
|
|
4
|
+
// 1. naive.config.json: before 0.3.0, `kits` listed the venture's Naive packages. A name that is a
|
|
5
|
+
// Naive package moves into `packages` (pinned by the upgrader); a Mentura kit stays in `kits`; any
|
|
6
|
+
// other name is escalated, never guessed.
|
|
7
|
+
// 2. Routes inside records: decision unlocks, the team plan's route globs (who may read and write
|
|
8
|
+
// what) and the where-used list's parent routes still name layer and kit routes
|
|
9
|
+
// (purpose/validation/solution). Each is rewritten to its package route through the route aliases
|
|
10
|
+
// (validation/solution), so access and locks keep meaning what they meant. A glob that spans
|
|
11
|
+
// routes now in several packages (purpose/**) cannot be rewritten safely and is escalated.
|
|
12
|
+
//
|
|
13
|
+
// Every change goes through ctx (schema/upgrades.mjs).
|
|
14
|
+
|
|
15
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { ventureFile } from "../venture-paths.mjs";
|
|
18
|
+
|
|
19
|
+
export const id = "kit-to-package";
|
|
20
|
+
export const describe = "Moves Naive packages out of naive.config.json kits into packages, and rewrites layer and kit routes inside records (decision unlocks, team-plan access, where-used parents) to package routes";
|
|
21
|
+
|
|
22
|
+
const repo = new URL("../..", import.meta.url).pathname;
|
|
23
|
+
|
|
24
|
+
function aliases() {
|
|
25
|
+
const f = process.env.MENTURA_ROUTE_ALIASES ?? join(repo, "interface/route-aliases.json");
|
|
26
|
+
// Longest first, so purpose/validation/problem wins over a shorter alias it starts with.
|
|
27
|
+
return existsSync(f) ? JSON.parse(readFileSync(f, "utf8")).aliases.slice().sort((a, b) => b.from.length - a.from.length) : [];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** A route or route glob rewritten through the aliases: { to } when it moved, { escalate } when it spans moved routes, else null. */
|
|
31
|
+
export function rewriteRoute(route, list = aliases()) {
|
|
32
|
+
if (typeof route !== "string") return null;
|
|
33
|
+
const hit = list.find((a) => route === a.from || route.startsWith(`${a.from}/`));
|
|
34
|
+
if (hit) return { to: hit.to + route.slice(hit.from.length), alias: hit };
|
|
35
|
+
const star = route.indexOf("*");
|
|
36
|
+
if (star >= 0) {
|
|
37
|
+
const head = route.slice(0, star).replace(/\/$/, "");
|
|
38
|
+
// A glob from the root (**) still covers every route after the move.
|
|
39
|
+
const spans = head === "" ? [] : list.filter((a) => a.from === head || a.from.startsWith(`${head}/`));
|
|
40
|
+
if (spans.length) return { escalate: `${route} spans routes that moved to ${[...new Set(spans.map((a) => a.to.split("/")[0]))].join(", ")}` };
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function apply(dir, ctx) {
|
|
46
|
+
const list = aliases();
|
|
47
|
+
|
|
48
|
+
// 1. kits that are Naive packages become packages.
|
|
49
|
+
const cfg = ctx.config;
|
|
50
|
+
if (Array.isArray(cfg.kits) && cfg.kits.length) {
|
|
51
|
+
const keep = [];
|
|
52
|
+
for (const name of cfg.kits) {
|
|
53
|
+
if (existsSync(join(repo, "packages", name, "package.json"))) {
|
|
54
|
+
cfg.packages = { ...(cfg.packages ?? {}), [name]: cfg.packages?.[name] ?? {} };
|
|
55
|
+
ctx.note(`naive.config.json: ${name} is a Naive package, so it moved from kits to packages`);
|
|
56
|
+
} else if (existsSync(join(repo, "platform/kits", name, "kit.json"))) keep.push(name);
|
|
57
|
+
else { keep.push(name); ctx.escalate(`naive.config.json: kits names ${name}, which is neither a Naive package nor a Mentura kit; left as it is`); }
|
|
58
|
+
}
|
|
59
|
+
if (keep.length !== cfg.kits.length) ctx.configChanged();
|
|
60
|
+
if (keep.length) cfg.kits = keep; else delete cfg.kits;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 2. Routes inside records.
|
|
64
|
+
const rewrite = (file, value, where) => {
|
|
65
|
+
const r = rewriteRoute(value, list);
|
|
66
|
+
if (!r) return value;
|
|
67
|
+
if (r.escalate) { ctx.escalate(`${file}: ${where} ${r.escalate}; rewrite it yourself`); return value; }
|
|
68
|
+
return r.to;
|
|
69
|
+
};
|
|
70
|
+
const rewriteFile = (file, fn) => {
|
|
71
|
+
if (!existsSync(ventureFile(dir, file))) return;
|
|
72
|
+
const before = readFileSync(ventureFile(dir, file), "utf8");
|
|
73
|
+
const rec = JSON.parse(before);
|
|
74
|
+
fn(rec);
|
|
75
|
+
const after = JSON.stringify(rec, null, 2) + "\n";
|
|
76
|
+
if (after.trim() !== before.trim()) ctx.write(file, after, { note: "routes renamed from layer and kit routes to package routes (EE-071)" });
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const decisionFiles = (sub = "") => readdirSync(ventureFile(dir, sub), { withFileTypes: true }).flatMap((e) => {
|
|
80
|
+
const rel = sub ? `${sub}/${e.name}` : e.name;
|
|
81
|
+
if (e.isDirectory()) return e.name.startsWith(".") || e.name.startsWith("_") || existsSync(join(dir, rel, "venture.json")) ? [] : decisionFiles(rel);
|
|
82
|
+
return e.name.endsWith(".decision.json") ? [rel] : [];
|
|
83
|
+
});
|
|
84
|
+
for (const f of decisionFiles()) rewriteFile(f, (d) => {
|
|
85
|
+
for (const u of d.unlocks ?? []) if (Array.isArray(u.routes)) u.routes = u.routes.map((g) => rewrite(f, g, "unlocks route"));
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
for (const f of ["people/team-plan.json", "operations/team-plan.json"]) rewriteFile(f, (p) => {
|
|
89
|
+
for (const role of p.roles ?? []) for (const k of ["read", "write"]) if (Array.isArray(role.routes?.[k])) role.routes[k] = role.routes[k].map((g) => rewrite(f, g, `role ${role.id} ${k}`));
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
rewriteFile("knowledge/where-used.json", (w) => {
|
|
93
|
+
for (const fact of w.facts ?? []) if (fact.parent?.route) fact.parent.route = rewrite("knowledge/where-used.json", fact.parent.route, `fact ${fact.id} parent`);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Migration package-layout (framework 0.2.0, EE-070): moves a venture from the layer layout onto
|
|
2
|
+
// the package folder layout, like a Next.js codemod. Files move with git mv when git tracks them and
|
|
3
|
+
// with a plain rename otherwise. A file with no clear new home is archived under _private/ and
|
|
4
|
+
// escalated for a person, never guessed. Old routes keep resolving through interface/route-aliases.json.
|
|
5
|
+
//
|
|
6
|
+
// Every change goes through ctx (schema/upgrades.mjs), so a dry run (--check) reports the same moves
|
|
7
|
+
// without touching anything, and the upgrader records each one in provenance.
|
|
8
|
+
|
|
9
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { ventureFile } from "../venture-paths.mjs";
|
|
12
|
+
import { layoutOf } from "../venture-paths.mjs";
|
|
13
|
+
|
|
14
|
+
export const id = "package-layout";
|
|
15
|
+
export const describe = "Moves records from the layer folders (purpose/, pillars/, products/, knowledge/) into package folders (foundation/, validation/, product/, marketing/, people/, decisions/)";
|
|
16
|
+
|
|
17
|
+
export function apply(dir, ctx) {
|
|
18
|
+
// A venture in the structured layout (EE-086) is already past this layout: nothing to move.
|
|
19
|
+
if (layoutOf(dir) === "structured") return;
|
|
20
|
+
const load = (p) => JSON.parse(readFileSync(p, "utf8"));
|
|
21
|
+
// A decision file infers its target from the folder it sits in. Stamp that path before the file
|
|
22
|
+
// moves, so the decision still points at the same record.
|
|
23
|
+
const stampDecisions = (folder) => {
|
|
24
|
+
const d = ventureFile(dir, folder);
|
|
25
|
+
if (!existsSync(d)) return;
|
|
26
|
+
for (const f of readdirSync(d).filter((x) => x.endsWith(".decision.json"))) {
|
|
27
|
+
const rec = load(join(d, f));
|
|
28
|
+
if (rec.decides?.path) continue;
|
|
29
|
+
const at = folder.split("/").slice(0, -1).join("/");
|
|
30
|
+
const base = f.split(".")[0];
|
|
31
|
+
rec.decides = { ...(rec.decides ?? {}), path: at ? `${at}/${base}.json` : `${base}.json` };
|
|
32
|
+
ctx.write(`${folder}/${f}`, JSON.stringify(rec, null, 2) + "\n", { note: "stamped the record it decides before the move (EE-070)", log: false });
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const pairs = [
|
|
37
|
+
["purpose/validation/problem.json", "foundation/problem.json"],
|
|
38
|
+
["purpose/icp.json", "foundation/icp.json"],
|
|
39
|
+
["purpose/alignment.json", "foundation/alignment.json"],
|
|
40
|
+
["purpose/telos.draft.md", "foundation/telos.draft.md"],
|
|
41
|
+
["purpose/validation/solution.json", "validation/solution.json"],
|
|
42
|
+
["purpose/validation/go-to-market.json", "validation/go-to-market.json"],
|
|
43
|
+
["operations/team-plan.json", "people/team-plan.json"],
|
|
44
|
+
["pillars/brand.md", "marketing/brand.md"],
|
|
45
|
+
// A venture made since init writes a root AGENTS.md keeps it; the old README becomes the knowledge layout.
|
|
46
|
+
["knowledge/README.md", existsSync(join(dir, "AGENTS.md")) ? "knowledge/AGENTS.md" : "AGENTS.md"],
|
|
47
|
+
["purpose/anatomy.answers.reasoned.json", "product/anatomy.answers.reasoned.json"],
|
|
48
|
+
["purpose/anatomy.matrix.md", "product/anatomy.matrix.md"],
|
|
49
|
+
];
|
|
50
|
+
for (const [a, b] of pairs) ctx.mv(a, b);
|
|
51
|
+
|
|
52
|
+
const list = (rel, ext) => existsSync(ventureFile(dir, rel)) ? readdirSync(ventureFile(dir, rel)).filter((f) => f.endsWith(ext)) : [];
|
|
53
|
+
for (const f of list("products", ".json")) ctx.mv(`products/${f}`, `product/${f}`);
|
|
54
|
+
for (const f of list("purpose/anatomy", ".json")) ctx.mv(`purpose/anatomy/${f}`, `product/anatomy/${f}`);
|
|
55
|
+
|
|
56
|
+
for (const folder of ["purpose/decisions", "purpose/anatomy/decisions", "operations/decisions"]) {
|
|
57
|
+
stampDecisions(folder);
|
|
58
|
+
for (const f of list(folder, ".decision.json")) ctx.mv(`${folder}/${f}`, `decisions/${f}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
for (const f of ["product.md", "business.md"]) {
|
|
62
|
+
if (existsSync(join(ventureFile(dir, "pillars"), f))) {
|
|
63
|
+
ctx.mv(`pillars/${f}`, `_private/pillars/${f}`);
|
|
64
|
+
ctx.escalate(`${f.replace(".md", "")} pillar: the brief names a home only for brand (marketing/). Archived at _private/pillars/${f} rather than guessed.`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
for (const f of list("purpose/research", "")) {
|
|
68
|
+
ctx.mv(`purpose/research/${f}`, `_private/research/${f}`);
|
|
69
|
+
ctx.escalate(`purpose/research/${f}: no package home in the route table. Archived at _private/research/${f}.`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (const gone of ["purpose", "pillars", "knowledge", "products"]) ctx.removeEmpty(gone);
|
|
73
|
+
|
|
74
|
+
const policy = "governance/publication-policy.json";
|
|
75
|
+
if (existsSync(ventureFile(dir, policy))) {
|
|
76
|
+
const text = readFileSync(ventureFile(dir, policy), "utf8");
|
|
77
|
+
if (text.includes("pillars/brand.md")) ctx.write(policy, text.replaceAll("pillars/brand.md", "marketing/brand.md"), { note: "the brand pillar moved to marketing/brand.md (EE-070)" });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
for (const sub of ["raw/dump", "raw/sources", "ideas", "finance", "customers", "investors", "money", "public"]) ctx.keep(sub);
|
|
81
|
+
|
|
82
|
+
// The layout release, as before: the moves this migration made and what it escalated.
|
|
83
|
+
if (ctx.moved.length || ctx.escalated.length) ctx.write(".release/layout.json", JSON.stringify({
|
|
84
|
+
version: 1,
|
|
85
|
+
at: ctx.at,
|
|
86
|
+
note: "Moved onto the package folder layout (EE-070). Old routes stay as aliases for one release.",
|
|
87
|
+
moves: ctx.moved.map(([from, to]) => ({ from, to })),
|
|
88
|
+
escalated: ctx.escalated,
|
|
89
|
+
}, null, 2) + "\n", { activity: "release", note: "package folder layout", derived_from: ctx.moved.map(([, to]) => to) });
|
|
90
|
+
}
|