arkgate 4.8.8 → 4.8.10

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 (65) hide show
  1. package/CHANGELOG.md +141 -3
  2. package/README.md +9 -6
  3. package/bin/ark-check-runtime.mjs +24 -2
  4. package/bin/ark-layer-match.mjs +25 -10
  5. package/bin/ark.mjs +18 -10
  6. package/bin/lib/agent-homes.mjs +1 -1
  7. package/bin/lib/analysis-engine.mjs +8 -8
  8. package/bin/lib/architecture-scan.mjs +91 -4
  9. package/bin/lib/ark-order-facts.mjs +11 -4
  10. package/bin/lib/ark-order-sensors.mjs +103 -3
  11. package/bin/lib/arkrule-file-hints.mjs +255 -20
  12. package/bin/lib/arkrules-sensors.mjs +364 -68
  13. package/bin/lib/baseline-key.mjs +45 -1
  14. package/bin/lib/config-contract.mjs +9 -3
  15. package/bin/lib/config-extras.mjs +1 -0
  16. package/bin/lib/contract-smells.mjs +12 -6
  17. package/bin/lib/diagnostic-catalog.mjs +1 -0
  18. package/bin/lib/doctor-human.mjs +35 -10
  19. package/bin/lib/doctor-next-actions.mjs +24 -3
  20. package/bin/lib/field-install.mjs +23 -2
  21. package/bin/lib/first-run-help.mjs +69 -5
  22. package/bin/lib/gate-files.mjs +108 -22
  23. package/bin/lib/managed-upgrade.mjs +9 -1
  24. package/bin/lib/resolved-candidate-facts.mjs +82 -1
  25. package/bin/lib/rules-inventory.mjs +7 -3
  26. package/bin/lib/upgrade-command.mjs +17 -4
  27. package/bin/lib/upstream-report.mjs +330 -0
  28. package/bin/lib/violations.mjs +51 -15
  29. package/dist/{configTypes-0eHpocR3.d.ts → configTypes-j7so8B4O.d.ts} +12 -0
  30. package/dist/{diagnosticCatalog-DxKCTBbp.d.ts → diagnosticCatalog-biferT4R.d.ts} +11 -5
  31. package/dist/eslint/index.cjs +5 -8
  32. package/dist/eslint/index.d.ts +6 -4
  33. package/dist/eslint/index.js +5 -8
  34. package/dist/index.cjs +30 -33
  35. package/dist/index.d.ts +18 -6
  36. package/dist/index.js +30 -33
  37. package/dist/nestjs/index.cjs +3 -3
  38. package/dist/nestjs/index.d.ts +3 -3
  39. package/dist/nestjs/index.js +2 -2
  40. package/dist/order/index.cjs +1 -1
  41. package/dist/order/index.d.ts +6 -2
  42. package/dist/order/index.js +1 -1
  43. package/dist/runtime/index.cjs +11 -11
  44. package/dist/runtime/index.d.ts +6 -6
  45. package/dist/runtime/index.js +11 -11
  46. package/dist/{types-BK47clMl.d.ts → types-Djbs3KjE.d.ts} +1 -1
  47. package/dist/{types-DxvmJO-D.d.ts → types-tGhZUiGX.d.ts} +1 -1
  48. package/docs/README.md +4 -3
  49. package/docs/agent-guide.md +27 -2
  50. package/docs/ai-gates.md +8 -0
  51. package/docs/arkorder.md +30 -7
  52. package/docs/brownfield-adoption.md +30 -0
  53. package/docs/configuration.md +61 -14
  54. package/docs/develop.md +4 -2
  55. package/docs/diagnostics.md +10 -0
  56. package/docs/package-surface.md +7 -5
  57. package/docs/use.md +11 -0
  58. package/package.json +1 -1
  59. package/schemas/ark.config.schema.json +12 -2
  60. package/server.json +2 -2
  61. package/templates/agent-skills/README.md +1 -1
  62. package/templates/agent-skills/ark-contract/SKILL.md +1 -1
  63. package/templates/agent-skills/ark-explore/SKILL.md +24 -3
  64. package/templates/skills/ark-contract.md +1 -1
  65. package/templates/skills/ark-explore.md +24 -3
@@ -1,4 +1,4 @@
1
- import { a as ArkConfigRule, f as ArkConfigLayer, A as ArkConfig } from './configTypes-0eHpocR3.js';
1
+ import { a as ArkConfigRule, f as ArkConfigLayer, A as ArkConfig } from './configTypes-j7so8B4O.js';
2
2
 
