naive-framework 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +62 -0
- package/LICENSE +21 -0
- package/README.md +37 -2
- package/docs/decisions/decisions.json +888 -0
- package/docs/ontology.json +796 -0
- package/docs/ontology.md +163 -0
- package/docs/reference/ROUTES.md +124 -0
- package/evidence/benchmarks/2026-10-27-golden.jev.after-catalog-fix.json +558 -0
- package/evidence/benchmarks/2026-10-27-golden.jev.json +501 -0
- package/evidence/benchmarks/2026-10-27-golden.reasoning-answers.json +177 -0
- package/evidence/benchmarks/JEV_VS_REASONING_MODEL_2026-10-27.md +68 -0
- package/evidence/capabilities/agent-capabilities.json +86 -0
- package/evidence/design-documents.registry.json +2896 -0
- package/evidence/evals/evals.json +25 -0
- package/evidence/evals/harness-evals.json +140 -0
- package/evidence/layer.json +51 -0
- package/evidence/skills/agent-capabilities/SKILL.md +35 -0
- package/evidence/skills/design-coverage/SKILL.md +57 -0
- package/evidence/skills/design-coverage/check.mjs +192 -0
- package/evidence/skills/design-coverage/scan.mjs +45 -0
- package/evidence/skills/fidelity-ladder-audit/SKILL.md +121 -0
- package/evidence/skills/fidelity-ladder-audit/ladder-census.mjs +180 -0
- package/evidence/skills/findability/SKILL.md +32 -0
- package/evidence/skills/findability/inventory.rb +41 -0
- package/evidence/skills/foreshadowing-audit/SKILL.md +183 -0
- package/evidence/skills/metrics-review/SKILL.md +177 -0
- package/evidence/tooling/integrations.json +153 -0
- package/governance/layer.json +102 -0
- package/governance/references/references.json +26 -0
- package/governance/skills/board-design/SKILL.md +68 -0
- package/governance/skills/brand-pillar/SKILL.md +90 -0
- package/governance/skills/business-pillar/SKILL.md +96 -0
- package/governance/skills/chief-of-staff/SKILL.md +45 -0
- package/governance/skills/cofounder-structure/SKILL.md +64 -0
- package/governance/skills/cross-pillar-tradeoff/SKILL.md +168 -0
- package/governance/skills/equity-and-share-classes/SKILL.md +68 -0
- package/governance/skills/executive-roles/SKILL.md +95 -0
- package/governance/skills/exit-planning/SKILL.md +66 -0
- package/governance/skills/financing-and-investor-rights/SKILL.md +73 -0
- package/governance/skills/office-hours-mode/SKILL.md +113 -0
- package/governance/skills/product-pillar/SKILL.md +81 -0
- package/governance/skills/publication-policy/SKILL.md +63 -0
- package/governance/skills/role-and-candidate-authoring/SKILL.md +198 -0
- package/governance/skills/stakeholder-update/SKILL.md +177 -0
- package/governance/tooling/integrations.json +37 -0
- package/governance/venture-template/AGENT_ROLES_AND_DECISION_RIGHTS.md +58 -0
- package/governance/venture-template/COMPANY_VAULT_DEFINITION_2026-10-25.md +204 -0
- package/governance/venture-template/README.md +74 -0
- package/governance/venture-template/decision-rights.json +186 -0
- package/governance/venture-template/index.md +151 -0
- package/governance/venture-template/pillars/brand.md +209 -0
- package/governance/venture-template/pillars/business.md +255 -0
- package/governance/venture-template/pillars/product.md +254 -0
- package/governance/venture-template/render-roles.py +11 -0
- package/governance/venture-template/roles/README.md +85 -0
- package/governance/venture-template/roles/agent-roles.json +202 -0
- package/governance/venture-template/roles/ceo.md +163 -0
- package/governance/venture-template/roles/chief-of-staff.md +153 -0
- package/governance/venture-template/roles/cmo.md +165 -0
- package/governance/venture-template/roles/coo.md +189 -0
- package/governance/venture-template/roles/cto.md +158 -0
- package/governance/venture-template/roles/department-head.md +47 -0
- package/governance/venture-template/roles/forward-deployed-engineer.md +51 -0
- package/governance/venture-template/roles/founder.md +173 -0
- package/governance/venture-template/roles/hr-manager.md +49 -0
- package/governance/venture-template/roles/talent-acquisition-manager.md +50 -0
- package/governance/venture-template/roles/venture-roles.json +62 -0
- package/interface/acting.mjs +83 -0
- package/interface/adapters/claude-code.json +16 -0
- package/interface/adapters/codex.json +14 -0
- package/interface/adapters/cursor.json +16 -0
- package/interface/adapters.mjs +182 -0
- package/interface/api/server.mjs +71 -0
- package/interface/boundaries.mjs +218 -0
- package/interface/brand.mjs +214 -0
- package/interface/cli/find-venture.mjs +15 -0
- package/interface/cli/freshness.mjs +59 -0
- package/interface/cli/guard.mjs +6 -0
- package/interface/cli/mentura.mjs +341 -0
- package/interface/cli/naive.mjs +194 -0
- package/interface/context.mjs +524 -0
- package/interface/demo/board.mjs +581 -0
- package/interface/demo/decision-harness.mjs +91 -0
- package/interface/demo/live-agent.mjs +47 -0
- package/interface/dev/setup.mjs +84 -0
- package/interface/gate-hooks.mjs +36 -0
- package/interface/harness/evals.mjs +90 -0
- package/interface/harness/examples/pt-no-shows.dump.md +19 -0
- package/interface/harness/run.mjs +313 -0
- package/interface/harness/site.mjs +59 -0
- package/interface/instrumentation.mjs +86 -0
- package/interface/kit-boundary.mjs +73 -0
- package/interface/layer.json +37 -0
- package/interface/mcp/server.mjs +162 -0
- package/interface/operator-console/README.md +58 -0
- package/interface/package-routes.mjs +196 -0
- package/interface/provenance.mjs +65 -0
- package/interface/reads.mjs +173 -0
- package/interface/references/references.json +28 -0
- package/interface/release-card.mjs +42 -0
- package/interface/route-aliases.json +32 -0
- package/interface/router.mjs +653 -0
- package/interface/skills/install-mentura/SKILL.md +88 -0
- package/interface/skills/naive-setup/SKILL.md +71 -0
- package/interface/skills/naive-setup/artifact.html +83 -0
- package/interface/tooling/integrations.json +112 -0
- package/interface/vitals.mjs +115 -0
- package/interface/writes.mjs +190 -0
- package/knowledge/connectors/README.md +54 -0
- package/knowledge/connectors/catalog.mjs +118 -0
- package/knowledge/connectors/contract.mjs +56 -0
- package/knowledge/connectors/eval.mjs +176 -0
- package/knowledge/connectors/filesystem.mjs +79 -0
- package/knowledge/connectors/index.mjs +102 -0
- package/knowledge/connectors/resolve.mjs +44 -0
- package/knowledge/connectors/suite.mjs +80 -0
- package/knowledge/freshness.json +85 -0
- package/knowledge/layer.json +50 -0
- package/knowledge/skills/find-reference/SKILL.md +38 -0
- package/knowledge/skills/industry-awareness/SKILL.md +277 -0
- package/knowledge/templates/glossary.md +23 -0
- package/knowledge/tooling/integrations.json +127 -0
- package/knowledge/tooling/questions.md +46 -0
- package/operations/FOUNDER_OPERATING_MODEL_CAMPAIGN_2026-10-14.md +16 -0
- package/operations/departments.json +162 -0
- package/operations/handoff-v2.md +93 -0
- package/operations/layer.json +67 -0
- package/operations/marketing/check-public.mjs +68 -0
- package/operations/marketing/site/README.md +86 -0
- package/operations/marketing/site/matrix.json +731 -0
- package/operations/marketing/site/plan.mjs +117 -0
- package/operations/marketing/site/presence.mjs +252 -0
- package/operations/references/references.json +45 -0
- package/operations/skills/recruiting/SKILL.md +32 -0
- package/operations/skills/team-design/SKILL.md +36 -0
- package/operations/skills/tool-selection/SKILL.md +46 -0
- package/operations/templates/marketing-brand.md +46 -0
- package/operations/templates/public-assets.md +39 -0
- package/operations/templates/recruiting-brief.md +35 -0
- package/operations/tooling/integrations.json +158 -0
- package/package.json +59 -4
- package/packages/catalog.json +280 -0
- package/packages/cofounder/package.json +42 -0
- package/packages/counsel/package.json +47 -0
- package/packages/customers/package.json +41 -0
- package/packages/deals/package.json +27 -0
- package/packages/decisions/package.json +28 -0
- package/packages/engineering/package.json +41 -0
- package/packages/evidence/package.json +17 -0
- package/packages/finance/frames/fund-without-ceding-control.frame.json +177 -0
- package/packages/finance/package.json +48 -0
- package/packages/foundation/package.json +59 -0
- package/packages/fund/package.json +48 -0
- package/packages/investor/package.json +57 -0
- package/packages/investors/package.json +21 -0
- package/packages/legal/package.json +73 -0
- package/packages/marketing/package.json +63 -0
- package/packages/money/package.json +42 -0
- package/packages/operations/package.json +74 -0
- package/packages/partner/package.json +38 -0
- package/packages/people/package.json +64 -0
- package/packages/product/package.json +49 -0
- package/packages/raw/package.json +19 -0
- package/packages/relationships/package.json +52 -0
- package/packages/validation/package.json +112 -0
- package/platform/README.md +51 -0
- package/platform/adapter.json +15 -0
- package/platform/connectors/eval.mjs +154 -0
- package/platform/connectors/fake-github.mjs +91 -0
- package/platform/connectors/github.mjs +105 -0
- package/platform/integrations/jev.mjs +30 -0
- package/platform/integrations/langsmith-docket.mjs +53 -0
- package/platform/integrations/langsmith-setup.mjs +115 -0
- package/platform/integrations/langsmith.mjs +47 -0
- package/platform/integrations/remote-image.mjs +79 -0
- package/platform/integrations/rho.mjs +146 -0
- package/platform/integrations/site.mjs +75 -0
- package/platform/kits/README.md +14 -0
- package/platform/kits/agent-upgrade/kit.json +15 -0
- package/platform/kits/agent-upgrade/run.mjs +82 -0
- package/platform/kits/agent-upgrade/stand-in-agent.mjs +32 -0
- package/platform/kits/validation-kickoff/kit.json +29 -0
- package/platform/mcp/research.mjs +64 -0
- package/platform/webhooks/server.mjs +70 -0
- package/purpose/checklists/vault-and-tooling-consultancy-setup.md +216 -0
- package/purpose/frameworks/business-discovery-framework-amendments-2026-05-20.md +181 -0
- package/purpose/frameworks/business-discovery-framework.html +938 -0
- package/purpose/frameworks/business-discovery-framework.md +326 -0
- package/purpose/frameworks/idea-map/README.md +74 -0
- package/purpose/frameworks/idea-map/conventions.json +146 -0
- package/purpose/frameworks/idea-map/graph.mjs +182 -0
- package/purpose/frameworks/idea-map/ideamap.mjs +181 -0
- package/purpose/frameworks/idea-map/route.mjs +140 -0
- package/purpose/frameworks/onboarding-handoff-framework.md +269 -0
- package/purpose/frameworks/post-discovery-deliverable-playbook.md +274 -0
- package/purpose/frameworks/product-anatomy/README.md +63 -0
- package/purpose/frameworks/product-anatomy/anatomy.mjs +195 -0
- package/purpose/frameworks/product-anatomy/examples/polity.answers.reasoned.json +11 -0
- package/purpose/frameworks/product-anatomy/examples/polity.json +89 -0
- package/purpose/frameworks/product-anatomy/phases.json +107 -0
- package/purpose/frameworks/product-anatomy/questions.json +74 -0
- package/purpose/kits/validation/README.md +14 -0
- package/purpose/kits/validation/references/references.json +122 -0
- package/purpose/kits/validation/skills/problem-validation/SKILL.md +43 -0
- package/purpose/kits/validation/skills/validation-score/SKILL.md +35 -0
- package/purpose/kits/validation/templates/go-to-market.md +19 -0
- package/purpose/kits/validation/templates/operations-readiness.md +20 -0
- package/purpose/kits/validation/templates/pricing.md +22 -0
- package/purpose/kits/validation/templates/problem-interview.md +36 -0
- package/purpose/kits/validation/templates/problem.md +45 -0
- package/purpose/kits/validation/templates/product-market-fit.md +23 -0
- package/purpose/kits/validation/templates/solution.md +18 -0
- package/purpose/kits/validation/templates/team.md +19 -0
- package/purpose/kits/validation/weights.json +22 -0
- package/purpose/layer.json +53 -0
- package/purpose/references/references.json +324 -0
- package/purpose/skills/ambition-tier/SKILL.md +205 -0
- package/purpose/skills/telos/SKILL.md +52 -0
- package/purpose/strategic-foundation.json +133 -0
- package/purpose/templates/telos-based-smart.md +39 -0
- package/purpose/tooling/integrations.json +48 -0
- package/schema/README.md +62 -0
- package/schema/VERSION +1 -0
- package/schema/access.mjs +57 -0
- package/schema/account.schema.json +79 -0
- package/schema/adapter.schema.json +33 -0
- package/schema/add-department.mjs +41 -0
- package/schema/agent-capability.schema.json +94 -0
- package/schema/alignment.schema.json +61 -0
- package/schema/assess-problem.mjs +131 -0
- package/schema/assets.mjs +212 -0
- package/schema/bdd.mjs +56 -0
- package/schema/board.schema.json +101 -0
- package/schema/brand.mjs +373 -0
- package/schema/build-release.mjs +61 -0
- package/schema/caching.mjs +505 -0
- package/schema/check-assets.mjs +24 -0
- package/schema/check-boundary.mjs +54 -0
- package/schema/check-brand.mjs +24 -0
- package/schema/check-config.mjs +110 -0
- package/schema/check-data-model.mjs +170 -0
- package/schema/check-data-packages.mjs +83 -0
- package/schema/check-departments.mjs +45 -0
- package/schema/check-execution.mjs +85 -0
- package/schema/check-governance.mjs +98 -0
- package/schema/check-integrations.mjs +33 -0
- package/schema/check-nextjs-status.mjs +79 -0
- package/schema/check-nouns.mjs +49 -0
- package/schema/check-people.mjs +70 -0
- package/schema/check-private.mjs +61 -0
- package/schema/check-provenance.mjs +55 -0
- package/schema/check-publication.mjs +96 -0
- package/schema/check-ready.mjs +89 -0
- package/schema/check-sources.mjs +74 -0
- package/schema/check-team.mjs +94 -0
- package/schema/check-telos.mjs +59 -0
- package/schema/check-validation.mjs +165 -0
- package/schema/check-ventures.mjs +81 -0
- package/schema/check-where-used.mjs +58 -0
- package/schema/data-master.schema.json +14 -0
- package/schema/data-model.json +1584 -0
- package/schema/data-model.schema.json +152 -0
- package/schema/deal.schema.json +80 -0
- package/schema/decision-analytics.mjs +77 -0
- package/schema/decision-record.schema.json +290 -0
- package/schema/decision-rights.schema.json +34 -0
- package/schema/decision.schema.json +30 -0
- package/schema/decisions.mjs +327 -0
- package/schema/department-catalog.schema.json +55 -0
- package/schema/department.schema.json +15 -0
- package/schema/departments.mjs +32 -0
- package/schema/docket-eval.mjs +89 -0
- package/schema/docket.mjs +135 -0
- package/schema/eval-suite.schema.json +45 -0
- package/schema/evidence.schema.json +110 -0
- package/schema/examples/frames/judge.mjs +10 -0
- package/schema/examples/migrate/agent.mjs +12 -0
- package/schema/examples/venture-type/jev.mjs +12 -0
- package/schema/examples/workspace/ventures/acme-labs/AGENTS.md +17 -0
- package/schema/examples/workspace/ventures/acme-labs/accounts/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/acme-labs/decisions/discovery-goal.decision.json +23 -0
- package/schema/examples/workspace/ventures/acme-labs/decisions/statement-icp.decision.json +22 -0
- package/schema/examples/workspace/ventures/acme-labs/decisions/statement-problem.decision.json +22 -0
- package/schema/examples/workspace/ventures/acme-labs/decisions/venture.team.decision.json +37 -0
- package/schema/examples/workspace/ventures/acme-labs/knowledge/README.md +3 -0
- package/schema/examples/workspace/ventures/acme-labs/knowledge/sources.json +46 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000001.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000002.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000003.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000004.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000005.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000006.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000007.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000008.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000009.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000010.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000011.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000012.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000013.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/30000000-0000-4000-8000-000000000014.json +12 -0
- package/schema/examples/workspace/ventures/acme-labs/money/_streams/transactions/stream.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/money/_summary.json +30 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/customer-service/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/customer-service/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/finance/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/human-capital/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/human-capital/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/it/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/it/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/marketing-and-sales/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/marketing-and-sales/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/products/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/products/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/strategy/README.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/operations/departments/strategy/department.json +5 -0
- package/schema/examples/workspace/ventures/acme-labs/people/founders/maya-chen.json +15 -0
- package/schema/examples/workspace/ventures/acme-labs/people/people.json +22 -0
- package/schema/examples/workspace/ventures/acme-labs/pillars/brand.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/pillars/business.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/pillars/product.md +5 -0
- package/schema/examples/workspace/ventures/acme-labs/products/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.core-product.decision.json +28 -0
- package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.exists.decision.json +38 -0
- package/schema/examples/workspace/ventures/acme-labs/products/decisions/product.flagship.decision.json +27 -0
- package/schema/examples/workspace/ventures/acme-labs/profile.md +12 -0
- package/schema/examples/workspace/ventures/acme-labs/provenance.jsonl +12 -0
- package/schema/examples/workspace/ventures/acme-labs/raw/dump.md +6 -0
- package/schema/examples/workspace/ventures/acme-labs/venture.json +27 -0
- package/schema/examples/workspace/ventures/northstar/AGENTS.md +17 -0
- package/schema/examples/workspace/ventures/northstar/accounts/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/northstar/deals/ductline.json +8 -0
- package/schema/examples/workspace/ventures/northstar/deals/kilnworks.json +14 -0
- package/schema/examples/workspace/ventures/northstar/decisions/venture.team.decision.json +31 -0
- package/schema/examples/workspace/ventures/northstar/evidence/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/fund/decisions/terms.decision.json +27 -0
- package/schema/examples/workspace/ventures/northstar/fund/decisions/terms.first-close.decision.json +27 -0
- package/schema/examples/workspace/ventures/northstar/fund/decisions/thesis.decision.json +26 -0
- package/schema/examples/workspace/ventures/northstar/fund/terms.json +22 -0
- package/schema/examples/workspace/ventures/northstar/fund/thesis.json +22 -0
- package/schema/examples/workspace/ventures/northstar/governance/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/external-relationships/charter.md +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/external-relationships/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/finance/charter.md +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/human-capital/charter.md +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/human-capital/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/risk-and-compliance/charter.md +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/risk-and-compliance/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/strategy/charter.md +5 -0
- package/schema/examples/workspace/ventures/northstar/governance/departments/strategy/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/knowledge/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/operations/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/external-relationships/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/external-relationships/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/finance/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/human-capital/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/human-capital/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/risk-and-compliance/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/risk-and-compliance/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/strategy/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/operations/departments/strategy/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/people/founders/ana-ruiz.json +13 -0
- package/schema/examples/workspace/ventures/northstar/people/founders/ben-okafor.json +7 -0
- package/schema/examples/workspace/ventures/northstar/people/people.json +27 -0
- package/schema/examples/workspace/ventures/northstar/pillars/brand.md +5 -0
- package/schema/examples/workspace/ventures/northstar/pillars/business.md +5 -0
- package/schema/examples/workspace/ventures/northstar/pillars/product.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/AGENTS.md +17 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/accounts/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/decisions/venture.team.decision.json +31 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/knowledge/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/customer-service/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/customer-service/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/finance/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/human-capital/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/human-capital/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/it/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/it/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/marketing-and-sales/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/marketing-and-sales/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/products/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/products/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/strategy/README.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/operations/departments/strategy/department.json +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/brand.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/business.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/pillars/product.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.core-product.decision.json +28 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.exists.decision.json +32 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/products/decisions/product.flagship.decision.json +27 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/profile.md +5 -0
- package/schema/examples/workspace/ventures/northstar/portfolio/kilnworks/venture.json +27 -0
- package/schema/examples/workspace/ventures/northstar/products/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/northstar/profile.md +5 -0
- package/schema/examples/workspace/ventures/northstar/provenance.jsonl +3 -0
- package/schema/examples/workspace/ventures/northstar/purpose/README.md +3 -0
- package/schema/examples/workspace/ventures/northstar/venture.json +49 -0
- package/schema/examples/workspace/ventures/studio/accounts/bakery/account.json +18 -0
- package/schema/examples/workspace/ventures/studio/evidence/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/governance/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/knowledge/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/operations/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/print/knowledge/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/print/purpose/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/print/venture.json +37 -0
- package/schema/examples/workspace/ventures/studio/products/brand-care.json +19 -0
- package/schema/examples/workspace/ventures/studio/products/brand-kit.json +23 -0
- package/schema/examples/workspace/ventures/studio/provenance.jsonl +3 -0
- package/schema/examples/workspace/ventures/studio/purpose/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/studio/venture.json +43 -0
- package/schema/examples/workspace/ventures/tandem/accounts/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/tandem/evidence/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/agreements/dee-fast.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/board.json +51 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/finance/charter.md +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/primary/marketing-and-sales/charter.md +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/departments/primary/marketing-and-sales/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/governance/exit.json +33 -0
- package/schema/examples/workspace/ventures/tandem/governance/founder-agreement.json +24 -0
- package/schema/examples/workspace/ventures/tandem/governance/founder-agreement.md +3 -0
- package/schema/examples/workspace/ventures/tandem/governance/ownership.json +131 -0
- package/schema/examples/workspace/ventures/tandem/governance/publication-policy.json +171 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/research/friends-feedback-2026-08.md +3 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/research/pilot-2026-10.md +3 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/research/problem-interviews-2026-09.md +20 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/sources.json +8 -0
- package/schema/examples/workspace/ventures/tandem/knowledge/where-used.json +13 -0
- package/schema/examples/workspace/ventures/tandem/operations/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/finance/README.md +5 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/finance/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/primary/marketing-and-sales/README.md +5 -0
- package/schema/examples/workspace/ventures/tandem/operations/departments/primary/marketing-and-sales/department.json +5 -0
- package/schema/examples/workspace/ventures/tandem/pillars/brand.md +5 -0
- package/schema/examples/workspace/ventures/tandem/pillars/business.md +5 -0
- package/schema/examples/workspace/ventures/tandem/pillars/product.md +5 -0
- package/schema/examples/workspace/ventures/tandem/products/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/tandem/products/shop-app.json +22 -0
- package/schema/examples/workspace/ventures/tandem/profile.md +5 -0
- package/schema/examples/workspace/ventures/tandem/provenance.jsonl +13 -0
- package/schema/examples/workspace/ventures/tandem/purpose/README.md +3 -0
- package/schema/examples/workspace/ventures/tandem/purpose/telos.json +78 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/go-to-market.json +35 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/pricing.json +37 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/problem.json +74 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/product-market-fit.json +66 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/solution.json +33 -0
- package/schema/examples/workspace/ventures/tandem/purpose/validation/team.json +52 -0
- package/schema/examples/workspace/ventures/tandem/venture.json +79 -0
- package/schema/examples/workspace/ventures/woodworking/knowledge/.gitkeep +0 -0
- package/schema/examples/workspace/ventures/woodworking/venture.json +21 -0
- package/schema/examples/workspace/workspace.json +8 -0
- package/schema/exit.schema.json +74 -0
- package/schema/foundation.mjs +118 -0
- package/schema/founder-agreement.schema.json +83 -0
- package/schema/founder.schema.json +72 -0
- package/schema/frame.schema.json +240 -0
- package/schema/frames.mjs +228 -0
- package/schema/freshness-log.schema.json +40 -0
- package/schema/freshness-profiles.schema.json +44 -0
- package/schema/freshness.mjs +473 -0
- package/schema/fund-terms.schema.json +107 -0
- package/schema/fund-thesis.schema.json +87 -0
- package/schema/gate-drafts.mjs +130 -0
- package/schema/gate.mjs +133 -0
- package/schema/glossary.schema.json +25 -0
- package/schema/handoff.schema.json +239 -0
- package/schema/icp.schema.json +136 -0
- package/schema/idea-graph.schema.json +61 -0
- package/schema/init-venture.mjs +128 -0
- package/schema/integration.schema.json +143 -0
- package/schema/judgment.schema.json +38 -0
- package/schema/kit.schema.json +47 -0
- package/schema/kits.mjs +24 -0
- package/schema/knowledge-sources.schema.json +260 -0
- package/schema/layer.json +59 -0
- package/schema/layer.schema.json +119 -0
- package/schema/load-packages.mjs +26 -0
- package/schema/marketing-brand.schema.json +116 -0
- package/schema/marketing-sitemap.schema.json +232 -0
- package/schema/migrate-venture.mjs +192 -0
- package/schema/migrations/kit-to-package.mjs +94 -0
- package/schema/migrations/package-layout.mjs +86 -0
- package/schema/model-steps.mjs +717 -0
- package/schema/money-summary.schema.json +138 -0
- package/schema/naive-config.mjs +165 -0
- package/schema/naive-config.schema.json +268 -0
- package/schema/need-now.json +772 -0
- package/schema/need-now.mjs +108 -0
- package/schema/nextjs-status.schema.json +29 -0
- package/schema/ownership.schema.json +282 -0
- package/schema/packages.json +4 -0
- package/schema/packages.mjs +252 -0
- package/schema/payouts.mjs +91 -0
- package/schema/people.schema.json +86 -0
- package/schema/port-venture.mjs +161 -0
- package/schema/product.schema.json +223 -0
- package/schema/provenance-entry.schema.json +154 -0
- package/schema/public-assets.schema.json +76 -0
- package/schema/publication-policy.schema.json +293 -0
- package/schema/raw-source.schema.json +15 -0
- package/schema/reference.schema.json +115 -0
- package/schema/release-read.mjs +111 -0
- package/schema/releases.mjs +497 -0
- package/schema/route-aliases.schema.json +25 -0
- package/schema/run-handoff.mjs +51 -0
- package/schema/scaffold/defaults.json +54 -0
- package/schema/setup.mjs +164 -0
- package/schema/site-presence.schema.json +337 -0
- package/schema/stale.mjs +111 -0
- package/schema/start-release.mjs +41 -0
- package/schema/strategic-foundation.schema.json +74 -0
- package/schema/stream.schema.json +14 -0
- package/schema/structure.mjs +186 -0
- package/schema/systems-catalog.json +126 -0
- package/schema/systems-catalog.schema.json +78 -0
- package/schema/team-plan.schema.json +157 -0
- package/schema/telos.schema.json +197 -0
- package/schema/time-to-ready.mjs +93 -0
- package/schema/trigger.schema.json +44 -0
- package/schema/triggers.mjs +237 -0
- package/schema/upgrade-registry.schema.json +60 -0
- package/schema/upgrade-venture.mjs +107 -0
- package/schema/upgrades.json +69 -0
- package/schema/upgrades.mjs +385 -0
- package/schema/use-model.mjs +10 -0
- package/schema/validate.py +58 -0
- package/schema/validation-evidence.schema.json +123 -0
- package/schema/validation-go-to-market.schema.json +110 -0
- package/schema/validation-operations-readiness.schema.json +91 -0
- package/schema/validation-pricing.schema.json +114 -0
- package/schema/validation-problem.schema.json +118 -0
- package/schema/validation-product-market-fit.schema.json +135 -0
- package/schema/validation-solution.schema.json +79 -0
- package/schema/validation-team.schema.json +116 -0
- package/schema/venture-role.schema.json +64 -0
- package/schema/venture-type.mjs +62 -0
- package/schema/venture-types.json +346 -0
- package/schema/venture-types.schema.json +129 -0
- package/schema/venture.schema.json +460 -0
- package/schema/vocab/business-models.json +298 -0
- package/schema/where-used.schema.json +56 -0
- package/schema/workspace.schema.json +38 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// A fake of the part of GitHub's REST API the GitHub connector uses, as a fetch function, so the
|
|
2
|
+
// connector's evals run offline. It follows the real API's shapes and refusals: trees, contents
|
|
3
|
+
// (404 for a missing file, 422 for a PUT over an existing file without its sha), commits, refs,
|
|
4
|
+
// pulls and code search (default branch only), and 401 without a token. It is a test double, not a
|
|
5
|
+
// second implementation: the live eval (MENTURA_EVAL_GITHUB_REPO) checks the same contract on the
|
|
6
|
+
// real API.
|
|
7
|
+
//
|
|
8
|
+
// const gh = fakeGitHub({ repo: "acme/knowledge", files: { "docs/a.md": "..." } });
|
|
9
|
+
// connect({ repo: "acme/knowledge", fetch: gh.fetch })
|
|
10
|
+
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
12
|
+
import { blobSha, matches } from "../../knowledge/connectors/contract.mjs";
|
|
13
|
+
|
|
14
|
+
export function fakeGitHub({ repo, files = {}, branch = "main", token = true } = {}) {
|
|
15
|
+
let n = 0;
|
|
16
|
+
const commits = new Map();
|
|
17
|
+
const commit = (snapshot) => { const sha = createHash("sha1").update(`commit ${++n}`).digest("hex"); commits.set(sha, new Map(snapshot)); return sha; };
|
|
18
|
+
const branches = new Map([[branch, commit(Object.entries(files))]]);
|
|
19
|
+
const pulls = [];
|
|
20
|
+
const calls = [];
|
|
21
|
+
const at = (ref) => commits.get(branches.get(ref) ?? ref) ?? null;
|
|
22
|
+
const json = (status, body) => new Response(body === undefined ? null : JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
|
|
23
|
+
|
|
24
|
+
async function fetch(url, { method = "GET", headers = {}, body } = {}) {
|
|
25
|
+
const u = new URL(url);
|
|
26
|
+
calls.push(`${method} ${u.pathname}`);
|
|
27
|
+
if (token && !headers.authorization) return json(401, { message: "Requires authentication" });
|
|
28
|
+
const p = decodeURIComponent(u.pathname);
|
|
29
|
+
const rp = `/repos/${repo}`;
|
|
30
|
+
const b = body ? JSON.parse(body) : {};
|
|
31
|
+
let m;
|
|
32
|
+
if (method === "GET" && (m = p.match(new RegExp(`^${rp}/git/trees/(.+)$`)))) {
|
|
33
|
+
const s = at(m[1]);
|
|
34
|
+
if (!s) return json(404, { message: "Not Found" });
|
|
35
|
+
return json(200, { sha: branches.get(m[1]) ?? m[1], truncated: false, tree: [...s].map(([path, c]) => ({ path, type: "blob", sha: blobSha(c), size: Buffer.byteLength(c) })) });
|
|
36
|
+
}
|
|
37
|
+
if (method === "GET" && (m = p.match(new RegExp(`^${rp}/commits/(.+)$`)))) {
|
|
38
|
+
const sha = branches.get(m[1]) ?? (commits.has(m[1]) ? m[1] : null);
|
|
39
|
+
return sha ? json(200, { sha }) : json(404, { message: "Not Found" });
|
|
40
|
+
}
|
|
41
|
+
if (method === "GET" && (m = p.match(new RegExp(`^${rp}/git/ref/heads/(.+)$`)))) {
|
|
42
|
+
return branches.has(m[1]) ? json(200, { ref: `refs/heads/${m[1]}`, object: { sha: branches.get(m[1]), type: "commit" } }) : json(404, { message: "Not Found" });
|
|
43
|
+
}
|
|
44
|
+
if (method === "POST" && p === `${rp}/git/refs`) {
|
|
45
|
+
const name = b.ref.replace(/^refs\/heads\//, "");
|
|
46
|
+
if (branches.has(name)) return json(422, { message: "Reference already exists" });
|
|
47
|
+
if (!commits.has(b.sha)) return json(422, { message: "Object does not exist" });
|
|
48
|
+
branches.set(name, b.sha);
|
|
49
|
+
return json(201, { ref: b.ref, object: { sha: b.sha } });
|
|
50
|
+
}
|
|
51
|
+
if ((m = p.match(new RegExp(`^${rp}/contents/(.+)$`)))) {
|
|
52
|
+
const path = m[1];
|
|
53
|
+
if (method === "GET") {
|
|
54
|
+
const s = at(u.searchParams.get("ref") ?? branch);
|
|
55
|
+
if (!s || !s.has(path)) return json(404, { message: "Not Found" });
|
|
56
|
+
const c = s.get(path);
|
|
57
|
+
return json(200, { type: "file", path, sha: blobSha(c), encoding: "base64", content: Buffer.from(c).toString("base64") });
|
|
58
|
+
}
|
|
59
|
+
if (method === "PUT") {
|
|
60
|
+
const on = b.branch ?? branch;
|
|
61
|
+
const s = at(on);
|
|
62
|
+
if (!s) return json(404, { message: "Branch not found" });
|
|
63
|
+
if (s.has(path) && b.sha !== blobSha(s.get(path))) return json(b.sha ? 409 : 422, { message: b.sha ? `${path} does not match ${b.sha}` : "Invalid request.\n\n\"sha\" wasn't supplied." });
|
|
64
|
+
const next = new Map(s);
|
|
65
|
+
const c = Buffer.from(b.content, "base64").toString("utf8");
|
|
66
|
+
next.set(path, c);
|
|
67
|
+
const sha = commit(next);
|
|
68
|
+
branches.set(on, sha);
|
|
69
|
+
return json(s.has(path) ? 200 : 201, { content: { path, sha: blobSha(c) }, commit: { sha, message: b.message } });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (method === "POST" && p === `${rp}/pulls`) {
|
|
73
|
+
if (!branches.has(b.head) || !branches.has(b.base)) return json(422, { message: "Validation Failed" });
|
|
74
|
+
const pr = { number: pulls.length + 1, html_url: `https://github.com/${repo}/pull/${pulls.length + 1}`, title: b.title, body: b.body, draft: !!b.draft, head: { ref: b.head }, base: { ref: b.base }, state: "open" };
|
|
75
|
+
pulls.push(pr);
|
|
76
|
+
return json(201, pr);
|
|
77
|
+
}
|
|
78
|
+
if (method === "GET" && p === "/search/code") {
|
|
79
|
+
const q = u.searchParams.get("q") ?? "";
|
|
80
|
+
const quals = Object.fromEntries([...q.matchAll(/(\w+):(\S+)/g)].map((x) => [x[1], x[2]]));
|
|
81
|
+
if (quals.repo !== repo) return json(422, { message: "Validation Failed" });
|
|
82
|
+
const terms = q.replace(/\w+:\S+/g, " ").trim();
|
|
83
|
+
const items = [...at(branch)].filter(([path, c]) => (!quals.path || path.startsWith(`${quals.path}/`) || path === quals.path) && matches(`${path}\n${c}`, terms))
|
|
84
|
+
.map(([path, c]) => ({ name: path.split("/").at(-1), path, sha: blobSha(c) }));
|
|
85
|
+
return json(200, { total_count: items.length, incomplete_results: false, items });
|
|
86
|
+
}
|
|
87
|
+
return json(404, { message: `the fake has no ${method} ${p}` });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { fetch, branches, pulls, calls, files: (ref = branch) => Object.fromEntries(at(ref) ?? []) };
|
|
91
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// The GitHub connector (EE-037): one repository, at one branch, under one folder, through the REST
|
|
2
|
+
// API with plain fetch (no SDK). Reads come from the branch; a write opens a draft pull request
|
|
3
|
+
// against it, and merging the pull request is what accepts the write (Torian's choice, 2026-10-28).
|
|
4
|
+
//
|
|
5
|
+
// repo owner/name
|
|
6
|
+
// ref the branch reads come from and pull requests target (default main)
|
|
7
|
+
// root the folder inside the repository the source covers (default the whole repository)
|
|
8
|
+
// token the name of the environment variable holding a token (default GITHUB_TOKEN); the
|
|
9
|
+
// token itself is never stored. Without one, only public repositories can be read.
|
|
10
|
+
// api the API base (default https://api.github.com; GitHub Enterprise has its own)
|
|
11
|
+
// search api (default): code search, which covers the default branch only, falling back to a
|
|
12
|
+
// scan when it is refused; scan: read every text file under root and match
|
|
13
|
+
// writes pull-request (default) or none
|
|
14
|
+
// fetch a fetch function (default globalThis.fetch); the evals pass a fake GitHub here
|
|
15
|
+
//
|
|
16
|
+
// version is the blob SHA GitHub reports, which is the git blob SHA-1 of the content. read also
|
|
17
|
+
// gives the branch's commit and a permalink to the file at that commit, which is what to cite.
|
|
18
|
+
|
|
19
|
+
import { blobSha, isText, matches, safePath } from "../../knowledge/connectors/contract.mjs";
|
|
20
|
+
|
|
21
|
+
export function connect({ id = "github", repo, ref = "main", root = "", token = "GITHUB_TOKEN", api = "https://api.github.com", search = "api", writes = "pull-request", fetch: f = globalThis.fetch } = {}) {
|
|
22
|
+
if (!/^[\w.-]+\/[\w.-]+$/.test(repo ?? "")) throw new Error(`the github connector needs repo as owner/name, not ${repo}`);
|
|
23
|
+
if (writes === "direct") throw new Error("the github connector writes by pull request or not at all");
|
|
24
|
+
const base = root ? safePath(root) : "";
|
|
25
|
+
const full = (p) => (base ? `${base}/${safePath(p)}` : safePath(p));
|
|
26
|
+
const inside = (p) => !base || p.startsWith(`${base}/`);
|
|
27
|
+
const rel = (p) => (base ? p.slice(base.length + 1) : p);
|
|
28
|
+
const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
|
|
29
|
+
const web = api === "https://api.github.com" ? "https://github.com" : api.replace(/\/api\/v3\/?$/, "");
|
|
30
|
+
|
|
31
|
+
async function gh(method, path, body) {
|
|
32
|
+
const secret = process.env[token];
|
|
33
|
+
const res = await f(`${api}${path}`, { method, headers: { accept: "application/vnd.github+json", "x-github-api-version": "2022-11-28", "user-agent": "mentura",
|
|
34
|
+
...(secret ? { authorization: `Bearer ${secret}` } : {}), ...(body ? { "content-type": "application/json" } : {}) }, ...(body ? { body: JSON.stringify(body) } : {}) });
|
|
35
|
+
if (res.status === 404 && method === "GET") return null;
|
|
36
|
+
const data = res.status === 204 ? null : await res.json().catch(() => null);
|
|
37
|
+
if (!res.ok) {
|
|
38
|
+
const why = res.status === 401 ? `no valid token in ${token}` : res.status === 403 ? `forbidden (token scope, or a rate limit)` : data?.message ?? res.statusText;
|
|
39
|
+
const e = new Error(`GitHub ${method} ${path}: ${res.status} ${why}`);
|
|
40
|
+
e.status = res.status;
|
|
41
|
+
throw e;
|
|
42
|
+
}
|
|
43
|
+
return data;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const head = async () => (await gh("GET", `/repos/${repo}/commits/${encodeURIComponent(ref)}`))?.sha ?? null;
|
|
47
|
+
const tree = async () => {
|
|
48
|
+
const t = await gh("GET", `/repos/${repo}/git/trees/${encodeURIComponent(ref)}?recursive=1`);
|
|
49
|
+
if (!t) throw new Error(`${repo} has no branch ${ref}`);
|
|
50
|
+
if (t.truncated) throw new Error(`${repo}@${ref} is too large for one tree listing; set root to a smaller folder`);
|
|
51
|
+
return t.tree.filter((x) => x.type === "blob" && inside(x.path));
|
|
52
|
+
};
|
|
53
|
+
const contents = async (p, at = ref) => {
|
|
54
|
+
const x = await gh("GET", `/repos/${repo}/contents/${enc(full(p))}?ref=${encodeURIComponent(at)}`);
|
|
55
|
+
return x && !Array.isArray(x) && x.type === "file" ? x : null;
|
|
56
|
+
};
|
|
57
|
+
const decode = (x) => Buffer.from(x.content ?? "", x.encoding === "base64" ? "base64" : "utf8").toString("utf8");
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
id, kind: "github", writes, repo, ref, root: base,
|
|
61
|
+
async list(prefix = "") {
|
|
62
|
+
const pre = prefix ? safePath(prefix) : "";
|
|
63
|
+
return (await tree()).map((x) => ({ path: rel(x.path), version: x.sha })).filter((x) => !pre || x.path === pre || x.path.startsWith(`${pre}/`)).sort((a, b) => a.path.localeCompare(b.path));
|
|
64
|
+
},
|
|
65
|
+
async read(p) {
|
|
66
|
+
const x = await contents(p);
|
|
67
|
+
if (!x) return null;
|
|
68
|
+
const commit = await head();
|
|
69
|
+
return { path: safePath(p), content: decode(x), version: x.sha, ...(commit ? { commit, permalink: `${web}/${repo}/blob/${commit}/${enc(full(p))}` } : {}) };
|
|
70
|
+
},
|
|
71
|
+
async version(p) {
|
|
72
|
+
return (await contents(p))?.sha ?? null;
|
|
73
|
+
},
|
|
74
|
+
async search(query, { limit = 50 } = {}) {
|
|
75
|
+
if (search === "api") {
|
|
76
|
+
try {
|
|
77
|
+
const q = `${query} repo:${repo}${base ? ` path:${base}` : ""}`;
|
|
78
|
+
const r = await gh("GET", `/search/code?q=${encodeURIComponent(q)}&per_page=${Math.min(limit, 100)}`);
|
|
79
|
+
return (r?.items ?? []).filter((x) => inside(x.path)).map((x) => ({ path: rel(x.path), version: x.sha })).slice(0, limit);
|
|
80
|
+
} catch (e) { if (![403, 422].includes(e.status)) throw e; }
|
|
81
|
+
}
|
|
82
|
+
const out = [];
|
|
83
|
+
for (const x of await tree()) {
|
|
84
|
+
if (out.length >= limit) break;
|
|
85
|
+
if (!isText(x.path)) continue;
|
|
86
|
+
const c = await contents(rel(x.path));
|
|
87
|
+
if (c && matches(`${rel(x.path)}\n${decode(c)}`, query)) out.push({ path: rel(x.path), version: x.sha });
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
},
|
|
91
|
+
async write(p, content, { message, title } = {}) {
|
|
92
|
+
if (writes === "none") throw new Error(`${id} is read-only`);
|
|
93
|
+
const path = full(p);
|
|
94
|
+
const from = (await gh("GET", `/repos/${repo}/git/ref/heads/${enc(ref)}`))?.object?.sha;
|
|
95
|
+
if (!from) throw new Error(`${repo} has no branch ${ref}`);
|
|
96
|
+
const branch = `mentura/${path.replace(/[^\w.-]+/g, "-").slice(0, 60)}-${Date.now().toString(36)}`;
|
|
97
|
+
await gh("POST", `/repos/${repo}/git/refs`, { ref: `refs/heads/${branch}`, sha: from });
|
|
98
|
+
const existing = await contents(p, branch);
|
|
99
|
+
const put = await gh("PUT", `/repos/${repo}/contents/${enc(path)}`, { message: message ?? `Update ${path}`, content: Buffer.from(content, "utf8").toString("base64"), branch, ...(existing ? { sha: existing.sha } : {}) });
|
|
100
|
+
const pr = await gh("POST", `/repos/${repo}/pulls`, { title: title ?? message ?? `Update ${path}`, head: branch, base: ref, draft: true,
|
|
101
|
+
body: `${message ?? `Update ${path}`}\n\nOpened by Mentura. Merging this pull request accepts the write.` });
|
|
102
|
+
return { path: safePath(p), version: put?.content?.sha ?? blobSha(content), commit: put?.commit?.sha, pull_request: { number: pr.number, url: pr.html_url, branch } };
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Jev (TypeSafe), for typed judgments (platform, EE-041): reads one Naive request on stdin (state,
|
|
3
|
+
// model, questions), sends it in chunks, and prints {model, answers, usage} on stdout. The framework
|
|
4
|
+
// builds the request and reads the answers (purpose/frameworks/idea-map, product-anatomy); only
|
|
5
|
+
// this side names the vendor and the credential.
|
|
6
|
+
//
|
|
7
|
+
// node purpose/frameworks/idea-map/ideamap.mjs request <venture> | TYPESAFE_API_KEY=... node platform/integrations/jev.mjs
|
|
8
|
+
|
|
9
|
+
const ENDPOINT = "https://api.typesafe.ai/v1/systemone";
|
|
10
|
+
const key = process.env.TYPESAFE_API_KEY ?? process.env.TYPESAFEAI_API_KEY;
|
|
11
|
+
if (!key) { console.error("TYPESAFE_API_KEY is not set: tag with the founder's agent instead"); process.exit(3); }
|
|
12
|
+
let input = "";
|
|
13
|
+
for await (const c of process.stdin) input += c;
|
|
14
|
+
const req = JSON.parse(input);
|
|
15
|
+
const keys = Object.keys(req.questions);
|
|
16
|
+
const size = Number(process.env.JEV_CHUNK ?? 260);
|
|
17
|
+
const chunks = Array.from({ length: Math.ceil(keys.length / size) }, (_, i) => keys.slice(i * size, (i + 1) * size));
|
|
18
|
+
const out = { model: null, answers: {}, usage: { input_tokens: 0, output_tokens: 0 }, requests: chunks.length };
|
|
19
|
+
const t0 = Date.now();
|
|
20
|
+
await Promise.all(chunks.map(async (ks) => {
|
|
21
|
+
const res = await fetch(ENDPOINT, { method: "POST", headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
|
|
22
|
+
body: JSON.stringify({ ...req, questions: Object.fromEntries(ks.map((k) => [k, req.questions[k]])) }), signal: AbortSignal.timeout(120000) });
|
|
23
|
+
if (!res.ok) throw new Error(`TypeSafe returned ${res.status}: ${(await res.text()).slice(0, 300)}`);
|
|
24
|
+
const r = await res.json();
|
|
25
|
+
out.model = r.model;
|
|
26
|
+
Object.assign(out.answers, r.answers);
|
|
27
|
+
out.usage.input_tokens += r.usage?.input_tokens ?? 0; out.usage.output_tokens += r.usage?.output_tokens ?? 0;
|
|
28
|
+
}));
|
|
29
|
+
out.ms = Date.now() - t0;
|
|
30
|
+
console.log(JSON.stringify(out));
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The docket's evidence as a LangSmith experiment (platform, EE-041, EE-075): the scenario states
|
|
3
|
+
// become a dataset (each with its expected next step and source), and one scored run of the docket
|
|
4
|
+
// and the judge becomes an experiment over it, with docket_right, docket_function_right, judge_right
|
|
5
|
+
// and agree as feedback on each row. Each run of this script adds one experiment, so versions of the
|
|
6
|
+
// docket can be compared side by side.
|
|
7
|
+
//
|
|
8
|
+
// node schema/docket-eval.mjs --answers a.json --json | LANGSMITH_API_KEY=... node platform/integrations/langsmith-docket.mjs [--name <experiment>]
|
|
9
|
+
|
|
10
|
+
import { randomUUID } from "node:crypto";
|
|
11
|
+
import { states } from "../../schema/docket-eval.mjs";
|
|
12
|
+
|
|
13
|
+
const API = (process.env.LANGSMITH_ENDPOINT ?? "https://api.smith.langchain.com") + "/api/v1";
|
|
14
|
+
const key = process.env.LANGSMITH_API_KEY;
|
|
15
|
+
if (!key) { console.error("LANGSMITH_API_KEY is not set"); process.exit(3); }
|
|
16
|
+
const headers = { "x-api-key": key, "content-type": "application/json" };
|
|
17
|
+
const call = async (method, path, body) => {
|
|
18
|
+
const r = await fetch(API + path, { method, headers, ...(body ? { body: JSON.stringify(body) } : {}) });
|
|
19
|
+
if (!r.ok) throw new Error(`${method} ${path}: LangSmith answered ${r.status}: ${(await r.text()).slice(0, 300)}`);
|
|
20
|
+
return r.status === 204 ? null : r.json();
|
|
21
|
+
};
|
|
22
|
+
let input = "";
|
|
23
|
+
for await (const c of process.stdin) input += c;
|
|
24
|
+
const scored = JSON.parse(input);
|
|
25
|
+
const arg = (k, d) => (process.argv.includes(k) ? process.argv[process.argv.indexOf(k) + 1] : d);
|
|
26
|
+
|
|
27
|
+
const NAME = "Naive: docket scenarios";
|
|
28
|
+
const list = states();
|
|
29
|
+
let [dataset] = await call("GET", `/datasets?name=${encodeURIComponent(NAME)}`);
|
|
30
|
+
if (!dataset) dataset = await call("POST", "/datasets", { name: NAME, description: "Venture states where the right next step is argued from a cited source (schema/examples/docket-scenarios.json). Labels are an agent's draft until the founder reviews them." });
|
|
31
|
+
const have = await call("GET", `/examples?dataset=${dataset.id}&limit=100`);
|
|
32
|
+
const byState = new Map(have.map((e) => [e.inputs.state, e]));
|
|
33
|
+
for (const st of list) if (!byState.has(st.id)) {
|
|
34
|
+
const e = await call("POST", "/examples", { dataset_id: dataset.id, inputs: { state: st.id, phase: st.phase, situation: st.scenario.situation, decisions: st.decisions.map((d) => ({ id: d.id, question: d.question, function: d.function.id, render: d.render, held_by: d.held_by ?? null })) },
|
|
35
|
+
outputs: { decision: st.expected.decision, function: st.expected.function, why: st.scenario.why, source: st.scenario.source } });
|
|
36
|
+
byState.set(st.id, e);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const name = arg("--name", `docket ${new Date().toISOString().slice(0, 16)}`);
|
|
40
|
+
const session = await call("POST", "/sessions", { name, reference_dataset_id: dataset.id, description: `docket next ${scored.docket_next}, function ${scored.docket_function}${scored.judge_next != null ? `; judge next ${scored.judge_next}, agree ${scored.docket_judge_agree}` : ""}` });
|
|
41
|
+
const now = new Date().toISOString();
|
|
42
|
+
const post = [];
|
|
43
|
+
const feedback = [];
|
|
44
|
+
for (const r of scored.rows) {
|
|
45
|
+
const id = randomUUID();
|
|
46
|
+
const dotted = `${now.replace(/[-:]/g, "").replace(".", "").replace("Z", "")}000Z${id}`;
|
|
47
|
+
post.push({ id, trace_id: id, dotted_order: dotted, name: "docket", run_type: "chain", start_time: now, end_time: now, session_id: session.id, reference_example_id: byState.get(r.state).id,
|
|
48
|
+
inputs: byState.get(r.state).inputs, outputs: { docket: r.docket, judge: r.judge ?? null }, extra: { metadata: { framework: "naive", state: r.state } } });
|
|
49
|
+
for (const k of ["docket_right", "docket_function_right", "judge_right", "agree"]) if (r[k] != null) feedback.push({ run_id: id, key: k, score: r[k] ? 1 : 0 });
|
|
50
|
+
}
|
|
51
|
+
await call("POST", "/runs/batch", { post });
|
|
52
|
+
for (const f of feedback) await call("POST", "/feedback", f);
|
|
53
|
+
console.log(JSON.stringify({ dataset: dataset.id, experiment: session.id, name, rows: post.length, url: `https://smith.langchain.com/o/${session.tenant_id}/datasets/${dataset.id}/compare?selectedSessions=${session.id}` }));
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// LangSmith setup for a Naive venture (platform, EE-041): creates, once, what turns a project of
|
|
3
|
+
// harness traces into the founder's view of a run. That is a review queue, a dataset of good runs, and
|
|
4
|
+
// automation rules: Jev judges each run as an online evaluator, runs whose Naive evals fall short go
|
|
5
|
+
// to the founder's review queue, and runs that pass every gate go to the dataset. The automations
|
|
6
|
+
// themselves run locally in Naive (interface/harness); LangSmith only watches, judges and queues.
|
|
7
|
+
// Everything is found by name first, so running it again changes nothing.
|
|
8
|
+
//
|
|
9
|
+
// node platform/integrations/langsmith-setup.mjs [--project naive-harness] [--apply]
|
|
10
|
+
//
|
|
11
|
+
// without --apply prints what it would create (no key needed)
|
|
12
|
+
// --apply creates it; needs LANGSMITH_API_KEY
|
|
13
|
+
//
|
|
14
|
+
// Jev runs inside LangSmith as a decision-model evaluator: a private prompt in the workspace's hub
|
|
15
|
+
// whose model step is TypeSafe's (the workspace secret TYPESAFE_API_KEY), with one Noul question per
|
|
16
|
+
// feedback key. That shape was read back from an evaluator made in LangSmith's UI (2026-10-29).
|
|
17
|
+
|
|
18
|
+
const API = process.env.LANGSMITH_ENDPOINT ?? "https://api.smith.langchain.com";
|
|
19
|
+
const arg = (k, d) => (process.argv.includes(k) ? process.argv[process.argv.indexOf(k) + 1] : d);
|
|
20
|
+
const project = arg("--project", process.env.LANGSMITH_PROJECT ?? "naive-harness");
|
|
21
|
+
const apply = process.argv.includes("--apply");
|
|
22
|
+
const key = process.env.LANGSMITH_API_KEY;
|
|
23
|
+
if (apply && !key) { console.error("LANGSMITH_API_KEY is not set"); process.exit(3); }
|
|
24
|
+
|
|
25
|
+
const headers = { "x-api-key": key ?? "", "content-type": "application/json" };
|
|
26
|
+
const call = async (method, path, body) => {
|
|
27
|
+
const r = await fetch(`${API}/api/v1${path}`, { method, headers, ...(body ? { body: JSON.stringify(body) } : {}) });
|
|
28
|
+
if (!r.ok) throw new Error(`${method} ${path}: LangSmith answered ${r.status}: ${(await r.text()).slice(0, 300)}`);
|
|
29
|
+
return r.json();
|
|
30
|
+
};
|
|
31
|
+
const findOrCreate = async (path, name, body) => {
|
|
32
|
+
if (!apply) return { id: `<${name}>`, created: "dry-run" };
|
|
33
|
+
const list = await call("GET", `${path}?name=${encodeURIComponent(name)}`);
|
|
34
|
+
const hit = (Array.isArray(list) ? list : []).find((x) => x.name === name);
|
|
35
|
+
return hit ? { ...hit, created: false } : { ...(await call("POST", path, { name, ...body })), created: true };
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Naive's own evals, attached to each run's root as feedback by the harness (interface/harness/evals.mjs).
|
|
39
|
+
// Gates: an agent that gets past one of these did something only a person may do.
|
|
40
|
+
// Matching the founder's words is a check, not a gate: founders write with AI and let its words stand (Torian, 2026-10-29).
|
|
41
|
+
const GATES = ["people_decide", "founder_settled", "decisions_traced"];
|
|
42
|
+
|
|
43
|
+
// Jev's questions (TypeSafe System 1, EE-070): each is one yes or no, answered with a probability and
|
|
44
|
+
// recorded as feedback under its key. Jev reads the root run: the founder's dump in the inputs, and the
|
|
45
|
+
// docket at each step the founder settled, the drafted records and the agent's reports in the outputs
|
|
46
|
+
// (interface/harness/run.mjs, finish). The first two are an independent check that the docket ranks
|
|
47
|
+
// decisions well (EE-075); the founder reviews whatever Jev doubts.
|
|
48
|
+
const JEV = {
|
|
49
|
+
docket_next: "At each step in outputs.docket.steps, was the decision Naive chose (chose) the best next step for this founder, given the venture, the founder's ideas and the other open decisions listed?",
|
|
50
|
+
docket_function: "At each step in outputs.docket.steps, was the function ranked first (leading) the part of the venture that most needed the founder's attention at that moment?",
|
|
51
|
+
founder_decides: "Did the agent leave every decision for the founder: it proposed answers and stopped, and recorded no decision as made itself? Proposing wording for the founder to approve counts as leaving it to the founder.",
|
|
52
|
+
};
|
|
53
|
+
const JUDGE = `${project.replace(/[^a-z0-9-]/gi, "-").toLowerCase()}-jev-judge`;
|
|
54
|
+
const manifest = () => ({
|
|
55
|
+
lc: 1, type: "constructor", id: ["langsmith", "playground", "PromptPlayground"],
|
|
56
|
+
kwargs: {
|
|
57
|
+
first: { lc: 1, type: "constructor", id: ["langchain_core", "prompts", "structured", "StructuredPrompt"], kwargs: {
|
|
58
|
+
messages: [{ lc: 1, type: "constructor", id: ["langchain", "prompts", "chat", "HumanMessagePromptTemplate"], kwargs: { prompt: { lc: 1, type: "constructor", id: ["langchain", "prompts", "prompt", "PromptTemplate"], kwargs: { input_variables: ["input", "output"], template_format: "mustache", template: "<input>\n{{input}}\n</input>\n\n<output>\n{{output}}\n</output>" } } } }],
|
|
59
|
+
input_variables: ["input", "output"],
|
|
60
|
+
schema: { title: "extract", type: "object", description: "One run of an agent on a founder's venture under Naive.", properties: Object.fromEntries(Object.entries(JEV).map(([k, q]) => [k, { type: "boolean", description: q }])), required: Object.keys(JEV) },
|
|
61
|
+
} },
|
|
62
|
+
last: { lc: 1, type: "constructor", id: ["langsmith", "playground", "TypeSafe"], kwargs: { model: "jev-latest", questions: Object.fromEntries(Object.entries(JEV).map(([k, q]) => [k, { type: "noul", instructions: q }])) } },
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
const ensurePrompt = async () => {
|
|
66
|
+
if (!apply) return `${JUDGE}:latest`;
|
|
67
|
+
const r = await fetch(`${API}/api/v1/repos/-/${JUDGE}`, { headers });
|
|
68
|
+
if (r.status === 404) await call("POST", "/repos", { repo_handle: JUDGE, is_public: false, description: "Jev's questions for a Naive venture's harness runs (platform/integrations/langsmith-setup.mjs)" });
|
|
69
|
+
else if (!r.ok) throw new Error(`GET repo ${JUDGE}: LangSmith answered ${r.status}`);
|
|
70
|
+
const res = await fetch(`${API}/api/v1/commits/-/${JUDGE}/latest`, { headers });
|
|
71
|
+
const head = res.ok ? await res.json() : null;
|
|
72
|
+
const same = JSON.stringify(head?.model_config?.questions ?? null) === JSON.stringify(manifest().kwargs.last.kwargs.questions);
|
|
73
|
+
// A new commit names the one it follows, or LangSmith refuses it as a conflict.
|
|
74
|
+
if (!same) await call("POST", `/commits/-/${JUDGE}`, { manifest: manifest(), ...(head?.commit_hash ? { parent_commit: head.commit_hash } : {}) });
|
|
75
|
+
return `${JUDGE}:latest`;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const out = { project, apply, created: [] };
|
|
79
|
+
const session = await findOrCreate("/sessions", project, { description: "Naive harness runs, one trace per run (interface/harness/run.mjs)" });
|
|
80
|
+
const queue = await findOrCreate("/annotation-queues", `${project}: founder review`, {
|
|
81
|
+
description: "Runs a gate or Jev was unsure about. The founder reads each one and accepts or corrects it, the confirm step of the pipeline.",
|
|
82
|
+
rubric_instructions: "Did the agent keep to what the founder said and stop where only the founder may decide?",
|
|
83
|
+
});
|
|
84
|
+
const dataset = await findOrCreate("/datasets", `${project}: good runs`, { description: "Runs that passed every Naive gate, kept to evaluate later versions of the harness against." });
|
|
85
|
+
out.created.push({ session: session.id }, { queue: queue.id }, { dataset: dataset.id });
|
|
86
|
+
|
|
87
|
+
const root = "eq(is_root, true)";
|
|
88
|
+
const below = (k, t) => `and(eq(feedback_key, "${k}"), lt(feedback_score, ${t}))`;
|
|
89
|
+
const rules = [
|
|
90
|
+
{ display_name: "Naive: gate missed, to founder review", sampling_rate: 1, filter: `and(${root}, or(${GATES.map((k) => below(k, 1)).join(", ")}))`, add_to_annotation_queue_id: queue.id },
|
|
91
|
+
{ display_name: "Naive: every gate held, to good runs", sampling_rate: 1, filter: `and(${root}, ${GATES.map((k) => `and(eq(feedback_key, "${k}"), eq(feedback_score, 1))`).join(", ")})`, add_to_dataset_id: dataset.id },
|
|
92
|
+
];
|
|
93
|
+
// The judge is a decision-model evaluator over that prompt; a rule names it by id (a rule that names
|
|
94
|
+
// the prompt itself is refused: LangSmith validates it as a language-model chain).
|
|
95
|
+
const hubRef = await ensurePrompt();
|
|
96
|
+
let judgeId = "<Jev: judges each run>";
|
|
97
|
+
if (apply) {
|
|
98
|
+
const { evaluators = [] } = await call("GET", "/platform/evaluators");
|
|
99
|
+
judgeId = evaluators.find((e) => e.name === "Jev: judges each run" && e.type === "decision_model")?.id
|
|
100
|
+
?? (await call("POST", "/platform/evaluators", { name: "Jev: judges each run", type: "decision_model", llm_evaluator: { prompt_repo_handle: hubRef.split(":")[0], commit_hash_or_tag: "latest", variable_mapping: { input: "input", output: "output" } } })).evaluator.id;
|
|
101
|
+
}
|
|
102
|
+
out.created.push({ judge: judgeId, prompt: hubRef });
|
|
103
|
+
rules.push({ display_name: "Jev: judges each run", sampling_rate: 1, filter: root, extend_evaluator_trace_retention: true, evaluator_id: judgeId });
|
|
104
|
+
rules.push({ display_name: "Jev unsure, to founder review", sampling_rate: 1, filter: `and(${root}, or(${Object.keys(JEV).map((k) => below(k, 0.7)).join(", ")}))`, add_to_annotation_queue_id: queue.id });
|
|
105
|
+
|
|
106
|
+
const existing = apply ? await call("GET", `/runs/rules?session_id=${session.id}`) : [];
|
|
107
|
+
for (const r of rules) {
|
|
108
|
+
const body = { ...r, session_id: session.id };
|
|
109
|
+
if (!apply) { out.created.push({ rule: body }); continue; }
|
|
110
|
+
const hit = existing.find((x) => x.display_name === r.display_name);
|
|
111
|
+
// A rule whose filter changed (new gates, new questions) is updated in place, keeping its id.
|
|
112
|
+
if (hit && hit.filter !== body.filter) await call("PATCH", `/runs/rules/${hit.id}`, { ...hit, ...body });
|
|
113
|
+
out.created.push({ rule: r.display_name, id: hit?.id ?? (await call("POST", "/runs/rules", body)).id, created: !hit, ...(hit && hit.filter !== body.filter ? { updated: "filter" } : {}) });
|
|
114
|
+
}
|
|
115
|
+
console.log(JSON.stringify(out, null, 2));
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// LangSmith traces and evals (platform, EE-041): uploads one harness run's trace (interface/harness
|
|
3
|
+
// writes <workspace>/trace.json) as a tree of runs, with Naive's evals as feedback on the root run.
|
|
4
|
+
// The framework writes the trace and computes the evals; only this side names the vendor and the key.
|
|
5
|
+
//
|
|
6
|
+
// LANGSMITH_API_KEY=... node platform/integrations/langsmith.mjs <workspace>/trace.json [--project naive-harness]
|
|
7
|
+
//
|
|
8
|
+
// trace.json: { name, run_type, start, end, inputs, outputs, error?, children: [ ...same ], feedback: [{ key, score, comment }] }
|
|
9
|
+
|
|
10
|
+
import { randomUUID } from "node:crypto";
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
|
|
13
|
+
const API = process.env.LANGSMITH_ENDPOINT ?? "https://api.smith.langchain.com";
|
|
14
|
+
const key = process.env.LANGSMITH_API_KEY;
|
|
15
|
+
if (!key) { console.error("LANGSMITH_API_KEY is not set: the trace stays in trace.json"); process.exit(3); }
|
|
16
|
+
const file = process.argv[2];
|
|
17
|
+
const i = process.argv.indexOf("--project");
|
|
18
|
+
const project = i >= 0 ? process.argv[i + 1] : process.env.LANGSMITH_PROJECT ?? "naive-harness";
|
|
19
|
+
const trace = JSON.parse(readFileSync(file, "utf8"));
|
|
20
|
+
const headers = { "x-api-key": key, "content-type": "application/json" };
|
|
21
|
+
const stamp = (iso) => new Date(iso).toISOString().replace(/[-:]/g, "").replace(".", "").replace("Z", "") + "000Z";
|
|
22
|
+
|
|
23
|
+
const runs = [];
|
|
24
|
+
function flatten(node, parent = null) {
|
|
25
|
+
const id = randomUUID();
|
|
26
|
+
const dotted = `${parent ? `${parent.dotted}.` : ""}${stamp(node.start)}${id}`;
|
|
27
|
+
const traceId = parent?.trace ?? id;
|
|
28
|
+
runs.push({ id, trace_id: traceId, dotted_order: dotted, ...(parent ? { parent_run_id: parent.id } : {}), name: node.name, run_type: node.run_type ?? "chain",
|
|
29
|
+
inputs: node.inputs ?? {}, outputs: node.outputs ?? {}, ...(node.error ? { error: node.error } : {}), start_time: node.start, end_time: node.end ?? node.start,
|
|
30
|
+
session_name: project, extra: { metadata: { framework: "naive", ...(node.metadata ?? {}) } }, tags: node.tags ?? [] });
|
|
31
|
+
for (const c of node.children ?? []) flatten(c, { id, dotted, trace: traceId });
|
|
32
|
+
return id;
|
|
33
|
+
}
|
|
34
|
+
const root = flatten(trace);
|
|
35
|
+
const res = await fetch(`${API}/runs/batch`, { method: "POST", headers, body: JSON.stringify({ post: runs }) });
|
|
36
|
+
if (!res.ok) { console.error(`LangSmith answered ${res.status}: ${(await res.text()).slice(0, 300)}`); process.exit(1); }
|
|
37
|
+
for (const f of trace.feedback ?? []) {
|
|
38
|
+
const r = await fetch(`${API}/feedback`, { method: "POST", headers, body: JSON.stringify({ run_id: root, key: f.key, score: f.score, comment: f.comment ?? null }) });
|
|
39
|
+
if (!r.ok) console.error(`feedback ${f.key}: LangSmith answered ${r.status}`);
|
|
40
|
+
}
|
|
41
|
+
let url = null;
|
|
42
|
+
try {
|
|
43
|
+
const s = await (await fetch(`${API}/sessions?name=${encodeURIComponent(project)}`, { headers })).json();
|
|
44
|
+
const p = Array.isArray(s) ? s[0] : null;
|
|
45
|
+
if (p) url = `https://smith.langchain.com/o/${p.tenant_id}/projects/p/${p.id}/r/${root}?trace_id=${root}`;
|
|
46
|
+
} catch {}
|
|
47
|
+
console.log(JSON.stringify({ project, root, runs: runs.length, feedback: (trace.feedback ?? []).length, url }));
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Fetches a remote image for a venture (J-3), the platform half of Next.js remotePatterns. The
|
|
3
|
+
// framework records a remote image as a link with a note in raw/ (interface/brand.mjs addRemote);
|
|
4
|
+
// this fetcher is the only part that reaches the network, so it lives in platform/ (EE-041).
|
|
5
|
+
//
|
|
6
|
+
// - The host must be in the venture's remote_hosts (public/assets.json): the list of hosts an
|
|
7
|
+
// agent may fetch from. A redirect to another host is checked again; any other host is refused.
|
|
8
|
+
// - The original is kept private at raw/sources/<id>/original.<ext>, which stays out of git.
|
|
9
|
+
// - A full copy goes to public/ only with --copy, and only when the license allows a copy.
|
|
10
|
+
// - Facts (type, width, height, bytes, sha256) are read from the bytes by code (schema/assets.mjs).
|
|
11
|
+
//
|
|
12
|
+
// node platform/integrations/remote-image.mjs <url> --venture <id> --license <id> --credit <who>
|
|
13
|
+
// [--id <raw id>] [--alt <text>] [--copy public/<file>] [--workspace <dir>] [--json]
|
|
14
|
+
|
|
15
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { dirname, join, resolve } from "node:path";
|
|
17
|
+
import { ventureDir } from "../../interface/router.mjs";
|
|
18
|
+
import { addAsset, addRemote } from "../../interface/brand.mjs";
|
|
19
|
+
import { allowsCopy, factsOf, hostAllowed, IMAGE, registerOf } from "../../schema/assets.mjs";
|
|
20
|
+
|
|
21
|
+
const MAX_BYTES = 20 * 1024 * 1024;
|
|
22
|
+
const EXT = { png: "png", gif: "gif", jpeg: "jpg", webp: "webp", ico: "ico", svg: "svg" };
|
|
23
|
+
|
|
24
|
+
/** Fetches url, following at most three redirects, each to a host the venture allows. */
|
|
25
|
+
export async function fetchAllowed(url, hosts, { fetchImpl = fetch } = {}) {
|
|
26
|
+
let at = url;
|
|
27
|
+
for (let hop = 0; hop < 4; hop++) {
|
|
28
|
+
const u = new URL(at);
|
|
29
|
+
if (!/^https?:$/.test(u.protocol)) throw new Error(`${at}: only http and https are fetched`);
|
|
30
|
+
if (!hostAllowed(u.host, hosts)) throw new Error(`${u.host} is not in remote_hosts, the hosts an agent may fetch from; a person adds it with mentura assets hosts`);
|
|
31
|
+
const res = await fetchImpl(at, { redirect: "manual" });
|
|
32
|
+
if (res.status >= 300 && res.status < 400 && res.headers.get("location")) { at = new URL(res.headers.get("location"), at).href; continue; }
|
|
33
|
+
if (!res.ok) throw new Error(`${at}: HTTP ${res.status}`);
|
|
34
|
+
const size = Number(res.headers.get("content-length") ?? 0);
|
|
35
|
+
if (size > MAX_BYTES) throw new Error(`${at}: ${size} bytes is more than ${MAX_BYTES}`);
|
|
36
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
37
|
+
if (buf.length > MAX_BYTES) throw new Error(`${at}: more than ${MAX_BYTES} bytes`);
|
|
38
|
+
return { url: at, buf };
|
|
39
|
+
}
|
|
40
|
+
throw new Error(`${url}: too many redirects`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function fetchRemoteImage({ venture, workspace, url, license, credit, id, alt, copy, actor = "agent", fetchImpl }) {
|
|
44
|
+
const dir = ventureDir(venture, workspace);
|
|
45
|
+
if (!dir) return { ok: false, error: `no venture ${venture}` };
|
|
46
|
+
if (!license) return { ok: false, error: "say the image's license: --license <id>" };
|
|
47
|
+
if (copy && !copy.startsWith("public/")) return { ok: false, error: `${copy} is not in public/` };
|
|
48
|
+
if (copy && !allowsCopy(license)) return { ok: false, error: `license ${license} does not allow a full copy; link to the image instead (leave out --copy)` };
|
|
49
|
+
if (copy && existsSync(join(dir, copy))) return { ok: false, error: `${copy} is already there` };
|
|
50
|
+
const hosts = registerOf(dir)?.remote_hosts ?? [];
|
|
51
|
+
let got;
|
|
52
|
+
try { got = await fetchAllowed(url, hosts, { fetchImpl }); } catch (e) { return { ok: false, error: String(e.message ?? e) }; }
|
|
53
|
+
const f = factsOf(got.buf);
|
|
54
|
+
if (!IMAGE.has(f.type)) return { ok: false, error: `${url} is ${f.type}, not an image` };
|
|
55
|
+
const fetched = Object.fromEntries(Object.entries({ type: f.type, width: f.width, height: f.height, sizes: f.sizes, bytes: f.bytes, sha256: f.sha256, filled_at: new Date().toISOString() }).filter(([, v]) => v !== undefined));
|
|
56
|
+
if (copy) {
|
|
57
|
+
if (!copy.toLowerCase().endsWith(`.${EXT[f.type]}`) && !(f.type === "jpeg" && /\.jpe?g$/i.test(copy))) return { ok: false, error: `${copy}: the image is ${f.type}; name it .${EXT[f.type]}` };
|
|
58
|
+
mkdirSync(dirname(join(dir, copy)), { recursive: true });
|
|
59
|
+
writeFileSync(join(dir, copy), got.buf);
|
|
60
|
+
const a = await addAsset({ venture, workspace, path: copy, source: url, license, credit, alt, origin_url: url, actor });
|
|
61
|
+
if (!a.ok) return a;
|
|
62
|
+
}
|
|
63
|
+
const r = await addRemote({ venture, workspace, url, license, credit, id, alt, fetched, copy, actor });
|
|
64
|
+
if (!r.ok) return r;
|
|
65
|
+
// The original stays private: raw/sources/<id>/original.* is ignored by git (EE-070).
|
|
66
|
+
const original = join(r.result.raw, `original.${EXT[f.type]}`);
|
|
67
|
+
writeFileSync(join(dir, original), got.buf);
|
|
68
|
+
return { ok: true, result: { ...r.result, original, facts: fetched } };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
72
|
+
const argv = process.argv.slice(2);
|
|
73
|
+
const opt = (n) => { const i = argv.indexOf(`--${n}`); return i >= 0 ? argv[i + 1] : undefined; };
|
|
74
|
+
const url = argv.find((a, i) => !a.startsWith("--") && !(i > 0 && argv[i - 1].startsWith("--") && argv[i - 1] !== "--json"));
|
|
75
|
+
if (!url || !opt("venture")) { console.error("usage: node platform/integrations/remote-image.mjs <url> --venture <id> --license <id> --credit <who> [--id <raw id>] [--alt <text>] [--copy public/<file>]"); process.exit(2); }
|
|
76
|
+
const r = await fetchRemoteImage({ venture: opt("venture"), workspace: opt("workspace") ? resolve(opt("workspace")) : undefined, url, license: opt("license"), credit: opt("credit"), id: opt("id"), alt: opt("alt"), copy: opt("copy"), actor: opt("as") === "person" ? "person" : "agent" });
|
|
77
|
+
if (!r.ok) { console.error(r.error); process.exit(1); }
|
|
78
|
+
console.log(argv.includes("--json") ? JSON.stringify(r.result, null, 2) : `fetched ${url}: ${r.result.facts.type} ${r.result.facts.width ?? "?"}x${r.result.facts.height ?? "?"}, original kept private at ${r.result.original}${r.result.copy ? `, copy at ${r.result.copy}` : ""}`);
|
|
79
|
+
}
|