arkgate 2.12.0 → 3.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +122 -0
  2. package/README.md +90 -51
  3. package/bin/ark-check.mjs +156 -39
  4. package/bin/ark-mcp.mjs +119 -6
  5. package/bin/ark-shared.mjs +216 -129
  6. package/bin/ark.mjs +134 -34
  7. package/bin/lib/adapter-contract.mjs +93 -0
  8. package/bin/lib/agent-gates.mjs +13 -0
  9. package/bin/lib/analysis-engine.mjs +1171 -0
  10. package/bin/lib/architecture-scan.mjs +84 -127
  11. package/bin/lib/ci-and-commands.mjs +40 -3
  12. package/bin/lib/codex-home.mjs +7 -0
  13. package/bin/lib/config-contract.mjs +331 -0
  14. package/bin/lib/config-warnings.mjs +7 -205
  15. package/bin/lib/doctor-plan.mjs +43 -16
  16. package/bin/lib/enforcement-profiles.mjs +97 -0
  17. package/bin/lib/field-install.mjs +67 -10
  18. package/bin/lib/gate-files.mjs +42 -3
  19. package/bin/lib/graph-cycles.mjs +4 -54
  20. package/bin/lib/hook-templates.mjs +33 -1
  21. package/bin/lib/host-support-matrix.mjs +83 -0
  22. package/bin/lib/install-migrate.mjs +99 -30
  23. package/bin/lib/mcp-adoption.mjs +35 -3
  24. package/bin/lib/open-html.mjs +75 -0
  25. package/bin/lib/presets.mjs +45 -4
  26. package/bin/lib/safety-diagnostics.mjs +36 -15
  27. package/bin/lib/scan-files.mjs +12 -1
  28. package/bin/lib/skill-install.mjs +72 -1
  29. package/bin/lib/source-policy.mjs +36 -0
  30. package/bin/lib/start-preview.mjs +271 -0
  31. package/bin/lib/ts-resolve.mjs +13 -3
  32. package/bin/lib/weakest-link.mjs +417 -0
  33. package/bin/lib/write-path-capabilities.mjs +186 -0
  34. package/bin/lib/write-path-detect.mjs +62 -99
  35. package/compat/nestjs.cjs +2 -0
  36. package/compat/nestjs.d.ts +2 -0
  37. package/compat/nestjs.js +1 -0
  38. package/compat/runtime.cjs +2 -0
  39. package/compat/runtime.d.ts +2 -0
  40. package/compat/runtime.js +1 -0
  41. package/dist/configContract-BxSIwVRo.d.cts +259 -0
  42. package/dist/configContract-BxSIwVRo.d.ts +259 -0
  43. package/dist/eslint/index.cjs +500 -61
  44. package/dist/eslint/index.d.cts +36 -20
  45. package/dist/eslint/index.d.ts +36 -20
  46. package/dist/eslint/index.js +500 -61
  47. package/dist/index.cjs +1349 -2741
  48. package/dist/index.d.cts +449 -483
  49. package/dist/index.d.ts +449 -483
  50. package/dist/index.js +1325 -2687
  51. package/docs/agent-guide.md +58 -34
  52. package/docs/ai-gates.md +79 -21
  53. package/docs/configuration.md +97 -0
  54. package/docs/enthusiast/README.md +3 -3
  55. package/docs/enthusiast/how-to-agent-gates.md +7 -3
  56. package/docs/migrate-from-ark-runtime-kernel.md +5 -3
  57. package/docs/package-surface.md +19 -19
  58. package/docs/production-hardening.md +31 -5
  59. package/docs/threat-model.md +65 -0
  60. package/docs/typescript-support.md +30 -3
  61. package/package.json +46 -11
  62. package/schemas/ark.analysis-result.schema.json +91 -0
  63. package/schemas/ark.config.schema.json +750 -0
  64. package/server.json +2 -2
  65. package/templates/hooks/pre-commit-ark +37 -0
  66. package/templates/skills/ark-architect.md +3 -2
  67. package/templates/skills/ark-coverage.md +2 -2
  68. package/templates/skills/ark-runtime.md +8 -5
  69. package/templates/skills/ark-upgrade.md +36 -16
  70. package/tests/fixtures/ts-consumer/ark.config.json +2 -0
  71. package/dist/eslint/index.cjs.map +0 -1
  72. package/dist/eslint/index.js.map +0 -1
  73. package/dist/index.cjs.map +0 -1
  74. package/dist/index.js.map +0 -1
  75. package/dist/nestjs/index.cjs +0 -2498
  76. package/dist/nestjs/index.cjs.map +0 -1
  77. package/dist/nestjs/index.d.cts +0 -22
  78. package/dist/nestjs/index.d.ts +0 -22
  79. package/dist/nestjs/index.js +0 -2474
  80. package/dist/nestjs/index.js.map +0 -1
  81. package/dist/runtime/index.cjs +0 -3352
  82. package/dist/runtime/index.cjs.map +0 -1
  83. package/dist/runtime/index.d.cts +0 -2
  84. package/dist/runtime/index.d.ts +0 -2
  85. package/dist/runtime/index.js +0 -3270
  86. package/dist/runtime/index.js.map +0 -1
  87. package/dist/types-BZ17b9i5.d.cts +0 -1068
  88. package/dist/types-BZ17b9i5.d.ts +0 -1068
@@ -1,7 +1,9 @@
1
1
  # ArkGate — Agent Integration Guide
2
2
 
3
3
  **ArkGate** (`arkgate`) — architecture co-pilot for AI TypeScript. This guide describes how AI
