arkgate 4.6.7 → 4.7.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 (56) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/README.md +20 -9
  3. package/SECURITY.md +1 -1
  4. package/bin/ark-check-runtime.mjs +13 -1
  5. package/bin/ark-mcp-runtime.mjs +65 -3
  6. package/bin/lib/adapter-contract.mjs +17 -36
  7. package/bin/lib/analysis-engine.mjs +6 -6
  8. package/bin/lib/ark-run-doctor.mjs +144 -0
  9. package/bin/lib/ark-run-facts.mjs +472 -0
  10. package/bin/lib/ark-run-report.mjs +57 -0
  11. package/bin/lib/ark-run-sensors.mjs +309 -0
  12. package/bin/lib/config-contract.mjs +86 -11
  13. package/bin/lib/diagnostic-catalog.mjs +8 -0
  14. package/bin/lib/doctor-advisories.mjs +45 -8
  15. package/bin/lib/doctor-human.mjs +10 -0
  16. package/bin/lib/doctor-plan.mjs +20 -16
  17. package/bin/lib/extra-merge-teeth.mjs +187 -0
  18. package/bin/lib/html-report-advisories.mjs +2 -0
  19. package/bin/lib/html-report-depth.mjs +22 -2
  20. package/bin/lib/html-report.mjs +16 -0
  21. package/bin/lib/remediation.mjs +132 -0
  22. package/bin/lib/resolved-candidate-facts.mjs +67 -2
  23. package/bin/lib/rules-under-contract.mjs +37 -89
  24. package/bin/lib/snippet-analysis.mjs +43 -2
  25. package/bin/lib/status-command.mjs +28 -0
  26. package/bin/lib/status-manifest.mjs +23 -0
  27. package/dist/{configTypes-l6XiwiC1.d.ts → configTypes-CgJimx9o.d.ts} +17 -3
  28. package/dist/eslint/index.cjs +6 -2
  29. package/dist/eslint/index.d.ts +70 -2
  30. package/dist/eslint/index.js +6 -2
  31. package/dist/index.cjs +35 -35
  32. package/dist/index.d.ts +787 -272
  33. package/dist/index.js +35 -35
  34. package/docs/README.md +2 -1
  35. package/docs/agent-guide.md +21 -15
  36. package/docs/ai-gates.md +13 -0
  37. package/docs/configuration.md +24 -11
  38. package/docs/develop.md +12 -3
  39. package/docs/diagnostics.md +75 -0
  40. package/docs/enthusiast/README.md +4 -3
  41. package/docs/package-surface.md +16 -13
  42. package/docs/product-voice.md +6 -3
  43. package/docs/threat-model.md +1 -1
  44. package/docs/use.md +5 -4
  45. package/package.json +1 -1
  46. package/schemas/ark.config.schema.json +41 -2
  47. package/schemas/ark.resolved-candidate-facts.schema.json +1 -1
  48. package/schemas/ark.status-manifest.schema.json +47 -0
  49. package/server.json +2 -2
  50. package/templates/agent-skills/README.md +1 -1
  51. package/templates/agent-skills/ark-adopt/SKILL.md +23 -2
  52. package/templates/agent-skills/ark-place/SKILL.md +26 -2
  53. package/templates/agent-skills/ark-runtime/SKILL.md +66 -24
  54. package/templates/skills/ark-adopt.md +23 -2
  55. package/templates/skills/ark-place.md +26 -2
  56. package/templates/skills/ark-runtime.md +66 -24
package/docs/README.md CHANGED
@@ -53,11 +53,12 @@ These are **not** the day-to-day product path. They stay in the repo for evidenc
53
53
  | Area | Path |
54
54
  |------|------|
55
55
  | Release notes (by version) | [releases/](releases/) · npm [CHANGELOG.md](../CHANGELOG.md) (Unreleased + 4.6.x) · [pre-4.6 archive](archive/CHANGELOG-pre-4.6.md) |
56
- | Epic plans | [plans/](plans/) — maintainer seeds, not required to use the package. Live: [alive-in-six-months](plans/alive-in-six-months/README.md) (`AL01`–`AL04` done on `main`; `AL05` parked). |
56
+ | Epic plans | [plans/](plans/) — maintainer seeds, not required to use the package. Live: [alive-in-six-months](plans/alive-in-six-months/README.md) (`AL01`–`AL04` done; `AL05` parked). [arkrun](plans/arkrun/README.md) (Phase RN; `RN01`–`RN15` done; `RN16` preparing **4.7.0**; ADRs [0020](adr/0020-arkrun-gated-extra-plane.md)–[0024](adr/0024-arkrun-transport-ports.md) accepted). |
57
57
  | Claims audit | [audit/claims-matrix.md](audit/claims-matrix.md) |
58
58
  | Field adoption kit (scaffolding, not closed) | [field/](field/) |
59
59
  | Runtime hardening (experimental) | [production-hardening.md](production-hardening.md) |
60
60
 
61
+ Current tree: [releases/4.7.0.md](releases/4.7.0.md) (`arkgate@4.7.0` prepared).
61
62
  Current published: [releases/4.6.7.md](releases/4.6.7.md) (`arkgate@4.6.7` on npm `latest`).
62
63
  Prior: [releases/4.6.6.md](releases/4.6.6.md) · [4.6.5](releases/4.6.5.md) · [4.6.4](releases/4.6.4.md) · [4.6.3](releases/4.6.3.md) · [4.6.2](releases/4.6.2.md) · [4.6.1](releases/4.6.1.md) · [4.6.0](releases/4.6.0.md).
63
64
  Older notes: [releases/](releases/). Config: [configuration.md](configuration.md).
@@ -688,11 +688,12 @@ cp node_modules/arkgate/templates/tests/ark-adoption-gaps.test.ts tests/ark-adop
688
688
 
689
689
  It checks real on-disk contract, MCP, skill, and report artifacts; it does not mock the gate.
690
690
 
691
- ## Experimental runtime: contract discovery
691
+ ## ArkRun kernel: contract discovery
692
692
 
693
- The runtime kernel is currently **experimental** and is not required for static gate adoption or
694
- presented as production-ready. If you are evaluating it, prefer `createStrictArkKernel()`. It
695
- wires the registry, graph,
693
+ The **ArkRun** kernel (`@arkgate/runtime`) is currently **experimental** and is not required for
694
+ static gate adoption or presented as production-ready. If you are evaluating it, prefer
695
+ `createStrictArkKernel()`. Each call creates an isolated instance — there is no process-wide
696
+ singleton. It wires the registry, graph,
696
697
  policies, event bus, audit trail, event contracts, outbox, observability,
697
698
  projections, metadata, workflow engine, and 11-layer architecture profile:
698
699
 
@@ -709,12 +710,13 @@ const contract = ark.manifest().toJSON();
709
710
  // contract.observability, projections
