# Developer Journey Atlas full public context Only publication-eligible routes are included. Documented complexity is a count-based route profile. No observed blocker diagnosis, association, or causal claim is available. # Developer Journey Atlas methodology The Atlas publishes only a selected account-creation-to-first-success route that passes deterministic platform identity, first-party source-content, claim-grounding, required-field, branch, and route-integrity gates. Documentation structure is not evidence of usability, conversion, abandonment, difficulty, or causality. # Shortest required path selection policy Date: 2026-07-21 ## Boundary Every audited journey begins at account creation and ends at the earliest meaningful first-success outcome established by current official evidence. The account, tenant, credentials, product resources, connected repositories, legal acceptance, and permissions do not exist at the start unless the developer goal explicitly names a prior artifact, such as an existing Git repository to deploy. ## Selected surface Use the platform's self-service web onboarding surface when one exists. Do not replace the product flow with a CLI, coding agent, infrastructure template, or third-party automation unless the selected developer goal explicitly requires that surface or no self-service path exists. ## Shortest-path rule Reconstruct complete official candidate routes to the same outcome, then select lexicographically: 1. Prefer a route without payment, administrator work, manual approval, or unavailable entitlement. 2. Minimize required developer actions. 3. When tied, prefer fewer unavoidable waits and fewer external-system handoffs. 4. When still tied, prefer the vendor's documented recommended, quickstart, default, or first route. 5. If a consequential tie remains, do not invent a winner. Mark the audit `needs-human-judgment`. No opaque weighted friction score is used. ## Units - A required action is one developer interaction or implementation action that changes state. - A required field is tracked under the form action that contains it and counted separately. - Documentation reading, optional work, platform automation, and passive waiting are not developer actions. - Required agreements, verifications, permissions, and external authorizations are included. - Platform automation and waits remain visible in their own fields. ## Publication gate The preserved source records in `records/` are evidence archives. A record is not a verified shortest path until a matching audit in `audits/` passes `shortest-path-audit.schema.json`, source-hash checks, evidence-reference checks, and cold or independent review. Only audits marked `verified` may expose action counts or peer comparison. All others must show their exact status and evidence gap. # Measurement contract (v2.0) ## What this corpus contains Developer Journey Atlas has two layers: 1. `records/` preserves detailed official-documentation evidence collected under the original research method. 2. `audits/` reconstructs the verified shortest required developer path from account creation to first success. A source record does not become a verified path merely because it validates. Public counts and comparisons come only from verified audit records. This is documentation and public-interface research. It is not telemetry, conversion, activation, drop-off, usability, or observed completion time. ## Required developer action One intentional interaction or implementation action performed by the developer before first success. Examples: - submit the account-creation form; - authorize repository access in GitHub; - choose `New > Web Service`; - install a dependency; - add required code; - run a command; - open the terminal result. Documentation reading, research-route selection, platform automation, and optional work are excluded. ## Required field One required input, checkbox, agreement, challenge, permission, URL, repository, command value, or other field contained in a required action. Fields are listed under their form or interaction and counted separately. A seven-field service form is one journey action and seven required fields. This prevents both hiding field burden and inflating the journey into one step per HTML control. ## External gate A required permission, administrator action, entitlement, payment, legal acceptance, identity-provider authorization, or other boundary outside the platform's direct control. The developer interaction may appear in the path. The gate itself is counted separately. ## Unavoidable wait A required asynchronous interval such as email delivery, provisioning, build, deployment, or human approval. Passive waiting is not a developer action. A separate developer action is counted only when the developer must interact again to continue. ## Platform outcome Automatic work performed by the platform or an external system, such as generating credentials, running a build, returning an API response, or marking a deploy Live. Platform outcomes remain visible but are never counted as developer actions. ## First success The earliest meaningful observable result explicitly named or demonstrated by the selected official getting-started route. Resource creation or credential visibility alone is not enough unless the official route defines it as the terminal developer result. ## Comparisons Anonymous peer context is withheld unless: - the subject and every peer have verified shortest-path audits; - the source research is marked complete; - all routes begin at account creation; - category and normalized first-success type match; - research granularity and comparability metadata are compatible; - at least three qualified peers remain. The comparison may show direct medians for required actions, required fields, unavoidable waits, and external gates. It must not combine them into a difficulty, quality, or drop-off score. ## Legacy measurements `selected-path-heuristic.json`, `ds-quality.json`, and original source-record step counts remain in the repository for provenance and migration analysis. They are not public shortest-path measurements and must not power user-facing claims. # Render public documented record ```json { "platform": { "name": "Render", "slug": "render", "organization": "Render" }, "category": "Cloud and application runtimes", "surface": { "name": "Your First Render Deploy, Dashboard Web Service", "selection_basis": "Render's Your First Render Deploy tutorial is the official first-app path. It documents free resources with no payment required, and the Dashboard tab is the first deployment method shown for creating a Web Service from a connected Git repo and opening the Live onrender.com URL.", "alternatives_considered": [ { "name": "Static Site on the same tutorial", "url": "https://render.com/docs/your-first-deploy", "reason_not_primary": "Peer service type for fully static apps; this reconstruction uses the Web Service path for server-side apps." }, { "name": "Render CLI deploy tab", "url": "https://render.com/docs/your-first-deploy", "reason_not_primary": "Peer deployment method on the same page; requires installing the CLI before first deploy." }, { "name": "Language/framework quickstarts", "url": "https://render.com/docs/your-first-deploy", "reason_not_primary": "Example-app variants after the general first-deploy tutorial." } ] }, "research_status": "complete", "researched_at": "2026-07-22", "official_docs_only": true, "entry_point": { "developer_intent": "Sign up for Render, connect a Git provider, deploy a server-side Web Service from a repository, and open the Live onrender.com URL.", "starting_url": "https://render.com/docs/your-first-deploy", "assumed_prior_state": [ "A GitHub, GitLab, or Bitbucket repository already contains the web app to deploy.", "No Render account or Live Web Service is assumed.", "No Render CLI install is assumed for the Dashboard path." ] }, "documented_first_success": { "official_milestone": "Your first deploy is Live and the app opens at its onrender.com URL", "normalized_outcome": "The developer's Web Service deploy is Live and serves its root content from the assigned onrender.com URL.", "observable_completion_signal": "The service shows Live status and opening the onrender.com URL returns the deployed app's root-path content.", "boundary_evidence": { "type": "explicitly-named", "official_label_or_terminal_state": "Your First Render Deploy walks signup, Git connection, Web Service creation, Deploy, then opening the deployed app; free resources require no payment.", "source_ids": [ "S2" ] }, "why_this_is_the_boundary": "The tutorial's documented terminal state is a successful first deploy that the developer can open. Signup, Git authorization, or form submission alone are not first success. Service-creation form fields are one configuration step with required details, not separate path steps.", "source_ids": [ "S2", "S4" ] }, "prerequisites": [ { "order": 1, "type": "account", "requirement": "A GitHub account that can authorize access to the application repository.", "required": true, "source_ids": [ "S2" ] }, { "order": 2, "type": "access", "requirement": "A GitHub repository containing the web app to deploy.", "required": true, "source_ids": [ "S2" ] }, { "order": 3, "type": "software", "requirement": "A server-side web app that listens for HTTP requests on Render's provided port and host.", "required": true, "source_ids": [ "S4" ] } ], "primary_path": [ { "step_number": 1, "phase": "account", "actor": "developer", "interface": "browser", "action": "Create a Render account with email and password.", "details": [], "input": "render_signup_url", "output": "render_account, dashboard_session", "success_signal": "The Render Dashboard opens.", "failure_or_wait": "", "required": true, "source_ids": [ "S2", "S7" ], "required_fields": [ { "label": "Email", "fieldType": "email", "required": true, "evidence": [ { "sourceId": "S7", "locator": "Create an account form, Email" } ] }, { "label": "Password", "fieldType": "password", "required": true, "evidence": [ { "sourceId": "S7", "locator": "Create an account form, Password" } ] } ] }, { "step_number": 2, "phase": "authenticate", "actor": "developer", "interface": "web-ui", "action": "Open Git Deployment Credentials in Account Settings.", "details": [], "input": "dashboard_session", "output": "git_credentials_view", "success_signal": "Git Deployment Credentials is visible.", "failure_or_wait": "", "required": true, "source_ids": [ "S2" ], "required_fields": [] }, { "step_number": 3, "phase": "authenticate", "actor": "developer", "interface": "web-ui", "action": "Click Add credential.", "details": [], "input": "git_credentials_view", "output": "git_provider_choices", "success_signal": "Git provider choices are visible.", "failure_or_wait": "", "required": true, "source_ids": [ "S2" ], "required_fields": [] }, { "step_number": 4, "phase": "authenticate", "actor": "developer", "interface": "web-ui", "action": "Choose GitHub as the Git provider.", "details": [], "input": "git_provider_choices, github_account", "output": "github_authorization_request", "success_signal": "GitHub authorization opens.", "failure_or_wait": "", "required": true, "source_ids": [ "S5" ], "required_fields": [] }, { "step_number": 5, "phase": "authenticate", "actor": "developer", "interface": "browser", "action": "Authorize Render to access the required GitHub repositories.", "details": [], "input": "github_authorization_request, app_repository", "output": "linked_github_credential, available_repository_list", "success_signal": "The Render Dashboard lists the authorized repositories.", "failure_or_wait": "", "required": true, "source_ids": [ "S5" ], "required_fields": [] }, { "step_number": 6, "phase": "configure", "actor": "developer", "interface": "web-ui", "action": "Open the New menu.", "details": [], "input": "dashboard_session, linked_github_credential", "output": "service_type_choices", "success_signal": "The service type menu is visible.", "failure_or_wait": "", "required": true, "source_ids": [ "S2" ], "required_fields": [] }, { "step_number": 7, "phase": "configure", "actor": "developer", "interface": "web-ui", "action": "Choose Web Service.", "details": [], "input": "service_type_choices", "output": "web_service_repository_picker", "success_signal": "The repository picker opens for a Web Service.", "failure_or_wait": "", "required": true, "source_ids": [ "S2" ], "required_fields": [] }, { "step_number": 8, "phase": "configure", "actor": "developer", "interface": "web-ui", "action": "Select the application repository.", "details": [], "input": "web_service_repository_picker, available_repository_list, app_repository", "output": "selected_repository", "success_signal": "The intended repository is selected.", "failure_or_wait": "", "required": true, "source_ids": [ "S5" ], "required_fields": [] }, { "step_number": 9, "phase": "configure", "actor": "developer", "interface": "web-ui", "action": "Click Connect for the selected repository.", "details": [], "input": "selected_repository", "output": "web_service_form", "success_signal": "The Web Service form opens.", "failure_or_wait": "", "required": true, "source_ids": [ "S5" ], "required_fields": [] }, { "step_number": 10, "phase": "configure", "actor": "developer", "interface": "web-ui", "action": "Complete the Web Service form.", "details": [], "input": "web_service_form, selected_repository, deployable_web_app", "output": "completed_service_form", "success_signal": "The Deploy Web Service action is available.", "failure_or_wait": "", "required": true, "source_ids": [ "S2" ], "required_fields": [ { "label": "Name", "fieldType": "text", "required": true, "evidence": [ { "sourceId": "S4", "locator": "Deploy your own code, Name field" } ] }, { "label": "Region", "fieldType": "choice", "required": true, "evidence": [ { "sourceId": "S4", "locator": "Deploy your own code, Region field" } ] }, { "label": "Branch", "fieldType": "text", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Branch" } ] }, { "label": "Root Directory", "fieldType": "text", "required": false, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Root Directory" } ] }, { "label": "Language", "fieldType": "choice", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Language" } ] }, { "label": "Build Command", "fieldType": "command", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Build Command" } ] }, { "label": "Start Command", "fieldType": "command", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Start Command" } ] }, { "label": "Instance Type", "fieldType": "choice", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Instance Type" } ] }, { "label": "Environment variables required by the app", "fieldType": "key-value", "required": false, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Environment Variables" } ] } ] }, { "step_number": 11, "phase": "execute", "actor": "developer", "interface": "web-ui", "action": "Click Deploy Web Service.", "details": [], "input": "completed_service_form", "output": "deploy_started", "success_signal": "Build and deploy logs are visible.", "failure_or_wait": "", "required": true, "source_ids": [ "S2" ], "required_fields": [] }, { "step_number": 12, "phase": "wait", "actor": "platform", "interface": "web-ui", "action": "Render builds and deploys the Web Service.", "details": [], "input": "deploy_started", "output": "deploy_finished", "success_signal": "The deploy process finishes.", "failure_or_wait": "Render builds and deploys the Web Service.", "required": true, "source_ids": [ "S2" ], "required_fields": [] }, { "step_number": 13, "phase": "wait", "actor": "platform", "interface": "web-ui", "action": "The service reaches Live status.", "details": [], "input": "deploy_finished", "output": "live_service, onrender_url", "success_signal": "The Dashboard shows Live status.", "failure_or_wait": "", "required": true, "source_ids": [ "S2" ], "required_fields": [] }, { "step_number": 14, "phase": "verify", "actor": "developer", "interface": "browser", "action": "Open the assigned onrender.com URL.", "details": [], "input": "onrender_url", "output": "root_response", "success_signal": "The browser receives the deployed app's root content.", "failure_or_wait": "", "required": true, "source_ids": [ "S2" ], "required_fields": [] }, { "step_number": 15, "phase": "verify", "actor": "developer", "interface": "browser", "action": "Confirm the deployed app's root content.", "details": [], "input": "root_response", "output": "first_success_confirmed", "success_signal": "The expected root content is visible.", "failure_or_wait": "", "required": true, "source_ids": [ "S2" ], "required_fields": [] }, { "step_number": 16, "phase": "verify", "actor": "platform", "interface": "browser", "action": "The first Web Service deploy is Live and serves its root content.", "details": [], "input": "first_success_confirmed, live_service", "output": "", "success_signal": "Live status and expected root content are both observed.", "failure_or_wait": "", "required": true, "source_ids": [ "S2", "S4" ], "required_fields": [] } ], "branches": [ { "at_step": 7, "condition": "The app consists entirely of static content.", "path": "Create a Dashboard Static Site and supply its static-site build and publish settings.", "effect_on_first_success": "Reaches the same live-root-content boundary through a different service type and field inventory.", "source_ids": [ "S2" ] }, { "at_step": 1, "condition": "The developer chooses the Render CLI deployment method.", "path": "Install and authorize the Render CLI, then create and monitor a Web Service from the command line.", "effect_on_first_success": "Adds CLI installation and authorization before reaching the same live-root-content boundary.", "source_ids": [ "S2" ] } ], "friction_gates": [ { "at_step": 1, "type": "account", "description": "The Dashboard deployment route requires a Render account.", "documented_requirement": true, "required": true, "source_ids": [ "S2" ] }, { "at_step": 1, "type": "terms", "description": "Creating an account requires agreement to Render's terms of service and privacy policy.", "documented_requirement": true, "required": true, "source_ids": [ "S7" ] }, { "at_step": 1, "type": "verification", "description": "The signup surface is protected by hCaptcha and may require a challenge.", "documented_requirement": true, "required": false, "source_ids": [ "S7" ] }, { "at_step": 5, "type": "permission", "description": "GitHub authorization must grant Render access to the repository used for deployment.", "documented_requirement": true, "required": true, "source_ids": [ "S5" ] }, { "at_step": 7, "type": "choice", "description": "The selected route chooses Web Service for a server-side web application.", "documented_requirement": true, "required": true, "source_ids": [ "S2" ] } ], "time_to_first_success": { "vendor_claim": true, "value": "Run your web app in minutes (vendor claim; not independently measured)", "source_ids": [ "S2" ] }, "sources": [ { "id": "S1", "title": "Render documentation home", "url": "https://render.com/docs", "official_domain": true, "source_type": "documentation", "accessed_at": "2026-07-22", "last_updated_if_shown": null, "sections_used": [ "Ship your first app" ], "evidence_supported": [ "Entry to first-deploy docs" ] }, { "id": "S2", "title": "Your First Render Deploy", "url": "https://render.com/docs/your-first-deploy", "official_domain": true, "source_type": "tutorial", "accessed_at": "2026-07-22", "last_updated_if_shown": null, "sections_used": [ "Sign up", "Connect your Git provider", "Choose a service type", "Deploy your code", "Dashboard Web Service fields", "Free instance" ], "evidence_supported": [ "Free resources, no payment required", "Git credential connection", "Web Service form fields", "Deploy then open Live URL" ] }, { "id": "S3", "title": "Service types", "url": "https://render.com/docs/service-types", "official_domain": true, "source_type": "documentation", "accessed_at": "2026-07-22", "last_updated_if_shown": null, "sections_used": [ "Web Services", "Static Sites" ], "evidence_supported": [ "Web Service versus Static Site" ] }, { "id": "S4", "title": "Web Services", "url": "https://render.com/docs/web-services", "official_domain": true, "source_type": "documentation", "accessed_at": "2026-07-22", "last_updated_if_shown": null, "sections_used": [ "Deploy", "Port binding" ], "evidence_supported": [ "Web Service deploy behavior", "0.0.0.0 binding expectation" ] }, { "id": "S5", "title": "GitHub on Render", "url": "https://render.com/docs/github", "official_domain": true, "source_type": "documentation", "accessed_at": "2026-07-22", "last_updated_if_shown": null, "sections_used": [ "Connect GitHub" ], "evidence_supported": [ "GitHub authorization for deploys" ] }, { "id": "S6", "title": "Login settings", "url": "https://render.com/docs/login-settings", "official_domain": true, "source_type": "documentation", "accessed_at": "2026-07-22", "last_updated_if_shown": null, "sections_used": [ "Git Deployment Credentials" ], "evidence_supported": [ "Account Settings credential management" ] }, { "id": "S7", "title": "Render register", "url": "https://dashboard.render.com/register", "official_domain": true, "source_type": "account-setup", "accessed_at": "2026-07-22", "last_updated_if_shown": null, "sections_used": [ "Signup" ], "evidence_supported": [ "Free account signup entry" ] } ], "uncertainties": [ { "question": "Exact interactive signup fields on dashboard.render.com/register.", "impact": "Could add undocumented form fields before the first Dashboard session.", "reason_unresolved": "The tutorial says signup is fast and free without publishing the interactive field contract.", "checked_source_ids": [ "S2", "S7" ] } ], "excluded_after_success": [ "CLI installation", "Paid instance types", "Custom domains and TLS beyond the default onrender.com URL", "Background Workers, Cron Jobs, and other service types" ], "candidate_paths": [], "candidate_path_gap": null, "journey_graph": { "schemaVersion": "1.0", "platformSlug": "render", "startingState": { "boundary": "account_creation", "assumptions": [ "The developer has a GitHub account.", "A GitHub repository contains a deployable web app.", "The app binds its public HTTP server to 0.0.0.0 on the port Render provides." ], "availableInputs": [ "render_signup_url" ] }, "comparisonBasis": { "developerJobKey": "deploy-existing-server-side-web-app-from-git", "startingBoundaryKey": "account-creation-with-git-account-and-deployable-repository", "firstSuccessOutcomeClass": "meaningful_result", "firstSuccessBoundaryKey": "public-live-url-serves-application-root-content", "routeGranularityVersion": "journey-graph-1.0-atomic-events", "categoryKey": "cloud-application-runtime", "evidenceFreshnessDate": "2026-07-25", "organizationKey": "render", "documentationSetKey": "render-first-deploy-web-service-github" }, "prerequisites": [ { "id": "github-account", "type": "account", "requirement": "A GitHub account that can authorize access to the application repository.", "required": true, "produces": [ "github_account" ], "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, prerequisites" } ] }, { "id": "application-repository", "type": "access", "requirement": "A GitHub repository containing the web app to deploy.", "required": true, "produces": [ "app_repository" ], "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, prerequisites" } ] }, { "id": "deployable-web-app", "type": "software", "requirement": "A server-side web app that listens for HTTP requests on Render's provided port and host.", "required": true, "produces": [ "deployable_web_app" ], "evidence": [ { "sourceId": "S4", "locator": "Web Services, port binding" } ] } ], "nodes": [ { "id": "create-render-account", "kind": "developer_action", "phase": "account", "actor": "developer", "interface": "browser", "action": "Create a Render account with email and password.", "required": true, "requiredFields": [ { "label": "Email", "fieldType": "email", "required": true, "evidence": [ { "sourceId": "S7", "locator": "Create an account form, Email" } ] }, { "label": "Password", "fieldType": "password", "required": true, "evidence": [ { "sourceId": "S7", "locator": "Create an account form, Password" } ] } ], "inputs": [ "render_signup_url" ], "outputs": [ "render_account", "dashboard_session" ], "successSignal": "The Render Dashboard opens.", "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, Sign up" }, { "sourceId": "S7", "locator": "Create an account form" } ], "requiresFieldInventory": true }, { "id": "open-git-credentials", "kind": "developer_action", "phase": "authenticate", "actor": "developer", "interface": "web-ui", "action": "Open Git Deployment Credentials in Account Settings.", "required": true, "requiredFields": [], "inputs": [ "dashboard_session" ], "outputs": [ "git_credentials_view" ], "successSignal": "Git Deployment Credentials is visible.", "evidence": [ { "sourceId": "S2", "locator": "2. Connect your Git provider" } ], "requiresFieldInventory": false }, { "id": "add-git-credential", "kind": "developer_action", "phase": "authenticate", "actor": "developer", "interface": "web-ui", "action": "Click Add credential.", "required": true, "requiredFields": [], "inputs": [ "git_credentials_view" ], "outputs": [ "git_provider_choices" ], "successSignal": "Git provider choices are visible.", "evidence": [ { "sourceId": "S2", "locator": "2. Connect your Git provider" } ], "requiresFieldInventory": false }, { "id": "choose-github", "kind": "decision", "phase": "authenticate", "actor": "developer", "interface": "web-ui", "action": "Choose GitHub as the Git provider.", "required": true, "requiredFields": [], "inputs": [ "git_provider_choices", "github_account" ], "outputs": [ "github_authorization_request" ], "successSignal": "GitHub authorization opens.", "evidence": [ { "sourceId": "S5", "locator": "Setup, step 2" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false, "decisionOptions": [ { "label": "GitHub", "selected": true, "effect": "Continues to the selected GitHub authorization route.", "evidence": [ { "sourceId": "S5", "locator": "Setup, step 2" } ] }, { "label": "GitLab or Bitbucket", "selected": false, "effect": "Uses a different Git provider authorization path before repository selection.", "evidence": [ { "sourceId": "S2", "locator": "Connect your Git provider" } ] } ] }, { "id": "authorize-render-github", "kind": "developer_action", "phase": "authenticate", "actor": "developer", "interface": "browser", "action": "Authorize Render to access the required GitHub repositories.", "required": true, "requiredFields": [], "inputs": [ "github_authorization_request", "app_repository" ], "outputs": [ "linked_github_credential", "available_repository_list" ], "successSignal": "The Render Dashboard lists the authorized repositories.", "evidence": [ { "sourceId": "S5", "locator": "Setup, steps 2 and 3" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false }, { "id": "open-new-service-menu", "kind": "developer_action", "phase": "configure", "actor": "developer", "interface": "web-ui", "action": "Open the New menu.", "required": true, "requiredFields": [], "inputs": [ "dashboard_session", "linked_github_credential" ], "outputs": [ "service_type_choices" ], "successSignal": "The service type menu is visible.", "evidence": [ { "sourceId": "S2", "locator": "Deploy your code, step 1" } ], "requiresFieldInventory": false }, { "id": "choose-web-service", "kind": "decision", "phase": "configure", "actor": "developer", "interface": "web-ui", "action": "Choose Web Service.", "required": true, "requiredFields": [], "inputs": [ "service_type_choices" ], "outputs": [ "web_service_repository_picker" ], "successSignal": "The repository picker opens for a Web Service.", "evidence": [ { "sourceId": "S2", "locator": "Deploy your code, step 1" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false, "decisionOptions": [ { "label": "Web Service", "selected": true, "effect": "Continues to the selected server-side web app deployment route.", "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, Choose a service type" } ] }, { "label": "Static Site", "selected": false, "effect": "Uses the static-site branch with different build and publish settings.", "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, Static Site alternative" } ] }, { "label": "Other service types", "selected": false, "effect": "Uses a different service setup route and field inventory.", "evidence": [ { "sourceId": "S2", "locator": "Deploy your code, step 1" } ] } ] }, { "id": "select-repository", "kind": "developer_action", "phase": "configure", "actor": "developer", "interface": "web-ui", "action": "Select the application repository.", "required": true, "requiredFields": [], "inputs": [ "web_service_repository_picker", "available_repository_list", "app_repository" ], "outputs": [ "selected_repository" ], "successSignal": "The intended repository is selected.", "evidence": [ { "sourceId": "S5", "locator": "Setup, successful link paragraph" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false }, { "id": "connect-repository", "kind": "developer_action", "phase": "configure", "actor": "developer", "interface": "web-ui", "action": "Click Connect for the selected repository.", "required": true, "requiredFields": [], "inputs": [ "selected_repository" ], "outputs": [ "web_service_form" ], "successSignal": "The Web Service form opens.", "evidence": [ { "sourceId": "S5", "locator": "Setup, successful link paragraph" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false }, { "id": "complete-service-form", "kind": "developer_action", "phase": "configure", "actor": "developer", "interface": "web-ui", "action": "Complete the Web Service form.", "required": true, "requiredFields": [ { "label": "Name", "fieldType": "text", "required": true, "evidence": [ { "sourceId": "S4", "locator": "Deploy your own code, Name field" } ] }, { "label": "Region", "fieldType": "choice", "required": true, "evidence": [ { "sourceId": "S4", "locator": "Deploy your own code, Region field" } ] }, { "label": "Branch", "fieldType": "text", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Branch" } ] }, { "label": "Root Directory", "fieldType": "text", "required": false, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Root Directory" } ] }, { "label": "Language", "fieldType": "choice", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Language" } ] }, { "label": "Build Command", "fieldType": "command", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Build Command" } ] }, { "label": "Start Command", "fieldType": "command", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Start Command" } ] }, { "label": "Instance Type", "fieldType": "choice", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Instance Type" } ] }, { "label": "Environment variables required by the app", "fieldType": "key-value", "required": false, "evidence": [ { "sourceId": "S2", "locator": "Web service fields, Environment Variables" } ] } ], "inputs": [ "web_service_form", "selected_repository", "deployable_web_app" ], "outputs": [ "completed_service_form" ], "successSignal": "The Deploy Web Service action is available.", "evidence": [ { "sourceId": "S2", "locator": "2. Configure deployment, Web service fields" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": true }, { "id": "start-deploy", "kind": "developer_action", "phase": "execute", "actor": "developer", "interface": "web-ui", "action": "Click Deploy Web Service.", "required": true, "requiredFields": [], "inputs": [ "completed_service_form" ], "outputs": [ "deploy_started" ], "successSignal": "Build and deploy logs are visible.", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false }, { "id": "wait-for-deploy", "kind": "passive_wait", "phase": "wait", "actor": "platform", "interface": "web-ui", "action": "Render builds and deploys the Web Service.", "required": true, "requiredFields": [], "inputs": [ "deploy_started" ], "outputs": [ "deploy_finished" ], "successSignal": "The deploy process finishes.", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false }, { "id": "service-live", "kind": "platform_outcome", "phase": "wait", "actor": "platform", "interface": "web-ui", "action": "The service reaches Live status.", "required": true, "requiredFields": [], "inputs": [ "deploy_finished" ], "outputs": [ "live_service", "onrender_url" ], "successSignal": "The Dashboard shows Live status.", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false }, { "id": "open-service-url", "kind": "developer_action", "phase": "verify", "actor": "developer", "interface": "browser", "action": "Open the assigned onrender.com URL.", "required": true, "requiredFields": [], "inputs": [ "onrender_url" ], "outputs": [ "root_response" ], "successSignal": "The browser receives the deployed app's root content.", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false }, { "id": "confirm-root-content", "kind": "developer_action", "phase": "verify", "actor": "developer", "interface": "browser", "action": "Confirm the deployed app's root content.", "required": true, "requiredFields": [], "inputs": [ "root_response" ], "outputs": [ "first_success_confirmed" ], "successSignal": "The expected root content is visible.", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false }, { "id": "first-success", "kind": "terminal_outcome", "phase": "verify", "actor": "platform", "interface": "browser", "action": "The first Web Service deploy is Live and serves its root content.", "required": true, "requiredFields": [], "inputs": [ "first_success_confirmed", "live_service" ], "outputs": [], "successSignal": "Live status and expected root content are both observed.", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" }, { "sourceId": "S4", "locator": "Deploy a web service" } ], "branchId": "github-dashboard-route", "requiresFieldInventory": false } ], "edges": [ { "from": "create-render-account", "to": "open-git-credentials", "evidence": [ { "sourceId": "S2", "locator": "Sign up to Connect your Git provider" } ] }, { "from": "open-git-credentials", "to": "add-git-credential", "evidence": [ { "sourceId": "S2", "locator": "2. Connect your Git provider" } ] }, { "from": "add-git-credential", "to": "choose-github", "condition": "GitHub route selected", "evidence": [ { "sourceId": "S5", "locator": "Setup" } ] }, { "from": "choose-github", "to": "authorize-render-github", "evidence": [ { "sourceId": "S5", "locator": "Setup, step 2" } ] }, { "from": "authorize-render-github", "to": "open-new-service-menu", "evidence": [ { "sourceId": "S5", "locator": "Setup, successful link paragraph" } ] }, { "from": "open-new-service-menu", "to": "choose-web-service", "condition": "Server-side web app route selected", "evidence": [ { "sourceId": "S2", "locator": "Deploy your code" } ] }, { "from": "choose-web-service", "to": "select-repository", "evidence": [ { "sourceId": "S2", "locator": "Deploy your code" } ] }, { "from": "select-repository", "to": "connect-repository", "evidence": [ { "sourceId": "S5", "locator": "Setup, successful link paragraph" } ] }, { "from": "connect-repository", "to": "complete-service-form", "evidence": [ { "sourceId": "S2", "locator": "2. Configure deployment" } ] }, { "from": "complete-service-form", "to": "start-deploy", "evidence": [ { "sourceId": "S2", "locator": "2. Configure deployment to 3. Deploy" } ] }, { "from": "start-deploy", "to": "wait-for-deploy", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" } ] }, { "from": "wait-for-deploy", "to": "service-live", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" } ] }, { "from": "service-live", "to": "open-service-url", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" } ] }, { "from": "open-service-url", "to": "confirm-root-content", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" } ] }, { "from": "confirm-root-content", "to": "first-success", "evidence": [ { "sourceId": "S2", "locator": "3. Deploy" } ] } ], "externalGates": [ { "id": "render-account-required", "type": "account", "description": "The Dashboard deployment route requires a Render account.", "atNodeId": "create-render-account", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, Sign up" } ] }, { "id": "render-terms", "type": "terms", "description": "Creating an account requires agreement to Render's terms of service and privacy policy.", "atNodeId": "create-render-account", "required": true, "evidence": [ { "sourceId": "S7", "locator": "Create an account form, terms agreement" } ] }, { "id": "signup-challenge", "type": "verification", "description": "The signup surface is protected by hCaptcha and may require a challenge.", "atNodeId": "create-render-account", "required": false, "evidence": [ { "sourceId": "S7", "locator": "Create an account form, hCaptcha protection" } ] }, { "id": "github-authorization", "type": "permission", "description": "GitHub authorization must grant Render access to the repository used for deployment.", "atNodeId": "authorize-render-github", "required": true, "evidence": [ { "sourceId": "S5", "locator": "Connect GitHub, Setup steps 2 and 3" } ] }, { "id": "service-type-choice", "type": "choice", "description": "The selected route chooses Web Service for a server-side web application.", "atNodeId": "choose-web-service", "required": true, "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, Choose a service type" } ] } ], "candidateRoutes": [ { "id": "github-dashboard-web-service", "status": "selected", "nodeIds": [ "create-render-account", "open-git-credentials", "add-git-credential", "choose-github", "authorize-render-github", "open-new-service-menu", "choose-web-service", "select-repository", "connect-repository", "complete-service-form", "start-deploy", "wait-for-deploy", "service-live", "open-service-url", "confirm-root-content", "first-success" ], "selectionBasis": "The official first-deploy tutorial documents the Dashboard route, and the Web Service branch reaches live root content for a server-side web app.", "condition": "The app runs server-side code, the repository is on GitHub, and the developer chooses the Dashboard deployment method.", "routeSummary": "Create a Dashboard Web Service from the authorized GitHub repository, deploy it, and confirm its root content.", "effectOnFirstSuccess": "Reaches a Live Web Service that serves the expected root content.", "reasonNotSelected": null, "branchAtNodeId": null, "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, Dashboard route" }, { "sourceId": "S4", "locator": "Web Services, Deploy your own code" } ] }, { "id": "github-dashboard-static-site", "status": "considered", "nodeIds": [], "selectionBasis": "The same official tutorial documents a Dashboard Static Site branch.", "condition": "The app consists entirely of static content.", "routeSummary": "Create a Dashboard Static Site and supply its static-site build and publish settings.", "effectOnFirstSuccess": "Reaches the same live-root-content boundary through a different service type and field inventory.", "reasonNotSelected": "The selected journey job is deploying a server-side web app, so the Static Site branch is not causally compatible.", "branchAtNodeId": "choose-web-service", "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, Static Site alternative" } ] }, { "id": "render-cli-web-service", "status": "considered", "nodeIds": [], "selectionBasis": "The same official tutorial documents a CLI Web Service deployment method.", "condition": "The developer chooses the Render CLI deployment method.", "routeSummary": "Install and authorize the Render CLI, then create and monitor a Web Service from the command line.", "effectOnFirstSuccess": "Adds CLI installation and authorization before reaching the same live-root-content boundary.", "reasonNotSelected": "The Dashboard route is presented first and avoids adding CLI installation to the selected first-deploy path.", "branchAtNodeId": "create-render-account", "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, CLI alternative" } ] } ], "uncertainties": [], "firstSuccessBoundary": { "nodeId": "first-success", "outcomeClass": "meaningful_result", "officialRouteContinues": false, "evidence": [ { "sourceId": "S2", "locator": "Your First Render Deploy, Open your app" }, { "sourceId": "S4", "locator": "Web Services, public URL" } ] }, "selectedRoute": { "id": "github-dashboard-web-service", "nodeIds": [ "create-render-account", "open-git-credentials", "add-git-credential", "choose-github", "authorize-render-github", "open-new-service-menu", "choose-web-service", "select-repository", "connect-repository", "complete-service-form", "start-deploy", "wait-for-deploy", "service-live", "open-service-url", "confirm-root-content", "first-success" ], "policy": "Select the official Dashboard Web Service route using GitHub, from account creation through Live root content.", "unresolvedReason": null } } } ``` # Deployed source ## web/index.html The active product document served before generated artifacts. ```html __PAGE_TITLE__

