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.
- package/dist/core/project/workflows.d.ts.map +1 -1
- package/dist/core/project/workflows.js +19 -5
- package/dist/core/project/workflows.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/agent-instructions.test.ts +88 -0
- package/src/core/project/agent-templates/AGENTS.md +43 -6
- package/src/core/project/agent-templates/shared-models.instructions.md +12 -0
- package/src/core/project/workflows.ts +19 -5
|
@@ -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,
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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":";AAAA;;;;;;;;;GASG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBH,
|
|
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,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
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|