naive-framework 0.0.0-stage → 0.1.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 +61 -0
- package/LICENSE +21 -0
- package/README.md +37 -2
- package/docs/decisions/decisions.json +861 -0
- package/docs/ontology.json +796 -0
- package/docs/ontology.md +163 -0
- package/docs/reference/ROUTES.md +125 -0
- package/evidence/benchmarks/2026-10-27-golden.jev.after-catalog-fix.json +558 -0
- package/evidence/benchmarks/2026-10-27-golden.jev.json +501 -0
- package/evidence/benchmarks/2026-10-27-golden.reasoning-answers.json +177 -0
- package/evidence/benchmarks/JEV_VS_REASONING_MODEL_2026-10-27.md +68 -0
- package/evidence/capabilities/agent-capabilities.json +86 -0
- package/evidence/design-documents.registry.json +2896 -0
- package/evidence/evals/evals.json +25 -0
- package/evidence/evals/harness-evals.json +140 -0
- package/evidence/layer.json +51 -0
- package/evidence/skills/agent-capabilities/SKILL.md +35 -0
- package/evidence/skills/design-coverage/SKILL.md +57 -0
- package/evidence/skills/design-coverage/check.mjs +192 -0
- package/evidence/skills/design-coverage/scan.mjs +45 -0
- package/evidence/skills/fidelity-ladder-audit/SKILL.md +121 -0
- package/evidence/skills/fidelity-ladder-audit/ladder-census.mjs +180 -0
- package/evidence/skills/findability/SKILL.md +32 -0
- package/evidence/skills/findability/inventory.rb +41 -0
- package/evidence/skills/foreshadowing-audit/SKILL.md +183 -0
- package/evidence/skills/metrics-review/SKILL.md +177 -0
- package/evidence/tooling/integrations.json +153 -0
- package/governance/layer.json +101 -0
- package/governance/references/references.json +26 -0
- package/governance/skills/board-design/SKILL.md +68 -0
- package/governance/skills/brand-pillar/SKILL.md +90 -0
- package/governance/skills/business-pillar/SKILL.md +96 -0
- package/governance/skills/chief-of-staff/SKILL.md +45 -0
- package/governance/skills/cofounder-structure/SKILL.md +64 -0
- package/governance/skills/cross-pillar-tradeoff/SKILL.md +168 -0
- package/governance/skills/equity-and-share-classes/SKILL.md +68 -0
- package/governance/skills/executive-roles/SKILL.md +95 -0
- package/governance/skills/exit-planning/SKILL.md +66 -0
- package/governance/skills/financing-and-investor-rights/SKILL.md +73 -0
- package/governance/skills/office-hours-mode/SKILL.md +113 -0
- package/governance/skills/product-pillar/SKILL.md +81 -0
- package/governance/skills/publication-policy/SKILL.md +63 -0
- package/governance/skills/role-and-candidate-authoring/SKILL.md +198 -0
- package/governance/skills/stakeholder-update/SKILL.md +177 -0
- package/governance/tooling/integrations.json +37 -0
- package/governance/venture-template/AGENT_ROLES_AND_DECISION_RIGHTS.md +58 -0
- package/governance/venture-template/COMPANY_VAULT_DEFINITION_2026-10-25.md +204 -0
- package/governance/venture-template/README.md +74 -0
- package/governance/venture-template/decision-rights.json +186 -0
- package/governance/venture-template/index.md +151 -0
- package/governance/venture-template/pillars/brand.md +209 -0
- package/governance/venture-template/pillars/business.md +255 -0
- package/governance/venture-template/pillars/product.md +254 -0
- package/governance/venture-template/render-roles.py +11 -0
- package/governance/venture-template/roles/README.md +85 -0
- package/governance/venture-template/roles/agent-roles.json +202 -0
- package/governance/venture-template/roles/ceo.md +163 -0
- package/governance/venture-template/roles/chief-of-staff.md +153 -0
- package/governance/venture-template/roles/cmo.md +165 -0
- package/governance/venture-template/roles/coo.md +189 -0
- package/governance/venture-template/roles/cto.md +158 -0
- package/governance/venture-template/roles/department-head.md +47 -0
- package/governance/venture-template/roles/forward-deployed-engineer.md +51 -0
- package/governance/venture-template/roles/founder.md +173 -0
- package/governance/venture-template/roles/hr-manager.md +49 -0
- package/governance/venture-template/roles/talent-acquisition-manager.md +50 -0
- package/interface/api/server.mjs +69 -0
- package/interface/cli/find-venture.mjs +15 -0
- package/interface/cli/mentura.mjs +271 -0
- package/interface/cli/naive.mjs +169 -0
- package/interface/demo/board.mjs +581 -0
- package/interface/demo/decision-harness.mjs +91 -0
- package/interface/demo/live-agent.mjs +47 -0
- package/interface/harness/evals.mjs +90 -0
- package/interface/harness/examples/pt-no-shows.dump.md +19 -0
- package/interface/harness/run.mjs +313 -0
- package/interface/harness/site.mjs +59 -0
- package/interface/layer.json +31 -0
- package/interface/mcp/server.mjs +122 -0
- package/interface/operator-console/README.md +58 -0
- package/interface/provenance.mjs +42 -0
- package/interface/references/references.json +28 -0
- package/interface/route-aliases.json +32 -0
- package/interface/router.mjs +580 -0
- package/interface/skills/install-mentura/SKILL.md +88 -0
- package/interface/tooling/integrations.json +112 -0
- package/knowledge/connectors/README.md +54 -0
- package/knowledge/connectors/catalog.mjs +118 -0
- package/knowledge/connectors/contract.mjs +56 -0
- package/knowledge/connectors/eval.mjs +176 -0
- package/knowledge/connectors/filesystem.mjs +79 -0
- package/knowledge/connectors/index.mjs +102 -0
- package/knowledge/connectors/resolve.mjs +44 -0
- package/knowledge/connectors/suite.mjs +80 -0
- package/knowledge/layer.json +42 -0
- package/knowledge/skills/find-reference/SKILL.md +38 -0
- package/knowledge/skills/industry-awareness/SKILL.md +277 -0
- package/knowledge/tooling/integrations.json +127 -0
- package/knowledge/tooling/questions.md +46 -0
- package/operations/FOUNDER_OPERATING_MODEL_CAMPAIGN_2026-10-14.md +16 -0
- package/operations/departments.json +162 -0
- package/operations/handoff-v2.md +93 -0
- package/operations/layer.json +60 -0
- package/operations/marketing/check-public.mjs +68 -0
- package/operations/marketing/site/README.md +86 -0
- package/operations/marketing/site/matrix.json +731 -0
- package/operations/marketing/site/plan.mjs +117 -0
- package/operations/marketing/site/presence.mjs +252 -0
- package/operations/references/references.json +45 -0
- package/operations/skills/recruiting/SKILL.md +32 -0
- package/operations/skills/team-design/SKILL.md +36 -0
- package/operations/skills/tool-selection/SKILL.md +46 -0
- package/operations/templates/recruiting-brief.md +35 -0
- package/operations/tooling/integrations.json +158 -0
- package/package.json +57 -4
- package/packages/catalog.json +272 -0
- package/packages/cofounder/package.json +42 -0
- package/packages/counsel/package.json +47 -0
- package/packages/customers/package.json +21 -0
- package/packages/decisions/package.json +17 -0
- package/packages/engineering/package.json +41 -0
- package/packages/evidence/package.json +17 -0
- package/packages/finance/package.json +48 -0
- package/packages/foundation/package.json +52 -0
- package/packages/investor/package.json +57 -0
- package/packages/investors/package.json +21 -0
- package/packages/legal/package.json +73 -0
- package/packages/marketing/package.json +57 -0
- package/packages/money/package.json +21 -0
- package/packages/operations/package.json +74 -0
- package/packages/partner/package.json +38 -0
- package/packages/people/package.json +64 -0
- package/packages/product/package.json +49 -0
- package/packages/raw/package.json +19 -0
- package/packages/relationships/package.json +52 -0
- package/packages/validation/package.json +99 -0
- package/platform/README.md +45 -0
- package/platform/connectors/eval.mjs +154 -0
- package/platform/connectors/fake-github.mjs +91 -0
- package/platform/connectors/github.mjs +105 -0
- package/platform/integrations/jev.mjs +30 -0
- package/platform/integrations/langsmith-docket.mjs +53 -0
- package/platform/integrations/langsmith-setup.mjs +115 -0
- package/platform/integrations/langsmith.mjs +47 -0
- package/platform/integrations/rho.mjs +145 -0
- package/platform/integrations/site.mjs +75 -0
- package/platform/kits/README.md +7 -0
- package/platform/mcp/research.mjs +64 -0
- package/purpose/checklists/vault-and-tooling-consultancy-setup.md +216 -0
- package/purpose/frameworks/business-discovery-framework-amendments-2026-05-20.md +181 -0
- package/purpose/frameworks/business-discovery-framework.html +938 -0
- package/purpose/frameworks/business-discovery-framework.md +326 -0
- package/purpose/frameworks/idea-map/README.md +74 -0
- package/purpose/frameworks/idea-map/conventions.json +146 -0
- package/purpose/frameworks/idea-map/graph.mjs +182 -0
- package/purpose/frameworks/idea-map/ideamap.mjs +179 -0
- package/purpose/frameworks/idea-map/route.mjs +140 -0
- package/purpose/frameworks/onboarding-handoff-framework.md +269 -0
- package/purpose/frameworks/post-discovery-deliverable-playbook.md +274 -0
- package/purpose/frameworks/product-anatomy/README.md +63 -0
- package/purpose/frameworks/product-anatomy/anatomy.mjs +195 -0
- package/purpose/frameworks/product-anatomy/examples/polity.answers.reasoned.json +11 -0
- package/purpose/frameworks/product-anatomy/examples/polity.json +89 -0
- package/purpose/frameworks/product-anatomy/phases.json +107 -0
- package/purpose/frameworks/product-anatomy/questions.json +74 -0
- package/purpose/kits/validation/README.md +14 -0
- package/purpose/kits/validation/references/references.json +122 -0
- package/purpose/kits/validation/skills/problem-validation/SKILL.md +43 -0
- package/purpose/kits/validation/skills/validation-score/SKILL.md +35 -0
- package/purpose/kits/validation/templates/go-to-market.md +19 -0
- package/purpose/kits/validation/templates/operations-readiness.md +20 -0
- package/purpose/kits/validation/templates/pricing.md +22 -0
- package/purpose/kits/validation/templates/problem-interview.md +36 -0
- package/purpose/kits/validation/templates/problem.md +45 -0
- package/purpose/kits/validation/templates/product-market-fit.md +23 -0
- package/purpose/kits/validation/templates/solution.md +18 -0
- package/purpose/kits/validation/templates/team.md +19 -0
- package/purpose/kits/validation/weights.json +22 -0
- package/purpose/layer.json +53 -0
- package/purpose/references/references.json +324 -0
- package/purpose/skills/ambition-tier/SKILL.md +205 -0
- package/purpose/skills/telos/SKILL.md +52 -0
- package/purpose/strategic-foundation.json +133 -0
- package/purpose/templates/telos-based-smart.md +39 -0
- package/purpose/tooling/integrations.json +48 -0
- package/schema/README.md +61 -0
- package/schema/VERSION +1 -0
- package/schema/account.schema.json +79 -0
- package/schema/add-department.mjs +41 -0
- package/schema/agent-capability.schema.json +94 -0
- package/schema/alignment.schema.json +61 -0
- package/schema/assess-problem.mjs +131 -0
- package/schema/bdd.mjs +56 -0
- package/schema/board.schema.json +101 -0
- package/schema/check-boundary.mjs +54 -0
- package/schema/check-data-model.mjs +170 -0
- package/schema/check-data-packages.mjs +83 -0
- package/schema/check-departments.mjs +45 -0
- package/schema/check-execution.mjs +85 -0
- package/schema/check-governance.mjs +98 -0
- package/schema/check-integrations.mjs +33 -0
- package/schema/check-nextjs-status.mjs +77 -0
- package/schema/check-nouns.mjs +49 -0
- package/schema/check-private.mjs +61 -0
- package/schema/check-provenance.mjs +55 -0
- package/schema/check-publication.mjs +96 -0
- package/schema/check-ready.mjs +89 -0
- package/schema/check-sources.mjs +66 -0
- package/schema/check-team.mjs +94 -0
- package/schema/check-telos.mjs +59 -0
- package/schema/check-validation.mjs +165 -0
- package/schema/check-ventures.mjs +81 -0
- package/schema/check-where-used.mjs +58 -0
- package/schema/data-master.schema.json +14 -0
- package/schema/data-model.json +1258 -0
- package/schema/data-model.schema.json +152 -0
- package/schema/decision-analytics.mjs +77 -0
- package/schema/decision-record.schema.json +290 -0
- package/schema/decision-rights.schema.json +34 -0
- package/schema/decision.schema.json +30 -0
- package/schema/decisions.mjs +321 -0
- package/schema/department-catalog.schema.json +55 -0
- package/schema/department.schema.json +15 -0
- package/schema/departments.mjs +32 -0
- package/schema/docket-eval.mjs +89 -0
- package/schema/docket.mjs +135 -0
- package/schema/eval-suite.schema.json +45 -0
- package/schema/evidence.schema.json +110 -0
- package/schema/examples/migrate/agent.mjs +12 -0
- package/schema/examples/workspace/ventures/studio/accounts/bakery/account.json +18 -0
- package/schema/examples/workspace/ventures/studio/evidence/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/governance/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/knowledge/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/operations/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/print/knowledge/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/print/purpose/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/print/venture.json +37 -0
- package/schema/examples/workspace/ventures/studio/products/brand-care.json +19 -0
- package/schema/examples/workspace/ventures/studio/products/brand-kit.json +23 -0
- package/schema/examples/workspace/ventures/studio/provenance.jsonl +3 -0
- package/schema/examples/workspace/ventures/studio/purpose/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/venture.json +43 -0
- package/schema/examples/workspace/ventures/tandem/accounts/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/tandem/evidence/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/agreements/dee-fast.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/board.json +51 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/finance/charter.md +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/primary/marketing-and-sales/charter.md +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/primary/marketing-and-sales/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/exit.json +33 -0
- package/schema/examples/workspace/ventures/tandem/governance/founder-agreement.json +24 -0
- package/schema/examples/workspace/ventures/tandem/governance/founder-agreement.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/ownership.json +131 -0
- package/schema/examples/workspace/ventures/tandem/governance/publication-policy.json +171 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/research/friends-feedback-2026-08.md +3 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/research/pilot-2026-10.md +3 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/research/problem-interviews-2026-09.md +20 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/sources.json +8 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/where-used.json +13 -0
- package/schema/examples/workspace/ventures/tandem/operations/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/finance/README.md +5 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/primary/marketing-and-sales/README.md +5 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/primary/marketing-and-sales/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/pillars/brand.md +5 -0
- package/schema/examples/workspace/ventures/tandem/pillars/business.md +5 -0
- package/schema/examples/workspace/ventures/tandem/pillars/product.md +5 -0
- package/schema/examples/workspace/ventures/tandem/products/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/tandem/products/shop-app.json +22 -0
- package/schema/examples/workspace/ventures/tandem/profile.md +5 -0
- package/schema/examples/workspace/ventures/tandem/provenance.jsonl +13 -0
- package/schema/examples/workspace/ventures/tandem/purpose/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/purpose/telos.json +78 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/go-to-market.json +35 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/pricing.json +37 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/problem.json +74 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/product-market-fit.json +66 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/solution.json +33 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/team.json +52 -0
- package/schema/examples/workspace/ventures/tandem/venture.json +79 -0
- package/schema/examples/workspace/ventures/woodworking/knowledge/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/woodworking/venture.json +21 -0
- package/schema/examples/workspace/workspace.json +8 -0
- package/schema/exit.schema.json +74 -0
- package/schema/foundation.mjs +118 -0
- package/schema/founder-agreement.schema.json +83 -0
- package/schema/gate.mjs +39 -0
- package/schema/handoff.schema.json +239 -0
- package/schema/icp.schema.json +136 -0
- package/schema/idea-graph.schema.json +61 -0
- package/schema/init-venture.mjs +98 -0
- package/schema/integration.schema.json +143 -0
- package/schema/knowledge-sources.schema.json +130 -0
- package/schema/layer.json +46 -0
- package/schema/layer.schema.json +119 -0
- package/schema/load-packages.mjs +26 -0
- package/schema/marketing-sitemap.schema.json +232 -0
- package/schema/migrate-venture.mjs +192 -0
- package/schema/need-now.json +601 -0
- package/schema/need-now.mjs +107 -0
- package/schema/nextjs-status.schema.json +29 -0
- package/schema/ownership.schema.json +282 -0
- package/schema/packages.json +4 -0
- package/schema/packages.mjs +247 -0
- package/schema/payouts.mjs +91 -0
- package/schema/port-venture.mjs +161 -0
- package/schema/product.schema.json +223 -0
- package/schema/provenance-entry.schema.json +154 -0
- package/schema/publication-policy.schema.json +293 -0
- package/schema/raw-source.schema.json +15 -0
- package/schema/reference.schema.json +115 -0
- package/schema/route-aliases.schema.json +25 -0
- package/schema/run-handoff.mjs +51 -0
- package/schema/scaffold/defaults.json +54 -0
- package/schema/site-presence.schema.json +337 -0
- package/schema/strategic-foundation.schema.json +74 -0
- package/schema/stream.schema.json +14 -0
- package/schema/team-plan.schema.json +157 -0
- package/schema/telos.schema.json +197 -0
- package/schema/time-to-ready.mjs +93 -0
- package/schema/upgrade-venture.mjs +129 -0
- package/schema/use-model.mjs +10 -0
- package/schema/validate.py +49 -0
- package/schema/validation-evidence.schema.json +123 -0
- package/schema/validation-go-to-market.schema.json +110 -0
- package/schema/validation-operations-readiness.schema.json +91 -0
- package/schema/validation-pricing.schema.json +114 -0
- package/schema/validation-problem.schema.json +118 -0
- package/schema/validation-product-market-fit.schema.json +135 -0
- package/schema/validation-solution.schema.json +79 -0
- package/schema/validation-team.schema.json +116 -0
- package/schema/venture.schema.json +407 -0
- package/schema/vocab/business-models.json +298 -0
- package/schema/where-used.schema.json +56 -0
- package/schema/workspace.schema.json +38 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// Grades each venture's validation records (purpose/validation/*.json, EE-026) from their cited
|
|
2
|
+
// evidence, adapting GRADE (the GRADE Working Group's method for rating certainty of evidence).
|
|
3
|
+
//
|
|
4
|
+
// item grade: starts by kind (behavior high, commitment moderate, stated and desk research low,
|
|
5
|
+
// opinion very low), then drops one level for each of: an adjacent or unknown audience (two
|
|
6
|
+
// for the wrong audience: indirectness); a sample under 5 for behavior, commitment or stated
|
|
7
|
+
// evidence (imprecision); general rather than specific answers to stated or opinion evidence;
|
|
8
|
+
// collected more than 18 months ago.
|
|
9
|
+
// record grade: the best supporting item's grade; up one when three or more supporting items
|
|
10
|
+
// from distinct sources grade low or better (consistency); down one when an item at that grade
|
|
11
|
+
// or better contradicts the claim (inconsistency). No evidence: very low ("claim only").
|
|
12
|
+
// weight: high 1, moderate 0.7, low 0.4, very low 0.1. The validation score multiplies each
|
|
13
|
+
// sub-score's Jev probability by this weight.
|
|
14
|
+
// Data checks: product-market fit's Ellis share (very disappointed / asked; 40% is the usual bar)
|
|
15
|
+
// and whether retention levels off; team gaps (skills needed with no holder); operations
|
|
16
|
+
// readiness grades as its weakest MAD tier.
|
|
17
|
+
// Score (--score): V = sum(w p e) / sum(w), weights and floors from purpose/kits/validation/weights.json
|
|
18
|
+
// by go-to-market path and venture kind; a missing sub-score counts 0 and is listed.
|
|
19
|
+
// Errors: duplicate evidence ids, a URL with no checked date, a source file that does not exist
|
|
20
|
+
// (paths are relative to the venture folder), a date in the future.
|
|
21
|
+
//
|
|
22
|
+
// node schema/check-validation.mjs <workspace or venture dir> [--json] [--score]
|
|
23
|
+
|
|
24
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
25
|
+
import { join } from "node:path";
|
|
26
|
+
|
|
27
|
+
const LEVELS = ["very low", "low", "moderate", "high"];
|
|
28
|
+
const WEIGHT = { "very low": 0.1, low: 0.4, moderate: 0.7, high: 1 };
|
|
29
|
+
const START = { behavior: 3, commitment: 2, stated: 1, "desk-research": 1, opinion: 0 };
|
|
30
|
+
const STALE_MONTHS = 18, MIN_SAMPLE = 5;
|
|
31
|
+
|
|
32
|
+
export function gradeItem(e, today = new Date()) {
|
|
33
|
+
let g = START[e.kind];
|
|
34
|
+
const why = [];
|
|
35
|
+
const down = (n, reason) => { g -= n; why.push(reason); };
|
|
36
|
+
if (e.audience === "wrong") down(2, "wrong audience");
|
|
37
|
+
else if (e.audience !== "target") down(1, `${e.audience} audience`);
|
|
38
|
+
if (["behavior", "commitment", "stated"].includes(e.kind) && (e.sample?.n ?? 0) < MIN_SAMPLE) down(1, `sample under ${MIN_SAMPLE}`);
|
|
39
|
+
if (["stated", "opinion"].includes(e.kind) && e.specificity !== "specific") down(1, "general, not specific");
|
|
40
|
+
const months = (today - new Date(e.collected)) / (30.44 * 864e5);
|
|
41
|
+
if (months > STALE_MONTHS) down(1, `older than ${STALE_MONTHS} months`);
|
|
42
|
+
return { level: LEVELS[Math.max(0, g)], why };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function gradeRecord(rec, today = new Date()) {
|
|
46
|
+
const items = (rec.evidence ?? []).map((e) => ({ e, ...gradeItem(e, today) }));
|
|
47
|
+
const sup = items.filter((i) => i.e.supports !== false);
|
|
48
|
+
if (!sup.length) return { level: "very low", weight: WEIGHT["very low"], why: [items.length ? "no supporting evidence" : "claim only: no evidence cited"], items };
|
|
49
|
+
let g = Math.max(...sup.map((i) => LEVELS.indexOf(i.level)));
|
|
50
|
+
const why = [];
|
|
51
|
+
const sources = new Set(sup.filter((i) => LEVELS.indexOf(i.level) >= 1).map((i) => i.e.source.url ?? i.e.source.path ?? i.e.source.title));
|
|
52
|
+
if (sources.size >= 3 && g < 3) { g++; why.push("consistent across 3 or more sources"); }
|
|
53
|
+
if (items.some((i) => i.e.supports === false && LEVELS.indexOf(i.level) >= g)) { g = Math.max(0, g - 1); why.push("contradicted by evidence as strong"); }
|
|
54
|
+
const level = LEVELS[g];
|
|
55
|
+
return { level, weight: WEIGHT[level], why, items };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const SUBSCORES = ["problem", "solution", "product-market-fit", "pricing", "go-to-market", "team", "operations-readiness"];
|
|
59
|
+
|
|
60
|
+
// Operations readiness grades as its weakest tier; every other record from its own evidence.
|
|
61
|
+
export function grade(name, rec, today = new Date()) {
|
|
62
|
+
if (name !== "operations-readiness") return gradeRecord(rec, today);
|
|
63
|
+
const tiers = rec.tiers.map((t) => ({ tier: t.tier, ...gradeRecord(t, today) }));
|
|
64
|
+
const worst = tiers.reduce((a, b) => (LEVELS.indexOf(b.level) < LEVELS.indexOf(a.level) ? b : a));
|
|
65
|
+
return { level: worst.level, weight: WEIGHT[worst.level], why: [`weakest tier: ${worst.tier}`], items: tiers.flatMap((t) => t.items), tiers: tiers.map((t) => ({ tier: t.tier, grade: t.level })) };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Facts the records' data shows, beside the grade.
|
|
69
|
+
export function facts(name, rec) {
|
|
70
|
+
const f = {};
|
|
71
|
+
if (name === "product-market-fit") {
|
|
72
|
+
if (rec.ellis) f.ellis_share = +(rec.ellis.very_disappointed / rec.ellis.asked).toFixed(2);
|
|
73
|
+
const c = (rec.retention?.cohorts ?? []).filter((x) => x.active.length >= 4);
|
|
74
|
+
if (c.length) f.retention_levels_off = c.every((x) => { const a = x.active.slice(-3); return Math.abs(a[0] - a[2]) / x.size <= 0.05 && a[2] > 0; });
|
|
75
|
+
}
|
|
76
|
+
if (name === "team") f.gaps = rec.needed.filter((n) => !rec.held.some((h) => h.skill === n.skill)).map((n) => `${n.skill} (by ${n.by_phase})`);
|
|
77
|
+
return f;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function kindOf(products) {
|
|
81
|
+
if (products.some((p) => p.software)) return "software";
|
|
82
|
+
if (products.some((p) => p.offering === "service")) return "service";
|
|
83
|
+
if (products.some((p) => p.offering === "content")) return "content";
|
|
84
|
+
return products.length ? "physical" : "software";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function score(records, W, { path = "build-first", kind = "software" } = {}) {
|
|
88
|
+
const parts = SUBSCORES.map((id) => {
|
|
89
|
+
const w = Math.max(0, (W.base[id] ?? 0) + (W.by_path[path]?.[id] ?? 0) + (W.by_kind[kind]?.[id] ?? 0));
|
|
90
|
+
const r = records[id];
|
|
91
|
+
const pe = r ? (r.probability ?? 0) * r.weight : 0;
|
|
92
|
+
const floor = W.floors_by_path[path]?.[id] ?? W.floors[id] ?? 0;
|
|
93
|
+
return { id, w, p: r?.probability ?? null, e: r?.weight ?? null, pe: +pe.toFixed(3), floor, stated: !!r, below_floor: w > 0 && pe < floor };
|
|
94
|
+
});
|
|
95
|
+
const total = parts.reduce((n, x) => n + x.w, 0);
|
|
96
|
+
const V = +(parts.reduce((n, x) => n + x.w * x.pe, 0) / total).toFixed(3);
|
|
97
|
+
const gain = [...parts].sort((a, b) => b.w * (1 - b.pe) - a.w * (1 - a.pe))[0];
|
|
98
|
+
const held = parts.filter((x) => x.below_floor).map((x) => x.id);
|
|
99
|
+
return { path, kind, V, threshold: W.threshold, recommends_validated: V >= W.threshold && !held.length, below_floor: held, not_stated: parts.filter((x) => !x.stated).map((x) => x.id), most_to_gain: gain.id, parts };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
103
|
+
const dir = process.argv[2];
|
|
104
|
+
if (!dir) { console.error("usage: node schema/check-validation.mjs <workspace or venture dir> [--json] [--score]"); process.exit(2); }
|
|
105
|
+
const load = (p) => JSON.parse(readFileSync(p, "utf8"));
|
|
106
|
+
const walk = (d) => readdirSync(d, { withFileTypes: true }).flatMap((e) => e.name === "node_modules" || e.name.startsWith(".") ? []
|
|
107
|
+
: e.isDirectory() ? walk(join(d, e.name)) : e.name === "venture.json" ? [d] : []);
|
|
108
|
+
const W = load(new URL("../purpose/kits/validation/weights.json", import.meta.url));
|
|
109
|
+
const errors = [], out = [], scores = [];
|
|
110
|
+
const today = new Date();
|
|
111
|
+
for (const root of walk(dir)) {
|
|
112
|
+
const v = load(join(root, "venture.json"));
|
|
113
|
+
const places = [["foundation/problem.json", "problem"], ["validation", null], ["purpose/validation", null]].flatMap(([rel, name]) => {
|
|
114
|
+
const p = join(root, rel);
|
|
115
|
+
if (name) return existsSync(p) ? [[name, p, `${v.id}/${rel}`]] : [];
|
|
116
|
+
if (!existsSync(p)) return [];
|
|
117
|
+
return readdirSync(p).filter((x) => x.endsWith(".json")).sort().map((f) => [f.replace(/\.json$/, ""), join(p, f), `${v.id}/${rel}/${f}`]);
|
|
118
|
+
});
|
|
119
|
+
if (!places.length) continue;
|
|
120
|
+
const graded = {};
|
|
121
|
+
let path;
|
|
122
|
+
const seen = new Set();
|
|
123
|
+
for (const [name, file, at] of places) {
|
|
124
|
+
if (seen.has(name)) continue;
|
|
125
|
+
seen.add(name);
|
|
126
|
+
const rec = load(file);
|
|
127
|
+
if (!SUBSCORES.includes(name)) { errors.push(`${at}: not a validation sub-score (${SUBSCORES.join(", ")})`); continue; }
|
|
128
|
+
const all = name === "operations-readiness" ? rec.tiers.flatMap((t) => t.evidence) : rec.evidence ?? [];
|
|
129
|
+
const ids = all.map((e) => e.id);
|
|
130
|
+
if (new Set(ids).size !== ids.length) errors.push(`${at}: duplicate evidence ids`);
|
|
131
|
+
for (const e of all) {
|
|
132
|
+
if (e.source.url && !e.source.checked) errors.push(`${at}: ${e.id} cites a url with no checked date`);
|
|
133
|
+
if (e.source.path && !existsSync(join(root, e.source.path))) errors.push(`${at}: ${e.id} source ${e.source.path} not found (paths are relative to the venture folder)`);
|
|
134
|
+
if (new Date(e.collected) > today) errors.push(`${at}: ${e.id} was collected in the future`);
|
|
135
|
+
}
|
|
136
|
+
if (name === "product-market-fit") {
|
|
137
|
+
if (rec.ellis && rec.ellis.very_disappointed > rec.ellis.asked) errors.push(`${at}: more very disappointed than asked`);
|
|
138
|
+
for (const c of rec.retention?.cohorts ?? []) if (c.active.some((a) => a > c.size)) errors.push(`${at}: cohort ${c.start} has more active users than its size`);
|
|
139
|
+
}
|
|
140
|
+
if (name === "go-to-market") path = rec.path;
|
|
141
|
+
const r = grade(name, rec, today);
|
|
142
|
+
graded[name] = { probability: rec.probability?.p ?? 0, weight: r.weight };
|
|
143
|
+
out.push({ venture: v.id, record: name, grade: r.level, weight: r.weight, why: r.why, probability: rec.probability?.p ?? null, facts: facts(name, rec), tiers: r.tiers,
|
|
144
|
+
items: r.items.map((i) => ({ id: i.e.id, kind: i.e.kind, grade: i.level, why: i.why, supports: i.e.supports !== false })) });
|
|
145
|
+
}
|
|
146
|
+
const products = ["product", "products"].flatMap((d) => existsSync(join(root, d)) ? readdirSync(join(root, d)).filter((f) => f.endsWith(".json")).map((f) => load(join(root, d, f))) : []);
|
|
147
|
+
scores.push({ venture: v.id, ...score(graded, W, { path: path ?? "build-first", kind: kindOf(products) }) });
|
|
148
|
+
}
|
|
149
|
+
const wantScore = process.argv.includes("--score");
|
|
150
|
+
if (process.argv.includes("--json")) console.log(JSON.stringify(wantScore ? { records: out, scores } : out, null, 2));
|
|
151
|
+
else {
|
|
152
|
+
for (const o of out) {
|
|
153
|
+
const f = Object.entries(o.facts).map(([k, x]) => `${k} ${Array.isArray(x) ? x.join(", ") || "none" : x}`).join("; ");
|
|
154
|
+
console.log(`${o.venture}/${o.record}: ${o.grade} (weight ${o.weight})${o.why.length ? ` — ${o.why.join("; ")}` : ""}${f ? ` [${f}]` : ""}`);
|
|
155
|
+
for (const i of o.items) console.log(` ${i.supports ? "+" : "-"} ${i.id.padEnd(24)} ${i.kind.padEnd(14)} ${i.grade}${i.why.length ? ` (${i.why.join(", ")})` : ""}`);
|
|
156
|
+
}
|
|
157
|
+
if (wantScore) for (const s of scores) {
|
|
158
|
+
console.log(`\n${s.venture}: validation score ${s.V} (threshold ${s.threshold}; path ${s.path}, kind ${s.kind})${s.recommends_validated ? " — recommends Validation; the owner decides" : ""}`);
|
|
159
|
+
for (const p of s.parts) console.log(` ${p.id.padEnd(22)} w ${p.w} p ${p.p ?? "-"} e ${p.e ?? "-"} p*e ${p.pe}${p.below_floor ? ` below floor ${p.floor}` : ""}${p.stated ? "" : " not stated"}`);
|
|
160
|
+
console.log(` most to gain: ${s.most_to_gain}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (errors.length) { console.error(errors.join("\n")); process.exit(1); }
|
|
164
|
+
if (!process.argv.includes("--json")) console.log(`${out.length} validation records graded from their evidence.`);
|
|
165
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Checks the rules across a workspace's ventures that one venture.json alone cannot
|
|
2
|
+
// (EE-011, EE-012). Validate each file against its schema first; this checks how they fit.
|
|
3
|
+
//
|
|
4
|
+
// node schema/check-ventures.mjs <dir>
|
|
5
|
+
//
|
|
6
|
+
// Rules: venture ids are unique; every parent exists; no venture is its own ancestor;
|
|
7
|
+
// links point at known ventures; within a venture, product ids are unique, flows_to and
|
|
8
|
+
// an account's products and a product's part_of name that venture's own products, and a
|
|
9
|
+
// product's scope names its layer or tier. Layer locations exist, relative to the venture
|
|
10
|
+
// folder; several markets mark one primary. Warns on a business model outside the vocabulary. Warns when a formalized venture
|
|
11
|
+
// (a legal form, or other members) has no governance layer.
|
|
12
|
+
|
|
13
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
14
|
+
import { dirname, join } from "node:path";
|
|
15
|
+
|
|
16
|
+
const models = (() => {
|
|
17
|
+
const b = JSON.parse(readFileSync(new URL("vocab/business-models.json", import.meta.url), "utf8"));
|
|
18
|
+
return new Set([...b.patterns, ...b.extras].map((m) => m.id));
|
|
19
|
+
})();
|
|
20
|
+
|
|
21
|
+
const dir = process.argv[2];
|
|
22
|
+
if (!dir) { console.error("usage: node schema/check-ventures.mjs <dir>"); process.exit(2); }
|
|
23
|
+
const load = (p) => JSON.parse(readFileSync(p, "utf8"));
|
|
24
|
+
// node_modules is skipped, as the other checks skip it: an installed framework carries example ventures.
|
|
25
|
+
const walk = (d) => readdirSync(d, { withFileTypes: true }).flatMap((e) => e.name === "node_modules" || e.name.startsWith(".") ? []
|
|
26
|
+
: e.isDirectory() ? walk(join(d, e.name)) : e.name === "venture.json" ? [join(d, e.name)] : []);
|
|
27
|
+
const jsonIn = (d) => existsSync(d) ? readdirSync(d).filter((f) => f.endsWith(".json")).map((f) => join(d, f)) : [];
|
|
28
|
+
const accountsIn = (d) => existsSync(d) ? readdirSync(d).map((c) => join(d, c, "account.json")).filter(existsSync) : [];
|
|
29
|
+
|
|
30
|
+
const ventures = new Map();
|
|
31
|
+
const errors = [], warnings = [];
|
|
32
|
+
for (const f of walk(dir)) {
|
|
33
|
+
const v = load(f);
|
|
34
|
+
if (ventures.has(v.id)) errors.push(`${f}: duplicate venture id ${v.id}`);
|
|
35
|
+
const root = dirname(f);
|
|
36
|
+
for (const [k, l] of Object.entries(v.layers ?? {})) if (l && !existsSync(join(root, l.location))) errors.push(`${v.id}: ${k} layer location ${l.location} not found (relative to the venture folder)`);
|
|
37
|
+
const productFiles = [...jsonIn(join(root, "product")), ...jsonIn(join(root, "products"))];
|
|
38
|
+
ventures.set(v.id, { ...v, products: productFiles.map(load), accounts: accountsIn(join(root, "accounts")).map(load) });
|
|
39
|
+
}
|
|
40
|
+
if (!ventures.size) { console.error(`no venture.json found under ${dir}`); process.exit(1); }
|
|
41
|
+
|
|
42
|
+
for (const v of ventures.values()) {
|
|
43
|
+
if (v.parent !== null) {
|
|
44
|
+
if (!ventures.has(v.parent)) errors.push(`${v.id}: parent ${v.parent} not found`);
|
|
45
|
+
const seen = new Set([v.id]);
|
|
46
|
+
for (let p = ventures.get(v.parent); p; p = ventures.get(p.parent)) {
|
|
47
|
+
if (seen.has(p.id)) { errors.push(`${v.id}: its parents form a loop`); break; }
|
|
48
|
+
seen.add(p.id);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for (const l of v.links ?? []) if (!ventures.has(l.to)) errors.push(`${v.id}: link to unknown venture ${l.to}`);
|
|
52
|
+
const ids = new Set();
|
|
53
|
+
for (const p of v.products) {
|
|
54
|
+
if (ids.has(p.id)) errors.push(`${v.id}: duplicate product id ${p.id}`);
|
|
55
|
+
ids.add(p.id);
|
|
56
|
+
}
|
|
57
|
+
for (const p of v.products) for (const t of p.flows_to ?? []) if (!ids.has(t)) errors.push(`${v.id}/${p.id}: flows_to unknown product ${t}`);
|
|
58
|
+
for (const p of v.products) for (const m of p.business_model ?? []) if (!models.has(m)) warnings.push(`${v.id}/${p.id}: business model ${m} is not in schema/vocab/business-models.json`);
|
|
59
|
+
for (const p of v.products) if (Array.isArray(p.market) && p.market.filter((m) => m.primary).length !== 1) errors.push(`${v.id}/${p.id}: several markets need exactly one primary`);
|
|
60
|
+
for (const p of v.products) for (const k of p.part_of ?? []) if (!ids.has(k)) errors.push(`${v.id}/${p.id}: part_of unknown product ${k}`);
|
|
61
|
+
for (const p of v.products) {
|
|
62
|
+
const sc = p.scope;
|
|
63
|
+
if (sc?.level === "layer" && !sc.layer) errors.push(`${v.id}/${p.id}: a layer-scoped product names its layer`);
|
|
64
|
+
if (sc?.level === "tier" && (!sc.tier || (sc.layer && sc.layer !== "operations"))) errors.push(`${v.id}/${p.id}: a tier-scoped product names its tier, which sits in the operations layer`);
|
|
65
|
+
}
|
|
66
|
+
const repos = new Set(); // a venture may use its own repos or a parent's (EE-020)
|
|
67
|
+
for (let a = v; a; a = ventures.get(a.parent)) for (const r of a.repos ?? []) repos.add(r.id);
|
|
68
|
+
for (const r of v.repos ?? []) for (const t of r.products ?? []) if (!ids.has(t)) errors.push(`${v.id}/repos/${r.id}: holds unknown product ${t}`);
|
|
69
|
+
for (const p of v.products) {
|
|
70
|
+
if (p.software && !repos.size) errors.push(`${v.id}/${p.id}: builds software, so the venture (or a parent) needs a repository in repos`);
|
|
71
|
+
if (p.repo && !repos.has(p.repo)) errors.push(`${v.id}/${p.id}: repo ${p.repo} is not in the venture's repos`);
|
|
72
|
+
}
|
|
73
|
+
for (const c of v.accounts) for (const t of c.products ?? []) if (!ids.has(t)) errors.push(`${v.id}/accounts/${c.id}: buys or uses unknown product ${t}`);
|
|
74
|
+
const formal = (v.form?.legal_form && v.form.legal_form !== "none") || (v.members?.length ?? 0) > 0;
|
|
75
|
+
if (formal && !v.layers.governance) warnings.push(`${v.id}: formalized (legal form or members) but has no governance layer`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
for (const w of warnings) console.warn(`warning: ${w}`);
|
|
79
|
+
if (errors.length) { console.error(errors.join("\n")); process.exit(1); }
|
|
80
|
+
const count = (k) => [...ventures.values()].reduce((n, v) => n + v[k].length, 0);
|
|
81
|
+
console.log(`${ventures.size} ventures, ${count("products")} products, ${count("accounts")} accounts: all cross-venture rules hold.`);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Checks each venture's where-used list (EE-042): every parent route and child source exists, and
|
|
2
|
+
// every live child shows its parent's value. A child that disagrees is drift: the parent changed
|
|
3
|
+
// and the change has not reached it. Frozen children are history and are not checked. Children in
|
|
4
|
+
// a source that is not on the file system are listed as not checked here: reading them needs the
|
|
5
|
+
// network, which is the platform's.
|
|
6
|
+
//
|
|
7
|
+
// node schema/check-where-used.mjs <workspace or venture dir> [--json]
|
|
8
|
+
|
|
9
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { connect, sourceFor, sourcesOf } from "../knowledge/connectors/index.mjs";
|
|
12
|
+
import { resolve } from "../interface/router.mjs";
|
|
13
|
+
|
|
14
|
+
const dir = process.argv[2];
|
|
15
|
+
if (!dir) { console.error("usage: node schema/check-where-used.mjs <workspace or venture dir> [--json]"); process.exit(2); }
|
|
16
|
+
const FILE = "knowledge/where-used.json";
|
|
17
|
+
const walk = (d) => readdirSync(d, { withFileTypes: true }).flatMap((e) => e.name === "node_modules" || e.name.startsWith(".") ? []
|
|
18
|
+
: e.isDirectory() ? walk(join(d, e.name)) : e.name === "venture.json" ? [d] : []);
|
|
19
|
+
const at = (obj, pointer) => pointer.split("/").slice(1).map((k) => k.replace(/~1/g, "/").replace(/~0/g, "~")).reduce((o, k) => o == null ? undefined : o[k], obj);
|
|
20
|
+
|
|
21
|
+
const errors = [], drift = [], unchecked = [];
|
|
22
|
+
let lists = 0, checked = 0;
|
|
23
|
+
for (const v of walk(dir)) {
|
|
24
|
+
if (!existsSync(join(v, FILE))) continue;
|
|
25
|
+
lists++;
|
|
26
|
+
const id = JSON.parse(readFileSync(join(v, "venture.json"), "utf8")).id;
|
|
27
|
+
const ids = new Map(sourcesOf(v).sources.map((s) => [s.id, s]));
|
|
28
|
+
for (const fact of JSON.parse(readFileSync(join(v, FILE), "utf8")).facts) {
|
|
29
|
+
const where = `${id}: ${fact.id}`;
|
|
30
|
+
const { r, params } = resolve(fact.parent.route);
|
|
31
|
+
if (!r || r.kind !== "record" || r.collection === "list") { errors.push(`${where}: parent ${fact.parent.route} is not a record route`); continue; }
|
|
32
|
+
const context = r.collection === "item" && (r.record === "product" || r.record === "account") ? { [r.record]: params.id } : {};
|
|
33
|
+
const src = sourceFor(v, r.record, context);
|
|
34
|
+
const cands = (r.collection === "item" ? r.files.map((f) => f.replace("*", params.id)) : r.files).filter((f) => !f.includes("*"));
|
|
35
|
+
const path = cands.find((f) => existsSync(join(v, f))) ?? cands[0];
|
|
36
|
+
if (src.connector !== "filesystem") { unchecked.push(`${where}: parent is in ${src.id}`); continue; }
|
|
37
|
+
const parent = await (await connect(src, v)).read(path);
|
|
38
|
+
const value = parent && at(JSON.parse(parent.content), fact.parent.pointer);
|
|
39
|
+
if (value === undefined || value === null) { errors.push(`${where}: ${fact.parent.route} has no value at ${fact.parent.pointer}`); continue; }
|
|
40
|
+
for (const child of fact.children) {
|
|
41
|
+
const cw = `${where} -> ${child.source}://${child.path}`;
|
|
42
|
+
const s = ids.get(child.source);
|
|
43
|
+
if (!s) { errors.push(`${cw}: ${child.source} is not one of the venture's sources`); continue; }
|
|
44
|
+
if (child.status === "frozen") continue;
|
|
45
|
+
if (s.connector !== "filesystem") { unchecked.push(`${cw}: needs the network (the platform checks it)`); continue; }
|
|
46
|
+
const got = await (await connect(s, v)).read(child.path);
|
|
47
|
+
if (!got) { errors.push(`${cw}: no such file`); continue; }
|
|
48
|
+
checked++;
|
|
49
|
+
const ok = child.match.kind === "json"
|
|
50
|
+
? JSON.stringify(at(JSON.parse(got.content), child.match.pointer)) === JSON.stringify(value)
|
|
51
|
+
: got.content.includes(child.match.template.replaceAll("{value}", String(value)));
|
|
52
|
+
if (!ok) drift.push(`${cw}: does not show ${JSON.stringify(value)} (${child.match.kind === "json" ? child.match.pointer : child.match.template}); deliver by ${child.deliver}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (process.argv.includes("--json")) console.log(JSON.stringify({ lists, checked, drift, unchecked, errors }, null, 2));
|
|
57
|
+
if (errors.length || drift.length) { for (const e of [...errors, ...drift]) console.error(e); process.exit(1); }
|
|
58
|
+
if (!process.argv.includes("--json")) console.log(`${lists} where-used lists: ${checked} live children show their parent's value${unchecked.length ? `; ${unchecked.length} need the platform to check` : ""}.`);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "data-master.schema.json",
|
|
4
|
+
"title": "Data package master record",
|
|
5
|
+
"description": "One master record in a data package (customers, investors or money), at <package>/<id>.json (EE-070). The package is never complete. Its gates are coverage and freshness. Activity lives in append-only _streams/.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["id"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
|
|
10
|
+
"name": { "type": "string" },
|
|
11
|
+
"summary": { "type": "string" }
|
|
12
|
+
},
|
|
13
|
+
"additionalProperties": true
|
|
14
|
+
}
|