4
- agents and codegen tools safely interact with the write gate, MCP tools, and `/ark-*` skills.
4
+ agents and codegen tools safely interact with write hooks, advisory MCP tools, CI, and `/ark-*`
5
+ skills. Guarantees differ by host; start with the
6
+ [canonical host support matrix](../README.md#host-enforcement-support).
5
7
 
6
8
  CLI names: prefer **`arkgate` / `arkgate-check` / `arkgate-mcp`**; aliases `ark` / `ark-check` /
7
9
  `ark-mcp` still work for one major. TypeScript **5.x / 6.x / 7.x** as the project compiler:
@@ -23,10 +25,13 @@ Each of the twelve archetypes (`crud-product`, `api-backend`, `frontend-surface`
23
25
  - plain-language analogy and anti-patterns,
24
26
  - optional book references for depth only.
25
27
 
26
- Scoring is **deterministic**: repo shape signals (workspaces, UI dirs, API surface,
27
- persistence, jobs, workflows, CLI `bin`, source-file count, …) are matched against the
28
- playbook. Framework packages may appear as secondary `toolHints` in JSON output never as
29
- the primary archetype id.
28
+ Scoring is **deterministic** and source/graph-first. Ark discovers package units and roots from
29
+ workspace manifests, `tsconfig`/`jsconfig` references, package exports and entrypoints, plus
30
+ conventional `src`/`source` directories. Runtime and peer dependencies contribute framework
31
+ signals; dev-only dependencies are reported but do not determine the application shape. Docs,
32
+ examples, and test packages are reported separately and excluded from root-product inference.
33
+ Framework packages may appear as secondary `toolHints` in JSON output — never as the primary
34
+ archetype id.
30
35
 
31
36
  All playbook labels, analogies, anti-patterns, and `--recommend` prose are **English**
32
37
  (`locale: "en"` in the playbook). Agents should present them as-is unless a future locale
@@ -41,7 +46,10 @@ npx ark-check --recommend --json
41
46
 
42
47
  `--recommend` does not require `ark.config.json`. It exits `0` and prints a progressive
43
48
  adoption plan: archetype id, preset, `confidence`, `runnerUp`, `why` (shape signals),
49
+ structured positive/negative `evidence`, discovered `signals.packageUnits`,
44
50
  `adoptInOrder.phase1`, `firstCommand` (`ark init --archetype …`), and `checkCommand`.
51
+ When the top two shapes are close or projected governed coverage is below 90%, JSON sets
52
+ `requiresConfirmation: true` and explains why in `confirmationReasons`.
45
53
 
46
54
  Human output highlights phase-1 layers and the analogy; JSON is the stable contract for
47
55
  MCP `ark_recommend` and the `/ark-architect` skill.
@@ -49,7 +57,7 @@ MCP `ark_recommend` and the `/ark-architect` skill.
49
57
  ### Terminal onboarding (Phase B)
50
58
 
51
59
  ```bash
52
- npx ark start --yes # preferred: shape → contract → **day-zero origin**gates → plan
60
+ npx ark start --yes # preferred: shape → compact contract → active hostCI → plan
53
61
  npx ark init --archetype crud-product --yes # non-interactive: shape → preset → origin → gates
54
62
  npx ark init # TTY wizard: pick application shape (1–8), not a framework
55
63
  npx ark-check --doctor # includes "New here?" when coverage is low or config is fresh
@@ -57,14 +65,20 @@ npx ark-check --report beginner.html --beginner # simplified HTML for enthusiast
57
65
  npx ark-check --watch # debounced re-check when governed files change
58
66
  ```
59
67
 
60
- **Day-zero origin (2.12+):** as soon as `ark.config.json` exists, `ark start` / `ark init`
61
- freeze `.ark/reports/origin.*` **before** writing agent docs, skills, or CI templates.
62
- Later `--report` shows evolution vs that snapshot. Do not `--reset-origin` unless the user
63
- explicitly wants a new baseline.
68
+ **Day-zero origin (2.12+):** `ark init` freezes `.ark/reports/origin.*` before writing agent
69
+ docs or CI templates. Compact `ark start` keeps first-run setup under five project files and
70
+ 25 KB;
71
+ run `ark-check --report ark-report.html` explicitly when you want to establish an origin/evolution
72
+ baseline. Do not `--reset-origin` unless the user explicitly wants a new baseline.
64
73
 
65
- **Default agent co-pilot:** `/ark-autopilot` (explore-first, dual plan A remediation + B
66
- pattern bets). Recon without applying: `/ark-explore`. Never treat empty `--plan` as
67
- “architecture healthy” without the explore pass.
74
+ To remove a compact host integration, preview `ark start --remove-host <host>` and add `--apply`
75
+ only after review. Ark removes only its exact compact artifacts, leaves customized files untouched
76
+ as unresolved decisions, and restores the integration with `ark start --tools <host> --apply`.
77
+
78
+ **Full-skill agent co-pilot:** after explicitly installing the `/ark-*` pack, use
79
+ `/ark-autopilot` (explore-first, dual plan A remediation + B pattern bets). Recon without
80
+ applying: `/ark-explore`. The default compact router uses MCP/CLI directly. Never treat empty
81
+ `--plan` as “architecture healthy” without the explore pass.
68
82
 
69
83
  `ark init --archetype <id>` maps playbook ids to named presets (`hexagonal`, `layered`,
70
84
  `feature-sliced`, `monorepo`). With `--yes` and no archetype, Ark auto-selects from
@@ -209,32 +223,35 @@ directories (`utils/`, `lib/`) must be classified explicitly via `/ark-contract`
209
223
 
210
224
  ## Supported agent hosts
211
225
 
212
- Wire write-gate + MCP + `/ark-*` skills with:
226
+ Wire write-gate + MCP + the full `/ark-*` skill set with:
213
227
 
214
228
  ```bash
215
229
  npx arkgate-check --install-agent-gates --tools claude,cursor,codex,grok
216
230
  # alias: npx ark-check --install-agent-gates --tools claude,cursor,codex,grok
217
231
  ```
218
232
 
219
- | Host | Write gate | MCP | Skills path |
220
- |------|------------|-----|-------------|
221
- | Claude Code | PreToolUse hook | `.mcp.json` / `claude mcp add` | `.claude/skills/<name>/SKILL.md` |
222
- | Cursor | Advisory (rules + MCP) | `.cursor/mcp.json` | `.cursor/commands/` |
223
- | OpenAI Codex | MCP + CI | `$CODEX_HOME/config.toml` (global; absolute `--root`; multi-project → secondary `ark_<slug>` unless `--force`) | `$CODEX_HOME/prompts` (`--codex-home`) |
224
- | **Grok Build** | PreToolUse hook (`.grok/hooks/`) | `.grok/config.toml` + `.mcp.json` | `.grok/skills/<name>/SKILL.md` |
233
+ | Host | Installed paths | Skills path |
234
+ |------|-----------------|-------------|
235
+ | Claude Code | `.claude/settings.json` hook + `.mcp.json` / `claude mcp add` | `.claude/skills/<name>/SKILL.md` |
236
+ | Cursor | `.cursor/mcp.json` + `.cursor/rules/ark.mdc` | `.cursor/commands/` |
237
+ | OpenAI Codex | `$CODEX_HOME/config.toml` (global; absolute `--root`; multi-project → secondary `ark_<slug>` unless `--force`; doctor defers non-temp home gaps when session host ≠ Codex — see [ai-gates.md](ai-gates.md)) | `$CODEX_HOME/prompts` (`--codex-home`; fix when using Codex) |
238
+ | **Grok Build** | `.grok/hooks/ark-write-gate.json` + `.grok/config.toml` / `.mcp.json` | `.grok/skills/<name>/SKILL.md` |
225
239
 
226
- Full copy-paste setups: [ai-gates.md](ai-gates.md). Skill inventory: main [README](../README.md#agent-skills-ark-).
240
+ This is a path reference, not a guarantee table. Full copy-paste setups:
241
+ [ai-gates.md](ai-gates.md). Skill inventory: main [README](../README.md#agent-skills-ark-).
227
242
 
228
- ## Contract Discovery
243
+ ## Experimental runtime: contract discovery
229
244
 
230
- Prefer `createStrictArkKernel()` for strict projects. It wires the registry, graph,
245
+ The runtime kernel is currently **experimental** and is not required for static gate adoption or
246
+ presented as production-ready. If you are evaluating it, prefer `createStrictArkKernel()`. It
247
+ wires the registry, graph,
231
248
  policies, event bus, audit trail, event contracts, outbox, observability,
232
249
  projections, metadata, workflow engine, and 11-layer architecture profile:
233
250
 
234
251
  ```ts
235
252
  import {
236
253
  createStrictArkKernel,
237
- } from 'arkgate/runtime';
254
+ } from '@arkgate/runtime';
238
255
 
239
256
  const ark = createStrictArkKernel();
240
257
  // ... define intents, event contracts, metadata, projections, and workflows through ark.*
@@ -244,8 +261,8 @@ const contract = ark.manifest().toJSON();
244
261
  // contract.observability, projections
245
262
  ```
246
263
 
247
- Prefer `arkgate/runtime` for the optional kernel (root `arkgate` still re-exports for
248
- compat). Package surface policy: [package-surface.md](package-surface.md).
264
+ Use `@arkgate/runtime` only when evaluating the experimental kernel. The stable `arkgate` gate
265
+ package contains no runtime implementation. Package surface policy: [package-surface.md](package-surface.md).
249
266
 
250
267
  Agents should read `contract` and `ark.observability.report()` before generating or modifying code.
251
268
 
@@ -354,11 +371,17 @@ if (!result.valid) {
354
371
  }
355
372
  ```
356
373
 
357
- Passing the `typescript` module enables built-in AST checks for raw publish calls, missing
358
- `metadata.source`, and source-layer mismatches. `ark-mcp` enables these checks
359
- automatically when TypeScript is available.
374
+ Passing the `typescript` module enables built-in AST/symbol checks for dependencies, forbidden
375
+ ambient globals, raw publish calls, missing `metadata.source`, and source-layer mismatches.
376
+ `ark-mcp` enables these checks automatically when TypeScript is available. The exact supported
377
+ syntax and unresolved-dynamic policy are documented in
378
+ [Scanner soundness envelope](ai-gates.md#scanner-soundness-envelope).
360
379
 
361
- 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`.
380
+ Relevant violation codes include `LAYER_IMPORT_VIOLATION`, `FORBIDDEN_GLOBAL`,
381
+ `DYNAMIC_IMPORT_NOT_ALLOWLISTED`, `DYNAMIC_REQUIRE_NOT_ALLOWLISTED`, `RAW_EVENT_PUBLISH`,
382
+ `PUBLISH_MISSING_SOURCE`, `PUBLISH_SOURCE_LAYER_MISMATCH`, `FORBIDDEN_PATTERN`,
383
+ `FORBIDDEN_SUBSTRING`, `FORBIDDEN_IMPORT`, `POLICY_VIOLATION`, `UNKNOWN_INTENT`,
384
+ `LAYER_REFERENCE_VIOLATION`, `EXTENSION_ERROR`, and `AST_ANALYZER_ERROR`.
362
385
 
363
386
  Use `ark-check` in CI for repository-level checks that need real file paths:
364
387
 
@@ -461,8 +484,9 @@ Example config:
461
484
  ```
462
485
 
463
486
  `ark-check` resolves imports through the TypeScript module resolver against your
464
- `tsconfig.json` — relative, path-alias (e.g. `@infra/db`), package imports, dynamic
465
- `import()`, and `require()` — plus string intent references. It also flags raw
487
+ `tsconfig.json` — relative, path-alias (e.g. `@infra/db`), package/workspace imports,
488
+ TypeScript `import = require()`, dynamic `import()`, and `require()` — plus string intent
489
+ references. It also flags raw
466
490
  `publish()` calls, publish calls without `metadata.source`, and source intent literals
467
491
  whose resolved layer differs from the publishing file layer. Pass `--tsconfig <path>` to force one config
468
492
  for every file; otherwise each source file uses the nearest `tsconfig.json` above it (like
@@ -623,8 +647,8 @@ Register the server itself in `.mcp.json` so the agent can read `ark://manifest`
623
647
  }
624
648
  ```
625
649
 
626
- This makes the manifest + AI gate an enforced checkpoint rather than a library the agent
627
- must remember to call.
650
+ On Claude/Grok, the installed PreToolUse hook makes matched writes an enforced checkpoint. MCP
651
+ registration by itself remains advisory on every host because the agent must call the tool.
628
652
 
629
653
  ## Recommended Agent Workflow
630
654
 
package/docs/ai-gates.md CHANGED
@@ -1,12 +1,14 @@
1
1
  # Gating AI Agents with ArkGate
2
2
 
3
3
  **ArkGate** (`arkgate`) is the architecture co-pilot for AI TypeScript (write gate · CI · plan/loop).
4
- The write-path gate is what makes it different from every other architecture linter:
5
- generated code is validated against your architecture **before it lands on disk**, not
6
- after the PR is red.
4
+ On Claude Code and Grok Build, an installed and trusted PreToolUse hook can block matched writes
5
+ before they land on disk. Cursor and OpenAI Codex use advisory MCP validation at write time; CI is
6
+ their hard repository check. Codex 0.123+ dispatches hooks for its native `apply_patch` handler,
7
+ but Code Mode hosts can execute deferred nested writes without that project hook event. See the
8
+ [canonical host support matrix](../README.md#host-enforcement-support) before installing.
7
9
 
8
10
  Everything below uses the same `ark.config.json` as `arkgate-check` / `ark-check` (CI) — one
9
- contract, enforced everywhere. Generate it once:
11
+ contract shared by every surface. Generate it once:
10
12
 
11
13
  ```bash
12
14
  npx arkgate-check --init
@@ -20,6 +22,11 @@ npx arkgate start
20
22
  # or: npx ark init
21
23
  ```
22
24
 
25
+ `ark start` asks for the active agent on a TTY (or detects it otherwise) and applies a compact
26
+ router setup: at most five project files and no `package.json` change unless you pass `--install`.
27
+ Use `--tools <host>` to select the host explicitly. The broader command below remains the explicit
28
+ way to install the full per-host `/ark-*` skill inventory.
29
+
23
30
  For non-interactive defaults, use:
24
31
 
25
32
  ```bash
@@ -34,14 +41,14 @@ npx arkgate-check --install-agent-gates
34
41
  ```
35
42
 
36
43
  The command writes templates for `.mcp.json`, Claude hooks, Cursor MCP/rules,
37
- GitHub Actions, `AGENTS.md`, a Codex TOML snippet under `docs/`, and (when
44
+ GitHub Actions, `AGENTS.md`, Codex `.codex/hooks.json` plus a TOML snippet under `docs/`, and (when
38
45
  selected) Grok Build project files under `.grok/`. It skips existing files unless
39
46
  you pass `--force`, so review and commit only the templates that match your project.
40
47
 
41
48
  **Doctor (W5):** `ark-check --doctor --json` includes `doctor.writePath`
42
49
  (`mode`: `repair` | `reject-only` | `mcp-only` | `none`, plus `prepareWrite` /
43
- `autoPatch` flags) so leads can see whether the write path is repair-capable or
44
- still reject-only.
50
+ `autoPatch` flags), the supported profile for the active host, and the evidence actually found.
51
+ Supported capability and installed guarantee are deliberately separate.
45
52
 
46
53
  If your project uses Codex or Grok, treat MCP registration as part of the default
47
54
  setup, not an optional extra. Ark works best when the agent can read `ark://manifest`
@@ -88,7 +95,7 @@ When no mechanical-safe patch applies, `autoPatch` is `null` (host still re-reas
88
95
  `ark_prepare_write` / judgment). Grok deny JSON also includes `autoPatch` + `"repair": true`
89
96
  when repair mode is on.
90
97
 
91
- `--install-agent-gates` writes Claude/Grok PreToolUse commands with `--hook-repair` enabled.
98
+ `--install-agent-gates` writes Claude/Grok/Codex PreToolUse commands with `--hook-repair` enabled.
92
99
  Reject-only installs: drop `--hook-repair` (or unset `ARK_HOOK_REPAIR`).
93
100
 
94
101
  Add to your project's `.claude/settings.json`:
@@ -223,12 +230,30 @@ path. If it reports violations, fix them before writing. The architecture
223
230
  contract is available as the `ark://manifest` resource.
224
231
  ```
225
232
 
226
- Your hard backstop in Cursor is CI: `ark-check` fails the PR on anything that slips through.
233
+ Your repository backstop in Cursor is CI: `ark-check` fails its check on anything that slips
234
+ through. It blocks the merge only when that status is required by repository policy.
227
235
 
228
236
  ## OpenAI Codex CLI
229
237
 
230
238
  Recommended for Ark projects.
231
239
 
240
+ Codex 0.123+ dispatches `PreToolUse` for the native `apply_patch` handler. Ark installs
241
+ `.codex/hooks.json` with `ApplyPatch|apply_patch|Write|Edit|MultiEdit` aliases and reconstructs
242
+ every added or updated file in a multi-file patch before allowing it. The hook root uses
243
+ `${CODEX_PROJECT_DIR:-${PWD:-.}}`; it must not use Claude-only `CLAUDE_PROJECT_DIR`.
244
+
245
+ This hook is best-effort in Codex Code Mode: some hosts execute deferred nested `apply_patch`
246
+ calls without dispatching the project `PreToolUse` event. ArkGate therefore does not treat the
247
+ presence of `.codex/hooks.json` as a universal hard-write guarantee; MCP remains advisory and the
248
+ required CI status is the hard repository boundary.
249
+
250
+ ```bash
251
+ npx ark-check --install-agent-gates --tools codex
252
+ ```
253
+
254
+ The generated hook includes `--hook-repair`, so a rejected patch carries the same structured
255
+ repair envelope as Claude and Grok. Codex still needs hook trust enabled for the project.
256
+
232
257
  Unlike Claude/Cursor (project-local MCP files), **Codex loads MCP servers only from
233
258
  `$CODEX_HOME/config.toml`** (default `~/.codex/config.toml`) — a **global** home file.
234
259
  Hand-editing with relative `--root .` is wrong: Codex does not use the project as cwd, so
@@ -251,8 +276,8 @@ args = ["arkgate-mcp", "--root", "/absolute/path/to/project", "--config", "/abso
251
276
  Then **restart Codex** — it does not hot-load MCP servers. Expect resource `ark://manifest`
252
277
  and tools `validate_code`, `ark_check`, `ark_coverage`, `ark_place`.
253
278
 
254
- Same model as Cursor for enforcement: MCP for discovery/validation, `ark-check` in CI as
255
- the hard gate. Register the MCP server as soon as the repo is adopted.
279
+ Codex uses the best-effort local patch hook plus advisory MCP for discovery/validation and
280
+ `ark-check` as the hard merge backstop. Register all three as soon as the repo is adopted.
256
281
 
257
282
  ### Multi-project Codex (home config last-wins)
258
283
 
@@ -272,11 +297,15 @@ primary A. It writes a **scoped secondary** table:
272
297
  |------|---------|
273
298
  | Add B without moving primary | `ark-check --install-agent-gates --tools codex` (no `--force`) |
274
299
  | Make B the primary binding | `ark-check --install-agent-gates --tools codex --force` |
275
- | Doctor: primary points at another permanent project | gap id `codex-home-multi-project` (warn if no secondary yet; info if scoped table already present) |
300
+ | Doctor: primary points at another permanent project | gap id `codex-home-multi-project` (warn if no secondary yet and session host is unknown/Codex; **info + `deferred`** when the session host is known and not Codex — e.g. Grok/Claude/Cursor; info if a scoped secondary is already present) |
301
+ | When using Codex: refresh home skills/MCP | `ark-check --install-agent-gates --skills-only --codex-home --force` |
276
302
 
277
303
  `ark-check --doctor` surfaces the multi-project state so you are not left thinking B owns
278
- `ark://manifest` when only a secondary table exists. Temp/upgrade primary roots are still
279
- rewritten fail-closed (not multi-project).
304
+ `ark://manifest` when only a secondary table exists. **Deferred (fix when using Codex):**
305
+ non-temp Codex-home gaps (`codex-home-multi-project`, stale `$CODEX_HOME/prompts`) are
306
+ severity **info**, marked `deferred: true`, and omitted from Top actions when the session
307
+ host is known and not Codex — `/ark-upgrade` on Grok/Claude is not Incomplete because of
308
+ them. **Temp/upgrade primary roots** stay fail-closed urgent (rewritten, not multi-project).
280
309
 
281
310
  ## Grok Build (xAI)
282
311
 
@@ -320,7 +349,8 @@ command = "npx"
320
349
  args = ["ark-mcp", "--root", ".", "--config", "ark.config.json"]
321
350
  ```
322
351
 
323
- Then restart Grok or refresh via `/mcps`. Pair with CI `ark-check` as the hard merge gate.
352
+ Then restart Grok or refresh via `/mcps`. Pair with CI `ark-check`; require that status if it
353
+ must block merges.
324
354
 
325
355
  ## Instruction-tier agents: Windsurf, Cline, Copilot, Kiro, Roo Code, Continue, Gemini CLI
326
356
 
@@ -345,14 +375,15 @@ npx ark-check --install-agent-gates --tools windsurf,cline,copilot,kiro,roo,cont
345
375
 
346
376
  All of them derive from the same contract as `AGENTS.md` and the Cursor rule, so the
347
377
  steps cannot drift. These are advisory (the agent reads rules; nothing blocks the
348
- write) keep `ark-check` in CI as the hard gate.
378
+ write). Keep `ark-check` in CI and require its status when it must block merges.
349
379
 
350
380
  ## Any other agent runtime with shell hooks
351
381
 
352
- If your runtime can run a shell command before file writes and pass the tool payload on stdin (Claude Code or Grok PreToolUse contracts), `ark-mcp --hook` works as-is. The contract:
382
+ If your runtime can run a shell command before file writes and pass the tool payload on stdin, `ark-mcp --hook` works as-is. The contract:
353
383
 
354
384
  - stdin (Claude): JSON `{ "tool_name": "Write|Edit|MultiEdit", "tool_input": { "file_path": ..., ... } }`
355
385
  - stdin (Grok): JSON `{ "toolName": "write|search_replace|…", "toolInput": { "file_path": ..., ... } }` (also accepts Claude names)
386
+ - stdin (Codex): JSON `{ "tool_name": "apply_patch", "tool_input": { "patch": "*** Begin Patch…" } }`
356
387
  - exit `0` → allow; exit `2` → block, human-readable violations on stderr
357
388
  - Grok payloads also get `{ "decision": "deny", "reason": "…" }` on stdout when blocked
358
389
  - plumbing problems (no stdin, non-source files, files outside `--root`) never block
@@ -387,14 +418,16 @@ Prefer keeping editor + CI on the same `ark.config.json` — do not maintain a p
387
418
 
388
419
  ## CI backstop
389
420
 
390
- Whatever the agent side does, gate the merge:
421
+ Whatever the agent side does, run the merge profile in CI:
391
422
 
392
423
  ```yaml
393
- - run: npx ark-check --root . --config ark.config.json --strict
424
+ - run: npx ark-check --root . --config ark.config.json --strict-merge
394
425
  ```
395
426
 
396
- The `--strict` profile also requires the generated CI/write gates and fails on safety
397
- diagnostics. Configure reviewed exceptions explicitly:
427
+ `--strict-merge` requires strict config plus the shared gate files (`AGENTS.md`, MCP config,
428
+ and CI workflow) and fails on safety diagnostics. `--strict` is a compatibility alias. Neither
429
+ profile requires an editor hook; add `--require-write-hook claude|grok` only when CI must verify
430
+ that host-specific local boundary too. Configure reviewed exceptions explicitly:
398
431
 
399
432
  ```json
400
433
  {
@@ -411,6 +444,31 @@ diagnostics. Configure reviewed exceptions explicitly:
411
444
  `ark-check --doctor --json` reports counts under `doctor.safety`. An `any` cast is
412
445
  reported as lost static assurance; it does not imply that a runtime schema was bypassed.
413
446
 
447
+ ### Scanner soundness envelope
448
+
449
+ ArkGate uses the TypeScript compiler API for the governed source files. The repository scanner
450
+ and `createAICodeGate({ typescript })` recognize these dependency forms:
451
+
452
+ - `import ... from 'literal'`, side-effect imports, and `export ... from 'literal'`;
453
+ - TypeScript `import x = require('literal')` external-module references;
454
+ - direct `import('literal')` and direct `require('literal')` calls; and
455
+ - relative, tsconfig path-alias, package, and installed workspace-package targets that resolve
456
+ to source inside the project root. Third-party or escaped targets are deliberately not governed.
457
+
458
+ Direct `import(expr)` emits `DYNAMIC_IMPORT_NOT_ALLOWLISTED`; direct `require(expr)` emits
459
+ `DYNAMIC_REQUIRE_NOT_ALLOWLISTED`. They are warnings in the default reporting profile and fail
460
+ `--strict-config` / `--strict-merge`. The existing `dynamicImportAllowlist` name is retained for
461
+ compatibility and is the reviewed file-level exception for both forms. Aliased loaders (for
462
+ example `const load = require; load(expr)`) and runtime-computed module maps are not resolved.
463
+
464
+ Forbidden globals use single-file TypeScript binding: parameters, variables, functions, classes,
465
+ and imports declared in the file shadow ambient names. Bare ambient value references are reported
466
+ even when assigned to an alias, and static dotted access through `globalThis` is normalized (for
467
+ example `globalThis.Date.now()`). This is not whole-program data-flow analysis: computed property
468
+ names, aliases of dotted members, and cross-file symbol provenance are outside the current
469
+ envelope. When callers omit the `typescript` option, AICodeGate retains its conservative literal
470
+ fallback and does not claim symbol-aware parity; the shipped `ark-mcp` path supplies TypeScript.
471
+
414
472
  Adopting Ark on an existing codebase with violations? Freeze them once and ratchet down:
415
473
 
416
474
  ```bash
@@ -0,0 +1,97 @@
1
+ # Versioned `ark.config.json`
2
+
3
+ ArkGate treats `ark.config.json` as a versioned product contract, not an untyped settings bag.
4
+ The CLI, MCP server, and ESLint plugin all use the same parser, migration, defaults, and validator.
5
+
6
+ ## Start a config
7
+
8
+ `arkgate start`, `arkgate init`, and every preset emit the current metadata:
9
+
10
+ ```json
11
+ {
12
+ "$schema": "https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",
13
+ "schemaVersion": "1.0",
14
+ "include": ["src"],
15
+ "layers": [],
16
+ "rules": []
17
+ }
18
+ ```
19
+
20
+ `$schema` is for editor completion. `schemaVersion` controls ArkGate's runtime contract and is
21
+ independent from the npm package version.
22
+
23
+ For offline editor completion, point `$schema` at the installed file instead:
24
+
25
+ ```json
26
+ {
27
+ "$schema": "./node_modules/arkgate/schemas/ark.config.schema.json",
28
+ "schemaVersion": "1.0"
29
+ }
30
+ ```
31
+
32
+ The same schema is exported through the stable package subpaths `arkgate/schema` and
33
+ `arkgate/schema/ark.config.schema.json`. Node tooling can locate it with
34
+ `require.resolve('arkgate/schema')`.
35
+
36
+ ## Compatibility and migration
37
+
38
+ Configs without `schemaVersion` are the legacy shape shipped through ArkGate 1.x and early 2.x.
39
+ The loader deterministically projects them to schema `1.0` in memory by adding contract metadata
40
+ and the established defaults. It never rewrites the user's file during a check. Newly generated
41
+ configs always contain the metadata, and unsupported future versions fail at
42
+ `$.schemaVersion` instead of being guessed.
43
+
44
+ Current defaults are:
45
+
46
+ | Field | Default |
47
+ |---|---|
48
+ | `include` | `["src"]` |
49
+ | `layers` | `[]` |
50
+ | `rules` | ArkGate's strict 11-layer deny matrix |
51
+ | `exclude` | `[]` |
52
+ | `excludeGenerated` | `true` |
53
+ | `cyclePolicy` | `"strict"` |
54
+ | `dynamicImportAllowlist` | `[]` |
55
+ | safety thresholds | zero; opt-ins disabled |
56
+
57
+ JSON Schema `default` values document the effective behavior. Optional defaults are not written
58
+ back to disk.
59
+
60
+ ## Unknown and invalid fields
61
+
62
+ Unknown fields fail closed at every object level. Diagnostics name the exact JSON path:
63
+
64
+ ```text
65
+ Invalid ArkGate config (/repo/ark.config.json):
66
+ - $.layers[0].forbiddenGlobal: unknown field
67
+ ```
68
+
69
+ The same input cannot pass CI while being silently ignored by MCP or ESLint. Invalid JSON, wrong
70
+ types, empty required strings, duplicate string-array entries, negative safety thresholds, and
71
+ unsupported schema versions also fail before scanning begins.
72
+
73
+ ## Supported fields
74
+
75
+ Top-level fields:
76
+
77
+ - `$schema`, `schemaVersion`, `name`
78
+ - `include`, `exclude`, `excludeGenerated`, `frameworkOverlay`
79
+ - `layers`, `rules`, `cyclePolicy`
80
+ - `dynamicImportAllowlist`, `safety`
81
+
82
+ Layer fields:
83
+
84
+ - `name`, `patterns`, `exclude`, `description`
85
+ - `intentPrefixes`, `forbiddenGlobals`, `mayImportInfrastructure`, `optional`
86
+
87
+ Rule fields:
88
+
89
+ - `from`, `to`, `allowed`, `message`, `peerIsolation`, `sliceFolders`
90
+
91
+ Safety fields:
92
+
93
+ - `maxTsSuppressions`, `maxAnyCasts`
94
+ - `allowInMemory`, `allowDisabledPeerIsolation`
95
+
96
+ The packaged JSON Schema is authoritative for types, constraints, defaults, and the unknown-key
97
+ policy.
@@ -15,7 +15,7 @@ aliases `ark` / `ark-check` still work).
15
15
  |------|---------|
16
16
  | **Suggest** | Propose an application shape and install a starter contract. |
17
17
  | **Adapt** | Match the contract to your real layout / raise governed coverage. |
18
- | **Enforce** | The contract actually governs your code; gates hold the line. |
18
+ | **Enforce** | The contract covers the real code and checked edges are clean; host/CI guarantees remain separate. |
19
19
 
20
20
  `ark start` and `ark-check --plan` will not claim "everything is guarded" while governed coverage is near zero. On Nest/Next/express starters, init also merges **framework filename conventions** into the layer globs so day-one coverage is real.
21
21
 
@@ -27,7 +27,7 @@ aliases `ark` / `ark-check` still work).
27
27
  | **How-to** | [Pick your application shape](how-to-pick-shape.md) | Run `--recommend` / `ark_recommend` and read the plan |
28
28
  | **How-to** | [Use a gallery starter](how-to-gallery-starter.md) | Copy a phase-1 scaffold that matches your archetype |
29
29
  | **How-to** | [Apply an enthusiast policy pack](how-to-policy-pack.md) | Write `ark.config.json` from a named preset |
30
- | **How-to** | [Install agent gates](how-to-agent-gates.md) | Wire the write gate and `/ark-*` skills |
30
+ | **How-to** | [Install agent gates](how-to-agent-gates.md) | Wire the host-appropriate write path and `/ark-*` skills |
31
31
  | **Reference** | [Archetypes and presets](reference-archetypes.md) | Look up playbook ids, presets, and phase-1 layers |
32
32
  | **Reference** | [Commands and artifacts](reference-commands.md) | `--recommend`, `--write-plan`, `ark-adoption-plan.json`, fix-class JSON |
33
33
  | **Explanation** | [Why application shape matters](explanation-application-shape.md) | Understand shapes vs frameworks and progressive phases |
@@ -60,4 +60,4 @@ Deep teaching example (runnable API + break exercises): [hexagonal-order-api](..
60
60
 
61
61
  - [Agent integration guide](../agent-guide.md)
62
62
  - [Public demos](../demos/)
63
- - [Examples index](../../examples/README.md)
63
+ - [Examples index](../../examples/README.md)
@@ -8,7 +8,7 @@ npx arkgate-check --install-agent-gates --tools claude,cursor,codex,grok
8
8
 
9
9
  Installs:
10
10
 
11
- - Write-gate hook configuration (Claude / Grok PreToolUse; Cursor advisory + MCP)
11
+ - Write-path configuration (Claude/Grok hard PreToolUse; Cursor/Codex advisory MCP)
12
12
  — PreToolUse uses **`--hook-repair`** (W4): on deny, stderr may include
13
13
  `ARK_REPAIR_JSON` / `ARK_AUTOPATCH_JSON` for hosts that re-inject a patch.
14
14
  Still exit 2 / hard block; never silent write. Drop `--hook-repair` for
@@ -24,6 +24,9 @@ Installs:
24
24
  | Codex | `docs/ark-codex-config.toml` + home MCP/prompts |
25
25
  | **Grok Build** | `.grok/config.toml`, `.grok/hooks/`, `.grok/skills/` |
26
26
 
27
+ See the [canonical host support matrix](../../README.md#host-enforcement-support) for the exact
28
+ local, MCP, CI, and repair guarantees. The table above only lists installed paths.
29
+
27
30
  ## Session hint
28
31
 
29
32
  `arkgate-mcp --session-context` appends when governed coverage is low:
@@ -39,7 +42,8 @@ npx arkgate-check --doctor
39
42
  npx arkgate-check --require-gates
40
43
  ```
41
44
 
42
- Doctor JSON (`--doctor --json`) includes **`writePath`**: whether PreToolUse is
45
+ Doctor JSON (`--doctor --json`) includes **`writePath`**: the active host's supported profile,
46
+ installed evidence, and whether PreToolUse is
43
47
  `repair` (machine-readable autoPatch on deny), `reject-only`, `mcp-only`, or
44
48
  `none` — plus `prepareWrite` / `autoPatch` booleans for leads.
45
49
 
@@ -49,4 +53,4 @@ After upgrading the package, refresh skills so agents see the latest plan kinds:
49
53
  npx arkgate-check --install-agent-gates --skills-only --force
50
54
  ```
51
55
 
52
- Full copy-paste setups: [docs/ai-gates.md](../ai-gates.md).
56
+ Full copy-paste setups: [docs/ai-gates.md](../ai-gates.md).
@@ -129,13 +129,15 @@ Or edit `.grok/config.toml` → `args` use `arkgate-mcp`.
129
129
 
130
130
  ### TypeScript imports (runtime / Nest / ESLint only)
131
131
 
132
+ The runtime and Nest surfaces are currently **experimental**; migrating the package name does not
133
+ require adopting them. Static CLI/MCP enforcement remains the supported product path.
134
+
132
135
  ```diff
133
136
  - import { createStrictArkKernelFromConfig } from 'ark-runtime-kernel';
134
- + import { createStrictArkKernelFromConfig } from 'arkgate/runtime';
135
- // root `arkgate` still re-exports kernel symbols this major (compat)
137
+ + import { createStrictArkKernelFromConfig } from '@arkgate/runtime';
136
138
 
137
139
  - import { ArkModule } from 'ark-runtime-kernel/nestjs';
138
- + import { ArkModule } from 'arkgate/nestjs';
140
+ + import { ArkModule } from '@arkgate/runtime/nestjs';
139
141
 
140
142
  - import ark from 'ark-runtime-kernel/eslint';
141
143
  + import ark from 'arkgate/eslint';
@@ -3,10 +3,10 @@
3
3
  **Product wedge:** write gate · CI gate · co-pilot (plan / loop / skills).
4
4
  **Not the wedge:** the optional in-process runtime kernel.
5
5
 
6
- **Public product site:** [arkgate.online](https://www.arkgate.online/) (promise + only flow).
6
+ **Public product site:** [arkgate.online](https://www.arkgate.online/) (promise + only flow).
7
7
  In-repo `docs/` remains the package/agent reference. Source: GitHub; distribution: npm.
8
8
 
9
- This document is the consumer contract for **what is stable** vs **what is opt-in**.
9
+ This document is the consumer contract for **what is stable** vs **what is experimental**.
10
10
 
11
11
  ---
12
12
 
@@ -16,7 +16,9 @@ This document is the consumer contract for **what is stable** vs **what is opt-i
16
16
  |---------|----------------|-----------------|
17
17
  | **CLI** | `arkgate` / `arkgate-check` (aliases `ark` / `ark-check`) | Flags and human text may improve; **JSON output shapes** for `--json` (check, doctor, plan, coverage, recommend) are stable within a major. Additive fields OK; removals/renames are major. |
18
18
  | **MCP tools** | `arkgate-mcp` / `ark://…` resources | Tool names and primary argument shapes are stable within a major. |
19
- | **`ark.config.json`** | Layer globs, rules, include/exclude, forbiddenGlobals, intent prefixes, `peerIsolation`, `dynamicImportAllowlist`, `safety` thresholds | Schema fields documented in playbooks/examples are stable; new optional fields may appear. |
19
+ | **`ark.config.json`** | Layer globs, rules, include/exclude, forbiddenGlobals, intent prefixes, `peerIsolation`, `dynamicImportAllowlist`, `safety` thresholds | Versioned by `schemaVersion`; unknown fields fail closed and migrations preserve the previous supported major. |
20
+ | **`arkgate/schema/analysis-result`** | Public CLI/MCP/hook diagnostic envelope (`schemaVersion`, `valid`, `diagnostics`) | Versioned JSON Schema; committed v1 compatibility fixture protects rule, severity, location, and evidence fields. |
21
+ | **Config JSON Schema** | `arkgate/schema` or `arkgate/schema/ark.config.schema.json` | Stable package resource subpaths for editor completion and contract tooling. |
20
22
  | **Agent skills** | `/ark-*` templates installed by `--install-agent-gates` | Skill *names* and “default flow” are stable; internal skill prose may evolve (e.g. explore dual-plan seed, day-zero origin order). |
21
23
  | **ESLint subpath** | `arkgate/eslint` | Config-driven layer/import rules; loads consumer `ark.config.json`. |
22
24
  | **GitHub Action** | `pedroknigge/arkgate` (see `action.yml`) | The `uses:` tag/SHA selects the checker source; `version` remains an optional exact npm compatibility override. |
@@ -25,33 +27,31 @@ Gates need **no application code imports**. Most projects only use the CLI + MCP
25
27
 
26
28
  ---
27
29
 
28
- ## Opt-in surfaces
30
+ ## Experimental opt-in surfaces
31
+
32
+ These APIs are shipped for evaluation and compatibility, but they are **not production-ready
33
+ product claims**. Static architecture enforcement does not depend on them.
29
34
 
30
35
  | Surface | Import path | Notes |
31
36
  |---------|-------------|--------|
32
- | **Runtime kernel** | **`arkgate/runtime`** (preferred) | Event bus, intents, policies, sagas, outbox, projections, `createArkKernel` / strict helpers. Optional. Not required for architecture enforcement. Built-in stores are **InMemory reference only** (not production durability) — see [production-hardening.md](./production-hardening.md). |
33
- | **Root package barrel** | `arkgate` | Still re-exports the runtime kernel for **compatibility**. Prefer `arkgate/runtime` for new code. Root may be thinned in a future **major**. |
34
- | **NestJS adapter** | `arkgate/nestjs` | Optional peer `@nestjs/common`. Wires a kernel into Nest DI. |
37
+ | **Runtime kernel** | **`@arkgate/runtime`** | Separate 0.x package, published under the `experimental` tag. Event bus, intents, policies, sagas, event buffer, projections, and strict helpers. Built-in stores are **InMemory reference only**. |
38
+ | **Runtime migration shim** | `arkgate/runtime` | Deprecated forwarder to `@arkgate/runtime`; contains no implementation and is removed in ArkGate 4. |
39
+ | **NestJS adapter** | `@arkgate/runtime/nestjs` | Experimental optional peer `@nestjs/common`; the deprecated `arkgate/nestjs` path forwards here. |
35
40
 
36
41
  ---
37
42
 
38
43
  ## Recommended imports
39
44
 
40
45
  ```ts
41
- // Preferred opt-in runtime kernel
42
- import {
43
- createStrictArkKernel,
44
- createStrictArkKernelFromConfig,
45
- } from 'arkgate/runtime';
46
-
47
- // Still works this major (compat; not preferred for new code)
48
- import { createStrictArkKernel } from 'arkgate';
46
+ // Preferred path when evaluating the experimental runtime kernel
47
+ import { createStrictArkKernel, createStrictArkKernelFromConfig } from '@arkgate/runtime';
49
48
 
50
49
  // Nest adapter
51
- import { ArkModule, InjectArk } from 'arkgate/nestjs';
50
+ import { ArkModule, InjectArk } from '@arkgate/runtime/nestjs';
52
51
  ```
53
52
 
54
- See [production-hardening.md](./production-hardening.md) for runtime operational guidance.
53
+ See [production-hardening.md](./production-hardening.md) for requirements an eventual
54
+ production deployment would need to satisfy; it is not a readiness certification.
55
55
 
56
56
  ---
57
57
 
@@ -71,8 +71,8 @@ See [production-hardening.md](./production-hardening.md) for runtime operational
71
71
  | Break CLI JSON field, MCP tool rename, or required `ark.config` field | **major** |
72
72
  | New optional config field, new CLI flag, additive JSON | **minor** |
73
73
  | Bugfix with no contract change | **patch** |
74
- | Prefer `arkgate/runtime` over root (docs only; root still exports) | **patch/minor** |
75
- | Remove root kernel re-exports | **major** (with migration notes) |
74
+ | Additive experimental runtime API | `@arkgate/runtime` prerelease/minor |
75
+ | Remove deprecated `arkgate/runtime` forwarding shim | ArkGate **4.0** |
76
76
 
77
77
  ---
78
78