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
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "systems-catalog.schema.json",
|
|
4
|
+
"title": "Systems catalog",
|
|
5
|
+
"description": "The systems of record create-venture offers per function (schema/systems-catalog.json): each system's kind, what its address looks like, and the code that connects to it, if any.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"version",
|
|
9
|
+
"systems",
|
|
10
|
+
"functions"
|
|
11
|
+
],
|
|
12
|
+
"additionalProperties": false,
|
|
13
|
+
"properties": {
|
|
14
|
+
"version": {
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
"note": {
|
|
18
|
+
"type": "string"
|
|
19
|
+
},
|
|
20
|
+
"systems": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"additionalProperties": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"required": [
|
|
25
|
+
"label",
|
|
26
|
+
"kind",
|
|
27
|
+
"address",
|
|
28
|
+
"connect"
|
|
29
|
+
],
|
|
30
|
+
"additionalProperties": false,
|
|
31
|
+
"properties": {
|
|
32
|
+
"label": {
|
|
33
|
+
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
"kind": {
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
"address": {
|
|
39
|
+
"type": "string"
|
|
40
|
+
},
|
|
41
|
+
"connect": {
|
|
42
|
+
"type": [
|
|
43
|
+
"string",
|
|
44
|
+
"null"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"functions": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"propertyNames": {
|
|
53
|
+
"enum": [
|
|
54
|
+
"strategy",
|
|
55
|
+
"products",
|
|
56
|
+
"marketing-and-sales",
|
|
57
|
+
"supply-chain",
|
|
58
|
+
"service-delivery",
|
|
59
|
+
"customer-service",
|
|
60
|
+
"human-capital",
|
|
61
|
+
"it",
|
|
62
|
+
"finance",
|
|
63
|
+
"assets",
|
|
64
|
+
"risk-and-compliance",
|
|
65
|
+
"external-relationships",
|
|
66
|
+
"capabilities",
|
|
67
|
+
"legal"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
"additionalProperties": {
|
|
71
|
+
"type": "array",
|
|
72
|
+
"items": {
|
|
73
|
+
"type": "string"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
package/schema/time-to-ready.mjs
CHANGED
|
@@ -15,6 +15,7 @@ import { execFileSync } from "node:child_process";
|
|
|
15
15
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
16
16
|
import { join, dirname } from "node:path";
|
|
17
17
|
import { needNow } from "./need-now.mjs";
|
|
18
|
+
import { ventureFile } from "./venture-paths.mjs";
|
|
18
19
|
|
|
19
20
|
const load = (p) => JSON.parse(readFileSync(p, "utf8"));
|
|
20
21
|
const day = (d) => d ? d.slice(0, 10) : null;
|
|
@@ -43,19 +44,19 @@ export function timeToReady(dir) {
|
|
|
43
44
|
const rels = (model.records.find((r) => r.id === type)?.paths ?? []).filter((p) => p.startsWith("instance/**/")).map((p) => p.slice("instance/**/".length));
|
|
44
45
|
return here.filter((x) => rels.some((g) => glob(g).test(x)));
|
|
45
46
|
};
|
|
46
|
-
const seen = (type) => { const fs = where(type); return fs.length ? fs.map((f) => firstSeen(
|
|
47
|
+
const seen = (type) => { const fs = where(type); return fs.length ? fs.map((f) => firstSeen(ventureFile(dir, f))).sort()[0] : null; };
|
|
47
48
|
|
|
48
49
|
// Running.
|
|
49
50
|
const nn = needNow(dir);
|
|
50
|
-
const products = where("product").map((f) => ({ f, p: load(
|
|
51
|
+
const products = where("product").map((f) => ({ f, p: load(ventureFile(dir, f)) }));
|
|
51
52
|
const offered = products.filter(({ p }) => p.status === "live");
|
|
52
53
|
const telosFile = where("telos")[0];
|
|
53
|
-
const telos = telosFile ? load(
|
|
54
|
+
const telos = telosFile ? load(ventureFile(dir, telosFile)) : null;
|
|
54
55
|
const conditions = {
|
|
55
56
|
promise: v.core?.promise ? firstSeen(join(dir, "venture.json")) : null,
|
|
56
|
-
product_offered: offered.length ? offered.map(({ f }) => firstSeen(
|
|
57
|
+
product_offered: offered.length ? offered.map(({ f }) => firstSeen(ventureFile(dir, f))).sort()[0] : null,
|
|
57
58
|
first_account: seen("account"),
|
|
58
|
-
next_exit_criteria: nn.next && telos?.phases?.some((p) => p.phase === nn.next) ? firstSeen(
|
|
59
|
+
next_exit_criteria: nn.next && telos?.phases?.some((p) => p.phase === nn.next) ? firstSeen(ventureFile(dir, telosFile)) : null,
|
|
59
60
|
};
|
|
60
61
|
const missing = Object.entries(conditions).filter(([, d]) => !d).map(([k]) => k);
|
|
61
62
|
const runningOn = missing.length ? null : Object.values(conditions).sort().at(-1);
|
|
@@ -75,7 +76,7 @@ export function timeToReady(dir) {
|
|
|
75
76
|
|
|
76
77
|
// MAD tiers.
|
|
77
78
|
const opsFile = where("validation-operations-readiness")[0];
|
|
78
|
-
const tiers = opsFile ? load(
|
|
79
|
+
const tiers = opsFile ? load(ventureFile(dir, opsFile)).tiers.map((t) => ({ tier: t.tier, ready_on: t.ready_on ?? null, days: days(start, t.ready_on) })) : [];
|
|
79
80
|
|
|
80
81
|
return { venture: v.id, phase: nn.phase, started: start, running: { on: runningOn, days: days(start, runningOn), missing, conditions }, layers: layerRows, tiers };
|
|
81
82
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "trigger.schema.json",
|
|
4
|
+
"title": "Trigger",
|
|
5
|
+
"description": "What starts the next step when something happens in a venture (M-12), as React's event handlers and effects trigger actions. An event is a line of the venture's provenance log: a record written, drafted, accepted, confirmed or moved. A trigger lives in naive.config.json triggers, or in a Mentura kit's automations; a kit's automation also names the package it needs, and runs only once that package is complete. A run that fails is recorded and raised as a decision for the founder, never lost (E-7). schema/triggers.mjs runs them.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["id", "on", "run"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
|
|
11
|
+
"on": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"additionalProperties": false,
|
|
14
|
+
"description": "Which provenance entries start it; every field given must match",
|
|
15
|
+
"properties": {
|
|
16
|
+
"activity": {
|
|
17
|
+
"oneOf": [
|
|
18
|
+
{ "enum": ["write", "draft", "accept", "baseline", "confirm", "move", "release"] },
|
|
19
|
+
{ "type": "array", "minItems": 1, "items": { "enum": ["write", "draft", "accept", "baseline", "confirm", "move", "release"] } }
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"route": { "type": "string", "description": "A glob over the entry's route, such as foundation/**" },
|
|
23
|
+
"entity": { "type": "string", "description": "A glob over the file the entry names" },
|
|
24
|
+
"by": { "enum": ["person", "agent"], "description": "Only entries by a person, or only by an agent" }
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"run": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"additionalProperties": false,
|
|
30
|
+
"description": "The next step: one router call, or a decision proposed for a person",
|
|
31
|
+
"properties": {
|
|
32
|
+
"route": { "type": "string" },
|
|
33
|
+
"action": { "enum": ["read", "check", "run", "write", "layout", "view"] },
|
|
34
|
+
"input": {},
|
|
35
|
+
"propose": { "type": "object", "description": "A decision record (decision-record.schema.json) proposed for a person to decide" }
|
|
36
|
+
},
|
|
37
|
+
"oneOf": [ { "required": ["route", "action"] }, { "required": ["propose"] } ]
|
|
38
|
+
},
|
|
39
|
+
"needs": { "type": "string", "description": "The package that must be complete first (required for a kit's automation)" },
|
|
40
|
+
"once": { "type": "boolean", "description": "Run it once only; later events do not start it again" },
|
|
41
|
+
"enabled": { "type": "boolean", "default": true },
|
|
42
|
+
"note": { "type": "string" }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Triggers (M-12) and what happens when one fails (E-7). In React an event handler or an effect starts
|
|
3
|
+
// an action when something happens; in Naive an event is a line of the venture's provenance log (a
|
|
4
|
+
// record written, drafted, accepted, confirmed or moved), and a trigger starts the next step: one router
|
|
5
|
+
// call, or a decision proposed for a person. Triggers come from naive.config.json `triggers`, and from
|
|
6
|
+
// the automations of the Mentura kits the venture lists in `kits`. A kit's automation runs only once
|
|
7
|
+
// the package it needs is complete; until then its run waits, and is retried on every later event.
|
|
8
|
+
//
|
|
9
|
+
// React's error boundaries do not catch errors in event handlers or async code: you catch and store
|
|
10
|
+
// them yourself. So does this. Every run is stored in <venture>/.naive/triggers.json before the cursor
|
|
11
|
+
// moves past its event. A run that fails, or throws, is raised as a decision for the founder (retry,
|
|
12
|
+
// skip this event, or turn the trigger off) and settled when the founder decides it. A crash of the
|
|
13
|
+
// runner itself is kept by the provenance hook and raised on the next run. Nothing is lost.
|
|
14
|
+
//
|
|
15
|
+
// node schema/triggers.mjs <venture dir> [--json] the triggers, their recent runs and open failures
|
|
16
|
+
// node schema/triggers.mjs <venture dir> --fire run what the new events start (the provenance hook does this)
|
|
17
|
+
//
|
|
18
|
+
// Trigger runs act as agents (id trigger-<id>, via router), so their writes meet the same gates as any
|
|
19
|
+
// agent's: a gated record is drafted for a person. A trigger never fires on its own writes.
|
|
20
|
+
|
|
21
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
22
|
+
import { join } from "node:path";
|
|
23
|
+
import { entries } from "../interface/provenance.mjs";
|
|
24
|
+
import { call, glob } from "../interface/router.mjs";
|
|
25
|
+
import { decisions, propose } from "./decisions.mjs";
|
|
26
|
+
import { kit } from "./kits.mjs";
|
|
27
|
+
import { CONFIG, readConfig, writeConfig } from "./naive-config.mjs";
|
|
28
|
+
import { packages } from "./packages.mjs";
|
|
29
|
+
import { ventureFile } from "./venture-paths.mjs";
|
|
30
|
+
|
|
31
|
+
export const STATE = ".naive/triggers.json";
|
|
32
|
+
export const ERRORS = ".naive/trigger-errors.jsonl";
|
|
33
|
+
const load = (p) => JSON.parse(readFileSync(p, "utf8"));
|
|
34
|
+
const now = () => new Date().toISOString();
|
|
35
|
+
|
|
36
|
+
/** The venture's triggers, from its config and its kits, with what is wrong with any of them. */
|
|
37
|
+
export function triggersOf(dir) {
|
|
38
|
+
const cfg = readConfig(dir);
|
|
39
|
+
const off = new Set(cfg.triggers_off ?? []);
|
|
40
|
+
const problems = [];
|
|
41
|
+
const out = (cfg.triggers ?? []).map((t) => ({ ...t, from: "naive.config.json" }));
|
|
42
|
+
for (const name of cfg.kits ?? []) {
|
|
43
|
+
const k = kit(name);
|
|
44
|
+
if (!k) { problems.push(`kit ${name} is listed in ${CONFIG} kits but is not installed (platform/kits/${name}/kit.json)`); continue; }
|
|
45
|
+
for (const a of k.automations ?? []) {
|
|
46
|
+
if (!a.needs) { problems.push(`kit ${name}: automation ${a.id} names no package it needs, so it never runs (a kit's automation runs only once its package is complete)`); continue; }
|
|
47
|
+
out.push({ ...a, id: `${name}-${a.id}`, from: `kit ${name}` });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const seen = new Set();
|
|
51
|
+
for (const t of out) { if (seen.has(t.id)) problems.push(`trigger ${t.id} is defined twice; the first one runs`); seen.add(t.id); }
|
|
52
|
+
return { triggers: out.filter((t, i) => out.findIndex((x) => x.id === t.id) === i).map((t) => ({ ...t, enabled: t.enabled !== false && !off.has(t.id) })), problems };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Whether a provenance entry starts a trigger. */
|
|
56
|
+
export function matches(t, e) {
|
|
57
|
+
const on = t.on ?? {};
|
|
58
|
+
const acts = on.activity ? [on.activity].flat() : null;
|
|
59
|
+
if (acts && !acts.includes(e.activity)) return false;
|
|
60
|
+
if (on.route && !(e.route && glob(on.route).test(e.route))) return false;
|
|
61
|
+
if (on.entity && !glob(on.entity).test(e.entity)) return false;
|
|
62
|
+
if (on.by && e.agent?.kind !== on.by) return false;
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function readState(dir) {
|
|
67
|
+
const f = ventureFile(dir, STATE);
|
|
68
|
+
if (existsSync(f)) {
|
|
69
|
+
try { const s = load(f); if (Array.isArray(s.runs) && Array.isArray(s.waiting)) return s; } catch {}
|
|
70
|
+
// A state file that cannot be read is kept beside it, and the failure is raised; runs start again from now.
|
|
71
|
+
const kept = `.naive/triggers.unreadable-${Date.now()}.json`;
|
|
72
|
+
renameSync(f, ventureFile(dir, kept));
|
|
73
|
+
return { since: now(), cursor: null, runs: [], waiting: [], unreadable: kept };
|
|
74
|
+
}
|
|
75
|
+
// Triggers start with the events after they were configured, not the venture's whole history.
|
|
76
|
+
const cfg = ventureFile(dir, CONFIG);
|
|
77
|
+
return { since: existsSync(cfg) ? statSync(cfg).mtime.toISOString() : now(), cursor: null, runs: [], waiting: [] };
|
|
78
|
+
}
|
|
79
|
+
const saveState = (dir, s) => { mkdirSync(join(dir, ".naive"), { recursive: true }); writeFileSync(ventureFile(dir, STATE), JSON.stringify(s, null, 2) + "\n"); };
|
|
80
|
+
|
|
81
|
+
const complete = (dir, name) => { try { return packages(dir).complete.includes(name); } catch { return false; } };
|
|
82
|
+
const brief = (x) => (x == null ? null : typeof x === "string" ? x.slice(0, 300) : JSON.stringify(x).slice(0, 300));
|
|
83
|
+
|
|
84
|
+
// E-7: a failed run becomes a decision the founder owes. It fails open: the rest of the venture goes on.
|
|
85
|
+
function raise(dir, run) {
|
|
86
|
+
const v = load(join(dir, "venture.json"));
|
|
87
|
+
// A runner failure can recur across state files, so its id carries the time instead of the run number.
|
|
88
|
+
const id = `trigger-${run.trigger}-failed-${run.trigger === "runner" ? Date.now().toString(36) : run.n}`.replace(/[^a-z0-9-]+/g, "-").slice(0, 80);
|
|
89
|
+
const r = propose(dir, { id, question: `Trigger ${run.trigger} ${run.outcome === "uncaught" ? "crashed" : "failed"} on ${run.activity ?? "an event"} of ${run.entity ?? "the venture"}: ${String(run.error).split("\n")[0].slice(0, 300)}. Retry it, skip this event, or turn the trigger off?`,
|
|
90
|
+
options: ["Retry", "Skip this event", "Turn the trigger off"], layer: "operations", boundary: "fail-open", needed_in: v.phase, decides: { path: CONFIG },
|
|
91
|
+
note: `Raised by schema/triggers.mjs (E-7). The run is kept in ${STATE} as run ${run.n}.` }, { agentId: "naive-triggers", via: "router" });
|
|
92
|
+
return r.ok ? id : null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function runOne(dir, t, e, state, extra = {}) {
|
|
96
|
+
const v = load(join(dir, "venture.json"));
|
|
97
|
+
const run = { n: state.runs.length + 1, trigger: t.id, from: t.from, event: e?.hash ?? null, entity: e?.entity ?? null, activity: e?.activity ?? null, at: now(), ...extra };
|
|
98
|
+
try {
|
|
99
|
+
let r;
|
|
100
|
+
if (t.run.propose) r = propose(dir, t.run.propose, { agentId: `trigger-${t.id}`, via: "router" });
|
|
101
|
+
else if (typeof t.run.route !== "string") throw new Error(`trigger ${t.id} names no route to run`); // a malformed trigger crashes; the router would read it as a broken route table
|
|
102
|
+
else r = await call({ venture: v.id, workspace: dir, route: t.run.route, action: t.run.action, input: t.run.input, actor: "agent", actor_id: `trigger-${t.id}`, via: "router",
|
|
103
|
+
provenance: { derived_from: e?.entity && !/:\/\//.test(e.entity) ? [e.entity] : undefined, note: `trigger ${t.id} on ${e?.activity ?? "retry"} of ${e?.entity ?? "?"}` } });
|
|
104
|
+
run.outcome = r.ok ? "ran" : "failed";
|
|
105
|
+
if (r.ok) run.result = brief(r.result); else run.error = r.error ?? brief(r.result) ?? "the call did not succeed";
|
|
106
|
+
} catch (err) { run.outcome = "uncaught"; run.error = String(err?.stack ?? err).slice(0, 2000); }
|
|
107
|
+
if (run.outcome !== "ran") { const d = raise(dir, run); run.status = d ? "raised" : "unraised"; if (d) run.decision = d; }
|
|
108
|
+
state.runs.push(run);
|
|
109
|
+
saveState(dir, state);
|
|
110
|
+
return run;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Settles failures the founder has decided: retry the run, skip its event, or turn the trigger off. */
|
|
114
|
+
export async function settle(dir, state = readState(dir)) {
|
|
115
|
+
const raised = state.runs.filter((r) => r.status === "raised");
|
|
116
|
+
if (!raised.length) return [];
|
|
117
|
+
const ds = new Map(decisions(dir).decisions.map((d) => [d.id, d]));
|
|
118
|
+
const { triggers } = triggersOf(dir);
|
|
119
|
+
const log = entries(dir);
|
|
120
|
+
const done = [];
|
|
121
|
+
for (const run of raised) {
|
|
122
|
+
const d = ds.get(run.decision);
|
|
123
|
+
if (!d || !["decided", "withdrawn"].includes(d.status)) continue;
|
|
124
|
+
const answer = String(d.answer ?? "").toLowerCase();
|
|
125
|
+
if (d.status === "withdrawn" || answer.startsWith("skip")) run.status = "skipped";
|
|
126
|
+
else if (/\boff\b|disable|turn/.test(answer)) {
|
|
127
|
+
const cfg = readConfig(dir);
|
|
128
|
+
cfg.triggers_off = [...new Set([...(cfg.triggers_off ?? []), run.trigger])];
|
|
129
|
+
writeConfig(dir, cfg);
|
|
130
|
+
run.status = "turned off";
|
|
131
|
+
} else if (answer.startsWith("retry")) {
|
|
132
|
+
run.status = "retried";
|
|
133
|
+
const t = triggers.find((x) => x.id === run.trigger);
|
|
134
|
+
const e = log.find((x) => x.hash === run.event);
|
|
135
|
+
saveState(dir, state);
|
|
136
|
+
if (t && t.enabled) { const again = await runOne(dir, t, e, state, { retry_of: run.n }); run.retried_as = again.n; }
|
|
137
|
+
else run.status = "retried, but the trigger is gone or off";
|
|
138
|
+
} else continue;
|
|
139
|
+
run.settled_at = now();
|
|
140
|
+
done.push(run);
|
|
141
|
+
saveState(dir, state);
|
|
142
|
+
}
|
|
143
|
+
return done;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Runs what the events since the last run start. Returns the runs it made. */
|
|
147
|
+
export async function fire(dir, { rounds = 20 } = {}) {
|
|
148
|
+
const held = process.env.NAIVE_TRIGGERS_ACTIVE;
|
|
149
|
+
process.env.NAIVE_TRIGGERS_ACTIVE = "fire";
|
|
150
|
+
const state = readState(dir);
|
|
151
|
+
const made = [];
|
|
152
|
+
try {
|
|
153
|
+
if (state.unreadable) {
|
|
154
|
+
const run = { n: 1, trigger: "runner", from: "schema/triggers.mjs", at: now(), outcome: "failed", error: `${STATE} could not be read; it is kept at ${state.unreadable} and triggers start again from now` };
|
|
155
|
+
const d = raise(dir, run); run.status = d ? "raised" : "unraised"; if (d) run.decision = d;
|
|
156
|
+
delete state.unreadable; state.runs.push(run); made.push(run); saveState(dir, state);
|
|
157
|
+
}
|
|
158
|
+
// A crash the provenance hook kept is a failure too.
|
|
159
|
+
const ef = ventureFile(dir, ERRORS);
|
|
160
|
+
if (existsSync(ef)) {
|
|
161
|
+
for (const l of readFileSync(ef, "utf8").split("\n").filter(Boolean)) {
|
|
162
|
+
const x = JSON.parse(l);
|
|
163
|
+
const run = { n: state.runs.length + 1, trigger: "runner", from: "provenance hook", event: null, entity: null, activity: null, at: x.at, outcome: "uncaught", error: x.error };
|
|
164
|
+
const d = raise(dir, run); run.status = d ? "raised" : "unraised"; if (d) run.decision = d;
|
|
165
|
+
state.runs.push(run); made.push(run);
|
|
166
|
+
}
|
|
167
|
+
writeFileSync(ef, "");
|
|
168
|
+
saveState(dir, state);
|
|
169
|
+
}
|
|
170
|
+
made.push(...await settle(dir, state));
|
|
171
|
+
const { triggers } = triggersOf(dir);
|
|
172
|
+
const active = triggers.filter((t) => t.enabled);
|
|
173
|
+
const ranOnce = (t) => t.once && state.runs.some((r) => r.trigger === t.id && r.outcome === "ran");
|
|
174
|
+
for (let round = 0; round < rounds; round++) {
|
|
175
|
+
const log = entries(dir);
|
|
176
|
+
const at = state.cursor ? log.findIndex((e) => e.hash === state.cursor) + 1 : log.findIndex((e) => e.at >= state.since);
|
|
177
|
+
const pending = at < 0 ? [] : log.slice(at);
|
|
178
|
+
// Runs waiting on a package go first, once the package is complete.
|
|
179
|
+
for (const w of [...state.waiting]) {
|
|
180
|
+
const t = active.find((x) => x.id === w.trigger);
|
|
181
|
+
if (!t || ranOnce(t)) { state.waiting = state.waiting.filter((x) => x !== w); continue; }
|
|
182
|
+
if (!complete(dir, t.needs)) continue;
|
|
183
|
+
state.waiting = state.waiting.filter((x) => x !== w);
|
|
184
|
+
made.push(await runOne(dir, t, log.find((e) => e.hash === w.event), state, { waited_since: w.at }));
|
|
185
|
+
}
|
|
186
|
+
if (!pending.length) break;
|
|
187
|
+
for (const e of pending) {
|
|
188
|
+
for (const t of active) {
|
|
189
|
+
if (!matches(t, e) || e.agent?.id === `trigger-${t.id}` || ranOnce(t)) continue;
|
|
190
|
+
if (t.needs && !complete(dir, t.needs)) {
|
|
191
|
+
if (!state.waiting.some((w) => w.trigger === t.id)) state.waiting.push({ trigger: t.id, event: e.hash, at: now(), needs: t.needs });
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
made.push(await runOne(dir, t, e, state));
|
|
195
|
+
}
|
|
196
|
+
state.cursor = e.hash;
|
|
197
|
+
saveState(dir, state);
|
|
198
|
+
}
|
|
199
|
+
if (round === rounds - 1 && entries(dir).at(-1)?.hash !== state.cursor) {
|
|
200
|
+
const run = { n: state.runs.length + 1, trigger: "runner", from: "schema/triggers.mjs", at: now(), outcome: "failed", error: `triggers kept starting each other for ${rounds} rounds; the rest wait for the next event` };
|
|
201
|
+
const d = raise(dir, run); run.status = d ? "raised" : "unraised"; if (d) run.decision = d;
|
|
202
|
+
state.runs.push(run); made.push(run); saveState(dir, state);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return made;
|
|
206
|
+
} finally {
|
|
207
|
+
if (held === undefined) delete process.env.NAIVE_TRIGGERS_ACTIVE; else process.env.NAIVE_TRIGGERS_ACTIVE = held;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** The triggers, the latest runs, what waits on a package, and the failures still open. */
|
|
212
|
+
export function report(dir) {
|
|
213
|
+
const { triggers, problems } = triggersOf(dir);
|
|
214
|
+
// Read only: a listing never moves an unreadable state file aside (the next run does, and raises it).
|
|
215
|
+
const s = (() => { try { return load(ventureFile(dir, STATE)); } catch { return { runs: [], waiting: [] }; } })();
|
|
216
|
+
return { triggers: triggers.map((t) => ({ id: t.id, from: t.from, on: t.on, run: t.run.propose ? { propose: t.run.propose.id } : { route: t.run.route, action: t.run.action }, needs: t.needs ?? null, needs_complete: t.needs ? complete(dir, t.needs) : null, enabled: t.enabled, once: !!t.once })),
|
|
217
|
+
problems, runs: s.runs.slice(-10), waiting: s.waiting, open: s.runs.filter((r) => r.status === "raised").map((r) => ({ run: r.n, trigger: r.trigger, error: r.error, decision: r.decision, decide: `mentura decide ${r.decision} --venture ${load(join(dir, "venture.json")).id} --by <your name> --answer "Retry" (or "Skip this event", "Turn the trigger off")` })) };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
221
|
+
const dir = process.argv[2];
|
|
222
|
+
if (!dir || !existsSync(join(dir, "venture.json"))) { console.error("usage: node schema/triggers.mjs <venture dir> [--fire] [--json]"); process.exit(2); }
|
|
223
|
+
const json = process.argv.includes("--json"), quiet = process.argv.includes("--quiet");
|
|
224
|
+
if (process.argv.includes("--fire")) {
|
|
225
|
+
const made = await fire(dir);
|
|
226
|
+
if (json) console.log(JSON.stringify(made, null, 2));
|
|
227
|
+
else if (!quiet) for (const r of made) console.log(`${(r.outcome ?? r.status).padEnd(9)} ${r.trigger}${r.entity ? ` on ${r.activity} of ${r.entity}` : ""}${r.error ? `: ${String(r.error).split("\n")[0]}` : ""}${r.decision && r.status === "raised" ? ` (raised as decision ${r.decision})` : ""}`);
|
|
228
|
+
process.exit(0);
|
|
229
|
+
}
|
|
230
|
+
const r = report(dir);
|
|
231
|
+
if (json) { console.log(JSON.stringify(r, null, 2)); process.exit(0); }
|
|
232
|
+
if (!r.triggers.length) console.log(`no triggers: add them to ${CONFIG} triggers, or list a kit in kits`);
|
|
233
|
+
for (const t of r.triggers) console.log(`trigger ${t.id} (${t.from})${t.enabled ? "" : " [off]"}: on ${JSON.stringify(t.on)} run ${JSON.stringify(t.run)}${t.needs ? `, needs ${t.needs} (${t.needs_complete ? "complete" : "not complete yet"})` : ""}`);
|
|
234
|
+
for (const p of r.problems) console.log(`problem ${p}`);
|
|
235
|
+
for (const x of r.runs) console.log(`run ${String(x.n).padEnd(5)} ${x.outcome.padEnd(9)} ${x.trigger}${x.entity ? ` on ${x.activity} of ${x.entity}` : ""}${x.status ? ` [${x.status}]` : ""}`);
|
|
236
|
+
for (const w of r.waiting) console.log(`waiting ${w.trigger}: needs the ${w.needs} package complete`);
|
|
237
|
+
for (const o of r.open) console.log(`failed ${o.trigger} (run ${o.run}): ${String(o.error).split("\n")[0]}\n ${o.decide}`);
|
|
238
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "upgrade-registry.schema.json",
|
|
4
|
+
"title": "Upgrade registry",
|
|
5
|
+
"description": "Naive's versions, the migrations between them, and each package's version and channel (schema/upgrades.json, EE-076). naive upgrade reads it from the installed copy. A migration rewrites a venture's records when the framework or one package changes, like a Next.js codemod; a version's guide is bundled in docs/upgrades/.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["framework", "versions", "migrations", "packages"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"framework": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$", "description": "The installed framework version" },
|
|
11
|
+
"note": { "type": "string" },
|
|
12
|
+
"channels": { "type": "object", "additionalProperties": { "type": "string" } },
|
|
13
|
+
"versions": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"minItems": 1,
|
|
16
|
+
"items": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"required": ["version", "date", "summary", "guide", "migrations"],
|
|
19
|
+
"additionalProperties": false,
|
|
20
|
+
"properties": {
|
|
21
|
+
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
|
|
22
|
+
"date": { "type": "string", "format": "date" },
|
|
23
|
+
"summary": { "type": "string" },
|
|
24
|
+
"guide": { "type": ["string", "null"], "description": "The upgrade guide for this version, a repository path, or null for the first version" },
|
|
25
|
+
"migrations": { "type": "array", "items": { "type": "string" }, "description": "Framework migrations that move a venture onto this version, in order" }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"migrations": {
|
|
30
|
+
"type": "array",
|
|
31
|
+
"items": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"required": ["id", "module", "package"],
|
|
34
|
+
"additionalProperties": false,
|
|
35
|
+
"properties": {
|
|
36
|
+
"id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
|
|
37
|
+
"module": { "type": "string", "description": "A module exporting id, describe and apply(dir, ctx)" },
|
|
38
|
+
"package": { "type": ["string", "null"], "description": "The package whose schema changed, or null for a framework migration" },
|
|
39
|
+
"from": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$", "description": "A package migration: the oldest package version it upgrades" },
|
|
40
|
+
"to": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$", "description": "A package migration: the package version it upgrades to" },
|
|
41
|
+
"decision": { "type": "string" },
|
|
42
|
+
"aliases": { "type": "string", "description": "The route aliases file that keeps the old routes working" }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"packages": {
|
|
47
|
+
"type": "object",
|
|
48
|
+
"additionalProperties": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"required": ["version", "channel"],
|
|
51
|
+
"additionalProperties": false,
|
|
52
|
+
"properties": {
|
|
53
|
+
"version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
|
|
54
|
+
"channel": { "enum": ["stable", "experimental"] },
|
|
55
|
+
"note": { "type": "string" }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|