swallowkit 2.0.0-alpha.10 → 2.0.0-alpha.11

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.
@@ -1 +1 @@
1
- {"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../../src/core/project/workflows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,CA8Q/D;AAED,eAAO,MAAM,aAAa,QAAwC,CAAC;AACnE,eAAO,MAAM,UAAU,QAAiC,CAAC;AAEzD,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAS9E;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAS9F;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAS7E"}
1
+ {"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../../src/core/project/workflows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,CA4R/D;AAED,eAAO,MAAM,aAAa,QAAwC,CAAC;AACnE,eAAO,MAAM,UAAU,QAAiC,CAAC;AAEzD,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAS9E;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAS9F;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAS7E"}
@@ -55,10 +55,10 @@ function buildWorkflowDocs(runCmd) {
55
55
  fileName: "add-model.md",
56
56
  title: "Add a new model (autonomous loop)",
57
57
  skillName: "swallowkit-add-model",
58
- skillDescription: "Add a new data model to a SwallowKit project and deterministically derive CRUD Functions, BFF routes, UI pages, and Cosmos DB infra from it using the plan/apply/verify loop. Use when asked to add a model, entity, resource, table, or a new CRUD feature.",
58
+ skillDescription: "Add a new persistent model, including models with custom APIs, and generate required infrastructure. Derive CRUD Functions, BFF routes, and UI only when needed using the plan/apply/verify loop. Use when asked to add a model, entity, resource, table, or a new CRUD feature.",
59
59
  content: `# Workflow: Add a new model
60
60
 
61
- Goal: add a data model and derive CRUD/BFF/UI/infra deterministically.
61
+ Goal: add a persistent model and generate its required infrastructure, even with custom APIs. A hand-written model alone is not complete.
62
62
 
63
63
  ## Responsibility boundary
64
64
 
@@ -70,15 +70,18 @@ Goal: add a data model and derive CRUD/BFF/UI/infra deterministically.
70
70
 
71
71
  1. Create the model file (deterministic template):
72
72
  \`${runCmd} swallowkit machine generate model <name> --overwrite never\`
73
+ - This is the machine equivalent of \`${runCmd} swallowkit create-model <name>\`.
74
+ Preserve existing schemas; model creation alone does not generate a Cosmos DB container.
73
75
  2. Edit \`shared/models/<name>.ts\` — add domain fields (free-form authoring).
74
76
  - Native C#/Python types follow Zod, not names: \`z.iso.datetime()\` for dates, \`z.number().int()\` for integers.
75
77
  - \`<model>Id\` fields reference a model only when it exists in \`shared/models\`; otherwise declare
76
78
  \`export const references = { fieldId: 'Model' }\` (or \`false\` to opt out).
77
- 3. Compute the change plan (writes nothing):
79
+ 3. When CRUD is needed, compute the change plan (writes nothing):
78
80
  \`${runCmd} swallowkit machine plan scaffold <name>\`
79
81
  - \`status: "requires-human"\` → review \`data.conflicts\`; only proceed with \`--approve\` if overwriting is intended.
80
82
  - Must not change Bicep/infrastructure? Add \`--skip-infra\` to plan and apply. Nothing under \`infra/\` changes and
81
83
  the plan warns \`infra-skipped\`; later run \`${runCmd} swallowkit migrations add-model <name>\` to add only the container migration.
84
+ State the reason and pending infrastructure work; a passing verify does not mean the model is complete or deployment-ready.
82
85
  - Read \`data.warnings\`. \`user-scoped-data-without-auth\` means generated CRUD would expose every user's documents;
83
86
  add auth (\`swallowkit-add-auth\`) and owner-scoped ai-authored endpoints before exposing the model.
84
87
  - \`auth-policy-without-auth\` blocks generation before file writes: configure authentication with plan/apply auth,
@@ -88,11 +91,22 @@ Goal: add a data model and derive CRUD/BFF/UI/infra deterministically.
88
91
  Single-provider \`auth.provider\` supports role lists only; named policies block with \`auth-named-policy-requires-named-scheme\`.
89
92
  - Scaffold appends missing exports to \`shared/index.ts\` for hand-authored models too.
90
93
  Manual exports are allowed; no managed markers exist in that file.
91
- 4. Apply:
94
+ - If custom APIs replace CRUD, skip scaffold (including \`--api-only\`, which still generates CRUD).
95
+ Review \`${runCmd} swallowkit migrations add-model <name> --dry-run\`, then run
96
+ \`${runCmd} swallowkit migrations add-model <name>\` to generate only the container migration and generation records.
97
+ Keep the schema exported from \`shared/index.ts\`. External connector models need their connector mapping, not a Cosmos container.
98
+ 4. Apply the reviewed CRUD scaffold plan, if needed:
92
99
  \`${runCmd} swallowkit machine apply scaffold --plan <planId>\`
93
100
  5. Verify:
94
- \`${runCmd} swallowkit machine verify project\`
101
+ - Inspect \`machine inspect entities\`, \`machine inspect infra\`, \`machine inspect artifacts\`, and \`machine inspect drift\`.
102
+ Match the model's container name and partition key to its Bicep, \`sourceModel\` in
103
+ \`infra/migrations/manifest.json\`, and \`.swallowkit/artifacts.json\`.
104
+ For a baseline-owned container, verify the tracked definition and \`infra/main.bicep\` wiring instead of requiring a new migration.
105
+ Do not hand-edit a checksum-locked baseline or an existing migration.
106
+ - Run \`${runCmd} swallowkit machine verify project\`.
95
107
  - \`summary.done: false\` → \`${runCmd} swallowkit machine explain failure\` and repair, then re-verify.
108
+ - Required infrastructure still missing? Report the reason and remaining work, not completion or deployment readiness.
109
+ Local generation does not provision Azure; follow the separate provision workflow and human approval gates.
96
110
  6. If \`dev-seeds/\` exists, update seed JSON for the new model. Seeds are only
97
111
  applied by \`${runCmd} swallowkit dev --seed-env <environment>\` — editing the
98
112
  JSON alone does nothing.
@@ -1 +1 @@
1
- {"version":3,"file":"workflows.js","sourceRoot":"","sources":["../../../src/core/project/workflows.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workflows.js","sourceRoot":"","sources":["../../../src/core/project/workflows.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swallowkit",
3
- "version": "2.0.0-alpha.10",
3
+ "version": "2.0.0-alpha.11",
4
4
  "description": "Type-safe schema-driven development toolkit for Next.js and React applications on Azure",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,6 +1,9 @@
1
1
  import * as fs from "fs";
2
2
  import * as os from "os";
3
3
  import * as path from "path";
4
+ import { BackendLanguage, FrontendFramework } from "../types";
5
+ import { PackageManager, getCommands } from "../utils/package-manager";
6
+ import { buildWorkflowDocs } from "../core/project/workflows";
4
7
  import {
5
8
  AGENT_TEMPLATE_FILES,
6
9
  AgentInstructionContext,
@@ -19,6 +22,19 @@ const representativeContext: AgentInstructionContext = {
19
22
  };
20
23
 
21
24
  const repositoryRoot = path.resolve(__dirname, "../..");
25
+ const frontends: FrontendFramework[] = ["nextjs", "react"];
26
+ const backendLanguages: BackendLanguage[] = ["typescript", "csharp", "python"];
27
+ const packageManagers: PackageManager[] = ["npm", "pnpm"];
28
+ const persistentModelContexts: AgentInstructionContext[] = frontends.flatMap((frontend) =>
29
+ backendLanguages.flatMap((backendLanguage) =>
30
+ packageManagers.map((packageManager) => ({
31
+ projectName: "persistent-app",
32
+ frontend,
33
+ backendLanguage,
34
+ packageManager,
35
+ }))
36
+ )
37
+ );
22
38
 
23
39
  describe("coding-agent instruction contract", () => {
24
40
  it("applies SwallowKit before implementation and composes with external processes", () => {
@@ -133,6 +149,66 @@ describe("coding-agent instruction contract", () => {
133
149
  }
134
150
  });
135
151
 
152
+ it.each(persistentModelContexts)(
153
+ "writes the init persistent-model contract for $frontend/$backendLanguage/$packageManager",
154
+ (context) => {
155
+ const tempDir = fs.mkdtempSync(path.join(repositoryRoot, ".tmp-persistent-agent-docs-"));
156
+ try {
157
+ // init uses this writer for both frontend variants.
158
+ writeAgentInstructionFiles(tempDir, context);
159
+ const agents = fs.readFileSync(path.join(tempDir, "AGENTS.md"), "utf-8").replace(/\s+/g, " ");
160
+ const sharedModels = fs.readFileSync(
161
+ path.join(tempDir, ".github", "instructions", AGENT_TEMPLATE_FILES.sharedModelsInstructions),
162
+ "utf-8"
163
+ );
164
+ const runCmd = getCommands(context.packageManager).exec;
165
+ for (const document of [agents, sharedModels]) {
166
+ expect(document).toContain(`${runCmd} swallowkit machine generate model <model> --overwrite never`);
167
+ expect(document).toContain(`${runCmd} swallowkit migrations add-model <model> --dry-run`);
168
+ expect(document).toContain(`${runCmd} swallowkit migrations add-model <model>`);
169
+ expect(document).toContain("custom APIs");
170
+ expect(document).toContain("required infrastructure is missing");
171
+ expect(document).not.toMatch(/\{\{[A-Za-z]+\}\}/);
172
+ }
173
+ expect(agents).toContain(`${runCmd} swallowkit create-model <model>`);
174
+ expect(agents).toContain("A hand-written model alone is not complete");
175
+ expect(agents).toContain("does **not** generate a Cosmos DB container");
176
+ expect(agents).toContain("do **not** scaffold unnecessary CRUD");
177
+ expect(agents).toContain("`--api-only` skips UI only");
178
+ expect(agents).toContain("`machine apply scaffold --plan <planId>`");
179
+ expect(agents).toContain(`${runCmd} swallowkit machine verify project`);
180
+ for (const inspect of ["entities", "infra", "artifacts", "drift"]) {
181
+ expect(agents).toContain(`machine inspect ${inspect}`);
182
+ }
183
+ for (const record of ["infra/migrations/manifest.json", ".swallowkit/artifacts.json", "sourceModel"]) {
184
+ expect(agents).toContain(record);
185
+ }
186
+ expect(agents).toContain("container name and partition key");
187
+ expect(agents).toContain("baseline-owned container");
188
+ expect(agents).toContain("External `connectorConfig` models");
189
+ expect(agents).toContain("state the reason and the pending");
190
+ expect(agents).toContain("Even if `verify project` passes");
191
+ expect(agents).toContain("Generation is local, not Azure provisioning");
192
+ } finally {
193
+ fs.rmSync(tempDir, { recursive: true, force: true });
194
+ }
195
+ }
196
+ );
197
+
198
+ it.each(["npx", "pnpm exec"])("aligns the add-model runbook and skill content for %s", (runCmd) => {
199
+ const workflow = buildWorkflowDocs(runCmd).find((doc) => doc.skillName === "swallowkit-add-model");
200
+ expect(workflow).toBeDefined();
201
+ expect(workflow?.skillDescription).toContain("including models with custom APIs");
202
+ expect(workflow?.content).toContain(`${runCmd} swallowkit machine generate model <name> --overwrite never`);
203
+ expect(workflow?.content).toContain(`${runCmd} swallowkit create-model <name>`);
204
+ expect(workflow?.content).toContain("If custom APIs replace CRUD, skip scaffold");
205
+ expect(workflow?.content).toContain(`${runCmd} swallowkit migrations add-model <name> --dry-run`);
206
+ expect(workflow?.content).toContain(`${runCmd} swallowkit migrations add-model <name>`);
207
+ expect(workflow?.content).toContain("infra/migrations/manifest.json");
208
+ expect(workflow?.content).toContain(".swallowkit/artifacts.json");
209
+ expect(workflow?.content).toContain("a passing verify does not mean the model is complete or deployment-ready");
210
+ });
211
+
136
212
  it("covers the requested model-change, new-feature, BFF, and deployment scenarios", () => {
137
213
  const agentsMd = buildAgentsMd(representativeContext);
138
214
  const pathInstructions = buildPathSpecificInstructions(representativeContext);
@@ -200,6 +276,18 @@ describe("coding-agent documentation synchronization", () => {
200
276
  ].map((match) => match[1]);
201
277
 
202
278
  expect(translatedSourceSections).toEqual(sourceSections);
279
+ expect(translation).toContain("カスタム API の有無にかかわらず");
280
+ expect(translation).toContain("手書きモデルを追加しただけでは完了ではありません");
281
+ expect(translation).toContain("{{runCmd}} swallowkit machine generate model <model> --overwrite never");
282
+ expect(translation).toContain("{{runCmd}} swallowkit create-model <model>");
283
+ expect(translation).toContain("{{runCmd}} swallowkit migrations add-model <model> --dry-run");
284
+ expect(translation).toContain("{{runCmd}} swallowkit migrations add-model <model>");
285
+ expect(translation).toContain("不要な CRUD を scaffold してはなりません");
286
+ expect(translation).toContain("理由と未完了");
287
+ expect(translation).toContain("デプロイ可能と案内したりしてはなりません");
288
+ for (const record of ["infra/migrations/manifest.json", ".swallowkit/artifacts.json", "sourceModel"]) {
289
+ expect(translation).toContain(record);
290
+ }
203
291
  });
204
292
 
205
293
  it("exposes matching major EN/JA guide topics and both sidebar entries", () => {
@@ -274,12 +274,49 @@ SwallowKit should generate framework-owned CRUD artifacts.
274
274
 
275
275
  Do not manually recreate boilerplate that SwallowKit owns.
276
276
 
277
- When the task must not change Bicep or other infrastructure, still scaffold the
278
- model: pass `--skip-infra` to `plan scaffold` / `apply scaffold` (MCP
279
- `skipInfra: true`, or `swallowkit scaffold --skip-infra`). Nothing under
280
- `infra/` changes, the plan reports `infra-skipped`, and `verify project` still
281
- passes. Generate only the pending container migration later with
282
- `{{runCmd}} swallowkit migrations add-model <model>`.
277
+ ### Persistent models require infrastructure, even with custom APIs
278
+
279
+ Whenever adding a persistent model, execute the installed SwallowKit model
280
+ creation and infrastructure generation workflow, whether or not it has custom
281
+ APIs. A hand-written model alone is not complete.
282
+
283
+ 1. Create the source-of-truth schema with
284
+ `{{runCmd}} swallowkit machine generate model <model> --overwrite never`
285
+ (the machine equivalent of `{{runCmd}} swallowkit create-model <model>`),
286
+ then author its domain fields in `shared/models/` and check its export from
287
+ `shared/index.ts`. Preserve an existing hand-written schema; do not overwrite
288
+ it just to run the template command. Model creation alone does **not**
289
+ generate a Cosmos DB container.
290
+ 2. If generated CRUD is needed, use `machine plan scaffold <model>` →
291
+ `machine apply scaffold --plan <planId>` to derive Functions, BFF, UI,
292
+ OpenAPI/native schema assets as applicable, and the container migration.
293
+ `--api-only` skips UI only; it still generates CRUD Functions and BFF routes.
294
+ If custom APIs replace CRUD, do **not** scaffold unnecessary CRUD. Instead run
295
+ `{{runCmd}} swallowkit migrations add-model <model> --dry-run`, review the
296
+ changes, then `{{runCmd}} swallowkit migrations add-model <model>` to generate
297
+ only the Cosmos DB container migration and its generation records.
298
+ 3. Inspect `machine inspect entities`, `machine inspect infra`,
299
+ `machine inspect artifacts`, and `machine inspect drift`, then run
300
+ `{{runCmd}} swallowkit machine verify project`. Check that the model's
301
+ container name and partition key match the generated Bicep under
302
+ `infra/migrations/`, its `sourceModel` entry in
303
+ `infra/migrations/manifest.json`, and `.swallowkit/artifacts.json`.
304
+ An existing baseline-owned container may need no new migration; verify its
305
+ tracked definition and wiring in `infra/main.bicep` instead. External
306
+ `connectorConfig` models use the configured connector rather than Cosmos DB;
307
+ verify that mapping instead of inventing a Cosmos container.
308
+
309
+ Do not hand-edit the checksum-locked baseline or an existing migration to add
310
+ a container; use the current migration workflow. Generation is local, not Azure
311
+ provisioning. Deployment still follows the provisioning approval gates below.
312
+
313
+ If infrastructure generation must be deferred, state the reason and the pending
314
+ container/migration work explicitly. For CRUD, pass `--skip-infra` to
315
+ `plan scaffold` / `apply scaffold` (MCP `skipInfra: true`). Nothing under `infra/`
316
+ changes and the plan reports `infra-skipped`. Generate the pending migration
317
+ later with `{{runCmd}} swallowkit migrations add-model <model>`. Even if
318
+ `verify project` passes, do not mark the persistent model complete or describe
319
+ the project as deployment-ready while required infrastructure is missing.
283
320
 
284
321
  Treat plan `warnings` as decisions to make, not noise. In particular,
285
322
  `user-scoped-data-without-auth` means the model looks per-user (for example a
@@ -22,6 +22,18 @@ source-of-truth models, subject to the current result of
22
22
  `shared/index.ts`, including manually authored models. Manual exports are
23
23
  allowed; there are no managed markers and existing content is preserved.
24
24
  - For relationships, use nested schemas rather than duplicating model shapes.
25
+ - For every new persistent model, follow the root `AGENTS.md` persistent-model
26
+ workflow even with custom APIs. Use `{{runCmd}} swallowkit machine generate model <model> --overwrite never`
27
+ (the `create-model` equivalent), preserve existing schemas, and generate the
28
+ required infrastructure. Model creation alone does not create a container.
29
+ Use plan/apply scaffold when CRUD is needed; for custom APIs replacing CRUD,
30
+ review `{{runCmd}} swallowkit migrations add-model <model> --dry-run`, then run
31
+ `{{runCmd}} swallowkit migrations add-model <model>` without unnecessary CRUD.
32
+ Check the model, container Bicep, migration manifest, and artifact ledger
33
+ correspondence, then inspect drift and verify project. For connector models,
34
+ verify the external connector mapping instead of generating a Cosmos container.
35
+ If generation is deferred, state why and what remains; do not claim completion
36
+ or deployment readiness while required infrastructure is missing.
25
37
 
26
38
  ## Optional model declarations (exact formats)
27
39
 
@@ -36,10 +36,10 @@ export function buildWorkflowDocs(runCmd: string): WorkflowDoc[] {
36
36
  title: "Add a new model (autonomous loop)",
37
37
  skillName: "swallowkit-add-model",
38
38
  skillDescription:
39
- "Add a new data model to a SwallowKit project and deterministically derive CRUD Functions, BFF routes, UI pages, and Cosmos DB infra from it using the plan/apply/verify loop. Use when asked to add a model, entity, resource, table, or a new CRUD feature.",
39
+ "Add a new persistent model, including models with custom APIs, and generate required infrastructure. Derive CRUD Functions, BFF routes, and UI only when needed using the plan/apply/verify loop. Use when asked to add a model, entity, resource, table, or a new CRUD feature.",
40
40
  content: `# Workflow: Add a new model
41
41
 
42
- Goal: add a data model and derive CRUD/BFF/UI/infra deterministically.
42
+ Goal: add a persistent model and generate its required infrastructure, even with custom APIs. A hand-written model alone is not complete.
43
43
 
44
44
  ## Responsibility boundary
45
45
 
@@ -51,15 +51,18 @@ Goal: add a data model and derive CRUD/BFF/UI/infra deterministically.
51
51
 
52
52
  1. Create the model file (deterministic template):
53
53
  \`${runCmd} swallowkit machine generate model <name> --overwrite never\`
54
+ - This is the machine equivalent of \`${runCmd} swallowkit create-model <name>\`.
55
+ Preserve existing schemas; model creation alone does not generate a Cosmos DB container.
54
56
  2. Edit \`shared/models/<name>.ts\` — add domain fields (free-form authoring).
55
57
  - Native C#/Python types follow Zod, not names: \`z.iso.datetime()\` for dates, \`z.number().int()\` for integers.
56
58
  - \`<model>Id\` fields reference a model only when it exists in \`shared/models\`; otherwise declare
57
59
  \`export const references = { fieldId: 'Model' }\` (or \`false\` to opt out).
58
- 3. Compute the change plan (writes nothing):
60
+ 3. When CRUD is needed, compute the change plan (writes nothing):
59
61
  \`${runCmd} swallowkit machine plan scaffold <name>\`
60
62
  - \`status: "requires-human"\` → review \`data.conflicts\`; only proceed with \`--approve\` if overwriting is intended.
61
63
  - Must not change Bicep/infrastructure? Add \`--skip-infra\` to plan and apply. Nothing under \`infra/\` changes and
62
64
  the plan warns \`infra-skipped\`; later run \`${runCmd} swallowkit migrations add-model <name>\` to add only the container migration.
65
+ State the reason and pending infrastructure work; a passing verify does not mean the model is complete or deployment-ready.
63
66
  - Read \`data.warnings\`. \`user-scoped-data-without-auth\` means generated CRUD would expose every user's documents;
64
67
  add auth (\`swallowkit-add-auth\`) and owner-scoped ai-authored endpoints before exposing the model.
65
68
  - \`auth-policy-without-auth\` blocks generation before file writes: configure authentication with plan/apply auth,
@@ -69,11 +72,22 @@ Goal: add a data model and derive CRUD/BFF/UI/infra deterministically.
69
72
  Single-provider \`auth.provider\` supports role lists only; named policies block with \`auth-named-policy-requires-named-scheme\`.
70
73
  - Scaffold appends missing exports to \`shared/index.ts\` for hand-authored models too.
71
74
  Manual exports are allowed; no managed markers exist in that file.
72
- 4. Apply:
75
+ - If custom APIs replace CRUD, skip scaffold (including \`--api-only\`, which still generates CRUD).
76
+ Review \`${runCmd} swallowkit migrations add-model <name> --dry-run\`, then run
77
+ \`${runCmd} swallowkit migrations add-model <name>\` to generate only the container migration and generation records.
78
+ Keep the schema exported from \`shared/index.ts\`. External connector models need their connector mapping, not a Cosmos container.
79
+ 4. Apply the reviewed CRUD scaffold plan, if needed:
73
80
  \`${runCmd} swallowkit machine apply scaffold --plan <planId>\`
74
81
  5. Verify:
75
- \`${runCmd} swallowkit machine verify project\`
82
+ - Inspect \`machine inspect entities\`, \`machine inspect infra\`, \`machine inspect artifacts\`, and \`machine inspect drift\`.
83
+ Match the model's container name and partition key to its Bicep, \`sourceModel\` in
84
+ \`infra/migrations/manifest.json\`, and \`.swallowkit/artifacts.json\`.
85
+ For a baseline-owned container, verify the tracked definition and \`infra/main.bicep\` wiring instead of requiring a new migration.
86
+ Do not hand-edit a checksum-locked baseline or an existing migration.
87
+ - Run \`${runCmd} swallowkit machine verify project\`.
76
88
  - \`summary.done: false\` → \`${runCmd} swallowkit machine explain failure\` and repair, then re-verify.
89
+ - Required infrastructure still missing? Report the reason and remaining work, not completion or deployment readiness.
90
+ Local generation does not provision Azure; follow the separate provision workflow and human approval gates.
77
91
  6. If \`dev-seeds/\` exists, update seed JSON for the new model. Seeds are only
78
92
  applied by \`${runCmd} swallowkit dev --seed-env <environment>\` — editing the
79
93
  JSON alone does nothing.