swallowkit 1.0.0-beta.56 β†’ 1.0.0-beta.58

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.
Files changed (40) hide show
  1. package/README.ja.md +1 -0
  2. package/README.md +1 -0
  3. package/dist/cli/commands/init.d.ts.map +1 -1
  4. package/dist/cli/commands/init.js +12 -498
  5. package/dist/cli/commands/init.js.map +1 -1
  6. package/dist/cli/commands/scaffold.d.ts.map +1 -1
  7. package/dist/cli/commands/scaffold.js +8 -6
  8. package/dist/cli/commands/scaffold.js.map +1 -1
  9. package/dist/core/operations/file-session.d.ts +3 -0
  10. package/dist/core/operations/file-session.d.ts.map +1 -1
  11. package/dist/core/operations/file-session.js +8 -0
  12. package/dist/core/operations/file-session.js.map +1 -1
  13. package/dist/core/operations/scaffold-plan.d.ts.map +1 -1
  14. package/dist/core/operations/scaffold-plan.js +1 -9
  15. package/dist/core/operations/scaffold-plan.js.map +1 -1
  16. package/dist/core/project/agent-instructions.d.ts +29 -0
  17. package/dist/core/project/agent-instructions.d.ts.map +1 -0
  18. package/dist/core/project/agent-instructions.js +159 -0
  19. package/dist/core/project/agent-instructions.js.map +1 -0
  20. package/dist/core/scaffold/native-schema-generator.d.ts +7 -1
  21. package/dist/core/scaffold/native-schema-generator.d.ts.map +1 -1
  22. package/dist/core/scaffold/native-schema-generator.js +104 -47
  23. package/dist/core/scaffold/native-schema-generator.js.map +1 -1
  24. package/package.json +1 -1
  25. package/src/__tests__/agent-instructions.test.ts +237 -0
  26. package/src/__tests__/init.test.ts +2 -0
  27. package/src/__tests__/plan-apply.test.ts +167 -0
  28. package/src/__tests__/scaffold.test.ts +2 -2
  29. package/src/cli/commands/init.ts +19 -525
  30. package/src/cli/commands/scaffold.ts +15 -8
  31. package/src/core/operations/file-session.ts +12 -0
  32. package/src/core/operations/scaffold-plan.ts +2 -11
  33. package/src/core/project/agent-instructions.ts +167 -0
  34. package/src/core/project/agent-templates/AGENTS.md +442 -0
  35. package/src/core/project/agent-templates/CLAUDE.md +28 -0
  36. package/src/core/project/agent-templates/azure-functions.instructions.md +22 -0
  37. package/src/core/project/agent-templates/bff-routes.instructions.md +18 -0
  38. package/src/core/project/agent-templates/copilot-instructions.md +24 -0
  39. package/src/core/project/agent-templates/shared-models.instructions.md +35 -0
  40. package/src/core/scaffold/native-schema-generator.ts +152 -70
@@ -18,6 +18,7 @@ import {
18
18
  } from "../../utils/package-manager";
19
19
  import { syncProjectManifest } from "../../core/project/manifest";
20
20
  import { writeWorkflowDocs, writeAgentSkills } from "../../core/project/workflows";
