swallowkit 1.0.0-beta.8 → 1.0.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.ja.md +87 -181
- package/README.md +87 -238
- package/dist/__tests__/fixtures.d.ts +12 -0
- package/dist/__tests__/fixtures.d.ts.map +1 -1
- package/dist/__tests__/fixtures.js +101 -0
- package/dist/__tests__/fixtures.js.map +1 -1
- package/dist/cli/commands/add-auth.d.ts +15 -0
- package/dist/cli/commands/add-auth.d.ts.map +1 -0
- package/dist/cli/commands/add-auth.js +790 -0
- package/dist/cli/commands/add-auth.js.map +1 -0
- package/dist/cli/commands/add-connector.d.ts +20 -0
- package/dist/cli/commands/add-connector.d.ts.map +1 -0
- package/dist/cli/commands/add-connector.js +164 -0
- package/dist/cli/commands/add-connector.js.map +1 -0
- package/dist/cli/commands/cosmos-worktree-isolation.d.ts +25 -0
- package/dist/cli/commands/cosmos-worktree-isolation.d.ts.map +1 -0
- package/dist/cli/commands/cosmos-worktree-isolation.js +124 -0
- package/dist/cli/commands/cosmos-worktree-isolation.js.map +1 -0
- package/dist/cli/commands/create-model.d.ts +1 -4
- package/dist/cli/commands/create-model.d.ts.map +1 -1
- package/dist/cli/commands/create-model.js +20 -82
- package/dist/cli/commands/create-model.js.map +1 -1
- package/dist/cli/commands/dev-seeds.d.ts +27 -0
- package/dist/cli/commands/dev-seeds.d.ts.map +1 -1
- package/dist/cli/commands/dev-seeds.js +188 -6
- package/dist/cli/commands/dev-seeds.js.map +1 -1
- package/dist/cli/commands/dev.d.ts +30 -0
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +495 -129
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/init.d.ts +70 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +797 -768
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/scaffold.d.ts +24 -3
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.js +408 -189
- package/dist/cli/commands/scaffold.js.map +1 -1
- package/dist/cli/index.d.ts +5 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +335 -58
- package/dist/cli/index.js.map +1 -1
- package/dist/core/config.d.ts +13 -3
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +151 -8
- package/dist/core/config.js.map +1 -1
- package/dist/core/mock/connector-mock-server.d.ts +101 -0
- package/dist/core/mock/connector-mock-server.d.ts.map +1 -0
- package/dist/core/mock/connector-mock-server.js +480 -0
- package/dist/core/mock/connector-mock-server.js.map +1 -0
- package/dist/core/mock/zod-mock-generator.d.ts +14 -0
- package/dist/core/mock/zod-mock-generator.d.ts.map +1 -0
- package/dist/core/mock/zod-mock-generator.js +163 -0
- package/dist/core/mock/zod-mock-generator.js.map +1 -0
- package/dist/core/operations/auth-operations.d.ts +61 -0
- package/dist/core/operations/auth-operations.d.ts.map +1 -0
- package/dist/core/operations/auth-operations.js +272 -0
- package/dist/core/operations/auth-operations.js.map +1 -0
- package/dist/core/operations/create-model.d.ts +15 -0
- package/dist/core/operations/create-model.d.ts.map +1 -0
- package/dist/core/operations/create-model.js +185 -0
- package/dist/core/operations/create-model.js.map +1 -0
- package/dist/core/operations/file-session.d.ts +56 -0
- package/dist/core/operations/file-session.d.ts.map +1 -0
- package/dist/core/operations/file-session.js +203 -0
- package/dist/core/operations/file-session.js.map +1 -0
- package/dist/core/operations/provision-operations.d.ts +52 -0
- package/dist/core/operations/provision-operations.d.ts.map +1 -0
- package/dist/core/operations/provision-operations.js +211 -0
- package/dist/core/operations/provision-operations.js.map +1 -0
- package/dist/core/operations/runtime.d.ts +37 -0
- package/dist/core/operations/runtime.d.ts.map +1 -0
- package/dist/core/operations/runtime.js +248 -0
- package/dist/core/operations/runtime.js.map +1 -0
- package/dist/core/operations/scaffold-apply.d.ts +21 -0
- package/dist/core/operations/scaffold-apply.d.ts.map +1 -0
- package/dist/core/operations/scaffold-apply.js +57 -0
- package/dist/core/operations/scaffold-apply.js.map +1 -0
- package/dist/core/operations/scaffold-machine.d.ts +16 -0
- package/dist/core/operations/scaffold-machine.d.ts.map +1 -0
- package/dist/core/operations/scaffold-machine.js +51 -0
- package/dist/core/operations/scaffold-machine.js.map +1 -0
- package/dist/core/operations/scaffold-plan.d.ts +43 -0
- package/dist/core/operations/scaffold-plan.d.ts.map +1 -0
- package/dist/core/operations/scaffold-plan.js +187 -0
- package/dist/core/operations/scaffold-plan.js.map +1 -0
- package/dist/core/project/agent-instructions.d.ts +29 -0
- package/dist/core/project/agent-instructions.d.ts.map +1 -0
- package/dist/core/project/agent-instructions.js +160 -0
- package/dist/core/project/agent-instructions.js.map +1 -0
- package/dist/core/project/artifacts.d.ts +58 -0
- package/dist/core/project/artifacts.d.ts.map +1 -0
- package/dist/core/project/artifacts.js +179 -0
- package/dist/core/project/artifacts.js.map +1 -0
- package/dist/core/project/boundaries.d.ts +50 -0
- package/dist/core/project/boundaries.d.ts.map +1 -0
- package/dist/core/project/boundaries.js +117 -0
- package/dist/core/project/boundaries.js.map +1 -0
- package/dist/core/project/capabilities.d.ts +58 -0
- package/dist/core/project/capabilities.d.ts.map +1 -0
- package/dist/core/project/capabilities.js +135 -0
- package/dist/core/project/capabilities.js.map +1 -0
- package/dist/core/project/drift.d.ts +29 -0
- package/dist/core/project/drift.d.ts.map +1 -0
- package/dist/core/project/drift.js +188 -0
- package/dist/core/project/drift.js.map +1 -0
- package/dist/core/project/infra.d.ts +49 -0
- package/dist/core/project/infra.d.ts.map +1 -0
- package/dist/core/project/infra.js +167 -0
- package/dist/core/project/infra.js.map +1 -0
- package/dist/core/project/manifest.d.ts +92 -0
- package/dist/core/project/manifest.d.ts.map +1 -0
- package/dist/core/project/manifest.js +321 -0
- package/dist/core/project/manifest.js.map +1 -0
- package/dist/core/project/state.d.ts +15 -0
- package/dist/core/project/state.d.ts.map +1 -0
- package/dist/core/project/state.js +106 -0
- package/dist/core/project/state.js.map +1 -0
- package/dist/core/project/validation.d.ts +20 -0
- package/dist/core/project/validation.d.ts.map +1 -0
- package/dist/core/project/validation.js +274 -0
- package/dist/core/project/validation.js.map +1 -0
- package/dist/core/project/workflows.d.ts +43 -0
- package/dist/core/project/workflows.d.ts.map +1 -0
- package/dist/core/project/workflows.js +299 -0
- package/dist/core/project/workflows.js.map +1 -0
- package/dist/core/scaffold/auth-generator.d.ts +63 -0
- package/dist/core/scaffold/auth-generator.d.ts.map +1 -0
- package/dist/core/scaffold/auth-generator.js +1774 -0
- package/dist/core/scaffold/auth-generator.js.map +1 -0
- package/dist/core/scaffold/connector-functions-generator.d.ts +41 -0
- package/dist/core/scaffold/connector-functions-generator.d.ts.map +1 -0
- package/dist/core/scaffold/connector-functions-generator.js +1029 -0
- package/dist/core/scaffold/connector-functions-generator.js.map +1 -0
- package/dist/core/scaffold/functions-generator.d.ts +4 -3
- package/dist/core/scaffold/functions-generator.d.ts.map +1 -1
- package/dist/core/scaffold/functions-generator.js +405 -134
- package/dist/core/scaffold/functions-generator.js.map +1 -1
- package/dist/core/scaffold/model-parser.d.ts +20 -0
- package/dist/core/scaffold/model-parser.d.ts.map +1 -1
- package/dist/core/scaffold/model-parser.js +229 -78
- package/dist/core/scaffold/model-parser.js.map +1 -1
- package/dist/core/scaffold/native-schema-generator.d.ts +19 -0
- package/dist/core/scaffold/native-schema-generator.d.ts.map +1 -0
- package/dist/core/scaffold/native-schema-generator.js +753 -0
- package/dist/core/scaffold/native-schema-generator.js.map +1 -0
- package/dist/core/scaffold/nextjs-generator.d.ts +8 -0
- package/dist/core/scaffold/nextjs-generator.d.ts.map +1 -1
- package/dist/core/scaffold/nextjs-generator.js +152 -8
- package/dist/core/scaffold/nextjs-generator.js.map +1 -1
- package/dist/core/scaffold/ui-generator.d.ts +17 -4
- package/dist/core/scaffold/ui-generator.d.ts.map +1 -1
- package/dist/core/scaffold/ui-generator.js +174 -34
- package/dist/core/scaffold/ui-generator.js.map +1 -1
- package/dist/core/verify/index.d.ts +69 -0
- package/dist/core/verify/index.d.ts.map +1 -0
- package/dist/core/verify/index.js +412 -0
- package/dist/core/verify/index.js.map +1 -0
- package/dist/machine/contracts.d.ts +24 -0
- package/dist/machine/contracts.d.ts.map +1 -0
- package/dist/machine/contracts.js +3 -0
- package/dist/machine/contracts.js.map +1 -0
- package/dist/machine/errors.d.ts +14 -0
- package/dist/machine/errors.d.ts.map +1 -0
- package/dist/machine/errors.js +42 -0
- package/dist/machine/errors.js.map +1 -0
- package/dist/machine/index.d.ts +3 -0
- package/dist/machine/index.d.ts.map +1 -0
- package/dist/machine/index.js +566 -0
- package/dist/machine/index.js.map +1 -0
- package/dist/mcp/index.d.ts +25 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +425 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/types/index.d.ts +105 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/package-manager.d.ts +7 -11
- package/dist/utils/package-manager.d.ts.map +1 -1
- package/dist/utils/package-manager.js +42 -17
- package/dist/utils/package-manager.js.map +1 -1
- package/dist/utils/python-uv.d.ts +21 -0
- package/dist/utils/python-uv.d.ts.map +1 -0
- package/dist/utils/python-uv.js +111 -0
- package/dist/utils/python-uv.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +49 -0
- package/dist/version.js.map +1 -0
- package/package.json +15 -17
- package/src/__tests__/__snapshots__/functions-generator.test.ts.snap +716 -22
- package/src/__tests__/__snapshots__/nextjs-generator.test.ts.snap +19 -7
- package/src/__tests__/__snapshots__/ui-generator.test.ts.snap +20 -12
- package/src/__tests__/agent-instructions.test.ts +237 -0
- package/src/__tests__/agent-loop-phase34.test.ts +513 -0
- package/src/__tests__/auth.test.ts +770 -0
- package/src/__tests__/bff-swa-auth.test.ts +275 -0
- package/src/__tests__/config.test.ts +176 -3
- package/src/__tests__/connector-functions-generator.test.ts +288 -0
- package/src/__tests__/connector-mock-server.test.ts +459 -0
- package/src/__tests__/connector-model-bff.test.ts +162 -0
- package/src/__tests__/cosmos-worktree-isolation.test.ts +149 -0
- package/src/__tests__/dev-seeds.test.ts +124 -0
- package/src/__tests__/dev.test.ts +254 -0
- package/src/__tests__/file-session.test.ts +98 -0
- package/src/__tests__/fixtures.ts +101 -0
- package/src/__tests__/functions-generator.test.ts +137 -1
- package/src/__tests__/init.test.ts +386 -1
- package/src/__tests__/jest-globals.d.ts +8 -0
- package/src/__tests__/machine.test.ts +371 -0
- package/src/__tests__/mcp.test.ts +253 -0
- package/src/__tests__/model-parser.test.ts +142 -0
- package/src/__tests__/multi-auth.test.ts +160 -0
- package/src/__tests__/nextjs-generator.test.ts +8 -0
- package/src/__tests__/package-manager.test.ts +59 -4
- package/src/__tests__/plan-apply.test.ts +499 -0
- package/src/__tests__/python-uv.test.ts +48 -0
- package/src/__tests__/scaffold.test.ts +287 -24
- package/src/__tests__/tsconfig.json +15 -0
- package/src/__tests__/ui-generator.test.ts +104 -0
- package/src/__tests__/zod-mock-generator.test.ts +132 -0
- package/src/cli/commands/add-auth.ts +853 -0
- package/src/cli/commands/add-connector.ts +159 -0
- package/src/cli/commands/cosmos-worktree-isolation.ts +130 -0
- package/src/cli/commands/create-model.ts +21 -100
- package/src/cli/commands/dev-seeds.ts +278 -7
- package/src/cli/commands/dev.ts +607 -160
- package/src/cli/commands/init.ts +880 -808
- package/src/cli/commands/scaffold.ts +531 -236
- package/src/cli/index.ts +338 -60
- package/src/core/config.ts +145 -9
- package/src/core/mock/connector-mock-server.ts +555 -0
- package/src/core/mock/zod-mock-generator.ts +205 -0
- package/src/core/operations/auth-operations.ts +360 -0
- package/src/core/operations/create-model.ts +191 -0
- package/src/core/operations/file-session.ts +222 -0
- package/src/core/operations/provision-operations.ts +297 -0
- package/src/core/operations/runtime.ts +258 -0
- package/src/core/operations/scaffold-apply.ts +106 -0
- package/src/core/operations/scaffold-machine.ts +77 -0
- package/src/core/operations/scaffold-plan.ts +215 -0
- package/src/core/project/agent-instructions.ts +167 -0
- package/src/core/project/agent-templates/AGENTS.md +504 -0
- package/src/core/project/agent-templates/CLAUDE.md +31 -0
- package/src/core/project/agent-templates/azure-functions.instructions.md +22 -0
- package/src/core/project/agent-templates/bff-routes.instructions.md +18 -0
- package/src/core/project/agent-templates/copilot-instructions.md +27 -0
- package/src/core/project/agent-templates/shared-models.instructions.md +72 -0
- package/src/core/project/artifacts.ts +205 -0
- package/src/core/project/boundaries.ts +170 -0
- package/src/core/project/capabilities.ts +193 -0
- package/src/core/project/drift.ts +202 -0
- package/src/core/project/infra.ts +196 -0
- package/src/core/project/manifest.ts +402 -0
- package/src/core/project/state.ts +77 -0
- package/src/core/project/validation.ts +295 -0
- package/src/core/project/workflows.ts +295 -0
- package/src/core/scaffold/auth-generator.ts +1824 -0
- package/src/core/scaffold/connector-functions-generator.ts +1133 -0
- package/src/core/scaffold/functions-generator.ts +432 -134
- package/src/core/scaffold/model-parser.ts +244 -90
- package/src/core/scaffold/native-schema-generator.ts +904 -0
- package/src/core/scaffold/nextjs-generator.ts +174 -9
- package/src/core/scaffold/ui-generator.ts +191 -36
- package/src/core/verify/index.ts +468 -0
- package/src/machine/contracts.ts +33 -0
- package/src/machine/errors.ts +45 -0
- package/src/machine/index.ts +690 -0
- package/src/mcp/index.ts +423 -0
- package/src/types/index.ts +137 -0
- package/src/utils/package-manager.ts +41 -19
- package/src/utils/python-uv.ts +96 -0
- package/src/version.ts +13 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "functions/**"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Azure Functions — Backend Rules
|
|
6
|
+
|
|
7
|
+
The root `AGENTS.md` is the canonical contract. Azure Functions own application
|
|
8
|
+
business logic and data access, but generated handlers and contracts may be
|
|
9
|
+
deterministic. Inspect boundaries before choosing an edit location.
|
|
10
|
+
|
|
11
|
+
- Put custom behavior only in an ai-authored location reported by the current
|
|
12
|
+
boundary contract.
|
|
13
|
+
- Never directly edit deterministic handlers or generated schema assets.
|
|
14
|
+
- Keep backend contracts aligned with `shared/models/` through MCP-first
|
|
15
|
+
plan/apply, using the machine interface as fallback.
|
|
16
|
+
- Auto-generate `id`, `createdAt`, and `updatedAt` on the backend. Never trust
|
|
17
|
+
client-sent values for these fields.
|
|
18
|
+
- Container names use PascalCase plural form and default to `/id` as the
|
|
19
|
+
partition key unless the source-of-truth model says otherwise.
|
|
20
|
+
- Respect `requires-human` and run SwallowKit verification after changes.
|
|
21
|
+
|
|
22
|
+
Backend language: {{backendLanguageLabel}}.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "app/api/**"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# BFF API Routes — Rules
|
|
6
|
+
|
|
7
|
+
The root `AGENTS.md` is the canonical contract. Inspect the current
|
|
8
|
+
responsibility boundary before editing files in this layer.
|
|
9
|
+
|
|
10
|
+
- `app/api/` is a BFF/proxy layer. Never place business logic, database access,
|
|
11
|
+
or direct Cosmos DB calls here.
|
|
12
|
+
- Use `callFunction()` from `@/lib/api/call-function` to forward requests to
|
|
13
|
+
Azure Functions.
|
|
14
|
+
- Input/output validation may use schemas imported from `@{{projectName}}/shared`.
|
|
15
|
+
- Never directly edit a route reported as deterministic. Change its source of
|
|
16
|
+
truth and use MCP-first plan/apply, with the machine interface as fallback.
|
|
17
|
+
- Edit shared artifacts only outside managed markers.
|
|
18
|
+
- Respect `requires-human` and run SwallowKit verification after changes.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Copilot Instructions
|
|
2
|
+
|
|
3
|
+
This is a **SwallowKit** project.
|
|
4
|
+
|
|
5
|
+
Read and follow the root `AGENTS.md` as the canonical project contract.
|
|
6
|
+
|
|
7
|
+
SwallowKit applies during discovery, requirements clarification, specification,
|
|
8
|
+
planning, ticket decomposition, implementation, verification, and review — not
|
|
9
|
+
only during code generation.
|
|
10
|
+
|
|
11
|
+
Key rules:
|
|
12
|
+
|
|
13
|
+
- Inspect current SwallowKit capabilities instead of assuming them.
|
|
14
|
+
- Answer repository- and SwallowKit-inspectable questions before asking the human.
|
|
15
|
+
- Prefer `swallowkit_*` MCP tools when available.
|
|
16
|
+
- Otherwise use `{{runCmd}} swallowkit machine ...`.
|
|
17
|
+
- Inspect responsibility boundaries before editing framework-related files.
|
|
18
|
+
- Never hand-edit deterministic SwallowKit-managed artifacts.
|
|
19
|
+
- Add auth schemes only via plan/apply auth; never hand-write `auth.schemes`
|
|
20
|
+
in swallowkit.config (policies and `swa.allowedProviders` are hand-edited
|
|
21
|
+
after apply).
|
|
22
|
+
- Use plan/apply for deterministic generation.
|
|
23
|
+
- Respect `requires-human` states and other human approval gates.
|
|
24
|
+
- Run SwallowKit verification before completion.
|
|
25
|
+
|
|
26
|
+
Task-specific SwallowKit Agent Skills live under `.github/skills/`.
|
|
27
|
+
Agent-agnostic equivalents live under `.swallowkit/workflows/`.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "shared/models/**"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Shared Models — Zod Schema Rules
|
|
6
|
+
|
|
7
|
+
The root `AGENTS.md` is the canonical contract. Files here are ai-authored
|
|
8
|
+
source-of-truth models, subject to the current result of
|
|
9
|
+
`{{runCmd}} swallowkit machine inspect boundaries`.
|
|
10
|
+
|
|
11
|
+
## Rules
|
|
12
|
+
|
|
13
|
+
- Define Zod schemas using `zod/v4` (`import { z } from 'zod/v4'`).
|
|
14
|
+
- Use the Zod pattern where the schema constant and inferred TypeScript type
|
|
15
|
+
share the same name.
|
|
16
|
+
- `id` is a **required** string field: `id: z.string()`. Generated CRUD, UI,
|
|
17
|
+
and repositories assume `id` is always present — do NOT make it optional.
|
|
18
|
+
- `createdAt` and `updatedAt` are **optional** string fields
|
|
19
|
+
(`z.string().optional()`). The backend manages their values.
|
|
20
|
+
- Export a `displayName` string for UI display.
|
|
21
|
+
- Re-export every model from `shared/index.ts`, outside managed markers where
|
|
22
|
+
applicable.
|
|
23
|
+
- For relationships, use nested schemas rather than duplicating model shapes.
|
|
24
|
+
|
|
25
|
+
## Optional model declarations (exact formats)
|
|
26
|
+
|
|
27
|
+
These are the only declarations SwallowKit parses from a model file:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
// Cosmos DB partition key (default '/id'). Must reference a schema field.
|
|
31
|
+
export const partitionKey = '/learnerId';
|
|
32
|
+
|
|
33
|
+
// Role-based access control on generated CRUD.
|
|
34
|
+
export const authPolicy = { roles: ['admin'] };
|
|
35
|
+
// or: { read: ['user'], write: ['admin'] } or: { policy: 'adminOnly' }
|
|
36
|
+
|
|
37
|
+
// Human-readable name for generated UI.
|
|
38
|
+
export const displayName = 'Learner';
|
|
39
|
+
|
|
40
|
+
// Bind the model to a configured external connector instead of Cosmos DB.
|
|
41
|
+
export const connectorConfig = {
|
|
42
|
+
connector: 'mysql',
|
|
43
|
+
table: 'learners',
|
|
44
|
+
operations: ['list', 'get', 'create', 'update', 'delete'],
|
|
45
|
+
};
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The full machine-readable contract:
|
|
49
|
+
`{{runCmd}} swallowkit machine inspect capabilities`
|
|
50
|
+
|
|
51
|
+
After changing a model, do not manually patch generated artifacts.
|
|
52
|
+
|
|
53
|
+
## After changing a model
|
|
54
|
+
|
|
55
|
+
- The shared package is consumed via its built `dist/`. `verify project`
|
|
56
|
+
rebuilds it automatically, but if you typecheck manually, build the shared
|
|
57
|
+
package first — "no exported member" errors usually mean a stale `dist/`.
|
|
58
|
+
- If `dev-seeds/` exists, update the seed JSON. Seeds are only applied by
|
|
59
|
+
running `{{runCmd}} swallowkit dev --seed-env <environment>`; editing the
|
|
60
|
+
JSON alone does nothing.
|
|
61
|
+
|
|
62
|
+
Use the `swallowkit-modify-model` Agent Skill when available. Otherwise follow
|
|
63
|
+
`.swallowkit/workflows/modify-model.md`.
|
|
64
|
+
|
|
65
|
+
The normal agent workflow is:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
inspect drift → plan scaffold → apply scaffold → verify project
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Prefer the equivalent `swallowkit_*` MCP tools; use the machine interface as the
|
|
72
|
+
fallback. Stop for any `requires-human` result.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Artifact Ledger — `.swallowkit/artifacts.json`
|
|
3
|
+
*
|
|
4
|
+
* SwallowKit が生成・管理するファイルの所有権(Ownership)、内容ハッシュ、
|
|
5
|
+
* 生成元スキーマのハッシュ、Generator バージョンを記録する台帳。
|
|
6
|
+
* Git 管理を前提とし、Drift 検出と Plan の衝突判定の基礎データとなる。
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as fs from "fs";
|
|
10
|
+
import * as path from "path";
|
|
11
|
+
import { getSwallowKitVersion } from "../../version";
|
|
12
|
+
import {
|
|
13
|
+
ArtifactOwnership,
|
|
14
|
+
RecordedFileOperation,
|
|
15
|
+
hashFileIfExists,
|
|
16
|
+
} from "../operations/file-session";
|
|
17
|
+
|
|
18
|
+
export const SWALLOWKIT_ARTIFACTS_PATH = path.join(".swallowkit", "artifacts.json");
|
|
19
|
+
export const SWALLOWKIT_ARTIFACTS_VERSION = 1;
|
|
20
|
+
|
|
21
|
+
export type ArtifactLastOperation = "create" | "update" | "append" | "delete";
|
|
22
|
+
|
|
23
|
+
export interface ArtifactRecord {
|
|
24
|
+
/** Project-relative POSIX path */
|
|
25
|
+
path: string;
|
|
26
|
+
ownership: ArtifactOwnership;
|
|
27
|
+
/** Logical generator name, e.g. "scaffold", "create-model" */
|
|
28
|
+
generator: string;
|
|
29
|
+
generatorVersion: string;
|
|
30
|
+
/** Entity name the artifact was generated from, if any */
|
|
31
|
+
sourceModel?: string;
|
|
32
|
+
/** sha256 (LF normalized) of the source model file at generation time */
|
|
33
|
+
schemaHash?: string;
|
|
34
|
+
/** sha256 (LF normalized) of the artifact content at generation time */
|
|
35
|
+
contentHash: string;
|
|
36
|
+
generatedAt: string;
|
|
37
|
+
lastOperation: ArtifactLastOperation;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ArtifactLedger {
|
|
41
|
+
version: number;
|
|
42
|
+
swallowkitVersion: string;
|
|
43
|
+
artifacts: ArtifactRecord[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function loadArtifactLedger(projectRoot: string = process.cwd()): ArtifactLedger | null {
|
|
47
|
+
const ledgerPath = path.join(projectRoot, SWALLOWKIT_ARTIFACTS_PATH);
|
|
48
|
+
if (!fs.existsSync(ledgerPath)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(fs.readFileSync(ledgerPath, "utf-8")) as ArtifactLedger;
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function saveArtifactLedger(ledger: ArtifactLedger, projectRoot: string = process.cwd()): void {
|
|
60
|
+
const ledgerPath = path.join(projectRoot, SWALLOWKIT_ARTIFACTS_PATH);
|
|
61
|
+
fs.mkdirSync(path.dirname(ledgerPath), { recursive: true });
|
|
62
|
+
const sorted: ArtifactLedger = {
|
|
63
|
+
...ledger,
|
|
64
|
+
swallowkitVersion: getSwallowKitVersion(),
|
|
65
|
+
artifacts: [...ledger.artifacts].sort((a, b) => a.path.localeCompare(b.path)),
|
|
66
|
+
};
|
|
67
|
+
fs.writeFileSync(ledgerPath, JSON.stringify(sorted, null, 2) + "\n", "utf-8");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function findArtifactRecord(
|
|
71
|
+
ledger: ArtifactLedger | null,
|
|
72
|
+
relativePath: string
|
|
73
|
+
): ArtifactRecord | undefined {
|
|
74
|
+
return ledger?.artifacts.find((record) => record.path === relativePath);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function toLastOperation(action: RecordedFileOperation["action"]): ArtifactLastOperation | null {
|
|
78
|
+
switch (action) {
|
|
79
|
+
case "create":
|
|
80
|
+
return "create";
|
|
81
|
+
case "modify":
|
|
82
|
+
return "update";
|
|
83
|
+
case "append":
|
|
84
|
+
return "append";
|
|
85
|
+
case "delete":
|
|
86
|
+
return "delete";
|
|
87
|
+
default:
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface RecordArtifactContext {
|
|
93
|
+
/** sha256 of the source model file, when the operation batch originates from one model */
|
|
94
|
+
schemaHash?: string;
|
|
95
|
+
/** Fallback source model name */
|
|
96
|
+
sourceModel?: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* セッションで記録された操作を台帳へ反映する。
|
|
101
|
+
* - skip は台帳更新しない(既存記録があれば schemaHash のみ更新)
|
|
102
|
+
* - delete は台帳からレコードを削除する
|
|
103
|
+
*/
|
|
104
|
+
export function recordSessionOperations(
|
|
105
|
+
operations: RecordedFileOperation[],
|
|
106
|
+
context: RecordArtifactContext = {},
|
|
107
|
+
projectRoot: string = process.cwd()
|
|
108
|
+
): ArtifactLedger {
|
|
109
|
+
const ledger: ArtifactLedger = loadArtifactLedger(projectRoot) ?? {
|
|
110
|
+
version: SWALLOWKIT_ARTIFACTS_VERSION,
|
|
111
|
+
swallowkitVersion: getSwallowKitVersion(),
|
|
112
|
+
artifacts: [],
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const byPath = new Map(ledger.artifacts.map((record) => [record.path, record] as const));
|
|
116
|
+
const now = new Date().toISOString();
|
|
117
|
+
const generatorVersion = getSwallowKitVersion();
|
|
118
|
+
|
|
119
|
+
for (const operation of operations) {
|
|
120
|
+
if (operation.action === "delete") {
|
|
121
|
+
byPath.delete(operation.path);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (operation.action === "skip") {
|
|
126
|
+
const existing = byPath.get(operation.path);
|
|
127
|
+
if (existing && context.schemaHash) {
|
|
128
|
+
existing.schemaHash = context.schemaHash;
|
|
129
|
+
existing.generatorVersion = generatorVersion;
|
|
130
|
+
} else if (!existing && operation.newHash) {
|
|
131
|
+
// 内容一致でも台帳未登録なら記録し、以後の Drift 検出を可能にする
|
|
132
|
+
byPath.set(operation.path, {
|
|
133
|
+
path: operation.path,
|
|
134
|
+
ownership: operation.ownership,
|
|
135
|
+
generator: operation.generator,
|
|
136
|
+
generatorVersion,
|
|
137
|
+
sourceModel: operation.sourceModel ?? context.sourceModel,
|
|
138
|
+
schemaHash: context.schemaHash,
|
|
139
|
+
contentHash: operation.newHash,
|
|
140
|
+
generatedAt: now,
|
|
141
|
+
lastOperation: "update",
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const lastOperation = toLastOperation(operation.action);
|
|
148
|
+
if (!lastOperation || !operation.newHash) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
byPath.set(operation.path, {
|
|
153
|
+
path: operation.path,
|
|
154
|
+
ownership: operation.ownership,
|
|
155
|
+
generator: operation.generator,
|
|
156
|
+
generatorVersion,
|
|
157
|
+
sourceModel: operation.sourceModel ?? context.sourceModel,
|
|
158
|
+
schemaHash: context.schemaHash,
|
|
159
|
+
contentHash: operation.newHash,
|
|
160
|
+
generatedAt: now,
|
|
161
|
+
lastOperation,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const updated: ArtifactLedger = {
|
|
166
|
+
version: SWALLOWKIT_ARTIFACTS_VERSION,
|
|
167
|
+
swallowkitVersion: generatorVersion,
|
|
168
|
+
artifacts: Array.from(byPath.values()),
|
|
169
|
+
};
|
|
170
|
+
saveArtifactLedger(updated, projectRoot);
|
|
171
|
+
return updated;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface InspectedArtifact extends ArtifactRecord {
|
|
175
|
+
exists: boolean;
|
|
176
|
+
/** true when the current on-disk content differs from the recorded contentHash */
|
|
177
|
+
modified: boolean;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function inspectArtifacts(projectRoot: string = process.cwd()): {
|
|
181
|
+
ledgerFound: boolean;
|
|
182
|
+
swallowkitVersion: string | null;
|
|
183
|
+
artifacts: InspectedArtifact[];
|
|
184
|
+
} {
|
|
185
|
+
const ledger = loadArtifactLedger(projectRoot);
|
|
186
|
+
if (!ledger) {
|
|
187
|
+
return { ledgerFound: false, swallowkitVersion: null, artifacts: [] };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const artifacts = ledger.artifacts.map((record) => {
|
|
191
|
+
const absolutePath = path.join(projectRoot, record.path);
|
|
192
|
+
const currentHash = hashFileIfExists(absolutePath);
|
|
193
|
+
return {
|
|
194
|
+
...record,
|
|
195
|
+
exists: currentHash !== null,
|
|
196
|
+
modified: currentHash !== null && currentHash !== record.contentHash,
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
ledgerFound: true,
|
|
202
|
+
swallowkitVersion: ledger.swallowkitVersion,
|
|
203
|
+
artifacts: artifacts.sort((a, b) => a.path.localeCompare(b.path)),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Responsibility Boundaries — AI の自由生成と SwallowKit の決定論的処理の責任分界点。
|
|
3
|
+
*
|
|
4
|
+
* Coding Agent / 自律ループが「どこを自由に書いてよいか」「どこは SwallowKit の
|
|
5
|
+
* plan/apply に委ねるべきか」を機械可読な契約として取得できるようにする。
|
|
6
|
+
*
|
|
7
|
+
* zone:
|
|
8
|
+
* - deterministic: SwallowKit が決定論的に生成・再生成する領域。手編集しない。
|
|
9
|
+
* - ai-authored: AI / 開発者が自由に記述する領域。SwallowKit は上書きしない。
|
|
10
|
+
* - shared: マーカー区切りの共有領域。マーカー内は SwallowKit、外は自由。
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { ArtifactOwnership } from "../operations/file-session";
|
|
14
|
+
import { inspectArtifacts } from "./artifacts";
|
|
15
|
+
|
|
16
|
+
export type BoundaryZone = "deterministic" | "ai-authored" | "shared";
|
|
17
|
+
|
|
18
|
+
export type BoundaryEditPolicy =
|
|
19
|
+
| "never-hand-edit"
|
|
20
|
+
| "regenerate-via-plan-apply"
|
|
21
|
+
| "free-edit"
|
|
22
|
+
| "edit-outside-markers";
|
|
23
|
+
|
|
24
|
+
export interface OwnershipPolicy {
|
|
25
|
+
ownership: ArtifactOwnership;
|
|
26
|
+
zone: BoundaryZone;
|
|
27
|
+
editPolicy: BoundaryEditPolicy;
|
|
28
|
+
howToChange: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface BoundaryPathRule {
|
|
32
|
+
/** Path prefix or glob-like pattern (documentation purpose; matching is prefix-based) */
|
|
33
|
+
pattern: string;
|
|
34
|
+
zone: BoundaryZone;
|
|
35
|
+
editPolicy: BoundaryEditPolicy;
|
|
36
|
+
description: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface BoundaryArtifact {
|
|
40
|
+
path: string;
|
|
41
|
+
ownership: ArtifactOwnership;
|
|
42
|
+
zone: BoundaryZone;
|
|
43
|
+
editPolicy: BoundaryEditPolicy;
|
|
44
|
+
generator: string;
|
|
45
|
+
sourceModel?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface BoundariesContract {
|
|
49
|
+
contractVersion: number;
|
|
50
|
+
summary: string;
|
|
51
|
+
ownershipPolicies: OwnershipPolicy[];
|
|
52
|
+
/** 台帳に載っていないパスの既定規約 */
|
|
53
|
+
conventionRules: BoundaryPathRule[];
|
|
54
|
+
/** 台帳に記録された生成物ごとの解決結果 */
|
|
55
|
+
artifacts: BoundaryArtifact[];
|
|
56
|
+
guidance: string[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const OWNERSHIP_POLICIES: OwnershipPolicy[] = [
|
|
60
|
+
{
|
|
61
|
+
ownership: "managed",
|
|
62
|
+
zone: "deterministic",
|
|
63
|
+
editPolicy: "regenerate-via-plan-apply",
|
|
64
|
+
howToChange:
|
|
65
|
+
"Edit the source model (shared/models/*.ts) or configuration, then run `swallowkit machine plan scaffold <model>` and `apply scaffold`. Hand-edits are detected as drift and require --approve to overwrite.",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
ownership: "generated-once",
|
|
69
|
+
zone: "ai-authored",
|
|
70
|
+
editPolicy: "free-edit",
|
|
71
|
+
howToChange: "Generated once as a starting point. Edit freely; SwallowKit never regenerates it.",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
ownership: "user-owned",
|
|
75
|
+
zone: "ai-authored",
|
|
76
|
+
editPolicy: "free-edit",
|
|
77
|
+
howToChange:
|
|
78
|
+
"Owned by the developer/AI. SwallowKit only creates the initial version (e.g. model files). Edit freely; managed artifacts are regenerated from it.",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
ownership: "extension-point",
|
|
82
|
+
zone: "shared",
|
|
83
|
+
editPolicy: "edit-outside-markers",
|
|
84
|
+
howToChange:
|
|
85
|
+
"SwallowKit appends only inside marked sections (e.g. `# SwallowKit scaffold registrations`). Edit anywhere outside the markers freely; do not remove the markers.",
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
ownership: "metadata",
|
|
89
|
+
zone: "deterministic",
|
|
90
|
+
editPolicy: "never-hand-edit",
|
|
91
|
+
howToChange: "Managed entirely by SwallowKit tooling (.swallowkit/). Never hand-edit.",
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
export const CONVENTION_RULES: BoundaryPathRule[] = [
|
|
96
|
+
{
|
|
97
|
+
pattern: ".swallowkit/",
|
|
98
|
+
zone: "deterministic",
|
|
99
|
+
editPolicy: "never-hand-edit",
|
|
100
|
+
description: "SwallowKit metadata (manifest, artifact ledger, plan state). Managed by tooling only.",
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
pattern: "shared/models/",
|
|
104
|
+
zone: "ai-authored",
|
|
105
|
+
editPolicy: "free-edit",
|
|
106
|
+
description:
|
|
107
|
+
"Zod model schemas — the single source of truth. AI/developers author these freely; deterministic generation derives everything else from them.",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
pattern: "infra/main.bicep",
|
|
111
|
+
zone: "shared",
|
|
112
|
+
editPolicy: "edit-outside-markers",
|
|
113
|
+
description: "SwallowKit inserts container modules; other infrastructure edits are free.",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
pattern: "functions/function_app.py",
|
|
117
|
+
zone: "shared",
|
|
118
|
+
editPolicy: "edit-outside-markers",
|
|
119
|
+
description: "SwallowKit appends blueprint registrations under its marker; other edits are free.",
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
pattern: "shared/index.ts",
|
|
123
|
+
zone: "shared",
|
|
124
|
+
editPolicy: "edit-outside-markers",
|
|
125
|
+
description: "SwallowKit appends model exports; other exports may be added freely.",
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
pattern: "*",
|
|
129
|
+
zone: "ai-authored",
|
|
130
|
+
editPolicy: "free-edit",
|
|
131
|
+
description:
|
|
132
|
+
"Any path not recorded in the artifact ledger is AI/developer-authored. Business logic, custom pages, custom Functions, and tests belong here.",
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
const POLICY_BY_OWNERSHIP = new Map(OWNERSHIP_POLICIES.map((policy) => [policy.ownership, policy] as const));
|
|
137
|
+
|
|
138
|
+
export const BOUNDARY_GUIDANCE: string[] = [
|
|
139
|
+
"Author models and business logic freely (ai-authored zone), then let SwallowKit derive CRUD/BFF/UI/infra deterministically via plan/apply.",
|
|
140
|
+
"Never hand-edit deterministic-zone files; change the model or configuration and regenerate instead.",
|
|
141
|
+
"Use `swallowkit machine plan scaffold <model>` before applying; a plan with requiresApproval=true means a human (or explicit --approve) must confirm overwriting hand-edited files.",
|
|
142
|
+
"In shared-zone files, keep SwallowKit markers intact and edit outside them.",
|
|
143
|
+
"Run `swallowkit machine verify project` after applying changes; use `explain failure` to get repair evidence.",
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
export function inspectBoundaries(projectRoot: string = process.cwd()): BoundariesContract {
|
|
147
|
+
const inspected = inspectArtifacts(projectRoot);
|
|
148
|
+
|
|
149
|
+
const artifacts: BoundaryArtifact[] = inspected.artifacts.map((artifact) => {
|
|
150
|
+
const policy = POLICY_BY_OWNERSHIP.get(artifact.ownership);
|
|
151
|
+
return {
|
|
152
|
+
path: artifact.path,
|
|
153
|
+
ownership: artifact.ownership,
|
|
154
|
+
zone: policy?.zone ?? "ai-authored",
|
|
155
|
+
editPolicy: policy?.editPolicy ?? "free-edit",
|
|
156
|
+
generator: artifact.generator,
|
|
157
|
+
...(artifact.sourceModel ? { sourceModel: artifact.sourceModel } : {}),
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
contractVersion: 1,
|
|
163
|
+
summary:
|
|
164
|
+
"SwallowKit separates deterministic generation (models → CRUD/BFF/UI/infra via plan/apply) from AI free-form authoring (models, business logic, custom code). This contract tells agents which files belong to which side.",
|
|
165
|
+
ownershipPolicies: OWNERSHIP_POLICIES,
|
|
166
|
+
conventionRules: CONVENTION_RULES,
|
|
167
|
+
artifacts,
|
|
168
|
+
guidance: BOUNDARY_GUIDANCE,
|
|
169
|
+
};
|
|
170
|
+
}
|