arkgate 2.8.3 → 2.9.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/CHANGELOG.md +46 -0
- package/README.md +2 -1
- package/bin/ark-check.mjs +2 -2
- package/bin/ark-layer-match.mjs +88 -5
- package/bin/ark-mcp.mjs +7 -70
- package/bin/ark-shared.mjs +88 -8
- package/bin/ark.mjs +3 -2
- package/bin/lib/architecture-scan.mjs +16 -4
- package/bin/lib/config-warnings.mjs +11 -2
- package/bin/lib/doctor-plan.mjs +20 -0
- package/bin/lib/import-resolve.mjs +133 -0
- package/bin/lib/presets.mjs +207 -11
- package/bin/lib/remediation.mjs +15 -0
- package/bin/lib/suggestions.mjs +8 -3
- package/dist/eslint/index.cjs +63 -5
- package/dist/eslint/index.cjs.map +1 -1
- package/dist/eslint/index.d.cts +33 -1
- package/dist/eslint/index.d.ts +33 -1
- package/dist/eslint/index.js +63 -5
- package/dist/eslint/index.js.map +1 -1
- package/dist/index.cjs +103 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -9
- package/dist/index.d.ts +21 -9
- package/dist/index.js +103 -14
- package/dist/index.js.map +1 -1
- package/dist/nestjs/index.cjs +78 -4
- package/dist/nestjs/index.cjs.map +1 -1
- package/dist/nestjs/index.d.cts +1 -1
- package/dist/nestjs/index.d.ts +1 -1
- package/dist/nestjs/index.js +78 -4
- package/dist/nestjs/index.js.map +1 -1
- package/dist/runtime/index.cjs +103 -14
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +103 -14
- package/dist/runtime/index.js.map +1 -1
- package/dist/{types-CSJhEOk2.d.cts → types-D6Q8WHes.d.cts} +7 -0
- package/dist/{types-CSJhEOk2.d.ts → types-D6Q8WHes.d.ts} +7 -0
- package/docs/agent-guide.md +55 -4
- package/package.json +3 -1
- package/server.json +2 -2
- package/templates/architecture-playbook.json +65 -1
- package/templates/policy-packs/enthusiast-ddd-bounded-contexts.json +19 -0
- package/templates/policy-packs/enthusiast-ui-surface.json +18 -0
- package/templates/policy-packs/enthusiast-vertical-slice.json +18 -0
- package/templates/skills/ark-adopt.md +4 -0
- package/templates/skills/ark-architect.md +5 -1
- package/templates/skills/ark-autopilot.md +3 -1
- package/templates/skills/ark-fix.md +3 -0
- package/templates/skills/ark-place.md +7 -0
- package/templates/skills/ark-think.md +43 -0
|
@@ -274,6 +274,13 @@ interface ArchitectureRule {
|
|
|
274
274
|
to: string;
|
|
275
275
|
allowed: boolean;
|
|
276
276
|
message?: string;
|
|
277
|
+
/**
|
|
278
|
+
* When true with allowed:false: deny only when slice ids differ (same or cross layer).
|
|
279
|
+
* Requires path resolution at check time (write-gate / CI). Matches domain EdgeRule.
|
|
280
|
+
*/
|
|
281
|
+
peerIsolation?: boolean;
|
|
282
|
+
/** Parent folder names that own the slice id as the next path segment. */
|
|
283
|
+
sliceFolders?: string[];
|
|
277
284
|
}
|
|
278
285
|
interface ArchitectureProfile {
|
|
279
286
|
name: string;
|
|
@@ -274,6 +274,13 @@ interface ArchitectureRule {
|
|
|
274
274
|
to: string;
|
|
275
275
|
allowed: boolean;
|
|
276
276
|
message?: string;
|
|
277
|
+
/**
|
|
278
|
+
* When true with allowed:false: deny only when slice ids differ (same or cross layer).
|
|
279
|
+
* Requires path resolution at check time (write-gate / CI). Matches domain EdgeRule.
|
|
280
|
+
*/
|
|
281
|
+
peerIsolation?: boolean;
|
|
282
|
+
/** Parent folder names that own the slice id as the next path segment. */
|
|
283
|
+
sliceFolders?: string[];
|
|
277
284
|
}
|
|
278
285
|
interface ArchitectureProfile {
|
|
279
286
|
name: string;
|
package/docs/agent-guide.md
CHANGED
|
@@ -13,11 +13,12 @@ Before generating project structure, agents should read the **tool-agnostic appl
|
|
|
13
13
|
shape** that fits the repository — not a vendor stack label. Ark ships a versioned playbook
|
|
14
14
|
at `templates/architecture-playbook.json` (also in the npm package under `templates/`).
|
|
15
15
|
|
|
16
|
-
Each of the
|
|
16
|
+
Each of the twelve archetypes (`crud-product`, `api-backend`, `frontend-surface`,
|
|
17
17
|
`library-sdk`, `cli-utility`, `worker-pipeline`, `event-coordinator`,
|
|
18
|
-
`integration-bridge`, `multi-app-workspace`, `prototype-spike
|
|
18
|
+
`integration-bridge`, `multi-app-workspace`, `prototype-spike`,
|
|
19
|
+
`vertical-slice-product`, `ddd-bounded-contexts`) maps to:
|
|
19
20
|
|
|
20
|
-
- a named Ark preset (`hexagonal`, `layered`, `feature-sliced`, or `
|
|
21
|
+
- a named Ark preset (`hexagonal`, `layered`, `feature-sliced`, `monorepo`, `ui-surface`, `vertical-slice`, or `ddd-bounded-contexts`),
|
|
21
22
|
- phased 11-layer adoption (phase 1–3),
|
|
22
23
|
- plain-language analogy and anti-patterns,
|
|
23
24
|
- optional book references for depth only.
|
|
@@ -99,7 +100,7 @@ Polyglot repos: Ark only governs TypeScript/JS. Point include at package roots t
|
|
|
99
100
|
|
|
100
101
|
### Presets
|
|
101
102
|
|
|
102
|
-
- `hexagonal` / `layered` / `feature-sliced` / `monorepo` / **`ui-surface`** (UI/Vite/Remotion-style
|
|
103
|
+
- `hexagonal` / `layered` / `feature-sliced` / `monorepo` / **`ui-surface`** (UI/Vite/Remotion-style) / **`vertical-slice`** (features/* + peerIsolation) / **`ddd-bounded-contexts`** (contexts/*/domain|application|infra + shared kernel)
|
|
103
104
|
|
|
104
105
|
### Cycle policy
|
|
105
106
|
|
|
@@ -341,6 +342,56 @@ Use `ark-check` in CI for repository-level checks that need real file paths:
|
|
|
341
342
|
npx ark-check --root . --config ark.config.json
|
|
342
343
|
```
|
|
343
344
|
|
|
345
|
+
### Monorepo tooling (Turborepo / Nx)
|
|
346
|
+
|
|
347
|
+
Use **`ark init --preset monorepo`** (or archetype `multi-app-workspace`). Ark does **not**
|
|
348
|
+
reimplement the Nx project graph. It maps conventional trees:
|
|
349
|
+
|
|
350
|
+
| Tooling | Typical roots | Ark `include` fallback |
|
|
351
|
+
|---------|---------------|------------------------|
|
|
352
|
+
| Turborepo | `apps/`, `packages/` | `packages`, `apps`, `libs` |
|
|
353
|
+
| Nx | `apps/`, `libs/` | same |
|
|
354
|
+
|
|
355
|
+
Layers still match by folder **name** (`**/domain/**`, `**/application/**`, …) across packages.
|
|
356
|
+
Doctor surfaces `turbo.json` / `nx.json` as monorepo tooling hints.
|
|
357
|
+
|
|
358
|
+
### Nest modular monolith
|
|
359
|
+
|
|
360
|
+
Prefer **`hexagonal`** with Nest filename overlays (`*.controller.ts` / services). If you
|
|
361
|
+
literally have `src/contexts/*` bounded contexts, use **`ddd-bounded-contexts`**. Do not
|
|
362
|
+
invent a separate Nest-only engine — modules map to `src/**/domain/**` style globs already.
|
|
363
|
+
|
|
364
|
+
### Clean / Onion aliases
|
|
365
|
+
|
|
366
|
+
`ark init --preset clean-architecture` and `--preset onion-architecture` are **aliases** of
|
|
367
|
+
`hexagonal` (same layer matrix). Prefer the hexagonal name in docs; aliases exist for
|
|
368
|
+
discoverability.
|
|
369
|
+
|
|
370
|
+
### Peer isolation (cross-slice bans)
|
|
371
|
+
|
|
372
|
+
Classic rules deny **layer A → layer B** always. **Same-layer is always allowed** unless a
|
|
373
|
+
rule sets `peerIsolation: true`.
|
|
374
|
+
|
|
375
|
+
`peerIsolation: true` + `allowed: false` means: deny **only when importer and importee
|
|
376
|
+
resolve to different slice ids** (works for same-layer *and* cross-layer pairs). Same-slice
|
|
377
|
+
edges are not denied by that rule.
|
|
378
|
+
|
|
379
|
+
```json
|
|
380
|
+
{
|
|
381
|
+
"from": "Features",
|
|
382
|
+
"to": "Features",
|
|
383
|
+
"allowed": false,
|
|
384
|
+
"peerIsolation": true
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
- **Denied:** `src/features/auth/**` → `src/features/payments/**` (different slice id).
|
|
389
|
+
- **Allowed:** same-slice imports; classic non-peerIsolation denies still apply across layers.
|
|
390
|
+
- **`sliceFolders`:** optional parent segments (default: inferred from layer globs).
|
|
391
|
+
- **Fail-open:** missing paths or unclassifiable slices → do not deny via peerIsolation.
|
|
392
|
+
- Enforced by `ark-check`, `arkgate/eslint`, and `ark-mcp` when paths resolve.
|
|
393
|
+
- Fixes are **judgment** (not mechanical-safe).
|
|
394
|
+
|
|
344
395
|
Agents can generate a config from the project's actual directory layout instead of inventing layer mappings:
|
|
345
396
|
|
|
346
397
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arkgate",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"description": "ArkGate — architecture co-pilot for AI TypeScript (write gate, CI gate, plan/loop)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -73,6 +73,8 @@
|
|
|
73
73
|
"check:layer-match": "node scripts/generate-layer-match.mjs --check",
|
|
74
74
|
"generate:cli-pure": "node scripts/generate-cli-pure.mjs",
|
|
75
75
|
"check:cli-pure": "node scripts/generate-cli-pure.mjs --check",
|
|
76
|
+
"check:gallery-starters": "node scripts/check-gallery-starters.mjs",
|
|
77
|
+
"generate:gallery-starters": "node scripts/check-gallery-starters.mjs --write",
|
|
76
78
|
"test:ts-compat": "node scripts/ts-compat-matrix.mjs 5.9.3 && node scripts/ts-compat-matrix.mjs 6.0.3 && node scripts/ts-compat-matrix.mjs 7.0.2",
|
|
77
79
|
"eval:agent": "node eval/run.mjs",
|
|
78
80
|
"eval:corpus": "node eval/validate-corpus.mjs",
|
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/pedroknigge/arkgate",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.9.0",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "arkgate",
|
|
14
|
-
"version": "2.
|
|
14
|
+
"version": "2.9.0",
|
|
15
15
|
"runtimeHint": "npx",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
@@ -299,7 +299,8 @@
|
|
|
299
299
|
}
|
|
300
300
|
],
|
|
301
301
|
"detectionSignals": {
|
|
302
|
-
"workspaces": 10
|
|
302
|
+
"workspaces": 10,
|
|
303
|
+
"monorepoTooling": 4
|
|
303
304
|
},
|
|
304
305
|
"negativeSignals": {
|
|
305
306
|
"cli": 2,
|
|
@@ -334,6 +335,69 @@
|
|
|
334
335
|
"workflows": 4,
|
|
335
336
|
"jobs": 3
|
|
336
337
|
}
|
|
338
|
+
},
|
|
339
|
+
"vertical-slice-product": {
|
|
340
|
+
"label": "Feature-first product (vertical slices)",
|
|
341
|
+
"preset": "vertical-slice",
|
|
342
|
+
"phases": {
|
|
343
|
+
"1": ["Features", "Shared"],
|
|
344
|
+
"2": ["Lib", "App"],
|
|
345
|
+
"3": []
|
|
346
|
+
},
|
|
347
|
+
"analogy": "A food truck menu: each dish (feature) is cooked end-to-end; shared utensils stay in the common drawer — never borrow another dish's mise en place.",
|
|
348
|
+
"antiPatterns": [
|
|
349
|
+
"Importing code from features/A into features/B",
|
|
350
|
+
"Dumping business rules into shared/ just to avoid a cross-slice import"
|
|
351
|
+
],
|
|
352
|
+
"books": [
|
|
353
|
+
{
|
|
354
|
+
"title": "Vertical Slice Architecture",
|
|
355
|
+
"author": "Jimmy Bogard (community)",
|
|
356
|
+
"for": "organizing by use-case instead of technical layer only"
|
|
357
|
+
}
|
|
358
|
+
],
|
|
359
|
+
"detectionSignals": {
|
|
360
|
+
"verticalSliceLayout": 10,
|
|
361
|
+
"ui": 2,
|
|
362
|
+
"fullStackProduct": 2
|
|
363
|
+
},
|
|
364
|
+
"negativeSignals": {
|
|
365
|
+
"dddBoundedContextsLayout": 6,
|
|
366
|
+
"domainHeavy": 4,
|
|
367
|
+
"workspaces": 3,
|
|
368
|
+
"cli": 4
|
|
369
|
+
}
|
|
370
|
+
},
|
|
371
|
+
"ddd-bounded-contexts": {
|
|
372
|
+
"label": "Multiple business domains (bounded contexts)",
|
|
373
|
+
"preset": "ddd-bounded-contexts",
|
|
374
|
+
"phases": {
|
|
375
|
+
"1": ["DomainModel", "ApplicationOrchestration", "SharedKernel"],
|
|
376
|
+
"2": ["PersistenceAdapters", "PresentationAdapters"],
|
|
377
|
+
"3": []
|
|
378
|
+
},
|
|
379
|
+
"analogy": "Separate city districts: each has its own shops and rules; only the shared square (kernel) and mail (events) connect them — never dig tunnels between private basements.",
|
|
380
|
+
"antiPatterns": [
|
|
381
|
+
"One context importing another context's domain model",
|
|
382
|
+
"A god shared/ folder that re-exports every context"
|
|
383
|
+
],
|
|
384
|
+
"books": [
|
|
385
|
+
{
|
|
386
|
+
"title": "Implementing Domain-Driven Design",
|
|
387
|
+
"author": "Vernon",
|
|
388
|
+
"for": "bounded contexts, shared kernel, and integration patterns"
|
|
389
|
+
}
|
|
390
|
+
],
|
|
391
|
+
"detectionSignals": {
|
|
392
|
+
"dddBoundedContextsLayout": 12,
|
|
393
|
+
"domain": 3,
|
|
394
|
+
"domainHeavy": 2
|
|
395
|
+
},
|
|
396
|
+
"negativeSignals": {
|
|
397
|
+
"verticalSliceLayout": 4,
|
|
398
|
+
"tinyTree": 3,
|
|
399
|
+
"uiOnly": 4
|
|
400
|
+
}
|
|
337
401
|
}
|
|
338
402
|
}
|
|
339
403
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "enthusiast-ddd-bounded-contexts",
|
|
3
|
+
"preset": "ddd-bounded-contexts",
|
|
4
|
+
"variant": "enthusiast",
|
|
5
|
+
"label": "DDD bounded contexts — enthusiast",
|
|
6
|
+
"summary": "One folder per bounded context with domain / application / infrastructure / presentation. Shared kernel only for truly shared types; contexts do not import each other.",
|
|
7
|
+
"phases": {
|
|
8
|
+
"1": ["DomainModel", "ApplicationOrchestration", "SharedKernel"],
|
|
9
|
+
"2": ["PersistenceAdapters", "PresentationAdapters"],
|
|
10
|
+
"3": []
|
|
11
|
+
},
|
|
12
|
+
"layerDescriptions": {
|
|
13
|
+
"DomainModel": "Per-context pure business rules and entities. No I/O.",
|
|
14
|
+
"ApplicationOrchestration": "Per-context use cases that call domain through ports.",
|
|
15
|
+
"PresentationAdapters": "Controllers, HTTP, or UI entrypoints for a context.",
|
|
16
|
+
"PersistenceAdapters": "Repository and external I/O implementations for a context.",
|
|
17
|
+
"SharedKernel": "Cross-context primitives only — keep this thin."
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "enthusiast-ui-surface",
|
|
3
|
+
"preset": "ui-surface",
|
|
4
|
+
"variant": "enthusiast",
|
|
5
|
+
"label": "UI surface — enthusiast",
|
|
6
|
+
"summary": "Presentation-heavy trees (hooks, components, routes) with optional domain and data clients. Good for Vite/Next UI packages.",
|
|
7
|
+
"phases": {
|
|
8
|
+
"1": ["PresentationAdapters", "ApplicationOrchestration"],
|
|
9
|
+
"2": ["DomainModel", "PersistenceAdapters"],
|
|
10
|
+
"3": []
|
|
11
|
+
},
|
|
12
|
+
"layerDescriptions": {
|
|
13
|
+
"PresentationAdapters": "UI, routes, hooks, and components.",
|
|
14
|
+
"ApplicationOrchestration": "Server actions and feature orchestration when present.",
|
|
15
|
+
"DomainModel": "Shared types and pure view-models.",
|
|
16
|
+
"PersistenceAdapters": "Client data access and external API adapters."
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "enthusiast-vertical-slice",
|
|
3
|
+
"preset": "vertical-slice",
|
|
4
|
+
"variant": "enthusiast",
|
|
5
|
+
"label": "Vertical slice — enthusiast",
|
|
6
|
+
"summary": "Organize by feature slices under src/features. Shared and lib are the only escape hatches; sibling features must not import each other.",
|
|
7
|
+
"phases": {
|
|
8
|
+
"1": ["Features", "Shared"],
|
|
9
|
+
"2": ["Lib", "App"],
|
|
10
|
+
"3": []
|
|
11
|
+
},
|
|
12
|
+
"layerDescriptions": {
|
|
13
|
+
"Features": "One folder per feature/use-case — API, UI, hooks, types together. No imports from sibling features.",
|
|
14
|
+
"Shared": "Reusable primitives (UI kit, utils, types) with zero feature knowledge.",
|
|
15
|
+
"Lib": "Infrastructure clients (db, HTTP, env) shared across features.",
|
|
16
|
+
"App": "App shell, routing, and composition root."
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -32,7 +32,11 @@ Ark protects the **boundary around** a framework, not its internals. Nest/DI pub
|
|
|
32
32
|
## Steps
|
|
33
33
|
|
|
34
34
|
1. **Config** — missing → `ark-check --init` (detection). Keep existing unless asked to regenerate.
|
|
35
|
+
If the tree is `src/features` + `shared`/`lib` **without** FSD `entities`/`widgets`, prefer
|
|
36
|
+
`vertical-slice` (or pack `enthusiast-vertical-slice`) — do **not** force hexagonal.
|
|
37
|
+
If `src/contexts` or `src/bounded-contexts` exists, prefer `ddd-bounded-contexts`.
|
|
35
38
|
2. **Check + diagnose** — `summary.concentrated` / dominant edge → fix contract first, don’t freeze.
|
|
39
|
+
Cross-slice / cross-context `peerIsolation` hits are judgment: extract shared or events.
|
|
36
40
|
3. **Classify ungoverned** — use coverage `suggestions`; add layers/patterns via `/ark-contract`.
|
|
37
41
|
4. **Mine business rules → manifiesto** (model job — this is why the skill exists):
|
|
38
42
|
- Scan for loose domain: validators, pricing/policy functions, `can*`/`calculate*`, magic business constants, publish/intent strings, logic in UI/hooks that belongs in Domain.
|
|
@@ -70,6 +70,8 @@ package manager (`pnpm exec`, `yarn`, `npx`) — match the lockfile.
|
|
|
70
70
|
| `api-backend` | `examples/api-backend-starter/` |
|
|
71
71
|
| `worker-pipeline` | `examples/worker-pipeline-starter/` |
|
|
72
72
|
| `multi-app-workspace` | `examples/multi-app-workspace-starter/` |
|
|
73
|
+
| `vertical-slice-product` | `examples/vertical-slice-starter/` |
|
|
74
|
+
| `ddd-bounded-contexts` | `examples/ddd-context-starter/` |
|
|
73
75
|
|
|
74
76
|
Say they can copy that folder as a baseline (`npm install && npm run check`).
|
|
75
77
|
For a runnable API with break exercises, mention `examples/hexagonal-order-api/`.
|
|
@@ -78,7 +80,9 @@ package manager (`pnpm exec`, `yarn`, `npx`) — match the lockfile.
|
|
|
78
80
|
## Operating rules
|
|
79
81
|
|
|
80
82
|
- Never weaken `ark.config.json`, the baseline, CI, or agent settings to pass.
|
|
81
|
-
- Never invent layers outside the 11-layer profile or named presets
|
|
83
|
+
- Never invent layers outside the 11-layer profile or named presets
|
|
84
|
+
(`hexagonal`, `layered`, `feature-sliced`, `monorepo`, `ui-surface`,
|
|
85
|
+
`vertical-slice`, `ddd-bounded-contexts`).
|
|
82
86
|
- Flag unrecognized dirs (`utils/`, `lib/`) — user must classify via `/ark-contract`.
|
|
83
87
|
- Default to smallest viable phase 1; unlock phase 2 only when the user describes need.
|
|
84
88
|
- All user-facing copy is **English**.
|
|
@@ -35,9 +35,11 @@ never weaken the gate).
|
|
|
35
35
|
|
|
36
36
|
## Flow
|
|
37
37
|
|
|
38
|
-
1. **Setup if needed** — `ark start` if no `ark.config.json`.
|
|
38
|
+
1. **Setup if needed** — `ark start` if no `ark.config.json`. Trust `--recommend` / playbook:
|
|
39
|
+
`vertical-slice-product` and `ddd-bounded-contexts` are first-class shapes (not hexagonal by default).
|
|
39
40
|
2. **Origin report** — `ark-check --report ark-report.html` (do not `--reset-origin` unless asked).
|
|
40
41
|
3. **Plan + code read** — `--plan --json`; read each step’s source/target; group by edge.
|
|
42
|
+
Treat `peerIsolation` / cross-slice steps as **judgment** (never mechanical-safe).
|
|
41
43
|
4. **Concentrated edge?** — if one edge dominates, route to `/ark-contract` with a **source-based** diagnosis (not freeze).
|
|
42
44
|
5. **Worktree preferred** — discardable git worktree when possible.
|
|
43
45
|
6. **Mechanical-safe** — only kinds from `/ark-loop` table; one step, validate, rollback.
|
|
@@ -12,6 +12,9 @@ You fix violations Ark reports. Prefer structural fixes over silencing the gate.
|
|
|
12
12
|
|
|
13
13
|
- **Greenfield:** `/ark-architect` or `ark-check --recommend` / `ark start`.
|
|
14
14
|
- **Brownfield:** `/ark-adopt` — match contract to reality; do not force a starter preset.
|
|
15
|
+
- **peerIsolation / cross-slice:** always **judgment** — extract to shared, events/ports, or redesign ownership. Never auto-apply cross-feature or cross-context moves.
|
|
16
|
+
- **`vertical-slice` ownership:** feature code stays under `src/features/<slice>/…` (no sibling-slice imports); shared primitives in `src/shared/`; infra in `src/lib/`; shell in `src/app/`. Cross-feature edges are peerIsolation — extract shared or use events/ports.
|
|
17
|
+
- **`ddd-bounded-contexts` ownership:** code under `src/contexts/<context>/{domain,application,infrastructure,presentation}/`; shared kernel only under `src/shared/kernel/`. Cross-context imports (same or cross technical layer) are peerIsolation — integrate via application APIs/events, not peer technical layers.
|
|
15
18
|
- **Default path:** `ark start` → `/ark-autopilot` → `ark-check --doctor`.
|
|
16
19
|
|
|
17
20
|
## Anti-wrapper rule (mandatory)
|
|
@@ -34,6 +34,13 @@ not a stalling question.
|
|
|
34
34
|
that matches the direction (driven/persistence vs driving/http).
|
|
35
35
|
- Reacts to events, long-running coordination (saga/workflow), scheduled
|
|
36
36
|
jobs, projections → the event/workflow layers if the config declares them.
|
|
37
|
+
- **`vertical-slice` contract:** put co-located feature code under
|
|
38
|
+
`src/features/<slice>/…` (never import a sibling slice); shared primitives
|
|
39
|
+
under `src/shared/`; infra under `src/lib/`; shell under `src/app/`.
|
|
40
|
+
- **`ddd-bounded-contexts` contract:** put code under
|
|
41
|
+
`src/contexts/<context>/{domain,application,infrastructure,presentation}/`;
|
|
42
|
+
shared kernel only under `src/shared/kernel/`. Cross-context imports at the
|
|
43
|
+
same technical layer are peerIsolation violations.
|
|
37
44
|
3. **Answer concretely**: layer name, target directory (from the layer's
|
|
38
45
|
`patterns`), intent-name prefix if the layer declares `intentPrefixes`, and
|
|
39
46
|
which layers it may/may not import (from `rules`).
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ark-think
|
|
3
|
+
description: "Host-side architectural reasoning within the Ark contract — trade-offs, evolution, design options. No gate bypass. No package LLM call."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /ark-think — Architectural reasoning (host LLM only)
|
|
7
|
+
|
|
8
|
+
You are the user's architecture thinking partner **inside** the project's Ark contract.
|
|
9
|
+
This skill does **not** call any LLM API from the arkgate package. **You** (the host agent)
|
|
10
|
+
reason; the write-gate and CI remain deterministic.
|
|
11
|
+
|
|
12
|
+
## When to use
|
|
13
|
+
|
|
14
|
+
- Design trade-offs before writing code
|
|
15
|
+
- "Should this be a new layer or a feature slice?"
|
|
16
|
+
- Evolving brownfield layout toward a named preset
|
|
17
|
+
- Explaining why a peerIsolation or layer rule exists
|
|
18
|
+
|
|
19
|
+
## Steps
|
|
20
|
+
|
|
21
|
+
1. **Load the contract** — `ark.config.json`, MCP `ark://manifest` if available, and
|
|
22
|
+
`ark-check --coverage --json` / `--doctor` for honesty about governed%.
|
|
23
|
+
2. **Name the active shape** — which preset/archetype fits (hexagonal, vertical-slice,
|
|
24
|
+
ddd-bounded-contexts, feature-sliced, monorepo, …). If none, run `--recommend --json`.
|
|
25
|
+
3. **Reason within bounds** — propose options that **stay enforceable** by the gate.
|
|
26
|
+
Prefer concrete paths and import rules over abstract diagrams.
|
|
27
|
+
4. **Surface hard lines** — never suggest: weakening `ark.config.json` to pass, silent
|
|
28
|
+
judgment auto-apply, codemod engines, or skipping write-gate/CI.
|
|
29
|
+
5. **Hand off** — for placement use `/ark-place`; for config edits `/ark-contract`; for
|
|
30
|
+
bulk debt `/ark-loop` / `/ark-autopilot`; for violations `/ark-fix`.
|
|
31
|
+
|
|
32
|
+
## Output format
|
|
33
|
+
|
|
34
|
+
- **Context:** 2–3 sentences on current contract + shape
|
|
35
|
+
- **Options:** 2–3 alternatives with trade-offs (coupling, testability, AI-agent safety)
|
|
36
|
+
- **Recommendation:** one option + why it is enforceable today
|
|
37
|
+
- **Next command:** exact `ark-check` / skill to run next
|
|
38
|
+
|
|
39
|
+
## Related
|
|
40
|
+
|
|
41
|
+
- Greenfield shape: `/ark-architect`
|
|
42
|
+
- Brownfield: `/ark-adopt`
|
|
43
|
+
- Explain existing: `/ark-explain`
|