ark-runtime-kernel 1.1.0 → 1.3.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.
@@ -0,0 +1,353 @@
1
+ # Ark — Agent Integration Guide
2
+
3
+ This guide describes how AI agents and codegen tools can safely interact with Ark.
4
+
5
+ ## Contract Discovery
6
+
7
+ Prefer `createStrictArkKernel()` for strict projects. It wires the registry, graph,
8
+ policies, event bus, audit trail, event contracts, outbox, observability,
9
+ projections, metadata, workflow engine, and 11-layer architecture profile:
10
+
11
+ ```ts
12
+ import {
13
+ createStrictArkKernel,
14
+ } from 'ark-runtime-kernel';
15
+
16
+ const ark = createStrictArkKernel();
17
+ // ... define intents, event contracts, metadata, projections, and workflows through ark.*
18
+
19
+ const contract = ark.manifest().toJSON();
20
+ // contract.intents, policies, entities, graph, architecture, eventContracts,
21
+ // contract.observability, projections
22
+ ```
23
+
24
+ Agents should read `contract` and `ark.observability.report()` before generating or modifying code.
25
+
26
+ ## Naming Conventions
27
+
28
+ | Prefix | Layer | Example |
29
+ |--------|-------|---------|
30
+ | `Domain.*` | Domain events & entities | `Domain.Order.OrderPlaced` |
31
+ | `Application.*` | Use cases / orchestration | `Application.PlaceOrder` |
32
+ | `Adapter.Persistence.*` | Persistence adapters | `Adapter.Persistence.OrderRepo` |
33
+ | `Adapter.Integration.*` | External integrations | `Adapter.Integration.PaymentGateway.Charge` |
34
+ | `Workflow.*` | Sagas / long-running processes | `Workflow.OrderFulfillment` |
35
+ | `Job.*` | Background jobs / scheduling | `Job.InventoryRebuild` |
36
+ | `Presentation.*` | UI/API adapters | `Presentation.Api.PlaceOrder` |
37
+ | `Reporting.*` | Read models / projections | `Reporting.OrderSummary` |
38
+ | `Metadata.*` | Metadata and extension contracts | `Metadata.OrderSchema` |
39
+ | `Security.*`, `Audit.*`, `Observability.*` | Cross-cutting concerns | `Audit.OrderHistory` |
40
+ | `Kernel.*` | Ark-owned governance signals | `Kernel.PolicyViolation` |
41
+
42
+ Declare relationships at definition time:
43
+
44
+ ```ts
45
+ registry.define('Application.PlaceOrder', {
46
+ dependsOn: ['Domain.Order.OrderPlaced'],
47
+ produces: ['Domain.Order.OrderPlaced'],
48
+ });
49
+ ```
50
+
51
+ Strict kernels also enforce the **observed** producer→event layer flow at publish time
52
+ (`enforceObservedLayerFlow: 'hard'` by default). If a published event's real source and
53
+ intent cross a forbidden layer boundary — e.g. a `Adapter.Persistence.*` source producing
54
+ a `Domain.*` event — the publish throws `ObservedLayerFlowViolationError` before the event
55
+ reaches history, outbox, or subscribers. Use `'soft'` to record `layer.observedViolation`
56
+ trace/audit records without blocking, or `'off'` to disable. Agents should name the event's
57
+ `source` honestly: it is checked against the layer matrix, not just the intent name.
58
+
59
+ Strict kernels also require published events to have a registered source intent
60
+ and a matching event contract:
61
+
62
+ ```ts
63
+ const OrderPlaced = registry.define<
64
+ 'Domain.Order.OrderPlaced',
65
+ { orderId: string; amount: number }
66
+ >('Domain.Order.OrderPlaced');
67
+
68
+ registry.define('Application.PlaceOrder', {
69
+ produces: ['Domain.Order.OrderPlaced'],
70
+ });
71
+
72
+ ark.eventContracts.register({
73
+ intent: 'Domain.Order.OrderPlaced',
74
+ version: '1',
75
+ allowAdditionalFields: false,
76
+ schema: {
77
+ orderId: { type: 'string', required: true },
78
+ amount: { type: 'number', required: true },
79
+ },
80
+ });
81
+
82
+ const publisher = ark.publisher('Application.PlaceOrder');
83
+
84
+ await publisher.publish(OrderPlaced, { orderId: 'o1', amount: 99 }, {
85
+ eventVersion: '1',
86
+ });
87
+ ```
88
+
89
+ Agents should prefer `ark.publisher(sourceIntent).publish(...)` over direct
90
+ `eventBus.publish(...)`. Source-bound publishers stamp `metadata.source` internally and
91
+ reject attempts to override it with a different source.
92
+
93
+ Interceptors may enrich event payloads, but they must remain add-only:
94
+
95
+ ```ts
96
+ ark.eventBus.registerInterceptor(OrderPlaced, ({ intercept }) => {
97
+ intercept({ auditTag: 'checkout' });
98
+ }, 'audit-tag');
99
+ ```
100
+
101
+ If an interceptor overwrites an existing field or violates the registered event
102
+ contract, Ark records `interceptor.error` and keeps delivering the original event.
103
+
104
+ ## Code Generation Validation
105
+
106
+ Use `createAICodeGate()` before merging agent-generated source snippets:
107
+
108
+ ```ts
109
+ import * as ts from 'typescript';
110
+
111
+ const gate = createAICodeGate({
112
+ intents: registry.list(),
113
+ enforceIntentAllowlist: true,
114
+ architectureProfile: elevenLayerProfile,
115
+ typescript: ts,
116
+ extensions: [/* optional external AST analyzers implementing AIGateExtension */],
117
+ });
118
+
119
+ const result = gate.validate(generatedSource, {
120
+ filePath: 'src/domain/order.ts',
121
+ agentId: 'agent-1',
122
+ layer: 'DomainModel',
123
+ });
124
+ if (!result.valid) {
125
+ for (const v of result.violations) {
126
+ console.log(v.code, v.message, v.suggestion);
127
+ }
128
+ }
129
+ ```
130
+
131
+ Passing the `typescript` module enables built-in AST checks for raw publish calls, missing
132
+ `metadata.source`, and source-layer mismatches. `ark-mcp` enables these checks
133
+ automatically when TypeScript is available.
134
+
135
+ Violation codes (from `createAICodeGate`): `RAW_EVENT_PUBLISH`, `PUBLISH_MISSING_SOURCE`, `PUBLISH_SOURCE_LAYER_MISMATCH`, `FORBIDDEN_PATTERN`, `FORBIDDEN_SUBSTRING`, `FORBIDDEN_IMPORT`, `POLICY_VIOLATION`, `UNKNOWN_INTENT`, `LAYER_REFERENCE_VIOLATION`, `EXTENSION_ERROR`, `AST_ANALYZER_ERROR`.
136
+
137
+ Use `ark-check` in CI for repository-level checks that need real file paths:
138
+
139
+ ```bash
140
+ npx ark-check --root . --config ark.config.json
141
+ ```
142
+
143
+ Agents can generate a config from the project's actual directory layout instead of inventing layer mappings:
144
+
145
+ ```bash
146
+ npx ark-check --init
147
+ ```
148
+
149
+ Or print the full 11-layer template to adapt manually:
150
+
151
+ ```bash
152
+ npx ark-check --print-config eleven-layer
153
+ ```
154
+
155
+ Example config:
156
+
157
+ ```json
158
+ {
159
+ "include": ["src"],
160
+ "layers": [
161
+ {
162
+ "name": "DomainModel",
163
+ "patterns": ["src/domain/**"],
164
+ "intentPrefixes": ["Domain."]
165
+ },
166
+ {
167
+ "name": "PersistenceAdapters",
168
+ "patterns": ["src/adapters/persistence/**"],
169
+ "intentPrefixes": ["Adapter.Persistence."]
170
+ },
171
+ {
172
+ "name": "ApplicationOrchestration",
173
+ "patterns": ["src/application/**"],
174
+ "intentPrefixes": ["Application."]
175
+ }
176
+ ],
177
+ "rules": [
178
+ {
179
+ "from": "DomainModel",
180
+ "to": "PersistenceAdapters",
181
+ "allowed": false
182
+ }
183
+ ]
184
+ }
185
+ ```
186
+
187
+ `ark-check` resolves imports through the TypeScript module resolver against your
188
+ `tsconfig.json` — relative, path-alias (e.g. `@infra/db`), package imports, dynamic
189
+ `import()`, and `require()` — plus string intent references. It also flags raw
190
+ `publish()` calls, publish calls without `metadata.source`, and source intent literals
191
+ whose resolved layer differs from the publishing file layer. Pass `--tsconfig <path>` to point at a specific config
192
+ (otherwise the nearest `tsconfig.json` from `--root` is used). It resolves modules the way
193
+ your build does, but is intentionally not yet a full type-graph analyzer (cross-layer
194
+ type-only references beyond the import specifier are out of scope).
195
+
196
+ `ark-check --json` also reports `warnings` for incomplete governance coverage: missing
197
+ layers, unclassified included files, unmatched layer patterns, duplicate layers, and rules
198
+ that reference unknown layers. These are advisory by default. Use `--strict-config` once a
199
+ project is ready to fail CI on coverage gaps.
200
+
201
+ Use the optional ESLint plugin for fast local feedback:
202
+
203
+ ```js
204
+ import ark from 'ark-runtime-kernel/eslint';
205
+
206
+ export default [
207
+ ark.configs.recommended,
208
+ ];
209
+ ```
210
+
211
+ Rules: `ark/no-domain-infra-imports`, `ark/no-raw-event-publish`, and
212
+ `ark/require-publish-source`.
213
+
214
+ ## Runtime Observability
215
+
216
+ The event bus exposes a standard trace format:
217
+
218
+ ```ts
219
+ const bus = createEventBus({
220
+ maxHistorySize: 1000,
221
+ auditTrail,
222
+ traceSinks: [(record) => otelBridge(record)],
223
+ onSoftViolation: (result, event) => { /* advisory policies */ },
224
+ onHandlerError: (err, event, intent) => { /* subscriber failures */ },
225
+ });
226
+
227
+ await bus.publish(intent, payload);
228
+ const trace = bus.getTrace();
229
+ // trace[].type includes 'event.published', 'event.rawPublish', 'event.intercepted',
230
+ // 'interceptor.error', 'policy.hardViolation', 'policy.softViolation', 'handler.error'
231
+ ```
232
+
233
+ Native audit records are available through `auditTrail.query()`. Projection
234
+ state and checkpoints are available through `ProjectionRegistry`.
235
+
236
+ `ark.observability.report()` compares declared productions with observed runtime
237
+ flows. Use `observedButUndeclared` as a high-signal review queue for hidden coupling.
238
+
239
+ For tests, use `createArkTestHarness(ark)` to inspect events, traces, audit,
240
+ outbox, and observability snapshots without reaching into private internals.
241
+
242
+ ## Extension Points (External Layers)
243
+
244
+ Implement these interfaces in **external** packages — not inside the Ark core:
245
+
246
+ | Interface | Purpose |
247
+ |-----------|---------|
248
+ | `AIGateExtension` | Plug in AST/semantic analyzers for codegen validation |
249
+ | `Policy` | Custom architectural rules via `definePolicy()` |
250
+ | `LayerFlowRule` | Layer isolation via `defineLayerPolicy()` |
251
+ | `WorkflowStore` | Persist workflow snapshots outside memory |
252
+ | `ReadModelStore` | Persist projection/read-model state outside memory |
253
+ | `AuditStore` | Persist audit records outside memory |
254
+ | `OutboxStore` | Persist event outbox records outside memory |
255
+ | `EventInterceptor` | Add-only event enrichment before delivery |
256
+
257
+ ## Ports and Adapters
258
+
259
+ When generating adapter code, prefer ports with explicit ownership and allowlists:
260
+
261
+ ```ts
262
+ const PaymentGateway = definePort<PaymentGatewayPort>('PaymentGateway', {
263
+ ownerLayer: 'ApplicationOrchestration',
264
+ intent: 'Application.Port.PaymentGateway',
265
+ allowedAdapters: ['Adapter.Integration.StripePaymentGateway'],
266
+ });
267
+
268
+ createAdapter(PaymentGateway, stripeAdapter, {
269
+ name: 'Adapter.Integration.StripePaymentGateway',
270
+ layer: 'IntegrationAdapters',
271
+ requiredKeys: ['charge'],
272
+ });
273
+ ```
274
+
275
+ `createAdapter` rejects adapter names/intents not listed in `allowedAdapters`; use
276
+ `checkAdapterGovernance(adapter)` when a tool needs a non-throwing result.
277
+
278
+ Preset: `elevenLayerProfile` plus `defineArchitectureProfilePolicy()` forbids invalid declared dependencies across the 11-layer profile. `architecturalPolicies.cleanArchitectureMatrix()` remains available for the older four-prefix model.
279
+
280
+ Runtime support depth varies by design. Layers with dedicated kernel modules:
281
+ DomainModel/ApplicationOrchestration (intents, policies), WorkflowSagaEngine
282
+ (workflow engine), PersistenceAdapters (adapters, outbox), ReportingReadModels
283
+ (projections), ExtensibilityMetadata (metadata registry), SecurityAuditObservability
284
+ (audit trail, drift reporter), Kernel (event bus, graph, manifest).
285
+ PresentationAdapters, IntegrationAdapters, and BackgroundJobsScheduling are
286
+ **boundary-only on purpose**: Ark governs what they may import and publish, but does
287
+ not replace your web framework, HTTP clients, or job scheduler.
288
+
289
+ ## Write-Path Gate (MCP)
290
+
291
+ The strongest place to constrain an AI agent is the moment it writes a file, not after.
292
+ `ark-mcp` exposes Ark over MCP (zero dependencies, JSON-RPC over stdio) so a host can gate
293
+ the write path:
294
+
295
+ ```bash
296
+ npx ark-mcp --root . --config ark.config.json [--manifest ark.manifest.json]
297
+ ```
298
+
299
+ - **Resource `ark://manifest`** — contract discovery. Serve your exported
300
+ `ark.manifest().toJSON()` via `--manifest`, or omit it to get the 11-layer profile
301
+ (layers + rules) as the default contract.
302
+ - **Tool `validate_code`** — args `{ source, layer?, filePath? }`. Runs `createAICodeGate`
303
+ against the profile and (when a manifest is provided) the registered intent allowlist.
304
+ Returns `{ valid, violations, layer }`; `isError` is `true` when invalid. If `layer` is
305
+ omitted it is inferred from `filePath` via the config's layer patterns.
306
+
307
+ For hook-based enforcement, `ark-mcp --hook` runs one-shot: it reads a PreToolUse payload
308
+ from stdin, validates the post-edit file content, and exits `2` with violations on stderr
309
+ to block the write (`0` to allow). Working Claude Code configuration
310
+ (`.claude/settings.json`):
311
+
312
+ ```json
313
+ {
314
+ "hooks": {
315
+ "PreToolUse": [
316
+ {
317
+ "matcher": "Write|Edit|MultiEdit",
318
+ "hooks": [
319
+ {
320
+ "type": "command",
321
+ "command": "npx ark-mcp --hook --root \"$CLAUDE_PROJECT_DIR\""
322
+ }
323
+ ]
324
+ }
325
+ ]
326
+ }
327
+ }
328
+ ```
329
+
330
+ Register the server itself in `.mcp.json` so the agent can read `ark://manifest` and call
331
+ `validate_code` on demand:
332
+
333
+ ```json
334
+ {
335
+ "mcpServers": {
336
+ "ark": { "command": "npx", "args": ["ark-mcp", "--root", ".", "--config", "ark.config.json"] }
337
+ }
338
+ }
339
+ ```
340
+
341
+ This makes the manifest + AI gate an enforced checkpoint rather than a library the agent
342
+ must remember to call.
343
+
344
+ ## Recommended Agent Workflow
345
+
346
+ 1. **Read** manifest via `ark.manifest().toJSON()`
347
+ 2. **Generate** code using registered intents, profiles, metadata, projections, and workflow definitions
348
+ 3. **Validate snippets** with `createAICodeGate().validate(source, { layer })`
349
+ 4. **Validate repository** with `ark-check --root . --config ark.config.json`
350
+ 5. **Lint** with `ark-runtime-kernel/eslint` recommended rules
351
+ 6. **Wire** relationships via `registry.define(..., { dependsOn, produces })`
352
+ 7. **Register** event contracts before publishing in strict mode
353
+ 8. **Observe** runtime via `bus.getTrace()`, `auditTrail.query()`, outbox records, projection checkpoints, and `ark.observability.report()`
@@ -0,0 +1,177 @@
1
+ # Gating AI Agents with Ark
2
+
3
+ The write-path gate is what makes Ark different from every other architecture linter: generated code is validated against your architecture **before it lands on disk**, not after the PR is red.
4
+
5
+ Everything below uses the same `ark.config.json` as `ark-check` (CI) — one contract, enforced everywhere. Generate it once:
6
+
7
+ ```bash
8
+ npx ark-check --init
9
+ ```
10
+
11
+ For guided setup with prompts, use:
12
+
13
+ ```bash
14
+ npx ark init
15
+ ```
16
+
17
+ For non-interactive defaults, use:
18
+
19
+ ```bash
20
+ npx ark init --yes
21
+ ```
22
+
23
+ You can also generate only the starter gate files for common agent runtimes and CI:
24
+
25
+ ```bash
26
+ npx ark-check --install-agent-gates
27
+ ```
28
+
29
+ The command writes templates for `.mcp.json`, Claude hooks, Cursor MCP/rules,
30
+ GitHub Actions, `AGENTS.md`, and a Codex TOML snippet under `docs/`. It skips
31
+ existing files unless you pass `--force`, so review and commit only the templates
32
+ that match your project.
33
+
34
+ If your project uses Codex, treat the MCP registration as part of the default setup,
35
+ not an optional extra. Ark works best when Codex can read `ark://manifest` before it
36
+ writes code; that is the fast path to avoiding architecture drift during generation.
37
+
38
+ ## Claude Code — hook (recommended, hard block)
39
+
40
+ `ark-mcp --hook` is a one-shot PreToolUse gate: it reads the hook payload from stdin, computes the **post-edit** file content, validates it, and exits `2` (block, violations on stderr) or `0` (allow). The agent sees the violations and self-corrects.
41
+
42
+ Add to your project's `.claude/settings.json`:
43
+
44
+ ```json
45
+ {
46
+ "hooks": {
47
+ "PreToolUse": [
48
+ {
49
+ "matcher": "Write|Edit|MultiEdit",
50
+ "hooks": [
51
+ {
52
+ "type": "command",
53
+ "command": "npx ark-mcp --hook --root \"$CLAUDE_PROJECT_DIR\" --config ark.config.json"
54
+ }
55
+ ]
56
+ }
57
+ ]
58
+ }
59
+ }
60
+ ```
61
+
62
+ That's the whole setup. Try asking the agent to import a persistence adapter from your domain layer:
63
+
64
+ ```
65
+ Ark architecture gate blocked this write to src/domain/order.ts (layer: DomainModel):
66
+ - [FORBIDDEN_PATTERN] Forbidden pattern matched: /from ['"].*\/(infra|adapters|persistence|db)/i (line 1)
67
+ - [FORBIDDEN_IMPORT] Forbidden import target: "../adapters/persistence/pg-order-repository". (line 1)
68
+ Fix the violations and retry. The architecture contract is available as the ark://manifest MCP resource.
69
+ ```
70
+
71
+ ## Claude Code — MCP server (contract discovery + on-demand validation)
72
+
73
+ The MCP server exposes two things agents can use proactively:
74
+
75
+ - **`ark://manifest`** (resource) — the machine-readable architecture contract (layers + rules), so the agent can read the architecture before generating code.
76
+ - **`validate_code`** (tool) — validates a snippet against the architecture on demand.
77
+
78
+ ```bash
79
+ claude mcp add ark -- npx ark-mcp --root . --config ark.config.json
80
+ ```
81
+
82
+ or in `.mcp.json`:
83
+
84
+ ```json
85
+ {
86
+ "mcpServers": {
87
+ "ark": {
88
+ "type": "stdio",
89
+ "command": "npx",
90
+ "args": ["ark-mcp", "--root", ".", "--config", "ark.config.json"]
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ Use both: the MCP server for discovery, the hook for enforcement.
97
+
98
+ ## Cursor
99
+
100
+ Cursor supports MCP servers (`.cursor/mcp.json`):
101
+
102
+ ```json
103
+ {
104
+ "mcpServers": {
105
+ "ark": {
106
+ "command": "npx",
107
+ "args": ["ark-mcp", "--root", ".", "--config", "ark.config.json"]
108
+ }
109
+ }
110
+ }
111
+ ```
112
+
113
+ Cursor has no pre-write hook, so the gate is advisory at write time — pair it with a rules file so the agent actually calls it. `.cursor/rules/ark.mdc`:
114
+
115
+ ```markdown
116
+ ---
117
+ description: Ark architecture contract
118
+ alwaysApply: true
119
+ ---
120
+
121
+ Before writing or editing any TypeScript source file, call the `validate_code`
122
+ tool from the `ark` MCP server with the full post-edit file content and its
123
+ path. If it reports violations, fix them before writing. The architecture
124
+ contract is available as the `ark://manifest` resource.
125
+ ```
126
+
127
+ Your hard backstop in Cursor is CI: `ark-check` fails the PR on anything that slips through.
128
+
129
+ ## OpenAI Codex CLI
130
+
131
+ Recommended for Ark projects.
132
+
133
+ `~/.codex/config.toml`:
134
+
135
+ ```toml
136
+ [mcp_servers.ark]
137
+ command = "npx"
138
+ args = ["ark-mcp", "--root", ".", "--config", "ark.config.json"]
139
+ ```
140
+
141
+ Same model as Cursor: MCP for discovery/validation, `ark-check` in CI as the hard gate.
142
+ For Ark projects, register the MCP server as soon as the repo is adopted so the agent
143
+ has the contract available from the first edit.
144
+
145
+ ## Any other agent runtime with shell hooks
146
+
147
+ If your runtime can run a shell command before file writes and pass the tool payload on stdin (Claude Code's PreToolUse contract), `ark-mcp --hook` works as-is. The contract:
148
+
149
+ - stdin: JSON `{ "tool_name": "Write|Edit|MultiEdit", "tool_input": { "file_path": ..., ... } }`
150
+ - exit `0` → allow; exit `2` → block, human-readable violations on stderr
151
+ - plumbing problems (no stdin, non-source files, files outside `--root`) never block
152
+
153
+ ## ESLint (editor feedback)
154
+
155
+ For in-editor red squiggles on layer violations, add the ESLint plugin:
156
+
157
+ ```js
158
+ // eslint.config.js
159
+ import ark from 'ark-runtime-kernel/eslint';
160
+
161
+ export default [ark.configs.recommended];
162
+ ```
163
+
164
+ ## CI backstop
165
+
166
+ Whatever the agent side does, gate the merge:
167
+
168
+ ```yaml
169
+ - run: npx ark-check --root . --config ark.config.json --strict-config
170
+ ```
171
+
172
+ Adopting Ark on an existing codebase with violations? Freeze them once and ratchet down:
173
+
174
+ ```bash
175
+ npx ark-check --update-baseline # writes .ark-baseline.json — commit it
176
+ npx ark-check --baseline # only NEW violations fail
177
+ ```
@@ -0,0 +1,87 @@
1
+ {
2
+ "include": ["src"],
3
+ "layers": [
4
+ {
5
+ "name": "DomainModel",
6
+ "patterns": ["src/domain/**"],
7
+ "intentPrefixes": ["Domain."]
8
+ },
9
+ {
10
+ "name": "ApplicationOrchestration",
11
+ "patterns": ["src/application/**"],
12
+ "intentPrefixes": ["Application."]
13
+ },
14
+ {
15
+ "name": "PersistenceAdapters",
16
+ "patterns": ["src/adapters/persistence/**"],
17
+ "intentPrefixes": ["Adapter.Persistence."]
18
+ },
19
+ {
20
+ "name": "IntegrationAdapters",
21
+ "patterns": ["src/adapters/integration/**"],
22
+ "intentPrefixes": ["Adapter.Integration."]
23
+ },
24
+ {
25
+ "name": "WorkflowSagaEngine",
26
+ "patterns": ["src/workflows/**"],
27
+ "intentPrefixes": ["Workflow."]
28
+ },
29
+ {
30
+ "name": "BackgroundJobsScheduling",
31
+ "patterns": ["src/jobs/**"],
32
+ "intentPrefixes": ["Job."]
33
+ },
34
+ {
35
+ "name": "PresentationAdapters",
36
+ "patterns": ["src/presentation/**"],
37
+ "intentPrefixes": ["Presentation."]
38
+ },
39
+ {
40
+ "name": "ReportingReadModels",
41
+ "patterns": ["src/reporting/**"],
42
+ "intentPrefixes": ["Reporting."]
43
+ },
44
+ {
45
+ "name": "ExtensibilityMetadata",
46
+ "patterns": ["src/metadata/**"],
47
+ "intentPrefixes": ["Metadata."]
48
+ },
49
+ {
50
+ "name": "SecurityAuditObservability",
51
+ "patterns": ["src/security/**", "src/audit/**", "src/observability/**"],
52
+ "intentPrefixes": ["Security.", "Audit.", "Observability."]
53
+ },
54
+ {
55
+ "name": "Kernel",
56
+ "patterns": ["src/kernel/**"],
57
+ "intentPrefixes": ["Kernel."]
58
+ }
59
+ ],
60
+ "rules": [
61
+ {
62
+ "from": "DomainModel",
63
+ "to": "PersistenceAdapters",
64
+ "allowed": false
65
+ },
66
+ {
67
+ "from": "DomainModel",
68
+ "to": "IntegrationAdapters",
69
+ "allowed": false
70
+ },
71
+ {
72
+ "from": "DomainModel",
73
+ "to": "PresentationAdapters",
74
+ "allowed": false
75
+ },
76
+ {
77
+ "from": "PresentationAdapters",
78
+ "to": "PersistenceAdapters",
79
+ "allowed": false
80
+ },
81
+ {
82
+ "from": "ReportingReadModels",
83
+ "to": "PersistenceAdapters",
84
+ "allowed": false
85
+ }
86
+ ]
87
+ }
@@ -0,0 +1,28 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="760" height="330" viewBox="0 0 760 330" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="13">
2
+ <defs>
3
+ <clipPath id="window"><rect x="0" y="0" width="760" height="330" rx="10"/></clipPath>
4
+ </defs>
5
+ <g clip-path="url(#window)">
6
+ <rect width="760" height="330" fill="#0d1117"/>
7
+ <rect width="760" height="34" fill="#161b22"/>
8
+ <circle cx="20" cy="17" r="6" fill="#ff5f57"/>
9
+ <circle cx="40" cy="17" r="6" fill="#febc2e"/>
10
+ <circle cx="60" cy="17" r="6" fill="#28c840"/>
11
+ <text x="380" y="21" fill="#8b949e" text-anchor="middle" font-size="12">claude — my-hexagonal-app</text>
12
+
13
+ <text x="24" y="64" fill="#c9d1d9">&gt; add a findById method to Order that reads straight from postgres</text>
14
+
15
+ <text x="24" y="96" fill="#8b949e">● Edit(src/domain/order.ts)</text>
16
+ <text x="40" y="118" fill="#6e7681">import { PgOrderRepository } from '../adapters/persistence/pg-order-repository';</text>
17
+
18
+ <text x="24" y="152" fill="#f85149" font-weight="bold">✗ Ark architecture gate blocked this write to src/domain/order.ts (layer: DomainModel):</text>
19
+ <text x="40" y="174" fill="#f85149">- [FORBIDDEN_IMPORT] Forbidden import target: "../adapters/persistence/pg-order-repository".</text>
20
+ <text x="24" y="196" fill="#8b949e">Fix the violations and retry. The architecture contract is available as the</text>
21
+ <text x="24" y="214" fill="#8b949e">ark://manifest MCP resource.</text>
22
+
23
+ <text x="24" y="248" fill="#c9d1d9">● The domain layer can't import persistence adapters. I'll define the port in the</text>
24
+ <text x="24" y="266" fill="#c9d1d9">domain instead and implement it in src/adapters/persistence/.</text>
25
+
26
+ <text x="24" y="300" fill="#28c840">● Edit(src/domain/ports/order-repository.ts) ✔ allowed</text>
27
+ </g>
28
+ </svg>