3
3
  /**
4
4
  * Policy types for the Ark kernel.
@@ -1,4 +1,4 @@
1
- import { i as Policy, P as PolicyViolation, I as IntentName, j as IntentCreator, k as IntentRelationship, b as ArchitectureProfile, D as DomainEvent, E as EventMetadata, h as PolicyEnforcementMode, A as ArchitectureLayer, c as ArchitectureRule, d as ArkCheckConfig } from './types-BK47clMl.js';
1
+ import { i as Policy, P as PolicyViolation, I as IntentName, j as IntentCreator, k as IntentRelationship, b as ArchitectureProfile, D as DomainEvent, E as EventMetadata, h as PolicyEnforcementMode, A as ArchitectureLayer, c as ArchitectureRule, d as ArkCheckConfig } from './types-Djbs3KjE.js';
2
2
 
3
3
  /**
4
4
  * PolicyEngine
package/docs/README.md CHANGED
@@ -66,13 +66,14 @@ These are **not** the day-to-day product path. They stay in the repo for evidenc
66
66
  | Area | Path |
67
67
  |------|------|
68
68
  | 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) |
69
- | 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`–`RN17` done; shipped **4.7.0** + companion **4.7.4**; ADRs [0020](adr/0020-arkrun-gated-extra-plane.md)–[0024](adr/0024-arkrun-transport-ports.md) accepted). [one-catalog-one-root](plans/one-catalog-one-root/README.md) (Phase HS; `HS01`–`HS05` done; shipped **4.7.1**). [arkorder](plans/arkorder/README.md) (Phase OR; `OR01`–`OR07` done; shipped **4.8.0**; extra **inside** package `arkgate` as `arkgate/order`; ADRs [0027](adr/0027-arkorder-gated-extra-plane.md)–[0031](adr/0031-one-package-extras-deprecate-companion.md)). [arkorder-arkrun](plans/arkorder-arkrun/README.md) (Phase XP; `XP01`–`XP08` done; shipped **4.8.5**; ADR [0033](adr/0033-arkorder-runtime-half-is-arkrun.md)). [arkorder-valve-loop](plans/arkorder-valve-loop/README.md) (Phase LV; `LV01`–`LV09` done; shipped **4.8.6**; [ADR 0034](adr/0034-arkorder-valved-loop.md); does not close K01). [layer-description-projection](plans/layer-description-projection/README.md) (Phase LD; `LD01`–`LD06` done; shipped **4.8.7**; [ADR 0035](adr/0035-layer-description-projection.md); project `layers[].description`; no schema bump). [observability-tui](plans/observability-tui/README.md) (`OD01`–`OD04` done on the **4.8.8 prepared tree**; not yet published; in-memory honesty retained). |
69
+ | 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`–`RN17` done; shipped **4.7.0** + companion **4.7.4**; ADRs [0020](adr/0020-arkrun-gated-extra-plane.md)–[0024](adr/0024-arkrun-transport-ports.md) accepted). [one-catalog-one-root](plans/one-catalog-one-root/README.md) (Phase HS; `HS01`–`HS05` done; shipped **4.7.1**). [arkorder](plans/arkorder/README.md) (Phase OR; `OR01`–`OR07` done; shipped **4.8.0**; extra **inside** package `arkgate` as `arkgate/order`; ADRs [0027](adr/0027-arkorder-gated-extra-plane.md)–[0031](adr/0031-one-package-extras-deprecate-companion.md)). [arkorder-arkrun](plans/arkorder-arkrun/README.md) (Phase XP; `XP01`–`XP08` done; shipped **4.8.5**; ADR [0033](adr/0033-arkorder-runtime-half-is-arkrun.md)). [arkorder-valve-loop](plans/arkorder-valve-loop/README.md) (Phase LV; `LV01`–`LV09` done; shipped **4.8.6**; [ADR 0034](adr/0034-arkorder-valved-loop.md); does not close K01). [layer-description-projection](plans/layer-description-projection/README.md) (Phase LD; `LD01`–`LD06` done; shipped **4.8.7**; [ADR 0035](adr/0035-layer-description-projection.md); project `layers[].description`; no schema bump). [observability-tui](plans/observability-tui/README.md) (`OD01`–`OD04` done; shipped **4.8.8**; in-memory honesty retained). |
70
70
  | Claims audit | [audit/claims-matrix.md](audit/claims-matrix.md) |
71
71
  | Field adoption kit (scaffolding, not closed) | [field/](field/) |
72
72
  | Runtime hardening (experimental) | [production-hardening.md](production-hardening.md) |
73
73
 
74
- Prepared: [releases/4.8.8.md](releases/4.8.8.md) (`arkgate@4.8.8`; not published).
75
- Current published: [releases/4.8.7.md](releases/4.8.7.md) (`arkgate@4.8.7` on npm `latest`; does not close `K01`).
74
+ Prepared: [releases/4.8.10.md](releases/4.8.10.md) (`arkgate@4.8.10`; not published).
75
+ Current published: [releases/4.8.9.md](releases/4.8.9.md) (`arkgate@4.8.9` on npm `latest`; does not close `K01`).
76
+ Prior published: [releases/4.8.8.md](releases/4.8.8.md) (`arkgate@4.8.8`).
76
77
  Prior: [releases/4.8.6.md](releases/4.8.6.md) · [releases/4.8.5.md](releases/4.8.5.md) · [releases/4.8.4.md](releases/4.8.4.md) · [releases/4.8.3.md](releases/4.8.3.md) · [releases/4.8.2.md](releases/4.8.2.md) · [releases/4.8.1.md](releases/4.8.1.md) · [4.8.0](releases/4.8.0.md) · [4.7.6](releases/4.7.6.md) · [4.7.5](releases/4.7.5.md) · [4.7.4](releases/4.7.4.md) · [4.7.3](releases/4.7.3.md) · [4.7.2](releases/4.7.2.md) · [4.7.1](releases/4.7.1.md) · [4.7.0](releases/4.7.0.md) · [4.6.7](releases/4.6.7.md) · [4.6.6](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).
77
78
  Older notes: [releases/](releases/). Config: [configuration.md](configuration.md).
78
79
 
@@ -93,11 +93,26 @@ Default loop for each agent session (product language — no inventing residual)
93
93
  `unavailable`, run `ark-check --doctor` (and `--json` for the full 15-lens map) before treating
94
94
  residual as complete. When mode is `full`, status residual ids are a subset of doctor residual
95
95
  for the same facts.
96
+ 5. **Report ArkGate defects to upstream (human confirms first)** — if you find a bug, a false
97
+ green, a false red, a missing doc, or improvable behavior **in ArkGate itself** (the `arkgate`
98
+ package — not leftover design in the consumer app), run **`arkgate report` / `ark report`**
99
+ (existing dual bins — not a new skill). Default prints a draft GitHub issue for **upstream**
100
+ `pedroknigge/arkgate` (`package.json` `bugs.url`) with the installed arkgate version and an
101
+ optional last-check snippet. **Ask the human to confirm send.** Create only with `--submit`
102
+ **and** `--i-confirm-submit` (after they said yes) or a TTY `Type submit to send`. `--yes`
103
+ does not submit. One finding per invocation (`--finding <ref>`); otherwise one bundled field
104
+ report (`--title` is editable). If `gh` is missing or not logged in, the CLI prints the draft
105
+ plus the exact `gh issue create --repo pedroknigge/arkgate` command and exits 2. Never auto-file.
106
+ Never file ArkGate defects on the consumer product repo. This is not `ark-check --report` (HTML).
96
107
 
97
108
  ```bash
98
109
  npx ark status --json --expected-root /abs/project/root
99
110
  # mode !== full → full residual map:
100
111
  npx ark-check --doctor --json
112
+ # draft an upstream issue (nothing created yet):
113
+ npx ark report
114
+ # after the human says yes — one finding, upstream only:
115
+ npx ark report --submit --i-confirm-submit
101
116
  ```
102
117
 
103
118
  `--doctor --json` is a stable envelope (4.6.5+): `{ "schemaVersion": "1.0", "envelope": "doctor", "ok": boolean, "doctor": { … } }`.
@@ -358,7 +373,8 @@ into orchestration/persistence), `contract-lateral-adapter-allow` (adapter layer
358
373
  sibling adapter layer; X03 — an adapter into its OWN family's infra base, e.g.
359
374
  `PaymentsAdapters -> PaymentsInfra`, is the sanctioned direction and does not fire),
360
375
  `contract-dead-rule` (rule references an empty or unknown layer, or is a
361
- same-layer no-op; `optional: true` layers are exempt). Advisory only: it never changes the
376
+ same-layer allow / classic same-layer deny; a same-layer `peerIsolation: true`
377
+ + `allowed: false` wall is live, not this smell; `optional: true` layers are exempt). Advisory only: it never changes the
362
378
  verdict, `designFitness`, or `patternBets` — layer roles come from name heuristics, so treat a
363
379
  miss as a warning to read, not a defect to silence. A deliberate edge is acknowledged in
364
380
  `.ark/contract-smell-acks.json` (`{ acks: [{ id, edge, reason, reviewBy? }] }`); `acknowledged` counts
@@ -1095,7 +1111,7 @@ edges are not denied by that rule.
1095
1111
  - **`allowedCrossSlice`** (4.8.4): `[{ "from": "features/checkout", "to": "features/catalog" }]` — one directed slice→slice edge the repo declares on purpose. The reverse still denies.
1096
1112
  - **The denial names its reason:** `cross-slice edge a → b` (a fact about the code) vs `unclassifiable path (…)`, `no slice folders`, `no path evidence` (facts about the evidence ArkGate had).
1097
1113
  - Promoting a genuinely shared slice to its own layer remains the recommended model; the two declarations exist so ArkGate can enforce a repo that deliberately chose otherwise.
1098
- - Enforced by `ark-check`, `arkgate/eslint`, and `ark-mcp` (path-aware edges and path-less intent refs share the same SoT).
1114
+ - Enforced by `ark-check`, `arkgate/eslint`, and `ark-mcp` (path-aware edges and path-less intent refs at declared event/saga/publish-metadata sites share the same SoT).
1099
1115
  - Fixes are **judgment** (not mechanical-safe).
1100
1116
 
1101
1117
  Agents can generate a config from the project's actual directory layout instead of inventing layer mappings:
@@ -1146,6 +1162,15 @@ Example config:
1146
1162
  plus intent/publish evidence. It uses the nearest `tsconfig.json` unless `--tsconfig` is set;
1147
1163
  importless type references are out.
1148
1164
 
1165
+ Intent-prefix checks (`LAYER_INTENT_REFERENCE_VIOLATION` on the candidate, write-hook
1166
+ `LAYER_REFERENCE_VIOLATION` / `UNKNOWN_INTENT`) apply only at declared intent-reference sites:
1167
+ `publish` / `subscribe` / `defineIntent` / `registerHandler` arguments, `intent` / `onEvent` /
1168
+ `reactsTo` properties, and publish `metadata.source` (or the 2nd/3rd-arg `source` object). A
1169
+ string that merely matches a layer prefix — including a kernel DType name such as
1170
+ `Management.EvmInspection.Data` — is not an intent reference. `looksLikeArkIntent` still
1171
+ classifies names; it is not a scan of every quoted string. There is no `kernel.dtypePrefixes`
1172
+ exemption list. Real event and saga string refs still fail closed.
1173
+
1149
1174
  Each run parses the full candidate and ignores retired `.cache/ark-check.json`; `--no-cache` is a
1150
1175
  no-op. Z07 owns the identity-keyed snapshot after exact cold/warm parity.
1151
1176
 
package/docs/ai-gates.md CHANGED
@@ -894,3 +894,11 @@ Adopting Ark on an existing codebase with violations? Freeze them once and ratch
894
894
  npx ark-check --update-baseline # writes .ark-baseline.json — commit it
895
895
  npx ark-check --baseline # only NEW violations fail
896
896
  ```
897
+
898
+ `--update-baseline` also patches existing check **invocations** so CI keeps using the
899
+ new freeze file: `package.json` scripts and GitHub workflow `run:` lines that already
900
+ call `ark-check` / `arkgate-check` via `npx`, `pnpm`, `yarn`, `npm`, or `node`. Those
901
+ writes are outside the three law files (`ark.config.json`, `arkrules/`,
902
+ `.ark-baseline.json`) and are announced (`Synced --baseline into: …`). The matcher
903
+ does **not** append `--baseline` to YAML that only *names* the check — a
904
+ `concurrency.group` such as `ark-check-${{ github.ref }}`, or a job id `ark-check:`.
package/docs/arkorder.md CHANGED
@@ -25,7 +25,7 @@ Config: [configuration.md](configuration.md). Surface:
25
25
  | Is | Is not |
26
26
  |----|--------|
27
27
  | A **library** (`createOrderPlane`) plus **static sensors** | A running service, daemon, or hosted plane |
28
- | Valved verbs: `release` / `project` / `ingest` / `proposeRelease` / `apply` / `refreshSigma` | A generic `update` / `patch` / `set` |
28
+ | Valved verbs: `release` / `project` / `ingest` / `proposeRelease` / `apply` / `refreshSigma` / `restore` | A generic `update` / `patch` / `set` |
29
29
  | Opt-in extra on `ark.config.json` | Always-on; compact starters leave it off |
30
30
  | Consumer-named slow keys (`xiKeys`) | A construction OS, BIM, or FirmPack |
31
31
  | Same npm tarball | not `@arkgate/order` |
@@ -66,6 +66,9 @@ They already exist:
66
66
  | Capacity as data | `ConstraintPack.capacity` (`kind` / `sigmaKey` / `payloadKey` / `op`) | 4.8.6 |
67
67
  | Store port | `ReleaseStore` / `createMemoryReleaseStore` in-memory default — not durable, not K01 | 4.8.6 |
68
68
  | Thin travel helper | `ingestTravelAction` absorb→`send` / escalate_up human→`raises` | 4.8.6 |
69
+ | Verify a stored `Release.hash` | `hashOf(ξ, σ)` alias of `hashReleasePayload` — no `release()` side effect | 4.8.9 |
70
+ | Reinstall a frozen Release | `restore(release)` — process-local; hash is identity; not durable; does not close K01 | 4.8.9 |
71
+ | Default clock | omitted `clocks` is Kernel `Date.now()`; Domain must not call `Date.now` | 4.8.9 |
69
72
 
70
73
  Nothing here is a hosted runtime. Nothing here can be “down”. A degraded-mode
71
74
  contract would defend against an outage that cannot happen.
@@ -77,13 +80,13 @@ contract would defend against an outage that cannot happen.
77
80
  **ArkOrder freezes the pattern through a valve. ArkRun is how the residual travels.**
78
81
 
79
82
  ```ts
80
- import { createOrderPlane } from 'arkgate/order';
83
+ import { createOrderPlane, hashOf, hashReleasePayload } from 'arkgate/order';
81
84
 
82
85
  const plane = createOrderPlane({
83
86
  projector, // consumer: (release, sigma) => { allowedKinds, invalidated }
84
87
  xiSchema, // JSON Schema object; additionalProperties false
85
88
  maxXiKeys, // default 7
86
- clocks, // injected; Domain must not call Date.now
89
+ clocks, // optional; default Kernel Date.now(); Domain must not call Date.now
87
90
  packs, // data, not user predicates (capacity is kind/sigmaKey/payloadKey/op)
88
91
  informationBudget, // optional { cannotObserve: ['ledger'] } — not a config key
89
92
  sigmaMaxAgeMs, // optional σ freshness; never on ξ — not a config key
@@ -97,6 +100,8 @@ plane.ingest(event); // residual absorb | escalate_up | hold. Never a
97
100
  plane.proposeRelease(delta); // blast radius. Empty blast = domain error
98
101
  plane.apply(proposal); // valve: later ξ change
99
102
  plane.refreshSigma(sigma); // saldo / clocks; xiHash unchanged
103
+ plane.restore(release); // process-local install; hash is identity; not durable; not K01
104
+ hashOf(xi, sigma); // same bytes as hashReleasePayload; no freeze side effect
100
105
  ```
101
106
 
102
107
  There is no `update()`. Calling `update` / `patch` / `set` on the plane throws
@@ -112,9 +117,24 @@ There is no `update()`. Calling `update` / `patch` / `set` on the plane throws
112
117
  | Change plan / protocol / cost-code bound | `proposeRelease` then `apply` |
113
118
  | PATCH the slow key through Prisma/Drizzle | `ARKORDER_XI_FIELD_WRITE` |
114
119
 
115
- Copy [examples/arkorder-billing/](../examples/arkorder-billing/) and rename the
116
- three keys. Membership ids (`projectId`) are not keys: a `proposeRelease` that
117
- does not change `h(ξ)` fails closed (`ARKORDER_EMPTY_BLAST`).
120
+ Gallery (not in the npm tarball):
121
+ [examples/arkorder-billing](https://github.com/pedroknigge/arkgate/tree/main/examples/arkorder-billing).
122
+ Rename the three keys. Membership ids (`projectId`) are not keys: a
123
+ `proposeRelease` that does not change `h(ξ)` fails closed (`ARKORDER_EMPTY_BLAST`).
124
+
125
+ ---
126
+
127
+ ## Ingest kinds vs payload (deliberate)
128
+
129
+ `classifyIngest` uses `event.kind` for `escalateKinds` and `allowedKinds`.
130
+ `ConstraintPack` is data-only: a function in the pack is `hold` with
131
+ `reasonCode: pack` ([ADR 0016](adr/0016-arkrules-no-executable-core.md) /
132
+ [ADR 0034](adr/0034-arkorder-valved-loop.md) D5). Capacity already compares
133
+ numeric `payload[payloadKey]` against `sigma[sigmaKey]`.
134
+
135
+ A payload-dependent story such as "second week failing a goal" is domain /
136
+ projector work (a new kind, or that kind in `allowedKinds` when ξ says so).
137
+ It is not a pack predicate. Do not add user functions to `ConstraintPack`.
118
138
 
119
139
  ---
120
140
 
@@ -204,6 +224,8 @@ package, inspector, in-memory compare). ArkOrder does not grow a bus, outbox,
204
224
  or hosted replay. [ADR 0033](adr/0033-arkorder-runtime-half-is-arkrun.md).
205
225
 
206
226
  Durability (`K01`) stays parked. In-memory is the honesty line.
227
+ `restore(release)` reinstalls a frozen Release in this process. It is not a
228
+ store. It does not close `K01`.
207
229
 
208
230
  ---
209
231
 
@@ -233,6 +255,7 @@ In-memory `ReleaseStore` is **not** durable. Doctor / status `arkOrder` stays
233
255
 
234
256
  ```bash
235
257
  npx arkgate-check --doctor
236
- # copy examples/arkorder-billing/ and rename the three keys
258
+ # gallery (not in the npm tarball):
259
+ # https://github.com/pedroknigge/arkgate/tree/main/examples/arkorder-billing
237
260
  # /ark-adopt to turn arkOrder on advisory
238
261
  ```
@@ -135,6 +135,36 @@ If Ark still refuses (a single edge dominates), the contract is still wrong —
135
135
  step 3; don't `--force` past it. From now `ark-check --baseline` fails only on NEW
136
136
  violations — the ratchet only moves toward zero.
137
137
 
138
+ `ARKRULE_SCOPE_EMPTY` is a **config diagnostic**, not code debt. It is **not freezable**
139
+ (even with `--force`). There is no `allowEmptyScope` key: an enforced rule whose
140
+ `appliesTo` matches zero governed files is incomplete analysis and must not look green.
141
+
142
+ ### Law then product (when a rule needs a folder that does not exist yet)
143
+
144
+ `mixed-law-and-product` still requires law files (`ark.config.json`, `arkrules/`,
145
+ `.ark-baseline.json`) to travel without product. When the product folder is not there
146
+ yet, do **not** freeze the empty-scope finding. Sequence:
147
+
148
+ 1. **Law PR (advisory or placeholder):** declare the ArkRule as `advisory`, *or* point
149
+ `appliesTo` at a tracked placeholder path that already exists. Empty enforced scope
150
+ fails the gate and cannot be baselined.
151
+ 2. **Product PR:** add the folder and the code so `appliesTo` matches governed files.
152
+ 3. **Law PR (promote):** raise the rule to `enforced` (hash-bound policy acknowledgement
153
+ when required). The ratchet then protects the now-visible scope.
154
+
155
+ ### STRUCTURE freeze keys include the sensor
156
+
157
+ New `ARKRULE_STRUCTURE` keys are `ARKRULE_STRUCTURE|<file>|<layer>||<sensor>` (and
158
+ `<sensor>:<symbol>` when a class/method symbol is known). A freeze for
159
+ `orchestration-only` on a file must not silence `thin-adapter` or `writes-via-aggregate`
160
+ on the same file.
161
+
162
+ **v1 empty-target keys** (`ARKRULE_STRUCTURE|<file>|<layer>||`) still load as frozen
163
+ residual, but they are **exact-match only**. They do not prefix-match every later sensor
164
+ on that file — hidden new debt must not look green. After upgrade they go stale; re-freeze
165
+ in a law PR (`--update-baseline --force --contract-session --author <steward>` as
166
+ applicable) so new keys carry the sensor. Do not treat stale v1 rows as a wildcard mute.
167
+
138
168
  ## 5. Burn down, in order
139
169
 
140
170
  `summary.edges` is the burn-down order. Prefer `ark-check --plan`: it tags each step
@@ -90,7 +90,13 @@ Top-level fields:
90
90
  which files count as tests, replacing the built-in `*.test.*` / `tests/` name heuristic),
91
91
  `maxFiles` (evidence file budget, default `400`) and `coverageRoots` (path prefixes where the
92
92
  project declares its runner actually executes tests). Absence is silent and changes no verdict.
93
- Unknown keys fail closed. When the budget is hit, `INVARIANT_UNCOVERED` reports the numbers
93
+ Unknown keys fail closed. **`maxFiles` also bounds structural-hint preload** for
94
+ `orchestration-only`, `thin-adapter`, and `writes-via-aggregate` (the hint loader reuses
95
+ coverage contents when present). There is no separate `arkrules.hintBudget`. When eligible
96
+ governed files exceed that budget, the loader emits `ARKRULE_HINT_BUDGET_EXHAUSTED` with
97
+ exact hinted/governed counts and per-sensor reviewed N/M of scope; `--strict-config` fails
98
+ if an enforced hint sensor cannot see its scope. `--doctor` names this coupling.
99
+ When the coverage budget is hit, `INVARIANT_UNCOVERED` reports the numbers
94
100
  (files loaded, tests retained, files discarded at the cap) and names `coverage.maxFiles` as
95
101
  the knob that raises it — coverage never claims "never had tests" because of our own cap.
96
102
  `maxFiles` is clamped to a hard ceiling of 20000 (the config validator has no
@@ -126,17 +132,23 @@ Top-level fields:
126
132
  preflight / CI verdict and arm only when the layer plane is classified (same ≥50%
127
133
  governed and ≥1 populated-layer floor as ArkRules).
128
134
  - **`arkOrder`** (optional, schema `1.3+`) — inline ArkOrder extra (`mode`, `planeRoots`,
129
- `managedLayers`, `maxXiKeys`, **`xiKeys`**). Absence is silent. Unknown keys fail closed.
130
- Import `createOrderPlane` from `arkgate/order` (same package). Empty `planeRoots` in
131
- `enforced` mode fails closed (`ARKORDER_MISSING_PLANE`). `xiKeys` are the 3–5 slow
132
- names the product already knows (plan, protocol, cost-code bound). Empty `xiKeys`
133
- leaves `ARKORDER_XI_FIELD_WRITE` silent. Membership ids and recomputable statuses
134
- such as `paid` / `overdue` are not keys. Factory options
135
- `informationBudget`, `sigmaMaxAgeMs`, `store` (`ReleaseStore`), and capacity packs
136
- belong on `createOrderPlane`, not this extra object. Later ξ is `proposeRelease`
137
- then `apply`; `refreshSigma`; ingest residual `absorb | escalate_up | hold`.
138
- Demotion or deletion is a policy-delta **weakening**. Field ingest never mints
139
- a pattern.
135
+ `managedLayers`, `maxXiKeys`, **`xiKeys`**, optional **`appliesTo`**). Absence is silent.
136
+ Unknown keys fail closed. Import `createOrderPlane` from `arkgate/order` (same package).
137
+ Empty `planeRoots` in `enforced` mode fails closed (`ARKORDER_MISSING_PLANE`).
138
+ `xiKeys` is a repo-wide watchlist of slow names the product already knows (plan,
139
+ protocol, cost-code bound). Empty `xiKeys` leaves `ARKORDER_XI_FIELD_WRITE` silent.
140
+ `maxXiKeys` (default 7) is the Haken cap on one `release()` / `assertXiKeyCap`, not
141
+ a cap on watchlist length: eight named `xiKeys` with `maxXiKeys` 7 is valid.
142
+ `ARKORDER_TOO_MANY_PARAMS` fires when `release()` `keyCount` exceeds `maxXiKeys`.
143
+ Optional `appliesTo` uses the same glob engine as `layers[].patterns`. Absence or
144
+ empty keeps current behavior (every file in `managedLayers`). Non-empty emits
145
+ `ARKORDER_XI_FIELD_WRITE` only when the layer is managed **and** the file matches
146
+ at least one glob. Membership ids and recomputable statuses such as `paid` /
147
+ `overdue` are not keys. Factory options `informationBudget`, `sigmaMaxAgeMs`,
148
+ `store` (`ReleaseStore`), and capacity packs belong on `createOrderPlane`, not this
149
+ extra object. Later ξ is `proposeRelease` then `apply`; `refreshSigma`; ingest
150
+ residual `absorb | escalate_up | hold`. Demotion or deletion is a policy-delta
151
+ **weakening**. Field ingest never mints a pattern.
140
152
 
141
153
  **Activation is one shape.** ArkRun and ArkOrder both use `mode` + `managedLayers`.
142
154
  Absence of either extra is silent. They keep different *root* names because they
@@ -191,8 +203,36 @@ Rule fields:
191
203
  - `from`, `to`, `allowed`, `message`, `peerIsolation`, `sliceFolders`, `sharedRoots`,
192
204
  `allowedCrossSlice`
193
205
  - `peerIsolation: true` + `allowed: false`: deny only when slice ids differ; same-slice allows
194
- when both paths classify. Missing paths, empty slice folders, or unclassifiable slices
195
- **fail closed** (deny — cannot prove same-slice).
206
+ when both paths classify. Applies to **any** declared `from`→`to` pair, not only self-edges.
207
+ Missing paths, empty slice folders, or unclassifiable slices **fail closed** (deny — cannot
208
+ prove same-slice).
209
+
210
+ #### Cross-layer slice walls (already in the engine)
211
+
212
+ A slice wall on a cross-layer edge is a `peerIsolation` rule on that `from`/`to` pair
213
+ (`allowed: false`). There is no slice-wide engine mode, no new config key, and no new skill
214
+ name. `findDeniedEdgeDecision` already applies `peerIsolation` to any declared pair
215
+ (same-layer or cross-layer) — locked on `EdgeRule` and `findDeniedEdgeDecision` in
216
+ [`src/domain/layerMatch.ts`](../src/domain/layerMatch.ts). There is no dedicated ADR to add.
217
+
218
+ A feature slice is often cross-layer. Classic Application→Domain is allowed by omission, so
219
+ `ApplicationOrchestration/management` importing `DomainModel/projects` is invisible to an
220
+ Application→Application wall. Declare the cross-layer pair with the same `sliceFolders` /
221
+ `sharedRoots` as the same-layer wall:
222
+
223
+ ```jsonc
224
+ {
225
+ "from": "ApplicationOrchestration",
226
+ "to": "DomainModel",
227
+ "allowed": false,
228
+ "peerIsolation": true,
229
+ "sliceFolders": ["features"],
230
+ "sharedRoots": ["ui", "hooks"]
231
+ }
232
+ ```
233
+
234
+ Domain files that do not resolve to a slice **fail closed** unless they sit under a declared
235
+ `sharedRoots` entry. Do not invent a sixth rule shape for this.
196
236
 
197
237
  #### Declared peerIsolation exceptions (4.8.4)
198
238
 
@@ -413,6 +453,13 @@ Write-gate ApplyPatch denies a batch that mixes law files with product source. H
413
453
  never hit PreToolUse are unchanged. Local `pnpm` gates should call `--changed --base`, not
414
454
  only full-tree `--strict-merge`.
415
455
 
456
+ `--changed` honors the touched-file list for **file-local** ArkRules structure sensors
457
+ (class shape, orchestration-only, thin-adapter, writes-via-aggregate) and for
458
+ structural-hint preload. Import-edge, layer, and cycle sensors still evaluate the full
459
+ governed graph. That is a bound on the existing scan, not a second analysis engine, and
460
+ it does not turn a full-tree run into a seconds-long one. A `--changed` pass is not a
461
+ full-tree structural verdict.
462
+
416
463
  MCP clients can call `ark_policy_delta` with the previous `baseConfig`, an optional candidate
417
464
  contract (the current project contract is the default), and the same optional acknowledgement.
418
465
  It invokes the public classifier directly, is read-only, and marks a blocking result as an MCP
package/docs/develop.md CHANGED
@@ -214,8 +214,10 @@ First freeze is `release()`. Later pattern change is `proposeRelease` then
214
214
  `absorb | escalate_up | hold` + `reasonCode`; capacity pack as data;
215
215
  `createMemoryReleaseStore`; `ingestTravelAction`; ArkRun `decisionTape`.
216
216
 
217
- Copy [examples/arkorder-billing/](../examples/arkorder-billing/) (`plan` / `cycle` /
218
- `tenancy`) and rename the keys. Posting an invoice is absorbed; changing plan is
217
+ The billing gallery (`plan` / `cycle` / `tenancy`) lives on GitHub, not in the
218
+ npm tarball:
219
+ [examples/arkorder-billing](https://github.com/pedroknigge/arkgate/tree/main/examples/arkorder-billing).
220
+ Rename the keys. Posting an invoice is absorbed; changing plan is
219
221
  `proposeRelease` then `apply`. See [configuration.md](configuration.md) and
220
222
  [package-surface.md](package-surface.md).
221
223
 
@@ -43,6 +43,7 @@ Link form for agents: `docs/diagnostics.md#RULE_ID` (exact-case HTML anchors bel
43
43
  | [`ARKRULE_STRUCTURE`](#ARKRULE_STRUCTURE) | arkrules | ArkRule structure sensor failed |
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
+ | [`ARKRULE_HINT_BUDGET_EXHAUSTED`](#ARKRULE_HINT_BUDGET_EXHAUSTED) | arkrules | Structural-hint budget exhausted |
46
47
  | [`INVARIANT_UNCOVERED`](#INVARIANT_UNCOVERED) | arkrules | Invariant without coverage evidence |
47
48
  | [`INVARIANT_COVERAGE_OUTSIDE_ROOTS`](#INVARIANT_COVERAGE_OUTSIDE_ROOTS) | arkrules | Covering test outside the declared coverage roots |
48
49
  | [`ARKRUN_MISSING_ROOT`](#ARKRUN_MISSING_ROOT) | arkrun | No kernel factory in composition roots |
@@ -279,6 +280,15 @@ Link form for agents: `docs/diagnostics.md#RULE_ID` (exact-case HTML anchors bel
279
280
  - **Why:** An ArkRule’s appliesTo globs matched no governed files — the rule cannot observe what it claims to protect.
280
281
  - **Fix:** Fix appliesTo globs so they match governed files, or remove the rule. Enforced empty scope fails; advisory empty scope warns.
281
282
 
283
+ <a id="ARKRULE_HINT_BUDGET_EXHAUSTED"></a>
284
+
285
+ ### `ARKRULE_HINT_BUDGET_EXHAUSTED`
286
+
287
+ **Structural-hint budget exhausted**
288
+
289
+ - **Why:** `orchestration-only`, `thin-adapter`, and `writes-via-aggregate` only evaluate files the hint loader preloaded. When eligible governed files exceed that budget (`coverage.maxFiles`, default `400` — there is no `arkrules.hintBudget`), those sensors never saw the rest of their scope. Enforced + unreviewed is not green. The finding names exact hinted/governed counts and per-sensor reviewed N/M of scope.
290
+ - **Fix:** Raise `coverage.maxFiles` in ark.config.json (this cap also bounds structural-hint preload; `--doctor` names the coupling) so hinted/governed counts match, then re-run with `--strict-config`. An enforced hint sensor that cannot see its scope fails strict.
291
+
282
292
  <a id="INVARIANT_UNCOVERED"></a>
283
293
 
284
294
  ### `INVARIANT_UNCOVERED`
@@ -37,7 +37,8 @@ hardening guide remains repository-hosted rather than duplicated in the gate tar
37
37
 
38
38
  | Surface | How you use it | Stability notes |
39
39
  |---------|----------------|-----------------|
40
- | **CLI** | `arkgate` / `arkgate-check` (aliases `ark` / `ark-check`); optional ArkRun **`ark-dashboard`** / **`arkgate-dashboard`** | Flags and human text may improve; **JSON output shapes** for `--json` (check, doctor, plan, coverage, recommend, **status**, **agents-md**) are stable within a major. Additive fields OK; removals/renames are major. From 4.2, `--require-gates` implies strict config and verifies semantic Ark AGENTS, project-rooted MCP/compact Codex registration, and fail-closed CI rather than file presence alone. `ark status --json` is the unified status snapshot. `ark agents-md` is the version-matched agent projection (non-authoritative). **Dashboard bins** poll an ArkRun inspector snapshot (ANSI + interval polling; `--url` / `--interval`); they are not a gate verdict. The main CLI also accepts `ark dashboard` / `arkgate dashboard` as a passthrough to those bins. |
40
+ | **CLI** | `arkgate` / `arkgate-check` (aliases `ark` / `ark-check`); optional ArkRun **`ark-dashboard`** / **`arkgate-dashboard`** | Flags and human text may improve; **JSON output shapes** for `--json` (check, doctor, plan, coverage, recommend, **status**, **agents-md**, **report**) are stable within a major. Additive fields OK; removals/renames are major. From 4.2, `--require-gates` implies strict config and verifies semantic Ark AGENTS, project-rooted MCP/compact Codex registration, and fail-closed CI rather than file presence alone. `ark status --json` is the unified status snapshot. `ark agents-md` is the version-matched agent projection (non-authoritative). **`arkgate report` / `ark report`** drafts an upstream GitHub issue for `pedroknigge/arkgate` (`package.json` `bugs.url`) — never the consumer repo. **Dashboard bins** poll an ArkRun inspector snapshot (ANSI + interval polling; `--url` / `--interval`); they are not a gate verdict. The main CLI also accepts `ark dashboard` / `arkgate dashboard` as a passthrough to those bins. |
41
+ | **Upstream report CLI (4.8.10)** | `arkgate report` / `ark report` on the existing dual bins (no new bin, no new skill) | Default prints a draft for **upstream** `pedroknigge/arkgate` (`package.json` `bugs.url`) with the arkgate version and optional last-check snippet. Create only with `--submit` **and** `--i-confirm-submit` (after HITL) or TTY `Type submit to send`. `--yes` does not submit. Missing/unauthenticated `gh`: print the draft plus the exact `gh issue create --repo pedroknigge/arkgate` command, exit 2. Never files against the consumer repo. Not `ark-check --report` (HTML architecture report). |
41
42
  | **Host write boundaries** | Generated trusted PreToolUse/preToolUse hooks + `ark-mcp --hook`; inspect with doctor/status | Hard is always operation-scoped and runtime-evidenced. From 4.6.3, Codex CLI and local ChatGPT Desktop/App Server can hard-block a complete `apply_patch` sent as `tool_input.command`; `.codex/hooks.json` on disk remains unverified until a fresh covered invocation. Hosted tools, specialized hook opt-outs, shell/direct writes, incomplete reconstruction, and humans rely on required CI. Repair envelopes may emit, but Codex reinjection is not guaranteed. |
42
43
  | **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. |
43
44
  | **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`. |
@@ -191,7 +192,7 @@ claims. Static architecture enforcement does not depend on them.
191
192
  |---------|-------------|--------|
192
193
  | **ArkRun kernel** | **`arkgate/runtime`** | Public brand **ArkRun**. Same npm package `arkgate` (ADR 0031). Factory `createStrictArkKernel` (each call is an isolated instance; no process-wide `getKernel()` singleton). Root export does **not** include the factory. Optional extra `arkRun` on schema `1.2+`. 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, `/graph` slices of the information package, plus queue monitors **`GET /outbox`** and **`GET /workflows`** (full counts + sanitized samples capped at 32; no full event payloads; missing ports are unavailable; no public / authless bind). Snapshot `hardening.durability` classifies the explicit outbox/audit/workflow store ports; default `InMemory*` stores stay visibly `memory`, never durable. Dual bins **`ark-dashboard`** / **`arkgate-dashboard`** poll those JSON facts (ANSI TUI in `bin/` only — presentation is not in the kernel); `ark dashboard` / `arkgate dashboard` dispatch to the same executable. **Shadow / replay / compare** (`shadowInformationPackage`, `compareInformationPackages`, `replayInformationPackages`) are in-memory helpers on that snapshot — not durable, not a second bus (ADR 0033). **Decision tape** `decisionTape` `{ xiHash, event, residual }` via `appendDecisionTape` (ADR 0034). Built-in stores are **InMemory reference only**. Branding ArkRun is not a production-durability claim. **`@arkgate/runtime` is deprecated** leftover 0.x (`experimental` dist-tag). |
193
194
  | **NestJS adapter** | **`arkgate/nestjs`** | Experimental optional peer `@nestjs/common` for the ArkRun kernel. Same npm package. `@arkgate/runtime/nestjs` is deprecated. |
194
- | **ArkOrder plane** | **`arkgate/order`** | Public brand **ArkOrder**. Same npm package `arkgate` (ADR 0030) — not `@arkgate/order`. Factory `createOrderPlane`. Valved verbs: `release` / `project` / `ingest` / `proposeRelease` / `apply` / `refreshSigma`. No `update`. First freeze is `release()`; later ξ change is `apply` (`ARKORDER_UNVALVED_RELEASE`). Haken: few slow keys; ingest residual `absorb | escalate_up | hold` + closed `reasonCode`; empty blast fails closed. Capacity pack as data (`kind` / `sigmaKey` / `payloadKey` / `op`). Factory options (not config keys): `informationBudget.cannotObserve`, `sigmaMaxAgeMs`, `store` (`ReleaseStore` / `createMemoryReleaseStore`), `catalogDigest`. Thin travel: `ingestTravelAction` absorb→`send` / escalate_up human→`raises`. `IngestEscalate.target` includes `human`. Root `arkgate` export does **not** include the factory. Optional extra `arkOrder` on schema `1.3`. In-memory; not durable; does not close K01. Does not replace ArkRun. Runtime half (shadow/replay/compare + `decisionTape` / `appendDecisionTape`) is ArkRun (ADR 0033 / 0034). Canonical: [ArkOrder](arkorder.md). |
195
+ | **ArkOrder plane** | **`arkgate/order`** | Public brand **ArkOrder**. Same npm package `arkgate` (ADR 0030) — not `@arkgate/order`. Factory `createOrderPlane`. Valved verbs: `release` / `project` / `ingest` / `proposeRelease` / `apply` / `refreshSigma` / `restore`. No `update`. First freeze is `release()`; later ξ change is `apply` (`ARKORDER_UNVALVED_RELEASE`). `restore(release)` installs a previously frozen `Release` (hash remains identity; not durable). `hashOf` / `hashReleasePayload` verify a stored hash without a second freeze. Default Kernel clock is `Date.now()`. Optional `arkOrder.appliesTo` globs; `maxXiKeys` caps one `release()`, not `xiKeys.length`. Haken: few slow keys; ingest residual `absorb | escalate_up | hold` + closed `reasonCode`; empty blast fails closed. Capacity pack as data (`kind` / `sigmaKey` / `payloadKey` / `op`). Factory options (not config keys): `informationBudget.cannotObserve`, `sigmaMaxAgeMs`, `store` (`ReleaseStore` / `createMemoryReleaseStore`), `catalogDigest`. Thin travel: `ingestTravelAction` absorb→`send` / escalate_up human→`raises`. `IngestEscalate.target` includes `human`. Root `arkgate` export does **not** include the factory. Optional extra `arkOrder` on schema `1.3`. In-memory; not durable; does not close K01. Does not replace ArkRun. Runtime half (shadow/replay/compare + `decisionTape` / `appendDecisionTape`) is ArkRun (ADR 0033 / 0034). Billing gallery is git-only: [examples/arkorder-billing](https://github.com/pedroknigge/arkgate/tree/main/examples/arkorder-billing) (not in the npm tarball). Canonical: [ArkOrder](arkorder.md). |
195
196
 
196
197
  ---
197
198
 
@@ -201,7 +202,7 @@ claims. Static architecture enforcement does not depend on them.
201
202
  import { createAICodeGate } from 'arkgate';
202
203
  import { createStrictArkKernel, createStrictArkKernelFromConfig } from 'arkgate/runtime';
203
204
  import { ArkModule, InjectArk } from 'arkgate/nestjs';
204
- import { createOrderPlane } from 'arkgate/order';
205
+ import { createOrderPlane, hashOf } from 'arkgate/order';
205
206
  ```
206
207
 
207
208
  One install: `npm install arkgate`. `@arkgate/runtime` is deprecated.
@@ -265,8 +266,9 @@ production deployment would need to satisfy; it is not a readiness certification
265
266
  ## Release notes (maintainers)
266
267
 
267
268
  Ship notes for a version live under [releases/](https://github.com/pedroknigge/arkgate/tree/main/docs/releases)
268
- (current tree candidate: [4.8.8.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.8.8.md), prepared and not published;
269
- current published: [4.8.7.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.8.7.md);
269
+ (current published: [4.8.9.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.8.9.md);
270
+ prior published: [4.8.8.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.8.8.md);
271
+ prior published: [4.8.7.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.8.7.md);
270
272
  prior published: [4.8.6.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.8.6.md);
271
273
  prior published: [4.8.5.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.8.5.md);
272
274
  prior published: [4.8.4.md](https://github.com/pedroknigge/arkgate/blob/main/docs/releases/4.8.4.md);
package/docs/use.md CHANGED
@@ -163,12 +163,23 @@ Short loop so agents do not invent residual or re-run doctor every message:
163
163
  **`unavailable`** (or compass facts are missing), run `npx ark-check --doctor` (add `--json` for
164
164
  the full 15-lens map) before treating residual as complete. When mode is **`full`**, status
165
165
  residual ids are a safe subset of doctor residual for the same facts.
166
+ 5. **If ArkGate itself is wrong** — run `npx arkgate report` (alias `ark report`). Default prints
167
+ a draft GitHub issue for **upstream** `pedroknigge/arkgate` (`package.json` `bugs.url`) with
168
+ the arkgate version and last-check snippet. **Ask the human to confirm send.** Create only
169
+ with `--submit` and `--i-confirm-submit` (or TTY `Type submit to send`). `--yes` does not
170
+ submit. If `gh` is missing, the command prints the draft plus `gh issue create --repo
171
+ pedroknigge/arkgate …` and exits 2. Never auto-file. Never file ArkGate defects on the
172
+ consumer product repo. Not `arkgate-check --report` (HTML).
166
173
 
167
174
  ```bash
168
175
  npx ark status --json --expected-root /abs/project/root
169
176
  # when mode is not full:
170
177
  npx ark-check --doctor
171
178
  npx ark-check --doctor --json # doctor.improvementCompass
179
+ # draft an upstream issue (nothing created yet):
180
+ npx ark report
181
+ # after the human says yes — one finding, upstream only:
182
+ npx ark report --submit --i-confirm-submit
172
183
  ```
173
184
 
174
185
  Details: [agent-guide — Session recipe](agent-guide.md#session-recipe-agent-turn) ·
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkgate",
3
- "version": "4.8.8",
3
+ "version": "4.8.10",
4
4
  "description": "When the agent writes a bad import, the write doesn’t land. The same check fails the pull request.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -837,7 +837,7 @@
837
837
  "coverage": {
838
838
  "type": "object",
839
839
  "additionalProperties": false,
840
- "description": "Invariant coverage scan controls. testGlobs replaces the built-in test-name heuristic; maxFiles raises or lowers the evidence file budget; coverageRoots declares where the project runs its tests, so a covering test found outside them is reported instead of silently certifying an invariant.",
840
+ "description": "Invariant coverage scan controls. testGlobs replaces the built-in test-name heuristic; maxFiles raises or lowers the evidence file budget and also bounds structural-hint preload for orchestration-only, thin-adapter, and writes-via-aggregate (default 400; there is no arkrules.hintBudget); coverageRoots declares where the project runs its tests, so a covering test found outside them is reported instead of silently certifying an invariant.",
841
841
  "properties": {
842
842
  "testGlobs": {
843
843
  "type": "array",
@@ -850,7 +850,8 @@
850
850
  },
851
851
  "maxFiles": {
852
852
  "type": "integer",
853
- "minimum": 1
853
+ "minimum": 1,
854
+ "description": "Evidence file budget (default 400) and structural-hint preload cap for orchestration-only, thin-adapter, and writes-via-aggregate. Raise this when hinted/governed counts show truncated sensors. There is no separate arkrules.hintBudget."
854
855
  },
855
856
  "coverageRoots": {
856
857
  "type": "array",
@@ -954,6 +955,15 @@
954
955
  },
955
956
  "uniqueItems": true,
956
957
  "default": []
958
+ },
959
+ "appliesTo": {
960
+ "type": "array",
961
+ "items": {
962
+ "type": "string",
963
+ "minLength": 1
964
+ },
965
+ "uniqueItems": true,
966
+ "default": []
957
967
  }
958
968
  }
959
969
  }
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/pedroknigge/arkgate",
7
7
  "source": "github"
8
8
  },
9
- "version": "4.8.8",
9
+ "version": "4.8.10",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "arkgate",
14
- "version": "4.8.8",
14
+ "version": "4.8.10",
15
15
  "runtimeHint": "npx",
16
16
  "transport": {
17
17
  "type": "stdio"
@@ -7,7 +7,7 @@
7
7
  This directory is the **Agent Skills–compatible** packaging of the same **13**
8
8
  `/ark-*` skills shipped as flat templates for Ark install. **No new skill names.**
9
9
 
10
- Package version when last generated context: **arkgate@4.8.6**
10
+ Package version when last generated context: **arkgate@4.8.9**
11
11
  Schema: agent-skills package contract `1.0`
12
12
 
13
13
  ## Skills (frozen catalog)
@@ -45,7 +45,7 @@ Label findings **`[Layer]`** vs **`[ArkRules]`** vs **`[ArkRun]`** vs **`[ArkOrd
45
45
 
46
46
  Application / Features may declare advisory **`writes-via-aggregate`**: a use-case that imports a persistence driver and calls `.insert` / `.create` / `INSERT INTO` is the skip. Persistence adapters stay the write edge. Do not add `Externals/` or `admission.ts` as contract law.
47
47
 
48
- When `arkOrder` is on, name **`xiKeys`** (3–5 slow product decisions). Membership ids and recomputable statuses are not keys: derive a status on read or fold it from ingest instead. A use-case that persists those keys is `ARKORDER_XI_FIELD_WRITE`. First freeze is `release()`; later ξ is `proposeRelease` then `apply`; `refreshSigma`; ingest residual `absorb | escalate_up | hold` + `reasonCode`; capacity pack as data; in-memory `ReleaseStore`; ArkRun `decisionTape`. Copy [examples/arkorder-billing/](../../../examples/arkorder-billing/) and rename the three keys. The check remains silent on semantic entailment.
48
+ When `arkOrder` is on, name **`xiKeys`** (3–5 slow product decisions). Membership ids and recomputable statuses are not keys: derive a status on read or fold it from ingest instead. A use-case that persists those keys is `ARKORDER_XI_FIELD_WRITE`. First freeze is `release()`; later ξ is `proposeRelease` then `apply`; `refreshSigma`; ingest residual `absorb | escalate_up | hold` + `reasonCode`; capacity pack as data; in-memory `ReleaseStore`; ArkRun `decisionTape`. The billing gallery lives on GitHub, not in the npm tarball: [examples/arkorder-billing](https://github.com/pedroknigge/arkgate/tree/main/examples/arkorder-billing). Rename the three keys. The check remains silent on semantic entailment.
49
49
 
50
50
  ## Subagent fan-out (optional, host-dependent)
51
51
 
@@ -19,6 +19,7 @@ description: Map import rules and leftover design. No apply. CLI is a sensor; yo
19
19
  - Doctor #1: if ENFORCE + empty plan A and gates are already installed → **Shape** (`/ark-explore` then `/ark-autopilot`). Do not say install-agent-gates.
20
20
  - Distinguish **missing** skills vs **stale** catalog. Installed ≠ stale.
21
21
  - Hook green is not tree green (scripted edits bypass PreToolUse).
22
+ - Bug / false green / false red / missing doc / improvable behavior **in ArkGate itself** → draft one upstream GitHub issue (`pedroknigge/arkgate` or the installed package `repository.url`), **ask the human to confirm send**, then `gh issue create`. Never auto-file. Never file ArkGate defects on the consumer product repo.
22
23
 
23
24
  ## Autonomy contract
24
25
 
@@ -27,7 +28,24 @@ incomplete. **Do not write** config or product code (that is `/ark-adopt` / `/ar
27
28
  **CLI budget:** one doctor / coverage; then open ≥12 files across ≥4 dirs; then the map.
28
29
 
29
30
  **Still never:** weaken the config; invent `mechanical-safe` kinds; claim healthy because
30
- plan A is empty while leftover design work remains.
31
+ plan A is empty while leftover design work remains; auto-file GitHub issues; file ArkGate
32
+ defects on the consumer product repo; skip the human confirm step.
33
+
34
+ ## Report ArkGate defects (ask first)
35
+
36
+ This skill maps **this** tree. If recon shows a bug, false green, false red, missing doc, or
37
+ improvable behavior **in ArkGate itself** (the `arkgate` package — not leftover design in the
38
+ consumer app):
39
+
40
+ 1. Draft one GitHub issue for **upstream** (`pedroknigge/arkgate`, or `package.json`
41
+ `repository.url` of the installed `arkgate` package).
42
+ 2. **Ask the human in the loop to confirm send.** Do not create the issue until they say yes.
43
+ 3. If confirmed, `gh issue create` with the logged-in account. One finding per issue. Include
44
+ repro commands, version, and measured evidence.
45
+ 4. Never auto-file, batch-spam, or skip confirm. Never file ArkGate defects on the consumer
46
+ product repo.
47
+
48
+ Reporting is not applying product code. Stay map-only on this tree.
31
49
 
32
50
  Use when you need a decision-grade map or the **Primary post-green door**; hand off to
33
51
  `/ark-autopilot` to apply. Day-to-day place + gate work does not require this skill.
@@ -168,7 +186,7 @@ ArkGate has **always-on Layers** plus opt-in extras. The user chooses extras; yo
168
186
  ### Explore + extras
169
187
  - Map extras when present; never write `arkRun` / `arkOrder`. Extra off → residual `n/a` / silent.
170
188
  - When `arkOrder` is on, name the valve: first freeze `release()`; later ξ is `proposeRelease` then `apply`; `refreshSigma`; ingest residual `absorb | escalate_up | hold` + `reasonCode`; capacity pack as data; in-memory `ReleaseStore` (`createMemoryReleaseStore`); thin travel `ingestTravelAction`. ArkRun residual may include information package `decisionTape` `{ xiHash, event, residual }`.
171
- - Field path may name `examples/arkorder-billing/` (ArkOrder fixture — map only). First extra write is `/ark-adopt`; grind is `/ark-autopilot`.
189
+ - Field path may name the ArkOrder gallery on GitHub (`https://github.com/pedroknigge/arkgate/tree/main/examples/arkorder-billing`; not in the npm tarball — map only). First extra write is `/ark-adopt`; grind is `/ark-autopilot`.
172
190
 
173
191
  ## Output mode (pick one — do not invent a fourth)
174
192
 
@@ -297,7 +315,7 @@ When `examples/`, `templates/`, gallery starters, eval fixtures, or docs claim
297
315
  3. Diff **rule strength** across archetypes (missing denies = soft false-green for consumers).
298
316
  4. Note import style vs package surface docs (`arkgate` root barrel vs preferred subpath).
299
317
  5. Flag **false promises**: demo fails under its own check, or green with a hollow contract.
300
- 6. When extras are on, label residual `[ArkRun]` / `[ArkOrder]`. Field path may name `examples/arkorder-billing/`. Never write extras from this skill.
318
+ 6. When extras are on, label residual `[ArkRun]` / `[ArkOrder]`. Field path may name the ArkOrder gallery on GitHub (`https://github.com/pedroknigge/arkgate/tree/main/examples/arkorder-billing`; not in the npm tarball). Never write extras from this skill.
301
319
 
302
320
  If the repo is a **pure app** (no examples): state **Field path: internal** and do one of:
303
321
  - Name the **norm for new code** that the residual implies (e.g. “no new `platform/db` in routes”), or
@@ -431,6 +449,9 @@ Optional: **Diff vs naive sensor-only read** (what reading the tree changed).
431
449
  - Mode respected: no multi-week roadmap in recon mode; dual-plan seed capped at 3–5 B bets.
432
450
  - Clear handoff: `/ark-adopt` | `/ark-autopilot` | `/ark-place` | CLI | `stop`.
433
451
  - No gate weakening; no false ENFORCE claim; no README echo as primary content.
452
+ - If you found a bug / false green / false red / missing doc / improvable behavior in the
453
+ **ArkGate package**, you drafted one upstream issue, asked the human to confirm, and did not
454
+ `gh issue create` until they said yes. Never filed it on the consumer repo.
434
455
 
435
456
  ## Completion contract (skill incomplete if missing)
436
457