710
711
  ```
711
712
 
712
- Use `@arkgate/runtime` only when evaluating the experimental kernel. The stable `arkgate` gate
713
- package contains no runtime implementation. The companion is not currently present in the npm
714
- registry and is not published by the root release workflow. Verify availability with
715
- `npm view @arkgate/runtime dist-tags --json`; until a separate experimental publication exists,
716
- evaluate it only from a source checkout after `npm run build:runtime` and install the local
717
- `packages/runtime` folder. Package surface policy: [package-surface.md](package-surface.md).
713
+ Use `@arkgate/runtime` only when evaluating the experimental ArkRun kernel. The stable `arkgate`
714
+ gate package contains no runtime implementation (the kernel is not in the `arkgate` tarball). The
715
+ companion is not currently present in the npm registry and is not published by the root release
716
+ workflow. Verify availability with `npm view @arkgate/runtime dist-tags --json`; until a separate
717
+ experimental publication exists, evaluate it only from a source checkout after
718
+ `npm run build:runtime` and install the local `packages/runtime` folder. Package surface policy:
719
+ [package-surface.md](package-surface.md).
718
720
 
719
721
  Agents should read `contract` and `ark.observability.report()` before generating or modifying code.
720
722
 
@@ -968,7 +970,10 @@ export default [
968
970
  Rules: `ark/no-domain-infra-imports` (exact parity for on-disk, in-scope static relative
969
971
  imports/exports; resolved CLI/preflight is authoritative outside that envelope),
970
972
  `ark/no-forbidden-globals` (per-layer `forbiddenGlobals`),
971
- `ark/no-denied-capabilities` (per-layer capability deny sets), `ark/no-raw-event-publish`, and
973
+ `ark/no-denied-capabilities` (per-layer capability deny sets),
974
+ `ark/no-arkrun-kernel-in-domain` / `ark/no-arkrun-direct-new` /
975
+ `ark/no-arkrun-transport-bypass` (ArkRun extra; silent when absent; import / `new`
976
+ envelope only), `ark/no-raw-event-publish`, and
972
977
  `ark/require-publish-source`. See [ai-gates.md](ai-gates.md).
973
978
 
974
979
  ## Runtime Observability
@@ -1208,11 +1213,12 @@ advisory on every host because the agent must call the tool.
1208
1213
 
1209
1214
  Decision rationale: [ADR 0017 — MCP verdicts require explicit project identity](adr/0017-mcp-project-identity-binding.md).
1210
1215
 
1211
- ## Experimental runtime kernel workflow (not the default path)
1216
+ ## ArkRun kernel workflow (not the default path)
1212
1217
 
1213
- This section is for adopters who **opt into** the experimental `@arkgate/runtime` / kernel surfaces.
1214
- It is **not** the Beautiful Path day-zero curriculum. Default remains: `ark start` doctor compact
1215
- router (and `/ark-autopilot` only after the skill pack).
1218
+ This section is for adopters who **opt into** the experimental **ArkRun** kernel
1219
+ (`@arkgate/runtime`). Construct it with `createStrictArkKernel` (per instance; no process-wide
1220
+ singleton). It is **not** the Beautiful Path day-zero curriculum. Default remains: `ark start` →
1221
+ doctor → compact router (and `/ark-autopilot` only after the skill pack).
1216
1222
 
1217
1223
  1. **Read** manifest via `ark.manifest().toJSON()`
1218
1224
  2. **Generate** code using registered intents, profiles, metadata, projections, and workflow definitions
package/docs/ai-gates.md CHANGED
@@ -687,6 +687,8 @@ export default [
687
687
  // no-domain-infra-imports → config-driven layer edges (type-only + value)
688
688
  // no-forbidden-globals → layer.forbiddenGlobals from ark.config.json
689
689
  // ark/no-denied-capabilities → layer.capabilities.deny / layer.pure
690
+ // ark/no-arkrun-kernel-in-domain + no-arkrun-direct-new + no-arkrun-transport-bypass
691
+ // → arkRun extra (silent when absent; import / `new` envelope only)
690
692
  // no-raw-event-publish + require-publish-source → runtime event hygiene
691
693
  ];
692
694
  ```
@@ -714,6 +716,17 @@ Additional rule notes:
714
716
  - Value forbidden edges error (same pass/fail as `arkgate-check`). Type-only forbidden edges are **placement debt** (reported with `typeOnly`); merge blocking prefers value edges — align with doctor `typeEdgePolicy`.
715
717
  - `no-forbidden-globals` applies from the file layer’s `forbiddenGlobals`; the `globals` option is only a standalone fallback when no project config applies, never an override that weakens the project contract. Layers without either surface are not inventively restricted. `process` also owns exact value imports of `process` / `node:process`; type-only forms, subpaths, and `child_process` stay excluded. If the same layer also denies the `process` capability, this rule is the single `FORBIDDEN_GLOBAL` voice.
716
718
  - Without `ark.config.json`, `no-domain-infra-imports` emits no contract verdict.
719
+ - **ArkRun (RN06):** when `arkRun` is present, `no-arkrun-kernel-in-domain`,
720
+ `no-arkrun-direct-new`, and `no-arkrun-transport-bypass` reuse the same
721
+ `ARKRUN_*` sensors as ark-check. Envelope is the current file: package
722
+ specifiers (kernel / closed broker list), `require` / export / dynamic-literal
723
+ of those specifiers, and `new` of constructors admitted from this file's
724
+ exported classes, `@arkgate/runtime` PascalCase imports, or on-disk
725
+ relative/alias import targets. Absence of the extra is silent. Composition-root
726
+ factory files skip `direct-new`. Domain-role layers skip `direct-new` and flag
727
+ kernel imports (including type-only). Type-only broker imports do not flag
728
+ transport-bypass. Missing-root and undeclared emit/handle/depend are **not**
729
+ in this adapter — use CLI / preflight / CI.
717
730
 
718
731
  Rule ids are `ark/<kebab-name>`. Individual rules are also on `ark.rules` if you wire them by hand.
719
732
  Prefer keeping editor + CI on the same `ark.config.json`. Use the rule-local `globals` list only