21
+ import { writeAgentInstructionFiles } from "../../core/project/agent-instructions";
21
22
  import {
22
23
  buildCSharpCodegenToolManifestSource,
23
24
  buildPythonCodegenRequirementsSource,
@@ -789,7 +790,7 @@ function runSimple(command: string, args: string[], cwd: string): Promise<void>
789
790
  export function injectSwallowKitNextConfig(nextConfigContent: string, projectName: string): string {
790
791
  return nextConfigContent.replace(
791
792
  /(const\s+nextConfig[:\s]*(?::\s*NextConfig\s*)?=\s*\{)(\s*\/\*[^*]*\*\/)?/,
792
- `$1\n output: 'standalone',\n transpilePackages: ['@${projectName}/shared'],\n serverExternalPackages: ['applicationinsights', 'diagnostic-channel-publishers'],$2`
793
+ `$1\n output: 'standalone',\n agentRules: false, // SwallowKit owns the canonical root AGENTS.md contract\n transpilePackages: ['@${projectName}/shared'],\n serverExternalPackages: ['applicationinsights', 'diagnostic-channel-publishers'],$2`
793
794
  );
794
795
  }
795
796
 
@@ -2105,532 +2106,34 @@ This project was generated by SwallowKit. If you encounter any issues or have su
2105
2106
  console.log('βœ… README.md created\n');
2106
2107
  }
2107
2108
 
2108
- function createAiAgentFiles(projectDir: string, projectName: string, backendLanguage: BackendLanguage, pm: PackageManager) {
2109
+ function createAiAgentFiles(
2110
+ projectDir: string,
2111
+ projectName: string,
2112
+ backendLanguage: BackendLanguage,
2113
+ pm: PackageManager
2114
+ ) {
2109
2115
  console.log('πŸ€– Creating AI agent instruction files...\n');
2110
- const backendLanguageLabel = getBackendLanguageLabel(backendLanguage);
2111
2116
  const runCmd = pm === 'pnpm' ? 'pnpm' : 'npx';
2112
- const projectMcpConfigSource = buildSwallowKitMcpProjectConfigSource(pm);
2113
- const functionsStructureLine = backendLanguage === 'typescript'
2114
- ? `β”‚ └── src/ # HTTP trigger handlers with Cosmos DB bindings`
2115
- : backendLanguage === 'csharp'
2116
- ? `β”‚ β”œβ”€β”€ Crud/ # C# HTTP trigger handlers\nβ”‚ └── generated/ # Native-generated C# schema assets`
2117
- : `β”‚ β”œβ”€β”€ blueprints/ # Python HTTP trigger handlers\nβ”‚ └── generated/ # Native-generated Python schema assets`;
2118
- const backendSchemaNote = backendLanguage === 'typescript'
2119
- ? `- The shared package (\`@${projectName}/shared\`) is consumed by both Next.js and Azure Functions as a workspace dependency.`
2120
- : `- The frontend/BFF source of truth stays in \`shared/models/\` as Zod schemas.\n- \`swallowkit scaffold\` exports OpenAPI into \`functions/openapi/\` and generates ${backendLanguageLabel} schema assets into \`functions/generated/\` with native ${backendLanguageLabel} tooling.`;
2121
- const backendRulesNote = backendLanguage === 'typescript'
2122
- ? `- All CRUD operations and business logic live in \`functions/src/\`.\n- Use Azure Functions Cosmos DB **input/output bindings** (\`extraInputs\`/\`extraOutputs\`) for reads and writes.\n- Use the Cosmos DB SDK client directly **only** for delete operations (bindings do not support delete).\n- Validate all data against Zod schemas before writing to Cosmos DB.\n- The backend auto-generates \`id\` (UUID), \`createdAt\`, and \`updatedAt\` β€” never trust client-sent values for these fields.`
2123
- : `- All business logic lives in \`functions/\` and the generated handlers perform real Cosmos DB CRUD.\n- Keep Zod schemas in \`shared/models/\` as the source of truth.\n- Regenerate backend contracts with \`swallowkit scaffold shared/models/<name>.ts\` whenever a schema changes.\n- Use the native-generated schema assets in \`functions/generated/\` to keep backend contracts aligned.\n- The backend should still own \`id\`, \`createdAt\`, and \`updatedAt\`.`;
2124
-
2125
- // ── 1. AGENTS.md (Codex / generic agents) ──────────────────────────
2126
-
2127
- const agentsMd = `# AGENTS.md
2128
-
2129
- This project was generated by **SwallowKit**.
2130
- All coding agents **must** follow the architecture and conventions described below.
2131
-
2132
- ## Architecture Overview
2133
-
2134
- This is a full-stack application deployed on Azure with a TypeScript frontend/BFF and an Azure Functions backend in ${backendLanguageLabel}.
2135
-
2136
- \`\`\`
2137
- Frontend (React / Next.js App Router)
2138
- ↓ fetch('/api/{model}', ...)
2139
- BFF Layer (Next.js API Routes)
2140
- ↓ HTTP β†’ Azure Functions
2141
- Backend (Azure Functions)
2142
- ↓
2143
- Azure Cosmos DB (Document Database)
2144
- \`\`\`
2145
-
2146
- ### Project Structure
2147
-
2148
- \`\`\`
2149
- ${projectName}/
2150
- β”œβ”€β”€ app/ # Next.js App Router
2151
- β”‚ β”œβ”€β”€ api/ # BFF API routes (proxy to Azure Functions)
2152
- β”‚ └── {model}/ # UI pages per model (list, detail, create, edit)
2153
- β”œβ”€β”€ functions/ # Azure Functions (backend)
2154
- ${functionsStructureLine}
2155
- β”œβ”€β”€ shared/ # Shared workspace package
2156
- β”‚ β”œβ”€β”€ models/ # Zod schema definitions (single source of truth)
2157
- β”‚ └── index.ts # Re-exports all models
2158
- β”œβ”€β”€ lib/
2159
- β”‚ └── api/ # API client utilities (backend.ts, call-function.ts)
2160
- β”œβ”€β”€ components/ # Shared React components
2161
- β”œβ”€β”€ infra/ # Bicep infrastructure-as-code files
2162
- β”‚ β”œβ”€β”€ main.bicep
2163
- β”‚ └── modules/
2164
- β”œβ”€β”€ .mcp.json # Project-scoped MCP bootstrap resolving SwallowKit on each launch
2165
- └── .github/workflows/ # CI/CD workflows (if configured)
2166
- \`\`\`
2167
-
2168
- ## Setup & Everyday Commands
2169
-
2170
- \`\`\`bash
2171
- ${pm} install # install dependencies
2172
- ${runCmd} swallowkit dev # Next.js (3000) + Azure Functions (7071)
2173
- ${pm} run build # production build
2174
- ${pm} run lint # ESLint (generated code must stay error-free)
2175
- ${runCmd} swallowkit verify # structure / drift / typecheck (exit 1 on failure)
2176
- \`\`\`
2177
-
2178
- Run \`${runCmd} swallowkit verify\` (or \`machine verify project\`) before finishing any task.
2179
-
2180
- ## SwallowKit MCP / Machine Workflow
2181
-
2182
- - This repository includes a project-scoped \`.mcp.json\` file that resolves and starts the latest SwallowKit MCP server on each launch. Set \`SWALLOWKIT_MCP_VERSION\` in that file to pin a specific version.
2183
- - Prefer the \`swallowkit_*\` MCP tools for framework-owned inspection, validation, and generation when they are available.
2184
- - If MCP is unavailable in your runtime, fall back to the machine CLI:
2185
- - \`${runCmd} swallowkit machine inspect project\`
2186
- - \`${runCmd} swallowkit machine inspect boundaries\` β€” responsibility boundary contract (which files you may edit freely)
2187
- - \`${runCmd} swallowkit machine validate project\`
2188
- - \`${runCmd} swallowkit machine plan scaffold <name>\` β†’ \`apply scaffold --plan <planId>\` β€” safe two-phase generation
2189
- - \`${runCmd} swallowkit machine verify project\` β†’ \`explain failure\` β€” verification loop
2190
- - Do not hand-edit framework-owned artifacts when the MCP or machine interface can generate or validate them for you.
2191
- - The MCP bootstrap uses ${pm} and requires network access when the selected version is not cached.
2192
- - **Always invoke SwallowKit via \`${runCmd}\`.** Do not mix package manager commands.
2193
-
2194
- ## Autonomous Loop (Plan / Apply / Verify)
2195
-
2196
- Machine commands return a \`status\` terminal state (\`complete\` / \`in-progress\` / \`blocked\` / \`requires-human\` / \`failed\`) and \`nextActions\`. Standard loop:
2197
-
2198
- 1. \`plan scaffold <model>\` β€” compute changes without writing (get \`planId\`)
2199
- 2. \`apply scaffold --plan <planId>\` β€” apply with freshness + approval checks
2200
- 3. \`verify project\` β€” structure / drift / typecheck (and project-specific checks)
2201
- 4. \`explain failure\` β€” evidence and repair actions when verification fails
2202
-
2203
- Step-by-step runbooks live in \`.swallowkit/workflows/\` (agent-agnostic Markdown):
2204
-
2205
- - \`.swallowkit/workflows/add-model.md\`
2206
- - \`.swallowkit/workflows/modify-model.md\`
2207
- - \`.swallowkit/workflows/verify-and-repair.md\`
2208
- - \`.swallowkit/workflows/provision.md\`
2209
-
2210
- The same runbooks are installed as **Agent Skills** ([agentskills.io](https://agentskills.io/) open standard) under \`.github/skills/\`:
2211
-
2212
- | Skill | Use when |
2213
- |-------|----------|
2214
- | \`swallowkit-add-model\` | adding a new model / entity / CRUD feature |
2215
- | \`swallowkit-modify-model\` | changing an existing schema and re-aligning artifacts |
2216
- | \`swallowkit-verify-repair\` | converging to a verified state after any change |
2217
- | \`swallowkit-provision\` | provisioning Azure infrastructure (human approval required) |
2218
-
2219
- Skills-aware agents (GitHub Copilot in VS Code / CLI / cloud agent, and other agents supporting the standard) discover these automatically from their \`name\`/\`description\` and load the body on demand. If your agent does not support skills, read the equivalent runbook in \`.swallowkit/workflows/\` before performing these tasks.
2220
-
2221
- ## Responsibility Boundary (AI Γ— Deterministic Generation)
2222
-
2223
- - **ai-authored (write freely)**: \`shared/models/\`, business logic, custom pages/components, tests.
2224
- - **deterministic (never hand-edit)**: artifacts recorded in \`.swallowkit/artifacts.json\` with \`managed\` ownership, and \`.swallowkit/\` metadata. Change the model/config and regenerate via plan/apply instead.
2225
- - **shared (edit outside markers)**: \`infra/main.bicep\`, \`functions/function_app.py\`, \`shared/index.ts\`.
2226
- - Full machine-readable contract: \`${runCmd} swallowkit machine inspect boundaries\`
2227
-
2228
- ## Critical Design Principles
2229
-
2230
- ### 1. Next.js API Routes Are Strictly a BFF (Backend for Frontend)
2231
-
2232
- - \`app/api/\` routes exist **only** to proxy requests to Azure Functions.
2233
- - **Never** place business logic, database access, or direct Cosmos DB calls in Next.js API routes.
2234
- - The BFF layer may validate input/output with Zod schemas before forwarding to Functions.
2235
- - Use the \`callFunction\` helper (\`lib/api/call-function.ts\`) or the \`api\` client (\`lib/api/backend.ts\`) to call Azure Functions.
2236
-
2237
- Example BFF route pattern:
2238
-
2239
- \`\`\`typescript
2240
- // app/api/{model}/route.ts
2241
- import { callFunction } from '@/lib/api/call-function';
2242
- import { ModelSchema } from '@${projectName}/shared';
2243
- import { z } from 'zod/v4';
2244
-
2245
- export async function GET() {
2246
- return callFunction({
2247
- method: 'GET',
2248
- path: '/api/{model}',
2249
- responseSchema: z.array(ModelSchema),
2250
- });
2251
- }
2252
-
2253
- export async function POST(request: NextRequest) {
2254
- const body = await request.json();
2255
- return callFunction({
2256
- method: 'POST',
2257
- path: '/api/{model}',
2258
- body,
2259
- inputSchema: ModelSchema.omit({ id: true, createdAt: true, updatedAt: true }),
2260
- responseSchema: ModelSchema,
2261
- successStatus: 201,
2262
- });
2263
- }
2264
- \`\`\`
2265
-
2266
- ### 2. Zod Schemas Are the Single Source of Truth
2267
-
2268
- - All data models are defined **once** as Zod schemas in \`shared/models/\`.
2269
- - TypeScript types are derived with \`z.infer<typeof Schema>\` β€” never define types separately.
2270
- - ${backendSchemaNote}
2271
-
2272
- Model definition pattern:
2273
-
2274
- \`\`\`typescript
2275
- // shared/models/{model}.ts
2276
- import { z } from 'zod/v4';
2277
-
2278
- export const Todo = z.object({
2279
- id: z.string(),
2280
- name: z.string().min(1),
2281
- // ... your fields
2282
- createdAt: z.string().optional(),
2283
- updatedAt: z.string().optional(),
2284
- });
2285
-
2286
- export type Todo = z.infer<typeof Todo>;
2287
- export const displayName = 'Todo';
2288
- \`\`\`
2289
-
2290
- Key rules:
2291
- - Use the **Zod official pattern**: the schema constant and the TypeScript type share the same name.
2292
- - \`id\`, \`createdAt\`, and \`updatedAt\` are auto-managed by the backend. Mark them as \`optional()\` in the schema.
2293
- - Always re-export models from \`shared/index.ts\`.
2294
-
2295
- ### 3. Azure Functions Own All Business Logic and Data Access
2296
-
2297
- - ${backendRulesNote}
2298
-
2299
- ${backendLanguage === 'typescript' ? 'Azure Functions handler pattern:' : `Generated ${backendLanguageLabel} handlers live under \`functions/\`. Re-run \`swallowkit scaffold shared/models/<name>.ts\` after schema changes to keep generated CRUD handlers and the native schema assets under \`functions/generated/\` in sync.`}
2300
-
2301
- ${backendLanguage === 'typescript' ? `\`\`\`typescript
2302
- // functions/src/{model}.ts
2303
- import { app } from '@azure/functions';
2304
- import { ModelSchema } from '@${projectName}/shared';
2305
-
2306
- const containerName = 'Models'; // PascalCase + 's'
2307
-
2308
- app.http('{model}-get-all', {
2309
- methods: ['GET'],
2310
- route: '{model}',
2311
- authLevel: 'function',
2312
- extraInputs: [{ type: 'cosmosDB', name: 'cosmosInput', containerName, ... }],
2313
- handler: async (request, context) => {
2314
- const documents = context.extraInputs.get('cosmosInput');
2315
- const validated = z.array(ModelSchema).parse(documents);
2316
- return { status: 200, jsonBody: validated };
2317
- },
2318
- });
2319
- \`\`\`` : ''}
2320
-
2321
- ## Naming Conventions
2322
-
2323
- | Item | Convention | Example |
2324
- |------|-----------|---------|
2325
- | Model schema file | \`shared/models/{kebab-case}.ts\` | \`shared/models/todo.ts\` |
2326
- | Schema/type name | PascalCase (same name for both) | \`export const Todo = z.object({...}); export type Todo = z.infer<typeof Todo>;\` |
2327
- | Functions handler file | backend-language specific under \`functions/\` | \`${backendLanguage === 'typescript' ? 'functions/src/todo.ts' : backendLanguage === 'csharp' ? 'functions/Crud/TodoCrudFunctions.cs' : 'functions/blueprints/todo.py'}\` |
2328
- | Functions handler name | \`{camelCase}-{operation}\` | \`todo-get-all\`, \`todo-create\` |
2329
- | API route path | \`/api/{camelCase}\` | \`/api/todo\`, \`/api/todo/{id}\` |
2330
- | BFF route file | \`app/api/{kebab-case}/route.ts\` | \`app/api/todo/route.ts\` |
2331
- | BFF detail route | \`app/api/{kebab-case}/[id]/route.ts\` | \`app/api/todo/[id]/route.ts\` |
2332
- | UI page directory | \`app/{kebab-case}/\` | \`app/todo/page.tsx\` |
2333
- | React component | PascalCase | \`TodoForm.tsx\` |
2334
- | Cosmos DB container | PascalCase + 's' | \`Todos\` |
2335
- | Cosmos DB partition key | \`/id\` (default) | Custom: \`export const partitionKey = '/field'\` |
2336
- | Bicep container file | \`infra/containers/{kebab-case}-container.bicep\` | \`infra/containers/todo-container.bicep\` |
2337
-
2338
- ## Adding New Models (SwallowKit CLI)
2339
-
2340
- Use the SwallowKit CLI β€” do **not** manually create model files or CRUD boilerplate.
2341
- For autonomous agents, prefer the plan/apply loop above (or the \`swallowkit-add-model\` skill); the commands below are the human-friendly equivalents.
2342
-
2343
- ### Create a new data model
2344
-
2345
- \`\`\`bash
2346
- ${runCmd} swallowkit create-model <name>
2347
- # Multiple models at once:
2348
- ${runCmd} swallowkit create-model user post comment
2349
- \`\`\`
2350
-
2351
- Creates \`shared/models/<name>.ts\` with a Zod schema template including \`id\`, \`createdAt\`, \`updatedAt\`.
2352
- Edit the generated file to add your domain-specific fields, then run scaffold.
2353
-
2354
- ### Generate full CRUD from a model
2355
-
2356
- \`\`\`bash
2357
- ${runCmd} swallowkit scaffold shared/models/<name>.ts
2358
- \`\`\`
2359
-
2360
- Generates:
2361
- - Azure Functions handlers (${backendLanguage === 'typescript' ? '`functions/src/<name>.ts`' : '`functions/` language-specific CRUD files + `functions/generated/` schema assets'})
2362
- - BFF API routes (\`app/api/<name>/route.ts\`, \`app/api/<name>/[id]/route.ts\`)
2363
- - UI pages (\`app/<name>/page.tsx\`, detail, create, edit pages)
2364
- - Cosmos DB Bicep container config (\`infra/containers/<name>-container.bicep\`)
2365
-
2366
- ### Start development servers
2367
-
2368
- \`\`\`bash
2369
- ${runCmd} swallowkit dev
2370
- \`\`\`
2371
2117
 
2372
- Runs Next.js (http://localhost:3000) and Azure Functions (http://localhost:7071) concurrently.
2373
- Checks for Cosmos DB Emulator availability.
2374
-
2375
- ### Provision Azure resources
2376
-
2377
- \`\`\`bash
2378
- ${runCmd} swallowkit provision --resource-group <name> --location <region>
2379
- \`\`\`
2380
-
2381
- Deploys Bicep infrastructure: Static Web Apps, Functions, Cosmos DB, Storage, Managed Identity.
2382
-
2383
- ### Typical workflow for "add a new feature/model"
2384
-
2385
- 1. \`${runCmd} swallowkit create-model <name>\`
2386
- 2. Edit \`shared/models/<name>.ts\` β€” add fields
2387
- 3. \`${runCmd} swallowkit scaffold shared/models/<name>.ts\`
2388
- 4. \`${runCmd} swallowkit dev\` β€” verify at http://localhost:3000/<name>
2389
- 5. If \`dev-seeds/\` already exists, update the seed JSON files to include realistic data for the new model and adjust existing seeds if relationships changed.
2390
-
2391
- ## Do NOT
2392
-
2393
- - **Do not** put business logic or database calls in \`app/api/\` routes. They are BFF only.
2394
- - **Do not** define TypeScript interfaces/types separately from Zod schemas. Always derive types with \`z.infer<>\`.
2395
- - **Do not** manually duplicate model definitions across layers. Use the shared package.
2396
- - **Do not** manually create CRUD boilerplate. Use \`swallowkit scaffold\`.
2397
- - **Do not** hardcode Cosmos DB connection strings. Use Managed Identity (\`CosmosDBConnection__accountEndpoint\`) in production and emulator settings locally.
2398
- - By default, all containers use \`/id\` as the partition key. To use a custom partition key, add \`export const partitionKey = '/yourField'\` to the model file. The scaffold command will apply it across all layers.
2399
-
2400
- ## Technology Stack
2401
-
2402
- - **Frontend**: Next.js (App Router), React, TypeScript, Tailwind CSS
2403
- - **BFF**: Next.js API Routes (proxy only)
2404
- - **Backend**: Azure Functions (${backendLanguageLabel})
2405
- - **Database**: Azure Cosmos DB (NoSQL)
2406
- - **Schema**: Zod (shared across all layers via workspace package)
2407
- - **Infrastructure**: Bicep (IaC)
2408
- - **Hosting**: Azure Static Web Apps (frontend) + Azure Functions Flex Consumption (backend)
2409
- - **Auth**: Azure Managed Identity (no connection strings in production)
2410
- - **Monitoring**: Application Insights
2411
- `;
2412
-
2413
- fs.writeFileSync(path.join(projectDir, 'AGENTS.md'), agentsMd);
2414
- console.log(' βœ… AGENTS.md (Codex / generic agents)');
2415
-
2416
- // ── 2. CLAUDE.md (Claude Code) ─────────────────────────────────────
2417
-
2418
- const claudeMd = `# CLAUDE.md
2419
-
2420
- This file is for Claude Code. Read AGENTS.md in the project root for the full architecture, conventions, and rules.
2421
-
2422
- ## Quick Reference
2423
-
2424
- - **Architecture**: Next.js (frontend) β†’ BFF (API routes, proxy only) β†’ Azure Functions (backend) β†’ Cosmos DB
2425
- - **Schema**: Zod schemas in \`shared/models/\` are the single source of truth. Never define types separately.
2426
- - **BFF rule**: \`app/api/\` routes must ONLY proxy to Azure Functions via \`callFunction()\`. No business logic.
2427
- - **Backend language**: ${backendLanguageLabel}
2428
- - **Backend rule**: Regenerate backend contracts with \`swallowkit scaffold\` after schema changes and keep \`functions/generated/\` in sync.
2429
-
2430
- ## SwallowKit MCP
2431
-
2432
- - This repository includes a project-scoped \`.mcp.json\` that resolves and starts the latest SwallowKit MCP server on each launch. Set \`SWALLOWKIT_MCP_VERSION\` in that file to pin a specific version.
2433
- - When the \`swallowkit_*\` tools are available, prefer them for inspect / validate / generate tasks.
2434
- - If MCP is unavailable, use \`${runCmd} swallowkit machine ...\` instead.
2435
- - For generation, prefer the two-phase flow: \`plan scaffold <name>\` β†’ \`apply scaffold --plan <planId>\` β†’ \`verify project\`. Runbooks: \`.swallowkit/workflows/\`.
2436
- - Agent Skills (agentskills.io) for the same workflows live in \`.github/skills/\` (\`swallowkit-add-model\`, \`swallowkit-modify-model\`, \`swallowkit-verify-repair\`, \`swallowkit-provision\`). If your runtime does not auto-discover them, read the relevant \`SKILL.md\` before performing these tasks.
2437
- - Boundary contract (what you may edit freely vs what SwallowKit regenerates): \`${runCmd} swallowkit machine inspect boundaries\`
2438
- - **Always invoke SwallowKit via \`${runCmd}\`.** Do not mix package manager commands.
2439
-
2440
- ## SwallowKit CLI Commands
2441
-
2442
- | Task | Command |
2443
- |------|---------|
2444
- | Create model | \`${runCmd} swallowkit create-model <name>\` |
2445
- | Generate CRUD | \`${runCmd} swallowkit scaffold shared/models/<name>.ts\` |
2446
- | Dev servers | \`${runCmd} swallowkit dev\` |
2447
- | Provision Azure | \`${runCmd} swallowkit provision --resource-group <rg> --location <region>\` |
2448
-
2449
- ## Workflow: Add a new model
2450
-
2451
- 1. \`${runCmd} swallowkit create-model <name>\`
2452
- 2. Edit \`shared/models/<name>.ts\` β€” add your fields
2453
- 3. \`${runCmd} swallowkit scaffold shared/models/<name>.ts\`
2454
- 4. \`${runCmd} swallowkit dev\` β€” verify at http://localhost:3000/<name>
2455
- 5. If \`dev-seeds/\` exists, update the seed JSON files to include data for the new model and adjust existing seeds if relationships changed.
2456
- `;
2457
-
2458
- fs.writeFileSync(path.join(projectDir, 'CLAUDE.md'), claudeMd);
2459
- console.log(' βœ… CLAUDE.md (Claude Code)');
2460
-
2461
- fs.writeFileSync(path.join(projectDir, '.mcp.json'), projectMcpConfigSource);
2462
- console.log(' βœ… .mcp.json (project-scoped MCP bootstrap)');
2463
-
2464
- // ── 3. .github/copilot-instructions.md (GitHub Copilot) ────────────
2465
-
2466
- const ghDir = path.join(projectDir, '.github');
2467
- fs.mkdirSync(ghDir, { recursive: true });
2468
-
2469
- const copilotInstructions = `# Copilot Instructions
2470
-
2471
- This project was generated by **SwallowKit**. See \`AGENTS.md\` in the project root for the full specification.
2472
-
2473
- ## Architecture (3-layer)
2474
-
2475
- \`\`\`
2476
- Frontend (Next.js App Router) β†’ BFF (Next.js API Routes) β†’ Backend (Azure Functions) β†’ Cosmos DB
2477
- \`\`\`
2478
-
2479
- ## Key Rules
2480
-
2481
- 1. **BFF is proxy only** β€” \`app/api/\` routes call Azure Functions via \`callFunction()\`. No business logic, no direct DB access.
2482
- 2. **Zod = single source of truth** β€” Models live in \`shared/models/\`. Types are derived with \`z.infer<>\`. Never define types separately.
2483
- 3. **Backend owns data** β€” All CRUD and business logic stay in \`functions/\`, and generated contract assets under \`functions/generated/\` must stay aligned with \`shared/models/\`.
2484
- 4. **Use the CLI** β€” Run \`${runCmd} swallowkit create-model <name>\` then \`${runCmd} swallowkit scaffold shared/models/<name>.ts\` to add models. Do not create boilerplate manually.
2485
- 5. **Maintain seed data** β€” When adding models or changing schemas, update the JSON files under \`dev-seeds/\` to keep seed data consistent with the current schema.
2486
-
2487
- ## SwallowKit Framework Operations
2488
-
2489
- - Prefer the SwallowKit MCP or machine interface for framework-owned inspection, validation, and generation instead of hand-editing generated files.
2490
- - If your runtime loads project-scoped MCP config from \`.mcp.json\`, use the \`swallowkit_*\` tools.
2491
- - Otherwise use \`${runCmd} swallowkit machine inspect project\`, \`${runCmd} swallowkit machine validate project\`, and the two-phase flow \`${runCmd} swallowkit machine plan scaffold <name>\` β†’ \`apply scaffold --plan <planId>\` β†’ \`verify project\`.
2492
- - Agent Skills in \`.github/skills/\` (\`swallowkit-add-model\`, \`swallowkit-modify-model\`, \`swallowkit-verify-repair\`, \`swallowkit-provision\`) cover these workflows β€” load them when the task matches.
2493
- - Boundary contract: \`${runCmd} swallowkit machine inspect boundaries\` tells you which files are free to edit and which are regenerated. Runbooks live in \`.swallowkit/workflows/\`.
2494
- - **Always invoke SwallowKit via \`${runCmd}\`.** Do not mix package manager commands.
2495
-
2496
- ## Naming
2497
-
2498
- - Schema/type: PascalCase, same name for both (\`export const Todo = z.object({...}); export type Todo = z.infer<typeof Todo>;\`)
2499
- - Files: kebab-case (\`shared/models/todo.ts\`, backend handlers under \`functions/\`)
2500
- - Cosmos DB containers: PascalCase + 's' (\`Todos\`), partition key default \`/id\` (customizable via \`export const partitionKey\`)
2501
-
2502
- ## Managed Fields
2503
-
2504
- \`id\`, \`createdAt\`, \`updatedAt\` are auto-managed by the backend. Define them as \`optional()\` in schemas. Never trust client-sent values.
2505
- `;
2506
-
2507
- fs.writeFileSync(path.join(ghDir, 'copilot-instructions.md'), copilotInstructions);
2508
- console.log(' βœ… .github/copilot-instructions.md (GitHub Copilot)');
2509
-
2510
- // ── 4. .github/instructions/*.instructions.md (Copilot layer-specific) ──
2511
-
2512
- const instructionsDir = path.join(ghDir, 'instructions');
2513
- fs.mkdirSync(instructionsDir, { recursive: true });
2514
-
2515
- // 4a. shared/models β€” Zod schema layer
2516
- const sharedModelsInstructions = `---
2517
- applyTo: "shared/models/**"
2518
- ---
2519
-
2520
- # Shared Models β€” Zod Schema Rules
2521
-
2522
- Files in this directory are the **single source of truth** for data models across the entire application.
2523
-
2524
- ## Rules
2525
-
2526
- - Define Zod schemas using \`zod/v4\` (\`import { z } from 'zod/v4'\`).
2527
- - Use the **Zod official pattern**: the schema constant and the TypeScript type share the same name.
2528
- \`\`\`typescript
2529
- export const Todo = z.object({ ... });
2530
- export type Todo = z.infer<typeof Todo>;
2531
- \`\`\`
2532
- - Always include \`id: z.string()\`, \`createdAt: z.string().optional()\`, \`updatedAt: z.string().optional()\`. These are managed by the backend.
2533
- - Export a \`displayName\` string constant for UI display.
2534
- - Re-export every model from \`shared/index.ts\`.
2535
- - For relationships, use **nested schemas** (import and embed the related schema), not ID references.
2536
- - After editing a model, run \`${runCmd} swallowkit scaffold shared/models/<name>.ts\` to regenerate CRUD code.
2537
- `;
2538
-
2539
- fs.writeFileSync(
2540
- path.join(instructionsDir, 'shared-models.instructions.md'),
2541
- sharedModelsInstructions
2542
- );
2543
-
2544
- // 4b. app/api β€” BFF layer
2545
- const bffInstructions = `---
2546
- applyTo: "app/api/**"
2547
- ---
2548
-
2549
- # BFF API Routes β€” Rules
2550
-
2551
- Files in \`app/api/\` are the **BFF (Backend for Frontend)** layer. They exist solely to proxy requests to Azure Functions.
2552
-
2553
- ## Rules
2554
-
2555
- - **Never** put business logic, database access, or direct Cosmos DB calls here.
2556
- - Use \`callFunction()\` from \`@/lib/api/call-function\` to forward requests to Azure Functions.
2557
- - You may validate input/output with Zod schemas before forwarding.
2558
- - Import schemas from \`@${projectName}/shared\`.
2559
-
2560
- ## Pattern
2561
-
2562
- \`\`\`typescript
2563
- import { callFunction } from '@/lib/api/call-function';
2564
- import { ModelSchema } from '@${projectName}/shared';
2565
- import { z } from 'zod/v4';
2566
-
2567
- export async function GET() {
2568
- return callFunction({
2569
- method: 'GET',
2570
- path: '/api/{model}',
2571
- responseSchema: z.array(ModelSchema),
2118
+ writeAgentInstructionFiles(projectDir, {
2119
+ projectName,
2120
+ backendLanguage,
2121
+ packageManager: pm,
2572
2122
  });
2573
- }
2574
- \`\`\`
2575
- `;
2576
-
2577
- fs.writeFileSync(
2578
- path.join(instructionsDir, 'bff-routes.instructions.md'),
2579
- bffInstructions
2580
- );
2581
-
2582
- // 4c. functions β€” Azure Functions backend layer
2583
- const functionsInstructions = `---
2584
- applyTo: "functions/**"
2585
- ---
2586
-
2587
- # Azure Functions β€” Backend Rules
2588
-
2589
- Files in \`functions/\` contain all business logic and data access for this application.
2590
-
2591
- ## Rules
2592
-
2593
- - Keep backend contracts aligned with \`shared/models/\` by rerunning \`swallowkit scaffold\` after schema changes.
2594
- - For TypeScript backends, use Cosmos DB **input/output bindings** (\`extraInputs\`/\`extraOutputs\`) for reads and writes.
2595
- - For C#/Python backends, consume the native-generated assets in \`functions/generated/\`.
2596
- - Auto-generate \`id\` (UUID), \`createdAt\`, and \`updatedAt\` on the backend. Never trust client-sent values.
2597
- - Container names are PascalCase + 's' (e.g., \`Todos\`). Partition key defaults to \`/id\` but can be customized per model.
2598
-
2599
- ## Handler Pattern
2600
-
2601
- \`\`\`typescript
2602
- import { app } from '@azure/functions';
2603
- import { ModelSchema } from '@${projectName}/shared';
2604
-
2605
- app.http('{model}-get-all', {
2606
- methods: ['GET'],
2607
- route: '{model}',
2608
- authLevel: 'function',
2609
- extraInputs: [cosmosInput],
2610
- handler: async (request, context) => {
2611
- const documents = context.extraInputs.get(cosmosInput);
2612
- const validated = z.array(ModelSchema).parse(documents);
2613
- return { status: 200, jsonBody: validated };
2614
- },
2615
- });
2616
- \`\`\`
2617
- `;
2123
+ console.log(' βœ… AGENTS.md (canonical project contract)');
2124
+ console.log(' βœ… CLAUDE.md (Claude Code adapter)');
2125
+ console.log(' βœ… .github/copilot-instructions.md (GitHub Copilot adapter)');
2126
+ console.log(' βœ… .github/instructions/ (path-specific instructions)');
2618
2127
 
2619
2128
  fs.writeFileSync(
2620
- path.join(instructionsDir, 'azure-functions.instructions.md'),
2621
- functionsInstructions
2129
+ path.join(projectDir, '.mcp.json'),
2130
+ buildSwallowKitMcpProjectConfigSource(pm)
2622
2131
  );
2132
+ console.log(' βœ… .mcp.json (project-scoped MCP bootstrap)');
2623
2133
 
2624
- console.log(' βœ… .github/instructions/ (Copilot layer-specific instructions)');
2625
- console.log(' - shared-models.instructions.md');
2626
- console.log(' - bff-routes.instructions.md');
2627
- console.log(' - azure-functions.instructions.md');
2628
-
2629
- // ── 5. .swallowkit/workflows/*.md (agent-agnostic runbooks) ────────
2630
2134
  writeWorkflowDocs(projectDir, runCmd);
2631
2135
  console.log(' βœ… .swallowkit/workflows/ (agent-agnostic autonomous-loop runbooks)');
2632
2136
 
2633
- // ── 6. .github/skills/<name>/SKILL.md (Agent Skills, agentskills.io) ─
2634
2137
  const skillPaths = writeAgentSkills(projectDir, runCmd);
2635
2138
  console.log(' βœ… .github/skills/ (Agent Skills β€” agentskills.io open standard)');
2636
2139
  for (const skillPath of skillPaths) {
@@ -2638,16 +2141,7 @@ app.http('{model}-get-all', {
2638
2141
  }
2639
2142
 
2640
2143
  console.log('\nβœ… AI agent files created\n');
2641
- console.log(' Supported agents:');
2642
- console.log(' - OpenAI Codex β†’ AGENTS.md');
2643
- console.log(' - Claude Code β†’ CLAUDE.md (+ AGENTS.md)');
2644
- console.log(' - Project MCP runtimes β†’ .mcp.json');
2645
- console.log(' - GitHub Copilot β†’ .github/copilot-instructions.md');
2646
- console.log(' - GitHub Copilot (edit) β†’ .github/instructions/*.instructions.md');
2647
- console.log(' - Skills-aware agents β†’ .github/skills/*/SKILL.md');
2648
- console.log('');
2649
2144
  }
2650
-
2651
2145
  export function buildFunctionsHostKeyBicepExpression(): string {
2652
2146
  return "listKeys('${resourceId('Microsoft.Web/sites', functionsAppName)}/host/default', '2023-12-01').functionKeys.default";
2653
2147
  }
@@ -31,7 +31,7 @@ import {
31
31
  generateAuthLayout,
32
32
  UIAuthOptions,
33
33
  } from "../../core/scaffold/ui-generator";
34
- import { generateLanguageSchemaArtifacts } from "../../core/scaffold/native-schema-generator";
34
+ import { generateLanguageSchemaArtifacts, validateNativeSchemaToolchain } from "../../core/scaffold/native-schema-generator";
35
35
  import { detectFromProject, getCommands } from "../../utils/package-manager";
36
36
  import {
37
37
  BackendLanguage,
@@ -135,6 +135,19 @@ export async function scaffoldCommand(options: ScaffoldOptions) {
135
135
  const relatedModels = backendLanguage === "typescript"
136
136
  ? [modelInfo]
137
137
  : await collectModelGraph(modelPath);
138
+ for (const relatedModel of relatedModels) {
139
+ session.registerInput(relatedModel.filePath);
140
+ }
141
+
142
+ // 4b. 書き込み前に倖部 codegen toolchain γ‚’ζ€œθ¨Όγ—γ€ε€±ζ•—ζ™‚γ―γƒ—γƒ­γ‚Έγ‚§γ‚―γƒˆη„‘ε€‰ζ›΄γ§η΅‚δΊ†γ™γ‚‹
143
+ if (session.mode === "commit" && backendLanguage !== "typescript" && !isConnectorModel) {
144
+ await validateNativeSchemaToolchain(
145
+ relatedModels,
146
+ modelInfo,
147
+ backendLanguage,
148
+ path.join(process.cwd(), functionsDir)
149
+ );
150
+ }
138
151
 
139
152
  if (options.apiOnly) {
140
153
  console.log("ℹ️ --api-only skips UI generation only; Functions, BFF routes, OpenAPI, and native schema assets are still updated.");
@@ -152,13 +165,7 @@ export async function scaffoldCommand(options: ScaffoldOptions) {
152
165
  await generateFunctionsCode(modelInfo, functionsDir, sharedPackageName, backendLanguage, session);
153
166
 
154
167
  if (backendLanguage !== "typescript") {
155
- if (session.mode === "collect") {
156
- session.addWarning(
157
- `external-codegen: ${functionsDir}/openapi and ${functionsDir}/generated are regenerated by external tooling on apply and are not included in this plan.`
158
- );
159
- } else {
160
- await generateLanguageSchemaArtifacts(relatedModels, modelInfo, functionsDir, backendLanguage);
161
- }
168
+ await generateLanguageSchemaArtifacts(relatedModels, modelInfo, functionsDir, backendLanguage, session);
162
169
  }
163
170
  }
164
171
 
@@ -75,6 +75,7 @@ export class FileOperationSession {
75
75
  readonly warnings: string[] = [];
76
76
 
77
77
  private readonly operationsByPath = new Map<string, RecordedFileOperation>();
78
+ private readonly inputFingerprintsByPath = new Map<string, string | null>();
78
79
  /** overlay: absolute normalized path -> content (null = deleted in session) */
79
80
  private readonly overlay = new Map<string, string | null>();
80
81
 
@@ -87,12 +88,23 @@ export class FileOperationSession {
87
88
  return Array.from(this.operationsByPath.values()).sort((a, b) => a.path.localeCompare(b.path));
88
89
  }
89
90
 
91
+ get inputFingerprints(): Record<string, string | null> {
92
+ return Object.fromEntries(
93
+ Array.from(this.inputFingerprintsByPath.entries()).sort(([left], [right]) => left.localeCompare(right))
94
+ );
95
+ }
96
+
90
97
  addWarning(message: string): void {
91
98
  if (!this.warnings.includes(message)) {
92
99
  this.warnings.push(message);
93
100
  }
94
101
  }
95
102
 
103
+ registerInput(absolutePath: string): void {
104
+ const relativePath = toProjectRelativePath(this.rootDirectory, absolutePath);
105
+ this.inputFingerprintsByPath.set(relativePath, hashFileIfExists(absolutePath));
106
+ }
107
+
96
108
  private overlayKey(absolutePath: string): string {
97
109
  return path.resolve(absolutePath);
98
110
  }