Roadmap phases 1–2: correctness/trust fixes + Tier 1 quick wins + Tier 2/3 quality foundation#234
Roadmap phases 1–2: correctness/trust fixes + Tier 1 quick wins + Tier 2/3 quality foundation#234Marve10s wants to merge 28 commits into
Conversation
…t on failure Install, database-setup and native-build steps no longer swallow errors: they return structured SetupStepResult values that createProject collects, so the CLI reports 'created with N unfinished setup step(s)' plus a recovery hint instead of a false 'created successfully'. A fatal scaffolding error now removes the half-written directory it created (never a pre-existing/merge dir); set BTS_KEEP_FAILED_OUTPUT=1 to keep partial output for debugging.
Previously only 'template'-classified failures set a non-zero exit, so genuine compile/build/typecheck errors whose output did not match a curated TEMPLATE_PATTERN were classified 'unknown' and silently passed CI. The smoke runner now fails on any non-skipped, non-advisory step failure; transient 'environment' failures stay non-gating but are surfaced.
Adds a check-types script to 17 previously-unchecked generated packages (db, auth server, all api servers, native, and react frontends) so the root 'turbo/bun check-types' actually type-checks them, closing the silent type-drift hole that let heroui-native and stripe apiVersion regressions ship. A new meta-test (check-types-coverage.test.ts) enforces that every generated package either defines check-types or is explicitly allowlisted with a reason. Validated via real install + check-types on TypeScript and react-native stacks.
ECOSYSTEM_COUNT was hardcoded to 7 and ECOSYSTEM_NAMES omitted .NET, so the marketing/SEO surface (compare page, llms.txt, SoftwareApplication JSON-LD) under-reported the product as 7 ecosystems. Now derived from the canonical EcosystemSchema via a typed display-name Record, so the count and names can never drift from the schema again.
…ase filename Adds agents-md to the default aiDocs selection (alongside claude-md) so every scaffold ships both CLAUDE.md and AGENTS.md by default — matching create-next-app and the cross-tool AGENTS.md standard read by Codex/Cursor/Copilot/etc. Also fixes the generated filename from non-standard 'Agents.md' to 'AGENTS.md' (matters on case-sensitive filesystems), and syncs the display labels plus the web builder default (DEFAULT_STACK_SELECTION) so CLI/web --yes parity holds.
Wires up the built-but-unrouted ShowcasePage (components/showcase). A server-side loader fetches projects via Convex's lightweight HTTP client so the reactive Convex React SDK stays out of the client entry chunk, and degrades to an empty gallery when Convex is unconfigured/unreachable. Adds /showcase to the sitemap.
Adds a public /analytics route that aggregates the Convex telemetry (getStats + getDailyStats) into the dashboard's data shape and renders the existing prop-driven chart sections (metrics, timeline, stack-configuration, dev-tools). Uses a server-side loader via Convex's HTTP client (no reactive Convex SDK in the client bundle) and degrades to an empty dashboard when Convex is unconfigured; the live event feed is intentionally left for a follow-up. Adds Showcase + Analytics entries to the nav and /analytics to the sitemap.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8e9ef19ce3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| () => ({ | ||
| total: data.totalProjects, | ||
| avgPerDay: data.avgProjectsPerDay, | ||
| lastUpdatedIso: data.lastUpdated ?? "", |
There was a problem hiding this comment.
Provide a valid fallback before rendering empty analytics
When VITE_CONVEX_URL is unset, getStats returns null, or the Convex request is caught, loadAnalytics() returns EMPTY_ANALYTICS_DATA with lastUpdated: null; this line then passes "" as legacy.lastUpdatedIso. AnalyticsHeader formats that value unconditionally with format(new Date(legacy.lastUpdatedIso), ...), which throws on an invalid date, so /analytics crashes instead of degrading to the intended empty dashboard. Use a null-aware legacy date or omit the legacy timestamp when no analytics data exists.
Useful? React with 👍 / 👎.
The smoke preset suite had no react-native preset, so Expo was never install+typechecked by the per-PR strict-smoke matrix (e2e-test.yaml's smoke-strict-core runs --preset pr-core on every PR) — only occasionally via nightly random generation — despite heroui-native drift being a recurring RN bug. Adds a native-uniwind-trpc preset to pr-core; combined with the native check-types added in this branch, every PR now type-checks an Expo frontend. Validated end-to-end through the smoke harness (1/1 pass).
DEFAULT_STACK_SELECTION.aiDocs became ["claude-md","agents-md"] (AGENTS.md default), so the stack-translation default test must compare against that. Uses reversed order to also exercise the array-insensitive comparison.
…teral drift guards (Tier-2) - compatibility-properties.test.ts: fast-check invariants (determinism, changes⟺adjusted, key-set preservation, well-formed issues, YOLO bypass) over the compatibility engine. Deliberately omits idempotence/convergence/constraint-satisfaction (empirically false on the real engine). - schema-template-coverage.test.ts: asserts every non-none enum value is generatable (template dir / hbs conditional / processor ref), with a documented allowlist of the real selectable-but-not-generated gaps (mostly .NET stubs). - api-literal-drift.test.ts: guards the stripe apiVersion literal against the pinned stripe major (fails closed on a major bump).
Diagnoses a scaffolded project: parses bts.jsonc, checks lockfile/node_modules, required env vars (from .env.example), and runs the ecosystem build/type checks (reusing runGeneratedChecks). Supports --skip-checks and --json.
bfs_create_project/bfs_plan_project now accept astroIntegration (fixes a latent bug where MCP-built Astro projects could never pick an integration), aiDocs (agents can request AGENTS.md/cursorrules, defaulting to the canonical ["claude-md","agents-md"]), analytics, effect, and versionChannel; and bfs_create_project takes an optional targetDir parent directory.
createDraft had no dotnet case (returned undefined -> dotnet combos silently skipped) and DEFAULT_ECOSYSTEM_WEIGHTS lacked a dotnet entry. Adds makeDotnetDraft (only generatable .NET values: aspnet-minimal + minimal-api/graphql-hotchocolate/ grpc-dotnet, ef-core, xunit), the switch case, the weight, and dotnet to SUPPORTED_SMOKE_ECOSYSTEMS so nightly random generation covers .NET.
trpc-cli calls process.exit(0) after a handler resolves, which silently overrode doctor's process.exitCode=1 — so `bfs doctor && deploy` proceeded even when the diagnosis failed. Exit synchronously with process.exit(1) on the failure paths instead. Also report `signal X` when check-types is killed by a signal (exitCode null).
…defaults) The AGENTS.md default change missed two spots that still used ["claude-md"]: the programmatic createVirtual API (index.ts) and MCP_COMPATIBILITY_DEFAULTS (mcp.ts). Aligning createVirtual means every scaffold (incl. the snapshot fixtures) now ships AGENTS.md by default — snapshots regenerated accordingly.
The global quoted-substring corpus false-positived dotnet values via the graph-backend display-name map (aspnet-mvc/aspnet-blazor) and a cross-ecosystem SST template (dotnetDeploy:aws), masking the exact selectable-but-not-generated class the guard targets. dotnet categories now match only against dotnet-relevant files; the genuinely-unimplemented .NET values are explicitly allowlisted.
New `github-actions` addon emits .github/workflows/ci.yml — install + lint (when biome/oxlint is selected) + check-types + build — parameterized by package manager (bun/pnpm/npm/yarn) and ecosystem (TS/rust/go/python, with a degrade branch for the rest). Pure file emission via the addon handler's catch-all; no new deps. Wired through schema/option-metadata/compatibility/stack-graph/ stack-translation + the CLI prompt + web option metadata (cli-builder-sync parity).
…stack tools All tools now declare outputSchema/structuredContent (typed results) and annotations (readOnlyHint on the read tools, non-read on create/add) so clients can auto-approve reads and gate writes; bfs_check_compatibility also surfaces evaluateCompatibility issues (code/optionId/suggestions). Adds bfs_list_presets (mern/pern/t3/uniwind with stack summaries) and bfs_recommend_stack (deterministic NL-brief -> compatibility-validated config + rationale + reproducible command; e.g. 'SaaS with payments and auth' -> better-auth + stripe + postgres, matched to pern).
…, and CI for all ecosystems Adversarial-verification fixes for the roadmap work: - bfs_check_compatibility: filter evaluation.issues to the target ecosystem so a clean TS stack no longer reports cross-ecosystem false positives (hasIssues now reflects only relevant categories). - bfs_recommend_stack: gate TS-web fields (frontend/backend/runtime/api) out of the summary for native-backend ecosystems, and add an explicit rationale note that brief keyword analysis is TypeScript-only. - recommendStackFromBrief: treat admin/dashboard/portal/members/rbac/ permissions/roles as auth signals (better-auth). - config-prompts: allow the github-actions addon for non-TS ecosystems (was silently dropped alongside docker-compose). - ci.yml addon: route react-native through the JS package-manager flow instead of the degrade echo; make pnpm/yarn install non-strict to match bun/npm; add real CI jobs for elixir, java (maven+gradle), and dotnet so the addon is useful across all 8 ecosystems.
…necone) New TypeScript-ecosystem option category for AI embeddings / semantic search, modeled on the existing backend-service categories (search/cms/fileStorage). - types: VectorDbSchema + VECTOR_DB_VALUES; wired through option-metadata (TYPESCRIPT_CATEGORY_ORDER only), stack-translation (defaults, url keys, part-role maps, reproducible command), compatibility (convex/firebase/ react-native force-none, standalone-backend requirement, TS-only gate), defaults, stack-graph (legacy single categories + defineTools), and the VectorDb type. - template-generator: server-side lib templates for all four providers under templates/vector-db/<provider>/server/base/src/lib/vector.ts; handler + generator wiring, dependency processor, version pins, preflight rule. - cli: --vector-db flag, interactive prompt (TS + standalone backend only), config-prompts resolver, MCP input schema + field docs, default-config and bts.jsonc round-trip, reproducible-command emission. - web: TECH_OPTIONS + tech-icons + resource links + stack-builder category wiring so the builder exposes the category at parity with the CLI. Each provider is a standalone service (pgvector connects to a dedicated Postgres+pgvector instance via PGVECTOR_DATABASE_URL), so there is no coupling to the project's primary database. Verified: all four generated projects install + type-check clean against their real client SDKs.
- chroma/pinecone aren't on simpleicons (CDN 404 failed validate:tech-icons); ship local /icon/chroma.svg + /icon/pinecone.svg and point the registry + TECH_OPTIONS at them (qdrant/pgvector keep their valid simpleicons slugs). - smoke/e2e presets hung on the new interactive vectorDb prompt because the command builder never emitted the flag; render buildCommand now emits --vector-db (withExplicitScalar → 'none' default) for the TypeScript flag set, mirroring --search.
Inline compatibility fixtures (and any caller) that predate the vectorDb category omit the field entirely. The no-backend service override then saw `undefined !== "none"` and reported defaulting it as a spurious adjustment, breaking 'no change expected' assertions (e.g. Go better-auth stacks). Default a missing vectorDb to 'none' up front so it is never mistaken for an adjustment.
…lers import Smoke-gating template bugs surfaced by the strict smoke gate: - stripe: env server schema never declared STRIPE_SECRET_KEY/STRIPE_WEBHOOK_SECRET (only a polar block existed), and stripe.ts pinned apiVersion '2024-12-18' while stripe@^22 now types it as '2026-05-27.dahlia'. Add the stripe env block, bump the literal, and update the api-literal-drift guard's expected value for major 22. - api package: graphql-yoga/ts-rest/garph contexts import better-auth types directly for any backend, but the dep was only added for express/fastify -> 'Cannot find module better-auth' on e.g. adonisjs. Broaden the condition. - go: cmd/server/main.go imported internal/handlers whenever an ORM was set, but handlers is only generated for gin/echo/fiber/chi web frameworks -> 'package .../internal/handlers is not in std' for web-framework=none. Gate the handlers import on the web framework, decoupled from the database import. Verified: stripe combo (solid+adonisjs+graphql-yoga+better-auth+stripe) and go combo (sqlc+gqlgen+none) both install/tidy + type-check/build clean; gin still imports handlers and builds.
…edis/celery More smoke/e2e gating template bugs: - vinext mode-toggle still used the radix `asChild` API while its dropdown-menu is @base-ui (render prop) like the other react frontends -> web typecheck failure. Switch to render={<Button .../>} to match next/react-vite/etc. - better-auth index.ts always passed `database: env.DATABASE_URL`, but with database=none there is no DATABASE_URL in the env schema (auth typecheck failure, e.g. tanstack-start-fullstack). Gate the database field on database != none so better-auth falls back to its in-memory default. - python pyproject pinned redis>=7.0.0, which is unsatisfiable with celery[redis] (kombu caps redis<6.5) -> uv sync failure. Lower the floor to redis>=5.0.1 so uv resolves 7.x normally and 6.4.x alongside celery. Verified: vinext + tanstack-start type-check clean; python uv sync --all-extras resolves; t3 builds + type-checks clean (its dev-check flake is not a template bug).
Follow-up to the redis/celery pin fix — the RQ task-queue test hard-coded the old redis>=7.0.0 floor.
…auth redis, go handlers import, dev-check timeout Smoke / strict-smoke gating failures on PR #234: - db/redis/base: ioredis zscore returns string|null but zset.score() was declared number|null -> db typecheck failure on *-redis combos. Await and coerce with Number(). - api/garph routers: createResolvers(ctx) only reads ctx when auth=better-auth -> TS6133 unused param when auth=none. Emit _ctx when not better-auth. - api/garph context: context.ts only branched on hono/elysia/express/fastify/fets/adonisjs/self(next|tanstack|astro); nestjs (and self+other frontends) produced an empty file the generator skips -> "Cannot find module '../context'". Add a generic session-only fallback for uncovered backends/frontends. - auth/better-auth: database=redis is a KV store, not a SQL adapter, but the orm=none / kysely / mikroorm blocks still passed `database: env.DATABASE_URL` (string) -> server typecheck failure ('string' not assignable to better-auth database). Exclude redis so better-auth falls back to its in-memory default. - go cmd/server/main.go: internal/handlers was imported for any gin/echo/fiber/chi web framework, but handlers are only referenced when goOrm is gorm/sqlc/ent -> "imported and not used" for orm=none (e.g. echo+grpc-go). Gate the import on web framework AND orm. - testing/dev-check: bump URL-detection (60s->120s) and total (90s->150s) timeouts so heavy Next presets (preset-t3) reliably print their dev URL under CI load. Verified: the four failing TS/Go combos scaffold + install + type-check / build clean; full apps/cli suite (./test/*.test.ts) 3290 pass / 0 fail.
Summary
Roadmap phases 1–2 from the multi-agent codebase analysis (
docs/next-updates-roadmap.md). Large but cohesive: correctness/trust fixes, Tier‑1 quick wins, and the Tier‑2 quality foundation + contained Tier‑3 items. Every change is validated locally (suites + builds) and the Tier‑2/3 work was additionally put through an adversarial verification pass that caught two HIGH issues before merge.Phase 1 — correctness/trust + Tier 1
🔴 Bugs
BTS_KEEP_FAILED_OUTPUT=1to keep).check-typesadded to 17 generated packages + a coverage meta-test (closes the silent type-drift hole).Tier 1
5.
.NETecosystem stat fixed (7→8), derived from the schema. 6.AGENTS.mdgenerated by default (standard uppercase) + label/parity sync. 7./showcaseroute shipped. 8./analyticspopular-stacks dashboard (new aggregation transform) + nav + sitemap. Plus react-native added to the per-PR smoke matrix (pr-core).Phase 2 — Tier 2 quality foundation + Tier 3
dotnetcombo generator case (only generatable .NET values) + enabled inSUPPORTED_SMOKE_ECOSYSTEMS.noneenum value must be generatable or explicitly allowlisted; surfaces the real .NET selectable-but-not-generated gaps. Matching is scoped per-ecosystem so it has genuine teeth.apiVersionvs the pinned stripe major (fails closed on a major bump).bfs doctor— diagnoses a scaffolded project (bts.jsonc, deps, env vars, build/type checks); exits non-zero on failure so it works as a CI gate.astroIntegration(fixes a latent bug where MCP-built Astro projects could never pick an integration),aiDocs,analytics,effect,versionChannel, and an optionaltargetDir.Adversarial verification fixes (found by the verify workflow, not the green suites)
bfs doctoralways exited 0 — trpc-cli'sprocess.exit(0)overrodeprocess.exitCode; now exits synchronously on failure (verified:EXIT:1).aspnet-mvc/aspnet-blazor(via the display-name map) anddotnetDeploy:aws(via the SST template); dotnet matching is now scoped and the genuine gaps are allowlisted.createVirtual+MCP_COMPATIBILITY_DEFAULTSstill shipped onlyCLAUDE.md; completed (snapshots regenerated).types-suite regression from the AGENTS.md default (a hard-coded default in the stack-translation test) — fixed.Validation
packages/types92/0 ·packages/template-generator127/0 · web parity 27/0 · web build ✓ ·testing/tsc 0 errors · CLI/types builds + publint + lint clean.check-typespasses on TS + react-native stacks;bfs doctorexit-code verified on real failing projects; MCP end-to-end smoke confirmed the Astro integration fix flows through; the dotnet combo generation verified SDK-free (CI runs the .NET build).Notes / follow-ups
templates.generated.ts+ dist are gitignored (built in CI); only sources are in the diff./showcase+/analyticsbuild/typecheck and degrade gracefully, but their live data needs the Convex deployment populated +VITE_CONVEX_URL.bfs add,bfs upgrade, vector DB category, golden-path SaaS templates, MCP structured outputs /recommend_stack) are deferred to their own design+validation cycles.