Search a platform. See the first mile.

Find the steps, fields, gates, and official sources from account creation to first success.

``` ## web/app.js Search, durable routing, explicit research consent, sharing, and route rendering. ```javascript const el = { searchView: document.querySelector("#search-view"), form: document.querySelector("#search-form"), input: document.querySelector("#search"), searchStatus: document.querySelector("#search-status"), searchResults: document.querySelector("#search-results"), searchError: document.querySelector("#search-error"), searchRetry: document.querySelector("#search-retry"), result: document.querySelector("#result"), status: document.querySelector("#global-status"), }; let providers = []; let providerCount = 0; let activePoll = 0; let researchPending = false; const POLL_INTERVAL_MS = 2500; const MAX_POLLS = 160; const DISCOVERY_SLUGS = [ "stripe", "openai", "github", "google-gemini-api", "mistral-ai", "xai-api", "anthropic", "auth0", "twilio", "slack", "sentry", "render", ]; function esc(value) { return String(value ?? "") .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } function safeHttpUrl(value) { try { const url = new URL(String(value)); return ["http:", "https:"].includes(url.protocol) ? url.href : ""; } catch { return ""; } } function announce(message) { el.status.textContent = ""; window.setTimeout(() => { el.status.textContent = message; }, 20); } async function api(path, options = {}) { const response = await fetch(path, options); const body = await response.json().catch(() => ({ error: { message: "The server returned an unreadable response." } })); if (!response.ok || body.error) { const error = new Error(body.error?.message || `Request failed (${response.status}).`); error.code = body.error?.code; error.status = response.status; throw error; } return body; } function setMeta(title, description, url = location.href) { document.title = title; document.querySelector('meta[name="description"]')?.setAttribute("content", description); document.querySelector('meta[property="og:title"]')?.setAttribute("content", title); document.querySelector('meta[property="og:description"]')?.setAttribute("content", description); document.querySelector('link[rel="canonical"]')?.setAttribute("href", url); document.querySelector('meta[property="og:url"]')?.setAttribute("content", url); } function setRootMetadata() { setMeta( "Developer Journey Atlas", "Search a developer platform and see the documented first-mile path from account creation to first success.", `${location.origin}/`, ); } function setNotFoundMetadata(slug) { setMeta( "Route not reviewed | Developer Journey Atlas", "Research this platform to reconstruct the source-grounded first-mile path.", `${location.origin}/platform/${encodeURIComponent(slug)}`, ); } function normalizeProvider(provider, published = false) { return { name: String(provider.name ?? ""), slug: String(provider.slug ?? ""), aliases: Array.isArray(provider.searchAliases) ? provider.searchAliases.map(String) : [], category: String(provider.category ?? ""), outcome: String(provider.outcome ?? ""), routeStatus: String(provider.routeStatus ?? (published ? "published" : "known_needs_review")), reviewReasons: Array.isArray(provider.reviewReasons) ? provider.reviewReasons.map(String) : [], published: published || provider.routeStatus === "published", }; } function mergeProviders(catalog, corpus) { const merged = new Map(); for (const provider of catalog) { if (provider.name && provider.slug) merged.set(provider.slug, normalizeProvider(provider)); } for (const provider of corpus) { if (!provider.name || !provider.slug) continue; const current = merged.get(provider.slug); merged.set(provider.slug, { ...(current ?? normalizeProvider(provider)), name: provider.name, category: provider.category ?? current?.category ?? "", outcome: provider.outcome ?? current?.outcome ?? "", routeStatus: provider.routeStatus ?? current?.routeStatus ?? "known_needs_review", reviewReasons: provider.reviewReasons ?? current?.reviewReasons ?? [], published: provider.routeStatus === "published", }); } return [...merged.values()].sort((a, b) => a.name.localeCompare(b.name)); } async function loadProviders() { el.searchError.hidden = true; el.searchStatus.textContent = "Loading platforms..."; try { const publishedResponse = await fetch("/api/platforms?include=all"); if (!publishedResponse.ok) throw new Error("Platform search failed."); const published = await publishedResponse.json(); const catalogProviders = []; providers = mergeProviders(catalogProviders, Array.isArray(published?.data) ? published.data : []); providerCount = Number(published?.meta?.count ?? providers.length); if (!providers.length) throw new Error("Platform search is empty."); renderMatches(); } catch { providers = []; providerCount = 0; el.searchResults.hidden = true; el.searchError.hidden = false; el.searchStatus.textContent = ""; } } function discoveryProviders() { const bySlug = new Map(providers.map((provider) => [provider.slug, provider])); const selected = DISCOVERY_SLUGS.map((slug) => bySlug.get(slug)).filter(Boolean); if (selected.length >= 8) return selected; const selectedSlugs = new Set(selected.map((provider) => provider.slug)); return [ ...selected, ...providers.filter((provider) => !selectedSlugs.has(provider.slug)).slice(0, 12 - selected.length), ]; } function matchesFor(query) { const normalized = query.trim().toLowerCase(); if (!normalized) return discoveryProviders(); return providers.filter((provider) => `${provider.name} ${provider.slug} ${provider.aliases.join(" ")}`.toLowerCase().includes(normalized) ).slice(0, 10); } function providerResult(provider) { return `
  • `; } function renderMatches() { if (!providers.length) return; const query = el.input.value.trim(); const matches = matchesFor(query); el.searchResults.innerHTML = matches.map(providerResult).join(""); el.searchResults.hidden = matches.length === 0; if (!query) { el.searchStatus.textContent = `${providerCount || providers.length} platforms loaded. Pick one or type to search.`; } else if (matches.length) { el.searchStatus.textContent = `${matches.length} match${matches.length === 1 ? "" : "es"}`; } else { el.searchStatus.textContent = `No saved platform for "${query}". You can research it.`; } } function showSearch() { activePoll += 1; researchPending = false; document.body.classList.remove("detail-page"); el.searchView.hidden = false; el.result.hidden = true; el.result.innerHTML = ""; setRootMetadata(); } function showResultSurface() { document.body.classList.add("detail-page"); el.searchView.hidden = true; el.result.hidden = false; } function pushPlatformRoute(slug) { const target = `/platform/${encodeURIComponent(slug)}`; if (location.pathname !== target) history.pushState({ slug }, "", target); } function backLink() { return '← Search'; } function compactSteps(steps) { if (!Array.isArray(steps) || !steps.length) return '

    No steps are available yet.

    '; return `
      ${steps.map((step) => `
    1. ${esc(step.action)}

      ${step.successSignal ? `${esc(step.successSignal)}` : ""} ${Array.isArray(step.requiredFields) && step.requiredFields.length ? ` ` : ""} ${Array.isArray(step.frictionGates) && step.frictionGates.length ? ` ` : ""}
    2. `).join("")}
    `; } function renderComplexity(complexity) { if (!complexity?.dimensions) return ""; const d = complexity.dimensions; const items = [ ["Actions", d.requiredActions], ["Fields", d.requiredFields], ["Choices", d.decisionPoints], ["Gates", d.documentedExternalGates], ["Waits", d.unavoidableWaits], ]; return `

    Complexity

    ${esc(complexity.rating)} (${esc(complexity.score)})

    ${esc(complexity.note)}

    ${items.map(([label, value]) => `
    ${esc(label)}
    ${esc(value)}
    `).join("")}
    `; } function sourceLinks(sources) { if (!Array.isArray(sources) || !sources.length) return "

    No sources are available.

    "; const links = sources.map((source) => { const url = safeHttpUrl(source.url); return url ? `
  • ${esc(source.title)}
  • ` : `
  • ${esc(source.title)}
  • `; }).join(""); return ``; } /** Banner shown above a saved route that has not passed maintainer review. */ function draftNotice() { return `

    This route was built from official documentation by an automated research run. A maintainer has not reviewed it, and it is not part of the published corpus.

    `; } function renderJourney(journey, review = {}) { const isDraft = review.reviewStatus === "unreviewed_draft"; const startUrl = safeHttpUrl(journey.startingUrl); const firstSuccess = journey.routeScope?.firstSuccess || journey.outcome || "First successful API response"; const selectedPath = journey.routeScope?.selectedPath || "Follow the documented setup route below."; const prerequisites = Array.isArray(journey.prerequisites) && journey.prerequisites.length ? `` : "

    None documented.

    "; return `
    ${backLink()}

    ${isDraft ? "Research draft" : "Reviewed guide"}

    ${esc(journey.name)}

    ${esc(firstSuccess)}

    ${isDraft ? draftNotice() : ""} ${startUrl ? `Open official guide` : ""} ${renderComplexity(journey.complexity)}

    Path

    ${esc(selectedPath)}

    ${compactSteps(journey.steps)}
    Before you start ${prerequisites}
    Official sources

    Open to load sources.

    Domain comparison

    Open to load compatible peers.

    `; } async function loadOfficialEvidence(slug) { const mount = document.querySelector("#official-evidence-content"); if (!mount) return; mount.innerHTML = "

    Loading sources…

    "; try { const { data } = await api(`/api/platforms/${encodeURIComponent(slug)}/evidence?include=all`); mount.innerHTML = sourceLinks(data.sources); } catch { mount.innerHTML = "

    Sources could not be loaded.

    "; } } function wireJourney(journey) { const disclosure = document.querySelector("#official-evidence"); disclosure?.addEventListener("toggle", () => { if (disclosure.open && disclosure.dataset.loaded !== "true") { disclosure.dataset.loaded = "true"; loadOfficialEvidence(journey.slug); } }); const comparison = document.querySelector("#peer-comparison"); comparison?.addEventListener("toggle", () => { if (comparison.open && comparison.dataset.loaded !== "true") { comparison.dataset.loaded = "true"; loadPeerComparison(journey.slug); } }); } function renderPeerComparison(comparison) { if (!comparison?.available) { return `

    ${esc(comparison?.note ?? "Comparison is not available yet.")}

    ${esc(comparison?.qualifiedPeerCount ?? 0)} of ${esc(comparison?.requiredPeerCount ?? 3)} compatible peers are ready.

    `; } return `

    ${esc(comparison.note)}

    `; } async function loadPeerComparison(slug) { const mount = document.querySelector("#peer-comparison-content"); if (!mount) return; mount.innerHTML = "

    Loading comparison...

    "; try { const { data } = await api(`/api/platforms/${encodeURIComponent(slug)}/peer-comparison`); mount.innerHTML = renderPeerComparison(data); } catch { mount.innerHTML = "

    Comparison could not be loaded.

    "; } } async function showPlatform(slug, { push = true, focus = true } = {}) { activePoll += 1; researchPending = false; showResultSurface(); if (push) pushPlatformRoute(slug); el.result.innerHTML = '
    Loading guide…
    '; try { // include=all so a durable research draft resolves too; the response tells // us whether it is published or still awaiting review. const { data, meta } = await api(`/api/platforms/${encodeURIComponent(slug)}/journey?include=all`); el.result.innerHTML = renderJourney(data, meta ?? {}); wireJourney(data); setMeta( `${data.name} API setup | Developer Journey Atlas`, `See ${data.name}'s documented first-mile path.`, location.href, ); announce(`${data.name} guide loaded.`); if (focus) document.querySelector("#result-title")?.focus(); } catch { const provider = providers.find((candidate) => candidate.slug === slug); if (provider) { renderResearchOffer(provider.name, slug, provider); return; } try { const { data } = await api(`/api/platforms/${encodeURIComponent(slug)}?include=all`); renderResearchOffer(data.name ?? slug, slug, data); } catch { renderResearchOffer(slug, slug); } } } function renderResearchOffer(name, slug = "", provider = null) { activePoll += 1; researchPending = false; showResultSurface(); const known = provider?.routeStatus && provider.routeStatus !== "unknown"; el.result.innerHTML = `
    ${backLink()}

    ${known ? "Not mapped yet" : "New platform"}

    ${esc(name)}

    ${known ? "We know this platform belongs in the atlas. The step-by-step first-mile path still needs to be built from official docs." : "Build a first-mile path from official docs."}

    ${provider?.outcome ? `

    First goal: ${esc(provider.outcome)}

    ` : ""}

    The draft will show the steps, fields, gates, and sources here.

    `; document.querySelector("#research-btn")?.addEventListener("click", () => researchPlatform(name)); setNotFoundMetadata(slug || name); document.querySelector("#result-title")?.focus(); announce(`${name} is ready for research.`); } function setResearchStatus(message) { const status = document.querySelector("#research-status"); if (status) status.textContent = message; announce(message); } function renderResearchFailure(query, heading, message, retry = true) { researchPending = false; showResultSurface(); el.result.innerHTML = `
    ${backLink()}

    Research

    ${esc(heading)}

    ${esc(message)}

    ${retry ? '' : ""}
    `; document.querySelector("#research-btn")?.addEventListener("click", () => researchPlatform(query)); document.querySelector("#result-title")?.focus(); announce(`${heading}. ${message}`); } function renderResearchDraft(result) { const draft = result.draft; const startUrl = safeHttpUrl(draft.startingUrl); showResultSurface(); el.result.innerHTML = `
    ${backLink()}

    Research draft

    ${esc(draft.name)}

    ${esc(draft.firstSuccess)}

    ${draft.successSignal ? `

    Done when: ${esc(draft.successSignal)}

    ` : ""} ${startUrl ? `Open official guide` : ""} ${renderComplexity(draft.complexity)}

    Path

    ${compactSteps(draft.steps)}
    ${Array.isArray(draft.prerequisites) && draft.prerequisites.length ? `
    Before you start
    ` : ""}
    Official sources ${sourceLinks(draft.sources)}

    Saved privately for maintainer review.

    `; setMeta( `${draft.name} research draft | Developer Journey Atlas`, `A source-grounded draft path for ${draft.name}.`, location.href, ); document.querySelector("#result-title")?.focus(); announce(`${draft.name} research draft ready.`); } const OUTCOME_MESSAGE = { identity_ambiguous: ["Use a more specific name", "That name matches more than one platform.", false], identity_unresolved: ["Platform not confirmed", "We could not confirm the official platform.", false], no_official_source: ["No official guide found", "We could not find usable first-party setup documentation.", false], official_source_unusable: ["Official docs were not enough", "The pages did not contain enough detail to build the path.", false], invalid_output: ["Draft failed validation", "The draft missed required journey fields or contradicted the record schema.", true], claim_grounding_failed: ["Evidence check failed", "At least one action, field, option, gate, or edge was not supported by an accepted official source.", true], search_failed: ["Docs search is unavailable", "Try the research again.", true], model_failed: ["Route builder is unavailable", "Try the research again.", true], }; async function researchPlatform(query) { if (researchPending) return; researchPending = true; const button = document.querySelector("#research-btn"); if (button) button.disabled = true; setResearchStatus("Starting research…"); try { const body = await api("/api/research", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ platform: query }), }); if (body.data?.known) { await showPlatform(body.data.slug); return; } if (body.data?.result?.outcome === "draft_ready" && body.data.result.draft) { researchPending = false; renderResearchDraft(body.data.result); return; } if (!body.data?.runId) throw new Error("Research could not be started."); setResearchStatus("Researching official docs. This usually takes about a minute."); pollRunStatus(body.data.runId, query); } catch (error) { renderResearchFailure(query, "Research unavailable", error.message, true); } } async function pollRunStatus(runId, query) { const token = ++activePoll; for (let attempt = 0; attempt < MAX_POLLS; attempt += 1) { await new Promise((resolve) => window.setTimeout(resolve, POLL_INTERVAL_MS)); if (token !== activePoll) return; try { const { data } = await api(`/api/research/${encodeURIComponent(runId)}`); if (data.phase === "completed" && data.result) { researchPending = false; if (data.result.outcome === "known") { await showPlatform(data.result.slug); return; } if (data.result.outcome === "draft_ready" && data.result.draft) { renderResearchDraft(data.result); return; } const [heading, message, retry] = OUTCOME_MESSAGE[data.result.outcome] ?? ["Research could not finish", "The available evidence was not enough.", false]; renderResearchFailure(query, heading, message, retry); return; } if (data.phase === "failed") { renderResearchFailure(query, "Research failed", data.message || "Try again.", true); return; } setResearchStatus(data.phase === "retrying" ? "A research step is retrying…" : "Researching official docs. This usually takes about a minute."); } catch (error) { renderResearchFailure(query, "Research status unavailable", error.message, true); return; } } researchPending = false; renderResearchFailure(query, "Research is still running", "Return later and try again.", true); } async function submitQuery(rawQuery) { const query = rawQuery.trim(); if (!query) { el.searchStatus.textContent = "Enter a platform name."; el.input.focus(); return; } const matches = matchesFor(query); const exact = matches.find((provider) => provider.name.toLowerCase() === query.toLowerCase() || provider.slug.toLowerCase() === query.toLowerCase() || provider.aliases.some((alias) => alias.toLowerCase() === query.toLowerCase()) ); if (exact || matches.length === 1) { await showPlatform((exact ?? matches[0]).slug); return; } if (matches.length > 1) { el.searchResults.hidden = false; el.searchStatus.textContent = "Choose a platform below."; el.searchResults.querySelector("button")?.focus(); return; } const slug = query.toLowerCase().trim() .replace(/[^a-z0-9]+/g, "-") .replace(/^-+|-+$/g, ""); if (slug) pushPlatformRoute(slug); renderResearchOffer(query, slug); } function routeFromLocation() { const match = location.pathname.match(/^\/platform\/([^/]+)\/?$/); if (match) { showPlatform(decodeURIComponent(match[1]), { push: false, focus: false }); return; } showSearch(); } el.input.addEventListener("input", renderMatches); el.input.addEventListener("keydown", (event) => { if (event.key === "Escape") { el.input.value = ""; renderMatches(); } }); el.searchResults.addEventListener("click", (event) => { const button = event.target.closest("[data-provider]"); if (button) showPlatform(button.dataset.provider); }); el.searchRetry.addEventListener("click", loadProviders); el.form.addEventListener("submit", (event) => { event.preventDefault(); submitQuery(el.input.value); }); window.addEventListener("popstate", routeFromLocation); loadProviders().finally(routeFromLocation); ``` ## web/styles.css The active responsive and accessible visual system. ```css :root { color-scheme: light; --ink: #172033; --muted: #5b6475; --line: #dfe3ea; --surface: #ffffff; --wash: #f6f7fa; --accent: #5b4df5; --accent-hover: #4638dc; --accent-soft: #efedff; --focus: #1167d8; --radius: 16px; font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-synthesis: none; } * { box-sizing: border-box; } html { min-height: 100%; background: var(--wash); } body { min-height: 100vh; margin: 0; color: var(--ink); background: radial-gradient(circle at 50% 4%, rgba(91, 77, 245, 0.09), transparent 31rem), var(--wash); } a { color: inherit; } button, input { font: inherit; } button, a { -webkit-tap-highlight-color: transparent; } :focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; } [hidden] { display: none !important; } .skip-link { position: fixed; z-index: 10; top: 8px; left: 8px; padding: 10px 14px; border-radius: 8px; background: var(--ink); color: white; transform: translateY(-150%); } .skip-link:focus { transform: translateY(0); } .site-header { display: flex; align-items: center; justify-content: space-between; width: min(100% - 32px, 980px); margin: 0 auto; padding: 22px 0; } .site-header > a:last-child { color: var(--muted); font-size: 0.9rem; } .brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); font-size: 0.94rem; font-weight: 750; text-decoration: none; } .brand-mark { display: grid; width: 34px; height: 34px; place-items: center; border-radius: 10px; background: var(--ink); color: white; font-size: 0.72rem; letter-spacing: 0.04em; } main { width: min(100% - 32px, 760px); min-height: calc(100vh - 166px); margin: 0 auto; } .search-view { padding: clamp(64px, 12vh, 130px) 0 80px; } .search-intro { max-width: 670px; margin-bottom: 34px; } h1, h2, p { margin-top: 0; } h1 { max-width: 720px; margin-bottom: 14px; font-size: clamp(2.25rem, 7vw, 4.6rem); line-height: 0.99; letter-spacing: -0.055em; } h2 { margin-bottom: 12px; font-size: 1.18rem; letter-spacing: -0.02em; } .search-intro p, .result-lede { max-width: 660px; margin-bottom: 0; color: var(--muted); font-size: clamp(1.05rem, 2vw, 1.24rem); line-height: 1.55; } .search-form { position: relative; } .search-form label { display: block; margin-bottom: 9px; font-size: 0.9rem; font-weight: 720; } .search-row { display: grid; grid-template-columns: 1fr auto; gap: 10px; } input[type="search"] { width: 100%; min-height: 58px; padding: 0 18px; border: 1px solid #c9cfda; border-radius: 13px; background: var(--surface); color: var(--ink); font-size: 1.05rem; box-shadow: 0 10px 35px rgba(23, 32, 51, 0.06); } input[type="search"]::placeholder { color: #8a91a0; } .btn { display: inline-flex; min-height: 48px; align-items: center; justify-content: center; padding: 0 18px; border: 1px solid transparent; border-radius: 11px; font-weight: 750; text-decoration: none; cursor: pointer; } .search-row .btn { min-height: 58px; } .btn:disabled { cursor: wait; opacity: 0.6; } .btn-primary { background: var(--accent); color: white; } .btn-primary:hover { background: var(--accent-hover); } .btn-secondary { border-color: #c7ccd6; background: var(--surface); color: var(--ink); } .status-line { min-height: 24px; margin: 10px 2px 0; color: var(--muted); font-size: 0.88rem; } .search-results { margin: 8px 0 0; padding: 8px; border: 1px solid var(--line); border-radius: 13px; background: var(--surface); box-shadow: 0 18px 50px rgba(23, 32, 51, 0.1); list-style: none; } .search-results button { display: flex; width: 100%; align-items: center; padding: 13px 12px; border: 0; border-radius: 9px; background: transparent; color: var(--ink); text-align: left; cursor: pointer; } .search-results button:hover, .search-results button:focus-visible { background: var(--accent-soft); } .search-results span { font-weight: 700; } .result-panel { padding: 54px 0 88px; } .journey, .research-card, .compact-state { padding: clamp(24px, 5vw, 48px); border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); box-shadow: 0 18px 60px rgba(23, 32, 51, 0.08); } .journey h1, .research-card h1 { margin-bottom: 12px; font-size: clamp(2.25rem, 7vw, 4.25rem); } .back-link { display: inline-block; margin-bottom: 42px; color: var(--muted); font-size: 0.92rem; font-weight: 650; text-decoration: none; } .back-link:hover { color: var(--ink); } .state-label { margin-bottom: 10px; color: var(--accent); font-size: 0.76rem; font-weight: 800; letter-spacing: 0.09em; text-transform: uppercase; } .start-link { margin-top: 24px; } .journey section { margin-top: 46px; } .journey details { padding: 18px 0; border-top: 1px solid var(--line); } .journey details:first-of-type { margin-top: 34px; } summary { font-weight: 750; cursor: pointer; } details > :last-child { margin-bottom: 0; } .steps { margin: 20px 0 0; padding: 0; list-style: none; counter-reset: path; } .steps li { position: relative; min-height: 42px; margin: 0 0 18px; padding: 0 0 18px 48px; border-bottom: 1px solid var(--line); counter-increment: path; } .steps li:last-child { margin-bottom: 0; border-bottom: 0; } .steps li::before { content: counter(path); position: absolute; top: -3px; left: 0; display: grid; width: 32px; height: 32px; place-items: center; border-radius: 10px; background: var(--accent-soft); color: var(--accent-hover); font-weight: 800; } .steps p { margin-bottom: 5px; font-weight: 680; line-height: 1.45; } .steps small, .trust-note, .success-signal { color: var(--muted); line-height: 1.5; } .trust-note { max-width: 560px; margin: 20px 0; font-size: 0.9rem; } .success-signal { margin: 15px 0 0; } .draft-notice { max-width: 560px; margin: 20px 0; padding: 14px 16px; border: 1px solid var(--line); border-left: 3px solid var(--accent); border-radius: 8px; background: var(--wash); } .draft-notice p { margin: 0; font-size: 0.9rem; line-height: 1.5; } .source-list { padding-left: 20px; } .field-list, .gate-list, .review-list { margin: 10px 0 0; padding-left: 20px; color: var(--muted); font-size: 0.9rem; line-height: 1.45; } .gate-list li::marker { color: #c66b1f; } .review-list { max-width: 620px; margin-top: 18px; } .source-list li { margin: 10px 0; } .source-list a { color: var(--accent-hover); } .site-footer { display: flex; width: min(100% - 32px, 980px); align-items: center; gap: 18px; margin: 0 auto; padding: 26px 0 34px; color: var(--muted); font-size: 0.82rem; } .site-footer a { color: inherit; } .complexity-panel { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 24px; align-items: start; margin-top: 32px; padding: 20px; border: 1px solid var(--line); border-radius: 12px; background: #fbfcff; } .complexity-panel h2 { margin-bottom: 8px; text-transform: capitalize; } .complexity-panel p { margin-bottom: 0; color: var(--muted); line-height: 1.5; } .complexity-panel dl { display: grid; grid-template-columns: repeat(5, minmax(56px, auto)); gap: 10px; margin: 0; } .complexity-panel dl div { min-width: 56px; padding: 10px; border: 1px solid var(--line); border-radius: 10px; background: white; text-align: center; } .complexity-panel dt { color: var(--muted); font-size: 0.72rem; } .complexity-panel dd { margin: 2px 0 0; font-size: 1.1rem; font-weight: 800; } .comparison-list { margin: 16px 0 0; padding: 0; list-style: none; } .comparison-list li { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; padding: 12px 0; border-top: 1px solid var(--line); } .comparison-list small { grid-column: 1 / -1; color: var(--muted); } .visually-hidden { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; } @media (max-width: 580px) { .site-header { padding-top: 16px; } .site-header > a:last-child { display: none; } .search-view { padding-top: 48px; } .search-row { grid-template-columns: 1fr; } .search-row .btn { min-height: 52px; } .search-results button { align-items: flex-start; flex-direction: column; gap: 3px; } .result-panel { padding-top: 30px; } .journey, .research-card, .compact-state { padding: 24px 20px; border-radius: 14px; } .back-link { margin-bottom: 34px; } .complexity-panel { grid-template-columns: 1fr; } .complexity-panel dl { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; } } ``` ## src/server.ts The deployed Express composition root and platform-page metadata route. ```typescript import express from "express"; import path from "node:path"; import { readFile } from "node:fs/promises"; import { config, researchAvailability } from "./config.js"; import { createDataStore } from "./adapters/createStore.js"; import { createApiRouter } from "./api/router.js"; import { sendError } from "./api/http.js"; import { RenderWorkflowRunner } from "./adapters/renderWorkflows.js"; import type { WorkflowRunner } from "./workflows/contract.js"; import type { DataStore } from "./core/ports.js"; import type { PostgresDataStore } from "./adapters/postgresData.js"; // Build the Workflow runner from config. Returns null when the Render API key or // task slug is absent, so the research endpoints degrade cleanly. The web // service never runs research itself: it starts and reads durable Workflow runs. function buildWorkflowRunner(): WorkflowRunner | null { const { available, missing } = researchAvailability(); if (!available) { console.warn(`Live research disabled: missing ${missing.join(", ")}.`); return null; } return new RenderWorkflowRunner(config.workflowTaskSlug, config.renderApiKey); } function isPostgresStore(store: DataStore): store is PostgresDataStore { return typeof (store as PostgresDataStore).ping === "function"; } function escapeHtml(value: string): string { return value .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } function pageOrigin(req: express.Request): string { return config.publicBaseUrl || `${req.protocol}://${req.get("host")}`; } function renderPage( template: string, values: { title: string; description: string; canonicalUrl: string; socialImageUrl: string; coverage: string; }, ): string { return template .replaceAll("__PAGE_TITLE__", escapeHtml(values.title)) .replaceAll("__PAGE_DESCRIPTION__", escapeHtml(values.description)) .replaceAll("__CANONICAL_URL__", escapeHtml(values.canonicalUrl)) .replaceAll("__SOCIAL_IMAGE_URL__", escapeHtml(values.socialImageUrl)) .replaceAll("__PUBLIC_COVERAGE__", escapeHtml(values.coverage)); } // Composition root: choose Local vs Postgres DataStore, wire API, mount static assets. async function main(): Promise { let store: DataStore; let mode: string; try { ({ store, mode } = await createDataStore()); } catch { console.error("Server diagnostic: stage=dataset-load outcome=store_error"); process.exit(1); return; } const runner = buildWorkflowRunner(); const app = express(); app.disable("x-powered-by"); app.set("trust proxy", 1); app.use(express.json({ limit: "256kb" })); app.get("/healthz", async (_req, res) => { const payload: Record = { status: "ok", platforms: store.meta().count, dataStore: mode, blockerReasons: store.blockerReasonCount?.() ?? null, }; if (isPostgresStore(store)) { try { await store.ping(); payload.database = "up"; } catch { payload.database = "down"; res.status(503); } } res.json(payload); }); app.use("/api", createApiRouter(store, runner)); app.use("/api", (_req, res) => sendError(res, 404, "not_found", "Unknown API route.")); const webDir = path.join(config.dataRoot, "web"); const pageTemplate = await readFile(path.join(webDir, "index.html"), "utf8"); const publicRecords = store.meta().publicRecords ?? store.listRows().filter((row) => store.isPublicEligible(row.slug)).length; const reviewedRecords = store.meta().reviewedCorpusRecords ?? store.meta().totals.platforms; const coverage = `${publicRecords} of ${reviewedRecords} corpus records currently publish a reviewed route`; app.get("/", (req, res) => { const origin = pageOrigin(req); res.set("Cache-Control", "no-cache, no-store, must-revalidate"); res.type("html").send(renderPage(pageTemplate, { title: "Developer Journey Atlas", description: "Search 237 developer platforms and inspect reviewed first-mile routes from account creation to first success.", canonicalUrl: `${origin}/`, socialImageUrl: `${origin}/social-preview.svg`, coverage, })); }); app.get("/platform/:slug", async (req, res) => { const slug = String(req.params.slug); const row = store.isPublicEligible(slug) ? store.getRow(slug) : undefined; const known = store.getRow(slug); const origin = pageOrigin(req); res.set("Cache-Control", "no-cache, no-store, must-revalidate"); if (!row && known) { res.type("html").send(renderPage(pageTemplate, { title: `${known.name} path builder | Developer Journey Atlas`, description: `${known.name} is in the Atlas corpus. Build its step-by-step path from official docs.`, canonicalUrl: `${origin}/platform/${encodeURIComponent(slug)}`, socialImageUrl: `${origin}/social-preview.svg`, coverage, })); return; } if (!row) { res.status(404).type("html").send(renderPage(pageTemplate, { title: "Route not found | Developer Journey Atlas", description: "This platform does not have a published source-grounded route.", canonicalUrl: `${origin}/platform/${encodeURIComponent(slug)}`, socialImageUrl: `${origin}/social-preview.svg`, coverage, })); return; } res.type("html").send(renderPage(pageTemplate, { title: `${row.name} documented route | Developer Journey Atlas`, description: `Inspect ${row.name}'s source-grounded route from account creation to first developer success.`, canonicalUrl: `${origin}/platform/${encodeURIComponent(row.slug)}`, socialImageUrl: `${origin}/social-preview.svg`, coverage, })); }); app.use(express.static(webDir, { setHeaders(res, filePath) { if (/\.(?:js|css|html)$/.test(filePath)) { res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); } }, })); app.use(express.static(config.publicDir, { index: false })); app.use((_err: unknown, _req: express.Request, res: express.Response, _next: express.NextFunction) => { console.error("Server diagnostic: stage=request outcome=internal_error"); sendError(res, 500, "internal_error", "Something went wrong."); }); app.listen(config.port, "0.0.0.0", () => { console.log( `Developer Journey Atlas listening on 0.0.0.0:${config.port} (${store.meta().count} platforms, store=${mode})`, ); }); } main().catch(() => { console.error("Server diagnostic: stage=startup outcome=internal_error"); process.exit(1); }); ``` ## src/api/router.ts The complete public API route index. ```typescript import { Router } from "express"; import type { DataStore } from "../core/ports.js"; import type { WorkflowRunner } from "../workflows/contract.js"; import { sendData } from "./http.js"; import { getPlatform, listPlatforms } from "./platforms.js"; import { getBlockerMeta, getPlatformEvidence, getPlatformJourney } from "./journey.js"; import { getPlatformCurve } from "./curve.js"; import { getPeerComparison } from "./peerComparison.js"; import { searchPlatforms } from "./search.js"; import { getResearchStatus, startResearch } from "./research.js"; import { getVerifyStatus, startVerify } from "./verify.js"; // Note: the cross-platform comparison endpoint (src/api/compare.ts + // src/core/comparison.ts) is intentionally NOT mounted. It computes a // score-based distribution that reads as a ranking, which the public surface // no longer shows. Those files are kept in the repo, marked experimental and // internal, in case a properly verified benchmark returns later. /** Single router index. One place to see every route the API exposes. */ export function createApiRouter(store: DataStore, runner: WorkflowRunner | null): Router { const router = Router(); router.get("/meta", (_req, res) => { const meta = store.meta(); sendData(res, { reviewedCorpusRecords: meta.reviewedCorpusRecords ?? meta.totals.platforms, researchDrafts: meta.researchDrafts ?? 0, publicRecords: meta.publicRecords ?? store.listRows().filter((row) => store.isPublicEligible(row.slug)).length, generatedAt: meta.generatedAt, audits: meta.audits, comparisonAvailable: true, comparisonRules: "Peer comparison is withheld unless the subject and at least three compatible domain peers pass graph integrity, public eligibility, freshness, and cohort-key checks.", }); }); router.get("/blockers/meta", getBlockerMeta(store)); router.get("/platforms", listPlatforms(store)); router.get("/platforms/:slug/peer-comparison", getPeerComparison(store)); router.get("/platforms/:slug/journey", getPlatformJourney(store)); router.get("/platforms/:slug/evidence", getPlatformEvidence(store)); router.get("/platforms/:slug/curve", getPlatformCurve(store)); router.get("/platforms/:slug", getPlatform(store)); router.get("/search", searchPlatforms(store)); // Async research: start a durable Workflow run, then poll its status by id. router.post("/research", startResearch(store, runner)); router.get("/research/:runId", getResearchStatus(store, runner)); router.post("/verify", startVerify(store, runner)); router.get("/verify/:runId", getVerifyStatus(runner)); return router; } ``` ## src/api/platforms.ts Fail-closed platform list and route presenter. ```typescript import type { Request, Response } from "express"; import type { DataStore, MetricRow, RouteStatus } from "../core/ports.js"; import { sendData, sendError } from "./http.js"; import { ensurePublicRow, ensureRow } from "./storeHelpers.js"; /** * Compact summary used by list and search results. Intentionally free of any * score, count, or comparability field: the public surface never ranks or * orders platforms against each other. */ export function routeStatus(row: MetricRow, store?: DataStore): RouteStatus { if (!store) return "unknown"; if (store.isPublicEligible(row.slug)) return "published"; return "known_needs_review"; } export function toSummary(row: MetricRow, store?: DataStore) { return { name: row.name, slug: row.slug, category: row.category, outcome: row.outcome, routeStatus: routeStatus(row, store), reviewReasons: [], }; } export function listPlatforms(store: DataStore) { return (req: Request, res: Response): void => { const includeAll = String(req.query.include ?? "").toLowerCase() === "all"; const rows = includeAll ? store.listRows() : store.listRows().filter((row) => store.isPublicEligible(row.slug)); const categories = [...new Set(rows.map((r) => r.category))].sort(); sendData(res, rows.map((row) => toSummary(row, store)), { count: rows.length, categories }); }; } export function getPlatform(store: DataStore) { return async (req: Request, res: Response): Promise => { const slug = String(req.params.slug); const includeAll = String(req.query.include ?? "").toLowerCase() === "all"; const row = includeAll ? await ensureRow(store, slug) : await ensurePublicRow(store, slug); if (!row) { sendError(res, 404, "not_found", `No platform found for "${slug}".`); return; } if (includeAll && !store.isPublicEligible(slug)) { sendData(res, { ...toSummary(row, store), routeStatus: routeStatus(row, store), reviewReasons: [], documentedRouteUrl: null, }); return; } const journey = store.getJourney?.(slug); if (!journey) { sendError(res, 404, "not_found", `No publication-eligible route found for "${slug}".`); return; } sendData(res, { name: journey.name, slug: journey.slug, organization: journey.organization, category: journey.category, outcome: row.outcome, startingUrl: journey.startingUrl, note: journey.note, documentedRouteUrl: `/api/platforms/${encodeURIComponent(slug)}/journey`, }); }; } ``` ## src/api/journey.ts Selected journey graph presenter with public blocker links suppressed. ```typescript import type { Request, Response } from "express"; import type { DataStore } from "../core/ports.js"; import { sendData, sendError } from "./http.js"; import { ensurePublicRow, ensureRow } from "./storeHelpers.js"; const PUBLISHED_EVIDENCE = "Published routes pass deterministic identity, source-content, claim-grounding, and selected-route integrity gates."; const DRAFT_EVIDENCE = "This route is an unreviewed research draft built from official sources. It has not passed maintainer review and is excluded from the public corpus."; /** * Review metadata for a route response. Drafts are labelled so a caller can * never mistake an unreviewed reconstruction for a published route. The * deterministic gate codes stay internal: only the coarse status is public. */ function reviewMeta(store: DataStore, slug: string): Record { return store.isPublicEligible(slug) ? { reviewStatus: "published", evidence: PUBLISHED_EVIDENCE } : { reviewStatus: "unreviewed_draft", evidence: DRAFT_EVIDENCE }; } /** * Resolve a row for a route response. The default stays fail-closed. Passing * include=all opts into an unreviewed research draft, but only when the record * carries a reconstructed graph: a corpus record awaiting review has no route * to show and still resolves to nothing. */ async function resolveRouteRow(store: DataStore, req: Request, slug: string) { const includeAll = String(req.query.include ?? "").toLowerCase() === "all"; if (!includeAll) return ensurePublicRow(store, slug); const row = await ensureRow(store, slug); if (!row || !store.getJourneyGraph?.(slug)) return undefined; return row; } /** GET /api/platforms/:slug/journey: selected source-grounded route. */ export function getPlatformJourney(store: DataStore) { return async (req: Request, res: Response): Promise => { const slug = String(req.params.slug); const row = await resolveRouteRow(store, req, slug); if (!row) { sendError(res, 404, "not_found", `No platform found for "${slug}".`); return; } if (!store.getJourney) { sendError(res, 501, "not_supported", "Journey overlay is not available on this data store."); return; } const journey = store.getJourney(slug); if (!journey) { sendError(res, 404, "not_found", `No journey record found for "${slug}".`); return; } sendData(res, journey, reviewMeta(store, slug)); }; } /** GET /api/platforms/:slug/evidence: progressive official-source disclosure. */ export function getPlatformEvidence(store: DataStore) { return async (req: Request, res: Response): Promise => { const slug = String(req.params.slug); const row = await resolveRouteRow(store, req, slug); if (!row) { sendError(res, 404, "not_found", `No platform found for "${slug}".`); return; } const evidence = store.getJourneyEvidence?.(slug); if (!evidence || evidence.sources.length === 0) { sendError(res, 404, "not_found", `No public evidence disclosure found for "${slug}".`); return; } sendData(res, evidence, reviewMeta(store, slug)); }; } /** GET /api/blockers/meta: public evaluation status only. */ export function getBlockerMeta(store: DataStore) { return (_req: Request, res: Response): void => { sendData(res, { publicLinksAvailable: false, note: "Blocker-reason links remain internal until the labeled evaluation and owner-approved thresholds pass.", }); }; } ``` ## src/api/peerComparison.ts Compatible-domain peer comparison presenter with strict qualification gates. ```typescript import type { Request, Response } from "express"; import type { DataStore } from "../core/ports.js"; import { buildPeerComparison } from "../core/peerComparison.js"; import { sendData, sendError } from "./http.js"; import { ensurePublicRow } from "./storeHelpers.js"; /** GET /api/platforms/:slug/peer-comparison: compatible-domain route comparison. */ export function getPeerComparison(store: DataStore) { return async (req: Request, res: Response): Promise => { const slug = String(req.params.slug); const row = await ensurePublicRow(store, slug); if (!row) { sendError(res, 404, "not_found", `No publication-eligible platform found for "${slug}".`); return; } sendData(res, buildPeerComparison(store, slug)); }; } ``` ## src/api/research.ts Explicit research start and private review projection. ```typescript import type { Request, Response } from "express"; import { researchAvailability } from "../config.js"; import { sendData, sendError } from "./http.js"; import type { DataStore } from "../core/ports.js"; import type { WorkflowRunner } from "../workflows/contract.js"; import { buildResearchInput, InvalidResearchInput } from "../workflows/input.js"; import { buildNhjAuditFromRecord } from "../db/nhjAuditFromDraft.js"; import { persistResearchDraft } from "../db/persistResearchDraft.js"; import { attachResearchRunId, beginResearchClaim, cleanupResearchClaims, completeResearchClaim, completeResearchClaimByRunId, countRecentResearchStarts, failResearchClaim, failResearchClaimByRunId, } from "../db/researchClaims.js"; import { selectedPathRow } from "../../lib/measure.mjs"; import { ensureRow, isPostgresStore } from "./storeHelpers.js"; import type { PlatformRecord } from "../core/ports.js"; import { buildComplexityProfileFromRecord } from "../core/complexityProfile.js"; const RESEARCH_WINDOW_MS = 60 * 60 * 1_000; const RESEARCH_GLOBAL_LIMIT = Math.max( 1, Number(process.env.RESEARCH_GLOBAL_HOURLY_LIMIT ?? 300), ); // Local-only fallback when DATA_STORE=local (no ResearchClaim table usage). const DEDUPE_TTL_MS = 10 * 60 * 1_000; const recentRunsLocal = new Map(); function browserSafeDraft(record: PlatformRecord) { return { name: record.platform.name, slug: record.platform.slug, startingUrl: record.entry_point?.starting_url ?? null, firstSuccess: record.documented_first_success?.normalized_outcome ?? record.documented_first_success?.official_milestone ?? "First documented API success", successSignal: record.documented_first_success?.observable_completion_signal ?? null, prerequisites: (record.prerequisites ?? []).slice(0, 12).map((item) => ({ requirement: item.requirement, required: item.required, })), steps: (record.primary_path ?? []).slice(0, 30).map((step) => ({ stepNumber: step.step_number, action: step.action, successSignal: step.success_signal ?? null, requiredFields: (step.required_fields ?? []).map((field) => ({ label: field.label, type: field.fieldType, required: field.required, })), })), frictionGates: (record.friction_gates ?? []).slice(0, 20).map((gate) => ({ atStep: gate.at_step ?? null, type: gate.type ?? "other", description: gate.description ?? gate.requirement ?? "", })), complexity: buildComplexityProfileFromRecord(record), sources: (record.sources ?? []).slice(0, 12).map((source) => ({ title: source.title, url: source.url, accessedAt: source.accessed_at ?? null, })), }; } function browserSafeResearchResult(result: unknown): unknown { if (!result || typeof result !== "object" || !("outcome" in result)) return null; const value = result as { outcome: string; slug?: string; candidates?: unknown[]; message?: string }; switch (value.outcome) { case "known": return { outcome: "known", slug: value.slug }; case "identity_ambiguous": return { outcome: "identity_ambiguous", candidates: value.candidates ?? [] }; case "identity_unresolved": case "no_official_source": return { outcome: value.outcome }; case "official_source_unusable": return { outcome: value.outcome, message: "The official source pages did not contain usable retrieved content.", }; case "invalid_output": return { outcome: value.outcome, message: "The documentation could not be turned into a complete, internally consistent setup guide.", }; case "claim_grounding_failed": return { outcome: value.outcome, message: "At least one required action was not supported by the accepted official documentation.", }; case "search_failed": return { outcome: value.outcome, message: "Official-source discovery was unavailable. Try again later.", }; case "model_failed": return { outcome: value.outcome, message: "Route reconstruction was unavailable. Try again later.", }; case "review_required": return { outcome: value.outcome, slug: value.slug, message: "Research finished and remains private until maintainer review passes every publication gate.", }; default: return null; } } function workflowStartFailureFields(err: unknown): string { if (!err || typeof err !== "object") return "error=unknown"; const value = err as { name?: unknown; statusCode?: unknown }; const name = typeof value.name === "string" ? value.name : "unknown"; const statusCode = typeof value.statusCode === "number" ? value.statusCode : "unknown"; return `error=${name} statusCode=${statusCode}`; } function recentRunLocal(slug: string, now = Date.now()): string | null { const hit = recentRunsLocal.get(slug); if (hit && now - hit.at < DEDUPE_TTL_MS) return hit.runId; if (hit) recentRunsLocal.delete(slug); return null; } async function persistCompletedResearch(store: DataStore, result: { outcome: "completed"; slug: string; record: import("../core/ports.js").PlatformRecord; assessment: unknown; }, runId: string): Promise { if (!isPostgresStore(store)) return; const prisma = store.getPrisma(); const row = selectedPathRow(result.record); const audit = buildNhjAuditFromRecord(result.record); await persistResearchDraft(result.record, row, { prisma, audit }); store.ingestLive(result.record, row, audit); await completeResearchClaim(result.slug, prisma); await completeResearchClaimByRunId(runId, prisma); console.log(`Persisted research draft for ${result.slug} into Postgres.`); } /** * Start or refresh research for a platform. Validates and rate-limits, * short-circuits only public reviewed platforms, then starts a durable Workflow * run and returns 202 with a run id immediately. Concurrent developers who * request the same slug share one Workflow via ResearchClaim in Postgres. */ export function startResearch(store: DataStore, runner: WorkflowRunner | null) { return async (req: Request, res: Response): Promise => { if (!runner) { const status = researchAvailability(); sendError(res, 503, "research_unconfigured", `Live research is not configured on this deployment. Set ${status.missing.join(", ")}.`); return; } let input; try { input = buildResearchInput(req.body?.platform); } catch (err) { const message = err instanceof InvalidResearchInput ? err.message : "Provide a platform name."; sendError(res, 400, "bad_request", message); return; } // Reuse only public reviewed records before touching Workflow. A committed // corpus row is not proof that the atomic journey has been reconstructed. const known = await ensureRow(store, input.slug); if (known && store.isPublicEligible(input.slug)) { sendData(res, { known: true, slug: input.slug }, { status: 200 }); return; } if (isPostgresStore(store)) { const prisma = store.getPrisma(); try { await cleanupResearchClaims(prisma); const globalStarts = await countRecentResearchStarts(prisma, RESEARCH_WINDOW_MS); if (globalStarts >= RESEARCH_GLOBAL_LIMIT) { sendError( res, 429, "rate_limited", `The Atlas has reached its shared research capacity for this hour. Try again later.`, ); return; } const claim = await beginResearchClaim( { slug: input.slug, platform: input.platform }, prisma, ); if (claim.kind === "existing") { if (claim.claim.status === "completed") { const loaded = await ensureRow(store, input.slug); if (loaded && store.isPublicEligible(input.slug)) { sendData(res, { known: true, slug: input.slug }, { status: 200 }); return; } const existingDraft = store.getRecord(input.slug); if (existingDraft) { sendData(res, { result: { outcome: "draft_ready", slug: input.slug, draft: browserSafeDraft(existingDraft), message: "Using the saved private research draft.", }, }, { status: 200 }); return; } } if (claim.claim.runId) { res.status(202); sendData(res, { runId: claim.claim.runId, phase: "running", slug: input.slug, deduplicated: true, resumed: true, }); return; } // Another request is mid-start (claiming without runId yet): wait briefly then re-read. await new Promise((resolve) => setTimeout(resolve, 400)); const again = await beginResearchClaim( { slug: input.slug, platform: input.platform }, prisma, ); if (again.kind === "existing" && again.claim.runId) { res.status(202); sendData(res, { runId: again.claim.runId, phase: "running", slug: input.slug, deduplicated: true, resumed: true, }); return; } sendError(res, 409, "claim_in_progress", "Another request is starting this research. Retry in a moment."); return; } try { const { runId } = await runner.start(input); await attachResearchRunId(input.slug, runId, prisma); res.status(202); sendData(res, { runId, phase: "queued", slug: input.slug }); } catch (err) { await failResearchClaim(input.slug, prisma); console.error(`Research diagnostic: stage=workflow-start outcome=provider_error provider=render_workflows ${workflowStartFailureFields(err)}`); sendError(res, 502, "start_failed", "Could not start research right now. Try again shortly."); } return; } catch { console.error("Research diagnostic: stage=claim outcome=store_error provider=postgres"); sendError(res, 502, "start_failed", "Could not start research right now. Try again shortly."); return; } } // Local store: process-local dedupe only. const existingRunId = recentRunLocal(input.slug); if (existingRunId) { res.status(202); sendData(res, { runId: existingRunId, phase: "running", slug: input.slug, deduplicated: true }); return; } try { const { runId } = await runner.start(input); recentRunsLocal.set(input.slug, { runId, at: Date.now() }); res.status(202); sendData(res, { runId, phase: "queued", slug: input.slug }); } catch (err) { console.error(`Research diagnostic: stage=workflow-start outcome=provider_error provider=render_workflows ${workflowStartFailureFields(err)}`); sendError(res, 502, "start_failed", "Could not start research right now. Try again shortly."); } }; } /** * Read the server-side status of a Workflow run and return a browser-safe * projection. When a run completes, the draft is written to Postgres so every * instance can serve it on the next request. */ export function getResearchStatus(store: DataStore, runner: WorkflowRunner | null) { return async (req: Request, res: Response): Promise => { if (!runner) { sendError(res, 503, "research_unconfigured", "Live research is not configured on this deployment."); return; } const runId = typeof req.params.runId === "string" ? req.params.runId.trim() : ""; if (!runId || !/^[A-Za-z0-9._-]{1,128}$/.test(runId)) { sendError(res, 400, "bad_request", "Provide a valid run id."); return; } try { const projection = await runner.status(runId); if ( projection.phase === "completed" && projection.result && projection.result.outcome === "completed" && "record" in projection.result && projection.result.record ) { try { await persistCompletedResearch(store, projection.result, runId); } catch { console.error("Research diagnostic: stage=persist outcome=store_error provider=postgres"); sendError(res, 502, "persistence_failed", "Research finished, but the private review record could not be stored."); return; } sendData(res, { ...projection, result: { outcome: "draft_ready", slug: projection.result.slug, draft: browserSafeDraft(projection.result.record), message: "Research finished. This draft stays private until maintainer review.", }, }); return; } const safeResult = browserSafeResearchResult(projection.result); if (projection.phase === "completed" && isPostgresStore(store)) { try { if ( safeResult && typeof safeResult === "object" && "outcome" in safeResult && (safeResult.outcome === "known" || safeResult.outcome === "review_required") ) { await completeResearchClaimByRunId(runId, store.getPrisma()); } else { await failResearchClaimByRunId(runId, store.getPrisma()); } } catch { console.error("Research diagnostic: stage=claim-terminal outcome=store_error provider=postgres"); } } sendData(res, { ...projection, result: safeResult, message: projection.phase === "completed" && projection.result && !safeResult ? "This run is not a public research result." : projection.message, }); } catch { console.error("Research diagnostic: stage=workflow-status outcome=not_found provider=render_workflows"); sendError(res, 404, "run_not_found", "That research run could not be found."); } }; } ``` ## src/core/complexityProfile.ts Auditable documented structural complexity dimensions and rating formula. ```typescript import type { JourneyExternalGate, JourneyNode } from "./journeyGraph.js"; import type { PlatformRecord } from "./ports.js"; export type ComplexityRating = "low" | "medium" | "high" | "very-high"; export interface ComplexityDimensions { requiredActions: number; requiredFields: number; decisionPoints: number; documentedExternalGates: number; unavoidableWaits: number; platformOutcomes: number; totalAtomicNodes: number; } export interface ComplexityProfile { rating: ComplexityRating; score: number; formula: string; dimensions: ComplexityDimensions; evidenceState: "documented-graph" | "draft-primary-path"; note: string; } const FORMULA = "required actions + 0.35*required fields + 1.2*decision points + 1.5*documented external gates + unavoidable waits + 0.4*platform outcomes"; function ratingFor(score: number): ComplexityRating { if (score >= 28) return "very-high"; if (score >= 16) return "high"; if (score >= 8) return "medium"; return "low"; } function profile(dimensions: ComplexityDimensions, evidenceState: ComplexityProfile["evidenceState"]): ComplexityProfile { const score = Number(( dimensions.requiredActions + dimensions.requiredFields * 0.35 + dimensions.decisionPoints * 1.2 + dimensions.documentedExternalGates * 1.5 + dimensions.unavoidableWaits + dimensions.platformOutcomes * 0.4 ).toFixed(2)); return { rating: ratingFor(score), score, formula: FORMULA, dimensions, evidenceState, note: "This is documented structural complexity, not observed user difficulty. It counts required work, fields, branches, gates, waits, and platform status changes in the selected first-mile route.", }; } export function buildComplexityProfileFromGraph( nodes: JourneyNode[], externalGates: JourneyExternalGate[], ): ComplexityProfile { const selectedIds = new Set(nodes.map((node) => node.id)); return profile({ requiredActions: nodes.filter((node) => node.kind === "developer_action" && node.required).length, requiredFields: nodes .flatMap((node) => node.requiredFields) .filter((field) => field.required).length, decisionPoints: nodes.filter((node) => node.kind === "decision" && node.required).length, documentedExternalGates: externalGates.filter((gate) => gate.required && selectedIds.has(gate.atNodeId)).length, unavoidableWaits: nodes.filter((node) => node.kind === "passive_wait" && node.required).length, platformOutcomes: nodes.filter((node) => node.kind === "platform_outcome" && node.required).length, totalAtomicNodes: nodes.length, }, "documented-graph"); } export function buildComplexityProfileFromRecord(record: PlatformRecord): ComplexityProfile { const steps = record.primary_path ?? []; const gates = record.friction_gates ?? []; return profile({ requiredActions: steps.filter((step) => step.required !== false && step.actor !== "platform" && step.actor !== "system" && step.phase !== "wait").length, requiredFields: steps .flatMap((step) => step.required_fields ?? []) .filter((field) => field.required !== false).length, decisionPoints: (record.branches as unknown[] | undefined)?.length ?? 0, documentedExternalGates: gates.length, unavoidableWaits: [ ...steps.filter((step) => step.required !== false && step.phase === "wait"), ...gates.filter((gate) => gate.type === "wait"), ].length, platformOutcomes: steps.filter((step) => step.required !== false && (step.actor === "platform" || step.actor === "system")).length, totalAtomicNodes: steps.length, }, "draft-primary-path"); } ``` ## src/core/peerComparison.ts Reviewed-route compatible peer qualification and comparison dimensions. ```typescript import type { JourneyComparisonBasis, JourneyGraph } from "./journeyGraph.js"; import { validateJourneyGraph } from "./journeyGraph.js"; import type { DataStore, PlatformRecord } from "./ports.js"; export const MIN_QUALIFIED_PEERS = 3; export const COMPARISON_FRESHNESS_DAYS = 90; export const COMPARISON_CRITERIA = [ "The same developer job and account-creation starting boundary", "The same first-success outcome and boundary", "The same route granularity and platform category", "A distinct organization and documentation set", `Reviewed evidence no more than ${COMPARISON_FRESHNESS_DAYS} days old`, ] as const; export type ComparisonDimensionKey = | "requiredActions" | "requiredFields" | "externalGates" | "unavoidableWaits"; export interface RouteMeasurements { requiredActions: number; requiredFields: number; externalGates: number; unavoidableWaits: number; } export interface QualifiedPeer { slug: string; name: string; organization: string; measurements: RouteMeasurements; } export interface ComparisonDimension { key: ComparisonDimensionKey; label: string; subjectValue: number; peerMedian: number; peerMinimum: number; peerMaximum: number; position: "below" | "at" | "above"; } export interface AvailablePeerComparison { slug: string; available: true; qualifiedPeerCount: number; requiredPeerCount: number; criteria: readonly string[]; subject: QualifiedPeer; peers: QualifiedPeer[]; dimensions: ComparisonDimension[]; note: string; } export interface UnavailablePeerComparison { slug: string; available: false; reason: | "subject_not_comparison_qualified" | "insufficient_qualified_peers"; qualifiedPeerCount: number; requiredPeerCount: number; criteria: readonly string[]; note: string; } export type PeerComparison = AvailablePeerComparison | UnavailablePeerComparison; const DIMENSIONS: ReadonlyArray<{ key: ComparisonDimensionKey; label: string }> = [ { key: "requiredActions", label: "Required developer actions" }, { key: "requiredFields", label: "Required fields" }, { key: "externalGates", label: "Documented external gates" }, { key: "unavoidableWaits", label: "Unavoidable waits" }, ]; const COMPATIBILITY_KEYS: ReadonlyArray = [ "developerJobKey", "startingBoundaryKey", "firstSuccessOutcomeClass", "firstSuccessBoundaryKey", "routeGranularityVersion", "categoryKey", ]; function isNonEmpty(value: unknown): value is string { return typeof value === "string" && value.trim().length > 0; } function validFreshnessDate(value: string, now: Date): boolean { if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) return false; const timestamp = Date.parse(`${value}T00:00:00Z`); if (!Number.isFinite(timestamp)) return false; const ageMs = now.getTime() - timestamp; return ageMs >= 0 && ageMs <= COMPARISON_FRESHNESS_DAYS * 24 * 60 * 60 * 1000; } function validBasis( graph: JourneyGraph, record: PlatformRecord, now: Date, ): graph is JourneyGraph & { comparisonBasis: JourneyComparisonBasis } { const basis = graph.comparisonBasis; if (!basis) return false; if ( ![ basis.developerJobKey, basis.startingBoundaryKey, basis.firstSuccessBoundaryKey, basis.routeGranularityVersion, basis.categoryKey, basis.organizationKey, basis.documentationSetKey, ].every(isNonEmpty) ) { return false; } return ( basis.firstSuccessOutcomeClass === graph.firstSuccessBoundary.outcomeClass && basis.organizationKey === record.platform.organization.trim().toLowerCase() && validFreshnessDate(basis.evidenceFreshnessDate, now) ); } function compatible(left: JourneyComparisonBasis, right: JourneyComparisonBasis): boolean { return COMPATIBILITY_KEYS.every((key) => left[key] === right[key]); } function median(values: number[]): number { const sorted = [...values].sort((left, right) => left - right); const middle = Math.floor(sorted.length / 2); return sorted.length % 2 === 0 ? (sorted[middle - 1] + sorted[middle]) / 2 : sorted[middle]; } function peerFrom( graph: JourneyGraph, record: PlatformRecord, ): QualifiedPeer { return { slug: graph.platformSlug, name: record.platform.name, organization: record.platform.organization, measurements: measureSelectedRoute(graph), }; } function qualifiedSubject( store: DataStore, slug: string, now: Date, ): { graph: JourneyGraph & { comparisonBasis: JourneyComparisonBasis }; record: PlatformRecord } | null { if (!store.isPublicEligible(slug)) return null; const graph = store.getJourneyGraph?.(slug); const record = store.getRecord(slug); if (!graph || !record) return null; if (validateJourneyGraph(graph, slug).length > 0) return null; if (!validBasis(graph, record, now)) return null; return { graph, record }; } export function measureSelectedRoute(graph: JourneyGraph): RouteMeasurements { const selectedIds = new Set(graph.selectedRoute.nodeIds); const selectedNodes = graph.nodes.filter((node) => selectedIds.has(node.id)); return { requiredActions: selectedNodes.filter( (node) => node.kind === "developer_action" && node.required, ).length, requiredFields: selectedNodes .flatMap((node) => node.requiredFields) .filter((field) => field.required).length, externalGates: graph.externalGates.filter((gate) => selectedIds.has(gate.atNodeId)).length, unavoidableWaits: selectedNodes.filter( (node) => node.kind === "passive_wait" && node.required, ).length, }; } /** * Builds a public comparison only from public, graph-valid, explicitly * compatible, fresh records. Any missing proof returns an unavailable result. */ export function buildPeerComparison( store: DataStore, slug: string, now = new Date(), ): PeerComparison { const subject = qualifiedSubject(store, slug, now); if (!subject) { return { slug, available: false, reason: "subject_not_comparison_qualified", qualifiedPeerCount: 0, requiredPeerCount: MIN_QUALIFIED_PEERS, criteria: COMPARISON_CRITERIA, note: "Comparison requires a reviewed subject route with explicit, current cohort evidence.", }; } const peers: QualifiedPeer[] = []; const seenOrganizations = new Set([subject.graph.comparisonBasis.organizationKey]); const seenDocumentationSets = new Set([subject.graph.comparisonBasis.documentationSetKey]); const rows = [...store.listRows()].sort((left, right) => left.slug.localeCompare(right.slug)); for (const row of rows) { if (row.slug === slug) continue; const candidate = qualifiedSubject(store, row.slug, now); if (!candidate) continue; const basis = candidate.graph.comparisonBasis; if (!compatible(subject.graph.comparisonBasis, basis)) continue; if ( seenOrganizations.has(basis.organizationKey) || seenDocumentationSets.has(basis.documentationSetKey) ) { continue; } seenOrganizations.add(basis.organizationKey); seenDocumentationSets.add(basis.documentationSetKey); peers.push(peerFrom(candidate.graph, candidate.record)); } if (peers.length < MIN_QUALIFIED_PEERS) { return { slug, available: false, reason: "insufficient_qualified_peers", qualifiedPeerCount: peers.length, requiredPeerCount: MIN_QUALIFIED_PEERS, criteria: COMPARISON_CRITERIA, note: "No comparison is shown until at least three distinct, compatible peer routes pass every qualification rule.", }; } const subjectPeer = peerFrom(subject.graph, subject.record); const dimensions = DIMENSIONS.map(({ key, label }) => { const values = peers.map((peer) => peer.measurements[key]); const peerMedian = median(values); const subjectValue = subjectPeer.measurements[key]; return { key, label, subjectValue, peerMedian, peerMinimum: Math.min(...values), peerMaximum: Math.max(...values), position: subjectValue < peerMedian ? "below" : subjectValue > peerMedian ? "above" : "at", } satisfies ComparisonDimension; }); return { slug, available: true, qualifiedPeerCount: peers.length, requiredPeerCount: MIN_QUALIFIED_PEERS, criteria: COMPARISON_CRITERIA, subject: subjectPeer, peers, dimensions, note: "Values are direct counts from reviewed selected routes. They are not scores, ranks, or causal claims.", }; } ``` ## src/core/publicationGate.ts Identity, source, claim, and route publication gate. ```typescript import type { MetricRow } from "./ports.js"; export interface CorpusHealthRecord { slug: string; eligibility: { reconstruction: boolean; audit: boolean; public_display: boolean; reasons: string[]; }; } export interface CorpusHealthReport { summary: { records: number; eligible_for_public_display: number; }; records: CorpusHealthRecord[]; } export class PublicationGate { private readonly bySlug: Map; constructor(readonly report: CorpusHealthReport) { this.bySlug = new Map(report.records.map((record) => [record.slug, record])); } isEligible(slug: string): boolean { return this.bySlug.get(slug)?.eligibility.public_display === true; } reasons(slug: string): string[] { return this.bySlug.get(slug)?.eligibility.reasons ?? ["missing_corpus_health_record"]; } filterRows(rows: MetricRow[]): MetricRow[] { return rows.filter((row) => this.isEligible(row.slug)); } } ``` ## src/core/sourceAuthority.ts Deterministic first-party source authority checks. ```typescript import { createHash } from "node:crypto"; export interface PlatformIdentity { slug: string; canonicalName: string; organization: string; aliases: string[]; officialRootDomain: string; documentationDomains: string[]; applicationDomains: string[]; approvedGithubOrganizations: string[]; } export interface SourceAuthorityResult { accepted: boolean; authority: "official-domain" | "approved-organization-repository" | "rejected"; reason: string; canonicalUrl: string | null; } export interface FetchMetadata { canonicalUrl: string; redirectChain: string[]; httpStatus: number; contentType: string | null; retrievedAt: string; contentPresent: boolean; contentHash: string | null; contentTruncated: boolean; retrievedContentChars: number; visibleTitle: string | null; discoveredLinks: string[]; } function normalizedHost(value: string): string | null { try { return new URL(value).hostname.toLowerCase().replace(/\.$/, ""); } catch { return null; } } function isDomainOrSubdomain(host: string, acceptedDomain: string): boolean { const accepted = acceptedDomain.toLowerCase().replace(/^\./, "").replace(/\.$/, ""); return host === accepted || host.endsWith(`.${accepted}`); } function githubOwner(url: URL): string | null { if (url.hostname.toLowerCase() !== "github.com") return null; const owner = url.pathname.split("/").filter(Boolean)[0]; return owner ? owner.toLowerCase() : null; } export function normalizeIdentityKey(value: string): string { return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, " ").trim(); } export function resolvePlatformIdentity( requestedName: string, identities: PlatformIdentity[], ): | { outcome: "resolved"; identity: PlatformIdentity } | { outcome: "identity_ambiguous"; candidates: PlatformIdentity[] } | { outcome: "identity_unresolved"; candidates: PlatformIdentity[] } { const key = normalizeIdentityKey(requestedName); const candidates = identities.filter((identity) => { const keys = [ identity.slug, identity.canonicalName, identity.organization, ...identity.aliases, ].map(normalizeIdentityKey); return keys.includes(key); }); if (candidates.length === 1) return { outcome: "resolved", identity: candidates[0] }; return { outcome: candidates.length > 1 ? "identity_ambiguous" : "identity_unresolved", candidates, }; } export function validateSourceAuthority( rawUrl: string, identity: PlatformIdentity, ): SourceAuthorityResult { let url: URL; try { url = new URL(rawUrl); } catch { return { accepted: false, authority: "rejected", reason: "invalid_url", canonicalUrl: null, }; } if (url.protocol !== "https:") { return { accepted: false, authority: "rejected", reason: "https_required", canonicalUrl: url.toString(), }; } const owner = githubOwner(url); if (owner) { const approved = identity.approvedGithubOrganizations.map((item) => item.toLowerCase()); return approved.includes(owner) ? { accepted: true, authority: "approved-organization-repository", reason: "approved_github_organization", canonicalUrl: url.toString(), } : { accepted: false, authority: "rejected", reason: "github_organization_not_approved", canonicalUrl: url.toString(), }; } const host = normalizedHost(url.toString()); const acceptedDomains = [ identity.officialRootDomain, ...identity.documentationDomains, ...identity.applicationDomains, ]; if (host && acceptedDomains.some((domain) => isDomainOrSubdomain(host, domain))) { return { accepted: true, authority: "official-domain", reason: "domain_allowlist_match", canonicalUrl: url.toString(), }; } return { accepted: false, authority: "rejected", reason: "domain_not_allowlisted", canonicalUrl: url.toString(), }; } export function contentHash(content: string): string { return createHash("sha256").update(content, "utf8").digest("hex"); } export function sourceCanSupportClaims( authority: SourceAuthorityResult, metadata: FetchMetadata | null | undefined, ): boolean { return Boolean( authority.accepted && metadata && metadata.httpStatus >= 200 && metadata.httpStatus < 300 && metadata.contentPresent && metadata.contentHash, ); } ``` ## src/core/journeyGraph.ts Typed journey graph and selected-route integrity checks. ```typescript export type JourneyNodeKind = | "developer_action" | "decision" | "passive_wait" | "platform_outcome" | "terminal_outcome"; export interface EvidenceLocator { sourceId: string; locator: string; } export interface JourneyField { label: string; fieldType: string; required: boolean; evidence: EvidenceLocator[]; } export interface JourneyDecisionOption { label: string; selected: boolean; effect: string; evidence: EvidenceLocator[]; } export interface JourneyFailureMode { condition: string; recovery: string; evidence: EvidenceLocator[]; } export interface JourneyNode { id: string; kind: JourneyNodeKind; phase: string; actor: "developer" | "platform" | "system" | "administrator" | "external-system"; interface: string; action: string; required: boolean; requiredFields: JourneyField[]; inputs: string[]; outputs: string[]; successSignal: string; evidence: EvidenceLocator[]; branchId?: string | null; requiresFieldInventory: boolean; decisionOptions?: JourneyDecisionOption[]; failureModes?: JourneyFailureMode[]; } export interface JourneyEdge { from: string; to: string; condition?: string | null; evidence: EvidenceLocator[]; } export interface JourneyPrerequisite { id: string; type: string; requirement: string; required: boolean; produces: string[]; evidence: EvidenceLocator[]; } export interface JourneyExternalGate { id: string; type: string; description: string; atNodeId: string; required: boolean; evidence: EvidenceLocator[]; } export interface JourneyCandidateRoute { id: string; status: "selected" | "considered"; nodeIds: string[]; selectionBasis: string; condition: string; routeSummary: string; effectOnFirstSuccess: string; reasonNotSelected: string | null; branchAtNodeId: string | null; evidence: EvidenceLocator[]; } export interface JourneyUncertainty { targetType: "prerequisite" | "node" | "field" | "edge" | "route" | "terminal"; targetId: string; description: string; blocksPublication: boolean; } /** * Explicit cohort keys used for peer comparison. These values are authored * from reviewed evidence. Comparison code never infers compatibility from * names, categories, legacy scores, or fuzzy text similarity. */ export interface JourneyComparisonBasis { developerJobKey: string; startingBoundaryKey: string; firstSuccessOutcomeClass: "meaningful_result" | "resource_creation"; firstSuccessBoundaryKey: string; routeGranularityVersion: string; categoryKey: string; evidenceFreshnessDate: string; organizationKey: string; documentationSetKey: string; } export interface JourneyGraph { schemaVersion: "1.0"; platformSlug: string; startingState: { boundary: "account_creation"; assumptions: string[]; availableInputs: string[]; }; prerequisites: JourneyPrerequisite[]; nodes: JourneyNode[]; edges: JourneyEdge[]; externalGates: JourneyExternalGate[]; candidateRoutes: JourneyCandidateRoute[]; uncertainties: JourneyUncertainty[]; firstSuccessBoundary: { nodeId: string; outcomeClass: "meaningful_result" | "resource_creation"; officialRouteContinues: boolean; evidence: EvidenceLocator[]; }; selectedRoute: { id: string | null; nodeIds: string[]; policy: string; unresolvedReason: string | null; }; comparisonBasis?: JourneyComparisonBasis; } export interface JourneyGraphFinding { code: | "route_unresolved" | "unknown_node" | "duplicate_node" | "near_duplicate_action" | "compound_action" | "missing_field_inventory" | "missing_decision_options" | "field_inventory_status_missing" | "field_inventory_inconsistent" | "wrong_actor_for_event" | "documentation_navigation_action" | "broken_causal_input" | "missing_evidence" | "missing_evidence_locator" | "missing_route_edge" | "unknown_edge_endpoint" | "duplicate_edge" | "branch_concatenation" | "route_not_declared" | "invalid_candidate_route" | "unknown_gate_target" | "unresolved_uncertainty" | "invalid_terminal" | "invalid_first_success_boundary" | "platform_slug_mismatch" | "invalid_starting_state"; nodeId?: string; message: string; } /** Editorial granularity findings remain publication blockers, not draft blockers. */ export function draftBlockingJourneyFindings( findings: JourneyGraphFinding[], ): JourneyGraphFinding[] { return findings.filter((finding) => finding.code !== "compound_action"); } function normalizedAction(value: string): string { return value .toLowerCase() .replace(/[^a-z0-9 ]+/g, " ") .replace(/\b(the|a|an|your|this|that)\b/g, " ") .replace(/\s+/g, " ") .trim(); } function tokens(value: string): Set { return new Set(normalizedAction(value).split(" ").filter((item) => item.length > 2)); } function jaccard(left: Set, right: Set): number { if (left.size === 0 || right.size === 0) return 0; const intersection = [...left].filter((item) => right.has(item)).length; const union = new Set([...left, ...right]).size; return union === 0 ? 0 : intersection / union; } function hasEvidence(evidence: EvidenceLocator[]): boolean { return ( Array.isArray(evidence) && evidence.length > 0 && evidence.every((item) => Boolean(item.sourceId?.trim() && item.locator?.trim())) ); } function looksCompound(action: string): boolean { const normalized = action.toLowerCase().replace( /\b(?:and(?: then)?|then)\s+(?:verify|confirm|check|observe|ensure)\s+(?:that\s+)?(?:the\s+)?(?:response|output|result|status|text|message|success|completion)\b(?:(?!\b(?:and(?: then)?|then|after that)\b).)*$/, "", ); const connectors = normalized.match(/\b(and then|then|and|after that)\b/g) ?? []; const verbs = normalized.match( /\b(open|click|select|choose|enter|create|copy|paste|authorize|connect|submit|run|send|confirm|verify|purchase|add|configure)\b/g, ) ?? []; return connectors.length > 0 && verbs.length > 1; } export function validateJourneyGraph( graph: JourneyGraph, expectedPlatformSlug?: string, ): JourneyGraphFinding[] { const findings: JourneyGraphFinding[] = []; if (expectedPlatformSlug && graph.platformSlug !== expectedPlatformSlug) { findings.push({ code: "platform_slug_mismatch", message: `Journey graph platform ${graph.platformSlug} does not match record platform ${expectedPlatformSlug}.`, }); } if (graph.startingState.boundary !== "account_creation") { findings.push({ code: "invalid_starting_state", message: "Selected journeys must begin at account creation unless an explicit comparable exception is approved.", }); } if (!graph.selectedRoute.id || graph.selectedRoute.unresolvedReason) { findings.push({ code: "route_unresolved", message: graph.selectedRoute.unresolvedReason ?? "No selected route id is present.", }); } const byId = new Map(graph.nodes.map((node) => [node.id, node])); const candidateRoutes = graph.candidateRoutes ?? []; const selectedCandidate = candidateRoutes.find((candidate) => candidate.id === graph.selectedRoute.id); if (!selectedCandidate || selectedCandidate.status !== "selected") { findings.push({ code: "route_not_declared", message: "The selected route must reference one explicitly declared candidate route.", }); } else if ( selectedCandidate.nodeIds.length !== graph.selectedRoute.nodeIds.length || selectedCandidate.nodeIds.some((id, index) => graph.selectedRoute.nodeIds[index] !== id) ) { findings.push({ code: "invalid_candidate_route", message: "The selected route must exactly match its declared candidate route.", }); } if (candidateRoutes.filter((candidate) => candidate.status === "selected").length !== 1) { findings.push({ code: "invalid_candidate_route", message: "Exactly one candidate route must have selected status.", }); } for (const candidate of candidateRoutes) { if ( !candidate.id.trim() || (candidate.status === "selected" && candidate.nodeIds.length === 0) || candidate.nodeIds.some((id) => !byId.has(id)) || !candidate.selectionBasis.trim() || !candidate.condition.trim() || !candidate.routeSummary.trim() || !candidate.effectOnFirstSuccess.trim() || (candidate.status === "selected" && candidate.reasonNotSelected !== null) || (candidate.status === "considered" && !candidate.reasonNotSelected?.trim()) || (candidate.status === "selected" && candidate.branchAtNodeId !== null) || (candidate.status === "considered" && !candidate.branchAtNodeId) || (candidate.branchAtNodeId !== null && !byId.has(candidate.branchAtNodeId)) || !hasEvidence(candidate.evidence) ) { findings.push({ code: "invalid_candidate_route", message: `Candidate route ${candidate.id || "(missing id)"} is incomplete or references unknown nodes.`, }); } } const route = graph.selectedRoute.nodeIds.map((id) => { const node = byId.get(id); if (!node) { findings.push({ code: "unknown_node", nodeId: id, message: `Selected route references unknown node ${id}.` }); } return node; }).filter((node): node is JourneyNode => Boolean(node)); const seenIds = new Set(); const seenActions = new Map(); const priorActions: Array<{ id: string; action: string }> = []; const available = new Set(graph.startingState.availableInputs); for (const prerequisite of graph.prerequisites ?? []) { if (!hasEvidence(prerequisite.evidence)) { findings.push({ code: prerequisite.evidence?.length ? "missing_evidence_locator" : "missing_evidence", message: `Prerequisite ${prerequisite.id} needs an accepted source and a specific locator.`, }); } for (const output of prerequisite.produces) available.add(output); } const branchIds = new Set(); for (const node of route) { if (seenIds.has(node.id)) { findings.push({ code: "duplicate_node", nodeId: node.id, message: `Node ${node.id} appears more than once in the selected route.` }); } seenIds.add(node.id); if (node.branchId) branchIds.add(node.branchId); const normalized = normalizedAction(node.action); const exact = seenActions.get(normalized); if (exact) { findings.push({ code: "duplicate_node", nodeId: node.id, message: `Action duplicates ${exact}: ${node.action}`, }); } seenActions.set(normalized, node.id); for (const previous of priorActions) { if (jaccard(tokens(previous.action), tokens(node.action)) >= 0.86) { findings.push({ code: "near_duplicate_action", nodeId: node.id, message: `Action is near-duplicate of ${previous.id}: ${node.action}`, }); } } priorActions.push({ id: node.id, action: node.action }); if (node.kind === "developer_action" && looksCompound(node.action)) { findings.push({ code: "compound_action", nodeId: node.id, message: `Developer action contains multiple intentional interactions: ${node.action}`, }); } if (typeof node.requiresFieldInventory !== "boolean") { findings.push({ code: "field_inventory_status_missing", nodeId: node.id, message: "Every selected interaction must declare whether a field inventory is required.", }); } else if (node.requiresFieldInventory && node.requiredFields.length === 0) { findings.push({ code: "missing_field_inventory", nodeId: node.id, message: "This interaction requires a field inventory, but no fields are recorded.", }); } else if (!node.requiresFieldInventory && node.requiredFields.length > 0) { findings.push({ code: "field_inventory_inconsistent", nodeId: node.id, message: "The interaction records fields but declares that no field inventory is required.", }); } if (node.kind === "developer_action" && node.interface === "documentation") { findings.push({ code: "documentation_navigation_action", nodeId: node.id, message: "Opening or reading documentation cannot be counted as a developer journey action.", }); } if ( (node.kind === "passive_wait" || node.kind === "platform_outcome") && node.actor === "developer" ) { findings.push({ code: "wrong_actor_for_event", nodeId: node.id, message: `${node.kind} cannot be counted as a developer action.`, }); } for (const input of node.inputs) { if (!available.has(input)) { findings.push({ code: "broken_causal_input", nodeId: node.id, message: `Input "${input}" is not available from the starting state or an earlier output.`, }); } } for (const output of node.outputs) available.add(output); if (!hasEvidence(node.evidence)) { findings.push({ code: node.evidence?.length ? "missing_evidence_locator" : "missing_evidence", nodeId: node.id, message: "Every selected-route claim needs an accepted source and a specific locator.", }); } for (const field of node.requiredFields) { if (!hasEvidence(field.evidence)) { findings.push({ code: field.evidence?.length ? "missing_evidence_locator" : "missing_evidence", nodeId: node.id, message: `Required field "${field.label}" lacks accepted evidence and a locator.`, }); } } if ( node.kind === "decision" && (!Array.isArray(node.decisionOptions) || node.decisionOptions.length < 2) ) { findings.push({ code: "missing_decision_options", nodeId: node.id, message: "Decision nodes must list the documented options and their effect on the selected route.", }); } for (const option of node.decisionOptions ?? []) { if (!hasEvidence(option.evidence)) { findings.push({ code: option.evidence?.length ? "missing_evidence_locator" : "missing_evidence", nodeId: node.id, message: `Decision option "${option.label}" lacks accepted evidence and a locator.`, }); } } for (const failure of node.failureModes ?? []) { if (!hasEvidence(failure.evidence)) { findings.push({ code: failure.evidence?.length ? "missing_evidence_locator" : "missing_evidence", nodeId: node.id, message: `Failure mode "${failure.condition}" lacks accepted evidence and a locator.`, }); } } } if (branchIds.size > 1) { findings.push({ code: "branch_concatenation", message: `Selected route concatenates ${branchIds.size} alternate branches.`, }); } const terminal = route.at(-1); if (!terminal || terminal.kind !== "terminal_outcome" || !terminal.successSignal.trim()) { findings.push({ code: "invalid_terminal", nodeId: terminal?.id, message: "Selected route must end at an evidence-backed first-success terminal.", }); } const seenEdges = new Set(); for (const edge of graph.edges) { const key = `${edge.from}->${edge.to}`; if (!byId.has(edge.from) || !byId.has(edge.to)) { findings.push({ code: "unknown_edge_endpoint", message: `Edge ${key} references an unknown node.`, }); } if (seenEdges.has(key)) { findings.push({ code: "duplicate_edge", message: `Edge ${key} appears more than once.`, }); } seenEdges.add(key); if (!hasEvidence(edge.evidence)) { findings.push({ code: edge.evidence?.length ? "missing_evidence_locator" : "missing_evidence", message: `Edge ${edge.from} -> ${edge.to} needs an accepted source and a specific locator.`, }); } } for (let index = 0; index < route.length - 1; index += 1) { const from = route[index].id; const to = route[index + 1].id; if (!graph.edges.some((edge) => edge.from === from && edge.to === to)) { findings.push({ code: "missing_route_edge", nodeId: to, message: `Selected route has no explicit edge from ${from} to ${to}.`, }); } } for (const gate of graph.externalGates ?? []) { if (!byId.has(gate.atNodeId) || !route.some((node) => node.id === gate.atNodeId)) { findings.push({ code: "unknown_gate_target", nodeId: gate.atNodeId, message: `External gate ${gate.id} must attach to a node in the selected route.`, }); } if (!hasEvidence(gate.evidence)) { findings.push({ code: gate.evidence?.length ? "missing_evidence_locator" : "missing_evidence", nodeId: gate.atNodeId, message: `External gate ${gate.id} needs an accepted source and a specific locator.`, }); } } for (const uncertainty of graph.uncertainties ?? []) { if (uncertainty.blocksPublication) { findings.push({ code: "unresolved_uncertainty", nodeId: uncertainty.targetType === "node" ? uncertainty.targetId : undefined, message: `${uncertainty.targetType} ${uncertainty.targetId} has a publication-blocking uncertainty: ${uncertainty.description}`, }); } } const boundary = graph.firstSuccessBoundary; if ( !boundary || boundary.nodeId !== terminal?.id || !hasEvidence(boundary.evidence) || (boundary.outcomeClass === "resource_creation" && boundary.officialRouteContinues) ) { findings.push({ code: "invalid_first_success_boundary", nodeId: boundary?.nodeId, message: "The first-success boundary must match the selected terminal, cite evidence, and cannot stop at resource creation when the official route continues to a meaningful result.", }); } return findings; } export function selectedRouteNodes(graph: JourneyGraph): JourneyNode[] { const findings = validateJourneyGraph(graph); if (findings.length > 0) { throw new Error(`Journey graph is not selectable: ${findings.map((item) => item.code).join(", ")}`); } const byId = new Map(graph.nodes.map((node) => [node.id, node])); return graph.selectedRoute.nodeIds.map((id) => byId.get(id)).filter((node): node is JourneyNode => Boolean(node)); } ``` ## scripts/build-corpus-health.mjs Machine-readable corpus health and migration analysis generator. ```javascript import { readFileSync, readdirSync, writeFileSync } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const outputPath = path.join(root, "corpus-health.json"); const migrationPath = path.join(root, "migration-analysis.json"); const launchCohortsPath = path.join(root, "trust", "launch-cohort-candidates.json"); const COMPARISON_FRESHNESS_DAYS = 90; function readJson(file) { return JSON.parse(readFileSync(file, "utf8")); } function normalizeIdentityKey(value) { return String(value ?? "").trim().toLowerCase().replace(/[^a-z0-9]+/g, " ").trim(); } function identityCandidates(record, identities) { const requested = [ record.platform?.slug, record.platform?.name, record.platform?.organization, ].map(normalizeIdentityKey); return identities.filter((identity) => { const keys = [ identity.slug, identity.canonicalName, identity.organization, ...(identity.aliases ?? []), ].map(normalizeIdentityKey); return requested.some((key) => keys.includes(key)); }); } function isDomainOrSubdomain(host, domain) { const accepted = domain.toLowerCase().replace(/^\./, "").replace(/\.$/, ""); return host === accepted || host.endsWith(`.${accepted}`); } function sourceAuthority(source, identity) { let url; try { url = new URL(source.url); } catch { return { source_id: source.id, url: source.url, accepted: false, reason: "invalid_url" }; } if (url.protocol !== "https:") { return { source_id: source.id, url: source.url, accepted: false, reason: "https_required" }; } if (url.hostname.toLowerCase() === "github.com") { const owner = url.pathname.split("/").filter(Boolean)[0]?.toLowerCase(); const approved = (identity.approvedGithubOrganizations ?? []).map((item) => item.toLowerCase()); return { source_id: source.id, url: source.url, accepted: Boolean(owner && approved.includes(owner)), reason: owner && approved.includes(owner) ? "approved_github_organization" : "github_organization_not_approved", }; } const host = url.hostname.toLowerCase().replace(/\.$/, ""); const domains = [ identity.officialRootDomain, ...(identity.documentationDomains ?? []), ...(identity.applicationDomains ?? []), ]; const accepted = domains.some((domain) => isDomainOrSubdomain(host, domain)); return { source_id: source.id, url: source.url, accepted, reason: accepted ? "domain_allowlist_match" : "domain_not_allowlisted", }; } function loadOptionalJson(file) { try { return readJson(file); } catch { return null; } } function normalizedAction(value) { return String(value ?? "") .toLowerCase() .replace(/[^a-z0-9 ]+/g, " ") .replace(/\b(the|a|an|your|this|that)\b/g, " ") .replace(/\s+/g, " ") .trim(); } function daysOld(date, now) { const timestamp = Date.parse(`${date}T00:00:00Z`); if (!Number.isFinite(timestamp)) return null; return Math.floor((now.getTime() - timestamp) / (24 * 60 * 60 * 1000)); } function dispositionFor(record, now) { const age = record.last_retrieval_date?.slice(0, 10) ? daysOld(record.last_retrieval_date.slice(0, 10), now) : null; const passesEveryRuleExceptFreshness = record.resolved_platform_identity.status === "resolved" && record.source_authority.rejected_sources.length === 0 && record.source_authority.accepted_sources.length > 0 && record.source_content_availability.missing_or_unusable_source_ids.length === 0 && record.claims.without_evidence.length === 0 && record.journey_integrity.findings.length === 0; if ( passesEveryRuleExceptFreshness && age !== null && age > COMPARISON_FRESHNESS_DAYS ) { return { status: "stale", machine_readable_reasons: ["evidence_freshness_exceeded_90_days"], failed_freshness_rule: { maximum_age_days: COMPARISON_FRESHNESS_DAYS, observed_age_days: age, last_retrieval_date: record.last_retrieval_date, }, }; } if (record.eligibility.public_display) { return { status: "published", machine_readable_reasons: [], failed_freshness_rule: null, }; } if (record.resolved_platform_identity.status !== "resolved") { return { status: "identity_needs_approval", machine_readable_reasons: [record.resolved_platform_identity.status], failed_freshness_rule: null, }; } if (record.source_authority.rejected_sources.length > 0) { return { status: "excluded", machine_readable_reasons: [ "rejected_authoritative_source", ...record.source_authority.rejected_sources.map((source) => source.reason), ], failed_freshness_rule: null, }; } if ( record.source_authority.accepted_sources.length === 0 || record.source_content_availability.missing_or_unusable_source_ids.length > 0 || record.claims.without_evidence.length > 0 ) { return { status: "evidence_needs_review", machine_readable_reasons: [ ...(record.source_authority.accepted_sources.length === 0 ? ["no_accepted_source"] : []), ...(record.source_content_availability.missing_or_unusable_source_ids.length > 0 ? ["source_content_unavailable"] : []), ...(record.claims.without_evidence.length > 0 ? ["claim_grounding_failed"] : []), ], failed_freshness_rule: null, }; } return { status: "route_needs_review", machine_readable_reasons: record.journey_integrity.findings.map((finding) => finding.code), failed_freshness_rule: null, }; } function generatedFilesFor(slug) { return [ `trust/platform-identities.json`, `trust/source-evidence/${slug}.json`, `trust/journey-graphs/${slug}.json`, "corpus-health.json", "migration-analysis.json", "selected-path-heuristic.json", "public/data/index.json", `public/data/records/${slug}.json`, "public/llms.txt", "public/llms-full.txt", "public/sitemap.xml", "public/source/index.md", ]; } function looksCompound(action) { const normalized = action.toLowerCase(); const connectors = normalized.match(/\b(and then|then|and|after that)\b/g) ?? []; const verbs = normalized.match( /\b(open|click|select|choose|enter|create|copy|paste|authorize|connect|submit|run|send|confirm|verify|purchase|add|configure)\b/g, ) ?? []; return connectors.length > 0 && verbs.length > 1; } function graphHealth(graph, evidenceById, recordSourceIds, expectedPlatformSlug) { if (!graph) { return { selected_route_resolved: false, findings: [{ code: "missing_journey_graph", message: "No evidence-backed journey graph is committed." }], claims_with_evidence: 0, claims_without_evidence: [], field_inventory_count: 0, }; } const findings = []; const byId = new Map((graph.nodes ?? []).map((node) => [node.id, node])); const routeIds = graph.selectedRoute?.nodeIds ?? []; const route = routeIds.map((id) => byId.get(id)).filter(Boolean); if (!graph.selectedRoute?.id || graph.selectedRoute?.unresolvedReason) { findings.push({ code: "route_unresolved", message: graph.selectedRoute?.unresolvedReason ?? "No selected route." }); } if (graph.startingState?.boundary !== "account_creation") { findings.push({ code: "invalid_starting_state", message: "Route does not begin at account creation." }); } if (graph.platformSlug !== expectedPlatformSlug) { findings.push({ code: "platform_slug_mismatch" }); } if (route.length !== routeIds.length) { findings.push({ code: "unknown_node", message: "Selected route references an unknown node." }); } const seenIds = new Set(); const seenActions = new Map(); const available = new Set(graph.startingState?.availableInputs ?? []); const branches = new Set(); let claimsWithEvidence = 0; const claimsWithoutEvidence = []; let fieldInventoryCount = 0; function checkEvidence(owner, evidence) { if (!Array.isArray(evidence) || evidence.length === 0) { claimsWithoutEvidence.push(owner); return; } const valid = evidence.every((item) => { const sourceExists = recordSourceIds.has(item.sourceId); const metadata = evidenceById.get(item.sourceId); return Boolean( sourceExists && item.locator?.trim() && metadata?.content_present && metadata?.content_hash && metadata?.locator_coverage?.includes(item.locator) && metadata?.http_status >= 200 && metadata?.http_status < 300, ); }); if (valid) claimsWithEvidence += 1; else claimsWithoutEvidence.push(owner); } for (const prerequisite of graph.prerequisites ?? []) { checkEvidence(`prerequisite:${prerequisite.id}`, prerequisite.evidence); for (const output of prerequisite.produces ?? []) available.add(output); } for (const node of route) { if (seenIds.has(node.id)) findings.push({ code: "duplicate_node", node_id: node.id }); seenIds.add(node.id); const action = normalizedAction(node.action); if (seenActions.has(action)) { findings.push({ code: "duplicate_action", node_id: node.id, duplicates: seenActions.get(action) }); } seenActions.set(action, node.id); if (node.kind === "developer_action" && looksCompound(node.action)) { findings.push({ code: "compound_action", node_id: node.id }); } if (typeof node.requiresFieldInventory !== "boolean") { findings.push({ code: "field_inventory_status_missing", node_id: node.id }); } else if (node.requiresFieldInventory && (node.requiredFields ?? []).length === 0) { findings.push({ code: "missing_field_inventory", node_id: node.id }); } else if (!node.requiresFieldInventory && (node.requiredFields ?? []).length > 0) { findings.push({ code: "field_inventory_inconsistent", node_id: node.id }); } if (node.kind === "developer_action" && node.interface === "documentation") { findings.push({ code: "documentation_navigation_action", node_id: node.id }); } if ( ["passive_wait", "platform_outcome"].includes(node.kind) && node.actor === "developer" ) { findings.push({ code: "event_counted_as_developer_action", node_id: node.id }); } for (const input of node.inputs ?? []) { if (!available.has(input)) findings.push({ code: "broken_causal_input", node_id: node.id, input }); } for (const output of node.outputs ?? []) available.add(output); if (node.branchId) branches.add(node.branchId); checkEvidence(`node:${node.id}`, node.evidence); for (const field of node.requiredFields ?? []) { fieldInventoryCount += 1; checkEvidence(`field:${node.id}:${field.label}`, field.evidence); } } const edges = graph.edges ?? []; const seenEdges = new Set(); for (const edge of edges) { const key = `${edge.from}->${edge.to}`; if (!byId.has(edge.from) || !byId.has(edge.to)) { findings.push({ code: "unknown_edge_endpoint", edge: key }); } if (seenEdges.has(key)) findings.push({ code: "duplicate_edge", edge: key }); seenEdges.add(key); checkEvidence(`edge:${edge.from}:${edge.to}`, edge.evidence); } const edgeKeys = new Set(edges.map((edge) => `${edge.from}->${edge.to}`)); for (let index = 0; index < route.length - 1; index += 1) { const key = `${route[index].id}->${route[index + 1].id}`; if (!edgeKeys.has(key)) findings.push({ code: "missing_route_edge", edge: key }); } if (branches.size > 1) findings.push({ code: "branch_concatenation", branches: [...branches] }); const selectedCandidate = (graph.candidateRoutes ?? []) .find((candidate) => candidate.id === graph.selectedRoute?.id); if (!selectedCandidate || selectedCandidate.status !== "selected") { findings.push({ code: "route_not_declared" }); } else if ( selectedCandidate.nodeIds.length !== routeIds.length || selectedCandidate.nodeIds.some((id, index) => routeIds[index] !== id) ) { findings.push({ code: "invalid_candidate_route" }); } if ((graph.candidateRoutes ?? []).filter((candidate) => candidate.status === "selected").length !== 1) { findings.push({ code: "invalid_candidate_route" }); } for (const candidate of graph.candidateRoutes ?? []) { if ( !candidate.selectionBasis?.trim() || !candidate.condition?.trim() || !candidate.routeSummary?.trim() || !candidate.effectOnFirstSuccess?.trim() || (candidate.status === "selected" && candidate.reasonNotSelected !== null) || (candidate.status === "considered" && !candidate.reasonNotSelected?.trim()) || (candidate.status === "selected" && candidate.branchAtNodeId !== null) || (candidate.status === "considered" && !routeIds.includes(candidate.branchAtNodeId)) ) { findings.push({ code: "invalid_candidate_route", route_id: candidate.id }); } checkEvidence(`candidate-route:${candidate.id}`, candidate.evidence); } for (const gate of graph.externalGates ?? []) { if (!routeIds.includes(gate.atNodeId)) { findings.push({ code: "unknown_gate_target", gate_id: gate.id, node_id: gate.atNodeId }); } checkEvidence(`external-gate:${gate.id}`, gate.evidence); } for (const uncertainty of graph.uncertainties ?? []) { if (uncertainty.blocksPublication) { findings.push({ code: "unresolved_uncertainty", target_type: uncertainty.targetType, target_id: uncertainty.targetId, }); } } const terminal = route.at(-1); if (terminal?.kind !== "terminal_outcome") findings.push({ code: "invalid_terminal" }); const boundary = graph.firstSuccessBoundary; if ( !boundary || boundary.nodeId !== terminal?.id || (boundary.outcomeClass === "resource_creation" && boundary.officialRouteContinues) ) { findings.push({ code: "invalid_first_success_boundary" }); } else { checkEvidence("first-success-boundary", boundary.evidence); } if (claimsWithoutEvidence.length > 0) { findings.push({ code: "claim_grounding_failed", count: claimsWithoutEvidence.length }); } return { selected_route_resolved: Boolean(graph.selectedRoute?.id && !graph.selectedRoute?.unresolvedReason), findings, claims_with_evidence: claimsWithEvidence, claims_without_evidence: claimsWithoutEvidence, field_inventory_count: fieldInventoryCount, }; } const roster = readJson(path.join(root, "roster.json")); const identities = readJson(path.join(root, "trust", "platform-identities.json")).identities; const records = roster.map((entry) => readJson(path.join(root, "records", `${entry.slug}.json`))); const recordsBySlug = new Map(records.map((record) => [record.platform.slug, record])); const healthRecords = []; const generatedAt = new Date(); for (const record of records) { const slug = record.platform.slug; const candidates = identityCandidates(record, identities); const resolvedIdentity = candidates.length === 1 ? candidates[0] : null; const authority = resolvedIdentity ? (record.sources ?? []).map((source) => sourceAuthority(source, resolvedIdentity)) : []; const acceptedSources = authority.filter((item) => item.accepted); const rejectedSources = authority.filter((item) => !item.accepted); const evidenceFile = loadOptionalJson(path.join(root, "trust", "source-evidence", `${slug}.json`)); const evidenceRows = evidenceFile?.sources ?? []; const evidenceById = new Map(evidenceRows.map((item) => [item.source_id, item])); const missingContent = acceptedSources .filter((item) => { const metadata = evidenceById.get(item.source_id); return !metadata?.content_present || !metadata?.content_hash || metadata.http_status < 200 || metadata.http_status >= 300; }) .map((item) => item.source_id); const graph = loadOptionalJson(path.join(root, "trust", "journey-graphs", `${slug}.json`)); const graphResult = graphHealth( graph, evidenceById, new Set((record.sources ?? []).map((source) => source.id)), slug, ); const lastRetrievalDate = evidenceFile?.retrieved_at ?? null; const evidenceAgeDays = lastRetrievalDate?.slice(0, 10) ? daysOld(lastRetrievalDate.slice(0, 10), generatedAt) : null; const evidenceIsFresh = evidenceAgeDays !== null && evidenceAgeDays <= COMPARISON_FRESHNESS_DAYS; const identityStatus = candidates.length === 1 ? "resolved" : candidates.length > 1 ? "identity_ambiguous" : "identity_unresolved"; const eligible = identityStatus === "resolved" && rejectedSources.length === 0 && acceptedSources.length > 0 && missingContent.length === 0 && graphResult.findings.length === 0 && evidenceIsFresh; const reasons = [ ...(identityStatus === "resolved" ? [] : [identityStatus]), ...(rejectedSources.length ? ["rejected_authoritative_source"] : []), ...(missingContent.length ? ["source_content_unavailable"] : []), ...graphResult.findings.map((item) => item.code), ...(evidenceAgeDays === null ? ["evidence_retrieval_date_missing"] : []), ...(evidenceAgeDays !== null && !evidenceIsFresh ? ["evidence_freshness_exceeded_90_days"] : []), ]; healthRecords.push({ slug, resolved_platform_identity: { status: identityStatus, canonical_name: resolvedIdentity?.canonicalName ?? null, organization: resolvedIdentity?.organization ?? null, official_root_domain: resolvedIdentity?.officialRootDomain ?? null, candidate_slugs: candidates.map((item) => item.slug), }, source_authority: { accepted_sources: acceptedSources, rejected_sources: rejectedSources, }, source_content_availability: { metadata_records: evidenceRows.length, missing_or_unusable_source_ids: missingContent, }, claims: { with_evidence: graphResult.claims_with_evidence, without_evidence: graphResult.claims_without_evidence, }, journey_integrity: { selected_route_resolved: graphResult.selected_route_resolved, findings: graphResult.findings, required_field_inventory_count: graphResult.field_inventory_count, }, last_retrieval_date: lastRetrievalDate, eligibility: { reconstruction: eligible, audit: eligible, public_display: eligible, reasons, }, }); } const allowedDispositions = new Set([ "published", "excluded", "stale", "identity_needs_approval", "evidence_needs_review", "route_needs_review", ]); for (const healthRecord of healthRecords) { const record = recordsBySlug.get(healthRecord.slug); const sourcesById = new Map((record?.sources ?? []).map((source) => [source.id, source])); const disposition = dispositionFor(healthRecord, generatedAt); if (!allowedDispositions.has(disposition.status)) { throw new Error(`${healthRecord.slug}: unknown operational disposition ${disposition.status}`); } healthRecord.operational_disposition = { ...disposition, failed_evidence: { rejected_sources: healthRecord.source_authority.rejected_sources.map((source) => ({ source_id: source.source_id, url: source.url, reason: source.reason, })), missing_or_unusable_sources: healthRecord.source_content_availability.missing_or_unusable_source_ids.map((sourceId) => ({ source_id: sourceId, title: sourcesById.get(sourceId)?.title ?? null, url: sourcesById.get(sourceId)?.url ?? null, })), claims_without_evidence: healthRecord.claims.without_evidence, route_findings: healthRecord.journey_integrity.findings, }, generated_files_on_approval: generatedFilesFor(healthRecord.slug), }; } const launchPlan = readJson(launchCohortsPath); const cohortParticipants = launchPlan.cohorts.flatMap((cohort) => cohort.participant_slugs); if (launchPlan.cohorts.length < 5) { throw new Error("Launch cohort plan must contain at least five candidate cohorts."); } if (new Set(cohortParticipants).size < 20 || new Set(cohortParticipants).size !== cohortParticipants.length) { throw new Error("Launch cohort plan must contain at least 20 distinct platforms with no repeated platform."); } if ( launchPlan.priority_cohort_id && !launchPlan.cohorts.some((cohort) => cohort.id === launchPlan.priority_cohort_id) ) { throw new Error(`Unknown priority cohort: ${launchPlan.priority_cohort_id}`); } const healthBySlug = new Map(healthRecords.map((record) => [record.slug, record])); const candidateCohorts = launchPlan.cohorts.map((cohort) => { if (cohort.participant_slugs.length < 4) { throw new Error(`${cohort.id}: candidate cohort requires at least four platforms.`); } const participants = cohort.participant_slugs.map((slug) => { const healthRecord = healthBySlug.get(slug); const record = recordsBySlug.get(slug); if (!healthRecord || !record) throw new Error(`${cohort.id}: unknown platform ${slug}`); return { slug, healthRecord, record }; }); const organizations = new Set( participants.map(({ record }) => normalizeIdentityKey(record.platform.organization)), ); if (organizations.size !== participants.length) { throw new Error(`${cohort.id}: organizations must be distinct within the candidate cohort.`); } const qualifiedParticipants = participants.filter(({ healthRecord, record }) => { if (healthRecord.operational_disposition.status !== "published") return false; const graph = loadOptionalJson(path.join(root, "trust", "journey-graphs", `${healthRecord.slug}.json`)); const basis = graph?.comparisonBasis; return Boolean( basis && basis.developerJobKey === cohort.developer_job_key && basis.startingBoundaryKey === cohort.starting_boundary_key && basis.firstSuccessOutcomeClass === cohort.first_success_outcome_class && basis.firstSuccessBoundaryKey === cohort.first_success_boundary_key && basis.routeGranularityVersion === cohort.route_granularity_version && basis.categoryKey === cohort.category_key && basis.organizationKey === normalizeIdentityKey(record.platform.organization), ); }); return { id: cohort.id, status: qualifiedParticipants.length === participants.length ? "qualified" : "candidate_needs_review", developer_job_key: cohort.developer_job_key, starting_boundary_key: cohort.starting_boundary_key, first_success_outcome_class: cohort.first_success_outcome_class, first_success_boundary_key: cohort.first_success_boundary_key, route_granularity_version: cohort.route_granularity_version, category_key: cohort.category_key, review_hypothesis: cohort.review_hypothesis, publication_eligible_count: participants.filter( ({ healthRecord }) => healthRecord.operational_disposition.status === "published", ).length, comparison_qualified_count: qualifiedParticipants.length, required_platform_count: participants.length, participants: participants.map(({ slug, healthRecord, record }) => ({ slug, name: record.platform.name, organization: record.platform.organization, disposition: healthRecord.operational_disposition.status, blocking_reasons: healthRecord.operational_disposition.machine_readable_reasons, starting_url: record.entry_point?.starting_url ?? null, proposed_first_success: record.documented_first_success?.normalized_outcome ?? null, unresolved_questions: (record.uncertainties ?? []).map((item) => item.question), source_candidates: (record.sources ?? []).map((source) => ({ id: source.id, title: source.title, url: source.url, accessed_at: source.accessed_at ?? null, sections_used: source.sections_used ?? [], })), generated_files_on_approval: healthRecord.operational_disposition.generated_files_on_approval, })), required_review_sequence: [ "Approve one unambiguous platform identity per participant.", "Retrieve current first-party pages and record request, redirects, content, hashes, titles, links, authority, and locators.", "Reconstruct and validate one atomic selected route per participant.", "Independently review every route and its first-success boundary.", `Certify cohort equivalence and comparison basis only after all ${participants.length} routes pass.`, ], }; }); const dispositionCounts = Object.fromEntries( [...allowedDispositions].map((status) => [ status, healthRecords.filter((record) => record.operational_disposition.status === status).length, ]), ); if (Object.values(dispositionCounts).reduce((sum, count) => sum + count, 0) !== healthRecords.length) { throw new Error("Every corpus record must receive exactly one operational disposition."); } const rankedCohorts = [...candidateCohorts].sort((left, right) => right.publication_eligible_count - left.publication_eligible_count || left.id.localeCompare(right.id), ); const recommendedCohort = candidateCohorts.find((cohort) => cohort.id === launchPlan.priority_cohort_id) ?? rankedCohorts[0] ?? null; const candidateSlugSet = new Set(cohortParticipants); const dispositionRank = { route_needs_review: 0, evidence_needs_review: 1, identity_needs_approval: 2, stale: 3, excluded: 4, published: 5, }; const closestRecords = healthRecords .filter((record) => record.operational_disposition.status !== "published") .sort((left, right) => Number(candidateSlugSet.has(right.slug)) - Number(candidateSlugSet.has(left.slug)) || dispositionRank[left.operational_disposition.status] - dispositionRank[right.operational_disposition.status] || left.slug.localeCompare(right.slug), ) .slice(0, 20) .map((record) => ({ slug: record.slug, disposition: record.operational_disposition.status, blocking_reasons: record.operational_disposition.machine_readable_reasons, launch_cohorts: candidateCohorts .filter((cohort) => cohort.participants.some((participant) => participant.slug === record.slug)) .map((cohort) => cohort.id), })); const health = { schema_version: "1.0", generated_at: generatedAt.toISOString(), contract: "A record is public only when identity, source authority, source content, claim coverage, and selected-route integrity all pass.", summary: { records: healthRecords.length, identity_resolved: healthRecords.filter((item) => item.resolved_platform_identity.status === "resolved").length, records_with_rejected_sources: healthRecords.filter((item) => item.source_authority.rejected_sources.length > 0).length, records_with_content_metadata: healthRecords.filter((item) => item.source_content_availability.metadata_records > 0).length, records_with_selected_graph: healthRecords.filter((item) => item.journey_integrity.selected_route_resolved).length, eligible_for_public_display: healthRecords.filter((item) => item.eligibility.public_display).length, dispositions: dispositionCounts, candidate_launch_platforms: new Set(cohortParticipants).size, candidate_comparison_cohorts: candidateCohorts.length, qualified_comparison_cohorts: candidateCohorts.filter((cohort) => cohort.status === "qualified").length, routes_with_three_qualified_peers: candidateCohorts .filter((cohort) => cohort.status === "qualified") .reduce((sum, cohort) => sum + cohort.required_platform_count, 0), }, review_operations: { source: "trust/launch-cohort-candidates.json", status: launchPlan.status, priority_cohort_id: launchPlan.priority_cohort_id ?? null, priority_reason: launchPlan.priority_reason ?? null, closest_cohort: recommendedCohort?.id ?? null, closest_records: closestRecords, cohort_completion_candidates: candidateCohorts.map((cohort) => ({ cohort_id: cohort.id, remaining_platforms: cohort.participants .filter((participant) => participant.disposition !== "published") .map((participant) => participant.slug), remaining_count: cohort.participants.filter( (participant) => participant.disposition !== "published", ).length, })), recommended_next_review_action: recommendedCohort ? `Review identity candidates for the unpublished ${recommendedCohort.id} participants as one cohort, then retrieve and reconstruct those routes together.` : null, candidate_cohorts: candidateCohorts, }, records: healthRecords, }; const quality = readJson(path.join(root, "ds-quality.json")); const exactDuplicateRecords = []; for (const record of records) { const seen = new Map(); const duplicates = []; for (const step of record.primary_path ?? []) { const action = normalizedAction(step.action); if (seen.has(action)) { duplicates.push({ step_number: step.step_number, duplicates_step: seen.get(action) }); } else { seen.set(action, step.step_number); } } if (duplicates.length) exactDuplicateRecords.push({ slug: record.platform.slug, duplicates }); } const qualityBySlug = new Map((quality.records ?? []).map((item) => [item.slug, item])); const migration = { schema_version: "1.0", generated_at: health.generated_at, scope: "Analysis only. The representative Render route is repaired. All other records remain quarantined until identity, source, and route review passes.", summary: { records: records.length, records_with_compound_steps: quality.summary?.with_non_atomic_steps ?? null, compound_steps: (quality.records ?? []).reduce((sum, item) => sum + (item.non_atomic_step_count ?? 0), 0), records_with_exact_duplicate_actions: exactDuplicateRecords.length, exact_duplicate_actions: exactDuplicateRecords.reduce((sum, item) => sum + item.duplicates.length, 0), records_missing_field_inventories: records.length - health.summary.records_with_selected_graph, unresolved_routes: healthRecords.filter((item) => !item.journey_integrity.selected_route_resolved).length, broken_causal_continuity: healthRecords.filter((item) => item.journey_integrity.findings.some((finding) => finding.code === "broken_causal_input"), ).length, }, launch_review: { candidate_platforms: new Set(cohortParticipants).size, candidate_cohorts: candidateCohorts.length, qualified_cohorts: candidateCohorts.filter((cohort) => cohort.status === "qualified").length, public_route_shortfall: Math.max( 0, new Set(cohortParticipants).size - dispositionCounts.published, ), qualified_cohort_shortfall: Math.max( 0, 5 - candidateCohorts.filter((cohort) => cohort.status === "qualified").length, ), routes_with_three_qualified_peers: health.summary.routes_with_three_qualified_peers, recommended_next_review_action: health.review_operations.recommended_next_review_action, }, affected_records: (quality.records ?? []) .filter((item) => item.non_atomic_step_count > 0) .map((item) => ({ slug: item.slug, compound_step_numbers: (item.detector_matches ?? []) .filter((match) => match.detector === "non-atomic-step") .map((match) => match.step_number), exact_duplicate_steps: exactDuplicateRecords.find((entry) => entry.slug === item.slug)?.duplicates ?? [], disposition: item.slug === "render" ? "representative_repair" : "human_route_judgment", comparability_status: qualityBySlug.get(item.slug)?.comparability_status ?? null, })), }; function comparableJson(value) { const copy = structuredClone(value); delete copy.generated_at; return `${JSON.stringify(copy, null, 2)}\n`; } if (process.argv.includes("--check")) { const currentHealth = readJson(outputPath); const currentMigration = readJson(migrationPath); if (comparableJson(currentHealth) !== comparableJson(health) || comparableJson(currentMigration) !== comparableJson(migration)) { console.error("Corpus health artifacts are stale. Run npm run trust:health."); process.exit(1); } console.log( `Corpus health current: ${health.summary.eligible_for_public_display}/${health.summary.records} records eligible for public display.`, ); } else { writeFileSync(outputPath, `${JSON.stringify(health, null, 2)}\n`); writeFileSync(migrationPath, `${JSON.stringify(migration, null, 2)}\n`); console.log( `Corpus health: ${health.summary.eligible_for_public_display}/${health.summary.records} records eligible for public display.`, ); } ``` ## scripts/build-site.mjs Fail-closed machine artifact and source snapshot generator. ```javascript import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const outputRoot = path.join(projectRoot, "public"); const dataRoot = path.join(outputRoot, "data"); const recordsRoot = path.join(dataRoot, "records"); const sourceRoot = path.join(outputRoot, "source"); const canonicalUrl = process.env.PUBLIC_BASE_URL ?? "https://developer-journey-atlas.onrender.com"; const sourceFiles = [ { path: "web/index.html", language: "html", description: "The active product document served before generated artifacts." }, { path: "web/app.js", language: "javascript", description: "Search, durable routing, explicit research consent, sharing, and route rendering." }, { path: "web/styles.css", language: "css", description: "The active responsive and accessible visual system." }, { path: "src/server.ts", language: "typescript", description: "The deployed Express composition root and platform-page metadata route." }, { path: "src/api/router.ts", language: "typescript", description: "The complete public API route index." }, { path: "src/api/platforms.ts", language: "typescript", description: "Fail-closed platform list and route presenter." }, { path: "src/api/journey.ts", language: "typescript", description: "Selected journey graph presenter with public blocker links suppressed." }, { path: "src/api/peerComparison.ts", language: "typescript", description: "Compatible-domain peer comparison presenter with strict qualification gates." }, { path: "src/api/research.ts", language: "typescript", description: "Explicit research start and private review projection." }, { path: "src/core/complexityProfile.ts", language: "typescript", description: "Auditable documented structural complexity dimensions and rating formula." }, { path: "src/core/peerComparison.ts", language: "typescript", description: "Reviewed-route compatible peer qualification and comparison dimensions." }, { path: "src/core/publicationGate.ts", language: "typescript", description: "Identity, source, claim, and route publication gate." }, { path: "src/core/sourceAuthority.ts", language: "typescript", description: "Deterministic first-party source authority checks." }, { path: "src/core/journeyGraph.ts", language: "typescript", description: "Typed journey graph and selected-route integrity checks." }, { path: "scripts/build-corpus-health.mjs", language: "javascript", description: "Machine-readable corpus health and migration analysis generator." }, { path: "scripts/build-site.mjs", language: "javascript", description: "Fail-closed machine artifact and source snapshot generator." }, { path: "scripts/check-llm-site.mjs", language: "javascript", description: "Generated public-surface contract check." }, { path: "PRIVACY.md", language: "markdown", description: "Research provider, storage, retention, and deletion disclosure." }, { path: "EVENT-CONTRACT.txt", language: "text", description: "Uninstrumented privacy-preserving event contract." }, { path: "LAUNCH-CHECKLIST.txt", language: "text", description: "Human review and representative-user pilot gate." }, { path: "package.json", language: "json", description: "Supported build, audit, evaluation, and test commands." }, ]; function sourceUrl(filePath) { return `${canonicalUrl}/source/${filePath}`; } function fencedCode(language, content) { const runs = [...content.matchAll(/`+/g)].map((match) => match[0].length); const fence = "`".repeat(Math.max(3, ...runs.map((length) => length + 1))); return `${fence}${language}\n${content.trimEnd()}\n${fence}`; } await rm(outputRoot, { recursive: true, force: true }); await mkdir(recordsRoot, { recursive: true }); await mkdir(sourceRoot, { recursive: true }); await cp(path.join(projectRoot, "site", "robots.txt"), path.join(outputRoot, "robots.txt")); const coverage = JSON.parse(await readFile(path.join(projectRoot, "coverage.json"), "utf8")); const health = JSON.parse(await readFile(path.join(projectRoot, "corpus-health.json"), "utf8")); const atlas = JSON.parse(await readFile(path.join(projectRoot, "selected-path-heuristic.json"), "utf8")); const auditStatus = JSON.parse(await readFile(path.join(projectRoot, "audit-status.json"), "utf8")); const launchCohortPlan = JSON.parse( await readFile(path.join(projectRoot, "trust", "launch-cohort-candidates.json"), "utf8"), ); const eligibleSlugs = new Set( health.records .filter((record) => record.eligibility.public_display) .map((record) => record.slug), ); const eligibleRows = atlas.rows.filter((row) => eligibleSlugs.has(row.slug)); const rowBySlug = new Map(atlas.rows.map((row) => [row.slug, row])); const llmCohortCopy = { "llm-api-first-response": { label: "Direct model APIs", shortLabel: "Model provider", description: "APIs operated by model providers. These routes start with a new provider account and end when an authenticated request returns model output.", }, "managed-llm-inference-first-response": { label: "Inference and routing", shortLabel: "Inference or router", description: "Hosted services that run or route models. Model selection, routing, and the service provider remain visible in the review.", }, "cloud-llm-platform-first-response": { label: "Cloud platforms", shortLabel: "Cloud platform", description: "Model APIs inside cloud or data platforms. Their reviews include the surrounding account, billing, project, region, and access setup.", }, }; const llmProviderSearchAliases = { "google-gemini-api": ["Google", "Gemini"], "xai-api": ["xAI", "Grok"], "groqcloud": ["Groq", "GroqCloud"], "hugging-face": ["Hugging Face", "HF"], "nvidia-developer": ["NVIDIA", "NIM"], "cloudflare-workers-ai": ["Cloudflare", "Workers AI"], "amazon-bedrock": ["Amazon", "AWS", "Bedrock"], "microsoft-foundry": ["Microsoft", "Azure", "Azure AI Foundry"], "google-vertex-ai": ["Google", "GCP", "Vertex AI"], "ibm-watsonx-ai": ["IBM", "watsonx"], "oracle-generative-ai": ["Oracle", "OCI"], "databricks-foundation-model-api": ["Databricks"], "snowflake-cortex-ai": ["Snowflake", "Cortex"], }; const llmCohorts = launchCohortPlan.cohorts .filter((cohort) => llmCohortCopy[cohort.id]) .map((cohort) => { const copy = llmCohortCopy[cohort.id]; return { id: cohort.id, label: copy.label, shortLabel: copy.shortLabel, description: copy.description, providers: cohort.participant_slugs.map((slug) => { const row = rowBySlug.get(slug); if (!row) throw new Error(`LLM API catalog references missing platform "${slug}".`); const routePublished = eligibleSlugs.has(slug); return { name: row.name, slug: row.slug, cohortId: cohort.id, cohortLabel: copy.label, providerType: copy.shortLabel, searchAliases: llmProviderSearchAliases[row.slug] ?? [], routeStatus: routePublished ? "published" : "review_in_progress", routeUrl: routePublished ? `${canonicalUrl}/platform/${row.slug}` : null, }; }), }; }); const llmProviderSlugs = llmCohorts.flatMap((cohort) => cohort.providers.map((provider) => provider.slug)); const expectedLlmProviderCount = launchCohortPlan.cohorts .filter((cohort) => llmCohortCopy[cohort.id]) .reduce((count, cohort) => count + cohort.participant_slugs.length, 0); if ( llmProviderSlugs.length !== expectedLlmProviderCount || new Set(llmProviderSlugs).size !== expectedLlmProviderCount ) { throw new Error( `Expected ${expectedLlmProviderCount} unique LLM API providers, found ${llmProviderSlugs.length}.`, ); } const llmApiCatalog = { schemaVersion: 1, name: "LLM API research catalog", description: "A maintained inventory of currently documented LLM API providers, grouped by setup model. Catalog membership is not route verification or comparison certification.", generatedAt: coverage.generated_at, providerCount: llmProviderSlugs.length, routeReviewStatus: "in_progress", cohorts: llmCohorts, }; await writeFile( path.join(dataRoot, "llm-api-catalog.json"), `${JSON.stringify(llmApiCatalog, null, 2)}\n`, "utf8", ); function publicRecordFromGraph(record, graph) { const nodeById = new Map(graph.nodes.map((node) => [node.id, node])); const nodes = graph.selectedRoute.nodeIds.map((id) => nodeById.get(id)).filter(Boolean); const stepNumberByNodeId = new Map(nodes.map((node, index) => [node.id, index + 1])); const prerequisites = graph.prerequisites.map((item, index) => ({ order: index + 1, type: item.type, requirement: item.requirement, required: item.required, source_ids: [...new Set(item.evidence.map((evidence) => evidence.sourceId))], })); const frictionGates = graph.externalGates.map((gate) => ({ at_step: stepNumberByNodeId.get(gate.atNodeId), type: gate.type, description: gate.description, documented_requirement: true, required: gate.required, source_ids: [...new Set(gate.evidence.map((evidence) => evidence.sourceId))], })); const branches = graph.candidateRoutes .filter((candidate) => candidate.status === "considered") .map((candidate) => ({ at_step: stepNumberByNodeId.get(candidate.branchAtNodeId), condition: candidate.condition, path: candidate.routeSummary, effect_on_first_success: candidate.effectOnFirstSuccess, source_ids: [...new Set(candidate.evidence.map((evidence) => evidence.sourceId))], })); return { ...record, prerequisites, primary_path: nodes.map((node, index) => ({ step_number: index + 1, phase: node.phase, actor: node.actor, interface: node.interface, action: node.action, details: [], input: node.inputs.join(", "), output: node.outputs.join(", "), success_signal: node.successSignal, failure_or_wait: node.kind === "passive_wait" ? node.action : "", required: node.required, source_ids: [...new Set(node.evidence.map((evidence) => evidence.sourceId))], required_fields: node.requiredFields, })), branches, friction_gates: frictionGates, journey_graph: graph, }; } const publicRecords = new Map(); for (const row of eligibleRows) { const record = JSON.parse(await readFile(path.join(projectRoot, "records", `${row.slug}.json`), "utf8")); const graph = JSON.parse( await readFile(path.join(projectRoot, "trust", "journey-graphs", `${row.slug}.json`), "utf8"), ); const publicRecord = publicRecordFromGraph(record, graph); publicRecords.set(row.slug, publicRecord); await writeFile( path.join(recordsRoot, `${row.slug}.json`), `${JSON.stringify(publicRecord, null, 2)}\n`, "utf8", ); } await cp(path.join(projectRoot, "record.schema.json"), path.join(dataRoot, "record.schema.json")); const summary = { generatedAt: coverage.generated_at, reviewedCorpusRecords: coverage.roster_count, publicRoutes: eligibleRows.length, researchDrafts: 0, verifiedAudits: auditStatus.verified, blockerLinkEvaluation: "awaiting independent labels", publicAssociationsAvailable: false, }; await writeFile( path.join(dataRoot, "coverage-summary.json"), `${JSON.stringify(summary, null, 2)}\n`, "utf8", ); const records = eligibleRows.map((row) => ({ name: row.name, slug: row.slug, category: row.category, outcome: row.outcome, platformUrl: `${canonicalUrl}/platform/${row.slug}`, recordUrl: `${canonicalUrl}/data/records/${row.slug}.json`, evidenceClass: "documented_fact", })); const dataIndex = { schemaVersion: 2, name: "Developer Journey Atlas", description: "Publication-eligible documented routes from account creation to first success. Documentation structure is not user behavior or product quality.", canonicalUrl, generatedAt: coverage.generated_at, servingModel: { productUi: "packages/journey-corpus/web", machineArtifacts: "packages/journey-corpus/public", note: "Generated artifacts never shadow or describe a second frontend.", }, counts: summary, publicationContract: [ "Every public route passes deterministic platform identity, source authority, content availability, claim coverage, and selected-route integrity gates.", "Unevaluated blocker-reason links and cross-platform associations are not public.", "Documented structural complexity is shown as auditable counts and a formula, not observed difficulty or product quality.", "Peer comparison is withheld unless the subject and at least three compatible domain peers pass every qualification rule.", ], files: { llmIndex: `${canonicalUrl}/llms.txt`, fullContext: `${canonicalUrl}/llms-full.txt`, llmApiCatalog: `${canonicalUrl}/data/llm-api-catalog.json`, coverageSummary: `${canonicalUrl}/data/coverage-summary.json`, recordSchema: `${canonicalUrl}/data/record.schema.json`, measurementContract: `${canonicalUrl}/measurement-contract.md`, privacy: `${canonicalUrl}/privacy.md`, }, records, sourceCode: { index: `${canonicalUrl}/source/index.md`, license: "Apache-2.0", files: sourceFiles.map((file) => ({ path: file.path, url: sourceUrl(file.path), description: file.description, })), }, }; await writeFile(path.join(dataRoot, "index.json"), `${JSON.stringify(dataIndex, null, 2)}\n`, "utf8"); const selectionPolicy = await readFile(path.join(projectRoot, "SELECTION-POLICY.txt"), "utf8"); const measurementContract = await readFile(path.join(projectRoot, "MEASUREMENT-CONTRACT.txt"), "utf8"); const privacy = await readFile(path.join(projectRoot, "PRIVACY.md"), "utf8"); const eventContract = await readFile(path.join(projectRoot, "EVENT-CONTRACT.txt"), "utf8"); const launchChecklist = await readFile(path.join(projectRoot, "LAUNCH-CHECKLIST.txt"), "utf8"); const methodology = `# Developer Journey Atlas methodology The Atlas publishes only a selected account-creation-to-first-success route that passes deterministic platform identity, first-party source-content, claim-grounding, required-field, branch, and route-integrity gates. Documentation structure is not evidence of usability, conversion, abandonment, difficulty, or causality. ${selectionPolicy.trim()} ${measurementContract.trim()} `; await writeFile(path.join(outputRoot, "methodology.md"), methodology, "utf8"); await writeFile(path.join(outputRoot, "measurement-contract.md"), `${measurementContract.trim()}\n`, "utf8"); await writeFile(path.join(outputRoot, "privacy.md"), `${privacy.trim()}\n`, "utf8"); await writeFile(path.join(outputRoot, "event-contract.txt"), `${eventContract.trim()}\n`, "utf8"); await writeFile(path.join(outputRoot, "launch-checklist.txt"), `${launchChecklist.trim()}\n`, "utf8"); const sourceSections = []; for (const file of sourceFiles) { const content = await readFile(path.join(projectRoot, file.path), "utf8"); const destination = path.join(sourceRoot, file.path); await mkdir(path.dirname(destination), { recursive: true }); await writeFile(destination, content, "utf8"); sourceSections.push(`## ${file.path}\n\n${file.description}\n\n${fencedCode(file.language, content)}`); } const sourceIndex = `# Developer Journey Atlas deployed source\n\nThe active product UI is \`packages/journey-corpus/web\`. Generated public files are machine artifacts only.\n\n${sourceFiles.map((file) => `- [${file.path}](${sourceUrl(file.path)}): ${file.description}`).join("\n")}\n`; await writeFile(path.join(sourceRoot, "index.md"), sourceIndex, "utf8"); const recordLinks = records .map((record) => `- [${record.name}](${record.platformUrl}): ${record.outcome}`) .join("\n"); const llmCatalogSections = llmCohorts .map((cohort) => `### ${cohort.label}\n\n${cohort.providers.map((provider) => ( provider.routeStatus === "published" && provider.routeUrl ? `- [${provider.name}](${provider.routeUrl}): reviewed route published` : `- ${provider.name}: route review in progress` )).join("\n")}`) .join("\n\n"); const llmsIndex = `# Developer Journey Atlas > Publication-eligible, first-party documented routes from account creation to first success. The reviewed repository contains ${summary.reviewedCorpusRecords} records. ${summary.publicRoutes} currently passes every publication gate. Other records and database research drafts are not public routes. Documentation structure is not observed difficulty, conversion, abandonment, or causality. Model-selected blocker reasons and cross-platform associations are unavailable. Search covers the whole reviewed corpus. Published route pages show atomic steps, documented fields, friction gates, official evidence, and documented structural complexity. Compatible-domain comparison appears only when enough qualified peers exist. ## LLM API research catalog LLM APIs are one cohort inside the Atlas. The LLM cohort file tracks ${llmApiCatalog.providerCount} providers. Catalog membership means a research record exists. It does not mean a route or comparison has passed independent review. ${llmCatalogSections} ## Public routes ${recordLinks || "- No route currently passes every publication gate."} ## Contracts - [Machine-readable manifest](${canonicalUrl}/data/index.json) - [LLM API research catalog](${canonicalUrl}/data/llm-api-catalog.json) - [Methodology](${canonicalUrl}/methodology.md) - [Measurement contract](${canonicalUrl}/measurement-contract.md) - [Privacy and research data flow](${canonicalUrl}/privacy.md) - [Measurement availability](${canonicalUrl}/event-contract.txt): \`measurement_unavailable\`, with no collector installed. - [Whole-corpus human review gate](${canonicalUrl}/launch-checklist.txt) - [Deployed source](${canonicalUrl}/source/index.md) `; await writeFile(path.join(outputRoot, "llms.txt"), llmsIndex, "utf8"); const publicRecordSections = []; for (const record of records) { const content = `${JSON.stringify(publicRecords.get(record.slug), null, 2)}\n`; publicRecordSections.push(`# ${record.name} public documented record\n\n${fencedCode("json", content)}`); } const llmsFull = `# Developer Journey Atlas full public context Only publication-eligible routes are included. Documented complexity is a count-based route profile. No observed blocker diagnosis, association, or causal claim is available. ${methodology.trim()} ${publicRecordSections.join("\n\n")} # Deployed source ${sourceSections.join("\n\n")} `; await writeFile(path.join(outputRoot, "llms-full.txt"), llmsFull, "utf8"); const sitemapUrls = [ `${canonicalUrl}/`, ...records.map((record) => record.platformUrl), `${canonicalUrl}/llms.txt`, `${canonicalUrl}/llms-full.txt`, `${canonicalUrl}/methodology.md`, `${canonicalUrl}/measurement-contract.md`, `${canonicalUrl}/privacy.md`, `${canonicalUrl}/event-contract.txt`, `${canonicalUrl}/launch-checklist.txt`, `${canonicalUrl}/data/index.json`, `${canonicalUrl}/source/index.md`, ...records.map((record) => record.recordUrl), ]; const sitemap = ` ${sitemapUrls.map((url) => ` ${url}`).join("\n")} `; await writeFile(path.join(outputRoot, "sitemap.xml"), sitemap, "utf8"); console.log( `Built public artifacts for ${summary.publicRoutes} eligible route from ${summary.reviewedCorpusRecords} reviewed records.`, ); ``` ## scripts/check-llm-site.mjs Generated public-surface contract check. ```javascript import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; import Ajv2020 from "ajv/dist/2020.js"; import addFormats from "ajv-formats"; const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const publicRoot = path.join(projectRoot, "public"); const canonicalUrl = "https://developer-journey-atlas.onrender.com"; const requiredFiles = [ "llms.txt", "llms-full.txt", "methodology.md", "measurement-contract.md", "privacy.md", "event-contract.txt", "launch-checklist.txt", "sitemap.xml", "data/index.json", "data/llm-api-catalog.json", "data/coverage-summary.json", "data/record.schema.json", "data/records/render.json", "source/index.md", "source/web/index.html", "source/web/app.js", "source/web/styles.css", "source/src/server.ts", ]; for (const file of requiredFiles) { await readFile(path.join(publicRoot, file), "utf8"); } const manifest = JSON.parse(await readFile(path.join(publicRoot, "data/index.json"), "utf8")); assert.equal(manifest.schemaVersion, 2); assert.equal(manifest.counts.reviewedCorpusRecords, 237); assert.equal(manifest.counts.publicRoutes, 1); assert.equal(manifest.counts.researchDrafts, 0); assert.equal(manifest.counts.verifiedAudits, 0); assert.equal(manifest.counts.publicAssociationsAvailable, false); assert.equal(manifest.records.length, 1); assert.equal(manifest.records[0].slug, "render"); assert.equal(manifest.servingModel.productUi, "packages/journey-corpus/web"); assert.equal(manifest.sourceCode.license, "Apache-2.0"); assert.match(manifest.files.llmApiCatalog, /\/data\/llm-api-catalog\.json$/); const llmCatalog = JSON.parse(await readFile(path.join(publicRoot, "data/llm-api-catalog.json"), "utf8")); const launchCohortPlan = JSON.parse( await readFile(path.join(projectRoot, "trust", "launch-cohort-candidates.json"), "utf8"), ); const llmCohortIds = new Set([ "llm-api-first-response", "managed-llm-inference-first-response", "cloud-llm-platform-first-response", ]); const plannedLlmCohorts = launchCohortPlan.cohorts.filter((cohort) => llmCohortIds.has(cohort.id)); const plannedCountByCohort = new Map( plannedLlmCohorts.map((cohort) => [cohort.id, cohort.participant_slugs.length]), ); const catalogProviders = llmCatalog.cohorts.flatMap((cohort) => cohort.providers); assert.equal(llmCatalog.schemaVersion, 1); assert.equal(llmCatalog.providerCount, catalogProviders.length); assert.equal(llmCatalog.cohorts.length, plannedLlmCohorts.length); for (const cohort of llmCatalog.cohorts) { assert.equal(cohort.providers.length, plannedCountByCohort.get(cohort.id)); } assert.equal( new Set(catalogProviders.map((provider) => provider.slug)).size, llmCatalog.providerCount, ); assert.ok(catalogProviders.every( (provider) => provider.routeStatus === "published" ? provider.routeUrl === `${canonicalUrl}/platform/${provider.slug}` : provider.routeStatus === "review_in_progress" && provider.routeUrl === null, )); assert.ok(catalogProviders.every( (provider) => Array.isArray(provider.searchAliases), )); const providerBySlug = new Map( catalogProviders.map((provider) => [provider.slug, provider]), ); assert.ok(providerBySlug.get("xai-api").searchAliases.includes("Grok")); assert.ok(providerBySlug.get("amazon-bedrock").searchAliases.includes("AWS")); for (const source of manifest.sourceCode.files) { const canonical = await readFile(path.join(projectRoot, source.path), "utf8"); const published = await readFile(path.join(publicRoot, "source", source.path), "utf8"); assert.equal(published, canonical, `${source.path} source snapshot should be byte-for-byte current`); } const publicRecord = JSON.parse(await readFile(path.join(publicRoot, "data/records/render.json"), "utf8")); const recordSchema = JSON.parse(await readFile(path.join(publicRoot, "data/record.schema.json"), "utf8")); const ajv = new Ajv2020({ allErrors: true, strict: false }); addFormats(ajv); const validateRecord = ajv.compile(recordSchema); assert.equal(validateRecord(publicRecord), true, JSON.stringify(validateRecord.errors)); assert.equal(publicRecord.primary_path.length, 16); assert.equal(publicRecord.journey_graph.selectedRoute.nodeIds.length, 16); assert.equal(publicRecord.prerequisites.length, publicRecord.journey_graph.prerequisites.length); assert.equal(publicRecord.friction_gates.length, publicRecord.journey_graph.externalGates.length); assert.equal( publicRecord.branches.length, publicRecord.journey_graph.candidateRoutes.filter((route) => route.status === "considered").length, ); assert.equal( publicRecord.primary_path.flatMap((step) => step.required_fields || []).length, 11, ); const publicNodeIndex = new Map( publicRecord.journey_graph.selectedRoute.nodeIds.map((id, index) => [id, index + 1]), ); for (const [index, gate] of publicRecord.journey_graph.externalGates.entries()) { assert.equal(publicRecord.friction_gates[index].at_step, publicNodeIndex.get(gate.atNodeId)); assert.equal(publicRecord.friction_gates[index].required, gate.required); } assert.equal( publicRecord.friction_gates.some((gate) => /spin down after 15 minutes/i.test(gate.description)), false, ); assert.ok(publicRecord.journey_graph.nodes.some((node) => node.kind === "passive_wait")); assert.ok(publicRecord.journey_graph.nodes.some((node) => node.kind === "platform_outcome")); assert.ok(publicRecord.journey_graph.nodes.some((node) => node.kind === "terminal_outcome")); const serializedPublicData = JSON.stringify({ manifest, publicRecord }); for (const forbidden of [ "onboardingScore", "effortScore", "peerMedian", "blockerHypotheses", "model_selected", "clientIp", ]) { assert.equal(serializedPublicData.includes(forbidden), false, `${forbidden} must not be serialized publicly`); } const app = await readFile(path.join(projectRoot, "web/app.js"), "utf8"); assert.doesNotMatch(app, /renderOnboardingScore|onboardingScore|curvePlacement|score-card|percentile|leaderboard/i); assert.match(app, /Open official guide/); assert.match(app, /Official sources/); assert.match(app, /Domain comparison/); assert.match(app, /Complexity/); assert.match(app, /setNotFoundMetadata/); assert.match(app, /Not mapped yet/); assert.match(app, /Build path from docs/); assert.match(app, /Draft failed validation/); assert.match(app, /Try again/); assert.doesNotMatch(app, /Could not build a reliable path/); assert.match(app, /draft_ready/); assert.match(app, /renderResearchDraft/); assert.doesNotMatch(app, /Research stopped safely|draft did not pass the required record schema/i); assert.match(app, /Start research/); assert.match(app, /Build path from docs/); assert.match(app, /addEventListener\("click", \(\) => researchPlatform\(name\)\)/); const consentBody = app.match(/function renderResearchOffer\(name, slug = "", provider = null\) \{([\s\S]*?)\n\}/)?.[1] ?? ""; assert.doesNotMatch(consentBody, /\n\s*researchPlatform\(name\);/); const html = await readFile(path.join(projectRoot, "web/index.html"), "utf8"); assert.equal((html.match(//)?.[0] ?? ""; assert.doesNotMatch(headerBody, /render\.com\/deploy|deploy a personal copy/i); const llms = await readFile(path.join(publicRoot, "llms.txt"), "utf8"); assert.match(llms, /^# Developer Journey Atlas\n\n> /); assert.match(llms, /1 currently passes every publication gate/); assert.match(llms, /Search covers the whole reviewed corpus/); assert.match(llms, /LLM APIs are one cohort inside the Atlas/); assert.match(llms, /measurement_unavailable/i); const links = [...llms.matchAll(/\[[^\]]+\]\((https:\/\/[^)]+)\)/g)].map((match) => match[1]); for (const url of links.filter((value) => value.startsWith(canonicalUrl))) { const urlPath = new URL(url).pathname.replace(/^\//, ""); if (!urlPath || urlPath.startsWith("platform/")) continue; await readFile(path.join(publicRoot, urlPath), "utf8"); } const sitemap = await readFile(path.join(publicRoot, "sitemap.xml"), "utf8"); assert.match(sitemap, /\/platform\/render/); assert.equal((sitemap.match(/\/platform\//g) || []).length, 1); const fullContext = await readFile(path.join(publicRoot, "llms-full.txt"), "utf8"); assert.match(fullContext, /# Deployed source/); assert.match(fullContext, /function renderResearchOffer/); assert.ok(fullContext.length > 50_000, "full context should contain public methodology, route, and deployed source"); console.log( `Verified ${manifest.records.length} public route, ${manifest.sourceCode.files.length} current source files, and the fail-closed generated contract.`, ); ``` ## PRIVACY.md Research provider, storage, retention, and deletion disclosure. ```markdown # Privacy and research data flow Developer Journey Atlas separates search suggestions from explicit research. ## Search suggestions Typing in search sends the query to the Atlas server so it can match platform names in the corpus and label whether a reviewed route is public. Search terms are not written to Atlas analytics or research claims. ## Explicit research Research starts only after the user chooses **Start research** or **Refresh research**. The platform name is sent to the Atlas server, which can start a Render Workflow. That workflow can use You.com for constrained discovery and direct page retrieval, then OpenRouter for a machine reconstruction. Research results remain private until maintainer review passes platform identity, first-party source authority, retrieved-content, claim-grounding, selected-route, and public-evidence gates. Machine-selected blocker reasons remain internal. ## Stored fields and retention The research-claim store contains the normalized platform slug, platform name, workflow run ID, status, and timestamps. It does not store client IP addresses, credentials, cookies, private page content, full upstream payloads, or model reasoning. Completed and failed claims are deleted after seven days. Stale claiming or pending rows are deleted after 24 hours. The cleanup runs before new database-backed research and is also available through `npm run db:cleanup-research`. ## Deletion and access The maintainer can delete expired claim rows with the cleanup command. Production migrations are applied only by an authorized maintainer. Verification workflow starts and status reads require a server-side administrative secret that is never sent to browser JavaScript. ``` ## EVENT-CONTRACT.txt Uninstrumented privacy-preserving event contract. ```text # Atlas event contract Status: measurement_unavailable No analytics collector, persistence layer, query path, or verified test event is approved or installed. The browser does not emit these events. This contract defines a future privacy review and integration seam without claiming that the share or correction loop is measurable. Event names - platform_view: a publication-eligible route renders. Minimal properties: platform_slug, entry_kind. - share_copy: a durable route URL is copied successfully. Minimal property: platform_slug. - shared_link_open: a recipient opens a durable route with an approved, non-identifying share marker. Minimal property: platform_slug. - second_platform_view: the same approved anonymous session views a second eligible platform. Minimal properties: first_platform_slug, second_platform_slug. - correction_start: the prefilled correction form is opened. Minimal property: platform_slug. Privacy and implementation boundary - Do not include IP address, platform search text, provider payloads, source-page content, email, account IDs, or free-form correction text. - Do not add fingerprinting or a cross-site identifier. - An owner must approve the collector, lawful purpose, retention period, deletion path, anonymous-session design, and query owner before instrumentation. - A verified test event must demonstrate browser emission, persistence, queryability, and deletion before this status can change. - Pilot thresholds belong in LAUNCH-CHECKLIST.txt. They are decision thresholds, not evidence already collected. ``` ## LAUNCH-CHECKLIST.txt Human review and representative-user pilot gate. ```text # Atlas whole-corpus launch checklist Status: human review required Purpose Search any platform in the corpus and show the documented first-mile path from account creation to first developer success. LLM APIs are one cohort inside the corpus, not the product boundary. Per-platform review - Identity resolved to the current official platform and organization. - First-party source set reviewed, current, and sufficient for the selected route. - Starting boundary is account creation unless an explicit comparable exception is approved. - First-success boundary has an official label or observable terminal state. - Atomic selected route includes every required action from account creation through first success. - Account, app, OAuth or credential, scope, redirect URI, request, and verification fields are inventoried when documented. - Decision nodes list documented options, selected option, and effect on the first-success route. - External gates, unavoidable waits, automatic platform outcomes, and recovery states are attached to the exact route node. - Every prerequisite, node, field, option, edge, gate, branch, wait, and first-success claim has accepted source evidence. - Documented structural complexity profile is generated from the verified route. - Compatible-domain comparison is shown only after at least three qualified peers pass the same gates. - Potential friction is labeled as documented or potential, never as observed drop-off without behavioral evidence. - Durable direct link verified in the deployed environment. - Correction path opens with platform context, without automatic submission. - Publication decision recorded. Current state - Corpus records: 237. - Public routes: 1. - Qualified comparison cohorts: 0. - Routes with at least three qualified peers: 0. - Render is the only currently public route. - Remaining corpus records stay searchable as known platforms but non-public until the review gates above pass. Required pilot evidence - At least 20 representative people complete the route-understanding flow. - At least 5 people copy a platform share link. - At least 3 recipients open a shared link and view a second platform. - At least 2 useful corrections are started. - Route-accuracy and user-value protocols in `evaluation/product-validation-protocols.json` pass their predeclared thresholds. Local implementation does not satisfy human review, production deployment, or pilot validation by itself. ``` ## package.json Supported build, audit, evaluation, and test commands. ```json { "name": "developer-journey-atlas-corpus", "version": "1.0.0", "description": "Source-grounded developer onboarding journeys with an interactive research and comparison wrapper.", "type": "module", "private": true, "engines": { "node": "22.22.0" }, "scripts": { "validate": "node validate-records.mjs", "verify": "node verify.mjs", "build": "node build-all.mjs", "check": "node build-all.mjs --check", "trust:health": "node scripts/build-corpus-health.mjs", "trust:health:check": "node scripts/build-corpus-health.mjs --check", "review:corpus": "node scripts/review-corpus.mjs", "evaluation:build": "node scripts/build-validation-foundations.mjs", "reason:lab": "node scripts/reason-lab.mjs", "test": "node --test tests/regression.mjs tests/shortest-path-audit.test.mjs tests/review-operations.test.mjs", "site": "npm run trust:health && node scripts/build-site.mjs && node scripts/check-llm-site.mjs", "site:check": "node scripts/check-llm-site.mjs", "build:data": "npm run audit:paths:check && npm run trust:health && npm run evaluation:build && node build-catalog.mjs && node scripts/copy-blocker-catalog.mjs && node scripts/build-site.mjs && node scripts/check-llm-site.mjs", "audit:paths": "node scripts/validate-shortest-path-audits.mjs", "audit:paths:check": "node scripts/validate-shortest-path-audits.mjs --check", "build:app": "tsc -p tsconfig.json", "build:render": "npm ci --include=dev && npm run build:data && npm run build:app", "prisma:generate": "prisma generate", "db:migrate": "prisma migrate deploy", "db:seed": "node dist/db/seed.js", "db:cleanup-research": "node dist/db/cleanupResearchClaimsCli.js", "db:link-blockers": "node dist/db/linkBlockers.js", "db:setup": "prisma migrate deploy && npm run db:seed", "prebuild:app": "prisma generate", "start": "node dist/server.js", "start:workflows": "node dist/workflows/research.js", "dev": "npm run build:app && node dist/server.js", "dev:workflows": "npm run build:app && node dist/workflows/research.js", "test:app": "npm run build:app && node --test tests/app/*.test.mjs" }, "dependencies": { "@prisma/client": "6.19.3", "@renderinc/sdk": "0.6.0", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "express": "^5.1.0", "prisma": "6.19.3" }, "devDependencies": { "@types/express": "^5.0.0", "@types/node": "^24.0.0", "typescript": "^5.7.0" }, "license": "Apache-2.0" } ```