create-ailk 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -8
- package/component-catalog.json +12248 -0
- package/component-catalog.md +193 -68
- package/dist/cli.js +29 -1
- package/dist/derive-architecture.js +5 -2
- package/dist/lib/api-boot-assertion.d.ts +46 -0
- package/dist/lib/api-boot-assertion.js +70 -0
- package/dist/lib/extract-module-bundle.d.ts +50 -2
- package/dist/lib/extract-module-bundle.js +223 -15
- package/dist/lib/fetch-guard.d.ts +28 -0
- package/dist/lib/fetch-guard.js +101 -0
- package/dist/lib/fetch-module.js +4 -0
- package/dist/lib/fetch-template.js +4 -0
- package/dist/lib/import-graph.d.ts +29 -0
- package/dist/lib/import-graph.js +140 -0
- package/dist/module-architecture.d.ts +60 -8
- package/dist/module-architecture.js +587 -242
- package/dist/parse-args.js +6 -2
- package/dist/programmatic.d.ts +10 -0
- package/dist/programmatic.js +134 -19
- package/dist/site-chrome.d.ts +80 -0
- package/dist/site-chrome.js +135 -0
- package/dist/surfaces.d.ts +21 -6
- package/dist/surfaces.js +209 -36
- package/dist/template-manifest.d.ts +88 -3
- package/dist/template-manifest.js +281 -29
- package/dist/template-names.d.ts +1 -1
- package/dist/template-names.js +2 -0
- package/package.json +10 -2
- package/site-templates/_base/ailk-template.json +6 -0
- package/site-templates/_base/content/en/Pricing/pricing.mdx +169 -0
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.json +351 -0
- package/site-templates/marketing-site/TEMPLATE-MANIFEST.md +400 -0
- package/site-templates/marketing-site/ailk-template.json +11 -0
- package/site-templates/marketing-site/content/en/blog/05-this-vc-morning-routine-will-make-you-super-annoying.mdx +36 -0
- package/site-templates/marketing-site/provenance.json +4 -0
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.json +288 -0
- package/site-templates/marketing-site-free/TEMPLATE-MANIFEST.md +286 -0
- package/site-templates/marketing-site-free/ailk-template.json +2 -1
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.json +279 -0
- package/site-templates/minimalism-site/TEMPLATE-MANIFEST.md +336 -0
- package/site-templates/minimalism-site/ailk-template.json +22 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-1.svg +7 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-2.svg +7 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-3.svg +7 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-4.svg +7 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-5.svg +7 -0
- package/site-templates/minimalism-site/assets/avatar-placeholder-6.svg +7 -0
- package/site-templates/minimalism-site/assets/hero-backdrop.svg +17 -0
- package/site-templates/minimalism-site/assets/logo-placeholder-1.svg +6 -0
- package/site-templates/minimalism-site/assets/logo-placeholder-2.svg +6 -0
- package/site-templates/minimalism-site/assets/logo-placeholder-3.svg +6 -0
- package/site-templates/minimalism-site/assets/wordmark-placeholder.svg +28 -0
- package/site-templates/minimalism-site/content/en/AboutPage/about.mdx +110 -0
- package/site-templates/minimalism-site/content/en/ContactPage/contact.mdx +68 -0
- package/site-templates/minimalism-site/content/en/FAQPage/faq.mdx +57 -0
- package/site-templates/minimalism-site/content/en/HomePage/home.mdx +244 -0
- package/site-templates/minimalism-site/content/en/LandingPage/referral.mdx +77 -0
- package/site-templates/minimalism-site/content/en/LandingPage/reports.mdx +73 -0
- package/site-templates/minimalism-site/content/en/ReportPage/annual-letter-2024.mdx +52 -0
- package/site-templates/minimalism-site/content/en/ReportPage/field-notes-2023.mdx +52 -0
- package/site-templates/minimalism-site/content/en/ReportPage/platform-shift-2025.mdx +52 -0
- package/site-templates/minimalism-site/content/en/ReportPage/state-of-the-market-2026.mdx +52 -0
- package/site-templates/minimalism-site/content/en/Service/first-engagement.mdx +38 -0
- package/site-templates/minimalism-site/content/en/Service/second-engagement.mdx +38 -0
- package/site-templates/minimalism-site/content/en/Service/third-engagement.mdx +38 -0
- package/site-templates/minimalism-site/content/en/ServicesList/services.mdx +73 -0
- package/site-templates/minimalism-site/flows/referral.flow.json +71 -0
- package/site-templates/minimalism-site/provenance.json +4 -0
- package/site-templates/saas-product/TEMPLATE-MANIFEST.md +61 -0
- package/site-templates/saas-product/ailk-template.json +16 -0
- package/site-templates/saas-product/provenance.json +10 -0
- package/site-templates/simple-service/TEMPLATE-MANIFEST.json +240 -0
- package/site-templates/simple-service/TEMPLATE-MANIFEST.md +278 -0
- package/site-templates/simple-service/ailk-template.json +10 -0
- package/site-templates/simple-service/content/en/AboutPage/about.mdx +38 -0
- package/site-templates/simple-service/content/en/ContactPage/contact.mdx +67 -0
- package/site-templates/simple-service/content/en/FAQPage/faq.mdx +56 -0
- package/site-templates/simple-service/content/en/HomePage/home.mdx +85 -0
- package/site-templates/simple-service/content/en/Service/landscape-design.mdx +40 -0
- package/site-templates/simple-service/content/en/Service/lawn-maintenance.mdx +40 -0
- package/site-templates/simple-service/content/en/Service/seasonal-cleanup.mdx +40 -0
- package/site-templates/simple-service/content/en/ServicesList/services.mdx +72 -0
- package/site-templates/simple-service/provenance.json +4 -0
- package/templates/.claude/skills/README.md +16 -25
- package/templates/.env.example +102 -12
- package/templates/.github/workflows/ci.yml +48 -0
- package/templates/README.md +3 -1
- package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-31.552Z-fallback-1789916251590-037e9005.json +8 -0
- package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.840Z-fallback-1789916253842-b52659e9.json +12 -0
- package/templates/apps/api/.ailk/inbox/2026-09-20T14-57-33.844Z-fallback-1789916253845-6b266f8c.json +12 -0
- package/templates/apps/api/.env.example +13 -0
- package/templates/apps/api/CLAUDE.md +29 -2
- package/templates/apps/api/eslint.config.mjs +69 -0
- package/templates/apps/api/jest.config.cjs +3 -0
- package/templates/apps/api/package.json +7 -2
- package/templates/apps/api/src/__tests__/commerce-claim-registration.test.ts +407 -0
- package/templates/apps/api/src/__tests__/module-exclusion.test.ts +89 -9
- package/templates/apps/api/src/__tests__/review-surface-registration.test.ts +167 -0
- package/templates/apps/api/src/__tests__/server.test.ts +471 -0
- package/templates/apps/api/src/__tests__/vercel-handler.test.ts +45 -0
- package/templates/apps/api/src/__tests__/workspace-module-registration.test.ts +10 -1
- package/templates/apps/api/src/config/index.ts +62 -0
- package/templates/apps/api/src/config/modules.ts +7 -3
- package/templates/apps/api/src/lib/__mocks__/prisma.ts +241 -2
- package/templates/apps/api/src/lib/__tests__/auth-email-budget.test.ts +143 -0
- package/templates/apps/api/src/lib/__tests__/content-adapter.test.ts +23 -0
- package/templates/apps/api/src/lib/__tests__/deliverable-asset-store.test.ts +125 -0
- package/templates/apps/api/src/lib/__tests__/error-serializer.test.ts +20 -0
- package/templates/apps/api/src/lib/__tests__/require-commerce-claim.test.ts +317 -0
- package/templates/apps/api/src/lib/__tests__/site.test.ts +238 -0
- package/templates/apps/api/src/lib/__tests__/stripe.test.ts +75 -0
- package/templates/apps/api/src/lib/auth-email-budget.ts +160 -0
- package/templates/apps/api/src/lib/content-adapter.ts +57 -31
- package/templates/apps/api/src/lib/deliverable-asset-store.ts +76 -0
- package/templates/apps/api/src/lib/error-serializer.ts +23 -3
- package/templates/apps/api/src/lib/outbound-http.ts +7 -2
- package/templates/apps/api/src/lib/require-commerce-claim.ts +250 -0
- package/templates/apps/api/src/lib/site.ts +208 -9
- package/templates/apps/api/src/lib/stripe.ts +66 -0
- package/templates/apps/api/src/middleware/__tests__/default-tenant.test.ts +521 -0
- package/templates/apps/api/src/middleware/__tests__/rate-limit.test.ts +150 -0
- package/templates/apps/api/src/middleware/default-tenant.ts +136 -0
- package/templates/apps/api/src/middleware/rate-limit.ts +7 -1
- package/templates/apps/api/src/openapi/spec.ts +543 -2
- package/templates/apps/api/src/routes/auth/__tests__/auth-user.functional.test.ts +48 -0
- package/templates/apps/api/src/routes/auth/__tests__/transactional-email.test.ts +309 -0
- package/templates/apps/api/src/routes/auth/__tests__/user.test.ts +123 -0
- package/templates/apps/api/src/routes/auth/transactional-email.ts +273 -0
- package/templates/apps/api/src/routes/auth/user.ts +61 -0
- package/templates/apps/api/src/routes/checkout/__tests__/session.test.ts +434 -0
- package/templates/apps/api/src/routes/checkout/__tests__/sessions.test.ts +888 -0
- package/templates/apps/api/src/routes/checkout/index.ts +34 -0
- package/templates/apps/api/src/routes/checkout/session.ts +139 -0
- package/templates/apps/api/src/routes/checkout/sessions.ts +197 -0
- package/templates/apps/api/src/routes/content/__tests__/get-page.test.ts +554 -0
- package/templates/apps/api/src/routes/content/__tests__/list-pages.test.ts +108 -0
- package/templates/apps/api/src/routes/content/__tests__/search.test.ts +450 -0
- package/templates/apps/api/src/routes/content/get-page.ts +94 -12
- package/templates/apps/api/src/routes/content/index.ts +13 -73
- package/templates/apps/api/src/routes/content/list-pages.ts +15 -3
- package/templates/apps/api/src/routes/content/rate-limit.ts +15 -6
- package/templates/apps/api/src/routes/content/search.ts +129 -0
- package/templates/apps/api/src/routes/leads/__tests__/index.test.ts +447 -31
- package/templates/apps/api/src/routes/leads/__tests__/list.test.ts +171 -0
- package/templates/apps/api/src/routes/leads/index.ts +100 -13
- package/templates/apps/api/src/routes/leads/list.ts +104 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/configured-application.test.ts +51 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/drafts.test.ts +351 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/founder-identity.test.ts +51 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/me.test.ts +5 -2
- package/templates/apps/api/src/routes/project-listings/__tests__/public.test.ts +4 -1
- package/templates/apps/api/src/routes/project-listings/__tests__/resume-email.test.ts +58 -0
- package/templates/apps/api/src/routes/project-listings/__tests__/site-answers.test.ts +107 -6
- package/templates/apps/api/src/routes/project-listings/__tests__/site-key.test.ts +87 -2
- package/templates/apps/api/src/routes/project-listings/__tests__/structured-address.test.ts +51 -0
- package/templates/apps/api/src/routes/project-listings/start.ts +5 -1
- package/templates/apps/api/src/routes/requests/__tests__/confirm.test.ts +686 -0
- package/templates/apps/api/src/routes/requests/confirm.ts +601 -0
- package/templates/apps/api/src/routes/requests/index.ts +54 -0
- package/templates/apps/api/src/routes/webhooks/README.md +265 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-dunning.test.ts +749 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-flow-checkout.test.ts +330 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-idempotency.test.ts +262 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-org-billing.test.ts +285 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-rate-limit.test.ts +213 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe-request-paid.test.ts +301 -0
- package/templates/apps/api/src/routes/webhooks/__tests__/stripe.test.ts +648 -0
- package/templates/apps/api/src/routes/webhooks/index.ts +89 -0
- package/templates/apps/api/src/routes/webhooks/stripe.ts +1399 -0
- package/templates/apps/api/src/server.ts +521 -55
- package/templates/apps/api/src/services/__tests__/abandon-email.test.ts +39 -0
- package/templates/apps/api/src/services/__tests__/aeo-score.test.ts +217 -40
- package/templates/apps/api/src/services/__tests__/audit-log.test.ts +620 -0
- package/templates/apps/api/src/services/__tests__/consent.test.ts +2 -0
- package/templates/apps/api/src/services/__tests__/deliverable-fulfillment.test.ts +300 -5
- package/templates/apps/api/src/services/__tests__/deliverable-resend.test.ts +20 -0
- package/templates/apps/api/src/services/__tests__/dunning-policy.test.ts +368 -0
- package/templates/apps/api/src/services/__tests__/lead-promotion.test.ts +408 -0
- package/templates/apps/api/src/services/__tests__/lead-routing.test.ts +160 -0
- package/templates/apps/api/src/services/__tests__/leads-inbox.test.ts +329 -0
- package/templates/apps/api/src/services/__tests__/listing-config.test.ts +166 -0
- package/templates/apps/api/src/services/__tests__/project-listings.fence.test.ts +154 -0
- package/templates/apps/api/src/services/__tests__/public-site-resolver.test.ts +137 -0
- package/templates/apps/api/src/services/__tests__/request-confirm.test.ts +444 -0
- package/templates/apps/api/src/services/__tests__/revalidation.test.ts +238 -0
- package/templates/apps/api/src/services/__tests__/verified-email.test.ts +78 -0
- package/templates/apps/api/src/services/abandon-email.ts +8 -2
- package/templates/apps/api/src/services/aeo-score.ts +49 -12
- package/templates/apps/api/src/services/audit-log.ts +668 -0
- package/templates/apps/api/src/services/consent.ts +18 -0
- package/templates/apps/api/src/services/default-tenant.ts +300 -0
- package/templates/apps/api/src/services/deliverable-fulfillment.ts +141 -13
- package/templates/apps/api/src/services/dunning-policy.ts +294 -0
- package/templates/apps/api/src/services/entitlements.ts +80 -0
- package/templates/apps/api/src/services/lead-promotion.ts +160 -0
- package/templates/apps/api/src/services/lead-routing.ts +161 -2
- package/templates/apps/api/src/services/leads-inbox.ts +284 -0
- package/templates/apps/api/src/services/listing-config.ts +27 -9
- package/templates/apps/api/src/services/owner-workspaces.ts +132 -0
- package/templates/apps/api/src/services/project-listings.ts +201 -6
- package/templates/apps/api/src/services/public-site-resolver.ts +106 -0
- package/templates/apps/api/src/services/request-confirm.ts +646 -0
- package/templates/apps/api/src/services/revalidation.ts +173 -0
- package/templates/apps/api/src/services/verified-email.ts +71 -0
- package/templates/apps/api/src/vercel-handler.ts +75 -35
- package/templates/apps/mcp/.env.example +17 -0
- package/templates/apps/mcp/CLAUDE.md +58 -25
- package/templates/apps/mcp/__tests__/aeo-cli-parity.test.ts +6 -0
- package/templates/apps/mcp/__tests__/audit.test.ts +137 -8
- package/templates/apps/mcp/__tests__/catalog-drift.test.ts +79 -36
- package/templates/apps/mcp/__tests__/get_offerings.test.ts +111 -2
- package/templates/apps/mcp/__tests__/get_pricing.test.ts +82 -2
- package/templates/apps/mcp/__tests__/http-transport.test.ts +541 -2
- package/templates/apps/mcp/__tests__/index.test.ts +39 -0
- package/templates/apps/mcp/__tests__/lib/audit-single-page-readiness-scan.test.ts +143 -0
- package/templates/apps/mcp/__tests__/lib/commerce-claim.test.ts +111 -0
- package/templates/apps/mcp/__tests__/lib/content-adapter-parity.test.ts +65 -0
- package/templates/apps/mcp/__tests__/lib/content-adapter.test.ts +188 -0
- package/templates/apps/mcp/__tests__/lib/fail-closed-tools.test.ts +165 -0
- package/templates/apps/mcp/__tests__/lib/public-workspace.test.ts +124 -0
- package/templates/apps/mcp/__tests__/list_pages.test.ts +116 -0
- package/templates/apps/mcp/__tests__/module-exclusion.test.ts +7 -1
- package/templates/apps/mcp/__tests__/parity.test.ts +12 -9
- package/templates/apps/mcp/__tests__/purchase-disabled.test.ts +89 -22
- package/templates/apps/mcp/__tests__/read_content.test.ts +322 -1
- package/templates/apps/mcp/__tests__/search_content.test.ts +105 -2
- package/templates/apps/mcp/__tests__/server.test.ts +67 -14
- package/templates/apps/mcp/__tests__/start_purchase.test.ts +252 -0
- package/templates/apps/mcp/__tests__/tools/{scaffold.test.ts → create_project.test.ts} +23 -23
- package/templates/apps/mcp/__tests__/tools/purchase.test.ts +300 -123
- package/templates/apps/mcp/eslint.config.mjs +69 -0
- package/templates/apps/mcp/jest.config.cjs +13 -0
- package/templates/apps/mcp/package.json +8 -2
- package/templates/apps/mcp/src/abuse/index.ts +159 -24
- package/templates/apps/mcp/src/config/modules.ts +10 -5
- package/templates/apps/mcp/src/http-transport.ts +102 -29
- package/templates/apps/mcp/src/index.ts +73 -11
- package/templates/apps/mcp/src/lib/audit-single-page.ts +90 -3
- package/templates/apps/mcp/src/lib/commerce-claim.ts +94 -0
- package/templates/apps/mcp/src/lib/content-adapter.ts +113 -0
- package/templates/apps/mcp/src/lib/empty-content-adapter.ts +139 -0
- package/templates/apps/mcp/src/lib/prisma.ts +39 -0
- package/templates/apps/mcp/src/lib/public-workspace.ts +133 -0
- package/templates/apps/mcp/src/lib/stripe-tax-signal.ts +59 -0
- package/templates/apps/mcp/src/server.ts +61 -37
- package/templates/apps/mcp/src/tools/audit.ts +26 -2
- package/templates/apps/mcp/src/tools/{scaffold.ts → create_project.ts} +3 -3
- package/templates/apps/mcp/src/tools/get_business_hours.ts +4 -3
- package/templates/apps/mcp/src/tools/get_faq.ts +4 -3
- package/templates/apps/mcp/src/tools/get_locations.ts +5 -3
- package/templates/apps/mcp/src/tools/get_offerings.ts +16 -4
- package/templates/apps/mcp/src/tools/get_pricing.ts +25 -6
- package/templates/apps/mcp/src/tools/get_site_info.ts +4 -3
- package/templates/apps/mcp/src/tools/index.ts +9 -7
- package/templates/apps/mcp/src/tools/list_pages.ts +4 -3
- package/templates/apps/mcp/src/tools/purchase.ts +128 -45
- package/templates/apps/mcp/src/tools/read_content.ts +20 -6
- package/templates/apps/mcp/src/tools/search_content.ts +11 -4
- package/templates/apps/web/.env.example +74 -8
- package/templates/apps/web/CLAUDE.md +46 -0
- package/templates/apps/web/app/.well-known/mcp.json/build-manifest.ts +18 -2
- package/templates/apps/web/app/.well-known/mcp.json/route.ts +11 -3
- package/templates/apps/web/app/[locale]/(auth)/__tests__/auth-pages.test.tsx +282 -0
- package/templates/apps/web/app/[locale]/(auth)/__tests__/password-reset.test.tsx +515 -0
- package/templates/apps/web/app/[locale]/(auth)/forgot-password/forgot-password-card.tsx +89 -0
- package/templates/apps/web/app/[locale]/(auth)/forgot-password/page.tsx +109 -0
- package/templates/apps/web/app/[locale]/(auth)/layout.tsx +92 -0
- package/templates/apps/web/app/[locale]/(auth)/reset-password/page.tsx +135 -0
- package/templates/apps/web/app/[locale]/(auth)/reset-password/reset-password-card.tsx +109 -0
- package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/__tests__/page.test.tsx +48 -2
- package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/page.tsx +20 -6
- package/templates/apps/web/app/[locale]/(auth)/sign-in/sign-in-card.tsx +125 -0
- package/templates/apps/web/app/[locale]/(auth)/sign-up/page.tsx +96 -0
- package/templates/apps/web/app/[locale]/(auth)/sign-up/sign-up-card.tsx +101 -0
- package/templates/apps/web/app/[locale]/(auth)/use-auth-card-flow.ts +102 -0
- package/templates/apps/web/app/[locale]/(auth)/verify-email/page.tsx +87 -0
- package/templates/apps/web/app/[locale]/(authed)/__tests__/gate.test.tsx +20 -10
- package/templates/apps/web/app/[locale]/(authed)/account/__tests__/page.test.tsx +84 -0
- package/templates/apps/web/app/[locale]/(authed)/account/actions.ts +58 -0
- package/templates/apps/web/app/[locale]/(authed)/account/page.tsx +67 -14
- package/templates/apps/web/app/[locale]/(authed)/layout.tsx +19 -2
- package/templates/apps/web/app/[locale]/(authed)/leads/__tests__/page.test.tsx +181 -0
- package/templates/apps/web/app/[locale]/(authed)/leads/components/LeadsTable.tsx +137 -0
- package/templates/apps/web/app/[locale]/(authed)/leads/page.tsx +111 -0
- package/templates/apps/web/app/[locale]/(authed)/sign-in-gate.tsx +1 -1
- package/templates/apps/web/app/[locale]/[slug]/__tests__/page.test.tsx +111 -0
- package/templates/apps/web/app/[locale]/[slug]/page.tsx +65 -0
- package/templates/apps/web/app/[locale]/cancellation/page.tsx +44 -0
- package/templates/apps/web/app/[locale]/flows/[slug]/FlowStepperClient.tsx +1 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.permalink.test.tsx +1 -1
- package/templates/apps/web/app/[locale]/flows/[slug]/__tests__/FlowStepperClient.test.tsx +6 -5
- package/templates/apps/web/app/[locale]/flows/[slug]/flow.actions.ts +1 -1
- package/templates/apps/web/app/[locale]/layout.tsx +308 -65
- package/templates/apps/web/app/[locale]/purchase/__tests__/cancel.test.tsx +162 -0
- package/templates/apps/web/app/[locale]/purchase/__tests__/module-scope.test.ts +68 -0
- package/templates/apps/web/app/[locale]/purchase/__tests__/success.test.tsx +361 -0
- package/templates/apps/web/app/[locale]/purchase/cancel/page.tsx +115 -0
- package/templates/apps/web/app/[locale]/purchase/success/page.tsx +307 -0
- package/templates/apps/web/app/[locale]/returns/page.tsx +44 -0
- package/templates/apps/web/app/[locale]/shipping/page.tsx +44 -0
- package/templates/apps/web/app/api/revalidate/__tests__/route.test.ts +670 -0
- package/templates/apps/web/app/api/revalidate/route.ts +194 -0
- package/templates/apps/web/auth.ts +407 -8
- package/templates/apps/web/components/google-analytics.tsx +18 -1
- package/templates/apps/web/eslint.config.mjs +69 -0
- package/templates/apps/web/jest.config.cjs +15 -19
- package/templates/apps/web/lib/__tests__/auth-email.test.ts +214 -0
- package/templates/apps/web/lib/__tests__/auth-routes.test.ts +74 -0
- package/templates/apps/web/lib/__tests__/meeting-slugs.test.ts +72 -0
- package/templates/apps/web/lib/__tests__/structured-data.test.tsx +50 -6
- package/templates/apps/web/lib/auth-email.ts +318 -0
- package/templates/apps/web/lib/auth-env.ts +85 -0
- package/templates/apps/web/lib/auth-routes.ts +55 -0
- package/templates/apps/web/lib/meeting-slugs.ts +53 -0
- package/templates/apps/web/lib/nav-config.ts +27 -7
- package/templates/apps/web/lib/server-api.ts +1 -1
- package/templates/apps/web/lib/site-chrome.ts +29 -0
- package/templates/apps/web/lib/telemetry-scrub.ts +50 -0
- package/templates/apps/web/messages/en.json +216 -2
- package/templates/apps/web/next.config.mjs +20 -0
- package/templates/apps/web/package.json +8 -3
- package/templates/apps/web/sentry.client.config.ts +131 -0
- package/templates/apps/web/sentry.edge.config.ts +72 -0
- package/templates/apps/web/sentry.server.config.ts +72 -0
- package/templates/apps/web/src/lib/commerce-claim.ts +33 -0
- package/templates/apps/web/src/lib/commerce-sections.ts +61 -0
- package/templates/apps/web/src/lib/routes.ts +13 -18
- package/templates/brand_assets/README.md +24 -0
- package/templates/content/en/AboutPage/about.mdx +160 -15
- package/templates/content/en/CancellationPolicyPage/cancellation.mdx +108 -0
- package/templates/content/en/ContactPage/contact.mdx +90 -13
- package/templates/content/en/FAQPage/faq.mdx +62 -22
- package/templates/content/en/HomePage/home.mdx +244 -20
- package/templates/content/en/LandingPage/blog.mdx +83 -0
- package/templates/content/en/LandingPage/features.mdx +103 -0
- package/templates/content/en/LandingPage/how-it-works.mdx +143 -0
- package/templates/content/en/ReturnsPolicyPage/returns.mdx +108 -0
- package/templates/content/en/ShippingPolicyPage/shipping.mdx +108 -0
- package/templates/database/CHANGELOG.md +149 -0
- package/templates/database/README.md +10 -3
- package/templates/database/__tests__/appointment.db.test.ts +106 -0
- package/templates/database/__tests__/artifact-content-store.db.test.ts +316 -0
- package/templates/database/__tests__/composite-fence.db.test.ts +206 -0
- package/templates/database/__tests__/fence-fan-out.db.test.ts +711 -0
- package/templates/database/__tests__/fixtures/appointment-create-probe.ts +79 -0
- package/templates/database/__tests__/fixtures/project-listing-consent-probe.ts +100 -0
- package/templates/database/__tests__/flow-workspace-key.db.test.ts +263 -0
- package/templates/database/__tests__/prefixed-ids.db.test.ts +85 -9
- package/templates/database/__tests__/project-listing-consent-at.db.test.ts +111 -0
- package/templates/database/__tests__/seed.test.ts +1 -1
- package/templates/database/__tests__/tenancy.test.ts +141 -0
- package/templates/database/config/schema.prisma +79 -2
- package/templates/database/content/schema.prisma +87 -11
- package/templates/database/eslint.config.mjs +69 -0
- package/templates/database/inbox/schema.prisma +452 -9
- package/templates/database/jest.config.cjs +5 -3
- package/templates/database/migrations/20260915120000_project_listing_solution/migration.sql +15 -0
- package/templates/database/migrations/20260916120000_artifact_content_store/migration.sql +158 -0
- package/templates/database/migrations/20260917120000_callback_request_confirm/migration.sql +40 -0
- package/templates/database/migrations/20260918120000_add_appointment/migration.sql +67 -0
- package/templates/database/migrations/20260918120000_asset_metadata_columns/migration.sql +70 -0
- package/templates/database/migrations/20260919120000_flow_workspace_key/migration.sql +181 -0
- package/templates/database/migrations/20260919130000_flow_definition_admin_columns/migration.sql +172 -0
- package/templates/database/migrations/20260919130000_workspace_meetings/migration.sql +41 -0
- package/templates/database/migrations/20260919140000_inbox_workspace_key/migration.sql +185 -0
- package/templates/database/migrations/20260920120000_lead_handled_at/migration.sql +70 -0
- package/templates/database/migrations/20260920130000_lead_workspace_source_index/migration.sql +57 -0
- package/templates/database/migrations/20260921120000_deliverable_grant_workspace_key/migration.sql +68 -0
- package/templates/database/migrations/20260922120000_tenancy_fence/migration.sql +1067 -0
- package/templates/database/migrations/20260923120000_listing_capturing_magnet/migration.sql +210 -0
- package/templates/database/package.json +7 -3
- package/templates/database/seed.ts +1 -1
- package/templates/database/tenancy.ts +86 -1
- package/templates/database/tsconfig.json +1 -0
- package/templates/package.json +1 -14
- package/versions.json +52 -0
- package/site-templates/marketing-site-free/content/en/Pricing/pricing.mdx +0 -103
- package/templates/apps/api/src/routes/content/__tests__/create.test.ts +0 -253
- package/templates/apps/api/src/routes/content/__tests__/delete.test.ts +0 -215
- package/templates/apps/api/src/routes/content/__tests__/update.test.ts +0 -266
- package/templates/apps/api/src/routes/content/create.ts +0 -115
- package/templates/apps/api/src/routes/content/delete.ts +0 -82
- package/templates/apps/api/src/routes/content/update.ts +0 -112
- package/templates/apps/mcp/__tests__/create_page.test.ts +0 -202
- package/templates/apps/mcp/__tests__/delete_page.test.ts +0 -177
- package/templates/apps/mcp/__tests__/update_page.test.ts +0 -196
- package/templates/apps/mcp/src/tools/create_page.ts +0 -96
- package/templates/apps/mcp/src/tools/delete_page.ts +0 -74
- package/templates/apps/mcp/src/tools/update_page.ts +0 -92
- package/templates/apps/web/app/[locale]/sign-in/sign-in-card.tsx +0 -123
- /package/site-templates/{marketing-site-free → _base}/content/en/PrivacyPage/privacy.mdx +0 -0
- /package/site-templates/{marketing-site-free → _base}/content/en/TermsPage/terms.mdx +0 -0
- /package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/__tests__/next-path.test.ts +0 -0
- /package/templates/apps/web/app/[locale]/{sign-in → (auth)/sign-in}/next-path.ts +0 -0
- /package/templates/apps/web/{src/components → components}/SiteNav.tsx +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stripe-tax-signal — reads `commerce.stripe_tax` from project.yaml (#5949 D4).
|
|
3
|
+
*
|
|
4
|
+
* The declaration the audit's `tax-code-when-stripe-tax` rule grades against:
|
|
5
|
+
* "this site's Stripe account has Stripe Tax enabled, so every priced page owes
|
|
6
|
+
* a `stripe.taxCode`". Declarative only — nothing here calls Stripe, and no
|
|
7
|
+
* license claim is read.
|
|
8
|
+
*
|
|
9
|
+
* The actual YAML read + field extraction delegates to `loadCommerceConfig`
|
|
10
|
+
* (`@working-theory/aeo`, exported from the package root since #6012) — this
|
|
11
|
+
* file's own job is the directory PROBE: apps run from their own dirs in
|
|
12
|
+
* dev/build (`apps/mcp/`) but from repo root in some test setups, mirroring
|
|
13
|
+
* `apps/mcp/src/lib/locales.ts`'s own project.yaml probe (the same three
|
|
14
|
+
* candidates it walks; `apps/*` may not import `apps/*`, so a shared probe
|
|
15
|
+
* helper isn't an option either — only the parse/extract logic was the
|
|
16
|
+
* duplicate #6012 removes).
|
|
17
|
+
*
|
|
18
|
+
* NEVER throws. An unreadable, absent, malformed or non-boolean value all
|
|
19
|
+
* resolve to `undefined` — the site declares no Stripe Tax posture, and the
|
|
20
|
+
* rule passes saying so.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { readFileSync } from "node:fs";
|
|
24
|
+
import { dirname, join } from "node:path";
|
|
25
|
+
|
|
26
|
+
import { loadCommerceConfig } from "@working-theory/aeo";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Probe likely locations for project.yaml. Apps run from their own dirs in
|
|
30
|
+
* dev/build (`apps/mcp/`) but from repo root in some test setups — the same
|
|
31
|
+
* three candidates `locales.ts` walks.
|
|
32
|
+
*/
|
|
33
|
+
function resolveProjectYamlPath(cwd: string): string {
|
|
34
|
+
const candidates = [
|
|
35
|
+
join(cwd, "project.yaml"),
|
|
36
|
+
join(cwd, "..", "project.yaml"),
|
|
37
|
+
join(cwd, "..", "..", "project.yaml"),
|
|
38
|
+
];
|
|
39
|
+
for (const candidate of candidates) {
|
|
40
|
+
try {
|
|
41
|
+
readFileSync(candidate, "utf8");
|
|
42
|
+
return candidate;
|
|
43
|
+
} catch {
|
|
44
|
+
// continue
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return candidates[0] ?? join(cwd, "project.yaml");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* `commerce.stripe_tax` at `projectRoot` (default: the process cwd), or
|
|
52
|
+
* `undefined` when the site declares none.
|
|
53
|
+
*/
|
|
54
|
+
export function readStripeTaxSignal(
|
|
55
|
+
projectRoot: string = process.cwd(),
|
|
56
|
+
): boolean | undefined {
|
|
57
|
+
const resolvedPath = resolveProjectYamlPath(projectRoot);
|
|
58
|
+
return loadCommerceConfig(dirname(resolvedPath)).stripeTaxEnabled;
|
|
59
|
+
}
|
|
@@ -13,11 +13,16 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
getMcpToolRegistrations,
|
|
18
|
+
OSS_DISABLED_TOOLS,
|
|
19
|
+
} from "@working-theory/metadata";
|
|
17
20
|
|
|
18
21
|
import { isModuleEnabled } from "./config/modules.js";
|
|
22
|
+
import { mcpCommerceClaim } from "./lib/commerce-claim.js";
|
|
19
23
|
import { ailkAudit } from "./tools/audit.js";
|
|
20
24
|
import { ailkCaptureLead } from "./tools/capture_lead.js";
|
|
25
|
+
import { ailkCreateProject } from "./tools/create_project.js";
|
|
21
26
|
import { ailkGetBusinessHours } from "./tools/get_business_hours.js";
|
|
22
27
|
import { ailkGetFaq } from "./tools/get_faq.js";
|
|
23
28
|
import { ailkGetLocations } from "./tools/get_locations.js";
|
|
@@ -28,7 +33,6 @@ import { ailkListPages } from "./tools/list_pages.js";
|
|
|
28
33
|
import { ailkPurchase } from "./tools/purchase.js";
|
|
29
34
|
import { ailkReadContent } from "./tools/read_content.js";
|
|
30
35
|
import { ailkRequestCallback } from "./tools/request_callback.js";
|
|
31
|
-
import { ailkScaffold } from "./tools/scaffold.js";
|
|
32
36
|
import { ailkSearchContent } from "./tools/search_content.js";
|
|
33
37
|
import { ailkSubscribeNewsletter } from "./tools/subscribe_newsletter.js";
|
|
34
38
|
|
|
@@ -62,7 +66,7 @@ const HANDLERS: Record<string, (input: unknown) => Promise<unknown>> = {
|
|
|
62
66
|
capture_lead: (input) => ailkCaptureLead(input as never),
|
|
63
67
|
subscribe_newsletter: (input) => ailkSubscribeNewsletter(input as never),
|
|
64
68
|
request_callback: (input) => ailkRequestCallback(input as never),
|
|
65
|
-
|
|
69
|
+
create_project: (input) => ailkCreateProject(input as never),
|
|
66
70
|
};
|
|
67
71
|
|
|
68
72
|
type ToolHandler = (input: unknown) => Promise<unknown>;
|
|
@@ -107,14 +111,6 @@ const MODULE_TOOL_ENTRIES: Record<
|
|
|
107
111
|
specifier: "./tools/create_booking.js",
|
|
108
112
|
exportName: "ailkCreateBooking",
|
|
109
113
|
},
|
|
110
|
-
// D14a Stage 1 Unit C (#55): Paid-tier content write surface. Handlers
|
|
111
|
-
// self-gate via requirePaidTier and return canonical error bodies (no throw)
|
|
112
|
-
// for license / validation / conflict / not-found cases — see
|
|
113
|
-
// apps/mcp/src/lib/errors.ts. Catalog entries carry tier: "pro" so agents
|
|
114
|
-
// see the gating before invoking via list_tools.
|
|
115
|
-
create_page: { specifier: "./tools/create_page.js", exportName: "ailkCreatePage" },
|
|
116
|
-
update_page: { specifier: "./tools/update_page.js", exportName: "ailkUpdatePage" },
|
|
117
|
-
delete_page: { specifier: "./tools/delete_page.js", exportName: "ailkDeletePage" },
|
|
118
114
|
// D-48 signal-collectors — the flow engine's MCP twins of GET
|
|
119
115
|
// /v1/flows/:slug and POST /v1/flows/:slug/steps. Anonymous, identity-blind;
|
|
120
116
|
// free-anonymous status is now module-gated rather than unconditional.
|
|
@@ -140,7 +136,10 @@ async function resolveHandler(name: string): Promise<ToolHandler> {
|
|
|
140
136
|
if (!entry) {
|
|
141
137
|
throw new Error(`MCP catalog drift: no handler for tool '${name}'`);
|
|
142
138
|
}
|
|
143
|
-
const mod = (await import(entry.specifier)) as Record<
|
|
139
|
+
const mod = (await import(entry.specifier)) as Record<
|
|
140
|
+
string,
|
|
141
|
+
ToolHandler | undefined
|
|
142
|
+
>;
|
|
144
143
|
const fn = mod[entry.exportName];
|
|
145
144
|
if (!fn) {
|
|
146
145
|
throw new Error(
|
|
@@ -163,47 +162,72 @@ export interface RegisteredToolDescriptor {
|
|
|
163
162
|
|
|
164
163
|
/**
|
|
165
164
|
* Whether a catalog registration entry should register on this build/boot —
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* `
|
|
171
|
-
*
|
|
165
|
+
* three filters:
|
|
166
|
+
*
|
|
167
|
+
* 1. the OSS-disabled filter (static per-name set; empty since #5971);
|
|
168
|
+
* 2. the module-presence filter (S1, #5088): a tool tagged with `module`
|
|
169
|
+
* (e.g. `create_booking` carrying `module: "scheduling"`) registers only
|
|
170
|
+
* when {@link isModuleEnabled} says its module is present, the same way
|
|
171
|
+
* its `apps/api` HTTP route is module-conditional in `server.ts` there —
|
|
172
|
+
* so a tool and its route appear or vanish together, holding API↔MCP
|
|
173
|
+
* parity;
|
|
174
|
+
* 3. the ADD-ON CLAIM filter (#5971): a tool tagged `addon: "commerce"`
|
|
175
|
+
* registers only on a deployment that positively holds the `commerce`
|
|
176
|
+
* licence claim. Deliberately NOT the module filter — D-64/#5796 moved
|
|
177
|
+
* the commerce primitives off module gating precisely so that adding
|
|
178
|
+
* commerce to a live site is a licence change that lands no files on its
|
|
179
|
+
* repo, and "keyless site" / "keyed site" name the LICENCE, not an env
|
|
180
|
+
* allowlist.
|
|
181
|
+
*
|
|
182
|
+
* The claim is the boot-memoised `mcpCommerceClaim()`, so this stays
|
|
183
|
+
* synchronous — see `lib/commerce-claim.ts`.
|
|
172
184
|
*/
|
|
173
|
-
function shouldRegister(reg: {
|
|
185
|
+
function shouldRegister(reg: {
|
|
186
|
+
name: string;
|
|
187
|
+
module?: string;
|
|
188
|
+
addon?: "commerce";
|
|
189
|
+
}): boolean {
|
|
174
190
|
if (OSS_DISABLED_TOOLS.has(reg.name)) return false;
|
|
175
191
|
if (reg.module && !isModuleEnabled(reg.module)) return false;
|
|
192
|
+
if (reg.addon === "commerce" && mcpCommerceClaim() !== "claimed")
|
|
193
|
+
return false;
|
|
176
194
|
return true;
|
|
177
195
|
}
|
|
178
196
|
|
|
197
|
+
/**
|
|
198
|
+
* The {@link McpCatalogOptions} this boot's claims imply — passed to
|
|
199
|
+
* `getMcpToolRegistrations()` so the upstream catalog filter and
|
|
200
|
+
* {@link shouldRegister} agree by construction rather than by coincidence.
|
|
201
|
+
*/
|
|
202
|
+
function catalogOptionsForThisBoot(): { addons: { commerce: boolean } } {
|
|
203
|
+
return { addons: { commerce: mcpCommerceClaim() === "claimed" } };
|
|
204
|
+
}
|
|
205
|
+
|
|
179
206
|
/**
|
|
180
207
|
* Returns the list of tools that {@link createMcpServer} will register, after
|
|
181
|
-
* the OSS catalog filter ({@link OSS_DISABLED_TOOLS})
|
|
182
|
-
* filter are applied. Pure — no server instance
|
|
208
|
+
* the OSS catalog filter ({@link OSS_DISABLED_TOOLS}), the module-presence
|
|
209
|
+
* filter and the add-on claim filter are applied. Pure — no server instance
|
|
210
|
+
* is constructed.
|
|
183
211
|
*
|
|
184
|
-
* Consumed by `apps/mcp/__tests__/purchase-disabled.test.ts
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* re-enable criteria, that test fails RED.
|
|
212
|
+
* Consumed by `apps/mcp/__tests__/purchase-disabled.test.ts`, which drives
|
|
213
|
+
* both halves of the claim matrix: `start_purchase` absent on a keyless boot,
|
|
214
|
+
* present on a claimed one.
|
|
188
215
|
*/
|
|
189
216
|
export function listRegisteredTools(): RegisteredToolDescriptor[] {
|
|
190
|
-
return getMcpToolRegistrations()
|
|
217
|
+
return getMcpToolRegistrations(catalogOptionsForThisBoot())
|
|
191
218
|
.filter(shouldRegister)
|
|
192
219
|
.map((reg) => ({ name: reg.name, description: reg.description }));
|
|
193
220
|
}
|
|
194
221
|
|
|
195
222
|
/**
|
|
196
223
|
* Creates a configured McpServer with all AILK tools registered, less any
|
|
197
|
-
* tool name in {@link OSS_DISABLED_TOOLS}
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* Re-enable criteria for each disabled tool live at
|
|
205
|
-
* `docs/internal/roadmaps/phase-3-readiness.md`. S15a (issue #610) is the
|
|
206
|
-
* source of the disabled-tool filter.
|
|
224
|
+
* tool name in {@link OSS_DISABLED_TOOLS}, less any tool whose `module` is
|
|
225
|
+
* not enabled on this build (S1, #5088), and less any `addon`-tagged tool
|
|
226
|
+
* whose claim this deployment does not hold (#5971) — see
|
|
227
|
+
* {@link shouldRegister}. Every filter is applied defensively here even
|
|
228
|
+
* though the upstream `getMcpToolRegistrations()` already excludes the same
|
|
229
|
+
* entries: a belt-and-braces guard so a regression in the metadata package
|
|
230
|
+
* can't accidentally register something this boot should not serve.
|
|
207
231
|
*/
|
|
208
232
|
export function createMcpServer(): McpServer {
|
|
209
233
|
const server = new McpServer({
|
|
@@ -211,7 +235,7 @@ export function createMcpServer(): McpServer {
|
|
|
211
235
|
version: "0.1.0",
|
|
212
236
|
});
|
|
213
237
|
|
|
214
|
-
for (const reg of getMcpToolRegistrations()) {
|
|
238
|
+
for (const reg of getMcpToolRegistrations(catalogOptionsForThisBoot())) {
|
|
215
239
|
if (!shouldRegister(reg)) {
|
|
216
240
|
continue;
|
|
217
241
|
}
|
|
@@ -26,7 +26,10 @@ import {
|
|
|
26
26
|
entityMarkup,
|
|
27
27
|
faqHowtoIncentive,
|
|
28
28
|
jsonldValidity,
|
|
29
|
+
offerOnPricedPage,
|
|
30
|
+
policiesPresent,
|
|
29
31
|
schemaCoverage,
|
|
32
|
+
taxCodeWhenStripeTax,
|
|
30
33
|
type Rule,
|
|
31
34
|
} from "@working-theory/aeo";
|
|
32
35
|
import {
|
|
@@ -45,8 +48,21 @@ export { auditInputSchema, auditOutputSchema };
|
|
|
45
48
|
export type { AuditInput, AuditOutput };
|
|
46
49
|
|
|
47
50
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
51
|
+
* The MCP audit's rule set. Imported from the @working-theory/aeo public API;
|
|
52
|
+
* must not be re-implemented here.
|
|
53
|
+
*
|
|
54
|
+
* It is NOT identical to `packages/aeo/src/cli/index.ts`'s RULES array, and
|
|
55
|
+
* this comment used to claim it was. The two differ by exactly one member:
|
|
56
|
+
* the CLI carries `schemaCorrectness` (10 rules) and this set does not
|
|
57
|
+
* (9 rules). Everything else — including the two `always-*` example rules —
|
|
58
|
+
* is shared.
|
|
59
|
+
*
|
|
60
|
+
* The cause is mechanical, not a choice: `packages/aeo/src/index.ts` — the
|
|
61
|
+
* package's PUBLIC barrel — does not re-export `schemaCorrectness`, while
|
|
62
|
+
* `rules/index.ts` (the internal barrel the CLI imports from) exports all of
|
|
63
|
+
* them. A rule absent from the public barrel is unreachable from any app.
|
|
64
|
+
* Closing that gap would change this tool's `score` on every page, which is
|
|
65
|
+
* why #5949 left it alone; it is recorded as that spec's residual 1.
|
|
50
66
|
*/
|
|
51
67
|
const RULES: Rule[] = [
|
|
52
68
|
alwaysPasses,
|
|
@@ -55,6 +71,9 @@ const RULES: Rule[] = [
|
|
|
55
71
|
jsonldValidity,
|
|
56
72
|
faqHowtoIncentive,
|
|
57
73
|
entityMarkup,
|
|
74
|
+
policiesPresent,
|
|
75
|
+
offerOnPricedPage,
|
|
76
|
+
taxCodeWhenStripeTax,
|
|
58
77
|
];
|
|
59
78
|
|
|
60
79
|
/**
|
|
@@ -62,10 +81,14 @@ const RULES: Rule[] = [
|
|
|
62
81
|
*
|
|
63
82
|
* Accepts an optional `contentRoot` override for testing. When omitted,
|
|
64
83
|
* resolves the content root relative to cwd (supports ESM runtime).
|
|
84
|
+
*
|
|
85
|
+
* `projectRoot` is the matching seam for the project.yaml the readiness rules'
|
|
86
|
+
* Stripe-Tax signal is read from (#5949 D9); it likewise defaults to cwd.
|
|
65
87
|
*/
|
|
66
88
|
export async function ailkAudit(
|
|
67
89
|
input: AuditInput,
|
|
68
90
|
contentRoot?: string,
|
|
91
|
+
projectRoot?: string,
|
|
69
92
|
): Promise<AuditOutput> {
|
|
70
93
|
auditInputSchema.parse(input);
|
|
71
94
|
|
|
@@ -75,6 +98,7 @@ export async function ailkAudit(
|
|
|
75
98
|
const auditInput = await buildSinglePageAuditInput(
|
|
76
99
|
input as unknown as SinglePageInput,
|
|
77
100
|
contentRoot,
|
|
101
|
+
projectRoot,
|
|
78
102
|
);
|
|
79
103
|
const report = runAudit(auditInput, RULES);
|
|
80
104
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* create_project — creates an AI Launch Kit starter project via create-ailk.
|
|
3
3
|
*
|
|
4
4
|
* Agent-only: no web Server Action equivalent. Scaffolding is an
|
|
5
5
|
* orchestration-layer action that only makes sense for an agent driving a
|
|
@@ -76,7 +76,7 @@ function countFiles(dir: string): number {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
|
-
*
|
|
79
|
+
* ailkCreateProject handler.
|
|
80
80
|
*
|
|
81
81
|
* Spawns the create-ailk CLI binary to scaffold a starter project into
|
|
82
82
|
* targetDir. The binary must be pre-built (`pnpm --filter create-ailk build`).
|
|
@@ -84,7 +84,7 @@ function countFiles(dir: string): number {
|
|
|
84
84
|
* Accepts an optional `cliBin` override for testing (mirrors the contentRoot
|
|
85
85
|
* override pattern in ailkAudit).
|
|
86
86
|
*/
|
|
87
|
-
export async function
|
|
87
|
+
export async function ailkCreateProject(
|
|
88
88
|
input: ScaffoldInput,
|
|
89
89
|
cliBin?: string,
|
|
90
90
|
): Promise<ScaffoldOutput> {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* get_business_hours — returns business hours from LocalBusiness structured data.
|
|
3
3
|
*
|
|
4
|
-
* Pure read:
|
|
4
|
+
* Pure read: resolves its adapter through `getMcpContentAdapter()` — the one
|
|
5
|
+
* resolver seam (#5805, ADR 0011), MDX by default.
|
|
5
6
|
* Resolves a page by slug (default: "home") and extracts LocalBusiness schema.
|
|
6
7
|
* Returns null when the page is not found or has no openingHoursSpecification.
|
|
7
8
|
*
|
|
@@ -16,7 +17,6 @@
|
|
|
16
17
|
|
|
17
18
|
import { join } from "node:path";
|
|
18
19
|
|
|
19
|
-
import { createMdxAdapter } from "@working-theory/content-adapters";
|
|
20
20
|
import {
|
|
21
21
|
getBusinessHoursInputSchema,
|
|
22
22
|
getBusinessHoursOutputSchema,
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
type GetBusinessHoursOutput,
|
|
25
25
|
} from "@working-theory/validation";
|
|
26
26
|
|
|
27
|
+
import { getMcpContentAdapter } from "../lib/content-adapter.js";
|
|
27
28
|
import { resolveLocale } from "../lib/resolve-locale.js";
|
|
28
29
|
|
|
29
30
|
export { getBusinessHoursInputSchema, getBusinessHoursOutputSchema };
|
|
@@ -45,7 +46,7 @@ export async function ailkGetBusinessHours(
|
|
|
45
46
|
|
|
46
47
|
const root = contentRoot ?? join(process.cwd(), "content");
|
|
47
48
|
const locale = resolveLocale(input.locale);
|
|
48
|
-
const adapter =
|
|
49
|
+
const adapter = getMcpContentAdapter({ contentRoot: root, locale });
|
|
49
50
|
|
|
50
51
|
const slug = input.slug ?? DEFAULT_SLUG;
|
|
51
52
|
const data = await adapter.extractStructuredData("LocalBusiness", slug, locale);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* get_faq — returns FAQ question/answer pairs from FAQPage structured data.
|
|
3
3
|
*
|
|
4
|
-
* Pure read:
|
|
4
|
+
* Pure read: resolves its adapter through `getMcpContentAdapter()` — the one
|
|
5
|
+
* resolver seam (#5805, ADR 0011), MDX by default.
|
|
5
6
|
* Resolves a page by slug (default: "faq") and extracts FAQPage schema.
|
|
6
7
|
* Returns null when the page is not found or has no mainEntity questions.
|
|
7
8
|
*
|
|
@@ -16,7 +17,6 @@
|
|
|
16
17
|
|
|
17
18
|
import { join } from "node:path";
|
|
18
19
|
|
|
19
|
-
import { createMdxAdapter } from "@working-theory/content-adapters";
|
|
20
20
|
import {
|
|
21
21
|
getFaqInputSchema,
|
|
22
22
|
getFaqOutputSchema,
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
type GetFaqOutput,
|
|
25
25
|
} from "@working-theory/validation";
|
|
26
26
|
|
|
27
|
+
import { getMcpContentAdapter } from "../lib/content-adapter.js";
|
|
27
28
|
import { resolveLocale } from "../lib/resolve-locale.js";
|
|
28
29
|
|
|
29
30
|
export { getFaqInputSchema, getFaqOutputSchema };
|
|
@@ -45,7 +46,7 @@ export async function ailkGetFaq(
|
|
|
45
46
|
|
|
46
47
|
const root = contentRoot ?? join(process.cwd(), "content");
|
|
47
48
|
const locale = resolveLocale(input.locale);
|
|
48
|
-
const adapter =
|
|
49
|
+
const adapter = getMcpContentAdapter({ contentRoot: root, locale });
|
|
49
50
|
|
|
50
51
|
const slug = input.slug ?? DEFAULT_SLUG;
|
|
51
52
|
const data = await adapter.extractStructuredData("FAQPage", slug, locale);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* get_locations — returns all Place locations from structured data site-wide.
|
|
3
3
|
*
|
|
4
|
-
* Pure read:
|
|
4
|
+
* Pure read: resolves its adapter through `getMcpContentAdapter()` — the one
|
|
5
|
+
* resolver seam (#5805, ADR 0011), MDX by default.
|
|
5
6
|
* Lists all pages of type "Place" and extracts Place schema from each.
|
|
6
7
|
* Returns an empty array when no Place pages exist.
|
|
7
8
|
*
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
|
|
17
18
|
import { join } from "node:path";
|
|
18
19
|
|
|
19
|
-
import {
|
|
20
|
+
import { SCHEMA_ORG_TYPES } from "@working-theory/content-adapters";
|
|
20
21
|
import {
|
|
21
22
|
getLocationsInputSchema,
|
|
22
23
|
getLocationsOutputSchema,
|
|
@@ -24,6 +25,7 @@ import {
|
|
|
24
25
|
type GetLocationsOutput,
|
|
25
26
|
} from "@working-theory/validation";
|
|
26
27
|
|
|
28
|
+
import { getMcpContentAdapter } from "../lib/content-adapter.js";
|
|
27
29
|
import { resolveLocale } from "../lib/resolve-locale.js";
|
|
28
30
|
|
|
29
31
|
export { getLocationsInputSchema, getLocationsOutputSchema };
|
|
@@ -43,7 +45,7 @@ export async function ailkGetLocations(
|
|
|
43
45
|
|
|
44
46
|
const root = contentRoot ?? join(process.cwd(), "content");
|
|
45
47
|
const locale = resolveLocale(input.locale);
|
|
46
|
-
const adapter =
|
|
48
|
+
const adapter = getMcpContentAdapter({ contentRoot: root, locale });
|
|
47
49
|
|
|
48
50
|
// Place is not a page-level SchemaOrgType, so we iterate all types to find
|
|
49
51
|
// pages whose schema field has Place structured data.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* get_offerings — returns Services and/or Products as a unified offerings array.
|
|
3
3
|
*
|
|
4
|
-
* Pure read:
|
|
4
|
+
* Pure read: resolves its adapter through `getMcpContentAdapter()` — the one
|
|
5
|
+
* resolver seam (#5805, ADR 0011), MDX by default.
|
|
5
6
|
* Lists pages of type "Service" and/or "Product" and shapes them into a
|
|
6
7
|
* unified offerings array. Optionally filtered by type.
|
|
7
8
|
*
|
|
@@ -9,14 +10,20 @@
|
|
|
9
10
|
* project's allowlist; invalid or unknown values silently fall back to the
|
|
10
11
|
* default locale (AC-i18n-07). Lists are locale-scoped.
|
|
11
12
|
*
|
|
13
|
+
* The offering fields (#5838) — `provider`, `categories`, `price` and
|
|
14
|
+
* `priceCurrency` — come off the page's own frontmatter, the same shape the
|
|
15
|
+
* listing card renders from. `price` and `priceCurrency` are `null` (never a
|
|
16
|
+
* fabricated zero) for a listing that declares no price, and `categories` is
|
|
17
|
+
* `[]` for one that is untagged.
|
|
18
|
+
*
|
|
12
19
|
* Input: { type?: 'service' | 'product', locale?: string }
|
|
13
|
-
* Output: { offerings: Array<{ name, description, category?, image
|
|
20
|
+
* Output: { offerings: Array<{ name, description, category?, image?, provider, categories, price, priceCurrency }> }
|
|
14
21
|
* Session/scope: none — read-only public content.
|
|
15
22
|
*/
|
|
16
23
|
|
|
17
24
|
import { join } from "node:path";
|
|
18
25
|
|
|
19
|
-
import {
|
|
26
|
+
import { type SchemaOrgType } from "@working-theory/content-adapters";
|
|
20
27
|
import {
|
|
21
28
|
getOfferingsInputSchema,
|
|
22
29
|
getOfferingsOutputSchema,
|
|
@@ -24,6 +31,7 @@ import {
|
|
|
24
31
|
type GetOfferingsOutput,
|
|
25
32
|
} from "@working-theory/validation";
|
|
26
33
|
|
|
34
|
+
import { getMcpContentAdapter } from "../lib/content-adapter.js";
|
|
27
35
|
import { resolveLocale } from "../lib/resolve-locale.js";
|
|
28
36
|
|
|
29
37
|
export { getOfferingsInputSchema, getOfferingsOutputSchema };
|
|
@@ -43,7 +51,7 @@ export async function ailkGetOfferings(
|
|
|
43
51
|
|
|
44
52
|
const root = contentRoot ?? join(process.cwd(), "content");
|
|
45
53
|
const locale = resolveLocale(input.locale);
|
|
46
|
-
const adapter =
|
|
54
|
+
const adapter = getMcpContentAdapter({ contentRoot: root, locale });
|
|
47
55
|
|
|
48
56
|
const typesToFetch: SchemaOrgType[] = [];
|
|
49
57
|
if (!input.type || input.type === "service") typesToFetch.push("Service");
|
|
@@ -60,6 +68,10 @@ export async function ailkGetOfferings(
|
|
|
60
68
|
description: page.description,
|
|
61
69
|
category: page.schema?.["category"] as string | undefined,
|
|
62
70
|
image: page.image,
|
|
71
|
+
provider: page.provider ?? null,
|
|
72
|
+
categories: page.categories ?? [],
|
|
73
|
+
price: page.price ?? null,
|
|
74
|
+
priceCurrency: page.priceCurrency ?? null,
|
|
63
75
|
}));
|
|
64
76
|
|
|
65
77
|
return getOfferingsOutputSchema.parse({ offerings });
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* get_pricing — returns pricing tiers from Offer structured data.
|
|
3
3
|
*
|
|
4
|
-
* Pure read:
|
|
4
|
+
* Pure read: resolves its adapter through `getMcpContentAdapter()` — the one
|
|
5
|
+
* resolver seam (#5805, ADR 0011), MDX by default.
|
|
5
6
|
* Resolves a page by slug (default: "pricing") and extracts Offer schema.
|
|
6
7
|
* Returns null when the page is not found or has no offer data.
|
|
7
8
|
*
|
|
@@ -9,6 +10,12 @@
|
|
|
9
10
|
* project's allowlist; invalid or unknown values silently fall back to the
|
|
10
11
|
* default locale (AC-i18n-07).
|
|
11
12
|
*
|
|
13
|
+
* Fallback (#5838): when the page authors no `offers` in its `schema`, the
|
|
14
|
+
* offering fields on its own frontmatter answer instead — a listing that
|
|
15
|
+
* declares `price` + `priceCurrency` yields one tier named for the page. A
|
|
16
|
+
* listing with neither an authored offer nor a price still returns `null`: no
|
|
17
|
+
* price means no tier, never a fabricated zero.
|
|
18
|
+
*
|
|
12
19
|
* Input: { slug?: string, locale?: string }
|
|
13
20
|
* Output: { tiers: Array<{ name, price, priceCurrency, description? }> } | null
|
|
14
21
|
* Session/scope: none — read-only public content.
|
|
@@ -16,7 +23,6 @@
|
|
|
16
23
|
|
|
17
24
|
import { join } from "node:path";
|
|
18
25
|
|
|
19
|
-
import { createMdxAdapter } from "@working-theory/content-adapters";
|
|
20
26
|
import {
|
|
21
27
|
getPricingInputSchema,
|
|
22
28
|
getPricingOutputSchema,
|
|
@@ -24,6 +30,7 @@ import {
|
|
|
24
30
|
type GetPricingOutput,
|
|
25
31
|
} from "@working-theory/validation";
|
|
26
32
|
|
|
33
|
+
import { getMcpContentAdapter } from "../lib/content-adapter.js";
|
|
27
34
|
import { resolveLocale } from "../lib/resolve-locale.js";
|
|
28
35
|
|
|
29
36
|
export { getPricingInputSchema, getPricingOutputSchema };
|
|
@@ -45,13 +52,12 @@ export async function ailkGetPricing(
|
|
|
45
52
|
|
|
46
53
|
const root = contentRoot ?? join(process.cwd(), "content");
|
|
47
54
|
const locale = resolveLocale(input.locale);
|
|
48
|
-
const adapter =
|
|
55
|
+
const adapter = getMcpContentAdapter({ contentRoot: root, locale });
|
|
49
56
|
|
|
50
57
|
const slug = input.slug ?? DEFAULT_SLUG;
|
|
51
58
|
const data = await adapter.extractStructuredData("Product", slug, locale);
|
|
52
|
-
if (!data) return null;
|
|
53
59
|
|
|
54
|
-
const schema = data as Record<string, unknown>;
|
|
60
|
+
const schema = (data ?? {}) as Record<string, unknown>;
|
|
55
61
|
|
|
56
62
|
// Support both a top-level `offers` array and a single offer object.
|
|
57
63
|
const offersRaw = schema["offers"];
|
|
@@ -61,7 +67,20 @@ export async function ailkGetPricing(
|
|
|
61
67
|
? [offersRaw as Record<string, unknown>]
|
|
62
68
|
: [];
|
|
63
69
|
|
|
64
|
-
if (offersArr.length === 0)
|
|
70
|
+
if (offersArr.length === 0) {
|
|
71
|
+
const page = await adapter.getPageBySlug("Product", slug, locale);
|
|
72
|
+
if (!page || page.price === undefined) return null;
|
|
73
|
+
return getPricingOutputSchema.parse({
|
|
74
|
+
tiers: [
|
|
75
|
+
{
|
|
76
|
+
name: page.title,
|
|
77
|
+
price: page.price,
|
|
78
|
+
priceCurrency: page.priceCurrency ?? "USD",
|
|
79
|
+
...(page.summary !== undefined && { description: page.summary }),
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
});
|
|
83
|
+
}
|
|
65
84
|
|
|
66
85
|
const tiers = offersArr.map((offer) => ({
|
|
67
86
|
name: (offer["name"] as string) ?? "",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* get_site_info — returns structured site identity from the HomePage.
|
|
3
3
|
*
|
|
4
|
-
* Pure read:
|
|
4
|
+
* Pure read: resolves its adapter through `getMcpContentAdapter()` — the one
|
|
5
|
+
* resolver seam (#5805, ADR 0011), MDX by default.
|
|
5
6
|
* Resolves the HomePage by slug (default: "home") and extracts the `schema`
|
|
6
7
|
* frontmatter field. Returns null when the page is not found or has no schema.
|
|
7
8
|
*
|
|
@@ -16,7 +17,6 @@
|
|
|
16
17
|
|
|
17
18
|
import { join } from "node:path";
|
|
18
19
|
|
|
19
|
-
import { createMdxAdapter } from "@working-theory/content-adapters";
|
|
20
20
|
import {
|
|
21
21
|
getSiteInfoInputSchema,
|
|
22
22
|
getSiteInfoOutputSchema,
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
type GetSiteInfoOutput,
|
|
25
25
|
} from "@working-theory/validation";
|
|
26
26
|
|
|
27
|
+
import { getMcpContentAdapter } from "../lib/content-adapter.js";
|
|
27
28
|
import { resolveLocale } from "../lib/resolve-locale.js";
|
|
28
29
|
|
|
29
30
|
export { getSiteInfoInputSchema, getSiteInfoOutputSchema };
|
|
@@ -45,7 +46,7 @@ export async function ailkGetSiteInfo(
|
|
|
45
46
|
|
|
46
47
|
const root = contentRoot ?? join(process.cwd(), "content");
|
|
47
48
|
const locale = resolveLocale(input.locale);
|
|
48
|
-
const adapter =
|
|
49
|
+
const adapter = getMcpContentAdapter({ contentRoot: root, locale });
|
|
49
50
|
|
|
50
51
|
const slug = input.slug ?? DEFAULT_SLUG;
|
|
51
52
|
const data = await adapter.extractStructuredData("HomePage", slug, locale);
|
|
@@ -119,15 +119,17 @@ export {
|
|
|
119
119
|
export {
|
|
120
120
|
scaffoldInputSchema,
|
|
121
121
|
scaffoldOutputSchema,
|
|
122
|
-
|
|
122
|
+
ailkCreateProject,
|
|
123
123
|
type ScaffoldInput,
|
|
124
124
|
type ScaffoldOutput,
|
|
125
|
-
} from "./
|
|
126
|
-
|
|
127
|
-
// The scheduling tools (list_availability, get_event_meta, create_booking)
|
|
128
|
-
// the
|
|
129
|
-
//
|
|
130
|
-
//
|
|
125
|
+
} from "./create_project.js";
|
|
126
|
+
|
|
127
|
+
// The scheduling tools (list_availability, get_event_meta, create_booking)
|
|
128
|
+
// and the signal-collectors flow tools (get_flow, submit_flow_step) are
|
|
129
|
+
// deliberately NOT re-exported here. (The content-write tools that used to sit
|
|
130
|
+
// in this list — create_page, update_page, delete_page — no longer exist at
|
|
131
|
+
// all: #5853 retired them with their HTTP twins.)
|
|
132
|
+
// Both remaining groups are module-conditional slice files
|
|
131
133
|
// (#5182): a re-export from this barrel is a static path into a file the OSS
|
|
132
134
|
// strip removes, which reds the public tree's type-check. They are reached
|
|
133
135
|
// only through `createMcpServer`'s per-module loader in ../server.ts.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* list_pages — returns published content pages, optionally filtered by type.
|
|
3
3
|
*
|
|
4
|
-
* Pure read:
|
|
4
|
+
* Pure read: resolves its adapter through `getMcpContentAdapter()` — the one
|
|
5
|
+
* resolver seam (#5805, ADR 0011), MDX by default.
|
|
5
6
|
* No auth, no side effects, no network. The adapter reads from the filesystem.
|
|
6
7
|
*
|
|
7
8
|
* Phase 3 S3: optional `locale` parameter. Validated against `readLocales()`
|
|
@@ -17,7 +18,6 @@
|
|
|
17
18
|
import { join } from "node:path";
|
|
18
19
|
|
|
19
20
|
import {
|
|
20
|
-
createMdxAdapter,
|
|
21
21
|
SCHEMA_ORG_TYPES,
|
|
22
22
|
type SchemaOrgType,
|
|
23
23
|
} from "@working-theory/content-adapters";
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
type ListPagesOutput,
|
|
29
29
|
} from "@working-theory/validation";
|
|
30
30
|
|
|
31
|
+
import { getMcpContentAdapter } from "../lib/content-adapter.js";
|
|
31
32
|
import { resolveLocale } from "../lib/resolve-locale.js";
|
|
32
33
|
|
|
33
34
|
export { listPagesInputSchema, listPagesOutputSchema };
|
|
@@ -49,7 +50,7 @@ export async function ailkListPages(
|
|
|
49
50
|
// Default: resolve content/ relative to cwd (works in ESM and jest/commonjs).
|
|
50
51
|
const root = contentRoot ?? join(process.cwd(), "content");
|
|
51
52
|
const locale = resolveLocale(input.locale);
|
|
52
|
-
const adapter =
|
|
53
|
+
const adapter = getMcpContentAdapter({ contentRoot: root, locale });
|
|
53
54
|
|
|
54
55
|
const types: readonly SchemaOrgType[] = input.type
|
|
55
56
|
? [input.type]
|