ark-runtime-kernel 1.1.0 → 1.2.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,85 @@
1
+ # How I stopped Claude from breaking my hexagonal architecture
2
+
3
+ *Draft — publish on dev.to / HN / r/typescript alongside the repo going public.*
4
+
5
+ ---
6
+
7
+ AI agents write most of my code now. They're fast, they're tireless, and they have absolutely no respect for my architecture.
8
+
9
+ Ask an agent to "add a findById method to Order" and there's a decent chance it imports the Postgres repository straight into the domain layer. The code compiles. The tests pass. The PR looks fine at a glance. Three months of that and your hexagonal architecture is a decorative diagram.
10
+
11
+ The usual answer is "review harder" — which doesn't scale when the agent produces 30 PRs a week — or "add a linter", which catches the violation *after* the agent already built three files on top of it.
12
+
13
+ ## The insight: block at write time, not review time
14
+
15
+ Agent runtimes like Claude Code have pre-write hooks: a shell command that runs *before* a file edit lands, and can veto it. That's a fundamentally better enforcement point than CI:
16
+
17
+ 1. The violation never reaches disk.
18
+ 2. The agent sees the error **in its loop** and self-corrects immediately — it defines the port in the domain and implements it in the adapter, like you would have asked for in review.
19
+
20
+ So I built [Ark](https://github.com/pedroknigge/ark-runtime-kernel). You describe your architecture once, as data:
21
+
22
+ ```json
23
+ {
24
+ "layers": [
25
+ { "name": "DomainModel", "patterns": ["src/domain/**"] },
26
+ { "name": "PersistenceAdapters", "patterns": ["src/adapters/persistence/**"] }
27
+ ],
28
+ "rules": [
29
+ { "from": "DomainModel", "to": "PersistenceAdapters", "allowed": false }
30
+ ]
31
+ }
32
+ ```
33
+
34
+ Then wire it into Claude Code as a PreToolUse hook:
35
+
36
+ ```json
37
+ {
38
+ "hooks": {
39
+ "PreToolUse": [{
40
+ "matcher": "Write|Edit|MultiEdit",
41
+ "hooks": [{ "type": "command",
42
+ "command": "npx ark-mcp --hook --root \"$CLAUDE_PROJECT_DIR\" --config ark.config.json" }]
43
+ }]
44
+ }
45
+ }
46
+ ```
47
+
48
+ Now the same request plays out like this:
49
+
50
+ ```
51
+ ● Write(src/domain/order.ts)
52
+ ✗ Ark architecture gate blocked this write to src/domain/order.ts (layer: DomainModel):
53
+ - [FORBIDDEN_PATTERN] Forbidden pattern matched: /from ['"].*\/(infra|adapters|persistence|db)/i (line 1)
54
+ - [FORBIDDEN_IMPORT] Forbidden import target: "../adapters/persistence/order-repository". (line 1)
55
+ Fix the violations and retry. The architecture contract is available as the ark://manifest MCP resource.
56
+
57
+ ● The domain layer can't import persistence adapters. I'll define the port in
58
+ the domain instead and implement it in src/adapters/persistence/.
59
+ ```
60
+
61
+ The agent fixed its own architecture violation. Nobody reviewed anything.
62
+
63
+ ## Details that turned out to matter
64
+
65
+ **The gate validates the post-edit file, not the diff.** An edit snippet out of context tells you nothing about imports. `ark-mcp --hook` applies the proposed edit to the current file content and validates the result.
66
+
67
+ **The same config gates CI.** Not every write goes through an agent, and not every agent runtime has hooks. `ark-check` runs the same rules in CI with TypeScript's real module resolver — path aliases and all — so nothing merges that violates the contract, whoever wrote it.
68
+
69
+ **Agents can read the contract, not just bounce off it.** The MCP server also exposes `ark://manifest` — the architecture as JSON — so agents get the rules *before* generating code instead of learning by rejection.
70
+
71
+ **Existing codebases need a ratchet.** Nobody adopts a checker that greets them with 400 errors. `ark-check --update-baseline` freezes today's violations; from then on only *new* ones fail. The count only goes down.
72
+
73
+ ## What about dependency-cruiser / eslint-plugin-boundaries?
74
+
75
+ They're good tools and they cover the CI half. What they don't have is the write-time half: an MCP server and hook designed for agent runtimes, plus a machine-readable manifest for agents to consume. That's the part that changes agent behavior instead of just grading it.
76
+
77
+ ## Try it
78
+
79
+ ```bash
80
+ npm i -D ark-runtime-kernel typescript
81
+ npx ark-check --init # infers layers from your folder structure
82
+ npx ark-check # CI gate
83
+ ```
84
+
85
+ Repo: https://github.com/pedroknigge/ark-runtime-kernel — zero dependencies, MIT.
@@ -0,0 +1,59 @@
1
+ # Production Hardening
2
+
3
+ Ark's built-in stores are intentionally in-memory defaults. They are appropriate for tests,
4
+ local development, examples, and single-process demos. Production systems should provide
5
+ stores that match their durability, ordering, retention, and operational requirements.
6
+
7
+ ## In-Memory Defaults
8
+
9
+ These defaults do not survive process restarts:
10
+
11
+ - `InMemoryAuditStore`
12
+ - `InMemoryOutboxStore`
13
+ - `InMemoryReadModelStore`
14
+ - `InMemoryWorkflowStore`
15
+
16
+ Use them only when losing state is acceptable.
17
+
18
+ ## Production Store Checklist
19
+
20
+ When implementing Ark store interfaces in production, cover these guarantees explicitly:
21
+
22
+ - Durability: records survive process restarts and deploys.
23
+ - Idempotency: repeated writes or dispatch attempts do not corrupt state.
24
+ - Ordering: event/outbox ordering is defined where consumers depend on it.
25
+ - Concurrency: simultaneous publishers/workers cannot race checkpoints or workflow state.
26
+ - Retention: audit and trace records have an explicit retention policy.
27
+ - Observability: failed writes and dispatches are visible to operators.
28
+ - Migration: schema changes for stored records are versioned.
29
+
30
+ ## Interface Targets
31
+
32
+ | Concern | Interface |
33
+ |---------|-----------|
34
+ | Audit records | `AuditStore` |
35
+ | Outbox dispatch handoff | `OutboxStore` |
36
+ | Projection state | `ReadModelStore` |
37
+ | Workflow snapshots | `WorkflowStore` |
38
+
39
+ ## Example Shape
40
+
41
+ ```ts
42
+ class DurableAuditStore implements AuditStore {
43
+ async append(record: AuditRecord): Promise<void> {
44
+ // Insert into your database with an idempotent key.
45
+ }
46
+
47
+ async query(query: AuditQuery = {}): Promise<AuditRecord[]> {
48
+ // Apply query filters and retention-aware ordering.
49
+ return [];
50
+ }
51
+
52
+ async clear(): Promise<void> {
53
+ // Usually only enabled in tests or isolated maintenance jobs.
54
+ }
55
+ }
56
+ ```
57
+
58
+ Ark does not ship a database adapter in core because storage choice is operationally
59
+ specific. Keep those adapters in the application or a separate integration package.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ark-runtime-kernel",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Architectural Runtime Kernel — governance for Hexagonal + Event-Driven + DDD systems",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -24,6 +24,7 @@
24
24
  }
25
25
  },
26
26
  "bin": {
27
+ "ark": "bin/ark.mjs",
27
28
  "ark-check": "bin/ark-check.mjs",
28
29
  "ark-mcp": "bin/ark-mcp.mjs"
29
30
  },
@@ -31,6 +32,7 @@
31
32
  "files": [
32
33
  "bin",
33
34
  "dist",
35
+ "docs",
34
36
  "server.json",
35
37
  "README.md",
36
38
  "LICENSE"
@@ -43,6 +45,7 @@
43
45
  "typecheck": "tsc --noEmit",
44
46
  "check:architecture": "node bin/ark-check.mjs --root . --config ark.config.json --strict-config",
45
47
  "clean": "rm -rf dist",
48
+ "postinstall": "node bin/ark-postinstall.mjs",
46
49
  "release:npm": "node scripts/release-npm.mjs",
47
50
  "prepack": "npm run build"
48
51
  },