@@ -10,7 +10,7 @@ The CLI, MCP server, and ESLint plugin all use the same parser, migration, defau
10
10
  ```json
11
11
  {
12
12
  "$schema": "https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",
13
- "schemaVersion": "1.1",
13
+ "schemaVersion": "1.2",
14
14
  "include": ["src"],
15
15
  "layers": [],
16
16
  "rules": []
@@ -19,9 +19,11 @@ The CLI, MCP server, and ESLint plugin all use the same parser, migration, defau
19
19
 
20
20
  `$schema` is for editor completion. `schemaVersion` controls ArkGate's runtime contract and is
21
21
  independent from the npm package version. Schema **`1.1`** is additive over `1.0` and adds the
22
- optional top-level **`arkRules`** map (ADR 0012). Absence of `arkRules` changes no inter-layer
23
- verdict. Per-layer structure/invariant files use sibling schema
24
- `arkgate/schema/arkrules` (`schemas/ark.arkrules.schema.json`).
22
+ optional top-level **`arkRules`** map (ADR 0012). Schema **`1.2`** is additive over `1.1` and
23
+ adds the optional top-level **`arkRun`** extra (ADR 0020). Absence of `arkRules` or `arkRun`
24
+ changes no Layers / ArkRules verdict. Per-layer structure/invariant files use sibling schema
25
+ `arkgate/schema/arkrules` (`schemas/ark.arkrules.schema.json`). ArkRun v1 stays **inline**
26
+ (no sibling file).
25
27
 
26
28
  For offline editor completion, point `$schema` at the installed file instead:
27
29
 
@@ -39,7 +41,7 @@ The same schema is exported through the stable package subpaths `arkgate/schema`
39
41
  ## Compatibility and migration
40
42
 
41
43
  Configs without `schemaVersion` are the legacy shape shipped through ArkGate 1.x and early 2.x.
42
- The loader deterministically projects them through `unversioned → 1.0 → 1.1` in memory by adding
44
+ The loader deterministically projects them through `unversioned → 1.0 → 1.1 → 1.2` in memory by adding
43
45
  contract metadata and the established defaults. It never rewrites the user's file during a check.
44
46
  Newly generated
45
47
  configs always contain the metadata, and unsupported future versions fail at
@@ -85,6 +87,15 @@ Top-level fields:
85
87
  - **`arkRules`** (optional, schema `1.1+`) — map of layer name → project-relative path to an
86
88
  ArkRules file (e.g. `"DomainModel": "arkrules/DomainModel.json"`). Keys must match a declared
87
89
  layer. Missing/invalid referenced files **fail closed**.
90
+ - **`arkRun`** (optional, schema `1.2+`) — inline ArkRun extra (`mode`, `compositionRoots`,
91
+ `managedLayers`, `requireDeclarations`). Absence is silent. Unknown keys fail closed.
92
+ `managedLayers` must name existing `layers[].name` values. Empty `compositionRoots` in
93
+ `enforced` mode fails closed (`ARKRUN_MISSING_ROOT`); empty `managedLayers` in `enforced`
94
+ mode also fails closed (direct-new / undeclared / transport-bypass would otherwise no-op).
95
+ Compact starters do not enable this extra. Demotion (`enforced` → `advisory`) or deletion
96
+ is a policy-delta **weakening**. Enforced extra teeth share the CLI / MCP / hook /
97
+ preflight / CI verdict and arm only when the layer plane is classified (same ≥50%
98
+ governed and ≥1 populated-layer floor as ArkRules).
88
99
 
89
100
  Layer fields:
90
101
 
@@ -142,14 +153,16 @@ See [brownfield adoption](brownfield-adoption.md#nextjs-honesty-default-overlays
142
153
  | **Layers** | Inter-layer import graph | Always on |
143
154
  | **Structure sensors** | Intra-layer heuristics | Only `mode: "enforced"` |
144
155
  | **Invariants** | Catalog + coverage evidence (not a business runtime) | Only enforced + proven-uncovered |
156
+ | **ArkRun** (opt-in extra) | Kernel usage + complete declarations | Only `arkRun.mode: "enforced"` when classified |
145
157
 
146
- Absence of `arkRules` adds **no** extra merge teeth. **Advisory** structure sensors and advisory
147
- invariants also add **no** merge teeth (FG-ARKRULES-ADVISORY-ONLY) — packing every starter
148
- `arkrules/*` file does not make merge fail structure alone. Enforced structure/invariants arm
158
+ Absence of `arkRules` or `arkRun` adds **no** extra merge teeth. **Advisory** structure sensors, advisory
159
+ invariants, and advisory ArkRun also add **no** merge teeth (FG-ARKRULES-ADVISORY-ONLY / ADR 0020) — packing every starter
160
+ `arkrules/*` file does not make merge fail structure alone. Enforced structure/invariants/ArkRun arm
149
161
  `mergePlanes.extraMergeTeeth` only when the layer plane is honestly classified
150
- (governed ≥ 50% and ≥ 1 populated layer); empty classification never gets structure teeth
151
- (P1M-EXTRATEETH-EMPTY-GRAPH). Structure and invariants **never** merge into one architecture
152
- score. Doctor exposes `rulesUnderContract.mergePlanes` for which plane can fail.
162
+ (governed ≥ 50% and ≥ 1 populated layer); empty classification never gets extra-plane teeth
163
+ (P1M-EXTRATEETH-EMPTY-GRAPH). Extra planes **never** merge into one architecture
164
+ score. Doctor exposes `rulesUnderContract.mergePlanes` (including `mergePlanes.arkRun`) for which plane can fail,
165
+ and a dedicated `doctor.arkRun` section that is always `notAScore`.
153
166
 
154
167
  Safety fields:
155
168
 
package/docs/develop.md CHANGED
@@ -155,9 +155,18 @@ names. Details: [configuration.md](configuration.md#team-parliament-law-vs-featu
155
155
 
156
156
  ---
157
157
 
158
- ## Optional experimental runtime
159
-
160
- Gates need **no** runtime kernel. `@arkgate/runtime` is experimental, separate package, not the day-zero product. See [package-surface.md](package-surface.md) and [production-hardening.md](production-hardening.md).
158
+ ## Optional ArkRun extra and kernel
159
+
160
+ Gates need **no** runtime kernel. Optional **`arkRun`** on `ark.config.json` (schema `1.2`)
161
+ is a *gate* extra: kernel usage + complete declarations on the same write/CI plane as
162
+ Layers and ArkRules. Absence is silent. Compact starters leave it off.
163
+
164
+ The companion **ArkRun** kernel (`@arkgate/runtime`) is experimental, a separate package,
165
+ and not the day-zero product. `createStrictArkKernel` is the factory (per instance; no
166
+ process-wide singleton). The kernel is not bundled in the `arkgate` tarball. Built-in
167
+ stores are in-memory **reference only** — not production durability; `K01` stays parked.
168
+ See [configuration.md](configuration.md), [package-surface.md](package-surface.md), and
169
+ [production-hardening.md](production-hardening.md).
161
170
 
162
171
  ---
163
172
 
@@ -44,6 +44,13 @@ Link form for agents: `docs/diagnostics.md#RULE_ID` (exact-case HTML anchors bel
44
44
  | [`ARKRULE_INVARIANT`](#ARKRULE_INVARIANT) | arkrules | ArkRule invariant failed |
45
45
  | [`ARKRULE_SCOPE_EMPTY`](#ARKRULE_SCOPE_EMPTY) | arkrules | ArkRule appliesTo matched zero files |
46
46
  | [`INVARIANT_UNCOVERED`](#INVARIANT_UNCOVERED) | arkrules | Invariant without coverage evidence |
47
+ | [`ARKRUN_MISSING_ROOT`](#ARKRUN_MISSING_ROOT) | arkrun | No kernel factory in composition roots |
48
+ | [`ARKRUN_KERNEL_IN_DOMAIN`](#ARKRUN_KERNEL_IN_DOMAIN) | arkrun | Domain-role layer imports the kernel |
49
+ | [`ARKRUN_DIRECT_NEW`](#ARKRUN_DIRECT_NEW) | arkrun | Managed type constructed with new |
50
+ | [`ARKRUN_UNDECLARED_EMIT`](#ARKRUN_UNDECLARED_EMIT) | arkrun | Emit name not in raises/sends |
51
+ | [`ARKRUN_UNDECLARED_HANDLE`](#ARKRUN_UNDECLARED_HANDLE) | arkrun | Handle name not in reactsTo |
52
+ | [`ARKRUN_UNDECLARED_DEPEND`](#ARKRUN_UNDECLARED_DEPEND) | arkrun | Depend name not in uses |
53
+ | [`ARKRUN_TRANSPORT_BYPASS`](#ARKRUN_TRANSPORT_BYPASS) | arkrun | Homemade broker or emitter import |
47
54
  | [`INVALID_CHANGE_PATH`](#INVALID_CHANGE_PATH) | preflight | Unsafe change path |
48
55
  | [`DUPLICATE_CHANGE_PATH`](#DUPLICATE_CHANGE_PATH) | preflight | Duplicate path in change set |
49
56
  | [`DELETE_TARGET_MISSING`](#DELETE_TARGET_MISSING) | preflight | Delete target missing |
@@ -271,6 +278,74 @@ Link form for agents: `docs/diagnostics.md#RULE_ID` (exact-case HTML anchors bel
271
278
  - **Why:** An ArkRules invariant is under contract but no covering test title or declared symbol evidence was found (or coverage is partial). Kind is `never-had-tests` (adopt residual) vs `tests-disappeared` (suite exists).
272
279
  - **Fix:** Add a test title or declared symbol covering the arkruleId, then preflight again. Treat never-had-tests as adopt residual; treat tests-disappeared as a regression. Missing test globs report partial — never fake green.
273
280
 
281
+ ## ArkRun (opt-in extra)
282
+
283
+ Live adapters specialize `nextAction` with the call-site name or specifier when present
284
+ (casual `enthusiastHint` + engineer `nextAction`). Catalog **Fix** is the stable no-target form.
285
+
286
+ <a id="ARKRUN_MISSING_ROOT"></a>
287
+
288
+ ### `ARKRUN_MISSING_ROOT`
289
+
290
+ **No kernel factory in composition roots**
291
+
292
+ - **Why:** The ArkRun extra is on but no createArkKernel / createStrictArkKernel / createArkKernelFromConfig / createStrictArkKernelFromConfig factory was found in arkRun.compositionRoots, so agents can skip the kernel while the write gate stays green.
293
+ - **Fix:** Import createStrictArkKernel from @arkgate/runtime (never a removed arkgate/runtime shim) and call it in a composition root listed in arkRun.compositionRoots, then preflight again. Never mechanical-safe — factory placement is a design decision.
294
+
295
+ <a id="ARKRUN_KERNEL_IN_DOMAIN"></a>
296
+
297
+ ### `ARKRUN_KERNEL_IN_DOMAIN`
298
+
299
+ **Domain-role layer imports the kernel**
300
+
301
+ - **Why:** A Domain-role layer imports @arkgate/runtime or kernel types. Domain stays kernel-free; composition roots and adapters own the factory.
302
+ - **Fix:** Move the kernel import out of the Domain-role layer into a composition root or adapter. Import from @arkgate/runtime, never a removed arkgate/runtime shim, then preflight again. Never mechanical-safe.
303
+
304
+ <a id="ARKRUN_DIRECT_NEW"></a>
305
+
306
+ ### `ARKRUN_DIRECT_NEW`
307
+
308
+ **Managed type constructed with new**
309
+
310
+ - **Why:** A managed non-Domain file constructs an admitted type with new outside an ArkRun composition-root factory, skipping kernel resolve/registration.
311
+ - **Fix:** Resolve the type from the kernel instead of constructing it with new, then preflight again. Never mechanical-safe — rewiring construction is a design decision.
312
+
313
+ <a id="ARKRUN_UNDECLARED_EMIT"></a>
314
+
315
+ ### `ARKRUN_UNDECLARED_EMIT`
316
+
317
+ **Emit name not in raises/sends**
318
+
319
+ - **Why:** A publisher / publish / raise / send call-site literal is not listed in the file’s raises or sends declaration.
320
+ - **Fix:** Add the existing call-site name to raises or sends on the managed component, then preflight again. Mechanical-safe only when that literal already exists and the edit is the declaration list; inventing a new emit stays judgment.
321
+
322
+ <a id="ARKRUN_UNDECLARED_HANDLE"></a>
323
+
324
+ ### `ARKRUN_UNDECLARED_HANDLE`
325
+
326
+ **Handle name not in reactsTo**
327
+
328
+ - **Why:** A subscribe / registerHandler call-site literal is not listed in the file’s reactsTo declaration.
329
+ - **Fix:** Add the existing call-site name to reactsTo on the managed component, then preflight again. Mechanical-safe only when that literal already exists and the edit is the declaration list; inventing a new handle stays judgment.
330
+
331
+ <a id="ARKRUN_UNDECLARED_DEPEND"></a>
332
+
333
+ ### `ARKRUN_UNDECLARED_DEPEND`
334
+
335
+ **Depend name not in uses**
336
+
337
+ - **Why:** A resolve / resolveSingleton call-site literal is not listed in the file’s uses declaration.
338
+ - **Fix:** Add the existing call-site name to uses on the managed component, then preflight again. Mechanical-safe only when that literal already exists and the edit is the declaration list; inventing a new depend stays judgment.
339
+
340
+ <a id="ARKRUN_TRANSPORT_BYPASS"></a>
341
+
342
+ ### `ARKRUN_TRANSPORT_BYPASS`
343
+
344
+ **Homemade broker or emitter import**
345
+
346
+ - **Why:** A managed layer imports a closed broker/queue/emitter specifier (EventEmitter, queue clients, …) instead of the ArkRun kernel transport.
347
+ - **Fix:** Send through the ArkRun kernel transport instead of importing that broker or emitter, then preflight again. Never mechanical-safe — homemade buses stay judgment.
348
+
274
349
  ## Atomic preflight and change sets
275
350
 
276
351
  <a id="INVALID_CHANGE_PATH"></a>
@@ -27,10 +27,11 @@ aliases `ark` / `ark-check` still work).
27
27
  |-------|---------------|
28
28
  | **Layers** | Who may import whom (always on after start) |
29
29
  | **ArkRules** (optional) | Habits *inside* a layer — structure and named invariants as data |
30
+ | **ArkRun** (optional extra) | Kernel usage + complete declarations (`arkRun` on schema `1.2`) |
30
31
 
31
- You can stay on layers only. When you add ArkRules, start **advisory** and promote only with
32
- coverage. Residual labels: **`[Layer]`** vs **`[ArkRules]`**. Details:
33
- [use.md](../use.md) · [configuration](../configuration.md#arkrules-intra-layer-opt-in).
32
+ You can stay on layers only. When you add ArkRules or ArkRun, start **advisory** and promote only with
33
+ coverage. Compact starters leave ArkRun off. Residual labels: **`[Layer]`** vs **`[ArkRules]`**. Details:
34
+ [use.md](../use.md) · [configuration](../configuration.md).
34
35
 
35
36
  ## Start here
36
37
 
@@ -1,7 +1,7 @@
1
1
  # ArkGate package surface policy
2
2
 
3
3
  **Product wedge:** write gate · CI gate · co-pilot (plan / loop / skills).
4
- **Not the wedge:** the optional in-process runtime kernel.
4
+ **Not the wedge:** the optional in-process **ArkRun** kernel (`@arkgate/runtime`).
5
5
 
6
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.
@@ -21,6 +21,7 @@ hardening guide remains repository-hosted rather than duplicated in the gate tar
21
21
  | **Programmatic gate API** | `import { analyzeProject, loadContract, createAICodeGate, ... } from 'arkgate'` | The root export is the static gate/config/analysis contract listed below. It intentionally contains no runtime-kernel implementation. |
22
22
  | **Improvement compass (4.4; status honesty 4.5)** | `ark-check --doctor --json` → `doctor.improvementCompass`; human doctor section **Improvement compass (not a score)**; HTML report `data-advisory="improvementCompass"`. **`ark status --json` / MCP `ark_status`** project a thin `improvementCompass` residual map with explicit honesty **`mode`**: `full` \| `subset` \| `unavailable` (always `notAScore: true`). When `mode` is `full`, status residual lens **ids** are a **subset of** doctor residual for the same facts (report snapshot stores the thin slice after `--report`). Incomplete or missing session facts → `subset` / `unavailable` + `reasonCode` / `reason` — **never invent green residual**. Residual never flips `valid` / strict-merge / `goal.met`. When status mode ≠ full, run doctor for full 15-lens detail. | Additive schema `1.0`. Closed **15** lens ids (`soc`, `cohesion`, `coupling`, `srp`, `dip`, `ocp`, `encapsulation`, `modularity`, `scalability`, `resilience`, `security`, `maintainability`, `testability`, `domain`, `stack`) with status `ok` \| `residual` \| `not-instrumented` \| `out-of-scope`, evidence refs, optional `nextAction`, capped `topResidual`, always **`notAScore: true`**. Projection from existing smells / walls / cohesion / ArkRules / design-weak only — **never** a gate input. Out-of-scope locked for scalability, resilience, and app security (no residual invent from missing SAST/APM). Root API: `buildImprovementCompass` / `IMPROVEMENT_LENS_IDS`; status: `projectStatusImprovementCompass` / `STATUS_COMPASS_MODES`. |
23
23
  | **Deep-module coach (post-4.5 advisory)** | `ark-check --doctor --json` → `doctor.deepModuleCoach`; human doctor section **Deep-module coach (advisory — not a score)** always when doctor runs (empty candidates / hot-path `unavailable` are honesty, not omission); HTML `data-advisory="deepModuleCoach"`. | Additive schema `1.0`. Always **`notAScore: true`**. **`hotPaths`**: recent-churn heuristic from bounded git log; `available` + `status` `ok` \| `unavailable`; empty `paths` when history missing/incomplete — **never invent**. **`deepeningCandidates`**: cards projected only from existing design smells / physical cohesion / reshape pilot / pilotLoop / residual compass lenses — **empty when no evidence** (no fake candidates). Never flips `valid`, strict-merge, completeness green, or `goal.met`. Prefer deep modules / named seams / test-at-public-interface process language in skills. Domain pure + CLI gen mirror (`deepeningCoach.ts` / `bin/lib/deepening-coach.mjs`); **not** a root package export — consume via `doctor.deepModuleCoach` (or the gen mirror in Tooling). |
24
+ | **ArkRun doctor / status / report (RN08)** | `ark-check --doctor --json` → `doctor.arkRun`; HTML `data-advisory="arkRun"`; `ark status --json` / MCP `ark_status` → `arkRun`; `rulesUnderContract.mergePlanes.arkRun` | Additive. Always **`notAScore: true`**. Residual is a finding-id count (status residual `null` = unknown, not green). Advisory and absence never arm extra merge teeth; enforced teeth follow the classified-layer floor. Never a score or LLM verdict. |
24
25
  | **Upgrade what’s new (4.5.6+)** | `ark upgrade --json` → `whatsNew` (+ human **Suggested improvements** block; also on preview). | Always **`notAScore: true`**, **`neverGateInput: true`**. Closed try/inspect list: deep-module coach, improvement compass, session/status honesty, two-axis done, self-service honesty, registry-aware upgrade, skill drift/refresh, multi-project MCP, Codex hard-write refresh/trust/restart/verify, stale MCP/global CLI recovery. Never invents residual or flips gates. |
25
26
  | **Field upgrade truth (4.5.6)** | `ark upgrade` registry-aware install; JSON `reasonCode` / `suggestedInstallCmd`; `skillDrift`; `--refresh-skills`; `postUpgradeChecks`; `hostSelection`. | No false-skip when registry ahead; offline honesty; customized skills preserved unless opt-in refresh; checks are advisory only. |
26
27
  | **MCP process package honesty (4.5.6; fail-closed in 4.6.4)** | Every MCP tool context → `processPackage` (`processPackageMismatch` / `processStale`, versions, `nextAction`). | Multi-checkout users: restart MCP after pin bump. From 4.6.4, stale process context is non-authoritative; `ark_identity` remains diagnostic and project tools return `PROCESS_PACKAGE_STALE` until restart/retarget. Prefer project-local CLI until identity matched and versions align. |
@@ -38,10 +39,10 @@ hardening guide remains repository-hosted rather than duplicated in the gate tar
38
39
  | **Capability walls, every adapter** | CLI scan, pure IR engine, atomic preflight, `ark-mcp --hook` / MCP gate (`capabilityWalls`), ESLint `ark/no-denied-capabilities` | The same opt-in deny set enforces across every surface: hook/MCP and CLI cover ambient + import evidence (symbol-aware); the pure engine, preflight, and ESLint cover the import dimension (documented envelope). Dual depth everywhere: plain port hint (`FIX_HINTS`/`suggestion`) + stable JSON (`ruleId`, `capability`, `fixClass: inject-port`, deterministic `nextAction`). |
39
40
  | **Hook-path budgets (maintainer)** | Repository-only evidence: `npm run bench:hook-path`; `eval/performance/hook-budgets.v1.json`; CI job "Hook-path end-to-end budgets" | Measures the COMPLETE pre-tool paths as fresh child processes (hook cold/warm, doctor cold) at 1k/10k. D5 method locked: ceilings are Linux-baseline p95 + fixed headroom, set once per cycle, never ratcheted; scenarios without a recorded baseline stay in RECORDING mode and cannot fail CI. |
40
41
  | **Governance weight** | `ark-check --doctor --json` → `doctor.contractHealth.governanceWeight` | Additive, **advisory only** — raw facts (`declaredLayers`, `populatedLayers`, `governedFiles`, `rules`, `deniedEdges`, `allowedEdges`, `filesPerLayer`, `rulesPerLayer`) plus a fixed comparative band `weight: heavy | typical | light | unknown` and its fixed `note`. Fixed deterministic thresholds: **heavy** = fewer than 25 governed files per declared layer AND (6+ layers OR 4+ well-formed rules per layer); **light** = at most 2 layers over 150+ governed files; **unknown** = no layers or no governed files; everything else is **typical** (banding uses raw ratios; the reported ratios are rounded for display). `notAScore: true` is explicit: never a composite score, ranking, or gate input; the heavy note asks to justify NEW layers/rules and never suggests deleting working ones. Human doctor prints a line only for `heavy`/`light`. |
41
- | **Report parity and snapshot evidence (4.2)** | `ark-check --report` → advisory sections (`data-advisory="contractHealth\|ambientState\|parseHealth"`, nested `governanceWeight`) + layer wall badges; `.ark/reports/*.json` | The report is a rendering of doctor truth. **Standing rule:** every doctor advisory ships with its report section — enforced by the `reportParity` guard, which enumerates the doctor's advisory keys and fails on any missing section. Snapshots add best-effort Git `HEAD`/branch/dirty provenance without a shell; unavailable Git is explicit. Evolution renders the Ark score delta only when both snapshots name the same ArkGate version, while retaining raw facts across versions. |
42
+ | **Report parity and snapshot evidence (4.2)** | `ark-check --report` → advisory sections (`data-advisory="contractHealth\|ambientState\|parseHealth\|arkRun"`, nested `governanceWeight`) + layer wall badges; `.ark/reports/*.json` | The report is a rendering of doctor truth. **Standing rule:** every doctor advisory ships with its report section — enforced by the `reportParity` guard, which enumerates the doctor's advisory keys and fails on any missing section. Snapshots add best-effort Git `HEAD`/branch/dirty provenance without a shell; unavailable Git is explicit. Evolution renders the Ark score delta only when both snapshots name the same ArkGate version, while retaining raw facts across versions. Thin `arkRun` on `latest.json` is `notAScore` residual honesty for `ark status`. |
42
43
  | **MCP project identity (4.2)** | `ark_identity`; `arkgate/schema/project-identity` or `arkgate/schema/ark.project-identity.schema.json`; root API constants/helpers/types | Schema `1.0`. `projectId` hashes canonical root + config path and stays stable across contract edits/restarts; runtime id/start time are separate. Every project-bound tool result and error carries `projectIdentity`, `binding` (`matched` / `unverified` / `mismatch`), and `authoritative`. Canonical out-of-root config/file evidence fails before project data. |
43
44
  | **MCP tools and compatibility resource** | `arkgate-mcp`; `ark_manifest`; `ark_status`; `ark://manifest` | Tool names and primary argument shapes are stable within a major. Every tool accepts additive `project.expectedRoot` / optional `expectedProjectId`. The initial handshake requires the exact project root; a contained descendant is authoritative only together with the matching project id. Legacy tool calls remain callable but `unverified` and non-authoritative. `ark_manifest` is the authoritative contract surface after binding. **`ark_status`** returns the status manifest envelope (parity with `ark status --json`). Standard `resources/read` cannot portably carry the expectation, so `ark://manifest` remains compatibility-only and always unverified/non-authoritative. The server never retargets from input. |
44
- | **`ark.config.json`** | Layer globs, rules, include/exclude, forbiddenGlobals, intent prefixes, `peerIsolation`, `dynamicImportAllowlist`, `safety` thresholds; optional **`arkRules`** map (schema `1.1+`) | Versioned by `schemaVersion`; unknown fields fail closed and migrations preserve the previous supported major. Absence of `arkRules` is byte-for-byte silent on inter-layer verdicts. |
45
+ | **`ark.config.json`** | Layer globs, rules, include/exclude, forbiddenGlobals, intent prefixes, `peerIsolation`, `dynamicImportAllowlist`, `safety` thresholds; optional **`arkRules`** map (schema `1.1+`); optional **`arkRun`** extra (schema `1.2+`) | Versioned by `schemaVersion`; unknown fields fail closed and migrations preserve the previous supported major. Absence of `arkRules` or `arkRun` is byte-for-byte silent on Layers / ArkRules verdicts. Enforced `arkRun` extra teeth share the CLI / MCP / hook / preflight / CI verdict and arm only when the layer plane is classified (same ArkRules floor). |
45
46
  | **ArkRules inventory / under-contract (4.0; layer context 4.2)** | `ark-check --rules-inventory [--json]`; doctor `rulesUnderContract`; MCP `ark_rules_inventory` | Additive. Honest counts (inventoried / under-contract / frozen) — **never a score**. When configured layer evidence exists it overrides filename role guesses: a Domain file named `handler` is not a controller candidate. Test/fixture/seed/migration/exclusion surfaces plus narrow development-identity, PostgreSQL OID, and technical I/O constants are silent. Without layer evidence, backward-compatible path/content heuristics remain. Structure/invariant diagnostics use adapter `1.4` provenance. |
46
47
  | **`arkgate/schema/project-identity`** or **`arkgate/schema/ark.project-identity.schema.json`** | MCP canonical project, contract, runtime, expectation, and binding envelope | Schema `1.0`. Initial `expectedRoot` must be the exact project root. A contained descendant can match only when `expectedProjectId` is also present and correct; id-only matching stays non-authoritative. Mismatch codes are `PROJECT_ROOT_MISMATCH`, `PROJECT_ID_MISMATCH`, and `INVALID_PROJECT_EXPECTATION`. |
47
48
  | **Package pin dual-truth (4.0)** | doctor JSON `packageVersionTruth`; upgrade JSON/human note when pin behind CLI | Additive, advisory. Surfaces after `upgrade --no-install` when managed CLI is ahead of package.json. |
@@ -57,15 +58,15 @@ hardening guide remains repository-hosted rather than duplicated in the gate tar
57
58
  | **Design delta** | `--strict-merge` / `--strict` (created paths when a Git base exists); `--fail-on-new-smells --base-ref <ref>` (full ratchet); hook/MCP; schema/types | Schema `1.0`: identities, touched paths, optional `enforcementScope`. Default merge blocks **created** `domain-logic-in-ui` files vs merge-base; missing base skips (does not exit 2). Full new+worsened on touched paths remains opt-in `--fail-on-new-smells` (missing base fails closed). Historical residual and worsened-in-existing-file stay green on `--strict-merge`. Global doctor smells stay advisory. |
58
59
  | **`arkgate/schema/analysis-result`** or **`arkgate/schema/ark.analysis-result.schema.json`** | Public CLI/MCP/hook diagnostic envelope (`schemaVersion`, `mode`, `valid`, `completeness`, `completenessReasons`, `diagnostics`, resolved identities) | Schema **`1.5`** adds optional stable finding refs on diagnostics: `findingRef` (`fnv1a-` + hex), `targetKey` (baseline-compatible freeze identity), `docsCodePath` (`docs/diagnostics.md#RULE_ID`). Factory-emitted diagnostics always include them; consumer-owned 1.0–1.4 values remain valid without them. `1.4` added optional `evidence.arkruleId` / `evidence.arkruleSource` for ArkRules; `1.3` distinguished `resolved-candidate-facts` from `lexical-compatibility`; partial/unavailable analysis is always non-green, and resolved complete/partial results require policy/resolver/facts/tree identities. `1.2` added completeness and remains accepted alongside consumer-owned 1.0/1.1 values. |
59
60
  | **Stable finding refs (4.3)** | Root API `adapterFindingTargetKey` / `adapterFindingRefFromTargetKey` / `toAdapterDiagnostic` / `createAdapterResult`; CLI/MCP/repair envelopes via analysis-result diagnostics | Multi-turn re-address without fuzzy message match. `targetKey` **is** the baseline (occurrence) key so freeze identity is never orphaned; `findingRef` is a compact FNV-1a of that key. Line/message drift does not change the ref. Multi-turn fixture: `tests/fixtures/finding-refs/multi-turn-stability.json`. |
60
- | **Diagnostic code catalog** | Root API `DIAGNOSTIC_CATALOG` / `getDiagnosticCatalogEntry` / `diagnosticDocsPath`; docs [diagnostics.md](diagnostics.md) (`#RULE_ID` anchors) | Closed vocabulary of public `ruleId`s with why/fix anchors. Cataloguing only — no new rule semantics. Remediation parity is test-guarded. Docs ship in the npm tarball. |
61
- | **Status manifest** | CLI `ark status [--json] [--vs <ref>]`; MCP `ark_status`; `arkgate/schema/status-manifest`; root API `buildStatusManifest` / `ARK_STATUS_MANIFEST_SCHEMA` / `projectStatusImprovementCompass` | Schema `1.0`. One session/project snapshot: identity binding, honest write-path activation (`hard`\|`advisory`\|`unavailable`), last-check summary, rules residual counts, primary next action, **`improvementCompass`** with honesty **`mode`** `full`\|`subset`\|`unavailable` (residual ids only; always `notAScore: true`; optional `reasonCode`/`reason`/`factsSource`/`contractHash`), and optional **`vsBase`** (pin / contract / baseline grow vs a git ref; advisory only). **Not a score.** Residual never changes gate verdicts. Never prompts (`CI=1` forces JSON). Optional `--expected-root` / `--expected-project-id` (MCP `project`) for matched vs stale identity. |
61
+ | **Diagnostic code catalog** | Root API `DIAGNOSTIC_CATALOG` / `getDiagnosticCatalogEntry` / `diagnosticDocsPath`; docs [diagnostics.md](diagnostics.md) (`#RULE_ID` anchors) | Closed vocabulary of public `ruleId`s with why/fix anchors. Cataloguing only — no new rule semantics. Remediation parity is test-guarded. ArkRun `ARKRUN_*` codes (RN05) share dual-depth `nextAction` / `enthusiastHint`; declaration-list adds are mechanical-safe only when the call-site literal already exists. Docs ship in the npm tarball. |
62
+ | **Status manifest** | CLI `ark status [--json] [--vs <ref>]`; MCP `ark_status`; `arkgate/schema/status-manifest`; root API `buildStatusManifest` / `ARK_STATUS_MANIFEST_SCHEMA` / `projectStatusImprovementCompass` | Schema `1.0`. One session/project snapshot: identity binding, honest write-path activation (`hard`\|`advisory`\|`unavailable`), last-check summary, rules residual counts, primary next action, **`improvementCompass`** with honesty **`mode`** `full`\|`subset`\|`unavailable` (residual ids only; always `notAScore: true`; optional `reasonCode`/`reason`/`factsSource`/`contractHash`), optional **`vsBase`** (pin / contract / baseline grow vs a git ref; advisory only), and additive **`arkRun`** (`notAScore`; `present` / `mode` / `extraMergeTeeth` / residual count — null residual is unknown, not green). **Not a score.** Residual never changes gate verdicts. Never prompts (`CI=1` forces JSON). Optional `--expected-root` / `--expected-project-id` (MCP `project`) for matched vs stale identity. |
62
63
  | **Agent contract projection** | CLI `ark agents-md [--write] [--check] [--stdout] [--json]`; install/upgrade AGENTS templates; root API `buildAgentProjectionBlock` / `mergeAgentProjectionDocument` | Schema `1.0` (projection markers). Version-stamped managed block (`arkgateVersion` + contract summary + diagnostic short list). **Non-authoritative** — not a gate input; enforcement is ark-check / hooks / CI. Content-identity merge preserves customized regions outside markers. Drift: `--check` vs package version. |
63
64
  | **Agent Skills packaging** | `templates/agent-skills/<name>/SKILL.md` (+ package README); root API `ARK_SKILL_NAMES` / `validateAgentSkillsPackage`; `npm run check:agent-skills` | Schema `1.0` (package contract). Same **13** skill names as flat templates; Agent Skills–compatible layout for `npx skills add`. No new skill names. Layout is generated 1:1 from `templates/skills/*.md`. |
64
65
  | **`arkgate/schema/arkrules`** or **`arkgate/schema/ark.arkrules.schema.json`** | Per-layer structure sensors + invariant catalog (ADR 0012) | Schema `1.0`. Opt-in via root `arkRules` map (`ark.config` schema `1.1`). |
65
- | **`arkgate/schema/resolved-candidate-facts`** or **`arkgate/schema/ark.resolved-candidate-facts.schema.json`** | Versioned parity-capable input for `analyzeResolvedProject` / `preflightResolvedChange` | Schema `1.0` is serializable and deterministic. Tooling owns filesystem/compiler resolution; Domain/Kernel validate and evaluate supplied facts without importing those effects. Facts name resolver/compiler inputs, governed files, dependency evidence, completeness reasons, and candidate tree/facts hashes. |
66
+ | **`arkgate/schema/resolved-candidate-facts`** or **`arkgate/schema/ark.resolved-candidate-facts.schema.json`** | Versioned parity-capable input for `analyzeResolvedProject` / `preflightResolvedChange` | Schema `1.2` is additive: optional `classShapes` (1.1) plus ArkRun `arkRunKernelCalls` / `arkRunManagedNews` / `arkRunCompositionRootHits` / `arkRunDeclarations` (RN03–RN04). `1.0`/`1.1` payloads remain loadable. Tooling owns filesystem/compiler resolution; Domain/Kernel validate and evaluate supplied facts without importing those effects. Facts name resolver/compiler inputs, governed files, dependency evidence, completeness reasons, candidate tree/facts hashes, and (when present) ArkRun call-site and declaration evidence. Tier-1 sensors emit `ARKRUN_*` diagnostics from those facts: advisory never flips `valid`; enforced blocks. |
66
67
  | **Config JSON Schema** | `arkgate/schema` or `arkgate/schema/ark.config.schema.json` | Stable package resource subpaths for editor completion and contract tooling. |
67
68
  | **Agent skills** | `/ark-*` templates; install via `--install-agent-gates` (often `--skills-only` on top of compact) **or** Agent Skills ecosystem path | **Day zero** is the compact router from `ark start` / `start --apply` + doctor control plane — not the full skill pack. Skill *names* (frozen **13**) and the guided expert path (`/ark-autopilot` after pack install) are stable; internal skill prose may evolve. **4.0:** all skills except experimental `/ark-runtime` integrate **layers + ArkRules** and must label residual `[Layer]` vs `[ArkRules]`. **4.2:** repo catalogs are content-idempotent; the optional shared Codex home catalog is monotonic across 4.2.0+ installers. Pre-4.2 writers are outside that protocol and must be upgraded first. A durable pending-catalog journal preserves the floor across an interrupted install and is cleared only by its owning same/newer recovery. **4.3:** Agent Skills–compatible layout at `templates/agent-skills/<name>/SKILL.md` (1:1 with flat `templates/skills/*.md`); install via `npx skills add ./node_modules/arkgate/templates/agent-skills` (or the GitHub tree). Domain `ARK_SKILL_NAMES` + `validateAgentSkillsPackage`; drift `npm run check:agent-skills`. Skills never enforce. |
68
- | **ESLint subpath** | `arkgate/eslint` | Config-driven layer/import rules; loads consumer `ark.config.json`. |
69
+ | **ESLint subpath** | `arkgate/eslint` | Config-driven layer/import/purity rules plus ArkRun import/`new` envelope (`ark/no-arkrun-kernel-in-domain`, `ark/no-arkrun-direct-new`, `ark/no-arkrun-transport-bypass`) when `arkRun` is on; loads consumer `ark.config.json`. Absence of the extra is silent. Missing-root and undeclared-* stay CLI/MCP. |
69
70
  | **GitHub Action** | `pedroknigge/arkgate` (see `action.yml`) | The `uses:` tag/SHA selects the checker source; `version` remains an optional exact npm compatibility override. |
70
71
  | **Package metadata** | `arkgate/package.json` | Stable resource subpath for tooling that needs the installed manifest. |
71
72
 
@@ -152,7 +153,7 @@ The type-only root exports are also semver-supported:
152
153
 
153
154
  Runtime-kernel factories, `CAPABILITY_IDS`, `collectCapabilityUses`, and Domain capability mapping
154
155
  helpers are deliberately absent from this root. Use `@arkgate/runtime` for the experimental
155
- runtime, and `analyzeProject(...).ir.capabilityUses` for public capability evidence.
156
+ **ArkRun** kernel, and `analyzeProject(...).ir.capabilityUses` for public capability evidence.
156
157
 
157
158
  ---
158
159
 
@@ -163,15 +164,15 @@ product claims**. Static architecture enforcement does not depend on them.
163
164
 
164
165
  | Surface | Import path | Notes |
165
166
  |---------|-------------|--------|
166
- | **Runtime kernel** | **`@arkgate/runtime`** | Separate 0.x source package configured for the `experimental` tag. It is not currently present in the npm registry, and the root `publish-npm.yml` workflow does not publish it automatically. Event bus, intents, policies, sagas, event buffer, projections, and strict helpers. Built-in stores are **InMemory reference only**. |
167
- | **NestJS adapter** | `@arkgate/runtime/nestjs` | Experimental optional peer `@nestjs/common`. Root `arkgate/nestjs` and `arkgate/runtime` forwarders were **removed in AR04 / ArkGate 4** — import the companion package directly. |
167
+ | **ArkRun kernel** | **`@arkgate/runtime`** | Public brand **ArkRun**. Separate 0.x companion; `createStrictArkKernel` is the factory (each call is an isolated instance; no process-wide `getKernel()` singleton). Not bundled in the `arkgate` tarball (ADR 0004 / 0021). Not currently in the npm registry; root `publish-npm.yml` does not publish it automatically. Event bus, intents, policies, sagas, event buffer, projections, and strict helpers. Managed components declare `uses` / `reactsTo` / `raises` / `sends` on `register()`; `getDependencyInformationPackage()` is a JSON snapshot of ids, lifetime, and declarations and never includes factories, live instances, or input DTOs (ADR 0023). `requestGraph()` slices that snapshot into **process** or **technical** graphs with optional `nodeIds`, `degreesOfSeparation`, and include/exclude query; `formatArkRunGraphMermaid()` (also `graph.mermaid`) is a helper string, never a score. `send()` is the transport port (local / localBlocking / broker); missing broker falls back to in-process local delivery, `ephemeral` defaults true, and **no cloud SDKs ship** in the package (ADR 0024). Opt-in `startInspector()` / `startArkRunInspector()` binds **`127.0.0.1` only**, refuses `NODE_ENV=production`, lazy-loads HTTP, and serves JSON snapshots, SSE, and `/graph` slices of the information package (no public / authless bind). Built-in stores are **InMemory reference only**. Branding ArkRun is not a production-durability claim. |
168
+ | **NestJS adapter** | `@arkgate/runtime/nestjs` | Experimental optional peer `@nestjs/common` for the ArkRun kernel. Root `arkgate/nestjs` and `arkgate/runtime` forwarders were **removed in AR04 / ArkGate 4** — import the companion package directly. |
168
169
 
169
170
  ---
170
171
 
171
172
  ## Recommended imports
172
173
 
173
174
  ```ts
174
- // Preferred path when evaluating the experimental runtime kernel
175
+ // Preferred ArkRun factory each call is a new isolated instance (no getKernel() singleton)
175
176
  import { createStrictArkKernel, createStrictArkKernelFromConfig } from '@arkgate/runtime';
176
177
 
177
178
  // Nest adapter
@@ -204,7 +205,7 @@ production deployment would need to satisfy; it is not a readiness certification
204
205
  | Break CLI JSON field, MCP tool rename, or required `ark.config` field | **major** |
205
206
  | New optional config field, new CLI flag, additive JSON | **minor** |
206
207
  | Bugfix with no contract change | **patch** |
207
- | Additive experimental runtime API | `@arkgate/runtime` prerelease/minor |
208
+ | Additive experimental ArkRun kernel API | `@arkgate/runtime` prerelease/minor |
208
209
  | Remove deprecated `arkgate/runtime` / `arkgate/nestjs` forwarding shims | **Done (AR04)** — use `@arkgate/runtime` / `@arkgate/runtime/nestjs` |
209
210
 
210
211
  ---
@@ -212,9 +213,11 @@ production deployment would need to satisfy; it is not a readiness certification
212
213
  ## Release notes (maintainers)
213
214
 
214
215
  Ship notes for a version live under [releases/](https://github.com/pedroknigge/arkgate/tree/main/docs/releases)
215
- (current published: [4.6.7.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.7.md);
216
+ (current tree: [4.7.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.7.0.md);
217
+ current published: [4.6.7.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.7.md);
216
218
  prior published: [4.6.6.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.6.md);
217
219
  prior published: [4.6.5.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.5.md);
220
+ prior published: [4.6.4.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.4.md);
218
221
  prior published: [4.6.3.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.3.md);
219
222
  prior published: [4.6.2.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.2.md), [4.6.1.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.1.md), [4.6.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.6.0.md), [4.5.7.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.7.md), [4.5.6.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.6.md), [4.5.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.5.0.md), [4.4.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.4.0.md), [4.3.0.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.3.0.md),
220
223
  [4.2.1.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.2.1.md);
@@ -19,7 +19,8 @@ because the design space is small and honest.
19
19
  - **Gate side:** architecture config (`ark.config.json`) + pre-write block where the host
20
20
  supports it + required CI. Deterministic. Don’t show green if we could not verify.
21
21
  Two planes: **import rules** (who may import whom) always; **ArkRules** (structure rules
22
- inside a layer) opt-in.
22
+ inside a layer) opt-in. Third extra: **ArkRun** (kernel usage + declarations) via companion
23
+ `@arkgate/runtime` — not a durability claim.
23
24
  - **Coach side:** where code belongs, who talks to whom, how; fix imports first, then leftover
24
25
  design work; one small refactor at a time; never silent auto-reshape; never weaken the config.
25
26
  - **Five-door autonomy:** invoking `/ark-adopt`, `/ark-place`, `/ark-autopilot`, `/ark-explore`,
@@ -63,8 +64,9 @@ Examples:
63
64
 
64
65
  ## Lexicon (prefer) — 4.6 common words
65
66
 
66
- **Brands (keep):** **ArkGate** (product / npm `arkgate`) and **ArkRules** (opt-in structure rules
67
- inside a layer). Gloss on first mention; do not rebrand.
67
+ **Brands (keep):** **ArkGate** (product / npm `arkgate`), **ArkRules** (opt-in structure rules
68
+ inside a layer), and **ArkRun** (opt-in kernel-usage extra + companion `@arkgate/runtime`). Gloss
69
+ on first mention; do not rebrand. Branding ArkRun is not a durability claim.
68
70
 
69
71
  Human copy prefers the **common** column. JSON field names (`designWeak`, `ruleId`, MCP tools)
70
72
  stay stable unless a change explicitly adds an alias.
@@ -74,6 +76,7 @@ stay stable unless a change explicitly adds an alias.
74
76
  | **architecture config** | contract | `ark.config.json` layers, rules, include |
75
77
  | **import rules** / **allowed dependencies** | Layers plane / edges | Who may import whom; placement, purity, isolation |
76
78
  | **ArkRules** (opt-in; gloss: structure rules inside a layer) | ArkRules | Intra-layer sensors + domain invariant catalogs (`arkrules/*`) |
79
+ | **ArkRun** (opt-in; gloss: kernel usage + complete declarations) | arkRun | Extra plane on the gate; companion kernel is `@arkgate/runtime`; factory `createStrictArkKernel` (per instance, no singleton). Never a score. |
77
80
  | **advisory ArkRules** | advisory ArkRules | Default sensor mode — **not** merge teeth; does not fail CI/merge alone |
78
81
  | **extra merge checks** | extraMergeTeeth | Only when enforced structure/invariant rules exist **and** classification is honest |
79
82
  | **label `[Layer]` vs `[ArkRules]`** | dual-plane residual | Never blur import-rule findings with ArkRules findings |
@@ -1,6 +1,6 @@
1
1
  # Threat model — ArkGate
2
2
 
3
- **Scope:** architecture write/CI gates, agent hooks/MCP, and the experimental optional runtime.
3
+ **Scope:** architecture write/CI gates, agent hooks/MCP, and the experimental optional **ArkRun** kernel (`@arkgate/runtime`).
4
4
  **Not in scope:** full org identity platforms, browser XSS in consumer apps, or npm registry
5
5
  infrastructure beyond how this package is published.
6
6
 
package/docs/use.md CHANGED
@@ -59,16 +59,17 @@ unfinished architecture; **Not finished** is reserved for real project/config de
59
59
 
60
60
  ArkGate is **not** a web framework, ORM, or app runtime. It is architecture enforcement + a coach for AI TypeScript.
61
61
 
62
- ### Two planes (you choose)
62
+ ### Planes (you choose)
63
63
 
64
64
  | Plane | Plain English | Config | Enforces |
65
65
  |-------|---------------|--------|----------|
66
66
  | **Layers** | Who may talk to whom | `layers[]` + `rules[]` | Import direction, purity, forbidden globals, capabilities, peer isolation |
67
- | **ArkRules** (optional) | Habits *inside* a layer + named policies | `arkRules` + `arkrules/<Layer>.json` | Structure **heuristics** (module shape); invariant **catalog + coverage evidence** (not full business proof) |
67
+ | **ArkRules** (optional extra) | Habits *inside* a layer + named policies | `arkRules` + `arkrules/<Layer>.json` | Structure **heuristics** (module shape); invariant **catalog + coverage evidence** (not full business proof) |
68
+ | **ArkRun** (optional extra) | Kernel usage + complete declarations | `arkRun` on schema `1.2` | Only `mode: "enforced"` when the tree is classified. Absence is silent. Doctor `arkRun` is **not a score**. |
68
69
 
69
- Start always gives you **layers**. ArkRules templates may ship with start/init; they begin **advisory** until you promote them. Doctor / HTML show `rulesUnderContract` (catalog, **not a score**). No `arkRules` map is fine — only Layers run.
70
+ Start always gives you **layers**. ArkRules templates may ship with start/init; they begin **advisory** until you promote them. Compact starters do **not** turn on ArkRun — add it only if the project uses `@arkgate/runtime`. Doctor / HTML show `rulesUnderContract` (catalog, **not a score**). No `arkRules` / `arkRun` map is fine — only Layers run. In-memory kernel stores are **not** production durability.
70
71
 
71
- **Do not confuse:** green Layers ≠ perfect design (Shape residual can remain). Covered invariants ≠ “the business always does the right thing” — they mean the named policy is declared and has symbol/test evidence.
72
+ **Do not confuse:** green Layers ≠ perfect design (Shape residual can remain). Covered invariants ≠ “the business always does the right thing” — they mean the named policy is declared and has symbol/test evidence. ArkRun branding ≠ durable stores.
72
73
 
73
74
  ### New modules vs config edits
74
75
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkgate",
3
- "version": "4.6.7",
3
+ "version": "4.7.0",
4
4
  "description": "One architecture config. One check. One coach.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -21,8 +21,8 @@
21
21
  },
22
22
  "schemaVersion": {
23
23
  "type": "string",
24
- "const": "1.1",
25
- "default": "1.1"
24
+ "const": "1.2",
25
+ "default": "1.2"
26
26
  },
27
27
  "name": {
28
28
  "type": "string",
@@ -633,6 +633,9 @@
633
633
  },
634
634
  "default": {}
635
635
  },
636
+ "arkRun": {
637
+ "$ref": "#/$defs/arkRun"
638
+ },
636
639
  "stewards": {
637
640
  "type": "array",
638
641
  "items": {
@@ -793,6 +796,42 @@
793
796
  "default": false
794
797
  }
795
798
  }
799
+ },
800
+ "arkRun": {
801
+ "type": "object",
802
+ "additionalProperties": false,
803
+ "properties": {
804
+ "mode": {
805
+ "type": "string",
806
+ "enum": [
807
+ "advisory",
808
+ "enforced"
809
+ ],
810
+ "default": "advisory"
811
+ },
812
+ "compositionRoots": {
813
+ "type": "array",
814
+ "items": {
815
+ "type": "string",
816
+ "minLength": 1
817
+ },
818
+ "uniqueItems": true,
819
+ "default": []
820
+ },
821
+ "managedLayers": {
822
+ "type": "array",
823
+ "items": {
824
+ "type": "string",
825
+ "minLength": 1
826
+ },
827
+ "uniqueItems": true,
828
+ "default": []
829
+ },
830
+ "requireDeclarations": {
831
+ "type": "boolean",
832
+ "default": true
833
+ }
834
+ }
796
835
  }
797
836
  }
798
837
  }