arkgate 2.8.3 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +2 -1
  3. package/bin/ark-check.mjs +21 -3
  4. package/bin/ark-layer-match.mjs +88 -5
  5. package/bin/ark-mcp.mjs +7 -70
  6. package/bin/ark-shared.mjs +88 -8
  7. package/bin/ark.mjs +134 -22
  8. package/bin/lib/agent-gates.mjs +37 -3
  9. package/bin/lib/architecture-scan.mjs +16 -4
  10. package/bin/lib/config-warnings.mjs +11 -2
  11. package/bin/lib/doctor-plan.mjs +20 -0
  12. package/bin/lib/field-install.mjs +334 -0
  13. package/bin/lib/import-resolve.mjs +133 -0
  14. package/bin/lib/presets.mjs +207 -11
  15. package/bin/lib/remediation.mjs +15 -0
  16. package/bin/lib/suggestions.mjs +8 -3
  17. package/dist/eslint/index.cjs +63 -5
  18. package/dist/eslint/index.cjs.map +1 -1
  19. package/dist/eslint/index.d.cts +33 -1
  20. package/dist/eslint/index.d.ts +33 -1
  21. package/dist/eslint/index.js +63 -5
  22. package/dist/eslint/index.js.map +1 -1
  23. package/dist/index.cjs +103 -14
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +21 -9
  26. package/dist/index.d.ts +21 -9
  27. package/dist/index.js +103 -14
  28. package/dist/index.js.map +1 -1
  29. package/dist/nestjs/index.cjs +78 -4
  30. package/dist/nestjs/index.cjs.map +1 -1
  31. package/dist/nestjs/index.d.cts +1 -1
  32. package/dist/nestjs/index.d.ts +1 -1
  33. package/dist/nestjs/index.js +78 -4
  34. package/dist/nestjs/index.js.map +1 -1
  35. package/dist/runtime/index.cjs +103 -14
  36. package/dist/runtime/index.cjs.map +1 -1
  37. package/dist/runtime/index.d.cts +1 -1
  38. package/dist/runtime/index.d.ts +1 -1
  39. package/dist/runtime/index.js +103 -14
  40. package/dist/runtime/index.js.map +1 -1
  41. package/dist/{types-CSJhEOk2.d.cts → types-D6Q8WHes.d.cts} +7 -0
  42. package/dist/{types-CSJhEOk2.d.ts → types-D6Q8WHes.d.ts} +7 -0
  43. package/docs/agent-guide.md +55 -4
  44. package/package.json +3 -1
  45. package/server.json +2 -2
  46. package/templates/architecture-playbook.json +65 -1
  47. package/templates/policy-packs/enthusiast-ddd-bounded-contexts.json +19 -0
  48. package/templates/policy-packs/enthusiast-ui-surface.json +18 -0
  49. package/templates/policy-packs/enthusiast-vertical-slice.json +18 -0
  50. package/templates/skills/ark-adopt.md +4 -0
  51. package/templates/skills/ark-architect.md +5 -1
  52. package/templates/skills/ark-autopilot.md +10 -1
  53. package/templates/skills/ark-fix.md +3 -0
  54. package/templates/skills/ark-place.md +7 -0
  55. 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;
@@ -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 ten archetypes (`crud-product`, `api-backend`, `frontend-surface`,
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`) maps to:
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 `monorepo`),
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 hooks+lib+routes+components)
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.8.3",
3
+ "version": "2.9.1",
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.8.3",
9
+ "version": "2.9.1",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "arkgate",
14
- "version": "2.8.3",
14
+ "version": "2.9.1",
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,17 @@ never weaken the gate).
35
35
 
36
36
  ## Flow
37
37
 
38
- 1. **Setup if needed** — `ark start` if no `ark.config.json`.
38
+ 0. **False-green soft block (mandatory before victory)** — Run `ark-check --doctor` (or `--coverage`).
39
+ If Domain/Persistence (or similar cores) are **empty** while Application-class globs still cover
40
+ I/O dirs (`airtable`, `supabase`, `prisma`, `drizzle`, `repositories`, …), **do not** claim
41
+ ENFORCE / `goal.met` from type-only cleanup alone. Route to **`/ark-adopt`** or **`/ark-contract`**
42
+ first: reclassify real persistence/auth out of Application. Doctor gap id:
43
+ `contract-false-green-io-under-application`.
44
+ 1. **Setup if needed** — `ark start` if no `ark.config.json`. Trust `--recommend` / playbook:
45
+ `vertical-slice-product` and `ddd-bounded-contexts` are first-class shapes (not hexagonal by default).
39
46
  2. **Origin report** — `ark-check --report ark-report.html` (do not `--reset-origin` unless asked).
40
47
  3. **Plan + code read** — `--plan --json`; read each step’s source/target; group by edge.
48
+ Treat `peerIsolation` / cross-slice steps as **judgment** (never mechanical-safe).
41
49
  4. **Concentrated edge?** — if one edge dominates, route to `/ark-contract` with a **source-based** diagnosis (not freeze).
42
50
  5. **Worktree preferred** — discardable git worktree when possible.
43
51
  6. **Mechanical-safe** — only kinds from `/ark-loop` table; one step, validate, rollback.
@@ -53,6 +61,7 @@ never weaken the gate).
53
61
 
54
62
  - Disable rules, broaden allows, or baseline **new** debt to “finish”.
55
63
  - Claim clean while judgment steps were skipped without user decision.
64
+ - Claim ENFORCE / “done” when doctor reports `contract-false-green-io-under-application` (adopt first).
56
65
  - Replace host Nest/DI with the runtime kernel unasked.
57
66
 
58
67
  ## Done criteria
@@ -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`